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