1# Copyright (c) 2006-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr> 2# Copyright (c) 2010 Daniel Harding <dharding@gmail.com> 3# Copyright (c) 2011, 2013-2015 Google, Inc. 4# Copyright (c) 2013-2020 Claudiu Popa <pcmanticore@gmail.com> 5# Copyright (c) 2013 Phil Schaf <flying-sheep@web.de> 6# Copyright (c) 2014 Eevee (Alex Munroe) <amunroe@yelp.com> 7# Copyright (c) 2015-2016 Florian Bruhin <me@the-compiler.org> 8# Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com> 9# Copyright (c) 2015 Rene Zhang <rz99@cornell.edu> 10# Copyright (c) 2015 Philip Lorenz <philip@bithub.de> 11# Copyright (c) 2016-2017 Derek Gustafson <degustaf@gmail.com> 12# Copyright (c) 2017-2018 Bryce Guinta <bryce.paul.guinta@gmail.com> 13# Copyright (c) 2017-2018 Ashley Whetter <ashley@awhetter.co.uk> 14# Copyright (c) 2017 Łukasz Rogalski <rogalski.91@gmail.com> 15# Copyright (c) 2017 David Euresti <david@dropbox.com> 16# Copyright (c) 2018-2019 Nick Drozd <nicholasdrozd@gmail.com> 17# Copyright (c) 2018 Ville Skyttä <ville.skytta@iki.fi> 18# Copyright (c) 2018 Anthony Sottile <asottile@umich.edu> 19# Copyright (c) 2018 HoverHell <hoverhell@gmail.com> 20# Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com> 21# Copyright (c) 2019 Peter de Blanc <peter@standard.ai> 22# Copyright (c) 2020-2021 hippo91 <guillaume.peillex@gmail.com> 23# Copyright (c) 2020 Peter Kolbus <peter.kolbus@gmail.com> 24# Copyright (c) 2020 Tim Martin <tim@asymptotic.co.uk> 25# Copyright (c) 2020 Ram Rachum <ram@rachum.com> 26# Copyright (c) 2021 Marc Mueller <30130371+cdce8p@users.noreply.github.com> 27# Copyright (c) 2021 Daniël van Noord <13665637+DanielNoord@users.noreply.github.com> 28# Copyright (c) 2021 Pierre Sassoulas <pierre.sassoulas@gmail.com> 29# Copyright (c) 2021 David Liu <david@cs.toronto.edu> 30# Copyright (c) 2021 pre-commit-ci[bot] <bot@noreply.github.com> 31# Copyright (c) 2021 doranid <ddandd@gmail.com> 32# Copyright (c) 2021 Andrew Haigh <hello@nelf.in> 33 34# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html 35# For details: https://github.com/PyCQA/astroid/blob/main/LICENSE 36 37 38""" 39This module contains the classes for "scoped" node, i.e. which are opening a 40new local scope in the language definition : Module, ClassDef, FunctionDef (and 41Lambda, GeneratorExp, DictComp and SetComp to some extent). 42""" 43import builtins 44import io 45import itertools 46import os 47import sys 48import typing 49import warnings 50from typing import List, Optional, TypeVar, Union, overload 51 52from astroid import bases 53from astroid import decorators as decorators_mod 54from astroid import mixins, util 55from astroid.const import PY39_PLUS 56from astroid.context import ( 57 CallContext, 58 InferenceContext, 59 bind_context_to_node, 60 copy_context, 61) 62from astroid.exceptions import ( 63 AstroidBuildingError, 64 AstroidTypeError, 65 AttributeInferenceError, 66 DuplicateBasesError, 67 InconsistentMroError, 68 InferenceError, 69 MroError, 70 StatementMissing, 71 TooManyLevelsError, 72) 73from astroid.interpreter.dunder_lookup import lookup 74from astroid.interpreter.objectmodel import ClassModel, FunctionModel, ModuleModel 75from astroid.manager import AstroidManager 76from astroid.nodes import Arguments, Const, node_classes 77 78if sys.version_info >= (3, 6, 2): 79 from typing import NoReturn 80else: 81 from typing_extensions import NoReturn 82 83 84if sys.version_info >= (3, 8): 85 from typing import Literal 86else: 87 from typing_extensions import Literal 88 89 90ITER_METHODS = ("__iter__", "__getitem__") 91EXCEPTION_BASE_CLASSES = frozenset({"Exception", "BaseException"}) 92objects = util.lazy_import("objects") 93BUILTIN_DESCRIPTORS = frozenset( 94 {"classmethod", "staticmethod", "builtins.classmethod", "builtins.staticmethod"} 95) 96 97T = TypeVar("T") 98 99 100def _c3_merge(sequences, cls, context): 101 """Merges MROs in *sequences* to a single MRO using the C3 algorithm. 102 103 Adapted from http://www.python.org/download/releases/2.3/mro/. 104 105 """ 106 result = [] 107 while True: 108 sequences = [s for s in sequences if s] # purge empty sequences 109 if not sequences: 110 return result 111 for s1 in sequences: # find merge candidates among seq heads 112 candidate = s1[0] 113 for s2 in sequences: 114 if candidate in s2[1:]: 115 candidate = None 116 break # reject the current head, it appears later 117 else: 118 break 119 if not candidate: 120 # Show all the remaining bases, which were considered as 121 # candidates for the next mro sequence. 122 raise InconsistentMroError( 123 message="Cannot create a consistent method resolution order " 124 "for MROs {mros} of class {cls!r}.", 125 mros=sequences, 126 cls=cls, 127 context=context, 128 ) 129 130 result.append(candidate) 131 # remove the chosen candidate 132 for seq in sequences: 133 if seq[0] == candidate: 134 del seq[0] 135 return None 136 137 138def clean_typing_generic_mro(sequences: List[List["ClassDef"]]) -> None: 139 """A class can inherit from typing.Generic directly, as base, 140 and as base of bases. The merged MRO must however only contain the last entry. 141 To prepare for _c3_merge, remove some typing.Generic entries from 142 sequences if multiple are present. 143 144 This method will check if Generic is in inferred_bases and also 145 part of bases_mro. If true, remove it from inferred_bases 146 as well as its entry the bases_mro. 147 148 Format sequences: [[self]] + bases_mro + [inferred_bases] 149 """ 150 bases_mro = sequences[1:-1] 151 inferred_bases = sequences[-1] 152 # Check if Generic is part of inferred_bases 153 for i, base in enumerate(inferred_bases): 154 if base.qname() == "typing.Generic": 155 position_in_inferred_bases = i 156 break 157 else: 158 return 159 # Check if also part of bases_mro 160 # Ignore entry for typing.Generic 161 for i, seq in enumerate(bases_mro): 162 if i == position_in_inferred_bases: 163 continue 164 if any(base.qname() == "typing.Generic" for base in seq): 165 break 166 else: 167 return 168 # Found multiple Generics in mro, remove entry from inferred_bases 169 # and the corresponding one from bases_mro 170 inferred_bases.pop(position_in_inferred_bases) 171 bases_mro.pop(position_in_inferred_bases) 172 173 174def clean_duplicates_mro(sequences, cls, context): 175 for sequence in sequences: 176 names = [ 177 (node.lineno, node.qname()) if node.name else None for node in sequence 178 ] 179 last_index = dict(map(reversed, enumerate(names))) 180 if names and names[0] is not None and last_index[names[0]] != 0: 181 raise DuplicateBasesError( 182 message="Duplicates found in MROs {mros} for {cls!r}.", 183 mros=sequences, 184 cls=cls, 185 context=context, 186 ) 187 yield [ 188 node 189 for i, (node, name) in enumerate(zip(sequence, names)) 190 if name is None or last_index[name] == i 191 ] 192 193 194def function_to_method(n, klass): 195 if isinstance(n, FunctionDef): 196 if n.type == "classmethod": 197 return bases.BoundMethod(n, klass) 198 if n.type == "property": 199 return n 200 if n.type != "staticmethod": 201 return bases.UnboundMethod(n) 202 return n 203 204 205def builtin_lookup(name): 206 """lookup a name into the builtin module 207 return the list of matching statements and the astroid for the builtin 208 module 209 """ 210 builtin_astroid = AstroidManager().ast_from_module(builtins) 211 if name == "__dict__": 212 return builtin_astroid, () 213 try: 214 stmts = builtin_astroid.locals[name] 215 except KeyError: 216 stmts = () 217 return builtin_astroid, stmts 218 219 220# TODO move this Mixin to mixins.py; problem: 'FunctionDef' in _scope_lookup 221class LocalsDictNodeNG(node_classes.LookupMixIn, node_classes.NodeNG): 222 """this class provides locals handling common to Module, FunctionDef 223 and ClassDef nodes, including a dict like interface for direct access 224 to locals information 225 """ 226 227 # attributes below are set by the builder module or by raw factories 228 229 locals = {} 230 """A map of the name of a local variable to the node defining the local. 231 232 :type: dict(str, NodeNG) 233 """ 234 235 def qname(self): 236 """Get the 'qualified' name of the node. 237 238 For example: module.name, module.class.name ... 239 240 :returns: The qualified name. 241 :rtype: str 242 """ 243 # pylint: disable=no-member; github.com/pycqa/astroid/issues/278 244 if self.parent is None: 245 return self.name 246 return f"{self.parent.frame().qname()}.{self.name}" 247 248 def scope(self: T) -> T: 249 """The first parent node defining a new scope. 250 251 :returns: The first parent scope node. 252 :rtype: Module or FunctionDef or ClassDef or Lambda or GenExpr 253 """ 254 return self 255 256 def _scope_lookup(self, node, name, offset=0): 257 """XXX method for interfacing the scope lookup""" 258 try: 259 stmts = node._filter_stmts(self.locals[name], self, offset) 260 except KeyError: 261 stmts = () 262 if stmts: 263 return self, stmts 264 265 # Handle nested scopes: since class names do not extend to nested 266 # scopes (e.g., methods), we find the next enclosing non-class scope 267 pscope = self.parent and self.parent.scope() 268 while pscope is not None: 269 if not isinstance(pscope, ClassDef): 270 return pscope.scope_lookup(node, name) 271 pscope = pscope.parent and pscope.parent.scope() 272 273 # self is at the top level of a module, or is enclosed only by ClassDefs 274 return builtin_lookup(name) 275 276 def set_local(self, name, stmt): 277 """Define that the given name is declared in the given statement node. 278 279 .. seealso:: :meth:`scope` 280 281 :param name: The name that is being defined. 282 :type name: str 283 284 :param stmt: The statement that defines the given name. 285 :type stmt: NodeNG 286 """ 287 # assert not stmt in self.locals.get(name, ()), (self, stmt) 288 self.locals.setdefault(name, []).append(stmt) 289 290 __setitem__ = set_local 291 292 def _append_node(self, child): 293 """append a child, linking it in the tree""" 294 # pylint: disable=no-member; depending by the class 295 # which uses the current class as a mixin or base class. 296 # It's rewritten in 2.0, so it makes no sense for now 297 # to spend development time on it. 298 self.body.append(child) 299 child.parent = self 300 301 def add_local_node(self, child_node, name=None): 302 """Append a child that should alter the locals of this scope node. 303 304 :param child_node: The child node that will alter locals. 305 :type child_node: NodeNG 306 307 :param name: The name of the local that will be altered by 308 the given child node. 309 :type name: str or None 310 """ 311 if name != "__class__": 312 # add __class__ node as a child will cause infinite recursion later! 313 self._append_node(child_node) 314 self.set_local(name or child_node.name, child_node) 315 316 def __getitem__(self, item): 317 """The first node the defines the given local. 318 319 :param item: The name of the locally defined object. 320 :type item: str 321 322 :raises KeyError: If the name is not defined. 323 """ 324 return self.locals[item][0] 325 326 def __iter__(self): 327 """Iterate over the names of locals defined in this scoped node. 328 329 :returns: The names of the defined locals. 330 :rtype: iterable(str) 331 """ 332 return iter(self.keys()) 333 334 def keys(self): 335 """The names of locals defined in this scoped node. 336 337 :returns: The names of the defined locals. 338 :rtype: list(str) 339 """ 340 return list(self.locals.keys()) 341 342 def values(self): 343 """The nodes that define the locals in this scoped node. 344 345 :returns: The nodes that define locals. 346 :rtype: list(NodeNG) 347 """ 348 # pylint: disable=consider-using-dict-items 349 # It look like this class override items/keys/values, 350 # probably not worth the headache 351 return [self[key] for key in self.keys()] 352 353 def items(self): 354 """Get the names of the locals and the node that defines the local. 355 356 :returns: The names of locals and their associated node. 357 :rtype: list(tuple(str, NodeNG)) 358 """ 359 return list(zip(self.keys(), self.values())) 360 361 def __contains__(self, name): 362 """Check if a local is defined in this scope. 363 364 :param name: The name of the local to check for. 365 :type name: str 366 367 :returns: True if this node has a local of the given name, 368 False otherwise. 369 :rtype: bool 370 """ 371 return name in self.locals 372 373 374class Module(LocalsDictNodeNG): 375 """Class representing an :class:`ast.Module` node. 376 377 >>> import astroid 378 >>> node = astroid.extract_node('import astroid') 379 >>> node 380 <Import l.1 at 0x7f23b2e4e5c0> 381 >>> node.parent 382 <Module l.0 at 0x7f23b2e4eda0> 383 """ 384 385 _astroid_fields = ("body",) 386 387 fromlineno = 0 388 """The first line that this node appears on in the source code. 389 390 :type: int or None 391 """ 392 lineno = 0 393 """The line that this node appears on in the source code. 394 395 :type: int or None 396 """ 397 398 # attributes below are set by the builder module or by raw factories 399 400 file = None 401 """The path to the file that this ast has been extracted from. 402 403 This will be ``None`` when the representation has been built from a 404 built-in module. 405 406 :type: str or None 407 """ 408 file_bytes = None 409 """The string/bytes that this ast was built from. 410 411 :type: str or bytes or None 412 """ 413 file_encoding = None 414 """The encoding of the source file. 415 416 This is used to get unicode out of a source file. 417 Python 2 only. 418 419 :type: str or None 420 """ 421 name = None 422 """The name of the module. 423 424 :type: str or None 425 """ 426 pure_python = None 427 """Whether the ast was built from source. 428 429 :type: bool or None 430 """ 431 package = None 432 """Whether the node represents a package or a module. 433 434 :type: bool or None 435 """ 436 globals = None 437 """A map of the name of a global variable to the node defining the global. 438 439 :type: dict(str, NodeNG) 440 """ 441 442 # Future imports 443 future_imports = None 444 """The imports from ``__future__``. 445 446 :type: set(str) or None 447 """ 448 special_attributes = ModuleModel() 449 """The names of special attributes that this module has. 450 451 :type: objectmodel.ModuleModel 452 """ 453 454 # names of module attributes available through the global scope 455 scope_attrs = {"__name__", "__doc__", "__file__", "__path__", "__package__"} 456 """The names of module attributes available through the global scope. 457 458 :type: str(str) 459 """ 460 461 _other_fields = ( 462 "name", 463 "doc", 464 "file", 465 "path", 466 "package", 467 "pure_python", 468 "future_imports", 469 ) 470 _other_other_fields = ("locals", "globals") 471 472 lineno: None 473 col_offset: None 474 end_lineno: None 475 end_col_offset: None 476 parent: None 477 478 def __init__( 479 self, 480 name, 481 doc, 482 file=None, 483 path: Optional[List[str]] = None, 484 package=None, 485 parent=None, 486 pure_python=True, 487 ): 488 """ 489 :param name: The name of the module. 490 :type name: str 491 492 :param doc: The module docstring. 493 :type doc: str 494 495 :param file: The path to the file that this ast has been extracted from. 496 :type file: str or None 497 498 :param path: 499 :type path: Optional[List[str]] 500 501 :param package: Whether the node represents a package or a module. 502 :type package: bool or None 503 504 :param parent: The parent node in the syntax tree. 505 :type parent: NodeNG or None 506 507 :param pure_python: Whether the ast was built from source. 508 :type pure_python: bool or None 509 """ 510 self.name = name 511 self.doc = doc 512 self.file = file 513 self.path = path 514 self.package = package 515 self.parent = parent 516 self.pure_python = pure_python 517 self.locals = self.globals = {} 518 """A map of the name of a local variable to the node defining the local. 519 520 :type: dict(str, NodeNG) 521 """ 522 self.body = [] 523 """The contents of the module. 524 525 :type: list(NodeNG) or None 526 """ 527 self.future_imports = set() 528 529 # pylint: enable=redefined-builtin 530 531 def postinit(self, body=None): 532 """Do some setup after initialisation. 533 534 :param body: The contents of the module. 535 :type body: list(NodeNG) or None 536 """ 537 self.body = body 538 539 def _get_stream(self): 540 if self.file_bytes is not None: 541 return io.BytesIO(self.file_bytes) 542 if self.file is not None: 543 # pylint: disable=consider-using-with 544 stream = open(self.file, "rb") 545 return stream 546 return None 547 548 def stream(self): 549 """Get a stream to the underlying file or bytes. 550 551 :type: file or io.BytesIO or None 552 """ 553 return self._get_stream() 554 555 def block_range(self, lineno): 556 """Get a range from where this node starts to where this node ends. 557 558 :param lineno: Unused. 559 :type lineno: int 560 561 :returns: The range of line numbers that this node belongs to. 562 :rtype: tuple(int, int) 563 """ 564 return self.fromlineno, self.tolineno 565 566 def scope_lookup(self, node, name, offset=0): 567 """Lookup where the given variable is assigned. 568 569 :param node: The node to look for assignments up to. 570 Any assignments after the given node are ignored. 571 :type node: NodeNG 572 573 :param name: The name of the variable to find assignments for. 574 :type name: str 575 576 :param offset: The line offset to filter statements up to. 577 :type offset: int 578 579 :returns: This scope node and the list of assignments associated to the 580 given name according to the scope where it has been found (locals, 581 globals or builtin). 582 :rtype: tuple(str, list(NodeNG)) 583 """ 584 if name in self.scope_attrs and name not in self.locals: 585 try: 586 return self, self.getattr(name) 587 except AttributeInferenceError: 588 return self, () 589 return self._scope_lookup(node, name, offset) 590 591 def pytype(self): 592 """Get the name of the type that this node represents. 593 594 :returns: The name of the type. 595 :rtype: str 596 """ 597 return "builtins.module" 598 599 def display_type(self): 600 """A human readable type of this node. 601 602 :returns: The type of this node. 603 :rtype: str 604 """ 605 return "Module" 606 607 def getattr(self, name, context=None, ignore_locals=False): 608 if not name: 609 raise AttributeInferenceError(target=self, attribute=name, context=context) 610 611 result = [] 612 name_in_locals = name in self.locals 613 614 if name in self.special_attributes and not ignore_locals and not name_in_locals: 615 result = [self.special_attributes.lookup(name)] 616 elif not ignore_locals and name_in_locals: 617 result = self.locals[name] 618 elif self.package: 619 try: 620 result = [self.import_module(name, relative_only=True)] 621 except (AstroidBuildingError, SyntaxError) as exc: 622 raise AttributeInferenceError( 623 target=self, attribute=name, context=context 624 ) from exc 625 result = [n for n in result if not isinstance(n, node_classes.DelName)] 626 if result: 627 return result 628 raise AttributeInferenceError(target=self, attribute=name, context=context) 629 630 def igetattr(self, name, context=None): 631 """Infer the possible values of the given variable. 632 633 :param name: The name of the variable to infer. 634 :type name: str 635 636 :returns: The inferred possible values. 637 :rtype: iterable(NodeNG) or None 638 """ 639 # set lookup name since this is necessary to infer on import nodes for 640 # instance 641 context = copy_context(context) 642 context.lookupname = name 643 try: 644 return bases._infer_stmts(self.getattr(name, context), context, frame=self) 645 except AttributeInferenceError as error: 646 raise InferenceError( 647 str(error), target=self, attribute=name, context=context 648 ) from error 649 650 def fully_defined(self): 651 """Check if this module has been build from a .py file. 652 653 If so, the module contains a complete representation, 654 including the code. 655 656 :returns: True if the module has been built from a .py file. 657 :rtype: bool 658 """ 659 return self.file is not None and self.file.endswith(".py") 660 661 @overload 662 def statement(self, *, future: Literal[None] = ...) -> "Module": 663 ... 664 665 @overload 666 def statement(self, *, future: Literal[True]) -> NoReturn: 667 ... 668 669 def statement( 670 self, *, future: Literal[None, True] = None 671 ) -> Union["NoReturn", "Module"]: 672 """The first parent node, including self, marked as statement node. 673 674 When called on a :class:`Module` with the future parameter this raises an error. 675 676 TODO: Deprecate the future parameter and only raise StatementMissing 677 678 :raises StatementMissing: If no self has no parent attribute and future is True 679 """ 680 if future: 681 raise StatementMissing(target=self) 682 warnings.warn( 683 "In astroid 3.0.0 NodeNG.statement() will return either a nodes.Statement " 684 "or raise a StatementMissing exception. nodes.Module will no longer be " 685 "considered a statement. This behaviour can already be triggered " 686 "by passing 'future=True' to a statement() call.", 687 DeprecationWarning, 688 ) 689 return self 690 691 def previous_sibling(self): 692 """The previous sibling statement. 693 694 :returns: The previous sibling statement node. 695 :rtype: NodeNG or None 696 """ 697 698 def next_sibling(self): 699 """The next sibling statement node. 700 701 :returns: The next sibling statement node. 702 :rtype: NodeNG or None 703 """ 704 705 _absolute_import_activated = True 706 707 def absolute_import_activated(self): 708 """Whether :pep:`328` absolute import behaviour has been enabled. 709 710 :returns: True if :pep:`328` has been enabled, False otherwise. 711 :rtype: bool 712 """ 713 return self._absolute_import_activated 714 715 def import_module(self, modname, relative_only=False, level=None): 716 """Get the ast for a given module as if imported from this module. 717 718 :param modname: The name of the module to "import". 719 :type modname: str 720 721 :param relative_only: Whether to only consider relative imports. 722 :type relative_only: bool 723 724 :param level: The level of relative import. 725 :type level: int or None 726 727 :returns: The imported module ast. 728 :rtype: NodeNG 729 """ 730 if relative_only and level is None: 731 level = 0 732 absmodname = self.relative_to_absolute_name(modname, level) 733 734 try: 735 return AstroidManager().ast_from_module_name(absmodname) 736 except AstroidBuildingError: 737 # we only want to import a sub module or package of this module, 738 # skip here 739 if relative_only: 740 raise 741 return AstroidManager().ast_from_module_name(modname) 742 743 def relative_to_absolute_name(self, modname: str, level: int) -> str: 744 """Get the absolute module name for a relative import. 745 746 The relative import can be implicit or explicit. 747 748 :param modname: The module name to convert. 749 750 :param level: The level of relative import. 751 752 :returns: The absolute module name. 753 754 :raises TooManyLevelsError: When the relative import refers to a 755 module too far above this one. 756 """ 757 # XXX this returns non sens when called on an absolute import 758 # like 'pylint.checkers.astroid.utils' 759 # XXX doesn't return absolute name if self.name isn't absolute name 760 if self.absolute_import_activated() and level is None: 761 return modname 762 if level: 763 if self.package: 764 level = level - 1 765 package_name = self.name.rsplit(".", level)[0] 766 elif ( 767 self.path 768 and not os.path.exists(os.path.dirname(self.path[0]) + "/__init__.py") 769 and os.path.exists( 770 os.path.dirname(self.path[0]) + "/" + modname.split(".")[0] 771 ) 772 ): 773 level = level - 1 774 package_name = "" 775 else: 776 package_name = self.name.rsplit(".", level)[0] 777 if level and self.name.count(".") < level: 778 raise TooManyLevelsError(level=level, name=self.name) 779 780 elif self.package: 781 package_name = self.name 782 else: 783 package_name = self.name.rsplit(".", 1)[0] 784 785 if package_name: 786 if not modname: 787 return package_name 788 return f"{package_name}.{modname}" 789 return modname 790 791 def wildcard_import_names(self): 792 """The list of imported names when this module is 'wildcard imported'. 793 794 It doesn't include the '__builtins__' name which is added by the 795 current CPython implementation of wildcard imports. 796 797 :returns: The list of imported names. 798 :rtype: list(str) 799 """ 800 # We separate the different steps of lookup in try/excepts 801 # to avoid catching too many Exceptions 802 default = [name for name in self.keys() if not name.startswith("_")] 803 try: 804 all_values = self["__all__"] 805 except KeyError: 806 return default 807 808 try: 809 explicit = next(all_values.assigned_stmts()) 810 except (InferenceError, StopIteration): 811 return default 812 except AttributeError: 813 # not an assignment node 814 # XXX infer? 815 return default 816 817 # Try our best to detect the exported name. 818 inferred = [] 819 try: 820 explicit = next(explicit.infer()) 821 except (InferenceError, StopIteration): 822 return default 823 if not isinstance(explicit, (node_classes.Tuple, node_classes.List)): 824 return default 825 826 def str_const(node): 827 return isinstance(node, node_classes.Const) and isinstance(node.value, str) 828 829 for node in explicit.elts: 830 if str_const(node): 831 inferred.append(node.value) 832 else: 833 try: 834 inferred_node = next(node.infer()) 835 except (InferenceError, StopIteration): 836 continue 837 if str_const(inferred_node): 838 inferred.append(inferred_node.value) 839 return inferred 840 841 def public_names(self): 842 """The list of the names that are publicly available in this module. 843 844 :returns: The list of publc names. 845 :rtype: list(str) 846 """ 847 return [name for name in self.keys() if not name.startswith("_")] 848 849 def bool_value(self, context=None): 850 """Determine the boolean value of this node. 851 852 :returns: The boolean value of this node. 853 For a :class:`Module` this is always ``True``. 854 :rtype: bool 855 """ 856 return True 857 858 def get_children(self): 859 yield from self.body 860 861 def frame(self: T) -> T: 862 """The node's frame node. 863 864 A frame node is a :class:`Module`, :class:`FunctionDef`, 865 :class:`ClassDef` or :class:`Lambda`. 866 867 :returns: The node itself. 868 """ 869 return self 870 871 872class ComprehensionScope(LocalsDictNodeNG): 873 """Scoping for different types of comprehensions.""" 874 875 scope_lookup = LocalsDictNodeNG._scope_lookup 876 877 878class GeneratorExp(ComprehensionScope): 879 """Class representing an :class:`ast.GeneratorExp` node. 880 881 >>> import astroid 882 >>> node = astroid.extract_node('(thing for thing in things if thing)') 883 >>> node 884 <GeneratorExp l.1 at 0x7f23b2e4e400> 885 """ 886 887 _astroid_fields = ("elt", "generators") 888 _other_other_fields = ("locals",) 889 elt = None 890 """The element that forms the output of the expression. 891 892 :type: NodeNG or None 893 """ 894 generators = None 895 """The generators that are looped through. 896 897 :type: list(Comprehension) or None 898 """ 899 900 def __init__( 901 self, 902 lineno=None, 903 col_offset=None, 904 parent=None, 905 *, 906 end_lineno=None, 907 end_col_offset=None, 908 ): 909 """ 910 :param lineno: The line that this node appears on in the source code. 911 :type lineno: int or None 912 913 :param col_offset: The column that this node appears on in the 914 source code. 915 :type col_offset: int or None 916 917 :param parent: The parent node in the syntax tree. 918 :type parent: NodeNG or None 919 920 :param end_lineno: The last line this node appears on in the source code. 921 :type end_lineno: Optional[int] 922 923 :param end_col_offset: The end column this node appears on in the 924 source code. Note: This is after the last symbol. 925 :type end_col_offset: Optional[int] 926 """ 927 self.locals = {} 928 """A map of the name of a local variable to the node defining the local. 929 930 :type: dict(str, NodeNG) 931 """ 932 933 super().__init__( 934 lineno=lineno, 935 col_offset=col_offset, 936 end_lineno=end_lineno, 937 end_col_offset=end_col_offset, 938 parent=parent, 939 ) 940 941 def postinit(self, elt=None, generators=None): 942 """Do some setup after initialisation. 943 944 :param elt: The element that forms the output of the expression. 945 :type elt: NodeNG or None 946 947 :param generators: The generators that are looped through. 948 :type generators: list(Comprehension) or None 949 """ 950 self.elt = elt 951 if generators is None: 952 self.generators = [] 953 else: 954 self.generators = generators 955 956 def bool_value(self, context=None): 957 """Determine the boolean value of this node. 958 959 :returns: The boolean value of this node. 960 For a :class:`GeneratorExp` this is always ``True``. 961 :rtype: bool 962 """ 963 return True 964 965 def get_children(self): 966 yield self.elt 967 968 yield from self.generators 969 970 971class DictComp(ComprehensionScope): 972 """Class representing an :class:`ast.DictComp` node. 973 974 >>> import astroid 975 >>> node = astroid.extract_node('{k:v for k, v in things if k > v}') 976 >>> node 977 <DictComp l.1 at 0x7f23b2e41d68> 978 """ 979 980 _astroid_fields = ("key", "value", "generators") 981 _other_other_fields = ("locals",) 982 key = None 983 """What produces the keys. 984 985 :type: NodeNG or None 986 """ 987 value = None 988 """What produces the values. 989 990 :type: NodeNG or None 991 """ 992 generators = None 993 """The generators that are looped through. 994 995 :type: list(Comprehension) or None 996 """ 997 998 def __init__( 999 self, 1000 lineno=None, 1001 col_offset=None, 1002 parent=None, 1003 *, 1004 end_lineno=None, 1005 end_col_offset=None, 1006 ): 1007 """ 1008 :param lineno: The line that this node appears on in the source code. 1009 :type lineno: int or None 1010 1011 :param col_offset: The column that this node appears on in the 1012 source code. 1013 :type col_offset: int or None 1014 1015 :param parent: The parent node in the syntax tree. 1016 :type parent: NodeNG or None 1017 1018 :param end_lineno: The last line this node appears on in the source code. 1019 :type end_lineno: Optional[int] 1020 1021 :param end_col_offset: The end column this node appears on in the 1022 source code. Note: This is after the last symbol. 1023 :type end_col_offset: Optional[int] 1024 """ 1025 self.locals = {} 1026 """A map of the name of a local variable to the node defining the local. 1027 1028 :type: dict(str, NodeNG) 1029 """ 1030 1031 super().__init__( 1032 lineno=lineno, 1033 col_offset=col_offset, 1034 end_lineno=end_lineno, 1035 end_col_offset=end_col_offset, 1036 parent=parent, 1037 ) 1038 1039 def postinit(self, key=None, value=None, generators=None): 1040 """Do some setup after initialisation. 1041 1042 :param key: What produces the keys. 1043 :type key: NodeNG or None 1044 1045 :param value: What produces the values. 1046 :type value: NodeNG or None 1047 1048 :param generators: The generators that are looped through. 1049 :type generators: list(Comprehension) or None 1050 """ 1051 self.key = key 1052 self.value = value 1053 if generators is None: 1054 self.generators = [] 1055 else: 1056 self.generators = generators 1057 1058 def bool_value(self, context=None): 1059 """Determine the boolean value of this node. 1060 1061 :returns: The boolean value of this node. 1062 For a :class:`DictComp` this is always :class:`Uninferable`. 1063 :rtype: Uninferable 1064 """ 1065 return util.Uninferable 1066 1067 def get_children(self): 1068 yield self.key 1069 yield self.value 1070 1071 yield from self.generators 1072 1073 1074class SetComp(ComprehensionScope): 1075 """Class representing an :class:`ast.SetComp` node. 1076 1077 >>> import astroid 1078 >>> node = astroid.extract_node('{thing for thing in things if thing}') 1079 >>> node 1080 <SetComp l.1 at 0x7f23b2e41898> 1081 """ 1082 1083 _astroid_fields = ("elt", "generators") 1084 _other_other_fields = ("locals",) 1085 elt = None 1086 """The element that forms the output of the expression. 1087 1088 :type: NodeNG or None 1089 """ 1090 generators = None 1091 """The generators that are looped through. 1092 1093 :type: list(Comprehension) or None 1094 """ 1095 1096 def __init__( 1097 self, 1098 lineno=None, 1099 col_offset=None, 1100 parent=None, 1101 *, 1102 end_lineno=None, 1103 end_col_offset=None, 1104 ): 1105 """ 1106 :param lineno: The line that this node appears on in the source code. 1107 :type lineno: int or None 1108 1109 :param col_offset: The column that this node appears on in the 1110 source code. 1111 :type col_offset: int or None 1112 1113 :param parent: The parent node in the syntax tree. 1114 :type parent: NodeNG or None 1115 1116 :param end_lineno: The last line this node appears on in the source code. 1117 :type end_lineno: Optional[int] 1118 1119 :param end_col_offset: The end column this node appears on in the 1120 source code. Note: This is after the last symbol. 1121 :type end_col_offset: Optional[int] 1122 """ 1123 self.locals = {} 1124 """A map of the name of a local variable to the node defining the local. 1125 1126 :type: dict(str, NodeNG) 1127 """ 1128 1129 super().__init__( 1130 lineno=lineno, 1131 col_offset=col_offset, 1132 end_lineno=end_lineno, 1133 end_col_offset=end_col_offset, 1134 parent=parent, 1135 ) 1136 1137 def postinit(self, elt=None, generators=None): 1138 """Do some setup after initialisation. 1139 1140 :param elt: The element that forms the output of the expression. 1141 :type elt: NodeNG or None 1142 1143 :param generators: The generators that are looped through. 1144 :type generators: list(Comprehension) or None 1145 """ 1146 self.elt = elt 1147 if generators is None: 1148 self.generators = [] 1149 else: 1150 self.generators = generators 1151 1152 def bool_value(self, context=None): 1153 """Determine the boolean value of this node. 1154 1155 :returns: The boolean value of this node. 1156 For a :class:`SetComp` this is always :class:`Uninferable`. 1157 :rtype: Uninferable 1158 """ 1159 return util.Uninferable 1160 1161 def get_children(self): 1162 yield self.elt 1163 1164 yield from self.generators 1165 1166 1167class _ListComp(node_classes.NodeNG): 1168 """Class representing an :class:`ast.ListComp` node. 1169 1170 >>> import astroid 1171 >>> node = astroid.extract_node('[thing for thing in things if thing]') 1172 >>> node 1173 <ListComp l.1 at 0x7f23b2e418d0> 1174 """ 1175 1176 _astroid_fields = ("elt", "generators") 1177 elt = None 1178 """The element that forms the output of the expression. 1179 1180 :type: NodeNG or None 1181 """ 1182 generators = None 1183 """The generators that are looped through. 1184 1185 :type: list(Comprehension) or None 1186 """ 1187 1188 def postinit(self, elt=None, generators=None): 1189 """Do some setup after initialisation. 1190 1191 :param elt: The element that forms the output of the expression. 1192 :type elt: NodeNG or None 1193 1194 :param generators: The generators that are looped through. 1195 :type generators: list(Comprehension) or None 1196 """ 1197 self.elt = elt 1198 self.generators = generators 1199 1200 def bool_value(self, context=None): 1201 """Determine the boolean value of this node. 1202 1203 :returns: The boolean value of this node. 1204 For a :class:`ListComp` this is always :class:`Uninferable`. 1205 :rtype: Uninferable 1206 """ 1207 return util.Uninferable 1208 1209 def get_children(self): 1210 yield self.elt 1211 1212 yield from self.generators 1213 1214 1215class ListComp(_ListComp, ComprehensionScope): 1216 """Class representing an :class:`ast.ListComp` node. 1217 1218 >>> import astroid 1219 >>> node = astroid.extract_node('[thing for thing in things if thing]') 1220 >>> node 1221 <ListComp l.1 at 0x7f23b2e418d0> 1222 """ 1223 1224 _other_other_fields = ("locals",) 1225 1226 def __init__( 1227 self, 1228 lineno=None, 1229 col_offset=None, 1230 parent=None, 1231 *, 1232 end_lineno=None, 1233 end_col_offset=None, 1234 ): 1235 self.locals = {} 1236 """A map of the name of a local variable to the node defining it. 1237 1238 :type: dict(str, NodeNG) 1239 """ 1240 1241 super().__init__( 1242 lineno=lineno, 1243 col_offset=col_offset, 1244 end_lineno=end_lineno, 1245 end_col_offset=end_col_offset, 1246 parent=parent, 1247 ) 1248 1249 1250def _infer_decorator_callchain(node): 1251 """Detect decorator call chaining and see if the end result is a 1252 static or a classmethod. 1253 """ 1254 if not isinstance(node, FunctionDef): 1255 return None 1256 if not node.parent: 1257 return None 1258 try: 1259 result = next(node.infer_call_result(node.parent), None) 1260 except InferenceError: 1261 return None 1262 if isinstance(result, bases.Instance): 1263 result = result._proxied 1264 if isinstance(result, ClassDef): 1265 if result.is_subtype_of("builtins.classmethod"): 1266 return "classmethod" 1267 if result.is_subtype_of("builtins.staticmethod"): 1268 return "staticmethod" 1269 if isinstance(result, FunctionDef): 1270 if not result.decorators: 1271 return None 1272 # Determine if this function is decorated with one of the builtin descriptors we want. 1273 for decorator in result.decorators.nodes: 1274 if isinstance(decorator, node_classes.Name): 1275 if decorator.name in BUILTIN_DESCRIPTORS: 1276 return decorator.name 1277 if ( 1278 isinstance(decorator, node_classes.Attribute) 1279 and isinstance(decorator.expr, node_classes.Name) 1280 and decorator.expr.name == "builtins" 1281 and decorator.attrname in BUILTIN_DESCRIPTORS 1282 ): 1283 return decorator.attrname 1284 return None 1285 1286 1287class Lambda(mixins.FilterStmtsMixin, LocalsDictNodeNG): 1288 """Class representing an :class:`ast.Lambda` node. 1289 1290 >>> import astroid 1291 >>> node = astroid.extract_node('lambda arg: arg + 1') 1292 >>> node 1293 <Lambda.<lambda> l.1 at 0x7f23b2e41518> 1294 """ 1295 1296 _astroid_fields = ("args", "body") 1297 _other_other_fields = ("locals",) 1298 name = "<lambda>" 1299 is_lambda = True 1300 1301 def implicit_parameters(self): 1302 return 0 1303 1304 # function's type, 'function' | 'method' | 'staticmethod' | 'classmethod' 1305 @property 1306 def type(self): 1307 """Whether this is a method or function. 1308 1309 :returns: 'method' if this is a method, 'function' otherwise. 1310 :rtype: str 1311 """ 1312 if self.args.arguments and self.args.arguments[0].name == "self": 1313 if isinstance(self.parent.scope(), ClassDef): 1314 return "method" 1315 return "function" 1316 1317 def __init__( 1318 self, 1319 lineno=None, 1320 col_offset=None, 1321 parent=None, 1322 *, 1323 end_lineno=None, 1324 end_col_offset=None, 1325 ): 1326 """ 1327 :param lineno: The line that this node appears on in the source code. 1328 :type lineno: int or None 1329 1330 :param col_offset: The column that this node appears on in the 1331 source code. 1332 :type col_offset: int or None 1333 1334 :param parent: The parent node in the syntax tree. 1335 :type parent: NodeNG or None 1336 1337 :param end_lineno: The last line this node appears on in the source code. 1338 :type end_lineno: Optional[int] 1339 1340 :param end_col_offset: The end column this node appears on in the 1341 source code. Note: This is after the last symbol. 1342 :type end_col_offset: Optional[int] 1343 """ 1344 self.locals = {} 1345 """A map of the name of a local variable to the node defining it. 1346 1347 :type: dict(str, NodeNG) 1348 """ 1349 1350 self.args: Arguments 1351 """The arguments that the function takes.""" 1352 1353 self.body = [] 1354 """The contents of the function body. 1355 1356 :type: list(NodeNG) 1357 """ 1358 1359 super().__init__( 1360 lineno=lineno, 1361 col_offset=col_offset, 1362 end_lineno=end_lineno, 1363 end_col_offset=end_col_offset, 1364 parent=parent, 1365 ) 1366 1367 def postinit(self, args: Arguments, body): 1368 """Do some setup after initialisation. 1369 1370 :param args: The arguments that the function takes. 1371 1372 :param body: The contents of the function body. 1373 :type body: list(NodeNG) 1374 """ 1375 self.args = args 1376 self.body = body 1377 1378 def pytype(self): 1379 """Get the name of the type that this node represents. 1380 1381 :returns: The name of the type. 1382 :rtype: str 1383 """ 1384 if "method" in self.type: 1385 return "builtins.instancemethod" 1386 return "builtins.function" 1387 1388 def display_type(self): 1389 """A human readable type of this node. 1390 1391 :returns: The type of this node. 1392 :rtype: str 1393 """ 1394 if "method" in self.type: 1395 return "Method" 1396 return "Function" 1397 1398 def callable(self): 1399 """Whether this node defines something that is callable. 1400 1401 :returns: True if this defines something that is callable, 1402 False otherwise. 1403 For a :class:`Lambda` this is always ``True``. 1404 :rtype: bool 1405 """ 1406 return True 1407 1408 def argnames(self): 1409 """Get the names of each of the arguments. 1410 1411 :returns: The names of the arguments. 1412 :rtype: list(str) 1413 """ 1414 if self.args.arguments: # maybe None with builtin functions 1415 names = _rec_get_names(self.args.arguments) 1416 else: 1417 names = [] 1418 if self.args.vararg: 1419 names.append(self.args.vararg) 1420 if self.args.kwarg: 1421 names.append(self.args.kwarg) 1422 return names 1423 1424 def infer_call_result(self, caller, context=None): 1425 """Infer what the function returns when called. 1426 1427 :param caller: Unused 1428 :type caller: object 1429 """ 1430 # pylint: disable=no-member; github.com/pycqa/astroid/issues/291 1431 # args is in fact redefined later on by postinit. Can't be changed 1432 # to None due to a strong interaction between Lambda and FunctionDef. 1433 return self.body.infer(context) 1434 1435 def scope_lookup(self, node, name, offset=0): 1436 """Lookup where the given names is assigned. 1437 1438 :param node: The node to look for assignments up to. 1439 Any assignments after the given node are ignored. 1440 :type node: NodeNG 1441 1442 :param name: The name to find assignments for. 1443 :type name: str 1444 1445 :param offset: The line offset to filter statements up to. 1446 :type offset: int 1447 1448 :returns: This scope node and the list of assignments associated to the 1449 given name according to the scope where it has been found (locals, 1450 globals or builtin). 1451 :rtype: tuple(str, list(NodeNG)) 1452 """ 1453 if node in self.args.defaults or node in self.args.kw_defaults: 1454 frame = self.parent.frame() 1455 # line offset to avoid that def func(f=func) resolve the default 1456 # value to the defined function 1457 offset = -1 1458 else: 1459 # check this is not used in function decorators 1460 frame = self 1461 return frame._scope_lookup(node, name, offset) 1462 1463 def bool_value(self, context=None): 1464 """Determine the boolean value of this node. 1465 1466 :returns: The boolean value of this node. 1467 For a :class:`Lambda` this is always ``True``. 1468 :rtype: bool 1469 """ 1470 return True 1471 1472 def get_children(self): 1473 yield self.args 1474 yield self.body 1475 1476 def frame(self: T) -> T: 1477 """The node's frame node. 1478 1479 A frame node is a :class:`Module`, :class:`FunctionDef`, 1480 :class:`ClassDef` or :class:`Lambda`. 1481 1482 :returns: The node itself. 1483 """ 1484 return self 1485 1486 1487class FunctionDef(mixins.MultiLineBlockMixin, node_classes.Statement, Lambda): 1488 """Class representing an :class:`ast.FunctionDef`. 1489 1490 >>> import astroid 1491 >>> node = astroid.extract_node(''' 1492 ... def my_func(arg): 1493 ... return arg + 1 1494 ... ''') 1495 >>> node 1496 <FunctionDef.my_func l.2 at 0x7f23b2e71e10> 1497 """ 1498 1499 _astroid_fields = ("decorators", "args", "returns", "body") 1500 _multi_line_block_fields = ("body",) 1501 returns = None 1502 decorators = None 1503 """The decorators that are applied to this method or function. 1504 1505 :type: Decorators or None 1506 """ 1507 special_attributes = FunctionModel() 1508 """The names of special attributes that this function has. 1509 1510 :type: objectmodel.FunctionModel 1511 """ 1512 is_function = True 1513 """Whether this node indicates a function. 1514 1515 For a :class:`FunctionDef` this is always ``True``. 1516 1517 :type: bool 1518 """ 1519 type_annotation = None 1520 """If present, this will contain the type annotation passed by a type comment 1521 1522 :type: NodeNG or None 1523 """ 1524 type_comment_args = None 1525 """ 1526 If present, this will contain the type annotation for arguments 1527 passed by a type comment 1528 """ 1529 type_comment_returns = None 1530 """If present, this will contain the return type annotation, passed by a type comment""" 1531 # attributes below are set by the builder module or by raw factories 1532 _other_fields = ("name", "doc") 1533 _other_other_fields = ( 1534 "locals", 1535 "_type", 1536 "type_comment_returns", 1537 "type_comment_args", 1538 ) 1539 _type = None 1540 1541 def __init__( 1542 self, 1543 name=None, 1544 doc=None, 1545 lineno=None, 1546 col_offset=None, 1547 parent=None, 1548 *, 1549 end_lineno=None, 1550 end_col_offset=None, 1551 ): 1552 """ 1553 :param name: The name of the function. 1554 :type name: str or None 1555 1556 :param doc: The function's docstring. 1557 :type doc: str or None 1558 1559 :param lineno: The line that this node appears on in the source code. 1560 :type lineno: int or None 1561 1562 :param col_offset: The column that this node appears on in the 1563 source code. 1564 :type col_offset: int or None 1565 1566 :param parent: The parent node in the syntax tree. 1567 :type parent: NodeNG or None 1568 1569 :param end_lineno: The last line this node appears on in the source code. 1570 :type end_lineno: Optional[int] 1571 1572 :param end_col_offset: The end column this node appears on in the 1573 source code. Note: This is after the last symbol. 1574 :type end_col_offset: Optional[int] 1575 """ 1576 self.name = name 1577 """The name of the function. 1578 1579 :type name: str or None 1580 """ 1581 1582 self.doc = doc 1583 """The function's docstring. 1584 1585 :type doc: str or None 1586 """ 1587 1588 self.instance_attrs = {} 1589 super().__init__( 1590 lineno=lineno, 1591 col_offset=col_offset, 1592 end_lineno=end_lineno, 1593 end_col_offset=end_col_offset, 1594 parent=parent, 1595 ) 1596 if parent: 1597 frame = parent.frame() 1598 frame.set_local(name, self) 1599 1600 # pylint: disable=arguments-differ; different than Lambdas 1601 def postinit( 1602 self, 1603 args: Arguments, 1604 body, 1605 decorators=None, 1606 returns=None, 1607 type_comment_returns=None, 1608 type_comment_args=None, 1609 ): 1610 """Do some setup after initialisation. 1611 1612 :param args: The arguments that the function takes. 1613 1614 :param body: The contents of the function body. 1615 :type body: list(NodeNG) 1616 1617 :param decorators: The decorators that are applied to this 1618 method or function. 1619 :type decorators: Decorators or None 1620 :params type_comment_returns: 1621 The return type annotation passed via a type comment. 1622 :params type_comment_args: 1623 The args type annotation passed via a type comment. 1624 """ 1625 self.args = args 1626 self.body = body 1627 self.decorators = decorators 1628 self.returns = returns 1629 self.type_comment_returns = type_comment_returns 1630 self.type_comment_args = type_comment_args 1631 1632 @decorators_mod.cachedproperty 1633 def extra_decorators(self): 1634 """The extra decorators that this function can have. 1635 1636 Additional decorators are considered when they are used as 1637 assignments, as in ``method = staticmethod(method)``. 1638 The property will return all the callables that are used for 1639 decoration. 1640 1641 :type: list(NodeNG) 1642 """ 1643 frame = self.parent.frame() 1644 if not isinstance(frame, ClassDef): 1645 return [] 1646 1647 decorators = [] 1648 for assign in frame._get_assign_nodes(): 1649 if isinstance(assign.value, node_classes.Call) and isinstance( 1650 assign.value.func, node_classes.Name 1651 ): 1652 for assign_node in assign.targets: 1653 if not isinstance(assign_node, node_classes.AssignName): 1654 # Support only `name = callable(name)` 1655 continue 1656 1657 if assign_node.name != self.name: 1658 # Interested only in the assignment nodes that 1659 # decorates the current method. 1660 continue 1661 try: 1662 meth = frame[self.name] 1663 except KeyError: 1664 continue 1665 else: 1666 # Must be a function and in the same frame as the 1667 # original method. 1668 if ( 1669 isinstance(meth, FunctionDef) 1670 and assign_node.frame() == frame 1671 ): 1672 decorators.append(assign.value) 1673 return decorators 1674 1675 @decorators_mod.cachedproperty 1676 def type( 1677 self, 1678 ): # pylint: disable=invalid-overridden-method,too-many-return-statements 1679 """The function type for this node. 1680 1681 Possible values are: method, function, staticmethod, classmethod. 1682 1683 :type: str 1684 """ 1685 for decorator in self.extra_decorators: 1686 if decorator.func.name in BUILTIN_DESCRIPTORS: 1687 return decorator.func.name 1688 1689 frame = self.parent.frame() 1690 type_name = "function" 1691 if isinstance(frame, ClassDef): 1692 if self.name == "__new__": 1693 return "classmethod" 1694 if self.name == "__init_subclass__": 1695 return "classmethod" 1696 if self.name == "__class_getitem__": 1697 return "classmethod" 1698 1699 type_name = "method" 1700 1701 if not self.decorators: 1702 return type_name 1703 1704 for node in self.decorators.nodes: 1705 if isinstance(node, node_classes.Name): 1706 if node.name in BUILTIN_DESCRIPTORS: 1707 return node.name 1708 if ( 1709 isinstance(node, node_classes.Attribute) 1710 and isinstance(node.expr, node_classes.Name) 1711 and node.expr.name == "builtins" 1712 and node.attrname in BUILTIN_DESCRIPTORS 1713 ): 1714 return node.attrname 1715 1716 if isinstance(node, node_classes.Call): 1717 # Handle the following case: 1718 # @some_decorator(arg1, arg2) 1719 # def func(...) 1720 # 1721 try: 1722 current = next(node.func.infer()) 1723 except (InferenceError, StopIteration): 1724 continue 1725 _type = _infer_decorator_callchain(current) 1726 if _type is not None: 1727 return _type 1728 1729 try: 1730 for inferred in node.infer(): 1731 # Check to see if this returns a static or a class method. 1732 _type = _infer_decorator_callchain(inferred) 1733 if _type is not None: 1734 return _type 1735 1736 if not isinstance(inferred, ClassDef): 1737 continue 1738 for ancestor in inferred.ancestors(): 1739 if not isinstance(ancestor, ClassDef): 1740 continue 1741 if ancestor.is_subtype_of("builtins.classmethod"): 1742 return "classmethod" 1743 if ancestor.is_subtype_of("builtins.staticmethod"): 1744 return "staticmethod" 1745 except InferenceError: 1746 pass 1747 return type_name 1748 1749 @decorators_mod.cachedproperty 1750 def fromlineno(self): 1751 """The first line that this node appears on in the source code. 1752 1753 :type: int or None 1754 """ 1755 # lineno is the line number of the first decorator, we want the def 1756 # statement lineno 1757 lineno = self.lineno 1758 if self.decorators is not None: 1759 lineno += sum( 1760 node.tolineno - node.lineno + 1 for node in self.decorators.nodes 1761 ) 1762 1763 return lineno 1764 1765 @decorators_mod.cachedproperty 1766 def blockstart_tolineno(self): 1767 """The line on which the beginning of this block ends. 1768 1769 :type: int 1770 """ 1771 return self.args.tolineno 1772 1773 def block_range(self, lineno): 1774 """Get a range from the given line number to where this node ends. 1775 1776 :param lineno: Unused. 1777 :type lineno: int 1778 1779 :returns: The range of line numbers that this node belongs to, 1780 :rtype: tuple(int, int) 1781 """ 1782 return self.fromlineno, self.tolineno 1783 1784 def getattr(self, name, context=None): 1785 """this method doesn't look in the instance_attrs dictionary since it's 1786 done by an Instance proxy at inference time. 1787 """ 1788 if not name: 1789 raise AttributeInferenceError(target=self, attribute=name, context=context) 1790 1791 found_attrs = [] 1792 if name in self.instance_attrs: 1793 found_attrs = self.instance_attrs[name] 1794 if name in self.special_attributes: 1795 found_attrs.append(self.special_attributes.lookup(name)) 1796 if found_attrs: 1797 return found_attrs 1798 raise AttributeInferenceError(target=self, attribute=name) 1799 1800 def igetattr(self, name, context=None): 1801 """Inferred getattr, which returns an iterator of inferred statements.""" 1802 try: 1803 return bases._infer_stmts(self.getattr(name, context), context, frame=self) 1804 except AttributeInferenceError as error: 1805 raise InferenceError( 1806 str(error), target=self, attribute=name, context=context 1807 ) from error 1808 1809 def is_method(self): 1810 """Check if this function node represents a method. 1811 1812 :returns: True if this is a method, False otherwise. 1813 :rtype: bool 1814 """ 1815 # check we are defined in a ClassDef, because this is usually expected 1816 # (e.g. pylint...) when is_method() return True 1817 return self.type != "function" and isinstance(self.parent.frame(), ClassDef) 1818 1819 @decorators_mod.cached 1820 def decoratornames(self, context=None): 1821 """Get the qualified names of each of the decorators on this function. 1822 1823 :param context: 1824 An inference context that can be passed to inference functions 1825 :returns: The names of the decorators. 1826 :rtype: set(str) 1827 """ 1828 result = set() 1829 decoratornodes = [] 1830 if self.decorators is not None: 1831 decoratornodes += self.decorators.nodes 1832 decoratornodes += self.extra_decorators 1833 for decnode in decoratornodes: 1834 try: 1835 for infnode in decnode.infer(context=context): 1836 result.add(infnode.qname()) 1837 except InferenceError: 1838 continue 1839 return result 1840 1841 def is_bound(self): 1842 """Check if the function is bound to an instance or class. 1843 1844 :returns: True if the function is bound to an instance or class, 1845 False otherwise. 1846 :rtype: bool 1847 """ 1848 return self.type == "classmethod" 1849 1850 def is_abstract(self, pass_is_abstract=True, any_raise_is_abstract=False): 1851 """Check if the method is abstract. 1852 1853 A method is considered abstract if any of the following is true: 1854 * The only statement is 'raise NotImplementedError' 1855 * The only statement is 'raise <SomeException>' and any_raise_is_abstract is True 1856 * The only statement is 'pass' and pass_is_abstract is True 1857 * The method is annotated with abc.astractproperty/abc.abstractmethod 1858 1859 :returns: True if the method is abstract, False otherwise. 1860 :rtype: bool 1861 """ 1862 if self.decorators: 1863 for node in self.decorators.nodes: 1864 try: 1865 inferred = next(node.infer()) 1866 except (InferenceError, StopIteration): 1867 continue 1868 if inferred and inferred.qname() in { 1869 "abc.abstractproperty", 1870 "abc.abstractmethod", 1871 }: 1872 return True 1873 1874 for child_node in self.body: 1875 if isinstance(child_node, node_classes.Raise): 1876 if any_raise_is_abstract: 1877 return True 1878 if child_node.raises_not_implemented(): 1879 return True 1880 return pass_is_abstract and isinstance(child_node, node_classes.Pass) 1881 # empty function is the same as function with a single "pass" statement 1882 if pass_is_abstract: 1883 return True 1884 1885 def is_generator(self): 1886 """Check if this is a generator function. 1887 1888 :returns: True is this is a generator function, False otherwise. 1889 :rtype: bool 1890 """ 1891 return bool(next(self._get_yield_nodes_skip_lambdas(), False)) 1892 1893 def infer_yield_result(self, context=None): 1894 """Infer what the function yields when called 1895 1896 :returns: What the function yields 1897 :rtype: iterable(NodeNG or Uninferable) or None 1898 """ 1899 # pylint: disable=not-an-iterable 1900 # https://github.com/PyCQA/astroid/issues/1015 1901 for yield_ in self.nodes_of_class(node_classes.Yield): 1902 if yield_.value is None: 1903 const = node_classes.Const(None) 1904 const.parent = yield_ 1905 const.lineno = yield_.lineno 1906 yield const 1907 elif yield_.scope() == self: 1908 yield from yield_.value.infer(context=context) 1909 1910 def infer_call_result(self, caller=None, context=None): 1911 """Infer what the function returns when called. 1912 1913 :returns: What the function returns. 1914 :rtype: iterable(NodeNG or Uninferable) or None 1915 """ 1916 if self.is_generator(): 1917 if isinstance(self, AsyncFunctionDef): 1918 generator_cls = bases.AsyncGenerator 1919 else: 1920 generator_cls = bases.Generator 1921 result = generator_cls(self, generator_initial_context=context) 1922 yield result 1923 return 1924 # This is really a gigantic hack to work around metaclass generators 1925 # that return transient class-generating functions. Pylint's AST structure 1926 # cannot handle a base class object that is only used for calling __new__, 1927 # but does not contribute to the inheritance structure itself. We inject 1928 # a fake class into the hierarchy here for several well-known metaclass 1929 # generators, and filter it out later. 1930 if ( 1931 self.name == "with_metaclass" 1932 and len(self.args.args) == 1 1933 and self.args.vararg is not None 1934 ): 1935 metaclass = next(caller.args[0].infer(context), None) 1936 if isinstance(metaclass, ClassDef): 1937 try: 1938 class_bases = [next(arg.infer(context)) for arg in caller.args[1:]] 1939 except StopIteration as e: 1940 raise InferenceError(node=caller.args[1:], context=context) from e 1941 new_class = ClassDef(name="temporary_class") 1942 new_class.hide = True 1943 new_class.parent = self 1944 new_class.postinit( 1945 bases=[base for base in class_bases if base != util.Uninferable], 1946 body=[], 1947 decorators=[], 1948 metaclass=metaclass, 1949 ) 1950 yield new_class 1951 return 1952 returns = self._get_return_nodes_skip_functions() 1953 1954 first_return = next(returns, None) 1955 if not first_return: 1956 if self.body: 1957 if self.is_abstract(pass_is_abstract=True, any_raise_is_abstract=True): 1958 yield util.Uninferable 1959 else: 1960 yield node_classes.Const(None) 1961 return 1962 1963 raise InferenceError("The function does not have any return statements") 1964 1965 for returnnode in itertools.chain((first_return,), returns): 1966 if returnnode.value is None: 1967 yield node_classes.Const(None) 1968 else: 1969 try: 1970 yield from returnnode.value.infer(context) 1971 except InferenceError: 1972 yield util.Uninferable 1973 1974 def bool_value(self, context=None): 1975 """Determine the boolean value of this node. 1976 1977 :returns: The boolean value of this node. 1978 For a :class:`FunctionDef` this is always ``True``. 1979 :rtype: bool 1980 """ 1981 return True 1982 1983 def get_children(self): 1984 if self.decorators is not None: 1985 yield self.decorators 1986 1987 yield self.args 1988 1989 if self.returns is not None: 1990 yield self.returns 1991 1992 yield from self.body 1993 1994 def scope_lookup(self, node, name, offset=0): 1995 """Lookup where the given name is assigned.""" 1996 if name == "__class__": 1997 # __class__ is an implicit closure reference created by the compiler 1998 # if any methods in a class body refer to either __class__ or super. 1999 # In our case, we want to be able to look it up in the current scope 2000 # when `__class__` is being used. 2001 frame = self.parent.frame() 2002 if isinstance(frame, ClassDef): 2003 return self, [frame] 2004 return super().scope_lookup(node, name, offset) 2005 2006 def frame(self: T) -> T: 2007 """The node's frame node. 2008 2009 A frame node is a :class:`Module`, :class:`FunctionDef`, 2010 :class:`ClassDef` or :class:`Lambda`. 2011 2012 :returns: The node itself. 2013 """ 2014 return self 2015 2016 2017class AsyncFunctionDef(FunctionDef): 2018 """Class representing an :class:`ast.FunctionDef` node. 2019 2020 A :class:`AsyncFunctionDef` is an asynchronous function 2021 created with the `async` keyword. 2022 2023 >>> import astroid 2024 >>> node = astroid.extract_node(''' 2025 async def func(things): 2026 async for thing in things: 2027 print(thing) 2028 ''') 2029 >>> node 2030 <AsyncFunctionDef.func l.2 at 0x7f23b2e416d8> 2031 >>> node.body[0] 2032 <AsyncFor l.3 at 0x7f23b2e417b8> 2033 """ 2034 2035 2036def _rec_get_names(args, names=None): 2037 """return a list of all argument names""" 2038 if names is None: 2039 names = [] 2040 for arg in args: 2041 if isinstance(arg, node_classes.Tuple): 2042 _rec_get_names(arg.elts, names) 2043 else: 2044 names.append(arg.name) 2045 return names 2046 2047 2048def _is_metaclass(klass, seen=None): 2049 """Return if the given class can be 2050 used as a metaclass. 2051 """ 2052 if klass.name == "type": 2053 return True 2054 if seen is None: 2055 seen = set() 2056 for base in klass.bases: 2057 try: 2058 for baseobj in base.infer(): 2059 baseobj_name = baseobj.qname() 2060 if baseobj_name in seen: 2061 continue 2062 2063 seen.add(baseobj_name) 2064 if isinstance(baseobj, bases.Instance): 2065 # not abstract 2066 return False 2067 if baseobj is util.Uninferable: 2068 continue 2069 if baseobj is klass: 2070 continue 2071 if not isinstance(baseobj, ClassDef): 2072 continue 2073 if baseobj._type == "metaclass": 2074 return True 2075 if _is_metaclass(baseobj, seen): 2076 return True 2077 except InferenceError: 2078 continue 2079 return False 2080 2081 2082def _class_type(klass, ancestors=None): 2083 """return a ClassDef node type to differ metaclass and exception 2084 from 'regular' classes 2085 """ 2086 # XXX we have to store ancestors in case we have an ancestor loop 2087 if klass._type is not None: 2088 return klass._type 2089 if _is_metaclass(klass): 2090 klass._type = "metaclass" 2091 elif klass.name.endswith("Exception"): 2092 klass._type = "exception" 2093 else: 2094 if ancestors is None: 2095 ancestors = set() 2096 klass_name = klass.qname() 2097 if klass_name in ancestors: 2098 # XXX we are in loop ancestors, and have found no type 2099 klass._type = "class" 2100 return "class" 2101 ancestors.add(klass_name) 2102 for base in klass.ancestors(recurs=False): 2103 name = _class_type(base, ancestors) 2104 if name != "class": 2105 if name == "metaclass" and not _is_metaclass(klass): 2106 # don't propagate it if the current class 2107 # can't be a metaclass 2108 continue 2109 klass._type = base.type 2110 break 2111 if klass._type is None: 2112 klass._type = "class" 2113 return klass._type 2114 2115 2116def get_wrapping_class(node): 2117 """Get the class that wraps the given node. 2118 2119 We consider that a class wraps a node if the class 2120 is a parent for the said node. 2121 2122 :returns: The class that wraps the given node 2123 :rtype: ClassDef or None 2124 """ 2125 2126 klass = node.frame() 2127 while klass is not None and not isinstance(klass, ClassDef): 2128 if klass.parent is None: 2129 klass = None 2130 else: 2131 klass = klass.parent.frame() 2132 return klass 2133 2134 2135class ClassDef(mixins.FilterStmtsMixin, LocalsDictNodeNG, node_classes.Statement): 2136 """Class representing an :class:`ast.ClassDef` node. 2137 2138 >>> import astroid 2139 >>> node = astroid.extract_node(''' 2140 class Thing: 2141 def my_meth(self, arg): 2142 return arg + self.offset 2143 ''') 2144 >>> node 2145 <ClassDef.Thing l.2 at 0x7f23b2e9e748> 2146 """ 2147 2148 # some of the attributes below are set by the builder module or 2149 # by a raw factories 2150 2151 # a dictionary of class instances attributes 2152 _astroid_fields = ("decorators", "bases", "keywords", "body") # name 2153 2154 decorators = None 2155 """The decorators that are applied to this class. 2156 2157 :type: Decorators or None 2158 """ 2159 special_attributes = ClassModel() 2160 """The names of special attributes that this class has. 2161 2162 :type: objectmodel.ClassModel 2163 """ 2164 2165 _type = None 2166 _metaclass_hack = False 2167 hide = False 2168 type = property( 2169 _class_type, 2170 doc=( 2171 "The class type for this node.\n\n" 2172 "Possible values are: class, metaclass, exception.\n\n" 2173 ":type: str" 2174 ), 2175 ) 2176 _other_fields = ("name", "doc") 2177 _other_other_fields = ("locals", "_newstyle") 2178 _newstyle = None 2179 2180 def __init__( 2181 self, 2182 name=None, 2183 doc=None, 2184 lineno=None, 2185 col_offset=None, 2186 parent=None, 2187 *, 2188 end_lineno=None, 2189 end_col_offset=None, 2190 ): 2191 """ 2192 :param name: The name of the class. 2193 :type name: str or None 2194 2195 :param doc: The function's docstring. 2196 :type doc: str or None 2197 2198 :param lineno: The line that this node appears on in the source code. 2199 :type lineno: int or None 2200 2201 :param col_offset: The column that this node appears on in the 2202 source code. 2203 :type col_offset: int or None 2204 2205 :param parent: The parent node in the syntax tree. 2206 :type parent: NodeNG or None 2207 2208 :param end_lineno: The last line this node appears on in the source code. 2209 :type end_lineno: Optional[int] 2210 2211 :param end_col_offset: The end column this node appears on in the 2212 source code. Note: This is after the last symbol. 2213 :type end_col_offset: Optional[int] 2214 """ 2215 self.instance_attrs = {} 2216 self.locals = {} 2217 """A map of the name of a local variable to the node defining it. 2218 2219 :type: dict(str, NodeNG) 2220 """ 2221 2222 self.keywords = [] 2223 """The keywords given to the class definition. 2224 2225 This is usually for :pep:`3115` style metaclass declaration. 2226 2227 :type: list(Keyword) or None 2228 """ 2229 2230 self.bases = [] 2231 """What the class inherits from. 2232 2233 :type: list(NodeNG) 2234 """ 2235 2236 self.body = [] 2237 """The contents of the class body. 2238 2239 :type: list(NodeNG) 2240 """ 2241 2242 self.name = name 2243 """The name of the class. 2244 2245 :type name: str or None 2246 """ 2247 2248 self.doc = doc 2249 """The class' docstring. 2250 2251 :type doc: str or None 2252 """ 2253 2254 super().__init__( 2255 lineno=lineno, 2256 col_offset=col_offset, 2257 end_lineno=end_lineno, 2258 end_col_offset=end_col_offset, 2259 parent=parent, 2260 ) 2261 if parent is not None: 2262 parent.frame().set_local(name, self) 2263 2264 for local_name, node in self.implicit_locals(): 2265 self.add_local_node(node, local_name) 2266 2267 def implicit_parameters(self): 2268 return 1 2269 2270 def implicit_locals(self): 2271 """Get implicitly defined class definition locals. 2272 2273 :returns: the the name and Const pair for each local 2274 :rtype: tuple(tuple(str, node_classes.Const), ...) 2275 """ 2276 locals_ = (("__module__", self.special_attributes.attr___module__),) 2277 # __qualname__ is defined in PEP3155 2278 locals_ += (("__qualname__", self.special_attributes.attr___qualname__),) 2279 return locals_ 2280 2281 # pylint: disable=redefined-outer-name 2282 def postinit( 2283 self, bases, body, decorators, newstyle=None, metaclass=None, keywords=None 2284 ): 2285 """Do some setup after initialisation. 2286 2287 :param bases: What the class inherits from. 2288 :type bases: list(NodeNG) 2289 2290 :param body: The contents of the class body. 2291 :type body: list(NodeNG) 2292 2293 :param decorators: The decorators that are applied to this class. 2294 :type decorators: Decorators or None 2295 2296 :param newstyle: Whether this is a new style class or not. 2297 :type newstyle: bool or None 2298 2299 :param metaclass: The metaclass of this class. 2300 :type metaclass: NodeNG or None 2301 2302 :param keywords: The keywords given to the class definition. 2303 :type keywords: list(Keyword) or None 2304 """ 2305 if keywords is not None: 2306 self.keywords = keywords 2307 self.bases = bases 2308 self.body = body 2309 self.decorators = decorators 2310 if newstyle is not None: 2311 self._newstyle = newstyle 2312 if metaclass is not None: 2313 self._metaclass = metaclass 2314 2315 def _newstyle_impl(self, context=None): 2316 if context is None: 2317 context = InferenceContext() 2318 if self._newstyle is not None: 2319 return self._newstyle 2320 for base in self.ancestors(recurs=False, context=context): 2321 if base._newstyle_impl(context): 2322 self._newstyle = True 2323 break 2324 klass = self.declared_metaclass() 2325 # could be any callable, we'd need to infer the result of klass(name, 2326 # bases, dict). punt if it's not a class node. 2327 if klass is not None and isinstance(klass, ClassDef): 2328 self._newstyle = klass._newstyle_impl(context) 2329 if self._newstyle is None: 2330 self._newstyle = False 2331 return self._newstyle 2332 2333 _newstyle = None 2334 newstyle = property( 2335 _newstyle_impl, 2336 doc=("Whether this is a new style class or not\n\n" ":type: bool or None"), 2337 ) 2338 2339 @decorators_mod.cachedproperty 2340 def blockstart_tolineno(self): 2341 """The line on which the beginning of this block ends. 2342 2343 :type: int 2344 """ 2345 if self.bases: 2346 return self.bases[-1].tolineno 2347 2348 return self.fromlineno 2349 2350 def block_range(self, lineno): 2351 """Get a range from the given line number to where this node ends. 2352 2353 :param lineno: Unused. 2354 :type lineno: int 2355 2356 :returns: The range of line numbers that this node belongs to, 2357 :rtype: tuple(int, int) 2358 """ 2359 return self.fromlineno, self.tolineno 2360 2361 def pytype(self): 2362 """Get the name of the type that this node represents. 2363 2364 :returns: The name of the type. 2365 :rtype: str 2366 """ 2367 if self.newstyle: 2368 return "builtins.type" 2369 return "builtins.classobj" 2370 2371 def display_type(self): 2372 """A human readable type of this node. 2373 2374 :returns: The type of this node. 2375 :rtype: str 2376 """ 2377 return "Class" 2378 2379 def callable(self): 2380 """Whether this node defines something that is callable. 2381 2382 :returns: True if this defines something that is callable, 2383 False otherwise. 2384 For a :class:`ClassDef` this is always ``True``. 2385 :rtype: bool 2386 """ 2387 return True 2388 2389 def is_subtype_of(self, type_name, context=None): 2390 """Whether this class is a subtype of the given type. 2391 2392 :param type_name: The name of the type of check against. 2393 :type type_name: str 2394 2395 :returns: True if this class is a subtype of the given type, 2396 False otherwise. 2397 :rtype: bool 2398 """ 2399 if self.qname() == type_name: 2400 return True 2401 for anc in self.ancestors(context=context): 2402 if anc.qname() == type_name: 2403 return True 2404 return False 2405 2406 def _infer_type_call(self, caller, context): 2407 try: 2408 name_node = next(caller.args[0].infer(context)) 2409 except StopIteration as e: 2410 raise InferenceError(node=caller.args[0], context=context) from e 2411 if isinstance(name_node, node_classes.Const) and isinstance( 2412 name_node.value, str 2413 ): 2414 name = name_node.value 2415 else: 2416 return util.Uninferable 2417 2418 result = ClassDef(name, None) 2419 2420 # Get the bases of the class. 2421 try: 2422 class_bases = next(caller.args[1].infer(context)) 2423 except StopIteration as e: 2424 raise InferenceError(node=caller.args[1], context=context) from e 2425 if isinstance(class_bases, (node_classes.Tuple, node_classes.List)): 2426 bases = [] 2427 for base in class_bases.itered(): 2428 inferred = next(base.infer(context=context), None) 2429 if inferred: 2430 bases.append( 2431 node_classes.EvaluatedObject(original=base, value=inferred) 2432 ) 2433 result.bases = bases 2434 else: 2435 # There is currently no AST node that can represent an 'unknown' 2436 # node (Uninferable is not an AST node), therefore we simply return Uninferable here 2437 # although we know at least the name of the class. 2438 return util.Uninferable 2439 2440 # Get the members of the class 2441 try: 2442 members = next(caller.args[2].infer(context)) 2443 except (InferenceError, StopIteration): 2444 members = None 2445 2446 if members and isinstance(members, node_classes.Dict): 2447 for attr, value in members.items: 2448 if isinstance(attr, node_classes.Const) and isinstance(attr.value, str): 2449 result.locals[attr.value] = [value] 2450 2451 result.parent = caller.parent 2452 return result 2453 2454 def infer_call_result(self, caller, context=None): 2455 """infer what a class is returning when called""" 2456 if self.is_subtype_of("builtins.type", context) and len(caller.args) == 3: 2457 result = self._infer_type_call(caller, context) 2458 yield result 2459 return 2460 2461 dunder_call = None 2462 try: 2463 metaclass = self.metaclass(context=context) 2464 if metaclass is not None: 2465 dunder_call = next(metaclass.igetattr("__call__", context)) 2466 except (AttributeInferenceError, StopIteration): 2467 pass 2468 2469 if dunder_call and dunder_call.qname() != "builtins.type.__call__": 2470 # Call type.__call__ if not set metaclass 2471 # (since type is the default metaclass) 2472 context = bind_context_to_node(context, self) 2473 context.callcontext.callee = dunder_call 2474 yield from dunder_call.infer_call_result(caller, context) 2475 else: 2476 yield self.instantiate_class() 2477 2478 def scope_lookup(self, node, name, offset=0): 2479 """Lookup where the given name is assigned. 2480 2481 :param node: The node to look for assignments up to. 2482 Any assignments after the given node are ignored. 2483 :type node: NodeNG 2484 2485 :param name: The name to find assignments for. 2486 :type name: str 2487 2488 :param offset: The line offset to filter statements up to. 2489 :type offset: int 2490 2491 :returns: This scope node and the list of assignments associated to the 2492 given name according to the scope where it has been found (locals, 2493 globals or builtin). 2494 :rtype: tuple(str, list(NodeNG)) 2495 """ 2496 # If the name looks like a builtin name, just try to look 2497 # into the upper scope of this class. We might have a 2498 # decorator that it's poorly named after a builtin object 2499 # inside this class. 2500 lookup_upper_frame = ( 2501 isinstance(node.parent, node_classes.Decorators) 2502 and name in AstroidManager().builtins_module 2503 ) 2504 if ( 2505 any(node == base or base.parent_of(node) for base in self.bases) 2506 or lookup_upper_frame 2507 ): 2508 # Handle the case where we have either a name 2509 # in the bases of a class, which exists before 2510 # the actual definition or the case where we have 2511 # a Getattr node, with that name. 2512 # 2513 # name = ... 2514 # class A(name): 2515 # def name(self): ... 2516 # 2517 # import name 2518 # class A(name.Name): 2519 # def name(self): ... 2520 2521 frame = self.parent.frame() 2522 # line offset to avoid that class A(A) resolve the ancestor to 2523 # the defined class 2524 offset = -1 2525 else: 2526 frame = self 2527 return frame._scope_lookup(node, name, offset) 2528 2529 @property 2530 def basenames(self): 2531 """The names of the parent classes 2532 2533 Names are given in the order they appear in the class definition. 2534 2535 :type: list(str) 2536 """ 2537 return [bnode.as_string() for bnode in self.bases] 2538 2539 def ancestors(self, recurs=True, context=None): 2540 """Iterate over the base classes in prefixed depth first order. 2541 2542 :param recurs: Whether to recurse or return direct ancestors only. 2543 :type recurs: bool 2544 2545 :returns: The base classes 2546 :rtype: iterable(NodeNG) 2547 """ 2548 # FIXME: should be possible to choose the resolution order 2549 # FIXME: inference make infinite loops possible here 2550 yielded = {self} 2551 if context is None: 2552 context = InferenceContext() 2553 if not self.bases and self.qname() != "builtins.object": 2554 yield builtin_lookup("object")[1][0] 2555 return 2556 2557 for stmt in self.bases: 2558 with context.restore_path(): 2559 try: 2560 for baseobj in stmt.infer(context): 2561 if not isinstance(baseobj, ClassDef): 2562 if isinstance(baseobj, bases.Instance): 2563 baseobj = baseobj._proxied 2564 else: 2565 continue 2566 if not baseobj.hide: 2567 if baseobj in yielded: 2568 continue 2569 yielded.add(baseobj) 2570 yield baseobj 2571 if not recurs: 2572 continue 2573 for grandpa in baseobj.ancestors(recurs=True, context=context): 2574 if grandpa is self: 2575 # This class is the ancestor of itself. 2576 break 2577 if grandpa in yielded: 2578 continue 2579 yielded.add(grandpa) 2580 yield grandpa 2581 except InferenceError: 2582 continue 2583 2584 def local_attr_ancestors(self, name, context=None): 2585 """Iterate over the parents that define the given name. 2586 2587 :param name: The name to find definitions for. 2588 :type name: str 2589 2590 :returns: The parents that define the given name. 2591 :rtype: iterable(NodeNG) 2592 """ 2593 # Look up in the mro if we can. This will result in the 2594 # attribute being looked up just as Python does it. 2595 try: 2596 ancestors = self.mro(context)[1:] 2597 except MroError: 2598 # Fallback to use ancestors, we can't determine 2599 # a sane MRO. 2600 ancestors = self.ancestors(context=context) 2601 for astroid in ancestors: 2602 if name in astroid: 2603 yield astroid 2604 2605 def instance_attr_ancestors(self, name, context=None): 2606 """Iterate over the parents that define the given name as an attribute. 2607 2608 :param name: The name to find definitions for. 2609 :type name: str 2610 2611 :returns: The parents that define the given name as 2612 an instance attribute. 2613 :rtype: iterable(NodeNG) 2614 """ 2615 for astroid in self.ancestors(context=context): 2616 if name in astroid.instance_attrs: 2617 yield astroid 2618 2619 def has_base(self, node): 2620 """Whether this class directly inherits from the given node. 2621 2622 :param node: The node to check for. 2623 :type node: NodeNG 2624 2625 :returns: True if this class directly inherits from the given node. 2626 :rtype: bool 2627 """ 2628 return node in self.bases 2629 2630 def local_attr(self, name, context=None): 2631 """Get the list of assign nodes associated to the given name. 2632 2633 Assignments are looked for in both this class and in parents. 2634 2635 :returns: The list of assignments to the given name. 2636 :rtype: list(NodeNG) 2637 2638 :raises AttributeInferenceError: If no attribute with this name 2639 can be found in this class or parent classes. 2640 """ 2641 result = [] 2642 if name in self.locals: 2643 result = self.locals[name] 2644 else: 2645 class_node = next(self.local_attr_ancestors(name, context), None) 2646 if class_node: 2647 result = class_node.locals[name] 2648 result = [n for n in result if not isinstance(n, node_classes.DelAttr)] 2649 if result: 2650 return result 2651 raise AttributeInferenceError(target=self, attribute=name, context=context) 2652 2653 def instance_attr(self, name, context=None): 2654 """Get the list of nodes associated to the given attribute name. 2655 2656 Assignments are looked for in both this class and in parents. 2657 2658 :returns: The list of assignments to the given name. 2659 :rtype: list(NodeNG) 2660 2661 :raises AttributeInferenceError: If no attribute with this name 2662 can be found in this class or parent classes. 2663 """ 2664 # Return a copy, so we don't modify self.instance_attrs, 2665 # which could lead to infinite loop. 2666 values = list(self.instance_attrs.get(name, [])) 2667 # get all values from parents 2668 for class_node in self.instance_attr_ancestors(name, context): 2669 values += class_node.instance_attrs[name] 2670 values = [n for n in values if not isinstance(n, node_classes.DelAttr)] 2671 if values: 2672 return values 2673 raise AttributeInferenceError(target=self, attribute=name, context=context) 2674 2675 def instantiate_class(self): 2676 """Get an :class:`Instance` of the :class:`ClassDef` node. 2677 2678 :returns: An :class:`Instance` of the :class:`ClassDef` node, 2679 or self if this is not possible. 2680 :rtype: Instance or ClassDef 2681 """ 2682 try: 2683 if any(cls.name in EXCEPTION_BASE_CLASSES for cls in self.mro()): 2684 # Subclasses of exceptions can be exception instances 2685 return objects.ExceptionInstance(self) 2686 except MroError: 2687 pass 2688 return bases.Instance(self) 2689 2690 def getattr(self, name, context=None, class_context=True): 2691 """Get an attribute from this class, using Python's attribute semantic. 2692 2693 This method doesn't look in the :attr:`instance_attrs` dictionary 2694 since it is done by an :class:`Instance` proxy at inference time. 2695 It may return an :class:`Uninferable` object if 2696 the attribute has not been 2697 found, but a ``__getattr__`` or ``__getattribute__`` method is defined. 2698 If ``class_context`` is given, then it is considered that the 2699 attribute is accessed from a class context, 2700 e.g. ClassDef.attribute, otherwise it might have been accessed 2701 from an instance as well. If ``class_context`` is used in that 2702 case, then a lookup in the implicit metaclass and the explicit 2703 metaclass will be done. 2704 2705 :param name: The attribute to look for. 2706 :type name: str 2707 2708 :param class_context: Whether the attribute can be accessed statically. 2709 :type class_context: bool 2710 2711 :returns: The attribute. 2712 :rtype: list(NodeNG) 2713 2714 :raises AttributeInferenceError: If the attribute cannot be inferred. 2715 """ 2716 if not name: 2717 raise AttributeInferenceError(target=self, attribute=name, context=context) 2718 2719 values = self.locals.get(name, []) 2720 if name in self.special_attributes and class_context and not values: 2721 result = [self.special_attributes.lookup(name)] 2722 if name == "__bases__": 2723 # Need special treatment, since they are mutable 2724 # and we need to return all the values. 2725 result += values 2726 return result 2727 2728 # don't modify the list in self.locals! 2729 values = list(values) 2730 for classnode in self.ancestors(recurs=True, context=context): 2731 values += classnode.locals.get(name, []) 2732 2733 if class_context: 2734 values += self._metaclass_lookup_attribute(name, context) 2735 2736 if not values: 2737 raise AttributeInferenceError(target=self, attribute=name, context=context) 2738 2739 # Look for AnnAssigns, which are not attributes in the purest sense. 2740 for value in values: 2741 if isinstance(value, node_classes.AssignName): 2742 stmt = value.statement() 2743 if isinstance(stmt, node_classes.AnnAssign) and stmt.value is None: 2744 raise AttributeInferenceError( 2745 target=self, attribute=name, context=context 2746 ) 2747 return values 2748 2749 def _metaclass_lookup_attribute(self, name, context): 2750 """Search the given name in the implicit and the explicit metaclass.""" 2751 attrs = set() 2752 implicit_meta = self.implicit_metaclass() 2753 context = copy_context(context) 2754 metaclass = self.metaclass(context=context) 2755 for cls in (implicit_meta, metaclass): 2756 if cls and cls != self and isinstance(cls, ClassDef): 2757 cls_attributes = self._get_attribute_from_metaclass(cls, name, context) 2758 attrs.update(set(cls_attributes)) 2759 return attrs 2760 2761 def _get_attribute_from_metaclass(self, cls, name, context): 2762 try: 2763 attrs = cls.getattr(name, context=context, class_context=True) 2764 except AttributeInferenceError: 2765 return 2766 2767 for attr in bases._infer_stmts(attrs, context, frame=cls): 2768 if not isinstance(attr, FunctionDef): 2769 yield attr 2770 continue 2771 2772 if isinstance(attr, objects.Property): 2773 yield attr 2774 continue 2775 if attr.type == "classmethod": 2776 # If the method is a classmethod, then it will 2777 # be bound to the metaclass, not to the class 2778 # from where the attribute is retrieved. 2779 # get_wrapping_class could return None, so just 2780 # default to the current class. 2781 frame = get_wrapping_class(attr) or self 2782 yield bases.BoundMethod(attr, frame) 2783 elif attr.type == "staticmethod": 2784 yield attr 2785 else: 2786 yield bases.BoundMethod(attr, self) 2787 2788 def igetattr(self, name, context=None, class_context=True): 2789 """Infer the possible values of the given variable. 2790 2791 :param name: The name of the variable to infer. 2792 :type name: str 2793 2794 :returns: The inferred possible values. 2795 :rtype: iterable(NodeNG or Uninferable) 2796 """ 2797 # set lookup name since this is necessary to infer on import nodes for 2798 # instance 2799 context = copy_context(context) 2800 context.lookupname = name 2801 2802 metaclass = self.metaclass(context=context) 2803 try: 2804 attributes = self.getattr(name, context, class_context=class_context) 2805 # If we have more than one attribute, make sure that those starting from 2806 # the second one are from the same scope. This is to account for modifications 2807 # to the attribute happening *after* the attribute's definition (e.g. AugAssigns on lists) 2808 if len(attributes) > 1: 2809 first_attr, attributes = attributes[0], attributes[1:] 2810 first_scope = first_attr.scope() 2811 attributes = [first_attr] + [ 2812 attr 2813 for attr in attributes 2814 if attr.parent and attr.parent.scope() == first_scope 2815 ] 2816 2817 for inferred in bases._infer_stmts(attributes, context, frame=self): 2818 # yield Uninferable object instead of descriptors when necessary 2819 if not isinstance(inferred, node_classes.Const) and isinstance( 2820 inferred, bases.Instance 2821 ): 2822 try: 2823 inferred._proxied.getattr("__get__", context) 2824 except AttributeInferenceError: 2825 yield inferred 2826 else: 2827 yield util.Uninferable 2828 elif isinstance(inferred, objects.Property): 2829 function = inferred.function 2830 if not class_context: 2831 # Through an instance so we can solve the property 2832 yield from function.infer_call_result( 2833 caller=self, context=context 2834 ) 2835 # If we're in a class context, we need to determine if the property 2836 # was defined in the metaclass (a derived class must be a subclass of 2837 # the metaclass of all its bases), in which case we can resolve the 2838 # property. If not, i.e. the property is defined in some base class 2839 # instead, then we return the property object 2840 elif metaclass and function.parent.scope() is metaclass: 2841 # Resolve a property as long as it is not accessed through 2842 # the class itself. 2843 yield from function.infer_call_result( 2844 caller=self, context=context 2845 ) 2846 else: 2847 yield inferred 2848 else: 2849 yield function_to_method(inferred, self) 2850 except AttributeInferenceError as error: 2851 if not name.startswith("__") and self.has_dynamic_getattr(context): 2852 # class handle some dynamic attributes, return a Uninferable object 2853 yield util.Uninferable 2854 else: 2855 raise InferenceError( 2856 str(error), target=self, attribute=name, context=context 2857 ) from error 2858 2859 def has_dynamic_getattr(self, context=None): 2860 """Check if the class has a custom __getattr__ or __getattribute__. 2861 2862 If any such method is found and it is not from 2863 builtins, nor from an extension module, then the function 2864 will return True. 2865 2866 :returns: True if the class has a custom 2867 __getattr__ or __getattribute__, False otherwise. 2868 :rtype: bool 2869 """ 2870 2871 def _valid_getattr(node): 2872 root = node.root() 2873 return root.name != "builtins" and getattr(root, "pure_python", None) 2874 2875 try: 2876 return _valid_getattr(self.getattr("__getattr__", context)[0]) 2877 except AttributeInferenceError: 2878 # if self.newstyle: XXX cause an infinite recursion error 2879 try: 2880 getattribute = self.getattr("__getattribute__", context)[0] 2881 return _valid_getattr(getattribute) 2882 except AttributeInferenceError: 2883 pass 2884 return False 2885 2886 def getitem(self, index, context=None): 2887 """Return the inference of a subscript. 2888 2889 This is basically looking up the method in the metaclass and calling it. 2890 2891 :returns: The inferred value of a subscript to this class. 2892 :rtype: NodeNG 2893 2894 :raises AstroidTypeError: If this class does not define a 2895 ``__getitem__`` method. 2896 """ 2897 try: 2898 methods = lookup(self, "__getitem__") 2899 except AttributeInferenceError as exc: 2900 if isinstance(self, ClassDef): 2901 # subscripting a class definition may be 2902 # achieved thanks to __class_getitem__ method 2903 # which is a classmethod defined in the class 2904 # that supports subscript and not in the metaclass 2905 try: 2906 methods = self.getattr("__class_getitem__") 2907 # Here it is assumed that the __class_getitem__ node is 2908 # a FunctionDef. One possible improvement would be to deal 2909 # with more generic inference. 2910 except AttributeInferenceError: 2911 raise AstroidTypeError(node=self, context=context) from exc 2912 else: 2913 raise AstroidTypeError(node=self, context=context) from exc 2914 2915 method = methods[0] 2916 2917 # Create a new callcontext for providing index as an argument. 2918 new_context = bind_context_to_node(context, self) 2919 new_context.callcontext = CallContext(args=[index], callee=method) 2920 2921 try: 2922 return next(method.infer_call_result(self, new_context), util.Uninferable) 2923 except AttributeError: 2924 # Starting with python3.9, builtin types list, dict etc... 2925 # are subscriptable thanks to __class_getitem___ classmethod. 2926 # However in such case the method is bound to an EmptyNode and 2927 # EmptyNode doesn't have infer_call_result method yielding to 2928 # AttributeError 2929 if ( 2930 isinstance(method, node_classes.EmptyNode) 2931 and self.name in {"list", "dict", "set", "tuple", "frozenset"} 2932 and PY39_PLUS 2933 ): 2934 return self 2935 raise 2936 except InferenceError: 2937 return util.Uninferable 2938 2939 def methods(self): 2940 """Iterate over all of the method defined in this class and its parents. 2941 2942 :returns: The methods defined on the class. 2943 :rtype: iterable(FunctionDef) 2944 """ 2945 done = {} 2946 for astroid in itertools.chain(iter((self,)), self.ancestors()): 2947 for meth in astroid.mymethods(): 2948 if meth.name in done: 2949 continue 2950 done[meth.name] = None 2951 yield meth 2952 2953 def mymethods(self): 2954 """Iterate over all of the method defined in this class only. 2955 2956 :returns: The methods defined on the class. 2957 :rtype: iterable(FunctionDef) 2958 """ 2959 for member in self.values(): 2960 if isinstance(member, FunctionDef): 2961 yield member 2962 2963 def implicit_metaclass(self): 2964 """Get the implicit metaclass of the current class. 2965 2966 For newstyle classes, this will return an instance of builtins.type. 2967 For oldstyle classes, it will simply return None, since there's 2968 no implicit metaclass there. 2969 2970 :returns: The metaclass. 2971 :rtype: builtins.type or None 2972 """ 2973 if self.newstyle: 2974 return builtin_lookup("type")[1][0] 2975 return None 2976 2977 _metaclass = None 2978 2979 def declared_metaclass(self, context=None): 2980 """Return the explicit declared metaclass for the current class. 2981 2982 An explicit declared metaclass is defined 2983 either by passing the ``metaclass`` keyword argument 2984 in the class definition line (Python 3) or (Python 2) by 2985 having a ``__metaclass__`` class attribute, or if there are 2986 no explicit bases but there is a global ``__metaclass__`` variable. 2987 2988 :returns: The metaclass of this class, 2989 or None if one could not be found. 2990 :rtype: NodeNG or None 2991 """ 2992 for base in self.bases: 2993 try: 2994 for baseobj in base.infer(context=context): 2995 if isinstance(baseobj, ClassDef) and baseobj.hide: 2996 self._metaclass = baseobj._metaclass 2997 self._metaclass_hack = True 2998 break 2999 except InferenceError: 3000 pass 3001 3002 if self._metaclass: 3003 # Expects this from Py3k TreeRebuilder 3004 try: 3005 return next( 3006 node 3007 for node in self._metaclass.infer(context=context) 3008 if node is not util.Uninferable 3009 ) 3010 except (InferenceError, StopIteration): 3011 return None 3012 3013 return None 3014 3015 def _find_metaclass(self, seen=None, context=None): 3016 if seen is None: 3017 seen = set() 3018 seen.add(self) 3019 3020 klass = self.declared_metaclass(context=context) 3021 if klass is None: 3022 for parent in self.ancestors(context=context): 3023 if parent not in seen: 3024 klass = parent._find_metaclass(seen) 3025 if klass is not None: 3026 break 3027 return klass 3028 3029 def metaclass(self, context=None): 3030 """Get the metaclass of this class. 3031 3032 If this class does not define explicitly a metaclass, 3033 then the first defined metaclass in ancestors will be used 3034 instead. 3035 3036 :returns: The metaclass of this class. 3037 :rtype: NodeNG or None 3038 """ 3039 return self._find_metaclass(context=context) 3040 3041 def has_metaclass_hack(self): 3042 return self._metaclass_hack 3043 3044 def _islots(self): 3045 """Return an iterator with the inferred slots.""" 3046 if "__slots__" not in self.locals: 3047 return None 3048 for slots in self.igetattr("__slots__"): 3049 # check if __slots__ is a valid type 3050 for meth in ITER_METHODS: 3051 try: 3052 slots.getattr(meth) 3053 break 3054 except AttributeInferenceError: 3055 continue 3056 else: 3057 continue 3058 3059 if isinstance(slots, node_classes.Const): 3060 # a string. Ignore the following checks, 3061 # but yield the node, only if it has a value 3062 if slots.value: 3063 yield slots 3064 continue 3065 if not hasattr(slots, "itered"): 3066 # we can't obtain the values, maybe a .deque? 3067 continue 3068 3069 if isinstance(slots, node_classes.Dict): 3070 values = [item[0] for item in slots.items] 3071 else: 3072 values = slots.itered() 3073 if values is util.Uninferable: 3074 continue 3075 if not values: 3076 # Stop the iteration, because the class 3077 # has an empty list of slots. 3078 return values 3079 3080 for elt in values: 3081 try: 3082 for inferred in elt.infer(): 3083 if inferred is util.Uninferable: 3084 continue 3085 if not isinstance( 3086 inferred, node_classes.Const 3087 ) or not isinstance(inferred.value, str): 3088 continue 3089 if not inferred.value: 3090 continue 3091 yield inferred 3092 except InferenceError: 3093 continue 3094 3095 return None 3096 3097 def _slots(self): 3098 if not self.newstyle: 3099 raise NotImplementedError( 3100 "The concept of slots is undefined for old-style classes." 3101 ) 3102 3103 slots = self._islots() 3104 try: 3105 first = next(slots) 3106 except StopIteration as exc: 3107 # The class doesn't have a __slots__ definition or empty slots. 3108 if exc.args and exc.args[0] not in ("", None): 3109 return exc.args[0] 3110 return None 3111 return [first] + list(slots) 3112 3113 # Cached, because inferring them all the time is expensive 3114 @decorators_mod.cached 3115 def slots(self): 3116 """Get all the slots for this node. 3117 3118 :returns: The names of slots for this class. 3119 If the class doesn't define any slot, through the ``__slots__`` 3120 variable, then this function will return a None. 3121 Also, it will return None in the case the slots were not inferred. 3122 :rtype: list(str) or None 3123 """ 3124 3125 def grouped_slots( 3126 mro: List["ClassDef"], 3127 ) -> typing.Iterator[Optional[node_classes.NodeNG]]: 3128 # Not interested in object, since it can't have slots. 3129 for cls in mro[:-1]: 3130 try: 3131 cls_slots = cls._slots() 3132 except NotImplementedError: 3133 continue 3134 if cls_slots is not None: 3135 yield from cls_slots 3136 else: 3137 yield None 3138 3139 if not self.newstyle: 3140 raise NotImplementedError( 3141 "The concept of slots is undefined for old-style classes." 3142 ) 3143 3144 try: 3145 mro = self.mro() 3146 except MroError as e: 3147 raise NotImplementedError( 3148 "Cannot get slots while parsing mro fails." 3149 ) from e 3150 3151 slots = list(grouped_slots(mro)) 3152 if not all(slot is not None for slot in slots): 3153 return None 3154 3155 return sorted(set(slots), key=lambda item: item.value) 3156 3157 def _inferred_bases(self, context=None): 3158 # Similar with .ancestors, but the difference is when one base is inferred, 3159 # only the first object is wanted. That's because 3160 # we aren't interested in superclasses, as in the following 3161 # example: 3162 # 3163 # class SomeSuperClass(object): pass 3164 # class SomeClass(SomeSuperClass): pass 3165 # class Test(SomeClass): pass 3166 # 3167 # Inferring SomeClass from the Test's bases will give 3168 # us both SomeClass and SomeSuperClass, but we are interested 3169 # only in SomeClass. 3170 3171 if context is None: 3172 context = InferenceContext() 3173 if not self.bases and self.qname() != "builtins.object": 3174 yield builtin_lookup("object")[1][0] 3175 return 3176 3177 for stmt in self.bases: 3178 try: 3179 # Find the first non-None inferred base value 3180 baseobj = next( 3181 b 3182 for b in stmt.infer(context=context.clone()) 3183 if not (isinstance(b, Const) and b.value is None) 3184 ) 3185 except (InferenceError, StopIteration): 3186 continue 3187 if isinstance(baseobj, bases.Instance): 3188 baseobj = baseobj._proxied 3189 if not isinstance(baseobj, ClassDef): 3190 continue 3191 if not baseobj.hide: 3192 yield baseobj 3193 else: 3194 yield from baseobj.bases 3195 3196 def _compute_mro(self, context=None): 3197 inferred_bases = list(self._inferred_bases(context=context)) 3198 bases_mro = [] 3199 for base in inferred_bases: 3200 if base is self: 3201 continue 3202 3203 try: 3204 mro = base._compute_mro(context=context) 3205 bases_mro.append(mro) 3206 except NotImplementedError: 3207 # Some classes have in their ancestors both newstyle and 3208 # old style classes. For these we can't retrieve the .mro, 3209 # although in Python it's possible, since the class we are 3210 # currently working is in fact new style. 3211 # So, we fallback to ancestors here. 3212 ancestors = list(base.ancestors(context=context)) 3213 bases_mro.append(ancestors) 3214 3215 unmerged_mro = [[self]] + bases_mro + [inferred_bases] 3216 unmerged_mro = list(clean_duplicates_mro(unmerged_mro, self, context)) 3217 clean_typing_generic_mro(unmerged_mro) 3218 return _c3_merge(unmerged_mro, self, context) 3219 3220 def mro(self, context=None) -> List["ClassDef"]: 3221 """Get the method resolution order, using C3 linearization. 3222 3223 :returns: The list of ancestors, sorted by the mro. 3224 :rtype: list(NodeNG) 3225 :raises DuplicateBasesError: Duplicate bases in the same class base 3226 :raises InconsistentMroError: A class' MRO is inconsistent 3227 """ 3228 return self._compute_mro(context=context) 3229 3230 def bool_value(self, context=None): 3231 """Determine the boolean value of this node. 3232 3233 :returns: The boolean value of this node. 3234 For a :class:`ClassDef` this is always ``True``. 3235 :rtype: bool 3236 """ 3237 return True 3238 3239 def get_children(self): 3240 if self.decorators is not None: 3241 yield self.decorators 3242 3243 yield from self.bases 3244 if self.keywords is not None: 3245 yield from self.keywords 3246 yield from self.body 3247 3248 @decorators_mod.cached 3249 def _get_assign_nodes(self): 3250 children_assign_nodes = ( 3251 child_node._get_assign_nodes() for child_node in self.body 3252 ) 3253 return list(itertools.chain.from_iterable(children_assign_nodes)) 3254 3255 def frame(self: T) -> T: 3256 """The node's frame node. 3257 3258 A frame node is a :class:`Module`, :class:`FunctionDef`, 3259 :class:`ClassDef` or :class:`Lambda`. 3260 3261 :returns: The node itself. 3262 """ 3263 return self 3264