1# Copyright (c) 2009-2011, 2013-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
2# Copyright (c) 2010 Daniel Harding <dharding@gmail.com>
3# Copyright (c) 2012 FELD Boris <lothiraldan@gmail.com>
4# Copyright (c) 2013-2014 Google, Inc.
5# Copyright (c) 2014-2021 Claudiu Popa <pcmanticore@gmail.com>
6# Copyright (c) 2014 Eevee (Alex Munroe) <amunroe@yelp.com>
7# Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
8# Copyright (c) 2015 Florian Bruhin <me@the-compiler.org>
9# Copyright (c) 2016-2017 Derek Gustafson <degustaf@gmail.com>
10# Copyright (c) 2016 Jared Garst <jgarst@users.noreply.github.com>
11# Copyright (c) 2016 Jakub Wilk <jwilk@jwilk.net>
12# Copyright (c) 2016 Dave Baum <dbaum@google.com>
13# Copyright (c) 2017-2020 Ashley Whetter <ashley@awhetter.co.uk>
14# Copyright (c) 2017, 2019 Łukasz Rogalski <rogalski.91@gmail.com>
15# Copyright (c) 2017 rr- <rr-@sakuya.pl>
16# Copyright (c) 2018, 2021 Nick Drozd <nicholasdrozd@gmail.com>
17# Copyright (c) 2018-2021 hippo91 <guillaume.peillex@gmail.com>
18# Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
19# Copyright (c) 2018 Ville Skyttä <ville.skytta@iki.fi>
20# Copyright (c) 2018 brendanator <brendan.maginnis@gmail.com>
21# Copyright (c) 2018 HoverHell <hoverhell@gmail.com>
22# Copyright (c) 2019 kavins14 <kavin.singh@mail.utoronto.ca>
23# Copyright (c) 2019 kavins14 <kavinsingh@hotmail.com>
24# Copyright (c) 2020 Raphael Gaschignard <raphael@rtpg.co>
25# Copyright (c) 2020 Bryce Guinta <bryce.guinta@protonmail.com>
26# Copyright (c) 2021 Marc Mueller <30130371+cdce8p@users.noreply.github.com>
27# Copyright (c) 2021 Pierre Sassoulas <pierre.sassoulas@gmail.com>
28# Copyright (c) 2021 Daniël van Noord <13665637+DanielNoord@users.noreply.github.com>
29# Copyright (c) 2021 David Liu <david@cs.toronto.edu>
30# Copyright (c) 2021 Alphadelta14 <alpha@alphaservcomputing.solutions>
31# Copyright (c) 2021 Andrew Haigh <hello@nelf.in>
32# Copyright (c) 2021 Federico Bond <federicobond@gmail.com>
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"""Module for some node classes. More nodes in scoped_nodes.py"""
38
39import abc
40import itertools
41import sys
42import typing
43import warnings
44from functools import lru_cache
45from typing import TYPE_CHECKING, Callable, Generator, Optional
46
47from astroid import decorators, mixins, util
48from astroid.bases import Instance, _infer_stmts
49from astroid.const import Context
50from astroid.context import InferenceContext
51from astroid.exceptions import (
52    AstroidIndexError,
53    AstroidTypeError,
54    InferenceError,
55    NoDefault,
56    ParentMissingError,
57)
58from astroid.manager import AstroidManager
59from astroid.nodes.const import OP_PRECEDENCE
60from astroid.nodes.node_ng import NodeNG
61
62if sys.version_info >= (3, 8):
63    from typing import Literal
64else:
65    from typing_extensions import Literal
66
67if TYPE_CHECKING:
68    from astroid.nodes import LocalsDictNodeNG
69
70
71def _is_const(value):
72    return isinstance(value, tuple(CONST_CLS))
73
74
75@decorators.raise_if_nothing_inferred
76def unpack_infer(stmt, context=None):
77    """recursively generate nodes inferred by the given statement.
78    If the inferred value is a list or a tuple, recurse on the elements
79    """
80    if isinstance(stmt, (List, Tuple)):
81        for elt in stmt.elts:
82            if elt is util.Uninferable:
83                yield elt
84                continue
85            yield from unpack_infer(elt, context)
86        return dict(node=stmt, context=context)
87    # if inferred is a final node, return it and stop
88    inferred = next(stmt.infer(context), util.Uninferable)
89    if inferred is stmt:
90        yield inferred
91        return dict(node=stmt, context=context)
92    # else, infer recursively, except Uninferable object that should be returned as is
93    for inferred in stmt.infer(context):
94        if inferred is util.Uninferable:
95            yield inferred
96        else:
97            yield from unpack_infer(inferred, context)
98
99    return dict(node=stmt, context=context)
100
101
102def are_exclusive(stmt1, stmt2, exceptions: Optional[typing.List[str]] = None) -> bool:
103    """return true if the two given statements are mutually exclusive
104
105    `exceptions` may be a list of exception names. If specified, discard If
106    branches and check one of the statement is in an exception handler catching
107    one of the given exceptions.
108
109    algorithm :
110     1) index stmt1's parents
111     2) climb among stmt2's parents until we find a common parent
112     3) if the common parent is a If or TryExcept statement, look if nodes are
113        in exclusive branches
114    """
115    # index stmt1's parents
116    stmt1_parents = {}
117    children = {}
118    previous = stmt1
119    for node in stmt1.node_ancestors():
120        stmt1_parents[node] = 1
121        children[node] = previous
122        previous = node
123    # climb among stmt2's parents until we find a common parent
124    previous = stmt2
125    for node in stmt2.node_ancestors():
126        if node in stmt1_parents:
127            # if the common parent is a If or TryExcept statement, look if
128            # nodes are in exclusive branches
129            if isinstance(node, If) and exceptions is None:
130                if (
131                    node.locate_child(previous)[1]
132                    is not node.locate_child(children[node])[1]
133                ):
134                    return True
135            elif isinstance(node, TryExcept):
136                c2attr, c2node = node.locate_child(previous)
137                c1attr, c1node = node.locate_child(children[node])
138                if c1node is not c2node:
139                    first_in_body_caught_by_handlers = (
140                        c2attr == "handlers"
141                        and c1attr == "body"
142                        and previous.catch(exceptions)
143                    )
144                    second_in_body_caught_by_handlers = (
145                        c2attr == "body"
146                        and c1attr == "handlers"
147                        and children[node].catch(exceptions)
148                    )
149                    first_in_else_other_in_handlers = (
150                        c2attr == "handlers" and c1attr == "orelse"
151                    )
152                    second_in_else_other_in_handlers = (
153                        c2attr == "orelse" and c1attr == "handlers"
154                    )
155                    if any(
156                        (
157                            first_in_body_caught_by_handlers,
158                            second_in_body_caught_by_handlers,
159                            first_in_else_other_in_handlers,
160                            second_in_else_other_in_handlers,
161                        )
162                    ):
163                        return True
164                elif c2attr == "handlers" and c1attr == "handlers":
165                    return previous is not children[node]
166            return False
167        previous = node
168    return False
169
170
171# getitem() helpers.
172
173_SLICE_SENTINEL = object()
174
175
176def _slice_value(index, context=None):
177    """Get the value of the given slice index."""
178
179    if isinstance(index, Const):
180        if isinstance(index.value, (int, type(None))):
181            return index.value
182    elif index is None:
183        return None
184    else:
185        # Try to infer what the index actually is.
186        # Since we can't return all the possible values,
187        # we'll stop at the first possible value.
188        try:
189            inferred = next(index.infer(context=context))
190        except (InferenceError, StopIteration):
191            pass
192        else:
193            if isinstance(inferred, Const):
194                if isinstance(inferred.value, (int, type(None))):
195                    return inferred.value
196
197    # Use a sentinel, because None can be a valid
198    # value that this function can return,
199    # as it is the case for unspecified bounds.
200    return _SLICE_SENTINEL
201
202
203def _infer_slice(node, context=None):
204    lower = _slice_value(node.lower, context)
205    upper = _slice_value(node.upper, context)
206    step = _slice_value(node.step, context)
207    if all(elem is not _SLICE_SENTINEL for elem in (lower, upper, step)):
208        return slice(lower, upper, step)
209
210    raise AstroidTypeError(
211        message="Could not infer slice used in subscript",
212        node=node,
213        index=node.parent,
214        context=context,
215    )
216
217
218def _container_getitem(instance, elts, index, context=None):
219    """Get a slice or an item, using the given *index*, for the given sequence."""
220    try:
221        if isinstance(index, Slice):
222            index_slice = _infer_slice(index, context=context)
223            new_cls = instance.__class__()
224            new_cls.elts = elts[index_slice]
225            new_cls.parent = instance.parent
226            return new_cls
227        if isinstance(index, Const):
228            return elts[index.value]
229    except IndexError as exc:
230        raise AstroidIndexError(
231            message="Index {index!s} out of range",
232            node=instance,
233            index=index,
234            context=context,
235        ) from exc
236    except TypeError as exc:
237        raise AstroidTypeError(
238            message="Type error {error!r}", node=instance, index=index, context=context
239        ) from exc
240
241    raise AstroidTypeError(f"Could not use {index} as subscript index")
242
243
244class Statement(NodeNG):
245    """Statement node adding a few attributes"""
246
247    is_statement = True
248    """Whether this node indicates a statement."""
249
250    def next_sibling(self):
251        """The next sibling statement node.
252
253        :returns: The next sibling statement node.
254        :rtype: NodeNG or None
255        """
256        stmts = self.parent.child_sequence(self)
257        index = stmts.index(self)
258        try:
259            return stmts[index + 1]
260        except IndexError:
261            return None
262
263    def previous_sibling(self):
264        """The previous sibling statement.
265
266        :returns: The previous sibling statement node.
267        :rtype: NodeNG or None
268        """
269        stmts = self.parent.child_sequence(self)
270        index = stmts.index(self)
271        if index >= 1:
272            return stmts[index - 1]
273        return None
274
275
276class BaseContainer(
277    mixins.ParentAssignTypeMixin, NodeNG, Instance, metaclass=abc.ABCMeta
278):
279    """Base class for Set, FrozenSet, Tuple and List."""
280
281    _astroid_fields = ("elts",)
282
283    def __init__(
284        self,
285        lineno: Optional[int] = None,
286        col_offset: Optional[int] = None,
287        parent: Optional[NodeNG] = None,
288        *,
289        end_lineno: Optional[int] = None,
290        end_col_offset: Optional[int] = None,
291    ) -> None:
292        """
293        :param lineno: The line that this node appears on in the source code.
294
295        :param col_offset: The column that this node appears on in the
296            source code.
297
298        :param parent: The parent node in the syntax tree.
299
300        :param end_lineno: The last line this node appears on in the source code.
301
302        :param end_col_offset: The end column this node appears on in the
303            source code. Note: This is after the last symbol.
304        """
305        self.elts: typing.List[NodeNG] = []
306        """The elements in the node."""
307
308        super().__init__(
309            lineno=lineno,
310            col_offset=col_offset,
311            end_lineno=end_lineno,
312            end_col_offset=end_col_offset,
313            parent=parent,
314        )
315
316    def postinit(self, elts: typing.List[NodeNG]) -> None:
317        """Do some setup after initialisation.
318
319        :param elts: The list of elements the that node contains.
320        """
321        self.elts = elts
322
323    @classmethod
324    def from_elements(cls, elts=None):
325        """Create a node of this type from the given list of elements.
326
327        :param elts: The list of elements that the node should contain.
328        :type elts: list(NodeNG)
329
330        :returns: A new node containing the given elements.
331        :rtype: NodeNG
332        """
333        node = cls()
334        if elts is None:
335            node.elts = []
336        else:
337            node.elts = [const_factory(e) if _is_const(e) else e for e in elts]
338        return node
339
340    def itered(self):
341        """An iterator over the elements this node contains.
342
343        :returns: The contents of this node.
344        :rtype: iterable(NodeNG)
345        """
346        return self.elts
347
348    def bool_value(self, context=None):
349        """Determine the boolean value of this node.
350
351        :returns: The boolean value of this node.
352        :rtype: bool or Uninferable
353        """
354        return bool(self.elts)
355
356    @abc.abstractmethod
357    def pytype(self):
358        """Get the name of the type that this node represents.
359
360        :returns: The name of the type.
361        :rtype: str
362        """
363
364    def get_children(self):
365        yield from self.elts
366
367
368class LookupMixIn:
369    """Mixin to look up a name in the right scope."""
370
371    @lru_cache(maxsize=None)
372    def lookup(self, name):
373        """Lookup where the given variable is assigned.
374
375        The lookup starts from self's scope. If self is not a frame itself
376        and the name is found in the inner frame locals, statements will be
377        filtered to remove ignorable statements according to self's location.
378
379        :param name: The name of the variable to find assignments for.
380        :type name: str
381
382        :returns: The scope node and the list of assignments associated to the
383            given name according to the scope where it has been found (locals,
384            globals or builtin).
385        :rtype: tuple(str, list(NodeNG))
386        """
387        return self.scope().scope_lookup(self, name)
388
389    def ilookup(self, name):
390        """Lookup the inferred values of the given variable.
391
392        :param name: The variable name to find values for.
393        :type name: str
394
395        :returns: The inferred values of the statements returned from
396            :meth:`lookup`.
397        :rtype: iterable
398        """
399        frame, stmts = self.lookup(name)
400        context = InferenceContext()
401        return _infer_stmts(stmts, context, frame)
402
403    def _get_filtered_node_statements(self, nodes):
404        statements = [(node, node.statement()) for node in nodes]
405        # Next we check if we have ExceptHandlers that are parent
406        # of the underlying variable, in which case the last one survives
407        if len(statements) > 1 and all(
408            isinstance(stmt, ExceptHandler) for _, stmt in statements
409        ):
410            statements = [
411                (node, stmt) for node, stmt in statements if stmt.parent_of(self)
412            ]
413        return statements
414
415    def _filter_stmts(self, stmts, frame, offset):
416        """Filter the given list of statements to remove ignorable statements.
417
418        If self is not a frame itself and the name is found in the inner
419        frame locals, statements will be filtered to remove ignorable
420        statements according to self's location.
421
422        :param stmts: The statements to filter.
423        :type stmts: list(NodeNG)
424
425        :param frame: The frame that all of the given statements belong to.
426        :type frame: NodeNG
427
428        :param offset: The line offset to filter statements up to.
429        :type offset: int
430
431        :returns: The filtered statements.
432        :rtype: list(NodeNG)
433        """
434        # if offset == -1, my actual frame is not the inner frame but its parent
435        #
436        # class A(B): pass
437        #
438        # we need this to resolve B correctly
439        if offset == -1:
440            myframe = self.frame().parent.frame()
441        else:
442            myframe = self.frame()
443            # If the frame of this node is the same as the statement
444            # of this node, then the node is part of a class or
445            # a function definition and the frame of this node should be the
446            # the upper frame, not the frame of the definition.
447            # For more information why this is important,
448            # see Pylint issue #295.
449            # For example, for 'b', the statement is the same
450            # as the frame / scope:
451            #
452            # def test(b=1):
453            #     ...
454
455            if self.statement() is myframe and myframe.parent:
456                myframe = myframe.parent.frame()
457        mystmt = self.statement()
458        # line filtering if we are in the same frame
459        #
460        # take care node may be missing lineno information (this is the case for
461        # nodes inserted for living objects)
462        if myframe is frame and mystmt.fromlineno is not None:
463            assert mystmt.fromlineno is not None, mystmt
464            mylineno = mystmt.fromlineno + offset
465        else:
466            # disabling lineno filtering
467            mylineno = 0
468
469        _stmts = []
470        _stmt_parents = []
471        statements = self._get_filtered_node_statements(stmts)
472        for node, stmt in statements:
473            # line filtering is on and we have reached our location, break
474            if stmt.fromlineno and stmt.fromlineno > mylineno > 0:
475                break
476            # Ignore decorators with the same name as the
477            # decorated function
478            # Fixes issue #375
479            if mystmt is stmt and is_from_decorator(self):
480                continue
481            assert hasattr(node, "assign_type"), (
482                node,
483                node.scope(),
484                node.scope().locals,
485            )
486            assign_type = node.assign_type()
487            if node.has_base(self):
488                break
489
490            _stmts, done = assign_type._get_filtered_stmts(self, node, _stmts, mystmt)
491            if done:
492                break
493
494            optional_assign = assign_type.optional_assign
495            if optional_assign and assign_type.parent_of(self):
496                # we are inside a loop, loop var assignment is hiding previous
497                # assignment
498                _stmts = [node]
499                _stmt_parents = [stmt.parent]
500                continue
501
502            if isinstance(assign_type, NamedExpr):
503                # If the NamedExpr is in an if statement we do some basic control flow inference
504                if_parent = _get_if_statement_ancestor(assign_type)
505                if if_parent:
506                    # If the if statement is within another if statement we append the node
507                    # to possible statements
508                    if _get_if_statement_ancestor(if_parent):
509                        optional_assign = False
510                        _stmts.append(node)
511                        _stmt_parents.append(stmt.parent)
512                    # If the if statement is first-level and not within an orelse block
513                    # we know that it will be evaluated
514                    elif not if_parent.is_orelse:
515                        _stmts = [node]
516                        _stmt_parents = [stmt.parent]
517                    # Else we do not known enough about the control flow to be 100% certain
518                    # and we append to possible statements
519                    else:
520                        _stmts.append(node)
521                        _stmt_parents.append(stmt.parent)
522                else:
523                    _stmts = [node]
524                    _stmt_parents = [stmt.parent]
525
526            # XXX comment various branches below!!!
527            try:
528                pindex = _stmt_parents.index(stmt.parent)
529            except ValueError:
530                pass
531            else:
532                # we got a parent index, this means the currently visited node
533                # is at the same block level as a previously visited node
534                if _stmts[pindex].assign_type().parent_of(assign_type):
535                    # both statements are not at the same block level
536                    continue
537                # if currently visited node is following previously considered
538                # assignment and both are not exclusive, we can drop the
539                # previous one. For instance in the following code ::
540                #
541                #   if a:
542                #     x = 1
543                #   else:
544                #     x = 2
545                #   print x
546                #
547                # we can't remove neither x = 1 nor x = 2 when looking for 'x'
548                # of 'print x'; while in the following ::
549                #
550                #   x = 1
551                #   x = 2
552                #   print x
553                #
554                # we can remove x = 1 when we see x = 2
555                #
556                # moreover, on loop assignment types, assignment won't
557                # necessarily be done if the loop has no iteration, so we don't
558                # want to clear previous assignments if any (hence the test on
559                # optional_assign)
560                if not (optional_assign or are_exclusive(_stmts[pindex], node)):
561                    del _stmt_parents[pindex]
562                    del _stmts[pindex]
563
564            # If self and node are exclusive, then we can ignore node
565            if are_exclusive(self, node):
566                continue
567
568            # An AssignName node overrides previous assignments if:
569            #   1. node's statement always assigns
570            #   2. node and self are in the same block (i.e., has the same parent as self)
571            if isinstance(node, (NamedExpr, AssignName)):
572                if isinstance(stmt, ExceptHandler):
573                    # If node's statement is an ExceptHandler, then it is the variable
574                    # bound to the caught exception. If self is not contained within
575                    # the exception handler block, node should override previous assignments;
576                    # otherwise, node should be ignored, as an exception variable
577                    # is local to the handler block.
578                    if stmt.parent_of(self):
579                        _stmts = []
580                        _stmt_parents = []
581                    else:
582                        continue
583                elif not optional_assign and stmt.parent is mystmt.parent:
584                    _stmts = []
585                    _stmt_parents = []
586            elif isinstance(node, DelName):
587                # Remove all previously stored assignments
588                _stmts = []
589                _stmt_parents = []
590                continue
591            # Add the new assignment
592            _stmts.append(node)
593            if isinstance(node, Arguments) or isinstance(node.parent, Arguments):
594                # Special case for _stmt_parents when node is a function parameter;
595                # in this case, stmt is the enclosing FunctionDef, which is what we
596                # want to add to _stmt_parents, not stmt.parent. This case occurs when
597                # node is an Arguments node (representing varargs or kwargs parameter),
598                # and when node.parent is an Arguments node (other parameters).
599                # See issue #180.
600                _stmt_parents.append(stmt)
601            else:
602                _stmt_parents.append(stmt.parent)
603        return _stmts
604
605
606# Name classes
607
608
609class AssignName(
610    mixins.NoChildrenMixin, LookupMixIn, mixins.ParentAssignTypeMixin, NodeNG
611):
612    """Variation of :class:`ast.Assign` representing assignment to a name.
613
614    An :class:`AssignName` is the name of something that is assigned to.
615    This includes variables defined in a function signature or in a loop.
616
617    >>> import astroid
618    >>> node = astroid.extract_node('variable = range(10)')
619    >>> node
620    <Assign l.1 at 0x7effe1db8550>
621    >>> list(node.get_children())
622    [<AssignName.variable l.1 at 0x7effe1db8748>, <Call l.1 at 0x7effe1db8630>]
623    >>> list(node.get_children())[0].as_string()
624    'variable'
625    """
626
627    _other_fields = ("name",)
628
629    @decorators.deprecate_default_argument_values(name="str")
630    def __init__(
631        self,
632        name: Optional[str] = None,
633        lineno: Optional[int] = None,
634        col_offset: Optional[int] = None,
635        parent: Optional[NodeNG] = None,
636        *,
637        end_lineno: Optional[int] = None,
638        end_col_offset: Optional[int] = None,
639    ) -> None:
640        """
641        :param name: The name that is assigned to.
642
643        :param lineno: The line that this node appears on in the source code.
644
645        :param col_offset: The column that this node appears on in the
646            source code.
647
648        :param parent: The parent node in the syntax tree.
649
650        :param end_lineno: The last line this node appears on in the source code.
651
652        :param end_col_offset: The end column this node appears on in the
653            source code. Note: This is after the last symbol.
654        """
655        self.name: Optional[str] = name
656        """The name that is assigned to."""
657
658        super().__init__(
659            lineno=lineno,
660            col_offset=col_offset,
661            end_lineno=end_lineno,
662            end_col_offset=end_col_offset,
663            parent=parent,
664        )
665
666
667class DelName(
668    mixins.NoChildrenMixin, LookupMixIn, mixins.ParentAssignTypeMixin, NodeNG
669):
670    """Variation of :class:`ast.Delete` representing deletion of a name.
671
672    A :class:`DelName` is the name of something that is deleted.
673
674    >>> import astroid
675    >>> node = astroid.extract_node("del variable #@")
676    >>> list(node.get_children())
677    [<DelName.variable l.1 at 0x7effe1da4d30>]
678    >>> list(node.get_children())[0].as_string()
679    'variable'
680    """
681
682    _other_fields = ("name",)
683
684    @decorators.deprecate_default_argument_values(name="str")
685    def __init__(
686        self,
687        name: Optional[str] = None,
688        lineno: Optional[int] = None,
689        col_offset: Optional[int] = None,
690        parent: Optional[NodeNG] = None,
691        *,
692        end_lineno: Optional[int] = None,
693        end_col_offset: Optional[int] = None,
694    ) -> None:
695        """
696        :param name: The name that is being deleted.
697
698        :param lineno: The line that this node appears on in the source code.
699
700        :param col_offset: The column that this node appears on in the
701            source code.
702
703        :param parent: The parent node in the syntax tree.
704
705        :param end_lineno: The last line this node appears on in the source code.
706
707        :param end_col_offset: The end column this node appears on in the
708            source code. Note: This is after the last symbol.
709        """
710        self.name: Optional[str] = name
711        """The name that is being deleted."""
712
713        super().__init__(
714            lineno=lineno,
715            col_offset=col_offset,
716            end_lineno=end_lineno,
717            end_col_offset=end_col_offset,
718            parent=parent,
719        )
720
721
722class Name(mixins.NoChildrenMixin, LookupMixIn, NodeNG):
723    """Class representing an :class:`ast.Name` node.
724
725    A :class:`Name` node is something that is named, but not covered by
726    :class:`AssignName` or :class:`DelName`.
727
728    >>> import astroid
729    >>> node = astroid.extract_node('range(10)')
730    >>> node
731    <Call l.1 at 0x7effe1db8710>
732    >>> list(node.get_children())
733    [<Name.range l.1 at 0x7effe1db86a0>, <Const.int l.1 at 0x7effe1db8518>]
734    >>> list(node.get_children())[0].as_string()
735    'range'
736    """
737
738    _other_fields = ("name",)
739
740    @decorators.deprecate_default_argument_values(name="str")
741    def __init__(
742        self,
743        name: Optional[str] = None,
744        lineno: Optional[int] = None,
745        col_offset: Optional[int] = None,
746        parent: Optional[NodeNG] = None,
747        *,
748        end_lineno: Optional[int] = None,
749        end_col_offset: Optional[int] = None,
750    ) -> None:
751        """
752        :param name: The name that this node refers to.
753
754        :param lineno: The line that this node appears on in the source code.
755
756        :param col_offset: The column that this node appears on in the
757            source code.
758
759        :param parent: The parent node in the syntax tree.
760
761        :param end_lineno: The last line this node appears on in the source code.
762
763        :param end_col_offset: The end column this node appears on in the
764            source code. Note: This is after the last symbol.
765        """
766        self.name: Optional[str] = name
767        """The name that this node refers to."""
768
769        super().__init__(
770            lineno=lineno,
771            col_offset=col_offset,
772            end_lineno=end_lineno,
773            end_col_offset=end_col_offset,
774            parent=parent,
775        )
776
777    def _get_name_nodes(self):
778        yield self
779
780        for child_node in self.get_children():
781            yield from child_node._get_name_nodes()
782
783
784class Arguments(mixins.AssignTypeMixin, NodeNG):
785    """Class representing an :class:`ast.arguments` node.
786
787    An :class:`Arguments` node represents that arguments in a
788    function definition.
789
790    >>> import astroid
791    >>> node = astroid.extract_node('def foo(bar): pass')
792    >>> node
793    <FunctionDef.foo l.1 at 0x7effe1db8198>
794    >>> node.args
795    <Arguments l.1 at 0x7effe1db82e8>
796    """
797
798    # Python 3.4+ uses a different approach regarding annotations,
799    # each argument is a new class, _ast.arg, which exposes an
800    # 'annotation' attribute. In astroid though, arguments are exposed
801    # as is in the Arguments node and the only way to expose annotations
802    # is by using something similar with Python 3.3:
803    #  - we expose 'varargannotation' and 'kwargannotation' of annotations
804    #    of varargs and kwargs.
805    #  - we expose 'annotation', a list with annotations for
806    #    for each normal argument. If an argument doesn't have an
807    #    annotation, its value will be None.
808    _astroid_fields = (
809        "args",
810        "defaults",
811        "kwonlyargs",
812        "posonlyargs",
813        "posonlyargs_annotations",
814        "kw_defaults",
815        "annotations",
816        "varargannotation",
817        "kwargannotation",
818        "kwonlyargs_annotations",
819        "type_comment_args",
820        "type_comment_kwonlyargs",
821        "type_comment_posonlyargs",
822    )
823
824    _other_fields = ("vararg", "kwarg")
825
826    lineno: None
827    col_offset: None
828    end_lineno: None
829    end_col_offset: None
830
831    def __init__(
832        self,
833        vararg: Optional[str] = None,
834        kwarg: Optional[str] = None,
835        parent: Optional[NodeNG] = None,
836    ) -> None:
837        """
838        :param vararg: The name of the variable length arguments.
839
840        :param kwarg: The name of the variable length keyword arguments.
841
842        :param parent: The parent node in the syntax tree.
843        """
844        super().__init__(parent=parent)
845
846        self.vararg: Optional[str] = vararg  # can be None
847        """The name of the variable length arguments."""
848
849        self.kwarg: Optional[str] = kwarg  # can be None
850        """The name of the variable length keyword arguments."""
851
852        self.args: typing.List[AssignName]
853        """The names of the required arguments."""
854
855        self.defaults: typing.List[NodeNG]
856        """The default values for arguments that can be passed positionally."""
857
858        self.kwonlyargs: typing.List[AssignName]
859        """The keyword arguments that cannot be passed positionally."""
860
861        self.posonlyargs: typing.List[AssignName] = []
862        """The arguments that can only be passed positionally."""
863
864        self.kw_defaults: typing.List[Optional[NodeNG]]
865        """The default values for keyword arguments that cannot be passed positionally."""
866
867        self.annotations: typing.List[Optional[NodeNG]]
868        """The type annotations of arguments that can be passed positionally."""
869
870        self.posonlyargs_annotations: typing.List[Optional[NodeNG]] = []
871        """The type annotations of arguments that can only be passed positionally."""
872
873        self.kwonlyargs_annotations: typing.List[Optional[NodeNG]] = []
874        """The type annotations of arguments that cannot be passed positionally."""
875
876        self.type_comment_args: typing.List[Optional[NodeNG]] = []
877        """The type annotation, passed by a type comment, of each argument.
878
879        If an argument does not have a type comment,
880        the value for that argument will be None.
881        """
882
883        self.type_comment_kwonlyargs: typing.List[Optional[NodeNG]] = []
884        """The type annotation, passed by a type comment, of each keyword only argument.
885
886        If an argument does not have a type comment,
887        the value for that argument will be None.
888        """
889
890        self.type_comment_posonlyargs: typing.List[Optional[NodeNG]] = []
891        """The type annotation, passed by a type comment, of each positional argument.
892
893        If an argument does not have a type comment,
894        the value for that argument will be None.
895        """
896
897        self.varargannotation: Optional[NodeNG] = None  # can be None
898        """The type annotation for the variable length arguments."""
899
900        self.kwargannotation: Optional[NodeNG] = None  # can be None
901        """The type annotation for the variable length keyword arguments."""
902
903    # pylint: disable=too-many-arguments
904    def postinit(
905        self,
906        args: typing.List[AssignName],
907        defaults: typing.List[NodeNG],
908        kwonlyargs: typing.List[AssignName],
909        kw_defaults: typing.List[Optional[NodeNG]],
910        annotations: typing.List[Optional[NodeNG]],
911        posonlyargs: Optional[typing.List[AssignName]] = None,
912        kwonlyargs_annotations: Optional[typing.List[Optional[NodeNG]]] = None,
913        posonlyargs_annotations: Optional[typing.List[Optional[NodeNG]]] = None,
914        varargannotation: Optional[NodeNG] = None,
915        kwargannotation: Optional[NodeNG] = None,
916        type_comment_args: Optional[typing.List[Optional[NodeNG]]] = None,
917        type_comment_kwonlyargs: Optional[typing.List[Optional[NodeNG]]] = None,
918        type_comment_posonlyargs: Optional[typing.List[Optional[NodeNG]]] = None,
919    ) -> None:
920        """Do some setup after initialisation.
921
922        :param args: The names of the required arguments.
923
924        :param defaults: The default values for arguments that can be passed
925            positionally.
926
927        :param kwonlyargs: The keyword arguments that cannot be passed
928            positionally.
929
930        :param posonlyargs: The arguments that can only be passed
931            positionally.
932
933        :param kw_defaults: The default values for keyword arguments that
934            cannot be passed positionally.
935
936        :param annotations: The type annotations of arguments that can be
937            passed positionally.
938
939        :param kwonlyargs_annotations: The type annotations of arguments that
940            cannot be passed positionally. This should always be passed in
941            Python 3.
942
943        :param posonlyargs_annotations: The type annotations of arguments that
944            can only be passed positionally. This should always be passed in
945            Python 3.
946
947        :param varargannotation: The type annotation for the variable length
948            arguments.
949
950        :param kwargannotation: The type annotation for the variable length
951            keyword arguments.
952
953        :param type_comment_args: The type annotation,
954            passed by a type comment, of each argument.
955
956        :param type_comment_args: The type annotation,
957            passed by a type comment, of each keyword only argument.
958
959        :param type_comment_args: The type annotation,
960            passed by a type comment, of each positional argument.
961        """
962        self.args = args
963        self.defaults = defaults
964        self.kwonlyargs = kwonlyargs
965        if posonlyargs is not None:
966            self.posonlyargs = posonlyargs
967        self.kw_defaults = kw_defaults
968        self.annotations = annotations
969        if kwonlyargs_annotations is not None:
970            self.kwonlyargs_annotations = kwonlyargs_annotations
971        if posonlyargs_annotations is not None:
972            self.posonlyargs_annotations = posonlyargs_annotations
973        self.varargannotation = varargannotation
974        self.kwargannotation = kwargannotation
975        if type_comment_args is not None:
976            self.type_comment_args = type_comment_args
977        if type_comment_kwonlyargs is not None:
978            self.type_comment_kwonlyargs = type_comment_kwonlyargs
979        if type_comment_posonlyargs is not None:
980            self.type_comment_posonlyargs = type_comment_posonlyargs
981
982    def _infer_name(self, frame, name):
983        if self.parent is frame:
984            return name
985        return None
986
987    @decorators.cachedproperty
988    def fromlineno(self):
989        """The first line that this node appears on in the source code.
990
991        :type: int or None
992        """
993        lineno = super().fromlineno
994        return max(lineno, self.parent.fromlineno or 0)
995
996    @decorators.cachedproperty
997    def arguments(self):
998        """Get all the arguments for this node, including positional only and positional and keyword"""
999        return list(itertools.chain((self.posonlyargs or ()), self.args or ()))
1000
1001    def format_args(self):
1002        """Get the arguments formatted as string.
1003
1004        :returns: The formatted arguments.
1005        :rtype: str
1006        """
1007        result = []
1008        positional_only_defaults = []
1009        positional_or_keyword_defaults = self.defaults
1010        if self.defaults:
1011            args = self.args or []
1012            positional_or_keyword_defaults = self.defaults[-len(args) :]
1013            positional_only_defaults = self.defaults[: len(self.defaults) - len(args)]
1014
1015        if self.posonlyargs:
1016            result.append(
1017                _format_args(
1018                    self.posonlyargs,
1019                    positional_only_defaults,
1020                    self.posonlyargs_annotations,
1021                )
1022            )
1023            result.append("/")
1024        if self.args:
1025            result.append(
1026                _format_args(
1027                    self.args,
1028                    positional_or_keyword_defaults,
1029                    getattr(self, "annotations", None),
1030                )
1031            )
1032        if self.vararg:
1033            result.append(f"*{self.vararg}")
1034        if self.kwonlyargs:
1035            if not self.vararg:
1036                result.append("*")
1037            result.append(
1038                _format_args(
1039                    self.kwonlyargs, self.kw_defaults, self.kwonlyargs_annotations
1040                )
1041            )
1042        if self.kwarg:
1043            result.append(f"**{self.kwarg}")
1044        return ", ".join(result)
1045
1046    def default_value(self, argname):
1047        """Get the default value for an argument.
1048
1049        :param argname: The name of the argument to get the default value for.
1050        :type argname: str
1051
1052        :raises NoDefault: If there is no default value defined for the
1053            given argument.
1054        """
1055        args = self.arguments
1056        index = _find_arg(argname, args)[0]
1057        if index is not None:
1058            idx = index - (len(args) - len(self.defaults))
1059            if idx >= 0:
1060                return self.defaults[idx]
1061        index = _find_arg(argname, self.kwonlyargs)[0]
1062        if index is not None and self.kw_defaults[index] is not None:
1063            return self.kw_defaults[index]
1064        raise NoDefault(func=self.parent, name=argname)
1065
1066    def is_argument(self, name):
1067        """Check if the given name is defined in the arguments.
1068
1069        :param name: The name to check for.
1070        :type name: str
1071
1072        :returns: True if the given name is defined in the arguments,
1073            False otherwise.
1074        :rtype: bool
1075        """
1076        if name == self.vararg:
1077            return True
1078        if name == self.kwarg:
1079            return True
1080        return (
1081            self.find_argname(name, rec=True)[1] is not None
1082            or self.kwonlyargs
1083            and _find_arg(name, self.kwonlyargs, rec=True)[1] is not None
1084        )
1085
1086    def find_argname(self, argname, rec=False):
1087        """Get the index and :class:`AssignName` node for given name.
1088
1089        :param argname: The name of the argument to search for.
1090        :type argname: str
1091
1092        :param rec: Whether or not to include arguments in unpacked tuples
1093            in the search.
1094        :type rec: bool
1095
1096        :returns: The index and node for the argument.
1097        :rtype: tuple(str or None, AssignName or None)
1098        """
1099        if self.arguments:
1100            return _find_arg(argname, self.arguments, rec)
1101        return None, None
1102
1103    def get_children(self):
1104        yield from self.posonlyargs or ()
1105
1106        for elt in self.posonlyargs_annotations:
1107            if elt is not None:
1108                yield elt
1109
1110        yield from self.args or ()
1111
1112        yield from self.defaults
1113        yield from self.kwonlyargs
1114
1115        for elt in self.kw_defaults:
1116            if elt is not None:
1117                yield elt
1118
1119        for elt in self.annotations:
1120            if elt is not None:
1121                yield elt
1122
1123        if self.varargannotation is not None:
1124            yield self.varargannotation
1125
1126        if self.kwargannotation is not None:
1127            yield self.kwargannotation
1128
1129        for elt in self.kwonlyargs_annotations:
1130            if elt is not None:
1131                yield elt
1132
1133
1134def _find_arg(argname, args, rec=False):
1135    for i, arg in enumerate(args):
1136        if isinstance(arg, Tuple):
1137            if rec:
1138                found = _find_arg(argname, arg.elts)
1139                if found[0] is not None:
1140                    return found
1141        elif arg.name == argname:
1142            return i, arg
1143    return None, None
1144
1145
1146def _format_args(args, defaults=None, annotations=None):
1147    values = []
1148    if args is None:
1149        return ""
1150    if annotations is None:
1151        annotations = []
1152    if defaults is not None:
1153        default_offset = len(args) - len(defaults)
1154    packed = itertools.zip_longest(args, annotations)
1155    for i, (arg, annotation) in enumerate(packed):
1156        if isinstance(arg, Tuple):
1157            values.append(f"({_format_args(arg.elts)})")
1158        else:
1159            argname = arg.name
1160            default_sep = "="
1161            if annotation is not None:
1162                argname += ": " + annotation.as_string()
1163                default_sep = " = "
1164            values.append(argname)
1165
1166            if defaults is not None and i >= default_offset:
1167                if defaults[i - default_offset] is not None:
1168                    values[-1] += default_sep + defaults[i - default_offset].as_string()
1169    return ", ".join(values)
1170
1171
1172class AssignAttr(mixins.ParentAssignTypeMixin, NodeNG):
1173    """Variation of :class:`ast.Assign` representing assignment to an attribute.
1174
1175    >>> import astroid
1176    >>> node = astroid.extract_node('self.attribute = range(10)')
1177    >>> node
1178    <Assign l.1 at 0x7effe1d521d0>
1179    >>> list(node.get_children())
1180    [<AssignAttr.attribute l.1 at 0x7effe1d52320>, <Call l.1 at 0x7effe1d522e8>]
1181    >>> list(node.get_children())[0].as_string()
1182    'self.attribute'
1183    """
1184
1185    _astroid_fields = ("expr",)
1186    _other_fields = ("attrname",)
1187
1188    @decorators.deprecate_default_argument_values(attrname="str")
1189    def __init__(
1190        self,
1191        attrname: Optional[str] = None,
1192        lineno: Optional[int] = None,
1193        col_offset: Optional[int] = None,
1194        parent: Optional[NodeNG] = None,
1195        *,
1196        end_lineno: Optional[int] = None,
1197        end_col_offset: Optional[int] = None,
1198    ) -> None:
1199        """
1200        :param attrname: The name of the attribute being assigned to.
1201
1202        :param lineno: The line that this node appears on in the source code.
1203
1204        :param col_offset: The column that this node appears on in the
1205            source code.
1206
1207        :param parent: The parent node in the syntax tree.
1208
1209        :param end_lineno: The last line this node appears on in the source code.
1210
1211        :param end_col_offset: The end column this node appears on in the
1212            source code. Note: This is after the last symbol.
1213        """
1214        self.expr: Optional[NodeNG] = None
1215        """What has the attribute that is being assigned to."""
1216
1217        self.attrname: Optional[str] = attrname
1218        """The name of the attribute being assigned to."""
1219
1220        super().__init__(
1221            lineno=lineno,
1222            col_offset=col_offset,
1223            end_lineno=end_lineno,
1224            end_col_offset=end_col_offset,
1225            parent=parent,
1226        )
1227
1228    def postinit(self, expr: Optional[NodeNG] = None) -> None:
1229        """Do some setup after initialisation.
1230
1231        :param expr: What has the attribute that is being assigned to.
1232        """
1233        self.expr = expr
1234
1235    def get_children(self):
1236        yield self.expr
1237
1238
1239class Assert(Statement):
1240    """Class representing an :class:`ast.Assert` node.
1241
1242    An :class:`Assert` node represents an assert statement.
1243
1244    >>> import astroid
1245    >>> node = astroid.extract_node('assert len(things) == 10, "Not enough things"')
1246    >>> node
1247    <Assert l.1 at 0x7effe1d527b8>
1248    """
1249
1250    _astroid_fields = ("test", "fail")
1251
1252    def __init__(
1253        self,
1254        lineno: Optional[int] = None,
1255        col_offset: Optional[int] = None,
1256        parent: Optional[NodeNG] = None,
1257        *,
1258        end_lineno: Optional[int] = None,
1259        end_col_offset: Optional[int] = None,
1260    ) -> None:
1261        """
1262        :param lineno: The line that this node appears on in the source code.
1263
1264        :param col_offset: The column that this node appears on in the
1265            source code.
1266
1267        :param parent: The parent node in the syntax tree.
1268
1269        :param end_lineno: The last line this node appears on in the source code.
1270
1271        :param end_col_offset: The end column this node appears on in the
1272            source code. Note: This is after the last symbol.
1273        """
1274        self.test: Optional[NodeNG] = None
1275        """The test that passes or fails the assertion."""
1276
1277        self.fail: Optional[NodeNG] = None  # can be None
1278        """The message shown when the assertion fails."""
1279
1280        super().__init__(
1281            lineno=lineno,
1282            col_offset=col_offset,
1283            end_lineno=end_lineno,
1284            end_col_offset=end_col_offset,
1285            parent=parent,
1286        )
1287
1288    def postinit(
1289        self, test: Optional[NodeNG] = None, fail: Optional[NodeNG] = None
1290    ) -> None:
1291        """Do some setup after initialisation.
1292
1293        :param test: The test that passes or fails the assertion.
1294
1295        :param fail: The message shown when the assertion fails.
1296        """
1297        self.fail = fail
1298        self.test = test
1299
1300    def get_children(self):
1301        yield self.test
1302
1303        if self.fail is not None:
1304            yield self.fail
1305
1306
1307class Assign(mixins.AssignTypeMixin, Statement):
1308    """Class representing an :class:`ast.Assign` node.
1309
1310    An :class:`Assign` is a statement where something is explicitly
1311    asssigned to.
1312
1313    >>> import astroid
1314    >>> node = astroid.extract_node('variable = range(10)')
1315    >>> node
1316    <Assign l.1 at 0x7effe1db8550>
1317    """
1318
1319    _astroid_fields = ("targets", "value")
1320    _other_other_fields = ("type_annotation",)
1321
1322    def __init__(
1323        self,
1324        lineno: Optional[int] = None,
1325        col_offset: Optional[int] = None,
1326        parent: Optional[NodeNG] = None,
1327        *,
1328        end_lineno: Optional[int] = None,
1329        end_col_offset: Optional[int] = None,
1330    ) -> None:
1331        """
1332        :param lineno: The line that this node appears on in the source code.
1333
1334        :param col_offset: The column that this node appears on in the
1335            source code.
1336
1337        :param parent: The parent node in the syntax tree.
1338
1339        :param end_lineno: The last line this node appears on in the source code.
1340
1341        :param end_col_offset: The end column this node appears on in the
1342            source code. Note: This is after the last symbol.
1343        """
1344        self.targets: typing.List[NodeNG] = []
1345        """What is being assigned to."""
1346
1347        self.value: Optional[NodeNG] = None
1348        """The value being assigned to the variables."""
1349
1350        self.type_annotation: Optional[NodeNG] = None  # can be None
1351        """If present, this will contain the type annotation passed by a type comment"""
1352
1353        super().__init__(
1354            lineno=lineno,
1355            col_offset=col_offset,
1356            end_lineno=end_lineno,
1357            end_col_offset=end_col_offset,
1358            parent=parent,
1359        )
1360
1361    def postinit(
1362        self,
1363        targets: Optional[typing.List[NodeNG]] = None,
1364        value: Optional[NodeNG] = None,
1365        type_annotation: Optional[NodeNG] = None,
1366    ) -> None:
1367        """Do some setup after initialisation.
1368
1369        :param targets: What is being assigned to.
1370        :param value: The value being assigned to the variables.
1371        :param type_annotation:
1372        """
1373        if targets is not None:
1374            self.targets = targets
1375        self.value = value
1376        self.type_annotation = type_annotation
1377
1378    def get_children(self):
1379        yield from self.targets
1380
1381        yield self.value
1382
1383    @decorators.cached
1384    def _get_assign_nodes(self):
1385        return [self] + list(self.value._get_assign_nodes())
1386
1387    def _get_yield_nodes_skip_lambdas(self):
1388        yield from self.value._get_yield_nodes_skip_lambdas()
1389
1390
1391class AnnAssign(mixins.AssignTypeMixin, Statement):
1392    """Class representing an :class:`ast.AnnAssign` node.
1393
1394    An :class:`AnnAssign` is an assignment with a type annotation.
1395
1396    >>> import astroid
1397    >>> node = astroid.extract_node('variable: List[int] = range(10)')
1398    >>> node
1399    <AnnAssign l.1 at 0x7effe1d4c630>
1400    """
1401
1402    _astroid_fields = ("target", "annotation", "value")
1403    _other_fields = ("simple",)
1404
1405    def __init__(
1406        self,
1407        lineno: Optional[int] = None,
1408        col_offset: Optional[int] = None,
1409        parent: Optional[NodeNG] = None,
1410        *,
1411        end_lineno: Optional[int] = None,
1412        end_col_offset: Optional[int] = None,
1413    ) -> None:
1414        """
1415        :param lineno: The line that this node appears on in the source code.
1416
1417        :param col_offset: The column that this node appears on in the
1418            source code.
1419
1420        :param parent: The parent node in the syntax tree.
1421
1422        :param end_lineno: The last line this node appears on in the source code.
1423
1424        :param end_col_offset: The end column this node appears on in the
1425            source code. Note: This is after the last symbol.
1426        """
1427        self.target: Optional[NodeNG] = None
1428        """What is being assigned to."""
1429
1430        self.annotation: Optional[NodeNG] = None
1431        """The type annotation of what is being assigned to."""
1432
1433        self.value: Optional[NodeNG] = None  # can be None
1434        """The value being assigned to the variables."""
1435
1436        self.simple: Optional[int] = None
1437        """Whether :attr:`target` is a pure name or a complex statement."""
1438
1439        super().__init__(
1440            lineno=lineno,
1441            col_offset=col_offset,
1442            end_lineno=end_lineno,
1443            end_col_offset=end_col_offset,
1444            parent=parent,
1445        )
1446
1447    def postinit(
1448        self,
1449        target: NodeNG,
1450        annotation: NodeNG,
1451        simple: int,
1452        value: Optional[NodeNG] = None,
1453    ) -> None:
1454        """Do some setup after initialisation.
1455
1456        :param target: What is being assigned to.
1457
1458        :param annotation: The type annotation of what is being assigned to.
1459
1460        :param simple: Whether :attr:`target` is a pure name
1461            or a complex statement.
1462
1463        :param value: The value being assigned to the variables.
1464        """
1465        self.target = target
1466        self.annotation = annotation
1467        self.value = value
1468        self.simple = simple
1469
1470    def get_children(self):
1471        yield self.target
1472        yield self.annotation
1473
1474        if self.value is not None:
1475            yield self.value
1476
1477
1478class AugAssign(mixins.AssignTypeMixin, Statement):
1479    """Class representing an :class:`ast.AugAssign` node.
1480
1481    An :class:`AugAssign` is an assignment paired with an operator.
1482
1483    >>> import astroid
1484    >>> node = astroid.extract_node('variable += 1')
1485    >>> node
1486    <AugAssign l.1 at 0x7effe1db4d68>
1487    """
1488
1489    _astroid_fields = ("target", "value")
1490    _other_fields = ("op",)
1491
1492    @decorators.deprecate_default_argument_values(op="str")
1493    def __init__(
1494        self,
1495        op: Optional[str] = None,
1496        lineno: Optional[int] = None,
1497        col_offset: Optional[int] = None,
1498        parent: Optional[NodeNG] = None,
1499        *,
1500        end_lineno: Optional[int] = None,
1501        end_col_offset: Optional[int] = None,
1502    ) -> None:
1503        """
1504        :param op: The operator that is being combined with the assignment.
1505            This includes the equals sign.
1506
1507        :param lineno: The line that this node appears on in the source code.
1508
1509        :param col_offset: The column that this node appears on in the
1510            source code.
1511
1512        :param parent: The parent node in the syntax tree.
1513
1514        :param end_lineno: The last line this node appears on in the source code.
1515
1516        :param end_col_offset: The end column this node appears on in the
1517            source code. Note: This is after the last symbol.
1518        """
1519        self.target: Optional[NodeNG] = None
1520        """What is being assigned to."""
1521
1522        self.op: Optional[str] = op
1523        """The operator that is being combined with the assignment.
1524
1525        This includes the equals sign.
1526        """
1527
1528        self.value: Optional[NodeNG] = None
1529        """The value being assigned to the variable."""
1530
1531        super().__init__(
1532            lineno=lineno,
1533            col_offset=col_offset,
1534            end_lineno=end_lineno,
1535            end_col_offset=end_col_offset,
1536            parent=parent,
1537        )
1538
1539    def postinit(
1540        self, target: Optional[NodeNG] = None, value: Optional[NodeNG] = None
1541    ) -> None:
1542        """Do some setup after initialisation.
1543
1544        :param target: What is being assigned to.
1545
1546        :param value: The value being assigned to the variable.
1547        """
1548        self.target = target
1549        self.value = value
1550
1551    # This is set by inference.py
1552    def _infer_augassign(self, context=None):
1553        raise NotImplementedError
1554
1555    def type_errors(self, context=None):
1556        """Get a list of type errors which can occur during inference.
1557
1558        Each TypeError is represented by a :class:`BadBinaryOperationMessage` ,
1559        which holds the original exception.
1560
1561        :returns: The list of possible type errors.
1562        :rtype: list(BadBinaryOperationMessage)
1563        """
1564        try:
1565            results = self._infer_augassign(context=context)
1566            return [
1567                result
1568                for result in results
1569                if isinstance(result, util.BadBinaryOperationMessage)
1570            ]
1571        except InferenceError:
1572            return []
1573
1574    def get_children(self):
1575        yield self.target
1576        yield self.value
1577
1578    def _get_yield_nodes_skip_lambdas(self):
1579        """An AugAssign node can contain a Yield node in the value"""
1580        yield from self.value._get_yield_nodes_skip_lambdas()
1581        yield from super()._get_yield_nodes_skip_lambdas()
1582
1583
1584class BinOp(NodeNG):
1585    """Class representing an :class:`ast.BinOp` node.
1586
1587    A :class:`BinOp` node is an application of a binary operator.
1588
1589    >>> import astroid
1590    >>> node = astroid.extract_node('a + b')
1591    >>> node
1592    <BinOp l.1 at 0x7f23b2e8cfd0>
1593    """
1594
1595    _astroid_fields = ("left", "right")
1596    _other_fields = ("op",)
1597
1598    @decorators.deprecate_default_argument_values(op="str")
1599    def __init__(
1600        self,
1601        op: Optional[str] = None,
1602        lineno: Optional[int] = None,
1603        col_offset: Optional[int] = None,
1604        parent: Optional[NodeNG] = None,
1605        *,
1606        end_lineno: Optional[int] = None,
1607        end_col_offset: Optional[int] = None,
1608    ) -> None:
1609        """
1610        :param op: The operator.
1611
1612        :param lineno: The line that this node appears on in the source code.
1613
1614        :param col_offset: The column that this node appears on in the
1615            source code.
1616
1617        :param parent: The parent node in the syntax tree.
1618
1619        :param end_lineno: The last line this node appears on in the source code.
1620
1621        :param end_col_offset: The end column this node appears on in the
1622            source code. Note: This is after the last symbol.
1623        """
1624        self.left: Optional[NodeNG] = None
1625        """What is being applied to the operator on the left side."""
1626
1627        self.op: Optional[str] = op
1628        """The operator."""
1629
1630        self.right: Optional[NodeNG] = None
1631        """What is being applied to the operator on the right side."""
1632
1633        super().__init__(
1634            lineno=lineno,
1635            col_offset=col_offset,
1636            end_lineno=end_lineno,
1637            end_col_offset=end_col_offset,
1638            parent=parent,
1639        )
1640
1641    def postinit(
1642        self, left: Optional[NodeNG] = None, right: Optional[NodeNG] = None
1643    ) -> None:
1644        """Do some setup after initialisation.
1645
1646        :param left: What is being applied to the operator on the left side.
1647
1648        :param right: What is being applied to the operator on the right side.
1649        """
1650        self.left = left
1651        self.right = right
1652
1653    # This is set by inference.py
1654    def _infer_binop(self, context=None):
1655        raise NotImplementedError
1656
1657    def type_errors(self, context=None):
1658        """Get a list of type errors which can occur during inference.
1659
1660        Each TypeError is represented by a :class:`BadBinaryOperationMessage`,
1661        which holds the original exception.
1662
1663        :returns: The list of possible type errors.
1664        :rtype: list(BadBinaryOperationMessage)
1665        """
1666        try:
1667            results = self._infer_binop(context=context)
1668            return [
1669                result
1670                for result in results
1671                if isinstance(result, util.BadBinaryOperationMessage)
1672            ]
1673        except InferenceError:
1674            return []
1675
1676    def get_children(self):
1677        yield self.left
1678        yield self.right
1679
1680    def op_precedence(self):
1681        return OP_PRECEDENCE[self.op]
1682
1683    def op_left_associative(self):
1684        # 2**3**4 == 2**(3**4)
1685        return self.op != "**"
1686
1687
1688class BoolOp(NodeNG):
1689    """Class representing an :class:`ast.BoolOp` node.
1690
1691    A :class:`BoolOp` is an application of a boolean operator.
1692
1693    >>> import astroid
1694    >>> node = astroid.extract_node('a and b')
1695    >>> node
1696    <BinOp l.1 at 0x7f23b2e71c50>
1697    """
1698
1699    _astroid_fields = ("values",)
1700    _other_fields = ("op",)
1701
1702    @decorators.deprecate_default_argument_values(op="str")
1703    def __init__(
1704        self,
1705        op: Optional[str] = None,
1706        lineno: Optional[int] = None,
1707        col_offset: Optional[int] = None,
1708        parent: Optional[NodeNG] = None,
1709        *,
1710        end_lineno: Optional[int] = None,
1711        end_col_offset: Optional[int] = None,
1712    ) -> None:
1713        """
1714        :param op: The operator.
1715
1716        :param lineno: The line that this node appears on in the source code.
1717
1718        :param col_offset: The column that this node appears on in the
1719            source code.
1720
1721        :param parent: The parent node in the syntax tree.
1722
1723        :param end_lineno: The last line this node appears on in the source code.
1724
1725        :param end_col_offset: The end column this node appears on in the
1726            source code. Note: This is after the last symbol.
1727        """
1728        self.op: Optional[str] = op
1729        """The operator."""
1730
1731        self.values: typing.List[NodeNG] = []
1732        """The values being applied to the operator."""
1733
1734        super().__init__(
1735            lineno=lineno,
1736            col_offset=col_offset,
1737            end_lineno=end_lineno,
1738            end_col_offset=end_col_offset,
1739            parent=parent,
1740        )
1741
1742    def postinit(self, values: Optional[typing.List[NodeNG]] = None) -> None:
1743        """Do some setup after initialisation.
1744
1745        :param values: The values being applied to the operator.
1746        """
1747        if values is not None:
1748            self.values = values
1749
1750    def get_children(self):
1751        yield from self.values
1752
1753    def op_precedence(self):
1754        return OP_PRECEDENCE[self.op]
1755
1756
1757class Break(mixins.NoChildrenMixin, Statement):
1758    """Class representing an :class:`ast.Break` node.
1759
1760    >>> import astroid
1761    >>> node = astroid.extract_node('break')
1762    >>> node
1763    <Break l.1 at 0x7f23b2e9e5c0>
1764    """
1765
1766
1767class Call(NodeNG):
1768    """Class representing an :class:`ast.Call` node.
1769
1770    A :class:`Call` node is a call to a function, method, etc.
1771
1772    >>> import astroid
1773    >>> node = astroid.extract_node('function()')
1774    >>> node
1775    <Call l.1 at 0x7f23b2e71eb8>
1776    """
1777
1778    _astroid_fields = ("func", "args", "keywords")
1779
1780    def __init__(
1781        self,
1782        lineno: Optional[int] = None,
1783        col_offset: Optional[int] = None,
1784        parent: Optional[NodeNG] = None,
1785        *,
1786        end_lineno: Optional[int] = None,
1787        end_col_offset: Optional[int] = None,
1788    ) -> None:
1789        """
1790        :param lineno: The line that this node appears on in the source code.
1791
1792        :param col_offset: The column that this node appears on in the
1793            source code.
1794
1795        :param parent: The parent node in the syntax tree.
1796
1797        :param end_lineno: The last line this node appears on in the source code.
1798
1799        :param end_col_offset: The end column this node appears on in the
1800            source code. Note: This is after the last symbol.
1801        """
1802        self.func: Optional[NodeNG] = None
1803        """What is being called."""
1804
1805        self.args: typing.List[NodeNG] = []
1806        """The positional arguments being given to the call."""
1807
1808        self.keywords: typing.List["Keyword"] = []
1809        """The keyword arguments being given to the call."""
1810
1811        super().__init__(
1812            lineno=lineno,
1813            col_offset=col_offset,
1814            end_lineno=end_lineno,
1815            end_col_offset=end_col_offset,
1816            parent=parent,
1817        )
1818
1819    def postinit(
1820        self,
1821        func: Optional[NodeNG] = None,
1822        args: Optional[typing.List[NodeNG]] = None,
1823        keywords: Optional[typing.List["Keyword"]] = None,
1824    ) -> None:
1825        """Do some setup after initialisation.
1826
1827        :param func: What is being called.
1828
1829        :param args: The positional arguments being given to the call.
1830
1831        :param keywords: The keyword arguments being given to the call.
1832        """
1833        self.func = func
1834        if args is not None:
1835            self.args = args
1836        if keywords is not None:
1837            self.keywords = keywords
1838
1839    @property
1840    def starargs(self) -> typing.List["Starred"]:
1841        """The positional arguments that unpack something."""
1842        return [arg for arg in self.args if isinstance(arg, Starred)]
1843
1844    @property
1845    def kwargs(self) -> typing.List["Keyword"]:
1846        """The keyword arguments that unpack something."""
1847        return [keyword for keyword in self.keywords if keyword.arg is None]
1848
1849    def get_children(self):
1850        yield self.func
1851
1852        yield from self.args
1853
1854        yield from self.keywords
1855
1856
1857class Compare(NodeNG):
1858    """Class representing an :class:`ast.Compare` node.
1859
1860    A :class:`Compare` node indicates a comparison.
1861
1862    >>> import astroid
1863    >>> node = astroid.extract_node('a <= b <= c')
1864    >>> node
1865    <Compare l.1 at 0x7f23b2e9e6d8>
1866    >>> node.ops
1867    [('<=', <Name.b l.1 at 0x7f23b2e9e2b0>), ('<=', <Name.c l.1 at 0x7f23b2e9e390>)]
1868    """
1869
1870    _astroid_fields = ("left", "ops")
1871
1872    def __init__(
1873        self,
1874        lineno: Optional[int] = None,
1875        col_offset: Optional[int] = None,
1876        parent: Optional[NodeNG] = None,
1877        *,
1878        end_lineno: Optional[int] = None,
1879        end_col_offset: Optional[int] = None,
1880    ) -> None:
1881        """
1882        :param lineno: The line that this node appears on in the source code.
1883
1884        :param col_offset: The column that this node appears on in the
1885            source code.
1886
1887        :param parent: The parent node in the syntax tree.
1888
1889        :param end_lineno: The last line this node appears on in the source code.
1890
1891        :param end_col_offset: The end column this node appears on in the
1892            source code. Note: This is after the last symbol.
1893        """
1894        self.left: Optional[NodeNG] = None
1895        """The value at the left being applied to a comparison operator."""
1896
1897        self.ops: typing.List[typing.Tuple[str, NodeNG]] = []
1898        """The remainder of the operators and their relevant right hand value."""
1899
1900        super().__init__(
1901            lineno=lineno,
1902            col_offset=col_offset,
1903            end_lineno=end_lineno,
1904            end_col_offset=end_col_offset,
1905            parent=parent,
1906        )
1907
1908    def postinit(
1909        self,
1910        left: Optional[NodeNG] = None,
1911        ops: Optional[typing.List[typing.Tuple[str, NodeNG]]] = None,
1912    ) -> None:
1913        """Do some setup after initialisation.
1914
1915        :param left: The value at the left being applied to a comparison
1916            operator.
1917
1918        :param ops: The remainder of the operators
1919            and their relevant right hand value.
1920        """
1921        self.left = left
1922        if ops is not None:
1923            self.ops = ops
1924
1925    def get_children(self):
1926        """Get the child nodes below this node.
1927
1928        Overridden to handle the tuple fields and skip returning the operator
1929        strings.
1930
1931        :returns: The children.
1932        :rtype: iterable(NodeNG)
1933        """
1934        yield self.left
1935        for _, comparator in self.ops:
1936            yield comparator  # we don't want the 'op'
1937
1938    def last_child(self):
1939        """An optimized version of list(get_children())[-1]
1940
1941        :returns: The last child.
1942        :rtype: NodeNG
1943        """
1944        # XXX maybe if self.ops:
1945        return self.ops[-1][1]
1946        # return self.left
1947
1948
1949class Comprehension(NodeNG):
1950    """Class representing an :class:`ast.comprehension` node.
1951
1952    A :class:`Comprehension` indicates the loop inside any type of
1953    comprehension including generator expressions.
1954
1955    >>> import astroid
1956    >>> node = astroid.extract_node('[x for x in some_values]')
1957    >>> list(node.get_children())
1958    [<Name.x l.1 at 0x7f23b2e352b0>, <Comprehension l.1 at 0x7f23b2e35320>]
1959    >>> list(node.get_children())[1].as_string()
1960    'for x in some_values'
1961    """
1962
1963    _astroid_fields = ("target", "iter", "ifs")
1964    _other_fields = ("is_async",)
1965
1966    optional_assign = True
1967    """Whether this node optionally assigns a variable."""
1968
1969    lineno: None
1970    col_offset: None
1971    end_lineno: None
1972    end_col_offset: None
1973
1974    def __init__(self, parent: Optional[NodeNG] = None) -> None:
1975        """
1976        :param parent: The parent node in the syntax tree.
1977        """
1978        self.target: Optional[NodeNG] = None
1979        """What is assigned to by the comprehension."""
1980
1981        self.iter: Optional[NodeNG] = None
1982        """What is iterated over by the comprehension."""
1983
1984        self.ifs: typing.List[NodeNG] = []
1985        """The contents of any if statements that filter the comprehension."""
1986
1987        self.is_async: Optional[bool] = None
1988        """Whether this is an asynchronous comprehension or not."""
1989
1990        super().__init__(parent=parent)
1991
1992    # pylint: disable=redefined-builtin; same name as builtin ast module.
1993    def postinit(
1994        self,
1995        target: Optional[NodeNG] = None,
1996        iter: Optional[NodeNG] = None,
1997        ifs: Optional[typing.List[NodeNG]] = None,
1998        is_async: Optional[bool] = None,
1999    ) -> None:
2000        """Do some setup after initialisation.
2001
2002        :param target: What is assigned to by the comprehension.
2003
2004        :param iter: What is iterated over by the comprehension.
2005
2006        :param ifs: The contents of any if statements that filter
2007            the comprehension.
2008
2009        :param is_async: Whether this is an asynchronous comprehension or not.
2010        """
2011        self.target = target
2012        self.iter = iter
2013        if ifs is not None:
2014            self.ifs = ifs
2015        self.is_async = is_async
2016
2017    def assign_type(self):
2018        """The type of assignment that this node performs.
2019
2020        :returns: The assignment type.
2021        :rtype: NodeNG
2022        """
2023        return self
2024
2025    def _get_filtered_stmts(self, lookup_node, node, stmts, mystmt):
2026        """method used in filter_stmts"""
2027        if self is mystmt:
2028            if isinstance(lookup_node, (Const, Name)):
2029                return [lookup_node], True
2030
2031        elif self.statement() is mystmt:
2032            # original node's statement is the assignment, only keeps
2033            # current node (gen exp, list comp)
2034
2035            return [node], True
2036
2037        return stmts, False
2038
2039    def get_children(self):
2040        yield self.target
2041        yield self.iter
2042
2043        yield from self.ifs
2044
2045
2046class Const(mixins.NoChildrenMixin, NodeNG, Instance):
2047    """Class representing any constant including num, str, bool, None, bytes.
2048
2049    >>> import astroid
2050    >>> node = astroid.extract_node('(5, "This is a string.", True, None, b"bytes")')
2051    >>> node
2052    <Tuple.tuple l.1 at 0x7f23b2e358d0>
2053    >>> list(node.get_children())
2054    [<Const.int l.1 at 0x7f23b2e35940>,
2055    <Const.str l.1 at 0x7f23b2e35978>,
2056    <Const.bool l.1 at 0x7f23b2e359b0>,
2057    <Const.NoneType l.1 at 0x7f23b2e359e8>,
2058    <Const.bytes l.1 at 0x7f23b2e35a20>]
2059    """
2060
2061    _other_fields = ("value", "kind")
2062
2063    def __init__(
2064        self,
2065        value: typing.Any,
2066        lineno: Optional[int] = None,
2067        col_offset: Optional[int] = None,
2068        parent: Optional[NodeNG] = None,
2069        kind: Optional[str] = None,
2070        *,
2071        end_lineno: Optional[int] = None,
2072        end_col_offset: Optional[int] = None,
2073    ) -> None:
2074        """
2075        :param value: The value that the constant represents.
2076
2077        :param lineno: The line that this node appears on in the source code.
2078
2079        :param col_offset: The column that this node appears on in the
2080            source code.
2081
2082        :param parent: The parent node in the syntax tree.
2083
2084        :param kind: The string prefix. "u" for u-prefixed strings and ``None`` otherwise. Python 3.8+ only.
2085
2086        :param end_lineno: The last line this node appears on in the source code.
2087
2088        :param end_col_offset: The end column this node appears on in the
2089            source code. Note: This is after the last symbol.
2090        """
2091        self.value: typing.Any = value
2092        """The value that the constant represents."""
2093
2094        self.kind: Optional[str] = kind  # can be None
2095        """"The string prefix. "u" for u-prefixed strings and ``None`` otherwise. Python 3.8+ only."""
2096
2097        super().__init__(
2098            lineno=lineno,
2099            col_offset=col_offset,
2100            end_lineno=end_lineno,
2101            end_col_offset=end_col_offset,
2102            parent=parent,
2103        )
2104
2105    def __getattr__(self, name):
2106        # This is needed because of Proxy's __getattr__ method.
2107        # Calling object.__new__ on this class without calling
2108        # __init__ would result in an infinite loop otherwise
2109        # since __getattr__ is called when an attribute doesn't
2110        # exist and self._proxied indirectly calls self.value
2111        # and Proxy __getattr__ calls self.value
2112        if name == "value":
2113            raise AttributeError
2114        return super().__getattr__(name)
2115
2116    def getitem(self, index, context=None):
2117        """Get an item from this node if subscriptable.
2118
2119        :param index: The node to use as a subscript index.
2120        :type index: Const or Slice
2121
2122        :raises AstroidTypeError: When the given index cannot be used as a
2123            subscript index, or if this node is not subscriptable.
2124        """
2125        if isinstance(index, Const):
2126            index_value = index.value
2127        elif isinstance(index, Slice):
2128            index_value = _infer_slice(index, context=context)
2129
2130        else:
2131            raise AstroidTypeError(
2132                f"Could not use type {type(index)} as subscript index"
2133            )
2134
2135        try:
2136            if isinstance(self.value, (str, bytes)):
2137                return Const(self.value[index_value])
2138        except IndexError as exc:
2139            raise AstroidIndexError(
2140                message="Index {index!r} out of range",
2141                node=self,
2142                index=index,
2143                context=context,
2144            ) from exc
2145        except TypeError as exc:
2146            raise AstroidTypeError(
2147                message="Type error {error!r}", node=self, index=index, context=context
2148            ) from exc
2149
2150        raise AstroidTypeError(f"{self!r} (value={self.value})")
2151
2152    def has_dynamic_getattr(self):
2153        """Check if the node has a custom __getattr__ or __getattribute__.
2154
2155        :returns: True if the class has a custom
2156            __getattr__ or __getattribute__, False otherwise.
2157            For a :class:`Const` this is always ``False``.
2158        :rtype: bool
2159        """
2160        return False
2161
2162    def itered(self):
2163        """An iterator over the elements this node contains.
2164
2165        :returns: The contents of this node.
2166        :rtype: iterable(Const)
2167
2168        :raises TypeError: If this node does not represent something that is iterable.
2169        """
2170        if isinstance(self.value, str):
2171            return [const_factory(elem) for elem in self.value]
2172        raise TypeError(f"Cannot iterate over type {type(self.value)!r}")
2173
2174    def pytype(self):
2175        """Get the name of the type that this node represents.
2176
2177        :returns: The name of the type.
2178        :rtype: str
2179        """
2180        return self._proxied.qname()
2181
2182    def bool_value(self, context=None):
2183        """Determine the boolean value of this node.
2184
2185        :returns: The boolean value of this node.
2186        :rtype: bool
2187        """
2188        return bool(self.value)
2189
2190
2191class Continue(mixins.NoChildrenMixin, Statement):
2192    """Class representing an :class:`ast.Continue` node.
2193
2194    >>> import astroid
2195    >>> node = astroid.extract_node('continue')
2196    >>> node
2197    <Continue l.1 at 0x7f23b2e35588>
2198    """
2199
2200
2201class Decorators(NodeNG):
2202    """A node representing a list of decorators.
2203
2204    A :class:`Decorators` is the decorators that are applied to
2205    a method or function.
2206
2207    >>> import astroid
2208    >>> node = astroid.extract_node('''
2209    @property
2210    def my_property(self):
2211        return 3
2212    ''')
2213    >>> node
2214    <FunctionDef.my_property l.2 at 0x7f23b2e35d30>
2215    >>> list(node.get_children())[0]
2216    <Decorators l.1 at 0x7f23b2e35d68>
2217    """
2218
2219    _astroid_fields = ("nodes",)
2220
2221    def __init__(
2222        self,
2223        lineno: Optional[int] = None,
2224        col_offset: Optional[int] = None,
2225        parent: Optional[NodeNG] = None,
2226        *,
2227        end_lineno: Optional[int] = None,
2228        end_col_offset: Optional[int] = None,
2229    ) -> None:
2230        """
2231        :param lineno: The line that this node appears on in the source code.
2232
2233        :param col_offset: The column that this node appears on in the
2234            source code.
2235
2236        :param parent: The parent node in the syntax tree.
2237
2238        :param end_lineno: The last line this node appears on in the source code.
2239
2240        :param end_col_offset: The end column this node appears on in the
2241            source code. Note: This is after the last symbol.
2242        """
2243        self.nodes: typing.List[NodeNG]
2244        """The decorators that this node contains.
2245
2246        :type: list(Name or Call) or None
2247        """
2248
2249        super().__init__(
2250            lineno=lineno,
2251            col_offset=col_offset,
2252            end_lineno=end_lineno,
2253            end_col_offset=end_col_offset,
2254            parent=parent,
2255        )
2256
2257    def postinit(self, nodes: typing.List[NodeNG]) -> None:
2258        """Do some setup after initialisation.
2259
2260        :param nodes: The decorators that this node contains.
2261        :type nodes: list(Name or Call)
2262        """
2263        self.nodes = nodes
2264
2265    def scope(self) -> "LocalsDictNodeNG":
2266        """The first parent node defining a new scope.
2267        These can be Module, FunctionDef, ClassDef, Lambda, or GeneratorExp nodes.
2268
2269        :returns: The first parent scope node.
2270        """
2271        # skip the function node to go directly to the upper level scope
2272        if not self.parent:
2273            raise ParentMissingError(target=self)
2274        if not self.parent.parent:
2275            raise ParentMissingError(target=self.parent)
2276        return self.parent.parent.scope()
2277
2278    def get_children(self):
2279        yield from self.nodes
2280
2281
2282class DelAttr(mixins.ParentAssignTypeMixin, NodeNG):
2283    """Variation of :class:`ast.Delete` representing deletion of an attribute.
2284
2285    >>> import astroid
2286    >>> node = astroid.extract_node('del self.attr')
2287    >>> node
2288    <Delete l.1 at 0x7f23b2e35f60>
2289    >>> list(node.get_children())[0]
2290    <DelAttr.attr l.1 at 0x7f23b2e411d0>
2291    """
2292
2293    _astroid_fields = ("expr",)
2294    _other_fields = ("attrname",)
2295
2296    @decorators.deprecate_default_argument_values(attrname="str")
2297    def __init__(
2298        self,
2299        attrname: Optional[str] = None,
2300        lineno: Optional[int] = None,
2301        col_offset: Optional[int] = None,
2302        parent: Optional[NodeNG] = None,
2303        *,
2304        end_lineno: Optional[int] = None,
2305        end_col_offset: Optional[int] = None,
2306    ) -> None:
2307        """
2308        :param attrname: The name of the attribute that is being deleted.
2309
2310        :param lineno: The line that this node appears on in the source code.
2311
2312        :param col_offset: The column that this node appears on in the
2313            source code.
2314
2315        :param parent: The parent node in the syntax tree.
2316
2317        :param end_lineno: The last line this node appears on in the source code.
2318
2319        :param end_col_offset: The end column this node appears on in the
2320            source code. Note: This is after the last symbol.
2321        """
2322        self.expr: Optional[NodeNG] = None
2323        """The name that this node represents.
2324
2325        :type: Name or None
2326        """
2327
2328        self.attrname: Optional[str] = attrname
2329        """The name of the attribute that is being deleted."""
2330
2331        super().__init__(
2332            lineno=lineno,
2333            col_offset=col_offset,
2334            end_lineno=end_lineno,
2335            end_col_offset=end_col_offset,
2336            parent=parent,
2337        )
2338
2339    def postinit(self, expr: Optional[NodeNG] = None) -> None:
2340        """Do some setup after initialisation.
2341
2342        :param expr: The name that this node represents.
2343        :type expr: Name or None
2344        """
2345        self.expr = expr
2346
2347    def get_children(self):
2348        yield self.expr
2349
2350
2351class Delete(mixins.AssignTypeMixin, Statement):
2352    """Class representing an :class:`ast.Delete` node.
2353
2354    A :class:`Delete` is a ``del`` statement this is deleting something.
2355
2356    >>> import astroid
2357    >>> node = astroid.extract_node('del self.attr')
2358    >>> node
2359    <Delete l.1 at 0x7f23b2e35f60>
2360    """
2361
2362    _astroid_fields = ("targets",)
2363
2364    def __init__(
2365        self,
2366        lineno: Optional[int] = None,
2367        col_offset: Optional[int] = None,
2368        parent: Optional[NodeNG] = None,
2369        *,
2370        end_lineno: Optional[int] = None,
2371        end_col_offset: Optional[int] = None,
2372    ) -> None:
2373        """
2374        :param lineno: The line that this node appears on in the source code.
2375
2376        :param col_offset: The column that this node appears on in the
2377            source code.
2378
2379        :param parent: The parent node in the syntax tree.
2380
2381        :param end_lineno: The last line this node appears on in the source code.
2382
2383        :param end_col_offset: The end column this node appears on in the
2384            source code. Note: This is after the last symbol.
2385        """
2386        self.targets: typing.List[NodeNG] = []
2387        """What is being deleted."""
2388
2389        super().__init__(
2390            lineno=lineno,
2391            col_offset=col_offset,
2392            end_lineno=end_lineno,
2393            end_col_offset=end_col_offset,
2394            parent=parent,
2395        )
2396
2397    def postinit(self, targets: Optional[typing.List[NodeNG]] = None) -> None:
2398        """Do some setup after initialisation.
2399
2400        :param targets: What is being deleted.
2401        """
2402        if targets is not None:
2403            self.targets = targets
2404
2405    def get_children(self):
2406        yield from self.targets
2407
2408
2409class Dict(NodeNG, Instance):
2410    """Class representing an :class:`ast.Dict` node.
2411
2412    A :class:`Dict` is a dictionary that is created with ``{}`` syntax.
2413
2414    >>> import astroid
2415    >>> node = astroid.extract_node('{1: "1"}')
2416    >>> node
2417    <Dict.dict l.1 at 0x7f23b2e35cc0>
2418    """
2419
2420    _astroid_fields = ("items",)
2421
2422    def __init__(
2423        self,
2424        lineno: Optional[int] = None,
2425        col_offset: Optional[int] = None,
2426        parent: Optional[NodeNG] = None,
2427        *,
2428        end_lineno: Optional[int] = None,
2429        end_col_offset: Optional[int] = None,
2430    ) -> None:
2431        """
2432        :param lineno: The line that this node appears on in the source code.
2433
2434        :param col_offset: The column that this node appears on in the
2435            source code.
2436
2437        :param parent: The parent node in the syntax tree.
2438
2439        :param end_lineno: The last line this node appears on in the source code.
2440
2441        :param end_col_offset: The end column this node appears on in the
2442            source code. Note: This is after the last symbol.
2443        """
2444        self.items: typing.List[typing.Tuple[NodeNG, NodeNG]] = []
2445        """The key-value pairs contained in the dictionary."""
2446
2447        super().__init__(
2448            lineno=lineno,
2449            col_offset=col_offset,
2450            end_lineno=end_lineno,
2451            end_col_offset=end_col_offset,
2452            parent=parent,
2453        )
2454
2455    def postinit(self, items: typing.List[typing.Tuple[NodeNG, NodeNG]]) -> None:
2456        """Do some setup after initialisation.
2457
2458        :param items: The key-value pairs contained in the dictionary.
2459        """
2460        self.items = items
2461
2462    @classmethod
2463    def from_elements(cls, items=None):
2464        """Create a :class:`Dict` of constants from a live dictionary.
2465
2466        :param items: The items to store in the node.
2467        :type items: dict
2468
2469        :returns: The created dictionary node.
2470        :rtype: Dict
2471        """
2472        node = cls()
2473        if items is None:
2474            node.items = []
2475        else:
2476            node.items = [
2477                (const_factory(k), const_factory(v) if _is_const(v) else v)
2478                for k, v in items.items()
2479                # The keys need to be constants
2480                if _is_const(k)
2481            ]
2482        return node
2483
2484    def pytype(self):
2485        """Get the name of the type that this node represents.
2486
2487        :returns: The name of the type.
2488        :rtype: str
2489        """
2490        return "builtins.dict"
2491
2492    def get_children(self):
2493        """Get the key and value nodes below this node.
2494
2495        Children are returned in the order that they are defined in the source
2496        code, key first then the value.
2497
2498        :returns: The children.
2499        :rtype: iterable(NodeNG)
2500        """
2501        for key, value in self.items:
2502            yield key
2503            yield value
2504
2505    def last_child(self):
2506        """An optimized version of list(get_children())[-1]
2507
2508        :returns: The last child, or None if no children exist.
2509        :rtype: NodeNG or None
2510        """
2511        if self.items:
2512            return self.items[-1][1]
2513        return None
2514
2515    def itered(self):
2516        """An iterator over the keys this node contains.
2517
2518        :returns: The keys of this node.
2519        :rtype: iterable(NodeNG)
2520        """
2521        return [key for (key, _) in self.items]
2522
2523    def getitem(self, index, context=None):
2524        """Get an item from this node.
2525
2526        :param index: The node to use as a subscript index.
2527        :type index: Const or Slice
2528
2529        :raises AstroidTypeError: When the given index cannot be used as a
2530            subscript index, or if this node is not subscriptable.
2531        :raises AstroidIndexError: If the given index does not exist in the
2532            dictionary.
2533        """
2534        for key, value in self.items:
2535            # TODO(cpopa): no support for overriding yet, {1:2, **{1: 3}}.
2536            if isinstance(key, DictUnpack):
2537                try:
2538                    return value.getitem(index, context)
2539                except (AstroidTypeError, AstroidIndexError):
2540                    continue
2541            for inferredkey in key.infer(context):
2542                if inferredkey is util.Uninferable:
2543                    continue
2544                if isinstance(inferredkey, Const) and isinstance(index, Const):
2545                    if inferredkey.value == index.value:
2546                        return value
2547
2548        raise AstroidIndexError(index)
2549
2550    def bool_value(self, context=None):
2551        """Determine the boolean value of this node.
2552
2553        :returns: The boolean value of this node.
2554        :rtype: bool
2555        """
2556        return bool(self.items)
2557
2558
2559class Expr(Statement):
2560    """Class representing an :class:`ast.Expr` node.
2561
2562    An :class:`Expr` is any expression that does not have its value used or
2563    stored.
2564
2565    >>> import astroid
2566    >>> node = astroid.extract_node('method()')
2567    >>> node
2568    <Call l.1 at 0x7f23b2e352b0>
2569    >>> node.parent
2570    <Expr l.1 at 0x7f23b2e35278>
2571    """
2572
2573    _astroid_fields = ("value",)
2574
2575    def __init__(
2576        self,
2577        lineno: Optional[int] = None,
2578        col_offset: Optional[int] = None,
2579        parent: Optional[NodeNG] = None,
2580        *,
2581        end_lineno: Optional[int] = None,
2582        end_col_offset: Optional[int] = None,
2583    ) -> None:
2584        """
2585        :param lineno: The line that this node appears on in the source code.
2586
2587        :param col_offset: The column that this node appears on in the
2588            source code.
2589
2590        :param parent: The parent node in the syntax tree.
2591
2592        :param end_lineno: The last line this node appears on in the source code.
2593
2594        :param end_col_offset: The end column this node appears on in the
2595            source code. Note: This is after the last symbol.
2596        """
2597        self.value: Optional[NodeNG] = None
2598        """What the expression does."""
2599
2600        super().__init__(
2601            lineno=lineno,
2602            col_offset=col_offset,
2603            end_lineno=end_lineno,
2604            end_col_offset=end_col_offset,
2605            parent=parent,
2606        )
2607
2608    def postinit(self, value: Optional[NodeNG] = None) -> None:
2609        """Do some setup after initialisation.
2610
2611        :param value: What the expression does.
2612        """
2613        self.value = value
2614
2615    def get_children(self):
2616        yield self.value
2617
2618    def _get_yield_nodes_skip_lambdas(self):
2619        if not self.value.is_lambda:
2620            yield from self.value._get_yield_nodes_skip_lambdas()
2621
2622
2623class Ellipsis(mixins.NoChildrenMixin, NodeNG):  # pylint: disable=redefined-builtin
2624    """Class representing an :class:`ast.Ellipsis` node.
2625
2626    An :class:`Ellipsis` is the ``...`` syntax.
2627
2628    Deprecated since v2.6.0 - Use :class:`Const` instead.
2629    Will be removed with the release v2.7.0
2630    """
2631
2632
2633class EmptyNode(mixins.NoChildrenMixin, NodeNG):
2634    """Holds an arbitrary object in the :attr:`LocalsDictNodeNG.locals`."""
2635
2636    object = None
2637
2638
2639class ExceptHandler(mixins.MultiLineBlockMixin, mixins.AssignTypeMixin, Statement):
2640    """Class representing an :class:`ast.ExceptHandler`. node.
2641
2642    An :class:`ExceptHandler` is an ``except`` block on a try-except.
2643
2644    >>> import astroid
2645    >>> node = astroid.extract_node('''
2646        try:
2647            do_something()
2648        except Exception as error:
2649            print("Error!")
2650        ''')
2651    >>> node
2652    <TryExcept l.2 at 0x7f23b2e9d908>
2653    >>> node.handlers
2654    [<ExceptHandler l.4 at 0x7f23b2e9e860>]
2655    """
2656
2657    _astroid_fields = ("type", "name", "body")
2658    _multi_line_block_fields = ("body",)
2659
2660    def __init__(
2661        self,
2662        lineno: Optional[int] = None,
2663        col_offset: Optional[int] = None,
2664        parent: Optional[NodeNG] = None,
2665        *,
2666        end_lineno: Optional[int] = None,
2667        end_col_offset: Optional[int] = None,
2668    ) -> None:
2669        """
2670        :param lineno: The line that this node appears on in the source code.
2671
2672        :param col_offset: The column that this node appears on in the
2673            source code.
2674
2675        :param parent: The parent node in the syntax tree.
2676
2677        :param end_lineno: The last line this node appears on in the source code.
2678
2679        :param end_col_offset: The end column this node appears on in the
2680            source code. Note: This is after the last symbol.
2681        """
2682        self.type: Optional[NodeNG] = None  # can be None
2683        """The types that the block handles.
2684
2685        :type: Tuple or NodeNG or None
2686        """
2687
2688        self.name: Optional[AssignName] = None  # can be None
2689        """The name that the caught exception is assigned to."""
2690
2691        self.body: typing.List[NodeNG] = []
2692        """The contents of the block."""
2693
2694        super().__init__(
2695            lineno=lineno,
2696            col_offset=col_offset,
2697            end_lineno=end_lineno,
2698            end_col_offset=end_col_offset,
2699            parent=parent,
2700        )
2701
2702    def get_children(self):
2703        if self.type is not None:
2704            yield self.type
2705
2706        if self.name is not None:
2707            yield self.name
2708
2709        yield from self.body
2710
2711    # pylint: disable=redefined-builtin; had to use the same name as builtin ast module.
2712    def postinit(
2713        self,
2714        type: Optional[NodeNG] = None,
2715        name: Optional[AssignName] = None,
2716        body: Optional[typing.List[NodeNG]] = None,
2717    ) -> None:
2718        """Do some setup after initialisation.
2719
2720        :param type: The types that the block handles.
2721        :type type: Tuple or NodeNG or None
2722
2723        :param name: The name that the caught exception is assigned to.
2724
2725        :param body:The contents of the block.
2726        """
2727        self.type = type
2728        self.name = name
2729        if body is not None:
2730            self.body = body
2731
2732    @decorators.cachedproperty
2733    def blockstart_tolineno(self):
2734        """The line on which the beginning of this block ends.
2735
2736        :type: int
2737        """
2738        if self.name:
2739            return self.name.tolineno
2740        if self.type:
2741            return self.type.tolineno
2742        return self.lineno
2743
2744    def catch(self, exceptions: Optional[typing.List[str]]) -> bool:
2745        """Check if this node handles any of the given
2746
2747        :param exceptions: The names of the exceptions to check for.
2748        """
2749        if self.type is None or exceptions is None:
2750            return True
2751        for node in self.type._get_name_nodes():
2752            if node.name in exceptions:
2753                return True
2754        return False
2755
2756
2757class ExtSlice(NodeNG):
2758    """Class representing an :class:`ast.ExtSlice` node.
2759
2760    An :class:`ExtSlice` is a complex slice expression.
2761
2762    Deprecated since v2.6.0 - Now part of the :class:`Subscript` node.
2763    Will be removed with the release of v2.7.0
2764    """
2765
2766
2767class For(
2768    mixins.MultiLineBlockMixin,
2769    mixins.BlockRangeMixIn,
2770    mixins.AssignTypeMixin,
2771    Statement,
2772):
2773    """Class representing an :class:`ast.For` node.
2774
2775    >>> import astroid
2776    >>> node = astroid.extract_node('for thing in things: print(thing)')
2777    >>> node
2778    <For l.1 at 0x7f23b2e8cf28>
2779    """
2780
2781    _astroid_fields = ("target", "iter", "body", "orelse")
2782    _other_other_fields = ("type_annotation",)
2783    _multi_line_block_fields = ("body", "orelse")
2784
2785    optional_assign = True
2786    """Whether this node optionally assigns a variable.
2787
2788    This is always ``True`` for :class:`For` nodes.
2789    """
2790
2791    def __init__(
2792        self,
2793        lineno: Optional[int] = None,
2794        col_offset: Optional[int] = None,
2795        parent: Optional[NodeNG] = None,
2796        *,
2797        end_lineno: Optional[int] = None,
2798        end_col_offset: Optional[int] = None,
2799    ) -> None:
2800        """
2801        :param lineno: The line that this node appears on in the source code.
2802
2803        :param col_offset: The column that this node appears on in the
2804            source code.
2805
2806        :param parent: The parent node in the syntax tree.
2807
2808        :param end_lineno: The last line this node appears on in the source code.
2809
2810        :param end_col_offset: The end column this node appears on in the
2811            source code. Note: This is after the last symbol.
2812        """
2813        self.target: Optional[NodeNG] = None
2814        """What the loop assigns to."""
2815
2816        self.iter: Optional[NodeNG] = None
2817        """What the loop iterates over."""
2818
2819        self.body: typing.List[NodeNG] = []
2820        """The contents of the body of the loop."""
2821
2822        self.orelse: typing.List[NodeNG] = []
2823        """The contents of the ``else`` block of the loop."""
2824
2825        self.type_annotation: Optional[NodeNG] = None  # can be None
2826        """If present, this will contain the type annotation passed by a type comment"""
2827
2828        super().__init__(
2829            lineno=lineno,
2830            col_offset=col_offset,
2831            end_lineno=end_lineno,
2832            end_col_offset=end_col_offset,
2833            parent=parent,
2834        )
2835
2836    # pylint: disable=redefined-builtin; had to use the same name as builtin ast module.
2837    def postinit(
2838        self,
2839        target: Optional[NodeNG] = None,
2840        iter: Optional[NodeNG] = None,
2841        body: Optional[typing.List[NodeNG]] = None,
2842        orelse: Optional[typing.List[NodeNG]] = None,
2843        type_annotation: Optional[NodeNG] = None,
2844    ) -> None:
2845        """Do some setup after initialisation.
2846
2847        :param target: What the loop assigns to.
2848
2849        :param iter: What the loop iterates over.
2850
2851        :param body: The contents of the body of the loop.
2852
2853        :param orelse: The contents of the ``else`` block of the loop.
2854        """
2855        self.target = target
2856        self.iter = iter
2857        if body is not None:
2858            self.body = body
2859        if orelse is not None:
2860            self.orelse = orelse
2861        self.type_annotation = type_annotation
2862
2863    @decorators.cachedproperty
2864    def blockstart_tolineno(self):
2865        """The line on which the beginning of this block ends.
2866
2867        :type: int
2868        """
2869        return self.iter.tolineno
2870
2871    def get_children(self):
2872        yield self.target
2873        yield self.iter
2874
2875        yield from self.body
2876        yield from self.orelse
2877
2878
2879class AsyncFor(For):
2880    """Class representing an :class:`ast.AsyncFor` node.
2881
2882    An :class:`AsyncFor` is an asynchronous :class:`For` built with
2883    the ``async`` keyword.
2884
2885    >>> import astroid
2886    >>> node = astroid.extract_node('''
2887    async def func(things):
2888        async for thing in things:
2889            print(thing)
2890    ''')
2891    >>> node
2892    <AsyncFunctionDef.func l.2 at 0x7f23b2e416d8>
2893    >>> node.body[0]
2894    <AsyncFor l.3 at 0x7f23b2e417b8>
2895    """
2896
2897
2898class Await(NodeNG):
2899    """Class representing an :class:`ast.Await` node.
2900
2901    An :class:`Await` is the ``await`` keyword.
2902
2903    >>> import astroid
2904    >>> node = astroid.extract_node('''
2905    async def func(things):
2906        await other_func()
2907    ''')
2908    >>> node
2909    <AsyncFunctionDef.func l.2 at 0x7f23b2e41748>
2910    >>> node.body[0]
2911    <Expr l.3 at 0x7f23b2e419e8>
2912    >>> list(node.body[0].get_children())[0]
2913    <Await l.3 at 0x7f23b2e41a20>
2914    """
2915
2916    _astroid_fields = ("value",)
2917
2918    def __init__(
2919        self,
2920        lineno: Optional[int] = None,
2921        col_offset: Optional[int] = None,
2922        parent: Optional[NodeNG] = None,
2923        *,
2924        end_lineno: Optional[int] = None,
2925        end_col_offset: Optional[int] = None,
2926    ) -> None:
2927        """
2928        :param lineno: The line that this node appears on in the source code.
2929
2930        :param col_offset: The column that this node appears on in the
2931            source code.
2932
2933        :param parent: The parent node in the syntax tree.
2934
2935        :param end_lineno: The last line this node appears on in the source code.
2936
2937        :param end_col_offset: The end column this node appears on in the
2938            source code. Note: This is after the last symbol.
2939        """
2940        self.value: Optional[NodeNG] = None
2941        """What to wait for."""
2942
2943        super().__init__(
2944            lineno=lineno,
2945            col_offset=col_offset,
2946            end_lineno=end_lineno,
2947            end_col_offset=end_col_offset,
2948            parent=parent,
2949        )
2950
2951    def postinit(self, value: Optional[NodeNG] = None) -> None:
2952        """Do some setup after initialisation.
2953
2954        :param value: What to wait for.
2955        """
2956        self.value = value
2957
2958    def get_children(self):
2959        yield self.value
2960
2961
2962class ImportFrom(mixins.NoChildrenMixin, mixins.ImportFromMixin, Statement):
2963    """Class representing an :class:`ast.ImportFrom` node.
2964
2965    >>> import astroid
2966    >>> node = astroid.extract_node('from my_package import my_module')
2967    >>> node
2968    <ImportFrom l.1 at 0x7f23b2e415c0>
2969    """
2970
2971    _other_fields = ("modname", "names", "level")
2972
2973    def __init__(
2974        self,
2975        fromname: Optional[str],
2976        names: typing.List[typing.Tuple[str, Optional[str]]],
2977        level: Optional[int] = 0,
2978        lineno: Optional[int] = None,
2979        col_offset: Optional[int] = None,
2980        parent: Optional[NodeNG] = None,
2981        *,
2982        end_lineno: Optional[int] = None,
2983        end_col_offset: Optional[int] = None,
2984    ) -> None:
2985        """
2986        :param fromname: The module that is being imported from.
2987
2988        :param names: What is being imported from the module.
2989
2990        :param level: The level of relative import.
2991
2992        :param lineno: The line that this node appears on in the source code.
2993
2994        :param col_offset: The column that this node appears on in the
2995            source code.
2996
2997        :param parent: The parent node in the syntax tree.
2998
2999        :param end_lineno: The last line this node appears on in the source code.
3000
3001        :param end_col_offset: The end column this node appears on in the
3002            source code. Note: This is after the last symbol.
3003        """
3004        self.modname: Optional[str] = fromname  # can be None
3005        """The module that is being imported from.
3006
3007        This is ``None`` for relative imports.
3008        """
3009
3010        self.names: typing.List[typing.Tuple[str, Optional[str]]] = names
3011        """What is being imported from the module.
3012
3013        Each entry is a :class:`tuple` of the name being imported,
3014        and the alias that the name is assigned to (if any).
3015        """
3016
3017        # TODO When is 'level' None?
3018        self.level: Optional[int] = level  # can be None
3019        """The level of relative import.
3020
3021        Essentially this is the number of dots in the import.
3022        This is always 0 for absolute imports.
3023        """
3024
3025        super().__init__(
3026            lineno=lineno,
3027            col_offset=col_offset,
3028            end_lineno=end_lineno,
3029            end_col_offset=end_col_offset,
3030            parent=parent,
3031        )
3032
3033
3034class Attribute(NodeNG):
3035    """Class representing an :class:`ast.Attribute` node."""
3036
3037    _astroid_fields = ("expr",)
3038    _other_fields = ("attrname",)
3039
3040    @decorators.deprecate_default_argument_values(attrname="str")
3041    def __init__(
3042        self,
3043        attrname: Optional[str] = None,
3044        lineno: Optional[int] = None,
3045        col_offset: Optional[int] = None,
3046        parent: Optional[NodeNG] = None,
3047        *,
3048        end_lineno: Optional[int] = None,
3049        end_col_offset: Optional[int] = None,
3050    ) -> None:
3051        """
3052        :param attrname: The name of the attribute.
3053
3054        :param lineno: The line that this node appears on in the source code.
3055
3056        :param col_offset: The column that this node appears on in the
3057            source code.
3058
3059        :param parent: The parent node in the syntax tree.
3060
3061        :param end_lineno: The last line this node appears on in the source code.
3062
3063        :param end_col_offset: The end column this node appears on in the
3064            source code. Note: This is after the last symbol.
3065        """
3066        self.expr: Optional[NodeNG] = None
3067        """The name that this node represents.
3068
3069        :type: Name or None
3070        """
3071
3072        self.attrname: Optional[str] = attrname
3073        """The name of the attribute."""
3074
3075        super().__init__(
3076            lineno=lineno,
3077            col_offset=col_offset,
3078            end_lineno=end_lineno,
3079            end_col_offset=end_col_offset,
3080            parent=parent,
3081        )
3082
3083    def postinit(self, expr: Optional[NodeNG] = None) -> None:
3084        """Do some setup after initialisation.
3085
3086        :param expr: The name that this node represents.
3087        :type expr: Name or None
3088        """
3089        self.expr = expr
3090
3091    def get_children(self):
3092        yield self.expr
3093
3094
3095class Global(mixins.NoChildrenMixin, Statement):
3096    """Class representing an :class:`ast.Global` node.
3097
3098    >>> import astroid
3099    >>> node = astroid.extract_node('global a_global')
3100    >>> node
3101    <Global l.1 at 0x7f23b2e9de10>
3102    """
3103
3104    _other_fields = ("names",)
3105
3106    def __init__(
3107        self,
3108        names: typing.List[str],
3109        lineno: Optional[int] = None,
3110        col_offset: Optional[int] = None,
3111        parent: Optional[NodeNG] = None,
3112        *,
3113        end_lineno: Optional[int] = None,
3114        end_col_offset: Optional[int] = None,
3115    ) -> None:
3116        """
3117        :param names: The names being declared as global.
3118
3119        :param lineno: The line that this node appears on in the source code.
3120
3121        :param col_offset: The column that this node appears on in the
3122            source code.
3123
3124        :param parent: The parent node in the syntax tree.
3125
3126        :param end_lineno: The last line this node appears on in the source code.
3127
3128        :param end_col_offset: The end column this node appears on in the
3129            source code. Note: This is after the last symbol.
3130        """
3131        self.names: typing.List[str] = names
3132        """The names being declared as global."""
3133
3134        super().__init__(
3135            lineno=lineno,
3136            col_offset=col_offset,
3137            end_lineno=end_lineno,
3138            end_col_offset=end_col_offset,
3139            parent=parent,
3140        )
3141
3142    def _infer_name(self, frame, name):
3143        return name
3144
3145
3146class If(mixins.MultiLineBlockMixin, mixins.BlockRangeMixIn, Statement):
3147    """Class representing an :class:`ast.If` node.
3148
3149    >>> import astroid
3150    >>> node = astroid.extract_node('if condition: print(True)')
3151    >>> node
3152    <If l.1 at 0x7f23b2e9dd30>
3153    """
3154
3155    _astroid_fields = ("test", "body", "orelse")
3156    _multi_line_block_fields = ("body", "orelse")
3157
3158    def __init__(
3159        self,
3160        lineno: Optional[int] = None,
3161        col_offset: Optional[int] = None,
3162        parent: Optional[NodeNG] = None,
3163        *,
3164        end_lineno: Optional[int] = None,
3165        end_col_offset: Optional[int] = None,
3166    ) -> None:
3167        """
3168        :param lineno: The line that this node appears on in the source code.
3169
3170        :param col_offset: The column that this node appears on in the
3171            source code.
3172
3173        :param parent: The parent node in the syntax tree.
3174
3175        :param end_lineno: The last line this node appears on in the source code.
3176
3177        :param end_col_offset: The end column this node appears on in the
3178            source code. Note: This is after the last symbol.
3179        """
3180        self.test: Optional[NodeNG] = None
3181        """The condition that the statement tests."""
3182
3183        self.body: typing.List[NodeNG] = []
3184        """The contents of the block."""
3185
3186        self.orelse: typing.List[NodeNG] = []
3187        """The contents of the ``else`` block."""
3188
3189        self.is_orelse: bool = False
3190        """Whether the if-statement is the orelse-block of another if statement."""
3191
3192        super().__init__(
3193            lineno=lineno,
3194            col_offset=col_offset,
3195            end_lineno=end_lineno,
3196            end_col_offset=end_col_offset,
3197            parent=parent,
3198        )
3199
3200    def postinit(
3201        self,
3202        test: Optional[NodeNG] = None,
3203        body: Optional[typing.List[NodeNG]] = None,
3204        orelse: Optional[typing.List[NodeNG]] = None,
3205    ) -> None:
3206        """Do some setup after initialisation.
3207
3208        :param test: The condition that the statement tests.
3209
3210        :param body: The contents of the block.
3211
3212        :param orelse: The contents of the ``else`` block.
3213        """
3214        self.test = test
3215        if body is not None:
3216            self.body = body
3217        if orelse is not None:
3218            self.orelse = orelse
3219        if isinstance(self.parent, If) and self in self.parent.orelse:
3220            self.is_orelse = True
3221
3222    @decorators.cachedproperty
3223    def blockstart_tolineno(self):
3224        """The line on which the beginning of this block ends.
3225
3226        :type: int
3227        """
3228        return self.test.tolineno
3229
3230    def block_range(self, lineno):
3231        """Get a range from the given line number to where this node ends.
3232
3233        :param lineno: The line number to start the range at.
3234        :type lineno: int
3235
3236        :returns: The range of line numbers that this node belongs to,
3237            starting at the given line number.
3238        :rtype: tuple(int, int)
3239        """
3240        if lineno == self.body[0].fromlineno:
3241            return lineno, lineno
3242        if lineno <= self.body[-1].tolineno:
3243            return lineno, self.body[-1].tolineno
3244        return self._elsed_block_range(lineno, self.orelse, self.body[0].fromlineno - 1)
3245
3246    def get_children(self):
3247        yield self.test
3248
3249        yield from self.body
3250        yield from self.orelse
3251
3252    def has_elif_block(self):
3253        return len(self.orelse) == 1 and isinstance(self.orelse[0], If)
3254
3255    def _get_yield_nodes_skip_lambdas(self):
3256        """An If node can contain a Yield node in the test"""
3257        yield from self.test._get_yield_nodes_skip_lambdas()
3258        yield from super()._get_yield_nodes_skip_lambdas()
3259
3260    def is_sys_guard(self) -> bool:
3261        """Return True if IF stmt is a sys.version_info guard.
3262
3263        >>> import astroid
3264        >>> node = astroid.extract_node('''
3265        import sys
3266        if sys.version_info > (3, 8):
3267            from typing import Literal
3268        else:
3269            from typing_extensions import Literal
3270        ''')
3271        >>> node.is_sys_guard()
3272        True
3273        """
3274        warnings.warn(
3275            "The 'is_sys_guard' function is deprecated and will be removed in astroid 3.0.0 "
3276            "It has been moved to pylint and can be imported from 'pylint.checkers.utils' "
3277            "starting with pylint 2.12",
3278            DeprecationWarning,
3279        )
3280        if isinstance(self.test, Compare):
3281            value = self.test.left
3282            if isinstance(value, Subscript):
3283                value = value.value
3284            if isinstance(value, Attribute) and value.as_string() == "sys.version_info":
3285                return True
3286
3287        return False
3288
3289    def is_typing_guard(self) -> bool:
3290        """Return True if IF stmt is a typing guard.
3291
3292        >>> import astroid
3293        >>> node = astroid.extract_node('''
3294        from typing import TYPE_CHECKING
3295        if TYPE_CHECKING:
3296            from xyz import a
3297        ''')
3298        >>> node.is_typing_guard()
3299        True
3300        """
3301        warnings.warn(
3302            "The 'is_typing_guard' function is deprecated and will be removed in astroid 3.0.0 "
3303            "It has been moved to pylint and can be imported from 'pylint.checkers.utils' "
3304            "starting with pylint 2.12",
3305            DeprecationWarning,
3306        )
3307        return isinstance(
3308            self.test, (Name, Attribute)
3309        ) and self.test.as_string().endswith("TYPE_CHECKING")
3310
3311
3312class IfExp(NodeNG):
3313    """Class representing an :class:`ast.IfExp` node.
3314    >>> import astroid
3315    >>> node = astroid.extract_node('value if condition else other')
3316    >>> node
3317    <IfExp l.1 at 0x7f23b2e9dbe0>
3318    """
3319
3320    _astroid_fields = ("test", "body", "orelse")
3321
3322    def __init__(
3323        self,
3324        lineno: Optional[int] = None,
3325        col_offset: Optional[int] = None,
3326        parent: Optional[NodeNG] = None,
3327        *,
3328        end_lineno: Optional[int] = None,
3329        end_col_offset: Optional[int] = None,
3330    ) -> None:
3331        """
3332        :param lineno: The line that this node appears on in the source code.
3333
3334        :param col_offset: The column that this node appears on in the
3335            source code.
3336
3337        :param parent: The parent node in the syntax tree.
3338
3339        :param end_lineno: The last line this node appears on in the source code.
3340
3341        :param end_col_offset: The end column this node appears on in the
3342            source code. Note: This is after the last symbol.
3343        """
3344        self.test: Optional[NodeNG] = None
3345        """The condition that the statement tests."""
3346
3347        self.body: Optional[NodeNG] = None
3348        """The contents of the block."""
3349
3350        self.orelse: Optional[NodeNG] = None
3351        """The contents of the ``else`` block."""
3352
3353        super().__init__(
3354            lineno=lineno,
3355            col_offset=col_offset,
3356            end_lineno=end_lineno,
3357            end_col_offset=end_col_offset,
3358            parent=parent,
3359        )
3360
3361    def postinit(
3362        self,
3363        test: Optional[NodeNG] = None,
3364        body: Optional[NodeNG] = None,
3365        orelse: Optional[NodeNG] = None,
3366    ) -> None:
3367        """Do some setup after initialisation.
3368
3369        :param test: The condition that the statement tests.
3370
3371        :param body: The contents of the block.
3372
3373        :param orelse: The contents of the ``else`` block.
3374        """
3375        self.test = test
3376        self.body = body
3377        self.orelse = orelse
3378
3379    def get_children(self):
3380        yield self.test
3381        yield self.body
3382        yield self.orelse
3383
3384    def op_left_associative(self):
3385        # `1 if True else 2 if False else 3` is parsed as
3386        # `1 if True else (2 if False else 3)`
3387        return False
3388
3389
3390class Import(mixins.NoChildrenMixin, mixins.ImportFromMixin, Statement):
3391    """Class representing an :class:`ast.Import` node.
3392    >>> import astroid
3393    >>> node = astroid.extract_node('import astroid')
3394    >>> node
3395    <Import l.1 at 0x7f23b2e4e5c0>
3396    """
3397
3398    _other_fields = ("names",)
3399
3400    @decorators.deprecate_default_argument_values(names="list[tuple[str, str | None]]")
3401    def __init__(
3402        self,
3403        names: Optional[typing.List[typing.Tuple[str, Optional[str]]]] = None,
3404        lineno: Optional[int] = None,
3405        col_offset: Optional[int] = None,
3406        parent: Optional[NodeNG] = None,
3407        *,
3408        end_lineno: Optional[int] = None,
3409        end_col_offset: Optional[int] = None,
3410    ) -> None:
3411        """
3412        :param names: The names being imported.
3413
3414        :param lineno: The line that this node appears on in the source code.
3415
3416        :param col_offset: The column that this node appears on in the
3417            source code.
3418
3419        :param parent: The parent node in the syntax tree.
3420
3421        :param end_lineno: The last line this node appears on in the source code.
3422
3423        :param end_col_offset: The end column this node appears on in the
3424            source code. Note: This is after the last symbol.
3425        """
3426        self.names: typing.List[typing.Tuple[str, Optional[str]]] = names or []
3427        """The names being imported.
3428
3429        Each entry is a :class:`tuple` of the name being imported,
3430        and the alias that the name is assigned to (if any).
3431        """
3432
3433        super().__init__(
3434            lineno=lineno,
3435            col_offset=col_offset,
3436            end_lineno=end_lineno,
3437            end_col_offset=end_col_offset,
3438            parent=parent,
3439        )
3440
3441
3442class Index(NodeNG):
3443    """Class representing an :class:`ast.Index` node.
3444
3445    An :class:`Index` is a simple subscript.
3446
3447    Deprecated since v2.6.0 - Now part of the :class:`Subscript` node.
3448    Will be removed with the release of v2.7.0
3449    """
3450
3451
3452class Keyword(NodeNG):
3453    """Class representing an :class:`ast.keyword` node.
3454
3455    >>> import astroid
3456    >>> node = astroid.extract_node('function(a_kwarg=True)')
3457    >>> node
3458    <Call l.1 at 0x7f23b2e9e320>
3459    >>> node.keywords
3460    [<Keyword l.1 at 0x7f23b2e9e9b0>]
3461    """
3462
3463    _astroid_fields = ("value",)
3464    _other_fields = ("arg",)
3465
3466    def __init__(
3467        self,
3468        arg: Optional[str] = None,
3469        lineno: Optional[int] = None,
3470        col_offset: Optional[int] = None,
3471        parent: Optional[NodeNG] = None,
3472        *,
3473        end_lineno: Optional[int] = None,
3474        end_col_offset: Optional[int] = None,
3475    ) -> None:
3476        """
3477        :param arg: The argument being assigned to.
3478
3479        :param lineno: The line that this node appears on in the source code.
3480
3481        :param col_offset: The column that this node appears on in the
3482            source code.
3483
3484        :param parent: The parent node in the syntax tree.
3485
3486        :param end_lineno: The last line this node appears on in the source code.
3487
3488        :param end_col_offset: The end column this node appears on in the
3489            source code. Note: This is after the last symbol.
3490        """
3491        self.arg: Optional[str] = arg  # can be None
3492        """The argument being assigned to."""
3493
3494        self.value: Optional[NodeNG] = None
3495        """The value being assigned to the keyword argument."""
3496
3497        super().__init__(
3498            lineno=lineno,
3499            col_offset=col_offset,
3500            end_lineno=end_lineno,
3501            end_col_offset=end_col_offset,
3502            parent=parent,
3503        )
3504
3505    def postinit(self, value: Optional[NodeNG] = None) -> None:
3506        """Do some setup after initialisation.
3507
3508        :param value: The value being assigned to the ketword argument.
3509        """
3510        self.value = value
3511
3512    def get_children(self):
3513        yield self.value
3514
3515
3516class List(BaseContainer):
3517    """Class representing an :class:`ast.List` node.
3518
3519    >>> import astroid
3520    >>> node = astroid.extract_node('[1, 2, 3]')
3521    >>> node
3522    <List.list l.1 at 0x7f23b2e9e128>
3523    """
3524
3525    _other_fields = ("ctx",)
3526
3527    def __init__(
3528        self,
3529        ctx: Optional[Context] = None,
3530        lineno: Optional[int] = None,
3531        col_offset: Optional[int] = None,
3532        parent: Optional[NodeNG] = None,
3533        *,
3534        end_lineno: Optional[int] = None,
3535        end_col_offset: Optional[int] = None,
3536    ) -> None:
3537        """
3538        :param ctx: Whether the list is assigned to or loaded from.
3539
3540        :param lineno: The line that this node appears on in the source code.
3541
3542        :param col_offset: The column that this node appears on in the
3543            source code.
3544
3545        :param parent: The parent node in the syntax tree.
3546
3547        :param end_lineno: The last line this node appears on in the source code.
3548
3549        :param end_col_offset: The end column this node appears on in the
3550            source code. Note: This is after the last symbol.
3551        """
3552        self.ctx: Optional[Context] = ctx
3553        """Whether the list is assigned to or loaded from."""
3554
3555        super().__init__(
3556            lineno=lineno,
3557            col_offset=col_offset,
3558            end_lineno=end_lineno,
3559            end_col_offset=end_col_offset,
3560            parent=parent,
3561        )
3562
3563    def pytype(self):
3564        """Get the name of the type that this node represents.
3565
3566        :returns: The name of the type.
3567        :rtype: str
3568        """
3569        return "builtins.list"
3570
3571    def getitem(self, index, context=None):
3572        """Get an item from this node.
3573
3574        :param index: The node to use as a subscript index.
3575        :type index: Const or Slice
3576        """
3577        return _container_getitem(self, self.elts, index, context=context)
3578
3579
3580class Nonlocal(mixins.NoChildrenMixin, Statement):
3581    """Class representing an :class:`ast.Nonlocal` node.
3582
3583    >>> import astroid
3584    >>> node = astroid.extract_node('''
3585    def function():
3586        nonlocal var
3587    ''')
3588    >>> node
3589    <FunctionDef.function l.2 at 0x7f23b2e9e208>
3590    >>> node.body[0]
3591    <Nonlocal l.3 at 0x7f23b2e9e908>
3592    """
3593
3594    _other_fields = ("names",)
3595
3596    def __init__(
3597        self,
3598        names: typing.List[str],
3599        lineno: Optional[int] = None,
3600        col_offset: Optional[int] = None,
3601        parent: Optional[NodeNG] = None,
3602        *,
3603        end_lineno: Optional[int] = None,
3604        end_col_offset: Optional[int] = None,
3605    ) -> None:
3606        """
3607        :param names: The names being declared as not local.
3608
3609        :param lineno: The line that this node appears on in the source code.
3610
3611        :param col_offset: The column that this node appears on in the
3612            source code.
3613
3614        :param parent: The parent node in the syntax tree.
3615
3616        :param end_lineno: The last line this node appears on in the source code.
3617
3618        :param end_col_offset: The end column this node appears on in the
3619            source code. Note: This is after the last symbol.
3620        """
3621        self.names: typing.List[str] = names
3622        """The names being declared as not local."""
3623
3624        super().__init__(
3625            lineno=lineno,
3626            col_offset=col_offset,
3627            end_lineno=end_lineno,
3628            end_col_offset=end_col_offset,
3629            parent=parent,
3630        )
3631
3632    def _infer_name(self, frame, name):
3633        return name
3634
3635
3636class Pass(mixins.NoChildrenMixin, Statement):
3637    """Class representing an :class:`ast.Pass` node.
3638
3639    >>> import astroid
3640    >>> node = astroid.extract_node('pass')
3641    >>> node
3642    <Pass l.1 at 0x7f23b2e9e748>
3643    """
3644
3645
3646class Raise(Statement):
3647    """Class representing an :class:`ast.Raise` node.
3648
3649    >>> import astroid
3650    >>> node = astroid.extract_node('raise RuntimeError("Something bad happened!")')
3651    >>> node
3652    <Raise l.1 at 0x7f23b2e9e828>
3653    """
3654
3655    _astroid_fields = ("exc", "cause")
3656
3657    def __init__(
3658        self,
3659        lineno: Optional[int] = None,
3660        col_offset: Optional[int] = None,
3661        parent: Optional[NodeNG] = None,
3662        *,
3663        end_lineno: Optional[int] = None,
3664        end_col_offset: Optional[int] = None,
3665    ) -> None:
3666        """
3667        :param lineno: The line that this node appears on in the source code.
3668
3669        :param col_offset: The column that this node appears on in the
3670            source code.
3671
3672        :param parent: The parent node in the syntax tree.
3673
3674        :param end_lineno: The last line this node appears on in the source code.
3675
3676        :param end_col_offset: The end column this node appears on in the
3677            source code. Note: This is after the last symbol.
3678        """
3679        self.exc: Optional[NodeNG] = None  # can be None
3680        """What is being raised."""
3681
3682        self.cause: Optional[NodeNG] = None  # can be None
3683        """The exception being used to raise this one."""
3684
3685        super().__init__(
3686            lineno=lineno,
3687            col_offset=col_offset,
3688            end_lineno=end_lineno,
3689            end_col_offset=end_col_offset,
3690            parent=parent,
3691        )
3692
3693    def postinit(
3694        self,
3695        exc: Optional[NodeNG] = None,
3696        cause: Optional[NodeNG] = None,
3697    ) -> None:
3698        """Do some setup after initialisation.
3699
3700        :param exc: What is being raised.
3701
3702        :param cause: The exception being used to raise this one.
3703        """
3704        self.exc = exc
3705        self.cause = cause
3706
3707    def raises_not_implemented(self):
3708        """Check if this node raises a :class:`NotImplementedError`.
3709
3710        :returns: True if this node raises a :class:`NotImplementedError`,
3711            False otherwise.
3712        :rtype: bool
3713        """
3714        if not self.exc:
3715            return False
3716        for name in self.exc._get_name_nodes():
3717            if name.name == "NotImplementedError":
3718                return True
3719        return False
3720
3721    def get_children(self):
3722        if self.exc is not None:
3723            yield self.exc
3724
3725        if self.cause is not None:
3726            yield self.cause
3727
3728
3729class Return(Statement):
3730    """Class representing an :class:`ast.Return` node.
3731
3732    >>> import astroid
3733    >>> node = astroid.extract_node('return True')
3734    >>> node
3735    <Return l.1 at 0x7f23b8211908>
3736    """
3737
3738    _astroid_fields = ("value",)
3739
3740    def __init__(
3741        self,
3742        lineno: Optional[int] = None,
3743        col_offset: Optional[int] = None,
3744        parent: Optional[NodeNG] = None,
3745        *,
3746        end_lineno: Optional[int] = None,
3747        end_col_offset: Optional[int] = None,
3748    ) -> None:
3749        """
3750        :param lineno: The line that this node appears on in the source code.
3751
3752        :param col_offset: The column that this node appears on in the
3753            source code.
3754
3755        :param parent: The parent node in the syntax tree.
3756
3757        :param end_lineno: The last line this node appears on in the source code.
3758
3759        :param end_col_offset: The end column this node appears on in the
3760            source code. Note: This is after the last symbol.
3761        """
3762        self.value: Optional[NodeNG] = None  # can be None
3763        """The value being returned."""
3764
3765        super().__init__(
3766            lineno=lineno,
3767            col_offset=col_offset,
3768            end_lineno=end_lineno,
3769            end_col_offset=end_col_offset,
3770            parent=parent,
3771        )
3772
3773    def postinit(self, value: Optional[NodeNG] = None) -> None:
3774        """Do some setup after initialisation.
3775
3776        :param value: The value being returned.
3777        """
3778        self.value = value
3779
3780    def get_children(self):
3781        if self.value is not None:
3782            yield self.value
3783
3784    def is_tuple_return(self):
3785        return isinstance(self.value, Tuple)
3786
3787    def _get_return_nodes_skip_functions(self):
3788        yield self
3789
3790
3791class Set(BaseContainer):
3792    """Class representing an :class:`ast.Set` node.
3793
3794    >>> import astroid
3795    >>> node = astroid.extract_node('{1, 2, 3}')
3796    >>> node
3797    <Set.set l.1 at 0x7f23b2e71d68>
3798    """
3799
3800    def pytype(self):
3801        """Get the name of the type that this node represents.
3802
3803        :returns: The name of the type.
3804        :rtype: str
3805        """
3806        return "builtins.set"
3807
3808
3809class Slice(NodeNG):
3810    """Class representing an :class:`ast.Slice` node.
3811
3812    >>> import astroid
3813    >>> node = astroid.extract_node('things[1:3]')
3814    >>> node
3815    <Subscript l.1 at 0x7f23b2e71f60>
3816    >>> node.slice
3817    <Slice l.1 at 0x7f23b2e71e80>
3818    """
3819
3820    _astroid_fields = ("lower", "upper", "step")
3821
3822    def __init__(
3823        self,
3824        lineno: Optional[int] = None,
3825        col_offset: Optional[int] = None,
3826        parent: Optional[NodeNG] = None,
3827        *,
3828        end_lineno: Optional[int] = None,
3829        end_col_offset: Optional[int] = None,
3830    ) -> None:
3831        """
3832        :param lineno: The line that this node appears on in the source code.
3833
3834        :param col_offset: The column that this node appears on in the
3835            source code.
3836
3837        :param parent: The parent node in the syntax tree.
3838
3839        :param end_lineno: The last line this node appears on in the source code.
3840
3841        :param end_col_offset: The end column this node appears on in the
3842            source code. Note: This is after the last symbol.
3843        """
3844        self.lower: Optional[NodeNG] = None  # can be None
3845        """The lower index in the slice."""
3846
3847        self.upper: Optional[NodeNG] = None  # can be None
3848        """The upper index in the slice."""
3849
3850        self.step: Optional[NodeNG] = None  # can be None
3851        """The step to take between indexes."""
3852
3853        super().__init__(
3854            lineno=lineno,
3855            col_offset=col_offset,
3856            end_lineno=end_lineno,
3857            end_col_offset=end_col_offset,
3858            parent=parent,
3859        )
3860
3861    def postinit(
3862        self,
3863        lower: Optional[NodeNG] = None,
3864        upper: Optional[NodeNG] = None,
3865        step: Optional[NodeNG] = None,
3866    ) -> None:
3867        """Do some setup after initialisation.
3868
3869        :param lower: The lower index in the slice.
3870
3871        :param upper: The upper index in the slice.
3872
3873        :param step: The step to take between index.
3874        """
3875        self.lower = lower
3876        self.upper = upper
3877        self.step = step
3878
3879    def _wrap_attribute(self, attr):
3880        """Wrap the empty attributes of the Slice in a Const node."""
3881        if not attr:
3882            const = const_factory(attr)
3883            const.parent = self
3884            return const
3885        return attr
3886
3887    @decorators.cachedproperty
3888    def _proxied(self):
3889        builtins = AstroidManager().builtins_module
3890        return builtins.getattr("slice")[0]
3891
3892    def pytype(self):
3893        """Get the name of the type that this node represents.
3894
3895        :returns: The name of the type.
3896        :rtype: str
3897        """
3898        return "builtins.slice"
3899
3900    def igetattr(self, attrname, context=None):
3901        """Infer the possible values of the given attribute on the slice.
3902
3903        :param attrname: The name of the attribute to infer.
3904        :type attrname: str
3905
3906        :returns: The inferred possible values.
3907        :rtype: iterable(NodeNG)
3908        """
3909        if attrname == "start":
3910            yield self._wrap_attribute(self.lower)
3911        elif attrname == "stop":
3912            yield self._wrap_attribute(self.upper)
3913        elif attrname == "step":
3914            yield self._wrap_attribute(self.step)
3915        else:
3916            yield from self.getattr(attrname, context=context)
3917
3918    def getattr(self, attrname, context=None):
3919        return self._proxied.getattr(attrname, context)
3920
3921    def get_children(self):
3922        if self.lower is not None:
3923            yield self.lower
3924
3925        if self.upper is not None:
3926            yield self.upper
3927
3928        if self.step is not None:
3929            yield self.step
3930
3931
3932class Starred(mixins.ParentAssignTypeMixin, NodeNG):
3933    """Class representing an :class:`ast.Starred` node.
3934
3935    >>> import astroid
3936    >>> node = astroid.extract_node('*args')
3937    >>> node
3938    <Starred l.1 at 0x7f23b2e41978>
3939    """
3940
3941    _astroid_fields = ("value",)
3942    _other_fields = ("ctx",)
3943
3944    def __init__(
3945        self,
3946        ctx: Optional[Context] = None,
3947        lineno: Optional[int] = None,
3948        col_offset: Optional[int] = None,
3949        parent: Optional[NodeNG] = None,
3950        *,
3951        end_lineno: Optional[int] = None,
3952        end_col_offset: Optional[int] = None,
3953    ) -> None:
3954        """
3955        :param ctx: Whether the list is assigned to or loaded from.
3956
3957        :param lineno: The line that this node appears on in the source code.
3958
3959        :param col_offset: The column that this node appears on in the
3960            source code.
3961
3962        :param parent: The parent node in the syntax tree.
3963
3964        :param end_lineno: The last line this node appears on in the source code.
3965
3966        :param end_col_offset: The end column this node appears on in the
3967            source code. Note: This is after the last symbol.
3968        """
3969        self.value: Optional[NodeNG] = None
3970        """What is being unpacked."""
3971
3972        self.ctx: Optional[Context] = ctx
3973        """Whether the starred item is assigned to or loaded from."""
3974
3975        super().__init__(
3976            lineno=lineno,
3977            col_offset=col_offset,
3978            end_lineno=end_lineno,
3979            end_col_offset=end_col_offset,
3980            parent=parent,
3981        )
3982
3983    def postinit(self, value: Optional[NodeNG] = None) -> None:
3984        """Do some setup after initialisation.
3985
3986        :param value: What is being unpacked.
3987        """
3988        self.value = value
3989
3990    def get_children(self):
3991        yield self.value
3992
3993
3994class Subscript(NodeNG):
3995    """Class representing an :class:`ast.Subscript` node.
3996
3997    >>> import astroid
3998    >>> node = astroid.extract_node('things[1:3]')
3999    >>> node
4000    <Subscript l.1 at 0x7f23b2e71f60>
4001    """
4002
4003    _astroid_fields = ("value", "slice")
4004    _other_fields = ("ctx",)
4005
4006    def __init__(
4007        self,
4008        ctx: Optional[Context] = None,
4009        lineno: Optional[int] = None,
4010        col_offset: Optional[int] = None,
4011        parent: Optional[NodeNG] = None,
4012        *,
4013        end_lineno: Optional[int] = None,
4014        end_col_offset: Optional[int] = None,
4015    ) -> None:
4016        """
4017        :param ctx: Whether the subscripted item is assigned to or loaded from.
4018
4019        :param lineno: The line that this node appears on in the source code.
4020
4021        :param col_offset: The column that this node appears on in the
4022            source code.
4023
4024        :param parent: The parent node in the syntax tree.
4025
4026        :param end_lineno: The last line this node appears on in the source code.
4027
4028        :param end_col_offset: The end column this node appears on in the
4029            source code. Note: This is after the last symbol.
4030        """
4031        self.value: Optional[NodeNG] = None
4032        """What is being indexed."""
4033
4034        self.slice: Optional[NodeNG] = None
4035        """The slice being used to lookup."""
4036
4037        self.ctx: Optional[Context] = ctx
4038        """Whether the subscripted item is assigned to or loaded from."""
4039
4040        super().__init__(
4041            lineno=lineno,
4042            col_offset=col_offset,
4043            end_lineno=end_lineno,
4044            end_col_offset=end_col_offset,
4045            parent=parent,
4046        )
4047
4048    # pylint: disable=redefined-builtin; had to use the same name as builtin ast module.
4049    def postinit(
4050        self, value: Optional[NodeNG] = None, slice: Optional[NodeNG] = None
4051    ) -> None:
4052        """Do some setup after initialisation.
4053
4054        :param value: What is being indexed.
4055
4056        :param slice: The slice being used to lookup.
4057        """
4058        self.value = value
4059        self.slice = slice
4060
4061    def get_children(self):
4062        yield self.value
4063        yield self.slice
4064
4065
4066class TryExcept(mixins.MultiLineBlockMixin, mixins.BlockRangeMixIn, Statement):
4067    """Class representing an :class:`ast.TryExcept` node.
4068
4069    >>> import astroid
4070    >>> node = astroid.extract_node('''
4071        try:
4072            do_something()
4073        except Exception as error:
4074            print("Error!")
4075        ''')
4076    >>> node
4077    <TryExcept l.2 at 0x7f23b2e9d908>
4078    """
4079
4080    _astroid_fields = ("body", "handlers", "orelse")
4081    _multi_line_block_fields = ("body", "handlers", "orelse")
4082
4083    def __init__(
4084        self,
4085        lineno: Optional[int] = None,
4086        col_offset: Optional[int] = None,
4087        parent: Optional[NodeNG] = None,
4088        *,
4089        end_lineno: Optional[int] = None,
4090        end_col_offset: Optional[int] = None,
4091    ) -> None:
4092        """
4093        :param lineno: The line that this node appears on in the source code.
4094
4095        :param col_offset: The column that this node appears on in the
4096            source code.
4097
4098        :param parent: The parent node in the syntax tree.
4099
4100        :param end_lineno: The last line this node appears on in the source code.
4101
4102        :param end_col_offset: The end column this node appears on in the
4103            source code. Note: This is after the last symbol.
4104        """
4105        self.body: typing.List[NodeNG] = []
4106        """The contents of the block to catch exceptions from."""
4107
4108        self.handlers: typing.List[ExceptHandler] = []
4109        """The exception handlers."""
4110
4111        self.orelse: typing.List[NodeNG] = []
4112        """The contents of the ``else`` block."""
4113
4114        super().__init__(
4115            lineno=lineno,
4116            col_offset=col_offset,
4117            end_lineno=end_lineno,
4118            end_col_offset=end_col_offset,
4119            parent=parent,
4120        )
4121
4122    def postinit(
4123        self,
4124        body: Optional[typing.List[NodeNG]] = None,
4125        handlers: Optional[typing.List[ExceptHandler]] = None,
4126        orelse: Optional[typing.List[NodeNG]] = None,
4127    ) -> None:
4128        """Do some setup after initialisation.
4129
4130        :param body: The contents of the block to catch exceptions from.
4131
4132        :param handlers: The exception handlers.
4133
4134        :param orelse: The contents of the ``else`` block.
4135        """
4136        if body is not None:
4137            self.body = body
4138        if handlers is not None:
4139            self.handlers = handlers
4140        if orelse is not None:
4141            self.orelse = orelse
4142
4143    def _infer_name(self, frame, name):
4144        return name
4145
4146    def block_range(self, lineno):
4147        """Get a range from the given line number to where this node ends.
4148
4149        :param lineno: The line number to start the range at.
4150        :type lineno: int
4151
4152        :returns: The range of line numbers that this node belongs to,
4153            starting at the given line number.
4154        :rtype: tuple(int, int)
4155        """
4156        last = None
4157        for exhandler in self.handlers:
4158            if exhandler.type and lineno == exhandler.type.fromlineno:
4159                return lineno, lineno
4160            if exhandler.body[0].fromlineno <= lineno <= exhandler.body[-1].tolineno:
4161                return lineno, exhandler.body[-1].tolineno
4162            if last is None:
4163                last = exhandler.body[0].fromlineno - 1
4164        return self._elsed_block_range(lineno, self.orelse, last)
4165
4166    def get_children(self):
4167        yield from self.body
4168
4169        yield from self.handlers or ()
4170        yield from self.orelse or ()
4171
4172
4173class TryFinally(mixins.MultiLineBlockMixin, mixins.BlockRangeMixIn, Statement):
4174    """Class representing an :class:`ast.TryFinally` node.
4175
4176    >>> import astroid
4177    >>> node = astroid.extract_node('''
4178    try:
4179        do_something()
4180    except Exception as error:
4181        print("Error!")
4182    finally:
4183        print("Cleanup!")
4184    ''')
4185    >>> node
4186    <TryFinally l.2 at 0x7f23b2e41d68>
4187    """
4188
4189    _astroid_fields = ("body", "finalbody")
4190    _multi_line_block_fields = ("body", "finalbody")
4191
4192    def __init__(
4193        self,
4194        lineno: Optional[int] = None,
4195        col_offset: Optional[int] = None,
4196        parent: Optional[NodeNG] = None,
4197        *,
4198        end_lineno: Optional[int] = None,
4199        end_col_offset: Optional[int] = None,
4200    ) -> None:
4201        """
4202        :param lineno: The line that this node appears on in the source code.
4203
4204        :param col_offset: The column that this node appears on in the
4205            source code.
4206
4207        :param parent: The parent node in the syntax tree.
4208
4209        :param end_lineno: The last line this node appears on in the source code.
4210
4211        :param end_col_offset: The end column this node appears on in the
4212            source code. Note: This is after the last symbol.
4213        """
4214        self.body: typing.Union[typing.List[TryExcept], typing.List[NodeNG]] = []
4215        """The try-except that the finally is attached to."""
4216
4217        self.finalbody: typing.List[NodeNG] = []
4218        """The contents of the ``finally`` block."""
4219
4220        super().__init__(
4221            lineno=lineno,
4222            col_offset=col_offset,
4223            end_lineno=end_lineno,
4224            end_col_offset=end_col_offset,
4225            parent=parent,
4226        )
4227
4228    def postinit(
4229        self,
4230        body: typing.Union[typing.List[TryExcept], typing.List[NodeNG], None] = None,
4231        finalbody: Optional[typing.List[NodeNG]] = None,
4232    ) -> None:
4233        """Do some setup after initialisation.
4234
4235        :param body: The try-except that the finally is attached to.
4236
4237        :param finalbody: The contents of the ``finally`` block.
4238        """
4239        if body is not None:
4240            self.body = body
4241        if finalbody is not None:
4242            self.finalbody = finalbody
4243
4244    def block_range(self, lineno):
4245        """Get a range from the given line number to where this node ends.
4246
4247        :param lineno: The line number to start the range at.
4248        :type lineno: int
4249
4250        :returns: The range of line numbers that this node belongs to,
4251            starting at the given line number.
4252        :rtype: tuple(int, int)
4253        """
4254        child = self.body[0]
4255        # py2.5 try: except: finally:
4256        if (
4257            isinstance(child, TryExcept)
4258            and child.fromlineno == self.fromlineno
4259            and child.tolineno >= lineno > self.fromlineno
4260        ):
4261            return child.block_range(lineno)
4262        return self._elsed_block_range(lineno, self.finalbody)
4263
4264    def get_children(self):
4265        yield from self.body
4266        yield from self.finalbody
4267
4268
4269class Tuple(BaseContainer):
4270    """Class representing an :class:`ast.Tuple` node.
4271
4272    >>> import astroid
4273    >>> node = astroid.extract_node('(1, 2, 3)')
4274    >>> node
4275    <Tuple.tuple l.1 at 0x7f23b2e41780>
4276    """
4277
4278    _other_fields = ("ctx",)
4279
4280    def __init__(
4281        self,
4282        ctx: Optional[Context] = None,
4283        lineno: Optional[int] = None,
4284        col_offset: Optional[int] = None,
4285        parent: Optional[NodeNG] = None,
4286        *,
4287        end_lineno: Optional[int] = None,
4288        end_col_offset: Optional[int] = None,
4289    ) -> None:
4290        """
4291        :param ctx: Whether the tuple is assigned to or loaded from.
4292
4293        :param lineno: The line that this node appears on in the source code.
4294
4295        :param col_offset: The column that this node appears on in the
4296            source code.
4297
4298        :param parent: The parent node in the syntax tree.
4299
4300        :param end_lineno: The last line this node appears on in the source code.
4301
4302        :param end_col_offset: The end column this node appears on in the
4303            source code. Note: This is after the last symbol.
4304        """
4305        self.ctx: Optional[Context] = ctx
4306        """Whether the tuple is assigned to or loaded from."""
4307
4308        super().__init__(
4309            lineno=lineno,
4310            col_offset=col_offset,
4311            end_lineno=end_lineno,
4312            end_col_offset=end_col_offset,
4313            parent=parent,
4314        )
4315
4316    def pytype(self):
4317        """Get the name of the type that this node represents.
4318
4319        :returns: The name of the type.
4320        :rtype: str
4321        """
4322        return "builtins.tuple"
4323
4324    def getitem(self, index, context=None):
4325        """Get an item from this node.
4326
4327        :param index: The node to use as a subscript index.
4328        :type index: Const or Slice
4329        """
4330        return _container_getitem(self, self.elts, index, context=context)
4331
4332
4333class UnaryOp(NodeNG):
4334    """Class representing an :class:`ast.UnaryOp` node.
4335
4336    >>> import astroid
4337    >>> node = astroid.extract_node('-5')
4338    >>> node
4339    <UnaryOp l.1 at 0x7f23b2e4e198>
4340    """
4341
4342    _astroid_fields = ("operand",)
4343    _other_fields = ("op",)
4344
4345    @decorators.deprecate_default_argument_values(op="str")
4346    def __init__(
4347        self,
4348        op: Optional[str] = None,
4349        lineno: Optional[int] = None,
4350        col_offset: Optional[int] = None,
4351        parent: Optional[NodeNG] = None,
4352        *,
4353        end_lineno: Optional[int] = None,
4354        end_col_offset: Optional[int] = None,
4355    ) -> None:
4356        """
4357        :param op: The operator.
4358
4359        :param lineno: The line that this node appears on in the source code.
4360
4361        :param col_offset: The column that this node appears on in the
4362            source code.
4363
4364        :param parent: The parent node in the syntax tree.
4365
4366        :param end_lineno: The last line this node appears on in the source code.
4367
4368        :param end_col_offset: The end column this node appears on in the
4369            source code. Note: This is after the last symbol.
4370        """
4371        self.op: Optional[str] = op
4372        """The operator."""
4373
4374        self.operand: Optional[NodeNG] = None
4375        """What the unary operator is applied to."""
4376
4377        super().__init__(
4378            lineno=lineno,
4379            col_offset=col_offset,
4380            end_lineno=end_lineno,
4381            end_col_offset=end_col_offset,
4382            parent=parent,
4383        )
4384
4385    def postinit(self, operand: Optional[NodeNG] = None) -> None:
4386        """Do some setup after initialisation.
4387
4388        :param operand: What the unary operator is applied to.
4389        """
4390        self.operand = operand
4391
4392    # This is set by inference.py
4393    def _infer_unaryop(self, context=None):
4394        raise NotImplementedError
4395
4396    def type_errors(self, context=None):
4397        """Get a list of type errors which can occur during inference.
4398
4399        Each TypeError is represented by a :class:`BadBinaryOperationMessage`,
4400        which holds the original exception.
4401
4402        :returns: The list of possible type errors.
4403        :rtype: list(BadBinaryOperationMessage)
4404        """
4405        try:
4406            results = self._infer_unaryop(context=context)
4407            return [
4408                result
4409                for result in results
4410                if isinstance(result, util.BadUnaryOperationMessage)
4411            ]
4412        except InferenceError:
4413            return []
4414
4415    def get_children(self):
4416        yield self.operand
4417
4418    def op_precedence(self):
4419        if self.op == "not":
4420            return OP_PRECEDENCE[self.op]
4421
4422        return super().op_precedence()
4423
4424
4425class While(mixins.MultiLineBlockMixin, mixins.BlockRangeMixIn, Statement):
4426    """Class representing an :class:`ast.While` node.
4427
4428    >>> import astroid
4429    >>> node = astroid.extract_node('''
4430    while condition():
4431        print("True")
4432    ''')
4433    >>> node
4434    <While l.2 at 0x7f23b2e4e390>
4435    """
4436
4437    _astroid_fields = ("test", "body", "orelse")
4438    _multi_line_block_fields = ("body", "orelse")
4439
4440    def __init__(
4441        self,
4442        lineno: Optional[int] = None,
4443        col_offset: Optional[int] = None,
4444        parent: Optional[NodeNG] = None,
4445        *,
4446        end_lineno: Optional[int] = None,
4447        end_col_offset: Optional[int] = None,
4448    ) -> None:
4449        """
4450        :param lineno: The line that this node appears on in the source code.
4451
4452        :param col_offset: The column that this node appears on in the
4453            source code.
4454
4455        :param parent: The parent node in the syntax tree.
4456
4457        :param end_lineno: The last line this node appears on in the source code.
4458
4459        :param end_col_offset: The end column this node appears on in the
4460            source code. Note: This is after the last symbol.
4461        """
4462        self.test: Optional[NodeNG] = None
4463        """The condition that the loop tests."""
4464
4465        self.body: typing.List[NodeNG] = []
4466        """The contents of the loop."""
4467
4468        self.orelse: typing.List[NodeNG] = []
4469        """The contents of the ``else`` block."""
4470
4471        super().__init__(
4472            lineno=lineno,
4473            col_offset=col_offset,
4474            end_lineno=end_lineno,
4475            end_col_offset=end_col_offset,
4476            parent=parent,
4477        )
4478
4479    def postinit(
4480        self,
4481        test: Optional[NodeNG] = None,
4482        body: Optional[typing.List[NodeNG]] = None,
4483        orelse: Optional[typing.List[NodeNG]] = None,
4484    ) -> None:
4485        """Do some setup after initialisation.
4486
4487        :param test: The condition that the loop tests.
4488
4489        :param body: The contents of the loop.
4490
4491        :param orelse: The contents of the ``else`` block.
4492        """
4493        self.test = test
4494        if body is not None:
4495            self.body = body
4496        if orelse is not None:
4497            self.orelse = orelse
4498
4499    @decorators.cachedproperty
4500    def blockstart_tolineno(self):
4501        """The line on which the beginning of this block ends.
4502
4503        :type: int
4504        """
4505        return self.test.tolineno
4506
4507    def block_range(self, lineno):
4508        """Get a range from the given line number to where this node ends.
4509
4510        :param lineno: The line number to start the range at.
4511        :type lineno: int
4512
4513        :returns: The range of line numbers that this node belongs to,
4514            starting at the given line number.
4515        :rtype: tuple(int, int)
4516        """
4517        return self._elsed_block_range(lineno, self.orelse)
4518
4519    def get_children(self):
4520        yield self.test
4521
4522        yield from self.body
4523        yield from self.orelse
4524
4525    def _get_yield_nodes_skip_lambdas(self):
4526        """A While node can contain a Yield node in the test"""
4527        yield from self.test._get_yield_nodes_skip_lambdas()
4528        yield from super()._get_yield_nodes_skip_lambdas()
4529
4530
4531class With(
4532    mixins.MultiLineBlockMixin,
4533    mixins.BlockRangeMixIn,
4534    mixins.AssignTypeMixin,
4535    Statement,
4536):
4537    """Class representing an :class:`ast.With` node.
4538
4539    >>> import astroid
4540    >>> node = astroid.extract_node('''
4541    with open(file_path) as file_:
4542        print(file_.read())
4543    ''')
4544    >>> node
4545    <With l.2 at 0x7f23b2e4e710>
4546    """
4547
4548    _astroid_fields = ("items", "body")
4549    _other_other_fields = ("type_annotation",)
4550    _multi_line_block_fields = ("body",)
4551
4552    def __init__(
4553        self,
4554        lineno: Optional[int] = None,
4555        col_offset: Optional[int] = None,
4556        parent: Optional[NodeNG] = None,
4557        *,
4558        end_lineno: Optional[int] = None,
4559        end_col_offset: Optional[int] = None,
4560    ) -> None:
4561        """
4562        :param lineno: The line that this node appears on in the source code.
4563
4564        :param col_offset: The column that this node appears on in the
4565            source code.
4566
4567        :param parent: The parent node in the syntax tree.
4568
4569        :param end_lineno: The last line this node appears on in the source code.
4570
4571        :param end_col_offset: The end column this node appears on in the
4572            source code. Note: This is after the last symbol.
4573        """
4574        self.items: typing.List[typing.Tuple[NodeNG, Optional[NodeNG]]] = []
4575        """The pairs of context managers and the names they are assigned to."""
4576
4577        self.body: typing.List[NodeNG] = []
4578        """The contents of the ``with`` block."""
4579
4580        self.type_annotation: Optional[NodeNG] = None  # can be None
4581        """If present, this will contain the type annotation passed by a type comment"""
4582
4583        super().__init__(
4584            lineno=lineno,
4585            col_offset=col_offset,
4586            end_lineno=end_lineno,
4587            end_col_offset=end_col_offset,
4588            parent=parent,
4589        )
4590
4591    def postinit(
4592        self,
4593        items: Optional[typing.List[typing.Tuple[NodeNG, Optional[NodeNG]]]] = None,
4594        body: Optional[typing.List[NodeNG]] = None,
4595        type_annotation: Optional[NodeNG] = None,
4596    ) -> None:
4597        """Do some setup after initialisation.
4598
4599        :param items: The pairs of context managers and the names
4600            they are assigned to.
4601
4602        :param body: The contents of the ``with`` block.
4603        """
4604        if items is not None:
4605            self.items = items
4606        if body is not None:
4607            self.body = body
4608        self.type_annotation = type_annotation
4609
4610    @decorators.cachedproperty
4611    def blockstart_tolineno(self):
4612        """The line on which the beginning of this block ends.
4613
4614        :type: int
4615        """
4616        return self.items[-1][0].tolineno
4617
4618    def get_children(self):
4619        """Get the child nodes below this node.
4620
4621        :returns: The children.
4622        :rtype: iterable(NodeNG)
4623        """
4624        for expr, var in self.items:
4625            yield expr
4626            if var:
4627                yield var
4628        yield from self.body
4629
4630
4631class AsyncWith(With):
4632    """Asynchronous ``with`` built with the ``async`` keyword."""
4633
4634
4635class Yield(NodeNG):
4636    """Class representing an :class:`ast.Yield` node.
4637
4638    >>> import astroid
4639    >>> node = astroid.extract_node('yield True')
4640    >>> node
4641    <Yield l.1 at 0x7f23b2e4e5f8>
4642    """
4643
4644    _astroid_fields = ("value",)
4645
4646    def __init__(
4647        self,
4648        lineno: Optional[int] = None,
4649        col_offset: Optional[int] = None,
4650        parent: Optional[NodeNG] = None,
4651        *,
4652        end_lineno: Optional[int] = None,
4653        end_col_offset: Optional[int] = None,
4654    ) -> None:
4655        """
4656        :param lineno: The line that this node appears on in the source code.
4657
4658        :param col_offset: The column that this node appears on in the
4659            source code.
4660
4661        :param parent: The parent node in the syntax tree.
4662
4663        :param end_lineno: The last line this node appears on in the source code.
4664
4665        :param end_col_offset: The end column this node appears on in the
4666            source code. Note: This is after the last symbol.
4667        """
4668        self.value: Optional[NodeNG] = None  # can be None
4669        """The value to yield."""
4670
4671        super().__init__(
4672            lineno=lineno,
4673            col_offset=col_offset,
4674            end_lineno=end_lineno,
4675            end_col_offset=end_col_offset,
4676            parent=parent,
4677        )
4678
4679    def postinit(self, value: Optional[NodeNG] = None) -> None:
4680        """Do some setup after initialisation.
4681
4682        :param value: The value to yield.
4683        """
4684        self.value = value
4685
4686    def get_children(self):
4687        if self.value is not None:
4688            yield self.value
4689
4690    def _get_yield_nodes_skip_lambdas(self):
4691        yield self
4692
4693
4694class YieldFrom(Yield):  # TODO value is required, not optional
4695    """Class representing an :class:`ast.YieldFrom` node."""
4696
4697
4698class DictUnpack(mixins.NoChildrenMixin, NodeNG):
4699    """Represents the unpacking of dicts into dicts using :pep:`448`."""
4700
4701
4702class FormattedValue(NodeNG):
4703    """Class representing an :class:`ast.FormattedValue` node.
4704
4705    Represents a :pep:`498` format string.
4706
4707    >>> import astroid
4708    >>> node = astroid.extract_node('f"Format {type_}"')
4709    >>> node
4710    <JoinedStr l.1 at 0x7f23b2e4ed30>
4711    >>> node.values
4712    [<Const.str l.1 at 0x7f23b2e4eda0>, <FormattedValue l.1 at 0x7f23b2e4edd8>]
4713    """
4714
4715    _astroid_fields = ("value", "format_spec")
4716    _other_fields = ("conversion",)
4717
4718    def __init__(
4719        self,
4720        lineno: Optional[int] = None,
4721        col_offset: Optional[int] = None,
4722        parent: Optional[NodeNG] = None,
4723        *,
4724        end_lineno: Optional[int] = None,
4725        end_col_offset: Optional[int] = None,
4726    ) -> None:
4727        """
4728        :param lineno: The line that this node appears on in the source code.
4729
4730        :param col_offset: The column that this node appears on in the
4731            source code.
4732
4733        :param parent: The parent node in the syntax tree.
4734
4735        :param end_lineno: The last line this node appears on in the source code.
4736
4737        :param end_col_offset: The end column this node appears on in the
4738            source code. Note: This is after the last symbol.
4739        """
4740        self.value: NodeNG
4741        """The value to be formatted into the string."""
4742
4743        self.conversion: Optional[int] = None  # can be None
4744        """The type of formatting to be applied to the value.
4745
4746        .. seealso::
4747            :class:`ast.FormattedValue`
4748        """
4749
4750        self.format_spec: Optional[NodeNG] = None  # can be None
4751        """The formatting to be applied to the value.
4752
4753        .. seealso::
4754            :class:`ast.FormattedValue`
4755
4756        :type: JoinedStr or None
4757        """
4758
4759        super().__init__(
4760            lineno=lineno,
4761            col_offset=col_offset,
4762            end_lineno=end_lineno,
4763            end_col_offset=end_col_offset,
4764            parent=parent,
4765        )
4766
4767    def postinit(
4768        self,
4769        value: NodeNG,
4770        conversion: Optional[int] = None,
4771        format_spec: Optional[NodeNG] = None,
4772    ) -> None:
4773        """Do some setup after initialisation.
4774
4775        :param value: The value to be formatted into the string.
4776
4777        :param conversion: The type of formatting to be applied to the value.
4778
4779        :param format_spec: The formatting to be applied to the value.
4780        :type format_spec: JoinedStr or None
4781        """
4782        self.value = value
4783        self.conversion = conversion
4784        self.format_spec = format_spec
4785
4786    def get_children(self):
4787        yield self.value
4788
4789        if self.format_spec is not None:
4790            yield self.format_spec
4791
4792
4793class JoinedStr(NodeNG):
4794    """Represents a list of string expressions to be joined.
4795
4796    >>> import astroid
4797    >>> node = astroid.extract_node('f"Format {type_}"')
4798    >>> node
4799    <JoinedStr l.1 at 0x7f23b2e4ed30>
4800    """
4801
4802    _astroid_fields = ("values",)
4803
4804    def __init__(
4805        self,
4806        lineno: Optional[int] = None,
4807        col_offset: Optional[int] = None,
4808        parent: Optional[NodeNG] = None,
4809        *,
4810        end_lineno: Optional[int] = None,
4811        end_col_offset: Optional[int] = None,
4812    ) -> None:
4813        """
4814        :param lineno: The line that this node appears on in the source code.
4815
4816        :param col_offset: The column that this node appears on in the
4817            source code.
4818
4819        :param parent: The parent node in the syntax tree.
4820
4821        :param end_lineno: The last line this node appears on in the source code.
4822
4823        :param end_col_offset: The end column this node appears on in the
4824            source code. Note: This is after the last symbol.
4825        """
4826        self.values: typing.List[NodeNG] = []
4827        """The string expressions to be joined.
4828
4829        :type: list(FormattedValue or Const)
4830        """
4831
4832        super().__init__(
4833            lineno=lineno,
4834            col_offset=col_offset,
4835            end_lineno=end_lineno,
4836            end_col_offset=end_col_offset,
4837            parent=parent,
4838        )
4839
4840    def postinit(self, values: Optional[typing.List[NodeNG]] = None) -> None:
4841        """Do some setup after initialisation.
4842
4843        :param value: The string expressions to be joined.
4844
4845        :type: list(FormattedValue or Const)
4846        """
4847        if values is not None:
4848            self.values = values
4849
4850    def get_children(self):
4851        yield from self.values
4852
4853
4854class NamedExpr(mixins.AssignTypeMixin, NodeNG):
4855    """Represents the assignment from the assignment expression
4856
4857    >>> import astroid
4858    >>> module = astroid.parse('if a := 1: pass')
4859    >>> module.body[0].test
4860    <NamedExpr l.1 at 0x7f23b2e4ed30>
4861    """
4862
4863    _astroid_fields = ("target", "value")
4864
4865    optional_assign = True
4866    """Whether this node optionally assigns a variable.
4867
4868    Since NamedExpr are not always called they do not always assign."""
4869
4870    def __init__(
4871        self,
4872        lineno: Optional[int] = None,
4873        col_offset: Optional[int] = None,
4874        parent: Optional[NodeNG] = None,
4875        *,
4876        end_lineno: Optional[int] = None,
4877        end_col_offset: Optional[int] = None,
4878    ) -> None:
4879        """
4880        :param lineno: The line that this node appears on in the source code.
4881
4882        :param col_offset: The column that this node appears on in the
4883            source code.
4884
4885        :param parent: The parent node in the syntax tree.
4886
4887        :param end_lineno: The last line this node appears on in the source code.
4888
4889        :param end_col_offset: The end column this node appears on in the
4890            source code. Note: This is after the last symbol.
4891        """
4892        self.target: NodeNG
4893        """The assignment target
4894
4895        :type: Name
4896        """
4897
4898        self.value: NodeNG
4899        """The value that gets assigned in the expression"""
4900
4901        super().__init__(
4902            lineno=lineno,
4903            col_offset=col_offset,
4904            end_lineno=end_lineno,
4905            end_col_offset=end_col_offset,
4906            parent=parent,
4907        )
4908
4909    def postinit(self, target: NodeNG, value: NodeNG) -> None:
4910        self.target = target
4911        self.value = value
4912
4913    def frame(self):
4914        """The first parent frame node.
4915
4916        A frame node is a :class:`Module`, :class:`FunctionDef`,
4917        or :class:`ClassDef`.
4918
4919        :returns: The first parent frame node.
4920        """
4921        if not self.parent:
4922            raise ParentMissingError(target=self)
4923
4924        # For certain parents NamedExpr evaluate to the scope of the parent
4925        if isinstance(self.parent, (Arguments, Keyword, Comprehension)):
4926            if not self.parent.parent:
4927                raise ParentMissingError(target=self.parent)
4928            if not self.parent.parent.parent:
4929                raise ParentMissingError(target=self.parent.parent)
4930            return self.parent.parent.parent.frame()
4931
4932        return self.parent.frame()
4933
4934    def scope(self) -> "LocalsDictNodeNG":
4935        """The first parent node defining a new scope.
4936        These can be Module, FunctionDef, ClassDef, Lambda, or GeneratorExp nodes.
4937
4938        :returns: The first parent scope node.
4939        """
4940        if not self.parent:
4941            raise ParentMissingError(target=self)
4942
4943        # For certain parents NamedExpr evaluate to the scope of the parent
4944        if isinstance(self.parent, (Arguments, Keyword, Comprehension)):
4945            if not self.parent.parent:
4946                raise ParentMissingError(target=self.parent)
4947            if not self.parent.parent.parent:
4948                raise ParentMissingError(target=self.parent.parent)
4949            return self.parent.parent.parent.scope()
4950
4951        return self.parent.scope()
4952
4953    def set_local(self, name: str, stmt: AssignName) -> None:
4954        """Define that the given name is declared in the given statement node.
4955        NamedExpr's in Arguments, Keyword or Comprehension are evaluated in their
4956        parent's parent scope. So we add to their frame's locals.
4957
4958        .. seealso:: :meth:`scope`
4959
4960        :param name: The name that is being defined.
4961
4962        :param stmt: The statement that defines the given name.
4963        """
4964        self.frame().set_local(name, stmt)
4965
4966
4967class Unknown(mixins.AssignTypeMixin, NodeNG):
4968    """This node represents a node in a constructed AST where
4969    introspection is not possible.  At the moment, it's only used in
4970    the args attribute of FunctionDef nodes where function signature
4971    introspection failed.
4972    """
4973
4974    name = "Unknown"
4975
4976    def qname(self):
4977        return "Unknown"
4978
4979    def _infer(self, context=None, **kwargs):
4980        """Inference on an Unknown node immediately terminates."""
4981        yield util.Uninferable
4982
4983
4984class EvaluatedObject(NodeNG):
4985    """Contains an object that has already been inferred
4986
4987    This class is useful to pre-evaluate a particular node,
4988    with the resulting class acting as the non-evaluated node.
4989    """
4990
4991    name = "EvaluatedObject"
4992    _astroid_fields = ("original",)
4993    _other_fields = ("value",)
4994
4995    def __init__(
4996        self, original: NodeNG, value: typing.Union[NodeNG, util.Uninferable]
4997    ) -> None:
4998        self.original: NodeNG = original
4999        """The original node that has already been evaluated"""
5000
5001        self.value: typing.Union[NodeNG, util.Uninferable] = value
5002        """The inferred value"""
5003
5004        super().__init__(
5005            lineno=self.original.lineno,
5006            col_offset=self.original.col_offset,
5007            parent=self.original.parent,
5008        )
5009
5010    def infer(self, context=None, **kwargs):
5011        yield self.value
5012
5013
5014# Pattern matching #######################################################
5015
5016
5017class Match(Statement):
5018    """Class representing a :class:`ast.Match` node.
5019
5020    >>> import astroid
5021    >>> node = astroid.extract_node('''
5022    match x:
5023        case 200:
5024            ...
5025        case _:
5026            ...
5027    ''')
5028    >>> node
5029    <Match l.2 at 0x10c24e170>
5030    """
5031
5032    _astroid_fields = ("subject", "cases")
5033
5034    def __init__(
5035        self,
5036        lineno: Optional[int] = None,
5037        col_offset: Optional[int] = None,
5038        parent: Optional[NodeNG] = None,
5039        *,
5040        end_lineno: Optional[int] = None,
5041        end_col_offset: Optional[int] = None,
5042    ) -> None:
5043        self.subject: NodeNG
5044        self.cases: typing.List["MatchCase"]
5045        super().__init__(
5046            lineno=lineno,
5047            col_offset=col_offset,
5048            end_lineno=end_lineno,
5049            end_col_offset=end_col_offset,
5050            parent=parent,
5051        )
5052
5053    def postinit(
5054        self,
5055        *,
5056        subject: NodeNG,
5057        cases: typing.List["MatchCase"],
5058    ) -> None:
5059        self.subject = subject
5060        self.cases = cases
5061
5062
5063class Pattern(NodeNG):
5064    """Base class for all Pattern nodes."""
5065
5066
5067class MatchCase(mixins.MultiLineBlockMixin, NodeNG):
5068    """Class representing a :class:`ast.match_case` node.
5069
5070    >>> import astroid
5071    >>> node = astroid.extract_node('''
5072    match x:
5073        case 200:
5074            ...
5075    ''')
5076    >>> node.cases[0]
5077    <MatchCase l.3 at 0x10c24e590>
5078    """
5079
5080    _astroid_fields = ("pattern", "guard", "body")
5081    _multi_line_block_fields = ("body",)
5082
5083    lineno: None
5084    col_offset: None
5085    end_lineno: None
5086    end_col_offset: None
5087
5088    def __init__(self, *, parent: Optional[NodeNG] = None) -> None:
5089        self.pattern: Pattern
5090        self.guard: Optional[NodeNG]
5091        self.body: typing.List[NodeNG]
5092        super().__init__(parent=parent)
5093
5094    def postinit(
5095        self,
5096        *,
5097        pattern: Pattern,
5098        guard: Optional[NodeNG],
5099        body: typing.List[NodeNG],
5100    ) -> None:
5101        self.pattern = pattern
5102        self.guard = guard
5103        self.body = body
5104
5105
5106class MatchValue(Pattern):
5107    """Class representing a :class:`ast.MatchValue` node.
5108
5109    >>> import astroid
5110    >>> node = astroid.extract_node('''
5111    match x:
5112        case 200:
5113            ...
5114    ''')
5115    >>> node.cases[0].pattern
5116    <MatchValue l.3 at 0x10c24e200>
5117    """
5118
5119    _astroid_fields = ("value",)
5120
5121    def __init__(
5122        self,
5123        lineno: Optional[int] = None,
5124        col_offset: Optional[int] = None,
5125        parent: Optional[NodeNG] = None,
5126        *,
5127        end_lineno: Optional[int] = None,
5128        end_col_offset: Optional[int] = None,
5129    ) -> None:
5130        self.value: NodeNG
5131        super().__init__(
5132            lineno=lineno,
5133            col_offset=col_offset,
5134            end_lineno=end_lineno,
5135            end_col_offset=end_col_offset,
5136            parent=parent,
5137        )
5138
5139    def postinit(self, *, value: NodeNG) -> None:
5140        self.value = value
5141
5142
5143class MatchSingleton(Pattern):
5144    """Class representing a :class:`ast.MatchSingleton` node.
5145
5146    >>> import astroid
5147    >>> node = astroid.extract_node('''
5148    match x:
5149        case True:
5150            ...
5151        case False:
5152            ...
5153        case None:
5154            ...
5155    ''')
5156    >>> node.cases[0].pattern
5157    <MatchSingleton l.3 at 0x10c2282e0>
5158    >>> node.cases[1].pattern
5159    <MatchSingleton l.5 at 0x10c228af0>
5160    >>> node.cases[2].pattern
5161    <MatchSingleton l.7 at 0x10c229f90>
5162    """
5163
5164    _other_fields = ("value",)
5165
5166    def __init__(
5167        self,
5168        *,
5169        value: Literal[True, False, None],
5170        lineno: Optional[int] = None,
5171        col_offset: Optional[int] = None,
5172        end_lineno: Optional[int] = None,
5173        end_col_offset: Optional[int] = None,
5174        parent: Optional[NodeNG] = None,
5175    ) -> None:
5176        self.value: Literal[True, False, None] = value
5177        super().__init__(
5178            lineno=lineno,
5179            col_offset=col_offset,
5180            end_lineno=end_lineno,
5181            end_col_offset=end_col_offset,
5182            parent=parent,
5183        )
5184
5185
5186class MatchSequence(Pattern):
5187    """Class representing a :class:`ast.MatchSequence` node.
5188
5189    >>> import astroid
5190    >>> node = astroid.extract_node('''
5191    match x:
5192        case [1, 2]:
5193            ...
5194        case (1, 2, *_):
5195            ...
5196    ''')
5197    >>> node.cases[0].pattern
5198    <MatchSequence l.3 at 0x10ca80d00>
5199    >>> node.cases[1].pattern
5200    <MatchSequence l.5 at 0x10ca80b20>
5201    """
5202
5203    _astroid_fields = ("patterns",)
5204
5205    def __init__(
5206        self,
5207        lineno: Optional[int] = None,
5208        col_offset: Optional[int] = None,
5209        parent: Optional[NodeNG] = None,
5210        *,
5211        end_lineno: Optional[int] = None,
5212        end_col_offset: Optional[int] = None,
5213    ) -> None:
5214        self.patterns: typing.List[Pattern]
5215        super().__init__(
5216            lineno=lineno,
5217            col_offset=col_offset,
5218            end_lineno=end_lineno,
5219            end_col_offset=end_col_offset,
5220            parent=parent,
5221        )
5222
5223    def postinit(self, *, patterns: typing.List[Pattern]) -> None:
5224        self.patterns = patterns
5225
5226
5227class MatchMapping(mixins.AssignTypeMixin, Pattern):
5228    """Class representing a :class:`ast.MatchMapping` node.
5229
5230    >>> import astroid
5231    >>> node = astroid.extract_node('''
5232    match x:
5233        case {1: "Hello", 2: "World", 3: _, **rest}:
5234            ...
5235    ''')
5236    >>> node.cases[0].pattern
5237    <MatchMapping l.3 at 0x10c8a8850>
5238    """
5239
5240    _astroid_fields = ("keys", "patterns", "rest")
5241
5242    def __init__(
5243        self,
5244        lineno: Optional[int] = None,
5245        col_offset: Optional[int] = None,
5246        parent: Optional[NodeNG] = None,
5247        *,
5248        end_lineno: Optional[int] = None,
5249        end_col_offset: Optional[int] = None,
5250    ) -> None:
5251        self.keys: typing.List[NodeNG]
5252        self.patterns: typing.List[Pattern]
5253        self.rest: Optional[AssignName]
5254        super().__init__(
5255            lineno=lineno,
5256            col_offset=col_offset,
5257            end_lineno=end_lineno,
5258            end_col_offset=end_col_offset,
5259            parent=parent,
5260        )
5261
5262    def postinit(
5263        self,
5264        *,
5265        keys: typing.List[NodeNG],
5266        patterns: typing.List[Pattern],
5267        rest: Optional[AssignName],
5268    ) -> None:
5269        self.keys = keys
5270        self.patterns = patterns
5271        self.rest = rest
5272
5273    assigned_stmts: Callable[
5274        [
5275            "MatchMapping",
5276            AssignName,
5277            Optional[InferenceContext],
5278            Literal[None],
5279        ],
5280        Generator[NodeNG, None, None],
5281    ]
5282
5283
5284class MatchClass(Pattern):
5285    """Class representing a :class:`ast.MatchClass` node.
5286
5287    >>> import astroid
5288    >>> node = astroid.extract_node('''
5289    match x:
5290        case Point2D(0, 0):
5291            ...
5292        case Point3D(x=0, y=0, z=0):
5293            ...
5294    ''')
5295    >>> node.cases[0].pattern
5296    <MatchClass l.3 at 0x10ca83940>
5297    >>> node.cases[1].pattern
5298    <MatchClass l.5 at 0x10ca80880>
5299    """
5300
5301    _astroid_fields = ("cls", "patterns", "kwd_patterns")
5302    _other_fields = ("kwd_attrs",)
5303
5304    def __init__(
5305        self,
5306        lineno: Optional[int] = None,
5307        col_offset: Optional[int] = None,
5308        parent: Optional[NodeNG] = None,
5309        *,
5310        end_lineno: Optional[int] = None,
5311        end_col_offset: Optional[int] = None,
5312    ) -> None:
5313        self.cls: NodeNG
5314        self.patterns: typing.List[Pattern]
5315        self.kwd_attrs: typing.List[str]
5316        self.kwd_patterns: typing.List[Pattern]
5317        super().__init__(
5318            lineno=lineno,
5319            col_offset=col_offset,
5320            end_lineno=end_lineno,
5321            end_col_offset=end_col_offset,
5322            parent=parent,
5323        )
5324
5325    def postinit(
5326        self,
5327        *,
5328        cls: NodeNG,
5329        patterns: typing.List[Pattern],
5330        kwd_attrs: typing.List[str],
5331        kwd_patterns: typing.List[Pattern],
5332    ) -> None:
5333        self.cls = cls
5334        self.patterns = patterns
5335        self.kwd_attrs = kwd_attrs
5336        self.kwd_patterns = kwd_patterns
5337
5338
5339class MatchStar(mixins.AssignTypeMixin, Pattern):
5340    """Class representing a :class:`ast.MatchStar` node.
5341
5342    >>> import astroid
5343    >>> node = astroid.extract_node('''
5344    match x:
5345        case [1, *_]:
5346            ...
5347    ''')
5348    >>> node.cases[0].pattern.patterns[1]
5349    <MatchStar l.3 at 0x10ca809a0>
5350    """
5351
5352    _astroid_fields = ("name",)
5353
5354    def __init__(
5355        self,
5356        lineno: Optional[int] = None,
5357        col_offset: Optional[int] = None,
5358        parent: Optional[NodeNG] = None,
5359        *,
5360        end_lineno: Optional[int] = None,
5361        end_col_offset: Optional[int] = None,
5362    ) -> None:
5363        self.name: Optional[AssignName]
5364        super().__init__(
5365            lineno=lineno,
5366            col_offset=col_offset,
5367            end_lineno=end_lineno,
5368            end_col_offset=end_col_offset,
5369            parent=parent,
5370        )
5371
5372    def postinit(self, *, name: Optional[AssignName]) -> None:
5373        self.name = name
5374
5375    assigned_stmts: Callable[
5376        [
5377            "MatchStar",
5378            AssignName,
5379            Optional[InferenceContext],
5380            Literal[None],
5381        ],
5382        Generator[NodeNG, None, None],
5383    ]
5384
5385
5386class MatchAs(mixins.AssignTypeMixin, Pattern):
5387    """Class representing a :class:`ast.MatchAs` node.
5388
5389    >>> import astroid
5390    >>> node = astroid.extract_node('''
5391    match x:
5392        case [1, a]:
5393            ...
5394        case {'key': b}:
5395            ...
5396        case Point2D(0, 0) as c:
5397            ...
5398        case d:
5399            ...
5400    ''')
5401    >>> node.cases[0].pattern.patterns[1]
5402    <MatchAs l.3 at 0x10d0b2da0>
5403    >>> node.cases[1].pattern.patterns[0]
5404    <MatchAs l.5 at 0x10d0b2920>
5405    >>> node.cases[2].pattern
5406    <MatchAs l.7 at 0x10d0b06a0>
5407    >>> node.cases[3].pattern
5408    <MatchAs l.9 at 0x10d09b880>
5409    """
5410
5411    _astroid_fields = ("pattern", "name")
5412
5413    def __init__(
5414        self,
5415        lineno: Optional[int] = None,
5416        col_offset: Optional[int] = None,
5417        parent: Optional[NodeNG] = None,
5418        *,
5419        end_lineno: Optional[int] = None,
5420        end_col_offset: Optional[int] = None,
5421    ) -> None:
5422        self.pattern: Optional[Pattern]
5423        self.name: Optional[AssignName]
5424        super().__init__(
5425            lineno=lineno,
5426            col_offset=col_offset,
5427            end_lineno=end_lineno,
5428            end_col_offset=end_col_offset,
5429            parent=parent,
5430        )
5431
5432    def postinit(
5433        self,
5434        *,
5435        pattern: Optional[Pattern],
5436        name: Optional[AssignName],
5437    ) -> None:
5438        self.pattern = pattern
5439        self.name = name
5440
5441    assigned_stmts: Callable[
5442        [
5443            "MatchAs",
5444            AssignName,
5445            Optional[InferenceContext],
5446            Literal[None],
5447        ],
5448        Generator[NodeNG, None, None],
5449    ]
5450
5451
5452class MatchOr(Pattern):
5453    """Class representing a :class:`ast.MatchOr` node.
5454
5455    >>> import astroid
5456    >>> node = astroid.extract_node('''
5457    match x:
5458        case 400 | 401 | 402:
5459            ...
5460    ''')
5461    >>> node.cases[0].pattern
5462    <MatchOr l.3 at 0x10d0b0b50>
5463    """
5464
5465    _astroid_fields = ("patterns",)
5466
5467    def __init__(
5468        self,
5469        lineno: Optional[int] = None,
5470        col_offset: Optional[int] = None,
5471        parent: Optional[NodeNG] = None,
5472        *,
5473        end_lineno: Optional[int] = None,
5474        end_col_offset: Optional[int] = None,
5475    ) -> None:
5476        self.patterns: typing.List[Pattern]
5477        super().__init__(
5478            lineno=lineno,
5479            col_offset=col_offset,
5480            end_lineno=end_lineno,
5481            end_col_offset=end_col_offset,
5482            parent=parent,
5483        )
5484
5485    def postinit(self, *, patterns: typing.List[Pattern]) -> None:
5486        self.patterns = patterns
5487
5488
5489# constants ##############################################################
5490
5491CONST_CLS = {
5492    list: List,
5493    tuple: Tuple,
5494    dict: Dict,
5495    set: Set,
5496    type(None): Const,
5497    type(NotImplemented): Const,
5498    type(...): Const,
5499}
5500
5501
5502def _update_const_classes():
5503    """update constant classes, so the keys of CONST_CLS can be reused"""
5504    klasses = (bool, int, float, complex, str, bytes)
5505    for kls in klasses:
5506        CONST_CLS[kls] = Const
5507
5508
5509_update_const_classes()
5510
5511
5512def _two_step_initialization(cls, value):
5513    instance = cls()
5514    instance.postinit(value)
5515    return instance
5516
5517
5518def _dict_initialization(cls, value):
5519    if isinstance(value, dict):
5520        value = tuple(value.items())
5521    return _two_step_initialization(cls, value)
5522
5523
5524_CONST_CLS_CONSTRUCTORS = {
5525    List: _two_step_initialization,
5526    Tuple: _two_step_initialization,
5527    Dict: _dict_initialization,
5528    Set: _two_step_initialization,
5529    Const: lambda cls, value: cls(value),
5530}
5531
5532
5533def const_factory(value):
5534    """return an astroid node for a python value"""
5535    # XXX we should probably be stricter here and only consider stuff in
5536    # CONST_CLS or do better treatment: in case where value is not in CONST_CLS,
5537    # we should rather recall the builder on this value than returning an empty
5538    # node (another option being that const_factory shouldn't be called with something
5539    # not in CONST_CLS)
5540    assert not isinstance(value, NodeNG)
5541
5542    # Hack for ignoring elements of a sequence
5543    # or a mapping, in order to avoid transforming
5544    # each element to an AST. This is fixed in 2.0
5545    # and this approach is a temporary hack.
5546    if isinstance(value, (list, set, tuple, dict)):
5547        elts = []
5548    else:
5549        elts = value
5550
5551    try:
5552        initializer_cls = CONST_CLS[value.__class__]
5553        initializer = _CONST_CLS_CONSTRUCTORS[initializer_cls]
5554        return initializer(initializer_cls, elts)
5555    except (KeyError, AttributeError):
5556        node = EmptyNode()
5557        node.object = value
5558        return node
5559
5560
5561def is_from_decorator(node):
5562    """Return True if the given node is the child of a decorator"""
5563    for parent in node.node_ancestors():
5564        if isinstance(parent, Decorators):
5565            return True
5566    return False
5567
5568
5569def _get_if_statement_ancestor(node: NodeNG) -> Optional[If]:
5570    """Return the first parent node that is an If node (or None)"""
5571    for parent in node.node_ancestors():
5572        if isinstance(parent, If):
5573            return parent
5574    return None
5575