-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathparse_python_to_json.py
More file actions
100 lines (78 loc) · 2.99 KB
/
parse_python_to_json.py
File metadata and controls
100 lines (78 loc) · 2.99 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
89
90
91
92
93
94
95
96
97
98
99
100
'''
Parses a Python source file into an AST in JSON format. can be viewed
online in a viewer like: http://jsonviewer.stack.hu/
Usage:
python parse_python_to_json.py --pyfile=test.py # pass in code within a file
python parse_python_to_json.py 'print "Hello world"' # pass in code as a string
Try running on its own source code; whoa very META!
python parse_python_to_json.py --pyfile=parse_python_to_json.py
Output: prints JSON to stdout
Created on 2017-01-20 by Philip Guo
'''
import ast
import json
import optparse
#import pprint
import pythonparser # based on https://github.com/m-labs/pythonparser
import os
import sys
#pp = pprint.PrettyPrinter()
class Visitor:
def visit(self, obj, level=0):
"""Visit a node or a list of nodes. Other values are ignored"""
if isinstance(obj, list):
return [self.visit(elt, level) for elt in obj]
elif isinstance(obj, pythonparser.ast.AST):
typ = obj.__class__.__name__
#print >> sys.stderr, obj
loc = None
if hasattr(obj, 'loc'):
loc = {
'start': {'line': obj.loc.begin().line(), 'column': obj.loc.begin().column()},
'end': {'line': obj.loc.end().line(), 'column': obj.loc.end().column()}
}
# TODO: check out obj._locs for more details later if needed
d = {}
d['type'] = typ
d['loc'] = loc
d['_fields'] = obj._fields
for field_name in obj._fields:
val = self.visit(getattr(obj, field_name), level+1)
d[field_name] = val
return d
else:
# let's hope this is a primitive type that's JSON-encodable!
return obj
if __name__ == "__main__":
parser = optparse.OptionParser()
parser.add_option("--pyfile", action="store", dest="pyfile",
help="Take input from a Python source file")
parser.add_option("--pp", action="store_true",
help="Pretty-print JSON for human viewing")
(options, args) = parser.parse_args()
if options.pyfile:
code = open(options.pyfile).read()
else:
code = args[0]
# make sure it ends with a newline to get parse() to work:
if code[-1] != '\n':
code += '\n'
indent_level = None
if options.pp:
indent_level = 2
try:
p = pythonparser.parse(code)
v = Visitor()
res = v.visit(p)
print json.dumps(res, indent=indent_level)
except pythonparser.diagnostic.Error as e:
error_obj = {'type': 'parse_error'}
diag = e.diagnostic
loc = diag.location
error_obj['loc'] = {
'start': {'line': loc.begin().line(), 'column': loc.begin().column()},
'end': {'line': loc.end().line(), 'column': loc.end().column()}
}
error_obj['message'] = diag.message()
print json.dumps(error_obj, indent=indent_level)
sys.exit(1)