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
|
#!/usr/bin/env python
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import ast
import json
import sys
def parse_file(f):
with open(f, "rb") as fh:
content = fh.read()
try:
return ast.parse(content)
except SyntaxError as e:
err = {
"path": f,
"message": e.msg,
"lineno": e.lineno,
"column": e.offset,
"source": e.text,
"rule": "is-parseable",
}
print(json.dumps(err))
def check_compat_py2(f):
"""Check Python 2 and Python 3 compatibility for a file with Python 2"""
root = parse_file(f)
# Ignore empty or un-parseable files.
if not root or not root.body:
return
futures = set()
haveprint = False
future_lineno = 1
may_have_relative_imports = False
for node in ast.walk(root):
if isinstance(node, ast.ImportFrom):
if node.module == "__future__":
future_lineno = node.lineno
futures |= set(n.name for n in node.names)
else:
may_have_relative_imports = True
elif isinstance(node, ast.Import):
may_have_relative_imports = True
elif isinstance(node, ast.Print):
haveprint = True
err = {
"path": f,
"lineno": future_lineno,
"column": 1,
}
if "absolute_import" not in futures and may_have_relative_imports:
err["rule"] = "require absolute_import"
err["message"] = "Missing from __future__ import absolute_import"
print(json.dumps(err))
if haveprint and "print_function" not in futures:
err["rule"] = "require print_function"
err["message"] = "Missing from __future__ import print_function"
print(json.dumps(err))
def check_compat_py3(f):
"""Check Python 3 compatibility of a file with Python 3."""
parse_file(f)
if __name__ == "__main__":
if sys.version_info[0] == 2:
fn = check_compat_py2
else:
fn = check_compat_py3
manifest = sys.argv[1]
with open(manifest, "r") as fh:
files = fh.read().splitlines()
for f in files:
fn(f)
sys.exit(0)
|