forked from jtriley/StarCluster
-
Notifications
You must be signed in to change notification settings - Fork 1
/
check.py
executable file
·170 lines (142 loc) · 5.14 KB
/
check.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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#!/usr/bin/env python
import os
import re
import ast
import sys
import glob
import subprocess
import pep8
from pyflakes import checker
def check(codeString, filename):
"""
Check the Python source given by C{codeString} for flakes.
@param codeString: The Python source to check.
@type codeString: C{str}
@param filename: The name of the file the source came from, used to report
errors.
@type filename: C{str}
@return: The number of warnings emitted.
@rtype: C{int}
"""
# First, compile into an AST and handle syntax errors.
try:
tree = compile(codeString, filename, "exec", ast.PyCF_ONLY_AST)
except SyntaxError, value:
msg = value.args[0]
(lineno, offset, text) = value.lineno, value.offset, value.text
# If there's an encoding problem with the file, the text is None.
if text is None:
# Avoid using msg, since for the only known case, it contains a
# bogus message that claims the encoding the file declared was
# unknown.
print >> sys.stderr, "%s: problem decoding source" % (filename, )
else:
line = text.splitlines()[-1]
if offset is not None:
offset = offset - (len(text) - len(line))
print >> sys.stderr, '%s:%d: %s' % (filename, lineno, msg)
print >> sys.stderr, line
if offset is not None:
print >> sys.stderr, " " * offset, "^"
return 1
else:
# Okay, it's syntactically valid. Now check it.
w = checker.Checker(tree, filename)
lines = codeString.split('\n')
messages = [message for message in w.messages
if lines[message.lineno - 1].find('pyflakes:ignore') < 0]
messages.sort(lambda a, b: cmp(a.lineno, b.lineno))
for warning in messages:
print warning
return len(messages)
def checkPath(filename):
"""
Check the given path, printing out any warnings detected.
@return: the number of warnings printed
"""
try:
return check(file(filename, 'U').read() + '\n', filename)
except IOError, msg:
print >> sys.stderr, "%s: %s" % (filename, msg.args[1])
return 1
def matches_file(file_name, match_files):
return any(re.compile(match_file).match(file_name) for match_file in
match_files)
def check_files(files, check):
clean = True
print check['start_msg']
for file_name in files:
if not matches_file(file_name, check.get('match_files', [])):
continue
if matches_file(file_name, check.get('ignore_files', [])):
continue
print 'checking file: %s' % file_name
process = subprocess.Popen(check['command'] % file_name,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE, shell=True)
out, err = process.communicate()
output = out + err
if output:
output_lines = ['%s: %s' % (file_name, line) for line in
(out + err).splitlines()]
print '\n'.join(output_lines)
if process.returncode != 0:
clean = False
if not clean:
raise Exception("ERROR: checks failed on some source files")
def find_py_files(path):
for cfile in glob.glob(os.path.join(path, '*')):
if os.path.isdir(cfile):
for py in find_py_files(cfile):
yield py
if cfile.endswith('.py'):
yield cfile
def check_pyflakes(files):
print(">>> Running pyflakes...")
clean = True
for pyfile in files:
if checkPath(pyfile) != 0:
clean = False
if not clean:
raise Exception("ERROR: pyflakes failed on some source files")
def check_pep8(files):
print(">>> Running pep8...")
sg = pep8.StyleGuide(parse_argv=False, config_file=False)
sg.options.repeat = True
sg.options.show_pep8 = True
report = sg.check_files(files)
if report.total_errors:
raise Exception("ERROR: pep8 failed on some source files")
def main(git_index=False, filetypes=['.py']):
files = []
if git_index:
p = subprocess.Popen(['git', 'status', '--porcelain'],
stdout=subprocess.PIPE)
out, err = p.communicate()
modified = re.compile('^(?:MM|M|A)(\s+)(?P<name>.*)')
for line in out.splitlines():
match = modified.match(line)
if match:
f = match.group('name')
if filetypes:
if f.endswith(tuple(filetypes)):
files.append(f)
else:
files.append(f)
else:
src = os.path.join(os.path.dirname(__file__), 'starcluster')
files = list(find_py_files(src))
if not files:
return
try:
check_pyflakes(files)
check_pep8(files)
print(">>> Clean!")
except Exception, e:
print
print(e)
print("ERROR: please fix the errors and re-run this script")
sys.exit(1)
if __name__ == '__main__':
git_index = '--git-index' in sys.argv
main(git_index=git_index)