node_ng.py 26 KB

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