prompt: 
  We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  getitem does not infer the actual unpacked value
  When trying to call `Dict.getitem()` on a context where we have a dict unpacking of anything beside a real dict, astroid currently raises an `AttributeError: 'getitem'`, which has 2 problems:
  
  - The object might be a reference against something constant, this pattern is usually seen when we have different sets of dicts that extend each other, and all of their values are inferrable. 
  - We can have something that is uninferable, but in that case instead of an `AttributeError` I think it makes sense to raise the usual `AstroidIndexError` which is supposed to be already handled by the downstream.
  
  
  Here is a short reproducer;
  
  ```py
  from astroid import parse
  
  
  source = """
  X = {
      'A': 'B'
  }
  
  Y = {
      **X
  }
  
  KEY = 'A'
  """
  
  tree = parse(source)
  
  first_dict = tree.body[0].value
  second_dict = tree.body[1].value
  key = tree.body[2].value
  
  print(f'{first_dict.getitem(key).value = }')
  print(f'{second_dict.getitem(key).value = }')
  
  
  ```
  
  The current output;
  
  ```
   $ python t1.py                                                                                                 3ms
  first_dict.getitem(key).value = 'B'
  Traceback (most recent call last):
    File "/home/isidentical/projects/astroid/t1.py", line 23, in <module>
      print(f'{second_dict.getitem(key).value = }')
    File "/home/isidentical/projects/astroid/astroid/nodes/node_classes.py", line 2254, in getitem
      return value.getitem(index, context)
  AttributeError: 'Name' object has no attribute 'getitem'
  ```
  
  Expeceted output;
  ```
   $ python t1.py                                                                                                 4ms
  first_dict.getitem(key).value = 'B'
  second_dict.getitem(key).value = 'B'
  
  ```
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  
  --- BEGIN FILE ---
  ```
  ### astroid/nodes/node_classes.py
  # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
  # For details: https://github.com/PyCQA/astroid/blob/main/LICENSE
  # Copyright (c) https://github.com/PyCQA/astroid/blob/main/CONTRIBUTORS.txt
  
  """Module for some node classes. More nodes in scoped_nodes.py"""
  
  from __future__ import annotations
  
  import abc
  import itertools
  import sys
  import typing
  import warnings
  from collections.abc import Generator, Iterator
  from functools import lru_cache
  from typing import TYPE_CHECKING, Any, Callable, ClassVar, Optional, TypeVar, Union
  
  from astroid import decorators, mixins, util
  from astroid.bases import Instance, _infer_stmts
  from astroid.const import Context
  from astroid.context import InferenceContext
  from astroid.exceptions import (
      AstroidIndexError,
      AstroidTypeError,
      InferenceError,
      NoDefault,
      ParentMissingError,
  )
  from astroid.manager import AstroidManager
  from astroid.nodes.const import OP_PRECEDENCE
  from astroid.nodes.node_ng import NodeNG
  
  if sys.version_info >= (3, 8):
      from typing import Literal
  else:
      from typing_extensions import Literal
  
  if TYPE_CHECKING:
      from astroid import nodes
      from astroid.nodes import LocalsDictNodeNG
  
  if sys.version_info >= (3, 8):
      from functools import cached_property
  else:
      from astroid.decorators import cachedproperty as cached_property
  
  
  def _is_const(value):
      return isinstance(value, tuple(CONST_CLS))
  
  
  _NodesT = TypeVar("_NodesT", bound=NodeNG)
  
  AssignedStmtsPossibleNode = Union["List", "Tuple", "AssignName", "AssignAttr", None]
  AssignedStmtsCall = Callable[
      [
          _NodesT,
          AssignedStmtsPossibleNode,
          Optional[InferenceContext],
          Optional[typing.List[int]],
      ],
      Any,
  ]
  
  
  @decorators.raise_if_nothing_inferred
  def unpack_infer(stmt, context=None):
      """recursively generate nodes inferred by the given statement.
      If the inferred value is a list or a tuple, recurse on the elements
      """
      if isinstance(stmt, (List, Tuple)):
          for elt in stmt.elts:
              if elt is util.Uninferable:
                  yield elt
                  continue
              yield from unpack_infer(elt, context)
          return dict(node=stmt, context=context)
      # if inferred is a final node, return it and stop
      inferred = next(stmt.infer(context), util.Uninferable)
      if inferred is stmt:
          yield inferred
          return dict(node=stmt, context=context)
      # else, infer recursively, except Uninferable object that should be returned as is
      for inferred in stmt.infer(context):
          if inferred is util.Uninferable:
              yield inferred
          else:
              yield from unpack_infer(inferred, context)
  
      return dict(node=stmt, context=context)
  
  
  def are_exclusive(stmt1, stmt2, exceptions: list[str] | None = None) -> bool:
      """return true if the two given statements are mutually exclusive
  
      `exceptions` may be a list of exception names. If specified, discard If
      branches and check one of the statement is in an exception handler catching
      one of the given exceptions.
  
      algorithm :
       1) index stmt1's parents
       2) climb among stmt2's parents until we find a common parent
       3) if the common parent is a If or TryExcept statement, look if nodes are
          in exclusive branches
      """
      # index stmt1's parents
      stmt1_parents = {}
      children = {}
      previous = stmt1
      for node in stmt1.node_ancestors():
          stmt1_parents[node] = 1
          children[node] = previous
          previous = node
      # climb among stmt2's parents until we find a common parent
      previous = stmt2
      for node in stmt2.node_ancestors():
          if node in stmt1_parents:
              # if the common parent is a If or TryExcept statement, look if
              # nodes are in exclusive branches
              if isinstance(node, If) and exceptions is None:
                  if (
                      node.locate_child(previous)[1]
                      is not node.locate_child(children[node])[1]
                  ):
                      return True
              elif isinstance(node, TryExcept):
                  c2attr, c2node = node.locate_child(previous)
                  c1attr, c1node = node.locate_child(children[node])
                  if c1node is not c2node:
                      first_in_body_caught_by_handlers = (
                          c2attr == "handlers"
                          and c1attr == "body"
                          and previous.catch(exceptions)
                      )
                      second_in_body_caught_by_handlers = (
                          c2attr == "body"
                          and c1attr == "handlers"
                          and children[node].catch(exceptions)
                      )
                      first_in_else_other_in_handlers = (
                          c2attr == "handlers" and c1attr == "orelse"
                      )
                      second_in_else_other_in_handlers = (
                          c2attr == "orelse" and c1attr == "handlers"
                      )
                      if any(
                          (
                              first_in_body_caught_by_handlers,
                              second_in_body_caught_by_handlers,
                              first_in_else_other_in_handlers,
                              second_in_else_other_in_handlers,
                          )
                      ):
                          return True
                  elif c2attr == "handlers" and c1attr == "handlers":
                      return previous is not children[node]
              return False
          previous = node
      return False
  
  
  # getitem() helpers.
  
  _SLICE_SENTINEL = object()
  
  
  def _slice_value(index, context=None):
      """Get the value of the given slice index."""
  
      if isinstance(index, Const):
          if isinstance(index.value, (int, type(None))):
              return index.value
      elif index is None:
          return None
      else:
          # Try to infer what the index actually is.
          # Since we can't return all the possible values,
          # we'll stop at the first possible value.
          try:
              inferred = next(index.infer(context=context))
          except (InferenceError, StopIteration):
              pass
          else:
              if isinstance(inferred, Const):
                  if isinstance(inferred.value, (int, type(None))):
                      return inferred.value
  
      # Use a sentinel, because None can be a valid
      # value that this function can return,
      # as it is the case for unspecified bounds.
      return _SLICE_SENTINEL
  
  
  def _infer_slice(node, context=None):
      lower = _slice_value(node.lower, context)
      upper = _slice_value(node.upper, context)
      step = _slice_value(node.step, context)
      if all(elem is not _SLICE_SENTINEL for elem in (lower, upper, step)):
          return slice(lower, upper, step)
  
      raise AstroidTypeError(
          message="Could not infer slice used in subscript",
          node=node,
          index=node.parent,
          context=context,
      )
  
  
  def _container_getitem(instance, elts, index, context=None):
      """Get a slice or an item, using the given *index*, for the given sequence."""
      try:
          if isinstance(index, Slice):
              index_slice = _infer_slice(index, context=context)
              new_cls = instance.__class__()
              new_cls.elts = elts[index_slice]
              new_cls.parent = instance.parent
              return new_cls
          if isinstance(index, Const):
              return elts[index.value]
      except IndexError as exc:
          raise AstroidIndexError(
              message="Index {index!s} out of range",
              node=instance,
              index=index,
              context=context,
          ) from exc
      except TypeError as exc:
          raise AstroidTypeError(
              message="Type error {error!r}", node=instance, index=index, context=context
          ) from exc
  
      raise AstroidTypeError(f"Could not use {index} as subscript index")
  
  
  class Statement(NodeNG):
      """Statement node adding a few attributes"""
  
      is_statement = True
      """Whether this node indicates a statement."""
  
      def next_sibling(self):
          """The next sibling statement node.
  
          :returns: The next sibling statement node.
          :rtype: NodeNG or None
          """
          stmts = self.parent.child_sequence(self)
          index = stmts.index(self)
          try:
              return stmts[index + 1]
          except IndexError:
              return None
  
      def previous_sibling(self):
          """The previous sibling statement.
  
          :returns: The previous sibling statement node.
          :rtype: NodeNG or None
          """
          stmts = self.parent.child_sequence(self)
          index = stmts.index(self)
          if index >= 1:
              return stmts[index - 1]
          return None
  
  
  class BaseContainer(
      mixins.ParentAssignTypeMixin, NodeNG, Instance, metaclass=abc.ABCMeta
  ):
      """Base class for Set, FrozenSet, Tuple and List."""
  
      _astroid_fields = ("elts",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.elts: list[NodeNG] = []
          """The elements in the node."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, elts: list[NodeNG]) -> None:
          """Do some setup after initialisation.
  
          :param elts: The list of elements the that node contains.
          """
          self.elts = elts
  
      @classmethod
      def from_elements(cls, elts=None):
          """Create a node of this type from the given list of elements.
  
          :param elts: The list of elements that the node should contain.
          :type elts: list(NodeNG)
  
          :returns: A new node containing the given elements.
          :rtype: NodeNG
          """
          node = cls()
          if elts is None:
              node.elts = []
          else:
              node.elts = [const_factory(e) if _is_const(e) else e for e in elts]
          return node
  
      def itered(self):
          """An iterator over the elements this node contains.
  
          :returns: The contents of this node.
          :rtype: iterable(NodeNG)
          """
          return self.elts
  
      def bool_value(self, context=None):
          """Determine the boolean value of this node.
  
          :returns: The boolean value of this node.
          :rtype: bool or Uninferable
          """
          return bool(self.elts)
  
      @abc.abstractmethod
      def pytype(self):
          """Get the name of the type that this node represents.
  
          :returns: The name of the type.
          :rtype: str
          """
  
      def get_children(self):
          yield from self.elts
  
  
  class LookupMixIn:
      """Mixin to look up a name in the right scope."""
  
      @lru_cache()  # noqa
      def lookup(self, name: str) -> tuple[str, list[NodeNG]]:
          """Lookup where the given variable is assigned.
  
          The lookup starts from self's scope. If self is not a frame itself
          and the name is found in the inner frame locals, statements will be
          filtered to remove ignorable statements according to self's location.
  
          :param name: The name of the variable to find assignments for.
  
          :returns: The scope node and the list of assignments associated to the
              given name according to the scope where it has been found (locals,
              globals or builtin).
          """
          return self.scope().scope_lookup(self, name)
  
      def ilookup(self, name):
          """Lookup the inferred values of the given variable.
  
          :param name: The variable name to find values for.
          :type name: str
  
          :returns: The inferred values of the statements returned from
              :meth:`lookup`.
          :rtype: iterable
          """
          frame, stmts = self.lookup(name)
          context = InferenceContext()
          return _infer_stmts(stmts, context, frame)
  
  
  # Name classes
  
  
  class AssignName(
      mixins.NoChildrenMixin, LookupMixIn, mixins.ParentAssignTypeMixin, NodeNG
  ):
      """Variation of :class:`ast.Assign` representing assignment to a name.
  
      An :class:`AssignName` is the name of something that is assigned to.
      This includes variables defined in a function signature or in a loop.
  
      >>> import astroid
      >>> node = astroid.extract_node('variable = range(10)')
      >>> node
      <Assign l.1 at 0x7effe1db8550>
      >>> list(node.get_children())
      [<AssignName.variable l.1 at 0x7effe1db8748>, <Call l.1 at 0x7effe1db8630>]
      >>> list(node.get_children())[0].as_string()
      'variable'
      """
  
      _other_fields = ("name",)
  
      @decorators.deprecate_default_argument_values(name="str")
      def __init__(
          self,
          name: str | None = None,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param name: The name that is assigned to.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.name: str | None = name
          """The name that is assigned to."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      assigned_stmts: ClassVar[AssignedStmtsCall[AssignName]]
      """Returns the assigned statement (non inferred) according to the assignment type.
      See astroid/protocols.py for actual implementation.
      """
  
  
  class DelName(
      mixins.NoChildrenMixin, LookupMixIn, mixins.ParentAssignTypeMixin, NodeNG
  ):
      """Variation of :class:`ast.Delete` representing deletion of a name.
  
      A :class:`DelName` is the name of something that is deleted.
  
      >>> import astroid
      >>> node = astroid.extract_node("del variable #@")
      >>> list(node.get_children())
      [<DelName.variable l.1 at 0x7effe1da4d30>]
      >>> list(node.get_children())[0].as_string()
      'variable'
      """
  
      _other_fields = ("name",)
  
      @decorators.deprecate_default_argument_values(name="str")
      def __init__(
          self,
          name: str | None = None,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param name: The name that is being deleted.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.name: str | None = name
          """The name that is being deleted."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
  
  class Name(mixins.NoChildrenMixin, LookupMixIn, NodeNG):
      """Class representing an :class:`ast.Name` node.
  
      A :class:`Name` node is something that is named, but not covered by
      :class:`AssignName` or :class:`DelName`.
  
      >>> import astroid
      >>> node = astroid.extract_node('range(10)')
      >>> node
      <Call l.1 at 0x7effe1db8710>
      >>> list(node.get_children())
      [<Name.range l.1 at 0x7effe1db86a0>, <Const.int l.1 at 0x7effe1db8518>]
      >>> list(node.get_children())[0].as_string()
      'range'
      """
  
      _other_fields = ("name",)
  
      @decorators.deprecate_default_argument_values(name="str")
      def __init__(
          self,
          name: str | None = None,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param name: The name that this node refers to.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.name: str | None = name
          """The name that this node refers to."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def _get_name_nodes(self):
          yield self
  
          for child_node in self.get_children():
              yield from child_node._get_name_nodes()
  
  
  class Arguments(mixins.AssignTypeMixin, NodeNG):
      """Class representing an :class:`ast.arguments` node.
  
      An :class:`Arguments` node represents that arguments in a
      function definition.
  
      >>> import astroid
      >>> node = astroid.extract_node('def foo(bar): pass')
      >>> node
      <FunctionDef.foo l.1 at 0x7effe1db8198>
      >>> node.args
      <Arguments l.1 at 0x7effe1db82e8>
      """
  
      # Python 3.4+ uses a different approach regarding annotations,
      # each argument is a new class, _ast.arg, which exposes an
      # 'annotation' attribute. In astroid though, arguments are exposed
      # as is in the Arguments node and the only way to expose annotations
      # is by using something similar with Python 3.3:
      #  - we expose 'varargannotation' and 'kwargannotation' of annotations
      #    of varargs and kwargs.
      #  - we expose 'annotation', a list with annotations for
      #    for each normal argument. If an argument doesn't have an
      #    annotation, its value will be None.
      _astroid_fields = (
          "args",
          "defaults",
          "kwonlyargs",
          "posonlyargs",
          "posonlyargs_annotations",
          "kw_defaults",
          "annotations",
          "varargannotation",
          "kwargannotation",
          "kwonlyargs_annotations",
          "type_comment_args",
          "type_comment_kwonlyargs",
          "type_comment_posonlyargs",
      )
  
      _other_fields = ("vararg", "kwarg")
  
      lineno: None
      col_offset: None
      end_lineno: None
      end_col_offset: None
  
      def __init__(
          self,
          vararg: str | None = None,
          kwarg: str | None = None,
          parent: NodeNG | None = None,
      ) -> None:
          """
          :param vararg: The name of the variable length arguments.
  
          :param kwarg: The name of the variable length keyword arguments.
  
          :param parent: The parent node in the syntax tree.
          """
          super().__init__(parent=parent)
  
          self.vararg: str | None = vararg  # can be None
          """The name of the variable length arguments."""
  
          self.kwarg: str | None = kwarg  # can be None
          """The name of the variable length keyword arguments."""
  
          self.args: list[AssignName] | None
          """The names of the required arguments.
  
          Can be None if the associated function does not have a retrievable
          signature and the arguments are therefore unknown.
          This can happen with (builtin) functions implemented in C that have
          incomplete signature information.
          """
          # TODO: Check if other attributes should also be None when
          # .args is None.
  
          self.defaults: list[NodeNG]
          """The default values for arguments that can be passed positionally."""
  
          self.kwonlyargs: list[AssignName]
          """The keyword arguments that cannot be passed positionally."""
  
          self.posonlyargs: list[AssignName] = []
          """The arguments that can only be passed positionally."""
  
          self.kw_defaults: list[NodeNG | None]
          """The default values for keyword arguments that cannot be passed positionally."""
  
          self.annotations: list[NodeNG | None]
          """The type annotations of arguments that can be passed positionally."""
  
          self.posonlyargs_annotations: list[NodeNG | None] = []
          """The type annotations of arguments that can only be passed positionally."""
  
          self.kwonlyargs_annotations: list[NodeNG | None] = []
          """The type annotations of arguments that cannot be passed positionally."""
  
          self.type_comment_args: list[NodeNG | None] = []
          """The type annotation, passed by a type comment, of each argument.
  
          If an argument does not have a type comment,
          the value for that argument will be None.
          """
  
          self.type_comment_kwonlyargs: list[NodeNG | None] = []
          """The type annotation, passed by a type comment, of each keyword only argument.
  
          If an argument does not have a type comment,
          the value for that argument will be None.
          """
  
          self.type_comment_posonlyargs: list[NodeNG | None] = []
          """The type annotation, passed by a type comment, of each positional argument.
  
          If an argument does not have a type comment,
          the value for that argument will be None.
          """
  
          self.varargannotation: NodeNG | None = None  # can be None
          """The type annotation for the variable length arguments."""
  
          self.kwargannotation: NodeNG | None = None  # can be None
          """The type annotation for the variable length keyword arguments."""
  
      # pylint: disable=too-many-arguments
      def postinit(
          self,
          args: list[AssignName] | None,
          defaults: list[NodeNG],
          kwonlyargs: list[AssignName],
          kw_defaults: list[NodeNG | None],
          annotations: list[NodeNG | None],
          posonlyargs: list[AssignName] | None = None,
          kwonlyargs_annotations: list[NodeNG | None] | None = None,
          posonlyargs_annotations: list[NodeNG | None] | None = None,
          varargannotation: NodeNG | None = None,
          kwargannotation: NodeNG | None = None,
          type_comment_args: list[NodeNG | None] | None = None,
          type_comment_kwonlyargs: list[NodeNG | None] | None = None,
          type_comment_posonlyargs: list[NodeNG | None] | None = None,
      ) -> None:
          """Do some setup after initialisation.
  
          :param args: The names of the required arguments.
  
          :param defaults: The default values for arguments that can be passed
              positionally.
  
          :param kwonlyargs: The keyword arguments that cannot be passed
              positionally.
  
          :param posonlyargs: The arguments that can only be passed
              positionally.
  
          :param kw_defaults: The default values for keyword arguments that
              cannot be passed positionally.
  
          :param annotations: The type annotations of arguments that can be
              passed positionally.
  
          :param kwonlyargs_annotations: The type annotations of arguments that
              cannot be passed positionally. This should always be passed in
              Python 3.
  
          :param posonlyargs_annotations: The type annotations of arguments that
              can only be passed positionally. This should always be passed in
              Python 3.
  
          :param varargannotation: The type annotation for the variable length
              arguments.
  
          :param kwargannotation: The type annotation for the variable length
              keyword arguments.
  
          :param type_comment_args: The type annotation,
              passed by a type comment, of each argument.
  
          :param type_comment_args: The type annotation,
              passed by a type comment, of each keyword only argument.
  
          :param type_comment_args: The type annotation,
              passed by a type comment, of each positional argument.
          """
          self.args = args
          self.defaults = defaults
          self.kwonlyargs = kwonlyargs
          if posonlyargs is not None:
              self.posonlyargs = posonlyargs
          self.kw_defaults = kw_defaults
          self.annotations = annotations
          if kwonlyargs_annotations is not None:
              self.kwonlyargs_annotations = kwonlyargs_annotations
          if posonlyargs_annotations is not None:
              self.posonlyargs_annotations = posonlyargs_annotations
          self.varargannotation = varargannotation
          self.kwargannotation = kwargannotation
          if type_comment_args is not None:
              self.type_comment_args = type_comment_args
          if type_comment_kwonlyargs is not None:
              self.type_comment_kwonlyargs = type_comment_kwonlyargs
          if type_comment_posonlyargs is not None:
              self.type_comment_posonlyargs = type_comment_posonlyargs
  
      assigned_stmts: ClassVar[AssignedStmtsCall[Arguments]]
      """Returns the assigned statement (non inferred) according to the assignment type.
      See astroid/protocols.py for actual implementation.
      """
  
      def _infer_name(self, frame, name):
          if self.parent is frame:
              return name
          return None
  
      @cached_property
      def fromlineno(self):
          """The first line that this node appears on in the source code.
  
          :type: int or None
          """
          lineno = super().fromlineno
          return max(lineno, self.parent.fromlineno or 0)
  
      @cached_property
      def arguments(self):
          """Get all the arguments for this node, including positional only and positional and keyword"""
          return list(itertools.chain((self.posonlyargs or ()), self.args or ()))
  
      def format_args(self):
          """Get the arguments formatted as string.
  
          :returns: The formatted arguments.
          :rtype: str
          """
          result = []
          positional_only_defaults = []
          positional_or_keyword_defaults = self.defaults
          if self.defaults:
              args = self.args or []
              positional_or_keyword_defaults = self.defaults[-len(args) :]
              positional_only_defaults = self.defaults[: len(self.defaults) - len(args)]
  
          if self.posonlyargs:
              result.append(
                  _format_args(
                      self.posonlyargs,
                      positional_only_defaults,
                      self.posonlyargs_annotations,
                  )
              )
              result.append("/")
          if self.args:
              result.append(
                  _format_args(
                      self.args,
                      positional_or_keyword_defaults,
                      getattr(self, "annotations", None),
                  )
              )
          if self.vararg:
              result.append(f"*{self.vararg}")
          if self.kwonlyargs:
              if not self.vararg:
                  result.append("*")
              result.append(
                  _format_args(
                      self.kwonlyargs, self.kw_defaults, self.kwonlyargs_annotations
                  )
              )
          if self.kwarg:
              result.append(f"**{self.kwarg}")
          return ", ".join(result)
  
      def default_value(self, argname):
          """Get the default value for an argument.
  
          :param argname: The name of the argument to get the default value for.
          :type argname: str
  
          :raises NoDefault: If there is no default value defined for the
              given argument.
          """
          args = self.arguments
          index = _find_arg(argname, args)[0]
          if index is not None:
              idx = index - (len(args) - len(self.defaults))
              if idx >= 0:
                  return self.defaults[idx]
          index = _find_arg(argname, self.kwonlyargs)[0]
          if index is not None and self.kw_defaults[index] is not None:
              return self.kw_defaults[index]
          raise NoDefault(func=self.parent, name=argname)
  
      def is_argument(self, name):
          """Check if the given name is defined in the arguments.
  
          :param name: The name to check for.
          :type name: str
  
          :returns: True if the given name is defined in the arguments,
              False otherwise.
          :rtype: bool
          """
          if name == self.vararg:
              return True
          if name == self.kwarg:
              return True
          return (
              self.find_argname(name, rec=True)[1] is not None
              or self.kwonlyargs
              and _find_arg(name, self.kwonlyargs, rec=True)[1] is not None
          )
  
      def find_argname(self, argname, rec=False):
          """Get the index and :class:`AssignName` node for given name.
  
          :param argname: The name of the argument to search for.
          :type argname: str
  
          :param rec: Whether or not to include arguments in unpacked tuples
              in the search.
          :type rec: bool
  
          :returns: The index and node for the argument.
          :rtype: tuple(str or None, AssignName or None)
          """
          if self.arguments:
              return _find_arg(argname, self.arguments, rec)
          return None, None
  
      def get_children(self):
          yield from self.posonlyargs or ()
  
          for elt in self.posonlyargs_annotations:
              if elt is not None:
                  yield elt
  
          yield from self.args or ()
  
          yield from self.defaults
          yield from self.kwonlyargs
  
          for elt in self.kw_defaults:
              if elt is not None:
                  yield elt
  
          for elt in self.annotations:
              if elt is not None:
                  yield elt
  
          if self.varargannotation is not None:
              yield self.varargannotation
  
          if self.kwargannotation is not None:
              yield self.kwargannotation
  
          for elt in self.kwonlyargs_annotations:
              if elt is not None:
                  yield elt
  
  
  def _find_arg(argname, args, rec=False):
      for i, arg in enumerate(args):
          if isinstance(arg, Tuple):
              if rec:
                  found = _find_arg(argname, arg.elts)
                  if found[0] is not None:
                      return found
          elif arg.name == argname:
              return i, arg
      return None, None
  
  
  def _format_args(args, defaults=None, annotations=None):
      values = []
      if args is None:
          return ""
      if annotations is None:
          annotations = []
      if defaults is not None:
          default_offset = len(args) - len(defaults)
      packed = itertools.zip_longest(args, annotations)
      for i, (arg, annotation) in enumerate(packed):
          if isinstance(arg, Tuple):
              values.append(f"({_format_args(arg.elts)})")
          else:
              argname = arg.name
              default_sep = "="
              if annotation is not None:
                  argname += ": " + annotation.as_string()
                  default_sep = " = "
              values.append(argname)
  
              if defaults is not None and i >= default_offset:
                  if defaults[i - default_offset] is not None:
                      values[-1] += default_sep + defaults[i - default_offset].as_string()
      return ", ".join(values)
  
  
  class AssignAttr(mixins.ParentAssignTypeMixin, NodeNG):
      """Variation of :class:`ast.Assign` representing assignment to an attribute.
  
      >>> import astroid
      >>> node = astroid.extract_node('self.attribute = range(10)')
      >>> node
      <Assign l.1 at 0x7effe1d521d0>
      >>> list(node.get_children())
      [<AssignAttr.attribute l.1 at 0x7effe1d52320>, <Call l.1 at 0x7effe1d522e8>]
      >>> list(node.get_children())[0].as_string()
      'self.attribute'
      """
  
      _astroid_fields = ("expr",)
      _other_fields = ("attrname",)
  
      @decorators.deprecate_default_argument_values(attrname="str")
      def __init__(
          self,
          attrname: str | None = None,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param attrname: The name of the attribute being assigned to.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.expr: NodeNG | None = None
          """What has the attribute that is being assigned to."""
  
          self.attrname: str | None = attrname
          """The name of the attribute being assigned to."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, expr: NodeNG | None = None) -> None:
          """Do some setup after initialisation.
  
          :param expr: What has the attribute that is being assigned to.
          """
          self.expr = expr
  
      assigned_stmts: ClassVar[AssignedStmtsCall[AssignAttr]]
      """Returns the assigned statement (non inferred) according to the assignment type.
      See astroid/protocols.py for actual implementation.
      """
  
      def get_children(self):
          yield self.expr
  
  
  class Assert(Statement):
      """Class representing an :class:`ast.Assert` node.
  
      An :class:`Assert` node represents an assert statement.
  
      >>> import astroid
      >>> node = astroid.extract_node('assert len(things) == 10, "Not enough things"')
      >>> node
      <Assert l.1 at 0x7effe1d527b8>
      """
  
      _astroid_fields = ("test", "fail")
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.test: NodeNG | None = None
          """The test that passes or fails the assertion."""
  
          self.fail: NodeNG | None = None  # can be None
          """The message shown when the assertion fails."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, test: NodeNG | None = None, fail: NodeNG | None = None) -> None:
          """Do some setup after initialisation.
  
          :param test: The test that passes or fails the assertion.
  
          :param fail: The message shown when the assertion fails.
          """
          self.fail = fail
          self.test = test
  
      def get_children(self):
          yield self.test
  
          if self.fail is not None:
              yield self.fail
  
  
  class Assign(mixins.AssignTypeMixin, Statement):
      """Class representing an :class:`ast.Assign` node.
  
      An :class:`Assign` is a statement where something is explicitly
      asssigned to.
  
      >>> import astroid
      >>> node = astroid.extract_node('variable = range(10)')
      >>> node
      <Assign l.1 at 0x7effe1db8550>
      """
  
      _astroid_fields = ("targets", "value")
      _other_other_fields = ("type_annotation",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.targets: list[NodeNG] = []
          """What is being assigned to."""
  
          self.value: NodeNG | None = None
          """The value being assigned to the variables."""
  
          self.type_annotation: NodeNG | None = None  # can be None
          """If present, this will contain the type annotation passed by a type comment"""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self,
          targets: list[NodeNG] | None = None,
          value: NodeNG | None = None,
          type_annotation: NodeNG | None = None,
      ) -> None:
          """Do some setup after initialisation.
  
          :param targets: What is being assigned to.
          :param value: The value being assigned to the variables.
          :param type_annotation:
          """
          if targets is not None:
              self.targets = targets
          self.value = value
          self.type_annotation = type_annotation
  
      assigned_stmts: ClassVar[AssignedStmtsCall[Assign]]
      """Returns the assigned statement (non inferred) according to the assignment type.
      See astroid/protocols.py for actual implementation.
      """
  
      def get_children(self):
          yield from self.targets
  
          yield self.value
  
      @decorators.cached
      def _get_assign_nodes(self):
          return [self] + list(self.value._get_assign_nodes())
  
      def _get_yield_nodes_skip_lambdas(self):
          yield from self.value._get_yield_nodes_skip_lambdas()
  
  
  class AnnAssign(mixins.AssignTypeMixin, Statement):
      """Class representing an :class:`ast.AnnAssign` node.
  
      An :class:`AnnAssign` is an assignment with a type annotation.
  
      >>> import astroid
      >>> node = astroid.extract_node('variable: List[int] = range(10)')
      >>> node
      <AnnAssign l.1 at 0x7effe1d4c630>
      """
  
      _astroid_fields = ("target", "annotation", "value")
      _other_fields = ("simple",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.target: NodeNG | None = None
          """What is being assigned to."""
  
          self.annotation: NodeNG | None = None
          """The type annotation of what is being assigned to."""
  
          self.value: NodeNG | None = None  # can be None
          """The value being assigned to the variables."""
  
          self.simple: int | None = None
          """Whether :attr:`target` is a pure name or a complex statement."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self,
          target: NodeNG,
          annotation: NodeNG,
          simple: int,
          value: NodeNG | None = None,
      ) -> None:
          """Do some setup after initialisation.
  
          :param target: What is being assigned to.
  
          :param annotation: The type annotation of what is being assigned to.
  
          :param simple: Whether :attr:`target` is a pure name
              or a complex statement.
  
          :param value: The value being assigned to the variables.
          """
          self.target = target
          self.annotation = annotation
          self.value = value
          self.simple = simple
  
      assigned_stmts: ClassVar[AssignedStmtsCall[AnnAssign]]
      """Returns the assigned statement (non inferred) according to the assignment type.
      See astroid/protocols.py for actual implementation.
      """
  
      def get_children(self):
          yield self.target
          yield self.annotation
  
          if self.value is not None:
              yield self.value
  
  
  class AugAssign(mixins.AssignTypeMixin, Statement):
      """Class representing an :class:`ast.AugAssign` node.
  
      An :class:`AugAssign` is an assignment paired with an operator.
  
      >>> import astroid
      >>> node = astroid.extract_node('variable += 1')
      >>> node
      <AugAssign l.1 at 0x7effe1db4d68>
      """
  
      _astroid_fields = ("target", "value")
      _other_fields = ("op",)
  
      @decorators.deprecate_default_argument_values(op="str")
      def __init__(
          self,
          op: str | None = None,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param op: The operator that is being combined with the assignment.
              This includes the equals sign.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.target: NodeNG | None = None
          """What is being assigned to."""
  
          self.op: str | None = op
          """The operator that is being combined with the assignment.
  
          This includes the equals sign.
          """
  
          self.value: NodeNG | None = None
          """The value being assigned to the variable."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self, target: NodeNG | None = None, value: NodeNG | None = None
      ) -> None:
          """Do some setup after initialisation.
  
          :param target: What is being assigned to.
  
          :param value: The value being assigned to the variable.
          """
          self.target = target
          self.value = value
  
      assigned_stmts: ClassVar[AssignedStmtsCall[AugAssign]]
      """Returns the assigned statement (non inferred) according to the assignment type.
      See astroid/protocols.py for actual implementation.
      """
  
      # This is set by inference.py
      def _infer_augassign(self, context=None):
          raise NotImplementedError
  
      def type_errors(self, context=None):
          """Get a list of type errors which can occur during inference.
  
          Each TypeError is represented by a :class:`BadBinaryOperationMessage` ,
          which holds the original exception.
  
          :returns: The list of possible type errors.
          :rtype: list(BadBinaryOperationMessage)
          """
          try:
              results = self._infer_augassign(context=context)
              return [
                  result
                  for result in results
                  if isinstance(result, util.BadBinaryOperationMessage)
              ]
          except InferenceError:
              return []
  
      def get_children(self):
          yield self.target
          yield self.value
  
      def _get_yield_nodes_skip_lambdas(self):
          """An AugAssign node can contain a Yield node in the value"""
          yield from self.value._get_yield_nodes_skip_lambdas()
          yield from super()._get_yield_nodes_skip_lambdas()
  
  
  class BinOp(NodeNG):
      """Class representing an :class:`ast.BinOp` node.
  
      A :class:`BinOp` node is an application of a binary operator.
  
      >>> import astroid
      >>> node = astroid.extract_node('a + b')
      >>> node
      <BinOp l.1 at 0x7f23b2e8cfd0>
      """
  
      _astroid_fields = ("left", "right")
      _other_fields = ("op",)
  
      @decorators.deprecate_default_argument_values(op="str")
      def __init__(
          self,
          op: str | None = None,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param op: The operator.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.left: NodeNG | None = None
          """What is being applied to the operator on the left side."""
  
          self.op: str | None = op
          """The operator."""
  
          self.right: NodeNG | None = None
          """What is being applied to the operator on the right side."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, left: NodeNG | None = None, right: NodeNG | None = None) -> None:
          """Do some setup after initialisation.
  
          :param left: What is being applied to the operator on the left side.
  
          :param right: What is being applied to the operator on the right side.
          """
          self.left = left
          self.right = right
  
      # This is set by inference.py
      def _infer_binop(self, context=None):
          raise NotImplementedError
  
      def type_errors(self, context=None):
          """Get a list of type errors which can occur during inference.
  
          Each TypeError is represented by a :class:`BadBinaryOperationMessage`,
          which holds the original exception.
  
          :returns: The list of possible type errors.
          :rtype: list(BadBinaryOperationMessage)
          """
          try:
              results = self._infer_binop(context=context)
              return [
                  result
                  for result in results
                  if isinstance(result, util.BadBinaryOperationMessage)
              ]
          except InferenceError:
              return []
  
      def get_children(self):
          yield self.left
          yield self.right
  
      def op_precedence(self):
          return OP_PRECEDENCE[self.op]
  
      def op_left_associative(self):
          # 2**3**4 == 2**(3**4)
          return self.op != "**"
  
  
  class BoolOp(NodeNG):
      """Class representing an :class:`ast.BoolOp` node.
  
      A :class:`BoolOp` is an application of a boolean operator.
  
      >>> import astroid
      >>> node = astroid.extract_node('a and b')
      >>> node
      <BinOp l.1 at 0x7f23b2e71c50>
      """
  
      _astroid_fields = ("values",)
      _other_fields = ("op",)
  
      @decorators.deprecate_default_argument_values(op="str")
      def __init__(
          self,
          op: str | None = None,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param op: The operator.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.op: str | None = op
          """The operator."""
  
          self.values: list[NodeNG] = []
          """The values being applied to the operator."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, values: list[NodeNG] | None = None) -> None:
          """Do some setup after initialisation.
  
          :param values: The values being applied to the operator.
          """
          if values is not None:
              self.values = values
  
      def get_children(self):
          yield from self.values
  
      def op_precedence(self):
          return OP_PRECEDENCE[self.op]
  
  
  class Break(mixins.NoChildrenMixin, Statement):
      """Class representing an :class:`ast.Break` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('break')
      >>> node
      <Break l.1 at 0x7f23b2e9e5c0>
      """
  
  
  class Call(NodeNG):
      """Class representing an :class:`ast.Call` node.
  
      A :class:`Call` node is a call to a function, method, etc.
  
      >>> import astroid
      >>> node = astroid.extract_node('function()')
      >>> node
      <Call l.1 at 0x7f23b2e71eb8>
      """
  
      _astroid_fields = ("func", "args", "keywords")
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.func: NodeNG | None = None
          """What is being called."""
  
          self.args: list[NodeNG] = []
          """The positional arguments being given to the call."""
  
          self.keywords: list[Keyword] = []
          """The keyword arguments being given to the call."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self,
          func: NodeNG | None = None,
          args: list[NodeNG] | None = None,
          keywords: list[Keyword] | None = None,
      ) -> None:
          """Do some setup after initialisation.
  
          :param func: What is being called.
  
          :param args: The positional arguments being given to the call.
  
          :param keywords: The keyword arguments being given to the call.
          """
          self.func = func
          if args is not None:
              self.args = args
          if keywords is not None:
              self.keywords = keywords
  
      @property
      def starargs(self) -> list[Starred]:
          """The positional arguments that unpack something."""
          return [arg for arg in self.args if isinstance(arg, Starred)]
  
      @property
      def kwargs(self) -> list[Keyword]:
          """The keyword arguments that unpack something."""
          return [keyword for keyword in self.keywords if keyword.arg is None]
  
      def get_children(self):
          yield self.func
  
          yield from self.args
  
          yield from self.keywords
  
  
  class Compare(NodeNG):
      """Class representing an :class:`ast.Compare` node.
  
      A :class:`Compare` node indicates a comparison.
  
      >>> import astroid
      >>> node = astroid.extract_node('a <= b <= c')
      >>> node
      <Compare l.1 at 0x7f23b2e9e6d8>
      >>> node.ops
      [('<=', <Name.b l.1 at 0x7f23b2e9e2b0>), ('<=', <Name.c l.1 at 0x7f23b2e9e390>)]
      """
  
      _astroid_fields = ("left", "ops")
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.left: NodeNG | None = None
          """The value at the left being applied to a comparison operator."""
  
          self.ops: list[tuple[str, NodeNG]] = []
          """The remainder of the operators and their relevant right hand value."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self,
          left: NodeNG | None = None,
          ops: list[tuple[str, NodeNG]] | None = None,
      ) -> None:
          """Do some setup after initialisation.
  
          :param left: The value at the left being applied to a comparison
              operator.
  
          :param ops: The remainder of the operators
              and their relevant right hand value.
          """
          self.left = left
          if ops is not None:
              self.ops = ops
  
      def get_children(self):
          """Get the child nodes below this node.
  
          Overridden to handle the tuple fields and skip returning the operator
          strings.
  
          :returns: The children.
          :rtype: iterable(NodeNG)
          """
          yield self.left
          for _, comparator in self.ops:
              yield comparator  # we don't want the 'op'
  
      def last_child(self):
          """An optimized version of list(get_children())[-1]
  
          :returns: The last child.
          :rtype: NodeNG
          """
          # XXX maybe if self.ops:
          return self.ops[-1][1]
          # return self.left
  
  
  class Comprehension(NodeNG):
      """Class representing an :class:`ast.comprehension` node.
  
      A :class:`Comprehension` indicates the loop inside any type of
      comprehension including generator expressions.
  
      >>> import astroid
      >>> node = astroid.extract_node('[x for x in some_values]')
      >>> list(node.get_children())
      [<Name.x l.1 at 0x7f23b2e352b0>, <Comprehension l.1 at 0x7f23b2e35320>]
      >>> list(node.get_children())[1].as_string()
      'for x in some_values'
      """
  
      _astroid_fields = ("target", "iter", "ifs")
      _other_fields = ("is_async",)
  
      optional_assign = True
      """Whether this node optionally assigns a variable."""
  
      lineno: None
      col_offset: None
      end_lineno: None
      end_col_offset: None
  
      def __init__(self, parent: NodeNG | None = None) -> None:
          """
          :param parent: The parent node in the syntax tree.
          """
          self.target: NodeNG | None = None
          """What is assigned to by the comprehension."""
  
          self.iter: NodeNG | None = None
          """What is iterated over by the comprehension."""
  
          self.ifs: list[NodeNG] = []
          """The contents of any if statements that filter the comprehension."""
  
          self.is_async: bool | None = None
          """Whether this is an asynchronous comprehension or not."""
  
          super().__init__(parent=parent)
  
      # pylint: disable=redefined-builtin; same name as builtin ast module.
      def postinit(
          self,
          target: NodeNG | None = None,
          iter: NodeNG | None = None,
          ifs: list[NodeNG] | None = None,
          is_async: bool | None = None,
      ) -> None:
          """Do some setup after initialisation.
  
          :param target: What is assigned to by the comprehension.
  
          :param iter: What is iterated over by the comprehension.
  
          :param ifs: The contents of any if statements that filter
              the comprehension.
  
          :param is_async: Whether this is an asynchronous comprehension or not.
          """
          self.target = target
          self.iter = iter
          if ifs is not None:
              self.ifs = ifs
          self.is_async = is_async
  
      assigned_stmts: ClassVar[AssignedStmtsCall[Comprehension]]
      """Returns the assigned statement (non inferred) according to the assignment type.
      See astroid/protocols.py for actual implementation.
      """
  
      def assign_type(self):
          """The type of assignment that this node performs.
  
          :returns: The assignment type.
          :rtype: NodeNG
          """
          return self
  
      def _get_filtered_stmts(self, lookup_node, node, stmts, mystmt: Statement | None):
          """method used in filter_stmts"""
          if self is mystmt:
              if isinstance(lookup_node, (Const, Name)):
                  return [lookup_node], True
  
          elif self.statement(future=True) is mystmt:
              # original node's statement is the assignment, only keeps
              # current node (gen exp, list comp)
  
              return [node], True
  
          return stmts, False
  
      def get_children(self):
          yield self.target
          yield self.iter
  
          yield from self.ifs
  
  
  class Const(mixins.NoChildrenMixin, NodeNG, Instance):
      """Class representing any constant including num, str, bool, None, bytes.
  
      >>> import astroid
      >>> node = astroid.extract_node('(5, "This is a string.", True, None, b"bytes")')
      >>> node
      <Tuple.tuple l.1 at 0x7f23b2e358d0>
      >>> list(node.get_children())
      [<Const.int l.1 at 0x7f23b2e35940>,
      <Const.str l.1 at 0x7f23b2e35978>,
      <Const.bool l.1 at 0x7f23b2e359b0>,
      <Const.NoneType l.1 at 0x7f23b2e359e8>,
      <Const.bytes l.1 at 0x7f23b2e35a20>]
      """
  
      _other_fields = ("value", "kind")
  
      def __init__(
          self,
          value: Any,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          kind: str | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param value: The value that the constant represents.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param kind: The string prefix. "u" for u-prefixed strings and ``None`` otherwise. Python 3.8+ only.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.value: Any = value
          """The value that the constant represents."""
  
          self.kind: str | None = kind  # can be None
          """"The string prefix. "u" for u-prefixed strings and ``None`` otherwise. Python 3.8+ only."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def __getattr__(self, name):
          # This is needed because of Proxy's __getattr__ method.
          # Calling object.__new__ on this class without calling
          # __init__ would result in an infinite loop otherwise
          # since __getattr__ is called when an attribute doesn't
          # exist and self._proxied indirectly calls self.value
          # and Proxy __getattr__ calls self.value
          if name == "value":
              raise AttributeError
          return super().__getattr__(name)
  
      def getitem(self, index, context=None):
          """Get an item from this node if subscriptable.
  
          :param index: The node to use as a subscript index.
          :type index: Const or Slice
  
          :raises AstroidTypeError: When the given index cannot be used as a
              subscript index, or if this node is not subscriptable.
          """
          if isinstance(index, Const):
              index_value = index.value
          elif isinstance(index, Slice):
              index_value = _infer_slice(index, context=context)
  
          else:
              raise AstroidTypeError(
                  f"Could not use type {type(index)} as subscript index"
              )
  
          try:
              if isinstance(self.value, (str, bytes)):
                  return Const(self.value[index_value])
          except IndexError as exc:
              raise AstroidIndexError(
                  message="Index {index!r} out of range",
                  node=self,
                  index=index,
                  context=context,
              ) from exc
          except TypeError as exc:
              raise AstroidTypeError(
                  message="Type error {error!r}", node=self, index=index, context=context
              ) from exc
  
          raise AstroidTypeError(f"{self!r} (value={self.value})")
  
      def has_dynamic_getattr(self):
          """Check if the node has a custom __getattr__ or __getattribute__.
  
          :returns: True if the class has a custom
              __getattr__ or __getattribute__, False otherwise.
              For a :class:`Const` this is always ``False``.
          :rtype: bool
          """
          return False
  
      def itered(self):
          """An iterator over the elements this node contains.
  
          :returns: The contents of this node.
          :rtype: iterable(Const)
  
          :raises TypeError: If this node does not represent something that is iterable.
          """
          if isinstance(self.value, str):
              return [const_factory(elem) for elem in self.value]
          raise TypeError(f"Cannot iterate over type {type(self.value)!r}")
  
      def pytype(self):
          """Get the name of the type that this node represents.
  
          :returns: The name of the type.
          :rtype: str
          """
          return self._proxied.qname()
  
      def bool_value(self, context=None):
          """Determine the boolean value of this node.
  
          :returns: The boolean value of this node.
          :rtype: bool
          """
          return bool(self.value)
  
  
  class Continue(mixins.NoChildrenMixin, Statement):
      """Class representing an :class:`ast.Continue` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('continue')
      >>> node
      <Continue l.1 at 0x7f23b2e35588>
      """
  
  
  class Decorators(NodeNG):
      """A node representing a list of decorators.
  
      A :class:`Decorators` is the decorators that are applied to
      a method or function.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
      @property
      def my_property(self):
          return 3
      ''')
      >>> node
      <FunctionDef.my_property l.2 at 0x7f23b2e35d30>
      >>> list(node.get_children())[0]
      <Decorators l.1 at 0x7f23b2e35d68>
      """
  
      _astroid_fields = ("nodes",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.nodes: list[NodeNG]
          """The decorators that this node contains.
  
          :type: list(Name or Call) or None
          """
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, nodes: list[NodeNG]) -> None:
          """Do some setup after initialisation.
  
          :param nodes: The decorators that this node contains.
          :type nodes: list(Name or Call)
          """
          self.nodes = nodes
  
      def scope(self) -> LocalsDictNodeNG:
          """The first parent node defining a new scope.
          These can be Module, FunctionDef, ClassDef, Lambda, or GeneratorExp nodes.
  
          :returns: The first parent scope node.
          """
          # skip the function node to go directly to the upper level scope
          if not self.parent:
              raise ParentMissingError(target=self)
          if not self.parent.parent:
              raise ParentMissingError(target=self.parent)
          return self.parent.parent.scope()
  
      def get_children(self):
          yield from self.nodes
  
  
  class DelAttr(mixins.ParentAssignTypeMixin, NodeNG):
      """Variation of :class:`ast.Delete` representing deletion of an attribute.
  
      >>> import astroid
      >>> node = astroid.extract_node('del self.attr')
      >>> node
      <Delete l.1 at 0x7f23b2e35f60>
      >>> list(node.get_children())[0]
      <DelAttr.attr l.1 at 0x7f23b2e411d0>
      """
  
      _astroid_fields = ("expr",)
      _other_fields = ("attrname",)
  
      @decorators.deprecate_default_argument_values(attrname="str")
      def __init__(
          self,
          attrname: str | None = None,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param attrname: The name of the attribute that is being deleted.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.expr: NodeNG | None = None
          """The name that this node represents.
  
          :type: Name or None
          """
  
          self.attrname: str | None = attrname
          """The name of the attribute that is being deleted."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, expr: NodeNG | None = None) -> None:
          """Do some setup after initialisation.
  
          :param expr: The name that this node represents.
          :type expr: Name or None
          """
          self.expr = expr
  
      def get_children(self):
          yield self.expr
  
  
  class Delete(mixins.AssignTypeMixin, Statement):
      """Class representing an :class:`ast.Delete` node.
  
      A :class:`Delete` is a ``del`` statement this is deleting something.
  
      >>> import astroid
      >>> node = astroid.extract_node('del self.attr')
      >>> node
      <Delete l.1 at 0x7f23b2e35f60>
      """
  
      _astroid_fields = ("targets",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.targets: list[NodeNG] = []
          """What is being deleted."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, targets: list[NodeNG] | None = None) -> None:
          """Do some setup after initialisation.
  
          :param targets: What is being deleted.
          """
          if targets is not None:
              self.targets = targets
  
      def get_children(self):
          yield from self.targets
  
  
  class Dict(NodeNG, Instance):
      """Class representing an :class:`ast.Dict` node.
  
      A :class:`Dict` is a dictionary that is created with ``{}`` syntax.
  
      >>> import astroid
      >>> node = astroid.extract_node('{1: "1"}')
      >>> node
      <Dict.dict l.1 at 0x7f23b2e35cc0>
      """
  
      _astroid_fields = ("items",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.items: list[tuple[NodeNG, NodeNG]] = []
          """The key-value pairs contained in the dictionary."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, items: list[tuple[NodeNG, NodeNG]]) -> None:
          """Do some setup after initialisation.
  
          :param items: The key-value pairs contained in the dictionary.
          """
          self.items = items
  
      @classmethod
      def from_elements(cls, items=None):
          """Create a :class:`Dict` of constants from a live dictionary.
  
          :param items: The items to store in the node.
          :type items: dict
  
          :returns: The created dictionary node.
          :rtype: Dict
          """
          node = cls()
          if items is None:
              node.items = []
          else:
              node.items = [
                  (const_factory(k), const_factory(v) if _is_const(v) else v)
                  for k, v in items.items()
                  # The keys need to be constants
                  if _is_const(k)
              ]
          return node
  
      def pytype(self):
          """Get the name of the type that this node represents.
  
          :returns: The name of the type.
          :rtype: str
          """
          return "builtins.dict"
  
      def get_children(self):
          """Get the key and value nodes below this node.
  
          Children are returned in the order that they are defined in the source
          code, key first then the value.
  
          :returns: The children.
          :rtype: iterable(NodeNG)
          """
          for key, value in self.items:
              yield key
              yield value
  
      def last_child(self):
          """An optimized version of list(get_children())[-1]
  
          :returns: The last child, or None if no children exist.
          :rtype: NodeNG or None
          """
          if self.items:
              return self.items[-1][1]
          return None
  
      def itered(self):
          """An iterator over the keys this node contains.
  
          :returns: The keys of this node.
          :rtype: iterable(NodeNG)
          """
          return [key for (key, _) in self.items]
  
      def getitem(self, index, context=None):
          """Get an item from this node.
  
          :param index: The node to use as a subscript index.
          :type index: Const or Slice
  
          :raises AstroidTypeError: When the given index cannot be used as a
              subscript index, or if this node is not subscriptable.
          :raises AstroidIndexError: If the given index does not exist in the
              dictionary.
          """
          for key, value in self.items:
              # TODO(cpopa): no support for overriding yet, {1:2, **{1: 3}}.
              if isinstance(key, DictUnpack):
                  try:
                      return value.getitem(index, context)
                  except (AstroidTypeError, AstroidIndexError):
                      continue
              for inferredkey in key.infer(context):
                  if inferredkey is util.Uninferable:
                      continue
                  if isinstance(inferredkey, Const) and isinstance(index, Const):
                      if inferredkey.value == index.value:
                          return value
  
          raise AstroidIndexError(index)
  
      def bool_value(self, context=None):
          """Determine the boolean value of this node.
  
          :returns: The boolean value of this node.
          :rtype: bool
          """
          return bool(self.items)
  
  
  class Expr(Statement):
      """Class representing an :class:`ast.Expr` node.
  
      An :class:`Expr` is any expression that does not have its value used or
      stored.
  
      >>> import astroid
      >>> node = astroid.extract_node('method()')
      >>> node
      <Call l.1 at 0x7f23b2e352b0>
      >>> node.parent
      <Expr l.1 at 0x7f23b2e35278>
      """
  
      _astroid_fields = ("value",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.value: NodeNG | None = None
          """What the expression does."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, value: NodeNG | None = None) -> None:
          """Do some setup after initialisation.
  
          :param value: What the expression does.
          """
          self.value = value
  
      def get_children(self):
          yield self.value
  
      def _get_yield_nodes_skip_lambdas(self):
          if not self.value.is_lambda:
              yield from self.value._get_yield_nodes_skip_lambdas()
  
  
  class Ellipsis(mixins.NoChildrenMixin, NodeNG):  # pylint: disable=redefined-builtin
      """Class representing an :class:`ast.Ellipsis` node.
  
      An :class:`Ellipsis` is the ``...`` syntax.
  
      Deprecated since v2.6.0 - Use :class:`Const` instead.
      Will be removed with the release v2.7.0
      """
  
  
  class EmptyNode(mixins.NoChildrenMixin, NodeNG):
      """Holds an arbitrary object in the :attr:`LocalsDictNodeNG.locals`."""
  
      object = None
  
  
  class ExceptHandler(mixins.MultiLineBlockMixin, mixins.AssignTypeMixin, Statement):
      """Class representing an :class:`ast.ExceptHandler`. node.
  
      An :class:`ExceptHandler` is an ``except`` block on a try-except.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
          try:
              do_something()
          except Exception as error:
              print("Error!")
          ''')
      >>> node
      <TryExcept l.2 at 0x7f23b2e9d908>
      >>> node.handlers
      [<ExceptHandler l.4 at 0x7f23b2e9e860>]
      """
  
      _astroid_fields = ("type", "name", "body")
      _multi_line_block_fields = ("body",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.type: NodeNG | None = None  # can be None
          """The types that the block handles.
  
          :type: Tuple or NodeNG or None
          """
  
          self.name: AssignName | None = None  # can be None
          """The name that the caught exception is assigned to."""
  
          self.body: list[NodeNG] = []
          """The contents of the block."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      assigned_stmts: ClassVar[AssignedStmtsCall[ExceptHandler]]
      """Returns the assigned statement (non inferred) according to the assignment type.
      See astroid/protocols.py for actual implementation.
      """
  
      def get_children(self):
          if self.type is not None:
              yield self.type
  
          if self.name is not None:
              yield self.name
  
          yield from self.body
  
      # pylint: disable=redefined-builtin; had to use the same name as builtin ast module.
      def postinit(
          self,
          type: NodeNG | None = None,
          name: AssignName | None = None,
          body: list[NodeNG] | None = None,
      ) -> None:
          """Do some setup after initialisation.
  
          :param type: The types that the block handles.
          :type type: Tuple or NodeNG or None
  
          :param name: The name that the caught exception is assigned to.
  
          :param body:The contents of the block.
          """
          self.type = type
          self.name = name
          if body is not None:
              self.body = body
  
      @cached_property
      def blockstart_tolineno(self):
          """The line on which the beginning of this block ends.
  
          :type: int
          """
          if self.name:
              return self.name.tolineno
          if self.type:
              return self.type.tolineno
          return self.lineno
  
      def catch(self, exceptions: list[str] | None) -> bool:
          """Check if this node handles any of the given
  
          :param exceptions: The names of the exceptions to check for.
          """
          if self.type is None or exceptions is None:
              return True
          return any(node.name in exceptions for node in self.type._get_name_nodes())
  
  
  class ExtSlice(NodeNG):
      """Class representing an :class:`ast.ExtSlice` node.
  
      An :class:`ExtSlice` is a complex slice expression.
  
      Deprecated since v2.6.0 - Now part of the :class:`Subscript` node.
      Will be removed with the release of v2.7.0
      """
  
  
  class For(
      mixins.MultiLineBlockMixin,
      mixins.BlockRangeMixIn,
      mixins.AssignTypeMixin,
      Statement,
  ):
      """Class representing an :class:`ast.For` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('for thing in things: print(thing)')
      >>> node
      <For l.1 at 0x7f23b2e8cf28>
      """
  
      _astroid_fields = ("target", "iter", "body", "orelse")
      _other_other_fields = ("type_annotation",)
      _multi_line_block_fields = ("body", "orelse")
  
      optional_assign = True
      """Whether this node optionally assigns a variable.
  
      This is always ``True`` for :class:`For` nodes.
      """
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.target: NodeNG | None = None
          """What the loop assigns to."""
  
          self.iter: NodeNG | None = None
          """What the loop iterates over."""
  
          self.body: list[NodeNG] = []
          """The contents of the body of the loop."""
  
          self.orelse: list[NodeNG] = []
          """The contents of the ``else`` block of the loop."""
  
          self.type_annotation: NodeNG | None = None  # can be None
          """If present, this will contain the type annotation passed by a type comment"""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      # pylint: disable=redefined-builtin; had to use the same name as builtin ast module.
      def postinit(
          self,
          target: NodeNG | None = None,
          iter: NodeNG | None = None,
          body: list[NodeNG] | None = None,
          orelse: list[NodeNG] | None = None,
          type_annotation: NodeNG | None = None,
      ) -> None:
          """Do some setup after initialisation.
  
          :param target: What the loop assigns to.
  
          :param iter: What the loop iterates over.
  
          :param body: The contents of the body of the loop.
  
          :param orelse: The contents of the ``else`` block of the loop.
          """
          self.target = target
          self.iter = iter
          if body is not None:
              self.body = body
          if orelse is not None:
              self.orelse = orelse
          self.type_annotation = type_annotation
  
      assigned_stmts: ClassVar[AssignedStmtsCall[For]]
      """Returns the assigned statement (non inferred) according to the assignment type.
      See astroid/protocols.py for actual implementation.
      """
  
      @cached_property
      def blockstart_tolineno(self):
          """The line on which the beginning of this block ends.
  
          :type: int
          """
          return self.iter.tolineno
  
      def get_children(self):
          yield self.target
          yield self.iter
  
          yield from self.body
          yield from self.orelse
  
  
  class AsyncFor(For):
      """Class representing an :class:`ast.AsyncFor` node.
  
      An :class:`AsyncFor` is an asynchronous :class:`For` built with
      the ``async`` keyword.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
      async def func(things):
          async for thing in things:
              print(thing)
      ''')
      >>> node
      <AsyncFunctionDef.func l.2 at 0x7f23b2e416d8>
      >>> node.body[0]
      <AsyncFor l.3 at 0x7f23b2e417b8>
      """
  
  
  class Await(NodeNG):
      """Class representing an :class:`ast.Await` node.
  
      An :class:`Await` is the ``await`` keyword.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
      async def func(things):
          await other_func()
      ''')
      >>> node
      <AsyncFunctionDef.func l.2 at 0x7f23b2e41748>
      >>> node.body[0]
      <Expr l.3 at 0x7f23b2e419e8>
      >>> list(node.body[0].get_children())[0]
      <Await l.3 at 0x7f23b2e41a20>
      """
  
      _astroid_fields = ("value",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.value: NodeNG | None = None
          """What to wait for."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, value: NodeNG | None = None) -> None:
          """Do some setup after initialisation.
  
          :param value: What to wait for.
          """
          self.value = value
  
      def get_children(self):
          yield self.value
  
  
  class ImportFrom(mixins.NoChildrenMixin, mixins.ImportFromMixin, Statement):
      """Class representing an :class:`ast.ImportFrom` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('from my_package import my_module')
      >>> node
      <ImportFrom l.1 at 0x7f23b2e415c0>
      """
  
      _other_fields = ("modname", "names", "level")
  
      def __init__(
          self,
          fromname: str | None,
          names: list[tuple[str, str | None]],
          level: int | None = 0,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param fromname: The module that is being imported from.
  
          :param names: What is being imported from the module.
  
          :param level: The level of relative import.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.modname: str | None = fromname  # can be None
          """The module that is being imported from.
  
          This is ``None`` for relative imports.
          """
  
          self.names: list[tuple[str, str | None]] = names
          """What is being imported from the module.
  
          Each entry is a :class:`tuple` of the name being imported,
          and the alias that the name is assigned to (if any).
          """
  
          # TODO When is 'level' None?
          self.level: int | None = level  # can be None
          """The level of relative import.
  
          Essentially this is the number of dots in the import.
          This is always 0 for absolute imports.
          """
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
  
  class Attribute(NodeNG):
      """Class representing an :class:`ast.Attribute` node."""
  
      _astroid_fields = ("expr",)
      _other_fields = ("attrname",)
  
      @decorators.deprecate_default_argument_values(attrname="str")
      def __init__(
          self,
          attrname: str | None = None,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param attrname: The name of the attribute.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.expr: NodeNG | None = None
          """The name that this node represents.
  
          :type: Name or None
          """
  
          self.attrname: str | None = attrname
          """The name of the attribute."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, expr: NodeNG | None = None) -> None:
          """Do some setup after initialisation.
  
          :param expr: The name that this node represents.
          :type expr: Name or None
          """
          self.expr = expr
  
      def get_children(self):
          yield self.expr
  
  
  class Global(mixins.NoChildrenMixin, Statement):
      """Class representing an :class:`ast.Global` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('global a_global')
      >>> node
      <Global l.1 at 0x7f23b2e9de10>
      """
  
      _other_fields = ("names",)
  
      def __init__(
          self,
          names: list[str],
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param names: The names being declared as global.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.names: list[str] = names
          """The names being declared as global."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def _infer_name(self, frame, name):
          return name
  
  
  class If(mixins.MultiLineBlockMixin, mixins.BlockRangeMixIn, Statement):
      """Class representing an :class:`ast.If` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('if condition: print(True)')
      >>> node
      <If l.1 at 0x7f23b2e9dd30>
      """
  
      _astroid_fields = ("test", "body", "orelse")
      _multi_line_block_fields = ("body", "orelse")
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.test: NodeNG | None = None
          """The condition that the statement tests."""
  
          self.body: list[NodeNG] = []
          """The contents of the block."""
  
          self.orelse: list[NodeNG] = []
          """The contents of the ``else`` block."""
  
          self.is_orelse: bool = False
          """Whether the if-statement is the orelse-block of another if statement."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self,
          test: NodeNG | None = None,
          body: list[NodeNG] | None = None,
          orelse: list[NodeNG] | None = None,
      ) -> None:
          """Do some setup after initialisation.
  
          :param test: The condition that the statement tests.
  
          :param body: The contents of the block.
  
          :param orelse: The contents of the ``else`` block.
          """
          self.test = test
          if body is not None:
              self.body = body
          if orelse is not None:
              self.orelse = orelse
          if isinstance(self.parent, If) and self in self.parent.orelse:
              self.is_orelse = True
  
      @cached_property
      def blockstart_tolineno(self):
          """The line on which the beginning of this block ends.
  
          :type: int
          """
          return self.test.tolineno
  
      def block_range(self, lineno):
          """Get a range from the given line number to where this node ends.
  
          :param lineno: The line number to start the range at.
          :type lineno: int
  
          :returns: The range of line numbers that this node belongs to,
              starting at the given line number.
          :rtype: tuple(int, int)
          """
          if lineno == self.body[0].fromlineno:
              return lineno, lineno
          if lineno <= self.body[-1].tolineno:
              return lineno, self.body[-1].tolineno
          return self._elsed_block_range(lineno, self.orelse, self.body[0].fromlineno - 1)
  
      def get_children(self):
          yield self.test
  
          yield from self.body
          yield from self.orelse
  
      def has_elif_block(self):
          return len(self.orelse) == 1 and isinstance(self.orelse[0], If)
  
      def _get_yield_nodes_skip_lambdas(self):
          """An If node can contain a Yield node in the test"""
          yield from self.test._get_yield_nodes_skip_lambdas()
          yield from super()._get_yield_nodes_skip_lambdas()
  
      def is_sys_guard(self) -> bool:
          """Return True if IF stmt is a sys.version_info guard.
  
          >>> import astroid
          >>> node = astroid.extract_node('''
          import sys
          if sys.version_info > (3, 8):
              from typing import Literal
          else:
              from typing_extensions import Literal
          ''')
          >>> node.is_sys_guard()
          True
          """
          warnings.warn(
              "The 'is_sys_guard' function is deprecated and will be removed in astroid 3.0.0 "
              "It has been moved to pylint and can be imported from 'pylint.checkers.utils' "
              "starting with pylint 2.12",
              DeprecationWarning,
          )
          if isinstance(self.test, Compare):
              value = self.test.left
              if isinstance(value, Subscript):
                  value = value.value
              if isinstance(value, Attribute) and value.as_string() == "sys.version_info":
                  return True
  
          return False
  
      def is_typing_guard(self) -> bool:
          """Return True if IF stmt is a typing guard.
  
          >>> import astroid
          >>> node = astroid.extract_node('''
          from typing import TYPE_CHECKING
          if TYPE_CHECKING:
              from xyz import a
          ''')
          >>> node.is_typing_guard()
          True
          """
          warnings.warn(
              "The 'is_typing_guard' function is deprecated and will be removed in astroid 3.0.0 "
              "It has been moved to pylint and can be imported from 'pylint.checkers.utils' "
              "starting with pylint 2.12",
              DeprecationWarning,
          )
          return isinstance(
              self.test, (Name, Attribute)
          ) and self.test.as_string().endswith("TYPE_CHECKING")
  
  
  class IfExp(NodeNG):
      """Class representing an :class:`ast.IfExp` node.
      >>> import astroid
      >>> node = astroid.extract_node('value if condition else other')
      >>> node
      <IfExp l.1 at 0x7f23b2e9dbe0>
      """
  
      _astroid_fields = ("test", "body", "orelse")
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.test: NodeNG | None = None
          """The condition that the statement tests."""
  
          self.body: NodeNG | None = None
          """The contents of the block."""
  
          self.orelse: NodeNG | None = None
          """The contents of the ``else`` block."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self,
          test: NodeNG | None = None,
          body: NodeNG | None = None,
          orelse: NodeNG | None = None,
      ) -> None:
          """Do some setup after initialisation.
  
          :param test: The condition that the statement tests.
  
          :param body: The contents of the block.
  
          :param orelse: The contents of the ``else`` block.
          """
          self.test = test
          self.body = body
          self.orelse = orelse
  
      def get_children(self):
          yield self.test
          yield self.body
          yield self.orelse
  
      def op_left_associative(self):
          # `1 if True else 2 if False else 3` is parsed as
          # `1 if True else (2 if False else 3)`
          return False
  
  
  class Import(mixins.NoChildrenMixin, mixins.ImportFromMixin, Statement):
      """Class representing an :class:`ast.Import` node.
      >>> import astroid
      >>> node = astroid.extract_node('import astroid')
      >>> node
      <Import l.1 at 0x7f23b2e4e5c0>
      """
  
      _other_fields = ("names",)
  
      @decorators.deprecate_default_argument_values(names="list[tuple[str, str | None]]")
      def __init__(
          self,
          names: list[tuple[str, str | None]] | None = None,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param names: The names being imported.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.names: list[tuple[str, str | None]] = names or []
          """The names being imported.
  
          Each entry is a :class:`tuple` of the name being imported,
          and the alias that the name is assigned to (if any).
          """
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
  
  class Index(NodeNG):
      """Class representing an :class:`ast.Index` node.
  
      An :class:`Index` is a simple subscript.
  
      Deprecated since v2.6.0 - Now part of the :class:`Subscript` node.
      Will be removed with the release of v2.7.0
      """
  
  
  class Keyword(NodeNG):
      """Class representing an :class:`ast.keyword` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('function(a_kwarg=True)')
      >>> node
      <Call l.1 at 0x7f23b2e9e320>
      >>> node.keywords
      [<Keyword l.1 at 0x7f23b2e9e9b0>]
      """
  
      _astroid_fields = ("value",)
      _other_fields = ("arg",)
  
      def __init__(
          self,
          arg: str | None = None,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param arg: The argument being assigned to.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.arg: str | None = arg  # can be None
          """The argument being assigned to."""
  
          self.value: NodeNG | None = None
          """The value being assigned to the keyword argument."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, value: NodeNG | None = None) -> None:
          """Do some setup after initialisation.
  
          :param value: The value being assigned to the keyword argument.
          """
          self.value = value
  
      def get_children(self):
          yield self.value
  
  
  class List(BaseContainer):
      """Class representing an :class:`ast.List` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('[1, 2, 3]')
      >>> node
      <List.list l.1 at 0x7f23b2e9e128>
      """
  
      _other_fields = ("ctx",)
  
      def __init__(
          self,
          ctx: Context | None = None,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param ctx: Whether the list is assigned to or loaded from.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.ctx: Context | None = ctx
          """Whether the list is assigned to or loaded from."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      assigned_stmts: ClassVar[AssignedStmtsCall[List]]
      """Returns the assigned statement (non inferred) according to the assignment type.
      See astroid/protocols.py for actual implementation.
      """
  
      def pytype(self):
          """Get the name of the type that this node represents.
  
          :returns: The name of the type.
          :rtype: str
          """
          return "builtins.list"
  
      def getitem(self, index, context=None):
          """Get an item from this node.
  
          :param index: The node to use as a subscript index.
          :type index: Const or Slice
          """
          return _container_getitem(self, self.elts, index, context=context)
  
  
  class Nonlocal(mixins.NoChildrenMixin, Statement):
      """Class representing an :class:`ast.Nonlocal` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
      def function():
          nonlocal var
      ''')
      >>> node
      <FunctionDef.function l.2 at 0x7f23b2e9e208>
      >>> node.body[0]
      <Nonlocal l.3 at 0x7f23b2e9e908>
      """
  
      _other_fields = ("names",)
  
      def __init__(
          self,
          names: list[str],
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param names: The names being declared as not local.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.names: list[str] = names
          """The names being declared as not local."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def _infer_name(self, frame, name):
          return name
  
  
  class Pass(mixins.NoChildrenMixin, Statement):
      """Class representing an :class:`ast.Pass` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('pass')
      >>> node
      <Pass l.1 at 0x7f23b2e9e748>
      """
  
  
  class Raise(Statement):
      """Class representing an :class:`ast.Raise` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('raise RuntimeError("Something bad happened!")')
      >>> node
      <Raise l.1 at 0x7f23b2e9e828>
      """
  
      _astroid_fields = ("exc", "cause")
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.exc: NodeNG | None = None  # can be None
          """What is being raised."""
  
          self.cause: NodeNG | None = None  # can be None
          """The exception being used to raise this one."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self,
          exc: NodeNG | None = None,
          cause: NodeNG | None = None,
      ) -> None:
          """Do some setup after initialisation.
  
          :param exc: What is being raised.
  
          :param cause: The exception being used to raise this one.
          """
          self.exc = exc
          self.cause = cause
  
      def raises_not_implemented(self):
          """Check if this node raises a :class:`NotImplementedError`.
  
          :returns: True if this node raises a :class:`NotImplementedError`,
              False otherwise.
          :rtype: bool
          """
          if not self.exc:
              return False
          return any(
              name.name == "NotImplementedError" for name in self.exc._get_name_nodes()
          )
  
      def get_children(self):
          if self.exc is not None:
              yield self.exc
  
          if self.cause is not None:
              yield self.cause
  
  
  class Return(Statement):
      """Class representing an :class:`ast.Return` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('return True')
      >>> node
      <Return l.1 at 0x7f23b8211908>
      """
  
      _astroid_fields = ("value",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.value: NodeNG | None = None  # can be None
          """The value being returned."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, value: NodeNG | None = None) -> None:
          """Do some setup after initialisation.
  
          :param value: The value being returned.
          """
          self.value = value
  
      def get_children(self):
          if self.value is not None:
              yield self.value
  
      def is_tuple_return(self):
          return isinstance(self.value, Tuple)
  
      def _get_return_nodes_skip_functions(self):
          yield self
  
  
  class Set(BaseContainer):
      """Class representing an :class:`ast.Set` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('{1, 2, 3}')
      >>> node
      <Set.set l.1 at 0x7f23b2e71d68>
      """
  
      def pytype(self):
          """Get the name of the type that this node represents.
  
          :returns: The name of the type.
          :rtype: str
          """
          return "builtins.set"
  
  
  class Slice(NodeNG):
      """Class representing an :class:`ast.Slice` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('things[1:3]')
      >>> node
      <Subscript l.1 at 0x7f23b2e71f60>
      >>> node.slice
      <Slice l.1 at 0x7f23b2e71e80>
      """
  
      _astroid_fields = ("lower", "upper", "step")
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.lower: NodeNG | None = None  # can be None
          """The lower index in the slice."""
  
          self.upper: NodeNG | None = None  # can be None
          """The upper index in the slice."""
  
          self.step: NodeNG | None = None  # can be None
          """The step to take between indexes."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self,
          lower: NodeNG | None = None,
          upper: NodeNG | None = None,
          step: NodeNG | None = None,
      ) -> None:
          """Do some setup after initialisation.
  
          :param lower: The lower index in the slice.
  
          :param upper: The upper index in the slice.
  
          :param step: The step to take between index.
          """
          self.lower = lower
          self.upper = upper
          self.step = step
  
      def _wrap_attribute(self, attr):
          """Wrap the empty attributes of the Slice in a Const node."""
          if not attr:
              const = const_factory(attr)
              const.parent = self
              return const
          return attr
  
      @cached_property
      def _proxied(self):
          builtins = AstroidManager().builtins_module
          return builtins.getattr("slice")[0]
  
      def pytype(self):
          """Get the name of the type that this node represents.
  
          :returns: The name of the type.
          :rtype: str
          """
          return "builtins.slice"
  
      def igetattr(self, attrname, context=None):
          """Infer the possible values of the given attribute on the slice.
  
          :param attrname: The name of the attribute to infer.
          :type attrname: str
  
          :returns: The inferred possible values.
          :rtype: iterable(NodeNG)
          """
          if attrname == "start":
              yield self._wrap_attribute(self.lower)
          elif attrname == "stop":
              yield self._wrap_attribute(self.upper)
          elif attrname == "step":
              yield self._wrap_attribute(self.step)
          else:
              yield from self.getattr(attrname, context=context)
  
      def getattr(self, attrname, context=None):
          return self._proxied.getattr(attrname, context)
  
      def get_children(self):
          if self.lower is not None:
              yield self.lower
  
          if self.upper is not None:
              yield self.upper
  
          if self.step is not None:
              yield self.step
  
  
  class Starred(mixins.ParentAssignTypeMixin, NodeNG):
      """Class representing an :class:`ast.Starred` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('*args')
      >>> node
      <Starred l.1 at 0x7f23b2e41978>
      """
  
      _astroid_fields = ("value",)
      _other_fields = ("ctx",)
  
      def __init__(
          self,
          ctx: Context | None = None,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param ctx: Whether the list is assigned to or loaded from.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.value: NodeNG | None = None
          """What is being unpacked."""
  
          self.ctx: Context | None = ctx
          """Whether the starred item is assigned to or loaded from."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, value: NodeNG | None = None) -> None:
          """Do some setup after initialisation.
  
          :param value: What is being unpacked.
          """
          self.value = value
  
      assigned_stmts: ClassVar[AssignedStmtsCall[Starred]]
      """Returns the assigned statement (non inferred) according to the assignment type.
      See astroid/protocols.py for actual implementation.
      """
  
      def get_children(self):
          yield self.value
  
  
  class Subscript(NodeNG):
      """Class representing an :class:`ast.Subscript` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('things[1:3]')
      >>> node
      <Subscript l.1 at 0x7f23b2e71f60>
      """
  
      _astroid_fields = ("value", "slice")
      _other_fields = ("ctx",)
  
      def __init__(
          self,
          ctx: Context | None = None,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param ctx: Whether the subscripted item is assigned to or loaded from.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.value: NodeNG | None = None
          """What is being indexed."""
  
          self.slice: NodeNG | None = None
          """The slice being used to lookup."""
  
          self.ctx: Context | None = ctx
          """Whether the subscripted item is assigned to or loaded from."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      # pylint: disable=redefined-builtin; had to use the same name as builtin ast module.
      def postinit(
          self, value: NodeNG | None = None, slice: NodeNG | None = None
      ) -> None:
          """Do some setup after initialisation.
  
          :param value: What is being indexed.
  
          :param slice: The slice being used to lookup.
          """
          self.value = value
          self.slice = slice
  
      def get_children(self):
          yield self.value
          yield self.slice
  
  
  class TryExcept(mixins.MultiLineBlockMixin, mixins.BlockRangeMixIn, Statement):
      """Class representing an :class:`ast.TryExcept` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
          try:
              do_something()
          except Exception as error:
              print("Error!")
          ''')
      >>> node
      <TryExcept l.2 at 0x7f23b2e9d908>
      """
  
      _astroid_fields = ("body", "handlers", "orelse")
      _multi_line_block_fields = ("body", "handlers", "orelse")
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.body: list[NodeNG] = []
          """The contents of the block to catch exceptions from."""
  
          self.handlers: list[ExceptHandler] = []
          """The exception handlers."""
  
          self.orelse: list[NodeNG] = []
          """The contents of the ``else`` block."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self,
          body: list[NodeNG] | None = None,
          handlers: list[ExceptHandler] | None = None,
          orelse: list[NodeNG] | None = None,
      ) -> None:
          """Do some setup after initialisation.
  
          :param body: The contents of the block to catch exceptions from.
  
          :param handlers: The exception handlers.
  
          :param orelse: The contents of the ``else`` block.
          """
          if body is not None:
              self.body = body
          if handlers is not None:
              self.handlers = handlers
          if orelse is not None:
              self.orelse = orelse
  
      def _infer_name(self, frame, name):
          return name
  
      def block_range(self, lineno):
          """Get a range from the given line number to where this node ends.
  
          :param lineno: The line number to start the range at.
          :type lineno: int
  
          :returns: The range of line numbers that this node belongs to,
              starting at the given line number.
          :rtype: tuple(int, int)
          """
          last = None
          for exhandler in self.handlers:
              if exhandler.type and lineno == exhandler.type.fromlineno:
                  return lineno, lineno
              if exhandler.body[0].fromlineno <= lineno <= exhandler.body[-1].tolineno:
                  return lineno, exhandler.body[-1].tolineno
              if last is None:
                  last = exhandler.body[0].fromlineno - 1
          return self._elsed_block_range(lineno, self.orelse, last)
  
      def get_children(self):
          yield from self.body
  
          yield from self.handlers or ()
          yield from self.orelse or ()
  
  
  class TryFinally(mixins.MultiLineBlockMixin, mixins.BlockRangeMixIn, Statement):
      """Class representing an :class:`ast.TryFinally` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
      try:
          do_something()
      except Exception as error:
          print("Error!")
      finally:
          print("Cleanup!")
      ''')
      >>> node
      <TryFinally l.2 at 0x7f23b2e41d68>
      """
  
      _astroid_fields = ("body", "finalbody")
      _multi_line_block_fields = ("body", "finalbody")
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.body: list[NodeNG | TryExcept] = []
          """The try-except that the finally is attached to."""
  
          self.finalbody: list[NodeNG] = []
          """The contents of the ``finally`` block."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self,
          body: list[NodeNG | TryExcept] | None = None,
          finalbody: list[NodeNG] | None = None,
      ) -> None:
          """Do some setup after initialisation.
  
          :param body: The try-except that the finally is attached to.
  
          :param finalbody: The contents of the ``finally`` block.
          """
          if body is not None:
              self.body = body
          if finalbody is not None:
              self.finalbody = finalbody
  
      def block_range(self, lineno):
          """Get a range from the given line number to where this node ends.
  
          :param lineno: The line number to start the range at.
          :type lineno: int
  
          :returns: The range of line numbers that this node belongs to,
              starting at the given line number.
          :rtype: tuple(int, int)
          """
          child = self.body[0]
          # py2.5 try: except: finally:
          if (
              isinstance(child, TryExcept)
              and child.fromlineno == self.fromlineno
              and child.tolineno >= lineno > self.fromlineno
          ):
              return child.block_range(lineno)
          return self._elsed_block_range(lineno, self.finalbody)
  
      def get_children(self):
          yield from self.body
          yield from self.finalbody
  
  
  class Tuple(BaseContainer):
      """Class representing an :class:`ast.Tuple` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('(1, 2, 3)')
      >>> node
      <Tuple.tuple l.1 at 0x7f23b2e41780>
      """
  
      _other_fields = ("ctx",)
  
      def __init__(
          self,
          ctx: Context | None = None,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param ctx: Whether the tuple is assigned to or loaded from.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.ctx: Context | None = ctx
          """Whether the tuple is assigned to or loaded from."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      assigned_stmts: ClassVar[AssignedStmtsCall[Tuple]]
      """Returns the assigned statement (non inferred) according to the assignment type.
      See astroid/protocols.py for actual implementation.
      """
  
      def pytype(self):
          """Get the name of the type that this node represents.
  
          :returns: The name of the type.
          :rtype: str
          """
          return "builtins.tuple"
  
      def getitem(self, index, context=None):
          """Get an item from this node.
  
          :param index: The node to use as a subscript index.
          :type index: Const or Slice
          """
          return _container_getitem(self, self.elts, index, context=context)
  
  
  class UnaryOp(NodeNG):
      """Class representing an :class:`ast.UnaryOp` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('-5')
      >>> node
      <UnaryOp l.1 at 0x7f23b2e4e198>
      """
  
      _astroid_fields = ("operand",)
      _other_fields = ("op",)
  
      @decorators.deprecate_default_argument_values(op="str")
      def __init__(
          self,
          op: str | None = None,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param op: The operator.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.op: str | None = op
          """The operator."""
  
          self.operand: NodeNG | None = None
          """What the unary operator is applied to."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, operand: NodeNG | None = None) -> None:
          """Do some setup after initialisation.
  
          :param operand: What the unary operator is applied to.
          """
          self.operand = operand
  
      # This is set by inference.py
      def _infer_unaryop(self, context=None):
          raise NotImplementedError
  
      def type_errors(self, context=None):
          """Get a list of type errors which can occur during inference.
  
          Each TypeError is represented by a :class:`BadBinaryOperationMessage`,
          which holds the original exception.
  
          :returns: The list of possible type errors.
          :rtype: list(BadBinaryOperationMessage)
          """
          try:
              results = self._infer_unaryop(context=context)
              return [
                  result
                  for result in results
                  if isinstance(result, util.BadUnaryOperationMessage)
              ]
          except InferenceError:
              return []
  
      def get_children(self):
          yield self.operand
  
      def op_precedence(self):
          if self.op == "not":
              return OP_PRECEDENCE[self.op]
  
          return super().op_precedence()
  
  
  class While(mixins.MultiLineBlockMixin, mixins.BlockRangeMixIn, Statement):
      """Class representing an :class:`ast.While` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
      while condition():
          print("True")
      ''')
      >>> node
      <While l.2 at 0x7f23b2e4e390>
      """
  
      _astroid_fields = ("test", "body", "orelse")
      _multi_line_block_fields = ("body", "orelse")
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.test: NodeNG | None = None
          """The condition that the loop tests."""
  
          self.body: list[NodeNG] = []
          """The contents of the loop."""
  
          self.orelse: list[NodeNG] = []
          """The contents of the ``else`` block."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self,
          test: NodeNG | None = None,
          body: list[NodeNG] | None = None,
          orelse: list[NodeNG] | None = None,
      ) -> None:
          """Do some setup after initialisation.
  
          :param test: The condition that the loop tests.
  
          :param body: The contents of the loop.
  
          :param orelse: The contents of the ``else`` block.
          """
          self.test = test
          if body is not None:
              self.body = body
          if orelse is not None:
              self.orelse = orelse
  
      @cached_property
      def blockstart_tolineno(self):
          """The line on which the beginning of this block ends.
  
          :type: int
          """
          return self.test.tolineno
  
      def block_range(self, lineno):
          """Get a range from the given line number to where this node ends.
  
          :param lineno: The line number to start the range at.
          :type lineno: int
  
          :returns: The range of line numbers that this node belongs to,
              starting at the given line number.
          :rtype: tuple(int, int)
          """
          return self._elsed_block_range(lineno, self.orelse)
  
      def get_children(self):
          yield self.test
  
          yield from self.body
          yield from self.orelse
  
      def _get_yield_nodes_skip_lambdas(self):
          """A While node can contain a Yield node in the test"""
          yield from self.test._get_yield_nodes_skip_lambdas()
          yield from super()._get_yield_nodes_skip_lambdas()
  
  
  class With(
      mixins.MultiLineBlockMixin,
      mixins.BlockRangeMixIn,
      mixins.AssignTypeMixin,
      Statement,
  ):
      """Class representing an :class:`ast.With` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
      with open(file_path) as file_:
          print(file_.read())
      ''')
      >>> node
      <With l.2 at 0x7f23b2e4e710>
      """
  
      _astroid_fields = ("items", "body")
      _other_other_fields = ("type_annotation",)
      _multi_line_block_fields = ("body",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.items: list[tuple[NodeNG, NodeNG | None]] = []
          """The pairs of context managers and the names they are assigned to."""
  
          self.body: list[NodeNG] = []
          """The contents of the ``with`` block."""
  
          self.type_annotation: NodeNG | None = None  # can be None
          """If present, this will contain the type annotation passed by a type comment"""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self,
          items: list[tuple[NodeNG, NodeNG | None]] | None = None,
          body: list[NodeNG] | None = None,
          type_annotation: NodeNG | None = None,
      ) -> None:
          """Do some setup after initialisation.
  
          :param items: The pairs of context managers and the names
              they are assigned to.
  
          :param body: The contents of the ``with`` block.
          """
          if items is not None:
              self.items = items
          if body is not None:
              self.body = body
          self.type_annotation = type_annotation
  
      assigned_stmts: ClassVar[AssignedStmtsCall[With]]
      """Returns the assigned statement (non inferred) according to the assignment type.
      See astroid/protocols.py for actual implementation.
      """
  
      @cached_property
      def blockstart_tolineno(self):
          """The line on which the beginning of this block ends.
  
          :type: int
          """
          return self.items[-1][0].tolineno
  
      def get_children(self):
          """Get the child nodes below this node.
  
          :returns: The children.
          :rtype: iterable(NodeNG)
          """
          for expr, var in self.items:
              yield expr
              if var:
                  yield var
          yield from self.body
  
  
  class AsyncWith(With):
      """Asynchronous ``with`` built with the ``async`` keyword."""
  
  
  class Yield(NodeNG):
      """Class representing an :class:`ast.Yield` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('yield True')
      >>> node
      <Yield l.1 at 0x7f23b2e4e5f8>
      """
  
      _astroid_fields = ("value",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.value: NodeNG | None = None  # can be None
          """The value to yield."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, value: NodeNG | None = None) -> None:
          """Do some setup after initialisation.
  
          :param value: The value to yield.
          """
          self.value = value
  
      def get_children(self):
          if self.value is not None:
              yield self.value
  
      def _get_yield_nodes_skip_lambdas(self):
          yield self
  
  
  class YieldFrom(Yield):  # TODO value is required, not optional
      """Class representing an :class:`ast.YieldFrom` node."""
  
  
  class DictUnpack(mixins.NoChildrenMixin, NodeNG):
      """Represents the unpacking of dicts into dicts using :pep:`448`."""
  
  
  class FormattedValue(NodeNG):
      """Class representing an :class:`ast.FormattedValue` node.
  
      Represents a :pep:`498` format string.
  
      >>> import astroid
      >>> node = astroid.extract_node('f"Format {type_}"')
      >>> node
      <JoinedStr l.1 at 0x7f23b2e4ed30>
      >>> node.values
      [<Const.str l.1 at 0x7f23b2e4eda0>, <FormattedValue l.1 at 0x7f23b2e4edd8>]
      """
  
      _astroid_fields = ("value", "format_spec")
      _other_fields = ("conversion",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.value: NodeNG
          """The value to be formatted into the string."""
  
          self.conversion: int | None = None  # can be None
          """The type of formatting to be applied to the value.
  
          .. seealso::
              :class:`ast.FormattedValue`
          """
  
          self.format_spec: NodeNG | None = None  # can be None
          """The formatting to be applied to the value.
  
          .. seealso::
              :class:`ast.FormattedValue`
  
          :type: JoinedStr or None
          """
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self,
          value: NodeNG,
          conversion: int | None = None,
          format_spec: NodeNG | None = None,
      ) -> None:
          """Do some setup after initialisation.
  
          :param value: The value to be formatted into the string.
  
          :param conversion: The type of formatting to be applied to the value.
  
          :param format_spec: The formatting to be applied to the value.
          :type format_spec: JoinedStr or None
          """
          self.value = value
          self.conversion = conversion
          self.format_spec = format_spec
  
      def get_children(self):
          yield self.value
  
          if self.format_spec is not None:
              yield self.format_spec
  
  
  class JoinedStr(NodeNG):
      """Represents a list of string expressions to be joined.
  
      >>> import astroid
      >>> node = astroid.extract_node('f"Format {type_}"')
      >>> node
      <JoinedStr l.1 at 0x7f23b2e4ed30>
      """
  
      _astroid_fields = ("values",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.values: list[NodeNG] = []
          """The string expressions to be joined.
  
          :type: list(FormattedValue or Const)
          """
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, values: list[NodeNG] | None = None) -> None:
          """Do some setup after initialisation.
  
          :param value: The string expressions to be joined.
  
          :type: list(FormattedValue or Const)
          """
          if values is not None:
              self.values = values
  
      def get_children(self):
          yield from self.values
  
  
  class NamedExpr(mixins.AssignTypeMixin, NodeNG):
      """Represents the assignment from the assignment expression
  
      >>> import astroid
      >>> module = astroid.parse('if a := 1: pass')
      >>> module.body[0].test
      <NamedExpr l.1 at 0x7f23b2e4ed30>
      """
  
      _astroid_fields = ("target", "value")
  
      optional_assign = True
      """Whether this node optionally assigns a variable.
  
      Since NamedExpr are not always called they do not always assign."""
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.target: NodeNG
          """The assignment target
  
          :type: Name
          """
  
          self.value: NodeNG
          """The value that gets assigned in the expression"""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, target: NodeNG, value: NodeNG) -> None:
          self.target = target
          self.value = value
  
      assigned_stmts: ClassVar[AssignedStmtsCall[NamedExpr]]
      """Returns the assigned statement (non inferred) according to the assignment type.
      See astroid/protocols.py for actual implementation.
      """
  
      def frame(
          self, *, future: Literal[None, True] = None
      ) -> nodes.FunctionDef | nodes.Module | nodes.ClassDef | nodes.Lambda:
          """The first parent frame node.
  
          A frame node is a :class:`Module`, :class:`FunctionDef`,
          or :class:`ClassDef`.
  
          :returns: The first parent frame node.
          """
          if not self.parent:
              raise ParentMissingError(target=self)
  
          # For certain parents NamedExpr evaluate to the scope of the parent
          if isinstance(self.parent, (Arguments, Keyword, Comprehension)):
              if not self.parent.parent:
                  raise ParentMissingError(target=self.parent)
              if not self.parent.parent.parent:
                  raise ParentMissingError(target=self.parent.parent)
              return self.parent.parent.parent.frame(future=True)
  
          return self.parent.frame(future=True)
  
      def scope(self) -> LocalsDictNodeNG:
          """The first parent node defining a new scope.
          These can be Module, FunctionDef, ClassDef, Lambda, or GeneratorExp nodes.
  
          :returns: The first parent scope node.
          """
          if not self.parent:
              raise ParentMissingError(target=self)
  
          # For certain parents NamedExpr evaluate to the scope of the parent
          if isinstance(self.parent, (Arguments, Keyword, Comprehension)):
              if not self.parent.parent:
                  raise ParentMissingError(target=self.parent)
              if not self.parent.parent.parent:
                  raise ParentMissingError(target=self.parent.parent)
              return self.parent.parent.parent.scope()
  
          return self.parent.scope()
  
      def set_local(self, name: str, stmt: AssignName) -> None:
          """Define that the given name is declared in the given statement node.
          NamedExpr's in Arguments, Keyword or Comprehension are evaluated in their
          parent's parent scope. So we add to their frame's locals.
  
          .. seealso:: :meth:`scope`
  
          :param name: The name that is being defined.
  
          :param stmt: The statement that defines the given name.
          """
          self.frame(future=True).set_local(name, stmt)
  
  
  class Unknown(mixins.AssignTypeMixin, NodeNG):
      """This node represents a node in a constructed AST where
      introspection is not possible.  At the moment, it's only used in
      the args attribute of FunctionDef nodes where function signature
      introspection failed.
      """
  
      name = "Unknown"
  
      def qname(self):
          return "Unknown"
  
      def _infer(self, context=None, **kwargs):
          """Inference on an Unknown node immediately terminates."""
          yield util.Uninferable
  
  
  class EvaluatedObject(NodeNG):
      """Contains an object that has already been inferred
  
      This class is useful to pre-evaluate a particular node,
      with the resulting class acting as the non-evaluated node.
      """
  
      name = "EvaluatedObject"
      _astroid_fields = ("original",)
      _other_fields = ("value",)
  
      def __init__(
          self, original: NodeNG, value: NodeNG | type[util.Uninferable]
      ) -> None:
          self.original: NodeNG = original
          """The original node that has already been evaluated"""
  
          self.value: NodeNG | type[util.Uninferable] = value
          """The inferred value"""
  
          super().__init__(
              lineno=self.original.lineno,
              col_offset=self.original.col_offset,
              parent=self.original.parent,
          )
  
      def _infer(
          self, context: InferenceContext | None = None
      ) -> Iterator[NodeNG | type[util.Uninferable]]:
          yield self.value
  
  
  # Pattern matching #######################################################
  
  
  class Match(Statement):
      """Class representing a :class:`ast.Match` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
      match x:
          case 200:
              ...
          case _:
              ...
      ''')
      >>> node
      <Match l.2 at 0x10c24e170>
      """
  
      _astroid_fields = ("subject", "cases")
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          self.subject: NodeNG
          self.cases: list[MatchCase]
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self,
          *,
          subject: NodeNG,
          cases: list[MatchCase],
      ) -> None:
          self.subject = subject
          self.cases = cases
  
  
  class Pattern(NodeNG):
      """Base class for all Pattern nodes."""
  
  
  class MatchCase(mixins.MultiLineBlockMixin, NodeNG):
      """Class representing a :class:`ast.match_case` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
      match x:
          case 200:
              ...
      ''')
      >>> node.cases[0]
      <MatchCase l.3 at 0x10c24e590>
      """
  
      _astroid_fields = ("pattern", "guard", "body")
      _multi_line_block_fields = ("body",)
  
      lineno: None
      col_offset: None
      end_lineno: None
      end_col_offset: None
  
      def __init__(self, *, parent: NodeNG | None = None) -> None:
          self.pattern: Pattern
          self.guard: NodeNG | None
          self.body: list[NodeNG]
          super().__init__(parent=parent)
  
      def postinit(
          self,
          *,
          pattern: Pattern,
          guard: NodeNG | None,
          body: list[NodeNG],
      ) -> None:
          self.pattern = pattern
          self.guard = guard
          self.body = body
  
  
  class MatchValue(Pattern):
      """Class representing a :class:`ast.MatchValue` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
      match x:
          case 200:
              ...
      ''')
      >>> node.cases[0].pattern
      <MatchValue l.3 at 0x10c24e200>
      """
  
      _astroid_fields = ("value",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          self.value: NodeNG
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, *, value: NodeNG) -> None:
          self.value = value
  
  
  class MatchSingleton(Pattern):
      """Class representing a :class:`ast.MatchSingleton` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
      match x:
          case True:
              ...
          case False:
              ...
          case None:
              ...
      ''')
      >>> node.cases[0].pattern
      <MatchSingleton l.3 at 0x10c2282e0>
      >>> node.cases[1].pattern
      <MatchSingleton l.5 at 0x10c228af0>
      >>> node.cases[2].pattern
      <MatchSingleton l.7 at 0x10c229f90>
      """
  
      _other_fields = ("value",)
  
      def __init__(
          self,
          *,
          value: Literal[True, False, None],
          lineno: int | None = None,
          col_offset: int | None = None,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
          parent: NodeNG | None = None,
      ) -> None:
          self.value = value
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
  
  class MatchSequence(Pattern):
      """Class representing a :class:`ast.MatchSequence` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
      match x:
          case [1, 2]:
              ...
          case (1, 2, *_):
              ...
      ''')
      >>> node.cases[0].pattern
      <MatchSequence l.3 at 0x10ca80d00>
      >>> node.cases[1].pattern
      <MatchSequence l.5 at 0x10ca80b20>
      """
  
      _astroid_fields = ("patterns",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          self.patterns: list[Pattern]
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, *, patterns: list[Pattern]) -> None:
          self.patterns = patterns
  
  
  class MatchMapping(mixins.AssignTypeMixin, Pattern):
      """Class representing a :class:`ast.MatchMapping` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
      match x:
          case {1: "Hello", 2: "World", 3: _, **rest}:
              ...
      ''')
      >>> node.cases[0].pattern
      <MatchMapping l.3 at 0x10c8a8850>
      """
  
      _astroid_fields = ("keys", "patterns", "rest")
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          self.keys: list[NodeNG]
          self.patterns: list[Pattern]
          self.rest: AssignName | None
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self,
          *,
          keys: list[NodeNG],
          patterns: list[Pattern],
          rest: AssignName | None,
      ) -> None:
          self.keys = keys
          self.patterns = patterns
          self.rest = rest
  
      assigned_stmts: ClassVar[
          Callable[
              [
                  MatchMapping,
                  AssignName,
                  InferenceContext | None,
                  None,
              ],
              Generator[NodeNG, None, None],
          ]
      ]
      """Returns the assigned statement (non inferred) according to the assignment type.
      See astroid/protocols.py for actual implementation.
      """
  
  
  class MatchClass(Pattern):
      """Class representing a :class:`ast.MatchClass` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
      match x:
          case Point2D(0, 0):
              ...
          case Point3D(x=0, y=0, z=0):
              ...
      ''')
      >>> node.cases[0].pattern
      <MatchClass l.3 at 0x10ca83940>
      >>> node.cases[1].pattern
      <MatchClass l.5 at 0x10ca80880>
      """
  
      _astroid_fields = ("cls", "patterns", "kwd_patterns")
      _other_fields = ("kwd_attrs",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          self.cls: NodeNG
          self.patterns: list[Pattern]
          self.kwd_attrs: list[str]
          self.kwd_patterns: list[Pattern]
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self,
          *,
          cls: NodeNG,
          patterns: list[Pattern],
          kwd_attrs: list[str],
          kwd_patterns: list[Pattern],
      ) -> None:
          self.cls = cls
          self.patterns = patterns
          self.kwd_attrs = kwd_attrs
          self.kwd_patterns = kwd_patterns
  
  
  class MatchStar(mixins.AssignTypeMixin, Pattern):
      """Class representing a :class:`ast.MatchStar` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
      match x:
          case [1, *_]:
              ...
      ''')
      >>> node.cases[0].pattern.patterns[1]
      <MatchStar l.3 at 0x10ca809a0>
      """
  
      _astroid_fields = ("name",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          self.name: AssignName | None
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, *, name: AssignName | None) -> None:
          self.name = name
  
      assigned_stmts: ClassVar[
          Callable[
              [
                  MatchStar,
                  AssignName,
                  InferenceContext | None,
                  None,
              ],
              Generator[NodeNG, None, None],
          ]
      ]
      """Returns the assigned statement (non inferred) according to the assignment type.
      See astroid/protocols.py for actual implementation.
      """
  
  
  class MatchAs(mixins.AssignTypeMixin, Pattern):
      """Class representing a :class:`ast.MatchAs` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
      match x:
          case [1, a]:
              ...
          case {'key': b}:
              ...
          case Point2D(0, 0) as c:
              ...
          case d:
              ...
      ''')
      >>> node.cases[0].pattern.patterns[1]
      <MatchAs l.3 at 0x10d0b2da0>
      >>> node.cases[1].pattern.patterns[0]
      <MatchAs l.5 at 0x10d0b2920>
      >>> node.cases[2].pattern
      <MatchAs l.7 at 0x10d0b06a0>
      >>> node.cases[3].pattern
      <MatchAs l.9 at 0x10d09b880>
      """
  
      _astroid_fields = ("pattern", "name")
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          self.pattern: Pattern | None
          self.name: AssignName | None
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self,
          *,
          pattern: Pattern | None,
          name: AssignName | None,
      ) -> None:
          self.pattern = pattern
          self.name = name
  
      assigned_stmts: ClassVar[
          Callable[
              [
                  MatchAs,
                  AssignName,
                  InferenceContext | None,
                  None,
              ],
              Generator[NodeNG, None, None],
          ]
      ]
      """Returns the assigned statement (non inferred) according to the assignment type.
      See astroid/protocols.py for actual implementation.
      """
  
  
  class MatchOr(Pattern):
      """Class representing a :class:`ast.MatchOr` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
      match x:
          case 400 | 401 | 402:
              ...
      ''')
      >>> node.cases[0].pattern
      <MatchOr l.3 at 0x10d0b0b50>
      """
  
      _astroid_fields = ("patterns",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          self.patterns: list[Pattern]
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, *, patterns: list[Pattern]) -> None:
          self.patterns = patterns
  
  
  # constants ##############################################################
  
  CONST_CLS = {
      list: List,
      tuple: Tuple,
      dict: Dict,
      set: Set,
      type(None): Const,
      type(NotImplemented): Const,
      type(...): Const,
  }
  
  
  def _update_const_classes():
      """update constant classes, so the keys of CONST_CLS can be reused"""
      klasses = (bool, int, float, complex, str, bytes)
      for kls in klasses:
          CONST_CLS[kls] = Const
  
  
  _update_const_classes()
  
  
  def _two_step_initialization(cls, value):
      instance = cls()
      instance.postinit(value)
      return instance
  
  
  def _dict_initialization(cls, value):
      if isinstance(value, dict):
          value = tuple(value.items())
      return _two_step_initialization(cls, value)
  
  
  _CONST_CLS_CONSTRUCTORS = {
      List: _two_step_initialization,
      Tuple: _two_step_initialization,
      Dict: _dict_initialization,
      Set: _two_step_initialization,
      Const: lambda cls, value: cls(value),
  }
  
  
  def const_factory(value):
      """return an astroid node for a python value"""
      # XXX we should probably be stricter here and only consider stuff in
      # CONST_CLS or do better treatment: in case where value is not in CONST_CLS,
      # we should rather recall the builder on this value than returning an empty
      # node (another option being that const_factory shouldn't be called with something
      # not in CONST_CLS)
      assert not isinstance(value, NodeNG)
  
      # Hack for ignoring elements of a sequence
      # or a mapping, in order to avoid transforming
      # each element to an AST. This is fixed in 2.0
      # and this approach is a temporary hack.
      if isinstance(value, (list, set, tuple, dict)):
          elts = []
      else:
          elts = value
  
      try:
          initializer_cls = CONST_CLS[value.__class__]
          initializer = _CONST_CLS_CONSTRUCTORS[initializer_cls]
          return initializer(initializer_cls, elts)
      except (KeyError, AttributeError):
          node = EmptyNode()
          node.object = value
          return node
  
  ```
  --- END FILE ---
  
  Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.
  
  Every *SEARCH/REPLACE* edit must use this format:
  1. The file path
  2. The start of search block: <<<<<<< SEARCH
  3. A contiguous chunk of lines to search for in the existing source code
  4. The dividing line: =======
  5. The lines to replace into the source code
  6. The end of the replace block: >>>>>>> REPLACE
  
  Here is an example:
  
  ```python
  ### mathweb/flask/app.py
  <<<<<<< SEARCH
  from flask import Flask
  =======
  import math
  from flask import Flask
  >>>>>>> REPLACE
  ```
  
  Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
  Wrap the *SEARCH/REPLACE* edit in blocks ```python...```.
  
instance: {"FAIL_TO_PASS": "[\"tests/unittest_python3.py::Python3TC::test_unpacking_in_dict_getitem_uninferable\", \"tests/unittest_python3.py::Python3TC::test_unpacking_in_dict_getitem_with_ref\"]", "PASS_TO_PASS": "[\"tests/unittest_python3.py::Python3TC::test_annotation_as_string\", \"tests/unittest_python3.py::Python3TC::test_annotation_support\", \"tests/unittest_python3.py::Python3TC::test_as_string\", \"tests/unittest_python3.py::Python3TC::test_async_comprehensions\", \"tests/unittest_python3.py::Python3TC::test_async_comprehensions_as_string\", \"tests/unittest_python3.py::Python3TC::test_async_comprehensions_outside_coroutine\", \"tests/unittest_python3.py::Python3TC::test_format_string\", \"tests/unittest_python3.py::Python3TC::test_kwonlyargs_annotations_supper\", \"tests/unittest_python3.py::Python3TC::test_metaclass_ancestors\", \"tests/unittest_python3.py::Python3TC::test_metaclass_error\", \"tests/unittest_python3.py::Python3TC::test_metaclass_imported\", \"tests/unittest_python3.py::Python3TC::test_metaclass_multiple_keywords\", \"tests/unittest_python3.py::Python3TC::test_metaclass_yes_leak\", \"tests/unittest_python3.py::Python3TC::test_nested_unpacking_in_dicts\", \"tests/unittest_python3.py::Python3TC::test_old_syntax_works\", \"tests/unittest_python3.py::Python3TC::test_parent_metaclass\", \"tests/unittest_python3.py::Python3TC::test_simple_metaclass\", \"tests/unittest_python3.py::Python3TC::test_starred_notation\", \"tests/unittest_python3.py::Python3TC::test_underscores_in_numeral_literal\", \"tests/unittest_python3.py::Python3TC::test_unpacking_in_dict_getitem\", \"tests/unittest_python3.py::Python3TC::test_unpacking_in_dicts\", \"tests/unittest_python3.py::Python3TC::test_yield_from\", \"tests/unittest_python3.py::Python3TC::test_yield_from_as_string\", \"tests/unittest_python3.py::Python3TC::test_yield_from_is_generator\"]", "base_commit": "39c2a9805970ca57093d32bbaf0e6a63e05041d8", "created_at": "2021-10-03T15:58:07Z", "environment_setup_commit": "52f6d2d7722db383af035be929f18af5e9fe8cd5", "hints_text": "", "instance_id": "pylint-dev__astroid-1196", "patch": "diff --git a/astroid/nodes/node_classes.py b/astroid/nodes/node_classes.py\n--- a/astroid/nodes/node_classes.py\n+++ b/astroid/nodes/node_classes.py\n@@ -2346,24 +2346,33 @@ def itered(self):\n         \"\"\"\n         return [key for (key, _) in self.items]\n \n-    def getitem(self, index, context=None):\n+    def getitem(\n+        self, index: Const | Slice, context: InferenceContext | None = None\n+    ) -> NodeNG:\n         \"\"\"Get an item from this node.\n \n         :param index: The node to use as a subscript index.\n-        :type index: Const or Slice\n \n         :raises AstroidTypeError: When the given index cannot be used as a\n             subscript index, or if this node is not subscriptable.\n         :raises AstroidIndexError: If the given index does not exist in the\n             dictionary.\n         \"\"\"\n+        # pylint: disable-next=import-outside-toplevel; circular import\n+        from astroid.helpers import safe_infer\n+\n         for key, value in self.items:\n             # TODO(cpopa): no support for overriding yet, {1:2, **{1: 3}}.\n             if isinstance(key, DictUnpack):\n+                inferred_value = safe_infer(value, context)\n+                if not isinstance(inferred_value, Dict):\n+                    continue\n+\n                 try:\n-                    return value.getitem(index, context)\n+                    return inferred_value.getitem(index, context)\n                 except (AstroidTypeError, AstroidIndexError):\n                     continue\n+\n             for inferredkey in key.infer(context):\n                 if inferredkey is util.Uninferable:\n                     continue\n", "problem_statement": "getitem does not infer the actual unpacked value\nWhen trying to call `Dict.getitem()` on a context where we have a dict unpacking of anything beside a real dict, astroid currently raises an `AttributeError: 'getitem'`, which has 2 problems:\r\n\r\n- The object might be a reference against something constant, this pattern is usually seen when we have different sets of dicts that extend each other, and all of their values are inferrable. \r\n- We can have something that is uninferable, but in that case instead of an `AttributeError` I think it makes sense to raise the usual `AstroidIndexError` which is supposed to be already handled by the downstream.\r\n\r\n\r\nHere is a short reproducer;\r\n\r\n```py\r\nfrom astroid import parse\r\n\r\n\r\nsource = \"\"\"\r\nX = {\r\n    'A': 'B'\r\n}\r\n\r\nY = {\r\n    **X\r\n}\r\n\r\nKEY = 'A'\r\n\"\"\"\r\n\r\ntree = parse(source)\r\n\r\nfirst_dict = tree.body[0].value\r\nsecond_dict = tree.body[1].value\r\nkey = tree.body[2].value\r\n\r\nprint(f'{first_dict.getitem(key).value = }')\r\nprint(f'{second_dict.getitem(key).value = }')\r\n\r\n\r\n```\r\n\r\nThe current output;\r\n\r\n```\r\n $ python t1.py                                                                                                 3ms\r\nfirst_dict.getitem(key).value = 'B'\r\nTraceback (most recent call last):\r\n  File \"/home/isidentical/projects/astroid/t1.py\", line 23, in <module>\r\n    print(f'{second_dict.getitem(key).value = }')\r\n  File \"/home/isidentical/projects/astroid/astroid/nodes/node_classes.py\", line 2254, in getitem\r\n    return value.getitem(index, context)\r\nAttributeError: 'Name' object has no attribute 'getitem'\r\n```\r\n\r\nExpeceted output;\r\n```\r\n $ python t1.py                                                                                                 4ms\r\nfirst_dict.getitem(key).value = 'B'\r\nsecond_dict.getitem(key).value = 'B'\r\n\r\n```\r\n\n", "repo": "pylint-dev/astroid", "test_patch": "diff --git a/tests/unittest_python3.py b/tests/unittest_python3.py\n--- a/tests/unittest_python3.py\n+++ b/tests/unittest_python3.py\n@@ -5,7 +5,9 @@\n import unittest\n from textwrap import dedent\n \n-from astroid import nodes\n+import pytest\n+\n+from astroid import exceptions, nodes\n from astroid.builder import AstroidBuilder, extract_node\n from astroid.test_utils import require_version\n \n@@ -285,6 +287,33 @@ def test_unpacking_in_dict_getitem(self) -> None:\n             self.assertIsInstance(value, nodes.Const)\n             self.assertEqual(value.value, expected)\n \n+    @staticmethod\n+    def test_unpacking_in_dict_getitem_with_ref() -> None:\n+        node = extract_node(\n+            \"\"\"\n+        a = {1: 2}\n+        {**a, 2: 3}  #@\n+        \"\"\"\n+        )\n+        assert isinstance(node, nodes.Dict)\n+\n+        for key, expected in ((1, 2), (2, 3)):\n+            value = node.getitem(nodes.Const(key))\n+            assert isinstance(value, nodes.Const)\n+            assert value.value == expected\n+\n+    @staticmethod\n+    def test_unpacking_in_dict_getitem_uninferable() -> None:\n+        node = extract_node(\"{**a, 2: 3}\")\n+        assert isinstance(node, nodes.Dict)\n+\n+        with pytest.raises(exceptions.AstroidIndexError):\n+            node.getitem(nodes.Const(1))\n+\n+        value = node.getitem(nodes.Const(2))\n+        assert isinstance(value, nodes.Const)\n+        assert value.value == 3\n+\n     def test_format_string(self) -> None:\n         code = \"f'{greetings} {person}'\"\n         node = extract_node(code)\n", "version": "2.12"}
parsed_commit_content: {"file_diffs":[{"old_file_content":"# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html\n# For details: https://github.com/PyCQA/astroid/blob/main/LICENSE\n# Copyright (c) https://github.com/PyCQA/astroid/blob/main/CONTRIBUTORS.txt\n\n\"\"\"Module for some node classes. More nodes in scoped_nodes.py\"\"\"\n\nfrom __future__ import annotations\n\nimport abc\nimport itertools\nimport sys\nimport typing\nimport warnings\nfrom collections.abc import Generator, Iterator\nfrom functools import lru_cache\nfrom typing import TYPE_CHECKING, Any, Callable, ClassVar, Optional, TypeVar, Union\n\nfrom astroid import decorators, mixins, util\nfrom astroid.bases import Instance, _infer_stmts\nfrom astroid.const import Context\nfrom astroid.context import InferenceContext\nfrom astroid.exceptions import (\n    AstroidIndexError,\n    AstroidTypeError,\n    InferenceError,\n    NoDefault,\n    ParentMissingError,\n)\nfrom astroid.manager import AstroidManager\nfrom astroid.nodes.const import OP_PRECEDENCE\nfrom astroid.nodes.node_ng import NodeNG\n\nif sys.version_info >= (3, 8):\n    from typing import Literal\nelse:\n    from typing_extensions import Literal\n\nif TYPE_CHECKING:\n    from astroid import nodes\n    from astroid.nodes import LocalsDictNodeNG\n\nif sys.version_info >= (3, 8):\n    from functools import cached_property\nelse:\n    from astroid.decorators import cachedproperty as cached_property\n\n\ndef _is_const(value):\n    return isinstance(value, tuple(CONST_CLS))\n\n\n_NodesT = TypeVar(\"_NodesT\", bound=NodeNG)\n\nAssignedStmtsPossibleNode = Union[\"List\", \"Tuple\", \"AssignName\", \"AssignAttr\", None]\nAssignedStmtsCall = Callable[\n    [\n        _NodesT,\n        AssignedStmtsPossibleNode,\n        Optional[InferenceContext],\n        Optional[typing.List[int]],\n    ],\n    Any,\n]\n\n\n@decorators.raise_if_nothing_inferred\ndef unpack_infer(stmt, context=None):\n    \"\"\"recursively generate nodes inferred by the given statement.\n    If the inferred value is a list or a tuple, recurse on the elements\n    \"\"\"\n    if isinstance(stmt, (List, Tuple)):\n        for elt in stmt.elts:\n            if elt is util.Uninferable:\n                yield elt\n                continue\n            yield from unpack_infer(elt, context)\n        return dict(node=stmt, context=context)\n    # if inferred is a final node, return it and stop\n    inferred = next(stmt.infer(context), util.Uninferable)\n    if inferred is stmt:\n        yield inferred\n        return dict(node=stmt, context=context)\n    # else, infer recursively, except Uninferable object that should be returned as is\n    for inferred in stmt.infer(context):\n        if inferred is util.Uninferable:\n            yield inferred\n        else:\n            yield from unpack_infer(inferred, context)\n\n    return dict(node=stmt, context=context)\n\n\ndef are_exclusive(stmt1, stmt2, exceptions: list[str] | None = None) -> bool:\n    \"\"\"return true if the two given statements are mutually exclusive\n\n    `exceptions` may be a list of exception names. If specified, discard If\n    branches and check one of the statement is in an exception handler catching\n    one of the given exceptions.\n\n    algorithm :\n     1) index stmt1's parents\n     2) climb among stmt2's parents until we find a common parent\n     3) if the common parent is a If or TryExcept statement, look if nodes are\n        in exclusive branches\n    \"\"\"\n    # index stmt1's parents\n    stmt1_parents = {}\n    children = {}\n    previous = stmt1\n    for node in stmt1.node_ancestors():\n        stmt1_parents[node] = 1\n        children[node] = previous\n        previous = node\n    # climb among stmt2's parents until we find a common parent\n    previous = stmt2\n    for node in stmt2.node_ancestors():\n        if node in stmt1_parents:\n            # if the common parent is a If or TryExcept statement, look if\n            # nodes are in exclusive branches\n            if isinstance(node, If) and exceptions is None:\n                if (\n                    node.locate_child(previous)[1]\n                    is not node.locate_child(children[node])[1]\n                ):\n                    return True\n            elif isinstance(node, TryExcept):\n                c2attr, c2node = node.locate_child(previous)\n                c1attr, c1node = node.locate_child(children[node])\n                if c1node is not c2node:\n                    first_in_body_caught_by_handlers = (\n                        c2attr == \"handlers\"\n                        and c1attr == \"body\"\n                        and previous.catch(exceptions)\n                    )\n                    second_in_body_caught_by_handlers = (\n                        c2attr == \"body\"\n                        and c1attr == \"handlers\"\n                        and children[node].catch(exceptions)\n                    )\n                    first_in_else_other_in_handlers = (\n                        c2attr == \"handlers\" and c1attr == \"orelse\"\n                    )\n                    second_in_else_other_in_handlers = (\n                        c2attr == \"orelse\" and c1attr == \"handlers\"\n                    )\n                    if any(\n                        (\n                            first_in_body_caught_by_handlers,\n                            second_in_body_caught_by_handlers,\n                            first_in_else_other_in_handlers,\n                            second_in_else_other_in_handlers,\n                        )\n                    ):\n                        return True\n                elif c2attr == \"handlers\" and c1attr == \"handlers\":\n                    return previous is not children[node]\n            return False\n        previous = node\n    return False\n\n\n# getitem() helpers.\n\n_SLICE_SENTINEL = object()\n\n\ndef _slice_value(index, context=None):\n    \"\"\"Get the value of the given slice index.\"\"\"\n\n    if isinstance(index, Const):\n        if isinstance(index.value, (int, type(None))):\n            return index.value\n    elif index is None:\n        return None\n    else:\n        # Try to infer what the index actually is.\n        # Since we can't return all the possible values,\n        # we'll stop at the first possible value.\n        try:\n            inferred = next(index.infer(context=context))\n        except (InferenceError, StopIteration):\n            pass\n        else:\n            if isinstance(inferred, Const):\n                if isinstance(inferred.value, (int, type(None))):\n                    return inferred.value\n\n    # Use a sentinel, because None can be a valid\n    # value that this function can return,\n    # as it is the case for unspecified bounds.\n    return _SLICE_SENTINEL\n\n\ndef _infer_slice(node, context=None):\n    lower = _slice_value(node.lower, context)\n    upper = _slice_value(node.upper, context)\n    step = _slice_value(node.step, context)\n    if all(elem is not _SLICE_SENTINEL for elem in (lower, upper, step)):\n        return slice(lower, upper, step)\n\n    raise AstroidTypeError(\n        message=\"Could not infer slice used in subscript\",\n        node=node,\n        index=node.parent,\n        context=context,\n    )\n\n\ndef _container_getitem(instance, elts, index, context=None):\n    \"\"\"Get a slice or an item, using the given *index*, for the given sequence.\"\"\"\n    try:\n        if isinstance(index, Slice):\n            index_slice = _infer_slice(index, context=context)\n            new_cls = instance.__class__()\n            new_cls.elts = elts[index_slice]\n            new_cls.parent = instance.parent\n            return new_cls\n        if isinstance(index, Const):\n            return elts[index.value]\n    except IndexError as exc:\n        raise AstroidIndexError(\n            message=\"Index {index!s} out of range\",\n            node=instance,\n            index=index,\n            context=context,\n        ) from exc\n    except TypeError as exc:\n        raise AstroidTypeError(\n            message=\"Type error {error!r}\", node=instance, index=index, context=context\n        ) from exc\n\n    raise AstroidTypeError(f\"Could not use {index} as subscript index\")\n\n\nclass Statement(NodeNG):\n    \"\"\"Statement node adding a few attributes\"\"\"\n\n    is_statement = True\n    \"\"\"Whether this node indicates a statement.\"\"\"\n\n    def next_sibling(self):\n        \"\"\"The next sibling statement node.\n\n        :returns: The next sibling statement node.\n        :rtype: NodeNG or None\n        \"\"\"\n        stmts = self.parent.child_sequence(self)\n        index = stmts.index(self)\n        try:\n            return stmts[index + 1]\n        except IndexError:\n            return None\n\n    def previous_sibling(self):\n        \"\"\"The previous sibling statement.\n\n        :returns: The previous sibling statement node.\n        :rtype: NodeNG or None\n        \"\"\"\n        stmts = self.parent.child_sequence(self)\n        index = stmts.index(self)\n        if index >= 1:\n            return stmts[index - 1]\n        return None\n\n\nclass BaseContainer(\n    mixins.ParentAssignTypeMixin, NodeNG, Instance, metaclass=abc.ABCMeta\n):\n    \"\"\"Base class for Set, FrozenSet, Tuple and List.\"\"\"\n\n    _astroid_fields = (\"elts\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.elts: list[NodeNG] = []\n        \"\"\"The elements in the node.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, elts: list[NodeNG]) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param elts: The list of elements the that node contains.\n        \"\"\"\n        self.elts = elts\n\n    @classmethod\n    def from_elements(cls, elts=None):\n        \"\"\"Create a node of this type from the given list of elements.\n\n        :param elts: The list of elements that the node should contain.\n        :type elts: list(NodeNG)\n\n        :returns: A new node containing the given elements.\n        :rtype: NodeNG\n        \"\"\"\n        node = cls()\n        if elts is None:\n            node.elts = []\n        else:\n            node.elts = [const_factory(e) if _is_const(e) else e for e in elts]\n        return node\n\n    def itered(self):\n        \"\"\"An iterator over the elements this node contains.\n\n        :returns: The contents of this node.\n        :rtype: iterable(NodeNG)\n        \"\"\"\n        return self.elts\n\n    def bool_value(self, context=None):\n        \"\"\"Determine the boolean value of this node.\n\n        :returns: The boolean value of this node.\n        :rtype: bool or Uninferable\n        \"\"\"\n        return bool(self.elts)\n\n    @abc.abstractmethod\n    def pytype(self):\n        \"\"\"Get the name of the type that this node represents.\n\n        :returns: The name of the type.\n        :rtype: str\n        \"\"\"\n\n    def get_children(self):\n        yield from self.elts\n\n\nclass LookupMixIn:\n    \"\"\"Mixin to look up a name in the right scope.\"\"\"\n\n    @lru_cache()  # noqa\n    def lookup(self, name: str) -> tuple[str, list[NodeNG]]:\n        \"\"\"Lookup where the given variable is assigned.\n\n        The lookup starts from self's scope. If self is not a frame itself\n        and the name is found in the inner frame locals, statements will be\n        filtered to remove ignorable statements according to self's location.\n\n        :param name: The name of the variable to find assignments for.\n\n        :returns: The scope node and the list of assignments associated to the\n            given name according to the scope where it has been found (locals,\n            globals or builtin).\n        \"\"\"\n        return self.scope().scope_lookup(self, name)\n\n    def ilookup(self, name):\n        \"\"\"Lookup the inferred values of the given variable.\n\n        :param name: The variable name to find values for.\n        :type name: str\n\n        :returns: The inferred values of the statements returned from\n            :meth:`lookup`.\n        :rtype: iterable\n        \"\"\"\n        frame, stmts = self.lookup(name)\n        context = InferenceContext()\n        return _infer_stmts(stmts, context, frame)\n\n\n# Name classes\n\n\nclass AssignName(\n    mixins.NoChildrenMixin, LookupMixIn, mixins.ParentAssignTypeMixin, NodeNG\n):\n    \"\"\"Variation of :class:`ast.Assign` representing assignment to a name.\n\n    An :class:`AssignName` is the name of something that is assigned to.\n    This includes variables defined in a function signature or in a loop.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('variable = range(10)')\n    >>> node\n    <Assign l.1 at 0x7effe1db8550>\n    >>> list(node.get_children())\n    [<AssignName.variable l.1 at 0x7effe1db8748>, <Call l.1 at 0x7effe1db8630>]\n    >>> list(node.get_children())[0].as_string()\n    'variable'\n    \"\"\"\n\n    _other_fields = (\"name\",)\n\n    @decorators.deprecate_default_argument_values(name=\"str\")\n    def __init__(\n        self,\n        name: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param name: The name that is assigned to.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.name: str | None = name\n        \"\"\"The name that is assigned to.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[AssignName]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n\nclass DelName(\n    mixins.NoChildrenMixin, LookupMixIn, mixins.ParentAssignTypeMixin, NodeNG\n):\n    \"\"\"Variation of :class:`ast.Delete` representing deletion of a name.\n\n    A :class:`DelName` is the name of something that is deleted.\n\n    >>> import astroid\n    >>> node = astroid.extract_node(\"del variable #@\")\n    >>> list(node.get_children())\n    [<DelName.variable l.1 at 0x7effe1da4d30>]\n    >>> list(node.get_children())[0].as_string()\n    'variable'\n    \"\"\"\n\n    _other_fields = (\"name\",)\n\n    @decorators.deprecate_default_argument_values(name=\"str\")\n    def __init__(\n        self,\n        name: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param name: The name that is being deleted.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.name: str | None = name\n        \"\"\"The name that is being deleted.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n\nclass Name(mixins.NoChildrenMixin, LookupMixIn, NodeNG):\n    \"\"\"Class representing an :class:`ast.Name` node.\n\n    A :class:`Name` node is something that is named, but not covered by\n    :class:`AssignName` or :class:`DelName`.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('range(10)')\n    >>> node\n    <Call l.1 at 0x7effe1db8710>\n    >>> list(node.get_children())\n    [<Name.range l.1 at 0x7effe1db86a0>, <Const.int l.1 at 0x7effe1db8518>]\n    >>> list(node.get_children())[0].as_string()\n    'range'\n    \"\"\"\n\n    _other_fields = (\"name\",)\n\n    @decorators.deprecate_default_argument_values(name=\"str\")\n    def __init__(\n        self,\n        name: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param name: The name that this node refers to.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.name: str | None = name\n        \"\"\"The name that this node refers to.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def _get_name_nodes(self):\n        yield self\n\n        for child_node in self.get_children():\n            yield from child_node._get_name_nodes()\n\n\nclass Arguments(mixins.AssignTypeMixin, NodeNG):\n    \"\"\"Class representing an :class:`ast.arguments` node.\n\n    An :class:`Arguments` node represents that arguments in a\n    function definition.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('def foo(bar): pass')\n    >>> node\n    <FunctionDef.foo l.1 at 0x7effe1db8198>\n    >>> node.args\n    <Arguments l.1 at 0x7effe1db82e8>\n    \"\"\"\n\n    # Python 3.4+ uses a different approach regarding annotations,\n    # each argument is a new class, _ast.arg, which exposes an\n    # 'annotation' attribute. In astroid though, arguments are exposed\n    # as is in the Arguments node and the only way to expose annotations\n    # is by using something similar with Python 3.3:\n    #  - we expose 'varargannotation' and 'kwargannotation' of annotations\n    #    of varargs and kwargs.\n    #  - we expose 'annotation', a list with annotations for\n    #    for each normal argument. If an argument doesn't have an\n    #    annotation, its value will be None.\n    _astroid_fields = (\n        \"args\",\n        \"defaults\",\n        \"kwonlyargs\",\n        \"posonlyargs\",\n        \"posonlyargs_annotations\",\n        \"kw_defaults\",\n        \"annotations\",\n        \"varargannotation\",\n        \"kwargannotation\",\n        \"kwonlyargs_annotations\",\n        \"type_comment_args\",\n        \"type_comment_kwonlyargs\",\n        \"type_comment_posonlyargs\",\n    )\n\n    _other_fields = (\"vararg\", \"kwarg\")\n\n    lineno: None\n    col_offset: None\n    end_lineno: None\n    end_col_offset: None\n\n    def __init__(\n        self,\n        vararg: str | None = None,\n        kwarg: str | None = None,\n        parent: NodeNG | None = None,\n    ) -> None:\n        \"\"\"\n        :param vararg: The name of the variable length arguments.\n\n        :param kwarg: The name of the variable length keyword arguments.\n\n        :param parent: The parent node in the syntax tree.\n        \"\"\"\n        super().__init__(parent=parent)\n\n        self.vararg: str | None = vararg  # can be None\n        \"\"\"The name of the variable length arguments.\"\"\"\n\n        self.kwarg: str | None = kwarg  # can be None\n        \"\"\"The name of the variable length keyword arguments.\"\"\"\n\n        self.args: list[AssignName] | None\n        \"\"\"The names of the required arguments.\n\n        Can be None if the associated function does not have a retrievable\n        signature and the arguments are therefore unknown.\n        This can happen with (builtin) functions implemented in C that have\n        incomplete signature information.\n        \"\"\"\n        # TODO: Check if other attributes should also be None when\n        # .args is None.\n\n        self.defaults: list[NodeNG]\n        \"\"\"The default values for arguments that can be passed positionally.\"\"\"\n\n        self.kwonlyargs: list[AssignName]\n        \"\"\"The keyword arguments that cannot be passed positionally.\"\"\"\n\n        self.posonlyargs: list[AssignName] = []\n        \"\"\"The arguments that can only be passed positionally.\"\"\"\n\n        self.kw_defaults: list[NodeNG | None]\n        \"\"\"The default values for keyword arguments that cannot be passed positionally.\"\"\"\n\n        self.annotations: list[NodeNG | None]\n        \"\"\"The type annotations of arguments that can be passed positionally.\"\"\"\n\n        self.posonlyargs_annotations: list[NodeNG | None] = []\n        \"\"\"The type annotations of arguments that can only be passed positionally.\"\"\"\n\n        self.kwonlyargs_annotations: list[NodeNG | None] = []\n        \"\"\"The type annotations of arguments that cannot be passed positionally.\"\"\"\n\n        self.type_comment_args: list[NodeNG | None] = []\n        \"\"\"The type annotation, passed by a type comment, of each argument.\n\n        If an argument does not have a type comment,\n        the value for that argument will be None.\n        \"\"\"\n\n        self.type_comment_kwonlyargs: list[NodeNG | None] = []\n        \"\"\"The type annotation, passed by a type comment, of each keyword only argument.\n\n        If an argument does not have a type comment,\n        the value for that argument will be None.\n        \"\"\"\n\n        self.type_comment_posonlyargs: list[NodeNG | None] = []\n        \"\"\"The type annotation, passed by a type comment, of each positional argument.\n\n        If an argument does not have a type comment,\n        the value for that argument will be None.\n        \"\"\"\n\n        self.varargannotation: NodeNG | None = None  # can be None\n        \"\"\"The type annotation for the variable length arguments.\"\"\"\n\n        self.kwargannotation: NodeNG | None = None  # can be None\n        \"\"\"The type annotation for the variable length keyword arguments.\"\"\"\n\n    # pylint: disable=too-many-arguments\n    def postinit(\n        self,\n        args: list[AssignName] | None,\n        defaults: list[NodeNG],\n        kwonlyargs: list[AssignName],\n        kw_defaults: list[NodeNG | None],\n        annotations: list[NodeNG | None],\n        posonlyargs: list[AssignName] | None = None,\n        kwonlyargs_annotations: list[NodeNG | None] | None = None,\n        posonlyargs_annotations: list[NodeNG | None] | None = None,\n        varargannotation: NodeNG | None = None,\n        kwargannotation: NodeNG | None = None,\n        type_comment_args: list[NodeNG | None] | None = None,\n        type_comment_kwonlyargs: list[NodeNG | None] | None = None,\n        type_comment_posonlyargs: list[NodeNG | None] | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param args: The names of the required arguments.\n\n        :param defaults: The default values for arguments that can be passed\n            positionally.\n\n        :param kwonlyargs: The keyword arguments that cannot be passed\n            positionally.\n\n        :param posonlyargs: The arguments that can only be passed\n            positionally.\n\n        :param kw_defaults: The default values for keyword arguments that\n            cannot be passed positionally.\n\n        :param annotations: The type annotations of arguments that can be\n            passed positionally.\n\n        :param kwonlyargs_annotations: The type annotations of arguments that\n            cannot be passed positionally. This should always be passed in\n            Python 3.\n\n        :param posonlyargs_annotations: The type annotations of arguments that\n            can only be passed positionally. This should always be passed in\n            Python 3.\n\n        :param varargannotation: The type annotation for the variable length\n            arguments.\n\n        :param kwargannotation: The type annotation for the variable length\n            keyword arguments.\n\n        :param type_comment_args: The type annotation,\n            passed by a type comment, of each argument.\n\n        :param type_comment_args: The type annotation,\n            passed by a type comment, of each keyword only argument.\n\n        :param type_comment_args: The type annotation,\n            passed by a type comment, of each positional argument.\n        \"\"\"\n        self.args = args\n        self.defaults = defaults\n        self.kwonlyargs = kwonlyargs\n        if posonlyargs is not None:\n            self.posonlyargs = posonlyargs\n        self.kw_defaults = kw_defaults\n        self.annotations = annotations\n        if kwonlyargs_annotations is not None:\n            self.kwonlyargs_annotations = kwonlyargs_annotations\n        if posonlyargs_annotations is not None:\n            self.posonlyargs_annotations = posonlyargs_annotations\n        self.varargannotation = varargannotation\n        self.kwargannotation = kwargannotation\n        if type_comment_args is not None:\n            self.type_comment_args = type_comment_args\n        if type_comment_kwonlyargs is not None:\n            self.type_comment_kwonlyargs = type_comment_kwonlyargs\n        if type_comment_posonlyargs is not None:\n            self.type_comment_posonlyargs = type_comment_posonlyargs\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[Arguments]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def _infer_name(self, frame, name):\n        if self.parent is frame:\n            return name\n        return None\n\n    @cached_property\n    def fromlineno(self):\n        \"\"\"The first line that this node appears on in the source code.\n\n        :type: int or None\n        \"\"\"\n        lineno = super().fromlineno\n        return max(lineno, self.parent.fromlineno or 0)\n\n    @cached_property\n    def arguments(self):\n        \"\"\"Get all the arguments for this node, including positional only and positional and keyword\"\"\"\n        return list(itertools.chain((self.posonlyargs or ()), self.args or ()))\n\n    def format_args(self):\n        \"\"\"Get the arguments formatted as string.\n\n        :returns: The formatted arguments.\n        :rtype: str\n        \"\"\"\n        result = []\n        positional_only_defaults = []\n        positional_or_keyword_defaults = self.defaults\n        if self.defaults:\n            args = self.args or []\n            positional_or_keyword_defaults = self.defaults[-len(args) :]\n            positional_only_defaults = self.defaults[: len(self.defaults) - len(args)]\n\n        if self.posonlyargs:\n            result.append(\n                _format_args(\n                    self.posonlyargs,\n                    positional_only_defaults,\n                    self.posonlyargs_annotations,\n                )\n            )\n            result.append(\"/\")\n        if self.args:\n            result.append(\n                _format_args(\n                    self.args,\n                    positional_or_keyword_defaults,\n                    getattr(self, \"annotations\", None),\n                )\n            )\n        if self.vararg:\n            result.append(f\"*{self.vararg}\")\n        if self.kwonlyargs:\n            if not self.vararg:\n                result.append(\"*\")\n            result.append(\n                _format_args(\n                    self.kwonlyargs, self.kw_defaults, self.kwonlyargs_annotations\n                )\n            )\n        if self.kwarg:\n            result.append(f\"**{self.kwarg}\")\n        return \", \".join(result)\n\n    def default_value(self, argname):\n        \"\"\"Get the default value for an argument.\n\n        :param argname: The name of the argument to get the default value for.\n        :type argname: str\n\n        :raises NoDefault: If there is no default value defined for the\n            given argument.\n        \"\"\"\n        args = self.arguments\n        index = _find_arg(argname, args)[0]\n        if index is not None:\n            idx = index - (len(args) - len(self.defaults))\n            if idx >= 0:\n                return self.defaults[idx]\n        index = _find_arg(argname, self.kwonlyargs)[0]\n        if index is not None and self.kw_defaults[index] is not None:\n            return self.kw_defaults[index]\n        raise NoDefault(func=self.parent, name=argname)\n\n    def is_argument(self, name):\n        \"\"\"Check if the given name is defined in the arguments.\n\n        :param name: The name to check for.\n        :type name: str\n\n        :returns: True if the given name is defined in the arguments,\n            False otherwise.\n        :rtype: bool\n        \"\"\"\n        if name == self.vararg:\n            return True\n        if name == self.kwarg:\n            return True\n        return (\n            self.find_argname(name, rec=True)[1] is not None\n            or self.kwonlyargs\n            and _find_arg(name, self.kwonlyargs, rec=True)[1] is not None\n        )\n\n    def find_argname(self, argname, rec=False):\n        \"\"\"Get the index and :class:`AssignName` node for given name.\n\n        :param argname: The name of the argument to search for.\n        :type argname: str\n\n        :param rec: Whether or not to include arguments in unpacked tuples\n            in the search.\n        :type rec: bool\n\n        :returns: The index and node for the argument.\n        :rtype: tuple(str or None, AssignName or None)\n        \"\"\"\n        if self.arguments:\n            return _find_arg(argname, self.arguments, rec)\n        return None, None\n\n    def get_children(self):\n        yield from self.posonlyargs or ()\n\n        for elt in self.posonlyargs_annotations:\n            if elt is not None:\n                yield elt\n\n        yield from self.args or ()\n\n        yield from self.defaults\n        yield from self.kwonlyargs\n\n        for elt in self.kw_defaults:\n            if elt is not None:\n                yield elt\n\n        for elt in self.annotations:\n            if elt is not None:\n                yield elt\n\n        if self.varargannotation is not None:\n            yield self.varargannotation\n\n        if self.kwargannotation is not None:\n            yield self.kwargannotation\n\n        for elt in self.kwonlyargs_annotations:\n            if elt is not None:\n                yield elt\n\n\ndef _find_arg(argname, args, rec=False):\n    for i, arg in enumerate(args):\n        if isinstance(arg, Tuple):\n            if rec:\n                found = _find_arg(argname, arg.elts)\n                if found[0] is not None:\n                    return found\n        elif arg.name == argname:\n            return i, arg\n    return None, None\n\n\ndef _format_args(args, defaults=None, annotations=None):\n    values = []\n    if args is None:\n        return \"\"\n    if annotations is None:\n        annotations = []\n    if defaults is not None:\n        default_offset = len(args) - len(defaults)\n    packed = itertools.zip_longest(args, annotations)\n    for i, (arg, annotation) in enumerate(packed):\n        if isinstance(arg, Tuple):\n            values.append(f\"({_format_args(arg.elts)})\")\n        else:\n            argname = arg.name\n            default_sep = \"=\"\n            if annotation is not None:\n                argname += \": \" + annotation.as_string()\n                default_sep = \" = \"\n            values.append(argname)\n\n            if defaults is not None and i >= default_offset:\n                if defaults[i - default_offset] is not None:\n                    values[-1] += default_sep + defaults[i - default_offset].as_string()\n    return \", \".join(values)\n\n\nclass AssignAttr(mixins.ParentAssignTypeMixin, NodeNG):\n    \"\"\"Variation of :class:`ast.Assign` representing assignment to an attribute.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('self.attribute = range(10)')\n    >>> node\n    <Assign l.1 at 0x7effe1d521d0>\n    >>> list(node.get_children())\n    [<AssignAttr.attribute l.1 at 0x7effe1d52320>, <Call l.1 at 0x7effe1d522e8>]\n    >>> list(node.get_children())[0].as_string()\n    'self.attribute'\n    \"\"\"\n\n    _astroid_fields = (\"expr\",)\n    _other_fields = (\"attrname\",)\n\n    @decorators.deprecate_default_argument_values(attrname=\"str\")\n    def __init__(\n        self,\n        attrname: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param attrname: The name of the attribute being assigned to.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.expr: NodeNG | None = None\n        \"\"\"What has the attribute that is being assigned to.\"\"\"\n\n        self.attrname: str | None = attrname\n        \"\"\"The name of the attribute being assigned to.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, expr: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param expr: What has the attribute that is being assigned to.\n        \"\"\"\n        self.expr = expr\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[AssignAttr]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def get_children(self):\n        yield self.expr\n\n\nclass Assert(Statement):\n    \"\"\"Class representing an :class:`ast.Assert` node.\n\n    An :class:`Assert` node represents an assert statement.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('assert len(things) == 10, \"Not enough things\"')\n    >>> node\n    <Assert l.1 at 0x7effe1d527b8>\n    \"\"\"\n\n    _astroid_fields = (\"test\", \"fail\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.test: NodeNG | None = None\n        \"\"\"The test that passes or fails the assertion.\"\"\"\n\n        self.fail: NodeNG | None = None  # can be None\n        \"\"\"The message shown when the assertion fails.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, test: NodeNG | None = None, fail: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param test: The test that passes or fails the assertion.\n\n        :param fail: The message shown when the assertion fails.\n        \"\"\"\n        self.fail = fail\n        self.test = test\n\n    def get_children(self):\n        yield self.test\n\n        if self.fail is not None:\n            yield self.fail\n\n\nclass Assign(mixins.AssignTypeMixin, Statement):\n    \"\"\"Class representing an :class:`ast.Assign` node.\n\n    An :class:`Assign` is a statement where something is explicitly\n    asssigned to.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('variable = range(10)')\n    >>> node\n    <Assign l.1 at 0x7effe1db8550>\n    \"\"\"\n\n    _astroid_fields = (\"targets\", \"value\")\n    _other_other_fields = (\"type_annotation\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.targets: list[NodeNG] = []\n        \"\"\"What is being assigned to.\"\"\"\n\n        self.value: NodeNG | None = None\n        \"\"\"The value being assigned to the variables.\"\"\"\n\n        self.type_annotation: NodeNG | None = None  # can be None\n        \"\"\"If present, this will contain the type annotation passed by a type comment\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        targets: list[NodeNG] | None = None,\n        value: NodeNG | None = None,\n        type_annotation: NodeNG | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param targets: What is being assigned to.\n        :param value: The value being assigned to the variables.\n        :param type_annotation:\n        \"\"\"\n        if targets is not None:\n            self.targets = targets\n        self.value = value\n        self.type_annotation = type_annotation\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[Assign]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def get_children(self):\n        yield from self.targets\n\n        yield self.value\n\n    @decorators.cached\n    def _get_assign_nodes(self):\n        return [self] + list(self.value._get_assign_nodes())\n\n    def _get_yield_nodes_skip_lambdas(self):\n        yield from self.value._get_yield_nodes_skip_lambdas()\n\n\nclass AnnAssign(mixins.AssignTypeMixin, Statement):\n    \"\"\"Class representing an :class:`ast.AnnAssign` node.\n\n    An :class:`AnnAssign` is an assignment with a type annotation.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('variable: List[int] = range(10)')\n    >>> node\n    <AnnAssign l.1 at 0x7effe1d4c630>\n    \"\"\"\n\n    _astroid_fields = (\"target\", \"annotation\", \"value\")\n    _other_fields = (\"simple\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.target: NodeNG | None = None\n        \"\"\"What is being assigned to.\"\"\"\n\n        self.annotation: NodeNG | None = None\n        \"\"\"The type annotation of what is being assigned to.\"\"\"\n\n        self.value: NodeNG | None = None  # can be None\n        \"\"\"The value being assigned to the variables.\"\"\"\n\n        self.simple: int | None = None\n        \"\"\"Whether :attr:`target` is a pure name or a complex statement.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        target: NodeNG,\n        annotation: NodeNG,\n        simple: int,\n        value: NodeNG | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param target: What is being assigned to.\n\n        :param annotation: The type annotation of what is being assigned to.\n\n        :param simple: Whether :attr:`target` is a pure name\n            or a complex statement.\n\n        :param value: The value being assigned to the variables.\n        \"\"\"\n        self.target = target\n        self.annotation = annotation\n        self.value = value\n        self.simple = simple\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[AnnAssign]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def get_children(self):\n        yield self.target\n        yield self.annotation\n\n        if self.value is not None:\n            yield self.value\n\n\nclass AugAssign(mixins.AssignTypeMixin, Statement):\n    \"\"\"Class representing an :class:`ast.AugAssign` node.\n\n    An :class:`AugAssign` is an assignment paired with an operator.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('variable += 1')\n    >>> node\n    <AugAssign l.1 at 0x7effe1db4d68>\n    \"\"\"\n\n    _astroid_fields = (\"target\", \"value\")\n    _other_fields = (\"op\",)\n\n    @decorators.deprecate_default_argument_values(op=\"str\")\n    def __init__(\n        self,\n        op: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param op: The operator that is being combined with the assignment.\n            This includes the equals sign.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.target: NodeNG | None = None\n        \"\"\"What is being assigned to.\"\"\"\n\n        self.op: str | None = op\n        \"\"\"The operator that is being combined with the assignment.\n\n        This includes the equals sign.\n        \"\"\"\n\n        self.value: NodeNG | None = None\n        \"\"\"The value being assigned to the variable.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self, target: NodeNG | None = None, value: NodeNG | None = None\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param target: What is being assigned to.\n\n        :param value: The value being assigned to the variable.\n        \"\"\"\n        self.target = target\n        self.value = value\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[AugAssign]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    # This is set by inference.py\n    def _infer_augassign(self, context=None):\n        raise NotImplementedError\n\n    def type_errors(self, context=None):\n        \"\"\"Get a list of type errors which can occur during inference.\n\n        Each TypeError is represented by a :class:`BadBinaryOperationMessage` ,\n        which holds the original exception.\n\n        :returns: The list of possible type errors.\n        :rtype: list(BadBinaryOperationMessage)\n        \"\"\"\n        try:\n            results = self._infer_augassign(context=context)\n            return [\n                result\n                for result in results\n                if isinstance(result, util.BadBinaryOperationMessage)\n            ]\n        except InferenceError:\n            return []\n\n    def get_children(self):\n        yield self.target\n        yield self.value\n\n    def _get_yield_nodes_skip_lambdas(self):\n        \"\"\"An AugAssign node can contain a Yield node in the value\"\"\"\n        yield from self.value._get_yield_nodes_skip_lambdas()\n        yield from super()._get_yield_nodes_skip_lambdas()\n\n\nclass BinOp(NodeNG):\n    \"\"\"Class representing an :class:`ast.BinOp` node.\n\n    A :class:`BinOp` node is an application of a binary operator.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('a + b')\n    >>> node\n    <BinOp l.1 at 0x7f23b2e8cfd0>\n    \"\"\"\n\n    _astroid_fields = (\"left\", \"right\")\n    _other_fields = (\"op\",)\n\n    @decorators.deprecate_default_argument_values(op=\"str\")\n    def __init__(\n        self,\n        op: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param op: The operator.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.left: NodeNG | None = None\n        \"\"\"What is being applied to the operator on the left side.\"\"\"\n\n        self.op: str | None = op\n        \"\"\"The operator.\"\"\"\n\n        self.right: NodeNG | None = None\n        \"\"\"What is being applied to the operator on the right side.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, left: NodeNG | None = None, right: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param left: What is being applied to the operator on the left side.\n\n        :param right: What is being applied to the operator on the right side.\n        \"\"\"\n        self.left = left\n        self.right = right\n\n    # This is set by inference.py\n    def _infer_binop(self, context=None):\n        raise NotImplementedError\n\n    def type_errors(self, context=None):\n        \"\"\"Get a list of type errors which can occur during inference.\n\n        Each TypeError is represented by a :class:`BadBinaryOperationMessage`,\n        which holds the original exception.\n\n        :returns: The list of possible type errors.\n        :rtype: list(BadBinaryOperationMessage)\n        \"\"\"\n        try:\n            results = self._infer_binop(context=context)\n            return [\n                result\n                for result in results\n                if isinstance(result, util.BadBinaryOperationMessage)\n            ]\n        except InferenceError:\n            return []\n\n    def get_children(self):\n        yield self.left\n        yield self.right\n\n    def op_precedence(self):\n        return OP_PRECEDENCE[self.op]\n\n    def op_left_associative(self):\n        # 2**3**4 == 2**(3**4)\n        return self.op != \"**\"\n\n\nclass BoolOp(NodeNG):\n    \"\"\"Class representing an :class:`ast.BoolOp` node.\n\n    A :class:`BoolOp` is an application of a boolean operator.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('a and b')\n    >>> node\n    <BinOp l.1 at 0x7f23b2e71c50>\n    \"\"\"\n\n    _astroid_fields = (\"values\",)\n    _other_fields = (\"op\",)\n\n    @decorators.deprecate_default_argument_values(op=\"str\")\n    def __init__(\n        self,\n        op: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param op: The operator.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.op: str | None = op\n        \"\"\"The operator.\"\"\"\n\n        self.values: list[NodeNG] = []\n        \"\"\"The values being applied to the operator.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, values: list[NodeNG] | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param values: The values being applied to the operator.\n        \"\"\"\n        if values is not None:\n            self.values = values\n\n    def get_children(self):\n        yield from self.values\n\n    def op_precedence(self):\n        return OP_PRECEDENCE[self.op]\n\n\nclass Break(mixins.NoChildrenMixin, Statement):\n    \"\"\"Class representing an :class:`ast.Break` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('break')\n    >>> node\n    <Break l.1 at 0x7f23b2e9e5c0>\n    \"\"\"\n\n\nclass Call(NodeNG):\n    \"\"\"Class representing an :class:`ast.Call` node.\n\n    A :class:`Call` node is a call to a function, method, etc.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('function()')\n    >>> node\n    <Call l.1 at 0x7f23b2e71eb8>\n    \"\"\"\n\n    _astroid_fields = (\"func\", \"args\", \"keywords\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.func: NodeNG | None = None\n        \"\"\"What is being called.\"\"\"\n\n        self.args: list[NodeNG] = []\n        \"\"\"The positional arguments being given to the call.\"\"\"\n\n        self.keywords: list[Keyword] = []\n        \"\"\"The keyword arguments being given to the call.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        func: NodeNG | None = None,\n        args: list[NodeNG] | None = None,\n        keywords: list[Keyword] | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param func: What is being called.\n\n        :param args: The positional arguments being given to the call.\n\n        :param keywords: The keyword arguments being given to the call.\n        \"\"\"\n        self.func = func\n        if args is not None:\n            self.args = args\n        if keywords is not None:\n            self.keywords = keywords\n\n    @property\n    def starargs(self) -> list[Starred]:\n        \"\"\"The positional arguments that unpack something.\"\"\"\n        return [arg for arg in self.args if isinstance(arg, Starred)]\n\n    @property\n    def kwargs(self) -> list[Keyword]:\n        \"\"\"The keyword arguments that unpack something.\"\"\"\n        return [keyword for keyword in self.keywords if keyword.arg is None]\n\n    def get_children(self):\n        yield self.func\n\n        yield from self.args\n\n        yield from self.keywords\n\n\nclass Compare(NodeNG):\n    \"\"\"Class representing an :class:`ast.Compare` node.\n\n    A :class:`Compare` node indicates a comparison.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('a <= b <= c')\n    >>> node\n    <Compare l.1 at 0x7f23b2e9e6d8>\n    >>> node.ops\n    [('<=', <Name.b l.1 at 0x7f23b2e9e2b0>), ('<=', <Name.c l.1 at 0x7f23b2e9e390>)]\n    \"\"\"\n\n    _astroid_fields = (\"left\", \"ops\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.left: NodeNG | None = None\n        \"\"\"The value at the left being applied to a comparison operator.\"\"\"\n\n        self.ops: list[tuple[str, NodeNG]] = []\n        \"\"\"The remainder of the operators and their relevant right hand value.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        left: NodeNG | None = None,\n        ops: list[tuple[str, NodeNG]] | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param left: The value at the left being applied to a comparison\n            operator.\n\n        :param ops: The remainder of the operators\n            and their relevant right hand value.\n        \"\"\"\n        self.left = left\n        if ops is not None:\n            self.ops = ops\n\n    def get_children(self):\n        \"\"\"Get the child nodes below this node.\n\n        Overridden to handle the tuple fields and skip returning the operator\n        strings.\n\n        :returns: The children.\n        :rtype: iterable(NodeNG)\n        \"\"\"\n        yield self.left\n        for _, comparator in self.ops:\n            yield comparator  # we don't want the 'op'\n\n    def last_child(self):\n        \"\"\"An optimized version of list(get_children())[-1]\n\n        :returns: The last child.\n        :rtype: NodeNG\n        \"\"\"\n        # XXX maybe if self.ops:\n        return self.ops[-1][1]\n        # return self.left\n\n\nclass Comprehension(NodeNG):\n    \"\"\"Class representing an :class:`ast.comprehension` node.\n\n    A :class:`Comprehension` indicates the loop inside any type of\n    comprehension including generator expressions.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('[x for x in some_values]')\n    >>> list(node.get_children())\n    [<Name.x l.1 at 0x7f23b2e352b0>, <Comprehension l.1 at 0x7f23b2e35320>]\n    >>> list(node.get_children())[1].as_string()\n    'for x in some_values'\n    \"\"\"\n\n    _astroid_fields = (\"target\", \"iter\", \"ifs\")\n    _other_fields = (\"is_async\",)\n\n    optional_assign = True\n    \"\"\"Whether this node optionally assigns a variable.\"\"\"\n\n    lineno: None\n    col_offset: None\n    end_lineno: None\n    end_col_offset: None\n\n    def __init__(self, parent: NodeNG | None = None) -> None:\n        \"\"\"\n        :param parent: The parent node in the syntax tree.\n        \"\"\"\n        self.target: NodeNG | None = None\n        \"\"\"What is assigned to by the comprehension.\"\"\"\n\n        self.iter: NodeNG | None = None\n        \"\"\"What is iterated over by the comprehension.\"\"\"\n\n        self.ifs: list[NodeNG] = []\n        \"\"\"The contents of any if statements that filter the comprehension.\"\"\"\n\n        self.is_async: bool | None = None\n        \"\"\"Whether this is an asynchronous comprehension or not.\"\"\"\n\n        super().__init__(parent=parent)\n\n    # pylint: disable=redefined-builtin; same name as builtin ast module.\n    def postinit(\n        self,\n        target: NodeNG | None = None,\n        iter: NodeNG | None = None,\n        ifs: list[NodeNG] | None = None,\n        is_async: bool | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param target: What is assigned to by the comprehension.\n\n        :param iter: What is iterated over by the comprehension.\n\n        :param ifs: The contents of any if statements that filter\n            the comprehension.\n\n        :param is_async: Whether this is an asynchronous comprehension or not.\n        \"\"\"\n        self.target = target\n        self.iter = iter\n        if ifs is not None:\n            self.ifs = ifs\n        self.is_async = is_async\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[Comprehension]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def assign_type(self):\n        \"\"\"The type of assignment that this node performs.\n\n        :returns: The assignment type.\n        :rtype: NodeNG\n        \"\"\"\n        return self\n\n    def _get_filtered_stmts(self, lookup_node, node, stmts, mystmt: Statement | None):\n        \"\"\"method used in filter_stmts\"\"\"\n        if self is mystmt:\n            if isinstance(lookup_node, (Const, Name)):\n                return [lookup_node], True\n\n        elif self.statement(future=True) is mystmt:\n            # original node's statement is the assignment, only keeps\n            # current node (gen exp, list comp)\n\n            return [node], True\n\n        return stmts, False\n\n    def get_children(self):\n        yield self.target\n        yield self.iter\n\n        yield from self.ifs\n\n\nclass Const(mixins.NoChildrenMixin, NodeNG, Instance):\n    \"\"\"Class representing any constant including num, str, bool, None, bytes.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('(5, \"This is a string.\", True, None, b\"bytes\")')\n    >>> node\n    <Tuple.tuple l.1 at 0x7f23b2e358d0>\n    >>> list(node.get_children())\n    [<Const.int l.1 at 0x7f23b2e35940>,\n    <Const.str l.1 at 0x7f23b2e35978>,\n    <Const.bool l.1 at 0x7f23b2e359b0>,\n    <Const.NoneType l.1 at 0x7f23b2e359e8>,\n    <Const.bytes l.1 at 0x7f23b2e35a20>]\n    \"\"\"\n\n    _other_fields = (\"value\", \"kind\")\n\n    def __init__(\n        self,\n        value: Any,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        kind: str | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param value: The value that the constant represents.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param kind: The string prefix. \"u\" for u-prefixed strings and ``None`` otherwise. Python 3.8+ only.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.value: Any = value\n        \"\"\"The value that the constant represents.\"\"\"\n\n        self.kind: str | None = kind  # can be None\n        \"\"\"\"The string prefix. \"u\" for u-prefixed strings and ``None`` otherwise. Python 3.8+ only.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def __getattr__(self, name):\n        # This is needed because of Proxy's __getattr__ method.\n        # Calling object.__new__ on this class without calling\n        # __init__ would result in an infinite loop otherwise\n        # since __getattr__ is called when an attribute doesn't\n        # exist and self._proxied indirectly calls self.value\n        # and Proxy __getattr__ calls self.value\n        if name == \"value\":\n            raise AttributeError\n        return super().__getattr__(name)\n\n    def getitem(self, index, context=None):\n        \"\"\"Get an item from this node if subscriptable.\n\n        :param index: The node to use as a subscript index.\n        :type index: Const or Slice\n\n        :raises AstroidTypeError: When the given index cannot be used as a\n            subscript index, or if this node is not subscriptable.\n        \"\"\"\n        if isinstance(index, Const):\n            index_value = index.value\n        elif isinstance(index, Slice):\n            index_value = _infer_slice(index, context=context)\n\n        else:\n            raise AstroidTypeError(\n                f\"Could not use type {type(index)} as subscript index\"\n            )\n\n        try:\n            if isinstance(self.value, (str, bytes)):\n                return Const(self.value[index_value])\n        except IndexError as exc:\n            raise AstroidIndexError(\n                message=\"Index {index!r} out of range\",\n                node=self,\n                index=index,\n                context=context,\n            ) from exc\n        except TypeError as exc:\n            raise AstroidTypeError(\n                message=\"Type error {error!r}\", node=self, index=index, context=context\n            ) from exc\n\n        raise AstroidTypeError(f\"{self!r} (value={self.value})\")\n\n    def has_dynamic_getattr(self):\n        \"\"\"Check if the node has a custom __getattr__ or __getattribute__.\n\n        :returns: True if the class has a custom\n            __getattr__ or __getattribute__, False otherwise.\n            For a :class:`Const` this is always ``False``.\n        :rtype: bool\n        \"\"\"\n        return False\n\n    def itered(self):\n        \"\"\"An iterator over the elements this node contains.\n\n        :returns: The contents of this node.\n        :rtype: iterable(Const)\n\n        :raises TypeError: If this node does not represent something that is iterable.\n        \"\"\"\n        if isinstance(self.value, str):\n            return [const_factory(elem) for elem in self.value]\n        raise TypeError(f\"Cannot iterate over type {type(self.value)!r}\")\n\n    def pytype(self):\n        \"\"\"Get the name of the type that this node represents.\n\n        :returns: The name of the type.\n        :rtype: str\n        \"\"\"\n        return self._proxied.qname()\n\n    def bool_value(self, context=None):\n        \"\"\"Determine the boolean value of this node.\n\n        :returns: The boolean value of this node.\n        :rtype: bool\n        \"\"\"\n        return bool(self.value)\n\n\nclass Continue(mixins.NoChildrenMixin, Statement):\n    \"\"\"Class representing an :class:`ast.Continue` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('continue')\n    >>> node\n    <Continue l.1 at 0x7f23b2e35588>\n    \"\"\"\n\n\nclass Decorators(NodeNG):\n    \"\"\"A node representing a list of decorators.\n\n    A :class:`Decorators` is the decorators that are applied to\n    a method or function.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    @property\n    def my_property(self):\n        return 3\n    ''')\n    >>> node\n    <FunctionDef.my_property l.2 at 0x7f23b2e35d30>\n    >>> list(node.get_children())[0]\n    <Decorators l.1 at 0x7f23b2e35d68>\n    \"\"\"\n\n    _astroid_fields = (\"nodes\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.nodes: list[NodeNG]\n        \"\"\"The decorators that this node contains.\n\n        :type: list(Name or Call) or None\n        \"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, nodes: list[NodeNG]) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param nodes: The decorators that this node contains.\n        :type nodes: list(Name or Call)\n        \"\"\"\n        self.nodes = nodes\n\n    def scope(self) -> LocalsDictNodeNG:\n        \"\"\"The first parent node defining a new scope.\n        These can be Module, FunctionDef, ClassDef, Lambda, or GeneratorExp nodes.\n\n        :returns: The first parent scope node.\n        \"\"\"\n        # skip the function node to go directly to the upper level scope\n        if not self.parent:\n            raise ParentMissingError(target=self)\n        if not self.parent.parent:\n            raise ParentMissingError(target=self.parent)\n        return self.parent.parent.scope()\n\n    def get_children(self):\n        yield from self.nodes\n\n\nclass DelAttr(mixins.ParentAssignTypeMixin, NodeNG):\n    \"\"\"Variation of :class:`ast.Delete` representing deletion of an attribute.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('del self.attr')\n    >>> node\n    <Delete l.1 at 0x7f23b2e35f60>\n    >>> list(node.get_children())[0]\n    <DelAttr.attr l.1 at 0x7f23b2e411d0>\n    \"\"\"\n\n    _astroid_fields = (\"expr\",)\n    _other_fields = (\"attrname\",)\n\n    @decorators.deprecate_default_argument_values(attrname=\"str\")\n    def __init__(\n        self,\n        attrname: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param attrname: The name of the attribute that is being deleted.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.expr: NodeNG | None = None\n        \"\"\"The name that this node represents.\n\n        :type: Name or None\n        \"\"\"\n\n        self.attrname: str | None = attrname\n        \"\"\"The name of the attribute that is being deleted.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, expr: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param expr: The name that this node represents.\n        :type expr: Name or None\n        \"\"\"\n        self.expr = expr\n\n    def get_children(self):\n        yield self.expr\n\n\nclass Delete(mixins.AssignTypeMixin, Statement):\n    \"\"\"Class representing an :class:`ast.Delete` node.\n\n    A :class:`Delete` is a ``del`` statement this is deleting something.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('del self.attr')\n    >>> node\n    <Delete l.1 at 0x7f23b2e35f60>\n    \"\"\"\n\n    _astroid_fields = (\"targets\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.targets: list[NodeNG] = []\n        \"\"\"What is being deleted.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, targets: list[NodeNG] | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param targets: What is being deleted.\n        \"\"\"\n        if targets is not None:\n            self.targets = targets\n\n    def get_children(self):\n        yield from self.targets\n\n\nclass Dict(NodeNG, Instance):\n    \"\"\"Class representing an :class:`ast.Dict` node.\n\n    A :class:`Dict` is a dictionary that is created with ``{}`` syntax.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('{1: \"1\"}')\n    >>> node\n    <Dict.dict l.1 at 0x7f23b2e35cc0>\n    \"\"\"\n\n    _astroid_fields = (\"items\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.items: list[tuple[NodeNG, NodeNG]] = []\n        \"\"\"The key-value pairs contained in the dictionary.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, items: list[tuple[NodeNG, NodeNG]]) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param items: The key-value pairs contained in the dictionary.\n        \"\"\"\n        self.items = items\n\n    @classmethod\n    def from_elements(cls, items=None):\n        \"\"\"Create a :class:`Dict` of constants from a live dictionary.\n\n        :param items: The items to store in the node.\n        :type items: dict\n\n        :returns: The created dictionary node.\n        :rtype: Dict\n        \"\"\"\n        node = cls()\n        if items is None:\n            node.items = []\n        else:\n            node.items = [\n                (const_factory(k), const_factory(v) if _is_const(v) else v)\n                for k, v in items.items()\n                # The keys need to be constants\n                if _is_const(k)\n            ]\n        return node\n\n    def pytype(self):\n        \"\"\"Get the name of the type that this node represents.\n\n        :returns: The name of the type.\n        :rtype: str\n        \"\"\"\n        return \"builtins.dict\"\n\n    def get_children(self):\n        \"\"\"Get the key and value nodes below this node.\n\n        Children are returned in the order that they are defined in the source\n        code, key first then the value.\n\n        :returns: The children.\n        :rtype: iterable(NodeNG)\n        \"\"\"\n        for key, value in self.items:\n            yield key\n            yield value\n\n    def last_child(self):\n        \"\"\"An optimized version of list(get_children())[-1]\n\n        :returns: The last child, or None if no children exist.\n        :rtype: NodeNG or None\n        \"\"\"\n        if self.items:\n            return self.items[-1][1]\n        return None\n\n    def itered(self):\n        \"\"\"An iterator over the keys this node contains.\n\n        :returns: The keys of this node.\n        :rtype: iterable(NodeNG)\n        \"\"\"\n        return [key for (key, _) in self.items]\n\n    def getitem(self, index, context=None):\n        \"\"\"Get an item from this node.\n\n        :param index: The node to use as a subscript index.\n        :type index: Const or Slice\n\n        :raises AstroidTypeError: When the given index cannot be used as a\n            subscript index, or if this node is not subscriptable.\n        :raises AstroidIndexError: If the given index does not exist in the\n            dictionary.\n        \"\"\"\n        for key, value in self.items:\n            # TODO(cpopa): no support for overriding yet, {1:2, **{1: 3}}.\n            if isinstance(key, DictUnpack):\n                try:\n                    return value.getitem(index, context)\n                except (AstroidTypeError, AstroidIndexError):\n                    continue\n            for inferredkey in key.infer(context):\n                if inferredkey is util.Uninferable:\n                    continue\n                if isinstance(inferredkey, Const) and isinstance(index, Const):\n                    if inferredkey.value == index.value:\n                        return value\n\n        raise AstroidIndexError(index)\n\n    def bool_value(self, context=None):\n        \"\"\"Determine the boolean value of this node.\n\n        :returns: The boolean value of this node.\n        :rtype: bool\n        \"\"\"\n        return bool(self.items)\n\n\nclass Expr(Statement):\n    \"\"\"Class representing an :class:`ast.Expr` node.\n\n    An :class:`Expr` is any expression that does not have its value used or\n    stored.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('method()')\n    >>> node\n    <Call l.1 at 0x7f23b2e352b0>\n    >>> node.parent\n    <Expr l.1 at 0x7f23b2e35278>\n    \"\"\"\n\n    _astroid_fields = (\"value\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.value: NodeNG | None = None\n        \"\"\"What the expression does.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, value: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: What the expression does.\n        \"\"\"\n        self.value = value\n\n    def get_children(self):\n        yield self.value\n\n    def _get_yield_nodes_skip_lambdas(self):\n        if not self.value.is_lambda:\n            yield from self.value._get_yield_nodes_skip_lambdas()\n\n\nclass Ellipsis(mixins.NoChildrenMixin, NodeNG):  # pylint: disable=redefined-builtin\n    \"\"\"Class representing an :class:`ast.Ellipsis` node.\n\n    An :class:`Ellipsis` is the ``...`` syntax.\n\n    Deprecated since v2.6.0 - Use :class:`Const` instead.\n    Will be removed with the release v2.7.0\n    \"\"\"\n\n\nclass EmptyNode(mixins.NoChildrenMixin, NodeNG):\n    \"\"\"Holds an arbitrary object in the :attr:`LocalsDictNodeNG.locals`.\"\"\"\n\n    object = None\n\n\nclass ExceptHandler(mixins.MultiLineBlockMixin, mixins.AssignTypeMixin, Statement):\n    \"\"\"Class representing an :class:`ast.ExceptHandler`. node.\n\n    An :class:`ExceptHandler` is an ``except`` block on a try-except.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n        try:\n            do_something()\n        except Exception as error:\n            print(\"Error!\")\n        ''')\n    >>> node\n    <TryExcept l.2 at 0x7f23b2e9d908>\n    >>> node.handlers\n    [<ExceptHandler l.4 at 0x7f23b2e9e860>]\n    \"\"\"\n\n    _astroid_fields = (\"type\", \"name\", \"body\")\n    _multi_line_block_fields = (\"body\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.type: NodeNG | None = None  # can be None\n        \"\"\"The types that the block handles.\n\n        :type: Tuple or NodeNG or None\n        \"\"\"\n\n        self.name: AssignName | None = None  # can be None\n        \"\"\"The name that the caught exception is assigned to.\"\"\"\n\n        self.body: list[NodeNG] = []\n        \"\"\"The contents of the block.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[ExceptHandler]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def get_children(self):\n        if self.type is not None:\n            yield self.type\n\n        if self.name is not None:\n            yield self.name\n\n        yield from self.body\n\n    # pylint: disable=redefined-builtin; had to use the same name as builtin ast module.\n    def postinit(\n        self,\n        type: NodeNG | None = None,\n        name: AssignName | None = None,\n        body: list[NodeNG] | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param type: The types that the block handles.\n        :type type: Tuple or NodeNG or None\n\n        :param name: The name that the caught exception is assigned to.\n\n        :param body:The contents of the block.\n        \"\"\"\n        self.type = type\n        self.name = name\n        if body is not None:\n            self.body = body\n\n    @cached_property\n    def blockstart_tolineno(self):\n        \"\"\"The line on which the beginning of this block ends.\n\n        :type: int\n        \"\"\"\n        if self.name:\n            return self.name.tolineno\n        if self.type:\n            return self.type.tolineno\n        return self.lineno\n\n    def catch(self, exceptions: list[str] | None) -> bool:\n        \"\"\"Check if this node handles any of the given\n\n        :param exceptions: The names of the exceptions to check for.\n        \"\"\"\n        if self.type is None or exceptions is None:\n            return True\n        return any(node.name in exceptions for node in self.type._get_name_nodes())\n\n\nclass ExtSlice(NodeNG):\n    \"\"\"Class representing an :class:`ast.ExtSlice` node.\n\n    An :class:`ExtSlice` is a complex slice expression.\n\n    Deprecated since v2.6.0 - Now part of the :class:`Subscript` node.\n    Will be removed with the release of v2.7.0\n    \"\"\"\n\n\nclass For(\n    mixins.MultiLineBlockMixin,\n    mixins.BlockRangeMixIn,\n    mixins.AssignTypeMixin,\n    Statement,\n):\n    \"\"\"Class representing an :class:`ast.For` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('for thing in things: print(thing)')\n    >>> node\n    <For l.1 at 0x7f23b2e8cf28>\n    \"\"\"\n\n    _astroid_fields = (\"target\", \"iter\", \"body\", \"orelse\")\n    _other_other_fields = (\"type_annotation\",)\n    _multi_line_block_fields = (\"body\", \"orelse\")\n\n    optional_assign = True\n    \"\"\"Whether this node optionally assigns a variable.\n\n    This is always ``True`` for :class:`For` nodes.\n    \"\"\"\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.target: NodeNG | None = None\n        \"\"\"What the loop assigns to.\"\"\"\n\n        self.iter: NodeNG | None = None\n        \"\"\"What the loop iterates over.\"\"\"\n\n        self.body: list[NodeNG] = []\n        \"\"\"The contents of the body of the loop.\"\"\"\n\n        self.orelse: list[NodeNG] = []\n        \"\"\"The contents of the ``else`` block of the loop.\"\"\"\n\n        self.type_annotation: NodeNG | None = None  # can be None\n        \"\"\"If present, this will contain the type annotation passed by a type comment\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    # pylint: disable=redefined-builtin; had to use the same name as builtin ast module.\n    def postinit(\n        self,\n        target: NodeNG | None = None,\n        iter: NodeNG | None = None,\n        body: list[NodeNG] | None = None,\n        orelse: list[NodeNG] | None = None,\n        type_annotation: NodeNG | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param target: What the loop assigns to.\n\n        :param iter: What the loop iterates over.\n\n        :param body: The contents of the body of the loop.\n\n        :param orelse: The contents of the ``else`` block of the loop.\n        \"\"\"\n        self.target = target\n        self.iter = iter\n        if body is not None:\n            self.body = body\n        if orelse is not None:\n            self.orelse = orelse\n        self.type_annotation = type_annotation\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[For]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    @cached_property\n    def blockstart_tolineno(self):\n        \"\"\"The line on which the beginning of this block ends.\n\n        :type: int\n        \"\"\"\n        return self.iter.tolineno\n\n    def get_children(self):\n        yield self.target\n        yield self.iter\n\n        yield from self.body\n        yield from self.orelse\n\n\nclass AsyncFor(For):\n    \"\"\"Class representing an :class:`ast.AsyncFor` node.\n\n    An :class:`AsyncFor` is an asynchronous :class:`For` built with\n    the ``async`` keyword.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    async def func(things):\n        async for thing in things:\n            print(thing)\n    ''')\n    >>> node\n    <AsyncFunctionDef.func l.2 at 0x7f23b2e416d8>\n    >>> node.body[0]\n    <AsyncFor l.3 at 0x7f23b2e417b8>\n    \"\"\"\n\n\nclass Await(NodeNG):\n    \"\"\"Class representing an :class:`ast.Await` node.\n\n    An :class:`Await` is the ``await`` keyword.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    async def func(things):\n        await other_func()\n    ''')\n    >>> node\n    <AsyncFunctionDef.func l.2 at 0x7f23b2e41748>\n    >>> node.body[0]\n    <Expr l.3 at 0x7f23b2e419e8>\n    >>> list(node.body[0].get_children())[0]\n    <Await l.3 at 0x7f23b2e41a20>\n    \"\"\"\n\n    _astroid_fields = (\"value\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.value: NodeNG | None = None\n        \"\"\"What to wait for.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, value: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: What to wait for.\n        \"\"\"\n        self.value = value\n\n    def get_children(self):\n        yield self.value\n\n\nclass ImportFrom(mixins.NoChildrenMixin, mixins.ImportFromMixin, Statement):\n    \"\"\"Class representing an :class:`ast.ImportFrom` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('from my_package import my_module')\n    >>> node\n    <ImportFrom l.1 at 0x7f23b2e415c0>\n    \"\"\"\n\n    _other_fields = (\"modname\", \"names\", \"level\")\n\n    def __init__(\n        self,\n        fromname: str | None,\n        names: list[tuple[str, str | None]],\n        level: int | None = 0,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param fromname: The module that is being imported from.\n\n        :param names: What is being imported from the module.\n\n        :param level: The level of relative import.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.modname: str | None = fromname  # can be None\n        \"\"\"The module that is being imported from.\n\n        This is ``None`` for relative imports.\n        \"\"\"\n\n        self.names: list[tuple[str, str | None]] = names\n        \"\"\"What is being imported from the module.\n\n        Each entry is a :class:`tuple` of the name being imported,\n        and the alias that the name is assigned to (if any).\n        \"\"\"\n\n        # TODO When is 'level' None?\n        self.level: int | None = level  # can be None\n        \"\"\"The level of relative import.\n\n        Essentially this is the number of dots in the import.\n        This is always 0 for absolute imports.\n        \"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n\nclass Attribute(NodeNG):\n    \"\"\"Class representing an :class:`ast.Attribute` node.\"\"\"\n\n    _astroid_fields = (\"expr\",)\n    _other_fields = (\"attrname\",)\n\n    @decorators.deprecate_default_argument_values(attrname=\"str\")\n    def __init__(\n        self,\n        attrname: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param attrname: The name of the attribute.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.expr: NodeNG | None = None\n        \"\"\"The name that this node represents.\n\n        :type: Name or None\n        \"\"\"\n\n        self.attrname: str | None = attrname\n        \"\"\"The name of the attribute.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, expr: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param expr: The name that this node represents.\n        :type expr: Name or None\n        \"\"\"\n        self.expr = expr\n\n    def get_children(self):\n        yield self.expr\n\n\nclass Global(mixins.NoChildrenMixin, Statement):\n    \"\"\"Class representing an :class:`ast.Global` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('global a_global')\n    >>> node\n    <Global l.1 at 0x7f23b2e9de10>\n    \"\"\"\n\n    _other_fields = (\"names\",)\n\n    def __init__(\n        self,\n        names: list[str],\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param names: The names being declared as global.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.names: list[str] = names\n        \"\"\"The names being declared as global.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def _infer_name(self, frame, name):\n        return name\n\n\nclass If(mixins.MultiLineBlockMixin, mixins.BlockRangeMixIn, Statement):\n    \"\"\"Class representing an :class:`ast.If` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('if condition: print(True)')\n    >>> node\n    <If l.1 at 0x7f23b2e9dd30>\n    \"\"\"\n\n    _astroid_fields = (\"test\", \"body\", \"orelse\")\n    _multi_line_block_fields = (\"body\", \"orelse\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.test: NodeNG | None = None\n        \"\"\"The condition that the statement tests.\"\"\"\n\n        self.body: list[NodeNG] = []\n        \"\"\"The contents of the block.\"\"\"\n\n        self.orelse: list[NodeNG] = []\n        \"\"\"The contents of the ``else`` block.\"\"\"\n\n        self.is_orelse: bool = False\n        \"\"\"Whether the if-statement is the orelse-block of another if statement.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        test: NodeNG | None = None,\n        body: list[NodeNG] | None = None,\n        orelse: list[NodeNG] | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param test: The condition that the statement tests.\n\n        :param body: The contents of the block.\n\n        :param orelse: The contents of the ``else`` block.\n        \"\"\"\n        self.test = test\n        if body is not None:\n            self.body = body\n        if orelse is not None:\n            self.orelse = orelse\n        if isinstance(self.parent, If) and self in self.parent.orelse:\n            self.is_orelse = True\n\n    @cached_property\n    def blockstart_tolineno(self):\n        \"\"\"The line on which the beginning of this block ends.\n\n        :type: int\n        \"\"\"\n        return self.test.tolineno\n\n    def block_range(self, lineno):\n        \"\"\"Get a range from the given line number to where this node ends.\n\n        :param lineno: The line number to start the range at.\n        :type lineno: int\n\n        :returns: The range of line numbers that this node belongs to,\n            starting at the given line number.\n        :rtype: tuple(int, int)\n        \"\"\"\n        if lineno == self.body[0].fromlineno:\n            return lineno, lineno\n        if lineno <= self.body[-1].tolineno:\n            return lineno, self.body[-1].tolineno\n        return self._elsed_block_range(lineno, self.orelse, self.body[0].fromlineno - 1)\n\n    def get_children(self):\n        yield self.test\n\n        yield from self.body\n        yield from self.orelse\n\n    def has_elif_block(self):\n        return len(self.orelse) == 1 and isinstance(self.orelse[0], If)\n\n    def _get_yield_nodes_skip_lambdas(self):\n        \"\"\"An If node can contain a Yield node in the test\"\"\"\n        yield from self.test._get_yield_nodes_skip_lambdas()\n        yield from super()._get_yield_nodes_skip_lambdas()\n\n    def is_sys_guard(self) -> bool:\n        \"\"\"Return True if IF stmt is a sys.version_info guard.\n\n        >>> import astroid\n        >>> node = astroid.extract_node('''\n        import sys\n        if sys.version_info > (3, 8):\n            from typing import Literal\n        else:\n            from typing_extensions import Literal\n        ''')\n        >>> node.is_sys_guard()\n        True\n        \"\"\"\n        warnings.warn(\n            \"The 'is_sys_guard' function is deprecated and will be removed in astroid 3.0.0 \"\n            \"It has been moved to pylint and can be imported from 'pylint.checkers.utils' \"\n            \"starting with pylint 2.12\",\n            DeprecationWarning,\n        )\n        if isinstance(self.test, Compare):\n            value = self.test.left\n            if isinstance(value, Subscript):\n                value = value.value\n            if isinstance(value, Attribute) and value.as_string() == \"sys.version_info\":\n                return True\n\n        return False\n\n    def is_typing_guard(self) -> bool:\n        \"\"\"Return True if IF stmt is a typing guard.\n\n        >>> import astroid\n        >>> node = astroid.extract_node('''\n        from typing import TYPE_CHECKING\n        if TYPE_CHECKING:\n            from xyz import a\n        ''')\n        >>> node.is_typing_guard()\n        True\n        \"\"\"\n        warnings.warn(\n            \"The 'is_typing_guard' function is deprecated and will be removed in astroid 3.0.0 \"\n            \"It has been moved to pylint and can be imported from 'pylint.checkers.utils' \"\n            \"starting with pylint 2.12\",\n            DeprecationWarning,\n        )\n        return isinstance(\n            self.test, (Name, Attribute)\n        ) and self.test.as_string().endswith(\"TYPE_CHECKING\")\n\n\nclass IfExp(NodeNG):\n    \"\"\"Class representing an :class:`ast.IfExp` node.\n    >>> import astroid\n    >>> node = astroid.extract_node('value if condition else other')\n    >>> node\n    <IfExp l.1 at 0x7f23b2e9dbe0>\n    \"\"\"\n\n    _astroid_fields = (\"test\", \"body\", \"orelse\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.test: NodeNG | None = None\n        \"\"\"The condition that the statement tests.\"\"\"\n\n        self.body: NodeNG | None = None\n        \"\"\"The contents of the block.\"\"\"\n\n        self.orelse: NodeNG | None = None\n        \"\"\"The contents of the ``else`` block.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        test: NodeNG | None = None,\n        body: NodeNG | None = None,\n        orelse: NodeNG | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param test: The condition that the statement tests.\n\n        :param body: The contents of the block.\n\n        :param orelse: The contents of the ``else`` block.\n        \"\"\"\n        self.test = test\n        self.body = body\n        self.orelse = orelse\n\n    def get_children(self):\n        yield self.test\n        yield self.body\n        yield self.orelse\n\n    def op_left_associative(self):\n        # `1 if True else 2 if False else 3` is parsed as\n        # `1 if True else (2 if False else 3)`\n        return False\n\n\nclass Import(mixins.NoChildrenMixin, mixins.ImportFromMixin, Statement):\n    \"\"\"Class representing an :class:`ast.Import` node.\n    >>> import astroid\n    >>> node = astroid.extract_node('import astroid')\n    >>> node\n    <Import l.1 at 0x7f23b2e4e5c0>\n    \"\"\"\n\n    _other_fields = (\"names\",)\n\n    @decorators.deprecate_default_argument_values(names=\"list[tuple[str, str | None]]\")\n    def __init__(\n        self,\n        names: list[tuple[str, str | None]] | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param names: The names being imported.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.names: list[tuple[str, str | None]] = names or []\n        \"\"\"The names being imported.\n\n        Each entry is a :class:`tuple` of the name being imported,\n        and the alias that the name is assigned to (if any).\n        \"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n\nclass Index(NodeNG):\n    \"\"\"Class representing an :class:`ast.Index` node.\n\n    An :class:`Index` is a simple subscript.\n\n    Deprecated since v2.6.0 - Now part of the :class:`Subscript` node.\n    Will be removed with the release of v2.7.0\n    \"\"\"\n\n\nclass Keyword(NodeNG):\n    \"\"\"Class representing an :class:`ast.keyword` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('function(a_kwarg=True)')\n    >>> node\n    <Call l.1 at 0x7f23b2e9e320>\n    >>> node.keywords\n    [<Keyword l.1 at 0x7f23b2e9e9b0>]\n    \"\"\"\n\n    _astroid_fields = (\"value\",)\n    _other_fields = (\"arg\",)\n\n    def __init__(\n        self,\n        arg: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param arg: The argument being assigned to.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.arg: str | None = arg  # can be None\n        \"\"\"The argument being assigned to.\"\"\"\n\n        self.value: NodeNG | None = None\n        \"\"\"The value being assigned to the keyword argument.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, value: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: The value being assigned to the keyword argument.\n        \"\"\"\n        self.value = value\n\n    def get_children(self):\n        yield self.value\n\n\nclass List(BaseContainer):\n    \"\"\"Class representing an :class:`ast.List` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('[1, 2, 3]')\n    >>> node\n    <List.list l.1 at 0x7f23b2e9e128>\n    \"\"\"\n\n    _other_fields = (\"ctx\",)\n\n    def __init__(\n        self,\n        ctx: Context | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param ctx: Whether the list is assigned to or loaded from.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.ctx: Context | None = ctx\n        \"\"\"Whether the list is assigned to or loaded from.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[List]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def pytype(self):\n        \"\"\"Get the name of the type that this node represents.\n\n        :returns: The name of the type.\n        :rtype: str\n        \"\"\"\n        return \"builtins.list\"\n\n    def getitem(self, index, context=None):\n        \"\"\"Get an item from this node.\n\n        :param index: The node to use as a subscript index.\n        :type index: Const or Slice\n        \"\"\"\n        return _container_getitem(self, self.elts, index, context=context)\n\n\nclass Nonlocal(mixins.NoChildrenMixin, Statement):\n    \"\"\"Class representing an :class:`ast.Nonlocal` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    def function():\n        nonlocal var\n    ''')\n    >>> node\n    <FunctionDef.function l.2 at 0x7f23b2e9e208>\n    >>> node.body[0]\n    <Nonlocal l.3 at 0x7f23b2e9e908>\n    \"\"\"\n\n    _other_fields = (\"names\",)\n\n    def __init__(\n        self,\n        names: list[str],\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param names: The names being declared as not local.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.names: list[str] = names\n        \"\"\"The names being declared as not local.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def _infer_name(self, frame, name):\n        return name\n\n\nclass Pass(mixins.NoChildrenMixin, Statement):\n    \"\"\"Class representing an :class:`ast.Pass` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('pass')\n    >>> node\n    <Pass l.1 at 0x7f23b2e9e748>\n    \"\"\"\n\n\nclass Raise(Statement):\n    \"\"\"Class representing an :class:`ast.Raise` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('raise RuntimeError(\"Something bad happened!\")')\n    >>> node\n    <Raise l.1 at 0x7f23b2e9e828>\n    \"\"\"\n\n    _astroid_fields = (\"exc\", \"cause\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.exc: NodeNG | None = None  # can be None\n        \"\"\"What is being raised.\"\"\"\n\n        self.cause: NodeNG | None = None  # can be None\n        \"\"\"The exception being used to raise this one.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        exc: NodeNG | None = None,\n        cause: NodeNG | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param exc: What is being raised.\n\n        :param cause: The exception being used to raise this one.\n        \"\"\"\n        self.exc = exc\n        self.cause = cause\n\n    def raises_not_implemented(self):\n        \"\"\"Check if this node raises a :class:`NotImplementedError`.\n\n        :returns: True if this node raises a :class:`NotImplementedError`,\n            False otherwise.\n        :rtype: bool\n        \"\"\"\n        if not self.exc:\n            return False\n        return any(\n            name.name == \"NotImplementedError\" for name in self.exc._get_name_nodes()\n        )\n\n    def get_children(self):\n        if self.exc is not None:\n            yield self.exc\n\n        if self.cause is not None:\n            yield self.cause\n\n\nclass Return(Statement):\n    \"\"\"Class representing an :class:`ast.Return` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('return True')\n    >>> node\n    <Return l.1 at 0x7f23b8211908>\n    \"\"\"\n\n    _astroid_fields = (\"value\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.value: NodeNG | None = None  # can be None\n        \"\"\"The value being returned.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, value: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: The value being returned.\n        \"\"\"\n        self.value = value\n\n    def get_children(self):\n        if self.value is not None:\n            yield self.value\n\n    def is_tuple_return(self):\n        return isinstance(self.value, Tuple)\n\n    def _get_return_nodes_skip_functions(self):\n        yield self\n\n\nclass Set(BaseContainer):\n    \"\"\"Class representing an :class:`ast.Set` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('{1, 2, 3}')\n    >>> node\n    <Set.set l.1 at 0x7f23b2e71d68>\n    \"\"\"\n\n    def pytype(self):\n        \"\"\"Get the name of the type that this node represents.\n\n        :returns: The name of the type.\n        :rtype: str\n        \"\"\"\n        return \"builtins.set\"\n\n\nclass Slice(NodeNG):\n    \"\"\"Class representing an :class:`ast.Slice` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('things[1:3]')\n    >>> node\n    <Subscript l.1 at 0x7f23b2e71f60>\n    >>> node.slice\n    <Slice l.1 at 0x7f23b2e71e80>\n    \"\"\"\n\n    _astroid_fields = (\"lower\", \"upper\", \"step\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.lower: NodeNG | None = None  # can be None\n        \"\"\"The lower index in the slice.\"\"\"\n\n        self.upper: NodeNG | None = None  # can be None\n        \"\"\"The upper index in the slice.\"\"\"\n\n        self.step: NodeNG | None = None  # can be None\n        \"\"\"The step to take between indexes.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        lower: NodeNG | None = None,\n        upper: NodeNG | None = None,\n        step: NodeNG | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param lower: The lower index in the slice.\n\n        :param upper: The upper index in the slice.\n\n        :param step: The step to take between index.\n        \"\"\"\n        self.lower = lower\n        self.upper = upper\n        self.step = step\n\n    def _wrap_attribute(self, attr):\n        \"\"\"Wrap the empty attributes of the Slice in a Const node.\"\"\"\n        if not attr:\n            const = const_factory(attr)\n            const.parent = self\n            return const\n        return attr\n\n    @cached_property\n    def _proxied(self):\n        builtins = AstroidManager().builtins_module\n        return builtins.getattr(\"slice\")[0]\n\n    def pytype(self):\n        \"\"\"Get the name of the type that this node represents.\n\n        :returns: The name of the type.\n        :rtype: str\n        \"\"\"\n        return \"builtins.slice\"\n\n    def igetattr(self, attrname, context=None):\n        \"\"\"Infer the possible values of the given attribute on the slice.\n\n        :param attrname: The name of the attribute to infer.\n        :type attrname: str\n\n        :returns: The inferred possible values.\n        :rtype: iterable(NodeNG)\n        \"\"\"\n        if attrname == \"start\":\n            yield self._wrap_attribute(self.lower)\n        elif attrname == \"stop\":\n            yield self._wrap_attribute(self.upper)\n        elif attrname == \"step\":\n            yield self._wrap_attribute(self.step)\n        else:\n            yield from self.getattr(attrname, context=context)\n\n    def getattr(self, attrname, context=None):\n        return self._proxied.getattr(attrname, context)\n\n    def get_children(self):\n        if self.lower is not None:\n            yield self.lower\n\n        if self.upper is not None:\n            yield self.upper\n\n        if self.step is not None:\n            yield self.step\n\n\nclass Starred(mixins.ParentAssignTypeMixin, NodeNG):\n    \"\"\"Class representing an :class:`ast.Starred` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('*args')\n    >>> node\n    <Starred l.1 at 0x7f23b2e41978>\n    \"\"\"\n\n    _astroid_fields = (\"value\",)\n    _other_fields = (\"ctx\",)\n\n    def __init__(\n        self,\n        ctx: Context | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param ctx: Whether the list is assigned to or loaded from.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.value: NodeNG | None = None\n        \"\"\"What is being unpacked.\"\"\"\n\n        self.ctx: Context | None = ctx\n        \"\"\"Whether the starred item is assigned to or loaded from.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, value: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: What is being unpacked.\n        \"\"\"\n        self.value = value\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[Starred]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def get_children(self):\n        yield self.value\n\n\nclass Subscript(NodeNG):\n    \"\"\"Class representing an :class:`ast.Subscript` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('things[1:3]')\n    >>> node\n    <Subscript l.1 at 0x7f23b2e71f60>\n    \"\"\"\n\n    _astroid_fields = (\"value\", \"slice\")\n    _other_fields = (\"ctx\",)\n\n    def __init__(\n        self,\n        ctx: Context | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param ctx: Whether the subscripted item is assigned to or loaded from.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.value: NodeNG | None = None\n        \"\"\"What is being indexed.\"\"\"\n\n        self.slice: NodeNG | None = None\n        \"\"\"The slice being used to lookup.\"\"\"\n\n        self.ctx: Context | None = ctx\n        \"\"\"Whether the subscripted item is assigned to or loaded from.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    # pylint: disable=redefined-builtin; had to use the same name as builtin ast module.\n    def postinit(\n        self, value: NodeNG | None = None, slice: NodeNG | None = None\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: What is being indexed.\n\n        :param slice: The slice being used to lookup.\n        \"\"\"\n        self.value = value\n        self.slice = slice\n\n    def get_children(self):\n        yield self.value\n        yield self.slice\n\n\nclass TryExcept(mixins.MultiLineBlockMixin, mixins.BlockRangeMixIn, Statement):\n    \"\"\"Class representing an :class:`ast.TryExcept` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n        try:\n            do_something()\n        except Exception as error:\n            print(\"Error!\")\n        ''')\n    >>> node\n    <TryExcept l.2 at 0x7f23b2e9d908>\n    \"\"\"\n\n    _astroid_fields = (\"body\", \"handlers\", \"orelse\")\n    _multi_line_block_fields = (\"body\", \"handlers\", \"orelse\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.body: list[NodeNG] = []\n        \"\"\"The contents of the block to catch exceptions from.\"\"\"\n\n        self.handlers: list[ExceptHandler] = []\n        \"\"\"The exception handlers.\"\"\"\n\n        self.orelse: list[NodeNG] = []\n        \"\"\"The contents of the ``else`` block.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        body: list[NodeNG] | None = None,\n        handlers: list[ExceptHandler] | None = None,\n        orelse: list[NodeNG] | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param body: The contents of the block to catch exceptions from.\n\n        :param handlers: The exception handlers.\n\n        :param orelse: The contents of the ``else`` block.\n        \"\"\"\n        if body is not None:\n            self.body = body\n        if handlers is not None:\n            self.handlers = handlers\n        if orelse is not None:\n            self.orelse = orelse\n\n    def _infer_name(self, frame, name):\n        return name\n\n    def block_range(self, lineno):\n        \"\"\"Get a range from the given line number to where this node ends.\n\n        :param lineno: The line number to start the range at.\n        :type lineno: int\n\n        :returns: The range of line numbers that this node belongs to,\n            starting at the given line number.\n        :rtype: tuple(int, int)\n        \"\"\"\n        last = None\n        for exhandler in self.handlers:\n            if exhandler.type and lineno == exhandler.type.fromlineno:\n                return lineno, lineno\n            if exhandler.body[0].fromlineno <= lineno <= exhandler.body[-1].tolineno:\n                return lineno, exhandler.body[-1].tolineno\n            if last is None:\n                last = exhandler.body[0].fromlineno - 1\n        return self._elsed_block_range(lineno, self.orelse, last)\n\n    def get_children(self):\n        yield from self.body\n\n        yield from self.handlers or ()\n        yield from self.orelse or ()\n\n\nclass TryFinally(mixins.MultiLineBlockMixin, mixins.BlockRangeMixIn, Statement):\n    \"\"\"Class representing an :class:`ast.TryFinally` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    try:\n        do_something()\n    except Exception as error:\n        print(\"Error!\")\n    finally:\n        print(\"Cleanup!\")\n    ''')\n    >>> node\n    <TryFinally l.2 at 0x7f23b2e41d68>\n    \"\"\"\n\n    _astroid_fields = (\"body\", \"finalbody\")\n    _multi_line_block_fields = (\"body\", \"finalbody\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.body: list[NodeNG | TryExcept] = []\n        \"\"\"The try-except that the finally is attached to.\"\"\"\n\n        self.finalbody: list[NodeNG] = []\n        \"\"\"The contents of the ``finally`` block.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        body: list[NodeNG | TryExcept] | None = None,\n        finalbody: list[NodeNG] | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param body: The try-except that the finally is attached to.\n\n        :param finalbody: The contents of the ``finally`` block.\n        \"\"\"\n        if body is not None:\n            self.body = body\n        if finalbody is not None:\n            self.finalbody = finalbody\n\n    def block_range(self, lineno):\n        \"\"\"Get a range from the given line number to where this node ends.\n\n        :param lineno: The line number to start the range at.\n        :type lineno: int\n\n        :returns: The range of line numbers that this node belongs to,\n            starting at the given line number.\n        :rtype: tuple(int, int)\n        \"\"\"\n        child = self.body[0]\n        # py2.5 try: except: finally:\n        if (\n            isinstance(child, TryExcept)\n            and child.fromlineno == self.fromlineno\n            and child.tolineno >= lineno > self.fromlineno\n        ):\n            return child.block_range(lineno)\n        return self._elsed_block_range(lineno, self.finalbody)\n\n    def get_children(self):\n        yield from self.body\n        yield from self.finalbody\n\n\nclass Tuple(BaseContainer):\n    \"\"\"Class representing an :class:`ast.Tuple` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('(1, 2, 3)')\n    >>> node\n    <Tuple.tuple l.1 at 0x7f23b2e41780>\n    \"\"\"\n\n    _other_fields = (\"ctx\",)\n\n    def __init__(\n        self,\n        ctx: Context | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param ctx: Whether the tuple is assigned to or loaded from.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.ctx: Context | None = ctx\n        \"\"\"Whether the tuple is assigned to or loaded from.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[Tuple]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def pytype(self):\n        \"\"\"Get the name of the type that this node represents.\n\n        :returns: The name of the type.\n        :rtype: str\n        \"\"\"\n        return \"builtins.tuple\"\n\n    def getitem(self, index, context=None):\n        \"\"\"Get an item from this node.\n\n        :param index: The node to use as a subscript index.\n        :type index: Const or Slice\n        \"\"\"\n        return _container_getitem(self, self.elts, index, context=context)\n\n\nclass UnaryOp(NodeNG):\n    \"\"\"Class representing an :class:`ast.UnaryOp` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('-5')\n    >>> node\n    <UnaryOp l.1 at 0x7f23b2e4e198>\n    \"\"\"\n\n    _astroid_fields = (\"operand\",)\n    _other_fields = (\"op\",)\n\n    @decorators.deprecate_default_argument_values(op=\"str\")\n    def __init__(\n        self,\n        op: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param op: The operator.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.op: str | None = op\n        \"\"\"The operator.\"\"\"\n\n        self.operand: NodeNG | None = None\n        \"\"\"What the unary operator is applied to.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, operand: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param operand: What the unary operator is applied to.\n        \"\"\"\n        self.operand = operand\n\n    # This is set by inference.py\n    def _infer_unaryop(self, context=None):\n        raise NotImplementedError\n\n    def type_errors(self, context=None):\n        \"\"\"Get a list of type errors which can occur during inference.\n\n        Each TypeError is represented by a :class:`BadBinaryOperationMessage`,\n        which holds the original exception.\n\n        :returns: The list of possible type errors.\n        :rtype: list(BadBinaryOperationMessage)\n        \"\"\"\n        try:\n            results = self._infer_unaryop(context=context)\n            return [\n                result\n                for result in results\n                if isinstance(result, util.BadUnaryOperationMessage)\n            ]\n        except InferenceError:\n            return []\n\n    def get_children(self):\n        yield self.operand\n\n    def op_precedence(self):\n        if self.op == \"not\":\n            return OP_PRECEDENCE[self.op]\n\n        return super().op_precedence()\n\n\nclass While(mixins.MultiLineBlockMixin, mixins.BlockRangeMixIn, Statement):\n    \"\"\"Class representing an :class:`ast.While` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    while condition():\n        print(\"True\")\n    ''')\n    >>> node\n    <While l.2 at 0x7f23b2e4e390>\n    \"\"\"\n\n    _astroid_fields = (\"test\", \"body\", \"orelse\")\n    _multi_line_block_fields = (\"body\", \"orelse\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.test: NodeNG | None = None\n        \"\"\"The condition that the loop tests.\"\"\"\n\n        self.body: list[NodeNG] = []\n        \"\"\"The contents of the loop.\"\"\"\n\n        self.orelse: list[NodeNG] = []\n        \"\"\"The contents of the ``else`` block.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        test: NodeNG | None = None,\n        body: list[NodeNG] | None = None,\n        orelse: list[NodeNG] | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param test: The condition that the loop tests.\n\n        :param body: The contents of the loop.\n\n        :param orelse: The contents of the ``else`` block.\n        \"\"\"\n        self.test = test\n        if body is not None:\n            self.body = body\n        if orelse is not None:\n            self.orelse = orelse\n\n    @cached_property\n    def blockstart_tolineno(self):\n        \"\"\"The line on which the beginning of this block ends.\n\n        :type: int\n        \"\"\"\n        return self.test.tolineno\n\n    def block_range(self, lineno):\n        \"\"\"Get a range from the given line number to where this node ends.\n\n        :param lineno: The line number to start the range at.\n        :type lineno: int\n\n        :returns: The range of line numbers that this node belongs to,\n            starting at the given line number.\n        :rtype: tuple(int, int)\n        \"\"\"\n        return self._elsed_block_range(lineno, self.orelse)\n\n    def get_children(self):\n        yield self.test\n\n        yield from self.body\n        yield from self.orelse\n\n    def _get_yield_nodes_skip_lambdas(self):\n        \"\"\"A While node can contain a Yield node in the test\"\"\"\n        yield from self.test._get_yield_nodes_skip_lambdas()\n        yield from super()._get_yield_nodes_skip_lambdas()\n\n\nclass With(\n    mixins.MultiLineBlockMixin,\n    mixins.BlockRangeMixIn,\n    mixins.AssignTypeMixin,\n    Statement,\n):\n    \"\"\"Class representing an :class:`ast.With` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    with open(file_path) as file_:\n        print(file_.read())\n    ''')\n    >>> node\n    <With l.2 at 0x7f23b2e4e710>\n    \"\"\"\n\n    _astroid_fields = (\"items\", \"body\")\n    _other_other_fields = (\"type_annotation\",)\n    _multi_line_block_fields = (\"body\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.items: list[tuple[NodeNG, NodeNG | None]] = []\n        \"\"\"The pairs of context managers and the names they are assigned to.\"\"\"\n\n        self.body: list[NodeNG] = []\n        \"\"\"The contents of the ``with`` block.\"\"\"\n\n        self.type_annotation: NodeNG | None = None  # can be None\n        \"\"\"If present, this will contain the type annotation passed by a type comment\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        items: list[tuple[NodeNG, NodeNG | None]] | None = None,\n        body: list[NodeNG] | None = None,\n        type_annotation: NodeNG | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param items: The pairs of context managers and the names\n            they are assigned to.\n\n        :param body: The contents of the ``with`` block.\n        \"\"\"\n        if items is not None:\n            self.items = items\n        if body is not None:\n            self.body = body\n        self.type_annotation = type_annotation\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[With]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    @cached_property\n    def blockstart_tolineno(self):\n        \"\"\"The line on which the beginning of this block ends.\n\n        :type: int\n        \"\"\"\n        return self.items[-1][0].tolineno\n\n    def get_children(self):\n        \"\"\"Get the child nodes below this node.\n\n        :returns: The children.\n        :rtype: iterable(NodeNG)\n        \"\"\"\n        for expr, var in self.items:\n            yield expr\n            if var:\n                yield var\n        yield from self.body\n\n\nclass AsyncWith(With):\n    \"\"\"Asynchronous ``with`` built with the ``async`` keyword.\"\"\"\n\n\nclass Yield(NodeNG):\n    \"\"\"Class representing an :class:`ast.Yield` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('yield True')\n    >>> node\n    <Yield l.1 at 0x7f23b2e4e5f8>\n    \"\"\"\n\n    _astroid_fields = (\"value\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.value: NodeNG | None = None  # can be None\n        \"\"\"The value to yield.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, value: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: The value to yield.\n        \"\"\"\n        self.value = value\n\n    def get_children(self):\n        if self.value is not None:\n            yield self.value\n\n    def _get_yield_nodes_skip_lambdas(self):\n        yield self\n\n\nclass YieldFrom(Yield):  # TODO value is required, not optional\n    \"\"\"Class representing an :class:`ast.YieldFrom` node.\"\"\"\n\n\nclass DictUnpack(mixins.NoChildrenMixin, NodeNG):\n    \"\"\"Represents the unpacking of dicts into dicts using :pep:`448`.\"\"\"\n\n\nclass FormattedValue(NodeNG):\n    \"\"\"Class representing an :class:`ast.FormattedValue` node.\n\n    Represents a :pep:`498` format string.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('f\"Format {type_}\"')\n    >>> node\n    <JoinedStr l.1 at 0x7f23b2e4ed30>\n    >>> node.values\n    [<Const.str l.1 at 0x7f23b2e4eda0>, <FormattedValue l.1 at 0x7f23b2e4edd8>]\n    \"\"\"\n\n    _astroid_fields = (\"value\", \"format_spec\")\n    _other_fields = (\"conversion\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.value: NodeNG\n        \"\"\"The value to be formatted into the string.\"\"\"\n\n        self.conversion: int | None = None  # can be None\n        \"\"\"The type of formatting to be applied to the value.\n\n        .. seealso::\n            :class:`ast.FormattedValue`\n        \"\"\"\n\n        self.format_spec: NodeNG | None = None  # can be None\n        \"\"\"The formatting to be applied to the value.\n\n        .. seealso::\n            :class:`ast.FormattedValue`\n\n        :type: JoinedStr or None\n        \"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        value: NodeNG,\n        conversion: int | None = None,\n        format_spec: NodeNG | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: The value to be formatted into the string.\n\n        :param conversion: The type of formatting to be applied to the value.\n\n        :param format_spec: The formatting to be applied to the value.\n        :type format_spec: JoinedStr or None\n        \"\"\"\n        self.value = value\n        self.conversion = conversion\n        self.format_spec = format_spec\n\n    def get_children(self):\n        yield self.value\n\n        if self.format_spec is not None:\n            yield self.format_spec\n\n\nclass JoinedStr(NodeNG):\n    \"\"\"Represents a list of string expressions to be joined.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('f\"Format {type_}\"')\n    >>> node\n    <JoinedStr l.1 at 0x7f23b2e4ed30>\n    \"\"\"\n\n    _astroid_fields = (\"values\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.values: list[NodeNG] = []\n        \"\"\"The string expressions to be joined.\n\n        :type: list(FormattedValue or Const)\n        \"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, values: list[NodeNG] | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: The string expressions to be joined.\n\n        :type: list(FormattedValue or Const)\n        \"\"\"\n        if values is not None:\n            self.values = values\n\n    def get_children(self):\n        yield from self.values\n\n\nclass NamedExpr(mixins.AssignTypeMixin, NodeNG):\n    \"\"\"Represents the assignment from the assignment expression\n\n    >>> import astroid\n    >>> module = astroid.parse('if a := 1: pass')\n    >>> module.body[0].test\n    <NamedExpr l.1 at 0x7f23b2e4ed30>\n    \"\"\"\n\n    _astroid_fields = (\"target\", \"value\")\n\n    optional_assign = True\n    \"\"\"Whether this node optionally assigns a variable.\n\n    Since NamedExpr are not always called they do not always assign.\"\"\"\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.target: NodeNG\n        \"\"\"The assignment target\n\n        :type: Name\n        \"\"\"\n\n        self.value: NodeNG\n        \"\"\"The value that gets assigned in the expression\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, target: NodeNG, value: NodeNG) -> None:\n        self.target = target\n        self.value = value\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[NamedExpr]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def frame(\n        self, *, future: Literal[None, True] = None\n    ) -> nodes.FunctionDef | nodes.Module | nodes.ClassDef | nodes.Lambda:\n        \"\"\"The first parent frame node.\n\n        A frame node is a :class:`Module`, :class:`FunctionDef`,\n        or :class:`ClassDef`.\n\n        :returns: The first parent frame node.\n        \"\"\"\n        if not self.parent:\n            raise ParentMissingError(target=self)\n\n        # For certain parents NamedExpr evaluate to the scope of the parent\n        if isinstance(self.parent, (Arguments, Keyword, Comprehension)):\n            if not self.parent.parent:\n                raise ParentMissingError(target=self.parent)\n            if not self.parent.parent.parent:\n                raise ParentMissingError(target=self.parent.parent)\n            return self.parent.parent.parent.frame(future=True)\n\n        return self.parent.frame(future=True)\n\n    def scope(self) -> LocalsDictNodeNG:\n        \"\"\"The first parent node defining a new scope.\n        These can be Module, FunctionDef, ClassDef, Lambda, or GeneratorExp nodes.\n\n        :returns: The first parent scope node.\n        \"\"\"\n        if not self.parent:\n            raise ParentMissingError(target=self)\n\n        # For certain parents NamedExpr evaluate to the scope of the parent\n        if isinstance(self.parent, (Arguments, Keyword, Comprehension)):\n            if not self.parent.parent:\n                raise ParentMissingError(target=self.parent)\n            if not self.parent.parent.parent:\n                raise ParentMissingError(target=self.parent.parent)\n            return self.parent.parent.parent.scope()\n\n        return self.parent.scope()\n\n    def set_local(self, name: str, stmt: AssignName) -> None:\n        \"\"\"Define that the given name is declared in the given statement node.\n        NamedExpr's in Arguments, Keyword or Comprehension are evaluated in their\n        parent's parent scope. So we add to their frame's locals.\n\n        .. seealso:: :meth:`scope`\n\n        :param name: The name that is being defined.\n\n        :param stmt: The statement that defines the given name.\n        \"\"\"\n        self.frame(future=True).set_local(name, stmt)\n\n\nclass Unknown(mixins.AssignTypeMixin, NodeNG):\n    \"\"\"This node represents a node in a constructed AST where\n    introspection is not possible.  At the moment, it's only used in\n    the args attribute of FunctionDef nodes where function signature\n    introspection failed.\n    \"\"\"\n\n    name = \"Unknown\"\n\n    def qname(self):\n        return \"Unknown\"\n\n    def _infer(self, context=None, **kwargs):\n        \"\"\"Inference on an Unknown node immediately terminates.\"\"\"\n        yield util.Uninferable\n\n\nclass EvaluatedObject(NodeNG):\n    \"\"\"Contains an object that has already been inferred\n\n    This class is useful to pre-evaluate a particular node,\n    with the resulting class acting as the non-evaluated node.\n    \"\"\"\n\n    name = \"EvaluatedObject\"\n    _astroid_fields = (\"original\",)\n    _other_fields = (\"value\",)\n\n    def __init__(\n        self, original: NodeNG, value: NodeNG | type[util.Uninferable]\n    ) -> None:\n        self.original: NodeNG = original\n        \"\"\"The original node that has already been evaluated\"\"\"\n\n        self.value: NodeNG | type[util.Uninferable] = value\n        \"\"\"The inferred value\"\"\"\n\n        super().__init__(\n            lineno=self.original.lineno,\n            col_offset=self.original.col_offset,\n            parent=self.original.parent,\n        )\n\n    def _infer(\n        self, context: InferenceContext | None = None\n    ) -> Iterator[NodeNG | type[util.Uninferable]]:\n        yield self.value\n\n\n# Pattern matching #######################################################\n\n\nclass Match(Statement):\n    \"\"\"Class representing a :class:`ast.Match` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case 200:\n            ...\n        case _:\n            ...\n    ''')\n    >>> node\n    <Match l.2 at 0x10c24e170>\n    \"\"\"\n\n    _astroid_fields = (\"subject\", \"cases\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        self.subject: NodeNG\n        self.cases: list[MatchCase]\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        *,\n        subject: NodeNG,\n        cases: list[MatchCase],\n    ) -> None:\n        self.subject = subject\n        self.cases = cases\n\n\nclass Pattern(NodeNG):\n    \"\"\"Base class for all Pattern nodes.\"\"\"\n\n\nclass MatchCase(mixins.MultiLineBlockMixin, NodeNG):\n    \"\"\"Class representing a :class:`ast.match_case` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case 200:\n            ...\n    ''')\n    >>> node.cases[0]\n    <MatchCase l.3 at 0x10c24e590>\n    \"\"\"\n\n    _astroid_fields = (\"pattern\", \"guard\", \"body\")\n    _multi_line_block_fields = (\"body\",)\n\n    lineno: None\n    col_offset: None\n    end_lineno: None\n    end_col_offset: None\n\n    def __init__(self, *, parent: NodeNG | None = None) -> None:\n        self.pattern: Pattern\n        self.guard: NodeNG | None\n        self.body: list[NodeNG]\n        super().__init__(parent=parent)\n\n    def postinit(\n        self,\n        *,\n        pattern: Pattern,\n        guard: NodeNG | None,\n        body: list[NodeNG],\n    ) -> None:\n        self.pattern = pattern\n        self.guard = guard\n        self.body = body\n\n\nclass MatchValue(Pattern):\n    \"\"\"Class representing a :class:`ast.MatchValue` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case 200:\n            ...\n    ''')\n    >>> node.cases[0].pattern\n    <MatchValue l.3 at 0x10c24e200>\n    \"\"\"\n\n    _astroid_fields = (\"value\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        self.value: NodeNG\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, *, value: NodeNG) -> None:\n        self.value = value\n\n\nclass MatchSingleton(Pattern):\n    \"\"\"Class representing a :class:`ast.MatchSingleton` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case True:\n            ...\n        case False:\n            ...\n        case None:\n            ...\n    ''')\n    >>> node.cases[0].pattern\n    <MatchSingleton l.3 at 0x10c2282e0>\n    >>> node.cases[1].pattern\n    <MatchSingleton l.5 at 0x10c228af0>\n    >>> node.cases[2].pattern\n    <MatchSingleton l.7 at 0x10c229f90>\n    \"\"\"\n\n    _other_fields = (\"value\",)\n\n    def __init__(\n        self,\n        *,\n        value: Literal[True, False, None],\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n        parent: NodeNG | None = None,\n    ) -> None:\n        self.value = value\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n\nclass MatchSequence(Pattern):\n    \"\"\"Class representing a :class:`ast.MatchSequence` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case [1, 2]:\n            ...\n        case (1, 2, *_):\n            ...\n    ''')\n    >>> node.cases[0].pattern\n    <MatchSequence l.3 at 0x10ca80d00>\n    >>> node.cases[1].pattern\n    <MatchSequence l.5 at 0x10ca80b20>\n    \"\"\"\n\n    _astroid_fields = (\"patterns\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        self.patterns: list[Pattern]\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, *, patterns: list[Pattern]) -> None:\n        self.patterns = patterns\n\n\nclass MatchMapping(mixins.AssignTypeMixin, Pattern):\n    \"\"\"Class representing a :class:`ast.MatchMapping` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case {1: \"Hello\", 2: \"World\", 3: _, **rest}:\n            ...\n    ''')\n    >>> node.cases[0].pattern\n    <MatchMapping l.3 at 0x10c8a8850>\n    \"\"\"\n\n    _astroid_fields = (\"keys\", \"patterns\", \"rest\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        self.keys: list[NodeNG]\n        self.patterns: list[Pattern]\n        self.rest: AssignName | None\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        *,\n        keys: list[NodeNG],\n        patterns: list[Pattern],\n        rest: AssignName | None,\n    ) -> None:\n        self.keys = keys\n        self.patterns = patterns\n        self.rest = rest\n\n    assigned_stmts: ClassVar[\n        Callable[\n            [\n                MatchMapping,\n                AssignName,\n                InferenceContext | None,\n                None,\n            ],\n            Generator[NodeNG, None, None],\n        ]\n    ]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n\nclass MatchClass(Pattern):\n    \"\"\"Class representing a :class:`ast.MatchClass` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case Point2D(0, 0):\n            ...\n        case Point3D(x=0, y=0, z=0):\n            ...\n    ''')\n    >>> node.cases[0].pattern\n    <MatchClass l.3 at 0x10ca83940>\n    >>> node.cases[1].pattern\n    <MatchClass l.5 at 0x10ca80880>\n    \"\"\"\n\n    _astroid_fields = (\"cls\", \"patterns\", \"kwd_patterns\")\n    _other_fields = (\"kwd_attrs\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        self.cls: NodeNG\n        self.patterns: list[Pattern]\n        self.kwd_attrs: list[str]\n        self.kwd_patterns: list[Pattern]\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        *,\n        cls: NodeNG,\n        patterns: list[Pattern],\n        kwd_attrs: list[str],\n        kwd_patterns: list[Pattern],\n    ) -> None:\n        self.cls = cls\n        self.patterns = patterns\n        self.kwd_attrs = kwd_attrs\n        self.kwd_patterns = kwd_patterns\n\n\nclass MatchStar(mixins.AssignTypeMixin, Pattern):\n    \"\"\"Class representing a :class:`ast.MatchStar` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case [1, *_]:\n            ...\n    ''')\n    >>> node.cases[0].pattern.patterns[1]\n    <MatchStar l.3 at 0x10ca809a0>\n    \"\"\"\n\n    _astroid_fields = (\"name\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        self.name: AssignName | None\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, *, name: AssignName | None) -> None:\n        self.name = name\n\n    assigned_stmts: ClassVar[\n        Callable[\n            [\n                MatchStar,\n                AssignName,\n                InferenceContext | None,\n                None,\n            ],\n            Generator[NodeNG, None, None],\n        ]\n    ]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n\nclass MatchAs(mixins.AssignTypeMixin, Pattern):\n    \"\"\"Class representing a :class:`ast.MatchAs` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case [1, a]:\n            ...\n        case {'key': b}:\n            ...\n        case Point2D(0, 0) as c:\n            ...\n        case d:\n            ...\n    ''')\n    >>> node.cases[0].pattern.patterns[1]\n    <MatchAs l.3 at 0x10d0b2da0>\n    >>> node.cases[1].pattern.patterns[0]\n    <MatchAs l.5 at 0x10d0b2920>\n    >>> node.cases[2].pattern\n    <MatchAs l.7 at 0x10d0b06a0>\n    >>> node.cases[3].pattern\n    <MatchAs l.9 at 0x10d09b880>\n    \"\"\"\n\n    _astroid_fields = (\"pattern\", \"name\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        self.pattern: Pattern | None\n        self.name: AssignName | None\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        *,\n        pattern: Pattern | None,\n        name: AssignName | None,\n    ) -> None:\n        self.pattern = pattern\n        self.name = name\n\n    assigned_stmts: ClassVar[\n        Callable[\n            [\n                MatchAs,\n                AssignName,\n                InferenceContext | None,\n                None,\n            ],\n            Generator[NodeNG, None, None],\n        ]\n    ]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n\nclass MatchOr(Pattern):\n    \"\"\"Class representing a :class:`ast.MatchOr` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case 400 | 401 | 402:\n            ...\n    ''')\n    >>> node.cases[0].pattern\n    <MatchOr l.3 at 0x10d0b0b50>\n    \"\"\"\n\n    _astroid_fields = (\"patterns\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        self.patterns: list[Pattern]\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, *, patterns: list[Pattern]) -> None:\n        self.patterns = patterns\n\n\n# constants ##############################################################\n\nCONST_CLS = {\n    list: List,\n    tuple: Tuple,\n    dict: Dict,\n    set: Set,\n    type(None): Const,\n    type(NotImplemented): Const,\n    type(...): Const,\n}\n\n\ndef _update_const_classes():\n    \"\"\"update constant classes, so the keys of CONST_CLS can be reused\"\"\"\n    klasses = (bool, int, float, complex, str, bytes)\n    for kls in klasses:\n        CONST_CLS[kls] = Const\n\n\n_update_const_classes()\n\n\ndef _two_step_initialization(cls, value):\n    instance = cls()\n    instance.postinit(value)\n    return instance\n\n\ndef _dict_initialization(cls, value):\n    if isinstance(value, dict):\n        value = tuple(value.items())\n    return _two_step_initialization(cls, value)\n\n\n_CONST_CLS_CONSTRUCTORS = {\n    List: _two_step_initialization,\n    Tuple: _two_step_initialization,\n    Dict: _dict_initialization,\n    Set: _two_step_initialization,\n    Const: lambda cls, value: cls(value),\n}\n\n\ndef const_factory(value):\n    \"\"\"return an astroid node for a python value\"\"\"\n    # XXX we should probably be stricter here and only consider stuff in\n    # CONST_CLS or do better treatment: in case where value is not in CONST_CLS,\n    # we should rather recall the builder on this value than returning an empty\n    # node (another option being that const_factory shouldn't be called with something\n    # not in CONST_CLS)\n    assert not isinstance(value, NodeNG)\n\n    # Hack for ignoring elements of a sequence\n    # or a mapping, in order to avoid transforming\n    # each element to an AST. This is fixed in 2.0\n    # and this approach is a temporary hack.\n    if isinstance(value, (list, set, tuple, dict)):\n        elts = []\n    else:\n        elts = value\n\n    try:\n        initializer_cls = CONST_CLS[value.__class__]\n        initializer = _CONST_CLS_CONSTRUCTORS[initializer_cls]\n        return initializer(initializer_cls, elts)\n    except (KeyError, AttributeError):\n        node = EmptyNode()\n        node.object = value\n        return node\n","new_file_content":"# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html\n# For details: https://github.com/PyCQA/astroid/blob/main/LICENSE\n# Copyright (c) https://github.com/PyCQA/astroid/blob/main/CONTRIBUTORS.txt\n\n\"\"\"Module for some node classes. More nodes in scoped_nodes.py\"\"\"\n\nfrom __future__ import annotations\n\nimport abc\nimport itertools\nimport sys\nimport typing\nimport warnings\nfrom collections.abc import Generator, Iterator\nfrom functools import lru_cache\nfrom typing import TYPE_CHECKING, Any, Callable, ClassVar, Optional, TypeVar, Union\n\nfrom astroid import decorators, mixins, util\nfrom astroid.bases import Instance, _infer_stmts\nfrom astroid.const import Context\nfrom astroid.context import InferenceContext\nfrom astroid.exceptions import (\n    AstroidIndexError,\n    AstroidTypeError,\n    InferenceError,\n    NoDefault,\n    ParentMissingError,\n)\nfrom astroid.manager import AstroidManager\nfrom astroid.nodes.const import OP_PRECEDENCE\nfrom astroid.nodes.node_ng import NodeNG\n\nif sys.version_info >= (3, 8):\n    from typing import Literal\nelse:\n    from typing_extensions import Literal\n\nif TYPE_CHECKING:\n    from astroid import nodes\n    from astroid.nodes import LocalsDictNodeNG\n\nif sys.version_info >= (3, 8):\n    from functools import cached_property\nelse:\n    from astroid.decorators import cachedproperty as cached_property\n\n\ndef _is_const(value):\n    return isinstance(value, tuple(CONST_CLS))\n\n\n_NodesT = TypeVar(\"_NodesT\", bound=NodeNG)\n\nAssignedStmtsPossibleNode = Union[\"List\", \"Tuple\", \"AssignName\", \"AssignAttr\", None]\nAssignedStmtsCall = Callable[\n    [\n        _NodesT,\n        AssignedStmtsPossibleNode,\n        Optional[InferenceContext],\n        Optional[typing.List[int]],\n    ],\n    Any,\n]\n\n\n@decorators.raise_if_nothing_inferred\ndef unpack_infer(stmt, context=None):\n    \"\"\"recursively generate nodes inferred by the given statement.\n    If the inferred value is a list or a tuple, recurse on the elements\n    \"\"\"\n    if isinstance(stmt, (List, Tuple)):\n        for elt in stmt.elts:\n            if elt is util.Uninferable:\n                yield elt\n                continue\n            yield from unpack_infer(elt, context)\n        return dict(node=stmt, context=context)\n    # if inferred is a final node, return it and stop\n    inferred = next(stmt.infer(context), util.Uninferable)\n    if inferred is stmt:\n        yield inferred\n        return dict(node=stmt, context=context)\n    # else, infer recursively, except Uninferable object that should be returned as is\n    for inferred in stmt.infer(context):\n        if inferred is util.Uninferable:\n            yield inferred\n        else:\n            yield from unpack_infer(inferred, context)\n\n    return dict(node=stmt, context=context)\n\n\ndef are_exclusive(stmt1, stmt2, exceptions: list[str] | None = None) -> bool:\n    \"\"\"return true if the two given statements are mutually exclusive\n\n    `exceptions` may be a list of exception names. If specified, discard If\n    branches and check one of the statement is in an exception handler catching\n    one of the given exceptions.\n\n    algorithm :\n     1) index stmt1's parents\n     2) climb among stmt2's parents until we find a common parent\n     3) if the common parent is a If or TryExcept statement, look if nodes are\n        in exclusive branches\n    \"\"\"\n    # index stmt1's parents\n    stmt1_parents = {}\n    children = {}\n    previous = stmt1\n    for node in stmt1.node_ancestors():\n        stmt1_parents[node] = 1\n        children[node] = previous\n        previous = node\n    # climb among stmt2's parents until we find a common parent\n    previous = stmt2\n    for node in stmt2.node_ancestors():\n        if node in stmt1_parents:\n            # if the common parent is a If or TryExcept statement, look if\n            # nodes are in exclusive branches\n            if isinstance(node, If) and exceptions is None:\n                if (\n                    node.locate_child(previous)[1]\n                    is not node.locate_child(children[node])[1]\n                ):\n                    return True\n            elif isinstance(node, TryExcept):\n                c2attr, c2node = node.locate_child(previous)\n                c1attr, c1node = node.locate_child(children[node])\n                if c1node is not c2node:\n                    first_in_body_caught_by_handlers = (\n                        c2attr == \"handlers\"\n                        and c1attr == \"body\"\n                        and previous.catch(exceptions)\n                    )\n                    second_in_body_caught_by_handlers = (\n                        c2attr == \"body\"\n                        and c1attr == \"handlers\"\n                        and children[node].catch(exceptions)\n                    )\n                    first_in_else_other_in_handlers = (\n                        c2attr == \"handlers\" and c1attr == \"orelse\"\n                    )\n                    second_in_else_other_in_handlers = (\n                        c2attr == \"orelse\" and c1attr == \"handlers\"\n                    )\n                    if any(\n                        (\n                            first_in_body_caught_by_handlers,\n                            second_in_body_caught_by_handlers,\n                            first_in_else_other_in_handlers,\n                            second_in_else_other_in_handlers,\n                        )\n                    ):\n                        return True\n                elif c2attr == \"handlers\" and c1attr == \"handlers\":\n                    return previous is not children[node]\n            return False\n        previous = node\n    return False\n\n\n# getitem() helpers.\n\n_SLICE_SENTINEL = object()\n\n\ndef _slice_value(index, context=None):\n    \"\"\"Get the value of the given slice index.\"\"\"\n\n    if isinstance(index, Const):\n        if isinstance(index.value, (int, type(None))):\n            return index.value\n    elif index is None:\n        return None\n    else:\n        # Try to infer what the index actually is.\n        # Since we can't return all the possible values,\n        # we'll stop at the first possible value.\n        try:\n            inferred = next(index.infer(context=context))\n        except (InferenceError, StopIteration):\n            pass\n        else:\n            if isinstance(inferred, Const):\n                if isinstance(inferred.value, (int, type(None))):\n                    return inferred.value\n\n    # Use a sentinel, because None can be a valid\n    # value that this function can return,\n    # as it is the case for unspecified bounds.\n    return _SLICE_SENTINEL\n\n\ndef _infer_slice(node, context=None):\n    lower = _slice_value(node.lower, context)\n    upper = _slice_value(node.upper, context)\n    step = _slice_value(node.step, context)\n    if all(elem is not _SLICE_SENTINEL for elem in (lower, upper, step)):\n        return slice(lower, upper, step)\n\n    raise AstroidTypeError(\n        message=\"Could not infer slice used in subscript\",\n        node=node,\n        index=node.parent,\n        context=context,\n    )\n\n\ndef _container_getitem(instance, elts, index, context=None):\n    \"\"\"Get a slice or an item, using the given *index*, for the given sequence.\"\"\"\n    try:\n        if isinstance(index, Slice):\n            index_slice = _infer_slice(index, context=context)\n            new_cls = instance.__class__()\n            new_cls.elts = elts[index_slice]\n            new_cls.parent = instance.parent\n            return new_cls\n        if isinstance(index, Const):\n            return elts[index.value]\n    except IndexError as exc:\n        raise AstroidIndexError(\n            message=\"Index {index!s} out of range\",\n            node=instance,\n            index=index,\n            context=context,\n        ) from exc\n    except TypeError as exc:\n        raise AstroidTypeError(\n            message=\"Type error {error!r}\", node=instance, index=index, context=context\n        ) from exc\n\n    raise AstroidTypeError(f\"Could not use {index} as subscript index\")\n\n\nclass Statement(NodeNG):\n    \"\"\"Statement node adding a few attributes\"\"\"\n\n    is_statement = True\n    \"\"\"Whether this node indicates a statement.\"\"\"\n\n    def next_sibling(self):\n        \"\"\"The next sibling statement node.\n\n        :returns: The next sibling statement node.\n        :rtype: NodeNG or None\n        \"\"\"\n        stmts = self.parent.child_sequence(self)\n        index = stmts.index(self)\n        try:\n            return stmts[index + 1]\n        except IndexError:\n            return None\n\n    def previous_sibling(self):\n        \"\"\"The previous sibling statement.\n\n        :returns: The previous sibling statement node.\n        :rtype: NodeNG or None\n        \"\"\"\n        stmts = self.parent.child_sequence(self)\n        index = stmts.index(self)\n        if index >= 1:\n            return stmts[index - 1]\n        return None\n\n\nclass BaseContainer(\n    mixins.ParentAssignTypeMixin, NodeNG, Instance, metaclass=abc.ABCMeta\n):\n    \"\"\"Base class for Set, FrozenSet, Tuple and List.\"\"\"\n\n    _astroid_fields = (\"elts\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.elts: list[NodeNG] = []\n        \"\"\"The elements in the node.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, elts: list[NodeNG]) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param elts: The list of elements the that node contains.\n        \"\"\"\n        self.elts = elts\n\n    @classmethod\n    def from_elements(cls, elts=None):\n        \"\"\"Create a node of this type from the given list of elements.\n\n        :param elts: The list of elements that the node should contain.\n        :type elts: list(NodeNG)\n\n        :returns: A new node containing the given elements.\n        :rtype: NodeNG\n        \"\"\"\n        node = cls()\n        if elts is None:\n            node.elts = []\n        else:\n            node.elts = [const_factory(e) if _is_const(e) else e for e in elts]\n        return node\n\n    def itered(self):\n        \"\"\"An iterator over the elements this node contains.\n\n        :returns: The contents of this node.\n        :rtype: iterable(NodeNG)\n        \"\"\"\n        return self.elts\n\n    def bool_value(self, context=None):\n        \"\"\"Determine the boolean value of this node.\n\n        :returns: The boolean value of this node.\n        :rtype: bool or Uninferable\n        \"\"\"\n        return bool(self.elts)\n\n    @abc.abstractmethod\n    def pytype(self):\n        \"\"\"Get the name of the type that this node represents.\n\n        :returns: The name of the type.\n        :rtype: str\n        \"\"\"\n\n    def get_children(self):\n        yield from self.elts\n\n\nclass LookupMixIn:\n    \"\"\"Mixin to look up a name in the right scope.\"\"\"\n\n    @lru_cache()  # noqa\n    def lookup(self, name: str) -> tuple[str, list[NodeNG]]:\n        \"\"\"Lookup where the given variable is assigned.\n\n        The lookup starts from self's scope. If self is not a frame itself\n        and the name is found in the inner frame locals, statements will be\n        filtered to remove ignorable statements according to self's location.\n\n        :param name: The name of the variable to find assignments for.\n\n        :returns: The scope node and the list of assignments associated to the\n            given name according to the scope where it has been found (locals,\n            globals or builtin).\n        \"\"\"\n        return self.scope().scope_lookup(self, name)\n\n    def ilookup(self, name):\n        \"\"\"Lookup the inferred values of the given variable.\n\n        :param name: The variable name to find values for.\n        :type name: str\n\n        :returns: The inferred values of the statements returned from\n            :meth:`lookup`.\n        :rtype: iterable\n        \"\"\"\n        frame, stmts = self.lookup(name)\n        context = InferenceContext()\n        return _infer_stmts(stmts, context, frame)\n\n\n# Name classes\n\n\nclass AssignName(\n    mixins.NoChildrenMixin, LookupMixIn, mixins.ParentAssignTypeMixin, NodeNG\n):\n    \"\"\"Variation of :class:`ast.Assign` representing assignment to a name.\n\n    An :class:`AssignName` is the name of something that is assigned to.\n    This includes variables defined in a function signature or in a loop.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('variable = range(10)')\n    >>> node\n    <Assign l.1 at 0x7effe1db8550>\n    >>> list(node.get_children())\n    [<AssignName.variable l.1 at 0x7effe1db8748>, <Call l.1 at 0x7effe1db8630>]\n    >>> list(node.get_children())[0].as_string()\n    'variable'\n    \"\"\"\n\n    _other_fields = (\"name\",)\n\n    @decorators.deprecate_default_argument_values(name=\"str\")\n    def __init__(\n        self,\n        name: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param name: The name that is assigned to.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.name: str | None = name\n        \"\"\"The name that is assigned to.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[AssignName]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n\nclass DelName(\n    mixins.NoChildrenMixin, LookupMixIn, mixins.ParentAssignTypeMixin, NodeNG\n):\n    \"\"\"Variation of :class:`ast.Delete` representing deletion of a name.\n\n    A :class:`DelName` is the name of something that is deleted.\n\n    >>> import astroid\n    >>> node = astroid.extract_node(\"del variable #@\")\n    >>> list(node.get_children())\n    [<DelName.variable l.1 at 0x7effe1da4d30>]\n    >>> list(node.get_children())[0].as_string()\n    'variable'\n    \"\"\"\n\n    _other_fields = (\"name\",)\n\n    @decorators.deprecate_default_argument_values(name=\"str\")\n    def __init__(\n        self,\n        name: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param name: The name that is being deleted.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.name: str | None = name\n        \"\"\"The name that is being deleted.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n\nclass Name(mixins.NoChildrenMixin, LookupMixIn, NodeNG):\n    \"\"\"Class representing an :class:`ast.Name` node.\n\n    A :class:`Name` node is something that is named, but not covered by\n    :class:`AssignName` or :class:`DelName`.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('range(10)')\n    >>> node\n    <Call l.1 at 0x7effe1db8710>\n    >>> list(node.get_children())\n    [<Name.range l.1 at 0x7effe1db86a0>, <Const.int l.1 at 0x7effe1db8518>]\n    >>> list(node.get_children())[0].as_string()\n    'range'\n    \"\"\"\n\n    _other_fields = (\"name\",)\n\n    @decorators.deprecate_default_argument_values(name=\"str\")\n    def __init__(\n        self,\n        name: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param name: The name that this node refers to.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.name: str | None = name\n        \"\"\"The name that this node refers to.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def _get_name_nodes(self):\n        yield self\n\n        for child_node in self.get_children():\n            yield from child_node._get_name_nodes()\n\n\nclass Arguments(mixins.AssignTypeMixin, NodeNG):\n    \"\"\"Class representing an :class:`ast.arguments` node.\n\n    An :class:`Arguments` node represents that arguments in a\n    function definition.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('def foo(bar): pass')\n    >>> node\n    <FunctionDef.foo l.1 at 0x7effe1db8198>\n    >>> node.args\n    <Arguments l.1 at 0x7effe1db82e8>\n    \"\"\"\n\n    # Python 3.4+ uses a different approach regarding annotations,\n    # each argument is a new class, _ast.arg, which exposes an\n    # 'annotation' attribute. In astroid though, arguments are exposed\n    # as is in the Arguments node and the only way to expose annotations\n    # is by using something similar with Python 3.3:\n    #  - we expose 'varargannotation' and 'kwargannotation' of annotations\n    #    of varargs and kwargs.\n    #  - we expose 'annotation', a list with annotations for\n    #    for each normal argument. If an argument doesn't have an\n    #    annotation, its value will be None.\n    _astroid_fields = (\n        \"args\",\n        \"defaults\",\n        \"kwonlyargs\",\n        \"posonlyargs\",\n        \"posonlyargs_annotations\",\n        \"kw_defaults\",\n        \"annotations\",\n        \"varargannotation\",\n        \"kwargannotation\",\n        \"kwonlyargs_annotations\",\n        \"type_comment_args\",\n        \"type_comment_kwonlyargs\",\n        \"type_comment_posonlyargs\",\n    )\n\n    _other_fields = (\"vararg\", \"kwarg\")\n\n    lineno: None\n    col_offset: None\n    end_lineno: None\n    end_col_offset: None\n\n    def __init__(\n        self,\n        vararg: str | None = None,\n        kwarg: str | None = None,\n        parent: NodeNG | None = None,\n    ) -> None:\n        \"\"\"\n        :param vararg: The name of the variable length arguments.\n\n        :param kwarg: The name of the variable length keyword arguments.\n\n        :param parent: The parent node in the syntax tree.\n        \"\"\"\n        super().__init__(parent=parent)\n\n        self.vararg: str | None = vararg  # can be None\n        \"\"\"The name of the variable length arguments.\"\"\"\n\n        self.kwarg: str | None = kwarg  # can be None\n        \"\"\"The name of the variable length keyword arguments.\"\"\"\n\n        self.args: list[AssignName] | None\n        \"\"\"The names of the required arguments.\n\n        Can be None if the associated function does not have a retrievable\n        signature and the arguments are therefore unknown.\n        This can happen with (builtin) functions implemented in C that have\n        incomplete signature information.\n        \"\"\"\n        # TODO: Check if other attributes should also be None when\n        # .args is None.\n\n        self.defaults: list[NodeNG]\n        \"\"\"The default values for arguments that can be passed positionally.\"\"\"\n\n        self.kwonlyargs: list[AssignName]\n        \"\"\"The keyword arguments that cannot be passed positionally.\"\"\"\n\n        self.posonlyargs: list[AssignName] = []\n        \"\"\"The arguments that can only be passed positionally.\"\"\"\n\n        self.kw_defaults: list[NodeNG | None]\n        \"\"\"The default values for keyword arguments that cannot be passed positionally.\"\"\"\n\n        self.annotations: list[NodeNG | None]\n        \"\"\"The type annotations of arguments that can be passed positionally.\"\"\"\n\n        self.posonlyargs_annotations: list[NodeNG | None] = []\n        \"\"\"The type annotations of arguments that can only be passed positionally.\"\"\"\n\n        self.kwonlyargs_annotations: list[NodeNG | None] = []\n        \"\"\"The type annotations of arguments that cannot be passed positionally.\"\"\"\n\n        self.type_comment_args: list[NodeNG | None] = []\n        \"\"\"The type annotation, passed by a type comment, of each argument.\n\n        If an argument does not have a type comment,\n        the value for that argument will be None.\n        \"\"\"\n\n        self.type_comment_kwonlyargs: list[NodeNG | None] = []\n        \"\"\"The type annotation, passed by a type comment, of each keyword only argument.\n\n        If an argument does not have a type comment,\n        the value for that argument will be None.\n        \"\"\"\n\n        self.type_comment_posonlyargs: list[NodeNG | None] = []\n        \"\"\"The type annotation, passed by a type comment, of each positional argument.\n\n        If an argument does not have a type comment,\n        the value for that argument will be None.\n        \"\"\"\n\n        self.varargannotation: NodeNG | None = None  # can be None\n        \"\"\"The type annotation for the variable length arguments.\"\"\"\n\n        self.kwargannotation: NodeNG | None = None  # can be None\n        \"\"\"The type annotation for the variable length keyword arguments.\"\"\"\n\n    # pylint: disable=too-many-arguments\n    def postinit(\n        self,\n        args: list[AssignName] | None,\n        defaults: list[NodeNG],\n        kwonlyargs: list[AssignName],\n        kw_defaults: list[NodeNG | None],\n        annotations: list[NodeNG | None],\n        posonlyargs: list[AssignName] | None = None,\n        kwonlyargs_annotations: list[NodeNG | None] | None = None,\n        posonlyargs_annotations: list[NodeNG | None] | None = None,\n        varargannotation: NodeNG | None = None,\n        kwargannotation: NodeNG | None = None,\n        type_comment_args: list[NodeNG | None] | None = None,\n        type_comment_kwonlyargs: list[NodeNG | None] | None = None,\n        type_comment_posonlyargs: list[NodeNG | None] | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param args: The names of the required arguments.\n\n        :param defaults: The default values for arguments that can be passed\n            positionally.\n\n        :param kwonlyargs: The keyword arguments that cannot be passed\n            positionally.\n\n        :param posonlyargs: The arguments that can only be passed\n            positionally.\n\n        :param kw_defaults: The default values for keyword arguments that\n            cannot be passed positionally.\n\n        :param annotations: The type annotations of arguments that can be\n            passed positionally.\n\n        :param kwonlyargs_annotations: The type annotations of arguments that\n            cannot be passed positionally. This should always be passed in\n            Python 3.\n\n        :param posonlyargs_annotations: The type annotations of arguments that\n            can only be passed positionally. This should always be passed in\n            Python 3.\n\n        :param varargannotation: The type annotation for the variable length\n            arguments.\n\n        :param kwargannotation: The type annotation for the variable length\n            keyword arguments.\n\n        :param type_comment_args: The type annotation,\n            passed by a type comment, of each argument.\n\n        :param type_comment_args: The type annotation,\n            passed by a type comment, of each keyword only argument.\n\n        :param type_comment_args: The type annotation,\n            passed by a type comment, of each positional argument.\n        \"\"\"\n        self.args = args\n        self.defaults = defaults\n        self.kwonlyargs = kwonlyargs\n        if posonlyargs is not None:\n            self.posonlyargs = posonlyargs\n        self.kw_defaults = kw_defaults\n        self.annotations = annotations\n        if kwonlyargs_annotations is not None:\n            self.kwonlyargs_annotations = kwonlyargs_annotations\n        if posonlyargs_annotations is not None:\n            self.posonlyargs_annotations = posonlyargs_annotations\n        self.varargannotation = varargannotation\n        self.kwargannotation = kwargannotation\n        if type_comment_args is not None:\n            self.type_comment_args = type_comment_args\n        if type_comment_kwonlyargs is not None:\n            self.type_comment_kwonlyargs = type_comment_kwonlyargs\n        if type_comment_posonlyargs is not None:\n            self.type_comment_posonlyargs = type_comment_posonlyargs\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[Arguments]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def _infer_name(self, frame, name):\n        if self.parent is frame:\n            return name\n        return None\n\n    @cached_property\n    def fromlineno(self):\n        \"\"\"The first line that this node appears on in the source code.\n\n        :type: int or None\n        \"\"\"\n        lineno = super().fromlineno\n        return max(lineno, self.parent.fromlineno or 0)\n\n    @cached_property\n    def arguments(self):\n        \"\"\"Get all the arguments for this node, including positional only and positional and keyword\"\"\"\n        return list(itertools.chain((self.posonlyargs or ()), self.args or ()))\n\n    def format_args(self):\n        \"\"\"Get the arguments formatted as string.\n\n        :returns: The formatted arguments.\n        :rtype: str\n        \"\"\"\n        result = []\n        positional_only_defaults = []\n        positional_or_keyword_defaults = self.defaults\n        if self.defaults:\n            args = self.args or []\n            positional_or_keyword_defaults = self.defaults[-len(args) :]\n            positional_only_defaults = self.defaults[: len(self.defaults) - len(args)]\n\n        if self.posonlyargs:\n            result.append(\n                _format_args(\n                    self.posonlyargs,\n                    positional_only_defaults,\n                    self.posonlyargs_annotations,\n                )\n            )\n            result.append(\"/\")\n        if self.args:\n            result.append(\n                _format_args(\n                    self.args,\n                    positional_or_keyword_defaults,\n                    getattr(self, \"annotations\", None),\n                )\n            )\n        if self.vararg:\n            result.append(f\"*{self.vararg}\")\n        if self.kwonlyargs:\n            if not self.vararg:\n                result.append(\"*\")\n            result.append(\n                _format_args(\n                    self.kwonlyargs, self.kw_defaults, self.kwonlyargs_annotations\n                )\n            )\n        if self.kwarg:\n            result.append(f\"**{self.kwarg}\")\n        return \", \".join(result)\n\n    def default_value(self, argname):\n        \"\"\"Get the default value for an argument.\n\n        :param argname: The name of the argument to get the default value for.\n        :type argname: str\n\n        :raises NoDefault: If there is no default value defined for the\n            given argument.\n        \"\"\"\n        args = self.arguments\n        index = _find_arg(argname, args)[0]\n        if index is not None:\n            idx = index - (len(args) - len(self.defaults))\n            if idx >= 0:\n                return self.defaults[idx]\n        index = _find_arg(argname, self.kwonlyargs)[0]\n        if index is not None and self.kw_defaults[index] is not None:\n            return self.kw_defaults[index]\n        raise NoDefault(func=self.parent, name=argname)\n\n    def is_argument(self, name):\n        \"\"\"Check if the given name is defined in the arguments.\n\n        :param name: The name to check for.\n        :type name: str\n\n        :returns: True if the given name is defined in the arguments,\n            False otherwise.\n        :rtype: bool\n        \"\"\"\n        if name == self.vararg:\n            return True\n        if name == self.kwarg:\n            return True\n        return (\n            self.find_argname(name, rec=True)[1] is not None\n            or self.kwonlyargs\n            and _find_arg(name, self.kwonlyargs, rec=True)[1] is not None\n        )\n\n    def find_argname(self, argname, rec=False):\n        \"\"\"Get the index and :class:`AssignName` node for given name.\n\n        :param argname: The name of the argument to search for.\n        :type argname: str\n\n        :param rec: Whether or not to include arguments in unpacked tuples\n            in the search.\n        :type rec: bool\n\n        :returns: The index and node for the argument.\n        :rtype: tuple(str or None, AssignName or None)\n        \"\"\"\n        if self.arguments:\n            return _find_arg(argname, self.arguments, rec)\n        return None, None\n\n    def get_children(self):\n        yield from self.posonlyargs or ()\n\n        for elt in self.posonlyargs_annotations:\n            if elt is not None:\n                yield elt\n\n        yield from self.args or ()\n\n        yield from self.defaults\n        yield from self.kwonlyargs\n\n        for elt in self.kw_defaults:\n            if elt is not None:\n                yield elt\n\n        for elt in self.annotations:\n            if elt is not None:\n                yield elt\n\n        if self.varargannotation is not None:\n            yield self.varargannotation\n\n        if self.kwargannotation is not None:\n            yield self.kwargannotation\n\n        for elt in self.kwonlyargs_annotations:\n            if elt is not None:\n                yield elt\n\n\ndef _find_arg(argname, args, rec=False):\n    for i, arg in enumerate(args):\n        if isinstance(arg, Tuple):\n            if rec:\n                found = _find_arg(argname, arg.elts)\n                if found[0] is not None:\n                    return found\n        elif arg.name == argname:\n            return i, arg\n    return None, None\n\n\ndef _format_args(args, defaults=None, annotations=None):\n    values = []\n    if args is None:\n        return \"\"\n    if annotations is None:\n        annotations = []\n    if defaults is not None:\n        default_offset = len(args) - len(defaults)\n    packed = itertools.zip_longest(args, annotations)\n    for i, (arg, annotation) in enumerate(packed):\n        if isinstance(arg, Tuple):\n            values.append(f\"({_format_args(arg.elts)})\")\n        else:\n            argname = arg.name\n            default_sep = \"=\"\n            if annotation is not None:\n                argname += \": \" + annotation.as_string()\n                default_sep = \" = \"\n            values.append(argname)\n\n            if defaults is not None and i >= default_offset:\n                if defaults[i - default_offset] is not None:\n                    values[-1] += default_sep + defaults[i - default_offset].as_string()\n    return \", \".join(values)\n\n\nclass AssignAttr(mixins.ParentAssignTypeMixin, NodeNG):\n    \"\"\"Variation of :class:`ast.Assign` representing assignment to an attribute.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('self.attribute = range(10)')\n    >>> node\n    <Assign l.1 at 0x7effe1d521d0>\n    >>> list(node.get_children())\n    [<AssignAttr.attribute l.1 at 0x7effe1d52320>, <Call l.1 at 0x7effe1d522e8>]\n    >>> list(node.get_children())[0].as_string()\n    'self.attribute'\n    \"\"\"\n\n    _astroid_fields = (\"expr\",)\n    _other_fields = (\"attrname\",)\n\n    @decorators.deprecate_default_argument_values(attrname=\"str\")\n    def __init__(\n        self,\n        attrname: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param attrname: The name of the attribute being assigned to.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.expr: NodeNG | None = None\n        \"\"\"What has the attribute that is being assigned to.\"\"\"\n\n        self.attrname: str | None = attrname\n        \"\"\"The name of the attribute being assigned to.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, expr: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param expr: What has the attribute that is being assigned to.\n        \"\"\"\n        self.expr = expr\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[AssignAttr]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def get_children(self):\n        yield self.expr\n\n\nclass Assert(Statement):\n    \"\"\"Class representing an :class:`ast.Assert` node.\n\n    An :class:`Assert` node represents an assert statement.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('assert len(things) == 10, \"Not enough things\"')\n    >>> node\n    <Assert l.1 at 0x7effe1d527b8>\n    \"\"\"\n\n    _astroid_fields = (\"test\", \"fail\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.test: NodeNG | None = None\n        \"\"\"The test that passes or fails the assertion.\"\"\"\n\n        self.fail: NodeNG | None = None  # can be None\n        \"\"\"The message shown when the assertion fails.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, test: NodeNG | None = None, fail: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param test: The test that passes or fails the assertion.\n\n        :param fail: The message shown when the assertion fails.\n        \"\"\"\n        self.fail = fail\n        self.test = test\n\n    def get_children(self):\n        yield self.test\n\n        if self.fail is not None:\n            yield self.fail\n\n\nclass Assign(mixins.AssignTypeMixin, Statement):\n    \"\"\"Class representing an :class:`ast.Assign` node.\n\n    An :class:`Assign` is a statement where something is explicitly\n    asssigned to.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('variable = range(10)')\n    >>> node\n    <Assign l.1 at 0x7effe1db8550>\n    \"\"\"\n\n    _astroid_fields = (\"targets\", \"value\")\n    _other_other_fields = (\"type_annotation\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.targets: list[NodeNG] = []\n        \"\"\"What is being assigned to.\"\"\"\n\n        self.value: NodeNG | None = None\n        \"\"\"The value being assigned to the variables.\"\"\"\n\n        self.type_annotation: NodeNG | None = None  # can be None\n        \"\"\"If present, this will contain the type annotation passed by a type comment\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        targets: list[NodeNG] | None = None,\n        value: NodeNG | None = None,\n        type_annotation: NodeNG | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param targets: What is being assigned to.\n        :param value: The value being assigned to the variables.\n        :param type_annotation:\n        \"\"\"\n        if targets is not None:\n            self.targets = targets\n        self.value = value\n        self.type_annotation = type_annotation\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[Assign]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def get_children(self):\n        yield from self.targets\n\n        yield self.value\n\n    @decorators.cached\n    def _get_assign_nodes(self):\n        return [self] + list(self.value._get_assign_nodes())\n\n    def _get_yield_nodes_skip_lambdas(self):\n        yield from self.value._get_yield_nodes_skip_lambdas()\n\n\nclass AnnAssign(mixins.AssignTypeMixin, Statement):\n    \"\"\"Class representing an :class:`ast.AnnAssign` node.\n\n    An :class:`AnnAssign` is an assignment with a type annotation.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('variable: List[int] = range(10)')\n    >>> node\n    <AnnAssign l.1 at 0x7effe1d4c630>\n    \"\"\"\n\n    _astroid_fields = (\"target\", \"annotation\", \"value\")\n    _other_fields = (\"simple\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.target: NodeNG | None = None\n        \"\"\"What is being assigned to.\"\"\"\n\n        self.annotation: NodeNG | None = None\n        \"\"\"The type annotation of what is being assigned to.\"\"\"\n\n        self.value: NodeNG | None = None  # can be None\n        \"\"\"The value being assigned to the variables.\"\"\"\n\n        self.simple: int | None = None\n        \"\"\"Whether :attr:`target` is a pure name or a complex statement.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        target: NodeNG,\n        annotation: NodeNG,\n        simple: int,\n        value: NodeNG | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param target: What is being assigned to.\n\n        :param annotation: The type annotation of what is being assigned to.\n\n        :param simple: Whether :attr:`target` is a pure name\n            or a complex statement.\n\n        :param value: The value being assigned to the variables.\n        \"\"\"\n        self.target = target\n        self.annotation = annotation\n        self.value = value\n        self.simple = simple\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[AnnAssign]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def get_children(self):\n        yield self.target\n        yield self.annotation\n\n        if self.value is not None:\n            yield self.value\n\n\nclass AugAssign(mixins.AssignTypeMixin, Statement):\n    \"\"\"Class representing an :class:`ast.AugAssign` node.\n\n    An :class:`AugAssign` is an assignment paired with an operator.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('variable += 1')\n    >>> node\n    <AugAssign l.1 at 0x7effe1db4d68>\n    \"\"\"\n\n    _astroid_fields = (\"target\", \"value\")\n    _other_fields = (\"op\",)\n\n    @decorators.deprecate_default_argument_values(op=\"str\")\n    def __init__(\n        self,\n        op: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param op: The operator that is being combined with the assignment.\n            This includes the equals sign.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.target: NodeNG | None = None\n        \"\"\"What is being assigned to.\"\"\"\n\n        self.op: str | None = op\n        \"\"\"The operator that is being combined with the assignment.\n\n        This includes the equals sign.\n        \"\"\"\n\n        self.value: NodeNG | None = None\n        \"\"\"The value being assigned to the variable.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self, target: NodeNG | None = None, value: NodeNG | None = None\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param target: What is being assigned to.\n\n        :param value: The value being assigned to the variable.\n        \"\"\"\n        self.target = target\n        self.value = value\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[AugAssign]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    # This is set by inference.py\n    def _infer_augassign(self, context=None):\n        raise NotImplementedError\n\n    def type_errors(self, context=None):\n        \"\"\"Get a list of type errors which can occur during inference.\n\n        Each TypeError is represented by a :class:`BadBinaryOperationMessage` ,\n        which holds the original exception.\n\n        :returns: The list of possible type errors.\n        :rtype: list(BadBinaryOperationMessage)\n        \"\"\"\n        try:\n            results = self._infer_augassign(context=context)\n            return [\n                result\n                for result in results\n                if isinstance(result, util.BadBinaryOperationMessage)\n            ]\n        except InferenceError:\n            return []\n\n    def get_children(self):\n        yield self.target\n        yield self.value\n\n    def _get_yield_nodes_skip_lambdas(self):\n        \"\"\"An AugAssign node can contain a Yield node in the value\"\"\"\n        yield from self.value._get_yield_nodes_skip_lambdas()\n        yield from super()._get_yield_nodes_skip_lambdas()\n\n\nclass BinOp(NodeNG):\n    \"\"\"Class representing an :class:`ast.BinOp` node.\n\n    A :class:`BinOp` node is an application of a binary operator.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('a + b')\n    >>> node\n    <BinOp l.1 at 0x7f23b2e8cfd0>\n    \"\"\"\n\n    _astroid_fields = (\"left\", \"right\")\n    _other_fields = (\"op\",)\n\n    @decorators.deprecate_default_argument_values(op=\"str\")\n    def __init__(\n        self,\n        op: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param op: The operator.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.left: NodeNG | None = None\n        \"\"\"What is being applied to the operator on the left side.\"\"\"\n\n        self.op: str | None = op\n        \"\"\"The operator.\"\"\"\n\n        self.right: NodeNG | None = None\n        \"\"\"What is being applied to the operator on the right side.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, left: NodeNG | None = None, right: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param left: What is being applied to the operator on the left side.\n\n        :param right: What is being applied to the operator on the right side.\n        \"\"\"\n        self.left = left\n        self.right = right\n\n    # This is set by inference.py\n    def _infer_binop(self, context=None):\n        raise NotImplementedError\n\n    def type_errors(self, context=None):\n        \"\"\"Get a list of type errors which can occur during inference.\n\n        Each TypeError is represented by a :class:`BadBinaryOperationMessage`,\n        which holds the original exception.\n\n        :returns: The list of possible type errors.\n        :rtype: list(BadBinaryOperationMessage)\n        \"\"\"\n        try:\n            results = self._infer_binop(context=context)\n            return [\n                result\n                for result in results\n                if isinstance(result, util.BadBinaryOperationMessage)\n            ]\n        except InferenceError:\n            return []\n\n    def get_children(self):\n        yield self.left\n        yield self.right\n\n    def op_precedence(self):\n        return OP_PRECEDENCE[self.op]\n\n    def op_left_associative(self):\n        # 2**3**4 == 2**(3**4)\n        return self.op != \"**\"\n\n\nclass BoolOp(NodeNG):\n    \"\"\"Class representing an :class:`ast.BoolOp` node.\n\n    A :class:`BoolOp` is an application of a boolean operator.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('a and b')\n    >>> node\n    <BinOp l.1 at 0x7f23b2e71c50>\n    \"\"\"\n\n    _astroid_fields = (\"values\",)\n    _other_fields = (\"op\",)\n\n    @decorators.deprecate_default_argument_values(op=\"str\")\n    def __init__(\n        self,\n        op: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param op: The operator.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.op: str | None = op\n        \"\"\"The operator.\"\"\"\n\n        self.values: list[NodeNG] = []\n        \"\"\"The values being applied to the operator.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, values: list[NodeNG] | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param values: The values being applied to the operator.\n        \"\"\"\n        if values is not None:\n            self.values = values\n\n    def get_children(self):\n        yield from self.values\n\n    def op_precedence(self):\n        return OP_PRECEDENCE[self.op]\n\n\nclass Break(mixins.NoChildrenMixin, Statement):\n    \"\"\"Class representing an :class:`ast.Break` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('break')\n    >>> node\n    <Break l.1 at 0x7f23b2e9e5c0>\n    \"\"\"\n\n\nclass Call(NodeNG):\n    \"\"\"Class representing an :class:`ast.Call` node.\n\n    A :class:`Call` node is a call to a function, method, etc.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('function()')\n    >>> node\n    <Call l.1 at 0x7f23b2e71eb8>\n    \"\"\"\n\n    _astroid_fields = (\"func\", \"args\", \"keywords\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.func: NodeNG | None = None\n        \"\"\"What is being called.\"\"\"\n\n        self.args: list[NodeNG] = []\n        \"\"\"The positional arguments being given to the call.\"\"\"\n\n        self.keywords: list[Keyword] = []\n        \"\"\"The keyword arguments being given to the call.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        func: NodeNG | None = None,\n        args: list[NodeNG] | None = None,\n        keywords: list[Keyword] | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param func: What is being called.\n\n        :param args: The positional arguments being given to the call.\n\n        :param keywords: The keyword arguments being given to the call.\n        \"\"\"\n        self.func = func\n        if args is not None:\n            self.args = args\n        if keywords is not None:\n            self.keywords = keywords\n\n    @property\n    def starargs(self) -> list[Starred]:\n        \"\"\"The positional arguments that unpack something.\"\"\"\n        return [arg for arg in self.args if isinstance(arg, Starred)]\n\n    @property\n    def kwargs(self) -> list[Keyword]:\n        \"\"\"The keyword arguments that unpack something.\"\"\"\n        return [keyword for keyword in self.keywords if keyword.arg is None]\n\n    def get_children(self):\n        yield self.func\n\n        yield from self.args\n\n        yield from self.keywords\n\n\nclass Compare(NodeNG):\n    \"\"\"Class representing an :class:`ast.Compare` node.\n\n    A :class:`Compare` node indicates a comparison.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('a <= b <= c')\n    >>> node\n    <Compare l.1 at 0x7f23b2e9e6d8>\n    >>> node.ops\n    [('<=', <Name.b l.1 at 0x7f23b2e9e2b0>), ('<=', <Name.c l.1 at 0x7f23b2e9e390>)]\n    \"\"\"\n\n    _astroid_fields = (\"left\", \"ops\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.left: NodeNG | None = None\n        \"\"\"The value at the left being applied to a comparison operator.\"\"\"\n\n        self.ops: list[tuple[str, NodeNG]] = []\n        \"\"\"The remainder of the operators and their relevant right hand value.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        left: NodeNG | None = None,\n        ops: list[tuple[str, NodeNG]] | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param left: The value at the left being applied to a comparison\n            operator.\n\n        :param ops: The remainder of the operators\n            and their relevant right hand value.\n        \"\"\"\n        self.left = left\n        if ops is not None:\n            self.ops = ops\n\n    def get_children(self):\n        \"\"\"Get the child nodes below this node.\n\n        Overridden to handle the tuple fields and skip returning the operator\n        strings.\n\n        :returns: The children.\n        :rtype: iterable(NodeNG)\n        \"\"\"\n        yield self.left\n        for _, comparator in self.ops:\n            yield comparator  # we don't want the 'op'\n\n    def last_child(self):\n        \"\"\"An optimized version of list(get_children())[-1]\n\n        :returns: The last child.\n        :rtype: NodeNG\n        \"\"\"\n        # XXX maybe if self.ops:\n        return self.ops[-1][1]\n        # return self.left\n\n\nclass Comprehension(NodeNG):\n    \"\"\"Class representing an :class:`ast.comprehension` node.\n\n    A :class:`Comprehension` indicates the loop inside any type of\n    comprehension including generator expressions.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('[x for x in some_values]')\n    >>> list(node.get_children())\n    [<Name.x l.1 at 0x7f23b2e352b0>, <Comprehension l.1 at 0x7f23b2e35320>]\n    >>> list(node.get_children())[1].as_string()\n    'for x in some_values'\n    \"\"\"\n\n    _astroid_fields = (\"target\", \"iter\", \"ifs\")\n    _other_fields = (\"is_async\",)\n\n    optional_assign = True\n    \"\"\"Whether this node optionally assigns a variable.\"\"\"\n\n    lineno: None\n    col_offset: None\n    end_lineno: None\n    end_col_offset: None\n\n    def __init__(self, parent: NodeNG | None = None) -> None:\n        \"\"\"\n        :param parent: The parent node in the syntax tree.\n        \"\"\"\n        self.target: NodeNG | None = None\n        \"\"\"What is assigned to by the comprehension.\"\"\"\n\n        self.iter: NodeNG | None = None\n        \"\"\"What is iterated over by the comprehension.\"\"\"\n\n        self.ifs: list[NodeNG] = []\n        \"\"\"The contents of any if statements that filter the comprehension.\"\"\"\n\n        self.is_async: bool | None = None\n        \"\"\"Whether this is an asynchronous comprehension or not.\"\"\"\n\n        super().__init__(parent=parent)\n\n    # pylint: disable=redefined-builtin; same name as builtin ast module.\n    def postinit(\n        self,\n        target: NodeNG | None = None,\n        iter: NodeNG | None = None,\n        ifs: list[NodeNG] | None = None,\n        is_async: bool | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param target: What is assigned to by the comprehension.\n\n        :param iter: What is iterated over by the comprehension.\n\n        :param ifs: The contents of any if statements that filter\n            the comprehension.\n\n        :param is_async: Whether this is an asynchronous comprehension or not.\n        \"\"\"\n        self.target = target\n        self.iter = iter\n        if ifs is not None:\n            self.ifs = ifs\n        self.is_async = is_async\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[Comprehension]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def assign_type(self):\n        \"\"\"The type of assignment that this node performs.\n\n        :returns: The assignment type.\n        :rtype: NodeNG\n        \"\"\"\n        return self\n\n    def _get_filtered_stmts(self, lookup_node, node, stmts, mystmt: Statement | None):\n        \"\"\"method used in filter_stmts\"\"\"\n        if self is mystmt:\n            if isinstance(lookup_node, (Const, Name)):\n                return [lookup_node], True\n\n        elif self.statement(future=True) is mystmt:\n            # original node's statement is the assignment, only keeps\n            # current node (gen exp, list comp)\n\n            return [node], True\n\n        return stmts, False\n\n    def get_children(self):\n        yield self.target\n        yield self.iter\n\n        yield from self.ifs\n\n\nclass Const(mixins.NoChildrenMixin, NodeNG, Instance):\n    \"\"\"Class representing any constant including num, str, bool, None, bytes.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('(5, \"This is a string.\", True, None, b\"bytes\")')\n    >>> node\n    <Tuple.tuple l.1 at 0x7f23b2e358d0>\n    >>> list(node.get_children())\n    [<Const.int l.1 at 0x7f23b2e35940>,\n    <Const.str l.1 at 0x7f23b2e35978>,\n    <Const.bool l.1 at 0x7f23b2e359b0>,\n    <Const.NoneType l.1 at 0x7f23b2e359e8>,\n    <Const.bytes l.1 at 0x7f23b2e35a20>]\n    \"\"\"\n\n    _other_fields = (\"value\", \"kind\")\n\n    def __init__(\n        self,\n        value: Any,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        kind: str | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param value: The value that the constant represents.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param kind: The string prefix. \"u\" for u-prefixed strings and ``None`` otherwise. Python 3.8+ only.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.value: Any = value\n        \"\"\"The value that the constant represents.\"\"\"\n\n        self.kind: str | None = kind  # can be None\n        \"\"\"\"The string prefix. \"u\" for u-prefixed strings and ``None`` otherwise. Python 3.8+ only.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def __getattr__(self, name):\n        # This is needed because of Proxy's __getattr__ method.\n        # Calling object.__new__ on this class without calling\n        # __init__ would result in an infinite loop otherwise\n        # since __getattr__ is called when an attribute doesn't\n        # exist and self._proxied indirectly calls self.value\n        # and Proxy __getattr__ calls self.value\n        if name == \"value\":\n            raise AttributeError\n        return super().__getattr__(name)\n\n    def getitem(self, index, context=None):\n        \"\"\"Get an item from this node if subscriptable.\n\n        :param index: The node to use as a subscript index.\n        :type index: Const or Slice\n\n        :raises AstroidTypeError: When the given index cannot be used as a\n            subscript index, or if this node is not subscriptable.\n        \"\"\"\n        if isinstance(index, Const):\n            index_value = index.value\n        elif isinstance(index, Slice):\n            index_value = _infer_slice(index, context=context)\n\n        else:\n            raise AstroidTypeError(\n                f\"Could not use type {type(index)} as subscript index\"\n            )\n\n        try:\n            if isinstance(self.value, (str, bytes)):\n                return Const(self.value[index_value])\n        except IndexError as exc:\n            raise AstroidIndexError(\n                message=\"Index {index!r} out of range\",\n                node=self,\n                index=index,\n                context=context,\n            ) from exc\n        except TypeError as exc:\n            raise AstroidTypeError(\n                message=\"Type error {error!r}\", node=self, index=index, context=context\n            ) from exc\n\n        raise AstroidTypeError(f\"{self!r} (value={self.value})\")\n\n    def has_dynamic_getattr(self):\n        \"\"\"Check if the node has a custom __getattr__ or __getattribute__.\n\n        :returns: True if the class has a custom\n            __getattr__ or __getattribute__, False otherwise.\n            For a :class:`Const` this is always ``False``.\n        :rtype: bool\n        \"\"\"\n        return False\n\n    def itered(self):\n        \"\"\"An iterator over the elements this node contains.\n\n        :returns: The contents of this node.\n        :rtype: iterable(Const)\n\n        :raises TypeError: If this node does not represent something that is iterable.\n        \"\"\"\n        if isinstance(self.value, str):\n            return [const_factory(elem) for elem in self.value]\n        raise TypeError(f\"Cannot iterate over type {type(self.value)!r}\")\n\n    def pytype(self):\n        \"\"\"Get the name of the type that this node represents.\n\n        :returns: The name of the type.\n        :rtype: str\n        \"\"\"\n        return self._proxied.qname()\n\n    def bool_value(self, context=None):\n        \"\"\"Determine the boolean value of this node.\n\n        :returns: The boolean value of this node.\n        :rtype: bool\n        \"\"\"\n        return bool(self.value)\n\n\nclass Continue(mixins.NoChildrenMixin, Statement):\n    \"\"\"Class representing an :class:`ast.Continue` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('continue')\n    >>> node\n    <Continue l.1 at 0x7f23b2e35588>\n    \"\"\"\n\n\nclass Decorators(NodeNG):\n    \"\"\"A node representing a list of decorators.\n\n    A :class:`Decorators` is the decorators that are applied to\n    a method or function.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    @property\n    def my_property(self):\n        return 3\n    ''')\n    >>> node\n    <FunctionDef.my_property l.2 at 0x7f23b2e35d30>\n    >>> list(node.get_children())[0]\n    <Decorators l.1 at 0x7f23b2e35d68>\n    \"\"\"\n\n    _astroid_fields = (\"nodes\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.nodes: list[NodeNG]\n        \"\"\"The decorators that this node contains.\n\n        :type: list(Name or Call) or None\n        \"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, nodes: list[NodeNG]) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param nodes: The decorators that this node contains.\n        :type nodes: list(Name or Call)\n        \"\"\"\n        self.nodes = nodes\n\n    def scope(self) -> LocalsDictNodeNG:\n        \"\"\"The first parent node defining a new scope.\n        These can be Module, FunctionDef, ClassDef, Lambda, or GeneratorExp nodes.\n\n        :returns: The first parent scope node.\n        \"\"\"\n        # skip the function node to go directly to the upper level scope\n        if not self.parent:\n            raise ParentMissingError(target=self)\n        if not self.parent.parent:\n            raise ParentMissingError(target=self.parent)\n        return self.parent.parent.scope()\n\n    def get_children(self):\n        yield from self.nodes\n\n\nclass DelAttr(mixins.ParentAssignTypeMixin, NodeNG):\n    \"\"\"Variation of :class:`ast.Delete` representing deletion of an attribute.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('del self.attr')\n    >>> node\n    <Delete l.1 at 0x7f23b2e35f60>\n    >>> list(node.get_children())[0]\n    <DelAttr.attr l.1 at 0x7f23b2e411d0>\n    \"\"\"\n\n    _astroid_fields = (\"expr\",)\n    _other_fields = (\"attrname\",)\n\n    @decorators.deprecate_default_argument_values(attrname=\"str\")\n    def __init__(\n        self,\n        attrname: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param attrname: The name of the attribute that is being deleted.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.expr: NodeNG | None = None\n        \"\"\"The name that this node represents.\n\n        :type: Name or None\n        \"\"\"\n\n        self.attrname: str | None = attrname\n        \"\"\"The name of the attribute that is being deleted.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, expr: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param expr: The name that this node represents.\n        :type expr: Name or None\n        \"\"\"\n        self.expr = expr\n\n    def get_children(self):\n        yield self.expr\n\n\nclass Delete(mixins.AssignTypeMixin, Statement):\n    \"\"\"Class representing an :class:`ast.Delete` node.\n\n    A :class:`Delete` is a ``del`` statement this is deleting something.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('del self.attr')\n    >>> node\n    <Delete l.1 at 0x7f23b2e35f60>\n    \"\"\"\n\n    _astroid_fields = (\"targets\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.targets: list[NodeNG] = []\n        \"\"\"What is being deleted.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, targets: list[NodeNG] | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param targets: What is being deleted.\n        \"\"\"\n        if targets is not None:\n            self.targets = targets\n\n    def get_children(self):\n        yield from self.targets\n\n\nclass Dict(NodeNG, Instance):\n    \"\"\"Class representing an :class:`ast.Dict` node.\n\n    A :class:`Dict` is a dictionary that is created with ``{}`` syntax.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('{1: \"1\"}')\n    >>> node\n    <Dict.dict l.1 at 0x7f23b2e35cc0>\n    \"\"\"\n\n    _astroid_fields = (\"items\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.items: list[tuple[NodeNG, NodeNG]] = []\n        \"\"\"The key-value pairs contained in the dictionary.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, items: list[tuple[NodeNG, NodeNG]]) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param items: The key-value pairs contained in the dictionary.\n        \"\"\"\n        self.items = items\n\n    @classmethod\n    def from_elements(cls, items=None):\n        \"\"\"Create a :class:`Dict` of constants from a live dictionary.\n\n        :param items: The items to store in the node.\n        :type items: dict\n\n        :returns: The created dictionary node.\n        :rtype: Dict\n        \"\"\"\n        node = cls()\n        if items is None:\n            node.items = []\n        else:\n            node.items = [\n                (const_factory(k), const_factory(v) if _is_const(v) else v)\n                for k, v in items.items()\n                # The keys need to be constants\n                if _is_const(k)\n            ]\n        return node\n\n    def pytype(self):\n        \"\"\"Get the name of the type that this node represents.\n\n        :returns: The name of the type.\n        :rtype: str\n        \"\"\"\n        return \"builtins.dict\"\n\n    def get_children(self):\n        \"\"\"Get the key and value nodes below this node.\n\n        Children are returned in the order that they are defined in the source\n        code, key first then the value.\n\n        :returns: The children.\n        :rtype: iterable(NodeNG)\n        \"\"\"\n        for key, value in self.items:\n            yield key\n            yield value\n\n    def last_child(self):\n        \"\"\"An optimized version of list(get_children())[-1]\n\n        :returns: The last child, or None if no children exist.\n        :rtype: NodeNG or None\n        \"\"\"\n        if self.items:\n            return self.items[-1][1]\n        return None\n\n    def itered(self):\n        \"\"\"An iterator over the keys this node contains.\n\n        :returns: The keys of this node.\n        :rtype: iterable(NodeNG)\n        \"\"\"\n        return [key for (key, _) in self.items]\n\n    def getitem(\n        self, index: Const | Slice, context: InferenceContext | None = None\n    ) -> NodeNG:\n        \"\"\"Get an item from this node.\n\n        :param index: The node to use as a subscript index.\n\n        :raises AstroidTypeError: When the given index cannot be used as a\n            subscript index, or if this node is not subscriptable.\n        :raises AstroidIndexError: If the given index does not exist in the\n            dictionary.\n        \"\"\"\n        # pylint: disable-next=import-outside-toplevel; circular import\n        from astroid.helpers import safe_infer\n\n        for key, value in self.items:\n            # TODO(cpopa): no support for overriding yet, {1:2, **{1: 3}}.\n            if isinstance(key, DictUnpack):\n                inferred_value = safe_infer(value, context)\n                if not isinstance(inferred_value, Dict):\n                    continue\n\n                try:\n                    return inferred_value.getitem(index, context)\n                except (AstroidTypeError, AstroidIndexError):\n                    continue\n\n            for inferredkey in key.infer(context):\n                if inferredkey is util.Uninferable:\n                    continue\n                if isinstance(inferredkey, Const) and isinstance(index, Const):\n                    if inferredkey.value == index.value:\n                        return value\n\n        raise AstroidIndexError(index)\n\n    def bool_value(self, context=None):\n        \"\"\"Determine the boolean value of this node.\n\n        :returns: The boolean value of this node.\n        :rtype: bool\n        \"\"\"\n        return bool(self.items)\n\n\nclass Expr(Statement):\n    \"\"\"Class representing an :class:`ast.Expr` node.\n\n    An :class:`Expr` is any expression that does not have its value used or\n    stored.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('method()')\n    >>> node\n    <Call l.1 at 0x7f23b2e352b0>\n    >>> node.parent\n    <Expr l.1 at 0x7f23b2e35278>\n    \"\"\"\n\n    _astroid_fields = (\"value\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.value: NodeNG | None = None\n        \"\"\"What the expression does.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, value: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: What the expression does.\n        \"\"\"\n        self.value = value\n\n    def get_children(self):\n        yield self.value\n\n    def _get_yield_nodes_skip_lambdas(self):\n        if not self.value.is_lambda:\n            yield from self.value._get_yield_nodes_skip_lambdas()\n\n\nclass Ellipsis(mixins.NoChildrenMixin, NodeNG):  # pylint: disable=redefined-builtin\n    \"\"\"Class representing an :class:`ast.Ellipsis` node.\n\n    An :class:`Ellipsis` is the ``...`` syntax.\n\n    Deprecated since v2.6.0 - Use :class:`Const` instead.\n    Will be removed with the release v2.7.0\n    \"\"\"\n\n\nclass EmptyNode(mixins.NoChildrenMixin, NodeNG):\n    \"\"\"Holds an arbitrary object in the :attr:`LocalsDictNodeNG.locals`.\"\"\"\n\n    object = None\n\n\nclass ExceptHandler(mixins.MultiLineBlockMixin, mixins.AssignTypeMixin, Statement):\n    \"\"\"Class representing an :class:`ast.ExceptHandler`. node.\n\n    An :class:`ExceptHandler` is an ``except`` block on a try-except.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n        try:\n            do_something()\n        except Exception as error:\n            print(\"Error!\")\n        ''')\n    >>> node\n    <TryExcept l.2 at 0x7f23b2e9d908>\n    >>> node.handlers\n    [<ExceptHandler l.4 at 0x7f23b2e9e860>]\n    \"\"\"\n\n    _astroid_fields = (\"type\", \"name\", \"body\")\n    _multi_line_block_fields = (\"body\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.type: NodeNG | None = None  # can be None\n        \"\"\"The types that the block handles.\n\n        :type: Tuple or NodeNG or None\n        \"\"\"\n\n        self.name: AssignName | None = None  # can be None\n        \"\"\"The name that the caught exception is assigned to.\"\"\"\n\n        self.body: list[NodeNG] = []\n        \"\"\"The contents of the block.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[ExceptHandler]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def get_children(self):\n        if self.type is not None:\n            yield self.type\n\n        if self.name is not None:\n            yield self.name\n\n        yield from self.body\n\n    # pylint: disable=redefined-builtin; had to use the same name as builtin ast module.\n    def postinit(\n        self,\n        type: NodeNG | None = None,\n        name: AssignName | None = None,\n        body: list[NodeNG] | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param type: The types that the block handles.\n        :type type: Tuple or NodeNG or None\n\n        :param name: The name that the caught exception is assigned to.\n\n        :param body:The contents of the block.\n        \"\"\"\n        self.type = type\n        self.name = name\n        if body is not None:\n            self.body = body\n\n    @cached_property\n    def blockstart_tolineno(self):\n        \"\"\"The line on which the beginning of this block ends.\n\n        :type: int\n        \"\"\"\n        if self.name:\n            return self.name.tolineno\n        if self.type:\n            return self.type.tolineno\n        return self.lineno\n\n    def catch(self, exceptions: list[str] | None) -> bool:\n        \"\"\"Check if this node handles any of the given\n\n        :param exceptions: The names of the exceptions to check for.\n        \"\"\"\n        if self.type is None or exceptions is None:\n            return True\n        return any(node.name in exceptions for node in self.type._get_name_nodes())\n\n\nclass ExtSlice(NodeNG):\n    \"\"\"Class representing an :class:`ast.ExtSlice` node.\n\n    An :class:`ExtSlice` is a complex slice expression.\n\n    Deprecated since v2.6.0 - Now part of the :class:`Subscript` node.\n    Will be removed with the release of v2.7.0\n    \"\"\"\n\n\nclass For(\n    mixins.MultiLineBlockMixin,\n    mixins.BlockRangeMixIn,\n    mixins.AssignTypeMixin,\n    Statement,\n):\n    \"\"\"Class representing an :class:`ast.For` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('for thing in things: print(thing)')\n    >>> node\n    <For l.1 at 0x7f23b2e8cf28>\n    \"\"\"\n\n    _astroid_fields = (\"target\", \"iter\", \"body\", \"orelse\")\n    _other_other_fields = (\"type_annotation\",)\n    _multi_line_block_fields = (\"body\", \"orelse\")\n\n    optional_assign = True\n    \"\"\"Whether this node optionally assigns a variable.\n\n    This is always ``True`` for :class:`For` nodes.\n    \"\"\"\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.target: NodeNG | None = None\n        \"\"\"What the loop assigns to.\"\"\"\n\n        self.iter: NodeNG | None = None\n        \"\"\"What the loop iterates over.\"\"\"\n\n        self.body: list[NodeNG] = []\n        \"\"\"The contents of the body of the loop.\"\"\"\n\n        self.orelse: list[NodeNG] = []\n        \"\"\"The contents of the ``else`` block of the loop.\"\"\"\n\n        self.type_annotation: NodeNG | None = None  # can be None\n        \"\"\"If present, this will contain the type annotation passed by a type comment\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    # pylint: disable=redefined-builtin; had to use the same name as builtin ast module.\n    def postinit(\n        self,\n        target: NodeNG | None = None,\n        iter: NodeNG | None = None,\n        body: list[NodeNG] | None = None,\n        orelse: list[NodeNG] | None = None,\n        type_annotation: NodeNG | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param target: What the loop assigns to.\n\n        :param iter: What the loop iterates over.\n\n        :param body: The contents of the body of the loop.\n\n        :param orelse: The contents of the ``else`` block of the loop.\n        \"\"\"\n        self.target = target\n        self.iter = iter\n        if body is not None:\n            self.body = body\n        if orelse is not None:\n            self.orelse = orelse\n        self.type_annotation = type_annotation\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[For]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    @cached_property\n    def blockstart_tolineno(self):\n        \"\"\"The line on which the beginning of this block ends.\n\n        :type: int\n        \"\"\"\n        return self.iter.tolineno\n\n    def get_children(self):\n        yield self.target\n        yield self.iter\n\n        yield from self.body\n        yield from self.orelse\n\n\nclass AsyncFor(For):\n    \"\"\"Class representing an :class:`ast.AsyncFor` node.\n\n    An :class:`AsyncFor` is an asynchronous :class:`For` built with\n    the ``async`` keyword.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    async def func(things):\n        async for thing in things:\n            print(thing)\n    ''')\n    >>> node\n    <AsyncFunctionDef.func l.2 at 0x7f23b2e416d8>\n    >>> node.body[0]\n    <AsyncFor l.3 at 0x7f23b2e417b8>\n    \"\"\"\n\n\nclass Await(NodeNG):\n    \"\"\"Class representing an :class:`ast.Await` node.\n\n    An :class:`Await` is the ``await`` keyword.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    async def func(things):\n        await other_func()\n    ''')\n    >>> node\n    <AsyncFunctionDef.func l.2 at 0x7f23b2e41748>\n    >>> node.body[0]\n    <Expr l.3 at 0x7f23b2e419e8>\n    >>> list(node.body[0].get_children())[0]\n    <Await l.3 at 0x7f23b2e41a20>\n    \"\"\"\n\n    _astroid_fields = (\"value\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.value: NodeNG | None = None\n        \"\"\"What to wait for.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, value: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: What to wait for.\n        \"\"\"\n        self.value = value\n\n    def get_children(self):\n        yield self.value\n\n\nclass ImportFrom(mixins.NoChildrenMixin, mixins.ImportFromMixin, Statement):\n    \"\"\"Class representing an :class:`ast.ImportFrom` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('from my_package import my_module')\n    >>> node\n    <ImportFrom l.1 at 0x7f23b2e415c0>\n    \"\"\"\n\n    _other_fields = (\"modname\", \"names\", \"level\")\n\n    def __init__(\n        self,\n        fromname: str | None,\n        names: list[tuple[str, str | None]],\n        level: int | None = 0,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param fromname: The module that is being imported from.\n\n        :param names: What is being imported from the module.\n\n        :param level: The level of relative import.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.modname: str | None = fromname  # can be None\n        \"\"\"The module that is being imported from.\n\n        This is ``None`` for relative imports.\n        \"\"\"\n\n        self.names: list[tuple[str, str | None]] = names\n        \"\"\"What is being imported from the module.\n\n        Each entry is a :class:`tuple` of the name being imported,\n        and the alias that the name is assigned to (if any).\n        \"\"\"\n\n        # TODO When is 'level' None?\n        self.level: int | None = level  # can be None\n        \"\"\"The level of relative import.\n\n        Essentially this is the number of dots in the import.\n        This is always 0 for absolute imports.\n        \"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n\nclass Attribute(NodeNG):\n    \"\"\"Class representing an :class:`ast.Attribute` node.\"\"\"\n\n    _astroid_fields = (\"expr\",)\n    _other_fields = (\"attrname\",)\n\n    @decorators.deprecate_default_argument_values(attrname=\"str\")\n    def __init__(\n        self,\n        attrname: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param attrname: The name of the attribute.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.expr: NodeNG | None = None\n        \"\"\"The name that this node represents.\n\n        :type: Name or None\n        \"\"\"\n\n        self.attrname: str | None = attrname\n        \"\"\"The name of the attribute.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, expr: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param expr: The name that this node represents.\n        :type expr: Name or None\n        \"\"\"\n        self.expr = expr\n\n    def get_children(self):\n        yield self.expr\n\n\nclass Global(mixins.NoChildrenMixin, Statement):\n    \"\"\"Class representing an :class:`ast.Global` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('global a_global')\n    >>> node\n    <Global l.1 at 0x7f23b2e9de10>\n    \"\"\"\n\n    _other_fields = (\"names\",)\n\n    def __init__(\n        self,\n        names: list[str],\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param names: The names being declared as global.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.names: list[str] = names\n        \"\"\"The names being declared as global.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def _infer_name(self, frame, name):\n        return name\n\n\nclass If(mixins.MultiLineBlockMixin, mixins.BlockRangeMixIn, Statement):\n    \"\"\"Class representing an :class:`ast.If` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('if condition: print(True)')\n    >>> node\n    <If l.1 at 0x7f23b2e9dd30>\n    \"\"\"\n\n    _astroid_fields = (\"test\", \"body\", \"orelse\")\n    _multi_line_block_fields = (\"body\", \"orelse\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.test: NodeNG | None = None\n        \"\"\"The condition that the statement tests.\"\"\"\n\n        self.body: list[NodeNG] = []\n        \"\"\"The contents of the block.\"\"\"\n\n        self.orelse: list[NodeNG] = []\n        \"\"\"The contents of the ``else`` block.\"\"\"\n\n        self.is_orelse: bool = False\n        \"\"\"Whether the if-statement is the orelse-block of another if statement.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        test: NodeNG | None = None,\n        body: list[NodeNG] | None = None,\n        orelse: list[NodeNG] | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param test: The condition that the statement tests.\n\n        :param body: The contents of the block.\n\n        :param orelse: The contents of the ``else`` block.\n        \"\"\"\n        self.test = test\n        if body is not None:\n            self.body = body\n        if orelse is not None:\n            self.orelse = orelse\n        if isinstance(self.parent, If) and self in self.parent.orelse:\n            self.is_orelse = True\n\n    @cached_property\n    def blockstart_tolineno(self):\n        \"\"\"The line on which the beginning of this block ends.\n\n        :type: int\n        \"\"\"\n        return self.test.tolineno\n\n    def block_range(self, lineno):\n        \"\"\"Get a range from the given line number to where this node ends.\n\n        :param lineno: The line number to start the range at.\n        :type lineno: int\n\n        :returns: The range of line numbers that this node belongs to,\n            starting at the given line number.\n        :rtype: tuple(int, int)\n        \"\"\"\n        if lineno == self.body[0].fromlineno:\n            return lineno, lineno\n        if lineno <= self.body[-1].tolineno:\n            return lineno, self.body[-1].tolineno\n        return self._elsed_block_range(lineno, self.orelse, self.body[0].fromlineno - 1)\n\n    def get_children(self):\n        yield self.test\n\n        yield from self.body\n        yield from self.orelse\n\n    def has_elif_block(self):\n        return len(self.orelse) == 1 and isinstance(self.orelse[0], If)\n\n    def _get_yield_nodes_skip_lambdas(self):\n        \"\"\"An If node can contain a Yield node in the test\"\"\"\n        yield from self.test._get_yield_nodes_skip_lambdas()\n        yield from super()._get_yield_nodes_skip_lambdas()\n\n    def is_sys_guard(self) -> bool:\n        \"\"\"Return True if IF stmt is a sys.version_info guard.\n\n        >>> import astroid\n        >>> node = astroid.extract_node('''\n        import sys\n        if sys.version_info > (3, 8):\n            from typing import Literal\n        else:\n            from typing_extensions import Literal\n        ''')\n        >>> node.is_sys_guard()\n        True\n        \"\"\"\n        warnings.warn(\n            \"The 'is_sys_guard' function is deprecated and will be removed in astroid 3.0.0 \"\n            \"It has been moved to pylint and can be imported from 'pylint.checkers.utils' \"\n            \"starting with pylint 2.12\",\n            DeprecationWarning,\n        )\n        if isinstance(self.test, Compare):\n            value = self.test.left\n            if isinstance(value, Subscript):\n                value = value.value\n            if isinstance(value, Attribute) and value.as_string() == \"sys.version_info\":\n                return True\n\n        return False\n\n    def is_typing_guard(self) -> bool:\n        \"\"\"Return True if IF stmt is a typing guard.\n\n        >>> import astroid\n        >>> node = astroid.extract_node('''\n        from typing import TYPE_CHECKING\n        if TYPE_CHECKING:\n            from xyz import a\n        ''')\n        >>> node.is_typing_guard()\n        True\n        \"\"\"\n        warnings.warn(\n            \"The 'is_typing_guard' function is deprecated and will be removed in astroid 3.0.0 \"\n            \"It has been moved to pylint and can be imported from 'pylint.checkers.utils' \"\n            \"starting with pylint 2.12\",\n            DeprecationWarning,\n        )\n        return isinstance(\n            self.test, (Name, Attribute)\n        ) and self.test.as_string().endswith(\"TYPE_CHECKING\")\n\n\nclass IfExp(NodeNG):\n    \"\"\"Class representing an :class:`ast.IfExp` node.\n    >>> import astroid\n    >>> node = astroid.extract_node('value if condition else other')\n    >>> node\n    <IfExp l.1 at 0x7f23b2e9dbe0>\n    \"\"\"\n\n    _astroid_fields = (\"test\", \"body\", \"orelse\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.test: NodeNG | None = None\n        \"\"\"The condition that the statement tests.\"\"\"\n\n        self.body: NodeNG | None = None\n        \"\"\"The contents of the block.\"\"\"\n\n        self.orelse: NodeNG | None = None\n        \"\"\"The contents of the ``else`` block.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        test: NodeNG | None = None,\n        body: NodeNG | None = None,\n        orelse: NodeNG | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param test: The condition that the statement tests.\n\n        :param body: The contents of the block.\n\n        :param orelse: The contents of the ``else`` block.\n        \"\"\"\n        self.test = test\n        self.body = body\n        self.orelse = orelse\n\n    def get_children(self):\n        yield self.test\n        yield self.body\n        yield self.orelse\n\n    def op_left_associative(self):\n        # `1 if True else 2 if False else 3` is parsed as\n        # `1 if True else (2 if False else 3)`\n        return False\n\n\nclass Import(mixins.NoChildrenMixin, mixins.ImportFromMixin, Statement):\n    \"\"\"Class representing an :class:`ast.Import` node.\n    >>> import astroid\n    >>> node = astroid.extract_node('import astroid')\n    >>> node\n    <Import l.1 at 0x7f23b2e4e5c0>\n    \"\"\"\n\n    _other_fields = (\"names\",)\n\n    @decorators.deprecate_default_argument_values(names=\"list[tuple[str, str | None]]\")\n    def __init__(\n        self,\n        names: list[tuple[str, str | None]] | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param names: The names being imported.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.names: list[tuple[str, str | None]] = names or []\n        \"\"\"The names being imported.\n\n        Each entry is a :class:`tuple` of the name being imported,\n        and the alias that the name is assigned to (if any).\n        \"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n\nclass Index(NodeNG):\n    \"\"\"Class representing an :class:`ast.Index` node.\n\n    An :class:`Index` is a simple subscript.\n\n    Deprecated since v2.6.0 - Now part of the :class:`Subscript` node.\n    Will be removed with the release of v2.7.0\n    \"\"\"\n\n\nclass Keyword(NodeNG):\n    \"\"\"Class representing an :class:`ast.keyword` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('function(a_kwarg=True)')\n    >>> node\n    <Call l.1 at 0x7f23b2e9e320>\n    >>> node.keywords\n    [<Keyword l.1 at 0x7f23b2e9e9b0>]\n    \"\"\"\n\n    _astroid_fields = (\"value\",)\n    _other_fields = (\"arg\",)\n\n    def __init__(\n        self,\n        arg: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param arg: The argument being assigned to.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.arg: str | None = arg  # can be None\n        \"\"\"The argument being assigned to.\"\"\"\n\n        self.value: NodeNG | None = None\n        \"\"\"The value being assigned to the keyword argument.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, value: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: The value being assigned to the keyword argument.\n        \"\"\"\n        self.value = value\n\n    def get_children(self):\n        yield self.value\n\n\nclass List(BaseContainer):\n    \"\"\"Class representing an :class:`ast.List` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('[1, 2, 3]')\n    >>> node\n    <List.list l.1 at 0x7f23b2e9e128>\n    \"\"\"\n\n    _other_fields = (\"ctx\",)\n\n    def __init__(\n        self,\n        ctx: Context | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param ctx: Whether the list is assigned to or loaded from.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.ctx: Context | None = ctx\n        \"\"\"Whether the list is assigned to or loaded from.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[List]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def pytype(self):\n        \"\"\"Get the name of the type that this node represents.\n\n        :returns: The name of the type.\n        :rtype: str\n        \"\"\"\n        return \"builtins.list\"\n\n    def getitem(self, index, context=None):\n        \"\"\"Get an item from this node.\n\n        :param index: The node to use as a subscript index.\n        :type index: Const or Slice\n        \"\"\"\n        return _container_getitem(self, self.elts, index, context=context)\n\n\nclass Nonlocal(mixins.NoChildrenMixin, Statement):\n    \"\"\"Class representing an :class:`ast.Nonlocal` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    def function():\n        nonlocal var\n    ''')\n    >>> node\n    <FunctionDef.function l.2 at 0x7f23b2e9e208>\n    >>> node.body[0]\n    <Nonlocal l.3 at 0x7f23b2e9e908>\n    \"\"\"\n\n    _other_fields = (\"names\",)\n\n    def __init__(\n        self,\n        names: list[str],\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param names: The names being declared as not local.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.names: list[str] = names\n        \"\"\"The names being declared as not local.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def _infer_name(self, frame, name):\n        return name\n\n\nclass Pass(mixins.NoChildrenMixin, Statement):\n    \"\"\"Class representing an :class:`ast.Pass` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('pass')\n    >>> node\n    <Pass l.1 at 0x7f23b2e9e748>\n    \"\"\"\n\n\nclass Raise(Statement):\n    \"\"\"Class representing an :class:`ast.Raise` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('raise RuntimeError(\"Something bad happened!\")')\n    >>> node\n    <Raise l.1 at 0x7f23b2e9e828>\n    \"\"\"\n\n    _astroid_fields = (\"exc\", \"cause\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.exc: NodeNG | None = None  # can be None\n        \"\"\"What is being raised.\"\"\"\n\n        self.cause: NodeNG | None = None  # can be None\n        \"\"\"The exception being used to raise this one.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        exc: NodeNG | None = None,\n        cause: NodeNG | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param exc: What is being raised.\n\n        :param cause: The exception being used to raise this one.\n        \"\"\"\n        self.exc = exc\n        self.cause = cause\n\n    def raises_not_implemented(self):\n        \"\"\"Check if this node raises a :class:`NotImplementedError`.\n\n        :returns: True if this node raises a :class:`NotImplementedError`,\n            False otherwise.\n        :rtype: bool\n        \"\"\"\n        if not self.exc:\n            return False\n        return any(\n            name.name == \"NotImplementedError\" for name in self.exc._get_name_nodes()\n        )\n\n    def get_children(self):\n        if self.exc is not None:\n            yield self.exc\n\n        if self.cause is not None:\n            yield self.cause\n\n\nclass Return(Statement):\n    \"\"\"Class representing an :class:`ast.Return` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('return True')\n    >>> node\n    <Return l.1 at 0x7f23b8211908>\n    \"\"\"\n\n    _astroid_fields = (\"value\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.value: NodeNG | None = None  # can be None\n        \"\"\"The value being returned.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, value: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: The value being returned.\n        \"\"\"\n        self.value = value\n\n    def get_children(self):\n        if self.value is not None:\n            yield self.value\n\n    def is_tuple_return(self):\n        return isinstance(self.value, Tuple)\n\n    def _get_return_nodes_skip_functions(self):\n        yield self\n\n\nclass Set(BaseContainer):\n    \"\"\"Class representing an :class:`ast.Set` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('{1, 2, 3}')\n    >>> node\n    <Set.set l.1 at 0x7f23b2e71d68>\n    \"\"\"\n\n    def pytype(self):\n        \"\"\"Get the name of the type that this node represents.\n\n        :returns: The name of the type.\n        :rtype: str\n        \"\"\"\n        return \"builtins.set\"\n\n\nclass Slice(NodeNG):\n    \"\"\"Class representing an :class:`ast.Slice` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('things[1:3]')\n    >>> node\n    <Subscript l.1 at 0x7f23b2e71f60>\n    >>> node.slice\n    <Slice l.1 at 0x7f23b2e71e80>\n    \"\"\"\n\n    _astroid_fields = (\"lower\", \"upper\", \"step\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.lower: NodeNG | None = None  # can be None\n        \"\"\"The lower index in the slice.\"\"\"\n\n        self.upper: NodeNG | None = None  # can be None\n        \"\"\"The upper index in the slice.\"\"\"\n\n        self.step: NodeNG | None = None  # can be None\n        \"\"\"The step to take between indexes.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        lower: NodeNG | None = None,\n        upper: NodeNG | None = None,\n        step: NodeNG | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param lower: The lower index in the slice.\n\n        :param upper: The upper index in the slice.\n\n        :param step: The step to take between index.\n        \"\"\"\n        self.lower = lower\n        self.upper = upper\n        self.step = step\n\n    def _wrap_attribute(self, attr):\n        \"\"\"Wrap the empty attributes of the Slice in a Const node.\"\"\"\n        if not attr:\n            const = const_factory(attr)\n            const.parent = self\n            return const\n        return attr\n\n    @cached_property\n    def _proxied(self):\n        builtins = AstroidManager().builtins_module\n        return builtins.getattr(\"slice\")[0]\n\n    def pytype(self):\n        \"\"\"Get the name of the type that this node represents.\n\n        :returns: The name of the type.\n        :rtype: str\n        \"\"\"\n        return \"builtins.slice\"\n\n    def igetattr(self, attrname, context=None):\n        \"\"\"Infer the possible values of the given attribute on the slice.\n\n        :param attrname: The name of the attribute to infer.\n        :type attrname: str\n\n        :returns: The inferred possible values.\n        :rtype: iterable(NodeNG)\n        \"\"\"\n        if attrname == \"start\":\n            yield self._wrap_attribute(self.lower)\n        elif attrname == \"stop\":\n            yield self._wrap_attribute(self.upper)\n        elif attrname == \"step\":\n            yield self._wrap_attribute(self.step)\n        else:\n            yield from self.getattr(attrname, context=context)\n\n    def getattr(self, attrname, context=None):\n        return self._proxied.getattr(attrname, context)\n\n    def get_children(self):\n        if self.lower is not None:\n            yield self.lower\n\n        if self.upper is not None:\n            yield self.upper\n\n        if self.step is not None:\n            yield self.step\n\n\nclass Starred(mixins.ParentAssignTypeMixin, NodeNG):\n    \"\"\"Class representing an :class:`ast.Starred` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('*args')\n    >>> node\n    <Starred l.1 at 0x7f23b2e41978>\n    \"\"\"\n\n    _astroid_fields = (\"value\",)\n    _other_fields = (\"ctx\",)\n\n    def __init__(\n        self,\n        ctx: Context | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param ctx: Whether the list is assigned to or loaded from.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.value: NodeNG | None = None\n        \"\"\"What is being unpacked.\"\"\"\n\n        self.ctx: Context | None = ctx\n        \"\"\"Whether the starred item is assigned to or loaded from.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, value: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: What is being unpacked.\n        \"\"\"\n        self.value = value\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[Starred]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def get_children(self):\n        yield self.value\n\n\nclass Subscript(NodeNG):\n    \"\"\"Class representing an :class:`ast.Subscript` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('things[1:3]')\n    >>> node\n    <Subscript l.1 at 0x7f23b2e71f60>\n    \"\"\"\n\n    _astroid_fields = (\"value\", \"slice\")\n    _other_fields = (\"ctx\",)\n\n    def __init__(\n        self,\n        ctx: Context | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param ctx: Whether the subscripted item is assigned to or loaded from.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.value: NodeNG | None = None\n        \"\"\"What is being indexed.\"\"\"\n\n        self.slice: NodeNG | None = None\n        \"\"\"The slice being used to lookup.\"\"\"\n\n        self.ctx: Context | None = ctx\n        \"\"\"Whether the subscripted item is assigned to or loaded from.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    # pylint: disable=redefined-builtin; had to use the same name as builtin ast module.\n    def postinit(\n        self, value: NodeNG | None = None, slice: NodeNG | None = None\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: What is being indexed.\n\n        :param slice: The slice being used to lookup.\n        \"\"\"\n        self.value = value\n        self.slice = slice\n\n    def get_children(self):\n        yield self.value\n        yield self.slice\n\n\nclass TryExcept(mixins.MultiLineBlockMixin, mixins.BlockRangeMixIn, Statement):\n    \"\"\"Class representing an :class:`ast.TryExcept` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n        try:\n            do_something()\n        except Exception as error:\n            print(\"Error!\")\n        ''')\n    >>> node\n    <TryExcept l.2 at 0x7f23b2e9d908>\n    \"\"\"\n\n    _astroid_fields = (\"body\", \"handlers\", \"orelse\")\n    _multi_line_block_fields = (\"body\", \"handlers\", \"orelse\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.body: list[NodeNG] = []\n        \"\"\"The contents of the block to catch exceptions from.\"\"\"\n\n        self.handlers: list[ExceptHandler] = []\n        \"\"\"The exception handlers.\"\"\"\n\n        self.orelse: list[NodeNG] = []\n        \"\"\"The contents of the ``else`` block.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        body: list[NodeNG] | None = None,\n        handlers: list[ExceptHandler] | None = None,\n        orelse: list[NodeNG] | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param body: The contents of the block to catch exceptions from.\n\n        :param handlers: The exception handlers.\n\n        :param orelse: The contents of the ``else`` block.\n        \"\"\"\n        if body is not None:\n            self.body = body\n        if handlers is not None:\n            self.handlers = handlers\n        if orelse is not None:\n            self.orelse = orelse\n\n    def _infer_name(self, frame, name):\n        return name\n\n    def block_range(self, lineno):\n        \"\"\"Get a range from the given line number to where this node ends.\n\n        :param lineno: The line number to start the range at.\n        :type lineno: int\n\n        :returns: The range of line numbers that this node belongs to,\n            starting at the given line number.\n        :rtype: tuple(int, int)\n        \"\"\"\n        last = None\n        for exhandler in self.handlers:\n            if exhandler.type and lineno == exhandler.type.fromlineno:\n                return lineno, lineno\n            if exhandler.body[0].fromlineno <= lineno <= exhandler.body[-1].tolineno:\n                return lineno, exhandler.body[-1].tolineno\n            if last is None:\n                last = exhandler.body[0].fromlineno - 1\n        return self._elsed_block_range(lineno, self.orelse, last)\n\n    def get_children(self):\n        yield from self.body\n\n        yield from self.handlers or ()\n        yield from self.orelse or ()\n\n\nclass TryFinally(mixins.MultiLineBlockMixin, mixins.BlockRangeMixIn, Statement):\n    \"\"\"Class representing an :class:`ast.TryFinally` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    try:\n        do_something()\n    except Exception as error:\n        print(\"Error!\")\n    finally:\n        print(\"Cleanup!\")\n    ''')\n    >>> node\n    <TryFinally l.2 at 0x7f23b2e41d68>\n    \"\"\"\n\n    _astroid_fields = (\"body\", \"finalbody\")\n    _multi_line_block_fields = (\"body\", \"finalbody\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.body: list[NodeNG | TryExcept] = []\n        \"\"\"The try-except that the finally is attached to.\"\"\"\n\n        self.finalbody: list[NodeNG] = []\n        \"\"\"The contents of the ``finally`` block.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        body: list[NodeNG | TryExcept] | None = None,\n        finalbody: list[NodeNG] | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param body: The try-except that the finally is attached to.\n\n        :param finalbody: The contents of the ``finally`` block.\n        \"\"\"\n        if body is not None:\n            self.body = body\n        if finalbody is not None:\n            self.finalbody = finalbody\n\n    def block_range(self, lineno):\n        \"\"\"Get a range from the given line number to where this node ends.\n\n        :param lineno: The line number to start the range at.\n        :type lineno: int\n\n        :returns: The range of line numbers that this node belongs to,\n            starting at the given line number.\n        :rtype: tuple(int, int)\n        \"\"\"\n        child = self.body[0]\n        # py2.5 try: except: finally:\n        if (\n            isinstance(child, TryExcept)\n            and child.fromlineno == self.fromlineno\n            and child.tolineno >= lineno > self.fromlineno\n        ):\n            return child.block_range(lineno)\n        return self._elsed_block_range(lineno, self.finalbody)\n\n    def get_children(self):\n        yield from self.body\n        yield from self.finalbody\n\n\nclass Tuple(BaseContainer):\n    \"\"\"Class representing an :class:`ast.Tuple` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('(1, 2, 3)')\n    >>> node\n    <Tuple.tuple l.1 at 0x7f23b2e41780>\n    \"\"\"\n\n    _other_fields = (\"ctx\",)\n\n    def __init__(\n        self,\n        ctx: Context | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param ctx: Whether the tuple is assigned to or loaded from.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.ctx: Context | None = ctx\n        \"\"\"Whether the tuple is assigned to or loaded from.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[Tuple]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def pytype(self):\n        \"\"\"Get the name of the type that this node represents.\n\n        :returns: The name of the type.\n        :rtype: str\n        \"\"\"\n        return \"builtins.tuple\"\n\n    def getitem(self, index, context=None):\n        \"\"\"Get an item from this node.\n\n        :param index: The node to use as a subscript index.\n        :type index: Const or Slice\n        \"\"\"\n        return _container_getitem(self, self.elts, index, context=context)\n\n\nclass UnaryOp(NodeNG):\n    \"\"\"Class representing an :class:`ast.UnaryOp` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('-5')\n    >>> node\n    <UnaryOp l.1 at 0x7f23b2e4e198>\n    \"\"\"\n\n    _astroid_fields = (\"operand\",)\n    _other_fields = (\"op\",)\n\n    @decorators.deprecate_default_argument_values(op=\"str\")\n    def __init__(\n        self,\n        op: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param op: The operator.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.op: str | None = op\n        \"\"\"The operator.\"\"\"\n\n        self.operand: NodeNG | None = None\n        \"\"\"What the unary operator is applied to.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, operand: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param operand: What the unary operator is applied to.\n        \"\"\"\n        self.operand = operand\n\n    # This is set by inference.py\n    def _infer_unaryop(self, context=None):\n        raise NotImplementedError\n\n    def type_errors(self, context=None):\n        \"\"\"Get a list of type errors which can occur during inference.\n\n        Each TypeError is represented by a :class:`BadBinaryOperationMessage`,\n        which holds the original exception.\n\n        :returns: The list of possible type errors.\n        :rtype: list(BadBinaryOperationMessage)\n        \"\"\"\n        try:\n            results = self._infer_unaryop(context=context)\n            return [\n                result\n                for result in results\n                if isinstance(result, util.BadUnaryOperationMessage)\n            ]\n        except InferenceError:\n            return []\n\n    def get_children(self):\n        yield self.operand\n\n    def op_precedence(self):\n        if self.op == \"not\":\n            return OP_PRECEDENCE[self.op]\n\n        return super().op_precedence()\n\n\nclass While(mixins.MultiLineBlockMixin, mixins.BlockRangeMixIn, Statement):\n    \"\"\"Class representing an :class:`ast.While` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    while condition():\n        print(\"True\")\n    ''')\n    >>> node\n    <While l.2 at 0x7f23b2e4e390>\n    \"\"\"\n\n    _astroid_fields = (\"test\", \"body\", \"orelse\")\n    _multi_line_block_fields = (\"body\", \"orelse\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.test: NodeNG | None = None\n        \"\"\"The condition that the loop tests.\"\"\"\n\n        self.body: list[NodeNG] = []\n        \"\"\"The contents of the loop.\"\"\"\n\n        self.orelse: list[NodeNG] = []\n        \"\"\"The contents of the ``else`` block.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        test: NodeNG | None = None,\n        body: list[NodeNG] | None = None,\n        orelse: list[NodeNG] | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param test: The condition that the loop tests.\n\n        :param body: The contents of the loop.\n\n        :param orelse: The contents of the ``else`` block.\n        \"\"\"\n        self.test = test\n        if body is not None:\n            self.body = body\n        if orelse is not None:\n            self.orelse = orelse\n\n    @cached_property\n    def blockstart_tolineno(self):\n        \"\"\"The line on which the beginning of this block ends.\n\n        :type: int\n        \"\"\"\n        return self.test.tolineno\n\n    def block_range(self, lineno):\n        \"\"\"Get a range from the given line number to where this node ends.\n\n        :param lineno: The line number to start the range at.\n        :type lineno: int\n\n        :returns: The range of line numbers that this node belongs to,\n            starting at the given line number.\n        :rtype: tuple(int, int)\n        \"\"\"\n        return self._elsed_block_range(lineno, self.orelse)\n\n    def get_children(self):\n        yield self.test\n\n        yield from self.body\n        yield from self.orelse\n\n    def _get_yield_nodes_skip_lambdas(self):\n        \"\"\"A While node can contain a Yield node in the test\"\"\"\n        yield from self.test._get_yield_nodes_skip_lambdas()\n        yield from super()._get_yield_nodes_skip_lambdas()\n\n\nclass With(\n    mixins.MultiLineBlockMixin,\n    mixins.BlockRangeMixIn,\n    mixins.AssignTypeMixin,\n    Statement,\n):\n    \"\"\"Class representing an :class:`ast.With` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    with open(file_path) as file_:\n        print(file_.read())\n    ''')\n    >>> node\n    <With l.2 at 0x7f23b2e4e710>\n    \"\"\"\n\n    _astroid_fields = (\"items\", \"body\")\n    _other_other_fields = (\"type_annotation\",)\n    _multi_line_block_fields = (\"body\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.items: list[tuple[NodeNG, NodeNG | None]] = []\n        \"\"\"The pairs of context managers and the names they are assigned to.\"\"\"\n\n        self.body: list[NodeNG] = []\n        \"\"\"The contents of the ``with`` block.\"\"\"\n\n        self.type_annotation: NodeNG | None = None  # can be None\n        \"\"\"If present, this will contain the type annotation passed by a type comment\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        items: list[tuple[NodeNG, NodeNG | None]] | None = None,\n        body: list[NodeNG] | None = None,\n        type_annotation: NodeNG | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param items: The pairs of context managers and the names\n            they are assigned to.\n\n        :param body: The contents of the ``with`` block.\n        \"\"\"\n        if items is not None:\n            self.items = items\n        if body is not None:\n            self.body = body\n        self.type_annotation = type_annotation\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[With]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    @cached_property\n    def blockstart_tolineno(self):\n        \"\"\"The line on which the beginning of this block ends.\n\n        :type: int\n        \"\"\"\n        return self.items[-1][0].tolineno\n\n    def get_children(self):\n        \"\"\"Get the child nodes below this node.\n\n        :returns: The children.\n        :rtype: iterable(NodeNG)\n        \"\"\"\n        for expr, var in self.items:\n            yield expr\n            if var:\n                yield var\n        yield from self.body\n\n\nclass AsyncWith(With):\n    \"\"\"Asynchronous ``with`` built with the ``async`` keyword.\"\"\"\n\n\nclass Yield(NodeNG):\n    \"\"\"Class representing an :class:`ast.Yield` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('yield True')\n    >>> node\n    <Yield l.1 at 0x7f23b2e4e5f8>\n    \"\"\"\n\n    _astroid_fields = (\"value\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.value: NodeNG | None = None  # can be None\n        \"\"\"The value to yield.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, value: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: The value to yield.\n        \"\"\"\n        self.value = value\n\n    def get_children(self):\n        if self.value is not None:\n            yield self.value\n\n    def _get_yield_nodes_skip_lambdas(self):\n        yield self\n\n\nclass YieldFrom(Yield):  # TODO value is required, not optional\n    \"\"\"Class representing an :class:`ast.YieldFrom` node.\"\"\"\n\n\nclass DictUnpack(mixins.NoChildrenMixin, NodeNG):\n    \"\"\"Represents the unpacking of dicts into dicts using :pep:`448`.\"\"\"\n\n\nclass FormattedValue(NodeNG):\n    \"\"\"Class representing an :class:`ast.FormattedValue` node.\n\n    Represents a :pep:`498` format string.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('f\"Format {type_}\"')\n    >>> node\n    <JoinedStr l.1 at 0x7f23b2e4ed30>\n    >>> node.values\n    [<Const.str l.1 at 0x7f23b2e4eda0>, <FormattedValue l.1 at 0x7f23b2e4edd8>]\n    \"\"\"\n\n    _astroid_fields = (\"value\", \"format_spec\")\n    _other_fields = (\"conversion\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.value: NodeNG\n        \"\"\"The value to be formatted into the string.\"\"\"\n\n        self.conversion: int | None = None  # can be None\n        \"\"\"The type of formatting to be applied to the value.\n\n        .. seealso::\n            :class:`ast.FormattedValue`\n        \"\"\"\n\n        self.format_spec: NodeNG | None = None  # can be None\n        \"\"\"The formatting to be applied to the value.\n\n        .. seealso::\n            :class:`ast.FormattedValue`\n\n        :type: JoinedStr or None\n        \"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        value: NodeNG,\n        conversion: int | None = None,\n        format_spec: NodeNG | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: The value to be formatted into the string.\n\n        :param conversion: The type of formatting to be applied to the value.\n\n        :param format_spec: The formatting to be applied to the value.\n        :type format_spec: JoinedStr or None\n        \"\"\"\n        self.value = value\n        self.conversion = conversion\n        self.format_spec = format_spec\n\n    def get_children(self):\n        yield self.value\n\n        if self.format_spec is not None:\n            yield self.format_spec\n\n\nclass JoinedStr(NodeNG):\n    \"\"\"Represents a list of string expressions to be joined.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('f\"Format {type_}\"')\n    >>> node\n    <JoinedStr l.1 at 0x7f23b2e4ed30>\n    \"\"\"\n\n    _astroid_fields = (\"values\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.values: list[NodeNG] = []\n        \"\"\"The string expressions to be joined.\n\n        :type: list(FormattedValue or Const)\n        \"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, values: list[NodeNG] | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: The string expressions to be joined.\n\n        :type: list(FormattedValue or Const)\n        \"\"\"\n        if values is not None:\n            self.values = values\n\n    def get_children(self):\n        yield from self.values\n\n\nclass NamedExpr(mixins.AssignTypeMixin, NodeNG):\n    \"\"\"Represents the assignment from the assignment expression\n\n    >>> import astroid\n    >>> module = astroid.parse('if a := 1: pass')\n    >>> module.body[0].test\n    <NamedExpr l.1 at 0x7f23b2e4ed30>\n    \"\"\"\n\n    _astroid_fields = (\"target\", \"value\")\n\n    optional_assign = True\n    \"\"\"Whether this node optionally assigns a variable.\n\n    Since NamedExpr are not always called they do not always assign.\"\"\"\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.target: NodeNG\n        \"\"\"The assignment target\n\n        :type: Name\n        \"\"\"\n\n        self.value: NodeNG\n        \"\"\"The value that gets assigned in the expression\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, target: NodeNG, value: NodeNG) -> None:\n        self.target = target\n        self.value = value\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[NamedExpr]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def frame(\n        self, *, future: Literal[None, True] = None\n    ) -> nodes.FunctionDef | nodes.Module | nodes.ClassDef | nodes.Lambda:\n        \"\"\"The first parent frame node.\n\n        A frame node is a :class:`Module`, :class:`FunctionDef`,\n        or :class:`ClassDef`.\n\n        :returns: The first parent frame node.\n        \"\"\"\n        if not self.parent:\n            raise ParentMissingError(target=self)\n\n        # For certain parents NamedExpr evaluate to the scope of the parent\n        if isinstance(self.parent, (Arguments, Keyword, Comprehension)):\n            if not self.parent.parent:\n                raise ParentMissingError(target=self.parent)\n            if not self.parent.parent.parent:\n                raise ParentMissingError(target=self.parent.parent)\n            return self.parent.parent.parent.frame(future=True)\n\n        return self.parent.frame(future=True)\n\n    def scope(self) -> LocalsDictNodeNG:\n        \"\"\"The first parent node defining a new scope.\n        These can be Module, FunctionDef, ClassDef, Lambda, or GeneratorExp nodes.\n\n        :returns: The first parent scope node.\n        \"\"\"\n        if not self.parent:\n            raise ParentMissingError(target=self)\n\n        # For certain parents NamedExpr evaluate to the scope of the parent\n        if isinstance(self.parent, (Arguments, Keyword, Comprehension)):\n            if not self.parent.parent:\n                raise ParentMissingError(target=self.parent)\n            if not self.parent.parent.parent:\n                raise ParentMissingError(target=self.parent.parent)\n            return self.parent.parent.parent.scope()\n\n        return self.parent.scope()\n\n    def set_local(self, name: str, stmt: AssignName) -> None:\n        \"\"\"Define that the given name is declared in the given statement node.\n        NamedExpr's in Arguments, Keyword or Comprehension are evaluated in their\n        parent's parent scope. So we add to their frame's locals.\n\n        .. seealso:: :meth:`scope`\n\n        :param name: The name that is being defined.\n\n        :param stmt: The statement that defines the given name.\n        \"\"\"\n        self.frame(future=True).set_local(name, stmt)\n\n\nclass Unknown(mixins.AssignTypeMixin, NodeNG):\n    \"\"\"This node represents a node in a constructed AST where\n    introspection is not possible.  At the moment, it's only used in\n    the args attribute of FunctionDef nodes where function signature\n    introspection failed.\n    \"\"\"\n\n    name = \"Unknown\"\n\n    def qname(self):\n        return \"Unknown\"\n\n    def _infer(self, context=None, **kwargs):\n        \"\"\"Inference on an Unknown node immediately terminates.\"\"\"\n        yield util.Uninferable\n\n\nclass EvaluatedObject(NodeNG):\n    \"\"\"Contains an object that has already been inferred\n\n    This class is useful to pre-evaluate a particular node,\n    with the resulting class acting as the non-evaluated node.\n    \"\"\"\n\n    name = \"EvaluatedObject\"\n    _astroid_fields = (\"original\",)\n    _other_fields = (\"value\",)\n\n    def __init__(\n        self, original: NodeNG, value: NodeNG | type[util.Uninferable]\n    ) -> None:\n        self.original: NodeNG = original\n        \"\"\"The original node that has already been evaluated\"\"\"\n\n        self.value: NodeNG | type[util.Uninferable] = value\n        \"\"\"The inferred value\"\"\"\n\n        super().__init__(\n            lineno=self.original.lineno,\n            col_offset=self.original.col_offset,\n            parent=self.original.parent,\n        )\n\n    def _infer(\n        self, context: InferenceContext | None = None\n    ) -> Iterator[NodeNG | type[util.Uninferable]]:\n        yield self.value\n\n\n# Pattern matching #######################################################\n\n\nclass Match(Statement):\n    \"\"\"Class representing a :class:`ast.Match` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case 200:\n            ...\n        case _:\n            ...\n    ''')\n    >>> node\n    <Match l.2 at 0x10c24e170>\n    \"\"\"\n\n    _astroid_fields = (\"subject\", \"cases\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        self.subject: NodeNG\n        self.cases: list[MatchCase]\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        *,\n        subject: NodeNG,\n        cases: list[MatchCase],\n    ) -> None:\n        self.subject = subject\n        self.cases = cases\n\n\nclass Pattern(NodeNG):\n    \"\"\"Base class for all Pattern nodes.\"\"\"\n\n\nclass MatchCase(mixins.MultiLineBlockMixin, NodeNG):\n    \"\"\"Class representing a :class:`ast.match_case` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case 200:\n            ...\n    ''')\n    >>> node.cases[0]\n    <MatchCase l.3 at 0x10c24e590>\n    \"\"\"\n\n    _astroid_fields = (\"pattern\", \"guard\", \"body\")\n    _multi_line_block_fields = (\"body\",)\n\n    lineno: None\n    col_offset: None\n    end_lineno: None\n    end_col_offset: None\n\n    def __init__(self, *, parent: NodeNG | None = None) -> None:\n        self.pattern: Pattern\n        self.guard: NodeNG | None\n        self.body: list[NodeNG]\n        super().__init__(parent=parent)\n\n    def postinit(\n        self,\n        *,\n        pattern: Pattern,\n        guard: NodeNG | None,\n        body: list[NodeNG],\n    ) -> None:\n        self.pattern = pattern\n        self.guard = guard\n        self.body = body\n\n\nclass MatchValue(Pattern):\n    \"\"\"Class representing a :class:`ast.MatchValue` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case 200:\n            ...\n    ''')\n    >>> node.cases[0].pattern\n    <MatchValue l.3 at 0x10c24e200>\n    \"\"\"\n\n    _astroid_fields = (\"value\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        self.value: NodeNG\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, *, value: NodeNG) -> None:\n        self.value = value\n\n\nclass MatchSingleton(Pattern):\n    \"\"\"Class representing a :class:`ast.MatchSingleton` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case True:\n            ...\n        case False:\n            ...\n        case None:\n            ...\n    ''')\n    >>> node.cases[0].pattern\n    <MatchSingleton l.3 at 0x10c2282e0>\n    >>> node.cases[1].pattern\n    <MatchSingleton l.5 at 0x10c228af0>\n    >>> node.cases[2].pattern\n    <MatchSingleton l.7 at 0x10c229f90>\n    \"\"\"\n\n    _other_fields = (\"value\",)\n\n    def __init__(\n        self,\n        *,\n        value: Literal[True, False, None],\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n        parent: NodeNG | None = None,\n    ) -> None:\n        self.value = value\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n\nclass MatchSequence(Pattern):\n    \"\"\"Class representing a :class:`ast.MatchSequence` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case [1, 2]:\n            ...\n        case (1, 2, *_):\n            ...\n    ''')\n    >>> node.cases[0].pattern\n    <MatchSequence l.3 at 0x10ca80d00>\n    >>> node.cases[1].pattern\n    <MatchSequence l.5 at 0x10ca80b20>\n    \"\"\"\n\n    _astroid_fields = (\"patterns\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        self.patterns: list[Pattern]\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, *, patterns: list[Pattern]) -> None:\n        self.patterns = patterns\n\n\nclass MatchMapping(mixins.AssignTypeMixin, Pattern):\n    \"\"\"Class representing a :class:`ast.MatchMapping` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case {1: \"Hello\", 2: \"World\", 3: _, **rest}:\n            ...\n    ''')\n    >>> node.cases[0].pattern\n    <MatchMapping l.3 at 0x10c8a8850>\n    \"\"\"\n\n    _astroid_fields = (\"keys\", \"patterns\", \"rest\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        self.keys: list[NodeNG]\n        self.patterns: list[Pattern]\n        self.rest: AssignName | None\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        *,\n        keys: list[NodeNG],\n        patterns: list[Pattern],\n        rest: AssignName | None,\n    ) -> None:\n        self.keys = keys\n        self.patterns = patterns\n        self.rest = rest\n\n    assigned_stmts: ClassVar[\n        Callable[\n            [\n                MatchMapping,\n                AssignName,\n                InferenceContext | None,\n                None,\n            ],\n            Generator[NodeNG, None, None],\n        ]\n    ]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n\nclass MatchClass(Pattern):\n    \"\"\"Class representing a :class:`ast.MatchClass` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case Point2D(0, 0):\n            ...\n        case Point3D(x=0, y=0, z=0):\n            ...\n    ''')\n    >>> node.cases[0].pattern\n    <MatchClass l.3 at 0x10ca83940>\n    >>> node.cases[1].pattern\n    <MatchClass l.5 at 0x10ca80880>\n    \"\"\"\n\n    _astroid_fields = (\"cls\", \"patterns\", \"kwd_patterns\")\n    _other_fields = (\"kwd_attrs\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        self.cls: NodeNG\n        self.patterns: list[Pattern]\n        self.kwd_attrs: list[str]\n        self.kwd_patterns: list[Pattern]\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        *,\n        cls: NodeNG,\n        patterns: list[Pattern],\n        kwd_attrs: list[str],\n        kwd_patterns: list[Pattern],\n    ) -> None:\n        self.cls = cls\n        self.patterns = patterns\n        self.kwd_attrs = kwd_attrs\n        self.kwd_patterns = kwd_patterns\n\n\nclass MatchStar(mixins.AssignTypeMixin, Pattern):\n    \"\"\"Class representing a :class:`ast.MatchStar` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case [1, *_]:\n            ...\n    ''')\n    >>> node.cases[0].pattern.patterns[1]\n    <MatchStar l.3 at 0x10ca809a0>\n    \"\"\"\n\n    _astroid_fields = (\"name\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        self.name: AssignName | None\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, *, name: AssignName | None) -> None:\n        self.name = name\n\n    assigned_stmts: ClassVar[\n        Callable[\n            [\n                MatchStar,\n                AssignName,\n                InferenceContext | None,\n                None,\n            ],\n            Generator[NodeNG, None, None],\n        ]\n    ]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n\nclass MatchAs(mixins.AssignTypeMixin, Pattern):\n    \"\"\"Class representing a :class:`ast.MatchAs` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case [1, a]:\n            ...\n        case {'key': b}:\n            ...\n        case Point2D(0, 0) as c:\n            ...\n        case d:\n            ...\n    ''')\n    >>> node.cases[0].pattern.patterns[1]\n    <MatchAs l.3 at 0x10d0b2da0>\n    >>> node.cases[1].pattern.patterns[0]\n    <MatchAs l.5 at 0x10d0b2920>\n    >>> node.cases[2].pattern\n    <MatchAs l.7 at 0x10d0b06a0>\n    >>> node.cases[3].pattern\n    <MatchAs l.9 at 0x10d09b880>\n    \"\"\"\n\n    _astroid_fields = (\"pattern\", \"name\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        self.pattern: Pattern | None\n        self.name: AssignName | None\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        *,\n        pattern: Pattern | None,\n        name: AssignName | None,\n    ) -> None:\n        self.pattern = pattern\n        self.name = name\n\n    assigned_stmts: ClassVar[\n        Callable[\n            [\n                MatchAs,\n                AssignName,\n                InferenceContext | None,\n                None,\n            ],\n            Generator[NodeNG, None, None],\n        ]\n    ]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n\nclass MatchOr(Pattern):\n    \"\"\"Class representing a :class:`ast.MatchOr` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case 400 | 401 | 402:\n            ...\n    ''')\n    >>> node.cases[0].pattern\n    <MatchOr l.3 at 0x10d0b0b50>\n    \"\"\"\n\n    _astroid_fields = (\"patterns\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        self.patterns: list[Pattern]\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, *, patterns: list[Pattern]) -> None:\n        self.patterns = patterns\n\n\n# constants ##############################################################\n\nCONST_CLS = {\n    list: List,\n    tuple: Tuple,\n    dict: Dict,\n    set: Set,\n    type(None): Const,\n    type(NotImplemented): Const,\n    type(...): Const,\n}\n\n\ndef _update_const_classes():\n    \"\"\"update constant classes, so the keys of CONST_CLS can be reused\"\"\"\n    klasses = (bool, int, float, complex, str, bytes)\n    for kls in klasses:\n        CONST_CLS[kls] = Const\n\n\n_update_const_classes()\n\n\ndef _two_step_initialization(cls, value):\n    instance = cls()\n    instance.postinit(value)\n    return instance\n\n\ndef _dict_initialization(cls, value):\n    if isinstance(value, dict):\n        value = tuple(value.items())\n    return _two_step_initialization(cls, value)\n\n\n_CONST_CLS_CONSTRUCTORS = {\n    List: _two_step_initialization,\n    Tuple: _two_step_initialization,\n    Dict: _dict_initialization,\n    Set: _two_step_initialization,\n    Const: lambda cls, value: cls(value),\n}\n\n\ndef const_factory(value):\n    \"\"\"return an astroid node for a python value\"\"\"\n    # XXX we should probably be stricter here and only consider stuff in\n    # CONST_CLS or do better treatment: in case where value is not in CONST_CLS,\n    # we should rather recall the builder on this value than returning an empty\n    # node (another option being that const_factory shouldn't be called with something\n    # not in CONST_CLS)\n    assert not isinstance(value, NodeNG)\n\n    # Hack for ignoring elements of a sequence\n    # or a mapping, in order to avoid transforming\n    # each element to an AST. This is fixed in 2.0\n    # and this approach is a temporary hack.\n    if isinstance(value, (list, set, tuple, dict)):\n        elts = []\n    else:\n        elts = value\n\n    try:\n        initializer_cls = CONST_CLS[value.__class__]\n        initializer = _CONST_CLS_CONSTRUCTORS[initializer_cls]\n        return initializer(initializer_cls, elts)\n    except (KeyError, AttributeError):\n        node = EmptyNode()\n        node.object = value\n        return node\n","header":{"file":{"path":"astroid/nodes/node_classes.py"},"misc_line":null},"index_line":null,"is_binary_file":false,"binary_line":null,"minus_file":{"path":"a/astroid/nodes/node_classes.py"},"plus_file":{"path":"b/astroid/nodes/node_classes.py"},"hunks":[{"descriptor":{"old_range":{"start":2346,"length":24},"new_range":{"start":2346,"length":33},"section":"def itered(self):"},"line_group":{"all_lines":[{"content":"        \"\"\"","type":"context"},{"content":"        return [key for (key, _) in self.items]","type":"context"},{"content":"","type":"context"},{"content":"    def getitem(self, index, context=None):","type":"deleted"},{"content":"    def getitem(","type":"added"},{"content":"        self, index: Const | Slice, context: InferenceContext | None = None","type":"added"},{"content":"    ) -> NodeNG:","type":"added"},{"content":"        \"\"\"Get an item from this node.","type":"context"},{"content":"","type":"context"},{"content":"        :param index: The node to use as a subscript index.","type":"context"},{"content":"        :type index: Const or Slice","type":"deleted"},{"content":"","type":"context"},{"content":"        :raises AstroidTypeError: When the given index cannot be used as a","type":"context"},{"content":"            subscript index, or if this node is not subscriptable.","type":"context"},{"content":"        :raises AstroidIndexError: If the given index does not exist in the","type":"context"},{"content":"            dictionary.","type":"context"},{"content":"        \"\"\"","type":"context"},{"content":"        # pylint: disable-next=import-outside-toplevel; circular import","type":"added"},{"content":"        from astroid.helpers import safe_infer","type":"added"},{"content":"","type":"added"},{"content":"        for key, value in self.items:","type":"context"},{"content":"            # TODO(cpopa): no support for overriding yet, {1:2, **{1: 3}}.","type":"context"},{"content":"            if isinstance(key, DictUnpack):","type":"context"},{"content":"                inferred_value = safe_infer(value, context)","type":"added"},{"content":"                if not isinstance(inferred_value, Dict):","type":"added"},{"content":"                    continue","type":"added"},{"content":"","type":"added"},{"content":"                try:","type":"context"},{"content":"                    return value.getitem(index, context)","type":"deleted"},{"content":"                    return inferred_value.getitem(index, context)","type":"added"},{"content":"                except (AstroidTypeError, AstroidIndexError):","type":"context"},{"content":"                    continue","type":"context"},{"content":"","type":"added"},{"content":"            for inferredkey in key.infer(context):","type":"context"},{"content":"                if inferredkey is util.Uninferable:","type":"context"},{"content":"                    continue","type":"context"},{"content":"","type":"context"}]},"modified_entities":[],"added_entities":[],"deleted_entities":[]}]}],"old_commit_hash":"39c2a9805970ca57093d32bbaf0e6a63e05041d8","new_commit_hash":"460fab03b4128997fcb34e70a2ce50cbf03fe83a","commit_message":"Add changelog entry","commit_date":"2022-06-05T19:17:35+02:00","metadata":{}}
problem_statement: getitem does not infer the actual unpacked value
  When trying to call `Dict.getitem()` on a context where we have a dict unpacking of anything beside a real dict, astroid currently raises an `AttributeError: 'getitem'`, which has 2 problems:
  
  - The object might be a reference against something constant, this pattern is usually seen when we have different sets of dicts that extend each other, and all of their values are inferrable. 
  - We can have something that is uninferable, but in that case instead of an `AttributeError` I think it makes sense to raise the usual `AstroidIndexError` which is supposed to be already handled by the downstream.
  
  
  Here is a short reproducer;
  
  ```py
  from astroid import parse
  
  
  source = """
  X = {
      'A': 'B'
  }
  
  Y = {
      **X
  }
  
  KEY = 'A'
  """
  
  tree = parse(source)
  
  first_dict = tree.body[0].value
  second_dict = tree.body[1].value
  key = tree.body[2].value
  
  print(f'{first_dict.getitem(key).value = }')
  print(f'{second_dict.getitem(key).value = }')
  
  
  ```
  
  The current output;
  
  ```
   $ python t1.py                                                                                                 3ms
  first_dict.getitem(key).value = 'B'
  Traceback (most recent call last):
    File "/home/isidentical/projects/astroid/t1.py", line 23, in <module>
      print(f'{second_dict.getitem(key).value = }')
    File "/home/isidentical/projects/astroid/astroid/nodes/node_classes.py", line 2254, in getitem
      return value.getitem(index, context)
  AttributeError: 'Name' object has no attribute 'getitem'
  ```
  
  Expeceted output;
  ```
   $ python t1.py                                                                                                 4ms
  first_dict.getitem(key).value = 'B'
  second_dict.getitem(key).value = 'B'
  
  ```
  
  
patch: diff --git a/astroid/nodes/node_classes.py b/astroid/nodes/node_classes.py
  --- a/astroid/nodes/node_classes.py
  +++ b/astroid/nodes/node_classes.py
  @@ -2346,24 +2346,33 @@ def itered(self):
           """
           return [key for (key, _) in self.items]
   
  -    def getitem(self, index, context=None):
  +    def getitem(
  +        self, index: Const | Slice, context: InferenceContext | None = None
  +    ) -> NodeNG:
           """Get an item from this node.
   
           :param index: The node to use as a subscript index.
  -        :type index: Const or Slice
   
           :raises AstroidTypeError: When the given index cannot be used as a
               subscript index, or if this node is not subscriptable.
           :raises AstroidIndexError: If the given index does not exist in the
               dictionary.
           """
  +        # pylint: disable-next=import-outside-toplevel; circular import
  +        from astroid.helpers import safe_infer
  +
           for key, value in self.items:
               # TODO(cpopa): no support for overriding yet, {1:2, **{1: 3}}.
               if isinstance(key, DictUnpack):
  +                inferred_value = safe_infer(value, context)
  +                if not isinstance(inferred_value, Dict):
  +                    continue
  +
                   try:
  -                    return value.getitem(index, context)
  +                    return inferred_value.getitem(index, context)
                   except (AstroidTypeError, AstroidIndexError):
                       continue
  +
               for inferredkey in key.infer(context):
                   if inferredkey is util.Uninferable:
                       continue
   
  
file_context: {"astroid/nodes/node_classes.py": "# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html\n# For details: https://github.com/PyCQA/astroid/blob/main/LICENSE\n# Copyright (c) https://github.com/PyCQA/astroid/blob/main/CONTRIBUTORS.txt\n\n\"\"\"Module for some node classes. More nodes in scoped_nodes.py\"\"\"\n\nfrom __future__ import annotations\n\nimport abc\nimport itertools\nimport sys\nimport typing\nimport warnings\nfrom collections.abc import Generator, Iterator\nfrom functools import lru_cache\nfrom typing import TYPE_CHECKING, Any, Callable, ClassVar, Optional, TypeVar, Union\n\nfrom astroid import decorators, mixins, util\nfrom astroid.bases import Instance, _infer_stmts\nfrom astroid.const import Context\nfrom astroid.context import InferenceContext\nfrom astroid.exceptions import (\n    AstroidIndexError,\n    AstroidTypeError,\n    InferenceError,\n    NoDefault,\n    ParentMissingError,\n)\nfrom astroid.manager import AstroidManager\nfrom astroid.nodes.const import OP_PRECEDENCE\nfrom astroid.nodes.node_ng import NodeNG\n\nif sys.version_info >= (3, 8):\n    from typing import Literal\nelse:\n    from typing_extensions import Literal\n\nif TYPE_CHECKING:\n    from astroid import nodes\n    from astroid.nodes import LocalsDictNodeNG\n\nif sys.version_info >= (3, 8):\n    from functools import cached_property\nelse:\n    from astroid.decorators import cachedproperty as cached_property\n\n\ndef _is_const(value):\n    return isinstance(value, tuple(CONST_CLS))\n\n\n_NodesT = TypeVar(\"_NodesT\", bound=NodeNG)\n\nAssignedStmtsPossibleNode = Union[\"List\", \"Tuple\", \"AssignName\", \"AssignAttr\", None]\nAssignedStmtsCall = Callable[\n    [\n        _NodesT,\n        AssignedStmtsPossibleNode,\n        Optional[InferenceContext],\n        Optional[typing.List[int]],\n    ],\n    Any,\n]\n\n\n@decorators.raise_if_nothing_inferred\ndef unpack_infer(stmt, context=None):\n    \"\"\"recursively generate nodes inferred by the given statement.\n    If the inferred value is a list or a tuple, recurse on the elements\n    \"\"\"\n    if isinstance(stmt, (List, Tuple)):\n        for elt in stmt.elts:\n            if elt is util.Uninferable:\n                yield elt\n                continue\n            yield from unpack_infer(elt, context)\n        return dict(node=stmt, context=context)\n    # if inferred is a final node, return it and stop\n    inferred = next(stmt.infer(context), util.Uninferable)\n    if inferred is stmt:\n        yield inferred\n        return dict(node=stmt, context=context)\n    # else, infer recursively, except Uninferable object that should be returned as is\n    for inferred in stmt.infer(context):\n        if inferred is util.Uninferable:\n            yield inferred\n        else:\n            yield from unpack_infer(inferred, context)\n\n    return dict(node=stmt, context=context)\n\n\ndef are_exclusive(stmt1, stmt2, exceptions: list[str] | None = None) -> bool:\n    \"\"\"return true if the two given statements are mutually exclusive\n\n    `exceptions` may be a list of exception names. If specified, discard If\n    branches and check one of the statement is in an exception handler catching\n    one of the given exceptions.\n\n    algorithm :\n     1) index stmt1's parents\n     2) climb among stmt2's parents until we find a common parent\n     3) if the common parent is a If or TryExcept statement, look if nodes are\n        in exclusive branches\n    \"\"\"\n    # index stmt1's parents\n    stmt1_parents = {}\n    children = {}\n    previous = stmt1\n    for node in stmt1.node_ancestors():\n        stmt1_parents[node] = 1\n        children[node] = previous\n        previous = node\n    # climb among stmt2's parents until we find a common parent\n    previous = stmt2\n    for node in stmt2.node_ancestors():\n        if node in stmt1_parents:\n            # if the common parent is a If or TryExcept statement, look if\n            # nodes are in exclusive branches\n            if isinstance(node, If) and exceptions is None:\n                if (\n                    node.locate_child(previous)[1]\n                    is not node.locate_child(children[node])[1]\n                ):\n                    return True\n            elif isinstance(node, TryExcept):\n                c2attr, c2node = node.locate_child(previous)\n                c1attr, c1node = node.locate_child(children[node])\n                if c1node is not c2node:\n                    first_in_body_caught_by_handlers = (\n                        c2attr == \"handlers\"\n                        and c1attr == \"body\"\n                        and previous.catch(exceptions)\n                    )\n                    second_in_body_caught_by_handlers = (\n                        c2attr == \"body\"\n                        and c1attr == \"handlers\"\n                        and children[node].catch(exceptions)\n                    )\n                    first_in_else_other_in_handlers = (\n                        c2attr == \"handlers\" and c1attr == \"orelse\"\n                    )\n                    second_in_else_other_in_handlers = (\n                        c2attr == \"orelse\" and c1attr == \"handlers\"\n                    )\n                    if any(\n                        (\n                            first_in_body_caught_by_handlers,\n                            second_in_body_caught_by_handlers,\n                            first_in_else_other_in_handlers,\n                            second_in_else_other_in_handlers,\n                        )\n                    ):\n                        return True\n                elif c2attr == \"handlers\" and c1attr == \"handlers\":\n                    return previous is not children[node]\n            return False\n        previous = node\n    return False\n\n\n# getitem() helpers.\n\n_SLICE_SENTINEL = object()\n\n\ndef _slice_value(index, context=None):\n    \"\"\"Get the value of the given slice index.\"\"\"\n\n    if isinstance(index, Const):\n        if isinstance(index.value, (int, type(None))):\n            return index.value\n    elif index is None:\n        return None\n    else:\n        # Try to infer what the index actually is.\n        # Since we can't return all the possible values,\n        # we'll stop at the first possible value.\n        try:\n            inferred = next(index.infer(context=context))\n        except (InferenceError, StopIteration):\n            pass\n        else:\n            if isinstance(inferred, Const):\n                if isinstance(inferred.value, (int, type(None))):\n                    return inferred.value\n\n    # Use a sentinel, because None can be a valid\n    # value that this function can return,\n    # as it is the case for unspecified bounds.\n    return _SLICE_SENTINEL\n\n\ndef _infer_slice(node, context=None):\n    lower = _slice_value(node.lower, context)\n    upper = _slice_value(node.upper, context)\n    step = _slice_value(node.step, context)\n    if all(elem is not _SLICE_SENTINEL for elem in (lower, upper, step)):\n        return slice(lower, upper, step)\n\n    raise AstroidTypeError(\n        message=\"Could not infer slice used in subscript\",\n        node=node,\n        index=node.parent,\n        context=context,\n    )\n\n\ndef _container_getitem(instance, elts, index, context=None):\n    \"\"\"Get a slice or an item, using the given *index*, for the given sequence.\"\"\"\n    try:\n        if isinstance(index, Slice):\n            index_slice = _infer_slice(index, context=context)\n            new_cls = instance.__class__()\n            new_cls.elts = elts[index_slice]\n            new_cls.parent = instance.parent\n            return new_cls\n        if isinstance(index, Const):\n            return elts[index.value]\n    except IndexError as exc:\n        raise AstroidIndexError(\n            message=\"Index {index!s} out of range\",\n            node=instance,\n            index=index,\n            context=context,\n        ) from exc\n    except TypeError as exc:\n        raise AstroidTypeError(\n            message=\"Type error {error!r}\", node=instance, index=index, context=context\n        ) from exc\n\n    raise AstroidTypeError(f\"Could not use {index} as subscript index\")\n\n\nclass Statement(NodeNG):\n    \"\"\"Statement node adding a few attributes\"\"\"\n\n    is_statement = True\n    \"\"\"Whether this node indicates a statement.\"\"\"\n\n    def next_sibling(self):\n        \"\"\"The next sibling statement node.\n\n        :returns: The next sibling statement node.\n        :rtype: NodeNG or None\n        \"\"\"\n        stmts = self.parent.child_sequence(self)\n        index = stmts.index(self)\n        try:\n            return stmts[index + 1]\n        except IndexError:\n            return None\n\n    def previous_sibling(self):\n        \"\"\"The previous sibling statement.\n\n        :returns: The previous sibling statement node.\n        :rtype: NodeNG or None\n        \"\"\"\n        stmts = self.parent.child_sequence(self)\n        index = stmts.index(self)\n        if index >= 1:\n            return stmts[index - 1]\n        return None\n\n\nclass BaseContainer(\n    mixins.ParentAssignTypeMixin, NodeNG, Instance, metaclass=abc.ABCMeta\n):\n    \"\"\"Base class for Set, FrozenSet, Tuple and List.\"\"\"\n\n    _astroid_fields = (\"elts\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.elts: list[NodeNG] = []\n        \"\"\"The elements in the node.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, elts: list[NodeNG]) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param elts: The list of elements the that node contains.\n        \"\"\"\n        self.elts = elts\n\n    @classmethod\n    def from_elements(cls, elts=None):\n        \"\"\"Create a node of this type from the given list of elements.\n\n        :param elts: The list of elements that the node should contain.\n        :type elts: list(NodeNG)\n\n        :returns: A new node containing the given elements.\n        :rtype: NodeNG\n        \"\"\"\n        node = cls()\n        if elts is None:\n            node.elts = []\n        else:\n            node.elts = [const_factory(e) if _is_const(e) else e for e in elts]\n        return node\n\n    def itered(self):\n        \"\"\"An iterator over the elements this node contains.\n\n        :returns: The contents of this node.\n        :rtype: iterable(NodeNG)\n        \"\"\"\n        return self.elts\n\n    def bool_value(self, context=None):\n        \"\"\"Determine the boolean value of this node.\n\n        :returns: The boolean value of this node.\n        :rtype: bool or Uninferable\n        \"\"\"\n        return bool(self.elts)\n\n    @abc.abstractmethod\n    def pytype(self):\n        \"\"\"Get the name of the type that this node represents.\n\n        :returns: The name of the type.\n        :rtype: str\n        \"\"\"\n\n    def get_children(self):\n        yield from self.elts\n\n\nclass LookupMixIn:\n    \"\"\"Mixin to look up a name in the right scope.\"\"\"\n\n    @lru_cache()  # noqa\n    def lookup(self, name: str) -> tuple[str, list[NodeNG]]:\n        \"\"\"Lookup where the given variable is assigned.\n\n        The lookup starts from self's scope. If self is not a frame itself\n        and the name is found in the inner frame locals, statements will be\n        filtered to remove ignorable statements according to self's location.\n\n        :param name: The name of the variable to find assignments for.\n\n        :returns: The scope node and the list of assignments associated to the\n            given name according to the scope where it has been found (locals,\n            globals or builtin).\n        \"\"\"\n        return self.scope().scope_lookup(self, name)\n\n    def ilookup(self, name):\n        \"\"\"Lookup the inferred values of the given variable.\n\n        :param name: The variable name to find values for.\n        :type name: str\n\n        :returns: The inferred values of the statements returned from\n            :meth:`lookup`.\n        :rtype: iterable\n        \"\"\"\n        frame, stmts = self.lookup(name)\n        context = InferenceContext()\n        return _infer_stmts(stmts, context, frame)\n\n\n# Name classes\n\n\nclass AssignName(\n    mixins.NoChildrenMixin, LookupMixIn, mixins.ParentAssignTypeMixin, NodeNG\n):\n    \"\"\"Variation of :class:`ast.Assign` representing assignment to a name.\n\n    An :class:`AssignName` is the name of something that is assigned to.\n    This includes variables defined in a function signature or in a loop.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('variable = range(10)')\n    >>> node\n    <Assign l.1 at 0x7effe1db8550>\n    >>> list(node.get_children())\n    [<AssignName.variable l.1 at 0x7effe1db8748>, <Call l.1 at 0x7effe1db8630>]\n    >>> list(node.get_children())[0].as_string()\n    'variable'\n    \"\"\"\n\n    _other_fields = (\"name\",)\n\n    @decorators.deprecate_default_argument_values(name=\"str\")\n    def __init__(\n        self,\n        name: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param name: The name that is assigned to.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.name: str | None = name\n        \"\"\"The name that is assigned to.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[AssignName]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n\nclass DelName(\n    mixins.NoChildrenMixin, LookupMixIn, mixins.ParentAssignTypeMixin, NodeNG\n):\n    \"\"\"Variation of :class:`ast.Delete` representing deletion of a name.\n\n    A :class:`DelName` is the name of something that is deleted.\n\n    >>> import astroid\n    >>> node = astroid.extract_node(\"del variable #@\")\n    >>> list(node.get_children())\n    [<DelName.variable l.1 at 0x7effe1da4d30>]\n    >>> list(node.get_children())[0].as_string()\n    'variable'\n    \"\"\"\n\n    _other_fields = (\"name\",)\n\n    @decorators.deprecate_default_argument_values(name=\"str\")\n    def __init__(\n        self,\n        name: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param name: The name that is being deleted.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.name: str | None = name\n        \"\"\"The name that is being deleted.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n\nclass Name(mixins.NoChildrenMixin, LookupMixIn, NodeNG):\n    \"\"\"Class representing an :class:`ast.Name` node.\n\n    A :class:`Name` node is something that is named, but not covered by\n    :class:`AssignName` or :class:`DelName`.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('range(10)')\n    >>> node\n    <Call l.1 at 0x7effe1db8710>\n    >>> list(node.get_children())\n    [<Name.range l.1 at 0x7effe1db86a0>, <Const.int l.1 at 0x7effe1db8518>]\n    >>> list(node.get_children())[0].as_string()\n    'range'\n    \"\"\"\n\n    _other_fields = (\"name\",)\n\n    @decorators.deprecate_default_argument_values(name=\"str\")\n    def __init__(\n        self,\n        name: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param name: The name that this node refers to.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.name: str | None = name\n        \"\"\"The name that this node refers to.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def _get_name_nodes(self):\n        yield self\n\n        for child_node in self.get_children():\n            yield from child_node._get_name_nodes()\n\n\nclass Arguments(mixins.AssignTypeMixin, NodeNG):\n    \"\"\"Class representing an :class:`ast.arguments` node.\n\n    An :class:`Arguments` node represents that arguments in a\n    function definition.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('def foo(bar): pass')\n    >>> node\n    <FunctionDef.foo l.1 at 0x7effe1db8198>\n    >>> node.args\n    <Arguments l.1 at 0x7effe1db82e8>\n    \"\"\"\n\n    # Python 3.4+ uses a different approach regarding annotations,\n    # each argument is a new class, _ast.arg, which exposes an\n    # 'annotation' attribute. In astroid though, arguments are exposed\n    # as is in the Arguments node and the only way to expose annotations\n    # is by using something similar with Python 3.3:\n    #  - we expose 'varargannotation' and 'kwargannotation' of annotations\n    #    of varargs and kwargs.\n    #  - we expose 'annotation', a list with annotations for\n    #    for each normal argument. If an argument doesn't have an\n    #    annotation, its value will be None.\n    _astroid_fields = (\n        \"args\",\n        \"defaults\",\n        \"kwonlyargs\",\n        \"posonlyargs\",\n        \"posonlyargs_annotations\",\n        \"kw_defaults\",\n        \"annotations\",\n        \"varargannotation\",\n        \"kwargannotation\",\n        \"kwonlyargs_annotations\",\n        \"type_comment_args\",\n        \"type_comment_kwonlyargs\",\n        \"type_comment_posonlyargs\",\n    )\n\n    _other_fields = (\"vararg\", \"kwarg\")\n\n    lineno: None\n    col_offset: None\n    end_lineno: None\n    end_col_offset: None\n\n    def __init__(\n        self,\n        vararg: str | None = None,\n        kwarg: str | None = None,\n        parent: NodeNG | None = None,\n    ) -> None:\n        \"\"\"\n        :param vararg: The name of the variable length arguments.\n\n        :param kwarg: The name of the variable length keyword arguments.\n\n        :param parent: The parent node in the syntax tree.\n        \"\"\"\n        super().__init__(parent=parent)\n\n        self.vararg: str | None = vararg  # can be None\n        \"\"\"The name of the variable length arguments.\"\"\"\n\n        self.kwarg: str | None = kwarg  # can be None\n        \"\"\"The name of the variable length keyword arguments.\"\"\"\n\n        self.args: list[AssignName] | None\n        \"\"\"The names of the required arguments.\n\n        Can be None if the associated function does not have a retrievable\n        signature and the arguments are therefore unknown.\n        This can happen with (builtin) functions implemented in C that have\n        incomplete signature information.\n        \"\"\"\n        # TODO: Check if other attributes should also be None when\n        # .args is None.\n\n        self.defaults: list[NodeNG]\n        \"\"\"The default values for arguments that can be passed positionally.\"\"\"\n\n        self.kwonlyargs: list[AssignName]\n        \"\"\"The keyword arguments that cannot be passed positionally.\"\"\"\n\n        self.posonlyargs: list[AssignName] = []\n        \"\"\"The arguments that can only be passed positionally.\"\"\"\n\n        self.kw_defaults: list[NodeNG | None]\n        \"\"\"The default values for keyword arguments that cannot be passed positionally.\"\"\"\n\n        self.annotations: list[NodeNG | None]\n        \"\"\"The type annotations of arguments that can be passed positionally.\"\"\"\n\n        self.posonlyargs_annotations: list[NodeNG | None] = []\n        \"\"\"The type annotations of arguments that can only be passed positionally.\"\"\"\n\n        self.kwonlyargs_annotations: list[NodeNG | None] = []\n        \"\"\"The type annotations of arguments that cannot be passed positionally.\"\"\"\n\n        self.type_comment_args: list[NodeNG | None] = []\n        \"\"\"The type annotation, passed by a type comment, of each argument.\n\n        If an argument does not have a type comment,\n        the value for that argument will be None.\n        \"\"\"\n\n        self.type_comment_kwonlyargs: list[NodeNG | None] = []\n        \"\"\"The type annotation, passed by a type comment, of each keyword only argument.\n\n        If an argument does not have a type comment,\n        the value for that argument will be None.\n        \"\"\"\n\n        self.type_comment_posonlyargs: list[NodeNG | None] = []\n        \"\"\"The type annotation, passed by a type comment, of each positional argument.\n\n        If an argument does not have a type comment,\n        the value for that argument will be None.\n        \"\"\"\n\n        self.varargannotation: NodeNG | None = None  # can be None\n        \"\"\"The type annotation for the variable length arguments.\"\"\"\n\n        self.kwargannotation: NodeNG | None = None  # can be None\n        \"\"\"The type annotation for the variable length keyword arguments.\"\"\"\n\n    # pylint: disable=too-many-arguments\n    def postinit(\n        self,\n        args: list[AssignName] | None,\n        defaults: list[NodeNG],\n        kwonlyargs: list[AssignName],\n        kw_defaults: list[NodeNG | None],\n        annotations: list[NodeNG | None],\n        posonlyargs: list[AssignName] | None = None,\n        kwonlyargs_annotations: list[NodeNG | None] | None = None,\n        posonlyargs_annotations: list[NodeNG | None] | None = None,\n        varargannotation: NodeNG | None = None,\n        kwargannotation: NodeNG | None = None,\n        type_comment_args: list[NodeNG | None] | None = None,\n        type_comment_kwonlyargs: list[NodeNG | None] | None = None,\n        type_comment_posonlyargs: list[NodeNG | None] | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param args: The names of the required arguments.\n\n        :param defaults: The default values for arguments that can be passed\n            positionally.\n\n        :param kwonlyargs: The keyword arguments that cannot be passed\n            positionally.\n\n        :param posonlyargs: The arguments that can only be passed\n            positionally.\n\n        :param kw_defaults: The default values for keyword arguments that\n            cannot be passed positionally.\n\n        :param annotations: The type annotations of arguments that can be\n            passed positionally.\n\n        :param kwonlyargs_annotations: The type annotations of arguments that\n            cannot be passed positionally. This should always be passed in\n            Python 3.\n\n        :param posonlyargs_annotations: The type annotations of arguments that\n            can only be passed positionally. This should always be passed in\n            Python 3.\n\n        :param varargannotation: The type annotation for the variable length\n            arguments.\n\n        :param kwargannotation: The type annotation for the variable length\n            keyword arguments.\n\n        :param type_comment_args: The type annotation,\n            passed by a type comment, of each argument.\n\n        :param type_comment_args: The type annotation,\n            passed by a type comment, of each keyword only argument.\n\n        :param type_comment_args: The type annotation,\n            passed by a type comment, of each positional argument.\n        \"\"\"\n        self.args = args\n        self.defaults = defaults\n        self.kwonlyargs = kwonlyargs\n        if posonlyargs is not None:\n            self.posonlyargs = posonlyargs\n        self.kw_defaults = kw_defaults\n        self.annotations = annotations\n        if kwonlyargs_annotations is not None:\n            self.kwonlyargs_annotations = kwonlyargs_annotations\n        if posonlyargs_annotations is not None:\n            self.posonlyargs_annotations = posonlyargs_annotations\n        self.varargannotation = varargannotation\n        self.kwargannotation = kwargannotation\n        if type_comment_args is not None:\n            self.type_comment_args = type_comment_args\n        if type_comment_kwonlyargs is not None:\n            self.type_comment_kwonlyargs = type_comment_kwonlyargs\n        if type_comment_posonlyargs is not None:\n            self.type_comment_posonlyargs = type_comment_posonlyargs\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[Arguments]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def _infer_name(self, frame, name):\n        if self.parent is frame:\n            return name\n        return None\n\n    @cached_property\n    def fromlineno(self):\n        \"\"\"The first line that this node appears on in the source code.\n\n        :type: int or None\n        \"\"\"\n        lineno = super().fromlineno\n        return max(lineno, self.parent.fromlineno or 0)\n\n    @cached_property\n    def arguments(self):\n        \"\"\"Get all the arguments for this node, including positional only and positional and keyword\"\"\"\n        return list(itertools.chain((self.posonlyargs or ()), self.args or ()))\n\n    def format_args(self):\n        \"\"\"Get the arguments formatted as string.\n\n        :returns: The formatted arguments.\n        :rtype: str\n        \"\"\"\n        result = []\n        positional_only_defaults = []\n        positional_or_keyword_defaults = self.defaults\n        if self.defaults:\n            args = self.args or []\n            positional_or_keyword_defaults = self.defaults[-len(args) :]\n            positional_only_defaults = self.defaults[: len(self.defaults) - len(args)]\n\n        if self.posonlyargs:\n            result.append(\n                _format_args(\n                    self.posonlyargs,\n                    positional_only_defaults,\n                    self.posonlyargs_annotations,\n                )\n            )\n            result.append(\"/\")\n        if self.args:\n            result.append(\n                _format_args(\n                    self.args,\n                    positional_or_keyword_defaults,\n                    getattr(self, \"annotations\", None),\n                )\n            )\n        if self.vararg:\n            result.append(f\"*{self.vararg}\")\n        if self.kwonlyargs:\n            if not self.vararg:\n                result.append(\"*\")\n            result.append(\n                _format_args(\n                    self.kwonlyargs, self.kw_defaults, self.kwonlyargs_annotations\n                )\n            )\n        if self.kwarg:\n            result.append(f\"**{self.kwarg}\")\n        return \", \".join(result)\n\n    def default_value(self, argname):\n        \"\"\"Get the default value for an argument.\n\n        :param argname: The name of the argument to get the default value for.\n        :type argname: str\n\n        :raises NoDefault: If there is no default value defined for the\n            given argument.\n        \"\"\"\n        args = self.arguments\n        index = _find_arg(argname, args)[0]\n        if index is not None:\n            idx = index - (len(args) - len(self.defaults))\n            if idx >= 0:\n                return self.defaults[idx]\n        index = _find_arg(argname, self.kwonlyargs)[0]\n        if index is not None and self.kw_defaults[index] is not None:\n            return self.kw_defaults[index]\n        raise NoDefault(func=self.parent, name=argname)\n\n    def is_argument(self, name):\n        \"\"\"Check if the given name is defined in the arguments.\n\n        :param name: The name to check for.\n        :type name: str\n\n        :returns: True if the given name is defined in the arguments,\n            False otherwise.\n        :rtype: bool\n        \"\"\"\n        if name == self.vararg:\n            return True\n        if name == self.kwarg:\n            return True\n        return (\n            self.find_argname(name, rec=True)[1] is not None\n            or self.kwonlyargs\n            and _find_arg(name, self.kwonlyargs, rec=True)[1] is not None\n        )\n\n    def find_argname(self, argname, rec=False):\n        \"\"\"Get the index and :class:`AssignName` node for given name.\n\n        :param argname: The name of the argument to search for.\n        :type argname: str\n\n        :param rec: Whether or not to include arguments in unpacked tuples\n            in the search.\n        :type rec: bool\n\n        :returns: The index and node for the argument.\n        :rtype: tuple(str or None, AssignName or None)\n        \"\"\"\n        if self.arguments:\n            return _find_arg(argname, self.arguments, rec)\n        return None, None\n\n    def get_children(self):\n        yield from self.posonlyargs or ()\n\n        for elt in self.posonlyargs_annotations:\n            if elt is not None:\n                yield elt\n\n        yield from self.args or ()\n\n        yield from self.defaults\n        yield from self.kwonlyargs\n\n        for elt in self.kw_defaults:\n            if elt is not None:\n                yield elt\n\n        for elt in self.annotations:\n            if elt is not None:\n                yield elt\n\n        if self.varargannotation is not None:\n            yield self.varargannotation\n\n        if self.kwargannotation is not None:\n            yield self.kwargannotation\n\n        for elt in self.kwonlyargs_annotations:\n            if elt is not None:\n                yield elt\n\n\ndef _find_arg(argname, args, rec=False):\n    for i, arg in enumerate(args):\n        if isinstance(arg, Tuple):\n            if rec:\n                found = _find_arg(argname, arg.elts)\n                if found[0] is not None:\n                    return found\n        elif arg.name == argname:\n            return i, arg\n    return None, None\n\n\ndef _format_args(args, defaults=None, annotations=None):\n    values = []\n    if args is None:\n        return \"\"\n    if annotations is None:\n        annotations = []\n    if defaults is not None:\n        default_offset = len(args) - len(defaults)\n    packed = itertools.zip_longest(args, annotations)\n    for i, (arg, annotation) in enumerate(packed):\n        if isinstance(arg, Tuple):\n            values.append(f\"({_format_args(arg.elts)})\")\n        else:\n            argname = arg.name\n            default_sep = \"=\"\n            if annotation is not None:\n                argname += \": \" + annotation.as_string()\n                default_sep = \" = \"\n            values.append(argname)\n\n            if defaults is not None and i >= default_offset:\n                if defaults[i - default_offset] is not None:\n                    values[-1] += default_sep + defaults[i - default_offset].as_string()\n    return \", \".join(values)\n\n\nclass AssignAttr(mixins.ParentAssignTypeMixin, NodeNG):\n    \"\"\"Variation of :class:`ast.Assign` representing assignment to an attribute.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('self.attribute = range(10)')\n    >>> node\n    <Assign l.1 at 0x7effe1d521d0>\n    >>> list(node.get_children())\n    [<AssignAttr.attribute l.1 at 0x7effe1d52320>, <Call l.1 at 0x7effe1d522e8>]\n    >>> list(node.get_children())[0].as_string()\n    'self.attribute'\n    \"\"\"\n\n    _astroid_fields = (\"expr\",)\n    _other_fields = (\"attrname\",)\n\n    @decorators.deprecate_default_argument_values(attrname=\"str\")\n    def __init__(\n        self,\n        attrname: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param attrname: The name of the attribute being assigned to.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.expr: NodeNG | None = None\n        \"\"\"What has the attribute that is being assigned to.\"\"\"\n\n        self.attrname: str | None = attrname\n        \"\"\"The name of the attribute being assigned to.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, expr: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param expr: What has the attribute that is being assigned to.\n        \"\"\"\n        self.expr = expr\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[AssignAttr]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def get_children(self):\n        yield self.expr\n\n\nclass Assert(Statement):\n    \"\"\"Class representing an :class:`ast.Assert` node.\n\n    An :class:`Assert` node represents an assert statement.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('assert len(things) == 10, \"Not enough things\"')\n    >>> node\n    <Assert l.1 at 0x7effe1d527b8>\n    \"\"\"\n\n    _astroid_fields = (\"test\", \"fail\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.test: NodeNG | None = None\n        \"\"\"The test that passes or fails the assertion.\"\"\"\n\n        self.fail: NodeNG | None = None  # can be None\n        \"\"\"The message shown when the assertion fails.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, test: NodeNG | None = None, fail: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param test: The test that passes or fails the assertion.\n\n        :param fail: The message shown when the assertion fails.\n        \"\"\"\n        self.fail = fail\n        self.test = test\n\n    def get_children(self):\n        yield self.test\n\n        if self.fail is not None:\n            yield self.fail\n\n\nclass Assign(mixins.AssignTypeMixin, Statement):\n    \"\"\"Class representing an :class:`ast.Assign` node.\n\n    An :class:`Assign` is a statement where something is explicitly\n    asssigned to.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('variable = range(10)')\n    >>> node\n    <Assign l.1 at 0x7effe1db8550>\n    \"\"\"\n\n    _astroid_fields = (\"targets\", \"value\")\n    _other_other_fields = (\"type_annotation\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.targets: list[NodeNG] = []\n        \"\"\"What is being assigned to.\"\"\"\n\n        self.value: NodeNG | None = None\n        \"\"\"The value being assigned to the variables.\"\"\"\n\n        self.type_annotation: NodeNG | None = None  # can be None\n        \"\"\"If present, this will contain the type annotation passed by a type comment\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        targets: list[NodeNG] | None = None,\n        value: NodeNG | None = None,\n        type_annotation: NodeNG | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param targets: What is being assigned to.\n        :param value: The value being assigned to the variables.\n        :param type_annotation:\n        \"\"\"\n        if targets is not None:\n            self.targets = targets\n        self.value = value\n        self.type_annotation = type_annotation\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[Assign]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def get_children(self):\n        yield from self.targets\n\n        yield self.value\n\n    @decorators.cached\n    def _get_assign_nodes(self):\n        return [self] + list(self.value._get_assign_nodes())\n\n    def _get_yield_nodes_skip_lambdas(self):\n        yield from self.value._get_yield_nodes_skip_lambdas()\n\n\nclass AnnAssign(mixins.AssignTypeMixin, Statement):\n    \"\"\"Class representing an :class:`ast.AnnAssign` node.\n\n    An :class:`AnnAssign` is an assignment with a type annotation.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('variable: List[int] = range(10)')\n    >>> node\n    <AnnAssign l.1 at 0x7effe1d4c630>\n    \"\"\"\n\n    _astroid_fields = (\"target\", \"annotation\", \"value\")\n    _other_fields = (\"simple\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.target: NodeNG | None = None\n        \"\"\"What is being assigned to.\"\"\"\n\n        self.annotation: NodeNG | None = None\n        \"\"\"The type annotation of what is being assigned to.\"\"\"\n\n        self.value: NodeNG | None = None  # can be None\n        \"\"\"The value being assigned to the variables.\"\"\"\n\n        self.simple: int | None = None\n        \"\"\"Whether :attr:`target` is a pure name or a complex statement.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        target: NodeNG,\n        annotation: NodeNG,\n        simple: int,\n        value: NodeNG | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param target: What is being assigned to.\n\n        :param annotation: The type annotation of what is being assigned to.\n\n        :param simple: Whether :attr:`target` is a pure name\n            or a complex statement.\n\n        :param value: The value being assigned to the variables.\n        \"\"\"\n        self.target = target\n        self.annotation = annotation\n        self.value = value\n        self.simple = simple\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[AnnAssign]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def get_children(self):\n        yield self.target\n        yield self.annotation\n\n        if self.value is not None:\n            yield self.value\n\n\nclass AugAssign(mixins.AssignTypeMixin, Statement):\n    \"\"\"Class representing an :class:`ast.AugAssign` node.\n\n    An :class:`AugAssign` is an assignment paired with an operator.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('variable += 1')\n    >>> node\n    <AugAssign l.1 at 0x7effe1db4d68>\n    \"\"\"\n\n    _astroid_fields = (\"target\", \"value\")\n    _other_fields = (\"op\",)\n\n    @decorators.deprecate_default_argument_values(op=\"str\")\n    def __init__(\n        self,\n        op: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param op: The operator that is being combined with the assignment.\n            This includes the equals sign.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.target: NodeNG | None = None\n        \"\"\"What is being assigned to.\"\"\"\n\n        self.op: str | None = op\n        \"\"\"The operator that is being combined with the assignment.\n\n        This includes the equals sign.\n        \"\"\"\n\n        self.value: NodeNG | None = None\n        \"\"\"The value being assigned to the variable.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self, target: NodeNG | None = None, value: NodeNG | None = None\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param target: What is being assigned to.\n\n        :param value: The value being assigned to the variable.\n        \"\"\"\n        self.target = target\n        self.value = value\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[AugAssign]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    # This is set by inference.py\n    def _infer_augassign(self, context=None):\n        raise NotImplementedError\n\n    def type_errors(self, context=None):\n        \"\"\"Get a list of type errors which can occur during inference.\n\n        Each TypeError is represented by a :class:`BadBinaryOperationMessage` ,\n        which holds the original exception.\n\n        :returns: The list of possible type errors.\n        :rtype: list(BadBinaryOperationMessage)\n        \"\"\"\n        try:\n            results = self._infer_augassign(context=context)\n            return [\n                result\n                for result in results\n                if isinstance(result, util.BadBinaryOperationMessage)\n            ]\n        except InferenceError:\n            return []\n\n    def get_children(self):\n        yield self.target\n        yield self.value\n\n    def _get_yield_nodes_skip_lambdas(self):\n        \"\"\"An AugAssign node can contain a Yield node in the value\"\"\"\n        yield from self.value._get_yield_nodes_skip_lambdas()\n        yield from super()._get_yield_nodes_skip_lambdas()\n\n\nclass BinOp(NodeNG):\n    \"\"\"Class representing an :class:`ast.BinOp` node.\n\n    A :class:`BinOp` node is an application of a binary operator.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('a + b')\n    >>> node\n    <BinOp l.1 at 0x7f23b2e8cfd0>\n    \"\"\"\n\n    _astroid_fields = (\"left\", \"right\")\n    _other_fields = (\"op\",)\n\n    @decorators.deprecate_default_argument_values(op=\"str\")\n    def __init__(\n        self,\n        op: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param op: The operator.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.left: NodeNG | None = None\n        \"\"\"What is being applied to the operator on the left side.\"\"\"\n\n        self.op: str | None = op\n        \"\"\"The operator.\"\"\"\n\n        self.right: NodeNG | None = None\n        \"\"\"What is being applied to the operator on the right side.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, left: NodeNG | None = None, right: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param left: What is being applied to the operator on the left side.\n\n        :param right: What is being applied to the operator on the right side.\n        \"\"\"\n        self.left = left\n        self.right = right\n\n    # This is set by inference.py\n    def _infer_binop(self, context=None):\n        raise NotImplementedError\n\n    def type_errors(self, context=None):\n        \"\"\"Get a list of type errors which can occur during inference.\n\n        Each TypeError is represented by a :class:`BadBinaryOperationMessage`,\n        which holds the original exception.\n\n        :returns: The list of possible type errors.\n        :rtype: list(BadBinaryOperationMessage)\n        \"\"\"\n        try:\n            results = self._infer_binop(context=context)\n            return [\n                result\n                for result in results\n                if isinstance(result, util.BadBinaryOperationMessage)\n            ]\n        except InferenceError:\n            return []\n\n    def get_children(self):\n        yield self.left\n        yield self.right\n\n    def op_precedence(self):\n        return OP_PRECEDENCE[self.op]\n\n    def op_left_associative(self):\n        # 2**3**4 == 2**(3**4)\n        return self.op != \"**\"\n\n\nclass BoolOp(NodeNG):\n    \"\"\"Class representing an :class:`ast.BoolOp` node.\n\n    A :class:`BoolOp` is an application of a boolean operator.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('a and b')\n    >>> node\n    <BinOp l.1 at 0x7f23b2e71c50>\n    \"\"\"\n\n    _astroid_fields = (\"values\",)\n    _other_fields = (\"op\",)\n\n    @decorators.deprecate_default_argument_values(op=\"str\")\n    def __init__(\n        self,\n        op: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param op: The operator.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.op: str | None = op\n        \"\"\"The operator.\"\"\"\n\n        self.values: list[NodeNG] = []\n        \"\"\"The values being applied to the operator.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, values: list[NodeNG] | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param values: The values being applied to the operator.\n        \"\"\"\n        if values is not None:\n            self.values = values\n\n    def get_children(self):\n        yield from self.values\n\n    def op_precedence(self):\n        return OP_PRECEDENCE[self.op]\n\n\nclass Break(mixins.NoChildrenMixin, Statement):\n    \"\"\"Class representing an :class:`ast.Break` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('break')\n    >>> node\n    <Break l.1 at 0x7f23b2e9e5c0>\n    \"\"\"\n\n\nclass Call(NodeNG):\n    \"\"\"Class representing an :class:`ast.Call` node.\n\n    A :class:`Call` node is a call to a function, method, etc.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('function()')\n    >>> node\n    <Call l.1 at 0x7f23b2e71eb8>\n    \"\"\"\n\n    _astroid_fields = (\"func\", \"args\", \"keywords\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.func: NodeNG | None = None\n        \"\"\"What is being called.\"\"\"\n\n        self.args: list[NodeNG] = []\n        \"\"\"The positional arguments being given to the call.\"\"\"\n\n        self.keywords: list[Keyword] = []\n        \"\"\"The keyword arguments being given to the call.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        func: NodeNG | None = None,\n        args: list[NodeNG] | None = None,\n        keywords: list[Keyword] | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param func: What is being called.\n\n        :param args: The positional arguments being given to the call.\n\n        :param keywords: The keyword arguments being given to the call.\n        \"\"\"\n        self.func = func\n        if args is not None:\n            self.args = args\n        if keywords is not None:\n            self.keywords = keywords\n\n    @property\n    def starargs(self) -> list[Starred]:\n        \"\"\"The positional arguments that unpack something.\"\"\"\n        return [arg for arg in self.args if isinstance(arg, Starred)]\n\n    @property\n    def kwargs(self) -> list[Keyword]:\n        \"\"\"The keyword arguments that unpack something.\"\"\"\n        return [keyword for keyword in self.keywords if keyword.arg is None]\n\n    def get_children(self):\n        yield self.func\n\n        yield from self.args\n\n        yield from self.keywords\n\n\nclass Compare(NodeNG):\n    \"\"\"Class representing an :class:`ast.Compare` node.\n\n    A :class:`Compare` node indicates a comparison.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('a <= b <= c')\n    >>> node\n    <Compare l.1 at 0x7f23b2e9e6d8>\n    >>> node.ops\n    [('<=', <Name.b l.1 at 0x7f23b2e9e2b0>), ('<=', <Name.c l.1 at 0x7f23b2e9e390>)]\n    \"\"\"\n\n    _astroid_fields = (\"left\", \"ops\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.left: NodeNG | None = None\n        \"\"\"The value at the left being applied to a comparison operator.\"\"\"\n\n        self.ops: list[tuple[str, NodeNG]] = []\n        \"\"\"The remainder of the operators and their relevant right hand value.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        left: NodeNG | None = None,\n        ops: list[tuple[str, NodeNG]] | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param left: The value at the left being applied to a comparison\n            operator.\n\n        :param ops: The remainder of the operators\n            and their relevant right hand value.\n        \"\"\"\n        self.left = left\n        if ops is not None:\n            self.ops = ops\n\n    def get_children(self):\n        \"\"\"Get the child nodes below this node.\n\n        Overridden to handle the tuple fields and skip returning the operator\n        strings.\n\n        :returns: The children.\n        :rtype: iterable(NodeNG)\n        \"\"\"\n        yield self.left\n        for _, comparator in self.ops:\n            yield comparator  # we don't want the 'op'\n\n    def last_child(self):\n        \"\"\"An optimized version of list(get_children())[-1]\n\n        :returns: The last child.\n        :rtype: NodeNG\n        \"\"\"\n        # XXX maybe if self.ops:\n        return self.ops[-1][1]\n        # return self.left\n\n\nclass Comprehension(NodeNG):\n    \"\"\"Class representing an :class:`ast.comprehension` node.\n\n    A :class:`Comprehension` indicates the loop inside any type of\n    comprehension including generator expressions.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('[x for x in some_values]')\n    >>> list(node.get_children())\n    [<Name.x l.1 at 0x7f23b2e352b0>, <Comprehension l.1 at 0x7f23b2e35320>]\n    >>> list(node.get_children())[1].as_string()\n    'for x in some_values'\n    \"\"\"\n\n    _astroid_fields = (\"target\", \"iter\", \"ifs\")\n    _other_fields = (\"is_async\",)\n\n    optional_assign = True\n    \"\"\"Whether this node optionally assigns a variable.\"\"\"\n\n    lineno: None\n    col_offset: None\n    end_lineno: None\n    end_col_offset: None\n\n    def __init__(self, parent: NodeNG | None = None) -> None:\n        \"\"\"\n        :param parent: The parent node in the syntax tree.\n        \"\"\"\n        self.target: NodeNG | None = None\n        \"\"\"What is assigned to by the comprehension.\"\"\"\n\n        self.iter: NodeNG | None = None\n        \"\"\"What is iterated over by the comprehension.\"\"\"\n\n        self.ifs: list[NodeNG] = []\n        \"\"\"The contents of any if statements that filter the comprehension.\"\"\"\n\n        self.is_async: bool | None = None\n        \"\"\"Whether this is an asynchronous comprehension or not.\"\"\"\n\n        super().__init__(parent=parent)\n\n    # pylint: disable=redefined-builtin; same name as builtin ast module.\n    def postinit(\n        self,\n        target: NodeNG | None = None,\n        iter: NodeNG | None = None,\n        ifs: list[NodeNG] | None = None,\n        is_async: bool | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param target: What is assigned to by the comprehension.\n\n        :param iter: What is iterated over by the comprehension.\n\n        :param ifs: The contents of any if statements that filter\n            the comprehension.\n\n        :param is_async: Whether this is an asynchronous comprehension or not.\n        \"\"\"\n        self.target = target\n        self.iter = iter\n        if ifs is not None:\n            self.ifs = ifs\n        self.is_async = is_async\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[Comprehension]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def assign_type(self):\n        \"\"\"The type of assignment that this node performs.\n\n        :returns: The assignment type.\n        :rtype: NodeNG\n        \"\"\"\n        return self\n\n    def _get_filtered_stmts(self, lookup_node, node, stmts, mystmt: Statement | None):\n        \"\"\"method used in filter_stmts\"\"\"\n        if self is mystmt:\n            if isinstance(lookup_node, (Const, Name)):\n                return [lookup_node], True\n\n        elif self.statement(future=True) is mystmt:\n            # original node's statement is the assignment, only keeps\n            # current node (gen exp, list comp)\n\n            return [node], True\n\n        return stmts, False\n\n    def get_children(self):\n        yield self.target\n        yield self.iter\n\n        yield from self.ifs\n\n\nclass Const(mixins.NoChildrenMixin, NodeNG, Instance):\n    \"\"\"Class representing any constant including num, str, bool, None, bytes.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('(5, \"This is a string.\", True, None, b\"bytes\")')\n    >>> node\n    <Tuple.tuple l.1 at 0x7f23b2e358d0>\n    >>> list(node.get_children())\n    [<Const.int l.1 at 0x7f23b2e35940>,\n    <Const.str l.1 at 0x7f23b2e35978>,\n    <Const.bool l.1 at 0x7f23b2e359b0>,\n    <Const.NoneType l.1 at 0x7f23b2e359e8>,\n    <Const.bytes l.1 at 0x7f23b2e35a20>]\n    \"\"\"\n\n    _other_fields = (\"value\", \"kind\")\n\n    def __init__(\n        self,\n        value: Any,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        kind: str | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param value: The value that the constant represents.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param kind: The string prefix. \"u\" for u-prefixed strings and ``None`` otherwise. Python 3.8+ only.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.value: Any = value\n        \"\"\"The value that the constant represents.\"\"\"\n\n        self.kind: str | None = kind  # can be None\n        \"\"\"\"The string prefix. \"u\" for u-prefixed strings and ``None`` otherwise. Python 3.8+ only.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def __getattr__(self, name):\n        # This is needed because of Proxy's __getattr__ method.\n        # Calling object.__new__ on this class without calling\n        # __init__ would result in an infinite loop otherwise\n        # since __getattr__ is called when an attribute doesn't\n        # exist and self._proxied indirectly calls self.value\n        # and Proxy __getattr__ calls self.value\n        if name == \"value\":\n            raise AttributeError\n        return super().__getattr__(name)\n\n    def getitem(self, index, context=None):\n        \"\"\"Get an item from this node if subscriptable.\n\n        :param index: The node to use as a subscript index.\n        :type index: Const or Slice\n\n        :raises AstroidTypeError: When the given index cannot be used as a\n            subscript index, or if this node is not subscriptable.\n        \"\"\"\n        if isinstance(index, Const):\n            index_value = index.value\n        elif isinstance(index, Slice):\n            index_value = _infer_slice(index, context=context)\n\n        else:\n            raise AstroidTypeError(\n                f\"Could not use type {type(index)} as subscript index\"\n            )\n\n        try:\n            if isinstance(self.value, (str, bytes)):\n                return Const(self.value[index_value])\n        except IndexError as exc:\n            raise AstroidIndexError(\n                message=\"Index {index!r} out of range\",\n                node=self,\n                index=index,\n                context=context,\n            ) from exc\n        except TypeError as exc:\n            raise AstroidTypeError(\n                message=\"Type error {error!r}\", node=self, index=index, context=context\n            ) from exc\n\n        raise AstroidTypeError(f\"{self!r} (value={self.value})\")\n\n    def has_dynamic_getattr(self):\n        \"\"\"Check if the node has a custom __getattr__ or __getattribute__.\n\n        :returns: True if the class has a custom\n            __getattr__ or __getattribute__, False otherwise.\n            For a :class:`Const` this is always ``False``.\n        :rtype: bool\n        \"\"\"\n        return False\n\n    def itered(self):\n        \"\"\"An iterator over the elements this node contains.\n\n        :returns: The contents of this node.\n        :rtype: iterable(Const)\n\n        :raises TypeError: If this node does not represent something that is iterable.\n        \"\"\"\n        if isinstance(self.value, str):\n            return [const_factory(elem) for elem in self.value]\n        raise TypeError(f\"Cannot iterate over type {type(self.value)!r}\")\n\n    def pytype(self):\n        \"\"\"Get the name of the type that this node represents.\n\n        :returns: The name of the type.\n        :rtype: str\n        \"\"\"\n        return self._proxied.qname()\n\n    def bool_value(self, context=None):\n        \"\"\"Determine the boolean value of this node.\n\n        :returns: The boolean value of this node.\n        :rtype: bool\n        \"\"\"\n        return bool(self.value)\n\n\nclass Continue(mixins.NoChildrenMixin, Statement):\n    \"\"\"Class representing an :class:`ast.Continue` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('continue')\n    >>> node\n    <Continue l.1 at 0x7f23b2e35588>\n    \"\"\"\n\n\nclass Decorators(NodeNG):\n    \"\"\"A node representing a list of decorators.\n\n    A :class:`Decorators` is the decorators that are applied to\n    a method or function.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    @property\n    def my_property(self):\n        return 3\n    ''')\n    >>> node\n    <FunctionDef.my_property l.2 at 0x7f23b2e35d30>\n    >>> list(node.get_children())[0]\n    <Decorators l.1 at 0x7f23b2e35d68>\n    \"\"\"\n\n    _astroid_fields = (\"nodes\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.nodes: list[NodeNG]\n        \"\"\"The decorators that this node contains.\n\n        :type: list(Name or Call) or None\n        \"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, nodes: list[NodeNG]) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param nodes: The decorators that this node contains.\n        :type nodes: list(Name or Call)\n        \"\"\"\n        self.nodes = nodes\n\n    def scope(self) -> LocalsDictNodeNG:\n        \"\"\"The first parent node defining a new scope.\n        These can be Module, FunctionDef, ClassDef, Lambda, or GeneratorExp nodes.\n\n        :returns: The first parent scope node.\n        \"\"\"\n        # skip the function node to go directly to the upper level scope\n        if not self.parent:\n            raise ParentMissingError(target=self)\n        if not self.parent.parent:\n            raise ParentMissingError(target=self.parent)\n        return self.parent.parent.scope()\n\n    def get_children(self):\n        yield from self.nodes\n\n\nclass DelAttr(mixins.ParentAssignTypeMixin, NodeNG):\n    \"\"\"Variation of :class:`ast.Delete` representing deletion of an attribute.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('del self.attr')\n    >>> node\n    <Delete l.1 at 0x7f23b2e35f60>\n    >>> list(node.get_children())[0]\n    <DelAttr.attr l.1 at 0x7f23b2e411d0>\n    \"\"\"\n\n    _astroid_fields = (\"expr\",)\n    _other_fields = (\"attrname\",)\n\n    @decorators.deprecate_default_argument_values(attrname=\"str\")\n    def __init__(\n        self,\n        attrname: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param attrname: The name of the attribute that is being deleted.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.expr: NodeNG | None = None\n        \"\"\"The name that this node represents.\n\n        :type: Name or None\n        \"\"\"\n\n        self.attrname: str | None = attrname\n        \"\"\"The name of the attribute that is being deleted.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, expr: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param expr: The name that this node represents.\n        :type expr: Name or None\n        \"\"\"\n        self.expr = expr\n\n    def get_children(self):\n        yield self.expr\n\n\nclass Delete(mixins.AssignTypeMixin, Statement):\n    \"\"\"Class representing an :class:`ast.Delete` node.\n\n    A :class:`Delete` is a ``del`` statement this is deleting something.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('del self.attr')\n    >>> node\n    <Delete l.1 at 0x7f23b2e35f60>\n    \"\"\"\n\n    _astroid_fields = (\"targets\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.targets: list[NodeNG] = []\n        \"\"\"What is being deleted.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, targets: list[NodeNG] | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param targets: What is being deleted.\n        \"\"\"\n        if targets is not None:\n            self.targets = targets\n\n    def get_children(self):\n        yield from self.targets\n\n\nclass Dict(NodeNG, Instance):\n    \"\"\"Class representing an :class:`ast.Dict` node.\n\n    A :class:`Dict` is a dictionary that is created with ``{}`` syntax.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('{1: \"1\"}')\n    >>> node\n    <Dict.dict l.1 at 0x7f23b2e35cc0>\n    \"\"\"\n\n    _astroid_fields = (\"items\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.items: list[tuple[NodeNG, NodeNG]] = []\n        \"\"\"The key-value pairs contained in the dictionary.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, items: list[tuple[NodeNG, NodeNG]]) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param items: The key-value pairs contained in the dictionary.\n        \"\"\"\n        self.items = items\n\n    @classmethod\n    def from_elements(cls, items=None):\n        \"\"\"Create a :class:`Dict` of constants from a live dictionary.\n\n        :param items: The items to store in the node.\n        :type items: dict\n\n        :returns: The created dictionary node.\n        :rtype: Dict\n        \"\"\"\n        node = cls()\n        if items is None:\n            node.items = []\n        else:\n            node.items = [\n                (const_factory(k), const_factory(v) if _is_const(v) else v)\n                for k, v in items.items()\n                # The keys need to be constants\n                if _is_const(k)\n            ]\n        return node\n\n    def pytype(self):\n        \"\"\"Get the name of the type that this node represents.\n\n        :returns: The name of the type.\n        :rtype: str\n        \"\"\"\n        return \"builtins.dict\"\n\n    def get_children(self):\n        \"\"\"Get the key and value nodes below this node.\n\n        Children are returned in the order that they are defined in the source\n        code, key first then the value.\n\n        :returns: The children.\n        :rtype: iterable(NodeNG)\n        \"\"\"\n        for key, value in self.items:\n            yield key\n            yield value\n\n    def last_child(self):\n        \"\"\"An optimized version of list(get_children())[-1]\n\n        :returns: The last child, or None if no children exist.\n        :rtype: NodeNG or None\n        \"\"\"\n        if self.items:\n            return self.items[-1][1]\n        return None\n\n    def itered(self):\n        \"\"\"An iterator over the keys this node contains.\n\n        :returns: The keys of this node.\n        :rtype: iterable(NodeNG)\n        \"\"\"\n        return [key for (key, _) in self.items]\n\n    def getitem(self, index, context=None):\n        \"\"\"Get an item from this node.\n\n        :param index: The node to use as a subscript index.\n        :type index: Const or Slice\n\n        :raises AstroidTypeError: When the given index cannot be used as a\n            subscript index, or if this node is not subscriptable.\n        :raises AstroidIndexError: If the given index does not exist in the\n            dictionary.\n        \"\"\"\n        for key, value in self.items:\n            # TODO(cpopa): no support for overriding yet, {1:2, **{1: 3}}.\n            if isinstance(key, DictUnpack):\n                try:\n                    return value.getitem(index, context)\n                except (AstroidTypeError, AstroidIndexError):\n                    continue\n            for inferredkey in key.infer(context):\n                if inferredkey is util.Uninferable:\n                    continue\n                if isinstance(inferredkey, Const) and isinstance(index, Const):\n                    if inferredkey.value == index.value:\n                        return value\n\n        raise AstroidIndexError(index)\n\n    def bool_value(self, context=None):\n        \"\"\"Determine the boolean value of this node.\n\n        :returns: The boolean value of this node.\n        :rtype: bool\n        \"\"\"\n        return bool(self.items)\n\n\nclass Expr(Statement):\n    \"\"\"Class representing an :class:`ast.Expr` node.\n\n    An :class:`Expr` is any expression that does not have its value used or\n    stored.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('method()')\n    >>> node\n    <Call l.1 at 0x7f23b2e352b0>\n    >>> node.parent\n    <Expr l.1 at 0x7f23b2e35278>\n    \"\"\"\n\n    _astroid_fields = (\"value\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.value: NodeNG | None = None\n        \"\"\"What the expression does.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, value: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: What the expression does.\n        \"\"\"\n        self.value = value\n\n    def get_children(self):\n        yield self.value\n\n    def _get_yield_nodes_skip_lambdas(self):\n        if not self.value.is_lambda:\n            yield from self.value._get_yield_nodes_skip_lambdas()\n\n\nclass Ellipsis(mixins.NoChildrenMixin, NodeNG):  # pylint: disable=redefined-builtin\n    \"\"\"Class representing an :class:`ast.Ellipsis` node.\n\n    An :class:`Ellipsis` is the ``...`` syntax.\n\n    Deprecated since v2.6.0 - Use :class:`Const` instead.\n    Will be removed with the release v2.7.0\n    \"\"\"\n\n\nclass EmptyNode(mixins.NoChildrenMixin, NodeNG):\n    \"\"\"Holds an arbitrary object in the :attr:`LocalsDictNodeNG.locals`.\"\"\"\n\n    object = None\n\n\nclass ExceptHandler(mixins.MultiLineBlockMixin, mixins.AssignTypeMixin, Statement):\n    \"\"\"Class representing an :class:`ast.ExceptHandler`. node.\n\n    An :class:`ExceptHandler` is an ``except`` block on a try-except.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n        try:\n            do_something()\n        except Exception as error:\n            print(\"Error!\")\n        ''')\n    >>> node\n    <TryExcept l.2 at 0x7f23b2e9d908>\n    >>> node.handlers\n    [<ExceptHandler l.4 at 0x7f23b2e9e860>]\n    \"\"\"\n\n    _astroid_fields = (\"type\", \"name\", \"body\")\n    _multi_line_block_fields = (\"body\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.type: NodeNG | None = None  # can be None\n        \"\"\"The types that the block handles.\n\n        :type: Tuple or NodeNG or None\n        \"\"\"\n\n        self.name: AssignName | None = None  # can be None\n        \"\"\"The name that the caught exception is assigned to.\"\"\"\n\n        self.body: list[NodeNG] = []\n        \"\"\"The contents of the block.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[ExceptHandler]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def get_children(self):\n        if self.type is not None:\n            yield self.type\n\n        if self.name is not None:\n            yield self.name\n\n        yield from self.body\n\n    # pylint: disable=redefined-builtin; had to use the same name as builtin ast module.\n    def postinit(\n        self,\n        type: NodeNG | None = None,\n        name: AssignName | None = None,\n        body: list[NodeNG] | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param type: The types that the block handles.\n        :type type: Tuple or NodeNG or None\n\n        :param name: The name that the caught exception is assigned to.\n\n        :param body:The contents of the block.\n        \"\"\"\n        self.type = type\n        self.name = name\n        if body is not None:\n            self.body = body\n\n    @cached_property\n    def blockstart_tolineno(self):\n        \"\"\"The line on which the beginning of this block ends.\n\n        :type: int\n        \"\"\"\n        if self.name:\n            return self.name.tolineno\n        if self.type:\n            return self.type.tolineno\n        return self.lineno\n\n    def catch(self, exceptions: list[str] | None) -> bool:\n        \"\"\"Check if this node handles any of the given\n\n        :param exceptions: The names of the exceptions to check for.\n        \"\"\"\n        if self.type is None or exceptions is None:\n            return True\n        return any(node.name in exceptions for node in self.type._get_name_nodes())\n\n\nclass ExtSlice(NodeNG):\n    \"\"\"Class representing an :class:`ast.ExtSlice` node.\n\n    An :class:`ExtSlice` is a complex slice expression.\n\n    Deprecated since v2.6.0 - Now part of the :class:`Subscript` node.\n    Will be removed with the release of v2.7.0\n    \"\"\"\n\n\nclass For(\n    mixins.MultiLineBlockMixin,\n    mixins.BlockRangeMixIn,\n    mixins.AssignTypeMixin,\n    Statement,\n):\n    \"\"\"Class representing an :class:`ast.For` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('for thing in things: print(thing)')\n    >>> node\n    <For l.1 at 0x7f23b2e8cf28>\n    \"\"\"\n\n    _astroid_fields = (\"target\", \"iter\", \"body\", \"orelse\")\n    _other_other_fields = (\"type_annotation\",)\n    _multi_line_block_fields = (\"body\", \"orelse\")\n\n    optional_assign = True\n    \"\"\"Whether this node optionally assigns a variable.\n\n    This is always ``True`` for :class:`For` nodes.\n    \"\"\"\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.target: NodeNG | None = None\n        \"\"\"What the loop assigns to.\"\"\"\n\n        self.iter: NodeNG | None = None\n        \"\"\"What the loop iterates over.\"\"\"\n\n        self.body: list[NodeNG] = []\n        \"\"\"The contents of the body of the loop.\"\"\"\n\n        self.orelse: list[NodeNG] = []\n        \"\"\"The contents of the ``else`` block of the loop.\"\"\"\n\n        self.type_annotation: NodeNG | None = None  # can be None\n        \"\"\"If present, this will contain the type annotation passed by a type comment\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    # pylint: disable=redefined-builtin; had to use the same name as builtin ast module.\n    def postinit(\n        self,\n        target: NodeNG | None = None,\n        iter: NodeNG | None = None,\n        body: list[NodeNG] | None = None,\n        orelse: list[NodeNG] | None = None,\n        type_annotation: NodeNG | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param target: What the loop assigns to.\n\n        :param iter: What the loop iterates over.\n\n        :param body: The contents of the body of the loop.\n\n        :param orelse: The contents of the ``else`` block of the loop.\n        \"\"\"\n        self.target = target\n        self.iter = iter\n        if body is not None:\n            self.body = body\n        if orelse is not None:\n            self.orelse = orelse\n        self.type_annotation = type_annotation\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[For]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    @cached_property\n    def blockstart_tolineno(self):\n        \"\"\"The line on which the beginning of this block ends.\n\n        :type: int\n        \"\"\"\n        return self.iter.tolineno\n\n    def get_children(self):\n        yield self.target\n        yield self.iter\n\n        yield from self.body\n        yield from self.orelse\n\n\nclass AsyncFor(For):\n    \"\"\"Class representing an :class:`ast.AsyncFor` node.\n\n    An :class:`AsyncFor` is an asynchronous :class:`For` built with\n    the ``async`` keyword.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    async def func(things):\n        async for thing in things:\n            print(thing)\n    ''')\n    >>> node\n    <AsyncFunctionDef.func l.2 at 0x7f23b2e416d8>\n    >>> node.body[0]\n    <AsyncFor l.3 at 0x7f23b2e417b8>\n    \"\"\"\n\n\nclass Await(NodeNG):\n    \"\"\"Class representing an :class:`ast.Await` node.\n\n    An :class:`Await` is the ``await`` keyword.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    async def func(things):\n        await other_func()\n    ''')\n    >>> node\n    <AsyncFunctionDef.func l.2 at 0x7f23b2e41748>\n    >>> node.body[0]\n    <Expr l.3 at 0x7f23b2e419e8>\n    >>> list(node.body[0].get_children())[0]\n    <Await l.3 at 0x7f23b2e41a20>\n    \"\"\"\n\n    _astroid_fields = (\"value\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.value: NodeNG | None = None\n        \"\"\"What to wait for.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, value: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: What to wait for.\n        \"\"\"\n        self.value = value\n\n    def get_children(self):\n        yield self.value\n\n\nclass ImportFrom(mixins.NoChildrenMixin, mixins.ImportFromMixin, Statement):\n    \"\"\"Class representing an :class:`ast.ImportFrom` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('from my_package import my_module')\n    >>> node\n    <ImportFrom l.1 at 0x7f23b2e415c0>\n    \"\"\"\n\n    _other_fields = (\"modname\", \"names\", \"level\")\n\n    def __init__(\n        self,\n        fromname: str | None,\n        names: list[tuple[str, str | None]],\n        level: int | None = 0,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param fromname: The module that is being imported from.\n\n        :param names: What is being imported from the module.\n\n        :param level: The level of relative import.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.modname: str | None = fromname  # can be None\n        \"\"\"The module that is being imported from.\n\n        This is ``None`` for relative imports.\n        \"\"\"\n\n        self.names: list[tuple[str, str | None]] = names\n        \"\"\"What is being imported from the module.\n\n        Each entry is a :class:`tuple` of the name being imported,\n        and the alias that the name is assigned to (if any).\n        \"\"\"\n\n        # TODO When is 'level' None?\n        self.level: int | None = level  # can be None\n        \"\"\"The level of relative import.\n\n        Essentially this is the number of dots in the import.\n        This is always 0 for absolute imports.\n        \"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n\nclass Attribute(NodeNG):\n    \"\"\"Class representing an :class:`ast.Attribute` node.\"\"\"\n\n    _astroid_fields = (\"expr\",)\n    _other_fields = (\"attrname\",)\n\n    @decorators.deprecate_default_argument_values(attrname=\"str\")\n    def __init__(\n        self,\n        attrname: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param attrname: The name of the attribute.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.expr: NodeNG | None = None\n        \"\"\"The name that this node represents.\n\n        :type: Name or None\n        \"\"\"\n\n        self.attrname: str | None = attrname\n        \"\"\"The name of the attribute.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, expr: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param expr: The name that this node represents.\n        :type expr: Name or None\n        \"\"\"\n        self.expr = expr\n\n    def get_children(self):\n        yield self.expr\n\n\nclass Global(mixins.NoChildrenMixin, Statement):\n    \"\"\"Class representing an :class:`ast.Global` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('global a_global')\n    >>> node\n    <Global l.1 at 0x7f23b2e9de10>\n    \"\"\"\n\n    _other_fields = (\"names\",)\n\n    def __init__(\n        self,\n        names: list[str],\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param names: The names being declared as global.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.names: list[str] = names\n        \"\"\"The names being declared as global.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def _infer_name(self, frame, name):\n        return name\n\n\nclass If(mixins.MultiLineBlockMixin, mixins.BlockRangeMixIn, Statement):\n    \"\"\"Class representing an :class:`ast.If` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('if condition: print(True)')\n    >>> node\n    <If l.1 at 0x7f23b2e9dd30>\n    \"\"\"\n\n    _astroid_fields = (\"test\", \"body\", \"orelse\")\n    _multi_line_block_fields = (\"body\", \"orelse\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.test: NodeNG | None = None\n        \"\"\"The condition that the statement tests.\"\"\"\n\n        self.body: list[NodeNG] = []\n        \"\"\"The contents of the block.\"\"\"\n\n        self.orelse: list[NodeNG] = []\n        \"\"\"The contents of the ``else`` block.\"\"\"\n\n        self.is_orelse: bool = False\n        \"\"\"Whether the if-statement is the orelse-block of another if statement.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        test: NodeNG | None = None,\n        body: list[NodeNG] | None = None,\n        orelse: list[NodeNG] | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param test: The condition that the statement tests.\n\n        :param body: The contents of the block.\n\n        :param orelse: The contents of the ``else`` block.\n        \"\"\"\n        self.test = test\n        if body is not None:\n            self.body = body\n        if orelse is not None:\n            self.orelse = orelse\n        if isinstance(self.parent, If) and self in self.parent.orelse:\n            self.is_orelse = True\n\n    @cached_property\n    def blockstart_tolineno(self):\n        \"\"\"The line on which the beginning of this block ends.\n\n        :type: int\n        \"\"\"\n        return self.test.tolineno\n\n    def block_range(self, lineno):\n        \"\"\"Get a range from the given line number to where this node ends.\n\n        :param lineno: The line number to start the range at.\n        :type lineno: int\n\n        :returns: The range of line numbers that this node belongs to,\n            starting at the given line number.\n        :rtype: tuple(int, int)\n        \"\"\"\n        if lineno == self.body[0].fromlineno:\n            return lineno, lineno\n        if lineno <= self.body[-1].tolineno:\n            return lineno, self.body[-1].tolineno\n        return self._elsed_block_range(lineno, self.orelse, self.body[0].fromlineno - 1)\n\n    def get_children(self):\n        yield self.test\n\n        yield from self.body\n        yield from self.orelse\n\n    def has_elif_block(self):\n        return len(self.orelse) == 1 and isinstance(self.orelse[0], If)\n\n    def _get_yield_nodes_skip_lambdas(self):\n        \"\"\"An If node can contain a Yield node in the test\"\"\"\n        yield from self.test._get_yield_nodes_skip_lambdas()\n        yield from super()._get_yield_nodes_skip_lambdas()\n\n    def is_sys_guard(self) -> bool:\n        \"\"\"Return True if IF stmt is a sys.version_info guard.\n\n        >>> import astroid\n        >>> node = astroid.extract_node('''\n        import sys\n        if sys.version_info > (3, 8):\n            from typing import Literal\n        else:\n            from typing_extensions import Literal\n        ''')\n        >>> node.is_sys_guard()\n        True\n        \"\"\"\n        warnings.warn(\n            \"The 'is_sys_guard' function is deprecated and will be removed in astroid 3.0.0 \"\n            \"It has been moved to pylint and can be imported from 'pylint.checkers.utils' \"\n            \"starting with pylint 2.12\",\n            DeprecationWarning,\n        )\n        if isinstance(self.test, Compare):\n            value = self.test.left\n            if isinstance(value, Subscript):\n                value = value.value\n            if isinstance(value, Attribute) and value.as_string() == \"sys.version_info\":\n                return True\n\n        return False\n\n    def is_typing_guard(self) -> bool:\n        \"\"\"Return True if IF stmt is a typing guard.\n\n        >>> import astroid\n        >>> node = astroid.extract_node('''\n        from typing import TYPE_CHECKING\n        if TYPE_CHECKING:\n            from xyz import a\n        ''')\n        >>> node.is_typing_guard()\n        True\n        \"\"\"\n        warnings.warn(\n            \"The 'is_typing_guard' function is deprecated and will be removed in astroid 3.0.0 \"\n            \"It has been moved to pylint and can be imported from 'pylint.checkers.utils' \"\n            \"starting with pylint 2.12\",\n            DeprecationWarning,\n        )\n        return isinstance(\n            self.test, (Name, Attribute)\n        ) and self.test.as_string().endswith(\"TYPE_CHECKING\")\n\n\nclass IfExp(NodeNG):\n    \"\"\"Class representing an :class:`ast.IfExp` node.\n    >>> import astroid\n    >>> node = astroid.extract_node('value if condition else other')\n    >>> node\n    <IfExp l.1 at 0x7f23b2e9dbe0>\n    \"\"\"\n\n    _astroid_fields = (\"test\", \"body\", \"orelse\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.test: NodeNG | None = None\n        \"\"\"The condition that the statement tests.\"\"\"\n\n        self.body: NodeNG | None = None\n        \"\"\"The contents of the block.\"\"\"\n\n        self.orelse: NodeNG | None = None\n        \"\"\"The contents of the ``else`` block.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        test: NodeNG | None = None,\n        body: NodeNG | None = None,\n        orelse: NodeNG | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param test: The condition that the statement tests.\n\n        :param body: The contents of the block.\n\n        :param orelse: The contents of the ``else`` block.\n        \"\"\"\n        self.test = test\n        self.body = body\n        self.orelse = orelse\n\n    def get_children(self):\n        yield self.test\n        yield self.body\n        yield self.orelse\n\n    def op_left_associative(self):\n        # `1 if True else 2 if False else 3` is parsed as\n        # `1 if True else (2 if False else 3)`\n        return False\n\n\nclass Import(mixins.NoChildrenMixin, mixins.ImportFromMixin, Statement):\n    \"\"\"Class representing an :class:`ast.Import` node.\n    >>> import astroid\n    >>> node = astroid.extract_node('import astroid')\n    >>> node\n    <Import l.1 at 0x7f23b2e4e5c0>\n    \"\"\"\n\n    _other_fields = (\"names\",)\n\n    @decorators.deprecate_default_argument_values(names=\"list[tuple[str, str | None]]\")\n    def __init__(\n        self,\n        names: list[tuple[str, str | None]] | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param names: The names being imported.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.names: list[tuple[str, str | None]] = names or []\n        \"\"\"The names being imported.\n\n        Each entry is a :class:`tuple` of the name being imported,\n        and the alias that the name is assigned to (if any).\n        \"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n\nclass Index(NodeNG):\n    \"\"\"Class representing an :class:`ast.Index` node.\n\n    An :class:`Index` is a simple subscript.\n\n    Deprecated since v2.6.0 - Now part of the :class:`Subscript` node.\n    Will be removed with the release of v2.7.0\n    \"\"\"\n\n\nclass Keyword(NodeNG):\n    \"\"\"Class representing an :class:`ast.keyword` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('function(a_kwarg=True)')\n    >>> node\n    <Call l.1 at 0x7f23b2e9e320>\n    >>> node.keywords\n    [<Keyword l.1 at 0x7f23b2e9e9b0>]\n    \"\"\"\n\n    _astroid_fields = (\"value\",)\n    _other_fields = (\"arg\",)\n\n    def __init__(\n        self,\n        arg: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param arg: The argument being assigned to.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.arg: str | None = arg  # can be None\n        \"\"\"The argument being assigned to.\"\"\"\n\n        self.value: NodeNG | None = None\n        \"\"\"The value being assigned to the keyword argument.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, value: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: The value being assigned to the keyword argument.\n        \"\"\"\n        self.value = value\n\n    def get_children(self):\n        yield self.value\n\n\nclass List(BaseContainer):\n    \"\"\"Class representing an :class:`ast.List` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('[1, 2, 3]')\n    >>> node\n    <List.list l.1 at 0x7f23b2e9e128>\n    \"\"\"\n\n    _other_fields = (\"ctx\",)\n\n    def __init__(\n        self,\n        ctx: Context | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param ctx: Whether the list is assigned to or loaded from.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.ctx: Context | None = ctx\n        \"\"\"Whether the list is assigned to or loaded from.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[List]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def pytype(self):\n        \"\"\"Get the name of the type that this node represents.\n\n        :returns: The name of the type.\n        :rtype: str\n        \"\"\"\n        return \"builtins.list\"\n\n    def getitem(self, index, context=None):\n        \"\"\"Get an item from this node.\n\n        :param index: The node to use as a subscript index.\n        :type index: Const or Slice\n        \"\"\"\n        return _container_getitem(self, self.elts, index, context=context)\n\n\nclass Nonlocal(mixins.NoChildrenMixin, Statement):\n    \"\"\"Class representing an :class:`ast.Nonlocal` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    def function():\n        nonlocal var\n    ''')\n    >>> node\n    <FunctionDef.function l.2 at 0x7f23b2e9e208>\n    >>> node.body[0]\n    <Nonlocal l.3 at 0x7f23b2e9e908>\n    \"\"\"\n\n    _other_fields = (\"names\",)\n\n    def __init__(\n        self,\n        names: list[str],\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param names: The names being declared as not local.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.names: list[str] = names\n        \"\"\"The names being declared as not local.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def _infer_name(self, frame, name):\n        return name\n\n\nclass Pass(mixins.NoChildrenMixin, Statement):\n    \"\"\"Class representing an :class:`ast.Pass` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('pass')\n    >>> node\n    <Pass l.1 at 0x7f23b2e9e748>\n    \"\"\"\n\n\nclass Raise(Statement):\n    \"\"\"Class representing an :class:`ast.Raise` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('raise RuntimeError(\"Something bad happened!\")')\n    >>> node\n    <Raise l.1 at 0x7f23b2e9e828>\n    \"\"\"\n\n    _astroid_fields = (\"exc\", \"cause\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.exc: NodeNG | None = None  # can be None\n        \"\"\"What is being raised.\"\"\"\n\n        self.cause: NodeNG | None = None  # can be None\n        \"\"\"The exception being used to raise this one.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        exc: NodeNG | None = None,\n        cause: NodeNG | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param exc: What is being raised.\n\n        :param cause: The exception being used to raise this one.\n        \"\"\"\n        self.exc = exc\n        self.cause = cause\n\n    def raises_not_implemented(self):\n        \"\"\"Check if this node raises a :class:`NotImplementedError`.\n\n        :returns: True if this node raises a :class:`NotImplementedError`,\n            False otherwise.\n        :rtype: bool\n        \"\"\"\n        if not self.exc:\n            return False\n        return any(\n            name.name == \"NotImplementedError\" for name in self.exc._get_name_nodes()\n        )\n\n    def get_children(self):\n        if self.exc is not None:\n            yield self.exc\n\n        if self.cause is not None:\n            yield self.cause\n\n\nclass Return(Statement):\n    \"\"\"Class representing an :class:`ast.Return` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('return True')\n    >>> node\n    <Return l.1 at 0x7f23b8211908>\n    \"\"\"\n\n    _astroid_fields = (\"value\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.value: NodeNG | None = None  # can be None\n        \"\"\"The value being returned.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, value: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: The value being returned.\n        \"\"\"\n        self.value = value\n\n    def get_children(self):\n        if self.value is not None:\n            yield self.value\n\n    def is_tuple_return(self):\n        return isinstance(self.value, Tuple)\n\n    def _get_return_nodes_skip_functions(self):\n        yield self\n\n\nclass Set(BaseContainer):\n    \"\"\"Class representing an :class:`ast.Set` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('{1, 2, 3}')\n    >>> node\n    <Set.set l.1 at 0x7f23b2e71d68>\n    \"\"\"\n\n    def pytype(self):\n        \"\"\"Get the name of the type that this node represents.\n\n        :returns: The name of the type.\n        :rtype: str\n        \"\"\"\n        return \"builtins.set\"\n\n\nclass Slice(NodeNG):\n    \"\"\"Class representing an :class:`ast.Slice` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('things[1:3]')\n    >>> node\n    <Subscript l.1 at 0x7f23b2e71f60>\n    >>> node.slice\n    <Slice l.1 at 0x7f23b2e71e80>\n    \"\"\"\n\n    _astroid_fields = (\"lower\", \"upper\", \"step\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.lower: NodeNG | None = None  # can be None\n        \"\"\"The lower index in the slice.\"\"\"\n\n        self.upper: NodeNG | None = None  # can be None\n        \"\"\"The upper index in the slice.\"\"\"\n\n        self.step: NodeNG | None = None  # can be None\n        \"\"\"The step to take between indexes.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        lower: NodeNG | None = None,\n        upper: NodeNG | None = None,\n        step: NodeNG | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param lower: The lower index in the slice.\n\n        :param upper: The upper index in the slice.\n\n        :param step: The step to take between index.\n        \"\"\"\n        self.lower = lower\n        self.upper = upper\n        self.step = step\n\n    def _wrap_attribute(self, attr):\n        \"\"\"Wrap the empty attributes of the Slice in a Const node.\"\"\"\n        if not attr:\n            const = const_factory(attr)\n            const.parent = self\n            return const\n        return attr\n\n    @cached_property\n    def _proxied(self):\n        builtins = AstroidManager().builtins_module\n        return builtins.getattr(\"slice\")[0]\n\n    def pytype(self):\n        \"\"\"Get the name of the type that this node represents.\n\n        :returns: The name of the type.\n        :rtype: str\n        \"\"\"\n        return \"builtins.slice\"\n\n    def igetattr(self, attrname, context=None):\n        \"\"\"Infer the possible values of the given attribute on the slice.\n\n        :param attrname: The name of the attribute to infer.\n        :type attrname: str\n\n        :returns: The inferred possible values.\n        :rtype: iterable(NodeNG)\n        \"\"\"\n        if attrname == \"start\":\n            yield self._wrap_attribute(self.lower)\n        elif attrname == \"stop\":\n            yield self._wrap_attribute(self.upper)\n        elif attrname == \"step\":\n            yield self._wrap_attribute(self.step)\n        else:\n            yield from self.getattr(attrname, context=context)\n\n    def getattr(self, attrname, context=None):\n        return self._proxied.getattr(attrname, context)\n\n    def get_children(self):\n        if self.lower is not None:\n            yield self.lower\n\n        if self.upper is not None:\n            yield self.upper\n\n        if self.step is not None:\n            yield self.step\n\n\nclass Starred(mixins.ParentAssignTypeMixin, NodeNG):\n    \"\"\"Class representing an :class:`ast.Starred` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('*args')\n    >>> node\n    <Starred l.1 at 0x7f23b2e41978>\n    \"\"\"\n\n    _astroid_fields = (\"value\",)\n    _other_fields = (\"ctx\",)\n\n    def __init__(\n        self,\n        ctx: Context | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param ctx: Whether the list is assigned to or loaded from.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.value: NodeNG | None = None\n        \"\"\"What is being unpacked.\"\"\"\n\n        self.ctx: Context | None = ctx\n        \"\"\"Whether the starred item is assigned to or loaded from.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, value: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: What is being unpacked.\n        \"\"\"\n        self.value = value\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[Starred]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def get_children(self):\n        yield self.value\n\n\nclass Subscript(NodeNG):\n    \"\"\"Class representing an :class:`ast.Subscript` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('things[1:3]')\n    >>> node\n    <Subscript l.1 at 0x7f23b2e71f60>\n    \"\"\"\n\n    _astroid_fields = (\"value\", \"slice\")\n    _other_fields = (\"ctx\",)\n\n    def __init__(\n        self,\n        ctx: Context | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param ctx: Whether the subscripted item is assigned to or loaded from.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.value: NodeNG | None = None\n        \"\"\"What is being indexed.\"\"\"\n\n        self.slice: NodeNG | None = None\n        \"\"\"The slice being used to lookup.\"\"\"\n\n        self.ctx: Context | None = ctx\n        \"\"\"Whether the subscripted item is assigned to or loaded from.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    # pylint: disable=redefined-builtin; had to use the same name as builtin ast module.\n    def postinit(\n        self, value: NodeNG | None = None, slice: NodeNG | None = None\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: What is being indexed.\n\n        :param slice: The slice being used to lookup.\n        \"\"\"\n        self.value = value\n        self.slice = slice\n\n    def get_children(self):\n        yield self.value\n        yield self.slice\n\n\nclass TryExcept(mixins.MultiLineBlockMixin, mixins.BlockRangeMixIn, Statement):\n    \"\"\"Class representing an :class:`ast.TryExcept` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n        try:\n            do_something()\n        except Exception as error:\n            print(\"Error!\")\n        ''')\n    >>> node\n    <TryExcept l.2 at 0x7f23b2e9d908>\n    \"\"\"\n\n    _astroid_fields = (\"body\", \"handlers\", \"orelse\")\n    _multi_line_block_fields = (\"body\", \"handlers\", \"orelse\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.body: list[NodeNG] = []\n        \"\"\"The contents of the block to catch exceptions from.\"\"\"\n\n        self.handlers: list[ExceptHandler] = []\n        \"\"\"The exception handlers.\"\"\"\n\n        self.orelse: list[NodeNG] = []\n        \"\"\"The contents of the ``else`` block.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        body: list[NodeNG] | None = None,\n        handlers: list[ExceptHandler] | None = None,\n        orelse: list[NodeNG] | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param body: The contents of the block to catch exceptions from.\n\n        :param handlers: The exception handlers.\n\n        :param orelse: The contents of the ``else`` block.\n        \"\"\"\n        if body is not None:\n            self.body = body\n        if handlers is not None:\n            self.handlers = handlers\n        if orelse is not None:\n            self.orelse = orelse\n\n    def _infer_name(self, frame, name):\n        return name\n\n    def block_range(self, lineno):\n        \"\"\"Get a range from the given line number to where this node ends.\n\n        :param lineno: The line number to start the range at.\n        :type lineno: int\n\n        :returns: The range of line numbers that this node belongs to,\n            starting at the given line number.\n        :rtype: tuple(int, int)\n        \"\"\"\n        last = None\n        for exhandler in self.handlers:\n            if exhandler.type and lineno == exhandler.type.fromlineno:\n                return lineno, lineno\n            if exhandler.body[0].fromlineno <= lineno <= exhandler.body[-1].tolineno:\n                return lineno, exhandler.body[-1].tolineno\n            if last is None:\n                last = exhandler.body[0].fromlineno - 1\n        return self._elsed_block_range(lineno, self.orelse, last)\n\n    def get_children(self):\n        yield from self.body\n\n        yield from self.handlers or ()\n        yield from self.orelse or ()\n\n\nclass TryFinally(mixins.MultiLineBlockMixin, mixins.BlockRangeMixIn, Statement):\n    \"\"\"Class representing an :class:`ast.TryFinally` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    try:\n        do_something()\n    except Exception as error:\n        print(\"Error!\")\n    finally:\n        print(\"Cleanup!\")\n    ''')\n    >>> node\n    <TryFinally l.2 at 0x7f23b2e41d68>\n    \"\"\"\n\n    _astroid_fields = (\"body\", \"finalbody\")\n    _multi_line_block_fields = (\"body\", \"finalbody\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.body: list[NodeNG | TryExcept] = []\n        \"\"\"The try-except that the finally is attached to.\"\"\"\n\n        self.finalbody: list[NodeNG] = []\n        \"\"\"The contents of the ``finally`` block.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        body: list[NodeNG | TryExcept] | None = None,\n        finalbody: list[NodeNG] | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param body: The try-except that the finally is attached to.\n\n        :param finalbody: The contents of the ``finally`` block.\n        \"\"\"\n        if body is not None:\n            self.body = body\n        if finalbody is not None:\n            self.finalbody = finalbody\n\n    def block_range(self, lineno):\n        \"\"\"Get a range from the given line number to where this node ends.\n\n        :param lineno: The line number to start the range at.\n        :type lineno: int\n\n        :returns: The range of line numbers that this node belongs to,\n            starting at the given line number.\n        :rtype: tuple(int, int)\n        \"\"\"\n        child = self.body[0]\n        # py2.5 try: except: finally:\n        if (\n            isinstance(child, TryExcept)\n            and child.fromlineno == self.fromlineno\n            and child.tolineno >= lineno > self.fromlineno\n        ):\n            return child.block_range(lineno)\n        return self._elsed_block_range(lineno, self.finalbody)\n\n    def get_children(self):\n        yield from self.body\n        yield from self.finalbody\n\n\nclass Tuple(BaseContainer):\n    \"\"\"Class representing an :class:`ast.Tuple` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('(1, 2, 3)')\n    >>> node\n    <Tuple.tuple l.1 at 0x7f23b2e41780>\n    \"\"\"\n\n    _other_fields = (\"ctx\",)\n\n    def __init__(\n        self,\n        ctx: Context | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param ctx: Whether the tuple is assigned to or loaded from.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.ctx: Context | None = ctx\n        \"\"\"Whether the tuple is assigned to or loaded from.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[Tuple]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def pytype(self):\n        \"\"\"Get the name of the type that this node represents.\n\n        :returns: The name of the type.\n        :rtype: str\n        \"\"\"\n        return \"builtins.tuple\"\n\n    def getitem(self, index, context=None):\n        \"\"\"Get an item from this node.\n\n        :param index: The node to use as a subscript index.\n        :type index: Const or Slice\n        \"\"\"\n        return _container_getitem(self, self.elts, index, context=context)\n\n\nclass UnaryOp(NodeNG):\n    \"\"\"Class representing an :class:`ast.UnaryOp` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('-5')\n    >>> node\n    <UnaryOp l.1 at 0x7f23b2e4e198>\n    \"\"\"\n\n    _astroid_fields = (\"operand\",)\n    _other_fields = (\"op\",)\n\n    @decorators.deprecate_default_argument_values(op=\"str\")\n    def __init__(\n        self,\n        op: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param op: The operator.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.op: str | None = op\n        \"\"\"The operator.\"\"\"\n\n        self.operand: NodeNG | None = None\n        \"\"\"What the unary operator is applied to.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, operand: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param operand: What the unary operator is applied to.\n        \"\"\"\n        self.operand = operand\n\n    # This is set by inference.py\n    def _infer_unaryop(self, context=None):\n        raise NotImplementedError\n\n    def type_errors(self, context=None):\n        \"\"\"Get a list of type errors which can occur during inference.\n\n        Each TypeError is represented by a :class:`BadBinaryOperationMessage`,\n        which holds the original exception.\n\n        :returns: The list of possible type errors.\n        :rtype: list(BadBinaryOperationMessage)\n        \"\"\"\n        try:\n            results = self._infer_unaryop(context=context)\n            return [\n                result\n                for result in results\n                if isinstance(result, util.BadUnaryOperationMessage)\n            ]\n        except InferenceError:\n            return []\n\n    def get_children(self):\n        yield self.operand\n\n    def op_precedence(self):\n        if self.op == \"not\":\n            return OP_PRECEDENCE[self.op]\n\n        return super().op_precedence()\n\n\nclass While(mixins.MultiLineBlockMixin, mixins.BlockRangeMixIn, Statement):\n    \"\"\"Class representing an :class:`ast.While` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    while condition():\n        print(\"True\")\n    ''')\n    >>> node\n    <While l.2 at 0x7f23b2e4e390>\n    \"\"\"\n\n    _astroid_fields = (\"test\", \"body\", \"orelse\")\n    _multi_line_block_fields = (\"body\", \"orelse\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.test: NodeNG | None = None\n        \"\"\"The condition that the loop tests.\"\"\"\n\n        self.body: list[NodeNG] = []\n        \"\"\"The contents of the loop.\"\"\"\n\n        self.orelse: list[NodeNG] = []\n        \"\"\"The contents of the ``else`` block.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        test: NodeNG | None = None,\n        body: list[NodeNG] | None = None,\n        orelse: list[NodeNG] | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param test: The condition that the loop tests.\n\n        :param body: The contents of the loop.\n\n        :param orelse: The contents of the ``else`` block.\n        \"\"\"\n        self.test = test\n        if body is not None:\n            self.body = body\n        if orelse is not None:\n            self.orelse = orelse\n\n    @cached_property\n    def blockstart_tolineno(self):\n        \"\"\"The line on which the beginning of this block ends.\n\n        :type: int\n        \"\"\"\n        return self.test.tolineno\n\n    def block_range(self, lineno):\n        \"\"\"Get a range from the given line number to where this node ends.\n\n        :param lineno: The line number to start the range at.\n        :type lineno: int\n\n        :returns: The range of line numbers that this node belongs to,\n            starting at the given line number.\n        :rtype: tuple(int, int)\n        \"\"\"\n        return self._elsed_block_range(lineno, self.orelse)\n\n    def get_children(self):\n        yield self.test\n\n        yield from self.body\n        yield from self.orelse\n\n    def _get_yield_nodes_skip_lambdas(self):\n        \"\"\"A While node can contain a Yield node in the test\"\"\"\n        yield from self.test._get_yield_nodes_skip_lambdas()\n        yield from super()._get_yield_nodes_skip_lambdas()\n\n\nclass With(\n    mixins.MultiLineBlockMixin,\n    mixins.BlockRangeMixIn,\n    mixins.AssignTypeMixin,\n    Statement,\n):\n    \"\"\"Class representing an :class:`ast.With` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    with open(file_path) as file_:\n        print(file_.read())\n    ''')\n    >>> node\n    <With l.2 at 0x7f23b2e4e710>\n    \"\"\"\n\n    _astroid_fields = (\"items\", \"body\")\n    _other_other_fields = (\"type_annotation\",)\n    _multi_line_block_fields = (\"body\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.items: list[tuple[NodeNG, NodeNG | None]] = []\n        \"\"\"The pairs of context managers and the names they are assigned to.\"\"\"\n\n        self.body: list[NodeNG] = []\n        \"\"\"The contents of the ``with`` block.\"\"\"\n\n        self.type_annotation: NodeNG | None = None  # can be None\n        \"\"\"If present, this will contain the type annotation passed by a type comment\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        items: list[tuple[NodeNG, NodeNG | None]] | None = None,\n        body: list[NodeNG] | None = None,\n        type_annotation: NodeNG | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param items: The pairs of context managers and the names\n            they are assigned to.\n\n        :param body: The contents of the ``with`` block.\n        \"\"\"\n        if items is not None:\n            self.items = items\n        if body is not None:\n            self.body = body\n        self.type_annotation = type_annotation\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[With]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    @cached_property\n    def blockstart_tolineno(self):\n        \"\"\"The line on which the beginning of this block ends.\n\n        :type: int\n        \"\"\"\n        return self.items[-1][0].tolineno\n\n    def get_children(self):\n        \"\"\"Get the child nodes below this node.\n\n        :returns: The children.\n        :rtype: iterable(NodeNG)\n        \"\"\"\n        for expr, var in self.items:\n            yield expr\n            if var:\n                yield var\n        yield from self.body\n\n\nclass AsyncWith(With):\n    \"\"\"Asynchronous ``with`` built with the ``async`` keyword.\"\"\"\n\n\nclass Yield(NodeNG):\n    \"\"\"Class representing an :class:`ast.Yield` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('yield True')\n    >>> node\n    <Yield l.1 at 0x7f23b2e4e5f8>\n    \"\"\"\n\n    _astroid_fields = (\"value\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.value: NodeNG | None = None  # can be None\n        \"\"\"The value to yield.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, value: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: The value to yield.\n        \"\"\"\n        self.value = value\n\n    def get_children(self):\n        if self.value is not None:\n            yield self.value\n\n    def _get_yield_nodes_skip_lambdas(self):\n        yield self\n\n\nclass YieldFrom(Yield):  # TODO value is required, not optional\n    \"\"\"Class representing an :class:`ast.YieldFrom` node.\"\"\"\n\n\nclass DictUnpack(mixins.NoChildrenMixin, NodeNG):\n    \"\"\"Represents the unpacking of dicts into dicts using :pep:`448`.\"\"\"\n\n\nclass FormattedValue(NodeNG):\n    \"\"\"Class representing an :class:`ast.FormattedValue` node.\n\n    Represents a :pep:`498` format string.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('f\"Format {type_}\"')\n    >>> node\n    <JoinedStr l.1 at 0x7f23b2e4ed30>\n    >>> node.values\n    [<Const.str l.1 at 0x7f23b2e4eda0>, <FormattedValue l.1 at 0x7f23b2e4edd8>]\n    \"\"\"\n\n    _astroid_fields = (\"value\", \"format_spec\")\n    _other_fields = (\"conversion\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.value: NodeNG\n        \"\"\"The value to be formatted into the string.\"\"\"\n\n        self.conversion: int | None = None  # can be None\n        \"\"\"The type of formatting to be applied to the value.\n\n        .. seealso::\n            :class:`ast.FormattedValue`\n        \"\"\"\n\n        self.format_spec: NodeNG | None = None  # can be None\n        \"\"\"The formatting to be applied to the value.\n\n        .. seealso::\n            :class:`ast.FormattedValue`\n\n        :type: JoinedStr or None\n        \"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        value: NodeNG,\n        conversion: int | None = None,\n        format_spec: NodeNG | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: The value to be formatted into the string.\n\n        :param conversion: The type of formatting to be applied to the value.\n\n        :param format_spec: The formatting to be applied to the value.\n        :type format_spec: JoinedStr or None\n        \"\"\"\n        self.value = value\n        self.conversion = conversion\n        self.format_spec = format_spec\n\n    def get_children(self):\n        yield self.value\n\n        if self.format_spec is not None:\n            yield self.format_spec\n\n\nclass JoinedStr(NodeNG):\n    \"\"\"Represents a list of string expressions to be joined.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('f\"Format {type_}\"')\n    >>> node\n    <JoinedStr l.1 at 0x7f23b2e4ed30>\n    \"\"\"\n\n    _astroid_fields = (\"values\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.values: list[NodeNG] = []\n        \"\"\"The string expressions to be joined.\n\n        :type: list(FormattedValue or Const)\n        \"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, values: list[NodeNG] | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: The string expressions to be joined.\n\n        :type: list(FormattedValue or Const)\n        \"\"\"\n        if values is not None:\n            self.values = values\n\n    def get_children(self):\n        yield from self.values\n\n\nclass NamedExpr(mixins.AssignTypeMixin, NodeNG):\n    \"\"\"Represents the assignment from the assignment expression\n\n    >>> import astroid\n    >>> module = astroid.parse('if a := 1: pass')\n    >>> module.body[0].test\n    <NamedExpr l.1 at 0x7f23b2e4ed30>\n    \"\"\"\n\n    _astroid_fields = (\"target\", \"value\")\n\n    optional_assign = True\n    \"\"\"Whether this node optionally assigns a variable.\n\n    Since NamedExpr are not always called they do not always assign.\"\"\"\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.target: NodeNG\n        \"\"\"The assignment target\n\n        :type: Name\n        \"\"\"\n\n        self.value: NodeNG\n        \"\"\"The value that gets assigned in the expression\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, target: NodeNG, value: NodeNG) -> None:\n        self.target = target\n        self.value = value\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[NamedExpr]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def frame(\n        self, *, future: Literal[None, True] = None\n    ) -> nodes.FunctionDef | nodes.Module | nodes.ClassDef | nodes.Lambda:\n        \"\"\"The first parent frame node.\n\n        A frame node is a :class:`Module`, :class:`FunctionDef`,\n        or :class:`ClassDef`.\n\n        :returns: The first parent frame node.\n        \"\"\"\n        if not self.parent:\n            raise ParentMissingError(target=self)\n\n        # For certain parents NamedExpr evaluate to the scope of the parent\n        if isinstance(self.parent, (Arguments, Keyword, Comprehension)):\n            if not self.parent.parent:\n                raise ParentMissingError(target=self.parent)\n            if not self.parent.parent.parent:\n                raise ParentMissingError(target=self.parent.parent)\n            return self.parent.parent.parent.frame(future=True)\n\n        return self.parent.frame(future=True)\n\n    def scope(self) -> LocalsDictNodeNG:\n        \"\"\"The first parent node defining a new scope.\n        These can be Module, FunctionDef, ClassDef, Lambda, or GeneratorExp nodes.\n\n        :returns: The first parent scope node.\n        \"\"\"\n        if not self.parent:\n            raise ParentMissingError(target=self)\n\n        # For certain parents NamedExpr evaluate to the scope of the parent\n        if isinstance(self.parent, (Arguments, Keyword, Comprehension)):\n            if not self.parent.parent:\n                raise ParentMissingError(target=self.parent)\n            if not self.parent.parent.parent:\n                raise ParentMissingError(target=self.parent.parent)\n            return self.parent.parent.parent.scope()\n\n        return self.parent.scope()\n\n    def set_local(self, name: str, stmt: AssignName) -> None:\n        \"\"\"Define that the given name is declared in the given statement node.\n        NamedExpr's in Arguments, Keyword or Comprehension are evaluated in their\n        parent's parent scope. So we add to their frame's locals.\n\n        .. seealso:: :meth:`scope`\n\n        :param name: The name that is being defined.\n\n        :param stmt: The statement that defines the given name.\n        \"\"\"\n        self.frame(future=True).set_local(name, stmt)\n\n\nclass Unknown(mixins.AssignTypeMixin, NodeNG):\n    \"\"\"This node represents a node in a constructed AST where\n    introspection is not possible.  At the moment, it's only used in\n    the args attribute of FunctionDef nodes where function signature\n    introspection failed.\n    \"\"\"\n\n    name = \"Unknown\"\n\n    def qname(self):\n        return \"Unknown\"\n\n    def _infer(self, context=None, **kwargs):\n        \"\"\"Inference on an Unknown node immediately terminates.\"\"\"\n        yield util.Uninferable\n\n\nclass EvaluatedObject(NodeNG):\n    \"\"\"Contains an object that has already been inferred\n\n    This class is useful to pre-evaluate a particular node,\n    with the resulting class acting as the non-evaluated node.\n    \"\"\"\n\n    name = \"EvaluatedObject\"\n    _astroid_fields = (\"original\",)\n    _other_fields = (\"value\",)\n\n    def __init__(\n        self, original: NodeNG, value: NodeNG | type[util.Uninferable]\n    ) -> None:\n        self.original: NodeNG = original\n        \"\"\"The original node that has already been evaluated\"\"\"\n\n        self.value: NodeNG | type[util.Uninferable] = value\n        \"\"\"The inferred value\"\"\"\n\n        super().__init__(\n            lineno=self.original.lineno,\n            col_offset=self.original.col_offset,\n            parent=self.original.parent,\n        )\n\n    def _infer(\n        self, context: InferenceContext | None = None\n    ) -> Iterator[NodeNG | type[util.Uninferable]]:\n        yield self.value\n\n\n# Pattern matching #######################################################\n\n\nclass Match(Statement):\n    \"\"\"Class representing a :class:`ast.Match` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case 200:\n            ...\n        case _:\n            ...\n    ''')\n    >>> node\n    <Match l.2 at 0x10c24e170>\n    \"\"\"\n\n    _astroid_fields = (\"subject\", \"cases\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        self.subject: NodeNG\n        self.cases: list[MatchCase]\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        *,\n        subject: NodeNG,\n        cases: list[MatchCase],\n    ) -> None:\n        self.subject = subject\n        self.cases = cases\n\n\nclass Pattern(NodeNG):\n    \"\"\"Base class for all Pattern nodes.\"\"\"\n\n\nclass MatchCase(mixins.MultiLineBlockMixin, NodeNG):\n    \"\"\"Class representing a :class:`ast.match_case` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case 200:\n            ...\n    ''')\n    >>> node.cases[0]\n    <MatchCase l.3 at 0x10c24e590>\n    \"\"\"\n\n    _astroid_fields = (\"pattern\", \"guard\", \"body\")\n    _multi_line_block_fields = (\"body\",)\n\n    lineno: None\n    col_offset: None\n    end_lineno: None\n    end_col_offset: None\n\n    def __init__(self, *, parent: NodeNG | None = None) -> None:\n        self.pattern: Pattern\n        self.guard: NodeNG | None\n        self.body: list[NodeNG]\n        super().__init__(parent=parent)\n\n    def postinit(\n        self,\n        *,\n        pattern: Pattern,\n        guard: NodeNG | None,\n        body: list[NodeNG],\n    ) -> None:\n        self.pattern = pattern\n        self.guard = guard\n        self.body = body\n\n\nclass MatchValue(Pattern):\n    \"\"\"Class representing a :class:`ast.MatchValue` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case 200:\n            ...\n    ''')\n    >>> node.cases[0].pattern\n    <MatchValue l.3 at 0x10c24e200>\n    \"\"\"\n\n    _astroid_fields = (\"value\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        self.value: NodeNG\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, *, value: NodeNG) -> None:\n        self.value = value\n\n\nclass MatchSingleton(Pattern):\n    \"\"\"Class representing a :class:`ast.MatchSingleton` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case True:\n            ...\n        case False:\n            ...\n        case None:\n            ...\n    ''')\n    >>> node.cases[0].pattern\n    <MatchSingleton l.3 at 0x10c2282e0>\n    >>> node.cases[1].pattern\n    <MatchSingleton l.5 at 0x10c228af0>\n    >>> node.cases[2].pattern\n    <MatchSingleton l.7 at 0x10c229f90>\n    \"\"\"\n\n    _other_fields = (\"value\",)\n\n    def __init__(\n        self,\n        *,\n        value: Literal[True, False, None],\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n        parent: NodeNG | None = None,\n    ) -> None:\n        self.value = value\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n\nclass MatchSequence(Pattern):\n    \"\"\"Class representing a :class:`ast.MatchSequence` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case [1, 2]:\n            ...\n        case (1, 2, *_):\n            ...\n    ''')\n    >>> node.cases[0].pattern\n    <MatchSequence l.3 at 0x10ca80d00>\n    >>> node.cases[1].pattern\n    <MatchSequence l.5 at 0x10ca80b20>\n    \"\"\"\n\n    _astroid_fields = (\"patterns\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        self.patterns: list[Pattern]\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, *, patterns: list[Pattern]) -> None:\n        self.patterns = patterns\n\n\nclass MatchMapping(mixins.AssignTypeMixin, Pattern):\n    \"\"\"Class representing a :class:`ast.MatchMapping` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case {1: \"Hello\", 2: \"World\", 3: _, **rest}:\n            ...\n    ''')\n    >>> node.cases[0].pattern\n    <MatchMapping l.3 at 0x10c8a8850>\n    \"\"\"\n\n    _astroid_fields = (\"keys\", \"patterns\", \"rest\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        self.keys: list[NodeNG]\n        self.patterns: list[Pattern]\n        self.rest: AssignName | None\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        *,\n        keys: list[NodeNG],\n        patterns: list[Pattern],\n        rest: AssignName | None,\n    ) -> None:\n        self.keys = keys\n        self.patterns = patterns\n        self.rest = rest\n\n    assigned_stmts: ClassVar[\n        Callable[\n            [\n                MatchMapping,\n                AssignName,\n                InferenceContext | None,\n                None,\n            ],\n            Generator[NodeNG, None, None],\n        ]\n    ]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n\nclass MatchClass(Pattern):\n    \"\"\"Class representing a :class:`ast.MatchClass` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case Point2D(0, 0):\n            ...\n        case Point3D(x=0, y=0, z=0):\n            ...\n    ''')\n    >>> node.cases[0].pattern\n    <MatchClass l.3 at 0x10ca83940>\n    >>> node.cases[1].pattern\n    <MatchClass l.5 at 0x10ca80880>\n    \"\"\"\n\n    _astroid_fields = (\"cls\", \"patterns\", \"kwd_patterns\")\n    _other_fields = (\"kwd_attrs\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        self.cls: NodeNG\n        self.patterns: list[Pattern]\n        self.kwd_attrs: list[str]\n        self.kwd_patterns: list[Pattern]\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        *,\n        cls: NodeNG,\n        patterns: list[Pattern],\n        kwd_attrs: list[str],\n        kwd_patterns: list[Pattern],\n    ) -> None:\n        self.cls = cls\n        self.patterns = patterns\n        self.kwd_attrs = kwd_attrs\n        self.kwd_patterns = kwd_patterns\n\n\nclass MatchStar(mixins.AssignTypeMixin, Pattern):\n    \"\"\"Class representing a :class:`ast.MatchStar` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case [1, *_]:\n            ...\n    ''')\n    >>> node.cases[0].pattern.patterns[1]\n    <MatchStar l.3 at 0x10ca809a0>\n    \"\"\"\n\n    _astroid_fields = (\"name\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        self.name: AssignName | None\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, *, name: AssignName | None) -> None:\n        self.name = name\n\n    assigned_stmts: ClassVar[\n        Callable[\n            [\n                MatchStar,\n                AssignName,\n                InferenceContext | None,\n                None,\n            ],\n            Generator[NodeNG, None, None],\n        ]\n    ]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n\nclass MatchAs(mixins.AssignTypeMixin, Pattern):\n    \"\"\"Class representing a :class:`ast.MatchAs` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case [1, a]:\n            ...\n        case {'key': b}:\n            ...\n        case Point2D(0, 0) as c:\n            ...\n        case d:\n            ...\n    ''')\n    >>> node.cases[0].pattern.patterns[1]\n    <MatchAs l.3 at 0x10d0b2da0>\n    >>> node.cases[1].pattern.patterns[0]\n    <MatchAs l.5 at 0x10d0b2920>\n    >>> node.cases[2].pattern\n    <MatchAs l.7 at 0x10d0b06a0>\n    >>> node.cases[3].pattern\n    <MatchAs l.9 at 0x10d09b880>\n    \"\"\"\n\n    _astroid_fields = (\"pattern\", \"name\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        self.pattern: Pattern | None\n        self.name: AssignName | None\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        *,\n        pattern: Pattern | None,\n        name: AssignName | None,\n    ) -> None:\n        self.pattern = pattern\n        self.name = name\n\n    assigned_stmts: ClassVar[\n        Callable[\n            [\n                MatchAs,\n                AssignName,\n                InferenceContext | None,\n                None,\n            ],\n            Generator[NodeNG, None, None],\n        ]\n    ]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n\nclass MatchOr(Pattern):\n    \"\"\"Class representing a :class:`ast.MatchOr` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case 400 | 401 | 402:\n            ...\n    ''')\n    >>> node.cases[0].pattern\n    <MatchOr l.3 at 0x10d0b0b50>\n    \"\"\"\n\n    _astroid_fields = (\"patterns\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        self.patterns: list[Pattern]\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, *, patterns: list[Pattern]) -> None:\n        self.patterns = patterns\n\n\n# constants ##############################################################\n\nCONST_CLS = {\n    list: List,\n    tuple: Tuple,\n    dict: Dict,\n    set: Set,\n    type(None): Const,\n    type(NotImplemented): Const,\n    type(...): Const,\n}\n\n\ndef _update_const_classes():\n    \"\"\"update constant classes, so the keys of CONST_CLS can be reused\"\"\"\n    klasses = (bool, int, float, complex, str, bytes)\n    for kls in klasses:\n        CONST_CLS[kls] = Const\n\n\n_update_const_classes()\n\n\ndef _two_step_initialization(cls, value):\n    instance = cls()\n    instance.postinit(value)\n    return instance\n\n\ndef _dict_initialization(cls, value):\n    if isinstance(value, dict):\n        value = tuple(value.items())\n    return _two_step_initialization(cls, value)\n\n\n_CONST_CLS_CONSTRUCTORS = {\n    List: _two_step_initialization,\n    Tuple: _two_step_initialization,\n    Dict: _dict_initialization,\n    Set: _two_step_initialization,\n    Const: lambda cls, value: cls(value),\n}\n\n\ndef const_factory(value):\n    \"\"\"return an astroid node for a python value\"\"\"\n    # XXX we should probably be stricter here and only consider stuff in\n    # CONST_CLS or do better treatment: in case where value is not in CONST_CLS,\n    # we should rather recall the builder on this value than returning an empty\n    # node (another option being that const_factory shouldn't be called with something\n    # not in CONST_CLS)\n    assert not isinstance(value, NodeNG)\n\n    # Hack for ignoring elements of a sequence\n    # or a mapping, in order to avoid transforming\n    # each element to an AST. This is fixed in 2.0\n    # and this approach is a temporary hack.\n    if isinstance(value, (list, set, tuple, dict)):\n        elts = []\n    else:\n        elts = value\n\n    try:\n        initializer_cls = CONST_CLS[value.__class__]\n        initializer = _CONST_CLS_CONSTRUCTORS[initializer_cls]\n        return initializer(initializer_cls, elts)\n    except (KeyError, AttributeError):\n        node = EmptyNode()\n        node.object = value\n        return node\n"}
filelevel_patches: {"astroid/nodes/node_classes.py": "@@ -2346,24 +2346,33 @@ def itered(self):\n         \"\"\"\n         return [key for (key, _) in self.items]\n \n-    def getitem(self, index, context=None):\n+    def getitem(\n+        self, index: Const | Slice, context: InferenceContext | None = None\n+    ) -> NodeNG:\n         \"\"\"Get an item from this node.\n \n         :param index: The node to use as a subscript index.\n-        :type index: Const or Slice\n \n         :raises AstroidTypeError: When the given index cannot be used as a\n             subscript index, or if this node is not subscriptable.\n         :raises AstroidIndexError: If the given index does not exist in the\n             dictionary.\n         \"\"\"\n+        # pylint: disable-next=import-outside-toplevel; circular import\n+        from astroid.helpers import safe_infer\n+\n         for key, value in self.items:\n             # TODO(cpopa): no support for overriding yet, {1:2, **{1: 3}}.\n             if isinstance(key, DictUnpack):\n+                inferred_value = safe_infer(value, context)\n+                if not isinstance(inferred_value, Dict):\n+                    continue\n+\n                 try:\n-                    return value.getitem(index, context)\n+                    return inferred_value.getitem(index, context)\n                 except (AstroidTypeError, AstroidIndexError):\n                     continue\n+\n             for inferredkey in key.infer(context):\n                 if inferredkey is util.Uninferable:\n                     continue"}
messages.content: 
  We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  getitem does not infer the actual unpacked value
  When trying to call `Dict.getitem()` on a context where we have a dict unpacking of anything beside a real dict, astroid currently raises an `AttributeError: 'getitem'`, which has 2 problems:
  
  - The object might be a reference against something constant, this pattern is usually seen when we have different sets of dicts that extend each other, and all of their values are inferrable. 
  - We can have something that is uninferable, but in that case instead of an `AttributeError` I think it makes sense to raise the usual `AstroidIndexError` which is supposed to be already handled by the downstream.
  
  
  Here is a short reproducer;
  
  ```py
  from astroid import parse
  
  
  source = """
  X = {
      'A': 'B'
  }
  
  Y = {
      **X
  }
  
  KEY = 'A'
  """
  
  tree = parse(source)
  
  first_dict = tree.body[0].value
  second_dict = tree.body[1].value
  key = tree.body[2].value
  
  print(f'{first_dict.getitem(key).value = }')
  print(f'{second_dict.getitem(key).value = }')
  
  
  ```
  
  The current output;
  
  ```
   $ python t1.py                                                                                                 3ms
  first_dict.getitem(key).value = 'B'
  Traceback (most recent call last):
    File "/home/isidentical/projects/astroid/t1.py", line 23, in <module>
      print(f'{second_dict.getitem(key).value = }')
    File "/home/isidentical/projects/astroid/astroid/nodes/node_classes.py", line 2254, in getitem
      return value.getitem(index, context)
  AttributeError: 'Name' object has no attribute 'getitem'
  ```
  
  Expeceted output;
  ```
   $ python t1.py                                                                                                 4ms
  first_dict.getitem(key).value = 'B'
  second_dict.getitem(key).value = 'B'
  
  ```
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  
  --- BEGIN FILE ---
  ```
  ### astroid/nodes/node_classes.py
  # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
  # For details: https://github.com/PyCQA/astroid/blob/main/LICENSE
  # Copyright (c) https://github.com/PyCQA/astroid/blob/main/CONTRIBUTORS.txt
  
  """Module for some node classes. More nodes in scoped_nodes.py"""
  
  from __future__ import annotations
  
  import abc
  import itertools
  import sys
  import typing
  import warnings
  from collections.abc import Generator, Iterator
  from functools import lru_cache
  from typing import TYPE_CHECKING, Any, Callable, ClassVar, Optional, TypeVar, Union
  
  from astroid import decorators, mixins, util
  from astroid.bases import Instance, _infer_stmts
  from astroid.const import Context
  from astroid.context import InferenceContext
  from astroid.exceptions import (
      AstroidIndexError,
      AstroidTypeError,
      InferenceError,
      NoDefault,
      ParentMissingError,
  )
  from astroid.manager import AstroidManager
  from astroid.nodes.const import OP_PRECEDENCE
  from astroid.nodes.node_ng import NodeNG
  
  if sys.version_info >= (3, 8):
      from typing import Literal
  else:
      from typing_extensions import Literal
  
  if TYPE_CHECKING:
      from astroid import nodes
      from astroid.nodes import LocalsDictNodeNG
  
  if sys.version_info >= (3, 8):
      from functools import cached_property
  else:
      from astroid.decorators import cachedproperty as cached_property
  
  
  def _is_const(value):
      return isinstance(value, tuple(CONST_CLS))
  
  
  _NodesT = TypeVar("_NodesT", bound=NodeNG)
  
  AssignedStmtsPossibleNode = Union["List", "Tuple", "AssignName", "AssignAttr", None]
  AssignedStmtsCall = Callable[
      [
          _NodesT,
          AssignedStmtsPossibleNode,
          Optional[InferenceContext],
          Optional[typing.List[int]],
      ],
      Any,
  ]
  
  
  @decorators.raise_if_nothing_inferred
  def unpack_infer(stmt, context=None):
      """recursively generate nodes inferred by the given statement.
      If the inferred value is a list or a tuple, recurse on the elements
      """
      if isinstance(stmt, (List, Tuple)):
          for elt in stmt.elts:
              if elt is util.Uninferable:
                  yield elt
                  continue
              yield from unpack_infer(elt, context)
          return dict(node=stmt, context=context)
      # if inferred is a final node, return it and stop
      inferred = next(stmt.infer(context), util.Uninferable)
      if inferred is stmt:
          yield inferred
          return dict(node=stmt, context=context)
      # else, infer recursively, except Uninferable object that should be returned as is
      for inferred in stmt.infer(context):
          if inferred is util.Uninferable:
              yield inferred
          else:
              yield from unpack_infer(inferred, context)
  
      return dict(node=stmt, context=context)
  
  
  def are_exclusive(stmt1, stmt2, exceptions: list[str] | None = None) -> bool:
      """return true if the two given statements are mutually exclusive
  
      `exceptions` may be a list of exception names. If specified, discard If
      branches and check one of the statement is in an exception handler catching
      one of the given exceptions.
  
      algorithm :
       1) index stmt1's parents
       2) climb among stmt2's parents until we find a common parent
       3) if the common parent is a If or TryExcept statement, look if nodes are
          in exclusive branches
      """
      # index stmt1's parents
      stmt1_parents = {}
      children = {}
      previous = stmt1
      for node in stmt1.node_ancestors():
          stmt1_parents[node] = 1
          children[node] = previous
          previous = node
      # climb among stmt2's parents until we find a common parent
      previous = stmt2
      for node in stmt2.node_ancestors():
          if node in stmt1_parents:
              # if the common parent is a If or TryExcept statement, look if
              # nodes are in exclusive branches
              if isinstance(node, If) and exceptions is None:
                  if (
                      node.locate_child(previous)[1]
                      is not node.locate_child(children[node])[1]
                  ):
                      return True
              elif isinstance(node, TryExcept):
                  c2attr, c2node = node.locate_child(previous)
                  c1attr, c1node = node.locate_child(children[node])
                  if c1node is not c2node:
                      first_in_body_caught_by_handlers = (
                          c2attr == "handlers"
                          and c1attr == "body"
                          and previous.catch(exceptions)
                      )
                      second_in_body_caught_by_handlers = (
                          c2attr == "body"
                          and c1attr == "handlers"
                          and children[node].catch(exceptions)
                      )
                      first_in_else_other_in_handlers = (
                          c2attr == "handlers" and c1attr == "orelse"
                      )
                      second_in_else_other_in_handlers = (
                          c2attr == "orelse" and c1attr == "handlers"
                      )
                      if any(
                          (
                              first_in_body_caught_by_handlers,
                              second_in_body_caught_by_handlers,
                              first_in_else_other_in_handlers,
                              second_in_else_other_in_handlers,
                          )
                      ):
                          return True
                  elif c2attr == "handlers" and c1attr == "handlers":
                      return previous is not children[node]
              return False
          previous = node
      return False
  
  
  # getitem() helpers.
  
  _SLICE_SENTINEL = object()
  
  
  def _slice_value(index, context=None):
      """Get the value of the given slice index."""
  
      if isinstance(index, Const):
          if isinstance(index.value, (int, type(None))):
              return index.value
      elif index is None:
          return None
      else:
          # Try to infer what the index actually is.
          # Since we can't return all the possible values,
          # we'll stop at the first possible value.
          try:
              inferred = next(index.infer(context=context))
          except (InferenceError, StopIteration):
              pass
          else:
              if isinstance(inferred, Const):
                  if isinstance(inferred.value, (int, type(None))):
                      return inferred.value
  
      # Use a sentinel, because None can be a valid
      # value that this function can return,
      # as it is the case for unspecified bounds.
      return _SLICE_SENTINEL
  
  
  def _infer_slice(node, context=None):
      lower = _slice_value(node.lower, context)
      upper = _slice_value(node.upper, context)
      step = _slice_value(node.step, context)
      if all(elem is not _SLICE_SENTINEL for elem in (lower, upper, step)):
          return slice(lower, upper, step)
  
      raise AstroidTypeError(
          message="Could not infer slice used in subscript",
          node=node,
          index=node.parent,
          context=context,
      )
  
  
  def _container_getitem(instance, elts, index, context=None):
      """Get a slice or an item, using the given *index*, for the given sequence."""
      try:
          if isinstance(index, Slice):
              index_slice = _infer_slice(index, context=context)
              new_cls = instance.__class__()
              new_cls.elts = elts[index_slice]
              new_cls.parent = instance.parent
              return new_cls
          if isinstance(index, Const):
              return elts[index.value]
      except IndexError as exc:
          raise AstroidIndexError(
              message="Index {index!s} out of range",
              node=instance,
              index=index,
              context=context,
          ) from exc
      except TypeError as exc:
          raise AstroidTypeError(
              message="Type error {error!r}", node=instance, index=index, context=context
          ) from exc
  
      raise AstroidTypeError(f"Could not use {index} as subscript index")
  
  
  class Statement(NodeNG):
      """Statement node adding a few attributes"""
  
      is_statement = True
      """Whether this node indicates a statement."""
  
      def next_sibling(self):
          """The next sibling statement node.
  
          :returns: The next sibling statement node.
          :rtype: NodeNG or None
          """
          stmts = self.parent.child_sequence(self)
          index = stmts.index(self)
          try:
              return stmts[index + 1]
          except IndexError:
              return None
  
      def previous_sibling(self):
          """The previous sibling statement.
  
          :returns: The previous sibling statement node.
          :rtype: NodeNG or None
          """
          stmts = self.parent.child_sequence(self)
          index = stmts.index(self)
          if index >= 1:
              return stmts[index - 1]
          return None
  
  
  class BaseContainer(
      mixins.ParentAssignTypeMixin, NodeNG, Instance, metaclass=abc.ABCMeta
  ):
      """Base class for Set, FrozenSet, Tuple and List."""
  
      _astroid_fields = ("elts",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.elts: list[NodeNG] = []
          """The elements in the node."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, elts: list[NodeNG]) -> None:
          """Do some setup after initialisation.
  
          :param elts: The list of elements the that node contains.
          """
          self.elts = elts
  
      @classmethod
      def from_elements(cls, elts=None):
          """Create a node of this type from the given list of elements.
  
          :param elts: The list of elements that the node should contain.
          :type elts: list(NodeNG)
  
          :returns: A new node containing the given elements.
          :rtype: NodeNG
          """
          node = cls()
          if elts is None:
              node.elts = []
          else:
              node.elts = [const_factory(e) if _is_const(e) else e for e in elts]
          return node
  
      def itered(self):
          """An iterator over the elements this node contains.
  
          :returns: The contents of this node.
          :rtype: iterable(NodeNG)
          """
          return self.elts
  
      def bool_value(self, context=None):
          """Determine the boolean value of this node.
  
          :returns: The boolean value of this node.
          :rtype: bool or Uninferable
          """
          return bool(self.elts)
  
      @abc.abstractmethod
      def pytype(self):
          """Get the name of the type that this node represents.
  
          :returns: The name of the type.
          :rtype: str
          """
  
      def get_children(self):
          yield from self.elts
  
  
  class LookupMixIn:
      """Mixin to look up a name in the right scope."""
  
      @lru_cache()  # noqa
      def lookup(self, name: str) -> tuple[str, list[NodeNG]]:
          """Lookup where the given variable is assigned.
  
          The lookup starts from self's scope. If self is not a frame itself
          and the name is found in the inner frame locals, statements will be
          filtered to remove ignorable statements according to self's location.
  
          :param name: The name of the variable to find assignments for.
  
          :returns: The scope node and the list of assignments associated to the
              given name according to the scope where it has been found (locals,
              globals or builtin).
          """
          return self.scope().scope_lookup(self, name)
  
      def ilookup(self, name):
          """Lookup the inferred values of the given variable.
  
          :param name: The variable name to find values for.
          :type name: str
  
          :returns: The inferred values of the statements returned from
              :meth:`lookup`.
          :rtype: iterable
          """
          frame, stmts = self.lookup(name)
          context = InferenceContext()
          return _infer_stmts(stmts, context, frame)
  
  
  # Name classes
  
  
  class AssignName(
      mixins.NoChildrenMixin, LookupMixIn, mixins.ParentAssignTypeMixin, NodeNG
  ):
      """Variation of :class:`ast.Assign` representing assignment to a name.
  
      An :class:`AssignName` is the name of something that is assigned to.
      This includes variables defined in a function signature or in a loop.
  
      >>> import astroid
      >>> node = astroid.extract_node('variable = range(10)')
      >>> node
      <Assign l.1 at 0x7effe1db8550>
      >>> list(node.get_children())
      [<AssignName.variable l.1 at 0x7effe1db8748>, <Call l.1 at 0x7effe1db8630>]
      >>> list(node.get_children())[0].as_string()
      'variable'
      """
  
      _other_fields = ("name",)
  
      @decorators.deprecate_default_argument_values(name="str")
      def __init__(
          self,
          name: str | None = None,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param name: The name that is assigned to.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.name: str | None = name
          """The name that is assigned to."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      assigned_stmts: ClassVar[AssignedStmtsCall[AssignName]]
      """Returns the assigned statement (non inferred) according to the assignment type.
      See astroid/protocols.py for actual implementation.
      """
  
  
  class DelName(
      mixins.NoChildrenMixin, LookupMixIn, mixins.ParentAssignTypeMixin, NodeNG
  ):
      """Variation of :class:`ast.Delete` representing deletion of a name.
  
      A :class:`DelName` is the name of something that is deleted.
  
      >>> import astroid
      >>> node = astroid.extract_node("del variable #@")
      >>> list(node.get_children())
      [<DelName.variable l.1 at 0x7effe1da4d30>]
      >>> list(node.get_children())[0].as_string()
      'variable'
      """
  
      _other_fields = ("name",)
  
      @decorators.deprecate_default_argument_values(name="str")
      def __init__(
          self,
          name: str | None = None,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param name: The name that is being deleted.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.name: str | None = name
          """The name that is being deleted."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
  
  class Name(mixins.NoChildrenMixin, LookupMixIn, NodeNG):
      """Class representing an :class:`ast.Name` node.
  
      A :class:`Name` node is something that is named, but not covered by
      :class:`AssignName` or :class:`DelName`.
  
      >>> import astroid
      >>> node = astroid.extract_node('range(10)')
      >>> node
      <Call l.1 at 0x7effe1db8710>
      >>> list(node.get_children())
      [<Name.range l.1 at 0x7effe1db86a0>, <Const.int l.1 at 0x7effe1db8518>]
      >>> list(node.get_children())[0].as_string()
      'range'
      """
  
      _other_fields = ("name",)
  
      @decorators.deprecate_default_argument_values(name="str")
      def __init__(
          self,
          name: str | None = None,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param name: The name that this node refers to.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.name: str | None = name
          """The name that this node refers to."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def _get_name_nodes(self):
          yield self
  
          for child_node in self.get_children():
              yield from child_node._get_name_nodes()
  
  
  class Arguments(mixins.AssignTypeMixin, NodeNG):
      """Class representing an :class:`ast.arguments` node.
  
      An :class:`Arguments` node represents that arguments in a
      function definition.
  
      >>> import astroid
      >>> node = astroid.extract_node('def foo(bar): pass')
      >>> node
      <FunctionDef.foo l.1 at 0x7effe1db8198>
      >>> node.args
      <Arguments l.1 at 0x7effe1db82e8>
      """
  
      # Python 3.4+ uses a different approach regarding annotations,
      # each argument is a new class, _ast.arg, which exposes an
      # 'annotation' attribute. In astroid though, arguments are exposed
      # as is in the Arguments node and the only way to expose annotations
      # is by using something similar with Python 3.3:
      #  - we expose 'varargannotation' and 'kwargannotation' of annotations
      #    of varargs and kwargs.
      #  - we expose 'annotation', a list with annotations for
      #    for each normal argument. If an argument doesn't have an
      #    annotation, its value will be None.
      _astroid_fields = (
          "args",
          "defaults",
          "kwonlyargs",
          "posonlyargs",
          "posonlyargs_annotations",
          "kw_defaults",
          "annotations",
          "varargannotation",
          "kwargannotation",
          "kwonlyargs_annotations",
          "type_comment_args",
          "type_comment_kwonlyargs",
          "type_comment_posonlyargs",
      )
  
      _other_fields = ("vararg", "kwarg")
  
      lineno: None
      col_offset: None
      end_lineno: None
      end_col_offset: None
  
      def __init__(
          self,
          vararg: str | None = None,
          kwarg: str | None = None,
          parent: NodeNG | None = None,
      ) -> None:
          """
          :param vararg: The name of the variable length arguments.
  
          :param kwarg: The name of the variable length keyword arguments.
  
          :param parent: The parent node in the syntax tree.
          """
          super().__init__(parent=parent)
  
          self.vararg: str | None = vararg  # can be None
          """The name of the variable length arguments."""
  
          self.kwarg: str | None = kwarg  # can be None
          """The name of the variable length keyword arguments."""
  
          self.args: list[AssignName] | None
          """The names of the required arguments.
  
          Can be None if the associated function does not have a retrievable
          signature and the arguments are therefore unknown.
          This can happen with (builtin) functions implemented in C that have
          incomplete signature information.
          """
          # TODO: Check if other attributes should also be None when
          # .args is None.
  
          self.defaults: list[NodeNG]
          """The default values for arguments that can be passed positionally."""
  
          self.kwonlyargs: list[AssignName]
          """The keyword arguments that cannot be passed positionally."""
  
          self.posonlyargs: list[AssignName] = []
          """The arguments that can only be passed positionally."""
  
          self.kw_defaults: list[NodeNG | None]
          """The default values for keyword arguments that cannot be passed positionally."""
  
          self.annotations: list[NodeNG | None]
          """The type annotations of arguments that can be passed positionally."""
  
          self.posonlyargs_annotations: list[NodeNG | None] = []
          """The type annotations of arguments that can only be passed positionally."""
  
          self.kwonlyargs_annotations: list[NodeNG | None] = []
          """The type annotations of arguments that cannot be passed positionally."""
  
          self.type_comment_args: list[NodeNG | None] = []
          """The type annotation, passed by a type comment, of each argument.
  
          If an argument does not have a type comment,
          the value for that argument will be None.
          """
  
          self.type_comment_kwonlyargs: list[NodeNG | None] = []
          """The type annotation, passed by a type comment, of each keyword only argument.
  
          If an argument does not have a type comment,
          the value for that argument will be None.
          """
  
          self.type_comment_posonlyargs: list[NodeNG | None] = []
          """The type annotation, passed by a type comment, of each positional argument.
  
          If an argument does not have a type comment,
          the value for that argument will be None.
          """
  
          self.varargannotation: NodeNG | None = None  # can be None
          """The type annotation for the variable length arguments."""
  
          self.kwargannotation: NodeNG | None = None  # can be None
          """The type annotation for the variable length keyword arguments."""
  
      # pylint: disable=too-many-arguments
      def postinit(
          self,
          args: list[AssignName] | None,
          defaults: list[NodeNG],
          kwonlyargs: list[AssignName],
          kw_defaults: list[NodeNG | None],
          annotations: list[NodeNG | None],
          posonlyargs: list[AssignName] | None = None,
          kwonlyargs_annotations: list[NodeNG | None] | None = None,
          posonlyargs_annotations: list[NodeNG | None] | None = None,
          varargannotation: NodeNG | None = None,
          kwargannotation: NodeNG | None = None,
          type_comment_args: list[NodeNG | None] | None = None,
          type_comment_kwonlyargs: list[NodeNG | None] | None = None,
          type_comment_posonlyargs: list[NodeNG | None] | None = None,
      ) -> None:
          """Do some setup after initialisation.
  
          :param args: The names of the required arguments.
  
          :param defaults: The default values for arguments that can be passed
              positionally.
  
          :param kwonlyargs: The keyword arguments that cannot be passed
              positionally.
  
          :param posonlyargs: The arguments that can only be passed
              positionally.
  
          :param kw_defaults: The default values for keyword arguments that
              cannot be passed positionally.
  
          :param annotations: The type annotations of arguments that can be
              passed positionally.
  
          :param kwonlyargs_annotations: The type annotations of arguments that
              cannot be passed positionally. This should always be passed in
              Python 3.
  
          :param posonlyargs_annotations: The type annotations of arguments that
              can only be passed positionally. This should always be passed in
              Python 3.
  
          :param varargannotation: The type annotation for the variable length
              arguments.
  
          :param kwargannotation: The type annotation for the variable length
              keyword arguments.
  
          :param type_comment_args: The type annotation,
              passed by a type comment, of each argument.
  
          :param type_comment_args: The type annotation,
              passed by a type comment, of each keyword only argument.
  
          :param type_comment_args: The type annotation,
              passed by a type comment, of each positional argument.
          """
          self.args = args
          self.defaults = defaults
          self.kwonlyargs = kwonlyargs
          if posonlyargs is not None:
              self.posonlyargs = posonlyargs
          self.kw_defaults = kw_defaults
          self.annotations = annotations
          if kwonlyargs_annotations is not None:
              self.kwonlyargs_annotations = kwonlyargs_annotations
          if posonlyargs_annotations is not None:
              self.posonlyargs_annotations = posonlyargs_annotations
          self.varargannotation = varargannotation
          self.kwargannotation = kwargannotation
          if type_comment_args is not None:
              self.type_comment_args = type_comment_args
          if type_comment_kwonlyargs is not None:
              self.type_comment_kwonlyargs = type_comment_kwonlyargs
          if type_comment_posonlyargs is not None:
              self.type_comment_posonlyargs = type_comment_posonlyargs
  
      assigned_stmts: ClassVar[AssignedStmtsCall[Arguments]]
      """Returns the assigned statement (non inferred) according to the assignment type.
      See astroid/protocols.py for actual implementation.
      """
  
      def _infer_name(self, frame, name):
          if self.parent is frame:
              return name
          return None
  
      @cached_property
      def fromlineno(self):
          """The first line that this node appears on in the source code.
  
          :type: int or None
          """
          lineno = super().fromlineno
          return max(lineno, self.parent.fromlineno or 0)
  
      @cached_property
      def arguments(self):
          """Get all the arguments for this node, including positional only and positional and keyword"""
          return list(itertools.chain((self.posonlyargs or ()), self.args or ()))
  
      def format_args(self):
          """Get the arguments formatted as string.
  
          :returns: The formatted arguments.
          :rtype: str
          """
          result = []
          positional_only_defaults = []
          positional_or_keyword_defaults = self.defaults
          if self.defaults:
              args = self.args or []
              positional_or_keyword_defaults = self.defaults[-len(args) :]
              positional_only_defaults = self.defaults[: len(self.defaults) - len(args)]
  
          if self.posonlyargs:
              result.append(
                  _format_args(
                      self.posonlyargs,
                      positional_only_defaults,
                      self.posonlyargs_annotations,
                  )
              )
              result.append("/")
          if self.args:
              result.append(
                  _format_args(
                      self.args,
                      positional_or_keyword_defaults,
                      getattr(self, "annotations", None),
                  )
              )
          if self.vararg:
              result.append(f"*{self.vararg}")
          if self.kwonlyargs:
              if not self.vararg:
                  result.append("*")
              result.append(
                  _format_args(
                      self.kwonlyargs, self.kw_defaults, self.kwonlyargs_annotations
                  )
              )
          if self.kwarg:
              result.append(f"**{self.kwarg}")
          return ", ".join(result)
  
      def default_value(self, argname):
          """Get the default value for an argument.
  
          :param argname: The name of the argument to get the default value for.
          :type argname: str
  
          :raises NoDefault: If there is no default value defined for the
              given argument.
          """
          args = self.arguments
          index = _find_arg(argname, args)[0]
          if index is not None:
              idx = index - (len(args) - len(self.defaults))
              if idx >= 0:
                  return self.defaults[idx]
          index = _find_arg(argname, self.kwonlyargs)[0]
          if index is not None and self.kw_defaults[index] is not None:
              return self.kw_defaults[index]
          raise NoDefault(func=self.parent, name=argname)
  
      def is_argument(self, name):
          """Check if the given name is defined in the arguments.
  
          :param name: The name to check for.
          :type name: str
  
          :returns: True if the given name is defined in the arguments,
              False otherwise.
          :rtype: bool
          """
          if name == self.vararg:
              return True
          if name == self.kwarg:
              return True
          return (
              self.find_argname(name, rec=True)[1] is not None
              or self.kwonlyargs
              and _find_arg(name, self.kwonlyargs, rec=True)[1] is not None
          )
  
      def find_argname(self, argname, rec=False):
          """Get the index and :class:`AssignName` node for given name.
  
          :param argname: The name of the argument to search for.
          :type argname: str
  
          :param rec: Whether or not to include arguments in unpacked tuples
              in the search.
          :type rec: bool
  
          :returns: The index and node for the argument.
          :rtype: tuple(str or None, AssignName or None)
          """
          if self.arguments:
              return _find_arg(argname, self.arguments, rec)
          return None, None
  
      def get_children(self):
          yield from self.posonlyargs or ()
  
          for elt in self.posonlyargs_annotations:
              if elt is not None:
                  yield elt
  
          yield from self.args or ()
  
          yield from self.defaults
          yield from self.kwonlyargs
  
          for elt in self.kw_defaults:
              if elt is not None:
                  yield elt
  
          for elt in self.annotations:
              if elt is not None:
                  yield elt
  
          if self.varargannotation is not None:
              yield self.varargannotation
  
          if self.kwargannotation is not None:
              yield self.kwargannotation
  
          for elt in self.kwonlyargs_annotations:
              if elt is not None:
                  yield elt
  
  
  def _find_arg(argname, args, rec=False):
      for i, arg in enumerate(args):
          if isinstance(arg, Tuple):
              if rec:
                  found = _find_arg(argname, arg.elts)
                  if found[0] is not None:
                      return found
          elif arg.name == argname:
              return i, arg
      return None, None
  
  
  def _format_args(args, defaults=None, annotations=None):
      values = []
      if args is None:
          return ""
      if annotations is None:
          annotations = []
      if defaults is not None:
          default_offset = len(args) - len(defaults)
      packed = itertools.zip_longest(args, annotations)
      for i, (arg, annotation) in enumerate(packed):
          if isinstance(arg, Tuple):
              values.append(f"({_format_args(arg.elts)})")
          else:
              argname = arg.name
              default_sep = "="
              if annotation is not None:
                  argname += ": " + annotation.as_string()
                  default_sep = " = "
              values.append(argname)
  
              if defaults is not None and i >= default_offset:
                  if defaults[i - default_offset] is not None:
                      values[-1] += default_sep + defaults[i - default_offset].as_string()
      return ", ".join(values)
  
  
  class AssignAttr(mixins.ParentAssignTypeMixin, NodeNG):
      """Variation of :class:`ast.Assign` representing assignment to an attribute.
  
      >>> import astroid
      >>> node = astroid.extract_node('self.attribute = range(10)')
      >>> node
      <Assign l.1 at 0x7effe1d521d0>
      >>> list(node.get_children())
      [<AssignAttr.attribute l.1 at 0x7effe1d52320>, <Call l.1 at 0x7effe1d522e8>]
      >>> list(node.get_children())[0].as_string()
      'self.attribute'
      """
  
      _astroid_fields = ("expr",)
      _other_fields = ("attrname",)
  
      @decorators.deprecate_default_argument_values(attrname="str")
      def __init__(
          self,
          attrname: str | None = None,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param attrname: The name of the attribute being assigned to.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.expr: NodeNG | None = None
          """What has the attribute that is being assigned to."""
  
          self.attrname: str | None = attrname
          """The name of the attribute being assigned to."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, expr: NodeNG | None = None) -> None:
          """Do some setup after initialisation.
  
          :param expr: What has the attribute that is being assigned to.
          """
          self.expr = expr
  
      assigned_stmts: ClassVar[AssignedStmtsCall[AssignAttr]]
      """Returns the assigned statement (non inferred) according to the assignment type.
      See astroid/protocols.py for actual implementation.
      """
  
      def get_children(self):
          yield self.expr
  
  
  class Assert(Statement):
      """Class representing an :class:`ast.Assert` node.
  
      An :class:`Assert` node represents an assert statement.
  
      >>> import astroid
      >>> node = astroid.extract_node('assert len(things) == 10, "Not enough things"')
      >>> node
      <Assert l.1 at 0x7effe1d527b8>
      """
  
      _astroid_fields = ("test", "fail")
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.test: NodeNG | None = None
          """The test that passes or fails the assertion."""
  
          self.fail: NodeNG | None = None  # can be None
          """The message shown when the assertion fails."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, test: NodeNG | None = None, fail: NodeNG | None = None) -> None:
          """Do some setup after initialisation.
  
          :param test: The test that passes or fails the assertion.
  
          :param fail: The message shown when the assertion fails.
          """
          self.fail = fail
          self.test = test
  
      def get_children(self):
          yield self.test
  
          if self.fail is not None:
              yield self.fail
  
  
  class Assign(mixins.AssignTypeMixin, Statement):
      """Class representing an :class:`ast.Assign` node.
  
      An :class:`Assign` is a statement where something is explicitly
      asssigned to.
  
      >>> import astroid
      >>> node = astroid.extract_node('variable = range(10)')
      >>> node
      <Assign l.1 at 0x7effe1db8550>
      """
  
      _astroid_fields = ("targets", "value")
      _other_other_fields = ("type_annotation",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.targets: list[NodeNG] = []
          """What is being assigned to."""
  
          self.value: NodeNG | None = None
          """The value being assigned to the variables."""
  
          self.type_annotation: NodeNG | None = None  # can be None
          """If present, this will contain the type annotation passed by a type comment"""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self,
          targets: list[NodeNG] | None = None,
          value: NodeNG | None = None,
          type_annotation: NodeNG | None = None,
      ) -> None:
          """Do some setup after initialisation.
  
          :param targets: What is being assigned to.
          :param value: The value being assigned to the variables.
          :param type_annotation:
          """
          if targets is not None:
              self.targets = targets
          self.value = value
          self.type_annotation = type_annotation
  
      assigned_stmts: ClassVar[AssignedStmtsCall[Assign]]
      """Returns the assigned statement (non inferred) according to the assignment type.
      See astroid/protocols.py for actual implementation.
      """
  
      def get_children(self):
          yield from self.targets
  
          yield self.value
  
      @decorators.cached
      def _get_assign_nodes(self):
          return [self] + list(self.value._get_assign_nodes())
  
      def _get_yield_nodes_skip_lambdas(self):
          yield from self.value._get_yield_nodes_skip_lambdas()
  
  
  class AnnAssign(mixins.AssignTypeMixin, Statement):
      """Class representing an :class:`ast.AnnAssign` node.
  
      An :class:`AnnAssign` is an assignment with a type annotation.
  
      >>> import astroid
      >>> node = astroid.extract_node('variable: List[int] = range(10)')
      >>> node
      <AnnAssign l.1 at 0x7effe1d4c630>
      """
  
      _astroid_fields = ("target", "annotation", "value")
      _other_fields = ("simple",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.target: NodeNG | None = None
          """What is being assigned to."""
  
          self.annotation: NodeNG | None = None
          """The type annotation of what is being assigned to."""
  
          self.value: NodeNG | None = None  # can be None
          """The value being assigned to the variables."""
  
          self.simple: int | None = None
          """Whether :attr:`target` is a pure name or a complex statement."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self,
          target: NodeNG,
          annotation: NodeNG,
          simple: int,
          value: NodeNG | None = None,
      ) -> None:
          """Do some setup after initialisation.
  
          :param target: What is being assigned to.
  
          :param annotation: The type annotation of what is being assigned to.
  
          :param simple: Whether :attr:`target` is a pure name
              or a complex statement.
  
          :param value: The value being assigned to the variables.
          """
          self.target = target
          self.annotation = annotation
          self.value = value
          self.simple = simple
  
      assigned_stmts: ClassVar[AssignedStmtsCall[AnnAssign]]
      """Returns the assigned statement (non inferred) according to the assignment type.
      See astroid/protocols.py for actual implementation.
      """
  
      def get_children(self):
          yield self.target
          yield self.annotation
  
          if self.value is not None:
              yield self.value
  
  
  class AugAssign(mixins.AssignTypeMixin, Statement):
      """Class representing an :class:`ast.AugAssign` node.
  
      An :class:`AugAssign` is an assignment paired with an operator.
  
      >>> import astroid
      >>> node = astroid.extract_node('variable += 1')
      >>> node
      <AugAssign l.1 at 0x7effe1db4d68>
      """
  
      _astroid_fields = ("target", "value")
      _other_fields = ("op",)
  
      @decorators.deprecate_default_argument_values(op="str")
      def __init__(
          self,
          op: str | None = None,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param op: The operator that is being combined with the assignment.
              This includes the equals sign.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.target: NodeNG | None = None
          """What is being assigned to."""
  
          self.op: str | None = op
          """The operator that is being combined with the assignment.
  
          This includes the equals sign.
          """
  
          self.value: NodeNG | None = None
          """The value being assigned to the variable."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self, target: NodeNG | None = None, value: NodeNG | None = None
      ) -> None:
          """Do some setup after initialisation.
  
          :param target: What is being assigned to.
  
          :param value: The value being assigned to the variable.
          """
          self.target = target
          self.value = value
  
      assigned_stmts: ClassVar[AssignedStmtsCall[AugAssign]]
      """Returns the assigned statement (non inferred) according to the assignment type.
      See astroid/protocols.py for actual implementation.
      """
  
      # This is set by inference.py
      def _infer_augassign(self, context=None):
          raise NotImplementedError
  
      def type_errors(self, context=None):
          """Get a list of type errors which can occur during inference.
  
          Each TypeError is represented by a :class:`BadBinaryOperationMessage` ,
          which holds the original exception.
  
          :returns: The list of possible type errors.
          :rtype: list(BadBinaryOperationMessage)
          """
          try:
              results = self._infer_augassign(context=context)
              return [
                  result
                  for result in results
                  if isinstance(result, util.BadBinaryOperationMessage)
              ]
          except InferenceError:
              return []
  
      def get_children(self):
          yield self.target
          yield self.value
  
      def _get_yield_nodes_skip_lambdas(self):
          """An AugAssign node can contain a Yield node in the value"""
          yield from self.value._get_yield_nodes_skip_lambdas()
          yield from super()._get_yield_nodes_skip_lambdas()
  
  
  class BinOp(NodeNG):
      """Class representing an :class:`ast.BinOp` node.
  
      A :class:`BinOp` node is an application of a binary operator.
  
      >>> import astroid
      >>> node = astroid.extract_node('a + b')
      >>> node
      <BinOp l.1 at 0x7f23b2e8cfd0>
      """
  
      _astroid_fields = ("left", "right")
      _other_fields = ("op",)
  
      @decorators.deprecate_default_argument_values(op="str")
      def __init__(
          self,
          op: str | None = None,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param op: The operator.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.left: NodeNG | None = None
          """What is being applied to the operator on the left side."""
  
          self.op: str | None = op
          """The operator."""
  
          self.right: NodeNG | None = None
          """What is being applied to the operator on the right side."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, left: NodeNG | None = None, right: NodeNG | None = None) -> None:
          """Do some setup after initialisation.
  
          :param left: What is being applied to the operator on the left side.
  
          :param right: What is being applied to the operator on the right side.
          """
          self.left = left
          self.right = right
  
      # This is set by inference.py
      def _infer_binop(self, context=None):
          raise NotImplementedError
  
      def type_errors(self, context=None):
          """Get a list of type errors which can occur during inference.
  
          Each TypeError is represented by a :class:`BadBinaryOperationMessage`,
          which holds the original exception.
  
          :returns: The list of possible type errors.
          :rtype: list(BadBinaryOperationMessage)
          """
          try:
              results = self._infer_binop(context=context)
              return [
                  result
                  for result in results
                  if isinstance(result, util.BadBinaryOperationMessage)
              ]
          except InferenceError:
              return []
  
      def get_children(self):
          yield self.left
          yield self.right
  
      def op_precedence(self):
          return OP_PRECEDENCE[self.op]
  
      def op_left_associative(self):
          # 2**3**4 == 2**(3**4)
          return self.op != "**"
  
  
  class BoolOp(NodeNG):
      """Class representing an :class:`ast.BoolOp` node.
  
      A :class:`BoolOp` is an application of a boolean operator.
  
      >>> import astroid
      >>> node = astroid.extract_node('a and b')
      >>> node
      <BinOp l.1 at 0x7f23b2e71c50>
      """
  
      _astroid_fields = ("values",)
      _other_fields = ("op",)
  
      @decorators.deprecate_default_argument_values(op="str")
      def __init__(
          self,
          op: str | None = None,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param op: The operator.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.op: str | None = op
          """The operator."""
  
          self.values: list[NodeNG] = []
          """The values being applied to the operator."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, values: list[NodeNG] | None = None) -> None:
          """Do some setup after initialisation.
  
          :param values: The values being applied to the operator.
          """
          if values is not None:
              self.values = values
  
      def get_children(self):
          yield from self.values
  
      def op_precedence(self):
          return OP_PRECEDENCE[self.op]
  
  
  class Break(mixins.NoChildrenMixin, Statement):
      """Class representing an :class:`ast.Break` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('break')
      >>> node
      <Break l.1 at 0x7f23b2e9e5c0>
      """
  
  
  class Call(NodeNG):
      """Class representing an :class:`ast.Call` node.
  
      A :class:`Call` node is a call to a function, method, etc.
  
      >>> import astroid
      >>> node = astroid.extract_node('function()')
      >>> node
      <Call l.1 at 0x7f23b2e71eb8>
      """
  
      _astroid_fields = ("func", "args", "keywords")
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.func: NodeNG | None = None
          """What is being called."""
  
          self.args: list[NodeNG] = []
          """The positional arguments being given to the call."""
  
          self.keywords: list[Keyword] = []
          """The keyword arguments being given to the call."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self,
          func: NodeNG | None = None,
          args: list[NodeNG] | None = None,
          keywords: list[Keyword] | None = None,
      ) -> None:
          """Do some setup after initialisation.
  
          :param func: What is being called.
  
          :param args: The positional arguments being given to the call.
  
          :param keywords: The keyword arguments being given to the call.
          """
          self.func = func
          if args is not None:
              self.args = args
          if keywords is not None:
              self.keywords = keywords
  
      @property
      def starargs(self) -> list[Starred]:
          """The positional arguments that unpack something."""
          return [arg for arg in self.args if isinstance(arg, Starred)]
  
      @property
      def kwargs(self) -> list[Keyword]:
          """The keyword arguments that unpack something."""
          return [keyword for keyword in self.keywords if keyword.arg is None]
  
      def get_children(self):
          yield self.func
  
          yield from self.args
  
          yield from self.keywords
  
  
  class Compare(NodeNG):
      """Class representing an :class:`ast.Compare` node.
  
      A :class:`Compare` node indicates a comparison.
  
      >>> import astroid
      >>> node = astroid.extract_node('a <= b <= c')
      >>> node
      <Compare l.1 at 0x7f23b2e9e6d8>
      >>> node.ops
      [('<=', <Name.b l.1 at 0x7f23b2e9e2b0>), ('<=', <Name.c l.1 at 0x7f23b2e9e390>)]
      """
  
      _astroid_fields = ("left", "ops")
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.left: NodeNG | None = None
          """The value at the left being applied to a comparison operator."""
  
          self.ops: list[tuple[str, NodeNG]] = []
          """The remainder of the operators and their relevant right hand value."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self,
          left: NodeNG | None = None,
          ops: list[tuple[str, NodeNG]] | None = None,
      ) -> None:
          """Do some setup after initialisation.
  
          :param left: The value at the left being applied to a comparison
              operator.
  
          :param ops: The remainder of the operators
              and their relevant right hand value.
          """
          self.left = left
          if ops is not None:
              self.ops = ops
  
      def get_children(self):
          """Get the child nodes below this node.
  
          Overridden to handle the tuple fields and skip returning the operator
          strings.
  
          :returns: The children.
          :rtype: iterable(NodeNG)
          """
          yield self.left
          for _, comparator in self.ops:
              yield comparator  # we don't want the 'op'
  
      def last_child(self):
          """An optimized version of list(get_children())[-1]
  
          :returns: The last child.
          :rtype: NodeNG
          """
          # XXX maybe if self.ops:
          return self.ops[-1][1]
          # return self.left
  
  
  class Comprehension(NodeNG):
      """Class representing an :class:`ast.comprehension` node.
  
      A :class:`Comprehension` indicates the loop inside any type of
      comprehension including generator expressions.
  
      >>> import astroid
      >>> node = astroid.extract_node('[x for x in some_values]')
      >>> list(node.get_children())
      [<Name.x l.1 at 0x7f23b2e352b0>, <Comprehension l.1 at 0x7f23b2e35320>]
      >>> list(node.get_children())[1].as_string()
      'for x in some_values'
      """
  
      _astroid_fields = ("target", "iter", "ifs")
      _other_fields = ("is_async",)
  
      optional_assign = True
      """Whether this node optionally assigns a variable."""
  
      lineno: None
      col_offset: None
      end_lineno: None
      end_col_offset: None
  
      def __init__(self, parent: NodeNG | None = None) -> None:
          """
          :param parent: The parent node in the syntax tree.
          """
          self.target: NodeNG | None = None
          """What is assigned to by the comprehension."""
  
          self.iter: NodeNG | None = None
          """What is iterated over by the comprehension."""
  
          self.ifs: list[NodeNG] = []
          """The contents of any if statements that filter the comprehension."""
  
          self.is_async: bool | None = None
          """Whether this is an asynchronous comprehension or not."""
  
          super().__init__(parent=parent)
  
      # pylint: disable=redefined-builtin; same name as builtin ast module.
      def postinit(
          self,
          target: NodeNG | None = None,
          iter: NodeNG | None = None,
          ifs: list[NodeNG] | None = None,
          is_async: bool | None = None,
      ) -> None:
          """Do some setup after initialisation.
  
          :param target: What is assigned to by the comprehension.
  
          :param iter: What is iterated over by the comprehension.
  
          :param ifs: The contents of any if statements that filter
              the comprehension.
  
          :param is_async: Whether this is an asynchronous comprehension or not.
          """
          self.target = target
          self.iter = iter
          if ifs is not None:
              self.ifs = ifs
          self.is_async = is_async
  
      assigned_stmts: ClassVar[AssignedStmtsCall[Comprehension]]
      """Returns the assigned statement (non inferred) according to the assignment type.
      See astroid/protocols.py for actual implementation.
      """
  
      def assign_type(self):
          """The type of assignment that this node performs.
  
          :returns: The assignment type.
          :rtype: NodeNG
          """
          return self
  
      def _get_filtered_stmts(self, lookup_node, node, stmts, mystmt: Statement | None):
          """method used in filter_stmts"""
          if self is mystmt:
              if isinstance(lookup_node, (Const, Name)):
                  return [lookup_node], True
  
          elif self.statement(future=True) is mystmt:
              # original node's statement is the assignment, only keeps
              # current node (gen exp, list comp)
  
              return [node], True
  
          return stmts, False
  
      def get_children(self):
          yield self.target
          yield self.iter
  
          yield from self.ifs
  
  
  class Const(mixins.NoChildrenMixin, NodeNG, Instance):
      """Class representing any constant including num, str, bool, None, bytes.
  
      >>> import astroid
      >>> node = astroid.extract_node('(5, "This is a string.", True, None, b"bytes")')
      >>> node
      <Tuple.tuple l.1 at 0x7f23b2e358d0>
      >>> list(node.get_children())
      [<Const.int l.1 at 0x7f23b2e35940>,
      <Const.str l.1 at 0x7f23b2e35978>,
      <Const.bool l.1 at 0x7f23b2e359b0>,
      <Const.NoneType l.1 at 0x7f23b2e359e8>,
      <Const.bytes l.1 at 0x7f23b2e35a20>]
      """
  
      _other_fields = ("value", "kind")
  
      def __init__(
          self,
          value: Any,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          kind: str | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param value: The value that the constant represents.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param kind: The string prefix. "u" for u-prefixed strings and ``None`` otherwise. Python 3.8+ only.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.value: Any = value
          """The value that the constant represents."""
  
          self.kind: str | None = kind  # can be None
          """"The string prefix. "u" for u-prefixed strings and ``None`` otherwise. Python 3.8+ only."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def __getattr__(self, name):
          # This is needed because of Proxy's __getattr__ method.
          # Calling object.__new__ on this class without calling
          # __init__ would result in an infinite loop otherwise
          # since __getattr__ is called when an attribute doesn't
          # exist and self._proxied indirectly calls self.value
          # and Proxy __getattr__ calls self.value
          if name == "value":
              raise AttributeError
          return super().__getattr__(name)
  
      def getitem(self, index, context=None):
          """Get an item from this node if subscriptable.
  
          :param index: The node to use as a subscript index.
          :type index: Const or Slice
  
          :raises AstroidTypeError: When the given index cannot be used as a
              subscript index, or if this node is not subscriptable.
          """
          if isinstance(index, Const):
              index_value = index.value
          elif isinstance(index, Slice):
              index_value = _infer_slice(index, context=context)
  
          else:
              raise AstroidTypeError(
                  f"Could not use type {type(index)} as subscript index"
              )
  
          try:
              if isinstance(self.value, (str, bytes)):
                  return Const(self.value[index_value])
          except IndexError as exc:
              raise AstroidIndexError(
                  message="Index {index!r} out of range",
                  node=self,
                  index=index,
                  context=context,
              ) from exc
          except TypeError as exc:
              raise AstroidTypeError(
                  message="Type error {error!r}", node=self, index=index, context=context
              ) from exc
  
          raise AstroidTypeError(f"{self!r} (value={self.value})")
  
      def has_dynamic_getattr(self):
          """Check if the node has a custom __getattr__ or __getattribute__.
  
          :returns: True if the class has a custom
              __getattr__ or __getattribute__, False otherwise.
              For a :class:`Const` this is always ``False``.
          :rtype: bool
          """
          return False
  
      def itered(self):
          """An iterator over the elements this node contains.
  
          :returns: The contents of this node.
          :rtype: iterable(Const)
  
          :raises TypeError: If this node does not represent something that is iterable.
          """
          if isinstance(self.value, str):
              return [const_factory(elem) for elem in self.value]
          raise TypeError(f"Cannot iterate over type {type(self.value)!r}")
  
      def pytype(self):
          """Get the name of the type that this node represents.
  
          :returns: The name of the type.
          :rtype: str
          """
          return self._proxied.qname()
  
      def bool_value(self, context=None):
          """Determine the boolean value of this node.
  
          :returns: The boolean value of this node.
          :rtype: bool
          """
          return bool(self.value)
  
  
  class Continue(mixins.NoChildrenMixin, Statement):
      """Class representing an :class:`ast.Continue` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('continue')
      >>> node
      <Continue l.1 at 0x7f23b2e35588>
      """
  
  
  class Decorators(NodeNG):
      """A node representing a list of decorators.
  
      A :class:`Decorators` is the decorators that are applied to
      a method or function.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
      @property
      def my_property(self):
          return 3
      ''')
      >>> node
      <FunctionDef.my_property l.2 at 0x7f23b2e35d30>
      >>> list(node.get_children())[0]
      <Decorators l.1 at 0x7f23b2e35d68>
      """
  
      _astroid_fields = ("nodes",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.nodes: list[NodeNG]
          """The decorators that this node contains.
  
          :type: list(Name or Call) or None
          """
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, nodes: list[NodeNG]) -> None:
          """Do some setup after initialisation.
  
          :param nodes: The decorators that this node contains.
          :type nodes: list(Name or Call)
          """
          self.nodes = nodes
  
      def scope(self) -> LocalsDictNodeNG:
          """The first parent node defining a new scope.
          These can be Module, FunctionDef, ClassDef, Lambda, or GeneratorExp nodes.
  
          :returns: The first parent scope node.
          """
          # skip the function node to go directly to the upper level scope
          if not self.parent:
              raise ParentMissingError(target=self)
          if not self.parent.parent:
              raise ParentMissingError(target=self.parent)
          return self.parent.parent.scope()
  
      def get_children(self):
          yield from self.nodes
  
  
  class DelAttr(mixins.ParentAssignTypeMixin, NodeNG):
      """Variation of :class:`ast.Delete` representing deletion of an attribute.
  
      >>> import astroid
      >>> node = astroid.extract_node('del self.attr')
      >>> node
      <Delete l.1 at 0x7f23b2e35f60>
      >>> list(node.get_children())[0]
      <DelAttr.attr l.1 at 0x7f23b2e411d0>
      """
  
      _astroid_fields = ("expr",)
      _other_fields = ("attrname",)
  
      @decorators.deprecate_default_argument_values(attrname="str")
      def __init__(
          self,
          attrname: str | None = None,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param attrname: The name of the attribute that is being deleted.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.expr: NodeNG | None = None
          """The name that this node represents.
  
          :type: Name or None
          """
  
          self.attrname: str | None = attrname
          """The name of the attribute that is being deleted."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, expr: NodeNG | None = None) -> None:
          """Do some setup after initialisation.
  
          :param expr: The name that this node represents.
          :type expr: Name or None
          """
          self.expr = expr
  
      def get_children(self):
          yield self.expr
  
  
  class Delete(mixins.AssignTypeMixin, Statement):
      """Class representing an :class:`ast.Delete` node.
  
      A :class:`Delete` is a ``del`` statement this is deleting something.
  
      >>> import astroid
      >>> node = astroid.extract_node('del self.attr')
      >>> node
      <Delete l.1 at 0x7f23b2e35f60>
      """
  
      _astroid_fields = ("targets",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.targets: list[NodeNG] = []
          """What is being deleted."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, targets: list[NodeNG] | None = None) -> None:
          """Do some setup after initialisation.
  
          :param targets: What is being deleted.
          """
          if targets is not None:
              self.targets = targets
  
      def get_children(self):
          yield from self.targets
  
  
  class Dict(NodeNG, Instance):
      """Class representing an :class:`ast.Dict` node.
  
      A :class:`Dict` is a dictionary that is created with ``{}`` syntax.
  
      >>> import astroid
      >>> node = astroid.extract_node('{1: "1"}')
      >>> node
      <Dict.dict l.1 at 0x7f23b2e35cc0>
      """
  
      _astroid_fields = ("items",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.items: list[tuple[NodeNG, NodeNG]] = []
          """The key-value pairs contained in the dictionary."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, items: list[tuple[NodeNG, NodeNG]]) -> None:
          """Do some setup after initialisation.
  
          :param items: The key-value pairs contained in the dictionary.
          """
          self.items = items
  
      @classmethod
      def from_elements(cls, items=None):
          """Create a :class:`Dict` of constants from a live dictionary.
  
          :param items: The items to store in the node.
          :type items: dict
  
          :returns: The created dictionary node.
          :rtype: Dict
          """
          node = cls()
          if items is None:
              node.items = []
          else:
              node.items = [
                  (const_factory(k), const_factory(v) if _is_const(v) else v)
                  for k, v in items.items()
                  # The keys need to be constants
                  if _is_const(k)
              ]
          return node
  
      def pytype(self):
          """Get the name of the type that this node represents.
  
          :returns: The name of the type.
          :rtype: str
          """
          return "builtins.dict"
  
      def get_children(self):
          """Get the key and value nodes below this node.
  
          Children are returned in the order that they are defined in the source
          code, key first then the value.
  
          :returns: The children.
          :rtype: iterable(NodeNG)
          """
          for key, value in self.items:
              yield key
              yield value
  
      def last_child(self):
          """An optimized version of list(get_children())[-1]
  
          :returns: The last child, or None if no children exist.
          :rtype: NodeNG or None
          """
          if self.items:
              return self.items[-1][1]
          return None
  
      def itered(self):
          """An iterator over the keys this node contains.
  
          :returns: The keys of this node.
          :rtype: iterable(NodeNG)
          """
          return [key for (key, _) in self.items]
  
      def getitem(self, index, context=None):
          """Get an item from this node.
  
          :param index: The node to use as a subscript index.
          :type index: Const or Slice
  
          :raises AstroidTypeError: When the given index cannot be used as a
              subscript index, or if this node is not subscriptable.
          :raises AstroidIndexError: If the given index does not exist in the
              dictionary.
          """
          for key, value in self.items:
              # TODO(cpopa): no support for overriding yet, {1:2, **{1: 3}}.
              if isinstance(key, DictUnpack):
                  try:
                      return value.getitem(index, context)
                  except (AstroidTypeError, AstroidIndexError):
                      continue
              for inferredkey in key.infer(context):
                  if inferredkey is util.Uninferable:
                      continue
                  if isinstance(inferredkey, Const) and isinstance(index, Const):
                      if inferredkey.value == index.value:
                          return value
  
          raise AstroidIndexError(index)
  
      def bool_value(self, context=None):
          """Determine the boolean value of this node.
  
          :returns: The boolean value of this node.
          :rtype: bool
          """
          return bool(self.items)
  
  
  class Expr(Statement):
      """Class representing an :class:`ast.Expr` node.
  
      An :class:`Expr` is any expression that does not have its value used or
      stored.
  
      >>> import astroid
      >>> node = astroid.extract_node('method()')
      >>> node
      <Call l.1 at 0x7f23b2e352b0>
      >>> node.parent
      <Expr l.1 at 0x7f23b2e35278>
      """
  
      _astroid_fields = ("value",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.value: NodeNG | None = None
          """What the expression does."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, value: NodeNG | None = None) -> None:
          """Do some setup after initialisation.
  
          :param value: What the expression does.
          """
          self.value = value
  
      def get_children(self):
          yield self.value
  
      def _get_yield_nodes_skip_lambdas(self):
          if not self.value.is_lambda:
              yield from self.value._get_yield_nodes_skip_lambdas()
  
  
  class Ellipsis(mixins.NoChildrenMixin, NodeNG):  # pylint: disable=redefined-builtin
      """Class representing an :class:`ast.Ellipsis` node.
  
      An :class:`Ellipsis` is the ``...`` syntax.
  
      Deprecated since v2.6.0 - Use :class:`Const` instead.
      Will be removed with the release v2.7.0
      """
  
  
  class EmptyNode(mixins.NoChildrenMixin, NodeNG):
      """Holds an arbitrary object in the :attr:`LocalsDictNodeNG.locals`."""
  
      object = None
  
  
  class ExceptHandler(mixins.MultiLineBlockMixin, mixins.AssignTypeMixin, Statement):
      """Class representing an :class:`ast.ExceptHandler`. node.
  
      An :class:`ExceptHandler` is an ``except`` block on a try-except.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
          try:
              do_something()
          except Exception as error:
              print("Error!")
          ''')
      >>> node
      <TryExcept l.2 at 0x7f23b2e9d908>
      >>> node.handlers
      [<ExceptHandler l.4 at 0x7f23b2e9e860>]
      """
  
      _astroid_fields = ("type", "name", "body")
      _multi_line_block_fields = ("body",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.type: NodeNG | None = None  # can be None
          """The types that the block handles.
  
          :type: Tuple or NodeNG or None
          """
  
          self.name: AssignName | None = None  # can be None
          """The name that the caught exception is assigned to."""
  
          self.body: list[NodeNG] = []
          """The contents of the block."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      assigned_stmts: ClassVar[AssignedStmtsCall[ExceptHandler]]
      """Returns the assigned statement (non inferred) according to the assignment type.
      See astroid/protocols.py for actual implementation.
      """
  
      def get_children(self):
          if self.type is not None:
              yield self.type
  
          if self.name is not None:
              yield self.name
  
          yield from self.body
  
      # pylint: disable=redefined-builtin; had to use the same name as builtin ast module.
      def postinit(
          self,
          type: NodeNG | None = None,
          name: AssignName | None = None,
          body: list[NodeNG] | None = None,
      ) -> None:
          """Do some setup after initialisation.
  
          :param type: The types that the block handles.
          :type type: Tuple or NodeNG or None
  
          :param name: The name that the caught exception is assigned to.
  
          :param body:The contents of the block.
          """
          self.type = type
          self.name = name
          if body is not None:
              self.body = body
  
      @cached_property
      def blockstart_tolineno(self):
          """The line on which the beginning of this block ends.
  
          :type: int
          """
          if self.name:
              return self.name.tolineno
          if self.type:
              return self.type.tolineno
          return self.lineno
  
      def catch(self, exceptions: list[str] | None) -> bool:
          """Check if this node handles any of the given
  
          :param exceptions: The names of the exceptions to check for.
          """
          if self.type is None or exceptions is None:
              return True
          return any(node.name in exceptions for node in self.type._get_name_nodes())
  
  
  class ExtSlice(NodeNG):
      """Class representing an :class:`ast.ExtSlice` node.
  
      An :class:`ExtSlice` is a complex slice expression.
  
      Deprecated since v2.6.0 - Now part of the :class:`Subscript` node.
      Will be removed with the release of v2.7.0
      """
  
  
  class For(
      mixins.MultiLineBlockMixin,
      mixins.BlockRangeMixIn,
      mixins.AssignTypeMixin,
      Statement,
  ):
      """Class representing an :class:`ast.For` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('for thing in things: print(thing)')
      >>> node
      <For l.1 at 0x7f23b2e8cf28>
      """
  
      _astroid_fields = ("target", "iter", "body", "orelse")
      _other_other_fields = ("type_annotation",)
      _multi_line_block_fields = ("body", "orelse")
  
      optional_assign = True
      """Whether this node optionally assigns a variable.
  
      This is always ``True`` for :class:`For` nodes.
      """
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.target: NodeNG | None = None
          """What the loop assigns to."""
  
          self.iter: NodeNG | None = None
          """What the loop iterates over."""
  
          self.body: list[NodeNG] = []
          """The contents of the body of the loop."""
  
          self.orelse: list[NodeNG] = []
          """The contents of the ``else`` block of the loop."""
  
          self.type_annotation: NodeNG | None = None  # can be None
          """If present, this will contain the type annotation passed by a type comment"""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      # pylint: disable=redefined-builtin; had to use the same name as builtin ast module.
      def postinit(
          self,
          target: NodeNG | None = None,
          iter: NodeNG | None = None,
          body: list[NodeNG] | None = None,
          orelse: list[NodeNG] | None = None,
          type_annotation: NodeNG | None = None,
      ) -> None:
          """Do some setup after initialisation.
  
          :param target: What the loop assigns to.
  
          :param iter: What the loop iterates over.
  
          :param body: The contents of the body of the loop.
  
          :param orelse: The contents of the ``else`` block of the loop.
          """
          self.target = target
          self.iter = iter
          if body is not None:
              self.body = body
          if orelse is not None:
              self.orelse = orelse
          self.type_annotation = type_annotation
  
      assigned_stmts: ClassVar[AssignedStmtsCall[For]]
      """Returns the assigned statement (non inferred) according to the assignment type.
      See astroid/protocols.py for actual implementation.
      """
  
      @cached_property
      def blockstart_tolineno(self):
          """The line on which the beginning of this block ends.
  
          :type: int
          """
          return self.iter.tolineno
  
      def get_children(self):
          yield self.target
          yield self.iter
  
          yield from self.body
          yield from self.orelse
  
  
  class AsyncFor(For):
      """Class representing an :class:`ast.AsyncFor` node.
  
      An :class:`AsyncFor` is an asynchronous :class:`For` built with
      the ``async`` keyword.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
      async def func(things):
          async for thing in things:
              print(thing)
      ''')
      >>> node
      <AsyncFunctionDef.func l.2 at 0x7f23b2e416d8>
      >>> node.body[0]
      <AsyncFor l.3 at 0x7f23b2e417b8>
      """
  
  
  class Await(NodeNG):
      """Class representing an :class:`ast.Await` node.
  
      An :class:`Await` is the ``await`` keyword.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
      async def func(things):
          await other_func()
      ''')
      >>> node
      <AsyncFunctionDef.func l.2 at 0x7f23b2e41748>
      >>> node.body[0]
      <Expr l.3 at 0x7f23b2e419e8>
      >>> list(node.body[0].get_children())[0]
      <Await l.3 at 0x7f23b2e41a20>
      """
  
      _astroid_fields = ("value",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.value: NodeNG | None = None
          """What to wait for."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, value: NodeNG | None = None) -> None:
          """Do some setup after initialisation.
  
          :param value: What to wait for.
          """
          self.value = value
  
      def get_children(self):
          yield self.value
  
  
  class ImportFrom(mixins.NoChildrenMixin, mixins.ImportFromMixin, Statement):
      """Class representing an :class:`ast.ImportFrom` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('from my_package import my_module')
      >>> node
      <ImportFrom l.1 at 0x7f23b2e415c0>
      """
  
      _other_fields = ("modname", "names", "level")
  
      def __init__(
          self,
          fromname: str | None,
          names: list[tuple[str, str | None]],
          level: int | None = 0,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param fromname: The module that is being imported from.
  
          :param names: What is being imported from the module.
  
          :param level: The level of relative import.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.modname: str | None = fromname  # can be None
          """The module that is being imported from.
  
          This is ``None`` for relative imports.
          """
  
          self.names: list[tuple[str, str | None]] = names
          """What is being imported from the module.
  
          Each entry is a :class:`tuple` of the name being imported,
          and the alias that the name is assigned to (if any).
          """
  
          # TODO When is 'level' None?
          self.level: int | None = level  # can be None
          """The level of relative import.
  
          Essentially this is the number of dots in the import.
          This is always 0 for absolute imports.
          """
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
  
  class Attribute(NodeNG):
      """Class representing an :class:`ast.Attribute` node."""
  
      _astroid_fields = ("expr",)
      _other_fields = ("attrname",)
  
      @decorators.deprecate_default_argument_values(attrname="str")
      def __init__(
          self,
          attrname: str | None = None,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param attrname: The name of the attribute.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.expr: NodeNG | None = None
          """The name that this node represents.
  
          :type: Name or None
          """
  
          self.attrname: str | None = attrname
          """The name of the attribute."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, expr: NodeNG | None = None) -> None:
          """Do some setup after initialisation.
  
          :param expr: The name that this node represents.
          :type expr: Name or None
          """
          self.expr = expr
  
      def get_children(self):
          yield self.expr
  
  
  class Global(mixins.NoChildrenMixin, Statement):
      """Class representing an :class:`ast.Global` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('global a_global')
      >>> node
      <Global l.1 at 0x7f23b2e9de10>
      """
  
      _other_fields = ("names",)
  
      def __init__(
          self,
          names: list[str],
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param names: The names being declared as global.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.names: list[str] = names
          """The names being declared as global."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def _infer_name(self, frame, name):
          return name
  
  
  class If(mixins.MultiLineBlockMixin, mixins.BlockRangeMixIn, Statement):
      """Class representing an :class:`ast.If` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('if condition: print(True)')
      >>> node
      <If l.1 at 0x7f23b2e9dd30>
      """
  
      _astroid_fields = ("test", "body", "orelse")
      _multi_line_block_fields = ("body", "orelse")
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.test: NodeNG | None = None
          """The condition that the statement tests."""
  
          self.body: list[NodeNG] = []
          """The contents of the block."""
  
          self.orelse: list[NodeNG] = []
          """The contents of the ``else`` block."""
  
          self.is_orelse: bool = False
          """Whether the if-statement is the orelse-block of another if statement."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self,
          test: NodeNG | None = None,
          body: list[NodeNG] | None = None,
          orelse: list[NodeNG] | None = None,
      ) -> None:
          """Do some setup after initialisation.
  
          :param test: The condition that the statement tests.
  
          :param body: The contents of the block.
  
          :param orelse: The contents of the ``else`` block.
          """
          self.test = test
          if body is not None:
              self.body = body
          if orelse is not None:
              self.orelse = orelse
          if isinstance(self.parent, If) and self in self.parent.orelse:
              self.is_orelse = True
  
      @cached_property
      def blockstart_tolineno(self):
          """The line on which the beginning of this block ends.
  
          :type: int
          """
          return self.test.tolineno
  
      def block_range(self, lineno):
          """Get a range from the given line number to where this node ends.
  
          :param lineno: The line number to start the range at.
          :type lineno: int
  
          :returns: The range of line numbers that this node belongs to,
              starting at the given line number.
          :rtype: tuple(int, int)
          """
          if lineno == self.body[0].fromlineno:
              return lineno, lineno
          if lineno <= self.body[-1].tolineno:
              return lineno, self.body[-1].tolineno
          return self._elsed_block_range(lineno, self.orelse, self.body[0].fromlineno - 1)
  
      def get_children(self):
          yield self.test
  
          yield from self.body
          yield from self.orelse
  
      def has_elif_block(self):
          return len(self.orelse) == 1 and isinstance(self.orelse[0], If)
  
      def _get_yield_nodes_skip_lambdas(self):
          """An If node can contain a Yield node in the test"""
          yield from self.test._get_yield_nodes_skip_lambdas()
          yield from super()._get_yield_nodes_skip_lambdas()
  
      def is_sys_guard(self) -> bool:
          """Return True if IF stmt is a sys.version_info guard.
  
          >>> import astroid
          >>> node = astroid.extract_node('''
          import sys
          if sys.version_info > (3, 8):
              from typing import Literal
          else:
              from typing_extensions import Literal
          ''')
          >>> node.is_sys_guard()
          True
          """
          warnings.warn(
              "The 'is_sys_guard' function is deprecated and will be removed in astroid 3.0.0 "
              "It has been moved to pylint and can be imported from 'pylint.checkers.utils' "
              "starting with pylint 2.12",
              DeprecationWarning,
          )
          if isinstance(self.test, Compare):
              value = self.test.left
              if isinstance(value, Subscript):
                  value = value.value
              if isinstance(value, Attribute) and value.as_string() == "sys.version_info":
                  return True
  
          return False
  
      def is_typing_guard(self) -> bool:
          """Return True if IF stmt is a typing guard.
  
          >>> import astroid
          >>> node = astroid.extract_node('''
          from typing import TYPE_CHECKING
          if TYPE_CHECKING:
              from xyz import a
          ''')
          >>> node.is_typing_guard()
          True
          """
          warnings.warn(
              "The 'is_typing_guard' function is deprecated and will be removed in astroid 3.0.0 "
              "It has been moved to pylint and can be imported from 'pylint.checkers.utils' "
              "starting with pylint 2.12",
              DeprecationWarning,
          )
          return isinstance(
              self.test, (Name, Attribute)
          ) and self.test.as_string().endswith("TYPE_CHECKING")
  
  
  class IfExp(NodeNG):
      """Class representing an :class:`ast.IfExp` node.
      >>> import astroid
      >>> node = astroid.extract_node('value if condition else other')
      >>> node
      <IfExp l.1 at 0x7f23b2e9dbe0>
      """
  
      _astroid_fields = ("test", "body", "orelse")
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.test: NodeNG | None = None
          """The condition that the statement tests."""
  
          self.body: NodeNG | None = None
          """The contents of the block."""
  
          self.orelse: NodeNG | None = None
          """The contents of the ``else`` block."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self,
          test: NodeNG | None = None,
          body: NodeNG | None = None,
          orelse: NodeNG | None = None,
      ) -> None:
          """Do some setup after initialisation.
  
          :param test: The condition that the statement tests.
  
          :param body: The contents of the block.
  
          :param orelse: The contents of the ``else`` block.
          """
          self.test = test
          self.body = body
          self.orelse = orelse
  
      def get_children(self):
          yield self.test
          yield self.body
          yield self.orelse
  
      def op_left_associative(self):
          # `1 if True else 2 if False else 3` is parsed as
          # `1 if True else (2 if False else 3)`
          return False
  
  
  class Import(mixins.NoChildrenMixin, mixins.ImportFromMixin, Statement):
      """Class representing an :class:`ast.Import` node.
      >>> import astroid
      >>> node = astroid.extract_node('import astroid')
      >>> node
      <Import l.1 at 0x7f23b2e4e5c0>
      """
  
      _other_fields = ("names",)
  
      @decorators.deprecate_default_argument_values(names="list[tuple[str, str | None]]")
      def __init__(
          self,
          names: list[tuple[str, str | None]] | None = None,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param names: The names being imported.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.names: list[tuple[str, str | None]] = names or []
          """The names being imported.
  
          Each entry is a :class:`tuple` of the name being imported,
          and the alias that the name is assigned to (if any).
          """
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
  
  class Index(NodeNG):
      """Class representing an :class:`ast.Index` node.
  
      An :class:`Index` is a simple subscript.
  
      Deprecated since v2.6.0 - Now part of the :class:`Subscript` node.
      Will be removed with the release of v2.7.0
      """
  
  
  class Keyword(NodeNG):
      """Class representing an :class:`ast.keyword` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('function(a_kwarg=True)')
      >>> node
      <Call l.1 at 0x7f23b2e9e320>
      >>> node.keywords
      [<Keyword l.1 at 0x7f23b2e9e9b0>]
      """
  
      _astroid_fields = ("value",)
      _other_fields = ("arg",)
  
      def __init__(
          self,
          arg: str | None = None,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param arg: The argument being assigned to.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.arg: str | None = arg  # can be None
          """The argument being assigned to."""
  
          self.value: NodeNG | None = None
          """The value being assigned to the keyword argument."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, value: NodeNG | None = None) -> None:
          """Do some setup after initialisation.
  
          :param value: The value being assigned to the keyword argument.
          """
          self.value = value
  
      def get_children(self):
          yield self.value
  
  
  class List(BaseContainer):
      """Class representing an :class:`ast.List` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('[1, 2, 3]')
      >>> node
      <List.list l.1 at 0x7f23b2e9e128>
      """
  
      _other_fields = ("ctx",)
  
      def __init__(
          self,
          ctx: Context | None = None,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param ctx: Whether the list is assigned to or loaded from.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.ctx: Context | None = ctx
          """Whether the list is assigned to or loaded from."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      assigned_stmts: ClassVar[AssignedStmtsCall[List]]
      """Returns the assigned statement (non inferred) according to the assignment type.
      See astroid/protocols.py for actual implementation.
      """
  
      def pytype(self):
          """Get the name of the type that this node represents.
  
          :returns: The name of the type.
          :rtype: str
          """
          return "builtins.list"
  
      def getitem(self, index, context=None):
          """Get an item from this node.
  
          :param index: The node to use as a subscript index.
          :type index: Const or Slice
          """
          return _container_getitem(self, self.elts, index, context=context)
  
  
  class Nonlocal(mixins.NoChildrenMixin, Statement):
      """Class representing an :class:`ast.Nonlocal` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
      def function():
          nonlocal var
      ''')
      >>> node
      <FunctionDef.function l.2 at 0x7f23b2e9e208>
      >>> node.body[0]
      <Nonlocal l.3 at 0x7f23b2e9e908>
      """
  
      _other_fields = ("names",)
  
      def __init__(
          self,
          names: list[str],
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param names: The names being declared as not local.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.names: list[str] = names
          """The names being declared as not local."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def _infer_name(self, frame, name):
          return name
  
  
  class Pass(mixins.NoChildrenMixin, Statement):
      """Class representing an :class:`ast.Pass` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('pass')
      >>> node
      <Pass l.1 at 0x7f23b2e9e748>
      """
  
  
  class Raise(Statement):
      """Class representing an :class:`ast.Raise` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('raise RuntimeError("Something bad happened!")')
      >>> node
      <Raise l.1 at 0x7f23b2e9e828>
      """
  
      _astroid_fields = ("exc", "cause")
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.exc: NodeNG | None = None  # can be None
          """What is being raised."""
  
          self.cause: NodeNG | None = None  # can be None
          """The exception being used to raise this one."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self,
          exc: NodeNG | None = None,
          cause: NodeNG | None = None,
      ) -> None:
          """Do some setup after initialisation.
  
          :param exc: What is being raised.
  
          :param cause: The exception being used to raise this one.
          """
          self.exc = exc
          self.cause = cause
  
      def raises_not_implemented(self):
          """Check if this node raises a :class:`NotImplementedError`.
  
          :returns: True if this node raises a :class:`NotImplementedError`,
              False otherwise.
          :rtype: bool
          """
          if not self.exc:
              return False
          return any(
              name.name == "NotImplementedError" for name in self.exc._get_name_nodes()
          )
  
      def get_children(self):
          if self.exc is not None:
              yield self.exc
  
          if self.cause is not None:
              yield self.cause
  
  
  class Return(Statement):
      """Class representing an :class:`ast.Return` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('return True')
      >>> node
      <Return l.1 at 0x7f23b8211908>
      """
  
      _astroid_fields = ("value",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.value: NodeNG | None = None  # can be None
          """The value being returned."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, value: NodeNG | None = None) -> None:
          """Do some setup after initialisation.
  
          :param value: The value being returned.
          """
          self.value = value
  
      def get_children(self):
          if self.value is not None:
              yield self.value
  
      def is_tuple_return(self):
          return isinstance(self.value, Tuple)
  
      def _get_return_nodes_skip_functions(self):
          yield self
  
  
  class Set(BaseContainer):
      """Class representing an :class:`ast.Set` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('{1, 2, 3}')
      >>> node
      <Set.set l.1 at 0x7f23b2e71d68>
      """
  
      def pytype(self):
          """Get the name of the type that this node represents.
  
          :returns: The name of the type.
          :rtype: str
          """
          return "builtins.set"
  
  
  class Slice(NodeNG):
      """Class representing an :class:`ast.Slice` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('things[1:3]')
      >>> node
      <Subscript l.1 at 0x7f23b2e71f60>
      >>> node.slice
      <Slice l.1 at 0x7f23b2e71e80>
      """
  
      _astroid_fields = ("lower", "upper", "step")
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.lower: NodeNG | None = None  # can be None
          """The lower index in the slice."""
  
          self.upper: NodeNG | None = None  # can be None
          """The upper index in the slice."""
  
          self.step: NodeNG | None = None  # can be None
          """The step to take between indexes."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self,
          lower: NodeNG | None = None,
          upper: NodeNG | None = None,
          step: NodeNG | None = None,
      ) -> None:
          """Do some setup after initialisation.
  
          :param lower: The lower index in the slice.
  
          :param upper: The upper index in the slice.
  
          :param step: The step to take between index.
          """
          self.lower = lower
          self.upper = upper
          self.step = step
  
      def _wrap_attribute(self, attr):
          """Wrap the empty attributes of the Slice in a Const node."""
          if not attr:
              const = const_factory(attr)
              const.parent = self
              return const
          return attr
  
      @cached_property
      def _proxied(self):
          builtins = AstroidManager().builtins_module
          return builtins.getattr("slice")[0]
  
      def pytype(self):
          """Get the name of the type that this node represents.
  
          :returns: The name of the type.
          :rtype: str
          """
          return "builtins.slice"
  
      def igetattr(self, attrname, context=None):
          """Infer the possible values of the given attribute on the slice.
  
          :param attrname: The name of the attribute to infer.
          :type attrname: str
  
          :returns: The inferred possible values.
          :rtype: iterable(NodeNG)
          """
          if attrname == "start":
              yield self._wrap_attribute(self.lower)
          elif attrname == "stop":
              yield self._wrap_attribute(self.upper)
          elif attrname == "step":
              yield self._wrap_attribute(self.step)
          else:
              yield from self.getattr(attrname, context=context)
  
      def getattr(self, attrname, context=None):
          return self._proxied.getattr(attrname, context)
  
      def get_children(self):
          if self.lower is not None:
              yield self.lower
  
          if self.upper is not None:
              yield self.upper
  
          if self.step is not None:
              yield self.step
  
  
  class Starred(mixins.ParentAssignTypeMixin, NodeNG):
      """Class representing an :class:`ast.Starred` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('*args')
      >>> node
      <Starred l.1 at 0x7f23b2e41978>
      """
  
      _astroid_fields = ("value",)
      _other_fields = ("ctx",)
  
      def __init__(
          self,
          ctx: Context | None = None,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param ctx: Whether the list is assigned to or loaded from.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.value: NodeNG | None = None
          """What is being unpacked."""
  
          self.ctx: Context | None = ctx
          """Whether the starred item is assigned to or loaded from."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, value: NodeNG | None = None) -> None:
          """Do some setup after initialisation.
  
          :param value: What is being unpacked.
          """
          self.value = value
  
      assigned_stmts: ClassVar[AssignedStmtsCall[Starred]]
      """Returns the assigned statement (non inferred) according to the assignment type.
      See astroid/protocols.py for actual implementation.
      """
  
      def get_children(self):
          yield self.value
  
  
  class Subscript(NodeNG):
      """Class representing an :class:`ast.Subscript` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('things[1:3]')
      >>> node
      <Subscript l.1 at 0x7f23b2e71f60>
      """
  
      _astroid_fields = ("value", "slice")
      _other_fields = ("ctx",)
  
      def __init__(
          self,
          ctx: Context | None = None,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param ctx: Whether the subscripted item is assigned to or loaded from.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.value: NodeNG | None = None
          """What is being indexed."""
  
          self.slice: NodeNG | None = None
          """The slice being used to lookup."""
  
          self.ctx: Context | None = ctx
          """Whether the subscripted item is assigned to or loaded from."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      # pylint: disable=redefined-builtin; had to use the same name as builtin ast module.
      def postinit(
          self, value: NodeNG | None = None, slice: NodeNG | None = None
      ) -> None:
          """Do some setup after initialisation.
  
          :param value: What is being indexed.
  
          :param slice: The slice being used to lookup.
          """
          self.value = value
          self.slice = slice
  
      def get_children(self):
          yield self.value
          yield self.slice
  
  
  class TryExcept(mixins.MultiLineBlockMixin, mixins.BlockRangeMixIn, Statement):
      """Class representing an :class:`ast.TryExcept` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
          try:
              do_something()
          except Exception as error:
              print("Error!")
          ''')
      >>> node
      <TryExcept l.2 at 0x7f23b2e9d908>
      """
  
      _astroid_fields = ("body", "handlers", "orelse")
      _multi_line_block_fields = ("body", "handlers", "orelse")
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.body: list[NodeNG] = []
          """The contents of the block to catch exceptions from."""
  
          self.handlers: list[ExceptHandler] = []
          """The exception handlers."""
  
          self.orelse: list[NodeNG] = []
          """The contents of the ``else`` block."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self,
          body: list[NodeNG] | None = None,
          handlers: list[ExceptHandler] | None = None,
          orelse: list[NodeNG] | None = None,
      ) -> None:
          """Do some setup after initialisation.
  
          :param body: The contents of the block to catch exceptions from.
  
          :param handlers: The exception handlers.
  
          :param orelse: The contents of the ``else`` block.
          """
          if body is not None:
              self.body = body
          if handlers is not None:
              self.handlers = handlers
          if orelse is not None:
              self.orelse = orelse
  
      def _infer_name(self, frame, name):
          return name
  
      def block_range(self, lineno):
          """Get a range from the given line number to where this node ends.
  
          :param lineno: The line number to start the range at.
          :type lineno: int
  
          :returns: The range of line numbers that this node belongs to,
              starting at the given line number.
          :rtype: tuple(int, int)
          """
          last = None
          for exhandler in self.handlers:
              if exhandler.type and lineno == exhandler.type.fromlineno:
                  return lineno, lineno
              if exhandler.body[0].fromlineno <= lineno <= exhandler.body[-1].tolineno:
                  return lineno, exhandler.body[-1].tolineno
              if last is None:
                  last = exhandler.body[0].fromlineno - 1
          return self._elsed_block_range(lineno, self.orelse, last)
  
      def get_children(self):
          yield from self.body
  
          yield from self.handlers or ()
          yield from self.orelse or ()
  
  
  class TryFinally(mixins.MultiLineBlockMixin, mixins.BlockRangeMixIn, Statement):
      """Class representing an :class:`ast.TryFinally` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
      try:
          do_something()
      except Exception as error:
          print("Error!")
      finally:
          print("Cleanup!")
      ''')
      >>> node
      <TryFinally l.2 at 0x7f23b2e41d68>
      """
  
      _astroid_fields = ("body", "finalbody")
      _multi_line_block_fields = ("body", "finalbody")
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.body: list[NodeNG | TryExcept] = []
          """The try-except that the finally is attached to."""
  
          self.finalbody: list[NodeNG] = []
          """The contents of the ``finally`` block."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self,
          body: list[NodeNG | TryExcept] | None = None,
          finalbody: list[NodeNG] | None = None,
      ) -> None:
          """Do some setup after initialisation.
  
          :param body: The try-except that the finally is attached to.
  
          :param finalbody: The contents of the ``finally`` block.
          """
          if body is not None:
              self.body = body
          if finalbody is not None:
              self.finalbody = finalbody
  
      def block_range(self, lineno):
          """Get a range from the given line number to where this node ends.
  
          :param lineno: The line number to start the range at.
          :type lineno: int
  
          :returns: The range of line numbers that this node belongs to,
              starting at the given line number.
          :rtype: tuple(int, int)
          """
          child = self.body[0]
          # py2.5 try: except: finally:
          if (
              isinstance(child, TryExcept)
              and child.fromlineno == self.fromlineno
              and child.tolineno >= lineno > self.fromlineno
          ):
              return child.block_range(lineno)
          return self._elsed_block_range(lineno, self.finalbody)
  
      def get_children(self):
          yield from self.body
          yield from self.finalbody
  
  
  class Tuple(BaseContainer):
      """Class representing an :class:`ast.Tuple` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('(1, 2, 3)')
      >>> node
      <Tuple.tuple l.1 at 0x7f23b2e41780>
      """
  
      _other_fields = ("ctx",)
  
      def __init__(
          self,
          ctx: Context | None = None,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param ctx: Whether the tuple is assigned to or loaded from.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.ctx: Context | None = ctx
          """Whether the tuple is assigned to or loaded from."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      assigned_stmts: ClassVar[AssignedStmtsCall[Tuple]]
      """Returns the assigned statement (non inferred) according to the assignment type.
      See astroid/protocols.py for actual implementation.
      """
  
      def pytype(self):
          """Get the name of the type that this node represents.
  
          :returns: The name of the type.
          :rtype: str
          """
          return "builtins.tuple"
  
      def getitem(self, index, context=None):
          """Get an item from this node.
  
          :param index: The node to use as a subscript index.
          :type index: Const or Slice
          """
          return _container_getitem(self, self.elts, index, context=context)
  
  
  class UnaryOp(NodeNG):
      """Class representing an :class:`ast.UnaryOp` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('-5')
      >>> node
      <UnaryOp l.1 at 0x7f23b2e4e198>
      """
  
      _astroid_fields = ("operand",)
      _other_fields = ("op",)
  
      @decorators.deprecate_default_argument_values(op="str")
      def __init__(
          self,
          op: str | None = None,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param op: The operator.
  
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.op: str | None = op
          """The operator."""
  
          self.operand: NodeNG | None = None
          """What the unary operator is applied to."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, operand: NodeNG | None = None) -> None:
          """Do some setup after initialisation.
  
          :param operand: What the unary operator is applied to.
          """
          self.operand = operand
  
      # This is set by inference.py
      def _infer_unaryop(self, context=None):
          raise NotImplementedError
  
      def type_errors(self, context=None):
          """Get a list of type errors which can occur during inference.
  
          Each TypeError is represented by a :class:`BadBinaryOperationMessage`,
          which holds the original exception.
  
          :returns: The list of possible type errors.
          :rtype: list(BadBinaryOperationMessage)
          """
          try:
              results = self._infer_unaryop(context=context)
              return [
                  result
                  for result in results
                  if isinstance(result, util.BadUnaryOperationMessage)
              ]
          except InferenceError:
              return []
  
      def get_children(self):
          yield self.operand
  
      def op_precedence(self):
          if self.op == "not":
              return OP_PRECEDENCE[self.op]
  
          return super().op_precedence()
  
  
  class While(mixins.MultiLineBlockMixin, mixins.BlockRangeMixIn, Statement):
      """Class representing an :class:`ast.While` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
      while condition():
          print("True")
      ''')
      >>> node
      <While l.2 at 0x7f23b2e4e390>
      """
  
      _astroid_fields = ("test", "body", "orelse")
      _multi_line_block_fields = ("body", "orelse")
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.test: NodeNG | None = None
          """The condition that the loop tests."""
  
          self.body: list[NodeNG] = []
          """The contents of the loop."""
  
          self.orelse: list[NodeNG] = []
          """The contents of the ``else`` block."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self,
          test: NodeNG | None = None,
          body: list[NodeNG] | None = None,
          orelse: list[NodeNG] | None = None,
      ) -> None:
          """Do some setup after initialisation.
  
          :param test: The condition that the loop tests.
  
          :param body: The contents of the loop.
  
          :param orelse: The contents of the ``else`` block.
          """
          self.test = test
          if body is not None:
              self.body = body
          if orelse is not None:
              self.orelse = orelse
  
      @cached_property
      def blockstart_tolineno(self):
          """The line on which the beginning of this block ends.
  
          :type: int
          """
          return self.test.tolineno
  
      def block_range(self, lineno):
          """Get a range from the given line number to where this node ends.
  
          :param lineno: The line number to start the range at.
          :type lineno: int
  
          :returns: The range of line numbers that this node belongs to,
              starting at the given line number.
          :rtype: tuple(int, int)
          """
          return self._elsed_block_range(lineno, self.orelse)
  
      def get_children(self):
          yield self.test
  
          yield from self.body
          yield from self.orelse
  
      def _get_yield_nodes_skip_lambdas(self):
          """A While node can contain a Yield node in the test"""
          yield from self.test._get_yield_nodes_skip_lambdas()
          yield from super()._get_yield_nodes_skip_lambdas()
  
  
  class With(
      mixins.MultiLineBlockMixin,
      mixins.BlockRangeMixIn,
      mixins.AssignTypeMixin,
      Statement,
  ):
      """Class representing an :class:`ast.With` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
      with open(file_path) as file_:
          print(file_.read())
      ''')
      >>> node
      <With l.2 at 0x7f23b2e4e710>
      """
  
      _astroid_fields = ("items", "body")
      _other_other_fields = ("type_annotation",)
      _multi_line_block_fields = ("body",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.items: list[tuple[NodeNG, NodeNG | None]] = []
          """The pairs of context managers and the names they are assigned to."""
  
          self.body: list[NodeNG] = []
          """The contents of the ``with`` block."""
  
          self.type_annotation: NodeNG | None = None  # can be None
          """If present, this will contain the type annotation passed by a type comment"""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self,
          items: list[tuple[NodeNG, NodeNG | None]] | None = None,
          body: list[NodeNG] | None = None,
          type_annotation: NodeNG | None = None,
      ) -> None:
          """Do some setup after initialisation.
  
          :param items: The pairs of context managers and the names
              they are assigned to.
  
          :param body: The contents of the ``with`` block.
          """
          if items is not None:
              self.items = items
          if body is not None:
              self.body = body
          self.type_annotation = type_annotation
  
      assigned_stmts: ClassVar[AssignedStmtsCall[With]]
      """Returns the assigned statement (non inferred) according to the assignment type.
      See astroid/protocols.py for actual implementation.
      """
  
      @cached_property
      def blockstart_tolineno(self):
          """The line on which the beginning of this block ends.
  
          :type: int
          """
          return self.items[-1][0].tolineno
  
      def get_children(self):
          """Get the child nodes below this node.
  
          :returns: The children.
          :rtype: iterable(NodeNG)
          """
          for expr, var in self.items:
              yield expr
              if var:
                  yield var
          yield from self.body
  
  
  class AsyncWith(With):
      """Asynchronous ``with`` built with the ``async`` keyword."""
  
  
  class Yield(NodeNG):
      """Class representing an :class:`ast.Yield` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('yield True')
      >>> node
      <Yield l.1 at 0x7f23b2e4e5f8>
      """
  
      _astroid_fields = ("value",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.value: NodeNG | None = None  # can be None
          """The value to yield."""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, value: NodeNG | None = None) -> None:
          """Do some setup after initialisation.
  
          :param value: The value to yield.
          """
          self.value = value
  
      def get_children(self):
          if self.value is not None:
              yield self.value
  
      def _get_yield_nodes_skip_lambdas(self):
          yield self
  
  
  class YieldFrom(Yield):  # TODO value is required, not optional
      """Class representing an :class:`ast.YieldFrom` node."""
  
  
  class DictUnpack(mixins.NoChildrenMixin, NodeNG):
      """Represents the unpacking of dicts into dicts using :pep:`448`."""
  
  
  class FormattedValue(NodeNG):
      """Class representing an :class:`ast.FormattedValue` node.
  
      Represents a :pep:`498` format string.
  
      >>> import astroid
      >>> node = astroid.extract_node('f"Format {type_}"')
      >>> node
      <JoinedStr l.1 at 0x7f23b2e4ed30>
      >>> node.values
      [<Const.str l.1 at 0x7f23b2e4eda0>, <FormattedValue l.1 at 0x7f23b2e4edd8>]
      """
  
      _astroid_fields = ("value", "format_spec")
      _other_fields = ("conversion",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.value: NodeNG
          """The value to be formatted into the string."""
  
          self.conversion: int | None = None  # can be None
          """The type of formatting to be applied to the value.
  
          .. seealso::
              :class:`ast.FormattedValue`
          """
  
          self.format_spec: NodeNG | None = None  # can be None
          """The formatting to be applied to the value.
  
          .. seealso::
              :class:`ast.FormattedValue`
  
          :type: JoinedStr or None
          """
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self,
          value: NodeNG,
          conversion: int | None = None,
          format_spec: NodeNG | None = None,
      ) -> None:
          """Do some setup after initialisation.
  
          :param value: The value to be formatted into the string.
  
          :param conversion: The type of formatting to be applied to the value.
  
          :param format_spec: The formatting to be applied to the value.
          :type format_spec: JoinedStr or None
          """
          self.value = value
          self.conversion = conversion
          self.format_spec = format_spec
  
      def get_children(self):
          yield self.value
  
          if self.format_spec is not None:
              yield self.format_spec
  
  
  class JoinedStr(NodeNG):
      """Represents a list of string expressions to be joined.
  
      >>> import astroid
      >>> node = astroid.extract_node('f"Format {type_}"')
      >>> node
      <JoinedStr l.1 at 0x7f23b2e4ed30>
      """
  
      _astroid_fields = ("values",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.values: list[NodeNG] = []
          """The string expressions to be joined.
  
          :type: list(FormattedValue or Const)
          """
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, values: list[NodeNG] | None = None) -> None:
          """Do some setup after initialisation.
  
          :param value: The string expressions to be joined.
  
          :type: list(FormattedValue or Const)
          """
          if values is not None:
              self.values = values
  
      def get_children(self):
          yield from self.values
  
  
  class NamedExpr(mixins.AssignTypeMixin, NodeNG):
      """Represents the assignment from the assignment expression
  
      >>> import astroid
      >>> module = astroid.parse('if a := 1: pass')
      >>> module.body[0].test
      <NamedExpr l.1 at 0x7f23b2e4ed30>
      """
  
      _astroid_fields = ("target", "value")
  
      optional_assign = True
      """Whether this node optionally assigns a variable.
  
      Since NamedExpr are not always called they do not always assign."""
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          """
          :param lineno: The line that this node appears on in the source code.
  
          :param col_offset: The column that this node appears on in the
              source code.
  
          :param parent: The parent node in the syntax tree.
  
          :param end_lineno: The last line this node appears on in the source code.
  
          :param end_col_offset: The end column this node appears on in the
              source code. Note: This is after the last symbol.
          """
          self.target: NodeNG
          """The assignment target
  
          :type: Name
          """
  
          self.value: NodeNG
          """The value that gets assigned in the expression"""
  
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, target: NodeNG, value: NodeNG) -> None:
          self.target = target
          self.value = value
  
      assigned_stmts: ClassVar[AssignedStmtsCall[NamedExpr]]
      """Returns the assigned statement (non inferred) according to the assignment type.
      See astroid/protocols.py for actual implementation.
      """
  
      def frame(
          self, *, future: Literal[None, True] = None
      ) -> nodes.FunctionDef | nodes.Module | nodes.ClassDef | nodes.Lambda:
          """The first parent frame node.
  
          A frame node is a :class:`Module`, :class:`FunctionDef`,
          or :class:`ClassDef`.
  
          :returns: The first parent frame node.
          """
          if not self.parent:
              raise ParentMissingError(target=self)
  
          # For certain parents NamedExpr evaluate to the scope of the parent
          if isinstance(self.parent, (Arguments, Keyword, Comprehension)):
              if not self.parent.parent:
                  raise ParentMissingError(target=self.parent)
              if not self.parent.parent.parent:
                  raise ParentMissingError(target=self.parent.parent)
              return self.parent.parent.parent.frame(future=True)
  
          return self.parent.frame(future=True)
  
      def scope(self) -> LocalsDictNodeNG:
          """The first parent node defining a new scope.
          These can be Module, FunctionDef, ClassDef, Lambda, or GeneratorExp nodes.
  
          :returns: The first parent scope node.
          """
          if not self.parent:
              raise ParentMissingError(target=self)
  
          # For certain parents NamedExpr evaluate to the scope of the parent
          if isinstance(self.parent, (Arguments, Keyword, Comprehension)):
              if not self.parent.parent:
                  raise ParentMissingError(target=self.parent)
              if not self.parent.parent.parent:
                  raise ParentMissingError(target=self.parent.parent)
              return self.parent.parent.parent.scope()
  
          return self.parent.scope()
  
      def set_local(self, name: str, stmt: AssignName) -> None:
          """Define that the given name is declared in the given statement node.
          NamedExpr's in Arguments, Keyword or Comprehension are evaluated in their
          parent's parent scope. So we add to their frame's locals.
  
          .. seealso:: :meth:`scope`
  
          :param name: The name that is being defined.
  
          :param stmt: The statement that defines the given name.
          """
          self.frame(future=True).set_local(name, stmt)
  
  
  class Unknown(mixins.AssignTypeMixin, NodeNG):
      """This node represents a node in a constructed AST where
      introspection is not possible.  At the moment, it's only used in
      the args attribute of FunctionDef nodes where function signature
      introspection failed.
      """
  
      name = "Unknown"
  
      def qname(self):
          return "Unknown"
  
      def _infer(self, context=None, **kwargs):
          """Inference on an Unknown node immediately terminates."""
          yield util.Uninferable
  
  
  class EvaluatedObject(NodeNG):
      """Contains an object that has already been inferred
  
      This class is useful to pre-evaluate a particular node,
      with the resulting class acting as the non-evaluated node.
      """
  
      name = "EvaluatedObject"
      _astroid_fields = ("original",)
      _other_fields = ("value",)
  
      def __init__(
          self, original: NodeNG, value: NodeNG | type[util.Uninferable]
      ) -> None:
          self.original: NodeNG = original
          """The original node that has already been evaluated"""
  
          self.value: NodeNG | type[util.Uninferable] = value
          """The inferred value"""
  
          super().__init__(
              lineno=self.original.lineno,
              col_offset=self.original.col_offset,
              parent=self.original.parent,
          )
  
      def _infer(
          self, context: InferenceContext | None = None
      ) -> Iterator[NodeNG | type[util.Uninferable]]:
          yield self.value
  
  
  # Pattern matching #######################################################
  
  
  class Match(Statement):
      """Class representing a :class:`ast.Match` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
      match x:
          case 200:
              ...
          case _:
              ...
      ''')
      >>> node
      <Match l.2 at 0x10c24e170>
      """
  
      _astroid_fields = ("subject", "cases")
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          self.subject: NodeNG
          self.cases: list[MatchCase]
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self,
          *,
          subject: NodeNG,
          cases: list[MatchCase],
      ) -> None:
          self.subject = subject
          self.cases = cases
  
  
  class Pattern(NodeNG):
      """Base class for all Pattern nodes."""
  
  
  class MatchCase(mixins.MultiLineBlockMixin, NodeNG):
      """Class representing a :class:`ast.match_case` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
      match x:
          case 200:
              ...
      ''')
      >>> node.cases[0]
      <MatchCase l.3 at 0x10c24e590>
      """
  
      _astroid_fields = ("pattern", "guard", "body")
      _multi_line_block_fields = ("body",)
  
      lineno: None
      col_offset: None
      end_lineno: None
      end_col_offset: None
  
      def __init__(self, *, parent: NodeNG | None = None) -> None:
          self.pattern: Pattern
          self.guard: NodeNG | None
          self.body: list[NodeNG]
          super().__init__(parent=parent)
  
      def postinit(
          self,
          *,
          pattern: Pattern,
          guard: NodeNG | None,
          body: list[NodeNG],
      ) -> None:
          self.pattern = pattern
          self.guard = guard
          self.body = body
  
  
  class MatchValue(Pattern):
      """Class representing a :class:`ast.MatchValue` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
      match x:
          case 200:
              ...
      ''')
      >>> node.cases[0].pattern
      <MatchValue l.3 at 0x10c24e200>
      """
  
      _astroid_fields = ("value",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          self.value: NodeNG
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, *, value: NodeNG) -> None:
          self.value = value
  
  
  class MatchSingleton(Pattern):
      """Class representing a :class:`ast.MatchSingleton` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
      match x:
          case True:
              ...
          case False:
              ...
          case None:
              ...
      ''')
      >>> node.cases[0].pattern
      <MatchSingleton l.3 at 0x10c2282e0>
      >>> node.cases[1].pattern
      <MatchSingleton l.5 at 0x10c228af0>
      >>> node.cases[2].pattern
      <MatchSingleton l.7 at 0x10c229f90>
      """
  
      _other_fields = ("value",)
  
      def __init__(
          self,
          *,
          value: Literal[True, False, None],
          lineno: int | None = None,
          col_offset: int | None = None,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
          parent: NodeNG | None = None,
      ) -> None:
          self.value = value
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
  
  class MatchSequence(Pattern):
      """Class representing a :class:`ast.MatchSequence` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
      match x:
          case [1, 2]:
              ...
          case (1, 2, *_):
              ...
      ''')
      >>> node.cases[0].pattern
      <MatchSequence l.3 at 0x10ca80d00>
      >>> node.cases[1].pattern
      <MatchSequence l.5 at 0x10ca80b20>
      """
  
      _astroid_fields = ("patterns",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          self.patterns: list[Pattern]
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, *, patterns: list[Pattern]) -> None:
          self.patterns = patterns
  
  
  class MatchMapping(mixins.AssignTypeMixin, Pattern):
      """Class representing a :class:`ast.MatchMapping` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
      match x:
          case {1: "Hello", 2: "World", 3: _, **rest}:
              ...
      ''')
      >>> node.cases[0].pattern
      <MatchMapping l.3 at 0x10c8a8850>
      """
  
      _astroid_fields = ("keys", "patterns", "rest")
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          self.keys: list[NodeNG]
          self.patterns: list[Pattern]
          self.rest: AssignName | None
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self,
          *,
          keys: list[NodeNG],
          patterns: list[Pattern],
          rest: AssignName | None,
      ) -> None:
          self.keys = keys
          self.patterns = patterns
          self.rest = rest
  
      assigned_stmts: ClassVar[
          Callable[
              [
                  MatchMapping,
                  AssignName,
                  InferenceContext | None,
                  None,
              ],
              Generator[NodeNG, None, None],
          ]
      ]
      """Returns the assigned statement (non inferred) according to the assignment type.
      See astroid/protocols.py for actual implementation.
      """
  
  
  class MatchClass(Pattern):
      """Class representing a :class:`ast.MatchClass` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
      match x:
          case Point2D(0, 0):
              ...
          case Point3D(x=0, y=0, z=0):
              ...
      ''')
      >>> node.cases[0].pattern
      <MatchClass l.3 at 0x10ca83940>
      >>> node.cases[1].pattern
      <MatchClass l.5 at 0x10ca80880>
      """
  
      _astroid_fields = ("cls", "patterns", "kwd_patterns")
      _other_fields = ("kwd_attrs",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          self.cls: NodeNG
          self.patterns: list[Pattern]
          self.kwd_attrs: list[str]
          self.kwd_patterns: list[Pattern]
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self,
          *,
          cls: NodeNG,
          patterns: list[Pattern],
          kwd_attrs: list[str],
          kwd_patterns: list[Pattern],
      ) -> None:
          self.cls = cls
          self.patterns = patterns
          self.kwd_attrs = kwd_attrs
          self.kwd_patterns = kwd_patterns
  
  
  class MatchStar(mixins.AssignTypeMixin, Pattern):
      """Class representing a :class:`ast.MatchStar` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
      match x:
          case [1, *_]:
              ...
      ''')
      >>> node.cases[0].pattern.patterns[1]
      <MatchStar l.3 at 0x10ca809a0>
      """
  
      _astroid_fields = ("name",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          self.name: AssignName | None
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, *, name: AssignName | None) -> None:
          self.name = name
  
      assigned_stmts: ClassVar[
          Callable[
              [
                  MatchStar,
                  AssignName,
                  InferenceContext | None,
                  None,
              ],
              Generator[NodeNG, None, None],
          ]
      ]
      """Returns the assigned statement (non inferred) according to the assignment type.
      See astroid/protocols.py for actual implementation.
      """
  
  
  class MatchAs(mixins.AssignTypeMixin, Pattern):
      """Class representing a :class:`ast.MatchAs` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
      match x:
          case [1, a]:
              ...
          case {'key': b}:
              ...
          case Point2D(0, 0) as c:
              ...
          case d:
              ...
      ''')
      >>> node.cases[0].pattern.patterns[1]
      <MatchAs l.3 at 0x10d0b2da0>
      >>> node.cases[1].pattern.patterns[0]
      <MatchAs l.5 at 0x10d0b2920>
      >>> node.cases[2].pattern
      <MatchAs l.7 at 0x10d0b06a0>
      >>> node.cases[3].pattern
      <MatchAs l.9 at 0x10d09b880>
      """
  
      _astroid_fields = ("pattern", "name")
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          self.pattern: Pattern | None
          self.name: AssignName | None
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(
          self,
          *,
          pattern: Pattern | None,
          name: AssignName | None,
      ) -> None:
          self.pattern = pattern
          self.name = name
  
      assigned_stmts: ClassVar[
          Callable[
              [
                  MatchAs,
                  AssignName,
                  InferenceContext | None,
                  None,
              ],
              Generator[NodeNG, None, None],
          ]
      ]
      """Returns the assigned statement (non inferred) according to the assignment type.
      See astroid/protocols.py for actual implementation.
      """
  
  
  class MatchOr(Pattern):
      """Class representing a :class:`ast.MatchOr` node.
  
      >>> import astroid
      >>> node = astroid.extract_node('''
      match x:
          case 400 | 401 | 402:
              ...
      ''')
      >>> node.cases[0].pattern
      <MatchOr l.3 at 0x10d0b0b50>
      """
  
      _astroid_fields = ("patterns",)
  
      def __init__(
          self,
          lineno: int | None = None,
          col_offset: int | None = None,
          parent: NodeNG | None = None,
          *,
          end_lineno: int | None = None,
          end_col_offset: int | None = None,
      ) -> None:
          self.patterns: list[Pattern]
          super().__init__(
              lineno=lineno,
              col_offset=col_offset,
              end_lineno=end_lineno,
              end_col_offset=end_col_offset,
              parent=parent,
          )
  
      def postinit(self, *, patterns: list[Pattern]) -> None:
          self.patterns = patterns
  
  
  # constants ##############################################################
  
  CONST_CLS = {
      list: List,
      tuple: Tuple,
      dict: Dict,
      set: Set,
      type(None): Const,
      type(NotImplemented): Const,
      type(...): Const,
  }
  
  
  def _update_const_classes():
      """update constant classes, so the keys of CONST_CLS can be reused"""
      klasses = (bool, int, float, complex, str, bytes)
      for kls in klasses:
          CONST_CLS[kls] = Const
  
  
  _update_const_classes()
  
  
  def _two_step_initialization(cls, value):
      instance = cls()
      instance.postinit(value)
      return instance
  
  
  def _dict_initialization(cls, value):
      if isinstance(value, dict):
          value = tuple(value.items())
      return _two_step_initialization(cls, value)
  
  
  _CONST_CLS_CONSTRUCTORS = {
      List: _two_step_initialization,
      Tuple: _two_step_initialization,
      Dict: _dict_initialization,
      Set: _two_step_initialization,
      Const: lambda cls, value: cls(value),
  }
  
  
  def const_factory(value):
      """return an astroid node for a python value"""
      # XXX we should probably be stricter here and only consider stuff in
      # CONST_CLS or do better treatment: in case where value is not in CONST_CLS,
      # we should rather recall the builder on this value than returning an empty
      # node (another option being that const_factory shouldn't be called with something
      # not in CONST_CLS)
      assert not isinstance(value, NodeNG)
  
      # Hack for ignoring elements of a sequence
      # or a mapping, in order to avoid transforming
      # each element to an AST. This is fixed in 2.0
      # and this approach is a temporary hack.
      if isinstance(value, (list, set, tuple, dict)):
          elts = []
      else:
          elts = value
  
      try:
          initializer_cls = CONST_CLS[value.__class__]
          initializer = _CONST_CLS_CONSTRUCTORS[initializer_cls]
          return initializer(initializer_cls, elts)
      except (KeyError, AttributeError):
          node = EmptyNode()
          node.object = value
          return node
  
  ```
  --- END FILE ---
  
  Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.
  
  Every *SEARCH/REPLACE* edit must use this format:
  1. The file path
  2. The start of search block: <<<<<<< SEARCH
  3. A contiguous chunk of lines to search for in the existing source code
  4. The dividing line: =======
  5. The lines to replace into the source code
  6. The end of the replace block: >>>>>>> REPLACE
  
  Here is an example:
  
  ```python
  ### mathweb/flask/app.py
  <<<<<<< SEARCH
  from flask import Flask
  =======
  import math
  from flask import Flask
  >>>>>>> REPLACE
  ```
  
  Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
  Wrap the *SEARCH/REPLACE* edit in blocks ```python...```.
  
messages.role: user
verification_info: {"file_context": {"astroid/nodes/node_classes.py": "# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html\n# For details: https://github.com/PyCQA/astroid/blob/main/LICENSE\n# Copyright (c) https://github.com/PyCQA/astroid/blob/main/CONTRIBUTORS.txt\n\n\"\"\"Module for some node classes. More nodes in scoped_nodes.py\"\"\"\n\nfrom __future__ import annotations\n\nimport abc\nimport itertools\nimport sys\nimport typing\nimport warnings\nfrom collections.abc import Generator, Iterator\nfrom functools import lru_cache\nfrom typing import TYPE_CHECKING, Any, Callable, ClassVar, Optional, TypeVar, Union\n\nfrom astroid import decorators, mixins, util\nfrom astroid.bases import Instance, _infer_stmts\nfrom astroid.const import Context\nfrom astroid.context import InferenceContext\nfrom astroid.exceptions import (\n    AstroidIndexError,\n    AstroidTypeError,\n    InferenceError,\n    NoDefault,\n    ParentMissingError,\n)\nfrom astroid.manager import AstroidManager\nfrom astroid.nodes.const import OP_PRECEDENCE\nfrom astroid.nodes.node_ng import NodeNG\n\nif sys.version_info >= (3, 8):\n    from typing import Literal\nelse:\n    from typing_extensions import Literal\n\nif TYPE_CHECKING:\n    from astroid import nodes\n    from astroid.nodes import LocalsDictNodeNG\n\nif sys.version_info >= (3, 8):\n    from functools import cached_property\nelse:\n    from astroid.decorators import cachedproperty as cached_property\n\n\ndef _is_const(value):\n    return isinstance(value, tuple(CONST_CLS))\n\n\n_NodesT = TypeVar(\"_NodesT\", bound=NodeNG)\n\nAssignedStmtsPossibleNode = Union[\"List\", \"Tuple\", \"AssignName\", \"AssignAttr\", None]\nAssignedStmtsCall = Callable[\n    [\n        _NodesT,\n        AssignedStmtsPossibleNode,\n        Optional[InferenceContext],\n        Optional[typing.List[int]],\n    ],\n    Any,\n]\n\n\n@decorators.raise_if_nothing_inferred\ndef unpack_infer(stmt, context=None):\n    \"\"\"recursively generate nodes inferred by the given statement.\n    If the inferred value is a list or a tuple, recurse on the elements\n    \"\"\"\n    if isinstance(stmt, (List, Tuple)):\n        for elt in stmt.elts:\n            if elt is util.Uninferable:\n                yield elt\n                continue\n            yield from unpack_infer(elt, context)\n        return dict(node=stmt, context=context)\n    # if inferred is a final node, return it and stop\n    inferred = next(stmt.infer(context), util.Uninferable)\n    if inferred is stmt:\n        yield inferred\n        return dict(node=stmt, context=context)\n    # else, infer recursively, except Uninferable object that should be returned as is\n    for inferred in stmt.infer(context):\n        if inferred is util.Uninferable:\n            yield inferred\n        else:\n            yield from unpack_infer(inferred, context)\n\n    return dict(node=stmt, context=context)\n\n\ndef are_exclusive(stmt1, stmt2, exceptions: list[str] | None = None) -> bool:\n    \"\"\"return true if the two given statements are mutually exclusive\n\n    `exceptions` may be a list of exception names. If specified, discard If\n    branches and check one of the statement is in an exception handler catching\n    one of the given exceptions.\n\n    algorithm :\n     1) index stmt1's parents\n     2) climb among stmt2's parents until we find a common parent\n     3) if the common parent is a If or TryExcept statement, look if nodes are\n        in exclusive branches\n    \"\"\"\n    # index stmt1's parents\n    stmt1_parents = {}\n    children = {}\n    previous = stmt1\n    for node in stmt1.node_ancestors():\n        stmt1_parents[node] = 1\n        children[node] = previous\n        previous = node\n    # climb among stmt2's parents until we find a common parent\n    previous = stmt2\n    for node in stmt2.node_ancestors():\n        if node in stmt1_parents:\n            # if the common parent is a If or TryExcept statement, look if\n            # nodes are in exclusive branches\n            if isinstance(node, If) and exceptions is None:\n                if (\n                    node.locate_child(previous)[1]\n                    is not node.locate_child(children[node])[1]\n                ):\n                    return True\n            elif isinstance(node, TryExcept):\n                c2attr, c2node = node.locate_child(previous)\n                c1attr, c1node = node.locate_child(children[node])\n                if c1node is not c2node:\n                    first_in_body_caught_by_handlers = (\n                        c2attr == \"handlers\"\n                        and c1attr == \"body\"\n                        and previous.catch(exceptions)\n                    )\n                    second_in_body_caught_by_handlers = (\n                        c2attr == \"body\"\n                        and c1attr == \"handlers\"\n                        and children[node].catch(exceptions)\n                    )\n                    first_in_else_other_in_handlers = (\n                        c2attr == \"handlers\" and c1attr == \"orelse\"\n                    )\n                    second_in_else_other_in_handlers = (\n                        c2attr == \"orelse\" and c1attr == \"handlers\"\n                    )\n                    if any(\n                        (\n                            first_in_body_caught_by_handlers,\n                            second_in_body_caught_by_handlers,\n                            first_in_else_other_in_handlers,\n                            second_in_else_other_in_handlers,\n                        )\n                    ):\n                        return True\n                elif c2attr == \"handlers\" and c1attr == \"handlers\":\n                    return previous is not children[node]\n            return False\n        previous = node\n    return False\n\n\n# getitem() helpers.\n\n_SLICE_SENTINEL = object()\n\n\ndef _slice_value(index, context=None):\n    \"\"\"Get the value of the given slice index.\"\"\"\n\n    if isinstance(index, Const):\n        if isinstance(index.value, (int, type(None))):\n            return index.value\n    elif index is None:\n        return None\n    else:\n        # Try to infer what the index actually is.\n        # Since we can't return all the possible values,\n        # we'll stop at the first possible value.\n        try:\n            inferred = next(index.infer(context=context))\n        except (InferenceError, StopIteration):\n            pass\n        else:\n            if isinstance(inferred, Const):\n                if isinstance(inferred.value, (int, type(None))):\n                    return inferred.value\n\n    # Use a sentinel, because None can be a valid\n    # value that this function can return,\n    # as it is the case for unspecified bounds.\n    return _SLICE_SENTINEL\n\n\ndef _infer_slice(node, context=None):\n    lower = _slice_value(node.lower, context)\n    upper = _slice_value(node.upper, context)\n    step = _slice_value(node.step, context)\n    if all(elem is not _SLICE_SENTINEL for elem in (lower, upper, step)):\n        return slice(lower, upper, step)\n\n    raise AstroidTypeError(\n        message=\"Could not infer slice used in subscript\",\n        node=node,\n        index=node.parent,\n        context=context,\n    )\n\n\ndef _container_getitem(instance, elts, index, context=None):\n    \"\"\"Get a slice or an item, using the given *index*, for the given sequence.\"\"\"\n    try:\n        if isinstance(index, Slice):\n            index_slice = _infer_slice(index, context=context)\n            new_cls = instance.__class__()\n            new_cls.elts = elts[index_slice]\n            new_cls.parent = instance.parent\n            return new_cls\n        if isinstance(index, Const):\n            return elts[index.value]\n    except IndexError as exc:\n        raise AstroidIndexError(\n            message=\"Index {index!s} out of range\",\n            node=instance,\n            index=index,\n            context=context,\n        ) from exc\n    except TypeError as exc:\n        raise AstroidTypeError(\n            message=\"Type error {error!r}\", node=instance, index=index, context=context\n        ) from exc\n\n    raise AstroidTypeError(f\"Could not use {index} as subscript index\")\n\n\nclass Statement(NodeNG):\n    \"\"\"Statement node adding a few attributes\"\"\"\n\n    is_statement = True\n    \"\"\"Whether this node indicates a statement.\"\"\"\n\n    def next_sibling(self):\n        \"\"\"The next sibling statement node.\n\n        :returns: The next sibling statement node.\n        :rtype: NodeNG or None\n        \"\"\"\n        stmts = self.parent.child_sequence(self)\n        index = stmts.index(self)\n        try:\n            return stmts[index + 1]\n        except IndexError:\n            return None\n\n    def previous_sibling(self):\n        \"\"\"The previous sibling statement.\n\n        :returns: The previous sibling statement node.\n        :rtype: NodeNG or None\n        \"\"\"\n        stmts = self.parent.child_sequence(self)\n        index = stmts.index(self)\n        if index >= 1:\n            return stmts[index - 1]\n        return None\n\n\nclass BaseContainer(\n    mixins.ParentAssignTypeMixin, NodeNG, Instance, metaclass=abc.ABCMeta\n):\n    \"\"\"Base class for Set, FrozenSet, Tuple and List.\"\"\"\n\n    _astroid_fields = (\"elts\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.elts: list[NodeNG] = []\n        \"\"\"The elements in the node.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, elts: list[NodeNG]) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param elts: The list of elements the that node contains.\n        \"\"\"\n        self.elts = elts\n\n    @classmethod\n    def from_elements(cls, elts=None):\n        \"\"\"Create a node of this type from the given list of elements.\n\n        :param elts: The list of elements that the node should contain.\n        :type elts: list(NodeNG)\n\n        :returns: A new node containing the given elements.\n        :rtype: NodeNG\n        \"\"\"\n        node = cls()\n        if elts is None:\n            node.elts = []\n        else:\n            node.elts = [const_factory(e) if _is_const(e) else e for e in elts]\n        return node\n\n    def itered(self):\n        \"\"\"An iterator over the elements this node contains.\n\n        :returns: The contents of this node.\n        :rtype: iterable(NodeNG)\n        \"\"\"\n        return self.elts\n\n    def bool_value(self, context=None):\n        \"\"\"Determine the boolean value of this node.\n\n        :returns: The boolean value of this node.\n        :rtype: bool or Uninferable\n        \"\"\"\n        return bool(self.elts)\n\n    @abc.abstractmethod\n    def pytype(self):\n        \"\"\"Get the name of the type that this node represents.\n\n        :returns: The name of the type.\n        :rtype: str\n        \"\"\"\n\n    def get_children(self):\n        yield from self.elts\n\n\nclass LookupMixIn:\n    \"\"\"Mixin to look up a name in the right scope.\"\"\"\n\n    @lru_cache()  # noqa\n    def lookup(self, name: str) -> tuple[str, list[NodeNG]]:\n        \"\"\"Lookup where the given variable is assigned.\n\n        The lookup starts from self's scope. If self is not a frame itself\n        and the name is found in the inner frame locals, statements will be\n        filtered to remove ignorable statements according to self's location.\n\n        :param name: The name of the variable to find assignments for.\n\n        :returns: The scope node and the list of assignments associated to the\n            given name according to the scope where it has been found (locals,\n            globals or builtin).\n        \"\"\"\n        return self.scope().scope_lookup(self, name)\n\n    def ilookup(self, name):\n        \"\"\"Lookup the inferred values of the given variable.\n\n        :param name: The variable name to find values for.\n        :type name: str\n\n        :returns: The inferred values of the statements returned from\n            :meth:`lookup`.\n        :rtype: iterable\n        \"\"\"\n        frame, stmts = self.lookup(name)\n        context = InferenceContext()\n        return _infer_stmts(stmts, context, frame)\n\n\n# Name classes\n\n\nclass AssignName(\n    mixins.NoChildrenMixin, LookupMixIn, mixins.ParentAssignTypeMixin, NodeNG\n):\n    \"\"\"Variation of :class:`ast.Assign` representing assignment to a name.\n\n    An :class:`AssignName` is the name of something that is assigned to.\n    This includes variables defined in a function signature or in a loop.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('variable = range(10)')\n    >>> node\n    <Assign l.1 at 0x7effe1db8550>\n    >>> list(node.get_children())\n    [<AssignName.variable l.1 at 0x7effe1db8748>, <Call l.1 at 0x7effe1db8630>]\n    >>> list(node.get_children())[0].as_string()\n    'variable'\n    \"\"\"\n\n    _other_fields = (\"name\",)\n\n    @decorators.deprecate_default_argument_values(name=\"str\")\n    def __init__(\n        self,\n        name: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param name: The name that is assigned to.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.name: str | None = name\n        \"\"\"The name that is assigned to.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[AssignName]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n\nclass DelName(\n    mixins.NoChildrenMixin, LookupMixIn, mixins.ParentAssignTypeMixin, NodeNG\n):\n    \"\"\"Variation of :class:`ast.Delete` representing deletion of a name.\n\n    A :class:`DelName` is the name of something that is deleted.\n\n    >>> import astroid\n    >>> node = astroid.extract_node(\"del variable #@\")\n    >>> list(node.get_children())\n    [<DelName.variable l.1 at 0x7effe1da4d30>]\n    >>> list(node.get_children())[0].as_string()\n    'variable'\n    \"\"\"\n\n    _other_fields = (\"name\",)\n\n    @decorators.deprecate_default_argument_values(name=\"str\")\n    def __init__(\n        self,\n        name: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param name: The name that is being deleted.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.name: str | None = name\n        \"\"\"The name that is being deleted.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n\nclass Name(mixins.NoChildrenMixin, LookupMixIn, NodeNG):\n    \"\"\"Class representing an :class:`ast.Name` node.\n\n    A :class:`Name` node is something that is named, but not covered by\n    :class:`AssignName` or :class:`DelName`.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('range(10)')\n    >>> node\n    <Call l.1 at 0x7effe1db8710>\n    >>> list(node.get_children())\n    [<Name.range l.1 at 0x7effe1db86a0>, <Const.int l.1 at 0x7effe1db8518>]\n    >>> list(node.get_children())[0].as_string()\n    'range'\n    \"\"\"\n\n    _other_fields = (\"name\",)\n\n    @decorators.deprecate_default_argument_values(name=\"str\")\n    def __init__(\n        self,\n        name: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param name: The name that this node refers to.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.name: str | None = name\n        \"\"\"The name that this node refers to.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def _get_name_nodes(self):\n        yield self\n\n        for child_node in self.get_children():\n            yield from child_node._get_name_nodes()\n\n\nclass Arguments(mixins.AssignTypeMixin, NodeNG):\n    \"\"\"Class representing an :class:`ast.arguments` node.\n\n    An :class:`Arguments` node represents that arguments in a\n    function definition.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('def foo(bar): pass')\n    >>> node\n    <FunctionDef.foo l.1 at 0x7effe1db8198>\n    >>> node.args\n    <Arguments l.1 at 0x7effe1db82e8>\n    \"\"\"\n\n    # Python 3.4+ uses a different approach regarding annotations,\n    # each argument is a new class, _ast.arg, which exposes an\n    # 'annotation' attribute. In astroid though, arguments are exposed\n    # as is in the Arguments node and the only way to expose annotations\n    # is by using something similar with Python 3.3:\n    #  - we expose 'varargannotation' and 'kwargannotation' of annotations\n    #    of varargs and kwargs.\n    #  - we expose 'annotation', a list with annotations for\n    #    for each normal argument. If an argument doesn't have an\n    #    annotation, its value will be None.\n    _astroid_fields = (\n        \"args\",\n        \"defaults\",\n        \"kwonlyargs\",\n        \"posonlyargs\",\n        \"posonlyargs_annotations\",\n        \"kw_defaults\",\n        \"annotations\",\n        \"varargannotation\",\n        \"kwargannotation\",\n        \"kwonlyargs_annotations\",\n        \"type_comment_args\",\n        \"type_comment_kwonlyargs\",\n        \"type_comment_posonlyargs\",\n    )\n\n    _other_fields = (\"vararg\", \"kwarg\")\n\n    lineno: None\n    col_offset: None\n    end_lineno: None\n    end_col_offset: None\n\n    def __init__(\n        self,\n        vararg: str | None = None,\n        kwarg: str | None = None,\n        parent: NodeNG | None = None,\n    ) -> None:\n        \"\"\"\n        :param vararg: The name of the variable length arguments.\n\n        :param kwarg: The name of the variable length keyword arguments.\n\n        :param parent: The parent node in the syntax tree.\n        \"\"\"\n        super().__init__(parent=parent)\n\n        self.vararg: str | None = vararg  # can be None\n        \"\"\"The name of the variable length arguments.\"\"\"\n\n        self.kwarg: str | None = kwarg  # can be None\n        \"\"\"The name of the variable length keyword arguments.\"\"\"\n\n        self.args: list[AssignName] | None\n        \"\"\"The names of the required arguments.\n\n        Can be None if the associated function does not have a retrievable\n        signature and the arguments are therefore unknown.\n        This can happen with (builtin) functions implemented in C that have\n        incomplete signature information.\n        \"\"\"\n        # TODO: Check if other attributes should also be None when\n        # .args is None.\n\n        self.defaults: list[NodeNG]\n        \"\"\"The default values for arguments that can be passed positionally.\"\"\"\n\n        self.kwonlyargs: list[AssignName]\n        \"\"\"The keyword arguments that cannot be passed positionally.\"\"\"\n\n        self.posonlyargs: list[AssignName] = []\n        \"\"\"The arguments that can only be passed positionally.\"\"\"\n\n        self.kw_defaults: list[NodeNG | None]\n        \"\"\"The default values for keyword arguments that cannot be passed positionally.\"\"\"\n\n        self.annotations: list[NodeNG | None]\n        \"\"\"The type annotations of arguments that can be passed positionally.\"\"\"\n\n        self.posonlyargs_annotations: list[NodeNG | None] = []\n        \"\"\"The type annotations of arguments that can only be passed positionally.\"\"\"\n\n        self.kwonlyargs_annotations: list[NodeNG | None] = []\n        \"\"\"The type annotations of arguments that cannot be passed positionally.\"\"\"\n\n        self.type_comment_args: list[NodeNG | None] = []\n        \"\"\"The type annotation, passed by a type comment, of each argument.\n\n        If an argument does not have a type comment,\n        the value for that argument will be None.\n        \"\"\"\n\n        self.type_comment_kwonlyargs: list[NodeNG | None] = []\n        \"\"\"The type annotation, passed by a type comment, of each keyword only argument.\n\n        If an argument does not have a type comment,\n        the value for that argument will be None.\n        \"\"\"\n\n        self.type_comment_posonlyargs: list[NodeNG | None] = []\n        \"\"\"The type annotation, passed by a type comment, of each positional argument.\n\n        If an argument does not have a type comment,\n        the value for that argument will be None.\n        \"\"\"\n\n        self.varargannotation: NodeNG | None = None  # can be None\n        \"\"\"The type annotation for the variable length arguments.\"\"\"\n\n        self.kwargannotation: NodeNG | None = None  # can be None\n        \"\"\"The type annotation for the variable length keyword arguments.\"\"\"\n\n    # pylint: disable=too-many-arguments\n    def postinit(\n        self,\n        args: list[AssignName] | None,\n        defaults: list[NodeNG],\n        kwonlyargs: list[AssignName],\n        kw_defaults: list[NodeNG | None],\n        annotations: list[NodeNG | None],\n        posonlyargs: list[AssignName] | None = None,\n        kwonlyargs_annotations: list[NodeNG | None] | None = None,\n        posonlyargs_annotations: list[NodeNG | None] | None = None,\n        varargannotation: NodeNG | None = None,\n        kwargannotation: NodeNG | None = None,\n        type_comment_args: list[NodeNG | None] | None = None,\n        type_comment_kwonlyargs: list[NodeNG | None] | None = None,\n        type_comment_posonlyargs: list[NodeNG | None] | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param args: The names of the required arguments.\n\n        :param defaults: The default values for arguments that can be passed\n            positionally.\n\n        :param kwonlyargs: The keyword arguments that cannot be passed\n            positionally.\n\n        :param posonlyargs: The arguments that can only be passed\n            positionally.\n\n        :param kw_defaults: The default values for keyword arguments that\n            cannot be passed positionally.\n\n        :param annotations: The type annotations of arguments that can be\n            passed positionally.\n\n        :param kwonlyargs_annotations: The type annotations of arguments that\n            cannot be passed positionally. This should always be passed in\n            Python 3.\n\n        :param posonlyargs_annotations: The type annotations of arguments that\n            can only be passed positionally. This should always be passed in\n            Python 3.\n\n        :param varargannotation: The type annotation for the variable length\n            arguments.\n\n        :param kwargannotation: The type annotation for the variable length\n            keyword arguments.\n\n        :param type_comment_args: The type annotation,\n            passed by a type comment, of each argument.\n\n        :param type_comment_args: The type annotation,\n            passed by a type comment, of each keyword only argument.\n\n        :param type_comment_args: The type annotation,\n            passed by a type comment, of each positional argument.\n        \"\"\"\n        self.args = args\n        self.defaults = defaults\n        self.kwonlyargs = kwonlyargs\n        if posonlyargs is not None:\n            self.posonlyargs = posonlyargs\n        self.kw_defaults = kw_defaults\n        self.annotations = annotations\n        if kwonlyargs_annotations is not None:\n            self.kwonlyargs_annotations = kwonlyargs_annotations\n        if posonlyargs_annotations is not None:\n            self.posonlyargs_annotations = posonlyargs_annotations\n        self.varargannotation = varargannotation\n        self.kwargannotation = kwargannotation\n        if type_comment_args is not None:\n            self.type_comment_args = type_comment_args\n        if type_comment_kwonlyargs is not None:\n            self.type_comment_kwonlyargs = type_comment_kwonlyargs\n        if type_comment_posonlyargs is not None:\n            self.type_comment_posonlyargs = type_comment_posonlyargs\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[Arguments]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def _infer_name(self, frame, name):\n        if self.parent is frame:\n            return name\n        return None\n\n    @cached_property\n    def fromlineno(self):\n        \"\"\"The first line that this node appears on in the source code.\n\n        :type: int or None\n        \"\"\"\n        lineno = super().fromlineno\n        return max(lineno, self.parent.fromlineno or 0)\n\n    @cached_property\n    def arguments(self):\n        \"\"\"Get all the arguments for this node, including positional only and positional and keyword\"\"\"\n        return list(itertools.chain((self.posonlyargs or ()), self.args or ()))\n\n    def format_args(self):\n        \"\"\"Get the arguments formatted as string.\n\n        :returns: The formatted arguments.\n        :rtype: str\n        \"\"\"\n        result = []\n        positional_only_defaults = []\n        positional_or_keyword_defaults = self.defaults\n        if self.defaults:\n            args = self.args or []\n            positional_or_keyword_defaults = self.defaults[-len(args) :]\n            positional_only_defaults = self.defaults[: len(self.defaults) - len(args)]\n\n        if self.posonlyargs:\n            result.append(\n                _format_args(\n                    self.posonlyargs,\n                    positional_only_defaults,\n                    self.posonlyargs_annotations,\n                )\n            )\n            result.append(\"/\")\n        if self.args:\n            result.append(\n                _format_args(\n                    self.args,\n                    positional_or_keyword_defaults,\n                    getattr(self, \"annotations\", None),\n                )\n            )\n        if self.vararg:\n            result.append(f\"*{self.vararg}\")\n        if self.kwonlyargs:\n            if not self.vararg:\n                result.append(\"*\")\n            result.append(\n                _format_args(\n                    self.kwonlyargs, self.kw_defaults, self.kwonlyargs_annotations\n                )\n            )\n        if self.kwarg:\n            result.append(f\"**{self.kwarg}\")\n        return \", \".join(result)\n\n    def default_value(self, argname):\n        \"\"\"Get the default value for an argument.\n\n        :param argname: The name of the argument to get the default value for.\n        :type argname: str\n\n        :raises NoDefault: If there is no default value defined for the\n            given argument.\n        \"\"\"\n        args = self.arguments\n        index = _find_arg(argname, args)[0]\n        if index is not None:\n            idx = index - (len(args) - len(self.defaults))\n            if idx >= 0:\n                return self.defaults[idx]\n        index = _find_arg(argname, self.kwonlyargs)[0]\n        if index is not None and self.kw_defaults[index] is not None:\n            return self.kw_defaults[index]\n        raise NoDefault(func=self.parent, name=argname)\n\n    def is_argument(self, name):\n        \"\"\"Check if the given name is defined in the arguments.\n\n        :param name: The name to check for.\n        :type name: str\n\n        :returns: True if the given name is defined in the arguments,\n            False otherwise.\n        :rtype: bool\n        \"\"\"\n        if name == self.vararg:\n            return True\n        if name == self.kwarg:\n            return True\n        return (\n            self.find_argname(name, rec=True)[1] is not None\n            or self.kwonlyargs\n            and _find_arg(name, self.kwonlyargs, rec=True)[1] is not None\n        )\n\n    def find_argname(self, argname, rec=False):\n        \"\"\"Get the index and :class:`AssignName` node for given name.\n\n        :param argname: The name of the argument to search for.\n        :type argname: str\n\n        :param rec: Whether or not to include arguments in unpacked tuples\n            in the search.\n        :type rec: bool\n\n        :returns: The index and node for the argument.\n        :rtype: tuple(str or None, AssignName or None)\n        \"\"\"\n        if self.arguments:\n            return _find_arg(argname, self.arguments, rec)\n        return None, None\n\n    def get_children(self):\n        yield from self.posonlyargs or ()\n\n        for elt in self.posonlyargs_annotations:\n            if elt is not None:\n                yield elt\n\n        yield from self.args or ()\n\n        yield from self.defaults\n        yield from self.kwonlyargs\n\n        for elt in self.kw_defaults:\n            if elt is not None:\n                yield elt\n\n        for elt in self.annotations:\n            if elt is not None:\n                yield elt\n\n        if self.varargannotation is not None:\n            yield self.varargannotation\n\n        if self.kwargannotation is not None:\n            yield self.kwargannotation\n\n        for elt in self.kwonlyargs_annotations:\n            if elt is not None:\n                yield elt\n\n\ndef _find_arg(argname, args, rec=False):\n    for i, arg in enumerate(args):\n        if isinstance(arg, Tuple):\n            if rec:\n                found = _find_arg(argname, arg.elts)\n                if found[0] is not None:\n                    return found\n        elif arg.name == argname:\n            return i, arg\n    return None, None\n\n\ndef _format_args(args, defaults=None, annotations=None):\n    values = []\n    if args is None:\n        return \"\"\n    if annotations is None:\n        annotations = []\n    if defaults is not None:\n        default_offset = len(args) - len(defaults)\n    packed = itertools.zip_longest(args, annotations)\n    for i, (arg, annotation) in enumerate(packed):\n        if isinstance(arg, Tuple):\n            values.append(f\"({_format_args(arg.elts)})\")\n        else:\n            argname = arg.name\n            default_sep = \"=\"\n            if annotation is not None:\n                argname += \": \" + annotation.as_string()\n                default_sep = \" = \"\n            values.append(argname)\n\n            if defaults is not None and i >= default_offset:\n                if defaults[i - default_offset] is not None:\n                    values[-1] += default_sep + defaults[i - default_offset].as_string()\n    return \", \".join(values)\n\n\nclass AssignAttr(mixins.ParentAssignTypeMixin, NodeNG):\n    \"\"\"Variation of :class:`ast.Assign` representing assignment to an attribute.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('self.attribute = range(10)')\n    >>> node\n    <Assign l.1 at 0x7effe1d521d0>\n    >>> list(node.get_children())\n    [<AssignAttr.attribute l.1 at 0x7effe1d52320>, <Call l.1 at 0x7effe1d522e8>]\n    >>> list(node.get_children())[0].as_string()\n    'self.attribute'\n    \"\"\"\n\n    _astroid_fields = (\"expr\",)\n    _other_fields = (\"attrname\",)\n\n    @decorators.deprecate_default_argument_values(attrname=\"str\")\n    def __init__(\n        self,\n        attrname: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param attrname: The name of the attribute being assigned to.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.expr: NodeNG | None = None\n        \"\"\"What has the attribute that is being assigned to.\"\"\"\n\n        self.attrname: str | None = attrname\n        \"\"\"The name of the attribute being assigned to.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, expr: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param expr: What has the attribute that is being assigned to.\n        \"\"\"\n        self.expr = expr\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[AssignAttr]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def get_children(self):\n        yield self.expr\n\n\nclass Assert(Statement):\n    \"\"\"Class representing an :class:`ast.Assert` node.\n\n    An :class:`Assert` node represents an assert statement.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('assert len(things) == 10, \"Not enough things\"')\n    >>> node\n    <Assert l.1 at 0x7effe1d527b8>\n    \"\"\"\n\n    _astroid_fields = (\"test\", \"fail\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.test: NodeNG | None = None\n        \"\"\"The test that passes or fails the assertion.\"\"\"\n\n        self.fail: NodeNG | None = None  # can be None\n        \"\"\"The message shown when the assertion fails.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, test: NodeNG | None = None, fail: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param test: The test that passes or fails the assertion.\n\n        :param fail: The message shown when the assertion fails.\n        \"\"\"\n        self.fail = fail\n        self.test = test\n\n    def get_children(self):\n        yield self.test\n\n        if self.fail is not None:\n            yield self.fail\n\n\nclass Assign(mixins.AssignTypeMixin, Statement):\n    \"\"\"Class representing an :class:`ast.Assign` node.\n\n    An :class:`Assign` is a statement where something is explicitly\n    asssigned to.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('variable = range(10)')\n    >>> node\n    <Assign l.1 at 0x7effe1db8550>\n    \"\"\"\n\n    _astroid_fields = (\"targets\", \"value\")\n    _other_other_fields = (\"type_annotation\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.targets: list[NodeNG] = []\n        \"\"\"What is being assigned to.\"\"\"\n\n        self.value: NodeNG | None = None\n        \"\"\"The value being assigned to the variables.\"\"\"\n\n        self.type_annotation: NodeNG | None = None  # can be None\n        \"\"\"If present, this will contain the type annotation passed by a type comment\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        targets: list[NodeNG] | None = None,\n        value: NodeNG | None = None,\n        type_annotation: NodeNG | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param targets: What is being assigned to.\n        :param value: The value being assigned to the variables.\n        :param type_annotation:\n        \"\"\"\n        if targets is not None:\n            self.targets = targets\n        self.value = value\n        self.type_annotation = type_annotation\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[Assign]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def get_children(self):\n        yield from self.targets\n\n        yield self.value\n\n    @decorators.cached\n    def _get_assign_nodes(self):\n        return [self] + list(self.value._get_assign_nodes())\n\n    def _get_yield_nodes_skip_lambdas(self):\n        yield from self.value._get_yield_nodes_skip_lambdas()\n\n\nclass AnnAssign(mixins.AssignTypeMixin, Statement):\n    \"\"\"Class representing an :class:`ast.AnnAssign` node.\n\n    An :class:`AnnAssign` is an assignment with a type annotation.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('variable: List[int] = range(10)')\n    >>> node\n    <AnnAssign l.1 at 0x7effe1d4c630>\n    \"\"\"\n\n    _astroid_fields = (\"target\", \"annotation\", \"value\")\n    _other_fields = (\"simple\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.target: NodeNG | None = None\n        \"\"\"What is being assigned to.\"\"\"\n\n        self.annotation: NodeNG | None = None\n        \"\"\"The type annotation of what is being assigned to.\"\"\"\n\n        self.value: NodeNG | None = None  # can be None\n        \"\"\"The value being assigned to the variables.\"\"\"\n\n        self.simple: int | None = None\n        \"\"\"Whether :attr:`target` is a pure name or a complex statement.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        target: NodeNG,\n        annotation: NodeNG,\n        simple: int,\n        value: NodeNG | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param target: What is being assigned to.\n\n        :param annotation: The type annotation of what is being assigned to.\n\n        :param simple: Whether :attr:`target` is a pure name\n            or a complex statement.\n\n        :param value: The value being assigned to the variables.\n        \"\"\"\n        self.target = target\n        self.annotation = annotation\n        self.value = value\n        self.simple = simple\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[AnnAssign]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def get_children(self):\n        yield self.target\n        yield self.annotation\n\n        if self.value is not None:\n            yield self.value\n\n\nclass AugAssign(mixins.AssignTypeMixin, Statement):\n    \"\"\"Class representing an :class:`ast.AugAssign` node.\n\n    An :class:`AugAssign` is an assignment paired with an operator.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('variable += 1')\n    >>> node\n    <AugAssign l.1 at 0x7effe1db4d68>\n    \"\"\"\n\n    _astroid_fields = (\"target\", \"value\")\n    _other_fields = (\"op\",)\n\n    @decorators.deprecate_default_argument_values(op=\"str\")\n    def __init__(\n        self,\n        op: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param op: The operator that is being combined with the assignment.\n            This includes the equals sign.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.target: NodeNG | None = None\n        \"\"\"What is being assigned to.\"\"\"\n\n        self.op: str | None = op\n        \"\"\"The operator that is being combined with the assignment.\n\n        This includes the equals sign.\n        \"\"\"\n\n        self.value: NodeNG | None = None\n        \"\"\"The value being assigned to the variable.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self, target: NodeNG | None = None, value: NodeNG | None = None\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param target: What is being assigned to.\n\n        :param value: The value being assigned to the variable.\n        \"\"\"\n        self.target = target\n        self.value = value\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[AugAssign]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    # This is set by inference.py\n    def _infer_augassign(self, context=None):\n        raise NotImplementedError\n\n    def type_errors(self, context=None):\n        \"\"\"Get a list of type errors which can occur during inference.\n\n        Each TypeError is represented by a :class:`BadBinaryOperationMessage` ,\n        which holds the original exception.\n\n        :returns: The list of possible type errors.\n        :rtype: list(BadBinaryOperationMessage)\n        \"\"\"\n        try:\n            results = self._infer_augassign(context=context)\n            return [\n                result\n                for result in results\n                if isinstance(result, util.BadBinaryOperationMessage)\n            ]\n        except InferenceError:\n            return []\n\n    def get_children(self):\n        yield self.target\n        yield self.value\n\n    def _get_yield_nodes_skip_lambdas(self):\n        \"\"\"An AugAssign node can contain a Yield node in the value\"\"\"\n        yield from self.value._get_yield_nodes_skip_lambdas()\n        yield from super()._get_yield_nodes_skip_lambdas()\n\n\nclass BinOp(NodeNG):\n    \"\"\"Class representing an :class:`ast.BinOp` node.\n\n    A :class:`BinOp` node is an application of a binary operator.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('a + b')\n    >>> node\n    <BinOp l.1 at 0x7f23b2e8cfd0>\n    \"\"\"\n\n    _astroid_fields = (\"left\", \"right\")\n    _other_fields = (\"op\",)\n\n    @decorators.deprecate_default_argument_values(op=\"str\")\n    def __init__(\n        self,\n        op: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param op: The operator.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.left: NodeNG | None = None\n        \"\"\"What is being applied to the operator on the left side.\"\"\"\n\n        self.op: str | None = op\n        \"\"\"The operator.\"\"\"\n\n        self.right: NodeNG | None = None\n        \"\"\"What is being applied to the operator on the right side.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, left: NodeNG | None = None, right: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param left: What is being applied to the operator on the left side.\n\n        :param right: What is being applied to the operator on the right side.\n        \"\"\"\n        self.left = left\n        self.right = right\n\n    # This is set by inference.py\n    def _infer_binop(self, context=None):\n        raise NotImplementedError\n\n    def type_errors(self, context=None):\n        \"\"\"Get a list of type errors which can occur during inference.\n\n        Each TypeError is represented by a :class:`BadBinaryOperationMessage`,\n        which holds the original exception.\n\n        :returns: The list of possible type errors.\n        :rtype: list(BadBinaryOperationMessage)\n        \"\"\"\n        try:\n            results = self._infer_binop(context=context)\n            return [\n                result\n                for result in results\n                if isinstance(result, util.BadBinaryOperationMessage)\n            ]\n        except InferenceError:\n            return []\n\n    def get_children(self):\n        yield self.left\n        yield self.right\n\n    def op_precedence(self):\n        return OP_PRECEDENCE[self.op]\n\n    def op_left_associative(self):\n        # 2**3**4 == 2**(3**4)\n        return self.op != \"**\"\n\n\nclass BoolOp(NodeNG):\n    \"\"\"Class representing an :class:`ast.BoolOp` node.\n\n    A :class:`BoolOp` is an application of a boolean operator.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('a and b')\n    >>> node\n    <BinOp l.1 at 0x7f23b2e71c50>\n    \"\"\"\n\n    _astroid_fields = (\"values\",)\n    _other_fields = (\"op\",)\n\n    @decorators.deprecate_default_argument_values(op=\"str\")\n    def __init__(\n        self,\n        op: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param op: The operator.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.op: str | None = op\n        \"\"\"The operator.\"\"\"\n\n        self.values: list[NodeNG] = []\n        \"\"\"The values being applied to the operator.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, values: list[NodeNG] | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param values: The values being applied to the operator.\n        \"\"\"\n        if values is not None:\n            self.values = values\n\n    def get_children(self):\n        yield from self.values\n\n    def op_precedence(self):\n        return OP_PRECEDENCE[self.op]\n\n\nclass Break(mixins.NoChildrenMixin, Statement):\n    \"\"\"Class representing an :class:`ast.Break` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('break')\n    >>> node\n    <Break l.1 at 0x7f23b2e9e5c0>\n    \"\"\"\n\n\nclass Call(NodeNG):\n    \"\"\"Class representing an :class:`ast.Call` node.\n\n    A :class:`Call` node is a call to a function, method, etc.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('function()')\n    >>> node\n    <Call l.1 at 0x7f23b2e71eb8>\n    \"\"\"\n\n    _astroid_fields = (\"func\", \"args\", \"keywords\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.func: NodeNG | None = None\n        \"\"\"What is being called.\"\"\"\n\n        self.args: list[NodeNG] = []\n        \"\"\"The positional arguments being given to the call.\"\"\"\n\n        self.keywords: list[Keyword] = []\n        \"\"\"The keyword arguments being given to the call.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        func: NodeNG | None = None,\n        args: list[NodeNG] | None = None,\n        keywords: list[Keyword] | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param func: What is being called.\n\n        :param args: The positional arguments being given to the call.\n\n        :param keywords: The keyword arguments being given to the call.\n        \"\"\"\n        self.func = func\n        if args is not None:\n            self.args = args\n        if keywords is not None:\n            self.keywords = keywords\n\n    @property\n    def starargs(self) -> list[Starred]:\n        \"\"\"The positional arguments that unpack something.\"\"\"\n        return [arg for arg in self.args if isinstance(arg, Starred)]\n\n    @property\n    def kwargs(self) -> list[Keyword]:\n        \"\"\"The keyword arguments that unpack something.\"\"\"\n        return [keyword for keyword in self.keywords if keyword.arg is None]\n\n    def get_children(self):\n        yield self.func\n\n        yield from self.args\n\n        yield from self.keywords\n\n\nclass Compare(NodeNG):\n    \"\"\"Class representing an :class:`ast.Compare` node.\n\n    A :class:`Compare` node indicates a comparison.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('a <= b <= c')\n    >>> node\n    <Compare l.1 at 0x7f23b2e9e6d8>\n    >>> node.ops\n    [('<=', <Name.b l.1 at 0x7f23b2e9e2b0>), ('<=', <Name.c l.1 at 0x7f23b2e9e390>)]\n    \"\"\"\n\n    _astroid_fields = (\"left\", \"ops\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.left: NodeNG | None = None\n        \"\"\"The value at the left being applied to a comparison operator.\"\"\"\n\n        self.ops: list[tuple[str, NodeNG]] = []\n        \"\"\"The remainder of the operators and their relevant right hand value.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        left: NodeNG | None = None,\n        ops: list[tuple[str, NodeNG]] | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param left: The value at the left being applied to a comparison\n            operator.\n\n        :param ops: The remainder of the operators\n            and their relevant right hand value.\n        \"\"\"\n        self.left = left\n        if ops is not None:\n            self.ops = ops\n\n    def get_children(self):\n        \"\"\"Get the child nodes below this node.\n\n        Overridden to handle the tuple fields and skip returning the operator\n        strings.\n\n        :returns: The children.\n        :rtype: iterable(NodeNG)\n        \"\"\"\n        yield self.left\n        for _, comparator in self.ops:\n            yield comparator  # we don't want the 'op'\n\n    def last_child(self):\n        \"\"\"An optimized version of list(get_children())[-1]\n\n        :returns: The last child.\n        :rtype: NodeNG\n        \"\"\"\n        # XXX maybe if self.ops:\n        return self.ops[-1][1]\n        # return self.left\n\n\nclass Comprehension(NodeNG):\n    \"\"\"Class representing an :class:`ast.comprehension` node.\n\n    A :class:`Comprehension` indicates the loop inside any type of\n    comprehension including generator expressions.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('[x for x in some_values]')\n    >>> list(node.get_children())\n    [<Name.x l.1 at 0x7f23b2e352b0>, <Comprehension l.1 at 0x7f23b2e35320>]\n    >>> list(node.get_children())[1].as_string()\n    'for x in some_values'\n    \"\"\"\n\n    _astroid_fields = (\"target\", \"iter\", \"ifs\")\n    _other_fields = (\"is_async\",)\n\n    optional_assign = True\n    \"\"\"Whether this node optionally assigns a variable.\"\"\"\n\n    lineno: None\n    col_offset: None\n    end_lineno: None\n    end_col_offset: None\n\n    def __init__(self, parent: NodeNG | None = None) -> None:\n        \"\"\"\n        :param parent: The parent node in the syntax tree.\n        \"\"\"\n        self.target: NodeNG | None = None\n        \"\"\"What is assigned to by the comprehension.\"\"\"\n\n        self.iter: NodeNG | None = None\n        \"\"\"What is iterated over by the comprehension.\"\"\"\n\n        self.ifs: list[NodeNG] = []\n        \"\"\"The contents of any if statements that filter the comprehension.\"\"\"\n\n        self.is_async: bool | None = None\n        \"\"\"Whether this is an asynchronous comprehension or not.\"\"\"\n\n        super().__init__(parent=parent)\n\n    # pylint: disable=redefined-builtin; same name as builtin ast module.\n    def postinit(\n        self,\n        target: NodeNG | None = None,\n        iter: NodeNG | None = None,\n        ifs: list[NodeNG] | None = None,\n        is_async: bool | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param target: What is assigned to by the comprehension.\n\n        :param iter: What is iterated over by the comprehension.\n\n        :param ifs: The contents of any if statements that filter\n            the comprehension.\n\n        :param is_async: Whether this is an asynchronous comprehension or not.\n        \"\"\"\n        self.target = target\n        self.iter = iter\n        if ifs is not None:\n            self.ifs = ifs\n        self.is_async = is_async\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[Comprehension]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def assign_type(self):\n        \"\"\"The type of assignment that this node performs.\n\n        :returns: The assignment type.\n        :rtype: NodeNG\n        \"\"\"\n        return self\n\n    def _get_filtered_stmts(self, lookup_node, node, stmts, mystmt: Statement | None):\n        \"\"\"method used in filter_stmts\"\"\"\n        if self is mystmt:\n            if isinstance(lookup_node, (Const, Name)):\n                return [lookup_node], True\n\n        elif self.statement(future=True) is mystmt:\n            # original node's statement is the assignment, only keeps\n            # current node (gen exp, list comp)\n\n            return [node], True\n\n        return stmts, False\n\n    def get_children(self):\n        yield self.target\n        yield self.iter\n\n        yield from self.ifs\n\n\nclass Const(mixins.NoChildrenMixin, NodeNG, Instance):\n    \"\"\"Class representing any constant including num, str, bool, None, bytes.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('(5, \"This is a string.\", True, None, b\"bytes\")')\n    >>> node\n    <Tuple.tuple l.1 at 0x7f23b2e358d0>\n    >>> list(node.get_children())\n    [<Const.int l.1 at 0x7f23b2e35940>,\n    <Const.str l.1 at 0x7f23b2e35978>,\n    <Const.bool l.1 at 0x7f23b2e359b0>,\n    <Const.NoneType l.1 at 0x7f23b2e359e8>,\n    <Const.bytes l.1 at 0x7f23b2e35a20>]\n    \"\"\"\n\n    _other_fields = (\"value\", \"kind\")\n\n    def __init__(\n        self,\n        value: Any,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        kind: str | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param value: The value that the constant represents.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param kind: The string prefix. \"u\" for u-prefixed strings and ``None`` otherwise. Python 3.8+ only.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.value: Any = value\n        \"\"\"The value that the constant represents.\"\"\"\n\n        self.kind: str | None = kind  # can be None\n        \"\"\"\"The string prefix. \"u\" for u-prefixed strings and ``None`` otherwise. Python 3.8+ only.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def __getattr__(self, name):\n        # This is needed because of Proxy's __getattr__ method.\n        # Calling object.__new__ on this class without calling\n        # __init__ would result in an infinite loop otherwise\n        # since __getattr__ is called when an attribute doesn't\n        # exist and self._proxied indirectly calls self.value\n        # and Proxy __getattr__ calls self.value\n        if name == \"value\":\n            raise AttributeError\n        return super().__getattr__(name)\n\n    def getitem(self, index, context=None):\n        \"\"\"Get an item from this node if subscriptable.\n\n        :param index: The node to use as a subscript index.\n        :type index: Const or Slice\n\n        :raises AstroidTypeError: When the given index cannot be used as a\n            subscript index, or if this node is not subscriptable.\n        \"\"\"\n        if isinstance(index, Const):\n            index_value = index.value\n        elif isinstance(index, Slice):\n            index_value = _infer_slice(index, context=context)\n\n        else:\n            raise AstroidTypeError(\n                f\"Could not use type {type(index)} as subscript index\"\n            )\n\n        try:\n            if isinstance(self.value, (str, bytes)):\n                return Const(self.value[index_value])\n        except IndexError as exc:\n            raise AstroidIndexError(\n                message=\"Index {index!r} out of range\",\n                node=self,\n                index=index,\n                context=context,\n            ) from exc\n        except TypeError as exc:\n            raise AstroidTypeError(\n                message=\"Type error {error!r}\", node=self, index=index, context=context\n            ) from exc\n\n        raise AstroidTypeError(f\"{self!r} (value={self.value})\")\n\n    def has_dynamic_getattr(self):\n        \"\"\"Check if the node has a custom __getattr__ or __getattribute__.\n\n        :returns: True if the class has a custom\n            __getattr__ or __getattribute__, False otherwise.\n            For a :class:`Const` this is always ``False``.\n        :rtype: bool\n        \"\"\"\n        return False\n\n    def itered(self):\n        \"\"\"An iterator over the elements this node contains.\n\n        :returns: The contents of this node.\n        :rtype: iterable(Const)\n\n        :raises TypeError: If this node does not represent something that is iterable.\n        \"\"\"\n        if isinstance(self.value, str):\n            return [const_factory(elem) for elem in self.value]\n        raise TypeError(f\"Cannot iterate over type {type(self.value)!r}\")\n\n    def pytype(self):\n        \"\"\"Get the name of the type that this node represents.\n\n        :returns: The name of the type.\n        :rtype: str\n        \"\"\"\n        return self._proxied.qname()\n\n    def bool_value(self, context=None):\n        \"\"\"Determine the boolean value of this node.\n\n        :returns: The boolean value of this node.\n        :rtype: bool\n        \"\"\"\n        return bool(self.value)\n\n\nclass Continue(mixins.NoChildrenMixin, Statement):\n    \"\"\"Class representing an :class:`ast.Continue` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('continue')\n    >>> node\n    <Continue l.1 at 0x7f23b2e35588>\n    \"\"\"\n\n\nclass Decorators(NodeNG):\n    \"\"\"A node representing a list of decorators.\n\n    A :class:`Decorators` is the decorators that are applied to\n    a method or function.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    @property\n    def my_property(self):\n        return 3\n    ''')\n    >>> node\n    <FunctionDef.my_property l.2 at 0x7f23b2e35d30>\n    >>> list(node.get_children())[0]\n    <Decorators l.1 at 0x7f23b2e35d68>\n    \"\"\"\n\n    _astroid_fields = (\"nodes\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.nodes: list[NodeNG]\n        \"\"\"The decorators that this node contains.\n\n        :type: list(Name or Call) or None\n        \"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, nodes: list[NodeNG]) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param nodes: The decorators that this node contains.\n        :type nodes: list(Name or Call)\n        \"\"\"\n        self.nodes = nodes\n\n    def scope(self) -> LocalsDictNodeNG:\n        \"\"\"The first parent node defining a new scope.\n        These can be Module, FunctionDef, ClassDef, Lambda, or GeneratorExp nodes.\n\n        :returns: The first parent scope node.\n        \"\"\"\n        # skip the function node to go directly to the upper level scope\n        if not self.parent:\n            raise ParentMissingError(target=self)\n        if not self.parent.parent:\n            raise ParentMissingError(target=self.parent)\n        return self.parent.parent.scope()\n\n    def get_children(self):\n        yield from self.nodes\n\n\nclass DelAttr(mixins.ParentAssignTypeMixin, NodeNG):\n    \"\"\"Variation of :class:`ast.Delete` representing deletion of an attribute.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('del self.attr')\n    >>> node\n    <Delete l.1 at 0x7f23b2e35f60>\n    >>> list(node.get_children())[0]\n    <DelAttr.attr l.1 at 0x7f23b2e411d0>\n    \"\"\"\n\n    _astroid_fields = (\"expr\",)\n    _other_fields = (\"attrname\",)\n\n    @decorators.deprecate_default_argument_values(attrname=\"str\")\n    def __init__(\n        self,\n        attrname: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param attrname: The name of the attribute that is being deleted.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.expr: NodeNG | None = None\n        \"\"\"The name that this node represents.\n\n        :type: Name or None\n        \"\"\"\n\n        self.attrname: str | None = attrname\n        \"\"\"The name of the attribute that is being deleted.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, expr: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param expr: The name that this node represents.\n        :type expr: Name or None\n        \"\"\"\n        self.expr = expr\n\n    def get_children(self):\n        yield self.expr\n\n\nclass Delete(mixins.AssignTypeMixin, Statement):\n    \"\"\"Class representing an :class:`ast.Delete` node.\n\n    A :class:`Delete` is a ``del`` statement this is deleting something.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('del self.attr')\n    >>> node\n    <Delete l.1 at 0x7f23b2e35f60>\n    \"\"\"\n\n    _astroid_fields = (\"targets\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.targets: list[NodeNG] = []\n        \"\"\"What is being deleted.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, targets: list[NodeNG] | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param targets: What is being deleted.\n        \"\"\"\n        if targets is not None:\n            self.targets = targets\n\n    def get_children(self):\n        yield from self.targets\n\n\nclass Dict(NodeNG, Instance):\n    \"\"\"Class representing an :class:`ast.Dict` node.\n\n    A :class:`Dict` is a dictionary that is created with ``{}`` syntax.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('{1: \"1\"}')\n    >>> node\n    <Dict.dict l.1 at 0x7f23b2e35cc0>\n    \"\"\"\n\n    _astroid_fields = (\"items\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.items: list[tuple[NodeNG, NodeNG]] = []\n        \"\"\"The key-value pairs contained in the dictionary.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, items: list[tuple[NodeNG, NodeNG]]) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param items: The key-value pairs contained in the dictionary.\n        \"\"\"\n        self.items = items\n\n    @classmethod\n    def from_elements(cls, items=None):\n        \"\"\"Create a :class:`Dict` of constants from a live dictionary.\n\n        :param items: The items to store in the node.\n        :type items: dict\n\n        :returns: The created dictionary node.\n        :rtype: Dict\n        \"\"\"\n        node = cls()\n        if items is None:\n            node.items = []\n        else:\n            node.items = [\n                (const_factory(k), const_factory(v) if _is_const(v) else v)\n                for k, v in items.items()\n                # The keys need to be constants\n                if _is_const(k)\n            ]\n        return node\n\n    def pytype(self):\n        \"\"\"Get the name of the type that this node represents.\n\n        :returns: The name of the type.\n        :rtype: str\n        \"\"\"\n        return \"builtins.dict\"\n\n    def get_children(self):\n        \"\"\"Get the key and value nodes below this node.\n\n        Children are returned in the order that they are defined in the source\n        code, key first then the value.\n\n        :returns: The children.\n        :rtype: iterable(NodeNG)\n        \"\"\"\n        for key, value in self.items:\n            yield key\n            yield value\n\n    def last_child(self):\n        \"\"\"An optimized version of list(get_children())[-1]\n\n        :returns: The last child, or None if no children exist.\n        :rtype: NodeNG or None\n        \"\"\"\n        if self.items:\n            return self.items[-1][1]\n        return None\n\n    def itered(self):\n        \"\"\"An iterator over the keys this node contains.\n\n        :returns: The keys of this node.\n        :rtype: iterable(NodeNG)\n        \"\"\"\n        return [key for (key, _) in self.items]\n\n    def getitem(self, index, context=None):\n        \"\"\"Get an item from this node.\n\n        :param index: The node to use as a subscript index.\n        :type index: Const or Slice\n\n        :raises AstroidTypeError: When the given index cannot be used as a\n            subscript index, or if this node is not subscriptable.\n        :raises AstroidIndexError: If the given index does not exist in the\n            dictionary.\n        \"\"\"\n        for key, value in self.items:\n            # TODO(cpopa): no support for overriding yet, {1:2, **{1: 3}}.\n            if isinstance(key, DictUnpack):\n                try:\n                    return value.getitem(index, context)\n                except (AstroidTypeError, AstroidIndexError):\n                    continue\n            for inferredkey in key.infer(context):\n                if inferredkey is util.Uninferable:\n                    continue\n                if isinstance(inferredkey, Const) and isinstance(index, Const):\n                    if inferredkey.value == index.value:\n                        return value\n\n        raise AstroidIndexError(index)\n\n    def bool_value(self, context=None):\n        \"\"\"Determine the boolean value of this node.\n\n        :returns: The boolean value of this node.\n        :rtype: bool\n        \"\"\"\n        return bool(self.items)\n\n\nclass Expr(Statement):\n    \"\"\"Class representing an :class:`ast.Expr` node.\n\n    An :class:`Expr` is any expression that does not have its value used or\n    stored.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('method()')\n    >>> node\n    <Call l.1 at 0x7f23b2e352b0>\n    >>> node.parent\n    <Expr l.1 at 0x7f23b2e35278>\n    \"\"\"\n\n    _astroid_fields = (\"value\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.value: NodeNG | None = None\n        \"\"\"What the expression does.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, value: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: What the expression does.\n        \"\"\"\n        self.value = value\n\n    def get_children(self):\n        yield self.value\n\n    def _get_yield_nodes_skip_lambdas(self):\n        if not self.value.is_lambda:\n            yield from self.value._get_yield_nodes_skip_lambdas()\n\n\nclass Ellipsis(mixins.NoChildrenMixin, NodeNG):  # pylint: disable=redefined-builtin\n    \"\"\"Class representing an :class:`ast.Ellipsis` node.\n\n    An :class:`Ellipsis` is the ``...`` syntax.\n\n    Deprecated since v2.6.0 - Use :class:`Const` instead.\n    Will be removed with the release v2.7.0\n    \"\"\"\n\n\nclass EmptyNode(mixins.NoChildrenMixin, NodeNG):\n    \"\"\"Holds an arbitrary object in the :attr:`LocalsDictNodeNG.locals`.\"\"\"\n\n    object = None\n\n\nclass ExceptHandler(mixins.MultiLineBlockMixin, mixins.AssignTypeMixin, Statement):\n    \"\"\"Class representing an :class:`ast.ExceptHandler`. node.\n\n    An :class:`ExceptHandler` is an ``except`` block on a try-except.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n        try:\n            do_something()\n        except Exception as error:\n            print(\"Error!\")\n        ''')\n    >>> node\n    <TryExcept l.2 at 0x7f23b2e9d908>\n    >>> node.handlers\n    [<ExceptHandler l.4 at 0x7f23b2e9e860>]\n    \"\"\"\n\n    _astroid_fields = (\"type\", \"name\", \"body\")\n    _multi_line_block_fields = (\"body\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.type: NodeNG | None = None  # can be None\n        \"\"\"The types that the block handles.\n\n        :type: Tuple or NodeNG or None\n        \"\"\"\n\n        self.name: AssignName | None = None  # can be None\n        \"\"\"The name that the caught exception is assigned to.\"\"\"\n\n        self.body: list[NodeNG] = []\n        \"\"\"The contents of the block.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[ExceptHandler]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def get_children(self):\n        if self.type is not None:\n            yield self.type\n\n        if self.name is not None:\n            yield self.name\n\n        yield from self.body\n\n    # pylint: disable=redefined-builtin; had to use the same name as builtin ast module.\n    def postinit(\n        self,\n        type: NodeNG | None = None,\n        name: AssignName | None = None,\n        body: list[NodeNG] | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param type: The types that the block handles.\n        :type type: Tuple or NodeNG or None\n\n        :param name: The name that the caught exception is assigned to.\n\n        :param body:The contents of the block.\n        \"\"\"\n        self.type = type\n        self.name = name\n        if body is not None:\n            self.body = body\n\n    @cached_property\n    def blockstart_tolineno(self):\n        \"\"\"The line on which the beginning of this block ends.\n\n        :type: int\n        \"\"\"\n        if self.name:\n            return self.name.tolineno\n        if self.type:\n            return self.type.tolineno\n        return self.lineno\n\n    def catch(self, exceptions: list[str] | None) -> bool:\n        \"\"\"Check if this node handles any of the given\n\n        :param exceptions: The names of the exceptions to check for.\n        \"\"\"\n        if self.type is None or exceptions is None:\n            return True\n        return any(node.name in exceptions for node in self.type._get_name_nodes())\n\n\nclass ExtSlice(NodeNG):\n    \"\"\"Class representing an :class:`ast.ExtSlice` node.\n\n    An :class:`ExtSlice` is a complex slice expression.\n\n    Deprecated since v2.6.0 - Now part of the :class:`Subscript` node.\n    Will be removed with the release of v2.7.0\n    \"\"\"\n\n\nclass For(\n    mixins.MultiLineBlockMixin,\n    mixins.BlockRangeMixIn,\n    mixins.AssignTypeMixin,\n    Statement,\n):\n    \"\"\"Class representing an :class:`ast.For` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('for thing in things: print(thing)')\n    >>> node\n    <For l.1 at 0x7f23b2e8cf28>\n    \"\"\"\n\n    _astroid_fields = (\"target\", \"iter\", \"body\", \"orelse\")\n    _other_other_fields = (\"type_annotation\",)\n    _multi_line_block_fields = (\"body\", \"orelse\")\n\n    optional_assign = True\n    \"\"\"Whether this node optionally assigns a variable.\n\n    This is always ``True`` for :class:`For` nodes.\n    \"\"\"\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.target: NodeNG | None = None\n        \"\"\"What the loop assigns to.\"\"\"\n\n        self.iter: NodeNG | None = None\n        \"\"\"What the loop iterates over.\"\"\"\n\n        self.body: list[NodeNG] = []\n        \"\"\"The contents of the body of the loop.\"\"\"\n\n        self.orelse: list[NodeNG] = []\n        \"\"\"The contents of the ``else`` block of the loop.\"\"\"\n\n        self.type_annotation: NodeNG | None = None  # can be None\n        \"\"\"If present, this will contain the type annotation passed by a type comment\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    # pylint: disable=redefined-builtin; had to use the same name as builtin ast module.\n    def postinit(\n        self,\n        target: NodeNG | None = None,\n        iter: NodeNG | None = None,\n        body: list[NodeNG] | None = None,\n        orelse: list[NodeNG] | None = None,\n        type_annotation: NodeNG | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param target: What the loop assigns to.\n\n        :param iter: What the loop iterates over.\n\n        :param body: The contents of the body of the loop.\n\n        :param orelse: The contents of the ``else`` block of the loop.\n        \"\"\"\n        self.target = target\n        self.iter = iter\n        if body is not None:\n            self.body = body\n        if orelse is not None:\n            self.orelse = orelse\n        self.type_annotation = type_annotation\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[For]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    @cached_property\n    def blockstart_tolineno(self):\n        \"\"\"The line on which the beginning of this block ends.\n\n        :type: int\n        \"\"\"\n        return self.iter.tolineno\n\n    def get_children(self):\n        yield self.target\n        yield self.iter\n\n        yield from self.body\n        yield from self.orelse\n\n\nclass AsyncFor(For):\n    \"\"\"Class representing an :class:`ast.AsyncFor` node.\n\n    An :class:`AsyncFor` is an asynchronous :class:`For` built with\n    the ``async`` keyword.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    async def func(things):\n        async for thing in things:\n            print(thing)\n    ''')\n    >>> node\n    <AsyncFunctionDef.func l.2 at 0x7f23b2e416d8>\n    >>> node.body[0]\n    <AsyncFor l.3 at 0x7f23b2e417b8>\n    \"\"\"\n\n\nclass Await(NodeNG):\n    \"\"\"Class representing an :class:`ast.Await` node.\n\n    An :class:`Await` is the ``await`` keyword.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    async def func(things):\n        await other_func()\n    ''')\n    >>> node\n    <AsyncFunctionDef.func l.2 at 0x7f23b2e41748>\n    >>> node.body[0]\n    <Expr l.3 at 0x7f23b2e419e8>\n    >>> list(node.body[0].get_children())[0]\n    <Await l.3 at 0x7f23b2e41a20>\n    \"\"\"\n\n    _astroid_fields = (\"value\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.value: NodeNG | None = None\n        \"\"\"What to wait for.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, value: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: What to wait for.\n        \"\"\"\n        self.value = value\n\n    def get_children(self):\n        yield self.value\n\n\nclass ImportFrom(mixins.NoChildrenMixin, mixins.ImportFromMixin, Statement):\n    \"\"\"Class representing an :class:`ast.ImportFrom` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('from my_package import my_module')\n    >>> node\n    <ImportFrom l.1 at 0x7f23b2e415c0>\n    \"\"\"\n\n    _other_fields = (\"modname\", \"names\", \"level\")\n\n    def __init__(\n        self,\n        fromname: str | None,\n        names: list[tuple[str, str | None]],\n        level: int | None = 0,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param fromname: The module that is being imported from.\n\n        :param names: What is being imported from the module.\n\n        :param level: The level of relative import.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.modname: str | None = fromname  # can be None\n        \"\"\"The module that is being imported from.\n\n        This is ``None`` for relative imports.\n        \"\"\"\n\n        self.names: list[tuple[str, str | None]] = names\n        \"\"\"What is being imported from the module.\n\n        Each entry is a :class:`tuple` of the name being imported,\n        and the alias that the name is assigned to (if any).\n        \"\"\"\n\n        # TODO When is 'level' None?\n        self.level: int | None = level  # can be None\n        \"\"\"The level of relative import.\n\n        Essentially this is the number of dots in the import.\n        This is always 0 for absolute imports.\n        \"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n\nclass Attribute(NodeNG):\n    \"\"\"Class representing an :class:`ast.Attribute` node.\"\"\"\n\n    _astroid_fields = (\"expr\",)\n    _other_fields = (\"attrname\",)\n\n    @decorators.deprecate_default_argument_values(attrname=\"str\")\n    def __init__(\n        self,\n        attrname: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param attrname: The name of the attribute.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.expr: NodeNG | None = None\n        \"\"\"The name that this node represents.\n\n        :type: Name or None\n        \"\"\"\n\n        self.attrname: str | None = attrname\n        \"\"\"The name of the attribute.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, expr: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param expr: The name that this node represents.\n        :type expr: Name or None\n        \"\"\"\n        self.expr = expr\n\n    def get_children(self):\n        yield self.expr\n\n\nclass Global(mixins.NoChildrenMixin, Statement):\n    \"\"\"Class representing an :class:`ast.Global` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('global a_global')\n    >>> node\n    <Global l.1 at 0x7f23b2e9de10>\n    \"\"\"\n\n    _other_fields = (\"names\",)\n\n    def __init__(\n        self,\n        names: list[str],\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param names: The names being declared as global.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.names: list[str] = names\n        \"\"\"The names being declared as global.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def _infer_name(self, frame, name):\n        return name\n\n\nclass If(mixins.MultiLineBlockMixin, mixins.BlockRangeMixIn, Statement):\n    \"\"\"Class representing an :class:`ast.If` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('if condition: print(True)')\n    >>> node\n    <If l.1 at 0x7f23b2e9dd30>\n    \"\"\"\n\n    _astroid_fields = (\"test\", \"body\", \"orelse\")\n    _multi_line_block_fields = (\"body\", \"orelse\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.test: NodeNG | None = None\n        \"\"\"The condition that the statement tests.\"\"\"\n\n        self.body: list[NodeNG] = []\n        \"\"\"The contents of the block.\"\"\"\n\n        self.orelse: list[NodeNG] = []\n        \"\"\"The contents of the ``else`` block.\"\"\"\n\n        self.is_orelse: bool = False\n        \"\"\"Whether the if-statement is the orelse-block of another if statement.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        test: NodeNG | None = None,\n        body: list[NodeNG] | None = None,\n        orelse: list[NodeNG] | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param test: The condition that the statement tests.\n\n        :param body: The contents of the block.\n\n        :param orelse: The contents of the ``else`` block.\n        \"\"\"\n        self.test = test\n        if body is not None:\n            self.body = body\n        if orelse is not None:\n            self.orelse = orelse\n        if isinstance(self.parent, If) and self in self.parent.orelse:\n            self.is_orelse = True\n\n    @cached_property\n    def blockstart_tolineno(self):\n        \"\"\"The line on which the beginning of this block ends.\n\n        :type: int\n        \"\"\"\n        return self.test.tolineno\n\n    def block_range(self, lineno):\n        \"\"\"Get a range from the given line number to where this node ends.\n\n        :param lineno: The line number to start the range at.\n        :type lineno: int\n\n        :returns: The range of line numbers that this node belongs to,\n            starting at the given line number.\n        :rtype: tuple(int, int)\n        \"\"\"\n        if lineno == self.body[0].fromlineno:\n            return lineno, lineno\n        if lineno <= self.body[-1].tolineno:\n            return lineno, self.body[-1].tolineno\n        return self._elsed_block_range(lineno, self.orelse, self.body[0].fromlineno - 1)\n\n    def get_children(self):\n        yield self.test\n\n        yield from self.body\n        yield from self.orelse\n\n    def has_elif_block(self):\n        return len(self.orelse) == 1 and isinstance(self.orelse[0], If)\n\n    def _get_yield_nodes_skip_lambdas(self):\n        \"\"\"An If node can contain a Yield node in the test\"\"\"\n        yield from self.test._get_yield_nodes_skip_lambdas()\n        yield from super()._get_yield_nodes_skip_lambdas()\n\n    def is_sys_guard(self) -> bool:\n        \"\"\"Return True if IF stmt is a sys.version_info guard.\n\n        >>> import astroid\n        >>> node = astroid.extract_node('''\n        import sys\n        if sys.version_info > (3, 8):\n            from typing import Literal\n        else:\n            from typing_extensions import Literal\n        ''')\n        >>> node.is_sys_guard()\n        True\n        \"\"\"\n        warnings.warn(\n            \"The 'is_sys_guard' function is deprecated and will be removed in astroid 3.0.0 \"\n            \"It has been moved to pylint and can be imported from 'pylint.checkers.utils' \"\n            \"starting with pylint 2.12\",\n            DeprecationWarning,\n        )\n        if isinstance(self.test, Compare):\n            value = self.test.left\n            if isinstance(value, Subscript):\n                value = value.value\n            if isinstance(value, Attribute) and value.as_string() == \"sys.version_info\":\n                return True\n\n        return False\n\n    def is_typing_guard(self) -> bool:\n        \"\"\"Return True if IF stmt is a typing guard.\n\n        >>> import astroid\n        >>> node = astroid.extract_node('''\n        from typing import TYPE_CHECKING\n        if TYPE_CHECKING:\n            from xyz import a\n        ''')\n        >>> node.is_typing_guard()\n        True\n        \"\"\"\n        warnings.warn(\n            \"The 'is_typing_guard' function is deprecated and will be removed in astroid 3.0.0 \"\n            \"It has been moved to pylint and can be imported from 'pylint.checkers.utils' \"\n            \"starting with pylint 2.12\",\n            DeprecationWarning,\n        )\n        return isinstance(\n            self.test, (Name, Attribute)\n        ) and self.test.as_string().endswith(\"TYPE_CHECKING\")\n\n\nclass IfExp(NodeNG):\n    \"\"\"Class representing an :class:`ast.IfExp` node.\n    >>> import astroid\n    >>> node = astroid.extract_node('value if condition else other')\n    >>> node\n    <IfExp l.1 at 0x7f23b2e9dbe0>\n    \"\"\"\n\n    _astroid_fields = (\"test\", \"body\", \"orelse\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.test: NodeNG | None = None\n        \"\"\"The condition that the statement tests.\"\"\"\n\n        self.body: NodeNG | None = None\n        \"\"\"The contents of the block.\"\"\"\n\n        self.orelse: NodeNG | None = None\n        \"\"\"The contents of the ``else`` block.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        test: NodeNG | None = None,\n        body: NodeNG | None = None,\n        orelse: NodeNG | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param test: The condition that the statement tests.\n\n        :param body: The contents of the block.\n\n        :param orelse: The contents of the ``else`` block.\n        \"\"\"\n        self.test = test\n        self.body = body\n        self.orelse = orelse\n\n    def get_children(self):\n        yield self.test\n        yield self.body\n        yield self.orelse\n\n    def op_left_associative(self):\n        # `1 if True else 2 if False else 3` is parsed as\n        # `1 if True else (2 if False else 3)`\n        return False\n\n\nclass Import(mixins.NoChildrenMixin, mixins.ImportFromMixin, Statement):\n    \"\"\"Class representing an :class:`ast.Import` node.\n    >>> import astroid\n    >>> node = astroid.extract_node('import astroid')\n    >>> node\n    <Import l.1 at 0x7f23b2e4e5c0>\n    \"\"\"\n\n    _other_fields = (\"names\",)\n\n    @decorators.deprecate_default_argument_values(names=\"list[tuple[str, str | None]]\")\n    def __init__(\n        self,\n        names: list[tuple[str, str | None]] | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param names: The names being imported.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.names: list[tuple[str, str | None]] = names or []\n        \"\"\"The names being imported.\n\n        Each entry is a :class:`tuple` of the name being imported,\n        and the alias that the name is assigned to (if any).\n        \"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n\nclass Index(NodeNG):\n    \"\"\"Class representing an :class:`ast.Index` node.\n\n    An :class:`Index` is a simple subscript.\n\n    Deprecated since v2.6.0 - Now part of the :class:`Subscript` node.\n    Will be removed with the release of v2.7.0\n    \"\"\"\n\n\nclass Keyword(NodeNG):\n    \"\"\"Class representing an :class:`ast.keyword` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('function(a_kwarg=True)')\n    >>> node\n    <Call l.1 at 0x7f23b2e9e320>\n    >>> node.keywords\n    [<Keyword l.1 at 0x7f23b2e9e9b0>]\n    \"\"\"\n\n    _astroid_fields = (\"value\",)\n    _other_fields = (\"arg\",)\n\n    def __init__(\n        self,\n        arg: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param arg: The argument being assigned to.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.arg: str | None = arg  # can be None\n        \"\"\"The argument being assigned to.\"\"\"\n\n        self.value: NodeNG | None = None\n        \"\"\"The value being assigned to the keyword argument.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, value: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: The value being assigned to the keyword argument.\n        \"\"\"\n        self.value = value\n\n    def get_children(self):\n        yield self.value\n\n\nclass List(BaseContainer):\n    \"\"\"Class representing an :class:`ast.List` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('[1, 2, 3]')\n    >>> node\n    <List.list l.1 at 0x7f23b2e9e128>\n    \"\"\"\n\n    _other_fields = (\"ctx\",)\n\n    def __init__(\n        self,\n        ctx: Context | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param ctx: Whether the list is assigned to or loaded from.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.ctx: Context | None = ctx\n        \"\"\"Whether the list is assigned to or loaded from.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[List]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def pytype(self):\n        \"\"\"Get the name of the type that this node represents.\n\n        :returns: The name of the type.\n        :rtype: str\n        \"\"\"\n        return \"builtins.list\"\n\n    def getitem(self, index, context=None):\n        \"\"\"Get an item from this node.\n\n        :param index: The node to use as a subscript index.\n        :type index: Const or Slice\n        \"\"\"\n        return _container_getitem(self, self.elts, index, context=context)\n\n\nclass Nonlocal(mixins.NoChildrenMixin, Statement):\n    \"\"\"Class representing an :class:`ast.Nonlocal` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    def function():\n        nonlocal var\n    ''')\n    >>> node\n    <FunctionDef.function l.2 at 0x7f23b2e9e208>\n    >>> node.body[0]\n    <Nonlocal l.3 at 0x7f23b2e9e908>\n    \"\"\"\n\n    _other_fields = (\"names\",)\n\n    def __init__(\n        self,\n        names: list[str],\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param names: The names being declared as not local.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.names: list[str] = names\n        \"\"\"The names being declared as not local.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def _infer_name(self, frame, name):\n        return name\n\n\nclass Pass(mixins.NoChildrenMixin, Statement):\n    \"\"\"Class representing an :class:`ast.Pass` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('pass')\n    >>> node\n    <Pass l.1 at 0x7f23b2e9e748>\n    \"\"\"\n\n\nclass Raise(Statement):\n    \"\"\"Class representing an :class:`ast.Raise` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('raise RuntimeError(\"Something bad happened!\")')\n    >>> node\n    <Raise l.1 at 0x7f23b2e9e828>\n    \"\"\"\n\n    _astroid_fields = (\"exc\", \"cause\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.exc: NodeNG | None = None  # can be None\n        \"\"\"What is being raised.\"\"\"\n\n        self.cause: NodeNG | None = None  # can be None\n        \"\"\"The exception being used to raise this one.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        exc: NodeNG | None = None,\n        cause: NodeNG | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param exc: What is being raised.\n\n        :param cause: The exception being used to raise this one.\n        \"\"\"\n        self.exc = exc\n        self.cause = cause\n\n    def raises_not_implemented(self):\n        \"\"\"Check if this node raises a :class:`NotImplementedError`.\n\n        :returns: True if this node raises a :class:`NotImplementedError`,\n            False otherwise.\n        :rtype: bool\n        \"\"\"\n        if not self.exc:\n            return False\n        return any(\n            name.name == \"NotImplementedError\" for name in self.exc._get_name_nodes()\n        )\n\n    def get_children(self):\n        if self.exc is not None:\n            yield self.exc\n\n        if self.cause is not None:\n            yield self.cause\n\n\nclass Return(Statement):\n    \"\"\"Class representing an :class:`ast.Return` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('return True')\n    >>> node\n    <Return l.1 at 0x7f23b8211908>\n    \"\"\"\n\n    _astroid_fields = (\"value\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.value: NodeNG | None = None  # can be None\n        \"\"\"The value being returned.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, value: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: The value being returned.\n        \"\"\"\n        self.value = value\n\n    def get_children(self):\n        if self.value is not None:\n            yield self.value\n\n    def is_tuple_return(self):\n        return isinstance(self.value, Tuple)\n\n    def _get_return_nodes_skip_functions(self):\n        yield self\n\n\nclass Set(BaseContainer):\n    \"\"\"Class representing an :class:`ast.Set` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('{1, 2, 3}')\n    >>> node\n    <Set.set l.1 at 0x7f23b2e71d68>\n    \"\"\"\n\n    def pytype(self):\n        \"\"\"Get the name of the type that this node represents.\n\n        :returns: The name of the type.\n        :rtype: str\n        \"\"\"\n        return \"builtins.set\"\n\n\nclass Slice(NodeNG):\n    \"\"\"Class representing an :class:`ast.Slice` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('things[1:3]')\n    >>> node\n    <Subscript l.1 at 0x7f23b2e71f60>\n    >>> node.slice\n    <Slice l.1 at 0x7f23b2e71e80>\n    \"\"\"\n\n    _astroid_fields = (\"lower\", \"upper\", \"step\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.lower: NodeNG | None = None  # can be None\n        \"\"\"The lower index in the slice.\"\"\"\n\n        self.upper: NodeNG | None = None  # can be None\n        \"\"\"The upper index in the slice.\"\"\"\n\n        self.step: NodeNG | None = None  # can be None\n        \"\"\"The step to take between indexes.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        lower: NodeNG | None = None,\n        upper: NodeNG | None = None,\n        step: NodeNG | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param lower: The lower index in the slice.\n\n        :param upper: The upper index in the slice.\n\n        :param step: The step to take between index.\n        \"\"\"\n        self.lower = lower\n        self.upper = upper\n        self.step = step\n\n    def _wrap_attribute(self, attr):\n        \"\"\"Wrap the empty attributes of the Slice in a Const node.\"\"\"\n        if not attr:\n            const = const_factory(attr)\n            const.parent = self\n            return const\n        return attr\n\n    @cached_property\n    def _proxied(self):\n        builtins = AstroidManager().builtins_module\n        return builtins.getattr(\"slice\")[0]\n\n    def pytype(self):\n        \"\"\"Get the name of the type that this node represents.\n\n        :returns: The name of the type.\n        :rtype: str\n        \"\"\"\n        return \"builtins.slice\"\n\n    def igetattr(self, attrname, context=None):\n        \"\"\"Infer the possible values of the given attribute on the slice.\n\n        :param attrname: The name of the attribute to infer.\n        :type attrname: str\n\n        :returns: The inferred possible values.\n        :rtype: iterable(NodeNG)\n        \"\"\"\n        if attrname == \"start\":\n            yield self._wrap_attribute(self.lower)\n        elif attrname == \"stop\":\n            yield self._wrap_attribute(self.upper)\n        elif attrname == \"step\":\n            yield self._wrap_attribute(self.step)\n        else:\n            yield from self.getattr(attrname, context=context)\n\n    def getattr(self, attrname, context=None):\n        return self._proxied.getattr(attrname, context)\n\n    def get_children(self):\n        if self.lower is not None:\n            yield self.lower\n\n        if self.upper is not None:\n            yield self.upper\n\n        if self.step is not None:\n            yield self.step\n\n\nclass Starred(mixins.ParentAssignTypeMixin, NodeNG):\n    \"\"\"Class representing an :class:`ast.Starred` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('*args')\n    >>> node\n    <Starred l.1 at 0x7f23b2e41978>\n    \"\"\"\n\n    _astroid_fields = (\"value\",)\n    _other_fields = (\"ctx\",)\n\n    def __init__(\n        self,\n        ctx: Context | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param ctx: Whether the list is assigned to or loaded from.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.value: NodeNG | None = None\n        \"\"\"What is being unpacked.\"\"\"\n\n        self.ctx: Context | None = ctx\n        \"\"\"Whether the starred item is assigned to or loaded from.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, value: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: What is being unpacked.\n        \"\"\"\n        self.value = value\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[Starred]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def get_children(self):\n        yield self.value\n\n\nclass Subscript(NodeNG):\n    \"\"\"Class representing an :class:`ast.Subscript` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('things[1:3]')\n    >>> node\n    <Subscript l.1 at 0x7f23b2e71f60>\n    \"\"\"\n\n    _astroid_fields = (\"value\", \"slice\")\n    _other_fields = (\"ctx\",)\n\n    def __init__(\n        self,\n        ctx: Context | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param ctx: Whether the subscripted item is assigned to or loaded from.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.value: NodeNG | None = None\n        \"\"\"What is being indexed.\"\"\"\n\n        self.slice: NodeNG | None = None\n        \"\"\"The slice being used to lookup.\"\"\"\n\n        self.ctx: Context | None = ctx\n        \"\"\"Whether the subscripted item is assigned to or loaded from.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    # pylint: disable=redefined-builtin; had to use the same name as builtin ast module.\n    def postinit(\n        self, value: NodeNG | None = None, slice: NodeNG | None = None\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: What is being indexed.\n\n        :param slice: The slice being used to lookup.\n        \"\"\"\n        self.value = value\n        self.slice = slice\n\n    def get_children(self):\n        yield self.value\n        yield self.slice\n\n\nclass TryExcept(mixins.MultiLineBlockMixin, mixins.BlockRangeMixIn, Statement):\n    \"\"\"Class representing an :class:`ast.TryExcept` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n        try:\n            do_something()\n        except Exception as error:\n            print(\"Error!\")\n        ''')\n    >>> node\n    <TryExcept l.2 at 0x7f23b2e9d908>\n    \"\"\"\n\n    _astroid_fields = (\"body\", \"handlers\", \"orelse\")\n    _multi_line_block_fields = (\"body\", \"handlers\", \"orelse\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.body: list[NodeNG] = []\n        \"\"\"The contents of the block to catch exceptions from.\"\"\"\n\n        self.handlers: list[ExceptHandler] = []\n        \"\"\"The exception handlers.\"\"\"\n\n        self.orelse: list[NodeNG] = []\n        \"\"\"The contents of the ``else`` block.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        body: list[NodeNG] | None = None,\n        handlers: list[ExceptHandler] | None = None,\n        orelse: list[NodeNG] | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param body: The contents of the block to catch exceptions from.\n\n        :param handlers: The exception handlers.\n\n        :param orelse: The contents of the ``else`` block.\n        \"\"\"\n        if body is not None:\n            self.body = body\n        if handlers is not None:\n            self.handlers = handlers\n        if orelse is not None:\n            self.orelse = orelse\n\n    def _infer_name(self, frame, name):\n        return name\n\n    def block_range(self, lineno):\n        \"\"\"Get a range from the given line number to where this node ends.\n\n        :param lineno: The line number to start the range at.\n        :type lineno: int\n\n        :returns: The range of line numbers that this node belongs to,\n            starting at the given line number.\n        :rtype: tuple(int, int)\n        \"\"\"\n        last = None\n        for exhandler in self.handlers:\n            if exhandler.type and lineno == exhandler.type.fromlineno:\n                return lineno, lineno\n            if exhandler.body[0].fromlineno <= lineno <= exhandler.body[-1].tolineno:\n                return lineno, exhandler.body[-1].tolineno\n            if last is None:\n                last = exhandler.body[0].fromlineno - 1\n        return self._elsed_block_range(lineno, self.orelse, last)\n\n    def get_children(self):\n        yield from self.body\n\n        yield from self.handlers or ()\n        yield from self.orelse or ()\n\n\nclass TryFinally(mixins.MultiLineBlockMixin, mixins.BlockRangeMixIn, Statement):\n    \"\"\"Class representing an :class:`ast.TryFinally` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    try:\n        do_something()\n    except Exception as error:\n        print(\"Error!\")\n    finally:\n        print(\"Cleanup!\")\n    ''')\n    >>> node\n    <TryFinally l.2 at 0x7f23b2e41d68>\n    \"\"\"\n\n    _astroid_fields = (\"body\", \"finalbody\")\n    _multi_line_block_fields = (\"body\", \"finalbody\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.body: list[NodeNG | TryExcept] = []\n        \"\"\"The try-except that the finally is attached to.\"\"\"\n\n        self.finalbody: list[NodeNG] = []\n        \"\"\"The contents of the ``finally`` block.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        body: list[NodeNG | TryExcept] | None = None,\n        finalbody: list[NodeNG] | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param body: The try-except that the finally is attached to.\n\n        :param finalbody: The contents of the ``finally`` block.\n        \"\"\"\n        if body is not None:\n            self.body = body\n        if finalbody is not None:\n            self.finalbody = finalbody\n\n    def block_range(self, lineno):\n        \"\"\"Get a range from the given line number to where this node ends.\n\n        :param lineno: The line number to start the range at.\n        :type lineno: int\n\n        :returns: The range of line numbers that this node belongs to,\n            starting at the given line number.\n        :rtype: tuple(int, int)\n        \"\"\"\n        child = self.body[0]\n        # py2.5 try: except: finally:\n        if (\n            isinstance(child, TryExcept)\n            and child.fromlineno == self.fromlineno\n            and child.tolineno >= lineno > self.fromlineno\n        ):\n            return child.block_range(lineno)\n        return self._elsed_block_range(lineno, self.finalbody)\n\n    def get_children(self):\n        yield from self.body\n        yield from self.finalbody\n\n\nclass Tuple(BaseContainer):\n    \"\"\"Class representing an :class:`ast.Tuple` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('(1, 2, 3)')\n    >>> node\n    <Tuple.tuple l.1 at 0x7f23b2e41780>\n    \"\"\"\n\n    _other_fields = (\"ctx\",)\n\n    def __init__(\n        self,\n        ctx: Context | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param ctx: Whether the tuple is assigned to or loaded from.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.ctx: Context | None = ctx\n        \"\"\"Whether the tuple is assigned to or loaded from.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[Tuple]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def pytype(self):\n        \"\"\"Get the name of the type that this node represents.\n\n        :returns: The name of the type.\n        :rtype: str\n        \"\"\"\n        return \"builtins.tuple\"\n\n    def getitem(self, index, context=None):\n        \"\"\"Get an item from this node.\n\n        :param index: The node to use as a subscript index.\n        :type index: Const or Slice\n        \"\"\"\n        return _container_getitem(self, self.elts, index, context=context)\n\n\nclass UnaryOp(NodeNG):\n    \"\"\"Class representing an :class:`ast.UnaryOp` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('-5')\n    >>> node\n    <UnaryOp l.1 at 0x7f23b2e4e198>\n    \"\"\"\n\n    _astroid_fields = (\"operand\",)\n    _other_fields = (\"op\",)\n\n    @decorators.deprecate_default_argument_values(op=\"str\")\n    def __init__(\n        self,\n        op: str | None = None,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param op: The operator.\n\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.op: str | None = op\n        \"\"\"The operator.\"\"\"\n\n        self.operand: NodeNG | None = None\n        \"\"\"What the unary operator is applied to.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, operand: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param operand: What the unary operator is applied to.\n        \"\"\"\n        self.operand = operand\n\n    # This is set by inference.py\n    def _infer_unaryop(self, context=None):\n        raise NotImplementedError\n\n    def type_errors(self, context=None):\n        \"\"\"Get a list of type errors which can occur during inference.\n\n        Each TypeError is represented by a :class:`BadBinaryOperationMessage`,\n        which holds the original exception.\n\n        :returns: The list of possible type errors.\n        :rtype: list(BadBinaryOperationMessage)\n        \"\"\"\n        try:\n            results = self._infer_unaryop(context=context)\n            return [\n                result\n                for result in results\n                if isinstance(result, util.BadUnaryOperationMessage)\n            ]\n        except InferenceError:\n            return []\n\n    def get_children(self):\n        yield self.operand\n\n    def op_precedence(self):\n        if self.op == \"not\":\n            return OP_PRECEDENCE[self.op]\n\n        return super().op_precedence()\n\n\nclass While(mixins.MultiLineBlockMixin, mixins.BlockRangeMixIn, Statement):\n    \"\"\"Class representing an :class:`ast.While` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    while condition():\n        print(\"True\")\n    ''')\n    >>> node\n    <While l.2 at 0x7f23b2e4e390>\n    \"\"\"\n\n    _astroid_fields = (\"test\", \"body\", \"orelse\")\n    _multi_line_block_fields = (\"body\", \"orelse\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.test: NodeNG | None = None\n        \"\"\"The condition that the loop tests.\"\"\"\n\n        self.body: list[NodeNG] = []\n        \"\"\"The contents of the loop.\"\"\"\n\n        self.orelse: list[NodeNG] = []\n        \"\"\"The contents of the ``else`` block.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        test: NodeNG | None = None,\n        body: list[NodeNG] | None = None,\n        orelse: list[NodeNG] | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param test: The condition that the loop tests.\n\n        :param body: The contents of the loop.\n\n        :param orelse: The contents of the ``else`` block.\n        \"\"\"\n        self.test = test\n        if body is not None:\n            self.body = body\n        if orelse is not None:\n            self.orelse = orelse\n\n    @cached_property\n    def blockstart_tolineno(self):\n        \"\"\"The line on which the beginning of this block ends.\n\n        :type: int\n        \"\"\"\n        return self.test.tolineno\n\n    def block_range(self, lineno):\n        \"\"\"Get a range from the given line number to where this node ends.\n\n        :param lineno: The line number to start the range at.\n        :type lineno: int\n\n        :returns: The range of line numbers that this node belongs to,\n            starting at the given line number.\n        :rtype: tuple(int, int)\n        \"\"\"\n        return self._elsed_block_range(lineno, self.orelse)\n\n    def get_children(self):\n        yield self.test\n\n        yield from self.body\n        yield from self.orelse\n\n    def _get_yield_nodes_skip_lambdas(self):\n        \"\"\"A While node can contain a Yield node in the test\"\"\"\n        yield from self.test._get_yield_nodes_skip_lambdas()\n        yield from super()._get_yield_nodes_skip_lambdas()\n\n\nclass With(\n    mixins.MultiLineBlockMixin,\n    mixins.BlockRangeMixIn,\n    mixins.AssignTypeMixin,\n    Statement,\n):\n    \"\"\"Class representing an :class:`ast.With` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    with open(file_path) as file_:\n        print(file_.read())\n    ''')\n    >>> node\n    <With l.2 at 0x7f23b2e4e710>\n    \"\"\"\n\n    _astroid_fields = (\"items\", \"body\")\n    _other_other_fields = (\"type_annotation\",)\n    _multi_line_block_fields = (\"body\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.items: list[tuple[NodeNG, NodeNG | None]] = []\n        \"\"\"The pairs of context managers and the names they are assigned to.\"\"\"\n\n        self.body: list[NodeNG] = []\n        \"\"\"The contents of the ``with`` block.\"\"\"\n\n        self.type_annotation: NodeNG | None = None  # can be None\n        \"\"\"If present, this will contain the type annotation passed by a type comment\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        items: list[tuple[NodeNG, NodeNG | None]] | None = None,\n        body: list[NodeNG] | None = None,\n        type_annotation: NodeNG | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param items: The pairs of context managers and the names\n            they are assigned to.\n\n        :param body: The contents of the ``with`` block.\n        \"\"\"\n        if items is not None:\n            self.items = items\n        if body is not None:\n            self.body = body\n        self.type_annotation = type_annotation\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[With]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    @cached_property\n    def blockstart_tolineno(self):\n        \"\"\"The line on which the beginning of this block ends.\n\n        :type: int\n        \"\"\"\n        return self.items[-1][0].tolineno\n\n    def get_children(self):\n        \"\"\"Get the child nodes below this node.\n\n        :returns: The children.\n        :rtype: iterable(NodeNG)\n        \"\"\"\n        for expr, var in self.items:\n            yield expr\n            if var:\n                yield var\n        yield from self.body\n\n\nclass AsyncWith(With):\n    \"\"\"Asynchronous ``with`` built with the ``async`` keyword.\"\"\"\n\n\nclass Yield(NodeNG):\n    \"\"\"Class representing an :class:`ast.Yield` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('yield True')\n    >>> node\n    <Yield l.1 at 0x7f23b2e4e5f8>\n    \"\"\"\n\n    _astroid_fields = (\"value\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.value: NodeNG | None = None  # can be None\n        \"\"\"The value to yield.\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, value: NodeNG | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: The value to yield.\n        \"\"\"\n        self.value = value\n\n    def get_children(self):\n        if self.value is not None:\n            yield self.value\n\n    def _get_yield_nodes_skip_lambdas(self):\n        yield self\n\n\nclass YieldFrom(Yield):  # TODO value is required, not optional\n    \"\"\"Class representing an :class:`ast.YieldFrom` node.\"\"\"\n\n\nclass DictUnpack(mixins.NoChildrenMixin, NodeNG):\n    \"\"\"Represents the unpacking of dicts into dicts using :pep:`448`.\"\"\"\n\n\nclass FormattedValue(NodeNG):\n    \"\"\"Class representing an :class:`ast.FormattedValue` node.\n\n    Represents a :pep:`498` format string.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('f\"Format {type_}\"')\n    >>> node\n    <JoinedStr l.1 at 0x7f23b2e4ed30>\n    >>> node.values\n    [<Const.str l.1 at 0x7f23b2e4eda0>, <FormattedValue l.1 at 0x7f23b2e4edd8>]\n    \"\"\"\n\n    _astroid_fields = (\"value\", \"format_spec\")\n    _other_fields = (\"conversion\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.value: NodeNG\n        \"\"\"The value to be formatted into the string.\"\"\"\n\n        self.conversion: int | None = None  # can be None\n        \"\"\"The type of formatting to be applied to the value.\n\n        .. seealso::\n            :class:`ast.FormattedValue`\n        \"\"\"\n\n        self.format_spec: NodeNG | None = None  # can be None\n        \"\"\"The formatting to be applied to the value.\n\n        .. seealso::\n            :class:`ast.FormattedValue`\n\n        :type: JoinedStr or None\n        \"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        value: NodeNG,\n        conversion: int | None = None,\n        format_spec: NodeNG | None = None,\n    ) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: The value to be formatted into the string.\n\n        :param conversion: The type of formatting to be applied to the value.\n\n        :param format_spec: The formatting to be applied to the value.\n        :type format_spec: JoinedStr or None\n        \"\"\"\n        self.value = value\n        self.conversion = conversion\n        self.format_spec = format_spec\n\n    def get_children(self):\n        yield self.value\n\n        if self.format_spec is not None:\n            yield self.format_spec\n\n\nclass JoinedStr(NodeNG):\n    \"\"\"Represents a list of string expressions to be joined.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('f\"Format {type_}\"')\n    >>> node\n    <JoinedStr l.1 at 0x7f23b2e4ed30>\n    \"\"\"\n\n    _astroid_fields = (\"values\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.values: list[NodeNG] = []\n        \"\"\"The string expressions to be joined.\n\n        :type: list(FormattedValue or Const)\n        \"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, values: list[NodeNG] | None = None) -> None:\n        \"\"\"Do some setup after initialisation.\n\n        :param value: The string expressions to be joined.\n\n        :type: list(FormattedValue or Const)\n        \"\"\"\n        if values is not None:\n            self.values = values\n\n    def get_children(self):\n        yield from self.values\n\n\nclass NamedExpr(mixins.AssignTypeMixin, NodeNG):\n    \"\"\"Represents the assignment from the assignment expression\n\n    >>> import astroid\n    >>> module = astroid.parse('if a := 1: pass')\n    >>> module.body[0].test\n    <NamedExpr l.1 at 0x7f23b2e4ed30>\n    \"\"\"\n\n    _astroid_fields = (\"target\", \"value\")\n\n    optional_assign = True\n    \"\"\"Whether this node optionally assigns a variable.\n\n    Since NamedExpr are not always called they do not always assign.\"\"\"\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        \"\"\"\n        :param lineno: The line that this node appears on in the source code.\n\n        :param col_offset: The column that this node appears on in the\n            source code.\n\n        :param parent: The parent node in the syntax tree.\n\n        :param end_lineno: The last line this node appears on in the source code.\n\n        :param end_col_offset: The end column this node appears on in the\n            source code. Note: This is after the last symbol.\n        \"\"\"\n        self.target: NodeNG\n        \"\"\"The assignment target\n\n        :type: Name\n        \"\"\"\n\n        self.value: NodeNG\n        \"\"\"The value that gets assigned in the expression\"\"\"\n\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, target: NodeNG, value: NodeNG) -> None:\n        self.target = target\n        self.value = value\n\n    assigned_stmts: ClassVar[AssignedStmtsCall[NamedExpr]]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n    def frame(\n        self, *, future: Literal[None, True] = None\n    ) -> nodes.FunctionDef | nodes.Module | nodes.ClassDef | nodes.Lambda:\n        \"\"\"The first parent frame node.\n\n        A frame node is a :class:`Module`, :class:`FunctionDef`,\n        or :class:`ClassDef`.\n\n        :returns: The first parent frame node.\n        \"\"\"\n        if not self.parent:\n            raise ParentMissingError(target=self)\n\n        # For certain parents NamedExpr evaluate to the scope of the parent\n        if isinstance(self.parent, (Arguments, Keyword, Comprehension)):\n            if not self.parent.parent:\n                raise ParentMissingError(target=self.parent)\n            if not self.parent.parent.parent:\n                raise ParentMissingError(target=self.parent.parent)\n            return self.parent.parent.parent.frame(future=True)\n\n        return self.parent.frame(future=True)\n\n    def scope(self) -> LocalsDictNodeNG:\n        \"\"\"The first parent node defining a new scope.\n        These can be Module, FunctionDef, ClassDef, Lambda, or GeneratorExp nodes.\n\n        :returns: The first parent scope node.\n        \"\"\"\n        if not self.parent:\n            raise ParentMissingError(target=self)\n\n        # For certain parents NamedExpr evaluate to the scope of the parent\n        if isinstance(self.parent, (Arguments, Keyword, Comprehension)):\n            if not self.parent.parent:\n                raise ParentMissingError(target=self.parent)\n            if not self.parent.parent.parent:\n                raise ParentMissingError(target=self.parent.parent)\n            return self.parent.parent.parent.scope()\n\n        return self.parent.scope()\n\n    def set_local(self, name: str, stmt: AssignName) -> None:\n        \"\"\"Define that the given name is declared in the given statement node.\n        NamedExpr's in Arguments, Keyword or Comprehension are evaluated in their\n        parent's parent scope. So we add to their frame's locals.\n\n        .. seealso:: :meth:`scope`\n\n        :param name: The name that is being defined.\n\n        :param stmt: The statement that defines the given name.\n        \"\"\"\n        self.frame(future=True).set_local(name, stmt)\n\n\nclass Unknown(mixins.AssignTypeMixin, NodeNG):\n    \"\"\"This node represents a node in a constructed AST where\n    introspection is not possible.  At the moment, it's only used in\n    the args attribute of FunctionDef nodes where function signature\n    introspection failed.\n    \"\"\"\n\n    name = \"Unknown\"\n\n    def qname(self):\n        return \"Unknown\"\n\n    def _infer(self, context=None, **kwargs):\n        \"\"\"Inference on an Unknown node immediately terminates.\"\"\"\n        yield util.Uninferable\n\n\nclass EvaluatedObject(NodeNG):\n    \"\"\"Contains an object that has already been inferred\n\n    This class is useful to pre-evaluate a particular node,\n    with the resulting class acting as the non-evaluated node.\n    \"\"\"\n\n    name = \"EvaluatedObject\"\n    _astroid_fields = (\"original\",)\n    _other_fields = (\"value\",)\n\n    def __init__(\n        self, original: NodeNG, value: NodeNG | type[util.Uninferable]\n    ) -> None:\n        self.original: NodeNG = original\n        \"\"\"The original node that has already been evaluated\"\"\"\n\n        self.value: NodeNG | type[util.Uninferable] = value\n        \"\"\"The inferred value\"\"\"\n\n        super().__init__(\n            lineno=self.original.lineno,\n            col_offset=self.original.col_offset,\n            parent=self.original.parent,\n        )\n\n    def _infer(\n        self, context: InferenceContext | None = None\n    ) -> Iterator[NodeNG | type[util.Uninferable]]:\n        yield self.value\n\n\n# Pattern matching #######################################################\n\n\nclass Match(Statement):\n    \"\"\"Class representing a :class:`ast.Match` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case 200:\n            ...\n        case _:\n            ...\n    ''')\n    >>> node\n    <Match l.2 at 0x10c24e170>\n    \"\"\"\n\n    _astroid_fields = (\"subject\", \"cases\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        self.subject: NodeNG\n        self.cases: list[MatchCase]\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        *,\n        subject: NodeNG,\n        cases: list[MatchCase],\n    ) -> None:\n        self.subject = subject\n        self.cases = cases\n\n\nclass Pattern(NodeNG):\n    \"\"\"Base class for all Pattern nodes.\"\"\"\n\n\nclass MatchCase(mixins.MultiLineBlockMixin, NodeNG):\n    \"\"\"Class representing a :class:`ast.match_case` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case 200:\n            ...\n    ''')\n    >>> node.cases[0]\n    <MatchCase l.3 at 0x10c24e590>\n    \"\"\"\n\n    _astroid_fields = (\"pattern\", \"guard\", \"body\")\n    _multi_line_block_fields = (\"body\",)\n\n    lineno: None\n    col_offset: None\n    end_lineno: None\n    end_col_offset: None\n\n    def __init__(self, *, parent: NodeNG | None = None) -> None:\n        self.pattern: Pattern\n        self.guard: NodeNG | None\n        self.body: list[NodeNG]\n        super().__init__(parent=parent)\n\n    def postinit(\n        self,\n        *,\n        pattern: Pattern,\n        guard: NodeNG | None,\n        body: list[NodeNG],\n    ) -> None:\n        self.pattern = pattern\n        self.guard = guard\n        self.body = body\n\n\nclass MatchValue(Pattern):\n    \"\"\"Class representing a :class:`ast.MatchValue` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case 200:\n            ...\n    ''')\n    >>> node.cases[0].pattern\n    <MatchValue l.3 at 0x10c24e200>\n    \"\"\"\n\n    _astroid_fields = (\"value\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        self.value: NodeNG\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, *, value: NodeNG) -> None:\n        self.value = value\n\n\nclass MatchSingleton(Pattern):\n    \"\"\"Class representing a :class:`ast.MatchSingleton` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case True:\n            ...\n        case False:\n            ...\n        case None:\n            ...\n    ''')\n    >>> node.cases[0].pattern\n    <MatchSingleton l.3 at 0x10c2282e0>\n    >>> node.cases[1].pattern\n    <MatchSingleton l.5 at 0x10c228af0>\n    >>> node.cases[2].pattern\n    <MatchSingleton l.7 at 0x10c229f90>\n    \"\"\"\n\n    _other_fields = (\"value\",)\n\n    def __init__(\n        self,\n        *,\n        value: Literal[True, False, None],\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n        parent: NodeNG | None = None,\n    ) -> None:\n        self.value = value\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n\nclass MatchSequence(Pattern):\n    \"\"\"Class representing a :class:`ast.MatchSequence` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case [1, 2]:\n            ...\n        case (1, 2, *_):\n            ...\n    ''')\n    >>> node.cases[0].pattern\n    <MatchSequence l.3 at 0x10ca80d00>\n    >>> node.cases[1].pattern\n    <MatchSequence l.5 at 0x10ca80b20>\n    \"\"\"\n\n    _astroid_fields = (\"patterns\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        self.patterns: list[Pattern]\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, *, patterns: list[Pattern]) -> None:\n        self.patterns = patterns\n\n\nclass MatchMapping(mixins.AssignTypeMixin, Pattern):\n    \"\"\"Class representing a :class:`ast.MatchMapping` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case {1: \"Hello\", 2: \"World\", 3: _, **rest}:\n            ...\n    ''')\n    >>> node.cases[0].pattern\n    <MatchMapping l.3 at 0x10c8a8850>\n    \"\"\"\n\n    _astroid_fields = (\"keys\", \"patterns\", \"rest\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        self.keys: list[NodeNG]\n        self.patterns: list[Pattern]\n        self.rest: AssignName | None\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        *,\n        keys: list[NodeNG],\n        patterns: list[Pattern],\n        rest: AssignName | None,\n    ) -> None:\n        self.keys = keys\n        self.patterns = patterns\n        self.rest = rest\n\n    assigned_stmts: ClassVar[\n        Callable[\n            [\n                MatchMapping,\n                AssignName,\n                InferenceContext | None,\n                None,\n            ],\n            Generator[NodeNG, None, None],\n        ]\n    ]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n\nclass MatchClass(Pattern):\n    \"\"\"Class representing a :class:`ast.MatchClass` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case Point2D(0, 0):\n            ...\n        case Point3D(x=0, y=0, z=0):\n            ...\n    ''')\n    >>> node.cases[0].pattern\n    <MatchClass l.3 at 0x10ca83940>\n    >>> node.cases[1].pattern\n    <MatchClass l.5 at 0x10ca80880>\n    \"\"\"\n\n    _astroid_fields = (\"cls\", \"patterns\", \"kwd_patterns\")\n    _other_fields = (\"kwd_attrs\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        self.cls: NodeNG\n        self.patterns: list[Pattern]\n        self.kwd_attrs: list[str]\n        self.kwd_patterns: list[Pattern]\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        *,\n        cls: NodeNG,\n        patterns: list[Pattern],\n        kwd_attrs: list[str],\n        kwd_patterns: list[Pattern],\n    ) -> None:\n        self.cls = cls\n        self.patterns = patterns\n        self.kwd_attrs = kwd_attrs\n        self.kwd_patterns = kwd_patterns\n\n\nclass MatchStar(mixins.AssignTypeMixin, Pattern):\n    \"\"\"Class representing a :class:`ast.MatchStar` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case [1, *_]:\n            ...\n    ''')\n    >>> node.cases[0].pattern.patterns[1]\n    <MatchStar l.3 at 0x10ca809a0>\n    \"\"\"\n\n    _astroid_fields = (\"name\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        self.name: AssignName | None\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, *, name: AssignName | None) -> None:\n        self.name = name\n\n    assigned_stmts: ClassVar[\n        Callable[\n            [\n                MatchStar,\n                AssignName,\n                InferenceContext | None,\n                None,\n            ],\n            Generator[NodeNG, None, None],\n        ]\n    ]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n\nclass MatchAs(mixins.AssignTypeMixin, Pattern):\n    \"\"\"Class representing a :class:`ast.MatchAs` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case [1, a]:\n            ...\n        case {'key': b}:\n            ...\n        case Point2D(0, 0) as c:\n            ...\n        case d:\n            ...\n    ''')\n    >>> node.cases[0].pattern.patterns[1]\n    <MatchAs l.3 at 0x10d0b2da0>\n    >>> node.cases[1].pattern.patterns[0]\n    <MatchAs l.5 at 0x10d0b2920>\n    >>> node.cases[2].pattern\n    <MatchAs l.7 at 0x10d0b06a0>\n    >>> node.cases[3].pattern\n    <MatchAs l.9 at 0x10d09b880>\n    \"\"\"\n\n    _astroid_fields = (\"pattern\", \"name\")\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        self.pattern: Pattern | None\n        self.name: AssignName | None\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(\n        self,\n        *,\n        pattern: Pattern | None,\n        name: AssignName | None,\n    ) -> None:\n        self.pattern = pattern\n        self.name = name\n\n    assigned_stmts: ClassVar[\n        Callable[\n            [\n                MatchAs,\n                AssignName,\n                InferenceContext | None,\n                None,\n            ],\n            Generator[NodeNG, None, None],\n        ]\n    ]\n    \"\"\"Returns the assigned statement (non inferred) according to the assignment type.\n    See astroid/protocols.py for actual implementation.\n    \"\"\"\n\n\nclass MatchOr(Pattern):\n    \"\"\"Class representing a :class:`ast.MatchOr` node.\n\n    >>> import astroid\n    >>> node = astroid.extract_node('''\n    match x:\n        case 400 | 401 | 402:\n            ...\n    ''')\n    >>> node.cases[0].pattern\n    <MatchOr l.3 at 0x10d0b0b50>\n    \"\"\"\n\n    _astroid_fields = (\"patterns\",)\n\n    def __init__(\n        self,\n        lineno: int | None = None,\n        col_offset: int | None = None,\n        parent: NodeNG | None = None,\n        *,\n        end_lineno: int | None = None,\n        end_col_offset: int | None = None,\n    ) -> None:\n        self.patterns: list[Pattern]\n        super().__init__(\n            lineno=lineno,\n            col_offset=col_offset,\n            end_lineno=end_lineno,\n            end_col_offset=end_col_offset,\n            parent=parent,\n        )\n\n    def postinit(self, *, patterns: list[Pattern]) -> None:\n        self.patterns = patterns\n\n\n# constants ##############################################################\n\nCONST_CLS = {\n    list: List,\n    tuple: Tuple,\n    dict: Dict,\n    set: Set,\n    type(None): Const,\n    type(NotImplemented): Const,\n    type(...): Const,\n}\n\n\ndef _update_const_classes():\n    \"\"\"update constant classes, so the keys of CONST_CLS can be reused\"\"\"\n    klasses = (bool, int, float, complex, str, bytes)\n    for kls in klasses:\n        CONST_CLS[kls] = Const\n\n\n_update_const_classes()\n\n\ndef _two_step_initialization(cls, value):\n    instance = cls()\n    instance.postinit(value)\n    return instance\n\n\ndef _dict_initialization(cls, value):\n    if isinstance(value, dict):\n        value = tuple(value.items())\n    return _two_step_initialization(cls, value)\n\n\n_CONST_CLS_CONSTRUCTORS = {\n    List: _two_step_initialization,\n    Tuple: _two_step_initialization,\n    Dict: _dict_initialization,\n    Set: _two_step_initialization,\n    Const: lambda cls, value: cls(value),\n}\n\n\ndef const_factory(value):\n    \"\"\"return an astroid node for a python value\"\"\"\n    # XXX we should probably be stricter here and only consider stuff in\n    # CONST_CLS or do better treatment: in case where value is not in CONST_CLS,\n    # we should rather recall the builder on this value than returning an empty\n    # node (another option being that const_factory shouldn't be called with something\n    # not in CONST_CLS)\n    assert not isinstance(value, NodeNG)\n\n    # Hack for ignoring elements of a sequence\n    # or a mapping, in order to avoid transforming\n    # each element to an AST. This is fixed in 2.0\n    # and this approach is a temporary hack.\n    if isinstance(value, (list, set, tuple, dict)):\n        elts = []\n    else:\n        elts = value\n\n    try:\n        initializer_cls = CONST_CLS[value.__class__]\n        initializer = _CONST_CLS_CONSTRUCTORS[initializer_cls]\n        return initializer(initializer_cls, elts)\n    except (KeyError, AttributeError):\n        node = EmptyNode()\n        node.object = value\n        return node\n"}, "filelevel_patches": {"astroid/nodes/node_classes.py": "@@ -2346,24 +2346,33 @@ def itered(self):\n         \"\"\"\n         return [key for (key, _) in self.items]\n \n-    def getitem(self, index, context=None):\n+    def getitem(\n+        self, index: Const | Slice, context: InferenceContext | None = None\n+    ) -> NodeNG:\n         \"\"\"Get an item from this node.\n \n         :param index: The node to use as a subscript index.\n-        :type index: Const or Slice\n \n         :raises AstroidTypeError: When the given index cannot be used as a\n             subscript index, or if this node is not subscriptable.\n         :raises AstroidIndexError: If the given index does not exist in the\n             dictionary.\n         \"\"\"\n+        # pylint: disable-next=import-outside-toplevel; circular import\n+        from astroid.helpers import safe_infer\n+\n         for key, value in self.items:\n             # TODO(cpopa): no support for overriding yet, {1:2, **{1: 3}}.\n             if isinstance(key, DictUnpack):\n+                inferred_value = safe_infer(value, context)\n+                if not isinstance(inferred_value, Dict):\n+                    continue\n+\n                 try:\n-                    return value.getitem(index, context)\n+                    return inferred_value.getitem(index, context)\n                 except (AstroidTypeError, AstroidIndexError):\n                     continue\n+\n             for inferredkey in key.infer(context):\n                 if inferredkey is util.Uninferable:\n                     continue"}}