UtilitiesPython2/Py2SyntaxChecker.py

branch
Py2 comp.
changeset 2571
e6bb19eb87ea
parent 2552
1e893ea4e366
child 2572
dc6d76ab5d10
equal deleted inserted replaced
2552:1e893ea4e366 2571:e6bb19eb87ea
1 #!/usr/bin/env python2
2 # -*- coding: utf-8 -*-
3
4 # Copyright (c) 2011 - 2013 Detlev Offenbach <detlev@die-offenbachs.de>
5 #
6
7 """
8 Module implementing the syntax check for Python 2.
9 """
10
11 import sys
12 import re
13 import traceback
14
15 from Tools import readEncodedFile, normalizeCode, extractLineFlags
16
17
18 def compile(file, codestring):
19 """
20 Function to compile one Python source file to Python bytecode.
21
22 @param file source filename (string)
23 @param codestring source code (string)
24 @return A tuple indicating status (True = an error was found), the
25 file name, the line number, the index number, the code string
26 and the error message (boolean, string, string, string, string,
27 string). The values are only valid, if the status equals 1.
28 """
29 import __builtin__
30
31 try:
32 if type(file) == type(u""):
33 file = file.encode('utf-8')
34
35 if file.endswith('.ptl'):
36 try:
37 import quixote.ptl_compile
38 except ImportError:
39 return (0, None, None, None, None)
40 template = quixote.ptl_compile.Template(codestring, file)
41 template.compile()
42 else:
43 __builtin__.compile(codestring, file, 'exec')
44 except SyntaxError, detail:
45 index = "0"
46 code = ""
47 error = ""
48 lines = traceback.format_exception_only(SyntaxError, detail)
49 match = re.match('\s*File "(.+)", line (\d+)',
50 lines[0].replace('<string>', '%s' % file))
51 if match is not None:
52 fn, line = match.group(1, 2)
53 if lines[1].startswith('SyntaxError:'):
54 error = re.match('SyntaxError: (.+)', lines[1]).group(1)
55 else:
56 code = re.match('(.+)', lines[1]).group(1)
57 for seLine in lines[2:]:
58 if seLine.startswith('SyntaxError:'):
59 error = re.match('SyntaxError: (.+)', seLine).group(1)
60 elif seLine.rstrip().endswith('^'):
61 index = len(seLine.rstrip()) - 4
62 else:
63 fn = detail.filename
64 line = detail.lineno and detail.lineno or 1
65 error = detail.msg
66 return (1, fn, line, index, code, error)
67 except ValueError, detail:
68 index = "0"
69 code = ""
70 try:
71 fn = detail.filename
72 line = detail.lineno
73 error = detail.msg
74 except AttributeError:
75 fn = file
76 line = 1
77 error = unicode(detail)
78 return (1, fn, line, index, code, error)
79 except StandardError, detail:
80 try:
81 fn = detail.filename
82 line = detail.lineno
83 index = "0"
84 code = ""
85 error = detail.msg
86 return (1, fn, line, index, code, error)
87 except: # this catchall is intentional
88 pass
89
90 return (0, None, None, None, None, None)
91
92
93 def flakesCheck(fileName, codestring, ignoreStarImportWarnings):
94 """
95 Function to perform a pyflakes check.
96
97 @param fileName name of the file (string)
98 @param codestring source code to be checked (string)
99 @param ignoreStarImportWarnings flag indicating to
100 ignore 'star import' warnings (boolean)
101 @return list of strings containing the warnings
102 (marker, file name, line number, message)
103 """
104 from py2flakes.checker import Checker
105 from py2flakes.messages import ImportStarUsed
106
107 strings = []
108 lines = codestring.splitlines()
109 try:
110 warnings = Checker(codestring, fileName)
111 warnings.messages.sort(key=lambda a: a.lineno)
112 for warning in warnings.messages:
113 if ignoreStarImportWarnings and \
114 isinstance(warning, ImportStarUsed):
115 continue
116
117 _fn, lineno, message = warning.getMessageData()
118 if "__IGNORE_WARNING__" not in extractLineFlags(lines[lineno - 1].strip()):
119 strings.extend(["FLAKES_WARNING", _fn, lineno, message])
120 except SyntaxError as err:
121 if err.text.strip():
122 msg = err.text.strip()
123 else:
124 msg = err.msg
125 strings.extend(["FLAKES_ERROR", fileName, err.lineno, msg])
126
127 return strings
128
129 if __name__ == "__main__":
130 if len(sys.argv) < 2 or \
131 len(sys.argv) > 3 or \
132 (len(sys.argv) == 3 and sys.argv[1] not in ["-fi", "-fs"]):
133 print "ERROR"
134 print ""
135 print ""
136 print ""
137 print ""
138 print "No file name given."
139 else:
140 filename = sys.argv[-1]
141 try:
142 codestring = readEncodedFile(filename)[0]
143 codestring = normalizeCode(codestring)
144
145 syntaxerror, fname, line, index, code, error = \
146 compile(filename, codestring)
147 except IOError, msg:
148 # fake a syntax error
149 syntaxerror, fname, line, index, code, error = \
150 1, filename, "1", "0", "", "I/O Error: %s" % unicode(msg)
151
152 if syntaxerror:
153 print "ERROR"
154 else:
155 print "NO_ERROR"
156 print fname
157 print line
158 print index
159 print code
160 print error
161
162 if not syntaxerror and sys.argv[1] in ["-fi", "-fs"]:
163 # do pyflakes check
164 warningLines = flakesCheck(filename, codestring, sys.argv[1] == "-fi")
165 for warningLine in warningLines:
166 print warningLine
167
168 sys.exit(0)
169
170 #
171 # eflag: FileType = Python2

eric ide

mercurial