0
# Tree Manipulation
1
2
Tools and utilities for walking, inspecting, dumping, and modifying AST structures. This module provides comprehensive functionality for AST traversal, node comparison, pretty-printing, and tree transformation operations.
3
4
## Capabilities
5
6
### AST Pretty Printing
7
8
Dump AST structures in a human-readable format with customizable indentation and formatting options for debugging and analysis.
9
10
```python { .api }
11
def dump_tree(node, name=None, initial_indent='', indentation=' ',
12
maxline=120, maxmerged=80):
13
"""
14
Dump AST in pretty-printed format with indentation.
15
16
Parameters:
17
- node: AST node to dump
18
- name: str, optional name for the node
19
- initial_indent: str, initial indentation string (default: '')
20
- indentation: str, indentation string per level (default: 4 spaces)
21
- maxline: int, maximum line length (default: 120)
22
- maxmerged: int, maximum merged line length (default: 80)
23
24
Returns:
25
str: String representation of the AST
26
"""
27
```
28
29
**Usage Example:**
30
31
```python
32
import ast
33
import astor
34
35
code = """
36
def factorial(n):
37
if n <= 1:
38
return 1
39
return n * factorial(n - 1)
40
"""
41
42
tree = ast.parse(code)
43
print(astor.dump_tree(tree))
44
45
# With custom formatting
46
formatted_dump = astor.dump_tree(tree,
47
name="factorial_function",
48
initial_indent=">> ",
49
indentation=" ",
50
maxline=80)
51
print(formatted_dump)
52
```
53
54
### Node Iteration
55
56
Iterate over AST node attributes and list items for systematic node processing and analysis.
57
58
```python { .api }
59
def iter_node(node, name='', unknown=None):
60
"""
61
Iterate over AST node attributes or list items.
62
63
Parameters:
64
- node: AST node or list to iterate over
65
- name: str, name prefix for list items (default: '')
66
- unknown: set, set to collect unknown attributes (default: None)
67
68
Returns:
69
Iterator yielding (value, name) pairs
70
"""
71
```
72
73
**Usage Example:**
74
75
```python
76
import ast
77
import astor
78
79
code = "x = [1, 2, 3]"
80
tree = ast.parse(code)
81
82
# Iterate over all nodes and their attributes
83
for node in ast.walk(tree):
84
print(f"Node: {type(node).__name__}")
85
for value, name in astor.iter_node(node):
86
print(f" {name}: {value}")
87
```
88
89
### Tree Stripping
90
91
Remove all attributes from AST nodes that are not in the standard _fields specification.
92
93
```python { .api }
94
def strip_tree(node):
95
"""
96
Strip AST by removing all attributes not in _fields.
97
98
Parameters:
99
- node: AST node to strip
100
101
Returns:
102
set: Set of names of all stripped attributes
103
"""
104
```
105
106
**Usage Example:**
107
108
```python
109
import ast
110
import astor
111
112
code = "def func(): pass"
113
tree = ast.parse(code)
114
115
# Add some custom attributes
116
for node in ast.walk(tree):
117
node.custom_attr = "custom_value"
118
node.debug_info = {"line": 1}
119
120
# Strip non-standard attributes
121
stripped_attrs = astor.strip_tree(tree)
122
print(f"Stripped attributes: {stripped_attrs}")
123
```
124
125
### Advanced Tree Walking
126
127
The TreeWalk class provides sophisticated tree traversal capabilities with support for both recursive and non-recursive walking patterns.
128
129
```python { .api }
130
class TreeWalk:
131
"""
132
Tree walker that can traverse AST recursively or non-recursively.
133
134
Uses MetaFlatten metaclass for advanced traversal patterns.
135
"""
136
137
def __init__(self, node=None):
138
"""
139
Initialize walker and optionally start walking.
140
141
Parameters:
142
- node: AST node to start walking from (optional)
143
"""
144
145
def setup(self):
146
"""Set up node-specific handlers."""
147
148
def walk(self, node, name=''):
149
"""
150
Walk the tree starting at given node.
151
152
Parameters:
153
- node: AST node to start walking from
154
- name: str, name for the starting node (default: '')
155
"""
156
157
def replace(self, new_node):
158
"""
159
Replace current node with new node.
160
161
Parameters:
162
- new_node: AST node to replace current node with
163
"""
164
165
@property
166
def parent(self):
167
"""
168
Return parent node of current node.
169
170
Returns:
171
AST node that is the parent of the current node
172
"""
173
174
@property
175
def parent_name(self):
176
"""
177
Return parent node and name tuple.
178
179
Returns:
180
tuple: (parent_node, name) pair
181
"""
182
```
183
184
**Usage Example:**
185
186
```python
187
import ast
188
import astor
189
190
class VariableRenamer(astor.TreeWalk):
191
def __init__(self, old_name, new_name):
192
self.old_name = old_name
193
self.new_name = new_name
194
super().__init__()
195
196
def visit_Name(self, node):
197
if node.id == self.old_name:
198
node.id = self.new_name
199
200
code = "def func(x): return x + 1"
201
tree = ast.parse(code)
202
203
# Rename variable 'x' to 'value'
204
renamer = VariableRenamer('x', 'value')
205
renamer.walk(tree)
206
207
print(astor.to_source(tree))
208
```
209
210
### Explicit Node Visitor
211
212
Base class for AST visitors that require explicit handling of all node types, preventing silent failures for unhandled nodes.
213
214
```python { .api }
215
class ExplicitNodeVisitor(ast.NodeVisitor):
216
"""
217
NodeVisitor that removes implicit visits and requires explicit handlers.
218
219
Inherits from ast.NodeVisitor but raises errors for unhandled node types.
220
"""
221
222
def visit(self, node):
223
"""
224
Visit a node with explicit handler requirement.
225
226
Parameters:
227
- node: AST node to visit
228
229
Raises:
230
AttributeError: If no explicit handler exists for the node type
231
"""
232
233
def abort_visit(self, node):
234
"""
235
Default handler that raises AttributeError for unhandled nodes.
236
237
Parameters:
238
- node: AST node that has no explicit handler
239
240
Raises:
241
AttributeError: Always, to indicate missing handler
242
"""
243
```
244
245
### AST Comparison Utilities
246
247
Tools for comparing AST structures and enabling equality operations on AST nodes.
248
249
```python { .api }
250
def allow_ast_comparison():
251
"""
252
Monkey-patch AST nodes to enable equality comparison.
253
254
Modifies AST classes in-place to support == and != operations.
255
"""
256
257
def fast_compare(tree1, tree2):
258
"""
259
Optimized comparison of two AST trees for equality.
260
261
Parameters:
262
- tree1: First AST tree to compare
263
- tree2: Second AST tree to compare
264
265
Returns:
266
bool: True if trees are structurally equal, False otherwise
267
"""
268
```
269
270
**Usage Example:**
271
272
```python
273
import ast
274
import astor
275
276
# Enable AST comparison
277
astor.allow_ast_comparison()
278
279
code1 = "x = 1"
280
code2 = "x = 1"
281
code3 = "y = 1"
282
283
tree1 = ast.parse(code1)
284
tree2 = ast.parse(code2)
285
tree3 = ast.parse(code3)
286
287
# Now AST nodes support equality comparison
288
print(tree1 == tree2) # True
289
print(tree1 == tree3) # False
290
291
# Fast comparison for performance-critical code
292
print(astor.fast_compare(tree1, tree2)) # True
293
print(astor.fast_compare(tree1, tree3)) # False
294
```