node_ng.py 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814
  1. # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
  2. # For details: https://github.com/PyCQA/astroid/blob/main/LICENSE
  3. # Copyright (c) https://github.com/PyCQA/astroid/blob/main/CONTRIBUTORS.txt
  4. from __future__ import annotations
  5. import pprint
  6. import sys
  7. import warnings
  8. from collections.abc import Generator, Iterator
  9. from functools import singledispatch as _singledispatch
  10. from typing import (
  11. TYPE_CHECKING,
  12. Any,
  13. ClassVar,
  14. Tuple,
  15. Type,
  16. TypeVar,
  17. Union,
  18. cast,
  19. overload,
  20. )
  21. from astroid import decorators, util
  22. from astroid.context import InferenceContext
  23. from astroid.exceptions import (
  24. AstroidError,
  25. InferenceError,
  26. ParentMissingError,
  27. StatementMissing,
  28. UseInferenceDefault,
  29. )
  30. from astroid.manager import AstroidManager
  31. from astroid.nodes.as_string import AsStringVisitor
  32. from astroid.nodes.const import OP_PRECEDENCE
  33. from astroid.nodes.utils import Position
  34. from astroid.typing import InferenceErrorInfo, InferenceResult, InferFn
  35. if TYPE_CHECKING:
  36. from astroid import nodes
  37. if sys.version_info >= (3, 8):
  38. from typing import Literal
  39. else:
  40. from typing_extensions import Literal
  41. if sys.version_info >= (3, 8):
  42. from functools import cached_property
  43. else:
  44. from astroid.decorators import cachedproperty as cached_property
  45. # Types for 'NodeNG.nodes_of_class()'
  46. _NodesT = TypeVar("_NodesT", bound="NodeNG")
  47. _NodesT2 = TypeVar("_NodesT2", bound="NodeNG")
  48. _NodesT3 = TypeVar("_NodesT3", bound="NodeNG")
  49. SkipKlassT = Union[None, Type["NodeNG"], Tuple[Type["NodeNG"], ...]]
  50. class NodeNG:
  51. """A node of the new Abstract Syntax Tree (AST).
  52. This is the base class for all Astroid node classes.
  53. """
  54. is_statement: ClassVar[bool] = False
  55. """Whether this node indicates a statement."""
  56. optional_assign: ClassVar[
  57. bool
  58. ] = False # True for For (and for Comprehension if py <3.0)
  59. """Whether this node optionally assigns a variable.
  60. This is for loop assignments because loop won't necessarily perform an
  61. assignment if the loop has no iterations.
  62. This is also the case from comprehensions in Python 2.
  63. """
  64. is_function: ClassVar[bool] = False # True for FunctionDef nodes
  65. """Whether this node indicates a function."""
  66. is_lambda: ClassVar[bool] = False
  67. # Attributes below are set by the builder module or by raw factories
  68. _astroid_fields: ClassVar[tuple[str, ...]] = ()
  69. """Node attributes that contain child nodes.
  70. This is redefined in most concrete classes.
  71. """
  72. _other_fields: ClassVar[tuple[str, ...]] = ()
  73. """Node attributes that do not contain child nodes."""
  74. _other_other_fields: ClassVar[tuple[str, ...]] = ()
  75. """Attributes that contain AST-dependent fields."""
  76. # instance specific inference function infer(node, context)
  77. _explicit_inference: InferFn | None = None
  78. def __init__(
  79. self,
  80. lineno: int | None = None,
  81. col_offset: int | None = None,
  82. parent: NodeNG | None = None,
  83. *,
  84. end_lineno: int | None = None,
  85. end_col_offset: int | None = None,
  86. ) -> None:
  87. """
  88. :param lineno: The line that this node appears on in the source code.
  89. :param col_offset: The column that this node appears on in the
  90. source code.
  91. :param parent: The parent node in the syntax tree.
  92. :param end_lineno: The last line this node appears on in the source code.
  93. :param end_col_offset: The end column this node appears on in the
  94. source code. Note: This is after the last symbol.
  95. """
  96. self.lineno: int | None = lineno
  97. """The line that this node appears on in the source code."""
  98. self.col_offset: int | None = col_offset
  99. """The column that this node appears on in the source code."""
  100. self.parent: NodeNG | None = parent
  101. """The parent node in the syntax tree."""
  102. self.end_lineno: int | None = end_lineno
  103. """The last line this node appears on in the source code."""
  104. self.end_col_offset: int | None = end_col_offset
  105. """The end column this node appears on in the source code.
  106. Note: This is after the last symbol.
  107. """
  108. self.position: Position | None = None
  109. """Position of keyword(s) and name.
  110. Used as fallback for block nodes which might not provide good
  111. enough positional information. E.g. ClassDef, FunctionDef.
  112. """
  113. def infer(
  114. self, context: InferenceContext | None = None, **kwargs: Any
  115. ) -> Generator[InferenceResult, None, None]:
  116. """Get a generator of the inferred values.
  117. This is the main entry point to the inference system.
  118. .. seealso:: :ref:`inference`
  119. If the instance has some explicit inference function set, it will be
  120. called instead of the default interface.
  121. :returns: The inferred values.
  122. :rtype: iterable
  123. """
  124. if context is not None:
  125. context = context.extra_context.get(self, context)
  126. if self._explicit_inference is not None:
  127. # explicit_inference is not bound, give it self explicitly
  128. try:
  129. # pylint: disable=not-callable
  130. results = list(self._explicit_inference(self, context, **kwargs))
  131. if context is not None:
  132. context.nodes_inferred += len(results)
  133. yield from results
  134. return
  135. except UseInferenceDefault:
  136. pass
  137. if not context:
  138. # nodes_inferred?
  139. yield from self._infer(context=context, **kwargs)
  140. return
  141. key = (self, context.lookupname, context.callcontext, context.boundnode)
  142. if key in context.inferred:
  143. yield from context.inferred[key]
  144. return
  145. results = []
  146. # Limit inference amount to help with performance issues with
  147. # exponentially exploding possible results.
  148. limit = AstroidManager.max_inferable_values
  149. for i, result in enumerate(self._infer(context=context, **kwargs)):
  150. if i >= limit or (context.nodes_inferred > context.max_inferred):
  151. results.append(util.Uninferable)
  152. yield util.Uninferable
  153. break
  154. results.append(result)
  155. yield result
  156. context.nodes_inferred += 1
  157. # Cache generated results for subsequent inferences of the
  158. # same node using the same context
  159. context.inferred[key] = tuple(results)
  160. return
  161. def _repr_name(self) -> str:
  162. """Get a name for nice representation.
  163. This is either :attr:`name`, :attr:`attrname`, or the empty string.
  164. :returns: The nice name.
  165. :rtype: str
  166. """
  167. if all(name not in self._astroid_fields for name in ("name", "attrname")):
  168. return getattr(self, "name", "") or getattr(self, "attrname", "")
  169. return ""
  170. def __str__(self) -> str:
  171. rname = self._repr_name()
  172. cname = type(self).__name__
  173. if rname:
  174. string = "%(cname)s.%(rname)s(%(fields)s)"
  175. alignment = len(cname) + len(rname) + 2
  176. else:
  177. string = "%(cname)s(%(fields)s)"
  178. alignment = len(cname) + 1
  179. result = []
  180. for field in self._other_fields + self._astroid_fields:
  181. value = getattr(self, field)
  182. width = 80 - len(field) - alignment
  183. lines = pprint.pformat(value, indent=2, width=width).splitlines(True)
  184. inner = [lines[0]]
  185. for line in lines[1:]:
  186. inner.append(" " * alignment + line)
  187. result.append(f"{field}={''.join(inner)}")
  188. return string % {
  189. "cname": cname,
  190. "rname": rname,
  191. "fields": (",\n" + " " * alignment).join(result),
  192. }
  193. def __repr__(self) -> str:
  194. rname = self._repr_name()
  195. if rname:
  196. string = "<%(cname)s.%(rname)s l.%(lineno)s at 0x%(id)x>"
  197. else:
  198. string = "<%(cname)s l.%(lineno)s at 0x%(id)x>"
  199. return string % {
  200. "cname": type(self).__name__,
  201. "rname": rname,
  202. "lineno": self.fromlineno,
  203. "id": id(self),
  204. }
  205. def accept(self, visitor):
  206. """Visit this node using the given visitor."""
  207. func = getattr(visitor, "visit_" + self.__class__.__name__.lower())
  208. return func(self)
  209. def get_children(self) -> Iterator[NodeNG]:
  210. """Get the child nodes below this node."""
  211. for field in self._astroid_fields:
  212. attr = getattr(self, field)
  213. if attr is None:
  214. continue
  215. if isinstance(attr, (list, tuple)):
  216. yield from attr
  217. else:
  218. yield attr
  219. yield from ()
  220. def last_child(self) -> NodeNG | None:
  221. """An optimized version of list(get_children())[-1]."""
  222. for field in self._astroid_fields[::-1]:
  223. attr = getattr(self, field)
  224. if not attr: # None or empty list / tuple
  225. continue
  226. if isinstance(attr, (list, tuple)):
  227. return attr[-1]
  228. return attr
  229. return None
  230. def node_ancestors(self) -> Iterator[NodeNG]:
  231. """Yield parent, grandparent, etc until there are no more."""
  232. parent = self.parent
  233. while parent is not None:
  234. yield parent
  235. parent = parent.parent
  236. def parent_of(self, node) -> bool:
  237. """Check if this node is the parent of the given node.
  238. :param node: The node to check if it is the child.
  239. :type node: NodeNG
  240. :returns: Whether this node is the parent of the given node.
  241. """
  242. return any(self is parent for parent in node.node_ancestors())
  243. @overload
  244. def statement(self, *, future: None = ...) -> nodes.Statement | nodes.Module:
  245. ...
  246. @overload
  247. def statement(self, *, future: Literal[True]) -> nodes.Statement:
  248. ...
  249. def statement(
  250. self, *, future: Literal[None, True] = None
  251. ) -> nodes.Statement | nodes.Module:
  252. """The first parent node, including self, marked as statement node.
  253. TODO: Deprecate the future parameter and only raise StatementMissing and return
  254. nodes.Statement
  255. :raises AttributeError: If self has no parent attribute
  256. :raises StatementMissing: If self has no parent attribute and future is True
  257. """
  258. if self.is_statement:
  259. return cast("nodes.Statement", self)
  260. if not self.parent:
  261. if future:
  262. raise StatementMissing(target=self)
  263. warnings.warn(
  264. "In astroid 3.0.0 NodeNG.statement() will return either a nodes.Statement "
  265. "or raise a StatementMissing exception. AttributeError will no longer be raised. "
  266. "This behaviour can already be triggered "
  267. "by passing 'future=True' to a statement() call.",
  268. DeprecationWarning,
  269. stacklevel=2,
  270. )
  271. raise AttributeError(f"{self} object has no attribute 'parent'")
  272. return self.parent.statement(future=future)
  273. def frame(
  274. self, *, future: Literal[None, True] = None
  275. ) -> nodes.FunctionDef | nodes.Module | nodes.ClassDef | nodes.Lambda:
  276. """The first parent frame node.
  277. A frame node is a :class:`Module`, :class:`FunctionDef`,
  278. :class:`ClassDef` or :class:`Lambda`.
  279. :returns: The first parent frame node.
  280. """
  281. if self.parent is None:
  282. if future:
  283. raise ParentMissingError(target=self)
  284. warnings.warn(
  285. "In astroid 3.0.0 NodeNG.frame() will return either a Frame node, "
  286. "or raise ParentMissingError. AttributeError will no longer be raised. "
  287. "This behaviour can already be triggered "
  288. "by passing 'future=True' to a frame() call.",
  289. DeprecationWarning,
  290. stacklevel=2,
  291. )
  292. raise AttributeError(f"{self} object has no attribute 'parent'")
  293. return self.parent.frame(future=future)
  294. def scope(self) -> nodes.LocalsDictNodeNG:
  295. """The first parent node defining a new scope.
  296. These can be Module, FunctionDef, ClassDef, Lambda, or GeneratorExp nodes.
  297. :returns: The first parent scope node.
  298. """
  299. if not self.parent:
  300. raise ParentMissingError(target=self)
  301. return self.parent.scope()
  302. def root(self) -> nodes.Module:
  303. """Return the root node of the syntax tree.
  304. :returns: The root node.
  305. """
  306. if self.parent:
  307. return self.parent.root()
  308. return self # type: ignore[return-value] # Only 'Module' does not have a parent node.
  309. def child_sequence(self, child):
  310. """Search for the sequence that contains this child.
  311. :param child: The child node to search sequences for.
  312. :type child: NodeNG
  313. :returns: The sequence containing the given child node.
  314. :rtype: iterable(NodeNG)
  315. :raises AstroidError: If no sequence could be found that contains
  316. the given child.
  317. """
  318. for field in self._astroid_fields:
  319. node_or_sequence = getattr(self, field)
  320. if node_or_sequence is child:
  321. return [node_or_sequence]
  322. # /!\ compiler.ast Nodes have an __iter__ walking over child nodes
  323. if (
  324. isinstance(node_or_sequence, (tuple, list))
  325. and child in node_or_sequence
  326. ):
  327. return node_or_sequence
  328. msg = "Could not find %s in %s's children"
  329. raise AstroidError(msg % (repr(child), repr(self)))
  330. def locate_child(self, child):
  331. """Find the field of this node that contains the given child.
  332. :param child: The child node to search fields for.
  333. :type child: NodeNG
  334. :returns: A tuple of the name of the field that contains the child,
  335. and the sequence or node that contains the child node.
  336. :rtype: tuple(str, iterable(NodeNG) or NodeNG)
  337. :raises AstroidError: If no field could be found that contains
  338. the given child.
  339. """
  340. for field in self._astroid_fields:
  341. node_or_sequence = getattr(self, field)
  342. # /!\ compiler.ast Nodes have an __iter__ walking over child nodes
  343. if child is node_or_sequence:
  344. return field, child
  345. if (
  346. isinstance(node_or_sequence, (tuple, list))
  347. and child in node_or_sequence
  348. ):
  349. return field, node_or_sequence
  350. msg = "Could not find %s in %s's children"
  351. raise AstroidError(msg % (repr(child), repr(self)))
  352. # FIXME : should we merge child_sequence and locate_child ? locate_child
  353. # is only used in are_exclusive, child_sequence one time in pylint.
  354. def next_sibling(self):
  355. """The next sibling statement node.
  356. :returns: The next sibling statement node.
  357. :rtype: NodeNG or None
  358. """
  359. return self.parent.next_sibling()
  360. def previous_sibling(self):
  361. """The previous sibling statement.
  362. :returns: The previous sibling statement node.
  363. :rtype: NodeNG or None
  364. """
  365. return self.parent.previous_sibling()
  366. # these are lazy because they're relatively expensive to compute for every
  367. # single node, and they rarely get looked at
  368. @cached_property
  369. def fromlineno(self) -> int | None:
  370. """The first line that this node appears on in the source code."""
  371. if self.lineno is None:
  372. return self._fixed_source_line()
  373. return self.lineno
  374. @cached_property
  375. def tolineno(self) -> int | None:
  376. """The last line that this node appears on in the source code."""
  377. if self.end_lineno is not None:
  378. return self.end_lineno
  379. if not self._astroid_fields:
  380. # can't have children
  381. last_child = None
  382. else:
  383. last_child = self.last_child()
  384. if last_child is None:
  385. return self.fromlineno
  386. return last_child.tolineno
  387. def _fixed_source_line(self) -> int | None:
  388. """Attempt to find the line that this node appears on.
  389. We need this method since not all nodes have :attr:`lineno` set.
  390. """
  391. line = self.lineno
  392. _node = self
  393. try:
  394. while line is None:
  395. _node = next(_node.get_children())
  396. line = _node.lineno
  397. except StopIteration:
  398. parent = self.parent
  399. while parent and line is None:
  400. line = parent.lineno
  401. parent = parent.parent
  402. return line
  403. def block_range(self, lineno):
  404. """Get a range from the given line number to where this node ends.
  405. :param lineno: The line number to start the range at.
  406. :type lineno: int
  407. :returns: The range of line numbers that this node belongs to,
  408. starting at the given line number.
  409. :rtype: tuple(int, int or None)
  410. """
  411. return lineno, self.tolineno
  412. def set_local(self, name: str, stmt: NodeNG) -> None:
  413. """Define that the given name is declared in the given statement node.
  414. This definition is stored on the parent scope node.
  415. .. seealso:: :meth:`scope`
  416. :param name: The name that is being defined.
  417. :param stmt: The statement that defines the given name.
  418. """
  419. assert self.parent
  420. self.parent.set_local(name, stmt)
  421. @overload
  422. def nodes_of_class(
  423. self,
  424. klass: type[_NodesT],
  425. skip_klass: SkipKlassT = ...,
  426. ) -> Iterator[_NodesT]:
  427. ...
  428. @overload
  429. def nodes_of_class(
  430. self,
  431. klass: tuple[type[_NodesT], type[_NodesT2]],
  432. skip_klass: SkipKlassT = ...,
  433. ) -> Iterator[_NodesT] | Iterator[_NodesT2]:
  434. ...
  435. @overload
  436. def nodes_of_class(
  437. self,
  438. klass: tuple[type[_NodesT], type[_NodesT2], type[_NodesT3]],
  439. skip_klass: SkipKlassT = ...,
  440. ) -> Iterator[_NodesT] | Iterator[_NodesT2] | Iterator[_NodesT3]:
  441. ...
  442. @overload
  443. def nodes_of_class(
  444. self,
  445. klass: tuple[type[_NodesT], ...],
  446. skip_klass: SkipKlassT = ...,
  447. ) -> Iterator[_NodesT]:
  448. ...
  449. def nodes_of_class( # type: ignore[misc] # mypy doesn't correctly recognize the overloads
  450. self,
  451. klass: (
  452. type[_NodesT]
  453. | tuple[type[_NodesT], type[_NodesT2]]
  454. | tuple[type[_NodesT], type[_NodesT2], type[_NodesT3]]
  455. | tuple[type[_NodesT], ...]
  456. ),
  457. skip_klass: SkipKlassT = None,
  458. ) -> Iterator[_NodesT] | Iterator[_NodesT2] | Iterator[_NodesT3]:
  459. """Get the nodes (including this one or below) of the given types.
  460. :param klass: The types of node to search for.
  461. :param skip_klass: The types of node to ignore. This is useful to ignore
  462. subclasses of :attr:`klass`.
  463. :returns: The node of the given types.
  464. """
  465. if isinstance(self, klass):
  466. yield self
  467. if skip_klass is None:
  468. for child_node in self.get_children():
  469. yield from child_node.nodes_of_class(klass, skip_klass)
  470. return
  471. for child_node in self.get_children():
  472. if isinstance(child_node, skip_klass):
  473. continue
  474. yield from child_node.nodes_of_class(klass, skip_klass)
  475. @decorators.cached
  476. def _get_assign_nodes(self):
  477. return []
  478. def _get_name_nodes(self):
  479. for child_node in self.get_children():
  480. yield from child_node._get_name_nodes()
  481. def _get_return_nodes_skip_functions(self):
  482. yield from ()
  483. def _get_yield_nodes_skip_lambdas(self):
  484. yield from ()
  485. def _infer_name(self, frame, name):
  486. # overridden for ImportFrom, Import, Global, TryExcept, TryStar and Arguments
  487. pass
  488. def _infer(
  489. self, context: InferenceContext | None = None, **kwargs: Any
  490. ) -> Generator[InferenceResult, None, InferenceErrorInfo | None]:
  491. """We don't know how to resolve a statement by default."""
  492. # this method is overridden by most concrete classes
  493. raise InferenceError(
  494. "No inference function for {node!r}.", node=self, context=context
  495. )
  496. def inferred(self):
  497. """Get a list of the inferred values.
  498. .. seealso:: :ref:`inference`
  499. :returns: The inferred values.
  500. :rtype: list
  501. """
  502. return list(self.infer())
  503. def instantiate_class(self):
  504. """Instantiate an instance of the defined class.
  505. .. note::
  506. On anything other than a :class:`ClassDef` this will return self.
  507. :returns: An instance of the defined class.
  508. :rtype: object
  509. """
  510. return self
  511. def has_base(self, node) -> bool:
  512. """Check if this node inherits from the given type.
  513. :param node: The node defining the base to look for.
  514. Usually this is a :class:`Name` node.
  515. :type node: NodeNG
  516. """
  517. return False
  518. def callable(self) -> bool:
  519. """Whether this node defines something that is callable.
  520. :returns: Whether this defines something that is callable.
  521. """
  522. return False
  523. def eq(self, value) -> bool:
  524. return False
  525. def as_string(self) -> str:
  526. """Get the source code that this node represents."""
  527. return AsStringVisitor()(self)
  528. def repr_tree(
  529. self,
  530. ids=False,
  531. include_linenos=False,
  532. ast_state=False,
  533. indent=" ",
  534. max_depth=0,
  535. max_width=80,
  536. ) -> str:
  537. """Get a string representation of the AST from this node.
  538. :param ids: If true, includes the ids with the node type names.
  539. :type ids: bool
  540. :param include_linenos: If true, includes the line numbers and
  541. column offsets.
  542. :type include_linenos: bool
  543. :param ast_state: If true, includes information derived from
  544. the whole AST like local and global variables.
  545. :type ast_state: bool
  546. :param indent: A string to use to indent the output string.
  547. :type indent: str
  548. :param max_depth: If set to a positive integer, won't return
  549. nodes deeper than max_depth in the string.
  550. :type max_depth: int
  551. :param max_width: Attempt to format the output string to stay
  552. within this number of characters, but can exceed it under some
  553. circumstances. Only positive integer values are valid, the default is 80.
  554. :type max_width: int
  555. :returns: The string representation of the AST.
  556. :rtype: str
  557. """
  558. @_singledispatch
  559. def _repr_tree(node, result, done, cur_indent="", depth=1):
  560. """Outputs a representation of a non-tuple/list, non-node that's
  561. contained within an AST, including strings.
  562. """
  563. lines = pprint.pformat(
  564. node, width=max(max_width - len(cur_indent), 1)
  565. ).splitlines(True)
  566. result.append(lines[0])
  567. result.extend([cur_indent + line for line in lines[1:]])
  568. return len(lines) != 1
  569. # pylint: disable=unused-variable,useless-suppression; doesn't understand singledispatch
  570. @_repr_tree.register(tuple)
  571. @_repr_tree.register(list)
  572. def _repr_seq(node, result, done, cur_indent="", depth=1):
  573. """Outputs a representation of a sequence that's contained within an
  574. AST.
  575. """
  576. cur_indent += indent
  577. result.append("[")
  578. if not node:
  579. broken = False
  580. elif len(node) == 1:
  581. broken = _repr_tree(node[0], result, done, cur_indent, depth)
  582. elif len(node) == 2:
  583. broken = _repr_tree(node[0], result, done, cur_indent, depth)
  584. if not broken:
  585. result.append(", ")
  586. else:
  587. result.append(",\n")
  588. result.append(cur_indent)
  589. broken = _repr_tree(node[1], result, done, cur_indent, depth) or broken
  590. else:
  591. result.append("\n")
  592. result.append(cur_indent)
  593. for child in node[:-1]:
  594. _repr_tree(child, result, done, cur_indent, depth)
  595. result.append(",\n")
  596. result.append(cur_indent)
  597. _repr_tree(node[-1], result, done, cur_indent, depth)
  598. broken = True
  599. result.append("]")
  600. return broken
  601. # pylint: disable=unused-variable,useless-suppression; doesn't understand singledispatch
  602. @_repr_tree.register(NodeNG)
  603. def _repr_node(node, result, done, cur_indent="", depth=1):
  604. """Outputs a strings representation of an astroid node."""
  605. if node in done:
  606. result.append(
  607. indent + f"<Recursion on {type(node).__name__} with id={id(node)}"
  608. )
  609. return False
  610. done.add(node)
  611. if max_depth and depth > max_depth:
  612. result.append("...")
  613. return False
  614. depth += 1
  615. cur_indent += indent
  616. if ids:
  617. result.append(f"{type(node).__name__}<0x{id(node):x}>(\n")
  618. else:
  619. result.append(f"{type(node).__name__}(")
  620. fields = []
  621. if include_linenos:
  622. fields.extend(("lineno", "col_offset"))
  623. fields.extend(node._other_fields)
  624. fields.extend(node._astroid_fields)
  625. if ast_state:
  626. fields.extend(node._other_other_fields)
  627. if not fields:
  628. broken = False
  629. elif len(fields) == 1:
  630. result.append(f"{fields[0]}=")
  631. broken = _repr_tree(
  632. getattr(node, fields[0]), result, done, cur_indent, depth
  633. )
  634. else:
  635. result.append("\n")
  636. result.append(cur_indent)
  637. for field in fields[:-1]:
  638. # TODO: Remove this after removal of the 'doc' attribute
  639. if field == "doc":
  640. continue
  641. result.append(f"{field}=")
  642. _repr_tree(getattr(node, field), result, done, cur_indent, depth)
  643. result.append(",\n")
  644. result.append(cur_indent)
  645. result.append(f"{fields[-1]}=")
  646. _repr_tree(getattr(node, fields[-1]), result, done, cur_indent, depth)
  647. broken = True
  648. result.append(")")
  649. return broken
  650. result: list[str] = []
  651. _repr_tree(self, result, set())
  652. return "".join(result)
  653. def bool_value(self, context: InferenceContext | None = None):
  654. """Determine the boolean value of this node.
  655. The boolean value of a node can have three
  656. possible values:
  657. * False: For instance, empty data structures,
  658. False, empty strings, instances which return
  659. explicitly False from the __nonzero__ / __bool__
  660. method.
  661. * True: Most of constructs are True by default:
  662. classes, functions, modules etc
  663. * Uninferable: The inference engine is uncertain of the
  664. node's value.
  665. :returns: The boolean value of this node.
  666. :rtype: bool or Uninferable
  667. """
  668. return util.Uninferable
  669. def op_precedence(self):
  670. # Look up by class name or default to highest precedence
  671. return OP_PRECEDENCE.get(self.__class__.__name__, len(OP_PRECEDENCE))
  672. def op_left_associative(self) -> Literal[True]:
  673. # Everything is left associative except `**` and IfExp
  674. return True