variables.py 127 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267
  1. # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  2. # For details: https://github.com/pylint-dev/pylint/blob/main/LICENSE
  3. # Copyright (c) https://github.com/pylint-dev/pylint/blob/main/CONTRIBUTORS.txt
  4. """Variables checkers for Python code."""
  5. from __future__ import annotations
  6. import collections
  7. import copy
  8. import itertools
  9. import os
  10. import re
  11. import sys
  12. from collections import defaultdict
  13. from collections.abc import Generator, Iterable, Iterator
  14. from enum import Enum
  15. from functools import lru_cache
  16. from typing import TYPE_CHECKING, Any, NamedTuple
  17. import astroid
  18. from astroid import bases, extract_node, nodes, util
  19. from astroid.nodes import _base_nodes
  20. from astroid.typing import InferenceResult
  21. from pylint.checkers import BaseChecker, utils
  22. from pylint.checkers.utils import (
  23. in_type_checking_block,
  24. is_postponed_evaluation_enabled,
  25. is_sys_guard,
  26. )
  27. from pylint.constants import PY39_PLUS, TYPING_NEVER, TYPING_NORETURN
  28. from pylint.interfaces import CONTROL_FLOW, HIGH, INFERENCE, INFERENCE_FAILURE
  29. from pylint.typing import MessageDefinitionTuple
  30. if sys.version_info >= (3, 8):
  31. from functools import cached_property
  32. else:
  33. from astroid.decorators import cachedproperty as cached_property
  34. if TYPE_CHECKING:
  35. from pylint.lint import PyLinter
  36. SPECIAL_OBJ = re.compile("^_{2}[a-z]+_{2}$")
  37. FUTURE = "__future__"
  38. # regexp for ignored argument name
  39. IGNORED_ARGUMENT_NAMES = re.compile("_.*|^ignored_|^unused_")
  40. # In Python 3.7 abc has a Python implementation which is preferred
  41. # by astroid. Unfortunately this also messes up our explicit checks
  42. # for `abc`
  43. METACLASS_NAME_TRANSFORMS = {"_py_abc": "abc"}
  44. BUILTIN_RANGE = "builtins.range"
  45. TYPING_MODULE = "typing"
  46. TYPING_NAMES = frozenset(
  47. {
  48. "Any",
  49. "Callable",
  50. "ClassVar",
  51. "Generic",
  52. "Optional",
  53. "Tuple",
  54. "Type",
  55. "TypeVar",
  56. "Union",
  57. "AbstractSet",
  58. "ByteString",
  59. "Container",
  60. "ContextManager",
  61. "Hashable",
  62. "ItemsView",
  63. "Iterable",
  64. "Iterator",
  65. "KeysView",
  66. "Mapping",
  67. "MappingView",
  68. "MutableMapping",
  69. "MutableSequence",
  70. "MutableSet",
  71. "Sequence",
  72. "Sized",
  73. "ValuesView",
  74. "Awaitable",
  75. "AsyncIterator",
  76. "AsyncIterable",
  77. "Coroutine",
  78. "Collection",
  79. "AsyncGenerator",
  80. "AsyncContextManager",
  81. "Reversible",
  82. "SupportsAbs",
  83. "SupportsBytes",
  84. "SupportsComplex",
  85. "SupportsFloat",
  86. "SupportsInt",
  87. "SupportsRound",
  88. "Counter",
  89. "Deque",
  90. "Dict",
  91. "DefaultDict",
  92. "List",
  93. "Set",
  94. "FrozenSet",
  95. "NamedTuple",
  96. "Generator",
  97. "AnyStr",
  98. "Text",
  99. "Pattern",
  100. "BinaryIO",
  101. }
  102. )
  103. DICT_TYPES = (
  104. astroid.objects.DictValues,
  105. astroid.objects.DictKeys,
  106. astroid.objects.DictItems,
  107. astroid.nodes.node_classes.Dict,
  108. )
  109. NODES_WITH_VALUE_ATTR = (
  110. nodes.Assign,
  111. nodes.AnnAssign,
  112. nodes.AugAssign,
  113. nodes.Expr,
  114. nodes.Return,
  115. nodes.Match,
  116. )
  117. class VariableVisitConsumerAction(Enum):
  118. """Reported by _check_consumer() and its sub-methods to determine the
  119. subsequent action to take in _undefined_and_used_before_checker().
  120. Continue -> continue loop to next consumer
  121. Return -> return and thereby break the loop
  122. """
  123. CONTINUE = 0
  124. RETURN = 1
  125. def _is_from_future_import(stmt: nodes.ImportFrom, name: str) -> bool | None:
  126. """Check if the name is a future import from another module."""
  127. try:
  128. module = stmt.do_import_module(stmt.modname)
  129. except astroid.AstroidBuildingException:
  130. return None
  131. for local_node in module.locals.get(name, []):
  132. if isinstance(local_node, nodes.ImportFrom) and local_node.modname == FUTURE:
  133. return True
  134. return None
  135. @lru_cache(maxsize=1000)
  136. def overridden_method(
  137. klass: nodes.LocalsDictNodeNG, name: str | None
  138. ) -> nodes.FunctionDef | None:
  139. """Get overridden method if any."""
  140. try:
  141. parent = next(klass.local_attr_ancestors(name))
  142. except (StopIteration, KeyError):
  143. return None
  144. try:
  145. meth_node = parent[name]
  146. except KeyError:
  147. # We have found an ancestor defining <name> but it's not in the local
  148. # dictionary. This may happen with astroid built from living objects.
  149. return None
  150. if isinstance(meth_node, nodes.FunctionDef):
  151. return meth_node
  152. return None
  153. def _get_unpacking_extra_info(node: nodes.Assign, inferred: InferenceResult) -> str:
  154. """Return extra information to add to the message for unpacking-non-sequence
  155. and unbalanced-tuple/dict-unpacking errors.
  156. """
  157. more = ""
  158. if isinstance(inferred, DICT_TYPES):
  159. if isinstance(node, nodes.Assign):
  160. more = node.value.as_string()
  161. elif isinstance(node, nodes.For):
  162. more = node.iter.as_string()
  163. return more
  164. inferred_module = inferred.root().name
  165. if node.root().name == inferred_module:
  166. if node.lineno == inferred.lineno:
  167. more = f"'{inferred.as_string()}'"
  168. elif inferred.lineno:
  169. more = f"defined at line {inferred.lineno}"
  170. elif inferred.lineno:
  171. more = f"defined at line {inferred.lineno} of {inferred_module}"
  172. return more
  173. def _detect_global_scope(
  174. node: nodes.Name, frame: nodes.LocalsDictNodeNG, defframe: nodes.LocalsDictNodeNG
  175. ) -> bool:
  176. """Detect that the given frames share a global scope.
  177. Two frames share a global scope when neither
  178. of them are hidden under a function scope, as well
  179. as any parent scope of them, until the root scope.
  180. In this case, depending from something defined later on
  181. will only work if guarded by a nested function definition.
  182. Example:
  183. class A:
  184. # B has the same global scope as `C`, leading to a NameError.
  185. # Return True to indicate a shared scope.
  186. class B(C): ...
  187. class C: ...
  188. Whereas this does not lead to a NameError:
  189. class A:
  190. def guard():
  191. # Return False to indicate no scope sharing.
  192. class B(C): ...
  193. class C: ...
  194. """
  195. def_scope = scope = None
  196. if frame and frame.parent:
  197. scope = frame.parent.scope()
  198. if defframe and defframe.parent:
  199. def_scope = defframe.parent.scope()
  200. if (
  201. isinstance(frame, nodes.ClassDef)
  202. and scope is not def_scope
  203. and scope is utils.get_node_first_ancestor_of_type(node, nodes.FunctionDef)
  204. ):
  205. # If the current node's scope is a class nested under a function,
  206. # and the def_scope is something else, then they aren't shared.
  207. return False
  208. if isinstance(frame, nodes.FunctionDef):
  209. # If the parent of the current node is a
  210. # function, then it can be under its scope (defined in); or
  211. # the `->` part of annotations. The same goes
  212. # for annotations of function arguments, they'll have
  213. # their parent the Arguments node.
  214. if frame.parent_of(defframe):
  215. return node.lineno < defframe.lineno # type: ignore[no-any-return]
  216. if not isinstance(node.parent, (nodes.FunctionDef, nodes.Arguments)):
  217. return False
  218. elif any(
  219. not isinstance(f, (nodes.ClassDef, nodes.Module)) for f in (frame, defframe)
  220. ):
  221. # Not interested in other frames, since they are already
  222. # not in a global scope.
  223. return False
  224. break_scopes = []
  225. for current_scope in (scope, def_scope):
  226. # Look for parent scopes. If there is anything different
  227. # than a module or a class scope, then they frames don't
  228. # share a global scope.
  229. parent_scope = current_scope
  230. while parent_scope:
  231. if not isinstance(parent_scope, (nodes.ClassDef, nodes.Module)):
  232. break_scopes.append(parent_scope)
  233. break
  234. if parent_scope.parent:
  235. parent_scope = parent_scope.parent.scope()
  236. else:
  237. break
  238. if break_scopes and len(set(break_scopes)) != 1:
  239. # Store different scopes than expected.
  240. # If the stored scopes are, in fact, the very same, then it means
  241. # that the two frames (frame and defframe) share the same scope,
  242. # and we could apply our lineno analysis over them.
  243. # For instance, this works when they are inside a function, the node
  244. # that uses a definition and the definition itself.
  245. return False
  246. # At this point, we are certain that frame and defframe share a scope
  247. # and the definition of the first depends on the second.
  248. return frame.lineno < defframe.lineno # type: ignore[no-any-return]
  249. def _infer_name_module(
  250. node: nodes.Import, name: str
  251. ) -> Generator[InferenceResult, None, None]:
  252. context = astroid.context.InferenceContext()
  253. context.lookupname = name
  254. return node.infer(context, asname=False) # type: ignore[no-any-return]
  255. def _fix_dot_imports(
  256. not_consumed: dict[str, list[nodes.NodeNG]]
  257. ) -> list[tuple[str, _base_nodes.ImportNode]]:
  258. """Try to fix imports with multiple dots, by returning a dictionary
  259. with the import names expanded.
  260. The function unflattens root imports,
  261. like 'xml' (when we have both 'xml.etree' and 'xml.sax'), to 'xml.etree'
  262. and 'xml.sax' respectively.
  263. """
  264. names: dict[str, _base_nodes.ImportNode] = {}
  265. for name, stmts in not_consumed.items():
  266. if any(
  267. isinstance(stmt, nodes.AssignName)
  268. and isinstance(stmt.assign_type(), nodes.AugAssign)
  269. for stmt in stmts
  270. ):
  271. continue
  272. for stmt in stmts:
  273. if not isinstance(stmt, (nodes.ImportFrom, nodes.Import)):
  274. continue
  275. for imports in stmt.names:
  276. second_name = None
  277. import_module_name = imports[0]
  278. if import_module_name == "*":
  279. # In case of wildcard imports,
  280. # pick the name from inside the imported module.
  281. second_name = name
  282. else:
  283. name_matches_dotted_import = False
  284. if (
  285. import_module_name.startswith(name)
  286. and import_module_name.find(".") > -1
  287. ):
  288. name_matches_dotted_import = True
  289. if name_matches_dotted_import or name in imports:
  290. # Most likely something like 'xml.etree',
  291. # which will appear in the .locals as 'xml'.
  292. # Only pick the name if it wasn't consumed.
  293. second_name = import_module_name
  294. if second_name and second_name not in names:
  295. names[second_name] = stmt
  296. return sorted(names.items(), key=lambda a: a[1].fromlineno) # type: ignore[no-any-return]
  297. def _find_frame_imports(name: str, frame: nodes.LocalsDictNodeNG) -> bool:
  298. """Detect imports in the frame, with the required *name*.
  299. Such imports can be considered assignments if they are not globals.
  300. Returns True if an import for the given name was found.
  301. """
  302. if name in _flattened_scope_names(frame.nodes_of_class(nodes.Global)):
  303. return False
  304. imports = frame.nodes_of_class((nodes.Import, nodes.ImportFrom))
  305. for import_node in imports:
  306. for import_name, import_alias in import_node.names:
  307. # If the import uses an alias, check only that.
  308. # Otherwise, check only the import name.
  309. if import_alias:
  310. if import_alias == name:
  311. return True
  312. elif import_name and import_name == name:
  313. return True
  314. return False
  315. def _import_name_is_global(
  316. stmt: nodes.Global | _base_nodes.ImportNode, global_names: set[str]
  317. ) -> bool:
  318. for import_name, import_alias in stmt.names:
  319. # If the import uses an alias, check only that.
  320. # Otherwise, check only the import name.
  321. if import_alias:
  322. if import_alias in global_names:
  323. return True
  324. elif import_name in global_names:
  325. return True
  326. return False
  327. def _flattened_scope_names(
  328. iterator: Iterator[nodes.Global | nodes.Nonlocal],
  329. ) -> set[str]:
  330. values = (set(stmt.names) for stmt in iterator)
  331. return set(itertools.chain.from_iterable(values))
  332. def _assigned_locally(name_node: nodes.Name) -> bool:
  333. """Checks if name_node has corresponding assign statement in same scope."""
  334. name_node_scope = name_node.scope()
  335. assign_stmts = name_node_scope.nodes_of_class(nodes.AssignName)
  336. return any(a.name == name_node.name for a in assign_stmts) or _find_frame_imports(
  337. name_node.name, name_node_scope
  338. )
  339. def _has_locals_call_after_node(stmt: nodes.NodeNG, scope: nodes.FunctionDef) -> bool:
  340. skip_nodes = (
  341. nodes.FunctionDef,
  342. nodes.ClassDef,
  343. nodes.Import,
  344. nodes.ImportFrom,
  345. )
  346. for call in scope.nodes_of_class(nodes.Call, skip_klass=skip_nodes):
  347. inferred = utils.safe_infer(call.func)
  348. if (
  349. utils.is_builtin_object(inferred)
  350. and getattr(inferred, "name", None) == "locals"
  351. ):
  352. if stmt.lineno < call.lineno:
  353. return True
  354. return False
  355. MSGS: dict[str, MessageDefinitionTuple] = {
  356. "E0601": (
  357. "Using variable %r before assignment",
  358. "used-before-assignment",
  359. "Emitted when a local variable is accessed before its assignment took place. "
  360. "Assignments in try blocks are assumed not to have occurred when evaluating "
  361. "associated except/finally blocks. Assignments in except blocks are assumed "
  362. "not to have occurred when evaluating statements outside the block, except "
  363. "when the associated try block contains a return statement.",
  364. ),
  365. "E0602": (
  366. "Undefined variable %r",
  367. "undefined-variable",
  368. "Used when an undefined variable is accessed.",
  369. ),
  370. "E0603": (
  371. "Undefined variable name %r in __all__",
  372. "undefined-all-variable",
  373. "Used when an undefined variable name is referenced in __all__.",
  374. ),
  375. "E0604": (
  376. "Invalid object %r in __all__, must contain only strings",
  377. "invalid-all-object",
  378. "Used when an invalid (non-string) object occurs in __all__.",
  379. ),
  380. "E0605": (
  381. "Invalid format for __all__, must be tuple or list",
  382. "invalid-all-format",
  383. "Used when __all__ has an invalid format.",
  384. ),
  385. "E0611": (
  386. "No name %r in module %r",
  387. "no-name-in-module",
  388. "Used when a name cannot be found in a module.",
  389. ),
  390. "W0601": (
  391. "Global variable %r undefined at the module level",
  392. "global-variable-undefined",
  393. 'Used when a variable is defined through the "global" statement '
  394. "but the variable is not defined in the module scope.",
  395. ),
  396. "W0602": (
  397. "Using global for %r but no assignment is done",
  398. "global-variable-not-assigned",
  399. "When a variable defined in the global scope is modified in an inner scope, "
  400. "the 'global' keyword is required in the inner scope only if there is an "
  401. "assignment operation done in the inner scope.",
  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 discourages its usage. That doesn't mean you cannot "
  408. "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 an outer scope or except handler.",
  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 sequence %s: left side has %d "
  456. "label%s, right side has %d value%s",
  457. "unbalanced-tuple-unpacking",
  458. "Used when there is an unbalanced tuple unpacking in assignment",
  459. {"old_names": [("E0632", "old-unbalanced-tuple-unpacking")]},
  460. ),
  461. "E0633": (
  462. "Attempting to unpack a non-sequence%s",
  463. "unpacking-non-sequence",
  464. "Used when something which is not a sequence is used in an unpack assignment",
  465. {"old_names": [("W0633", "old-unpacking-non-sequence")]},
  466. ),
  467. "W0640": (
  468. "Cell variable %s defined in loop",
  469. "cell-var-from-loop",
  470. "A variable used in a closure is defined in a loop. "
  471. "This will result in all closures using the same value for "
  472. "the closed-over variable.",
  473. ),
  474. "W0641": (
  475. "Possibly unused variable %r",
  476. "possibly-unused-variable",
  477. "Used when a variable is defined but might not be used. "
  478. "The possibility comes from the fact that locals() might be used, "
  479. "which could consume or not the said variable",
  480. ),
  481. "W0642": (
  482. "Invalid assignment to %s in method",
  483. "self-cls-assignment",
  484. "Invalid assignment to self or cls in instance or class method "
  485. "respectively.",
  486. ),
  487. "E0643": (
  488. "Invalid index for iterable length",
  489. "potential-index-error",
  490. "Emitted when an index used on an iterable goes beyond the length of that "
  491. "iterable.",
  492. ),
  493. "W0644": (
  494. "Possible unbalanced dict unpacking with %s: "
  495. "left side has %d label%s, right side has %d value%s",
  496. "unbalanced-dict-unpacking",
  497. "Used when there is an unbalanced dict unpacking in assignment or for loop",
  498. ),
  499. }
  500. class ScopeConsumer(NamedTuple):
  501. """Store nodes and their consumption states."""
  502. to_consume: dict[str, list[nodes.NodeNG]]
  503. consumed: dict[str, list[nodes.NodeNG]]
  504. consumed_uncertain: defaultdict[str, list[nodes.NodeNG]]
  505. scope_type: str
  506. class NamesConsumer:
  507. """A simple class to handle consumed, to consume and scope type info of node locals."""
  508. def __init__(self, node: nodes.NodeNG, scope_type: str) -> None:
  509. self._atomic = ScopeConsumer(
  510. copy.copy(node.locals), {}, collections.defaultdict(list), scope_type
  511. )
  512. self.node = node
  513. self._if_nodes_deemed_uncertain: set[nodes.If] = set()
  514. def __repr__(self) -> str:
  515. _to_consumes = [f"{k}->{v}" for k, v in self._atomic.to_consume.items()]
  516. _consumed = [f"{k}->{v}" for k, v in self._atomic.consumed.items()]
  517. _consumed_uncertain = [
  518. f"{k}->{v}" for k, v in self._atomic.consumed_uncertain.items()
  519. ]
  520. to_consumes = ", ".join(_to_consumes)
  521. consumed = ", ".join(_consumed)
  522. consumed_uncertain = ", ".join(_consumed_uncertain)
  523. return f"""
  524. to_consume : {to_consumes}
  525. consumed : {consumed}
  526. consumed_uncertain: {consumed_uncertain}
  527. scope_type : {self._atomic.scope_type}
  528. """
  529. def __iter__(self) -> Iterator[Any]:
  530. return iter(self._atomic)
  531. @property
  532. def to_consume(self) -> dict[str, list[nodes.NodeNG]]:
  533. return self._atomic.to_consume
  534. @property
  535. def consumed(self) -> dict[str, list[nodes.NodeNG]]:
  536. return self._atomic.consumed
  537. @property
  538. def consumed_uncertain(self) -> defaultdict[str, list[nodes.NodeNG]]:
  539. """Retrieves nodes filtered out by get_next_to_consume() that may not
  540. have executed.
  541. These include nodes such as statements in except blocks, or statements
  542. in try blocks (when evaluating their corresponding except and finally
  543. blocks). Checkers that want to treat the statements as executed
  544. (e.g. for unused-variable) may need to add them back.
  545. """
  546. return self._atomic.consumed_uncertain
  547. @property
  548. def scope_type(self) -> str:
  549. return self._atomic.scope_type
  550. def mark_as_consumed(self, name: str, consumed_nodes: list[nodes.NodeNG]) -> None:
  551. """Mark the given nodes as consumed for the name.
  552. If all of the nodes for the name were consumed, delete the name from
  553. the to_consume dictionary
  554. """
  555. unconsumed = [n for n in self.to_consume[name] if n not in set(consumed_nodes)]
  556. self.consumed[name] = consumed_nodes
  557. if unconsumed:
  558. self.to_consume[name] = unconsumed
  559. else:
  560. del self.to_consume[name]
  561. def get_next_to_consume(self, node: nodes.Name) -> list[nodes.NodeNG] | None:
  562. """Return a list of the nodes that define `node` from this scope.
  563. If it is uncertain whether a node will be consumed, such as for statements in
  564. except blocks, add it to self.consumed_uncertain instead of returning it.
  565. Return None to indicate a special case that needs to be handled by the caller.
  566. """
  567. name = node.name
  568. parent_node = node.parent
  569. found_nodes = self.to_consume.get(name)
  570. node_statement = node.statement(future=True)
  571. if (
  572. found_nodes
  573. and isinstance(parent_node, nodes.Assign)
  574. and parent_node == found_nodes[0].parent
  575. ):
  576. lhs = found_nodes[0].parent.targets[0]
  577. if (
  578. isinstance(lhs, nodes.AssignName) and lhs.name == name
  579. ): # this name is defined in this very statement
  580. found_nodes = None
  581. if (
  582. found_nodes
  583. and isinstance(parent_node, nodes.For)
  584. and parent_node.iter == node
  585. and parent_node.target in found_nodes
  586. ):
  587. found_nodes = None
  588. # Before filtering, check that this node's name is not a nonlocal
  589. if any(
  590. isinstance(child, nodes.Nonlocal) and node.name in child.names
  591. for child in node.frame(future=True).get_children()
  592. ):
  593. return found_nodes
  594. # And no comprehension is under the node's frame
  595. if VariablesChecker._comprehension_between_frame_and_node(node):
  596. return found_nodes
  597. # Filter out assignments guarded by always false conditions
  598. if found_nodes:
  599. uncertain_nodes = self._uncertain_nodes_in_false_tests(found_nodes, node)
  600. self.consumed_uncertain[node.name] += uncertain_nodes
  601. uncertain_nodes_set = set(uncertain_nodes)
  602. found_nodes = [n for n in found_nodes if n not in uncertain_nodes_set]
  603. # Filter out assignments in ExceptHandlers that node is not contained in
  604. if found_nodes:
  605. found_nodes = [
  606. n
  607. for n in found_nodes
  608. if not isinstance(n.statement(future=True), nodes.ExceptHandler)
  609. or n.statement(future=True).parent_of(node)
  610. ]
  611. # Filter out assignments in an Except clause that the node is not
  612. # contained in, assuming they may fail
  613. if found_nodes:
  614. uncertain_nodes = self._uncertain_nodes_in_except_blocks(
  615. found_nodes, node, node_statement
  616. )
  617. self.consumed_uncertain[node.name] += uncertain_nodes
  618. uncertain_nodes_set = set(uncertain_nodes)
  619. found_nodes = [n for n in found_nodes if n not in uncertain_nodes_set]
  620. # If this node is in a Finally block of a Try/Finally,
  621. # filter out assignments in the try portion, assuming they may fail
  622. if found_nodes:
  623. uncertain_nodes = (
  624. self._uncertain_nodes_in_try_blocks_when_evaluating_finally_blocks(
  625. found_nodes, node_statement
  626. )
  627. )
  628. self.consumed_uncertain[node.name] += uncertain_nodes
  629. uncertain_nodes_set = set(uncertain_nodes)
  630. found_nodes = [n for n in found_nodes if n not in uncertain_nodes_set]
  631. # If this node is in an ExceptHandler,
  632. # filter out assignments in the try portion, assuming they may fail
  633. if found_nodes:
  634. uncertain_nodes = (
  635. self._uncertain_nodes_in_try_blocks_when_evaluating_except_blocks(
  636. found_nodes, node_statement
  637. )
  638. )
  639. self.consumed_uncertain[node.name] += uncertain_nodes
  640. uncertain_nodes_set = set(uncertain_nodes)
  641. found_nodes = [n for n in found_nodes if n not in uncertain_nodes_set]
  642. return found_nodes
  643. @staticmethod
  644. def _exhaustively_define_name_raise_or_return(
  645. name: str, node: nodes.NodeNG
  646. ) -> bool:
  647. """Return True if there is a collectively exhaustive set of paths under
  648. this `if_node` that define `name`, raise, or return.
  649. """
  650. # Handle try and with
  651. if isinstance(node, (nodes.TryExcept, nodes.TryFinally)):
  652. # Allow either a path through try/else/finally OR a path through ALL except handlers
  653. return (
  654. NamesConsumer._defines_name_raises_or_returns_recursive(name, node)
  655. or isinstance(node, nodes.TryExcept)
  656. and all(
  657. NamesConsumer._defines_name_raises_or_returns_recursive(
  658. name, handler
  659. )
  660. for handler in node.handlers
  661. )
  662. )
  663. if isinstance(node, nodes.With):
  664. return NamesConsumer._defines_name_raises_or_returns_recursive(name, node)
  665. if not isinstance(node, nodes.If):
  666. return False
  667. # Be permissive if there is a break
  668. if any(node.nodes_of_class(nodes.Break)):
  669. return True
  670. # Is there an assignment in this node itself, e.g. in named expression?
  671. if NamesConsumer._defines_name_raises_or_returns(name, node):
  672. return True
  673. # If there is no else, then there is no collectively exhaustive set of paths
  674. if not node.orelse:
  675. return False
  676. return NamesConsumer._branch_handles_name(
  677. name, node.body
  678. ) and NamesConsumer._branch_handles_name(name, node.orelse)
  679. @staticmethod
  680. def _branch_handles_name(name: str, body: Iterable[nodes.NodeNG]) -> bool:
  681. return any(
  682. NamesConsumer._defines_name_raises_or_returns(name, if_body_stmt)
  683. or isinstance(
  684. if_body_stmt,
  685. (nodes.If, nodes.TryExcept, nodes.TryFinally, nodes.With),
  686. )
  687. and NamesConsumer._exhaustively_define_name_raise_or_return(
  688. name, if_body_stmt
  689. )
  690. for if_body_stmt in body
  691. )
  692. def _uncertain_nodes_in_false_tests(
  693. self, found_nodes: list[nodes.NodeNG], node: nodes.NodeNG
  694. ) -> list[nodes.NodeNG]:
  695. """Identify nodes of uncertain execution because they are defined under
  696. tests that evaluate false.
  697. Don't identify a node if there is a collectively exhaustive set of paths
  698. that define the name, raise, or return (e.g. every if/else branch).
  699. """
  700. uncertain_nodes = []
  701. for other_node in found_nodes:
  702. if in_type_checking_block(other_node):
  703. continue
  704. if not isinstance(other_node, nodes.AssignName):
  705. continue
  706. closest_if = utils.get_node_first_ancestor_of_type(other_node, nodes.If)
  707. if closest_if is None:
  708. continue
  709. if node.frame() is not closest_if.frame():
  710. continue
  711. if closest_if is not None and closest_if.parent_of(node):
  712. continue
  713. # Name defined in every if/else branch
  714. if NamesConsumer._exhaustively_define_name_raise_or_return(
  715. other_node.name, closest_if
  716. ):
  717. continue
  718. # Higher-level if already determined to be always false
  719. if any(
  720. if_node.parent_of(closest_if)
  721. for if_node in self._if_nodes_deemed_uncertain
  722. ):
  723. uncertain_nodes.append(other_node)
  724. continue
  725. # All inferred values must test false
  726. if isinstance(closest_if.test, nodes.NamedExpr):
  727. test = closest_if.test.value
  728. else:
  729. test = closest_if.test
  730. all_inferred = utils.infer_all(test)
  731. if not all_inferred or not all(
  732. isinstance(inferred, nodes.Const) and not inferred.value
  733. for inferred in all_inferred
  734. ):
  735. continue
  736. uncertain_nodes.append(other_node)
  737. self._if_nodes_deemed_uncertain.add(closest_if)
  738. return uncertain_nodes
  739. @staticmethod
  740. def _uncertain_nodes_in_except_blocks(
  741. found_nodes: list[nodes.NodeNG],
  742. node: nodes.NodeNG,
  743. node_statement: nodes.Statement,
  744. ) -> list[nodes.NodeNG]:
  745. """Return any nodes in ``found_nodes`` that should be treated as uncertain
  746. because they are in an except block.
  747. """
  748. uncertain_nodes = []
  749. for other_node in found_nodes:
  750. other_node_statement = other_node.statement(future=True)
  751. # Only testing for statements in the except block of TryExcept
  752. closest_except_handler = utils.get_node_first_ancestor_of_type(
  753. other_node_statement, nodes.ExceptHandler
  754. )
  755. if not closest_except_handler:
  756. continue
  757. # If the other node is in the same scope as this node, assume it executes
  758. if closest_except_handler.parent_of(node):
  759. continue
  760. closest_try_except: nodes.TryExcept = closest_except_handler.parent
  761. # If the try or else blocks return, assume the except blocks execute.
  762. try_block_returns = any(
  763. isinstance(try_statement, nodes.Return)
  764. for try_statement in closest_try_except.body
  765. )
  766. else_block_returns = any(
  767. isinstance(else_statement, nodes.Return)
  768. for else_statement in closest_try_except.orelse
  769. )
  770. else_block_exits = any(
  771. isinstance(else_statement, nodes.Expr)
  772. and isinstance(else_statement.value, nodes.Call)
  773. and utils.is_terminating_func(else_statement.value)
  774. for else_statement in closest_try_except.orelse
  775. )
  776. if try_block_returns or else_block_returns or else_block_exits:
  777. # Exception: if this node is in the final block of the other_node_statement,
  778. # it will execute before returning. Assume the except statements are uncertain.
  779. if (
  780. isinstance(node_statement.parent, nodes.TryFinally)
  781. and node_statement in node_statement.parent.finalbody
  782. and closest_try_except.parent.parent_of(node_statement)
  783. ):
  784. uncertain_nodes.append(other_node)
  785. # Or the node_statement is in the else block of the relevant TryExcept
  786. elif (
  787. isinstance(node_statement.parent, nodes.TryExcept)
  788. and node_statement in node_statement.parent.orelse
  789. and closest_try_except.parent.parent_of(node_statement)
  790. ):
  791. uncertain_nodes.append(other_node)
  792. # Assume the except blocks execute, so long as each handler
  793. # defines the name, raises, or returns.
  794. elif all(
  795. NamesConsumer._defines_name_raises_or_returns_recursive(
  796. node.name, handler
  797. )
  798. for handler in closest_try_except.handlers
  799. ):
  800. continue
  801. if NamesConsumer._check_loop_finishes_via_except(node, closest_try_except):
  802. continue
  803. # Passed all tests for uncertain execution
  804. uncertain_nodes.append(other_node)
  805. return uncertain_nodes
  806. @staticmethod
  807. def _defines_name_raises_or_returns(name: str, node: nodes.NodeNG) -> bool:
  808. if isinstance(node, (nodes.Raise, nodes.Assert, nodes.Return)):
  809. return True
  810. if (
  811. isinstance(node, nodes.AnnAssign)
  812. and node.value
  813. and isinstance(node.target, nodes.AssignName)
  814. and node.target.name == name
  815. ):
  816. return True
  817. if isinstance(node, nodes.Assign):
  818. for target in node.targets:
  819. for elt in utils.get_all_elements(target):
  820. if isinstance(elt, nodes.Starred):
  821. elt = elt.value
  822. if isinstance(elt, nodes.AssignName) and elt.name == name:
  823. return True
  824. if isinstance(node, nodes.If):
  825. if any(
  826. child_named_expr.target.name == name
  827. for child_named_expr in node.nodes_of_class(nodes.NamedExpr)
  828. ):
  829. return True
  830. return False
  831. @staticmethod
  832. def _defines_name_raises_or_returns_recursive(
  833. name: str, node: nodes.NodeNG
  834. ) -> bool:
  835. """Return True if some child of `node` defines the name `name`,
  836. raises, or returns.
  837. """
  838. for stmt in node.get_children():
  839. if NamesConsumer._defines_name_raises_or_returns(name, stmt):
  840. return True
  841. if isinstance(stmt, (nodes.If, nodes.With)):
  842. if any(
  843. NamesConsumer._defines_name_raises_or_returns(name, nested_stmt)
  844. for nested_stmt in stmt.get_children()
  845. ):
  846. return True
  847. return False
  848. @staticmethod
  849. def _check_loop_finishes_via_except(
  850. node: nodes.NodeNG, other_node_try_except: nodes.TryExcept
  851. ) -> bool:
  852. """Check for a specific control flow scenario.
  853. Described in https://github.com/pylint-dev/pylint/issues/5683.
  854. A scenario where the only non-break exit from a loop consists of the very
  855. except handler we are examining, such that code in the `else` branch of
  856. the loop can depend on it being assigned.
  857. Example:
  858. for _ in range(3):
  859. try:
  860. do_something()
  861. except:
  862. name = 1 <-- only non-break exit from loop
  863. else:
  864. break
  865. else:
  866. print(name)
  867. """
  868. if not other_node_try_except.orelse:
  869. return False
  870. closest_loop: None | (
  871. nodes.For | nodes.While
  872. ) = utils.get_node_first_ancestor_of_type(node, (nodes.For, nodes.While))
  873. if closest_loop is None:
  874. return False
  875. if not any(
  876. else_statement is node or else_statement.parent_of(node)
  877. for else_statement in closest_loop.orelse
  878. ):
  879. # `node` not guarded by `else`
  880. return False
  881. for inner_else_statement in other_node_try_except.orelse:
  882. if isinstance(inner_else_statement, nodes.Break):
  883. break_stmt = inner_else_statement
  884. break
  885. else:
  886. # No break statement
  887. return False
  888. def _try_in_loop_body(
  889. other_node_try_except: nodes.TryExcept, loop: nodes.For | nodes.While
  890. ) -> bool:
  891. """Return True if `other_node_try_except` is a descendant of `loop`."""
  892. return any(
  893. loop_body_statement is other_node_try_except
  894. or loop_body_statement.parent_of(other_node_try_except)
  895. for loop_body_statement in loop.body
  896. )
  897. if not _try_in_loop_body(other_node_try_except, closest_loop):
  898. for ancestor in closest_loop.node_ancestors():
  899. if isinstance(ancestor, (nodes.For, nodes.While)):
  900. if _try_in_loop_body(other_node_try_except, ancestor):
  901. break
  902. else:
  903. # `other_node_try_except` didn't have a shared ancestor loop
  904. return False
  905. for loop_stmt in closest_loop.body:
  906. if NamesConsumer._recursive_search_for_continue_before_break(
  907. loop_stmt, break_stmt
  908. ):
  909. break
  910. else:
  911. # No continue found, so we arrived at our special case!
  912. return True
  913. return False
  914. @staticmethod
  915. def _recursive_search_for_continue_before_break(
  916. stmt: nodes.Statement, break_stmt: nodes.Break
  917. ) -> bool:
  918. """Return True if any Continue node can be found in descendants of `stmt`
  919. before encountering `break_stmt`, ignoring any nested loops.
  920. """
  921. if stmt is break_stmt:
  922. return False
  923. if isinstance(stmt, nodes.Continue):
  924. return True
  925. for child in stmt.get_children():
  926. if isinstance(stmt, (nodes.For, nodes.While)):
  927. continue
  928. if NamesConsumer._recursive_search_for_continue_before_break(
  929. child, break_stmt
  930. ):
  931. return True
  932. return False
  933. @staticmethod
  934. def _uncertain_nodes_in_try_blocks_when_evaluating_except_blocks(
  935. found_nodes: list[nodes.NodeNG], node_statement: nodes.Statement
  936. ) -> list[nodes.NodeNG]:
  937. """Return any nodes in ``found_nodes`` that should be treated as uncertain.
  938. Nodes are uncertain when they are in a try block and the ``node_statement``
  939. being evaluated is in one of its except handlers.
  940. """
  941. uncertain_nodes: list[nodes.NodeNG] = []
  942. closest_except_handler = utils.get_node_first_ancestor_of_type(
  943. node_statement, nodes.ExceptHandler
  944. )
  945. if closest_except_handler is None:
  946. return uncertain_nodes
  947. for other_node in found_nodes:
  948. other_node_statement = other_node.statement(future=True)
  949. # If the other statement is the except handler guarding `node`, it executes
  950. if other_node_statement is closest_except_handler:
  951. continue
  952. # Ensure other_node is in a try block
  953. (
  954. other_node_try_ancestor,
  955. other_node_try_ancestor_visited_child,
  956. ) = utils.get_node_first_ancestor_of_type_and_its_child(
  957. other_node_statement, nodes.TryExcept
  958. )
  959. if other_node_try_ancestor is None:
  960. continue
  961. if (
  962. other_node_try_ancestor_visited_child
  963. not in other_node_try_ancestor.body
  964. ):
  965. continue
  966. # Make sure nesting is correct -- there should be at least one
  967. # except handler that is a sibling attached to the try ancestor,
  968. # or is an ancestor of the try ancestor.
  969. if not any(
  970. closest_except_handler in other_node_try_ancestor.handlers
  971. or other_node_try_ancestor_except_handler
  972. in closest_except_handler.node_ancestors()
  973. for other_node_try_ancestor_except_handler in other_node_try_ancestor.handlers
  974. ):
  975. continue
  976. # Passed all tests for uncertain execution
  977. uncertain_nodes.append(other_node)
  978. return uncertain_nodes
  979. @staticmethod
  980. def _uncertain_nodes_in_try_blocks_when_evaluating_finally_blocks(
  981. found_nodes: list[nodes.NodeNG], node_statement: nodes.Statement
  982. ) -> list[nodes.NodeNG]:
  983. uncertain_nodes: list[nodes.NodeNG] = []
  984. (
  985. closest_try_finally_ancestor,
  986. child_of_closest_try_finally_ancestor,
  987. ) = utils.get_node_first_ancestor_of_type_and_its_child(
  988. node_statement, nodes.TryFinally
  989. )
  990. if closest_try_finally_ancestor is None:
  991. return uncertain_nodes
  992. if (
  993. child_of_closest_try_finally_ancestor
  994. not in closest_try_finally_ancestor.finalbody
  995. ):
  996. return uncertain_nodes
  997. for other_node in found_nodes:
  998. other_node_statement = other_node.statement(future=True)
  999. (
  1000. other_node_try_finally_ancestor,
  1001. child_of_other_node_try_finally_ancestor,
  1002. ) = utils.get_node_first_ancestor_of_type_and_its_child(
  1003. other_node_statement, nodes.TryFinally
  1004. )
  1005. if other_node_try_finally_ancestor is None:
  1006. continue
  1007. # other_node needs to descend from the try of a try/finally.
  1008. if (
  1009. child_of_other_node_try_finally_ancestor
  1010. not in other_node_try_finally_ancestor.body
  1011. ):
  1012. continue
  1013. # If the two try/finally ancestors are not the same, then
  1014. # node_statement's closest try/finally ancestor needs to be in
  1015. # the final body of other_node's try/finally ancestor, or
  1016. # descend from one of the statements in that final body.
  1017. if (
  1018. other_node_try_finally_ancestor is not closest_try_finally_ancestor
  1019. and not any(
  1020. other_node_final_statement is closest_try_finally_ancestor
  1021. or other_node_final_statement.parent_of(
  1022. closest_try_finally_ancestor
  1023. )
  1024. for other_node_final_statement in other_node_try_finally_ancestor.finalbody
  1025. )
  1026. ):
  1027. continue
  1028. # Passed all tests for uncertain execution
  1029. uncertain_nodes.append(other_node)
  1030. return uncertain_nodes
  1031. # pylint: disable=too-many-public-methods
  1032. class VariablesChecker(BaseChecker):
  1033. """BaseChecker for variables.
  1034. Checks for
  1035. * unused variables / imports
  1036. * undefined variables
  1037. * redefinition of variable from builtins or from an outer scope or except handler
  1038. * use of variable before assignment
  1039. * __all__ consistency
  1040. * self/cls assignment
  1041. """
  1042. name = "variables"
  1043. msgs = MSGS
  1044. options = (
  1045. (
  1046. "init-import",
  1047. {
  1048. "default": False,
  1049. "type": "yn",
  1050. "metavar": "<y or n>",
  1051. "help": "Tells whether we should check for unused import in "
  1052. "__init__ files.",
  1053. },
  1054. ),
  1055. (
  1056. "dummy-variables-rgx",
  1057. {
  1058. "default": "_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_",
  1059. "type": "regexp",
  1060. "metavar": "<regexp>",
  1061. "help": "A regular expression matching the name of dummy "
  1062. "variables (i.e. expected to not be used).",
  1063. },
  1064. ),
  1065. (
  1066. "additional-builtins",
  1067. {
  1068. "default": (),
  1069. "type": "csv",
  1070. "metavar": "<comma separated list>",
  1071. "help": "List of additional names supposed to be defined in "
  1072. "builtins. Remember that you should avoid defining new builtins "
  1073. "when possible.",
  1074. },
  1075. ),
  1076. (
  1077. "callbacks",
  1078. {
  1079. "default": ("cb_", "_cb"),
  1080. "type": "csv",
  1081. "metavar": "<callbacks>",
  1082. "help": "List of strings which can identify a callback "
  1083. "function by name. A callback name must start or "
  1084. "end with one of those strings.",
  1085. },
  1086. ),
  1087. (
  1088. "redefining-builtins-modules",
  1089. {
  1090. "default": (
  1091. "six.moves",
  1092. "past.builtins",
  1093. "future.builtins",
  1094. "builtins",
  1095. "io",
  1096. ),
  1097. "type": "csv",
  1098. "metavar": "<comma separated list>",
  1099. "help": "List of qualified module names which can have objects "
  1100. "that can redefine builtins.",
  1101. },
  1102. ),
  1103. (
  1104. "ignored-argument-names",
  1105. {
  1106. "default": IGNORED_ARGUMENT_NAMES,
  1107. "type": "regexp",
  1108. "metavar": "<regexp>",
  1109. "help": "Argument names that match this expression will be ignored.",
  1110. },
  1111. ),
  1112. (
  1113. "allow-global-unused-variables",
  1114. {
  1115. "default": True,
  1116. "type": "yn",
  1117. "metavar": "<y or n>",
  1118. "help": "Tells whether unused global variables should be treated as a violation.",
  1119. },
  1120. ),
  1121. (
  1122. "allowed-redefined-builtins",
  1123. {
  1124. "default": (),
  1125. "type": "csv",
  1126. "metavar": "<comma separated list>",
  1127. "help": "List of names allowed to shadow builtins",
  1128. },
  1129. ),
  1130. )
  1131. def __init__(self, linter: PyLinter) -> None:
  1132. super().__init__(linter)
  1133. self._to_consume: list[NamesConsumer] = []
  1134. self._type_annotation_names: list[str] = []
  1135. self._except_handler_names_queue: list[
  1136. tuple[nodes.ExceptHandler, nodes.AssignName]
  1137. ] = []
  1138. """This is a queue, last in first out."""
  1139. self._postponed_evaluation_enabled = False
  1140. @utils.only_required_for_messages(
  1141. "unbalanced-dict-unpacking",
  1142. )
  1143. def visit_for(self, node: nodes.For) -> None:
  1144. if not isinstance(node.target, nodes.Tuple):
  1145. return
  1146. targets = node.target.elts
  1147. inferred = utils.safe_infer(node.iter)
  1148. if not isinstance(inferred, DICT_TYPES):
  1149. return
  1150. values = self._nodes_to_unpack(inferred)
  1151. if not values:
  1152. # no dict items returned
  1153. return
  1154. if isinstance(inferred, astroid.objects.DictItems):
  1155. # dict.items() is a bit special because values will be a tuple
  1156. # So as long as there are always 2 targets and values each are
  1157. # a tuple with two items, this will unpack correctly.
  1158. # Example: `for key, val in {1: 2, 3: 4}.items()`
  1159. if len(targets) == 2 and all(len(x.elts) == 2 for x in values):
  1160. return
  1161. # Starred nodes indicate ambiguous unpacking
  1162. # if `dict.items()` is used so we won't flag them.
  1163. if any(isinstance(target, nodes.Starred) for target in targets):
  1164. return
  1165. if len(targets) != len(values):
  1166. details = _get_unpacking_extra_info(node, inferred)
  1167. self._report_unbalanced_unpacking(node, inferred, targets, values, details)
  1168. def leave_for(self, node: nodes.For) -> None:
  1169. self._store_type_annotation_names(node)
  1170. def visit_module(self, node: nodes.Module) -> None:
  1171. """Visit module : update consumption analysis variable
  1172. checks globals doesn't overrides builtins.
  1173. """
  1174. self._to_consume = [NamesConsumer(node, "module")]
  1175. self._postponed_evaluation_enabled = is_postponed_evaluation_enabled(node)
  1176. for name, stmts in node.locals.items():
  1177. if utils.is_builtin(name):
  1178. if self._should_ignore_redefined_builtin(stmts[0]) or name == "__doc__":
  1179. continue
  1180. self.add_message("redefined-builtin", args=name, node=stmts[0])
  1181. @utils.only_required_for_messages(
  1182. "unused-import",
  1183. "unused-wildcard-import",
  1184. "redefined-builtin",
  1185. "undefined-all-variable",
  1186. "invalid-all-object",
  1187. "invalid-all-format",
  1188. "unused-variable",
  1189. "undefined-variable",
  1190. )
  1191. def leave_module(self, node: nodes.Module) -> None:
  1192. """Leave module: check globals."""
  1193. assert len(self._to_consume) == 1
  1194. self._check_metaclasses(node)
  1195. not_consumed = self._to_consume.pop().to_consume
  1196. # attempt to check for __all__ if defined
  1197. if "__all__" in node.locals:
  1198. self._check_all(node, not_consumed)
  1199. # check for unused globals
  1200. self._check_globals(not_consumed)
  1201. # don't check unused imports in __init__ files
  1202. if not self.linter.config.init_import and node.package:
  1203. return
  1204. self._check_imports(not_consumed)
  1205. self._type_annotation_names = []
  1206. def visit_classdef(self, node: nodes.ClassDef) -> None:
  1207. """Visit class: update consumption analysis variable."""
  1208. self._to_consume.append(NamesConsumer(node, "class"))
  1209. def leave_classdef(self, node: nodes.ClassDef) -> None:
  1210. """Leave class: update consumption analysis variable."""
  1211. # Check for hidden ancestor names
  1212. # e.g. "six" in: Class X(six.with_metaclass(ABCMeta, object)):
  1213. for name_node in node.nodes_of_class(nodes.Name):
  1214. if (
  1215. isinstance(name_node.parent, nodes.Call)
  1216. and isinstance(name_node.parent.func, nodes.Attribute)
  1217. and isinstance(name_node.parent.func.expr, nodes.Name)
  1218. ):
  1219. hidden_name_node = name_node.parent.func.expr
  1220. for consumer in self._to_consume:
  1221. if hidden_name_node.name in consumer.to_consume:
  1222. consumer.mark_as_consumed(
  1223. hidden_name_node.name,
  1224. consumer.to_consume[hidden_name_node.name],
  1225. )
  1226. break
  1227. self._to_consume.pop()
  1228. def visit_lambda(self, node: nodes.Lambda) -> None:
  1229. """Visit lambda: update consumption analysis variable."""
  1230. self._to_consume.append(NamesConsumer(node, "lambda"))
  1231. def leave_lambda(self, _: nodes.Lambda) -> None:
  1232. """Leave lambda: update consumption analysis variable."""
  1233. # do not check for not used locals here
  1234. self._to_consume.pop()
  1235. def visit_generatorexp(self, node: nodes.GeneratorExp) -> None:
  1236. """Visit genexpr: update consumption analysis variable."""
  1237. self._to_consume.append(NamesConsumer(node, "comprehension"))
  1238. def leave_generatorexp(self, _: nodes.GeneratorExp) -> None:
  1239. """Leave genexpr: update consumption analysis variable."""
  1240. # do not check for not used locals here
  1241. self._to_consume.pop()
  1242. def visit_dictcomp(self, node: nodes.DictComp) -> None:
  1243. """Visit dictcomp: update consumption analysis variable."""
  1244. self._to_consume.append(NamesConsumer(node, "comprehension"))
  1245. def leave_dictcomp(self, _: nodes.DictComp) -> None:
  1246. """Leave dictcomp: update consumption analysis variable."""
  1247. # do not check for not used locals here
  1248. self._to_consume.pop()
  1249. def visit_setcomp(self, node: nodes.SetComp) -> None:
  1250. """Visit setcomp: update consumption analysis variable."""
  1251. self._to_consume.append(NamesConsumer(node, "comprehension"))
  1252. def leave_setcomp(self, _: nodes.SetComp) -> None:
  1253. """Leave setcomp: update consumption analysis variable."""
  1254. # do not check for not used locals here
  1255. self._to_consume.pop()
  1256. def visit_functiondef(self, node: nodes.FunctionDef) -> None:
  1257. """Visit function: update consumption analysis variable and check locals."""
  1258. self._to_consume.append(NamesConsumer(node, "function"))
  1259. if not (
  1260. self.linter.is_message_enabled("redefined-outer-name")
  1261. or self.linter.is_message_enabled("redefined-builtin")
  1262. ):
  1263. return
  1264. globs = node.root().globals
  1265. for name, stmt in node.items():
  1266. if name in globs and not isinstance(stmt, nodes.Global):
  1267. definition = globs[name][0]
  1268. if (
  1269. isinstance(definition, nodes.ImportFrom)
  1270. and definition.modname == FUTURE
  1271. ):
  1272. # It is a __future__ directive, not a symbol.
  1273. continue
  1274. # Do not take in account redefined names for the purpose
  1275. # of type checking.:
  1276. if any(
  1277. in_type_checking_block(definition) for definition in globs[name]
  1278. ):
  1279. continue
  1280. line = definition.fromlineno
  1281. if not self._is_name_ignored(stmt, name):
  1282. self.add_message(
  1283. "redefined-outer-name", args=(name, line), node=stmt
  1284. )
  1285. elif (
  1286. utils.is_builtin(name)
  1287. and not self._allowed_redefined_builtin(name)
  1288. and not self._should_ignore_redefined_builtin(stmt)
  1289. ):
  1290. # do not print Redefining builtin for additional builtins
  1291. self.add_message("redefined-builtin", args=name, node=stmt)
  1292. def leave_functiondef(self, node: nodes.FunctionDef) -> None:
  1293. """Leave function: check function's locals are consumed."""
  1294. self._check_metaclasses(node)
  1295. if node.type_comment_returns:
  1296. self._store_type_annotation_node(node.type_comment_returns)
  1297. if node.type_comment_args:
  1298. for argument_annotation in node.type_comment_args:
  1299. self._store_type_annotation_node(argument_annotation)
  1300. not_consumed = self._to_consume.pop().to_consume
  1301. if not (
  1302. self.linter.is_message_enabled("unused-variable")
  1303. or self.linter.is_message_enabled("possibly-unused-variable")
  1304. or self.linter.is_message_enabled("unused-argument")
  1305. ):
  1306. return
  1307. # Don't check arguments of function which are only raising an exception.
  1308. if utils.is_error(node):
  1309. return
  1310. # Don't check arguments of abstract methods or within an interface.
  1311. is_method = node.is_method()
  1312. if is_method and node.is_abstract():
  1313. return
  1314. global_names = _flattened_scope_names(node.nodes_of_class(nodes.Global))
  1315. nonlocal_names = _flattened_scope_names(node.nodes_of_class(nodes.Nonlocal))
  1316. comprehension_target_names: set[str] = set()
  1317. for comprehension_scope in node.nodes_of_class(nodes.ComprehensionScope):
  1318. for generator in comprehension_scope.generators:
  1319. for name in utils.find_assigned_names_recursive(generator.target):
  1320. comprehension_target_names.add(name)
  1321. for name, stmts in not_consumed.items():
  1322. self._check_is_unused(
  1323. name,
  1324. node,
  1325. stmts[0],
  1326. global_names,
  1327. nonlocal_names,
  1328. comprehension_target_names,
  1329. )
  1330. visit_asyncfunctiondef = visit_functiondef
  1331. leave_asyncfunctiondef = leave_functiondef
  1332. @utils.only_required_for_messages(
  1333. "global-variable-undefined",
  1334. "global-variable-not-assigned",
  1335. "global-statement",
  1336. "global-at-module-level",
  1337. "redefined-builtin",
  1338. )
  1339. def visit_global(self, node: nodes.Global) -> None:
  1340. """Check names imported exists in the global scope."""
  1341. frame = node.frame(future=True)
  1342. if isinstance(frame, nodes.Module):
  1343. self.add_message("global-at-module-level", node=node, confidence=HIGH)
  1344. return
  1345. module = frame.root()
  1346. default_message = True
  1347. locals_ = node.scope().locals
  1348. for name in node.names:
  1349. try:
  1350. assign_nodes = module.getattr(name)
  1351. except astroid.NotFoundError:
  1352. # unassigned global, skip
  1353. assign_nodes = []
  1354. not_defined_locally_by_import = not any(
  1355. isinstance(local, (nodes.Import, nodes.ImportFrom))
  1356. for local in locals_.get(name, ())
  1357. )
  1358. if (
  1359. not utils.is_reassigned_after_current(node, name)
  1360. and not utils.is_deleted_after_current(node, name)
  1361. and not_defined_locally_by_import
  1362. ):
  1363. self.add_message(
  1364. "global-variable-not-assigned",
  1365. args=name,
  1366. node=node,
  1367. confidence=HIGH,
  1368. )
  1369. default_message = False
  1370. continue
  1371. for anode in assign_nodes:
  1372. if (
  1373. isinstance(anode, nodes.AssignName)
  1374. and anode.name in module.special_attributes
  1375. ):
  1376. self.add_message("redefined-builtin", args=name, node=node)
  1377. break
  1378. if anode.frame(future=True) is module:
  1379. # module level assignment
  1380. break
  1381. if (
  1382. isinstance(anode, (nodes.ClassDef, nodes.FunctionDef))
  1383. and anode.parent is module
  1384. ):
  1385. # module level function assignment
  1386. break
  1387. else:
  1388. if not_defined_locally_by_import:
  1389. # global undefined at the module scope
  1390. self.add_message(
  1391. "global-variable-undefined",
  1392. args=name,
  1393. node=node,
  1394. confidence=HIGH,
  1395. )
  1396. default_message = False
  1397. if default_message:
  1398. self.add_message("global-statement", node=node, confidence=HIGH)
  1399. def visit_assignname(self, node: nodes.AssignName) -> None:
  1400. if isinstance(node.assign_type(), nodes.AugAssign):
  1401. self.visit_name(node)
  1402. def visit_delname(self, node: nodes.DelName) -> None:
  1403. self.visit_name(node)
  1404. def visit_name(self, node: nodes.Name | nodes.AssignName | nodes.DelName) -> None:
  1405. """Don't add the 'utils.only_required_for_messages' decorator here!
  1406. It's important that all 'Name' nodes are visited, otherwise the
  1407. 'NamesConsumers' won't be correct.
  1408. """
  1409. stmt = node.statement(future=True)
  1410. if stmt.fromlineno is None:
  1411. # name node from an astroid built from live code, skip
  1412. assert not stmt.root().file.endswith(".py")
  1413. return
  1414. self._undefined_and_used_before_checker(node, stmt)
  1415. self._loopvar_name(node)
  1416. @utils.only_required_for_messages("redefined-outer-name")
  1417. def visit_excepthandler(self, node: nodes.ExceptHandler) -> None:
  1418. if not node.name or not isinstance(node.name, nodes.AssignName):
  1419. return
  1420. for outer_except, outer_except_assign_name in self._except_handler_names_queue:
  1421. if node.name.name == outer_except_assign_name.name:
  1422. self.add_message(
  1423. "redefined-outer-name",
  1424. args=(outer_except_assign_name.name, outer_except.fromlineno),
  1425. node=node,
  1426. )
  1427. break
  1428. self._except_handler_names_queue.append((node, node.name))
  1429. @utils.only_required_for_messages("redefined-outer-name")
  1430. def leave_excepthandler(self, node: nodes.ExceptHandler) -> None:
  1431. if not node.name or not isinstance(node.name, nodes.AssignName):
  1432. return
  1433. self._except_handler_names_queue.pop()
  1434. def _undefined_and_used_before_checker(
  1435. self, node: nodes.Name, stmt: nodes.NodeNG
  1436. ) -> None:
  1437. frame = stmt.scope()
  1438. start_index = len(self._to_consume) - 1
  1439. # iterates through parent scopes, from the inner to the outer
  1440. base_scope_type = self._to_consume[start_index].scope_type
  1441. for i in range(start_index, -1, -1):
  1442. current_consumer = self._to_consume[i]
  1443. # Certain nodes shouldn't be checked as they get checked another time
  1444. if self._should_node_be_skipped(node, current_consumer, i == start_index):
  1445. continue
  1446. action, nodes_to_consume = self._check_consumer(
  1447. node, stmt, frame, current_consumer, base_scope_type
  1448. )
  1449. if nodes_to_consume:
  1450. # Any nodes added to consumed_uncertain by get_next_to_consume()
  1451. # should be added back so that they are marked as used.
  1452. # They will have already had a chance to emit used-before-assignment.
  1453. # We check here instead of before every single return in _check_consumer()
  1454. nodes_to_consume += current_consumer.consumed_uncertain[node.name]
  1455. current_consumer.mark_as_consumed(node.name, nodes_to_consume)
  1456. if action is VariableVisitConsumerAction.CONTINUE:
  1457. continue
  1458. if action is VariableVisitConsumerAction.RETURN:
  1459. return
  1460. # we have not found the name, if it isn't a builtin, that's an
  1461. # undefined name !
  1462. if not (
  1463. node.name in nodes.Module.scope_attrs
  1464. or utils.is_builtin(node.name)
  1465. or node.name in self.linter.config.additional_builtins
  1466. or (
  1467. node.name == "__class__"
  1468. and any(
  1469. i.is_method()
  1470. for i in node.node_ancestors()
  1471. if isinstance(i, nodes.FunctionDef)
  1472. )
  1473. )
  1474. ) and not utils.node_ignores_exception(node, NameError):
  1475. self.add_message("undefined-variable", args=node.name, node=node)
  1476. def _should_node_be_skipped(
  1477. self, node: nodes.Name, consumer: NamesConsumer, is_start_index: bool
  1478. ) -> bool:
  1479. """Tests a consumer and node for various conditions in which the node shouldn't
  1480. be checked for the undefined-variable and used-before-assignment checks.
  1481. """
  1482. if consumer.scope_type == "class":
  1483. # The list of base classes in the class definition is not part
  1484. # of the class body.
  1485. # If the current scope is a class scope but it's not the inner
  1486. # scope, ignore it. This prevents to access this scope instead of
  1487. # the globals one in function members when there are some common
  1488. # names.
  1489. if utils.is_ancestor_name(consumer.node, node) or (
  1490. not is_start_index and self._ignore_class_scope(node)
  1491. ):
  1492. return True
  1493. # Ignore inner class scope for keywords in class definition
  1494. if isinstance(node.parent, nodes.Keyword) and isinstance(
  1495. node.parent.parent, nodes.ClassDef
  1496. ):
  1497. return True
  1498. elif consumer.scope_type == "function" and self._defined_in_function_definition(
  1499. node, consumer.node
  1500. ):
  1501. # If the name node is used as a function default argument's value or as
  1502. # a decorator, then start from the parent frame of the function instead
  1503. # of the function frame - and thus open an inner class scope
  1504. return True
  1505. elif consumer.scope_type == "lambda" and utils.is_default_argument(
  1506. node, consumer.node
  1507. ):
  1508. return True
  1509. return False
  1510. # pylint: disable = too-many-return-statements, too-many-branches
  1511. def _check_consumer(
  1512. self,
  1513. node: nodes.Name,
  1514. stmt: nodes.NodeNG,
  1515. frame: nodes.LocalsDictNodeNG,
  1516. current_consumer: NamesConsumer,
  1517. base_scope_type: str,
  1518. ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
  1519. """Checks a consumer for conditions that should trigger messages."""
  1520. # If the name has already been consumed, only check it's not a loop
  1521. # variable used outside the loop.
  1522. if node.name in current_consumer.consumed:
  1523. # Avoid the case where there are homonyms inside function scope and
  1524. # comprehension current scope (avoid bug #1731)
  1525. if utils.is_func_decorator(current_consumer.node) or not isinstance(
  1526. node, nodes.ComprehensionScope
  1527. ):
  1528. self._check_late_binding_closure(node)
  1529. return (VariableVisitConsumerAction.RETURN, None)
  1530. found_nodes = current_consumer.get_next_to_consume(node)
  1531. if found_nodes is None:
  1532. return (VariableVisitConsumerAction.CONTINUE, None)
  1533. if not found_nodes:
  1534. if node.name in current_consumer.consumed_uncertain:
  1535. confidence = CONTROL_FLOW
  1536. else:
  1537. confidence = HIGH
  1538. self.add_message(
  1539. "used-before-assignment",
  1540. args=node.name,
  1541. node=node,
  1542. confidence=confidence,
  1543. )
  1544. # Mark for consumption any nodes added to consumed_uncertain by
  1545. # get_next_to_consume() because they might not have executed.
  1546. return (
  1547. VariableVisitConsumerAction.RETURN,
  1548. current_consumer.consumed_uncertain[node.name],
  1549. )
  1550. self._check_late_binding_closure(node)
  1551. defnode = utils.assign_parent(found_nodes[0])
  1552. defstmt = defnode.statement(future=True)
  1553. defframe = defstmt.frame(future=True)
  1554. # The class reuses itself in the class scope.
  1555. is_recursive_klass: bool = (
  1556. frame is defframe
  1557. and defframe.parent_of(node)
  1558. and isinstance(defframe, nodes.ClassDef)
  1559. and node.name == defframe.name
  1560. )
  1561. if (
  1562. is_recursive_klass
  1563. and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
  1564. and (
  1565. not utils.is_default_argument(node)
  1566. or node.scope().parent.scope() is not defframe
  1567. )
  1568. ):
  1569. # Self-referential class references are fine in lambda's --
  1570. # As long as they are not part of the default argument directly
  1571. # under the scope of the parent self-referring class.
  1572. # Example of valid default argument:
  1573. # class MyName3:
  1574. # myattr = 1
  1575. # mylambda3 = lambda: lambda a=MyName3: a
  1576. # Example of invalid default argument:
  1577. # class MyName4:
  1578. # myattr = 1
  1579. # mylambda4 = lambda a=MyName4: lambda: a
  1580. # If the above conditional is True,
  1581. # there is no possibility of undefined-variable
  1582. # Also do not consume class name
  1583. # (since consuming blocks subsequent checks)
  1584. # -- quit
  1585. return (VariableVisitConsumerAction.RETURN, None)
  1586. (
  1587. maybe_before_assign,
  1588. annotation_return,
  1589. use_outer_definition,
  1590. ) = self._is_variable_violation(
  1591. node,
  1592. defnode,
  1593. stmt,
  1594. defstmt,
  1595. frame,
  1596. defframe,
  1597. base_scope_type,
  1598. is_recursive_klass,
  1599. )
  1600. if use_outer_definition:
  1601. return (VariableVisitConsumerAction.CONTINUE, None)
  1602. if (
  1603. maybe_before_assign
  1604. and not utils.is_defined_before(node)
  1605. and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
  1606. ):
  1607. # Used and defined in the same place, e.g `x += 1` and `del x`
  1608. defined_by_stmt = defstmt is stmt and isinstance(
  1609. node, (nodes.DelName, nodes.AssignName)
  1610. )
  1611. if (
  1612. is_recursive_klass
  1613. or defined_by_stmt
  1614. or annotation_return
  1615. or isinstance(defstmt, nodes.Delete)
  1616. ):
  1617. if not utils.node_ignores_exception(node, NameError):
  1618. # Handle postponed evaluation of annotations
  1619. if not (
  1620. self._postponed_evaluation_enabled
  1621. and isinstance(
  1622. stmt,
  1623. (
  1624. nodes.AnnAssign,
  1625. nodes.FunctionDef,
  1626. nodes.Arguments,
  1627. ),
  1628. )
  1629. and node.name in node.root().locals
  1630. ):
  1631. if defined_by_stmt:
  1632. return (VariableVisitConsumerAction.CONTINUE, [node])
  1633. return (VariableVisitConsumerAction.CONTINUE, None)
  1634. elif base_scope_type != "lambda":
  1635. # E0601 may *not* occurs in lambda scope.
  1636. # Skip postponed evaluation of annotations
  1637. # and unevaluated annotations inside a function body
  1638. if not (
  1639. self._postponed_evaluation_enabled
  1640. and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
  1641. ) and not (
  1642. isinstance(stmt, nodes.AnnAssign)
  1643. and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
  1644. ):
  1645. self.add_message(
  1646. "used-before-assignment",
  1647. args=node.name,
  1648. node=node,
  1649. confidence=HIGH,
  1650. )
  1651. return (VariableVisitConsumerAction.RETURN, found_nodes)
  1652. elif base_scope_type == "lambda":
  1653. # E0601 can occur in class-level scope in lambdas, as in
  1654. # the following example:
  1655. # class A:
  1656. # x = lambda attr: f + attr
  1657. # f = 42
  1658. # We check lineno because doing the following is fine:
  1659. # class A:
  1660. # x = 42
  1661. # y = lambda attr: x + attr
  1662. if (
  1663. isinstance(frame, nodes.ClassDef)
  1664. and node.name in frame.locals
  1665. and stmt.fromlineno <= defstmt.fromlineno
  1666. ):
  1667. self.add_message(
  1668. "used-before-assignment",
  1669. args=node.name,
  1670. node=node,
  1671. confidence=HIGH,
  1672. )
  1673. elif self._is_only_type_assignment(node, defstmt):
  1674. if node.scope().locals.get(node.name):
  1675. self.add_message(
  1676. "used-before-assignment", args=node.name, node=node, confidence=HIGH
  1677. )
  1678. else:
  1679. self.add_message(
  1680. "undefined-variable", args=node.name, node=node, confidence=HIGH
  1681. )
  1682. return (VariableVisitConsumerAction.RETURN, found_nodes)
  1683. elif isinstance(defstmt, nodes.ClassDef):
  1684. return self._is_first_level_self_reference(node, defstmt, found_nodes)
  1685. elif isinstance(defnode, nodes.NamedExpr):
  1686. if isinstance(defnode.parent, nodes.IfExp):
  1687. if self._is_never_evaluated(defnode, defnode.parent):
  1688. self.add_message(
  1689. "undefined-variable",
  1690. args=node.name,
  1691. node=node,
  1692. confidence=INFERENCE,
  1693. )
  1694. return (VariableVisitConsumerAction.RETURN, found_nodes)
  1695. return (VariableVisitConsumerAction.RETURN, found_nodes)
  1696. @utils.only_required_for_messages("no-name-in-module")
  1697. def visit_import(self, node: nodes.Import) -> None:
  1698. """Check modules attribute accesses."""
  1699. if not self._analyse_fallback_blocks and utils.is_from_fallback_block(node):
  1700. # No need to verify this, since ImportError is already
  1701. # handled by the client code.
  1702. return
  1703. # Don't verify import if part of guarded import block
  1704. if in_type_checking_block(node):
  1705. return
  1706. if isinstance(node.parent, nodes.If) and is_sys_guard(node.parent):
  1707. return
  1708. for name, _ in node.names:
  1709. parts = name.split(".")
  1710. try:
  1711. module = next(_infer_name_module(node, parts[0]))
  1712. except astroid.ResolveError:
  1713. continue
  1714. if not isinstance(module, nodes.Module):
  1715. continue
  1716. self._check_module_attrs(node, module, parts[1:])
  1717. @utils.only_required_for_messages("no-name-in-module")
  1718. def visit_importfrom(self, node: nodes.ImportFrom) -> None:
  1719. """Check modules attribute accesses."""
  1720. if not self._analyse_fallback_blocks and utils.is_from_fallback_block(node):
  1721. # No need to verify this, since ImportError is already
  1722. # handled by the client code.
  1723. return
  1724. # Don't verify import if part of guarded import block
  1725. # I.e. `sys.version_info` or `typing.TYPE_CHECKING`
  1726. if in_type_checking_block(node):
  1727. return
  1728. if isinstance(node.parent, nodes.If) and is_sys_guard(node.parent):
  1729. return
  1730. name_parts = node.modname.split(".")
  1731. try:
  1732. module = node.do_import_module(name_parts[0])
  1733. except astroid.AstroidBuildingException:
  1734. return
  1735. module = self._check_module_attrs(node, module, name_parts[1:])
  1736. if not module:
  1737. return
  1738. for name, _ in node.names:
  1739. if name == "*":
  1740. continue
  1741. self._check_module_attrs(node, module, name.split("."))
  1742. @utils.only_required_for_messages(
  1743. "unbalanced-tuple-unpacking",
  1744. "unpacking-non-sequence",
  1745. "self-cls-assignment",
  1746. "unbalanced_dict_unpacking",
  1747. )
  1748. def visit_assign(self, node: nodes.Assign) -> None:
  1749. """Check unbalanced tuple unpacking for assignments and unpacking
  1750. non-sequences as well as in case self/cls get assigned.
  1751. """
  1752. self._check_self_cls_assign(node)
  1753. if not isinstance(node.targets[0], (nodes.Tuple, nodes.List)):
  1754. return
  1755. targets = node.targets[0].itered()
  1756. # Check if we have starred nodes.
  1757. if any(isinstance(target, nodes.Starred) for target in targets):
  1758. return
  1759. try:
  1760. inferred = utils.safe_infer(node.value)
  1761. if inferred is not None:
  1762. self._check_unpacking(inferred, node, targets)
  1763. except astroid.InferenceError:
  1764. return
  1765. # listcomp have now also their scope
  1766. def visit_listcomp(self, node: nodes.ListComp) -> None:
  1767. """Visit listcomp: update consumption analysis variable."""
  1768. self._to_consume.append(NamesConsumer(node, "comprehension"))
  1769. def leave_listcomp(self, _: nodes.ListComp) -> None:
  1770. """Leave listcomp: update consumption analysis variable."""
  1771. # do not check for not used locals here
  1772. self._to_consume.pop()
  1773. def leave_assign(self, node: nodes.Assign) -> None:
  1774. self._store_type_annotation_names(node)
  1775. def leave_with(self, node: nodes.With) -> None:
  1776. self._store_type_annotation_names(node)
  1777. def visit_arguments(self, node: nodes.Arguments) -> None:
  1778. for annotation in node.type_comment_args:
  1779. self._store_type_annotation_node(annotation)
  1780. # Relying on other checker's options, which might not have been initialized yet.
  1781. @cached_property
  1782. def _analyse_fallback_blocks(self) -> bool:
  1783. return bool(self.linter.config.analyse_fallback_blocks)
  1784. @cached_property
  1785. def _ignored_modules(self) -> Iterable[str]:
  1786. return self.linter.config.ignored_modules # type: ignore[no-any-return]
  1787. @cached_property
  1788. def _allow_global_unused_variables(self) -> bool:
  1789. return bool(self.linter.config.allow_global_unused_variables)
  1790. @staticmethod
  1791. def _defined_in_function_definition(
  1792. node: nodes.NodeNG, frame: nodes.NodeNG
  1793. ) -> bool:
  1794. in_annotation_or_default_or_decorator = False
  1795. if (
  1796. isinstance(frame, nodes.FunctionDef)
  1797. and node.statement(future=True) is frame
  1798. ):
  1799. in_annotation_or_default_or_decorator = (
  1800. (
  1801. node in frame.args.annotations
  1802. or node in frame.args.posonlyargs_annotations
  1803. or node in frame.args.kwonlyargs_annotations
  1804. or node is frame.args.varargannotation
  1805. or node is frame.args.kwargannotation
  1806. )
  1807. or frame.args.parent_of(node)
  1808. or (frame.decorators and frame.decorators.parent_of(node))
  1809. or (
  1810. frame.returns
  1811. and (node is frame.returns or frame.returns.parent_of(node))
  1812. )
  1813. )
  1814. return in_annotation_or_default_or_decorator
  1815. @staticmethod
  1816. def _in_lambda_or_comprehension_body(
  1817. node: nodes.NodeNG, frame: nodes.NodeNG
  1818. ) -> bool:
  1819. """Return True if node within a lambda/comprehension body (or similar) and thus
  1820. should not have access to class attributes in frame.
  1821. """
  1822. child = node
  1823. parent = node.parent
  1824. while parent is not None:
  1825. if parent is frame:
  1826. return False
  1827. if isinstance(parent, nodes.Lambda) and child is not parent.args:
  1828. # Body of lambda should not have access to class attributes.
  1829. return True
  1830. if isinstance(parent, nodes.Comprehension) and child is not parent.iter:
  1831. # Only iter of list/set/dict/generator comprehension should have access.
  1832. return True
  1833. if isinstance(parent, nodes.ComprehensionScope) and not (
  1834. parent.generators and child is parent.generators[0]
  1835. ):
  1836. # Body of list/set/dict/generator comprehension should not have access to class attributes.
  1837. # Furthermore, only the first generator (if multiple) in comprehension should have access.
  1838. return True
  1839. child = parent
  1840. parent = parent.parent
  1841. return False
  1842. # pylint: disable = too-many-branches
  1843. @staticmethod
  1844. def _is_variable_violation(
  1845. node: nodes.Name,
  1846. defnode: nodes.NodeNG,
  1847. stmt: nodes.Statement,
  1848. defstmt: nodes.Statement,
  1849. frame: nodes.LocalsDictNodeNG, # scope of statement of node
  1850. defframe: nodes.LocalsDictNodeNG,
  1851. base_scope_type: str,
  1852. is_recursive_klass: bool,
  1853. ) -> tuple[bool, bool, bool]:
  1854. maybe_before_assign = True
  1855. annotation_return = False
  1856. use_outer_definition = False
  1857. if frame is not defframe:
  1858. maybe_before_assign = _detect_global_scope(node, frame, defframe)
  1859. elif defframe.parent is None:
  1860. # we are at the module level, check the name is not
  1861. # defined in builtins
  1862. if (
  1863. node.name in defframe.scope_attrs
  1864. or astroid.builtin_lookup(node.name)[1]
  1865. ):
  1866. maybe_before_assign = False
  1867. else:
  1868. # we are in a local scope, check the name is not
  1869. # defined in global or builtin scope
  1870. # skip this lookup if name is assigned later in function scope/lambda
  1871. # Note: the node.frame() is not the same as the `frame` argument which is
  1872. # equivalent to frame.statement().scope()
  1873. forbid_lookup = (
  1874. isinstance(frame, nodes.FunctionDef)
  1875. or isinstance(node.frame(future=True), nodes.Lambda)
  1876. ) and _assigned_locally(node)
  1877. if not forbid_lookup and defframe.root().lookup(node.name)[1]:
  1878. maybe_before_assign = False
  1879. use_outer_definition = stmt == defstmt and not isinstance(
  1880. defnode, nodes.Comprehension
  1881. )
  1882. # check if we have a nonlocal
  1883. elif node.name in defframe.locals:
  1884. maybe_before_assign = not any(
  1885. isinstance(child, nodes.Nonlocal) and node.name in child.names
  1886. for child in defframe.get_children()
  1887. )
  1888. if (
  1889. base_scope_type == "lambda"
  1890. and isinstance(frame, nodes.ClassDef)
  1891. and node.name in frame.locals
  1892. ):
  1893. # This rule verifies that if the definition node of the
  1894. # checked name is an Arguments node and if the name
  1895. # is used a default value in the arguments defaults
  1896. # and the actual definition of the variable label
  1897. # is happening before the Arguments definition.
  1898. #
  1899. # bar = None
  1900. # foo = lambda bar=bar: bar
  1901. #
  1902. # In this case, maybe_before_assign should be False, otherwise
  1903. # it should be True.
  1904. maybe_before_assign = not (
  1905. isinstance(defnode, nodes.Arguments)
  1906. and node in defnode.defaults
  1907. and frame.locals[node.name][0].fromlineno < defstmt.fromlineno
  1908. )
  1909. elif isinstance(defframe, nodes.ClassDef) and isinstance(
  1910. frame, nodes.FunctionDef
  1911. ):
  1912. # Special rule for function return annotations,
  1913. # using a name defined earlier in the class containing the function.
  1914. if node is frame.returns and defframe.parent_of(frame.returns):
  1915. annotation_return = True
  1916. if (
  1917. frame.returns.name in defframe.locals
  1918. and defframe.locals[node.name][0].lineno < frame.lineno
  1919. ):
  1920. # Detect class assignments with a name defined earlier in the
  1921. # class. In this case, no warning should be raised.
  1922. maybe_before_assign = False
  1923. else:
  1924. maybe_before_assign = True
  1925. if isinstance(node.parent, nodes.Arguments):
  1926. maybe_before_assign = stmt.fromlineno <= defstmt.fromlineno
  1927. elif is_recursive_klass:
  1928. maybe_before_assign = True
  1929. else:
  1930. maybe_before_assign = (
  1931. maybe_before_assign and stmt.fromlineno <= defstmt.fromlineno
  1932. )
  1933. if maybe_before_assign and stmt.fromlineno == defstmt.fromlineno:
  1934. if (
  1935. isinstance(defframe, nodes.FunctionDef)
  1936. and frame is defframe
  1937. and defframe.parent_of(node)
  1938. and stmt is not defstmt
  1939. ):
  1940. # Single statement function, with the statement on the
  1941. # same line as the function definition
  1942. maybe_before_assign = False
  1943. elif (
  1944. isinstance(defstmt, NODES_WITH_VALUE_ATTR)
  1945. and VariablesChecker._maybe_used_and_assigned_at_once(defstmt)
  1946. and frame is defframe
  1947. and defframe.parent_of(node)
  1948. and stmt is defstmt
  1949. ):
  1950. # Single statement if, with assignment expression on same
  1951. # line as assignment
  1952. # x = b if (b := True) else False
  1953. maybe_before_assign = False
  1954. elif (
  1955. isinstance( # pylint: disable=too-many-boolean-expressions
  1956. defnode, nodes.NamedExpr
  1957. )
  1958. and frame is defframe
  1959. and defframe.parent_of(stmt)
  1960. and stmt is defstmt
  1961. and (
  1962. (
  1963. defnode.lineno == node.lineno
  1964. and defnode.col_offset < node.col_offset
  1965. )
  1966. or (defnode.lineno < node.lineno)
  1967. or (
  1968. # Issue in the `ast` module until py39
  1969. # Nodes in a multiline string have the same lineno
  1970. # Could be false-positive without check
  1971. not PY39_PLUS
  1972. and defnode.lineno == node.lineno
  1973. and isinstance(
  1974. defstmt,
  1975. (
  1976. nodes.Assign,
  1977. nodes.AnnAssign,
  1978. nodes.AugAssign,
  1979. nodes.Return,
  1980. ),
  1981. )
  1982. and isinstance(defstmt.value, nodes.JoinedStr)
  1983. )
  1984. )
  1985. ):
  1986. # Relation of a name to the same name in a named expression
  1987. # Could be used before assignment if self-referencing:
  1988. # (b := b)
  1989. # Otherwise, safe if used after assignment:
  1990. # (b := 2) and b
  1991. maybe_before_assign = defnode.value is node or any(
  1992. anc is defnode.value for anc in node.node_ancestors()
  1993. )
  1994. # Look for type checking definitions inside a type checking guard.
  1995. # Relevant for function annotations only, not variable annotations (AnnAssign)
  1996. if (
  1997. isinstance(defstmt, (nodes.Import, nodes.ImportFrom))
  1998. and isinstance(defstmt.parent, nodes.If)
  1999. and in_type_checking_block(defstmt)
  2000. and not in_type_checking_block(node)
  2001. ):
  2002. defstmt_parent = defstmt.parent
  2003. maybe_annotation = utils.get_node_first_ancestor_of_type(
  2004. node, nodes.AnnAssign
  2005. )
  2006. if not (
  2007. maybe_annotation
  2008. and utils.get_node_first_ancestor_of_type(
  2009. maybe_annotation, nodes.FunctionDef
  2010. )
  2011. ):
  2012. # Exempt those definitions that are used inside the type checking
  2013. # guard or that are defined in any elif/else type checking guard branches.
  2014. used_in_branch = defstmt_parent.parent_of(node)
  2015. if not used_in_branch:
  2016. if defstmt_parent.has_elif_block():
  2017. defined_in_or_else = utils.is_defined(
  2018. node.name, defstmt_parent.orelse[0]
  2019. )
  2020. else:
  2021. defined_in_or_else = any(
  2022. utils.is_defined(node.name, content)
  2023. for content in defstmt_parent.orelse
  2024. )
  2025. if not defined_in_or_else:
  2026. maybe_before_assign = True
  2027. return maybe_before_assign, annotation_return, use_outer_definition
  2028. @staticmethod
  2029. def _maybe_used_and_assigned_at_once(defstmt: nodes.Statement) -> bool:
  2030. """Check if `defstmt` has the potential to use and assign a name in the
  2031. same statement.
  2032. """
  2033. if isinstance(defstmt, nodes.Match):
  2034. return any(case.guard for case in defstmt.cases)
  2035. if isinstance(defstmt, nodes.IfExp):
  2036. return True
  2037. if isinstance(defstmt.value, nodes.BaseContainer):
  2038. return any(
  2039. VariablesChecker._maybe_used_and_assigned_at_once(elt)
  2040. for elt in defstmt.value.elts
  2041. if isinstance(elt, NODES_WITH_VALUE_ATTR + (nodes.IfExp, nodes.Match))
  2042. )
  2043. value = defstmt.value
  2044. if isinstance(value, nodes.IfExp):
  2045. return True
  2046. if isinstance(value, nodes.Lambda) and isinstance(value.body, nodes.IfExp):
  2047. return True
  2048. if isinstance(value, nodes.Dict) and any(
  2049. isinstance(item[0], nodes.IfExp) or isinstance(item[1], nodes.IfExp)
  2050. for item in value.items
  2051. ):
  2052. return True
  2053. if not isinstance(value, nodes.Call):
  2054. return False
  2055. return any(
  2056. any(isinstance(kwarg.value, nodes.IfExp) for kwarg in call.keywords)
  2057. or any(isinstance(arg, nodes.IfExp) for arg in call.args)
  2058. or (
  2059. isinstance(call.func, nodes.Attribute)
  2060. and isinstance(call.func.expr, nodes.IfExp)
  2061. )
  2062. for call in value.nodes_of_class(klass=nodes.Call)
  2063. )
  2064. def _is_only_type_assignment(
  2065. self, node: nodes.Name, defstmt: nodes.Statement
  2066. ) -> bool:
  2067. """Check if variable only gets assigned a type and never a value."""
  2068. if not isinstance(defstmt, nodes.AnnAssign) or defstmt.value:
  2069. return False
  2070. if node.name in self.linter.config.additional_builtins or utils.is_builtin(
  2071. node.name
  2072. ):
  2073. return False
  2074. defstmt_frame = defstmt.frame(future=True)
  2075. node_frame = node.frame(future=True)
  2076. parent = node
  2077. while parent is not defstmt_frame.parent:
  2078. parent_scope = parent.scope()
  2079. # Find out if any nonlocals receive values in nested functions
  2080. for inner_func in parent_scope.nodes_of_class(nodes.FunctionDef):
  2081. if inner_func is parent_scope:
  2082. continue
  2083. if any(
  2084. node.name in nl.names
  2085. for nl in inner_func.nodes_of_class(nodes.Nonlocal)
  2086. ) and any(
  2087. node.name == an.name
  2088. for an in inner_func.nodes_of_class(nodes.AssignName)
  2089. ):
  2090. return False
  2091. local_refs = parent_scope.locals.get(node.name, [])
  2092. for ref_node in local_refs:
  2093. # If local ref is in the same frame as our node, but on a later lineno
  2094. # we don't actually care about this local ref.
  2095. # Local refs are ordered, so we break.
  2096. # print(var)
  2097. # var = 1 # <- irrelevant
  2098. if defstmt_frame == node_frame and ref_node.lineno > node.lineno:
  2099. break
  2100. # If the parent of the local reference is anything but an AnnAssign
  2101. # Or if the AnnAssign adds a value the variable will now have a value
  2102. # var = 1 # OR
  2103. # var: int = 1
  2104. if (
  2105. not isinstance(ref_node.parent, nodes.AnnAssign)
  2106. or ref_node.parent.value
  2107. ) and not (
  2108. # EXCEPTION: will not have a value if a self-referencing named expression
  2109. # var: int
  2110. # if (var := var * var) <-- "var" still undefined
  2111. isinstance(ref_node.parent, nodes.NamedExpr)
  2112. and any(
  2113. anc is ref_node.parent.value for anc in node.node_ancestors()
  2114. )
  2115. ):
  2116. return False
  2117. parent = parent_scope.parent
  2118. return True
  2119. @staticmethod
  2120. def _is_first_level_self_reference(
  2121. node: nodes.Name, defstmt: nodes.ClassDef, found_nodes: list[nodes.NodeNG]
  2122. ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
  2123. """Check if a first level method's annotation or default values
  2124. refers to its own class, and return a consumer action.
  2125. """
  2126. if node.frame(future=True).parent == defstmt and node.statement(
  2127. future=True
  2128. ) == node.frame(future=True):
  2129. # Check if used as type annotation
  2130. # Break if postponed evaluation is enabled
  2131. if utils.is_node_in_type_annotation_context(node):
  2132. if not utils.is_postponed_evaluation_enabled(node):
  2133. return (VariableVisitConsumerAction.CONTINUE, None)
  2134. return (VariableVisitConsumerAction.RETURN, None)
  2135. # Check if used as default value by calling the class
  2136. if isinstance(node.parent, nodes.Call) and isinstance(
  2137. node.parent.parent, nodes.Arguments
  2138. ):
  2139. return (VariableVisitConsumerAction.CONTINUE, None)
  2140. return (VariableVisitConsumerAction.RETURN, found_nodes)
  2141. @staticmethod
  2142. def _is_never_evaluated(
  2143. defnode: nodes.NamedExpr, defnode_parent: nodes.IfExp
  2144. ) -> bool:
  2145. """Check if a NamedExpr is inside a side of if ... else that never
  2146. gets evaluated.
  2147. """
  2148. inferred_test = utils.safe_infer(defnode_parent.test)
  2149. if isinstance(inferred_test, nodes.Const):
  2150. if inferred_test.value is True and defnode == defnode_parent.orelse:
  2151. return True
  2152. if inferred_test.value is False and defnode == defnode_parent.body:
  2153. return True
  2154. return False
  2155. def _ignore_class_scope(self, node: nodes.NodeNG) -> bool:
  2156. """Return True if the node is in a local class scope, as an assignment.
  2157. Detect if we are in a local class scope, as an assignment.
  2158. For example, the following is fair game.
  2159. class A:
  2160. b = 1
  2161. c = lambda b=b: b * b
  2162. class B:
  2163. tp = 1
  2164. def func(self, arg: tp):
  2165. ...
  2166. class C:
  2167. tp = 2
  2168. def func(self, arg=tp):
  2169. ...
  2170. class C:
  2171. class Tp:
  2172. pass
  2173. class D(Tp):
  2174. ...
  2175. """
  2176. name = node.name
  2177. frame = node.statement(future=True).scope()
  2178. in_annotation_or_default_or_decorator = self._defined_in_function_definition(
  2179. node, frame
  2180. )
  2181. in_ancestor_list = utils.is_ancestor_name(frame, node)
  2182. if in_annotation_or_default_or_decorator or in_ancestor_list:
  2183. frame_locals = frame.parent.scope().locals
  2184. else:
  2185. frame_locals = frame.locals
  2186. return not (
  2187. (isinstance(frame, nodes.ClassDef) or in_annotation_or_default_or_decorator)
  2188. and not self._in_lambda_or_comprehension_body(node, frame)
  2189. and name in frame_locals
  2190. )
  2191. # pylint: disable = too-many-branches
  2192. def _loopvar_name(self, node: astroid.Name) -> None:
  2193. # filter variables according to node's scope
  2194. astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
  2195. # If this variable usage exists inside a function definition
  2196. # that exists in the same loop,
  2197. # the usage is safe because the function will not be defined either if
  2198. # the variable is not defined.
  2199. scope = node.scope()
  2200. # FunctionDef subclasses Lambda due to a curious ontology. Check both.
  2201. # See https://github.com/pylint-dev/astroid/issues/291
  2202. # TODO: Revisit when astroid 3.0 includes the change
  2203. if isinstance(scope, nodes.Lambda) and any(
  2204. asmt.scope().parent_of(scope) for asmt in astmts
  2205. ):
  2206. return
  2207. # Filter variables according to their respective scope. Test parent
  2208. # and statement to avoid #74747. This is not a total fix, which would
  2209. # introduce a mechanism similar to special attribute lookup in
  2210. # modules. Also, in order to get correct inference in this case, the
  2211. # scope lookup rules would need to be changed to return the initial
  2212. # assignment (which does not exist in code per se) as well as any later
  2213. # modifications.
  2214. if (
  2215. not astmts # pylint: disable=too-many-boolean-expressions
  2216. or (
  2217. astmts[0].parent == astmts[0].root()
  2218. and astmts[0].parent.parent_of(node)
  2219. )
  2220. or (
  2221. astmts[0].is_statement
  2222. or not isinstance(astmts[0].parent, nodes.Module)
  2223. and astmts[0].statement(future=True).parent_of(node)
  2224. )
  2225. ):
  2226. _astmts = []
  2227. else:
  2228. _astmts = astmts[:1]
  2229. for i, stmt in enumerate(astmts[1:]):
  2230. if astmts[i].statement(future=True).parent_of(
  2231. stmt
  2232. ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
  2233. continue
  2234. _astmts.append(stmt)
  2235. astmts = _astmts
  2236. if len(astmts) != 1:
  2237. return
  2238. assign = astmts[0].assign_type()
  2239. if not (
  2240. isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
  2241. and assign.statement(future=True) is not node.statement(future=True)
  2242. ):
  2243. return
  2244. if not isinstance(assign, nodes.For):
  2245. self.add_message("undefined-loop-variable", args=node.name, node=node)
  2246. return
  2247. for else_stmt in assign.orelse:
  2248. if isinstance(
  2249. else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
  2250. ):
  2251. return
  2252. # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
  2253. if isinstance(else_stmt, nodes.Expr) and isinstance(
  2254. else_stmt.value, nodes.Call
  2255. ):
  2256. inferred_func = utils.safe_infer(else_stmt.value.func)
  2257. if (
  2258. isinstance(inferred_func, nodes.FunctionDef)
  2259. and inferred_func.returns
  2260. ):
  2261. inferred_return = utils.safe_infer(inferred_func.returns)
  2262. if isinstance(
  2263. inferred_return, nodes.FunctionDef
  2264. ) and inferred_return.qname() in {
  2265. *TYPING_NORETURN,
  2266. *TYPING_NEVER,
  2267. "typing._SpecialForm",
  2268. }:
  2269. return
  2270. # typing_extensions.NoReturn returns a _SpecialForm
  2271. if (
  2272. isinstance(inferred_return, bases.Instance)
  2273. and inferred_return.qname() == "typing._SpecialForm"
  2274. ):
  2275. return
  2276. maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
  2277. if maybe_walrus:
  2278. maybe_comprehension = utils.get_node_first_ancestor_of_type(
  2279. maybe_walrus, nodes.Comprehension
  2280. )
  2281. if maybe_comprehension:
  2282. comprehension_scope = utils.get_node_first_ancestor_of_type(
  2283. maybe_comprehension, nodes.ComprehensionScope
  2284. )
  2285. if comprehension_scope is None:
  2286. # Should not be possible.
  2287. pass
  2288. elif (
  2289. comprehension_scope.parent.scope() is scope
  2290. and node.name in comprehension_scope.locals
  2291. ):
  2292. return
  2293. # For functions we can do more by inferring the length of the itered object
  2294. try:
  2295. inferred = next(assign.iter.infer())
  2296. # Prefer the target of enumerate() rather than the enumerate object itself
  2297. if (
  2298. isinstance(inferred, astroid.Instance)
  2299. and inferred.qname() == "builtins.enumerate"
  2300. ):
  2301. likely_call = assign.iter
  2302. if isinstance(assign.iter, nodes.IfExp):
  2303. likely_call = assign.iter.body
  2304. if isinstance(likely_call, nodes.Call):
  2305. inferred = next(likely_call.args[0].infer())
  2306. except astroid.InferenceError:
  2307. self.add_message("undefined-loop-variable", args=node.name, node=node)
  2308. else:
  2309. if (
  2310. isinstance(inferred, astroid.Instance)
  2311. and inferred.qname() == BUILTIN_RANGE
  2312. ):
  2313. # Consider range() objects safe, even if they might not yield any results.
  2314. return
  2315. # Consider sequences.
  2316. sequences = (
  2317. nodes.List,
  2318. nodes.Tuple,
  2319. nodes.Dict,
  2320. nodes.Set,
  2321. astroid.objects.FrozenSet,
  2322. )
  2323. if not isinstance(inferred, sequences):
  2324. self.add_message("undefined-loop-variable", args=node.name, node=node)
  2325. return
  2326. elements = getattr(inferred, "elts", getattr(inferred, "items", []))
  2327. if not elements:
  2328. self.add_message("undefined-loop-variable", args=node.name, node=node)
  2329. # pylint: disable = too-many-branches
  2330. def _check_is_unused(
  2331. self,
  2332. name: str,
  2333. node: nodes.FunctionDef,
  2334. stmt: nodes.NodeNG,
  2335. global_names: set[str],
  2336. nonlocal_names: Iterable[str],
  2337. comprehension_target_names: Iterable[str],
  2338. ) -> None:
  2339. # Ignore some special names specified by user configuration.
  2340. if self._is_name_ignored(stmt, name):
  2341. return
  2342. # Ignore names that were added dynamically to the Function scope
  2343. if (
  2344. isinstance(node, nodes.FunctionDef)
  2345. and name == "__class__"
  2346. and len(node.locals["__class__"]) == 1
  2347. and isinstance(node.locals["__class__"][0], nodes.ClassDef)
  2348. ):
  2349. return
  2350. # Ignore names imported by the global statement.
  2351. if isinstance(stmt, (nodes.Global, nodes.Import, nodes.ImportFrom)):
  2352. # Detect imports, assigned to global statements.
  2353. if global_names and _import_name_is_global(stmt, global_names):
  2354. return
  2355. # Ignore names in comprehension targets
  2356. if name in comprehension_target_names:
  2357. return
  2358. # Ignore names in string literal type annotation.
  2359. if name in self._type_annotation_names:
  2360. return
  2361. argnames = node.argnames()
  2362. # Care about functions with unknown argument (builtins)
  2363. if name in argnames:
  2364. if node.name == "__new__":
  2365. is_init_def = False
  2366. # Look for the `__init__` method in all the methods of the same class.
  2367. for n in node.parent.get_children():
  2368. is_init_def = hasattr(n, "name") and (n.name == "__init__")
  2369. if is_init_def:
  2370. break
  2371. # Ignore unused arguments check for `__new__` if `__init__` is defined.
  2372. if is_init_def:
  2373. return
  2374. self._check_unused_arguments(name, node, stmt, argnames, nonlocal_names)
  2375. else:
  2376. if stmt.parent and isinstance(
  2377. stmt.parent, (nodes.Assign, nodes.AnnAssign, nodes.Tuple, nodes.For)
  2378. ):
  2379. if name in nonlocal_names:
  2380. return
  2381. qname = asname = None
  2382. if isinstance(stmt, (nodes.Import, nodes.ImportFrom)):
  2383. # Need the complete name, which we don't have in .locals.
  2384. if len(stmt.names) > 1:
  2385. import_names = next(
  2386. (names for names in stmt.names if name in names), None
  2387. )
  2388. else:
  2389. import_names = stmt.names[0]
  2390. if import_names:
  2391. qname, asname = import_names
  2392. name = asname or qname
  2393. if _has_locals_call_after_node(stmt, node.scope()):
  2394. message_name = "possibly-unused-variable"
  2395. else:
  2396. if isinstance(stmt, nodes.Import):
  2397. if asname is not None:
  2398. msg = f"{qname} imported as {asname}"
  2399. else:
  2400. msg = f"import {name}"
  2401. self.add_message("unused-import", args=msg, node=stmt)
  2402. return
  2403. if isinstance(stmt, nodes.ImportFrom):
  2404. if asname is not None:
  2405. msg = f"{qname} imported from {stmt.modname} as {asname}"
  2406. else:
  2407. msg = f"{name} imported from {stmt.modname}"
  2408. self.add_message("unused-import", args=msg, node=stmt)
  2409. return
  2410. message_name = "unused-variable"
  2411. if isinstance(stmt, nodes.FunctionDef) and stmt.decorators:
  2412. return
  2413. # Don't check function stubs created only for type information
  2414. if utils.is_overload_stub(node):
  2415. return
  2416. # Special case for exception variable
  2417. if isinstance(stmt.parent, nodes.ExceptHandler) and any(
  2418. n.name == name for n in stmt.parent.nodes_of_class(nodes.Name)
  2419. ):
  2420. return
  2421. self.add_message(message_name, args=name, node=stmt)
  2422. def _is_name_ignored(
  2423. self, stmt: nodes.NodeNG, name: str
  2424. ) -> re.Pattern[str] | re.Match[str] | None:
  2425. authorized_rgx = self.linter.config.dummy_variables_rgx
  2426. if (
  2427. isinstance(stmt, nodes.AssignName)
  2428. and isinstance(stmt.parent, nodes.Arguments)
  2429. or isinstance(stmt, nodes.Arguments)
  2430. ):
  2431. regex: re.Pattern[str] = self.linter.config.ignored_argument_names
  2432. else:
  2433. regex = authorized_rgx
  2434. # See https://stackoverflow.com/a/47007761/2519059 to
  2435. # understand what this function return. Please do NOT use
  2436. # this elsewhere, this is confusing for no benefit
  2437. return regex and regex.match(name)
  2438. def _check_unused_arguments(
  2439. self,
  2440. name: str,
  2441. node: nodes.FunctionDef,
  2442. stmt: nodes.NodeNG,
  2443. argnames: list[str],
  2444. nonlocal_names: Iterable[str],
  2445. ) -> None:
  2446. is_method = node.is_method()
  2447. klass = node.parent.frame(future=True)
  2448. if is_method and isinstance(klass, nodes.ClassDef):
  2449. confidence = (
  2450. INFERENCE if utils.has_known_bases(klass) else INFERENCE_FAILURE
  2451. )
  2452. else:
  2453. confidence = HIGH
  2454. if is_method:
  2455. # Don't warn for the first argument of a (non static) method
  2456. if node.type != "staticmethod" and name == argnames[0]:
  2457. return
  2458. # Don't warn for argument of an overridden method
  2459. overridden = overridden_method(klass, node.name)
  2460. if overridden is not None and name in overridden.argnames():
  2461. return
  2462. if node.name in utils.PYMETHODS and node.name not in (
  2463. "__init__",
  2464. "__new__",
  2465. ):
  2466. return
  2467. # Don't check callback arguments
  2468. if any(
  2469. node.name.startswith(cb) or node.name.endswith(cb)
  2470. for cb in self.linter.config.callbacks
  2471. ):
  2472. return
  2473. # Don't check arguments of singledispatch.register function.
  2474. if utils.is_registered_in_singledispatch_function(node):
  2475. return
  2476. # Don't check function stubs created only for type information
  2477. if utils.is_overload_stub(node):
  2478. return
  2479. # Don't check protocol classes
  2480. if utils.is_protocol_class(klass):
  2481. return
  2482. if name in nonlocal_names:
  2483. return
  2484. self.add_message("unused-argument", args=name, node=stmt, confidence=confidence)
  2485. def _check_late_binding_closure(self, node: nodes.Name) -> None:
  2486. """Check whether node is a cell var that is assigned within a containing loop.
  2487. Special cases where we don't care about the error:
  2488. 1. When the node's function is immediately called, e.g. (lambda: i)()
  2489. 2. When the node's function is returned from within the loop, e.g. return lambda: i
  2490. """
  2491. if not self.linter.is_message_enabled("cell-var-from-loop"):
  2492. return
  2493. node_scope = node.frame(future=True)
  2494. # If node appears in a default argument expression,
  2495. # look at the next enclosing frame instead
  2496. if utils.is_default_argument(node, node_scope):
  2497. node_scope = node_scope.parent.frame(future=True)
  2498. # Check if node is a cell var
  2499. if (
  2500. not isinstance(node_scope, (nodes.Lambda, nodes.FunctionDef))
  2501. or node.name in node_scope.locals
  2502. ):
  2503. return
  2504. assign_scope, stmts = node.lookup(node.name)
  2505. if not stmts or not assign_scope.parent_of(node_scope):
  2506. return
  2507. if utils.is_comprehension(assign_scope):
  2508. self.add_message("cell-var-from-loop", node=node, args=node.name)
  2509. else:
  2510. # Look for an enclosing For loop.
  2511. # Currently, we only consider the first assignment
  2512. assignment_node = stmts[0]
  2513. maybe_for = assignment_node
  2514. while maybe_for and not isinstance(maybe_for, nodes.For):
  2515. if maybe_for is assign_scope:
  2516. break
  2517. maybe_for = maybe_for.parent
  2518. else:
  2519. if (
  2520. maybe_for
  2521. and maybe_for.parent_of(node_scope)
  2522. and not utils.is_being_called(node_scope)
  2523. and node_scope.parent
  2524. and not isinstance(node_scope.statement(future=True), nodes.Return)
  2525. ):
  2526. self.add_message("cell-var-from-loop", node=node, args=node.name)
  2527. def _should_ignore_redefined_builtin(self, stmt: nodes.NodeNG) -> bool:
  2528. if not isinstance(stmt, nodes.ImportFrom):
  2529. return False
  2530. return stmt.modname in self.linter.config.redefining_builtins_modules
  2531. def _allowed_redefined_builtin(self, name: str) -> bool:
  2532. return name in self.linter.config.allowed_redefined_builtins
  2533. @staticmethod
  2534. def _comprehension_between_frame_and_node(node: nodes.Name) -> bool:
  2535. """Return True if a ComprehensionScope intervenes between `node` and its
  2536. frame.
  2537. """
  2538. closest_comprehension_scope = utils.get_node_first_ancestor_of_type(
  2539. node, nodes.ComprehensionScope
  2540. )
  2541. return closest_comprehension_scope is not None and node.frame(
  2542. future=True
  2543. ).parent_of(closest_comprehension_scope)
  2544. def _store_type_annotation_node(self, type_annotation: nodes.NodeNG) -> None:
  2545. """Given a type annotation, store all the name nodes it refers to."""
  2546. if isinstance(type_annotation, nodes.Name):
  2547. self._type_annotation_names.append(type_annotation.name)
  2548. return
  2549. if isinstance(type_annotation, nodes.Attribute):
  2550. self._store_type_annotation_node(type_annotation.expr)
  2551. return
  2552. if not isinstance(type_annotation, nodes.Subscript):
  2553. return
  2554. if (
  2555. isinstance(type_annotation.value, nodes.Attribute)
  2556. and isinstance(type_annotation.value.expr, nodes.Name)
  2557. and type_annotation.value.expr.name == TYPING_MODULE
  2558. ):
  2559. self._type_annotation_names.append(TYPING_MODULE)
  2560. return
  2561. self._type_annotation_names.extend(
  2562. annotation.name for annotation in type_annotation.nodes_of_class(nodes.Name)
  2563. )
  2564. def _store_type_annotation_names(
  2565. self, node: nodes.For | nodes.Assign | nodes.With
  2566. ) -> None:
  2567. type_annotation = node.type_annotation
  2568. if not type_annotation:
  2569. return
  2570. self._store_type_annotation_node(node.type_annotation)
  2571. def _check_self_cls_assign(self, node: nodes.Assign) -> None:
  2572. """Check that self/cls don't get assigned."""
  2573. assign_names: set[str | None] = set()
  2574. for target in node.targets:
  2575. if isinstance(target, nodes.AssignName):
  2576. assign_names.add(target.name)
  2577. elif isinstance(target, nodes.Tuple):
  2578. assign_names.update(
  2579. elt.name for elt in target.elts if isinstance(elt, nodes.AssignName)
  2580. )
  2581. scope = node.scope()
  2582. nonlocals_with_same_name = node.scope().parent and any(
  2583. child for child in scope.body if isinstance(child, nodes.Nonlocal)
  2584. )
  2585. if nonlocals_with_same_name:
  2586. scope = node.scope().parent.scope()
  2587. if not (
  2588. isinstance(scope, nodes.FunctionDef)
  2589. and scope.is_method()
  2590. and "builtins.staticmethod" not in scope.decoratornames()
  2591. ):
  2592. return
  2593. argument_names = scope.argnames()
  2594. if not argument_names:
  2595. return
  2596. self_cls_name = argument_names[0]
  2597. if self_cls_name in assign_names:
  2598. self.add_message("self-cls-assignment", node=node, args=(self_cls_name,))
  2599. def _check_unpacking(
  2600. self, inferred: InferenceResult, node: nodes.Assign, targets: list[nodes.NodeNG]
  2601. ) -> None:
  2602. """Check for unbalanced tuple unpacking
  2603. and unpacking non sequences.
  2604. """
  2605. if utils.is_inside_abstract_class(node):
  2606. return
  2607. if utils.is_comprehension(node):
  2608. return
  2609. if isinstance(inferred, util.UninferableBase):
  2610. return
  2611. if (
  2612. isinstance(inferred.parent, nodes.Arguments)
  2613. and isinstance(node.value, nodes.Name)
  2614. and node.value.name == inferred.parent.vararg
  2615. ):
  2616. # Variable-length argument, we can't determine the length.
  2617. return
  2618. # Attempt to check unpacking is properly balanced
  2619. values = self._nodes_to_unpack(inferred)
  2620. details = _get_unpacking_extra_info(node, inferred)
  2621. if values is not None:
  2622. if len(targets) != len(values):
  2623. self._report_unbalanced_unpacking(
  2624. node, inferred, targets, values, details
  2625. )
  2626. # attempt to check unpacking may be possible (i.e. RHS is iterable)
  2627. elif not utils.is_iterable(inferred):
  2628. self._report_unpacking_non_sequence(node, details)
  2629. @staticmethod
  2630. def _nodes_to_unpack(node: nodes.NodeNG) -> list[nodes.NodeNG] | None:
  2631. """Return the list of values of the `Assign` node."""
  2632. if isinstance(node, (nodes.Tuple, nodes.List) + DICT_TYPES):
  2633. return node.itered() # type: ignore[no-any-return]
  2634. if isinstance(node, astroid.Instance) and any(
  2635. ancestor.qname() == "typing.NamedTuple" for ancestor in node.ancestors()
  2636. ):
  2637. return [i for i in node.values() if isinstance(i, nodes.AssignName)]
  2638. return None
  2639. def _report_unbalanced_unpacking(
  2640. self,
  2641. node: nodes.NodeNG,
  2642. inferred: InferenceResult,
  2643. targets: list[nodes.NodeNG],
  2644. values: list[nodes.NodeNG],
  2645. details: str,
  2646. ) -> None:
  2647. args = (
  2648. details,
  2649. len(targets),
  2650. "" if len(targets) == 1 else "s",
  2651. len(values),
  2652. "" if len(values) == 1 else "s",
  2653. )
  2654. symbol = (
  2655. "unbalanced-dict-unpacking"
  2656. if isinstance(inferred, DICT_TYPES)
  2657. else "unbalanced-tuple-unpacking"
  2658. )
  2659. self.add_message(symbol, node=node, args=args, confidence=INFERENCE)
  2660. def _report_unpacking_non_sequence(self, node: nodes.NodeNG, details: str) -> None:
  2661. if details and not details.startswith(" "):
  2662. details = f" {details}"
  2663. self.add_message("unpacking-non-sequence", node=node, args=details)
  2664. def _check_module_attrs(
  2665. self,
  2666. node: _base_nodes.ImportNode,
  2667. module: nodes.Module,
  2668. module_names: list[str],
  2669. ) -> nodes.Module | None:
  2670. """Check that module_names (list of string) are accessible through the
  2671. given module, if the latest access name corresponds to a module, return it.
  2672. """
  2673. while module_names:
  2674. name = module_names.pop(0)
  2675. if name == "__dict__":
  2676. module = None
  2677. break
  2678. try:
  2679. module = next(module.getattr(name)[0].infer())
  2680. if not isinstance(module, nodes.Module):
  2681. return None
  2682. except astroid.NotFoundError:
  2683. if module.name in self._ignored_modules:
  2684. return None
  2685. self.add_message(
  2686. "no-name-in-module", args=(name, module.name), node=node
  2687. )
  2688. return None
  2689. except astroid.InferenceError:
  2690. return None
  2691. if module_names:
  2692. modname = module.name if module else "__dict__"
  2693. self.add_message(
  2694. "no-name-in-module", node=node, args=(".".join(module_names), modname)
  2695. )
  2696. return None
  2697. if isinstance(module, nodes.Module):
  2698. return module
  2699. return None
  2700. def _check_all(
  2701. self, node: nodes.Module, not_consumed: dict[str, list[nodes.NodeNG]]
  2702. ) -> None:
  2703. try:
  2704. assigned = next(node.igetattr("__all__"))
  2705. except astroid.InferenceError:
  2706. return
  2707. if isinstance(assigned, util.UninferableBase):
  2708. return
  2709. if assigned.pytype() not in {"builtins.list", "builtins.tuple"}:
  2710. line, col = assigned.tolineno, assigned.col_offset
  2711. self.add_message("invalid-all-format", line=line, col_offset=col, node=node)
  2712. return
  2713. for elt in getattr(assigned, "elts", ()):
  2714. try:
  2715. elt_name = next(elt.infer())
  2716. except astroid.InferenceError:
  2717. continue
  2718. if isinstance(elt_name, util.UninferableBase):
  2719. continue
  2720. if not elt_name.parent:
  2721. continue
  2722. if not isinstance(elt_name, nodes.Const) or not isinstance(
  2723. elt_name.value, str
  2724. ):
  2725. self.add_message("invalid-all-object", args=elt.as_string(), node=elt)
  2726. continue
  2727. elt_name = elt_name.value
  2728. # If elt is in not_consumed, remove it from not_consumed
  2729. if elt_name in not_consumed:
  2730. del not_consumed[elt_name]
  2731. continue
  2732. if elt_name not in node.locals:
  2733. if not node.package:
  2734. self.add_message(
  2735. "undefined-all-variable", args=(elt_name,), node=elt
  2736. )
  2737. else:
  2738. basename = os.path.splitext(node.file)[0]
  2739. if os.path.basename(basename) == "__init__":
  2740. name = node.name + "." + elt_name
  2741. try:
  2742. astroid.modutils.file_from_modpath(name.split("."))
  2743. except ImportError:
  2744. self.add_message(
  2745. "undefined-all-variable", args=(elt_name,), node=elt
  2746. )
  2747. except SyntaxError:
  2748. # don't yield a syntax-error warning,
  2749. # because it will be later yielded
  2750. # when the file will be checked
  2751. pass
  2752. def _check_globals(self, not_consumed: dict[str, nodes.NodeNG]) -> None:
  2753. if self._allow_global_unused_variables:
  2754. return
  2755. for name, node_lst in not_consumed.items():
  2756. for node in node_lst:
  2757. if in_type_checking_block(node):
  2758. continue
  2759. self.add_message("unused-variable", args=(name,), node=node)
  2760. # pylint: disable = too-many-branches
  2761. def _check_imports(self, not_consumed: dict[str, list[nodes.NodeNG]]) -> None:
  2762. local_names = _fix_dot_imports(not_consumed)
  2763. checked = set()
  2764. unused_wildcard_imports: defaultdict[
  2765. tuple[str, nodes.ImportFrom], list[str]
  2766. ] = collections.defaultdict(list)
  2767. for name, stmt in local_names:
  2768. for imports in stmt.names:
  2769. real_name = imported_name = imports[0]
  2770. if imported_name == "*":
  2771. real_name = name
  2772. as_name = imports[1]
  2773. if real_name in checked:
  2774. continue
  2775. if name not in (real_name, as_name):
  2776. continue
  2777. checked.add(real_name)
  2778. is_type_annotation_import = (
  2779. imported_name in self._type_annotation_names
  2780. or as_name in self._type_annotation_names
  2781. )
  2782. is_dummy_import = (
  2783. as_name
  2784. and self.linter.config.dummy_variables_rgx
  2785. and self.linter.config.dummy_variables_rgx.match(as_name)
  2786. )
  2787. if isinstance(stmt, nodes.Import) or (
  2788. isinstance(stmt, nodes.ImportFrom) and not stmt.modname
  2789. ):
  2790. if isinstance(stmt, nodes.ImportFrom) and SPECIAL_OBJ.search(
  2791. imported_name
  2792. ):
  2793. # Filter special objects (__doc__, __all__) etc.,
  2794. # because they can be imported for exporting.
  2795. continue
  2796. if is_type_annotation_import or is_dummy_import:
  2797. # Most likely a typing import if it wasn't used so far.
  2798. # Also filter dummy variables.
  2799. continue
  2800. if as_name is None:
  2801. msg = f"import {imported_name}"
  2802. else:
  2803. msg = f"{imported_name} imported as {as_name}"
  2804. if not in_type_checking_block(stmt):
  2805. self.add_message("unused-import", args=msg, node=stmt)
  2806. elif isinstance(stmt, nodes.ImportFrom) and stmt.modname != FUTURE:
  2807. if SPECIAL_OBJ.search(imported_name):
  2808. # Filter special objects (__doc__, __all__) etc.,
  2809. # because they can be imported for exporting.
  2810. continue
  2811. if _is_from_future_import(stmt, name):
  2812. # Check if the name is in fact loaded from a
  2813. # __future__ import in another module.
  2814. continue
  2815. if is_type_annotation_import or is_dummy_import:
  2816. # Most likely a typing import if it wasn't used so far.
  2817. # Also filter dummy variables.
  2818. continue
  2819. if imported_name == "*":
  2820. unused_wildcard_imports[(stmt.modname, stmt)].append(name)
  2821. else:
  2822. if as_name is None:
  2823. msg = f"{imported_name} imported from {stmt.modname}"
  2824. else:
  2825. msg = f"{imported_name} imported from {stmt.modname} as {as_name}"
  2826. if not in_type_checking_block(stmt):
  2827. self.add_message("unused-import", args=msg, node=stmt)
  2828. # Construct string for unused-wildcard-import message
  2829. for module, unused_list in unused_wildcard_imports.items():
  2830. if len(unused_list) == 1:
  2831. arg_string = unused_list[0]
  2832. else:
  2833. arg_string = (
  2834. f"{', '.join(i for i in unused_list[:-1])} and {unused_list[-1]}"
  2835. )
  2836. self.add_message(
  2837. "unused-wildcard-import", args=(arg_string, module[0]), node=module[1]
  2838. )
  2839. del self._to_consume
  2840. def _check_metaclasses(self, node: nodes.Module | nodes.FunctionDef) -> None:
  2841. """Update consumption analysis for metaclasses."""
  2842. consumed: list[tuple[dict[str, list[nodes.NodeNG]], str]] = []
  2843. for child_node in node.get_children():
  2844. if isinstance(child_node, nodes.ClassDef):
  2845. consumed.extend(self._check_classdef_metaclasses(child_node, node))
  2846. # Pop the consumed items, in order to avoid having
  2847. # unused-import and unused-variable false positives
  2848. for scope_locals, name in consumed:
  2849. scope_locals.pop(name, None)
  2850. def _check_classdef_metaclasses(
  2851. self, klass: nodes.ClassDef, parent_node: nodes.Module | nodes.FunctionDef
  2852. ) -> list[tuple[dict[str, list[nodes.NodeNG]], str]]:
  2853. if not klass._metaclass:
  2854. # Skip if this class doesn't use explicitly a metaclass, but inherits it from ancestors
  2855. return []
  2856. consumed: list[tuple[dict[str, list[nodes.NodeNG]], str]] = []
  2857. metaclass = klass.metaclass()
  2858. name = ""
  2859. if isinstance(klass._metaclass, nodes.Name):
  2860. name = klass._metaclass.name
  2861. elif isinstance(klass._metaclass, nodes.Attribute) and klass._metaclass.expr:
  2862. attr = klass._metaclass.expr
  2863. while not isinstance(attr, nodes.Name):
  2864. attr = attr.expr
  2865. name = attr.name
  2866. elif isinstance(klass._metaclass, nodes.Call) and isinstance(
  2867. klass._metaclass.func, nodes.Name
  2868. ):
  2869. name = klass._metaclass.func.name
  2870. elif metaclass:
  2871. name = metaclass.root().name
  2872. found = False
  2873. name = METACLASS_NAME_TRANSFORMS.get(name, name)
  2874. if name:
  2875. # check enclosing scopes starting from most local
  2876. for scope_locals, _, _, _ in self._to_consume[::-1]:
  2877. found_nodes = scope_locals.get(name, [])
  2878. for found_node in found_nodes:
  2879. if found_node.lineno <= klass.lineno:
  2880. consumed.append((scope_locals, name))
  2881. found = True
  2882. break
  2883. # Check parent scope
  2884. nodes_in_parent_scope = parent_node.locals.get(name, [])
  2885. for found_node_parent in nodes_in_parent_scope:
  2886. if found_node_parent.lineno <= klass.lineno:
  2887. found = True
  2888. break
  2889. if (
  2890. not found
  2891. and not metaclass
  2892. and not (
  2893. name in nodes.Module.scope_attrs
  2894. or utils.is_builtin(name)
  2895. or name in self.linter.config.additional_builtins
  2896. )
  2897. ):
  2898. self.add_message("undefined-variable", node=klass, args=(name,))
  2899. return consumed
  2900. def visit_subscript(self, node: nodes.Subscript) -> None:
  2901. inferred_slice = utils.safe_infer(node.slice)
  2902. self._check_potential_index_error(node, inferred_slice)
  2903. def _check_potential_index_error(
  2904. self, node: nodes.Subscript, inferred_slice: nodes.NodeNG | None
  2905. ) -> None:
  2906. """Check for the potential-index-error message."""
  2907. # Currently we only check simple slices of a single integer
  2908. if not isinstance(inferred_slice, nodes.Const) or not isinstance(
  2909. inferred_slice.value, int
  2910. ):
  2911. return
  2912. # If the node.value is a Tuple or List without inference it is defined in place
  2913. if isinstance(node.value, (nodes.Tuple, nodes.List)):
  2914. # Add 1 because iterables are 0-indexed
  2915. if len(node.value.elts) < inferred_slice.value + 1:
  2916. self.add_message(
  2917. "potential-index-error", node=node, confidence=INFERENCE
  2918. )
  2919. return
  2920. @utils.only_required_for_messages(
  2921. "unused-import",
  2922. "unused-variable",
  2923. )
  2924. def visit_const(self, node: nodes.Const) -> None:
  2925. """Take note of names that appear inside string literal type annotations
  2926. unless the string is a parameter to `typing.Literal` or `typing.Annotation`.
  2927. """
  2928. if node.pytype() != "builtins.str":
  2929. return
  2930. if not utils.is_node_in_type_annotation_context(node):
  2931. return
  2932. # Check if parent's or grandparent's first child is typing.Literal
  2933. parent = node.parent
  2934. if isinstance(parent, nodes.Tuple):
  2935. parent = parent.parent
  2936. if isinstance(parent, nodes.Subscript):
  2937. origin = next(parent.get_children(), None)
  2938. if origin is not None and utils.is_typing_member(
  2939. origin, ("Annotated", "Literal")
  2940. ):
  2941. return
  2942. try:
  2943. annotation = extract_node(node.value)
  2944. self._store_type_annotation_node(annotation)
  2945. except ValueError:
  2946. # e.g. node.value is white space
  2947. pass
  2948. except astroid.AstroidSyntaxError:
  2949. # e.g. "?" or ":" in typing.Literal["?", ":"]
  2950. pass
  2951. def register(linter: PyLinter) -> None:
  2952. linter.register_checker(VariablesChecker(linter))