-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathexport.py
More file actions
88 lines (74 loc) · 2.51 KB
/
export.py
File metadata and controls
88 lines (74 loc) · 2.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import ast
import json
def export_json(tree, pretty_print=False):
assert(isinstance(tree, ast.AST))
return json.dumps(
export_dict(tree),
indent=4 if pretty_print else None,
sort_keys=True,
separators=(",", ": ") if pretty_print else (",", ":")
)
def export_dict(tree):
assert(isinstance(tree, ast.AST))
return DictExportVisitor().visit(tree)
class DictExportVisitor:
ast_type_field = "ast_type"
def visit(self, node):
node_type = node.__class__.__name__
meth = getattr(self, "visit_" + node_type, self.default_visit)
return meth(node)
def default_visit(self, node):
node_type = node.__class__.__name__
# Add node type
args = {
self.ast_type_field: node_type
}
# Visit fields
for field in node._fields:
assert field != self.ast_type_field
meth = getattr(
self, "visit_field_" + node_type + "_" + field,
self.default_visit_field
)
args[field] = meth(getattr(node, field))
# Visit attributes
for attr in node._attributes:
assert attr != self.ast_type_field
meth = getattr(
self, "visit_attribute_" + node_type + "_" + attr,
self.default_visit_field
)
# Use None as default when lineno/col_offset are not set
args[attr] = meth(getattr(node, attr, None))
return args
def default_visit_field(self, val):
if isinstance(val, ast.AST):
return self.visit(val)
elif isinstance(val, list) or isinstance(val, tuple):
return [self.visit(x) for x in val]
else:
return val
# Special visitors
def visit_str(self, val):
return str(val)
def visit_NoneType(self, val):
return None
def visit_field_NameConstant_value(self, val):
return str(val)
def visit_field_Num_n(self, val):
if isinstance(val, int):
return {
self.ast_type_field: "int",
"n": val
}
elif isinstance(val, float):
return {
self.ast_type_field: "float",
"n": val
}
elif isinstance(val, complex):
return {
self.ast_type_field: "complex",
"n": val.real,
"i": val.imag
}