-
Notifications
You must be signed in to change notification settings - Fork 0
/
astdumper.py
executable file
·93 lines (84 loc) · 3.71 KB
/
astdumper.py
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
89
90
91
92
93
#!/usr/bin/python3
import yaml
import inspect
from functools import cmp_to_key
class HumanFriendlyAstDumper(yaml.SafeDumper):
default_order = ['node_type'] #by default, 'node_type' should be always the first element
specialized_orders = {k: ['node_type'] + v for k,v in {
'assign': ['targets', 'value'],
'augassign': ['target', 'op', 'value'],
'name': ['id', 'ctx'],
'attribute': ['value', 'attr', 'ctx'],
'tuple': ['elts', 'ctx'],
'set': ['elts'],
'list': ['elts', 'ctx'],
'dict': ['keys', 'values'],
'listcomp': ['elt', 'generators'],
'dictcomp': ['key', 'value', 'generators'],
'comprehension': ['target', 'iter', 'ifs'],
'subscript': ['value', 'slide', 'ctx'],
'slice': ['lower', 'step', 'upper'],
'boolop': ['op', 'values'],
'binop': ['left', 'op', 'right'],
'compare': ['left', 'opes', 'comparators'],
'call': ['func', 'args', 'starargs', 'keywords', 'kwargs'],
'if': ['test', 'body', 'orelse'],
'ifexp': ['test', 'body', 'orelse'],
'for': ['target', 'iter', 'body', 'orelse'],
'while': ['test', 'body', 'orelse'],
'lambda': ['args', 'body'],
'functiondef': ['name', 'args', 'decorator_list', 'docstring', 'body'],
'classdef': ['name', 'bases', 'decorator_list', 'docstring', 'body'],
'import': ['names'],
'importfrom': ['module', 'level', 'names'],
'alias': ['name', 'asname'],
'tryexcept': ['body', 'handlers', 'orelse'],
'excepthandler': ['type', 'name', 'body'],
'with': ['context_expr', 'optional_vars', 'body'],
}.items()}
def __init__(self, *args, **kwargs):
super(HumanFriendlyAstDumper, self).__init__(*args, **kwargs)
self.add_representer(dict, self.represent_dict)
#materialize the key functions
self._default_key_fun = self._create_key_func(self.default_order)
self._specialized_key_funs = {k: self._create_key_func(v) for k, v in self.specialized_orders.items()}
def represent_dict(self, _, data):
if 'node_type' in data and data['node_type'] in self._specialized_key_funs:
key_fun = self._specialized_key_funs[data['node_type']]
else:
key_fun = self._default_key_fun
items = sorted(data.items(), key=key_fun)
return self.represent_mapping(u'tag:yaml.org,2002:map', items);
@staticmethod
def _create_key_func(order):
"""
returns a function which can be used by the builtin `sorted` as key function
`order` must be an array listing the values in increasing order.
The returned cmp functions uses the ordering specified by `order` whenever possible.
"""
def compare_func(x,y):
x = x[0]
y = y[0]
if x in order and y in order:
return order.index(x) - order.index(y)
elif x in order and y not in order:
return -1
elif x not in order and y in order:
return 1
else:
return -1 if x < y else 1 if x > y else 0
return cmp_to_key(compare_func)
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
data = yaml.load(sys.stdin)
elif len(sys.argv) == 2:
with open(sys.argv[1], 'r') as instream:
data = yaml.load(instream)
else:
print(inspect.cleandoc("""
Usage: astdumper.py [infile]
If infile is not given, input will be read from stdin
"""))
exit(1)
print(yaml.dump(data, Dumper=HumanFriendlyAstDumper))