scoped_nodes.py 98 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904
  1. # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
  2. # For details: https://github.com/pylint-dev/astroid/blob/main/LICENSE
  3. # Copyright (c) https://github.com/pylint-dev/astroid/blob/main/CONTRIBUTORS.txt
  4. """
  5. This module contains the classes for "scoped" node, i.e. which are opening a
  6. new local scope in the language definition : Module, ClassDef, FunctionDef (and
  7. Lambda, GeneratorExp, DictComp and SetComp to some extent).
  8. """
  9. from __future__ import annotations
  10. import io
  11. import itertools
  12. import os
  13. import sys
  14. from collections.abc import Generator, Iterable, Iterator, Sequence
  15. from functools import cached_property, lru_cache
  16. from typing import TYPE_CHECKING, Any, ClassVar, Literal, NoReturn
  17. from astroid import bases, protocols, util
  18. from astroid.context import (
  19. CallContext,
  20. InferenceContext,
  21. bind_context_to_node,
  22. copy_context,
  23. )
  24. from astroid.exceptions import (
  25. AstroidBuildingError,
  26. AstroidTypeError,
  27. AttributeInferenceError,
  28. DuplicateBasesError,
  29. InconsistentMroError,
  30. InferenceError,
  31. MroError,
  32. ParentMissingError,
  33. StatementMissing,
  34. TooManyLevelsError,
  35. )
  36. from astroid.interpreter.dunder_lookup import lookup
  37. from astroid.interpreter.objectmodel import ClassModel, FunctionModel, ModuleModel
  38. from astroid.manager import AstroidManager
  39. from astroid.nodes import _base_nodes, node_classes
  40. from astroid.nodes.scoped_nodes.mixin import ComprehensionScope, LocalsDictNodeNG
  41. from astroid.nodes.scoped_nodes.utils import builtin_lookup
  42. from astroid.nodes.utils import Position
  43. from astroid.typing import (
  44. InferBinaryOp,
  45. InferenceErrorInfo,
  46. InferenceResult,
  47. SuccessfulInferenceResult,
  48. )
  49. if sys.version_info >= (3, 11):
  50. from typing import Self
  51. else:
  52. from typing_extensions import Self
  53. if TYPE_CHECKING:
  54. from astroid import nodes, objects
  55. from astroid.nodes import Arguments, Const, NodeNG
  56. from astroid.nodes._base_nodes import LookupMixIn
  57. ITER_METHODS = ("__iter__", "__getitem__")
  58. EXCEPTION_BASE_CLASSES = frozenset({"Exception", "BaseException"})
  59. BUILTIN_DESCRIPTORS = frozenset(
  60. {"classmethod", "staticmethod", "builtins.classmethod", "builtins.staticmethod"}
  61. )
  62. def _c3_merge(sequences, cls, context):
  63. """Merges MROs in *sequences* to a single MRO using the C3 algorithm.
  64. Adapted from http://www.python.org/download/releases/2.3/mro/.
  65. """
  66. result = []
  67. while True:
  68. sequences = [s for s in sequences if s] # purge empty sequences
  69. if not sequences:
  70. return result
  71. for s1 in sequences: # find merge candidates among seq heads
  72. candidate = s1[0]
  73. for s2 in sequences:
  74. if candidate in s2[1:]:
  75. candidate = None
  76. break # reject the current head, it appears later
  77. else:
  78. break
  79. if not candidate:
  80. # Show all the remaining bases, which were considered as
  81. # candidates for the next mro sequence.
  82. raise InconsistentMroError(
  83. message="Cannot create a consistent method resolution order "
  84. "for MROs {mros} of class {cls!r}.",
  85. mros=sequences,
  86. cls=cls,
  87. context=context,
  88. )
  89. result.append(candidate)
  90. # remove the chosen candidate
  91. for seq in sequences:
  92. if seq[0] == candidate:
  93. del seq[0]
  94. return None
  95. def clean_typing_generic_mro(sequences: list[list[ClassDef]]) -> None:
  96. """A class can inherit from typing.Generic directly, as base,
  97. and as base of bases. The merged MRO must however only contain the last entry.
  98. To prepare for _c3_merge, remove some typing.Generic entries from
  99. sequences if multiple are present.
  100. This method will check if Generic is in inferred_bases and also
  101. part of bases_mro. If true, remove it from inferred_bases
  102. as well as its entry the bases_mro.
  103. Format sequences: [[self]] + bases_mro + [inferred_bases]
  104. """
  105. bases_mro = sequences[1:-1]
  106. inferred_bases = sequences[-1]
  107. # Check if Generic is part of inferred_bases
  108. for i, base in enumerate(inferred_bases):
  109. if base.qname() == "typing.Generic":
  110. position_in_inferred_bases = i
  111. break
  112. else:
  113. return
  114. # Check if also part of bases_mro
  115. # Ignore entry for typing.Generic
  116. for i, seq in enumerate(bases_mro):
  117. if i == position_in_inferred_bases:
  118. continue
  119. if any(base.qname() == "typing.Generic" for base in seq):
  120. break
  121. else:
  122. return
  123. # Found multiple Generics in mro, remove entry from inferred_bases
  124. # and the corresponding one from bases_mro
  125. inferred_bases.pop(position_in_inferred_bases)
  126. bases_mro.pop(position_in_inferred_bases)
  127. def clean_duplicates_mro(
  128. sequences: list[list[ClassDef]],
  129. cls: ClassDef,
  130. context: InferenceContext | None,
  131. ) -> list[list[ClassDef]]:
  132. for sequence in sequences:
  133. seen = set()
  134. for node in sequence:
  135. lineno_and_qname = (node.lineno, node.qname())
  136. if lineno_and_qname in seen:
  137. raise DuplicateBasesError(
  138. message="Duplicates found in MROs {mros} for {cls!r}.",
  139. mros=sequences,
  140. cls=cls,
  141. context=context,
  142. )
  143. seen.add(lineno_and_qname)
  144. return sequences
  145. def function_to_method(n, klass):
  146. if isinstance(n, FunctionDef):
  147. if n.type == "classmethod":
  148. return bases.BoundMethod(n, klass)
  149. if n.type == "property":
  150. return n
  151. if n.type != "staticmethod":
  152. return bases.UnboundMethod(n)
  153. return n
  154. def _infer_last(
  155. arg: SuccessfulInferenceResult, context: InferenceContext
  156. ) -> InferenceResult:
  157. res = util.Uninferable
  158. for b in arg.infer(context=context.clone()):
  159. res = b
  160. return res
  161. class Module(LocalsDictNodeNG):
  162. """Class representing an :class:`ast.Module` node.
  163. >>> import astroid
  164. >>> node = astroid.extract_node('import astroid')
  165. >>> node
  166. <Import l.1 at 0x7f23b2e4e5c0>
  167. >>> node.parent
  168. <Module l.0 at 0x7f23b2e4eda0>
  169. """
  170. _astroid_fields = ("doc_node", "body")
  171. doc_node: Const | None
  172. """The doc node associated with this node."""
  173. # attributes below are set by the builder module or by raw factories
  174. file_bytes: str | bytes | None = None
  175. """The string/bytes that this ast was built from."""
  176. file_encoding: str | None = None
  177. """The encoding of the source file.
  178. This is used to get unicode out of a source file.
  179. Python 2 only.
  180. """
  181. special_attributes = ModuleModel()
  182. """The names of special attributes that this module has."""
  183. # names of module attributes available through the global scope
  184. scope_attrs: ClassVar[set[str]] = {
  185. "__name__",
  186. "__doc__",
  187. "__file__",
  188. "__path__",
  189. "__package__",
  190. }
  191. """The names of module attributes available through the global scope."""
  192. _other_fields = (
  193. "name",
  194. "file",
  195. "path",
  196. "package",
  197. "pure_python",
  198. "future_imports",
  199. )
  200. _other_other_fields = ("locals", "globals")
  201. def __init__(
  202. self,
  203. name: str,
  204. file: str | None = None,
  205. path: Sequence[str] | None = None,
  206. package: bool = False,
  207. pure_python: bool = True,
  208. ) -> None:
  209. self.name = name
  210. """The name of the module."""
  211. self.file = file
  212. """The path to the file that this ast has been extracted from.
  213. This will be ``None`` when the representation has been built from a
  214. built-in module.
  215. """
  216. self.path = path
  217. self.package = package
  218. """Whether the node represents a package or a module."""
  219. self.pure_python = pure_python
  220. """Whether the ast was built from source."""
  221. self.globals: dict[str, list[InferenceResult]]
  222. """A map of the name of a global variable to the node defining the global."""
  223. self.locals = self.globals = {}
  224. """A map of the name of a local variable to the node defining the local."""
  225. self.body: list[node_classes.NodeNG] = []
  226. """The contents of the module."""
  227. self.future_imports: set[str] = set()
  228. """The imports from ``__future__``."""
  229. super().__init__(
  230. lineno=0, parent=None, col_offset=0, end_lineno=None, end_col_offset=None
  231. )
  232. # pylint: enable=redefined-builtin
  233. def postinit(
  234. self, body: list[node_classes.NodeNG], *, doc_node: Const | None = None
  235. ):
  236. self.body = body
  237. self.doc_node = doc_node
  238. def _get_stream(self):
  239. if self.file_bytes is not None:
  240. return io.BytesIO(self.file_bytes)
  241. if self.file is not None:
  242. # pylint: disable=consider-using-with
  243. stream = open(self.file, "rb")
  244. return stream
  245. return None
  246. def stream(self):
  247. """Get a stream to the underlying file or bytes.
  248. :type: file or io.BytesIO or None
  249. """
  250. return self._get_stream()
  251. def block_range(self, lineno: int) -> tuple[int, int]:
  252. """Get a range from where this node starts to where this node ends.
  253. :param lineno: Unused.
  254. :returns: The range of line numbers that this node belongs to.
  255. """
  256. return self.fromlineno, self.tolineno
  257. def scope_lookup(
  258. self, node: LookupMixIn, name: str, offset: int = 0
  259. ) -> tuple[LocalsDictNodeNG, list[node_classes.NodeNG]]:
  260. """Lookup where the given variable is assigned.
  261. :param node: The node to look for assignments up to.
  262. Any assignments after the given node are ignored.
  263. :param name: The name of the variable to find assignments for.
  264. :param offset: The line offset to filter statements up to.
  265. :returns: This scope node and the list of assignments associated to the
  266. given name according to the scope where it has been found (locals,
  267. globals or builtin).
  268. """
  269. if name in self.scope_attrs and name not in self.locals:
  270. try:
  271. return self, self.getattr(name)
  272. except AttributeInferenceError:
  273. return self, []
  274. return self._scope_lookup(node, name, offset)
  275. def pytype(self) -> Literal["builtins.module"]:
  276. """Get the name of the type that this node represents.
  277. :returns: The name of the type.
  278. """
  279. return "builtins.module"
  280. def display_type(self) -> str:
  281. """A human readable type of this node.
  282. :returns: The type of this node.
  283. :rtype: str
  284. """
  285. return "Module"
  286. def getattr(
  287. self, name, context: InferenceContext | None = None, ignore_locals=False
  288. ):
  289. if not name:
  290. raise AttributeInferenceError(target=self, attribute=name, context=context)
  291. result = []
  292. name_in_locals = name in self.locals
  293. if name in self.special_attributes and not ignore_locals and not name_in_locals:
  294. result = [self.special_attributes.lookup(name)]
  295. if name == "__name__":
  296. main_const = node_classes.const_factory("__main__")
  297. main_const.parent = AstroidManager().builtins_module
  298. result.append(main_const)
  299. elif not ignore_locals and name_in_locals:
  300. result = self.locals[name]
  301. elif self.package:
  302. try:
  303. result = [self.import_module(name, relative_only=True)]
  304. except (AstroidBuildingError, SyntaxError) as exc:
  305. raise AttributeInferenceError(
  306. target=self, attribute=name, context=context
  307. ) from exc
  308. result = [n for n in result if not isinstance(n, node_classes.DelName)]
  309. if result:
  310. return result
  311. raise AttributeInferenceError(target=self, attribute=name, context=context)
  312. def igetattr(
  313. self, name: str, context: InferenceContext | None = None
  314. ) -> Iterator[InferenceResult]:
  315. """Infer the possible values of the given variable.
  316. :param name: The name of the variable to infer.
  317. :returns: The inferred possible values.
  318. """
  319. # set lookup name since this is necessary to infer on import nodes for
  320. # instance
  321. context = copy_context(context)
  322. context.lookupname = name
  323. try:
  324. return bases._infer_stmts(self.getattr(name, context), context, frame=self)
  325. except AttributeInferenceError as error:
  326. raise InferenceError(
  327. str(error), target=self, attribute=name, context=context
  328. ) from error
  329. def fully_defined(self) -> bool:
  330. """Check if this module has been build from a .py file.
  331. If so, the module contains a complete representation,
  332. including the code.
  333. :returns: Whether the module has been built from a .py file.
  334. """
  335. return self.file is not None and self.file.endswith(".py")
  336. def statement(self) -> NoReturn:
  337. """The first parent node, including self, marked as statement node.
  338. When called on a :class:`Module` this raises a StatementMissing.
  339. """
  340. raise StatementMissing(target=self)
  341. def previous_sibling(self):
  342. """The previous sibling statement.
  343. :returns: The previous sibling statement node.
  344. :rtype: NodeNG or None
  345. """
  346. def next_sibling(self):
  347. """The next sibling statement node.
  348. :returns: The next sibling statement node.
  349. :rtype: NodeNG or None
  350. """
  351. _absolute_import_activated = True
  352. def absolute_import_activated(self) -> bool:
  353. """Whether :pep:`328` absolute import behaviour has been enabled.
  354. :returns: Whether :pep:`328` has been enabled.
  355. """
  356. return self._absolute_import_activated
  357. def import_module(
  358. self,
  359. modname: str,
  360. relative_only: bool = False,
  361. level: int | None = None,
  362. use_cache: bool = True,
  363. ) -> Module:
  364. """Get the ast for a given module as if imported from this module.
  365. :param modname: The name of the module to "import".
  366. :param relative_only: Whether to only consider relative imports.
  367. :param level: The level of relative import.
  368. :param use_cache: Whether to use the astroid_cache of modules.
  369. :returns: The imported module ast.
  370. """
  371. if relative_only and level is None:
  372. level = 0
  373. absmodname = self.relative_to_absolute_name(modname, level)
  374. try:
  375. return AstroidManager().ast_from_module_name(
  376. absmodname, use_cache=use_cache
  377. )
  378. except AstroidBuildingError:
  379. # we only want to import a sub module or package of this module,
  380. # skip here
  381. if relative_only:
  382. raise
  383. # Don't repeat the same operation, e.g. for missing modules
  384. # like "_winapi" or "nt" on POSIX systems.
  385. if modname == absmodname:
  386. raise
  387. return AstroidManager().ast_from_module_name(modname, use_cache=use_cache)
  388. def relative_to_absolute_name(self, modname: str, level: int | None) -> str:
  389. """Get the absolute module name for a relative import.
  390. The relative import can be implicit or explicit.
  391. :param modname: The module name to convert.
  392. :param level: The level of relative import.
  393. :returns: The absolute module name.
  394. :raises TooManyLevelsError: When the relative import refers to a
  395. module too far above this one.
  396. """
  397. # XXX this returns non sens when called on an absolute import
  398. # like 'pylint.checkers.astroid.utils'
  399. # XXX doesn't return absolute name if self.name isn't absolute name
  400. if self.absolute_import_activated() and level is None:
  401. return modname
  402. if level:
  403. if self.package:
  404. level = level - 1
  405. package_name = self.name.rsplit(".", level)[0]
  406. elif (
  407. self.path
  408. and not os.path.exists(os.path.dirname(self.path[0]) + "/__init__.py")
  409. and os.path.exists(
  410. os.path.dirname(self.path[0]) + "/" + modname.split(".")[0]
  411. )
  412. ):
  413. level = level - 1
  414. package_name = ""
  415. else:
  416. package_name = self.name.rsplit(".", level)[0]
  417. if level and self.name.count(".") < level:
  418. raise TooManyLevelsError(level=level, name=self.name)
  419. elif self.package:
  420. package_name = self.name
  421. else:
  422. package_name = self.name.rsplit(".", 1)[0]
  423. if package_name:
  424. if not modname:
  425. return package_name
  426. return f"{package_name}.{modname}"
  427. return modname
  428. def wildcard_import_names(self):
  429. """The list of imported names when this module is 'wildcard imported'.
  430. It doesn't include the '__builtins__' name which is added by the
  431. current CPython implementation of wildcard imports.
  432. :returns: The list of imported names.
  433. :rtype: list(str)
  434. """
  435. # We separate the different steps of lookup in try/excepts
  436. # to avoid catching too many Exceptions
  437. default = [name for name in self.keys() if not name.startswith("_")]
  438. try:
  439. all_values = self["__all__"]
  440. except KeyError:
  441. return default
  442. try:
  443. explicit = next(all_values.assigned_stmts())
  444. except (InferenceError, StopIteration):
  445. return default
  446. except AttributeError:
  447. # not an assignment node
  448. # XXX infer?
  449. return default
  450. # Try our best to detect the exported name.
  451. inferred = []
  452. try:
  453. explicit = next(explicit.infer())
  454. except (InferenceError, StopIteration):
  455. return default
  456. if not isinstance(explicit, (node_classes.Tuple, node_classes.List)):
  457. return default
  458. def str_const(node) -> bool:
  459. return isinstance(node, node_classes.Const) and isinstance(node.value, str)
  460. for node in explicit.elts:
  461. if str_const(node):
  462. inferred.append(node.value)
  463. else:
  464. try:
  465. inferred_node = next(node.infer())
  466. except (InferenceError, StopIteration):
  467. continue
  468. if str_const(inferred_node):
  469. inferred.append(inferred_node.value)
  470. return inferred
  471. def public_names(self):
  472. """The list of the names that are publicly available in this module.
  473. :returns: The list of public names.
  474. :rtype: list(str)
  475. """
  476. return [name for name in self.keys() if not name.startswith("_")]
  477. def bool_value(self, context: InferenceContext | None = None) -> bool:
  478. """Determine the boolean value of this node.
  479. :returns: The boolean value of this node.
  480. For a :class:`Module` this is always ``True``.
  481. """
  482. return True
  483. def get_children(self):
  484. yield from self.body
  485. def frame(self, *, future: Literal[None, True] = None) -> Self:
  486. """The node's frame node.
  487. A frame node is a :class:`Module`, :class:`FunctionDef`,
  488. :class:`ClassDef` or :class:`Lambda`.
  489. :returns: The node itself.
  490. """
  491. return self
  492. def _infer(
  493. self, context: InferenceContext | None = None, **kwargs: Any
  494. ) -> Generator[Module]:
  495. yield self
  496. class __SyntheticRoot(Module):
  497. def __init__(self):
  498. super().__init__("__astroid_synthetic", pure_python=False)
  499. SYNTHETIC_ROOT = __SyntheticRoot()
  500. class GeneratorExp(ComprehensionScope):
  501. """Class representing an :class:`ast.GeneratorExp` node.
  502. >>> import astroid
  503. >>> node = astroid.extract_node('(thing for thing in things if thing)')
  504. >>> node
  505. <GeneratorExp l.1 at 0x7f23b2e4e400>
  506. """
  507. _astroid_fields = ("elt", "generators")
  508. _other_other_fields = ("locals",)
  509. elt: NodeNG
  510. """The element that forms the output of the expression."""
  511. def __init__(
  512. self,
  513. lineno: int,
  514. col_offset: int,
  515. parent: NodeNG,
  516. *,
  517. end_lineno: int | None,
  518. end_col_offset: int | None,
  519. ) -> None:
  520. self.locals = {}
  521. """A map of the name of a local variable to the node defining the local."""
  522. self.generators: list[nodes.Comprehension] = []
  523. """The generators that are looped through."""
  524. super().__init__(
  525. lineno=lineno,
  526. col_offset=col_offset,
  527. end_lineno=end_lineno,
  528. end_col_offset=end_col_offset,
  529. parent=parent,
  530. )
  531. def postinit(self, elt: NodeNG, generators: list[nodes.Comprehension]) -> None:
  532. self.elt = elt
  533. self.generators = generators
  534. def bool_value(self, context: InferenceContext | None = None) -> Literal[True]:
  535. """Determine the boolean value of this node.
  536. :returns: The boolean value of this node.
  537. For a :class:`GeneratorExp` this is always ``True``.
  538. """
  539. return True
  540. def get_children(self):
  541. yield self.elt
  542. yield from self.generators
  543. class DictComp(ComprehensionScope):
  544. """Class representing an :class:`ast.DictComp` node.
  545. >>> import astroid
  546. >>> node = astroid.extract_node('{k:v for k, v in things if k > v}')
  547. >>> node
  548. <DictComp l.1 at 0x7f23b2e41d68>
  549. """
  550. _astroid_fields = ("key", "value", "generators")
  551. _other_other_fields = ("locals",)
  552. key: NodeNG
  553. """What produces the keys."""
  554. value: NodeNG
  555. """What produces the values."""
  556. def __init__(
  557. self,
  558. lineno: int,
  559. col_offset: int,
  560. parent: NodeNG,
  561. *,
  562. end_lineno: int | None,
  563. end_col_offset: int | None,
  564. ) -> None:
  565. self.locals = {}
  566. """A map of the name of a local variable to the node defining the local."""
  567. super().__init__(
  568. lineno=lineno,
  569. col_offset=col_offset,
  570. end_lineno=end_lineno,
  571. end_col_offset=end_col_offset,
  572. parent=parent,
  573. )
  574. def postinit(
  575. self, key: NodeNG, value: NodeNG, generators: list[nodes.Comprehension]
  576. ) -> None:
  577. self.key = key
  578. self.value = value
  579. self.generators = generators
  580. def bool_value(self, context: InferenceContext | None = None):
  581. """Determine the boolean value of this node.
  582. :returns: The boolean value of this node.
  583. For a :class:`DictComp` this is always :class:`Uninferable`.
  584. :rtype: Uninferable
  585. """
  586. return util.Uninferable
  587. def get_children(self):
  588. yield self.key
  589. yield self.value
  590. yield from self.generators
  591. class SetComp(ComprehensionScope):
  592. """Class representing an :class:`ast.SetComp` node.
  593. >>> import astroid
  594. >>> node = astroid.extract_node('{thing for thing in things if thing}')
  595. >>> node
  596. <SetComp l.1 at 0x7f23b2e41898>
  597. """
  598. _astroid_fields = ("elt", "generators")
  599. _other_other_fields = ("locals",)
  600. elt: NodeNG
  601. """The element that forms the output of the expression."""
  602. def __init__(
  603. self,
  604. lineno: int,
  605. col_offset: int,
  606. parent: NodeNG,
  607. *,
  608. end_lineno: int | None,
  609. end_col_offset: int | None,
  610. ) -> None:
  611. self.locals = {}
  612. """A map of the name of a local variable to the node defining the local."""
  613. self.generators: list[nodes.Comprehension] = []
  614. """The generators that are looped through."""
  615. super().__init__(
  616. lineno=lineno,
  617. col_offset=col_offset,
  618. end_lineno=end_lineno,
  619. end_col_offset=end_col_offset,
  620. parent=parent,
  621. )
  622. def postinit(self, elt: NodeNG, generators: list[nodes.Comprehension]) -> None:
  623. self.elt = elt
  624. self.generators = generators
  625. def bool_value(self, context: InferenceContext | None = None):
  626. """Determine the boolean value of this node.
  627. :returns: The boolean value of this node.
  628. For a :class:`SetComp` this is always :class:`Uninferable`.
  629. :rtype: Uninferable
  630. """
  631. return util.Uninferable
  632. def get_children(self):
  633. yield self.elt
  634. yield from self.generators
  635. class ListComp(ComprehensionScope):
  636. """Class representing an :class:`ast.ListComp` node.
  637. >>> import astroid
  638. >>> node = astroid.extract_node('[thing for thing in things if thing]')
  639. >>> node
  640. <ListComp l.1 at 0x7f23b2e418d0>
  641. """
  642. _astroid_fields = ("elt", "generators")
  643. _other_other_fields = ("locals",)
  644. elt: NodeNG
  645. """The element that forms the output of the expression."""
  646. def __init__(
  647. self,
  648. lineno: int,
  649. col_offset: int,
  650. parent: NodeNG,
  651. *,
  652. end_lineno: int | None,
  653. end_col_offset: int | None,
  654. ) -> None:
  655. self.locals = {}
  656. """A map of the name of a local variable to the node defining it."""
  657. self.generators: list[nodes.Comprehension] = []
  658. """The generators that are looped through."""
  659. super().__init__(
  660. lineno=lineno,
  661. col_offset=col_offset,
  662. end_lineno=end_lineno,
  663. end_col_offset=end_col_offset,
  664. parent=parent,
  665. )
  666. def postinit(self, elt: NodeNG, generators: list[nodes.Comprehension]):
  667. self.elt = elt
  668. self.generators = generators
  669. def bool_value(self, context: InferenceContext | None = None):
  670. """Determine the boolean value of this node.
  671. :returns: The boolean value of this node.
  672. For a :class:`ListComp` this is always :class:`Uninferable`.
  673. :rtype: Uninferable
  674. """
  675. return util.Uninferable
  676. def get_children(self):
  677. yield self.elt
  678. yield from self.generators
  679. def _infer_decorator_callchain(node):
  680. """Detect decorator call chaining and see if the end result is a
  681. static or a classmethod.
  682. """
  683. if not isinstance(node, FunctionDef):
  684. return None
  685. if not node.parent:
  686. return None
  687. try:
  688. result = next(node.infer_call_result(node.parent), None)
  689. except InferenceError:
  690. return None
  691. if isinstance(result, bases.Instance):
  692. result = result._proxied
  693. if isinstance(result, ClassDef):
  694. if result.is_subtype_of("builtins.classmethod"):
  695. return "classmethod"
  696. if result.is_subtype_of("builtins.staticmethod"):
  697. return "staticmethod"
  698. if isinstance(result, FunctionDef):
  699. if not result.decorators:
  700. return None
  701. # Determine if this function is decorated with one of the builtin descriptors we want.
  702. for decorator in result.decorators.nodes:
  703. if isinstance(decorator, node_classes.Name):
  704. if decorator.name in BUILTIN_DESCRIPTORS:
  705. return decorator.name
  706. if (
  707. isinstance(decorator, node_classes.Attribute)
  708. and isinstance(decorator.expr, node_classes.Name)
  709. and decorator.expr.name == "builtins"
  710. and decorator.attrname in BUILTIN_DESCRIPTORS
  711. ):
  712. return decorator.attrname
  713. return None
  714. class Lambda(_base_nodes.FilterStmtsBaseNode, LocalsDictNodeNG):
  715. """Class representing an :class:`ast.Lambda` node.
  716. >>> import astroid
  717. >>> node = astroid.extract_node('lambda arg: arg + 1')
  718. >>> node
  719. <Lambda.<lambda> l.1 at 0x7f23b2e41518>
  720. """
  721. _astroid_fields: ClassVar[tuple[str, ...]] = ("args", "body")
  722. _other_other_fields: ClassVar[tuple[str, ...]] = ("locals",)
  723. name = "<lambda>"
  724. is_lambda = True
  725. special_attributes = FunctionModel()
  726. """The names of special attributes that this function has."""
  727. args: Arguments
  728. """The arguments that the function takes."""
  729. body: NodeNG
  730. """The contents of the function body."""
  731. def implicit_parameters(self) -> Literal[0]:
  732. return 0
  733. @property
  734. def type(self) -> Literal["method", "function"]:
  735. """Whether this is a method or function.
  736. :returns: 'method' if this is a method, 'function' otherwise.
  737. """
  738. if self.args.arguments and self.args.arguments[0].name == "self":
  739. if self.parent and isinstance(self.parent.scope(), ClassDef):
  740. return "method"
  741. return "function"
  742. def __init__(
  743. self,
  744. lineno: int,
  745. col_offset: int,
  746. parent: NodeNG,
  747. *,
  748. end_lineno: int | None,
  749. end_col_offset: int | None,
  750. ):
  751. self.locals = {}
  752. """A map of the name of a local variable to the node defining it."""
  753. self.instance_attrs: dict[str, list[NodeNG]] = {}
  754. super().__init__(
  755. lineno=lineno,
  756. col_offset=col_offset,
  757. end_lineno=end_lineno,
  758. end_col_offset=end_col_offset,
  759. parent=parent,
  760. )
  761. def postinit(self, args: Arguments, body: NodeNG) -> None:
  762. self.args = args
  763. self.body = body
  764. def pytype(self) -> Literal["builtins.instancemethod", "builtins.function"]:
  765. """Get the name of the type that this node represents.
  766. :returns: The name of the type.
  767. """
  768. if "method" in self.type:
  769. return "builtins.instancemethod"
  770. return "builtins.function"
  771. def display_type(self) -> str:
  772. """A human readable type of this node.
  773. :returns: The type of this node.
  774. :rtype: str
  775. """
  776. if "method" in self.type:
  777. return "Method"
  778. return "Function"
  779. def callable(self) -> Literal[True]:
  780. """Whether this node defines something that is callable.
  781. :returns: Whether this defines something that is callable
  782. For a :class:`Lambda` this is always ``True``.
  783. """
  784. return True
  785. def argnames(self) -> list[str]:
  786. """Get the names of each of the arguments, including that
  787. of the collections of variable-length arguments ("args", "kwargs",
  788. etc.), as well as positional-only and keyword-only arguments.
  789. :returns: The names of the arguments.
  790. :rtype: list(str)
  791. """
  792. if self.args.arguments: # maybe None with builtin functions
  793. names = [elt.name for elt in self.args.arguments]
  794. else:
  795. names = []
  796. return names
  797. def infer_call_result(
  798. self,
  799. caller: SuccessfulInferenceResult | None,
  800. context: InferenceContext | None = None,
  801. ) -> Iterator[InferenceResult]:
  802. """Infer what the function returns when called."""
  803. return self.body.infer(context)
  804. def scope_lookup(
  805. self, node: LookupMixIn, name: str, offset: int = 0
  806. ) -> tuple[LocalsDictNodeNG, list[NodeNG]]:
  807. """Lookup where the given names is assigned.
  808. :param node: The node to look for assignments up to.
  809. Any assignments after the given node are ignored.
  810. :param name: The name to find assignments for.
  811. :param offset: The line offset to filter statements up to.
  812. :returns: This scope node and the list of assignments associated to the
  813. given name according to the scope where it has been found (locals,
  814. globals or builtin).
  815. """
  816. if (self.args.defaults and node in self.args.defaults) or (
  817. self.args.kw_defaults and node in self.args.kw_defaults
  818. ):
  819. if not self.parent:
  820. raise ParentMissingError(target=self)
  821. frame = self.parent.frame()
  822. # line offset to avoid that def func(f=func) resolve the default
  823. # value to the defined function
  824. offset = -1
  825. else:
  826. # check this is not used in function decorators
  827. frame = self
  828. return frame._scope_lookup(node, name, offset)
  829. def bool_value(self, context: InferenceContext | None = None) -> Literal[True]:
  830. """Determine the boolean value of this node.
  831. :returns: The boolean value of this node.
  832. For a :class:`Lambda` this is always ``True``.
  833. """
  834. return True
  835. def get_children(self):
  836. yield self.args
  837. yield self.body
  838. def frame(self, *, future: Literal[None, True] = None) -> Self:
  839. """The node's frame node.
  840. A frame node is a :class:`Module`, :class:`FunctionDef`,
  841. :class:`ClassDef` or :class:`Lambda`.
  842. :returns: The node itself.
  843. """
  844. return self
  845. def getattr(
  846. self, name: str, context: InferenceContext | None = None
  847. ) -> list[NodeNG]:
  848. if not name:
  849. raise AttributeInferenceError(target=self, attribute=name, context=context)
  850. found_attrs = []
  851. if name in self.instance_attrs:
  852. found_attrs = self.instance_attrs[name]
  853. if name in self.special_attributes:
  854. found_attrs.append(self.special_attributes.lookup(name))
  855. if found_attrs:
  856. return found_attrs
  857. raise AttributeInferenceError(target=self, attribute=name)
  858. def _infer(
  859. self, context: InferenceContext | None = None, **kwargs: Any
  860. ) -> Generator[Lambda]:
  861. yield self
  862. def _get_yield_nodes_skip_functions(self):
  863. """A Lambda node can contain a Yield node in the body."""
  864. yield from self.body._get_yield_nodes_skip_functions()
  865. class FunctionDef(
  866. _base_nodes.MultiLineBlockNode,
  867. _base_nodes.FilterStmtsBaseNode,
  868. _base_nodes.Statement,
  869. LocalsDictNodeNG,
  870. ):
  871. """Class representing an :class:`ast.FunctionDef`.
  872. >>> import astroid
  873. >>> node = astroid.extract_node('''
  874. ... def my_func(arg):
  875. ... return arg + 1
  876. ... ''')
  877. >>> node
  878. <FunctionDef.my_func l.2 at 0x7f23b2e71e10>
  879. """
  880. _astroid_fields = (
  881. "decorators",
  882. "args",
  883. "returns",
  884. "type_params",
  885. "doc_node",
  886. "body",
  887. )
  888. _multi_line_block_fields = ("body",)
  889. returns = None
  890. decorators: node_classes.Decorators | None
  891. """The decorators that are applied to this method or function."""
  892. doc_node: Const | None
  893. """The doc node associated with this node."""
  894. args: Arguments
  895. """The arguments that the function takes."""
  896. is_function = True
  897. """Whether this node indicates a function.
  898. For a :class:`FunctionDef` this is always ``True``.
  899. :type: bool
  900. """
  901. type_annotation = None
  902. """If present, this will contain the type annotation passed by a type comment
  903. :type: NodeNG or None
  904. """
  905. type_comment_args = None
  906. """
  907. If present, this will contain the type annotation for arguments
  908. passed by a type comment
  909. """
  910. type_comment_returns = None
  911. """If present, this will contain the return type annotation, passed by a type comment"""
  912. # attributes below are set by the builder module or by raw factories
  913. _other_fields = ("name", "position")
  914. _other_other_fields = (
  915. "locals",
  916. "_type",
  917. "type_comment_returns",
  918. "type_comment_args",
  919. )
  920. _type = None
  921. name = "<functiondef>"
  922. special_attributes = FunctionModel()
  923. """The names of special attributes that this function has."""
  924. def __init__(
  925. self,
  926. name: str,
  927. lineno: int,
  928. col_offset: int,
  929. parent: NodeNG,
  930. *,
  931. end_lineno: int | None,
  932. end_col_offset: int | None,
  933. ) -> None:
  934. self.name = name
  935. """The name of the function."""
  936. self.locals = {}
  937. """A map of the name of a local variable to the node defining it."""
  938. self.body: list[NodeNG] = []
  939. """The contents of the function body."""
  940. self.type_params: list[nodes.TypeVar | nodes.ParamSpec | nodes.TypeVarTuple] = (
  941. []
  942. )
  943. """PEP 695 (Python 3.12+) type params, e.g. first 'T' in def func[T]() -> T: ..."""
  944. self.instance_attrs: dict[str, list[NodeNG]] = {}
  945. super().__init__(
  946. lineno=lineno,
  947. col_offset=col_offset,
  948. end_lineno=end_lineno,
  949. end_col_offset=end_col_offset,
  950. parent=parent,
  951. )
  952. def postinit(
  953. self,
  954. args: Arguments,
  955. body: list[NodeNG],
  956. decorators: node_classes.Decorators | None = None,
  957. returns=None,
  958. type_comment_returns=None,
  959. type_comment_args=None,
  960. *,
  961. position: Position | None = None,
  962. doc_node: Const | None = None,
  963. type_params: (
  964. list[nodes.TypeVar | nodes.ParamSpec | nodes.TypeVarTuple] | None
  965. ) = None,
  966. ):
  967. """Do some setup after initialisation.
  968. :param args: The arguments that the function takes.
  969. :param body: The contents of the function body.
  970. :param decorators: The decorators that are applied to this
  971. method or function.
  972. :params type_comment_returns:
  973. The return type annotation passed via a type comment.
  974. :params type_comment_args:
  975. The args type annotation passed via a type comment.
  976. :params position:
  977. Position of function keyword(s) and name.
  978. :param doc_node:
  979. The doc node associated with this node.
  980. :param type_params:
  981. The type_params associated with this node.
  982. """
  983. self.args = args
  984. self.body = body
  985. self.decorators = decorators
  986. self.returns = returns
  987. self.type_comment_returns = type_comment_returns
  988. self.type_comment_args = type_comment_args
  989. self.position = position
  990. self.doc_node = doc_node
  991. self.type_params = type_params or []
  992. @cached_property
  993. def extra_decorators(self) -> list[node_classes.Call]:
  994. """The extra decorators that this function can have.
  995. Additional decorators are considered when they are used as
  996. assignments, as in ``method = staticmethod(method)``.
  997. The property will return all the callables that are used for
  998. decoration.
  999. """
  1000. if not (self.parent and isinstance(frame := self.parent.frame(), ClassDef)):
  1001. return []
  1002. decorators: list[node_classes.Call] = []
  1003. for assign in frame._assign_nodes_in_scope:
  1004. if isinstance(assign.value, node_classes.Call) and isinstance(
  1005. assign.value.func, node_classes.Name
  1006. ):
  1007. for assign_node in assign.targets:
  1008. if not isinstance(assign_node, node_classes.AssignName):
  1009. # Support only `name = callable(name)`
  1010. continue
  1011. if assign_node.name != self.name:
  1012. # Interested only in the assignment nodes that
  1013. # decorates the current method.
  1014. continue
  1015. try:
  1016. meth = frame[self.name]
  1017. except KeyError:
  1018. continue
  1019. else:
  1020. # Must be a function and in the same frame as the
  1021. # original method.
  1022. if (
  1023. isinstance(meth, FunctionDef)
  1024. and assign_node.frame() == frame
  1025. ):
  1026. decorators.append(assign.value)
  1027. return decorators
  1028. def pytype(self) -> Literal["builtins.instancemethod", "builtins.function"]:
  1029. """Get the name of the type that this node represents.
  1030. :returns: The name of the type.
  1031. """
  1032. if "method" in self.type:
  1033. return "builtins.instancemethod"
  1034. return "builtins.function"
  1035. def display_type(self) -> str:
  1036. """A human readable type of this node.
  1037. :returns: The type of this node.
  1038. :rtype: str
  1039. """
  1040. if "method" in self.type:
  1041. return "Method"
  1042. return "Function"
  1043. def callable(self) -> Literal[True]:
  1044. return True
  1045. def argnames(self) -> list[str]:
  1046. """Get the names of each of the arguments, including that
  1047. of the collections of variable-length arguments ("args", "kwargs",
  1048. etc.), as well as positional-only and keyword-only arguments.
  1049. :returns: The names of the arguments.
  1050. :rtype: list(str)
  1051. """
  1052. if self.args.arguments: # maybe None with builtin functions
  1053. names = [elt.name for elt in self.args.arguments]
  1054. else:
  1055. names = []
  1056. return names
  1057. def getattr(
  1058. self, name: str, context: InferenceContext | None = None
  1059. ) -> list[NodeNG]:
  1060. if not name:
  1061. raise AttributeInferenceError(target=self, attribute=name, context=context)
  1062. found_attrs = []
  1063. if name in self.instance_attrs:
  1064. found_attrs = self.instance_attrs[name]
  1065. if name in self.special_attributes:
  1066. found_attrs.append(self.special_attributes.lookup(name))
  1067. if found_attrs:
  1068. return found_attrs
  1069. raise AttributeInferenceError(target=self, attribute=name)
  1070. @cached_property
  1071. def type(self) -> str: # pylint: disable=too-many-return-statements # noqa: C901
  1072. """The function type for this node.
  1073. Possible values are: method, function, staticmethod, classmethod.
  1074. """
  1075. for decorator in self.extra_decorators:
  1076. if decorator.func.name in BUILTIN_DESCRIPTORS:
  1077. return decorator.func.name
  1078. if not self.parent:
  1079. raise ParentMissingError(target=self)
  1080. frame = self.parent.frame()
  1081. type_name = "function"
  1082. if isinstance(frame, ClassDef):
  1083. if self.name == "__new__":
  1084. return "classmethod"
  1085. if self.name == "__init_subclass__":
  1086. return "classmethod"
  1087. if self.name == "__class_getitem__":
  1088. return "classmethod"
  1089. type_name = "method"
  1090. if not self.decorators:
  1091. return type_name
  1092. for node in self.decorators.nodes:
  1093. if isinstance(node, node_classes.Name):
  1094. if node.name in BUILTIN_DESCRIPTORS:
  1095. return node.name
  1096. if (
  1097. isinstance(node, node_classes.Attribute)
  1098. and isinstance(node.expr, node_classes.Name)
  1099. and node.expr.name == "builtins"
  1100. and node.attrname in BUILTIN_DESCRIPTORS
  1101. ):
  1102. return node.attrname
  1103. if isinstance(node, node_classes.Call):
  1104. # Handle the following case:
  1105. # @some_decorator(arg1, arg2)
  1106. # def func(...)
  1107. #
  1108. try:
  1109. current = next(node.func.infer())
  1110. except (InferenceError, StopIteration):
  1111. continue
  1112. _type = _infer_decorator_callchain(current)
  1113. if _type is not None:
  1114. return _type
  1115. try:
  1116. for inferred in node.infer():
  1117. # Check to see if this returns a static or a class method.
  1118. _type = _infer_decorator_callchain(inferred)
  1119. if _type is not None:
  1120. return _type
  1121. if not isinstance(inferred, ClassDef):
  1122. continue
  1123. for ancestor in inferred.ancestors():
  1124. if not isinstance(ancestor, ClassDef):
  1125. continue
  1126. if ancestor.is_subtype_of("builtins.classmethod"):
  1127. return "classmethod"
  1128. if ancestor.is_subtype_of("builtins.staticmethod"):
  1129. return "staticmethod"
  1130. except InferenceError:
  1131. pass
  1132. return type_name
  1133. @cached_property
  1134. def fromlineno(self) -> int:
  1135. """The first line that this node appears on in the source code.
  1136. Can also return 0 if the line can not be determined.
  1137. """
  1138. # lineno is the line number of the first decorator, we want the def
  1139. # statement lineno. Similar to 'ClassDef.fromlineno'
  1140. lineno = self.lineno or 0
  1141. if self.decorators is not None:
  1142. lineno += sum(
  1143. node.tolineno - (node.lineno or 0) + 1 for node in self.decorators.nodes
  1144. )
  1145. return lineno or 0
  1146. @cached_property
  1147. def blockstart_tolineno(self):
  1148. """The line on which the beginning of this block ends.
  1149. :type: int
  1150. """
  1151. if self.returns:
  1152. return self.returns.tolineno
  1153. return self.args.tolineno
  1154. def implicit_parameters(self) -> Literal[0, 1]:
  1155. return 1 if self.is_bound() else 0
  1156. def block_range(self, lineno: int) -> tuple[int, int]:
  1157. """Get a range from the given line number to where this node ends.
  1158. :param lineno: Unused.
  1159. :returns: The range of line numbers that this node belongs to,
  1160. """
  1161. return self.fromlineno, self.tolineno
  1162. def igetattr(
  1163. self, name: str, context: InferenceContext | None = None
  1164. ) -> Iterator[InferenceResult]:
  1165. """Inferred getattr, which returns an iterator of inferred statements."""
  1166. try:
  1167. return bases._infer_stmts(self.getattr(name, context), context, frame=self)
  1168. except AttributeInferenceError as error:
  1169. raise InferenceError(
  1170. str(error), target=self, attribute=name, context=context
  1171. ) from error
  1172. def is_method(self) -> bool:
  1173. """Check if this function node represents a method.
  1174. :returns: Whether this is a method.
  1175. """
  1176. # check we are defined in a ClassDef, because this is usually expected
  1177. # (e.g. pylint...) when is_method() return True
  1178. return (
  1179. self.type != "function"
  1180. and self.parent is not None
  1181. and isinstance(self.parent.frame(), ClassDef)
  1182. )
  1183. def decoratornames(self, context: InferenceContext | None = None) -> set[str]:
  1184. """Get the qualified names of each of the decorators on this function.
  1185. :param context:
  1186. An inference context that can be passed to inference functions
  1187. :returns: The names of the decorators.
  1188. """
  1189. result = set()
  1190. decoratornodes = []
  1191. if self.decorators is not None:
  1192. decoratornodes += self.decorators.nodes
  1193. decoratornodes += self.extra_decorators
  1194. for decnode in decoratornodes:
  1195. try:
  1196. for infnode in decnode.infer(context=context):
  1197. result.add(infnode.qname())
  1198. except InferenceError:
  1199. continue
  1200. return result
  1201. def is_bound(self) -> bool:
  1202. """Check if the function is bound to an instance or class.
  1203. :returns: Whether the function is bound to an instance or class.
  1204. """
  1205. return self.type in {"method", "classmethod"}
  1206. def is_abstract(self, pass_is_abstract=True, any_raise_is_abstract=False) -> bool:
  1207. """Check if the method is abstract.
  1208. A method is considered abstract if any of the following is true:
  1209. * The only statement is 'raise NotImplementedError'
  1210. * The only statement is 'raise <SomeException>' and any_raise_is_abstract is True
  1211. * The only statement is 'pass' and pass_is_abstract is True
  1212. * The method is annotated with abc.astractproperty/abc.abstractmethod
  1213. :returns: Whether the method is abstract.
  1214. """
  1215. if self.decorators:
  1216. for node in self.decorators.nodes:
  1217. try:
  1218. inferred = next(node.infer())
  1219. except (InferenceError, StopIteration):
  1220. continue
  1221. if inferred and inferred.qname() in {
  1222. "abc.abstractproperty",
  1223. "abc.abstractmethod",
  1224. }:
  1225. return True
  1226. for child_node in self.body:
  1227. if isinstance(child_node, node_classes.Raise):
  1228. if any_raise_is_abstract:
  1229. return True
  1230. if child_node.raises_not_implemented():
  1231. return True
  1232. return pass_is_abstract and isinstance(child_node, node_classes.Pass)
  1233. # empty function is the same as function with a single "pass" statement
  1234. if pass_is_abstract:
  1235. return True
  1236. return False
  1237. def is_generator(self) -> bool:
  1238. """Check if this is a generator function.
  1239. :returns: Whether this is a generator function.
  1240. """
  1241. yields_without_lambdas = set(self._get_yield_nodes_skip_lambdas())
  1242. yields_without_functions = set(self._get_yield_nodes_skip_functions())
  1243. # Want an intersecting member that is neither in a lambda nor a function
  1244. return bool(yields_without_lambdas & yields_without_functions)
  1245. def _infer(
  1246. self, context: InferenceContext | None = None, **kwargs: Any
  1247. ) -> Generator[objects.Property | FunctionDef, None, InferenceErrorInfo]:
  1248. from astroid import objects # pylint: disable=import-outside-toplevel
  1249. if not (self.decorators and bases._is_property(self)):
  1250. yield self
  1251. return InferenceErrorInfo(node=self, context=context)
  1252. if not self.parent:
  1253. raise ParentMissingError(target=self)
  1254. prop_func = objects.Property(
  1255. function=self,
  1256. name=self.name,
  1257. lineno=self.lineno,
  1258. parent=self.parent,
  1259. col_offset=self.col_offset,
  1260. )
  1261. prop_func.postinit(body=[], args=self.args, doc_node=self.doc_node)
  1262. yield prop_func
  1263. return InferenceErrorInfo(node=self, context=context)
  1264. def infer_yield_result(self, context: InferenceContext | None = None):
  1265. """Infer what the function yields when called
  1266. :returns: What the function yields
  1267. :rtype: iterable(NodeNG or Uninferable) or None
  1268. """
  1269. for yield_ in self.nodes_of_class(node_classes.Yield):
  1270. if yield_.value is None:
  1271. yield node_classes.Const(None, parent=yield_, lineno=yield_.lineno)
  1272. elif yield_.scope() == self:
  1273. yield from yield_.value.infer(context=context)
  1274. def infer_call_result(
  1275. self,
  1276. caller: SuccessfulInferenceResult | None,
  1277. context: InferenceContext | None = None,
  1278. ) -> Iterator[InferenceResult]:
  1279. """Infer what the function returns when called."""
  1280. if context is None:
  1281. context = InferenceContext()
  1282. if self.is_generator():
  1283. if isinstance(self, AsyncFunctionDef):
  1284. generator_cls: type[bases.Generator] = bases.AsyncGenerator
  1285. else:
  1286. generator_cls = bases.Generator
  1287. result = generator_cls(self, generator_initial_context=context)
  1288. yield result
  1289. return
  1290. # This is really a gigantic hack to work around metaclass generators
  1291. # that return transient class-generating functions. Pylint's AST structure
  1292. # cannot handle a base class object that is only used for calling __new__,
  1293. # but does not contribute to the inheritance structure itself. We inject
  1294. # a fake class into the hierarchy here for several well-known metaclass
  1295. # generators, and filter it out later.
  1296. if (
  1297. self.name == "with_metaclass"
  1298. and caller is not None
  1299. and self.args.args
  1300. and len(self.args.args) == 1
  1301. and self.args.vararg is not None
  1302. ):
  1303. if isinstance(caller.args, node_classes.Arguments):
  1304. assert caller.args.args is not None
  1305. metaclass = next(caller.args.args[0].infer(context), None)
  1306. elif isinstance(caller.args, list):
  1307. metaclass = next(caller.args[0].infer(context), None)
  1308. else:
  1309. raise TypeError( # pragma: no cover
  1310. f"caller.args was neither Arguments nor list; got {type(caller.args)}"
  1311. )
  1312. if isinstance(metaclass, ClassDef):
  1313. class_bases = [_infer_last(x, context) for x in caller.args[1:]]
  1314. new_class = ClassDef(
  1315. name="temporary_class",
  1316. lineno=0,
  1317. col_offset=0,
  1318. end_lineno=0,
  1319. end_col_offset=0,
  1320. parent=SYNTHETIC_ROOT,
  1321. )
  1322. new_class.hide = True
  1323. new_class.postinit(
  1324. bases=[
  1325. base
  1326. for base in class_bases
  1327. if not isinstance(base, util.UninferableBase)
  1328. ],
  1329. body=[],
  1330. decorators=None,
  1331. metaclass=metaclass,
  1332. )
  1333. yield new_class
  1334. return
  1335. returns = self._get_return_nodes_skip_functions()
  1336. first_return = next(returns, None)
  1337. if not first_return:
  1338. if self.body:
  1339. if self.is_abstract(pass_is_abstract=True, any_raise_is_abstract=True):
  1340. yield util.Uninferable
  1341. else:
  1342. yield node_classes.Const(None)
  1343. return
  1344. raise InferenceError("The function does not have any return statements")
  1345. for returnnode in itertools.chain((first_return,), returns):
  1346. if returnnode.value is None:
  1347. yield node_classes.Const(None)
  1348. else:
  1349. try:
  1350. yield from returnnode.value.infer(context)
  1351. except InferenceError:
  1352. yield util.Uninferable
  1353. def bool_value(self, context: InferenceContext | None = None) -> bool:
  1354. """Determine the boolean value of this node.
  1355. :returns: The boolean value of this node.
  1356. For a :class:`FunctionDef` this is always ``True``.
  1357. """
  1358. return True
  1359. def get_children(self):
  1360. if self.decorators is not None:
  1361. yield self.decorators
  1362. yield self.args
  1363. if self.returns is not None:
  1364. yield self.returns
  1365. yield from self.type_params
  1366. yield from self.body
  1367. def scope_lookup(
  1368. self, node: LookupMixIn, name: str, offset: int = 0
  1369. ) -> tuple[LocalsDictNodeNG, list[nodes.NodeNG]]:
  1370. """Lookup where the given name is assigned."""
  1371. if name == "__class__":
  1372. # __class__ is an implicit closure reference created by the compiler
  1373. # if any methods in a class body refer to either __class__ or super.
  1374. # In our case, we want to be able to look it up in the current scope
  1375. # when `__class__` is being used.
  1376. if self.parent and isinstance(frame := self.parent.frame(), ClassDef):
  1377. return self, [frame]
  1378. if (self.args.defaults and node in self.args.defaults) or (
  1379. self.args.kw_defaults and node in self.args.kw_defaults
  1380. ):
  1381. if not self.parent:
  1382. raise ParentMissingError(target=self)
  1383. frame = self.parent.frame()
  1384. # line offset to avoid that def func(f=func) resolve the default
  1385. # value to the defined function
  1386. offset = -1
  1387. else:
  1388. # check this is not used in function decorators
  1389. frame = self
  1390. return frame._scope_lookup(node, name, offset)
  1391. def frame(self, *, future: Literal[None, True] = None) -> Self:
  1392. """The node's frame node.
  1393. A frame node is a :class:`Module`, :class:`FunctionDef`,
  1394. :class:`ClassDef` or :class:`Lambda`.
  1395. :returns: The node itself.
  1396. """
  1397. return self
  1398. class AsyncFunctionDef(FunctionDef):
  1399. """Class representing an :class:`ast.FunctionDef` node.
  1400. A :class:`AsyncFunctionDef` is an asynchronous function
  1401. created with the `async` keyword.
  1402. >>> import astroid
  1403. >>> node = astroid.extract_node('''
  1404. async def func(things):
  1405. async for thing in things:
  1406. print(thing)
  1407. ''')
  1408. >>> node
  1409. <AsyncFunctionDef.func l.2 at 0x7f23b2e416d8>
  1410. >>> node.body[0]
  1411. <AsyncFor l.3 at 0x7f23b2e417b8>
  1412. """
  1413. def _is_metaclass(
  1414. klass: ClassDef,
  1415. seen: set[str] | None = None,
  1416. context: InferenceContext | None = None,
  1417. ) -> bool:
  1418. """Return if the given class can be
  1419. used as a metaclass.
  1420. """
  1421. if klass.name == "type":
  1422. return True
  1423. if seen is None:
  1424. seen = set()
  1425. for base in klass.bases:
  1426. try:
  1427. for baseobj in base.infer(context=context):
  1428. baseobj_name = baseobj.qname()
  1429. if baseobj_name in seen:
  1430. continue
  1431. seen.add(baseobj_name)
  1432. if isinstance(baseobj, bases.Instance):
  1433. # not abstract
  1434. return False
  1435. if baseobj is klass:
  1436. continue
  1437. if not isinstance(baseobj, ClassDef):
  1438. continue
  1439. if baseobj._type == "metaclass":
  1440. return True
  1441. if _is_metaclass(baseobj, seen, context=context):
  1442. return True
  1443. except InferenceError:
  1444. continue
  1445. return False
  1446. def _class_type(
  1447. klass: ClassDef,
  1448. ancestors: set[str] | None = None,
  1449. context: InferenceContext | None = None,
  1450. ) -> Literal["class", "exception", "metaclass"]:
  1451. """return a ClassDef node type to differ metaclass and exception
  1452. from 'regular' classes
  1453. """
  1454. # XXX we have to store ancestors in case we have an ancestor loop
  1455. if klass._type is not None:
  1456. return klass._type
  1457. if _is_metaclass(klass, context=context):
  1458. klass._type = "metaclass"
  1459. elif klass.name.endswith("Exception"):
  1460. klass._type = "exception"
  1461. else:
  1462. if ancestors is None:
  1463. ancestors = set()
  1464. klass_name = klass.qname()
  1465. if klass_name in ancestors:
  1466. # XXX we are in loop ancestors, and have found no type
  1467. klass._type = "class"
  1468. return "class"
  1469. ancestors.add(klass_name)
  1470. for base in klass.ancestors(recurs=False):
  1471. name = _class_type(base, ancestors)
  1472. if name != "class":
  1473. if name == "metaclass" and klass._type != "metaclass":
  1474. # don't propagate it if the current class
  1475. # can't be a metaclass
  1476. continue
  1477. klass._type = base.type
  1478. break
  1479. if klass._type is None:
  1480. klass._type = "class"
  1481. return klass._type
  1482. def get_wrapping_class(node):
  1483. """Get the class that wraps the given node.
  1484. We consider that a class wraps a node if the class
  1485. is a parent for the said node.
  1486. :returns: The class that wraps the given node
  1487. :rtype: ClassDef or None
  1488. """
  1489. klass = node.frame()
  1490. while klass is not None and not isinstance(klass, ClassDef):
  1491. if klass.parent is None:
  1492. klass = None
  1493. else:
  1494. klass = klass.parent.frame()
  1495. return klass
  1496. class ClassDef(
  1497. _base_nodes.FilterStmtsBaseNode, LocalsDictNodeNG, _base_nodes.Statement
  1498. ):
  1499. """Class representing an :class:`ast.ClassDef` node.
  1500. >>> import astroid
  1501. >>> node = astroid.extract_node('''
  1502. class Thing:
  1503. def my_meth(self, arg):
  1504. return arg + self.offset
  1505. ''')
  1506. >>> node
  1507. <ClassDef.Thing l.2 at 0x7f23b2e9e748>
  1508. """
  1509. # some of the attributes below are set by the builder module or
  1510. # by a raw factories
  1511. # a dictionary of class instances attributes
  1512. _astroid_fields = (
  1513. "decorators",
  1514. "bases",
  1515. "keywords",
  1516. "doc_node",
  1517. "body",
  1518. "type_params",
  1519. ) # name
  1520. decorators = None
  1521. """The decorators that are applied to this class.
  1522. :type: Decorators or None
  1523. """
  1524. special_attributes = ClassModel()
  1525. """The names of special attributes that this class has.
  1526. :type: objectmodel.ClassModel
  1527. """
  1528. _type: Literal["class", "exception", "metaclass"] | None = None
  1529. _metaclass: NodeNG | None = None
  1530. _metaclass_hack = False
  1531. hide = False
  1532. type = property(
  1533. _class_type,
  1534. doc=(
  1535. "The class type for this node.\n\n"
  1536. "Possible values are: class, metaclass, exception.\n\n"
  1537. ":type: str"
  1538. ),
  1539. )
  1540. _other_fields = ("name", "is_dataclass", "position")
  1541. _other_other_fields = "locals"
  1542. def __init__(
  1543. self,
  1544. name: str,
  1545. lineno: int,
  1546. col_offset: int,
  1547. parent: NodeNG,
  1548. *,
  1549. end_lineno: int | None,
  1550. end_col_offset: int | None,
  1551. ) -> None:
  1552. self.instance_attrs: dict[str, NodeNG] = {}
  1553. self.locals = {}
  1554. """A map of the name of a local variable to the node defining it."""
  1555. self.keywords: list[node_classes.Keyword] = []
  1556. """The keywords given to the class definition.
  1557. This is usually for :pep:`3115` style metaclass declaration.
  1558. """
  1559. self.bases: list[SuccessfulInferenceResult] = []
  1560. """What the class inherits from."""
  1561. self.body: list[NodeNG] = []
  1562. """The contents of the class body."""
  1563. self.name = name
  1564. """The name of the class."""
  1565. self.decorators = None
  1566. """The decorators that are applied to this class."""
  1567. self.doc_node: Const | None = None
  1568. """The doc node associated with this node."""
  1569. self.is_dataclass: bool = False
  1570. """Whether this class is a dataclass."""
  1571. self.type_params: list[nodes.TypeVar | nodes.ParamSpec | nodes.TypeVarTuple] = (
  1572. []
  1573. )
  1574. """PEP 695 (Python 3.12+) type params, e.g. class MyClass[T]: ..."""
  1575. super().__init__(
  1576. lineno=lineno,
  1577. col_offset=col_offset,
  1578. end_lineno=end_lineno,
  1579. end_col_offset=end_col_offset,
  1580. parent=parent,
  1581. )
  1582. for local_name, node in self.implicit_locals():
  1583. self.add_local_node(node, local_name)
  1584. infer_binary_op: ClassVar[InferBinaryOp[ClassDef]] = (
  1585. protocols.instance_class_infer_binary_op
  1586. )
  1587. def implicit_parameters(self) -> Literal[1]:
  1588. return 1
  1589. def implicit_locals(self):
  1590. """Get implicitly defined class definition locals.
  1591. :returns: the the name and Const pair for each local
  1592. :rtype: tuple(tuple(str, node_classes.Const), ...)
  1593. """
  1594. locals_ = (("__module__", self.special_attributes.attr___module__),)
  1595. # __qualname__ is defined in PEP3155
  1596. locals_ += (
  1597. ("__qualname__", self.special_attributes.attr___qualname__),
  1598. ("__annotations__", self.special_attributes.attr___annotations__),
  1599. )
  1600. return locals_
  1601. # pylint: disable=redefined-outer-name
  1602. def postinit(
  1603. self,
  1604. bases: list[SuccessfulInferenceResult],
  1605. body: list[NodeNG],
  1606. decorators: node_classes.Decorators | None,
  1607. newstyle: bool | None = None,
  1608. metaclass: NodeNG | None = None,
  1609. keywords: list[node_classes.Keyword] | None = None,
  1610. *,
  1611. position: Position | None = None,
  1612. doc_node: Const | None = None,
  1613. type_params: (
  1614. list[nodes.TypeVar | nodes.ParamSpec | nodes.TypeVarTuple] | None
  1615. ) = None,
  1616. ) -> None:
  1617. if keywords is not None:
  1618. self.keywords = keywords
  1619. self.bases = bases
  1620. self.body = body
  1621. self.decorators = decorators
  1622. self._metaclass = metaclass
  1623. self.position = position
  1624. self.doc_node = doc_node
  1625. self.type_params = type_params or []
  1626. @cached_property
  1627. def blockstart_tolineno(self):
  1628. """The line on which the beginning of this block ends.
  1629. :type: int
  1630. """
  1631. if self.bases:
  1632. return self.bases[-1].tolineno
  1633. return self.fromlineno
  1634. def block_range(self, lineno: int) -> tuple[int, int]:
  1635. """Get a range from the given line number to where this node ends.
  1636. :param lineno: Unused.
  1637. :returns: The range of line numbers that this node belongs to,
  1638. """
  1639. return self.fromlineno, self.tolineno
  1640. def pytype(self) -> Literal["builtins.type"]:
  1641. """Get the name of the type that this node represents.
  1642. :returns: The name of the type.
  1643. """
  1644. return "builtins.type"
  1645. def display_type(self) -> str:
  1646. """A human readable type of this node.
  1647. :returns: The type of this node.
  1648. :rtype: str
  1649. """
  1650. return "Class"
  1651. def callable(self) -> bool:
  1652. """Whether this node defines something that is callable.
  1653. :returns: Whether this defines something that is callable.
  1654. For a :class:`ClassDef` this is always ``True``.
  1655. """
  1656. return True
  1657. def is_subtype_of(self, type_name, context: InferenceContext | None = None) -> bool:
  1658. """Whether this class is a subtype of the given type.
  1659. :param type_name: The name of the type of check against.
  1660. :type type_name: str
  1661. :returns: Whether this class is a subtype of the given type.
  1662. """
  1663. if self.qname() == type_name:
  1664. return True
  1665. return any(anc.qname() == type_name for anc in self.ancestors(context=context))
  1666. def _infer_type_call(self, caller, context):
  1667. try:
  1668. name_node = next(caller.args[0].infer(context))
  1669. except StopIteration as e:
  1670. raise InferenceError(node=caller.args[0], context=context) from e
  1671. if isinstance(name_node, node_classes.Const) and isinstance(
  1672. name_node.value, str
  1673. ):
  1674. name = name_node.value
  1675. else:
  1676. return util.Uninferable
  1677. result = ClassDef(
  1678. name,
  1679. lineno=0,
  1680. col_offset=0,
  1681. end_lineno=0,
  1682. end_col_offset=0,
  1683. parent=caller.parent,
  1684. )
  1685. # Get the bases of the class.
  1686. try:
  1687. class_bases = next(caller.args[1].infer(context))
  1688. except StopIteration as e:
  1689. raise InferenceError(node=caller.args[1], context=context) from e
  1690. if isinstance(class_bases, (node_classes.Tuple, node_classes.List)):
  1691. bases = []
  1692. for base in class_bases.itered():
  1693. inferred = next(base.infer(context=context), None)
  1694. if inferred:
  1695. bases.append(
  1696. node_classes.EvaluatedObject(original=base, value=inferred)
  1697. )
  1698. result.bases = bases
  1699. else:
  1700. # There is currently no AST node that can represent an 'unknown'
  1701. # node (Uninferable is not an AST node), therefore we simply return Uninferable here
  1702. # although we know at least the name of the class.
  1703. return util.Uninferable
  1704. # Get the members of the class
  1705. try:
  1706. members = next(caller.args[2].infer(context))
  1707. except (InferenceError, StopIteration):
  1708. members = None
  1709. if members and isinstance(members, node_classes.Dict):
  1710. for attr, value in members.items:
  1711. if isinstance(attr, node_classes.Const) and isinstance(attr.value, str):
  1712. result.locals[attr.value] = [value]
  1713. return result
  1714. def infer_call_result(
  1715. self,
  1716. caller: SuccessfulInferenceResult | None,
  1717. context: InferenceContext | None = None,
  1718. ) -> Iterator[InferenceResult]:
  1719. """infer what a class is returning when called"""
  1720. if self.is_subtype_of("builtins.type", context) and len(caller.args) == 3:
  1721. result = self._infer_type_call(caller, context)
  1722. yield result
  1723. return
  1724. dunder_call = None
  1725. try:
  1726. metaclass = self.metaclass(context=context)
  1727. if metaclass is not None:
  1728. # Only get __call__ if it's defined locally for the metaclass.
  1729. # Otherwise we will find ObjectModel.__call__ which will
  1730. # return an instance of the metaclass. Instantiating the class is
  1731. # handled later.
  1732. if "__call__" in metaclass.locals:
  1733. dunder_call = next(metaclass.igetattr("__call__", context))
  1734. except (AttributeInferenceError, StopIteration):
  1735. pass
  1736. if dunder_call and dunder_call.qname() != "builtins.type.__call__":
  1737. # Call type.__call__ if not set metaclass
  1738. # (since type is the default metaclass)
  1739. context = bind_context_to_node(context, self)
  1740. context.callcontext.callee = dunder_call
  1741. yield from dunder_call.infer_call_result(caller, context)
  1742. else:
  1743. yield self.instantiate_class()
  1744. def scope_lookup(
  1745. self, node: LookupMixIn, name: str, offset: int = 0
  1746. ) -> tuple[LocalsDictNodeNG, list[nodes.NodeNG]]:
  1747. """Lookup where the given name is assigned.
  1748. :param node: The node to look for assignments up to.
  1749. Any assignments after the given node are ignored.
  1750. :param name: The name to find assignments for.
  1751. :param offset: The line offset to filter statements up to.
  1752. :returns: This scope node and the list of assignments associated to the
  1753. given name according to the scope where it has been found (locals,
  1754. globals or builtin).
  1755. """
  1756. # If the name looks like a builtin name, just try to look
  1757. # into the upper scope of this class. We might have a
  1758. # decorator that it's poorly named after a builtin object
  1759. # inside this class.
  1760. lookup_upper_frame = (
  1761. isinstance(node.parent, node_classes.Decorators)
  1762. and name in AstroidManager().builtins_module
  1763. )
  1764. if (
  1765. any(
  1766. node == base or (base.parent_of(node) and not self.type_params)
  1767. for base in self.bases
  1768. )
  1769. or lookup_upper_frame
  1770. ):
  1771. # Handle the case where we have either a name
  1772. # in the bases of a class, which exists before
  1773. # the actual definition or the case where we have
  1774. # a Getattr node, with that name.
  1775. #
  1776. # name = ...
  1777. # class A(name):
  1778. # def name(self): ...
  1779. #
  1780. # import name
  1781. # class A(name.Name):
  1782. # def name(self): ...
  1783. if not self.parent:
  1784. raise ParentMissingError(target=self)
  1785. frame = self.parent.frame()
  1786. # line offset to avoid that class A(A) resolve the ancestor to
  1787. # the defined class
  1788. offset = -1
  1789. else:
  1790. frame = self
  1791. return frame._scope_lookup(node, name, offset)
  1792. @property
  1793. def basenames(self):
  1794. """The names of the parent classes
  1795. Names are given in the order they appear in the class definition.
  1796. :type: list(str)
  1797. """
  1798. return [bnode.as_string() for bnode in self.bases]
  1799. def ancestors(
  1800. self, recurs: bool = True, context: InferenceContext | None = None
  1801. ) -> Generator[ClassDef]:
  1802. """Iterate over the base classes in prefixed depth first order.
  1803. :param recurs: Whether to recurse or return direct ancestors only.
  1804. :returns: The base classes
  1805. """
  1806. # FIXME: should be possible to choose the resolution order
  1807. # FIXME: inference make infinite loops possible here
  1808. yielded = {self}
  1809. if context is None:
  1810. context = InferenceContext()
  1811. if not self.bases and self.qname() != "builtins.object":
  1812. # This should always be a ClassDef (which we don't assert for)
  1813. yield builtin_lookup("object")[1][0] # type: ignore[misc]
  1814. return
  1815. for stmt in self.bases:
  1816. with context.restore_path():
  1817. try:
  1818. for baseobj in stmt.infer(context):
  1819. if not isinstance(baseobj, ClassDef):
  1820. if isinstance(baseobj, bases.Instance):
  1821. baseobj = baseobj._proxied
  1822. else:
  1823. continue
  1824. if not baseobj.hide:
  1825. if baseobj in yielded:
  1826. continue
  1827. yielded.add(baseobj)
  1828. yield baseobj
  1829. if not recurs:
  1830. continue
  1831. for grandpa in baseobj.ancestors(recurs=True, context=context):
  1832. if grandpa is self:
  1833. # This class is the ancestor of itself.
  1834. break
  1835. if grandpa in yielded:
  1836. continue
  1837. yielded.add(grandpa)
  1838. yield grandpa
  1839. except InferenceError:
  1840. continue
  1841. def local_attr_ancestors(self, name, context: InferenceContext | None = None):
  1842. """Iterate over the parents that define the given name.
  1843. :param name: The name to find definitions for.
  1844. :type name: str
  1845. :returns: The parents that define the given name.
  1846. :rtype: iterable(NodeNG)
  1847. """
  1848. # Look up in the mro if we can. This will result in the
  1849. # attribute being looked up just as Python does it.
  1850. try:
  1851. ancestors: Iterable[ClassDef] = self.mro(context)[1:]
  1852. except MroError:
  1853. # Fallback to use ancestors, we can't determine
  1854. # a sane MRO.
  1855. ancestors = self.ancestors(context=context)
  1856. for astroid in ancestors:
  1857. if name in astroid:
  1858. yield astroid
  1859. def instance_attr_ancestors(self, name, context: InferenceContext | None = None):
  1860. """Iterate over the parents that define the given name as an attribute.
  1861. :param name: The name to find definitions for.
  1862. :type name: str
  1863. :returns: The parents that define the given name as
  1864. an instance attribute.
  1865. :rtype: iterable(NodeNG)
  1866. """
  1867. for astroid in self.ancestors(context=context):
  1868. if name in astroid.instance_attrs:
  1869. yield astroid
  1870. def has_base(self, node) -> bool:
  1871. """Whether this class directly inherits from the given node.
  1872. :param node: The node to check for.
  1873. :type node: NodeNG
  1874. :returns: Whether this class directly inherits from the given node.
  1875. """
  1876. return node in self.bases
  1877. def local_attr(self, name, context: InferenceContext | None = None):
  1878. """Get the list of assign nodes associated to the given name.
  1879. Assignments are looked for in both this class and in parents.
  1880. :returns: The list of assignments to the given name.
  1881. :rtype: list(NodeNG)
  1882. :raises AttributeInferenceError: If no attribute with this name
  1883. can be found in this class or parent classes.
  1884. """
  1885. result = []
  1886. if name in self.locals:
  1887. result = self.locals[name]
  1888. else:
  1889. class_node = next(self.local_attr_ancestors(name, context), None)
  1890. if class_node:
  1891. result = class_node.locals[name]
  1892. result = [n for n in result if not isinstance(n, node_classes.DelAttr)]
  1893. if result:
  1894. return result
  1895. raise AttributeInferenceError(target=self, attribute=name, context=context)
  1896. def instance_attr(self, name, context: InferenceContext | None = None):
  1897. """Get the list of nodes associated to the given attribute name.
  1898. Assignments are looked for in both this class and in parents.
  1899. :returns: The list of assignments to the given name.
  1900. :rtype: list(NodeNG)
  1901. :raises AttributeInferenceError: If no attribute with this name
  1902. can be found in this class or parent classes.
  1903. """
  1904. # Return a copy, so we don't modify self.instance_attrs,
  1905. # which could lead to infinite loop.
  1906. values = list(self.instance_attrs.get(name, []))
  1907. # get all values from parents
  1908. for class_node in self.instance_attr_ancestors(name, context):
  1909. values += class_node.instance_attrs[name]
  1910. values = [n for n in values if not isinstance(n, node_classes.DelAttr)]
  1911. if values:
  1912. return values
  1913. raise AttributeInferenceError(target=self, attribute=name, context=context)
  1914. def instantiate_class(self) -> bases.Instance:
  1915. """Get an :class:`Instance` of the :class:`ClassDef` node.
  1916. :returns: An :class:`Instance` of the :class:`ClassDef` node
  1917. """
  1918. from astroid import objects # pylint: disable=import-outside-toplevel
  1919. try:
  1920. if any(cls.name in EXCEPTION_BASE_CLASSES for cls in self.mro()):
  1921. # Subclasses of exceptions can be exception instances
  1922. return objects.ExceptionInstance(self)
  1923. except MroError:
  1924. pass
  1925. return bases.Instance(self)
  1926. def getattr(
  1927. self,
  1928. name: str,
  1929. context: InferenceContext | None = None,
  1930. class_context: bool = True,
  1931. ) -> list[InferenceResult]:
  1932. """Get an attribute from this class, using Python's attribute semantic.
  1933. This method doesn't look in the :attr:`instance_attrs` dictionary
  1934. since it is done by an :class:`Instance` proxy at inference time.
  1935. It may return an :class:`Uninferable` object if
  1936. the attribute has not been
  1937. found, but a ``__getattr__`` or ``__getattribute__`` method is defined.
  1938. If ``class_context`` is given, then it is considered that the
  1939. attribute is accessed from a class context,
  1940. e.g. ClassDef.attribute, otherwise it might have been accessed
  1941. from an instance as well. If ``class_context`` is used in that
  1942. case, then a lookup in the implicit metaclass and the explicit
  1943. metaclass will be done.
  1944. :param name: The attribute to look for.
  1945. :param class_context: Whether the attribute can be accessed statically.
  1946. :returns: The attribute.
  1947. :raises AttributeInferenceError: If the attribute cannot be inferred.
  1948. """
  1949. if not name:
  1950. raise AttributeInferenceError(target=self, attribute=name, context=context)
  1951. # don't modify the list in self.locals!
  1952. values: list[InferenceResult] = list(self.locals.get(name, []))
  1953. for classnode in self.ancestors(recurs=True, context=context):
  1954. values += classnode.locals.get(name, [])
  1955. if name in self.special_attributes and class_context and not values:
  1956. result = [self.special_attributes.lookup(name)]
  1957. return result
  1958. if class_context:
  1959. values += self._metaclass_lookup_attribute(name, context)
  1960. result: list[InferenceResult] = []
  1961. for value in values:
  1962. if isinstance(value, node_classes.AssignName):
  1963. stmt = value.statement()
  1964. # Ignore AnnAssigns without value, which are not attributes in the purest sense.
  1965. if isinstance(stmt, node_classes.AnnAssign) and stmt.value is None:
  1966. continue
  1967. result.append(value)
  1968. if not result:
  1969. raise AttributeInferenceError(target=self, attribute=name, context=context)
  1970. return result
  1971. @lru_cache(maxsize=1024) # noqa
  1972. def _metaclass_lookup_attribute(self, name, context):
  1973. """Search the given name in the implicit and the explicit metaclass."""
  1974. attrs = set()
  1975. implicit_meta = self.implicit_metaclass()
  1976. context = copy_context(context)
  1977. metaclass = self.metaclass(context=context)
  1978. for cls in (implicit_meta, metaclass):
  1979. if cls and cls != self and isinstance(cls, ClassDef):
  1980. cls_attributes = self._get_attribute_from_metaclass(cls, name, context)
  1981. attrs.update(cls_attributes)
  1982. return attrs
  1983. def _get_attribute_from_metaclass(self, cls, name, context):
  1984. from astroid import objects # pylint: disable=import-outside-toplevel
  1985. try:
  1986. attrs = cls.getattr(name, context=context, class_context=True)
  1987. except AttributeInferenceError:
  1988. return
  1989. for attr in bases._infer_stmts(attrs, context, frame=cls):
  1990. if not isinstance(attr, FunctionDef):
  1991. yield attr
  1992. continue
  1993. if isinstance(attr, objects.Property):
  1994. yield attr
  1995. continue
  1996. if attr.type == "classmethod":
  1997. # If the method is a classmethod, then it will
  1998. # be bound to the metaclass, not to the class
  1999. # from where the attribute is retrieved.
  2000. # get_wrapping_class could return None, so just
  2001. # default to the current class.
  2002. frame = get_wrapping_class(attr) or self
  2003. yield bases.BoundMethod(attr, frame)
  2004. elif attr.type == "staticmethod":
  2005. yield attr
  2006. else:
  2007. yield bases.BoundMethod(attr, self)
  2008. def igetattr(
  2009. self,
  2010. name: str,
  2011. context: InferenceContext | None = None,
  2012. class_context: bool = True,
  2013. ) -> Iterator[InferenceResult]:
  2014. """Infer the possible values of the given variable.
  2015. :param name: The name of the variable to infer.
  2016. :returns: The inferred possible values.
  2017. """
  2018. from astroid import objects # pylint: disable=import-outside-toplevel
  2019. # set lookup name since this is necessary to infer on import nodes for
  2020. # instance
  2021. context = copy_context(context)
  2022. context.lookupname = name
  2023. metaclass = self.metaclass(context=context)
  2024. try:
  2025. attributes = self.getattr(name, context, class_context=class_context)
  2026. # If we have more than one attribute, make sure that those starting from
  2027. # the second one are from the same scope. This is to account for modifications
  2028. # to the attribute happening *after* the attribute's definition (e.g. AugAssigns on lists)
  2029. if len(attributes) > 1:
  2030. first_attr, attributes = attributes[0], attributes[1:]
  2031. first_scope = first_attr.parent.scope()
  2032. attributes = [first_attr] + [
  2033. attr
  2034. for attr in attributes
  2035. if attr.parent and attr.parent.scope() == first_scope
  2036. ]
  2037. functions = [attr for attr in attributes if isinstance(attr, FunctionDef)]
  2038. setter = None
  2039. for function in functions:
  2040. dec_names = function.decoratornames(context=context)
  2041. for dec_name in dec_names:
  2042. if dec_name is util.Uninferable:
  2043. continue
  2044. if dec_name.split(".")[-1] == "setter":
  2045. setter = function
  2046. if setter:
  2047. break
  2048. if functions:
  2049. # Prefer only the last function, unless a property is involved.
  2050. last_function = functions[-1]
  2051. attributes = [
  2052. a
  2053. for a in attributes
  2054. if a not in functions or a is last_function or bases._is_property(a)
  2055. ]
  2056. for inferred in bases._infer_stmts(attributes, context, frame=self):
  2057. # yield Uninferable object instead of descriptors when necessary
  2058. if not isinstance(inferred, node_classes.Const) and isinstance(
  2059. inferred, bases.Instance
  2060. ):
  2061. try:
  2062. inferred._proxied.getattr("__get__", context)
  2063. except AttributeInferenceError:
  2064. yield inferred
  2065. else:
  2066. yield util.Uninferable
  2067. elif isinstance(inferred, objects.Property):
  2068. function = inferred.function
  2069. if not class_context:
  2070. if not context.callcontext and not setter:
  2071. context.callcontext = CallContext(
  2072. args=function.args.arguments, callee=function
  2073. )
  2074. # Through an instance so we can solve the property
  2075. yield from function.infer_call_result(
  2076. caller=self, context=context
  2077. )
  2078. # If we're in a class context, we need to determine if the property
  2079. # was defined in the metaclass (a derived class must be a subclass of
  2080. # the metaclass of all its bases), in which case we can resolve the
  2081. # property. If not, i.e. the property is defined in some base class
  2082. # instead, then we return the property object
  2083. elif metaclass and function.parent.scope() is metaclass:
  2084. # Resolve a property as long as it is not accessed through
  2085. # the class itself.
  2086. yield from function.infer_call_result(
  2087. caller=self, context=context
  2088. )
  2089. else:
  2090. yield inferred
  2091. else:
  2092. yield function_to_method(inferred, self)
  2093. except AttributeInferenceError as error:
  2094. if not name.startswith("__") and self.has_dynamic_getattr(context):
  2095. # class handle some dynamic attributes, return a Uninferable object
  2096. yield util.Uninferable
  2097. else:
  2098. raise InferenceError(
  2099. str(error), target=self, attribute=name, context=context
  2100. ) from error
  2101. def has_dynamic_getattr(self, context: InferenceContext | None = None) -> bool:
  2102. """Check if the class has a custom __getattr__ or __getattribute__.
  2103. If any such method is found and it is not from
  2104. builtins, nor from an extension module, then the function
  2105. will return True.
  2106. :returns: Whether the class has a custom __getattr__ or __getattribute__.
  2107. """
  2108. def _valid_getattr(node):
  2109. root = node.root()
  2110. return root.name != "builtins" and getattr(root, "pure_python", None)
  2111. try:
  2112. return _valid_getattr(self.getattr("__getattr__", context)[0])
  2113. except AttributeInferenceError:
  2114. try:
  2115. getattribute = self.getattr("__getattribute__", context)[0]
  2116. return _valid_getattr(getattribute)
  2117. except AttributeInferenceError:
  2118. pass
  2119. return False
  2120. def getitem(self, index, context: InferenceContext | None = None):
  2121. """Return the inference of a subscript.
  2122. This is basically looking up the method in the metaclass and calling it.
  2123. :returns: The inferred value of a subscript to this class.
  2124. :rtype: NodeNG
  2125. :raises AstroidTypeError: If this class does not define a
  2126. ``__getitem__`` method.
  2127. """
  2128. try:
  2129. methods = lookup(self, "__getitem__", context=context)
  2130. except AttributeInferenceError as exc:
  2131. if isinstance(self, ClassDef):
  2132. # subscripting a class definition may be
  2133. # achieved thanks to __class_getitem__ method
  2134. # which is a classmethod defined in the class
  2135. # that supports subscript and not in the metaclass
  2136. try:
  2137. methods = self.getattr("__class_getitem__")
  2138. # Here it is assumed that the __class_getitem__ node is
  2139. # a FunctionDef. One possible improvement would be to deal
  2140. # with more generic inference.
  2141. except AttributeInferenceError:
  2142. raise AstroidTypeError(node=self, context=context) from exc
  2143. else:
  2144. raise AstroidTypeError(node=self, context=context) from exc
  2145. method = methods[0]
  2146. # Create a new callcontext for providing index as an argument.
  2147. new_context = bind_context_to_node(context, self)
  2148. new_context.callcontext = CallContext(args=[index], callee=method)
  2149. try:
  2150. return next(method.infer_call_result(self, new_context), util.Uninferable)
  2151. except AttributeError:
  2152. # Starting with python3.9, builtin types list, dict etc...
  2153. # are subscriptable thanks to __class_getitem___ classmethod.
  2154. # However in such case the method is bound to an EmptyNode and
  2155. # EmptyNode doesn't have infer_call_result method yielding to
  2156. # AttributeError
  2157. if (
  2158. isinstance(method, node_classes.EmptyNode)
  2159. and self.pytype() == "builtins.type"
  2160. ):
  2161. return self
  2162. raise
  2163. except InferenceError:
  2164. return util.Uninferable
  2165. def methods(self):
  2166. """Iterate over all of the method defined in this class and its parents.
  2167. :returns: The methods defined on the class.
  2168. :rtype: iterable(FunctionDef)
  2169. """
  2170. done = {}
  2171. for astroid in itertools.chain(iter((self,)), self.ancestors()):
  2172. for meth in astroid.mymethods():
  2173. if meth.name in done:
  2174. continue
  2175. done[meth.name] = None
  2176. yield meth
  2177. def mymethods(self):
  2178. """Iterate over all of the method defined in this class only.
  2179. :returns: The methods defined on the class.
  2180. :rtype: iterable(FunctionDef)
  2181. """
  2182. for member in self.values():
  2183. if isinstance(member, FunctionDef):
  2184. yield member
  2185. def implicit_metaclass(self):
  2186. """Get the implicit metaclass of the current class.
  2187. This will return an instance of builtins.type.
  2188. :returns: The metaclass.
  2189. :rtype: builtins.type
  2190. """
  2191. return builtin_lookup("type")[1][0]
  2192. def declared_metaclass(
  2193. self, context: InferenceContext | None = None
  2194. ) -> SuccessfulInferenceResult | None:
  2195. """Return the explicit declared metaclass for the current class.
  2196. An explicit declared metaclass is defined
  2197. either by passing the ``metaclass`` keyword argument
  2198. in the class definition line (Python 3) or (Python 2) by
  2199. having a ``__metaclass__`` class attribute, or if there are
  2200. no explicit bases but there is a global ``__metaclass__`` variable.
  2201. :returns: The metaclass of this class,
  2202. or None if one could not be found.
  2203. """
  2204. for base in self.bases:
  2205. try:
  2206. for baseobj in base.infer(context=context):
  2207. if isinstance(baseobj, ClassDef) and baseobj.hide:
  2208. self._metaclass = baseobj._metaclass
  2209. self._metaclass_hack = True
  2210. break
  2211. except InferenceError:
  2212. pass
  2213. if self._metaclass:
  2214. # Expects this from Py3k TreeRebuilder
  2215. try:
  2216. return next(
  2217. node
  2218. for node in self._metaclass.infer(context=context)
  2219. if not isinstance(node, util.UninferableBase)
  2220. )
  2221. except (InferenceError, StopIteration):
  2222. return None
  2223. return None
  2224. def _find_metaclass(
  2225. self, seen: set[ClassDef] | None = None, context: InferenceContext | None = None
  2226. ) -> SuccessfulInferenceResult | None:
  2227. if seen is None:
  2228. seen = set()
  2229. seen.add(self)
  2230. klass = self.declared_metaclass(context=context)
  2231. if klass is None:
  2232. for parent in self.ancestors(context=context):
  2233. if parent not in seen:
  2234. klass = parent._find_metaclass(seen)
  2235. if klass is not None:
  2236. break
  2237. return klass
  2238. def metaclass(
  2239. self, context: InferenceContext | None = None
  2240. ) -> SuccessfulInferenceResult | None:
  2241. """Get the metaclass of this class.
  2242. If this class does not define explicitly a metaclass,
  2243. then the first defined metaclass in ancestors will be used
  2244. instead.
  2245. :returns: The metaclass of this class.
  2246. """
  2247. return self._find_metaclass(context=context)
  2248. def has_metaclass_hack(self) -> bool:
  2249. return self._metaclass_hack
  2250. def _islots(self):
  2251. """Return an iterator with the inferred slots."""
  2252. if "__slots__" not in self.locals:
  2253. return None
  2254. for slots in self.igetattr("__slots__"):
  2255. # check if __slots__ is a valid type
  2256. for meth in ITER_METHODS:
  2257. try:
  2258. slots.getattr(meth)
  2259. break
  2260. except AttributeInferenceError:
  2261. continue
  2262. else:
  2263. continue
  2264. if isinstance(slots, node_classes.Const):
  2265. # a string. Ignore the following checks,
  2266. # but yield the node, only if it has a value
  2267. if slots.value:
  2268. yield slots
  2269. continue
  2270. if not hasattr(slots, "itered"):
  2271. # we can't obtain the values, maybe a .deque?
  2272. continue
  2273. if isinstance(slots, node_classes.Dict):
  2274. values = [item[0] for item in slots.items]
  2275. else:
  2276. values = slots.itered()
  2277. if isinstance(values, util.UninferableBase):
  2278. continue
  2279. if not values:
  2280. # Stop the iteration, because the class
  2281. # has an empty list of slots.
  2282. return values
  2283. for elt in values:
  2284. try:
  2285. for inferred in elt.infer():
  2286. if not (
  2287. isinstance(inferred, node_classes.Const)
  2288. and isinstance(inferred.value, str)
  2289. ):
  2290. continue
  2291. if not inferred.value:
  2292. continue
  2293. yield inferred
  2294. except InferenceError:
  2295. continue
  2296. return None
  2297. def _slots(self):
  2298. slots = self._islots()
  2299. try:
  2300. first = next(slots)
  2301. except StopIteration as exc:
  2302. # The class doesn't have a __slots__ definition or empty slots.
  2303. if exc.args and exc.args[0] not in ("", None):
  2304. return exc.args[0]
  2305. return None
  2306. return [first, *slots]
  2307. # Cached, because inferring them all the time is expensive
  2308. @cached_property
  2309. def _all_slots(self):
  2310. """Get all the slots for this node.
  2311. :returns: The names of slots for this class.
  2312. If the class doesn't define any slot, through the ``__slots__``
  2313. variable, then this function will return a None.
  2314. Also, it will return None in the case the slots were not inferred.
  2315. :rtype: list(str) or None
  2316. """
  2317. def grouped_slots(
  2318. mro: list[ClassDef],
  2319. ) -> Iterator[node_classes.NodeNG | None]:
  2320. for cls in mro:
  2321. # Not interested in object, since it can't have slots.
  2322. if cls.qname() == "builtins.object":
  2323. continue
  2324. try:
  2325. cls_slots = cls._slots()
  2326. except NotImplementedError:
  2327. continue
  2328. if cls_slots is not None:
  2329. yield from cls_slots
  2330. else:
  2331. yield None
  2332. try:
  2333. mro = self.mro()
  2334. except MroError as e:
  2335. raise NotImplementedError(
  2336. "Cannot get slots while parsing mro fails."
  2337. ) from e
  2338. slots = list(grouped_slots(mro))
  2339. if not all(slot is not None for slot in slots):
  2340. return None
  2341. return sorted(set(slots), key=lambda item: item.value)
  2342. def slots(self):
  2343. return self._all_slots
  2344. def _inferred_bases(self, context: InferenceContext | None = None):
  2345. # Similar with .ancestors, but the difference is when one base is inferred,
  2346. # only the first object is wanted. That's because
  2347. # we aren't interested in superclasses, as in the following
  2348. # example:
  2349. #
  2350. # class SomeSuperClass(object): pass
  2351. # class SomeClass(SomeSuperClass): pass
  2352. # class Test(SomeClass): pass
  2353. #
  2354. # Inferring SomeClass from the Test's bases will give
  2355. # us both SomeClass and SomeSuperClass, but we are interested
  2356. # only in SomeClass.
  2357. if context is None:
  2358. context = InferenceContext()
  2359. if not self.bases and self.qname() != "builtins.object":
  2360. yield builtin_lookup("object")[1][0]
  2361. return
  2362. for stmt in self.bases:
  2363. try:
  2364. baseobj = _infer_last(stmt, context)
  2365. except InferenceError:
  2366. continue
  2367. if isinstance(baseobj, bases.Instance):
  2368. baseobj = baseobj._proxied
  2369. if not isinstance(baseobj, ClassDef):
  2370. continue
  2371. if not baseobj.hide:
  2372. yield baseobj
  2373. else:
  2374. yield from baseobj.bases
  2375. def _compute_mro(self, context: InferenceContext | None = None):
  2376. if self.qname() == "builtins.object":
  2377. return [self]
  2378. inferred_bases = list(self._inferred_bases(context=context))
  2379. bases_mro = []
  2380. for base in inferred_bases:
  2381. if base is self:
  2382. continue
  2383. mro = base._compute_mro(context=context)
  2384. bases_mro.append(mro)
  2385. unmerged_mro: list[list[ClassDef]] = [[self], *bases_mro, inferred_bases]
  2386. unmerged_mro = clean_duplicates_mro(unmerged_mro, self, context)
  2387. clean_typing_generic_mro(unmerged_mro)
  2388. return _c3_merge(unmerged_mro, self, context)
  2389. def mro(self, context: InferenceContext | None = None) -> list[ClassDef]:
  2390. """Get the method resolution order, using C3 linearization.
  2391. :returns: The list of ancestors, sorted by the mro.
  2392. :rtype: list(NodeNG)
  2393. :raises DuplicateBasesError: Duplicate bases in the same class base
  2394. :raises InconsistentMroError: A class' MRO is inconsistent
  2395. """
  2396. return self._compute_mro(context=context)
  2397. def bool_value(self, context: InferenceContext | None = None) -> Literal[True]:
  2398. """Determine the boolean value of this node.
  2399. :returns: The boolean value of this node.
  2400. For a :class:`ClassDef` this is always ``True``.
  2401. """
  2402. return True
  2403. def get_children(self):
  2404. if self.decorators is not None:
  2405. yield self.decorators
  2406. yield from self.bases
  2407. if self.keywords is not None:
  2408. yield from self.keywords
  2409. yield from self.type_params
  2410. yield from self.body
  2411. @cached_property
  2412. def _assign_nodes_in_scope(self):
  2413. children_assign_nodes = (
  2414. child_node._assign_nodes_in_scope for child_node in self.body
  2415. )
  2416. return list(itertools.chain.from_iterable(children_assign_nodes))
  2417. def frame(self, *, future: Literal[None, True] = None) -> Self:
  2418. """The node's frame node.
  2419. A frame node is a :class:`Module`, :class:`FunctionDef`,
  2420. :class:`ClassDef` or :class:`Lambda`.
  2421. :returns: The node itself.
  2422. """
  2423. return self
  2424. def _infer(
  2425. self, context: InferenceContext | None = None, **kwargs: Any
  2426. ) -> Generator[ClassDef]:
  2427. yield self