variables.py 92 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394
  1. # Copyright (c) 2006-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
  2. # Copyright (c) 2009 Mads Kiilerich <mads@kiilerich.com>
  3. # Copyright (c) 2010 Daniel Harding <dharding@gmail.com>
  4. # Copyright (c) 2011-2014, 2017 Google, Inc.
  5. # Copyright (c) 2012 FELD Boris <lothiraldan@gmail.com>
  6. # Copyright (c) 2013-2020 Claudiu Popa <pcmanticore@gmail.com>
  7. # Copyright (c) 2014 Michal Nowikowski <godfryd@gmail.com>
  8. # Copyright (c) 2014 Brett Cannon <brett@python.org>
  9. # Copyright (c) 2014 Ricardo Gemignani <ricardo.gemignani@gmail.com>
  10. # Copyright (c) 2014 Arun Persaud <arun@nubati.net>
  11. # Copyright (c) 2015 Dmitry Pribysh <dmand@yandex.ru>
  12. # Copyright (c) 2015 Radu Ciorba <radu@devrandom.ro>
  13. # Copyright (c) 2015 Simu Toni <simutoni@gmail.com>
  14. # Copyright (c) 2015 Ionel Cristian Maries <contact@ionelmc.ro>
  15. # Copyright (c) 2016, 2018-2019 Ashley Whetter <ashley@awhetter.co.uk>
  16. # Copyright (c) 2016, 2018 Jakub Wilk <jwilk@jwilk.net>
  17. # Copyright (c) 2016-2017 Derek Gustafson <degustaf@gmail.com>
  18. # Copyright (c) 2016-2017 Łukasz Rogalski <rogalski.91@gmail.com>
  19. # Copyright (c) 2016 Grant Welch <gwelch925+github@gmail.com>
  20. # Copyright (c) 2017-2018, 2021 Ville Skyttä <ville.skytta@iki.fi>
  21. # Copyright (c) 2017-2018, 2020 hippo91 <guillaume.peillex@gmail.com>
  22. # Copyright (c) 2017 Dan Garrette <dhgarrette@gmail.com>
  23. # Copyright (c) 2018-2019 Jim Robertson <jrobertson98atx@gmail.com>
  24. # Copyright (c) 2018 Mike Miller <mtmiller@users.noreply.github.com>
  25. # Copyright (c) 2018 Lucas Cimon <lucas.cimon@gmail.com>
  26. # Copyright (c) 2018 Drew <drewrisinger@users.noreply.github.com>
  27. # Copyright (c) 2018 Sushobhit <31987769+sushobhit27@users.noreply.github.com>
  28. # Copyright (c) 2018 ssolanki <sushobhitsolanki@gmail.com>
  29. # Copyright (c) 2018 Bryce Guinta <bryce.guinta@protonmail.com>
  30. # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
  31. # Copyright (c) 2018 Mike Frysinger <vapier@gmail.com>
  32. # Copyright (c) 2018 Marianna Polatoglou <mpolatoglou@bloomberg.net>
  33. # Copyright (c) 2018 mar-chi-pan <mar.polatoglou@gmail.com>
  34. # Copyright (c) 2019-2021 Pierre Sassoulas <pierre.sassoulas@gmail.com>
  35. # Copyright (c) 2019, 2021 Nick Drozd <nicholasdrozd@gmail.com>
  36. # Copyright (c) 2019 Djailla <bastien.vallet@gmail.com>
  37. # Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>
  38. # Copyright (c) 2020 Andrew Simmons <anjsimmo@gmail.com>
  39. # Copyright (c) 2020 Andrew Simmons <a.simmons@deakin.edu.au>
  40. # Copyright (c) 2020 Anthony Sottile <asottile@umich.edu>
  41. # Copyright (c) 2020 Ashley Whetter <ashleyw@activestate.com>
  42. # Copyright (c) 2021 Daniël van Noord <13665637+DanielNoord@users.noreply.github.com>
  43. # Copyright (c) 2021 Tushar Sadhwani <tushar.sadhwani000@gmail.com>
  44. # Copyright (c) 2021 Marc Mueller <30130371+cdce8p@users.noreply.github.com>
  45. # Copyright (c) 2021 bot <bot@noreply.github.com>
  46. # Copyright (c) 2021 David Liu <david@cs.toronto.edu>
  47. # Copyright (c) 2021 kasium <15907922+kasium@users.noreply.github.com>
  48. # Copyright (c) 2021 Marcin Kurczewski <rr-@sakuya.pl>
  49. # Copyright (c) 2021 Sergei Lebedev <185856+superbobry@users.noreply.github.com>
  50. # Copyright (c) 2021 Lorena B <46202743+lorena-b@users.noreply.github.com>
  51. # Copyright (c) 2021 haasea <44787650+haasea@users.noreply.github.com>
  52. # Copyright (c) 2021 Alexander Kapshuna <kapsh@kap.sh>
  53. # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  54. # For details: https://github.com/PyCQA/pylint/blob/main/LICENSE
  55. """variables checkers for Python code
  56. """
  57. import collections
  58. import copy
  59. import itertools
  60. import os
  61. import re
  62. import sys
  63. from enum import Enum
  64. from functools import lru_cache
  65. from typing import Any, DefaultDict, List, Optional, Set, Tuple, Union
  66. import astroid
  67. from astroid import nodes
  68. from pylint.checkers import BaseChecker, utils
  69. from pylint.checkers.utils import is_postponed_evaluation_enabled
  70. from pylint.constants import PY39_PLUS
  71. from pylint.interfaces import HIGH, INFERENCE, INFERENCE_FAILURE, IAstroidChecker
  72. from pylint.utils import get_global_option
  73. if sys.version_info >= (3, 8):
  74. from typing import Literal
  75. else:
  76. from typing_extensions import Literal
  77. SPECIAL_OBJ = re.compile("^_{2}[a-z]+_{2}$")
  78. FUTURE = "__future__"
  79. # regexp for ignored argument name
  80. IGNORED_ARGUMENT_NAMES = re.compile("_.*|^ignored_|^unused_")
  81. # In Python 3.7 abc has a Python implementation which is preferred
  82. # by astroid. Unfortunately this also messes up our explicit checks
  83. # for `abc`
  84. METACLASS_NAME_TRANSFORMS = {"_py_abc": "abc"}
  85. TYPING_TYPE_CHECKS_GUARDS = frozenset({"typing.TYPE_CHECKING", "TYPE_CHECKING"})
  86. BUILTIN_RANGE = "builtins.range"
  87. TYPING_MODULE = "typing"
  88. TYPING_NAMES = frozenset(
  89. {
  90. "Any",
  91. "Callable",
  92. "ClassVar",
  93. "Generic",
  94. "Optional",
  95. "Tuple",
  96. "Type",
  97. "TypeVar",
  98. "Union",
  99. "AbstractSet",
  100. "ByteString",
  101. "Container",
  102. "ContextManager",
  103. "Hashable",
  104. "ItemsView",
  105. "Iterable",
  106. "Iterator",
  107. "KeysView",
  108. "Mapping",
  109. "MappingView",
  110. "MutableMapping",
  111. "MutableSequence",
  112. "MutableSet",
  113. "Sequence",
  114. "Sized",
  115. "ValuesView",
  116. "Awaitable",
  117. "AsyncIterator",
  118. "AsyncIterable",
  119. "Coroutine",
  120. "Collection",
  121. "AsyncGenerator",
  122. "AsyncContextManager",
  123. "Reversible",
  124. "SupportsAbs",
  125. "SupportsBytes",
  126. "SupportsComplex",
  127. "SupportsFloat",
  128. "SupportsInt",
  129. "SupportsRound",
  130. "Counter",
  131. "Deque",
  132. "Dict",
  133. "DefaultDict",
  134. "List",
  135. "Set",
  136. "FrozenSet",
  137. "NamedTuple",
  138. "Generator",
  139. "AnyStr",
  140. "Text",
  141. "Pattern",
  142. "BinaryIO",
  143. }
  144. )
  145. class VariableVisitConsumerAction(Enum):
  146. """Used after _visit_consumer to determine the action to be taken
  147. Continue -> continue loop to next consumer
  148. Return -> return and thereby break the loop
  149. Consume -> consume the found nodes (second return value) and return
  150. """
  151. CONTINUE = 0
  152. RETURN = 1
  153. CONSUME = 2
  154. def _is_from_future_import(stmt, name):
  155. """Check if the name is a future import from another module."""
  156. try:
  157. module = stmt.do_import_module(stmt.modname)
  158. except astroid.AstroidBuildingException:
  159. return None
  160. for local_node in module.locals.get(name, []):
  161. if isinstance(local_node, nodes.ImportFrom) and local_node.modname == FUTURE:
  162. return True
  163. return None
  164. def in_for_else_branch(parent, stmt):
  165. """Returns True if stmt in inside the else branch for a parent For stmt."""
  166. return isinstance(parent, nodes.For) and any(
  167. else_stmt.parent_of(stmt) or else_stmt == stmt for else_stmt in parent.orelse
  168. )
  169. @lru_cache(maxsize=1000)
  170. def overridden_method(klass, name):
  171. """get overridden method if any"""
  172. try:
  173. parent = next(klass.local_attr_ancestors(name))
  174. except (StopIteration, KeyError):
  175. return None
  176. try:
  177. meth_node = parent[name]
  178. except KeyError:
  179. # We have found an ancestor defining <name> but it's not in the local
  180. # dictionary. This may happen with astroid built from living objects.
  181. return None
  182. if isinstance(meth_node, nodes.FunctionDef):
  183. return meth_node
  184. return None
  185. def _get_unpacking_extra_info(node, inferred):
  186. """return extra information to add to the message for unpacking-non-sequence
  187. and unbalanced-tuple-unpacking errors
  188. """
  189. more = ""
  190. inferred_module = inferred.root().name
  191. if node.root().name == inferred_module:
  192. if node.lineno == inferred.lineno:
  193. more = f" {inferred.as_string()}"
  194. elif inferred.lineno:
  195. more = f" defined at line {inferred.lineno}"
  196. elif inferred.lineno:
  197. more = f" defined at line {inferred.lineno} of {inferred_module}"
  198. return more
  199. def _detect_global_scope(node, frame, defframe):
  200. """Detect that the given frames shares a global
  201. scope.
  202. Two frames shares a global scope when neither
  203. of them are hidden under a function scope, as well
  204. as any of parent scope of them, until the root scope.
  205. In this case, depending from something defined later on
  206. will not work, because it is still undefined.
  207. Example:
  208. class A:
  209. # B has the same global scope as `C`, leading to a NameError.
  210. class B(C): ...
  211. class C: ...
  212. """
  213. def_scope = scope = None
  214. if frame and frame.parent:
  215. scope = frame.parent.scope()
  216. if defframe and defframe.parent:
  217. def_scope = defframe.parent.scope()
  218. if isinstance(frame, nodes.FunctionDef):
  219. # If the parent of the current node is a
  220. # function, then it can be under its scope
  221. # (defined in, which doesn't concern us) or
  222. # the `->` part of annotations. The same goes
  223. # for annotations of function arguments, they'll have
  224. # their parent the Arguments node.
  225. if not isinstance(node.parent, (nodes.FunctionDef, nodes.Arguments)):
  226. return False
  227. elif any(
  228. not isinstance(f, (nodes.ClassDef, nodes.Module)) for f in (frame, defframe)
  229. ):
  230. # Not interested in other frames, since they are already
  231. # not in a global scope.
  232. return False
  233. break_scopes = []
  234. for current_scope in (scope, def_scope):
  235. # Look for parent scopes. If there is anything different
  236. # than a module or a class scope, then they frames don't
  237. # share a global scope.
  238. parent_scope = current_scope
  239. while parent_scope:
  240. if not isinstance(parent_scope, (nodes.ClassDef, nodes.Module)):
  241. break_scopes.append(parent_scope)
  242. break
  243. if parent_scope.parent:
  244. parent_scope = parent_scope.parent.scope()
  245. else:
  246. break
  247. if break_scopes and len(set(break_scopes)) != 1:
  248. # Store different scopes than expected.
  249. # If the stored scopes are, in fact, the very same, then it means
  250. # that the two frames (frame and defframe) shares the same scope,
  251. # and we could apply our lineno analysis over them.
  252. # For instance, this works when they are inside a function, the node
  253. # that uses a definition and the definition itself.
  254. return False
  255. # At this point, we are certain that frame and defframe shares a scope
  256. # and the definition of the first depends on the second.
  257. return frame.lineno < defframe.lineno
  258. def _infer_name_module(node, name):
  259. context = astroid.context.InferenceContext()
  260. context.lookupname = name
  261. return node.infer(context, asname=False)
  262. def _fix_dot_imports(not_consumed):
  263. """Try to fix imports with multiple dots, by returning a dictionary
  264. with the import names expanded. The function unflattens root imports,
  265. like 'xml' (when we have both 'xml.etree' and 'xml.sax'), to 'xml.etree'
  266. and 'xml.sax' respectively.
  267. """
  268. names = {}
  269. for name, stmts in not_consumed.items():
  270. if any(
  271. isinstance(stmt, nodes.AssignName)
  272. and isinstance(stmt.assign_type(), nodes.AugAssign)
  273. for stmt in stmts
  274. ):
  275. continue
  276. for stmt in stmts:
  277. if not isinstance(stmt, (nodes.ImportFrom, nodes.Import)):
  278. continue
  279. for imports in stmt.names:
  280. second_name = None
  281. import_module_name = imports[0]
  282. if import_module_name == "*":
  283. # In case of wildcard imports,
  284. # pick the name from inside the imported module.
  285. second_name = name
  286. else:
  287. name_matches_dotted_import = False
  288. if (
  289. import_module_name.startswith(name)
  290. and import_module_name.find(".") > -1
  291. ):
  292. name_matches_dotted_import = True
  293. if name_matches_dotted_import or name in imports:
  294. # Most likely something like 'xml.etree',
  295. # which will appear in the .locals as 'xml'.
  296. # Only pick the name if it wasn't consumed.
  297. second_name = import_module_name
  298. if second_name and second_name not in names:
  299. names[second_name] = stmt
  300. return sorted(names.items(), key=lambda a: a[1].fromlineno)
  301. def _find_frame_imports(name, frame):
  302. """
  303. Detect imports in the frame, with the required
  304. *name*. Such imports can be considered assignments.
  305. Returns True if an import for the given name was found.
  306. """
  307. imports = frame.nodes_of_class((nodes.Import, nodes.ImportFrom))
  308. for import_node in imports:
  309. for import_name, import_alias in import_node.names:
  310. # If the import uses an alias, check only that.
  311. # Otherwise, check only the import name.
  312. if import_alias:
  313. if import_alias == name:
  314. return True
  315. elif import_name and import_name == name:
  316. return True
  317. return None
  318. def _import_name_is_global(stmt, global_names):
  319. for import_name, import_alias in stmt.names:
  320. # If the import uses an alias, check only that.
  321. # Otherwise, check only the import name.
  322. if import_alias:
  323. if import_alias in global_names:
  324. return True
  325. elif import_name in global_names:
  326. return True
  327. return False
  328. def _flattened_scope_names(iterator):
  329. values = (set(stmt.names) for stmt in iterator)
  330. return set(itertools.chain.from_iterable(values))
  331. def _assigned_locally(name_node):
  332. """
  333. Checks if name_node has corresponding assign statement in same scope
  334. """
  335. assign_stmts = name_node.scope().nodes_of_class(nodes.AssignName)
  336. return any(a.name == name_node.name for a in assign_stmts)
  337. def _is_type_checking_import(node: Union[nodes.Import, nodes.ImportFrom]) -> bool:
  338. """Check if an import node is guarded by a TYPE_CHECKS guard"""
  339. return any(
  340. isinstance(ancestor, nodes.If)
  341. and ancestor.test.as_string() in TYPING_TYPE_CHECKS_GUARDS
  342. for ancestor in node.node_ancestors()
  343. )
  344. def _has_locals_call_after_node(stmt, scope):
  345. skip_nodes = (
  346. nodes.FunctionDef,
  347. nodes.ClassDef,
  348. nodes.Import,
  349. nodes.ImportFrom,
  350. )
  351. for call in scope.nodes_of_class(nodes.Call, skip_klass=skip_nodes):
  352. inferred = utils.safe_infer(call.func)
  353. if (
  354. utils.is_builtin_object(inferred)
  355. and getattr(inferred, "name", None) == "locals"
  356. ):
  357. if stmt.lineno < call.lineno:
  358. return True
  359. return False
  360. MSGS = {
  361. "E0601": (
  362. "Using variable %r before assignment",
  363. "used-before-assignment",
  364. "Used when a local variable is accessed before its assignment.",
  365. ),
  366. "E0602": (
  367. "Undefined variable %r",
  368. "undefined-variable",
  369. "Used when an undefined variable is accessed.",
  370. ),
  371. "E0603": (
  372. "Undefined variable name %r in __all__",
  373. "undefined-all-variable",
  374. "Used when an undefined variable name is referenced in __all__.",
  375. ),
  376. "E0604": (
  377. "Invalid object %r in __all__, must contain only strings",
  378. "invalid-all-object",
  379. "Used when an invalid (non-string) object occurs in __all__.",
  380. ),
  381. "E0605": (
  382. "Invalid format for __all__, must be tuple or list",
  383. "invalid-all-format",
  384. "Used when __all__ has an invalid format.",
  385. ),
  386. "E0611": (
  387. "No name %r in module %r",
  388. "no-name-in-module",
  389. "Used when a name cannot be found in a module.",
  390. ),
  391. "W0601": (
  392. "Global variable %r undefined at the module level",
  393. "global-variable-undefined",
  394. 'Used when a variable is defined through the "global" statement '
  395. "but the variable is not defined in the module scope.",
  396. ),
  397. "W0602": (
  398. "Using global for %r but no assignment is done",
  399. "global-variable-not-assigned",
  400. 'Used when a variable is defined through the "global" statement '
  401. "but no assignment to this variable is done.",
  402. ),
  403. "W0603": (
  404. "Using the global statement", # W0121
  405. "global-statement",
  406. 'Used when you use the "global" statement to update a global '
  407. "variable. Pylint just try to discourage this "
  408. "usage. That doesn't mean you cannot use it !",
  409. ),
  410. "W0604": (
  411. "Using the global statement at the module level", # W0103
  412. "global-at-module-level",
  413. 'Used when you use the "global" statement at the module level '
  414. "since it has no effect",
  415. ),
  416. "W0611": (
  417. "Unused %s",
  418. "unused-import",
  419. "Used when an imported module or variable is not used.",
  420. ),
  421. "W0612": (
  422. "Unused variable %r",
  423. "unused-variable",
  424. "Used when a variable is defined but not used.",
  425. ),
  426. "W0613": (
  427. "Unused argument %r",
  428. "unused-argument",
  429. "Used when a function or method argument is not used.",
  430. ),
  431. "W0614": (
  432. "Unused import(s) %s from wildcard import of %s",
  433. "unused-wildcard-import",
  434. "Used when an imported module or variable is not used from a "
  435. "`'from X import *'` style import.",
  436. ),
  437. "W0621": (
  438. "Redefining name %r from outer scope (line %s)",
  439. "redefined-outer-name",
  440. "Used when a variable's name hides a name defined in the outer scope.",
  441. ),
  442. "W0622": (
  443. "Redefining built-in %r",
  444. "redefined-builtin",
  445. "Used when a variable or function override a built-in.",
  446. ),
  447. "W0631": (
  448. "Using possibly undefined loop variable %r",
  449. "undefined-loop-variable",
  450. "Used when a loop variable (i.e. defined by a for loop or "
  451. "a list comprehension or a generator expression) is used outside "
  452. "the loop.",
  453. ),
  454. "W0632": (
  455. "Possible unbalanced tuple unpacking with "
  456. "sequence%s: "
  457. "left side has %d label(s), right side has %d value(s)",
  458. "unbalanced-tuple-unpacking",
  459. "Used when there is an unbalanced tuple unpacking in assignment",
  460. {"old_names": [("E0632", "old-unbalanced-tuple-unpacking")]},
  461. ),
  462. "E0633": (
  463. "Attempting to unpack a non-sequence%s",
  464. "unpacking-non-sequence",
  465. "Used when something which is not "
  466. "a sequence is used in an unpack assignment",
  467. {"old_names": [("W0633", "old-unpacking-non-sequence")]},
  468. ),
  469. "W0640": (
  470. "Cell variable %s defined in loop",
  471. "cell-var-from-loop",
  472. "A variable used in a closure is defined in a loop. "
  473. "This will result in all closures using the same value for "
  474. "the closed-over variable.",
  475. ),
  476. "W0641": (
  477. "Possibly unused variable %r",
  478. "possibly-unused-variable",
  479. "Used when a variable is defined but might not be used. "
  480. "The possibility comes from the fact that locals() might be used, "
  481. "which could consume or not the said variable",
  482. ),
  483. "W0642": (
  484. "Invalid assignment to %s in method",
  485. "self-cls-assignment",
  486. "Invalid assignment to self or cls in instance or class method "
  487. "respectively.",
  488. ),
  489. }
  490. ScopeConsumer = collections.namedtuple(
  491. "ScopeConsumer", "to_consume consumed scope_type"
  492. )
  493. class NamesConsumer:
  494. """
  495. A simple class to handle consumed, to consume and scope type info of node locals
  496. """
  497. def __init__(self, node, scope_type):
  498. self._atomic = ScopeConsumer(copy.copy(node.locals), {}, scope_type)
  499. self.node = node
  500. def __repr__(self):
  501. to_consumes = [f"{k}->{v}" for k, v in self._atomic.to_consume.items()]
  502. consumed = [f"{k}->{v}" for k, v in self._atomic.consumed.items()]
  503. to_consumes = ", ".join(to_consumes)
  504. consumed = ", ".join(consumed)
  505. return f"""
  506. to_consume : {to_consumes}
  507. consumed : {consumed}
  508. scope_type : {self._atomic.scope_type}
  509. """
  510. def __iter__(self):
  511. return iter(self._atomic)
  512. @property
  513. def to_consume(self):
  514. return self._atomic.to_consume
  515. @property
  516. def consumed(self):
  517. return self._atomic.consumed
  518. @property
  519. def scope_type(self):
  520. return self._atomic.scope_type
  521. def mark_as_consumed(self, name, consumed_nodes):
  522. """
  523. Mark the given nodes as consumed for the name.
  524. If all of the nodes for the name were consumed, delete the name from
  525. the to_consume dictionary
  526. """
  527. unconsumed = [n for n in self.to_consume[name] if n not in set(consumed_nodes)]
  528. self.consumed[name] = consumed_nodes
  529. if unconsumed:
  530. self.to_consume[name] = unconsumed
  531. else:
  532. del self.to_consume[name]
  533. def get_next_to_consume(self, node):
  534. """
  535. Return a list of the nodes that define `node` from this scope.
  536. Return None to indicate a special case that needs to be handled by the caller.
  537. """
  538. name = node.name
  539. parent_node = node.parent
  540. found_nodes = self.to_consume.get(name)
  541. if (
  542. found_nodes
  543. and isinstance(parent_node, nodes.Assign)
  544. and parent_node == found_nodes[0].parent
  545. ):
  546. lhs = found_nodes[0].parent.targets[0]
  547. if lhs.name == name: # this name is defined in this very statement
  548. found_nodes = None
  549. if (
  550. found_nodes
  551. and isinstance(parent_node, nodes.For)
  552. and parent_node.iter == node
  553. and parent_node.target in found_nodes
  554. ):
  555. found_nodes = None
  556. # Filter out assignments in ExceptHandlers that node is not contained in
  557. if found_nodes:
  558. found_nodes = [
  559. n
  560. for n in found_nodes
  561. if not isinstance(n.statement(), nodes.ExceptHandler)
  562. or n.statement().parent_of(node)
  563. ]
  564. return found_nodes
  565. # pylint: disable=too-many-public-methods
  566. class VariablesChecker(BaseChecker):
  567. """checks for
  568. * unused variables / imports
  569. * undefined variables
  570. * redefinition of variable from builtins or from an outer scope
  571. * use of variable before assignment
  572. * __all__ consistency
  573. * self/cls assignment
  574. """
  575. __implements__ = IAstroidChecker
  576. name = "variables"
  577. msgs = MSGS
  578. priority = -1
  579. options = (
  580. (
  581. "init-import",
  582. {
  583. "default": 0,
  584. "type": "yn",
  585. "metavar": "<y or n>",
  586. "help": "Tells whether we should check for unused import in "
  587. "__init__ files.",
  588. },
  589. ),
  590. (
  591. "dummy-variables-rgx",
  592. {
  593. "default": "_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_",
  594. "type": "regexp",
  595. "metavar": "<regexp>",
  596. "help": "A regular expression matching the name of dummy "
  597. "variables (i.e. expected to not be used).",
  598. },
  599. ),
  600. (
  601. "additional-builtins",
  602. {
  603. "default": (),
  604. "type": "csv",
  605. "metavar": "<comma separated list>",
  606. "help": "List of additional names supposed to be defined in "
  607. "builtins. Remember that you should avoid defining new builtins "
  608. "when possible.",
  609. },
  610. ),
  611. (
  612. "callbacks",
  613. {
  614. "default": ("cb_", "_cb"),
  615. "type": "csv",
  616. "metavar": "<callbacks>",
  617. "help": "List of strings which can identify a callback "
  618. "function by name. A callback name must start or "
  619. "end with one of those strings.",
  620. },
  621. ),
  622. (
  623. "redefining-builtins-modules",
  624. {
  625. "default": (
  626. "six.moves",
  627. "past.builtins",
  628. "future.builtins",
  629. "builtins",
  630. "io",
  631. ),
  632. "type": "csv",
  633. "metavar": "<comma separated list>",
  634. "help": "List of qualified module names which can have objects "
  635. "that can redefine builtins.",
  636. },
  637. ),
  638. (
  639. "ignored-argument-names",
  640. {
  641. "default": IGNORED_ARGUMENT_NAMES,
  642. "type": "regexp",
  643. "metavar": "<regexp>",
  644. "help": "Argument names that match this expression will be "
  645. "ignored. Default to name with leading underscore.",
  646. },
  647. ),
  648. (
  649. "allow-global-unused-variables",
  650. {
  651. "default": True,
  652. "type": "yn",
  653. "metavar": "<y or n>",
  654. "help": "Tells whether unused global variables should be treated as a violation.",
  655. },
  656. ),
  657. (
  658. "allowed-redefined-builtins",
  659. {
  660. "default": (),
  661. "type": "csv",
  662. "metavar": "<comma separated list>",
  663. "help": "List of names allowed to shadow builtins",
  664. },
  665. ),
  666. )
  667. def __init__(self, linter=None):
  668. super().__init__(linter)
  669. self._to_consume: List[NamesConsumer] = []
  670. self._checking_mod_attr = None
  671. self._loop_variables = []
  672. self._type_annotation_names = []
  673. self._postponed_evaluation_enabled = False
  674. def open(self) -> None:
  675. """Called when loading the checker"""
  676. self._is_undefined_variable_enabled = self.linter.is_message_enabled(
  677. "undefined-variable"
  678. )
  679. self._is_used_before_assignment_enabled = self.linter.is_message_enabled(
  680. "used-before-assignment"
  681. )
  682. self._is_undefined_loop_variable_enabled = self.linter.is_message_enabled(
  683. "undefined-loop-variable"
  684. )
  685. @utils.check_messages("redefined-outer-name")
  686. def visit_for(self, node: nodes.For) -> None:
  687. assigned_to = [a.name for a in node.target.nodes_of_class(nodes.AssignName)]
  688. # Only check variables that are used
  689. dummy_rgx = self.config.dummy_variables_rgx
  690. assigned_to = [var for var in assigned_to if not dummy_rgx.match(var)]
  691. for variable in assigned_to:
  692. for outer_for, outer_variables in self._loop_variables:
  693. if variable in outer_variables and not in_for_else_branch(
  694. outer_for, node
  695. ):
  696. self.add_message(
  697. "redefined-outer-name",
  698. args=(variable, outer_for.fromlineno),
  699. node=node,
  700. )
  701. break
  702. self._loop_variables.append((node, assigned_to))
  703. @utils.check_messages("redefined-outer-name")
  704. def leave_for(self, node: nodes.For) -> None:
  705. self._loop_variables.pop()
  706. self._store_type_annotation_names(node)
  707. def visit_module(self, node: nodes.Module) -> None:
  708. """visit module : update consumption analysis variable
  709. checks globals doesn't overrides builtins
  710. """
  711. self._to_consume = [NamesConsumer(node, "module")]
  712. self._postponed_evaluation_enabled = is_postponed_evaluation_enabled(node)
  713. for name, stmts in node.locals.items():
  714. if utils.is_builtin(name):
  715. if self._should_ignore_redefined_builtin(stmts[0]) or name == "__doc__":
  716. continue
  717. self.add_message("redefined-builtin", args=name, node=stmts[0])
  718. @utils.check_messages(
  719. "unused-import",
  720. "unused-wildcard-import",
  721. "redefined-builtin",
  722. "undefined-all-variable",
  723. "invalid-all-object",
  724. "invalid-all-format",
  725. "unused-variable",
  726. )
  727. def leave_module(self, node: nodes.Module) -> None:
  728. """leave module: check globals"""
  729. assert len(self._to_consume) == 1
  730. self._check_metaclasses(node)
  731. not_consumed = self._to_consume.pop().to_consume
  732. # attempt to check for __all__ if defined
  733. if "__all__" in node.locals:
  734. self._check_all(node, not_consumed)
  735. # check for unused globals
  736. self._check_globals(not_consumed)
  737. # don't check unused imports in __init__ files
  738. if not self.config.init_import and node.package:
  739. return
  740. self._check_imports(not_consumed)
  741. def visit_classdef(self, node: nodes.ClassDef) -> None:
  742. """visit class: update consumption analysis variable"""
  743. self._to_consume.append(NamesConsumer(node, "class"))
  744. def leave_classdef(self, _: nodes.ClassDef) -> None:
  745. """leave class: update consumption analysis variable"""
  746. # do not check for not used locals here (no sense)
  747. self._to_consume.pop()
  748. def visit_lambda(self, node: nodes.Lambda) -> None:
  749. """visit lambda: update consumption analysis variable"""
  750. self._to_consume.append(NamesConsumer(node, "lambda"))
  751. def leave_lambda(self, _: nodes.Lambda) -> None:
  752. """leave lambda: update consumption analysis variable"""
  753. # do not check for not used locals here
  754. self._to_consume.pop()
  755. def visit_generatorexp(self, node: nodes.GeneratorExp) -> None:
  756. """visit genexpr: update consumption analysis variable"""
  757. self._to_consume.append(NamesConsumer(node, "comprehension"))
  758. def leave_generatorexp(self, _: nodes.GeneratorExp) -> None:
  759. """leave genexpr: update consumption analysis variable"""
  760. # do not check for not used locals here
  761. self._to_consume.pop()
  762. def visit_dictcomp(self, node: nodes.DictComp) -> None:
  763. """visit dictcomp: update consumption analysis variable"""
  764. self._to_consume.append(NamesConsumer(node, "comprehension"))
  765. def leave_dictcomp(self, _: nodes.DictComp) -> None:
  766. """leave dictcomp: update consumption analysis variable"""
  767. # do not check for not used locals here
  768. self._to_consume.pop()
  769. def visit_setcomp(self, node: nodes.SetComp) -> None:
  770. """visit setcomp: update consumption analysis variable"""
  771. self._to_consume.append(NamesConsumer(node, "comprehension"))
  772. def leave_setcomp(self, _: nodes.SetComp) -> None:
  773. """leave setcomp: update consumption analysis variable"""
  774. # do not check for not used locals here
  775. self._to_consume.pop()
  776. def visit_functiondef(self, node: nodes.FunctionDef) -> None:
  777. """visit function: update consumption analysis variable and check locals"""
  778. self._to_consume.append(NamesConsumer(node, "function"))
  779. if not (
  780. self.linter.is_message_enabled("redefined-outer-name")
  781. or self.linter.is_message_enabled("redefined-builtin")
  782. ):
  783. return
  784. globs = node.root().globals
  785. for name, stmt in node.items():
  786. if name in globs and not isinstance(stmt, nodes.Global):
  787. definition = globs[name][0]
  788. if (
  789. isinstance(definition, nodes.ImportFrom)
  790. and definition.modname == FUTURE
  791. ):
  792. # It is a __future__ directive, not a symbol.
  793. continue
  794. # Do not take in account redefined names for the purpose
  795. # of type checking.:
  796. if any(
  797. isinstance(definition.parent, nodes.If)
  798. and definition.parent.test.as_string() in TYPING_TYPE_CHECKS_GUARDS
  799. for definition in globs[name]
  800. ):
  801. continue
  802. line = definition.fromlineno
  803. if not self._is_name_ignored(stmt, name):
  804. self.add_message(
  805. "redefined-outer-name", args=(name, line), node=stmt
  806. )
  807. elif (
  808. utils.is_builtin(name)
  809. and not self._allowed_redefined_builtin(name)
  810. and not self._should_ignore_redefined_builtin(stmt)
  811. ):
  812. # do not print Redefining builtin for additional builtins
  813. self.add_message("redefined-builtin", args=name, node=stmt)
  814. def leave_functiondef(self, node: nodes.FunctionDef) -> None:
  815. """leave function: check function's locals are consumed"""
  816. self._check_metaclasses(node)
  817. if node.type_comment_returns:
  818. self._store_type_annotation_node(node.type_comment_returns)
  819. if node.type_comment_args:
  820. for argument_annotation in node.type_comment_args:
  821. self._store_type_annotation_node(argument_annotation)
  822. not_consumed = self._to_consume.pop().to_consume
  823. if not (
  824. self.linter.is_message_enabled("unused-variable")
  825. or self.linter.is_message_enabled("possibly-unused-variable")
  826. or self.linter.is_message_enabled("unused-argument")
  827. ):
  828. return
  829. # Don't check arguments of function which are only raising an exception.
  830. if utils.is_error(node):
  831. return
  832. # Don't check arguments of abstract methods or within an interface.
  833. is_method = node.is_method()
  834. if is_method and node.is_abstract():
  835. return
  836. global_names = _flattened_scope_names(node.nodes_of_class(nodes.Global))
  837. nonlocal_names = _flattened_scope_names(node.nodes_of_class(nodes.Nonlocal))
  838. for name, stmts in not_consumed.items():
  839. self._check_is_unused(name, node, stmts[0], global_names, nonlocal_names)
  840. visit_asyncfunctiondef = visit_functiondef
  841. leave_asyncfunctiondef = leave_functiondef
  842. @utils.check_messages(
  843. "global-variable-undefined",
  844. "global-variable-not-assigned",
  845. "global-statement",
  846. "global-at-module-level",
  847. "redefined-builtin",
  848. )
  849. def visit_global(self, node: nodes.Global) -> None:
  850. """check names imported exists in the global scope"""
  851. frame = node.frame()
  852. if isinstance(frame, nodes.Module):
  853. self.add_message("global-at-module-level", node=node)
  854. return
  855. module = frame.root()
  856. default_message = True
  857. locals_ = node.scope().locals
  858. for name in node.names:
  859. try:
  860. assign_nodes = module.getattr(name)
  861. except astroid.NotFoundError:
  862. # unassigned global, skip
  863. assign_nodes = []
  864. not_defined_locally_by_import = not any(
  865. isinstance(local, nodes.Import) for local in locals_.get(name, ())
  866. )
  867. if (
  868. not utils.is_reassigned_after_current(node, name)
  869. and not_defined_locally_by_import
  870. ):
  871. self.add_message("global-variable-not-assigned", args=name, node=node)
  872. default_message = False
  873. continue
  874. for anode in assign_nodes:
  875. if (
  876. isinstance(anode, nodes.AssignName)
  877. and anode.name in module.special_attributes
  878. ):
  879. self.add_message("redefined-builtin", args=name, node=node)
  880. break
  881. if anode.frame() is module:
  882. # module level assignment
  883. break
  884. if isinstance(anode, nodes.FunctionDef) and anode.parent is module:
  885. # module level function assignment
  886. break
  887. else:
  888. if not_defined_locally_by_import:
  889. # global undefined at the module scope
  890. self.add_message("global-variable-undefined", args=name, node=node)
  891. default_message = False
  892. if default_message:
  893. self.add_message("global-statement", node=node)
  894. def visit_assignname(self, node: nodes.AssignName) -> None:
  895. if isinstance(node.assign_type(), nodes.AugAssign):
  896. self.visit_name(node)
  897. def visit_delname(self, node: nodes.DelName) -> None:
  898. self.visit_name(node)
  899. def visit_name(self, node: nodes.Name) -> None:
  900. """Don't add the 'utils.check_messages' decorator here!
  901. It's important that all 'Name' nodes are visited, otherwise the
  902. 'NamesConsumers' won't be correct.
  903. """
  904. stmt = node.statement()
  905. if stmt.fromlineno is None:
  906. # name node from an astroid built from live code, skip
  907. assert not stmt.root().file.endswith(".py")
  908. return
  909. self._undefined_and_used_before_checker(node, stmt)
  910. if self._is_undefined_loop_variable_enabled:
  911. self._loopvar_name(node)
  912. def _undefined_and_used_before_checker(
  913. self, node: nodes.Name, stmt: nodes.NodeNG
  914. ) -> None:
  915. frame = stmt.scope()
  916. start_index = len(self._to_consume) - 1
  917. # iterates through parent scopes, from the inner to the outer
  918. base_scope_type = self._to_consume[start_index].scope_type
  919. for i in range(start_index, -1, -1):
  920. current_consumer = self._to_consume[i]
  921. # Certain nodes shouldn't be checked as they get checked another time
  922. if self._should_node_be_skipped(node, current_consumer, i == start_index):
  923. continue
  924. action, found_nodes = self._check_consumer(
  925. node, stmt, frame, current_consumer, i, base_scope_type
  926. )
  927. if action is VariableVisitConsumerAction.CONTINUE:
  928. continue
  929. if action is VariableVisitConsumerAction.CONSUME:
  930. current_consumer.mark_as_consumed(node.name, found_nodes)
  931. if action in {
  932. VariableVisitConsumerAction.RETURN,
  933. VariableVisitConsumerAction.CONSUME,
  934. }:
  935. return
  936. # we have not found the name, if it isn't a builtin, that's an
  937. # undefined name !
  938. if (
  939. self._is_undefined_variable_enabled
  940. and not (
  941. node.name in nodes.Module.scope_attrs
  942. or utils.is_builtin(node.name)
  943. or node.name in self.config.additional_builtins
  944. or (
  945. node.name == "__class__"
  946. and isinstance(frame, nodes.FunctionDef)
  947. and frame.is_method()
  948. )
  949. )
  950. and not utils.node_ignores_exception(node, NameError)
  951. ):
  952. self.add_message("undefined-variable", args=node.name, node=node)
  953. def _should_node_be_skipped(
  954. self, node: nodes.Name, consumer: NamesConsumer, is_start_index: bool
  955. ) -> bool:
  956. """Tests a consumer and node for various conditions in which the node
  957. shouldn't be checked for the undefined-variable and used-before-assignment checks.
  958. """
  959. if consumer.scope_type == "class":
  960. # The list of base classes in the class definition is not part
  961. # of the class body.
  962. # If the current scope is a class scope but it's not the inner
  963. # scope, ignore it. This prevents to access this scope instead of
  964. # the globals one in function members when there are some common
  965. # names.
  966. if utils.is_ancestor_name(consumer.node, node) or (
  967. not is_start_index and self._ignore_class_scope(node)
  968. ):
  969. return True
  970. # Ignore inner class scope for keywords in class definition
  971. if isinstance(node.parent, nodes.Keyword) and isinstance(
  972. node.parent.parent, nodes.ClassDef
  973. ):
  974. return True
  975. elif consumer.scope_type == "function" and self._defined_in_function_definition(
  976. node, consumer.node
  977. ):
  978. # If the name node is used as a function default argument's value or as
  979. # a decorator, then start from the parent frame of the function instead
  980. # of the function frame - and thus open an inner class scope
  981. return True
  982. elif consumer.scope_type == "lambda" and utils.is_default_argument(
  983. node, consumer.node
  984. ):
  985. return True
  986. return False
  987. # pylint: disable=too-many-return-statements
  988. def _check_consumer(
  989. self,
  990. node: nodes.Name,
  991. stmt: nodes.NodeNG,
  992. frame: nodes.LocalsDictNodeNG,
  993. current_consumer: NamesConsumer,
  994. consumer_level: int,
  995. base_scope_type: Any,
  996. ) -> Tuple[VariableVisitConsumerAction, Optional[Any]]:
  997. """Checks a consumer for conditions that should trigger messages"""
  998. # If the name has already been consumed, only check it's not a loop
  999. # variable used outside the loop.
  1000. # Avoid the case where there are homonyms inside function scope and
  1001. # comprehension current scope (avoid bug #1731)
  1002. if node.name in current_consumer.consumed:
  1003. if utils.is_func_decorator(current_consumer.node) or not (
  1004. current_consumer.scope_type == "comprehension"
  1005. and self._has_homonym_in_upper_function_scope(node, consumer_level)
  1006. ):
  1007. self._check_late_binding_closure(node)
  1008. self._loopvar_name(node)
  1009. return (VariableVisitConsumerAction.RETURN, None)
  1010. found_nodes = current_consumer.get_next_to_consume(node)
  1011. if found_nodes is None:
  1012. return (VariableVisitConsumerAction.CONTINUE, None)
  1013. if not found_nodes:
  1014. self.add_message("used-before-assignment", args=node.name, node=node)
  1015. return (VariableVisitConsumerAction.RETURN, found_nodes)
  1016. self._check_late_binding_closure(node)
  1017. if not (
  1018. self._is_undefined_variable_enabled
  1019. or self._is_used_before_assignment_enabled
  1020. ):
  1021. return (VariableVisitConsumerAction.CONSUME, found_nodes)
  1022. defnode = utils.assign_parent(found_nodes[0])
  1023. defstmt = defnode.statement()
  1024. defframe = defstmt.frame()
  1025. # The class reuses itself in the class scope.
  1026. is_recursive_klass = (
  1027. frame is defframe
  1028. and defframe.parent_of(node)
  1029. and isinstance(defframe, nodes.ClassDef)
  1030. and node.name == defframe.name
  1031. )
  1032. if (
  1033. is_recursive_klass
  1034. and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
  1035. and (
  1036. not utils.is_default_argument(node)
  1037. or node.scope().parent.scope() is not defframe
  1038. )
  1039. ):
  1040. # Self-referential class references are fine in lambda's --
  1041. # As long as they are not part of the default argument directly
  1042. # under the scope of the parent self-referring class.
  1043. # Example of valid default argument:
  1044. # class MyName3:
  1045. # myattr = 1
  1046. # mylambda3 = lambda: lambda a=MyName3: a
  1047. # Example of invalid default argument:
  1048. # class MyName4:
  1049. # myattr = 1
  1050. # mylambda4 = lambda a=MyName4: lambda: a
  1051. # If the above conditional is True,
  1052. # there is no possibility of undefined-variable
  1053. # Also do not consume class name
  1054. # (since consuming blocks subsequent checks)
  1055. # -- quit
  1056. return (VariableVisitConsumerAction.RETURN, None)
  1057. (
  1058. maybe_before_assign,
  1059. annotation_return,
  1060. use_outer_definition,
  1061. ) = self._is_variable_violation(
  1062. node,
  1063. defnode,
  1064. stmt,
  1065. defstmt,
  1066. frame,
  1067. defframe,
  1068. base_scope_type,
  1069. is_recursive_klass,
  1070. )
  1071. if use_outer_definition:
  1072. return (VariableVisitConsumerAction.CONTINUE, None)
  1073. if (
  1074. maybe_before_assign
  1075. and not utils.is_defined_before(node)
  1076. and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
  1077. ):
  1078. # Used and defined in the same place, e.g `x += 1` and `del x`
  1079. defined_by_stmt = defstmt is stmt and isinstance(
  1080. node, (nodes.DelName, nodes.AssignName)
  1081. )
  1082. if (
  1083. is_recursive_klass
  1084. or defined_by_stmt
  1085. or annotation_return
  1086. or isinstance(defstmt, nodes.Delete)
  1087. ):
  1088. if not utils.node_ignores_exception(node, NameError):
  1089. # Handle postponed evaluation of annotations
  1090. if not (
  1091. self._postponed_evaluation_enabled
  1092. and isinstance(
  1093. stmt,
  1094. (
  1095. nodes.AnnAssign,
  1096. nodes.FunctionDef,
  1097. nodes.Arguments,
  1098. ),
  1099. )
  1100. and node.name in node.root().locals
  1101. ):
  1102. self.add_message(
  1103. "undefined-variable", args=node.name, node=node
  1104. )
  1105. return (VariableVisitConsumerAction.CONSUME, found_nodes)
  1106. elif base_scope_type != "lambda":
  1107. # E0601 may *not* occurs in lambda scope.
  1108. # Handle postponed evaluation of annotations
  1109. if not (
  1110. self._postponed_evaluation_enabled
  1111. and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
  1112. ):
  1113. self.add_message(
  1114. "used-before-assignment", args=node.name, node=node
  1115. )
  1116. return (VariableVisitConsumerAction.CONSUME, found_nodes)
  1117. elif base_scope_type == "lambda":
  1118. # E0601 can occur in class-level scope in lambdas, as in
  1119. # the following example:
  1120. # class A:
  1121. # x = lambda attr: f + attr
  1122. # f = 42
  1123. if isinstance(frame, nodes.ClassDef) and node.name in frame.locals:
  1124. if isinstance(node.parent, nodes.Arguments):
  1125. if stmt.fromlineno <= defstmt.fromlineno:
  1126. # Doing the following is fine:
  1127. # class A:
  1128. # x = 42
  1129. # y = lambda attr=x: attr
  1130. self.add_message(
  1131. "used-before-assignment",
  1132. args=node.name,
  1133. node=node,
  1134. )
  1135. else:
  1136. self.add_message(
  1137. "undefined-variable", args=node.name, node=node
  1138. )
  1139. return (VariableVisitConsumerAction.CONSUME, found_nodes)
  1140. elif current_consumer.scope_type == "lambda":
  1141. self.add_message("undefined-variable", args=node.name, node=node)
  1142. return (VariableVisitConsumerAction.CONSUME, found_nodes)
  1143. elif self._is_only_type_assignment(node, defstmt):
  1144. self.add_message("undefined-variable", args=node.name, node=node)
  1145. return (VariableVisitConsumerAction.CONSUME, found_nodes)
  1146. elif isinstance(defstmt, nodes.ClassDef):
  1147. is_first_level_ref = self._is_first_level_self_reference(node, defstmt)
  1148. if is_first_level_ref == 2:
  1149. self.add_message("used-before-assignment", node=node, args=node.name)
  1150. if is_first_level_ref:
  1151. return (VariableVisitConsumerAction.RETURN, None)
  1152. elif isinstance(defnode, nodes.NamedExpr):
  1153. if isinstance(defnode.parent, nodes.IfExp):
  1154. if self._is_never_evaluated(defnode, defnode.parent):
  1155. self.add_message("undefined-variable", args=node.name, node=node)
  1156. return (VariableVisitConsumerAction.CONSUME, found_nodes)
  1157. return (VariableVisitConsumerAction.CONSUME, found_nodes)
  1158. @utils.check_messages("no-name-in-module")
  1159. def visit_import(self, node: nodes.Import) -> None:
  1160. """check modules attribute accesses"""
  1161. if not self._analyse_fallback_blocks and utils.is_from_fallback_block(node):
  1162. # No need to verify this, since ImportError is already
  1163. # handled by the client code.
  1164. return
  1165. if utils.is_node_in_guarded_import_block(node) is True:
  1166. # Don't verify import if part of guarded import block
  1167. # I.e. `sys.version_info` or `typing.TYPE_CHECKING`
  1168. return
  1169. for name, _ in node.names:
  1170. parts = name.split(".")
  1171. try:
  1172. module = next(_infer_name_module(node, parts[0]))
  1173. except astroid.ResolveError:
  1174. continue
  1175. if not isinstance(module, nodes.Module):
  1176. continue
  1177. self._check_module_attrs(node, module, parts[1:])
  1178. @utils.check_messages("no-name-in-module")
  1179. def visit_importfrom(self, node: nodes.ImportFrom) -> None:
  1180. """check modules attribute accesses"""
  1181. if not self._analyse_fallback_blocks and utils.is_from_fallback_block(node):
  1182. # No need to verify this, since ImportError is already
  1183. # handled by the client code.
  1184. return
  1185. if utils.is_node_in_guarded_import_block(node) is True:
  1186. # Don't verify import if part of guarded import block
  1187. # I.e. `sys.version_info` or `typing.TYPE_CHECKING`
  1188. return
  1189. name_parts = node.modname.split(".")
  1190. try:
  1191. module = node.do_import_module(name_parts[0])
  1192. except astroid.AstroidBuildingException:
  1193. return
  1194. module = self._check_module_attrs(node, module, name_parts[1:])
  1195. if not module:
  1196. return
  1197. for name, _ in node.names:
  1198. if name == "*":
  1199. continue
  1200. self._check_module_attrs(node, module, name.split("."))
  1201. @utils.check_messages(
  1202. "unbalanced-tuple-unpacking", "unpacking-non-sequence", "self-cls-assignment"
  1203. )
  1204. def visit_assign(self, node: nodes.Assign) -> None:
  1205. """Check unbalanced tuple unpacking for assignments
  1206. and unpacking non-sequences as well as in case self/cls
  1207. get assigned.
  1208. """
  1209. self._check_self_cls_assign(node)
  1210. if not isinstance(node.targets[0], (nodes.Tuple, nodes.List)):
  1211. return
  1212. targets = node.targets[0].itered()
  1213. try:
  1214. inferred = utils.safe_infer(node.value)
  1215. if inferred is not None:
  1216. self._check_unpacking(inferred, node, targets)
  1217. except astroid.InferenceError:
  1218. return
  1219. # listcomp have now also their scope
  1220. def visit_listcomp(self, node: nodes.ListComp) -> None:
  1221. """visit dictcomp: update consumption analysis variable"""
  1222. self._to_consume.append(NamesConsumer(node, "comprehension"))
  1223. def leave_listcomp(self, _: nodes.ListComp) -> None:
  1224. """leave dictcomp: update consumption analysis variable"""
  1225. # do not check for not used locals here
  1226. self._to_consume.pop()
  1227. def leave_assign(self, node: nodes.Assign) -> None:
  1228. self._store_type_annotation_names(node)
  1229. def leave_with(self, node: nodes.With) -> None:
  1230. self._store_type_annotation_names(node)
  1231. def visit_arguments(self, node: nodes.Arguments) -> None:
  1232. for annotation in node.type_comment_args:
  1233. self._store_type_annotation_node(annotation)
  1234. # Relying on other checker's options, which might not have been initialized yet.
  1235. @astroid.decorators.cachedproperty
  1236. def _analyse_fallback_blocks(self):
  1237. return get_global_option(self, "analyse-fallback-blocks", default=False)
  1238. @astroid.decorators.cachedproperty
  1239. def _ignored_modules(self):
  1240. return get_global_option(self, "ignored-modules", default=[])
  1241. @astroid.decorators.cachedproperty
  1242. def _allow_global_unused_variables(self):
  1243. return get_global_option(self, "allow-global-unused-variables", default=True)
  1244. @staticmethod
  1245. def _defined_in_function_definition(node, frame):
  1246. in_annotation_or_default_or_decorator = False
  1247. if isinstance(frame, nodes.FunctionDef) and node.statement() is frame:
  1248. in_annotation_or_default_or_decorator = (
  1249. (
  1250. node in frame.args.annotations
  1251. or node in frame.args.posonlyargs_annotations
  1252. or node in frame.args.kwonlyargs_annotations
  1253. or node is frame.args.varargannotation
  1254. or node is frame.args.kwargannotation
  1255. )
  1256. or frame.args.parent_of(node)
  1257. or (frame.decorators and frame.decorators.parent_of(node))
  1258. or (
  1259. frame.returns
  1260. and (node is frame.returns or frame.returns.parent_of(node))
  1261. )
  1262. )
  1263. return in_annotation_or_default_or_decorator
  1264. @staticmethod
  1265. def _in_lambda_or_comprehension_body(
  1266. node: nodes.NodeNG, frame: nodes.NodeNG
  1267. ) -> bool:
  1268. """return True if node within a lambda/comprehension body (or similar) and thus should not have access to class attributes in frame"""
  1269. child = node
  1270. parent = node.parent
  1271. while parent is not None:
  1272. if parent is frame:
  1273. return False
  1274. if isinstance(parent, nodes.Lambda) and child is not parent.args:
  1275. # Body of lambda should not have access to class attributes.
  1276. return True
  1277. if isinstance(parent, nodes.Comprehension) and child is not parent.iter:
  1278. # Only iter of list/set/dict/generator comprehension should have access.
  1279. return True
  1280. if isinstance(parent, nodes.ComprehensionScope) and not (
  1281. parent.generators and child is parent.generators[0]
  1282. ):
  1283. # Body of list/set/dict/generator comprehension should not have access to class attributes.
  1284. # Furthermore, only the first generator (if multiple) in comprehension should have access.
  1285. return True
  1286. child = parent
  1287. parent = parent.parent
  1288. return False
  1289. @staticmethod
  1290. def _is_variable_violation(
  1291. node: nodes.Name,
  1292. defnode,
  1293. stmt,
  1294. defstmt,
  1295. frame, # scope of statement of node
  1296. defframe,
  1297. base_scope_type,
  1298. is_recursive_klass,
  1299. ) -> Tuple[bool, bool, bool]:
  1300. # pylint: disable=too-many-nested-blocks
  1301. maybe_before_assign = True
  1302. annotation_return = False
  1303. use_outer_definition = False
  1304. if frame is not defframe:
  1305. maybe_before_assign = _detect_global_scope(node, frame, defframe)
  1306. elif defframe.parent is None:
  1307. # we are at the module level, check the name is not
  1308. # defined in builtins
  1309. if (
  1310. node.name in defframe.scope_attrs
  1311. or astroid.builtin_lookup(node.name)[1]
  1312. ):
  1313. maybe_before_assign = False
  1314. else:
  1315. # we are in a local scope, check the name is not
  1316. # defined in global or builtin scope
  1317. # skip this lookup if name is assigned later in function scope/lambda
  1318. # Note: the node.frame() is not the same as the `frame` argument which is
  1319. # equivalent to frame.statement().scope()
  1320. forbid_lookup = (
  1321. isinstance(frame, nodes.FunctionDef)
  1322. or isinstance(node.frame(), nodes.Lambda)
  1323. ) and _assigned_locally(node)
  1324. if not forbid_lookup and defframe.root().lookup(node.name)[1]:
  1325. maybe_before_assign = False
  1326. use_outer_definition = stmt == defstmt and not isinstance(
  1327. defnode, nodes.Comprehension
  1328. )
  1329. # check if we have a nonlocal
  1330. elif node.name in defframe.locals:
  1331. maybe_before_assign = not any(
  1332. isinstance(child, nodes.Nonlocal) and node.name in child.names
  1333. for child in defframe.get_children()
  1334. )
  1335. if (
  1336. base_scope_type == "lambda"
  1337. and isinstance(frame, nodes.ClassDef)
  1338. and node.name in frame.locals
  1339. ):
  1340. # This rule verifies that if the definition node of the
  1341. # checked name is an Arguments node and if the name
  1342. # is used a default value in the arguments defaults
  1343. # and the actual definition of the variable label
  1344. # is happening before the Arguments definition.
  1345. #
  1346. # bar = None
  1347. # foo = lambda bar=bar: bar
  1348. #
  1349. # In this case, maybe_before_assign should be False, otherwise
  1350. # it should be True.
  1351. maybe_before_assign = not (
  1352. isinstance(defnode, nodes.Arguments)
  1353. and node in defnode.defaults
  1354. and frame.locals[node.name][0].fromlineno < defstmt.fromlineno
  1355. )
  1356. elif isinstance(defframe, nodes.ClassDef) and isinstance(
  1357. frame, nodes.FunctionDef
  1358. ):
  1359. # Special rule for function return annotations,
  1360. # which uses the same name as the class where
  1361. # the function lives.
  1362. if node is frame.returns and defframe.parent_of(frame.returns):
  1363. maybe_before_assign = annotation_return = True
  1364. if (
  1365. maybe_before_assign
  1366. and defframe.name in defframe.locals
  1367. and defframe.locals[node.name][0].lineno < frame.lineno
  1368. ):
  1369. # Detect class assignments with the same
  1370. # name as the class. In this case, no warning
  1371. # should be raised.
  1372. maybe_before_assign = False
  1373. if isinstance(node.parent, nodes.Arguments):
  1374. maybe_before_assign = stmt.fromlineno <= defstmt.fromlineno
  1375. elif is_recursive_klass:
  1376. maybe_before_assign = True
  1377. else:
  1378. maybe_before_assign = (
  1379. maybe_before_assign and stmt.fromlineno <= defstmt.fromlineno
  1380. )
  1381. if maybe_before_assign and stmt.fromlineno == defstmt.fromlineno:
  1382. if (
  1383. isinstance(defframe, nodes.FunctionDef)
  1384. and frame is defframe
  1385. and defframe.parent_of(node)
  1386. and stmt is not defstmt
  1387. ):
  1388. # Single statement function, with the statement on the
  1389. # same line as the function definition
  1390. maybe_before_assign = False
  1391. elif (
  1392. isinstance( # pylint: disable=too-many-boolean-expressions
  1393. defstmt,
  1394. (
  1395. nodes.Assign,
  1396. nodes.AnnAssign,
  1397. nodes.AugAssign,
  1398. nodes.Expr,
  1399. nodes.Return,
  1400. ),
  1401. )
  1402. and (
  1403. isinstance(defstmt.value, nodes.IfExp)
  1404. or isinstance(defstmt.value, nodes.Lambda)
  1405. and isinstance(defstmt.value.body, nodes.IfExp)
  1406. )
  1407. and frame is defframe
  1408. and defframe.parent_of(node)
  1409. and stmt is defstmt
  1410. ):
  1411. # Single statement if, with assignment expression on same
  1412. # line as assignment
  1413. # x = b if (b := True) else False
  1414. maybe_before_assign = False
  1415. elif (
  1416. isinstance( # pylint: disable=too-many-boolean-expressions
  1417. defnode, nodes.NamedExpr
  1418. )
  1419. and frame is defframe
  1420. and defframe.parent_of(stmt)
  1421. and stmt is defstmt
  1422. and (
  1423. (
  1424. defnode.lineno == node.lineno
  1425. and defnode.col_offset < node.col_offset
  1426. )
  1427. or (defnode.lineno < node.lineno)
  1428. or (
  1429. # Issue in the `ast` module until py39
  1430. # Nodes in a multiline string have the same lineno
  1431. # Could be false-positive without check
  1432. not PY39_PLUS
  1433. and defnode.lineno == node.lineno
  1434. and isinstance(
  1435. defstmt,
  1436. (
  1437. nodes.Assign,
  1438. nodes.AnnAssign,
  1439. nodes.AugAssign,
  1440. nodes.Return,
  1441. ),
  1442. )
  1443. and isinstance(defstmt.value, nodes.JoinedStr)
  1444. )
  1445. )
  1446. ):
  1447. # Expressions, with assignment expressions
  1448. # Use only after assignment
  1449. # b = (c := 2) and c
  1450. maybe_before_assign = False
  1451. # Look for type checking definitions inside a type checking guard.
  1452. if isinstance(defstmt, (nodes.Import, nodes.ImportFrom)):
  1453. defstmt_parent = defstmt.parent
  1454. if (
  1455. isinstance(defstmt_parent, nodes.If)
  1456. and defstmt_parent.test.as_string() in TYPING_TYPE_CHECKS_GUARDS
  1457. ):
  1458. # Exempt those definitions that are used inside the type checking
  1459. # guard or that are defined in both type checking guard branches.
  1460. used_in_branch = defstmt_parent.parent_of(node)
  1461. defined_in_or_else = False
  1462. for definition in defstmt_parent.orelse:
  1463. if isinstance(definition, nodes.Assign):
  1464. defined_in_or_else = any(
  1465. target.name == node.name
  1466. for target in definition.targets
  1467. if isinstance(target, nodes.AssignName)
  1468. )
  1469. if defined_in_or_else:
  1470. break
  1471. if not used_in_branch and not defined_in_or_else:
  1472. maybe_before_assign = True
  1473. return maybe_before_assign, annotation_return, use_outer_definition
  1474. # pylint: disable-next=fixme
  1475. # TODO: The typing of `NodeNG.statement()` in astroid is non-specific
  1476. # After this has been updated the typing of `defstmt` should reflect this
  1477. # See: https://github.com/PyCQA/astroid/pull/1217
  1478. @staticmethod
  1479. def _is_only_type_assignment(node: nodes.Name, defstmt: nodes.NodeNG) -> bool:
  1480. """Check if variable only gets assigned a type and never a value"""
  1481. if not isinstance(defstmt, nodes.AnnAssign) or defstmt.value:
  1482. return False
  1483. defstmt_frame = defstmt.frame()
  1484. node_frame = node.frame()
  1485. parent = node
  1486. while parent is not defstmt_frame.parent:
  1487. parent_scope = parent.scope()
  1488. local_refs = parent_scope.locals.get(node.name, [])
  1489. for ref_node in local_refs:
  1490. # If local ref is in the same frame as our node, but on a later lineno
  1491. # we don't actually care about this local ref.
  1492. # Local refs are ordered, so we break.
  1493. # print(var)
  1494. # var = 1 # <- irrelevant
  1495. if defstmt_frame == node_frame and not ref_node.lineno < node.lineno:
  1496. break
  1497. # If the parent of the local refence is anything but a AnnAssign
  1498. # Or if the AnnAssign adds a value the variable will now have a value
  1499. # var = 1 # OR
  1500. # var: int = 1
  1501. if (
  1502. not isinstance(ref_node.parent, nodes.AnnAssign)
  1503. or ref_node.parent.value
  1504. ):
  1505. return False
  1506. parent = parent_scope.parent
  1507. return True
  1508. @staticmethod
  1509. def _is_first_level_self_reference(
  1510. node: nodes.Name, defstmt: nodes.ClassDef
  1511. ) -> Literal[0, 1, 2]:
  1512. """Check if a first level method's annotation or default values
  1513. refers to its own class.
  1514. Return values correspond to:
  1515. 0 = Continue
  1516. 1 = Break
  1517. 2 = Break + emit message
  1518. """
  1519. if (
  1520. node.frame().parent == defstmt
  1521. and node.statement(future=True) not in node.frame().body
  1522. ):
  1523. # Check if used as type annotation
  1524. # Break but don't emit message if postponed evaluation is enabled
  1525. if utils.is_node_in_type_annotation_context(node):
  1526. if not utils.is_postponed_evaluation_enabled(node):
  1527. return 2
  1528. return 1
  1529. # Check if used as default value by calling the class
  1530. if isinstance(node.parent, nodes.Call) and isinstance(
  1531. node.parent.parent, nodes.Arguments
  1532. ):
  1533. return 2
  1534. return 0
  1535. @staticmethod
  1536. def _is_never_evaluated(
  1537. defnode: nodes.NamedExpr, defnode_parent: nodes.IfExp
  1538. ) -> bool:
  1539. """Check if a NamedExpr is inside a side of if ... else that never
  1540. gets evaluated
  1541. """
  1542. inferred_test = utils.safe_infer(defnode_parent.test)
  1543. if isinstance(inferred_test, nodes.Const):
  1544. if inferred_test.value is True and defnode == defnode_parent.orelse:
  1545. return True
  1546. if inferred_test.value is False and defnode == defnode_parent.body:
  1547. return True
  1548. return False
  1549. def _ignore_class_scope(self, node):
  1550. """
  1551. Return True if the node is in a local class scope, as an assignment.
  1552. :param node: Node considered
  1553. :type node: astroid.Node
  1554. :return: True if the node is in a local class scope, as an assignment. False otherwise.
  1555. :rtype: bool
  1556. """
  1557. # Detect if we are in a local class scope, as an assignment.
  1558. # For example, the following is fair game.
  1559. #
  1560. # class A:
  1561. # b = 1
  1562. # c = lambda b=b: b * b
  1563. #
  1564. # class B:
  1565. # tp = 1
  1566. # def func(self, arg: tp):
  1567. # ...
  1568. # class C:
  1569. # tp = 2
  1570. # def func(self, arg=tp):
  1571. # ...
  1572. # class C:
  1573. # class Tp:
  1574. # pass
  1575. # class D(Tp):
  1576. # ...
  1577. name = node.name
  1578. frame = node.statement().scope()
  1579. in_annotation_or_default_or_decorator = self._defined_in_function_definition(
  1580. node, frame
  1581. )
  1582. in_ancestor_list = utils.is_ancestor_name(frame, node)
  1583. if in_annotation_or_default_or_decorator or in_ancestor_list:
  1584. frame_locals = frame.parent.scope().locals
  1585. else:
  1586. frame_locals = frame.locals
  1587. return not (
  1588. (isinstance(frame, nodes.ClassDef) or in_annotation_or_default_or_decorator)
  1589. and not self._in_lambda_or_comprehension_body(node, frame)
  1590. and name in frame_locals
  1591. )
  1592. def _loopvar_name(self, node: astroid.Name) -> None:
  1593. # filter variables according to node's scope
  1594. astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
  1595. # If this variable usage exists inside a function definition
  1596. # that exists in the same loop,
  1597. # the usage is safe because the function will not be defined either if
  1598. # the variable is not defined.
  1599. scope = node.scope()
  1600. if isinstance(scope, nodes.FunctionDef) and any(
  1601. asmt.statement().parent_of(scope) for asmt in astmts
  1602. ):
  1603. return
  1604. # filter variables according their respective scope test is_statement
  1605. # and parent to avoid #74747. This is not a total fix, which would
  1606. # introduce a mechanism similar to special attribute lookup in
  1607. # modules. Also, in order to get correct inference in this case, the
  1608. # scope lookup rules would need to be changed to return the initial
  1609. # assignment (which does not exist in code per se) as well as any later
  1610. # modifications.
  1611. if (
  1612. not astmts
  1613. or (astmts[0].is_statement or astmts[0].parent)
  1614. and astmts[0].statement().parent_of(node)
  1615. ):
  1616. _astmts = []
  1617. else:
  1618. _astmts = astmts[:1]
  1619. for i, stmt in enumerate(astmts[1:]):
  1620. if astmts[i].statement().parent_of(stmt) and not in_for_else_branch(
  1621. astmts[i].statement(), stmt
  1622. ):
  1623. continue
  1624. _astmts.append(stmt)
  1625. astmts = _astmts
  1626. if len(astmts) != 1:
  1627. return
  1628. assign = astmts[0].assign_type()
  1629. if not (
  1630. isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
  1631. and assign.statement() is not node.statement()
  1632. ):
  1633. return
  1634. # For functions we can do more by inferring the length of the itered object
  1635. if not isinstance(assign, nodes.For):
  1636. self.add_message("undefined-loop-variable", args=node.name, node=node)
  1637. return
  1638. try:
  1639. inferred = next(assign.iter.infer())
  1640. except astroid.InferenceError:
  1641. self.add_message("undefined-loop-variable", args=node.name, node=node)
  1642. else:
  1643. if (
  1644. isinstance(inferred, astroid.Instance)
  1645. and inferred.qname() == BUILTIN_RANGE
  1646. ):
  1647. # Consider range() objects safe, even if they might not yield any results.
  1648. return
  1649. # Consider sequences.
  1650. sequences = (
  1651. nodes.List,
  1652. nodes.Tuple,
  1653. nodes.Dict,
  1654. nodes.Set,
  1655. astroid.objects.FrozenSet,
  1656. )
  1657. if not isinstance(inferred, sequences):
  1658. self.add_message("undefined-loop-variable", args=node.name, node=node)
  1659. return
  1660. elements = getattr(inferred, "elts", getattr(inferred, "items", []))
  1661. if not elements:
  1662. self.add_message("undefined-loop-variable", args=node.name, node=node)
  1663. def _check_is_unused(self, name, node, stmt, global_names, nonlocal_names):
  1664. # Ignore some special names specified by user configuration.
  1665. if self._is_name_ignored(stmt, name):
  1666. return
  1667. # Ignore names that were added dynamically to the Function scope
  1668. if (
  1669. isinstance(node, nodes.FunctionDef)
  1670. and name == "__class__"
  1671. and len(node.locals["__class__"]) == 1
  1672. and isinstance(node.locals["__class__"][0], nodes.ClassDef)
  1673. ):
  1674. return
  1675. # Ignore names imported by the global statement.
  1676. if isinstance(stmt, (nodes.Global, nodes.Import, nodes.ImportFrom)):
  1677. # Detect imports, assigned to global statements.
  1678. if global_names and _import_name_is_global(stmt, global_names):
  1679. return
  1680. argnames = list(
  1681. itertools.chain(node.argnames(), [arg.name for arg in node.args.kwonlyargs])
  1682. )
  1683. # Care about functions with unknown argument (builtins)
  1684. if name in argnames:
  1685. self._check_unused_arguments(name, node, stmt, argnames)
  1686. else:
  1687. if stmt.parent and isinstance(stmt.parent, (nodes.Assign, nodes.AnnAssign)):
  1688. if name in nonlocal_names:
  1689. return
  1690. qname = asname = None
  1691. if isinstance(stmt, (nodes.Import, nodes.ImportFrom)):
  1692. # Need the complete name, which we don't have in .locals.
  1693. if len(stmt.names) > 1:
  1694. import_names = next(
  1695. (names for names in stmt.names if name in names), None
  1696. )
  1697. else:
  1698. import_names = stmt.names[0]
  1699. if import_names:
  1700. qname, asname = import_names
  1701. name = asname or qname
  1702. if _has_locals_call_after_node(stmt, node.scope()):
  1703. message_name = "possibly-unused-variable"
  1704. else:
  1705. if isinstance(stmt, nodes.Import):
  1706. if asname is not None:
  1707. msg = f"{qname} imported as {asname}"
  1708. else:
  1709. msg = f"import {name}"
  1710. self.add_message("unused-import", args=msg, node=stmt)
  1711. return
  1712. if isinstance(stmt, nodes.ImportFrom):
  1713. if asname is not None:
  1714. msg = f"{qname} imported from {stmt.modname} as {asname}"
  1715. else:
  1716. msg = f"{name} imported from {stmt.modname}"
  1717. self.add_message("unused-import", args=msg, node=stmt)
  1718. return
  1719. message_name = "unused-variable"
  1720. if isinstance(stmt, nodes.FunctionDef) and stmt.decorators:
  1721. return
  1722. # Don't check function stubs created only for type information
  1723. if utils.is_overload_stub(node):
  1724. return
  1725. # Special case for exception variable
  1726. if isinstance(stmt.parent, nodes.ExceptHandler) and any(
  1727. n.name == name for n in stmt.parent.nodes_of_class(nodes.Name)
  1728. ):
  1729. return
  1730. self.add_message(message_name, args=name, node=stmt)
  1731. def _is_name_ignored(self, stmt, name):
  1732. authorized_rgx = self.config.dummy_variables_rgx
  1733. if (
  1734. isinstance(stmt, nodes.AssignName)
  1735. and isinstance(stmt.parent, nodes.Arguments)
  1736. or isinstance(stmt, nodes.Arguments)
  1737. ):
  1738. regex = self.config.ignored_argument_names
  1739. else:
  1740. regex = authorized_rgx
  1741. return regex and regex.match(name)
  1742. def _check_unused_arguments(self, name, node, stmt, argnames):
  1743. is_method = node.is_method()
  1744. klass = node.parent.frame()
  1745. if is_method and isinstance(klass, nodes.ClassDef):
  1746. confidence = (
  1747. INFERENCE if utils.has_known_bases(klass) else INFERENCE_FAILURE
  1748. )
  1749. else:
  1750. confidence = HIGH
  1751. if is_method:
  1752. # Don't warn for the first argument of a (non static) method
  1753. if node.type != "staticmethod" and name == argnames[0]:
  1754. return
  1755. # Don't warn for argument of an overridden method
  1756. overridden = overridden_method(klass, node.name)
  1757. if overridden is not None and name in overridden.argnames():
  1758. return
  1759. if node.name in utils.PYMETHODS and node.name not in (
  1760. "__init__",
  1761. "__new__",
  1762. ):
  1763. return
  1764. # Don't check callback arguments
  1765. if any(
  1766. node.name.startswith(cb) or node.name.endswith(cb)
  1767. for cb in self.config.callbacks
  1768. ):
  1769. return
  1770. # Don't check arguments of singledispatch.register function.
  1771. if utils.is_registered_in_singledispatch_function(node):
  1772. return
  1773. # Don't check function stubs created only for type information
  1774. if utils.is_overload_stub(node):
  1775. return
  1776. # Don't check protocol classes
  1777. if utils.is_protocol_class(klass):
  1778. return
  1779. self.add_message("unused-argument", args=name, node=stmt, confidence=confidence)
  1780. def _check_late_binding_closure(self, node: nodes.Name) -> None:
  1781. """Check whether node is a cell var that is assigned within a containing loop.
  1782. Special cases where we don't care about the error:
  1783. 1. When the node's function is immediately called, e.g. (lambda: i)()
  1784. 2. When the node's function is returned from within the loop, e.g. return lambda: i
  1785. """
  1786. if not self.linter.is_message_enabled("cell-var-from-loop"):
  1787. return
  1788. node_scope = node.frame()
  1789. # If node appears in a default argument expression,
  1790. # look at the next enclosing frame instead
  1791. if utils.is_default_argument(node, node_scope):
  1792. node_scope = node_scope.parent.frame()
  1793. # Check if node is a cell var
  1794. if (
  1795. not isinstance(node_scope, (nodes.Lambda, nodes.FunctionDef))
  1796. or node.name in node_scope.locals
  1797. ):
  1798. return
  1799. assign_scope, stmts = node.lookup(node.name)
  1800. if not stmts or not assign_scope.parent_of(node_scope):
  1801. return
  1802. if utils.is_comprehension(assign_scope):
  1803. self.add_message("cell-var-from-loop", node=node, args=node.name)
  1804. else:
  1805. # Look for an enclosing For loop.
  1806. # Currently, we only consider the first assignment
  1807. assignment_node = stmts[0]
  1808. maybe_for = assignment_node
  1809. while maybe_for and not isinstance(maybe_for, nodes.For):
  1810. if maybe_for is assign_scope:
  1811. break
  1812. maybe_for = maybe_for.parent
  1813. else:
  1814. if (
  1815. maybe_for
  1816. and maybe_for.parent_of(node_scope)
  1817. and not utils.is_being_called(node_scope)
  1818. and not isinstance(node_scope.statement(), nodes.Return)
  1819. ):
  1820. self.add_message("cell-var-from-loop", node=node, args=node.name)
  1821. def _should_ignore_redefined_builtin(self, stmt):
  1822. if not isinstance(stmt, nodes.ImportFrom):
  1823. return False
  1824. return stmt.modname in self.config.redefining_builtins_modules
  1825. def _allowed_redefined_builtin(self, name):
  1826. return name in self.config.allowed_redefined_builtins
  1827. def _has_homonym_in_upper_function_scope(
  1828. self, node: nodes.Name, index: int
  1829. ) -> bool:
  1830. """
  1831. Return whether there is a node with the same name in the
  1832. to_consume dict of an upper scope and if that scope is a
  1833. function
  1834. :param node: node to check for
  1835. :param index: index of the current consumer inside self._to_consume
  1836. :return: True if there is a node with the same name in the
  1837. to_consume dict of an upper scope and if that scope
  1838. is a function, False otherwise
  1839. """
  1840. return any(
  1841. _consumer.scope_type == "function" and node.name in _consumer.to_consume
  1842. for _consumer in self._to_consume[index - 1 :: -1]
  1843. )
  1844. def _store_type_annotation_node(self, type_annotation):
  1845. """Given a type annotation, store all the name nodes it refers to"""
  1846. if isinstance(type_annotation, nodes.Name):
  1847. self._type_annotation_names.append(type_annotation.name)
  1848. return
  1849. if isinstance(type_annotation, nodes.Attribute):
  1850. self._store_type_annotation_node(type_annotation.expr)
  1851. return
  1852. if not isinstance(type_annotation, nodes.Subscript):
  1853. return
  1854. if (
  1855. isinstance(type_annotation.value, nodes.Attribute)
  1856. and isinstance(type_annotation.value.expr, nodes.Name)
  1857. and type_annotation.value.expr.name == TYPING_MODULE
  1858. ):
  1859. self._type_annotation_names.append(TYPING_MODULE)
  1860. return
  1861. self._type_annotation_names.extend(
  1862. annotation.name for annotation in type_annotation.nodes_of_class(nodes.Name)
  1863. )
  1864. def _store_type_annotation_names(self, node):
  1865. type_annotation = node.type_annotation
  1866. if not type_annotation:
  1867. return
  1868. self._store_type_annotation_node(node.type_annotation)
  1869. def _check_self_cls_assign(self, node: nodes.Assign) -> None:
  1870. """Check that self/cls don't get assigned"""
  1871. assign_names: Set[Optional[str]] = set()
  1872. for target in node.targets:
  1873. if isinstance(target, nodes.AssignName):
  1874. assign_names.add(target.name)
  1875. elif isinstance(target, nodes.Tuple):
  1876. assign_names.update(
  1877. elt.name for elt in target.elts if isinstance(elt, nodes.AssignName)
  1878. )
  1879. scope = node.scope()
  1880. nonlocals_with_same_name = any(
  1881. child for child in scope.body if isinstance(child, nodes.Nonlocal)
  1882. )
  1883. if nonlocals_with_same_name:
  1884. scope = node.scope().parent.scope()
  1885. if not (
  1886. isinstance(scope, nodes.FunctionDef)
  1887. and scope.is_method()
  1888. and "builtins.staticmethod" not in scope.decoratornames()
  1889. ):
  1890. return
  1891. argument_names = scope.argnames()
  1892. if not argument_names:
  1893. return
  1894. self_cls_name = argument_names[0]
  1895. if self_cls_name in assign_names:
  1896. self.add_message("self-cls-assignment", node=node, args=(self_cls_name,))
  1897. def _check_unpacking(self, inferred, node, targets):
  1898. """Check for unbalanced tuple unpacking
  1899. and unpacking non sequences.
  1900. """
  1901. if utils.is_inside_abstract_class(node):
  1902. return
  1903. if utils.is_comprehension(node):
  1904. return
  1905. if inferred is astroid.Uninferable:
  1906. return
  1907. if (
  1908. isinstance(inferred.parent, nodes.Arguments)
  1909. and isinstance(node.value, nodes.Name)
  1910. and node.value.name == inferred.parent.vararg
  1911. ):
  1912. # Variable-length argument, we can't determine the length.
  1913. return
  1914. if isinstance(inferred, (nodes.Tuple, nodes.List)):
  1915. # attempt to check unpacking is properly balanced
  1916. values = inferred.itered()
  1917. if len(targets) != len(values):
  1918. # Check if we have starred nodes.
  1919. if any(isinstance(target, nodes.Starred) for target in targets):
  1920. return
  1921. self.add_message(
  1922. "unbalanced-tuple-unpacking",
  1923. node=node,
  1924. args=(
  1925. _get_unpacking_extra_info(node, inferred),
  1926. len(targets),
  1927. len(values),
  1928. ),
  1929. )
  1930. # attempt to check unpacking may be possible (ie RHS is iterable)
  1931. elif not utils.is_iterable(inferred):
  1932. self.add_message(
  1933. "unpacking-non-sequence",
  1934. node=node,
  1935. args=(_get_unpacking_extra_info(node, inferred),),
  1936. )
  1937. def _check_module_attrs(self, node, module, module_names):
  1938. """check that module_names (list of string) are accessible through the
  1939. given module
  1940. if the latest access name corresponds to a module, return it
  1941. """
  1942. while module_names:
  1943. name = module_names.pop(0)
  1944. if name == "__dict__":
  1945. module = None
  1946. break
  1947. try:
  1948. module = next(module.getattr(name)[0].infer())
  1949. if module is astroid.Uninferable:
  1950. return None
  1951. except astroid.NotFoundError:
  1952. if module.name in self._ignored_modules:
  1953. return None
  1954. self.add_message(
  1955. "no-name-in-module", args=(name, module.name), node=node
  1956. )
  1957. return None
  1958. except astroid.InferenceError:
  1959. return None
  1960. if module_names:
  1961. modname = module.name if module else "__dict__"
  1962. self.add_message(
  1963. "no-name-in-module", node=node, args=(".".join(module_names), modname)
  1964. )
  1965. return None
  1966. if isinstance(module, nodes.Module):
  1967. return module
  1968. return None
  1969. def _check_all(self, node: nodes.Module, not_consumed):
  1970. assigned = next(node.igetattr("__all__"))
  1971. if assigned is astroid.Uninferable:
  1972. return
  1973. if not assigned.pytype() in {"builtins.list", "builtins.tuple"}:
  1974. line, col = assigned.tolineno, assigned.col_offset
  1975. self.add_message("invalid-all-format", line=line, col_offset=col, node=node)
  1976. return
  1977. for elt in getattr(assigned, "elts", ()):
  1978. try:
  1979. elt_name = next(elt.infer())
  1980. except astroid.InferenceError:
  1981. continue
  1982. if elt_name is astroid.Uninferable:
  1983. continue
  1984. if not elt_name.parent:
  1985. continue
  1986. if not isinstance(elt_name, nodes.Const) or not isinstance(
  1987. elt_name.value, str
  1988. ):
  1989. self.add_message("invalid-all-object", args=elt.as_string(), node=elt)
  1990. continue
  1991. elt_name = elt_name.value
  1992. # If elt is in not_consumed, remove it from not_consumed
  1993. if elt_name in not_consumed:
  1994. del not_consumed[elt_name]
  1995. continue
  1996. if elt_name not in node.locals:
  1997. if not node.package:
  1998. self.add_message(
  1999. "undefined-all-variable", args=(elt_name,), node=elt
  2000. )
  2001. else:
  2002. basename = os.path.splitext(node.file)[0]
  2003. if os.path.basename(basename) == "__init__":
  2004. name = node.name + "." + elt_name
  2005. try:
  2006. astroid.modutils.file_from_modpath(name.split("."))
  2007. except ImportError:
  2008. self.add_message(
  2009. "undefined-all-variable", args=(elt_name,), node=elt
  2010. )
  2011. except SyntaxError:
  2012. # don't yield a syntax-error warning,
  2013. # because it will be later yielded
  2014. # when the file will be checked
  2015. pass
  2016. def _check_globals(self, not_consumed):
  2017. if self._allow_global_unused_variables:
  2018. return
  2019. for name, node_lst in not_consumed.items():
  2020. for node in node_lst:
  2021. self.add_message("unused-variable", args=(name,), node=node)
  2022. def _check_imports(self, not_consumed):
  2023. local_names = _fix_dot_imports(not_consumed)
  2024. checked = set()
  2025. unused_wildcard_imports: DefaultDict[
  2026. Tuple[str, nodes.ImportFrom], List[str]
  2027. ] = collections.defaultdict(list)
  2028. for name, stmt in local_names:
  2029. for imports in stmt.names:
  2030. real_name = imported_name = imports[0]
  2031. if imported_name == "*":
  2032. real_name = name
  2033. as_name = imports[1]
  2034. if real_name in checked:
  2035. continue
  2036. if name not in (real_name, as_name):
  2037. continue
  2038. checked.add(real_name)
  2039. is_type_annotation_import = (
  2040. imported_name in self._type_annotation_names
  2041. or as_name in self._type_annotation_names
  2042. )
  2043. if isinstance(stmt, nodes.Import) or (
  2044. isinstance(stmt, nodes.ImportFrom) and not stmt.modname
  2045. ):
  2046. if isinstance(stmt, nodes.ImportFrom) and SPECIAL_OBJ.search(
  2047. imported_name
  2048. ):
  2049. # Filter special objects (__doc__, __all__) etc.,
  2050. # because they can be imported for exporting.
  2051. continue
  2052. if is_type_annotation_import:
  2053. # Most likely a typing import if it wasn't used so far.
  2054. continue
  2055. if as_name == "_":
  2056. continue
  2057. if as_name is None:
  2058. msg = f"import {imported_name}"
  2059. else:
  2060. msg = f"{imported_name} imported as {as_name}"
  2061. if not _is_type_checking_import(stmt):
  2062. self.add_message("unused-import", args=msg, node=stmt)
  2063. elif isinstance(stmt, nodes.ImportFrom) and stmt.modname != FUTURE:
  2064. if SPECIAL_OBJ.search(imported_name):
  2065. # Filter special objects (__doc__, __all__) etc.,
  2066. # because they can be imported for exporting.
  2067. continue
  2068. if _is_from_future_import(stmt, name):
  2069. # Check if the name is in fact loaded from a
  2070. # __future__ import in another module.
  2071. continue
  2072. if is_type_annotation_import:
  2073. # Most likely a typing import if it wasn't used so far.
  2074. continue
  2075. if imported_name == "*":
  2076. unused_wildcard_imports[(stmt.modname, stmt)].append(name)
  2077. else:
  2078. if as_name is None:
  2079. msg = f"{imported_name} imported from {stmt.modname}"
  2080. else:
  2081. msg = f"{imported_name} imported from {stmt.modname} as {as_name}"
  2082. if not _is_type_checking_import(stmt):
  2083. self.add_message("unused-import", args=msg, node=stmt)
  2084. # Construct string for unused-wildcard-import message
  2085. for module, unused_list in unused_wildcard_imports.items():
  2086. if len(unused_list) == 1:
  2087. arg_string = unused_list[0]
  2088. else:
  2089. arg_string = (
  2090. f"{', '.join(i for i in unused_list[:-1])} and {unused_list[-1]}"
  2091. )
  2092. self.add_message(
  2093. "unused-wildcard-import", args=(arg_string, module[0]), node=module[1]
  2094. )
  2095. del self._to_consume
  2096. def _check_metaclasses(self, node):
  2097. """Update consumption analysis for metaclasses."""
  2098. consumed = [] # [(scope_locals, consumed_key)]
  2099. for child_node in node.get_children():
  2100. if isinstance(child_node, nodes.ClassDef):
  2101. consumed.extend(self._check_classdef_metaclasses(child_node, node))
  2102. # Pop the consumed items, in order to avoid having
  2103. # unused-import and unused-variable false positives
  2104. for scope_locals, name in consumed:
  2105. scope_locals.pop(name, None)
  2106. def _check_classdef_metaclasses(self, klass, parent_node):
  2107. if not klass._metaclass:
  2108. # Skip if this class doesn't use explicitly a metaclass, but inherits it from ancestors
  2109. return []
  2110. consumed = [] # [(scope_locals, consumed_key)]
  2111. metaclass = klass.metaclass()
  2112. name = None
  2113. if isinstance(klass._metaclass, nodes.Name):
  2114. name = klass._metaclass.name
  2115. elif isinstance(klass._metaclass, nodes.Attribute) and klass._metaclass.expr:
  2116. attr = klass._metaclass.expr
  2117. while not isinstance(attr, nodes.Name):
  2118. attr = attr.expr
  2119. name = attr.name
  2120. elif metaclass:
  2121. name = metaclass.root().name
  2122. found = False
  2123. name = METACLASS_NAME_TRANSFORMS.get(name, name)
  2124. if name:
  2125. # check enclosing scopes starting from most local
  2126. for scope_locals, _, _ in self._to_consume[::-1]:
  2127. found_nodes = scope_locals.get(name, [])
  2128. for found_node in found_nodes:
  2129. if found_node.lineno <= klass.lineno:
  2130. consumed.append((scope_locals, name))
  2131. found = True
  2132. break
  2133. # Check parent scope
  2134. nodes_in_parent_scope = parent_node.locals.get(name, [])
  2135. for found_node_parent in nodes_in_parent_scope:
  2136. if found_node_parent.lineno <= klass.lineno:
  2137. found = True
  2138. break
  2139. if (
  2140. not found
  2141. and not metaclass
  2142. and not (
  2143. name in nodes.Module.scope_attrs
  2144. or utils.is_builtin(name)
  2145. or name in self.config.additional_builtins
  2146. )
  2147. ):
  2148. self.add_message("undefined-variable", node=klass, args=(name,))
  2149. return consumed
  2150. def register(linter):
  2151. """required method to auto register this checker"""
  2152. linter.register_checker(VariablesChecker(linter))