utils.py 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711
  1. # Copyright (c) 2006-2007, 2009-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
  2. # Copyright (c) 2009 Mads Kiilerich <mads@kiilerich.com>
  3. # Copyright (c) 2010 Daniel Harding <dharding@gmail.com>
  4. # Copyright (c) 2012-2014 Google, Inc.
  5. # Copyright (c) 2012 FELD Boris <lothiraldan@gmail.com>
  6. # Copyright (c) 2013-2020 Claudiu Popa <pcmanticore@gmail.com>
  7. # Copyright (c) 2014 Brett Cannon <brett@python.org>
  8. # Copyright (c) 2014 Ricardo Gemignani <ricardo.gemignani@gmail.com>
  9. # Copyright (c) 2014 Arun Persaud <arun@nubati.net>
  10. # Copyright (c) 2015 Dmitry Pribysh <dmand@yandex.ru>
  11. # Copyright (c) 2015 Florian Bruhin <me@the-compiler.org>
  12. # Copyright (c) 2015 Radu Ciorba <radu@devrandom.ro>
  13. # Copyright (c) 2015 Ionel Cristian Maries <contact@ionelmc.ro>
  14. # Copyright (c) 2016, 2018-2019 Ashley Whetter <ashley@awhetter.co.uk>
  15. # Copyright (c) 2016-2017 Łukasz Rogalski <rogalski.91@gmail.com>
  16. # Copyright (c) 2016-2017 Moises Lopez <moylop260@vauxoo.com>
  17. # Copyright (c) 2016 Brian C. Lane <bcl@redhat.com>
  18. # Copyright (c) 2017-2018, 2020 hippo91 <guillaume.peillex@gmail.com>
  19. # Copyright (c) 2017 ttenhoeve-aa <ttenhoeve@appannie.com>
  20. # Copyright (c) 2018 Alan Chan <achan961117@gmail.com>
  21. # Copyright (c) 2018 Sushobhit <31987769+sushobhit27@users.noreply.github.com>
  22. # Copyright (c) 2018 Yury Gribov <tetra2005@gmail.com>
  23. # Copyright (c) 2018 Caio Carrara <ccarrara@redhat.com>
  24. # Copyright (c) 2018 ssolanki <sushobhitsolanki@gmail.com>
  25. # Copyright (c) 2018 Bryce Guinta <bryce.guinta@protonmail.com>
  26. # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
  27. # Copyright (c) 2018 Ville Skyttä <ville.skytta@iki.fi>
  28. # Copyright (c) 2018 Brian Shaginaw <brian.shaginaw@warbyparker.com>
  29. # Copyright (c) 2019-2021 Pierre Sassoulas <pierre.sassoulas@gmail.com>
  30. # Copyright (c) 2019 Matthijs Blom <19817960+MatthijsBlom@users.noreply.github.com>
  31. # Copyright (c) 2019 Djailla <bastien.vallet@gmail.com>
  32. # Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>
  33. # Copyright (c) 2019 Nathan Marrow <nmarrow@google.com>
  34. # Copyright (c) 2019 Svet <svet@hyperscience.com>
  35. # Copyright (c) 2019 Pascal Corpet <pcorpet@users.noreply.github.com>
  36. # Copyright (c) 2020 Batuhan Taskaya <batuhanosmantaskaya@gmail.com>
  37. # Copyright (c) 2020 Luigi <luigi.cristofolini@q-ctrl.com>
  38. # Copyright (c) 2020 ethan-leba <ethanleba5@gmail.com>
  39. # Copyright (c) 2020 Damien Baty <damien.baty@polyconseil.fr>
  40. # Copyright (c) 2020 Andrew Simmons <anjsimmo@gmail.com>
  41. # Copyright (c) 2020 Ram Rachum <ram@rachum.com>
  42. # Copyright (c) 2020 Slavfox <slavfoxman@gmail.com>
  43. # Copyright (c) 2020 Anthony Sottile <asottile@umich.edu>
  44. # Copyright (c) 2021 Daniël van Noord <13665637+DanielNoord@users.noreply.github.com>
  45. # Copyright (c) 2021 bot <bot@noreply.github.com>
  46. # Copyright (c) 2021 Yu Shao, Pang <36848472+yushao2@users.noreply.github.com>
  47. # Copyright (c) 2021 Mark Byrne <31762852+mbyrnepr2@users.noreply.github.com>
  48. # Copyright (c) 2021 Nick Drozd <nicholasdrozd@gmail.com>
  49. # Copyright (c) 2021 Arianna Y <92831762+areveny@users.noreply.github.com>
  50. # Copyright (c) 2021 Jaehoon Hwang <jaehoonhwang@users.noreply.github.com>
  51. # Copyright (c) 2021 Samuel FORESTIER <HorlogeSkynet@users.noreply.github.com>
  52. # Copyright (c) 2021 Marc Mueller <30130371+cdce8p@users.noreply.github.com>
  53. # Copyright (c) 2021 David Liu <david@cs.toronto.edu>
  54. # Copyright (c) 2021 Matus Valo <matusvalo@users.noreply.github.com>
  55. # Copyright (c) 2021 Lorena B <46202743+lorena-b@users.noreply.github.com>
  56. # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  57. # For details: https://github.com/PyCQA/pylint/blob/main/LICENSE
  58. """some functions that may be useful for various checkers
  59. """
  60. import builtins
  61. import itertools
  62. import numbers
  63. import re
  64. import string
  65. import warnings
  66. from functools import lru_cache, partial
  67. from typing import (
  68. Callable,
  69. Dict,
  70. Iterable,
  71. List,
  72. Match,
  73. Optional,
  74. Set,
  75. Tuple,
  76. Type,
  77. TypeVar,
  78. Union,
  79. )
  80. import _string
  81. import astroid
  82. import astroid.objects
  83. from astroid import TooManyLevelsError, nodes
  84. from astroid.context import InferenceContext
  85. COMP_NODE_TYPES = (
  86. nodes.ListComp,
  87. nodes.SetComp,
  88. nodes.DictComp,
  89. nodes.GeneratorExp,
  90. )
  91. EXCEPTIONS_MODULE = "builtins"
  92. ABC_MODULES = {"abc", "_py_abc"}
  93. ABC_METHODS = {
  94. "abc.abstractproperty",
  95. "abc.abstractmethod",
  96. "abc.abstractclassmethod",
  97. "abc.abstractstaticmethod",
  98. }
  99. TYPING_PROTOCOLS = frozenset(
  100. {"typing.Protocol", "typing_extensions.Protocol", ".Protocol"}
  101. )
  102. ITER_METHOD = "__iter__"
  103. AITER_METHOD = "__aiter__"
  104. NEXT_METHOD = "__next__"
  105. GETITEM_METHOD = "__getitem__"
  106. CLASS_GETITEM_METHOD = "__class_getitem__"
  107. SETITEM_METHOD = "__setitem__"
  108. DELITEM_METHOD = "__delitem__"
  109. CONTAINS_METHOD = "__contains__"
  110. KEYS_METHOD = "keys"
  111. # Dictionary which maps the number of expected parameters a
  112. # special method can have to a set of special methods.
  113. # The following keys are used to denote the parameters restrictions:
  114. #
  115. # * None: variable number of parameters
  116. # * number: exactly that number of parameters
  117. # * tuple: this are the odd ones. Basically it means that the function
  118. # can work with any number of arguments from that tuple,
  119. # although it's best to implement it in order to accept
  120. # all of them.
  121. _SPECIAL_METHODS_PARAMS = {
  122. None: ("__new__", "__init__", "__call__"),
  123. 0: (
  124. "__del__",
  125. "__repr__",
  126. "__str__",
  127. "__bytes__",
  128. "__hash__",
  129. "__bool__",
  130. "__dir__",
  131. "__len__",
  132. "__length_hint__",
  133. "__iter__",
  134. "__reversed__",
  135. "__neg__",
  136. "__pos__",
  137. "__abs__",
  138. "__invert__",
  139. "__complex__",
  140. "__int__",
  141. "__float__",
  142. "__index__",
  143. "__trunc__",
  144. "__floor__",
  145. "__ceil__",
  146. "__enter__",
  147. "__aenter__",
  148. "__getnewargs_ex__",
  149. "__getnewargs__",
  150. "__getstate__",
  151. "__reduce__",
  152. "__copy__",
  153. "__unicode__",
  154. "__nonzero__",
  155. "__await__",
  156. "__aiter__",
  157. "__anext__",
  158. "__fspath__",
  159. ),
  160. 1: (
  161. "__format__",
  162. "__lt__",
  163. "__le__",
  164. "__eq__",
  165. "__ne__",
  166. "__gt__",
  167. "__ge__",
  168. "__getattr__",
  169. "__getattribute__",
  170. "__delattr__",
  171. "__delete__",
  172. "__instancecheck__",
  173. "__subclasscheck__",
  174. "__getitem__",
  175. "__missing__",
  176. "__delitem__",
  177. "__contains__",
  178. "__add__",
  179. "__sub__",
  180. "__mul__",
  181. "__truediv__",
  182. "__floordiv__",
  183. "__rfloordiv__",
  184. "__mod__",
  185. "__divmod__",
  186. "__lshift__",
  187. "__rshift__",
  188. "__and__",
  189. "__xor__",
  190. "__or__",
  191. "__radd__",
  192. "__rsub__",
  193. "__rmul__",
  194. "__rtruediv__",
  195. "__rmod__",
  196. "__rdivmod__",
  197. "__rpow__",
  198. "__rlshift__",
  199. "__rrshift__",
  200. "__rand__",
  201. "__rxor__",
  202. "__ror__",
  203. "__iadd__",
  204. "__isub__",
  205. "__imul__",
  206. "__itruediv__",
  207. "__ifloordiv__",
  208. "__imod__",
  209. "__ilshift__",
  210. "__irshift__",
  211. "__iand__",
  212. "__ixor__",
  213. "__ior__",
  214. "__ipow__",
  215. "__setstate__",
  216. "__reduce_ex__",
  217. "__deepcopy__",
  218. "__cmp__",
  219. "__matmul__",
  220. "__rmatmul__",
  221. "__imatmul__",
  222. "__div__",
  223. ),
  224. 2: ("__setattr__", "__get__", "__set__", "__setitem__", "__set_name__"),
  225. 3: ("__exit__", "__aexit__"),
  226. (0, 1): ("__round__",),
  227. (1, 2): ("__pow__",),
  228. }
  229. SPECIAL_METHODS_PARAMS = {
  230. name: params
  231. for params, methods in _SPECIAL_METHODS_PARAMS.items()
  232. for name in methods
  233. }
  234. PYMETHODS = set(SPECIAL_METHODS_PARAMS)
  235. SUBSCRIPTABLE_CLASSES_PEP585 = frozenset(
  236. (
  237. "builtins.tuple",
  238. "builtins.list",
  239. "builtins.dict",
  240. "builtins.set",
  241. "builtins.frozenset",
  242. "builtins.type",
  243. "collections.deque",
  244. "collections.defaultdict",
  245. "collections.OrderedDict",
  246. "collections.Counter",
  247. "collections.ChainMap",
  248. "_collections_abc.Awaitable",
  249. "_collections_abc.Coroutine",
  250. "_collections_abc.AsyncIterable",
  251. "_collections_abc.AsyncIterator",
  252. "_collections_abc.AsyncGenerator",
  253. "_collections_abc.Iterable",
  254. "_collections_abc.Iterator",
  255. "_collections_abc.Generator",
  256. "_collections_abc.Reversible",
  257. "_collections_abc.Container",
  258. "_collections_abc.Collection",
  259. "_collections_abc.Callable",
  260. "_collections_abc.Set",
  261. "_collections_abc.MutableSet",
  262. "_collections_abc.Mapping",
  263. "_collections_abc.MutableMapping",
  264. "_collections_abc.Sequence",
  265. "_collections_abc.MutableSequence",
  266. "_collections_abc.ByteString",
  267. "_collections_abc.MappingView",
  268. "_collections_abc.KeysView",
  269. "_collections_abc.ItemsView",
  270. "_collections_abc.ValuesView",
  271. "contextlib.AbstractContextManager",
  272. "contextlib.AbstractAsyncContextManager",
  273. "re.Pattern",
  274. "re.Match",
  275. )
  276. )
  277. T_Node = TypeVar("T_Node", bound=nodes.NodeNG)
  278. class NoSuchArgumentError(Exception):
  279. pass
  280. class InferredTypeError(Exception):
  281. pass
  282. def is_inside_lambda(node: nodes.NodeNG) -> bool:
  283. """Return whether the given node is inside a lambda"""
  284. warnings.warn(
  285. "utils.is_inside_lambda will be removed in favour of calling "
  286. "utils.get_node_first_ancestor_of_type(x, nodes.Lambda) in pylint 3.0",
  287. DeprecationWarning,
  288. )
  289. return any(isinstance(parent, nodes.Lambda) for parent in node.node_ancestors())
  290. def get_all_elements(
  291. node: nodes.NodeNG,
  292. ) -> Iterable[nodes.NodeNG]:
  293. """Recursively returns all atoms in nested lists and tuples."""
  294. if isinstance(node, (nodes.Tuple, nodes.List)):
  295. for child in node.elts:
  296. yield from get_all_elements(child)
  297. else:
  298. yield node
  299. def is_super(node: nodes.NodeNG) -> bool:
  300. """return True if the node is referencing the "super" builtin function"""
  301. if getattr(node, "name", None) == "super" and node.root().name == "builtins":
  302. return True
  303. return False
  304. def is_error(node: nodes.FunctionDef) -> bool:
  305. """Return true if the given function node only raises an exception"""
  306. return len(node.body) == 1 and isinstance(node.body[0], nodes.Raise)
  307. builtins = builtins.__dict__.copy() # type: ignore[assignment]
  308. SPECIAL_BUILTINS = ("__builtins__",) # '__path__', '__file__')
  309. def is_builtin_object(node: nodes.NodeNG) -> bool:
  310. """Returns True if the given node is an object from the __builtin__ module."""
  311. return node and node.root().name == "builtins"
  312. def is_builtin(name: str) -> bool:
  313. """return true if <name> could be considered as a builtin defined by python"""
  314. return name in builtins or name in SPECIAL_BUILTINS # type: ignore[operator]
  315. def is_defined_in_scope(
  316. var_node: nodes.NodeNG,
  317. varname: str,
  318. scope: nodes.NodeNG,
  319. ) -> bool:
  320. if isinstance(scope, nodes.If):
  321. for node in scope.body:
  322. if (
  323. isinstance(node, nodes.Assign)
  324. and any(
  325. isinstance(target, nodes.AssignName) and target.name == varname
  326. for target in node.targets
  327. )
  328. ) or (isinstance(node, nodes.Nonlocal) and varname in node.names):
  329. return True
  330. elif isinstance(scope, (COMP_NODE_TYPES, nodes.For)):
  331. for ass_node in scope.nodes_of_class(nodes.AssignName):
  332. if ass_node.name == varname:
  333. return True
  334. elif isinstance(scope, nodes.With):
  335. for expr, ids in scope.items:
  336. if expr.parent_of(var_node):
  337. break
  338. if ids and isinstance(ids, nodes.AssignName) and ids.name == varname:
  339. return True
  340. elif isinstance(scope, (nodes.Lambda, nodes.FunctionDef)):
  341. if scope.args.is_argument(varname):
  342. # If the name is found inside a default value
  343. # of a function, then let the search continue
  344. # in the parent's tree.
  345. if scope.args.parent_of(var_node):
  346. try:
  347. scope.args.default_value(varname)
  348. scope = scope.parent
  349. is_defined_in_scope(var_node, varname, scope)
  350. except astroid.NoDefault:
  351. pass
  352. return True
  353. if getattr(scope, "name", None) == varname:
  354. return True
  355. elif isinstance(scope, nodes.ExceptHandler):
  356. if isinstance(scope.name, nodes.AssignName):
  357. ass_node = scope.name
  358. if ass_node.name == varname:
  359. return True
  360. return False
  361. def is_defined_before(var_node: nodes.Name) -> bool:
  362. """Check if the given variable node is defined before
  363. Verify that the variable node is defined by a parent node
  364. (list, set, dict, or generator comprehension, lambda)
  365. or in a previous sibling node on the same line
  366. (statement_defining ; statement_using).
  367. """
  368. varname = var_node.name
  369. for parent in var_node.node_ancestors():
  370. if is_defined_in_scope(var_node, varname, parent):
  371. return True
  372. # possibly multiple statements on the same line using semi colon separator
  373. stmt = var_node.statement()
  374. _node = stmt.previous_sibling()
  375. lineno = stmt.fromlineno
  376. while _node and _node.fromlineno == lineno:
  377. for assign_node in _node.nodes_of_class(nodes.AssignName):
  378. if assign_node.name == varname:
  379. return True
  380. for imp_node in _node.nodes_of_class((nodes.ImportFrom, nodes.Import)):
  381. if varname in [name[1] or name[0] for name in imp_node.names]:
  382. return True
  383. _node = _node.previous_sibling()
  384. return False
  385. def is_default_argument(
  386. node: nodes.NodeNG, scope: Optional[nodes.NodeNG] = None
  387. ) -> bool:
  388. """return true if the given Name node is used in function or lambda
  389. default argument's value
  390. """
  391. if not scope:
  392. scope = node.scope()
  393. if isinstance(scope, (nodes.FunctionDef, nodes.Lambda)):
  394. all_defaults = itertools.chain(
  395. scope.args.defaults, (d for d in scope.args.kw_defaults if d is not None)
  396. )
  397. return any(
  398. default_name_node is node
  399. for default_node in all_defaults
  400. for default_name_node in default_node.nodes_of_class(nodes.Name)
  401. )
  402. return False
  403. def is_func_decorator(node: nodes.NodeNG) -> bool:
  404. """return true if the name is used in function decorator"""
  405. for parent in node.node_ancestors():
  406. if isinstance(parent, nodes.Decorators):
  407. return True
  408. if parent.is_statement or isinstance(
  409. parent,
  410. (
  411. nodes.Lambda,
  412. nodes.ComprehensionScope,
  413. nodes.ListComp,
  414. ),
  415. ):
  416. break
  417. return False
  418. def is_ancestor_name(frame: nodes.ClassDef, node: nodes.NodeNG) -> bool:
  419. """return whether `frame` is an astroid.Class node with `node` in the
  420. subtree of its bases attribute
  421. """
  422. if not isinstance(frame, nodes.ClassDef):
  423. return False
  424. return any(node in base.nodes_of_class(nodes.Name) for base in frame.bases)
  425. def is_being_called(node: nodes.NodeNG) -> bool:
  426. """return True if node is the function being called in a Call node"""
  427. return isinstance(node.parent, nodes.Call) and node.parent.func is node
  428. def assign_parent(node: nodes.NodeNG) -> nodes.NodeNG:
  429. """return the higher parent which is not an AssignName, Tuple or List node"""
  430. while node and isinstance(node, (nodes.AssignName, nodes.Tuple, nodes.List)):
  431. node = node.parent
  432. return node
  433. def overrides_a_method(class_node: nodes.ClassDef, name: str) -> bool:
  434. """return True if <name> is a method overridden from an ancestor
  435. which is not the base object class"""
  436. for ancestor in class_node.ancestors():
  437. if ancestor.name == "object":
  438. continue
  439. if name in ancestor and isinstance(ancestor[name], nodes.FunctionDef):
  440. return True
  441. return False
  442. def check_messages(*messages: str) -> Callable:
  443. """decorator to store messages that are handled by a checker method"""
  444. def store_messages(func):
  445. func.checks_msgs = messages
  446. return func
  447. return store_messages
  448. class IncompleteFormatString(Exception):
  449. """A format string ended in the middle of a format specifier."""
  450. class UnsupportedFormatCharacter(Exception):
  451. """A format character in a format string is not one of the supported
  452. format characters."""
  453. def __init__(self, index):
  454. super().__init__(index)
  455. self.index = index
  456. def parse_format_string(
  457. format_string: str,
  458. ) -> Tuple[Set[str], int, Dict[str, str], List[str]]:
  459. """Parses a format string, returning a tuple of (keys, num_args), where keys
  460. is the set of mapping keys in the format string, and num_args is the number
  461. of arguments required by the format string. Raises
  462. IncompleteFormatString or UnsupportedFormatCharacter if a
  463. parse error occurs."""
  464. keys = set()
  465. key_types = {}
  466. pos_types = []
  467. num_args = 0
  468. def next_char(i):
  469. i += 1
  470. if i == len(format_string):
  471. raise IncompleteFormatString
  472. return (i, format_string[i])
  473. i = 0
  474. while i < len(format_string):
  475. char = format_string[i]
  476. if char == "%":
  477. i, char = next_char(i)
  478. # Parse the mapping key (optional).
  479. key = None
  480. if char == "(":
  481. depth = 1
  482. i, char = next_char(i)
  483. key_start = i
  484. while depth != 0:
  485. if char == "(":
  486. depth += 1
  487. elif char == ")":
  488. depth -= 1
  489. i, char = next_char(i)
  490. key_end = i - 1
  491. key = format_string[key_start:key_end]
  492. # Parse the conversion flags (optional).
  493. while char in "#0- +":
  494. i, char = next_char(i)
  495. # Parse the minimum field width (optional).
  496. if char == "*":
  497. num_args += 1
  498. i, char = next_char(i)
  499. else:
  500. while char in string.digits:
  501. i, char = next_char(i)
  502. # Parse the precision (optional).
  503. if char == ".":
  504. i, char = next_char(i)
  505. if char == "*":
  506. num_args += 1
  507. i, char = next_char(i)
  508. else:
  509. while char in string.digits:
  510. i, char = next_char(i)
  511. # Parse the length modifier (optional).
  512. if char in "hlL":
  513. i, char = next_char(i)
  514. # Parse the conversion type (mandatory).
  515. flags = "diouxXeEfFgGcrs%a"
  516. if char not in flags:
  517. raise UnsupportedFormatCharacter(i)
  518. if key:
  519. keys.add(key)
  520. key_types[key] = char
  521. elif char != "%":
  522. num_args += 1
  523. pos_types.append(char)
  524. i += 1
  525. return keys, num_args, key_types, pos_types
  526. def split_format_field_names(format_string) -> Tuple[str, Iterable[Tuple[bool, str]]]:
  527. try:
  528. return _string.formatter_field_name_split(format_string)
  529. except ValueError as e:
  530. raise IncompleteFormatString() from e
  531. def collect_string_fields(format_string) -> Iterable[Optional[str]]:
  532. """Given a format string, return an iterator
  533. of all the valid format fields. It handles nested fields
  534. as well.
  535. """
  536. formatter = string.Formatter()
  537. try:
  538. parseiterator = formatter.parse(format_string)
  539. for result in parseiterator:
  540. if all(item is None for item in result[1:]):
  541. # not a replacement format
  542. continue
  543. name = result[1]
  544. nested = result[2]
  545. yield name
  546. if nested:
  547. yield from collect_string_fields(nested)
  548. except ValueError as exc:
  549. # Probably the format string is invalid.
  550. if exc.args[0].startswith("cannot switch from manual"):
  551. # On Jython, parsing a string with both manual
  552. # and automatic positions will fail with a ValueError,
  553. # while on CPython it will simply return the fields,
  554. # the validation being done in the interpreter (?).
  555. # We're just returning two mixed fields in order
  556. # to trigger the format-combined-specification check.
  557. yield ""
  558. yield "1"
  559. return
  560. raise IncompleteFormatString(format_string) from exc
  561. def parse_format_method_string(
  562. format_string: str,
  563. ) -> Tuple[List[Tuple[str, List[Tuple[bool, str]]]], int, int]:
  564. """
  565. Parses a PEP 3101 format string, returning a tuple of
  566. (keyword_arguments, implicit_pos_args_cnt, explicit_pos_args),
  567. where keyword_arguments is the set of mapping keys in the format string, implicit_pos_args_cnt
  568. is the number of arguments required by the format string and
  569. explicit_pos_args is the number of arguments passed with the position.
  570. """
  571. keyword_arguments = []
  572. implicit_pos_args_cnt = 0
  573. explicit_pos_args = set()
  574. for name in collect_string_fields(format_string):
  575. if name and str(name).isdigit():
  576. explicit_pos_args.add(str(name))
  577. elif name:
  578. keyname, fielditerator = split_format_field_names(name)
  579. if isinstance(keyname, numbers.Number):
  580. explicit_pos_args.add(str(keyname))
  581. try:
  582. keyword_arguments.append((keyname, list(fielditerator)))
  583. except ValueError as e:
  584. raise IncompleteFormatString() from e
  585. else:
  586. implicit_pos_args_cnt += 1
  587. return keyword_arguments, implicit_pos_args_cnt, len(explicit_pos_args)
  588. def is_attr_protected(attrname: str) -> bool:
  589. """return True if attribute name is protected (start with _ and some other
  590. details), False otherwise.
  591. """
  592. return (
  593. attrname[0] == "_"
  594. and attrname != "_"
  595. and not (attrname.startswith("__") and attrname.endswith("__"))
  596. )
  597. def node_frame_class(node: nodes.NodeNG) -> Optional[nodes.ClassDef]:
  598. """Return the class that is wrapping the given node
  599. The function returns a class for a method node (or a staticmethod or a
  600. classmethod), otherwise it returns `None`.
  601. """
  602. klass = node.frame()
  603. nodes_to_check = (
  604. nodes.NodeNG,
  605. astroid.UnboundMethod,
  606. astroid.BaseInstance,
  607. )
  608. while (
  609. klass
  610. and isinstance(klass, nodes_to_check)
  611. and not isinstance(klass, nodes.ClassDef)
  612. ):
  613. if klass.parent is None:
  614. return None
  615. klass = klass.parent.frame()
  616. return klass
  617. def get_outer_class(class_node: astroid.ClassDef) -> Optional[astroid.ClassDef]:
  618. """Return the class that is the outer class of given (nested) class_node"""
  619. parent_klass = class_node.parent.frame()
  620. return parent_klass if isinstance(parent_klass, astroid.ClassDef) else None
  621. def is_attr_private(attrname: str) -> Optional[Match[str]]:
  622. """Check that attribute name is private (at least two leading underscores,
  623. at most one trailing underscore)
  624. """
  625. regex = re.compile("^_{2,}.*[^_]+_?$")
  626. return regex.match(attrname)
  627. def get_argument_from_call(
  628. call_node: nodes.Call, position: Optional[int] = None, keyword: Optional[str] = None
  629. ) -> nodes.Name:
  630. """Returns the specified argument from a function call.
  631. :param nodes.Call call_node: Node representing a function call to check.
  632. :param int position: position of the argument.
  633. :param str keyword: the keyword of the argument.
  634. :returns: The node representing the argument, None if the argument is not found.
  635. :rtype: nodes.Name
  636. :raises ValueError: if both position and keyword are None.
  637. :raises NoSuchArgumentError: if no argument at the provided position or with
  638. the provided keyword.
  639. """
  640. if position is None and keyword is None:
  641. raise ValueError("Must specify at least one of: position or keyword.")
  642. if position is not None:
  643. try:
  644. return call_node.args[position]
  645. except IndexError:
  646. pass
  647. if keyword and call_node.keywords:
  648. for arg in call_node.keywords:
  649. if arg.arg == keyword:
  650. return arg.value
  651. raise NoSuchArgumentError
  652. def inherit_from_std_ex(node: nodes.NodeNG) -> bool:
  653. """
  654. Return whether the given class node is subclass of
  655. exceptions.Exception.
  656. """
  657. ancestors = node.ancestors() if hasattr(node, "ancestors") else []
  658. return any(
  659. ancestor.name in {"Exception", "BaseException"}
  660. and ancestor.root().name == EXCEPTIONS_MODULE
  661. for ancestor in itertools.chain([node], ancestors)
  662. )
  663. def error_of_type(handler: nodes.ExceptHandler, error_type) -> bool:
  664. """
  665. Check if the given exception handler catches
  666. the given error_type.
  667. The *handler* parameter is a node, representing an ExceptHandler node.
  668. The *error_type* can be an exception, such as AttributeError,
  669. the name of an exception, or it can be a tuple of errors.
  670. The function will return True if the handler catches any of the
  671. given errors.
  672. """
  673. def stringify_error(error):
  674. if not isinstance(error, str):
  675. return error.__name__
  676. return error
  677. if not isinstance(error_type, tuple):
  678. error_type = (error_type,)
  679. expected_errors = {stringify_error(error) for error in error_type}
  680. if not handler.type:
  681. return False
  682. return handler.catch(expected_errors)
  683. def decorated_with_property(node: nodes.FunctionDef) -> bool:
  684. """Detect if the given function node is decorated with a property."""
  685. if not node.decorators:
  686. return False
  687. for decorator in node.decorators.nodes:
  688. try:
  689. if _is_property_decorator(decorator):
  690. return True
  691. except astroid.InferenceError:
  692. pass
  693. return False
  694. def _is_property_kind(node, *kinds):
  695. if not isinstance(node, (astroid.UnboundMethod, nodes.FunctionDef)):
  696. return False
  697. if node.decorators:
  698. for decorator in node.decorators.nodes:
  699. if isinstance(decorator, nodes.Attribute) and decorator.attrname in kinds:
  700. return True
  701. return False
  702. def is_property_setter(node: nodes.FunctionDef) -> bool:
  703. """Check if the given node is a property setter"""
  704. return _is_property_kind(node, "setter")
  705. def is_property_deleter(node: nodes.FunctionDef) -> bool:
  706. """Check if the given node is a property deleter"""
  707. return _is_property_kind(node, "deleter")
  708. def is_property_setter_or_deleter(node: nodes.FunctionDef) -> bool:
  709. """Check if the given node is either a property setter or a deleter"""
  710. return _is_property_kind(node, "setter", "deleter")
  711. def _is_property_decorator(decorator: nodes.Name) -> bool:
  712. for inferred in decorator.infer():
  713. if isinstance(inferred, nodes.ClassDef):
  714. if inferred.qname() in {"builtins.property", "functools.cached_property"}:
  715. return True
  716. for ancestor in inferred.ancestors():
  717. if ancestor.name == "property" and ancestor.root().name == "builtins":
  718. return True
  719. elif isinstance(inferred, nodes.FunctionDef):
  720. # If decorator is function, check if it has exactly one return
  721. # and the return is itself a function decorated with property
  722. returns: List[nodes.Return] = list(
  723. inferred._get_return_nodes_skip_functions()
  724. )
  725. if len(returns) == 1 and isinstance(
  726. returns[0].value, (nodes.Name, nodes.Attribute)
  727. ):
  728. inferred = safe_infer(returns[0].value)
  729. if (
  730. inferred
  731. and isinstance(inferred, astroid.objects.Property)
  732. and isinstance(inferred.function, nodes.FunctionDef)
  733. ):
  734. return decorated_with_property(inferred.function)
  735. return False
  736. def decorated_with(
  737. func: Union[
  738. nodes.ClassDef, nodes.FunctionDef, astroid.BoundMethod, astroid.UnboundMethod
  739. ],
  740. qnames: Iterable[str],
  741. ) -> bool:
  742. """Determine if the `func` node has a decorator with the qualified name `qname`."""
  743. decorators = func.decorators.nodes if func.decorators else []
  744. for decorator_node in decorators:
  745. if isinstance(decorator_node, nodes.Call):
  746. # We only want to infer the function name
  747. decorator_node = decorator_node.func
  748. try:
  749. if any(
  750. i.name in qnames or i.qname() in qnames
  751. for i in decorator_node.infer()
  752. if i is not None and i != astroid.Uninferable
  753. ):
  754. return True
  755. except astroid.InferenceError:
  756. continue
  757. return False
  758. def uninferable_final_decorators(
  759. node: nodes.Decorators,
  760. ) -> List[Optional[Union[nodes.Attribute, nodes.Name]]]:
  761. """Return a list of uninferable `typing.final` decorators in `node`.
  762. This function is used to determine if the `typing.final` decorator is used
  763. with an unsupported Python version; the decorator cannot be inferred when
  764. using a Python version lower than 3.8.
  765. """
  766. decorators = []
  767. for decorator in getattr(node, "nodes", []):
  768. if isinstance(decorator, nodes.Attribute):
  769. try:
  770. import_node = decorator.expr.lookup(decorator.expr.name)[1][0]
  771. except AttributeError:
  772. continue
  773. elif isinstance(decorator, nodes.Name):
  774. import_node = decorator.lookup(decorator.name)[1][0]
  775. else:
  776. continue
  777. if not isinstance(import_node, (astroid.Import, astroid.ImportFrom)):
  778. continue
  779. import_names = dict(import_node.names)
  780. # from typing import final
  781. is_from_import = ("final" in import_names) and import_node.modname == "typing"
  782. # import typing
  783. is_import = ("typing" in import_names) and getattr(
  784. decorator, "attrname", None
  785. ) == "final"
  786. if (is_from_import or is_import) and safe_infer(decorator) in [
  787. astroid.Uninferable,
  788. None,
  789. ]:
  790. decorators.append(decorator)
  791. return decorators
  792. @lru_cache(maxsize=1024)
  793. def unimplemented_abstract_methods(
  794. node: nodes.ClassDef, is_abstract_cb: nodes.FunctionDef = None
  795. ) -> Dict[str, nodes.NodeNG]:
  796. """
  797. Get the unimplemented abstract methods for the given *node*.
  798. A method can be considered abstract if the callback *is_abstract_cb*
  799. returns a ``True`` value. The check defaults to verifying that
  800. a method is decorated with abstract methods.
  801. The function will work only for new-style classes. For old-style
  802. classes, it will simply return an empty dictionary.
  803. For the rest of them, it will return a dictionary of abstract method
  804. names and their inferred objects.
  805. """
  806. if is_abstract_cb is None:
  807. is_abstract_cb = partial(decorated_with, qnames=ABC_METHODS)
  808. visited: Dict[str, nodes.NodeNG] = {}
  809. try:
  810. mro = reversed(node.mro())
  811. except NotImplementedError:
  812. # Old style class, it will not have a mro.
  813. return {}
  814. except astroid.ResolveError:
  815. # Probably inconsistent hierarchy, don'try
  816. # to figure this out here.
  817. return {}
  818. for ancestor in mro:
  819. for obj in ancestor.values():
  820. inferred = obj
  821. if isinstance(obj, nodes.AssignName):
  822. inferred = safe_infer(obj)
  823. if not inferred:
  824. # Might be an abstract function,
  825. # but since we don't have enough information
  826. # in order to take this decision, we're taking
  827. # the *safe* decision instead.
  828. if obj.name in visited:
  829. del visited[obj.name]
  830. continue
  831. if not isinstance(inferred, nodes.FunctionDef):
  832. if obj.name in visited:
  833. del visited[obj.name]
  834. if isinstance(inferred, nodes.FunctionDef):
  835. # It's critical to use the original name,
  836. # since after inferring, an object can be something
  837. # else than expected, as in the case of the
  838. # following assignment.
  839. #
  840. # class A:
  841. # def keys(self): pass
  842. # __iter__ = keys
  843. abstract = is_abstract_cb(inferred)
  844. if abstract:
  845. visited[obj.name] = inferred
  846. elif not abstract and obj.name in visited:
  847. del visited[obj.name]
  848. return visited
  849. def find_try_except_wrapper_node(
  850. node: nodes.NodeNG,
  851. ) -> Optional[Union[nodes.ExceptHandler, nodes.TryExcept]]:
  852. """Return the ExceptHandler or the TryExcept node in which the node is."""
  853. current = node
  854. ignores = (nodes.ExceptHandler, nodes.TryExcept)
  855. while current and not isinstance(current.parent, ignores):
  856. current = current.parent
  857. if current and isinstance(current.parent, ignores):
  858. return current.parent
  859. return None
  860. def find_except_wrapper_node_in_scope(
  861. node: nodes.NodeNG,
  862. ) -> Optional[Union[nodes.ExceptHandler, nodes.TryExcept]]:
  863. """Return the ExceptHandler in which the node is, without going out of scope."""
  864. for current in node.node_ancestors():
  865. if isinstance(current, astroid.scoped_nodes.LocalsDictNodeNG):
  866. # If we're inside a function/class definition, we don't want to keep checking
  867. # higher ancestors for `except` clauses, because if these exist, it means our
  868. # function/class was defined in an `except` clause, rather than the current code
  869. # actually running in an `except` clause.
  870. return None
  871. if isinstance(current, nodes.ExceptHandler):
  872. return current
  873. return None
  874. def is_from_fallback_block(node: nodes.NodeNG) -> bool:
  875. """Check if the given node is from a fallback import block."""
  876. context = find_try_except_wrapper_node(node)
  877. if not context:
  878. return False
  879. if isinstance(context, nodes.ExceptHandler):
  880. other_body = context.parent.body
  881. handlers = context.parent.handlers
  882. else:
  883. other_body = itertools.chain.from_iterable(
  884. handler.body for handler in context.handlers
  885. )
  886. handlers = context.handlers
  887. has_fallback_imports = any(
  888. isinstance(import_node, (nodes.ImportFrom, nodes.Import))
  889. for import_node in other_body
  890. )
  891. ignores_import_error = _except_handlers_ignores_exceptions(
  892. handlers, (ImportError, ModuleNotFoundError)
  893. )
  894. return ignores_import_error or has_fallback_imports
  895. def _except_handlers_ignores_exceptions(
  896. handlers: nodes.ExceptHandler,
  897. exceptions: Tuple[Type[ImportError], Type[ModuleNotFoundError]],
  898. ) -> bool:
  899. func = partial(error_of_type, error_type=exceptions)
  900. return any(func(handler) for handler in handlers)
  901. def get_exception_handlers(
  902. node: nodes.NodeNG, exception=Exception
  903. ) -> Optional[List[nodes.ExceptHandler]]:
  904. """Return the collections of handlers handling the exception in arguments.
  905. Args:
  906. node (nodes.NodeNG): A node that is potentially wrapped in a try except.
  907. exception (builtin.Exception or str): exception or name of the exception.
  908. Returns:
  909. list: the collection of handlers that are handling the exception or None.
  910. """
  911. context = find_try_except_wrapper_node(node)
  912. if isinstance(context, nodes.TryExcept):
  913. return [
  914. handler for handler in context.handlers if error_of_type(handler, exception)
  915. ]
  916. return []
  917. def is_node_inside_try_except(node: nodes.Raise) -> bool:
  918. """Check if the node is directly under a Try/Except statement.
  919. (but not under an ExceptHandler!)
  920. Args:
  921. node (nodes.Raise): the node raising the exception.
  922. Returns:
  923. bool: True if the node is inside a try/except statement, False otherwise.
  924. """
  925. context = find_try_except_wrapper_node(node)
  926. return isinstance(context, nodes.TryExcept)
  927. def node_ignores_exception(node: nodes.NodeNG, exception=Exception) -> bool:
  928. """Check if the node is in a TryExcept which handles the given exception.
  929. If the exception is not given, the function is going to look for bare
  930. excepts.
  931. """
  932. managing_handlers = get_exception_handlers(node, exception)
  933. if not managing_handlers:
  934. return False
  935. return any(managing_handlers)
  936. def class_is_abstract(node: nodes.ClassDef) -> bool:
  937. """return true if the given class node should be considered as an abstract
  938. class
  939. """
  940. # Only check for explicit metaclass=ABCMeta on this specific class
  941. meta = node.declared_metaclass()
  942. if meta is not None:
  943. if meta.name == "ABCMeta" and meta.root().name in ABC_MODULES:
  944. return True
  945. for ancestor in node.ancestors():
  946. if ancestor.name == "ABC" and ancestor.root().name in ABC_MODULES:
  947. # abc.ABC inheritance
  948. return True
  949. for method in node.methods():
  950. if method.parent.frame() is node:
  951. if method.is_abstract(pass_is_abstract=False):
  952. return True
  953. return False
  954. def _supports_protocol_method(value: nodes.NodeNG, attr: str) -> bool:
  955. try:
  956. attributes = value.getattr(attr)
  957. except astroid.NotFoundError:
  958. return False
  959. first = attributes[0]
  960. if isinstance(first, nodes.AssignName):
  961. if isinstance(first.parent.value, nodes.Const):
  962. return False
  963. return True
  964. def is_comprehension(node: nodes.NodeNG) -> bool:
  965. comprehensions = (
  966. nodes.ListComp,
  967. nodes.SetComp,
  968. nodes.DictComp,
  969. nodes.GeneratorExp,
  970. )
  971. return isinstance(node, comprehensions)
  972. def _supports_mapping_protocol(value: nodes.NodeNG) -> bool:
  973. return _supports_protocol_method(
  974. value, GETITEM_METHOD
  975. ) and _supports_protocol_method(value, KEYS_METHOD)
  976. def _supports_membership_test_protocol(value: nodes.NodeNG) -> bool:
  977. return _supports_protocol_method(value, CONTAINS_METHOD)
  978. def _supports_iteration_protocol(value: nodes.NodeNG) -> bool:
  979. return _supports_protocol_method(value, ITER_METHOD) or _supports_protocol_method(
  980. value, GETITEM_METHOD
  981. )
  982. def _supports_async_iteration_protocol(value: nodes.NodeNG) -> bool:
  983. return _supports_protocol_method(value, AITER_METHOD)
  984. def _supports_getitem_protocol(value: nodes.NodeNG) -> bool:
  985. return _supports_protocol_method(value, GETITEM_METHOD)
  986. def _supports_setitem_protocol(value: nodes.NodeNG) -> bool:
  987. return _supports_protocol_method(value, SETITEM_METHOD)
  988. def _supports_delitem_protocol(value: nodes.NodeNG) -> bool:
  989. return _supports_protocol_method(value, DELITEM_METHOD)
  990. def _is_abstract_class_name(name: str) -> bool:
  991. lname = name.lower()
  992. is_mixin = lname.endswith("mixin")
  993. is_abstract = lname.startswith("abstract")
  994. is_base = lname.startswith("base") or lname.endswith("base")
  995. return is_mixin or is_abstract or is_base
  996. def is_inside_abstract_class(node: nodes.NodeNG) -> bool:
  997. while node is not None:
  998. if isinstance(node, nodes.ClassDef):
  999. if class_is_abstract(node):
  1000. return True
  1001. name = getattr(node, "name", None)
  1002. if name is not None and _is_abstract_class_name(name):
  1003. return True
  1004. node = node.parent
  1005. return False
  1006. def _supports_protocol(
  1007. value: nodes.NodeNG, protocol_callback: nodes.FunctionDef
  1008. ) -> bool:
  1009. if isinstance(value, nodes.ClassDef):
  1010. if not has_known_bases(value):
  1011. return True
  1012. # classobj can only be iterable if it has an iterable metaclass
  1013. meta = value.metaclass()
  1014. if meta is not None:
  1015. if protocol_callback(meta):
  1016. return True
  1017. if isinstance(value, astroid.BaseInstance):
  1018. if not has_known_bases(value):
  1019. return True
  1020. if value.has_dynamic_getattr():
  1021. return True
  1022. if protocol_callback(value):
  1023. return True
  1024. if (
  1025. isinstance(value, astroid.bases.Proxy)
  1026. and isinstance(value._proxied, astroid.BaseInstance)
  1027. and has_known_bases(value._proxied)
  1028. ):
  1029. value = value._proxied
  1030. return protocol_callback(value)
  1031. return False
  1032. def is_iterable(value: nodes.NodeNG, check_async: bool = False) -> bool:
  1033. if check_async:
  1034. protocol_check = _supports_async_iteration_protocol
  1035. else:
  1036. protocol_check = _supports_iteration_protocol
  1037. return _supports_protocol(value, protocol_check)
  1038. def is_mapping(value: nodes.NodeNG) -> bool:
  1039. return _supports_protocol(value, _supports_mapping_protocol)
  1040. def supports_membership_test(value: nodes.NodeNG) -> bool:
  1041. supported = _supports_protocol(value, _supports_membership_test_protocol)
  1042. return supported or is_iterable(value)
  1043. def supports_getitem(value: nodes.NodeNG, node: nodes.NodeNG) -> bool:
  1044. if isinstance(value, nodes.ClassDef):
  1045. if _supports_protocol_method(value, CLASS_GETITEM_METHOD):
  1046. return True
  1047. if is_class_subscriptable_pep585_with_postponed_evaluation_enabled(value, node):
  1048. return True
  1049. return _supports_protocol(value, _supports_getitem_protocol)
  1050. def supports_setitem(value: nodes.NodeNG, _: nodes.NodeNG) -> bool:
  1051. return _supports_protocol(value, _supports_setitem_protocol)
  1052. def supports_delitem(value: nodes.NodeNG, _: nodes.NodeNG) -> bool:
  1053. return _supports_protocol(value, _supports_delitem_protocol)
  1054. def _get_python_type_of_node(node):
  1055. pytype = getattr(node, "pytype", None)
  1056. if callable(pytype):
  1057. return pytype()
  1058. return None
  1059. @lru_cache(maxsize=1024)
  1060. def safe_infer(node: nodes.NodeNG, context=None) -> Optional[nodes.NodeNG]:
  1061. """Return the inferred value for the given node.
  1062. Return None if inference failed or if there is some ambiguity (more than
  1063. one node has been inferred of different types).
  1064. """
  1065. inferred_types = set()
  1066. try:
  1067. infer_gen = node.infer(context=context)
  1068. value = next(infer_gen)
  1069. except astroid.InferenceError:
  1070. return None
  1071. if value is not astroid.Uninferable:
  1072. inferred_types.add(_get_python_type_of_node(value))
  1073. try:
  1074. for inferred in infer_gen:
  1075. inferred_type = _get_python_type_of_node(inferred)
  1076. if inferred_type not in inferred_types:
  1077. return None # If there is ambiguity on the inferred node.
  1078. except astroid.InferenceError:
  1079. return None # There is some kind of ambiguity
  1080. except StopIteration:
  1081. return value
  1082. return value if len(inferred_types) <= 1 else None
  1083. @lru_cache(maxsize=512)
  1084. def infer_all(
  1085. node: nodes.NodeNG, context: InferenceContext = None
  1086. ) -> List[nodes.NodeNG]:
  1087. try:
  1088. return list(node.infer(context=context))
  1089. except astroid.InferenceError:
  1090. return []
  1091. def has_known_bases(klass: nodes.ClassDef, context=None) -> bool:
  1092. """Return true if all base classes of a class could be inferred."""
  1093. try:
  1094. return klass._all_bases_known
  1095. except AttributeError:
  1096. pass
  1097. for base in klass.bases:
  1098. result = safe_infer(base, context=context)
  1099. if (
  1100. not isinstance(result, nodes.ClassDef)
  1101. or result is klass
  1102. or not has_known_bases(result, context=context)
  1103. ):
  1104. klass._all_bases_known = False
  1105. return False
  1106. klass._all_bases_known = True
  1107. return True
  1108. def is_none(node: nodes.NodeNG) -> bool:
  1109. return (
  1110. node is None
  1111. or (isinstance(node, nodes.Const) and node.value is None)
  1112. or (isinstance(node, nodes.Name) and node.name == "None")
  1113. )
  1114. def node_type(node: nodes.NodeNG) -> Optional[nodes.NodeNG]:
  1115. """Return the inferred type for `node`
  1116. If there is more than one possible type, or if inferred type is Uninferable or None,
  1117. return None
  1118. """
  1119. # check there is only one possible type for the assign node. Else we
  1120. # don't handle it for now
  1121. types: Set[nodes.NodeNG] = set()
  1122. try:
  1123. for var_type in node.infer():
  1124. if var_type == astroid.Uninferable or is_none(var_type):
  1125. continue
  1126. types.add(var_type)
  1127. if len(types) > 1:
  1128. return None
  1129. except astroid.InferenceError:
  1130. return None
  1131. return types.pop() if types else None
  1132. def is_registered_in_singledispatch_function(node: nodes.FunctionDef) -> bool:
  1133. """Check if the given function node is a singledispatch function."""
  1134. singledispatch_qnames = (
  1135. "functools.singledispatch",
  1136. "singledispatch.singledispatch",
  1137. )
  1138. if not isinstance(node, nodes.FunctionDef):
  1139. return False
  1140. decorators = node.decorators.nodes if node.decorators else []
  1141. for decorator in decorators:
  1142. # func.register are function calls
  1143. if not isinstance(decorator, nodes.Call):
  1144. continue
  1145. func = decorator.func
  1146. if not isinstance(func, nodes.Attribute) or func.attrname != "register":
  1147. continue
  1148. try:
  1149. func_def = next(func.expr.infer())
  1150. except astroid.InferenceError:
  1151. continue
  1152. if isinstance(func_def, nodes.FunctionDef):
  1153. return decorated_with(func_def, singledispatch_qnames)
  1154. return False
  1155. def get_node_last_lineno(node: nodes.NodeNG) -> int:
  1156. """
  1157. Get the last lineno of the given node. For a simple statement this will just be node.lineno,
  1158. but for a node that has child statements (e.g. a method) this will be the lineno of the last
  1159. child statement recursively.
  1160. """
  1161. # 'finalbody' is always the last clause in a try statement, if present
  1162. if getattr(node, "finalbody", False):
  1163. return get_node_last_lineno(node.finalbody[-1])
  1164. # For if, while, and for statements 'orelse' is always the last clause.
  1165. # For try statements 'orelse' is the last in the absence of a 'finalbody'
  1166. if getattr(node, "orelse", False):
  1167. return get_node_last_lineno(node.orelse[-1])
  1168. # try statements have the 'handlers' last if there is no 'orelse' or 'finalbody'
  1169. if getattr(node, "handlers", False):
  1170. return get_node_last_lineno(node.handlers[-1])
  1171. # All compound statements have a 'body'
  1172. if getattr(node, "body", False):
  1173. return get_node_last_lineno(node.body[-1])
  1174. # Not a compound statement
  1175. return node.lineno
  1176. def is_postponed_evaluation_enabled(node: nodes.NodeNG) -> bool:
  1177. """Check if the postponed evaluation of annotations is enabled"""
  1178. module = node.root()
  1179. return "annotations" in module.future_imports
  1180. def is_class_subscriptable_pep585_with_postponed_evaluation_enabled(
  1181. value: nodes.ClassDef, node: nodes.NodeNG
  1182. ) -> bool:
  1183. """Check if class is subscriptable with PEP 585 and
  1184. postponed evaluation enabled.
  1185. """
  1186. return (
  1187. is_postponed_evaluation_enabled(node)
  1188. and value.qname() in SUBSCRIPTABLE_CLASSES_PEP585
  1189. and is_node_in_type_annotation_context(node)
  1190. )
  1191. def is_node_in_type_annotation_context(node: nodes.NodeNG) -> bool:
  1192. """Check if node is in type annotation context.
  1193. Check for 'AnnAssign', function 'Arguments',
  1194. or part of function return type anntation.
  1195. """
  1196. # pylint: disable=too-many-boolean-expressions
  1197. current_node, parent_node = node, node.parent
  1198. while True:
  1199. if (
  1200. isinstance(parent_node, nodes.AnnAssign)
  1201. and parent_node.annotation == current_node
  1202. or isinstance(parent_node, nodes.Arguments)
  1203. and current_node
  1204. in (
  1205. *parent_node.annotations,
  1206. *parent_node.posonlyargs_annotations,
  1207. *parent_node.kwonlyargs_annotations,
  1208. parent_node.varargannotation,
  1209. parent_node.kwargannotation,
  1210. )
  1211. or isinstance(parent_node, nodes.FunctionDef)
  1212. and parent_node.returns == current_node
  1213. ):
  1214. return True
  1215. current_node, parent_node = parent_node, parent_node.parent
  1216. if isinstance(parent_node, nodes.Module):
  1217. return False
  1218. def is_subclass_of(child: nodes.ClassDef, parent: nodes.ClassDef) -> bool:
  1219. """
  1220. Check if first node is a subclass of second node.
  1221. :param child: Node to check for subclass.
  1222. :param parent: Node to check for superclass.
  1223. :returns: True if child is derived from parent. False otherwise.
  1224. """
  1225. if not all(isinstance(node, nodes.ClassDef) for node in (child, parent)):
  1226. return False
  1227. for ancestor in child.ancestors():
  1228. try:
  1229. if astroid.helpers.is_subtype(ancestor, parent):
  1230. return True
  1231. except astroid.exceptions._NonDeducibleTypeHierarchy:
  1232. continue
  1233. return False
  1234. @lru_cache(maxsize=1024)
  1235. def is_overload_stub(node: nodes.NodeNG) -> bool:
  1236. """Check if a node if is a function stub decorated with typing.overload.
  1237. :param node: Node to check.
  1238. :returns: True if node is an overload function stub. False otherwise.
  1239. """
  1240. decorators = getattr(node, "decorators", None)
  1241. return bool(decorators and decorated_with(node, ["typing.overload", "overload"]))
  1242. def is_protocol_class(cls: nodes.NodeNG) -> bool:
  1243. """Check if the given node represents a protocol class
  1244. :param cls: The node to check
  1245. :returns: True if the node is a typing protocol class, false otherwise.
  1246. """
  1247. if not isinstance(cls, nodes.ClassDef):
  1248. return False
  1249. # Use .ancestors() since not all protocol classes can have
  1250. # their mro deduced.
  1251. return any(parent.qname() in TYPING_PROTOCOLS for parent in cls.ancestors())
  1252. def is_call_of_name(node: nodes.NodeNG, name: str) -> bool:
  1253. """Checks if node is a function call with the given name"""
  1254. return (
  1255. isinstance(node, nodes.Call)
  1256. and isinstance(node.func, nodes.Name)
  1257. and node.func.name == name
  1258. )
  1259. def is_test_condition(
  1260. node: nodes.NodeNG,
  1261. parent: Optional[nodes.NodeNG] = None,
  1262. ) -> bool:
  1263. """Returns true if the given node is being tested for truthiness"""
  1264. parent = parent or node.parent
  1265. if isinstance(parent, (nodes.While, nodes.If, nodes.IfExp, nodes.Assert)):
  1266. return node is parent.test or parent.test.parent_of(node)
  1267. if isinstance(parent, nodes.Comprehension):
  1268. return node in parent.ifs
  1269. return is_call_of_name(parent, "bool") and parent.parent_of(node)
  1270. def is_classdef_type(node: nodes.ClassDef) -> bool:
  1271. """Test if ClassDef node is Type."""
  1272. if node.name == "type":
  1273. return True
  1274. return any(isinstance(b, nodes.Name) and b.name == "type" for b in node.bases)
  1275. def is_attribute_typed_annotation(
  1276. node: Union[nodes.ClassDef, astroid.Instance], attr_name: str
  1277. ) -> bool:
  1278. """Test if attribute is typed annotation in current node
  1279. or any base nodes.
  1280. """
  1281. attribute = node.locals.get(attr_name, [None])[0]
  1282. if (
  1283. attribute
  1284. and isinstance(attribute, nodes.AssignName)
  1285. and isinstance(attribute.parent, nodes.AnnAssign)
  1286. ):
  1287. return True
  1288. for base in node.bases:
  1289. inferred = safe_infer(base)
  1290. if (
  1291. inferred
  1292. and isinstance(inferred, nodes.ClassDef)
  1293. and is_attribute_typed_annotation(inferred, attr_name)
  1294. ):
  1295. return True
  1296. return False
  1297. def is_assign_name_annotated_with(node: nodes.AssignName, typing_name: str) -> bool:
  1298. """Test if AssignName node has `typing_name` annotation.
  1299. Especially useful to check for `typing._SpecialForm` instances
  1300. like: `Union`, `Optional`, `Literal`, `ClassVar`, `Final`.
  1301. """
  1302. if not isinstance(node.parent, nodes.AnnAssign):
  1303. return False
  1304. annotation = node.parent.annotation
  1305. if isinstance(annotation, nodes.Subscript):
  1306. annotation = annotation.value
  1307. if (
  1308. isinstance(annotation, nodes.Name)
  1309. and annotation.name == typing_name
  1310. or isinstance(annotation, nodes.Attribute)
  1311. and annotation.attrname == typing_name
  1312. ):
  1313. return True
  1314. return False
  1315. def get_iterating_dictionary_name(
  1316. node: Union[nodes.For, nodes.Comprehension]
  1317. ) -> Optional[str]:
  1318. """Get the name of the dictionary which keys are being iterated over on
  1319. a ``nodes.For`` or ``nodes.Comprehension`` node.
  1320. If the iterating object is not either the keys method of a dictionary
  1321. or a dictionary itself, this returns None.
  1322. """
  1323. # Is it a proper keys call?
  1324. if (
  1325. isinstance(node.iter, nodes.Call)
  1326. and isinstance(node.iter.func, nodes.Attribute)
  1327. and node.iter.func.attrname == "keys"
  1328. ):
  1329. inferred = safe_infer(node.iter.func)
  1330. if not isinstance(inferred, astroid.BoundMethod):
  1331. return None
  1332. return node.iter.as_string().rpartition(".keys")[0]
  1333. # Is it a dictionary?
  1334. if isinstance(node.iter, (nodes.Name, nodes.Attribute)):
  1335. inferred = safe_infer(node.iter)
  1336. if not isinstance(inferred, nodes.Dict):
  1337. return None
  1338. return node.iter.as_string()
  1339. return None
  1340. def get_subscript_const_value(node: nodes.Subscript) -> nodes.Const:
  1341. """
  1342. Returns the value 'subscript.slice' of a Subscript node.
  1343. :param node: Subscript Node to extract value from
  1344. :returns: Const Node containing subscript value
  1345. :raises InferredTypeError: if the subscript node cannot be inferred as a Const
  1346. """
  1347. inferred = safe_infer(node.slice)
  1348. if not isinstance(inferred, nodes.Const):
  1349. raise InferredTypeError("Subscript.slice cannot be inferred as a nodes.Const")
  1350. return inferred
  1351. def get_import_name(
  1352. importnode: Union[nodes.Import, nodes.ImportFrom], modname: str
  1353. ) -> str:
  1354. """Get a prepared module name from the given import node
  1355. In the case of relative imports, this will return the
  1356. absolute qualified module name, which might be useful
  1357. for debugging. Otherwise, the initial module name
  1358. is returned unchanged.
  1359. :param importnode: node representing import statement.
  1360. :param modname: module name from import statement.
  1361. :returns: absolute qualified module name of the module
  1362. used in import.
  1363. """
  1364. if isinstance(importnode, nodes.ImportFrom) and importnode.level:
  1365. root = importnode.root()
  1366. if isinstance(root, nodes.Module):
  1367. try:
  1368. return root.relative_to_absolute_name(modname, level=importnode.level)
  1369. except TooManyLevelsError:
  1370. return modname
  1371. return modname
  1372. def is_sys_guard(node: nodes.If) -> bool:
  1373. """Return True if IF stmt is a sys.version_info guard.
  1374. >>> import sys
  1375. >>> if sys.version_info > (3, 8):
  1376. >>> from typing import Literal
  1377. >>> else:
  1378. >>> from typing_extensions import Literal
  1379. """
  1380. if isinstance(node.test, nodes.Compare):
  1381. value = node.test.left
  1382. if isinstance(value, nodes.Subscript):
  1383. value = value.value
  1384. if (
  1385. isinstance(value, nodes.Attribute)
  1386. and value.as_string() == "sys.version_info"
  1387. ):
  1388. return True
  1389. return False
  1390. def is_typing_guard(node: nodes.If) -> bool:
  1391. """Return True if IF stmt is a typing guard.
  1392. >>> from typing import TYPE_CHECKING
  1393. >>> if TYPE_CHECKING:
  1394. >>> from xyz import a
  1395. """
  1396. return isinstance(
  1397. node.test, (nodes.Name, nodes.Attribute)
  1398. ) and node.test.as_string().endswith("TYPE_CHECKING")
  1399. def is_node_in_guarded_import_block(node: nodes.NodeNG) -> bool:
  1400. """Return True if node is part for guarded if block.
  1401. I.e. `sys.version_info` or `typing.TYPE_CHECKING`
  1402. """
  1403. return isinstance(node.parent, nodes.If) and (
  1404. is_sys_guard(node.parent) or is_typing_guard(node.parent)
  1405. )
  1406. def is_reassigned_after_current(node: nodes.NodeNG, varname: str) -> bool:
  1407. """Check if the given variable name is reassigned in the same scope after the current node"""
  1408. return any(
  1409. a.name == varname and a.lineno > node.lineno
  1410. for a in node.scope().nodes_of_class((nodes.AssignName, nodes.FunctionDef))
  1411. )
  1412. def is_function_body_ellipsis(node: nodes.FunctionDef) -> bool:
  1413. """Checks whether a function body only consisst of a single Ellipsis"""
  1414. return (
  1415. len(node.body) == 1
  1416. and isinstance(node.body[0], nodes.Expr)
  1417. and isinstance(node.body[0].value, nodes.Const)
  1418. and node.body[0].value.value == Ellipsis
  1419. )
  1420. def is_base_container(node: Optional[nodes.NodeNG]) -> bool:
  1421. return isinstance(node, nodes.BaseContainer) and not node.elts
  1422. def is_empty_dict_literal(node: Optional[nodes.NodeNG]) -> bool:
  1423. return isinstance(node, nodes.Dict) and not node.items
  1424. def is_empty_str_literal(node: Optional[nodes.NodeNG]) -> bool:
  1425. return (
  1426. isinstance(node, nodes.Const) and isinstance(node.value, str) and not node.value
  1427. )
  1428. def returns_bool(node: nodes.NodeNG) -> bool:
  1429. """Returns true if a node is a return that returns a constant boolean"""
  1430. return (
  1431. isinstance(node, nodes.Return)
  1432. and isinstance(node.value, nodes.Const)
  1433. and node.value.value in {True, False}
  1434. )
  1435. def get_node_first_ancestor_of_type(
  1436. node: nodes.NodeNG, ancestor_type: Union[Type[T_Node], Tuple[Type[T_Node]]]
  1437. ) -> Optional[T_Node]:
  1438. """Return the first parent node that is any of the provided types (or None)"""
  1439. for ancestor in node.node_ancestors():
  1440. if isinstance(ancestor, ancestor_type):
  1441. return ancestor
  1442. return None