Coverage for src/_griffe/agents/nodes/ast.py: 57.32%
60 statements
« prev ^ index » next coverage.py v7.6.1, created at 2024-08-15 16:47 +0200
« prev ^ index » next coverage.py v7.6.1, created at 2024-08-15 16:47 +0200
1# This module contains utilities for navigating AST nodes.
3from __future__ import annotations
5from ast import AST
6from typing import Iterator
8from _griffe.exceptions import LastNodeError
11def ast_kind(node: AST) -> str:
12 """Return the kind of an AST node.
14 Parameters:
15 node: The AST node.
17 Returns:
18 The node kind.
19 """
20 return node.__class__.__name__.lower()
23def ast_children(node: AST) -> Iterator[AST]:
24 """Return the children of an AST node.
26 Parameters:
27 node: The AST node.
29 Yields:
30 The node children.
31 """
32 for field_name in node._fields:
33 try:
34 field = getattr(node, field_name)
35 except AttributeError:
36 continue
37 if isinstance(field, AST):
38 field.parent = node # type: ignore[attr-defined]
39 yield field
40 elif isinstance(field, list):
41 for child in field:
42 if isinstance(child, AST):
43 child.parent = node # type: ignore[attr-defined]
44 yield child
47def ast_previous_siblings(node: AST) -> Iterator[AST]:
48 """Return the previous siblings of this node, starting from the closest.
50 Parameters:
51 node: The AST node.
53 Yields:
54 The previous siblings.
55 """
56 for sibling in ast_children(node.parent): # type: ignore[attr-defined]
57 if sibling is not node:
58 yield sibling
59 else:
60 return
63def ast_next_siblings(node: AST) -> Iterator[AST]:
64 """Return the next siblings of this node, starting from the closest.
66 Parameters:
67 node: The AST node.
69 Yields:
70 The next siblings.
71 """
72 siblings = ast_children(node.parent) # type: ignore[attr-defined]
73 for sibling in siblings: 73 ↛ 76line 73 didn't jump to line 76 because the loop on line 73 didn't complete
74 if sibling is node:
75 break
76 yield from siblings
79def ast_siblings(node: AST) -> Iterator[AST]:
80 """Return the siblings of this node.
82 Parameters:
83 node: The AST node.
85 Yields:
86 The siblings.
87 """
88 siblings = ast_children(node.parent) # type: ignore[attr-defined]
89 for sibling in siblings:
90 if sibling is not node:
91 yield sibling
92 else:
93 break
94 yield from siblings
97def ast_previous(node: AST) -> AST:
98 """Return the previous sibling of this node.
100 Parameters:
101 node: The AST node.
103 Raises:
104 LastNodeError: When the node does not have previous siblings.
106 Returns:
107 The sibling.
108 """
109 try:
110 *_, last = ast_previous_siblings(node)
111 except ValueError:
112 raise LastNodeError("there is no previous node") from None
113 return last
116def ast_next(node: AST) -> AST:
117 """Return the next sibling of this node.
119 Parameters:
120 node: The AST node.
122 Raises:
123 LastNodeError: When the node does not have next siblings.
125 Returns:
126 The sibling.
127 """
128 try:
129 return next(ast_next_siblings(node))
130 except StopIteration:
131 raise LastNodeError("there is no next node") from None
134def ast_first_child(node: AST) -> AST:
135 """Return the first child of this node.
137 Parameters:
138 node: The AST node.
140 Raises:
141 LastNodeError: When the node does not have children.
143 Returns:
144 The child.
145 """
146 try:
147 return next(ast_children(node))
148 except StopIteration as error:
149 raise LastNodeError("there are no children node") from error
152def ast_last_child(node: AST) -> AST:
153 """Return the lasts child of this node.
155 Parameters:
156 node: The AST node.
158 Raises:
159 LastNodeError: When the node does not have children.
161 Returns:
162 The child.
163 """
164 try:
165 *_, last = ast_children(node)
166 except ValueError as error:
167 raise LastNodeError("there are no children node") from error
168 return last