test_undefined_names.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819
  1. import ast
  2. from pyflakes import messages as m, checker
  3. from pyflakes.test.harness import TestCase, skip
  4. class Test(TestCase):
  5. def test_undefined(self):
  6. self.flakes('bar', m.UndefinedName)
  7. def test_definedInListComp(self):
  8. self.flakes('[a for a in range(10) if a]')
  9. def test_undefinedInListComp(self):
  10. self.flakes('''
  11. [a for a in range(10)]
  12. a
  13. ''',
  14. m.UndefinedName)
  15. def test_undefinedExceptionName(self):
  16. """Exception names can't be used after the except: block.
  17. The exc variable is unused inside the exception handler."""
  18. self.flakes('''
  19. try:
  20. raise ValueError('ve')
  21. except ValueError as exc:
  22. pass
  23. exc
  24. ''', m.UndefinedName, m.UnusedVariable)
  25. def test_namesDeclaredInExceptBlocks(self):
  26. """Locals declared in except: blocks can be used after the block.
  27. This shows the example in test_undefinedExceptionName is
  28. different."""
  29. self.flakes('''
  30. try:
  31. raise ValueError('ve')
  32. except ValueError as exc:
  33. e = exc
  34. e
  35. ''')
  36. @skip('error reporting disabled due to false positives below')
  37. def test_undefinedExceptionNameObscuringLocalVariable(self):
  38. """Exception names obscure locals, can't be used after.
  39. Last line will raise UnboundLocalError on Python 3 after exiting
  40. the except: block. Note next two examples for false positives to
  41. watch out for."""
  42. self.flakes('''
  43. exc = 'Original value'
  44. try:
  45. raise ValueError('ve')
  46. except ValueError as exc:
  47. pass
  48. exc
  49. ''',
  50. m.UndefinedName)
  51. def test_undefinedExceptionNameObscuringLocalVariable2(self):
  52. """Exception names are unbound after the `except:` block.
  53. Last line will raise UnboundLocalError.
  54. The exc variable is unused inside the exception handler.
  55. """
  56. self.flakes('''
  57. try:
  58. raise ValueError('ve')
  59. except ValueError as exc:
  60. pass
  61. print(exc)
  62. exc = 'Original value'
  63. ''', m.UndefinedName, m.UnusedVariable)
  64. def test_undefinedExceptionNameObscuringLocalVariableFalsePositive1(self):
  65. """Exception names obscure locals, can't be used after. Unless.
  66. Last line will never raise UnboundLocalError because it's only
  67. entered if no exception was raised."""
  68. self.flakes('''
  69. exc = 'Original value'
  70. try:
  71. raise ValueError('ve')
  72. except ValueError as exc:
  73. print('exception logged')
  74. raise
  75. exc
  76. ''', m.UnusedVariable)
  77. def test_delExceptionInExcept(self):
  78. """The exception name can be deleted in the except: block."""
  79. self.flakes('''
  80. try:
  81. pass
  82. except Exception as exc:
  83. del exc
  84. ''')
  85. def test_undefinedExceptionNameObscuringLocalVariableFalsePositive2(self):
  86. """Exception names obscure locals, can't be used after. Unless.
  87. Last line will never raise UnboundLocalError because `error` is
  88. only falsy if the `except:` block has not been entered."""
  89. self.flakes('''
  90. exc = 'Original value'
  91. error = None
  92. try:
  93. raise ValueError('ve')
  94. except ValueError as exc:
  95. error = 'exception logged'
  96. if error:
  97. print(error)
  98. else:
  99. exc
  100. ''', m.UnusedVariable)
  101. @skip('error reporting disabled due to false positives below')
  102. def test_undefinedExceptionNameObscuringGlobalVariable(self):
  103. """Exception names obscure globals, can't be used after.
  104. Last line will raise UnboundLocalError because the existence of that
  105. exception name creates a local scope placeholder for it, obscuring any
  106. globals, etc."""
  107. self.flakes('''
  108. exc = 'Original value'
  109. def func():
  110. try:
  111. pass # nothing is raised
  112. except ValueError as exc:
  113. pass # block never entered, exc stays unbound
  114. exc
  115. ''',
  116. m.UndefinedLocal)
  117. @skip('error reporting disabled due to false positives below')
  118. def test_undefinedExceptionNameObscuringGlobalVariable2(self):
  119. """Exception names obscure globals, can't be used after.
  120. Last line will raise NameError on Python 3 because the name is
  121. locally unbound after the `except:` block, even if it's
  122. nonlocal. We should issue an error in this case because code
  123. only working correctly if an exception isn't raised, is invalid.
  124. Unless it's explicitly silenced, see false positives below."""
  125. self.flakes('''
  126. exc = 'Original value'
  127. def func():
  128. global exc
  129. try:
  130. raise ValueError('ve')
  131. except ValueError as exc:
  132. pass # block never entered, exc stays unbound
  133. exc
  134. ''',
  135. m.UndefinedLocal)
  136. def test_undefinedExceptionNameObscuringGlobalVariableFalsePositive1(self):
  137. """Exception names obscure globals, can't be used after. Unless.
  138. Last line will never raise NameError because it's only entered
  139. if no exception was raised."""
  140. self.flakes('''
  141. exc = 'Original value'
  142. def func():
  143. global exc
  144. try:
  145. raise ValueError('ve')
  146. except ValueError as exc:
  147. print('exception logged')
  148. raise
  149. exc
  150. ''', m.UnusedVariable)
  151. def test_undefinedExceptionNameObscuringGlobalVariableFalsePositive2(self):
  152. """Exception names obscure globals, can't be used after. Unless.
  153. Last line will never raise NameError because `error` is only
  154. falsy if the `except:` block has not been entered."""
  155. self.flakes('''
  156. exc = 'Original value'
  157. def func():
  158. global exc
  159. error = None
  160. try:
  161. raise ValueError('ve')
  162. except ValueError as exc:
  163. error = 'exception logged'
  164. if error:
  165. print(error)
  166. else:
  167. exc
  168. ''', m.UnusedVariable)
  169. def test_functionsNeedGlobalScope(self):
  170. self.flakes('''
  171. class a:
  172. def b():
  173. fu
  174. fu = 1
  175. ''')
  176. def test_builtins(self):
  177. self.flakes('range(10)')
  178. def test_builtinWindowsError(self):
  179. """
  180. C{WindowsError} is sometimes a builtin name, so no warning is emitted
  181. for using it.
  182. """
  183. self.flakes('WindowsError')
  184. def test_moduleAnnotations(self):
  185. """
  186. Use of the C{__annotations__} in module scope should not emit
  187. an undefined name warning when version is greater than or equal to 3.6.
  188. """
  189. self.flakes('__annotations__')
  190. def test_magicGlobalsFile(self):
  191. """
  192. Use of the C{__file__} magic global should not emit an undefined name
  193. warning.
  194. """
  195. self.flakes('__file__')
  196. def test_magicGlobalsBuiltins(self):
  197. """
  198. Use of the C{__builtins__} magic global should not emit an undefined
  199. name warning.
  200. """
  201. self.flakes('__builtins__')
  202. def test_magicGlobalsName(self):
  203. """
  204. Use of the C{__name__} magic global should not emit an undefined name
  205. warning.
  206. """
  207. self.flakes('__name__')
  208. def test_magicGlobalsPath(self):
  209. """
  210. Use of the C{__path__} magic global should not emit an undefined name
  211. warning, if you refer to it from a file called __init__.py.
  212. """
  213. self.flakes('__path__', m.UndefinedName)
  214. self.flakes('__path__', filename='package/__init__.py')
  215. def test_magicModuleInClassScope(self):
  216. """
  217. Use of the C{__module__} magic builtin should not emit an undefined
  218. name warning if used in class scope.
  219. """
  220. self.flakes('__module__', m.UndefinedName)
  221. self.flakes('''
  222. class Foo:
  223. __module__
  224. ''')
  225. self.flakes('''
  226. class Foo:
  227. def bar(self):
  228. __module__
  229. ''', m.UndefinedName)
  230. def test_magicQualnameInClassScope(self):
  231. """
  232. Use of the C{__qualname__} magic builtin should not emit an undefined
  233. name warning if used in class scope.
  234. """
  235. self.flakes('__qualname__', m.UndefinedName)
  236. self.flakes('''
  237. class Foo:
  238. __qualname__
  239. ''')
  240. self.flakes('''
  241. class Foo:
  242. def bar(self):
  243. __qualname__
  244. ''', m.UndefinedName)
  245. def test_globalImportStar(self):
  246. """Can't find undefined names with import *."""
  247. self.flakes('from fu import *; bar',
  248. m.ImportStarUsed, m.ImportStarUsage)
  249. def test_definedByGlobal(self):
  250. """
  251. "global" can make an otherwise undefined name in another function
  252. defined.
  253. """
  254. self.flakes('''
  255. def a(): global fu; fu = 1
  256. def b(): fu
  257. ''')
  258. self.flakes('''
  259. def c(): bar
  260. def b(): global bar; bar = 1
  261. ''')
  262. def test_definedByGlobalMultipleNames(self):
  263. """
  264. "global" can accept multiple names.
  265. """
  266. self.flakes('''
  267. def a(): global fu, bar; fu = 1; bar = 2
  268. def b(): fu; bar
  269. ''')
  270. def test_globalInGlobalScope(self):
  271. """
  272. A global statement in the global scope is ignored.
  273. """
  274. self.flakes('''
  275. global x
  276. def foo():
  277. print(x)
  278. ''', m.UndefinedName)
  279. def test_global_reset_name_only(self):
  280. """A global statement does not prevent other names being undefined."""
  281. # Only different undefined names are reported.
  282. # See following test that fails where the same name is used.
  283. self.flakes('''
  284. def f1():
  285. s
  286. def f2():
  287. global m
  288. ''', m.UndefinedName)
  289. @skip("todo")
  290. def test_unused_global(self):
  291. """An unused global statement does not define the name."""
  292. self.flakes('''
  293. def f1():
  294. m
  295. def f2():
  296. global m
  297. ''', m.UndefinedName)
  298. def test_del(self):
  299. """Del deletes bindings."""
  300. self.flakes('a = 1; del a; a', m.UndefinedName)
  301. def test_delGlobal(self):
  302. """Del a global binding from a function."""
  303. self.flakes('''
  304. a = 1
  305. def f():
  306. global a
  307. del a
  308. a
  309. ''')
  310. def test_delUndefined(self):
  311. """Del an undefined name."""
  312. self.flakes('del a', m.UndefinedName)
  313. def test_delConditional(self):
  314. """
  315. Ignores conditional bindings deletion.
  316. """
  317. self.flakes('''
  318. context = None
  319. test = True
  320. if False:
  321. del(test)
  322. assert(test)
  323. ''')
  324. def test_delConditionalNested(self):
  325. """
  326. Ignored conditional bindings deletion even if they are nested in other
  327. blocks.
  328. """
  329. self.flakes('''
  330. context = None
  331. test = True
  332. if False:
  333. with context():
  334. del(test)
  335. assert(test)
  336. ''')
  337. def test_delWhile(self):
  338. """
  339. Ignore bindings deletion if called inside the body of a while
  340. statement.
  341. """
  342. self.flakes('''
  343. def test():
  344. foo = 'bar'
  345. while False:
  346. del foo
  347. assert(foo)
  348. ''')
  349. def test_delWhileTestUsage(self):
  350. """
  351. Ignore bindings deletion if called inside the body of a while
  352. statement and name is used inside while's test part.
  353. """
  354. self.flakes('''
  355. def _worker():
  356. o = True
  357. while o is not True:
  358. del o
  359. o = False
  360. ''')
  361. def test_delWhileNested(self):
  362. """
  363. Ignore bindings deletions if node is part of while's test, even when
  364. del is in a nested block.
  365. """
  366. self.flakes('''
  367. context = None
  368. def _worker():
  369. o = True
  370. while o is not True:
  371. while True:
  372. with context():
  373. del o
  374. o = False
  375. ''')
  376. def test_globalFromNestedScope(self):
  377. """Global names are available from nested scopes."""
  378. self.flakes('''
  379. a = 1
  380. def b():
  381. def c():
  382. a
  383. ''')
  384. def test_laterRedefinedGlobalFromNestedScope(self):
  385. """
  386. Test that referencing a local name that shadows a global, before it is
  387. defined, generates a warning.
  388. """
  389. self.flakes('''
  390. a = 1
  391. def fun():
  392. a
  393. a = 2
  394. return a
  395. ''', m.UndefinedLocal)
  396. def test_laterRedefinedGlobalFromNestedScope2(self):
  397. """
  398. Test that referencing a local name in a nested scope that shadows a
  399. global declared in an enclosing scope, before it is defined, generates
  400. a warning.
  401. """
  402. self.flakes('''
  403. a = 1
  404. def fun():
  405. global a
  406. def fun2():
  407. a
  408. a = 2
  409. return a
  410. ''', m.UndefinedLocal)
  411. def test_intermediateClassScopeIgnored(self):
  412. """
  413. If a name defined in an enclosing scope is shadowed by a local variable
  414. and the name is used locally before it is bound, an unbound local
  415. warning is emitted, even if there is a class scope between the enclosing
  416. scope and the local scope.
  417. """
  418. self.flakes('''
  419. def f():
  420. x = 1
  421. class g:
  422. def h(self):
  423. a = x
  424. x = None
  425. print(x, a)
  426. print(x)
  427. ''', m.UndefinedLocal)
  428. def test_doubleNestingReportsClosestName(self):
  429. """
  430. Test that referencing a local name in a nested scope that shadows a
  431. variable declared in two different outer scopes before it is defined
  432. in the innermost scope generates an UnboundLocal warning which
  433. refers to the nearest shadowed name.
  434. """
  435. exc = self.flakes('''
  436. def a():
  437. x = 1
  438. def b():
  439. x = 2 # line 5
  440. def c():
  441. x
  442. x = 3
  443. return x
  444. return x
  445. return x
  446. ''', m.UndefinedLocal).messages[0]
  447. # _DoctestMixin.flakes adds two lines preceding the code above.
  448. expected_line_num = 7 if self.withDoctest else 5
  449. self.assertEqual(exc.message_args, ('x', expected_line_num))
  450. def test_laterRedefinedGlobalFromNestedScope3(self):
  451. """
  452. Test that referencing a local name in a nested scope that shadows a
  453. global, before it is defined, generates a warning.
  454. """
  455. self.flakes('''
  456. def fun():
  457. a = 1
  458. def fun2():
  459. a
  460. a = 1
  461. return a
  462. return a
  463. ''', m.UndefinedLocal)
  464. def test_undefinedAugmentedAssignment(self):
  465. self.flakes(
  466. '''
  467. def f(seq):
  468. a = 0
  469. seq[a] += 1
  470. seq[b] /= 2
  471. c[0] *= 2
  472. a -= 3
  473. d += 4
  474. e[any] = 5
  475. ''',
  476. m.UndefinedName, # b
  477. m.UndefinedName, # c
  478. m.UndefinedName, m.UnusedVariable, # d
  479. m.UndefinedName, # e
  480. )
  481. def test_nestedClass(self):
  482. """Nested classes can access enclosing scope."""
  483. self.flakes('''
  484. def f(foo):
  485. class C:
  486. bar = foo
  487. def f(self):
  488. return foo
  489. return C()
  490. f(123).f()
  491. ''')
  492. def test_badNestedClass(self):
  493. """Free variables in nested classes must bind at class creation."""
  494. self.flakes('''
  495. def f():
  496. class C:
  497. bar = foo
  498. foo = 456
  499. return foo
  500. f()
  501. ''', m.UndefinedName)
  502. def test_definedAsStarArgs(self):
  503. """Star and double-star arg names are defined."""
  504. self.flakes('''
  505. def f(a, *b, **c):
  506. print(a, b, c)
  507. ''')
  508. def test_definedAsStarUnpack(self):
  509. """Star names in unpack are defined."""
  510. self.flakes('''
  511. a, *b = range(10)
  512. print(a, b)
  513. ''')
  514. self.flakes('''
  515. *a, b = range(10)
  516. print(a, b)
  517. ''')
  518. self.flakes('''
  519. a, *b, c = range(10)
  520. print(a, b, c)
  521. ''')
  522. def test_usedAsStarUnpack(self):
  523. """
  524. Star names in unpack are used if RHS is not a tuple/list literal.
  525. """
  526. self.flakes('''
  527. def f():
  528. a, *b = range(10)
  529. ''')
  530. self.flakes('''
  531. def f():
  532. (*a, b) = range(10)
  533. ''')
  534. self.flakes('''
  535. def f():
  536. [a, *b, c] = range(10)
  537. ''')
  538. def test_unusedAsStarUnpack(self):
  539. """
  540. Star names in unpack are unused if RHS is a tuple/list literal.
  541. """
  542. self.flakes('''
  543. def f():
  544. a, *b = any, all, 4, 2, 'un'
  545. ''', m.UnusedVariable, m.UnusedVariable)
  546. self.flakes('''
  547. def f():
  548. (*a, b) = [bool, int, float, complex]
  549. ''', m.UnusedVariable, m.UnusedVariable)
  550. self.flakes('''
  551. def f():
  552. [a, *b, c] = 9, 8, 7, 6, 5, 4
  553. ''', m.UnusedVariable, m.UnusedVariable, m.UnusedVariable)
  554. def test_keywordOnlyArgs(self):
  555. """Keyword-only arg names are defined."""
  556. self.flakes('''
  557. def f(*, a, b=None):
  558. print(a, b)
  559. ''')
  560. self.flakes('''
  561. import default_b
  562. def f(*, a, b=default_b):
  563. print(a, b)
  564. ''')
  565. def test_keywordOnlyArgsUndefined(self):
  566. """Typo in kwonly name."""
  567. self.flakes('''
  568. def f(*, a, b=default_c):
  569. print(a, b)
  570. ''', m.UndefinedName)
  571. def test_annotationUndefined(self):
  572. """Undefined annotations."""
  573. self.flakes('''
  574. from abc import note1, note2, note3, note4, note5
  575. def func(a: note1, *args: note2,
  576. b: note3=12, **kw: note4) -> note5: pass
  577. ''')
  578. self.flakes('''
  579. def func():
  580. d = e = 42
  581. def func(a: {1, d}) -> (lambda c: e): pass
  582. ''')
  583. def test_metaClassUndefined(self):
  584. self.flakes('''
  585. from abc import ABCMeta
  586. class A(metaclass=ABCMeta): pass
  587. ''')
  588. def test_definedInGenExp(self):
  589. """
  590. Using the loop variable of a generator expression results in no
  591. warnings.
  592. """
  593. self.flakes('(a for a in [1, 2, 3] if a)')
  594. self.flakes('(b for b in (a for a in [1, 2, 3] if a) if b)')
  595. def test_undefinedInGenExpNested(self):
  596. """
  597. The loop variables of generator expressions nested together are
  598. not defined in the other generator.
  599. """
  600. self.flakes('(b for b in (a for a in [1, 2, 3] if b) if b)',
  601. m.UndefinedName)
  602. self.flakes('(b for b in (a for a in [1, 2, 3] if a) if a)',
  603. m.UndefinedName)
  604. def test_undefinedWithErrorHandler(self):
  605. """
  606. Some compatibility code checks explicitly for NameError.
  607. It should not trigger warnings.
  608. """
  609. self.flakes('''
  610. try:
  611. socket_map
  612. except NameError:
  613. socket_map = {}
  614. ''')
  615. self.flakes('''
  616. try:
  617. _memoryview.contiguous
  618. except (NameError, AttributeError):
  619. raise RuntimeError("Python >= 3.3 is required")
  620. ''')
  621. # If NameError is not explicitly handled, generate a warning
  622. self.flakes('''
  623. try:
  624. socket_map
  625. except:
  626. socket_map = {}
  627. ''', m.UndefinedName)
  628. self.flakes('''
  629. try:
  630. socket_map
  631. except Exception:
  632. socket_map = {}
  633. ''', m.UndefinedName)
  634. def test_definedInClass(self):
  635. """
  636. Defined name for generator expressions and dict/set comprehension.
  637. """
  638. self.flakes('''
  639. class A:
  640. T = range(10)
  641. Z = (x for x in T)
  642. L = [x for x in T]
  643. B = dict((i, str(i)) for i in T)
  644. ''')
  645. self.flakes('''
  646. class A:
  647. T = range(10)
  648. X = {x for x in T}
  649. Y = {x:x for x in T}
  650. ''')
  651. def test_definedInClassNested(self):
  652. """Defined name for nested generator expressions in a class."""
  653. self.flakes('''
  654. class A:
  655. T = range(10)
  656. Z = (x for x in (a for a in T))
  657. ''')
  658. def test_undefinedInLoop(self):
  659. """
  660. The loop variable is defined after the expression is computed.
  661. """
  662. self.flakes('''
  663. for i in range(i):
  664. print(i)
  665. ''', m.UndefinedName)
  666. self.flakes('''
  667. [42 for i in range(i)]
  668. ''', m.UndefinedName)
  669. self.flakes('''
  670. (42 for i in range(i))
  671. ''', m.UndefinedName)
  672. def test_definedFromLambdaInDictionaryComprehension(self):
  673. """
  674. Defined name referenced from a lambda function within a dict/set
  675. comprehension.
  676. """
  677. self.flakes('''
  678. {lambda: id(x) for x in range(10)}
  679. ''')
  680. def test_definedFromLambdaInGenerator(self):
  681. """
  682. Defined name referenced from a lambda function within a generator
  683. expression.
  684. """
  685. self.flakes('''
  686. any(lambda: id(x) for x in range(10))
  687. ''')
  688. def test_undefinedFromLambdaInDictionaryComprehension(self):
  689. """
  690. Undefined name referenced from a lambda function within a dict/set
  691. comprehension.
  692. """
  693. self.flakes('''
  694. {lambda: id(y) for x in range(10)}
  695. ''', m.UndefinedName)
  696. def test_undefinedFromLambdaInComprehension(self):
  697. """
  698. Undefined name referenced from a lambda function within a generator
  699. expression.
  700. """
  701. self.flakes('''
  702. any(lambda: id(y) for x in range(10))
  703. ''', m.UndefinedName)
  704. def test_dunderClass(self):
  705. code = '''
  706. class Test(object):
  707. def __init__(self):
  708. print(__class__.__name__)
  709. self.x = 1
  710. t = Test()
  711. '''
  712. self.flakes(code)
  713. class NameTests(TestCase):
  714. """
  715. Tests for some extra cases of name handling.
  716. """
  717. def test_impossibleContext(self):
  718. """
  719. A Name node with an unrecognized context results in a RuntimeError being
  720. raised.
  721. """
  722. tree = ast.parse("x = 10")
  723. # Make it into something unrecognizable.
  724. tree.body[0].targets[0].ctx = object()
  725. self.assertRaises(RuntimeError, checker.Checker, tree)