UtilitiesPython2/Py2SyntaxChecker.py

changeset 802
e8882d16384c
parent 795
917f1945355c
child 805
83ca4d1ff648
equal deleted inserted replaced
801:16f9875e278b 802:e8882d16384c
9 9
10 import sys 10 import sys
11 import re 11 import re
12 import traceback 12 import traceback
13 from codecs import BOM_UTF8, BOM_UTF16, BOM_UTF32 13 from codecs import BOM_UTF8, BOM_UTF16, BOM_UTF32
14
15 from py2flakes.checker import Checker
16 from py2flakes.messages import ImportStarUsed
14 17
15 coding_regexps = [ 18 coding_regexps = [
16 (2, re.compile(r'''coding[:=]\s*([-\w_.]+)''')), 19 (2, re.compile(r'''coding[:=]\s*([-\w_.]+)''')),
17 (1, re.compile(r'''<\?xml.*\bencoding\s*=\s*['"]([-\w_.]+)['"]\?>''')), 20 (1, re.compile(r'''<\?xml.*\bencoding\s*=\s*['"]([-\w_.]+)['"]\?>''')),
18 ] 21 ]
70 """ 73 """
71 Function to compile one Python source file to Python bytecode. 74 Function to compile one Python source file to Python bytecode.
72 75
73 @param file source filename (string) 76 @param file source filename (string)
74 @return A tuple indicating status (1 = an error was found), the 77 @return A tuple indicating status (1 = an error was found), the
75 filename, the linenumber, the code string and the error message 78 filename, the linenumber, the code string, the error message
76 (boolean, string, string, string, string). The values are only 79 and the full source code (boolean, string, string, string,
77 valid, if the status equals 1. 80 string, string). The values are only valid, if the status
81 equals 1.
78 """ 82 """
79 import __builtin__ 83 import __builtin__
80 try: 84 try:
81 f = open(file) 85 f = open(file)
82 codestring, encoding = decode(f.read()) 86 codestring, encoding = decode(f.read())
83 f.close() 87 f.close()
84 except IOError, msg: 88 except IOError, msg:
85 return (1, file, "1", "", "I/O Error: %s" % unicode(msg)) 89 return (1, file, "1", "", "I/O Error: %s" % unicode(msg), "")
86 90
87 if type(codestring) == type(u""): 91 if type(codestring) == type(u""):
88 codestring = codestring.encode('utf-8') 92 codestring = codestring.encode('utf-8')
89 codestring = codestring.replace("\r\n","\n") 93 codestring = codestring.replace("\r\n","\n")
90 codestring = codestring.replace("\r","\n") 94 codestring = codestring.replace("\r","\n")
101 import quixote.ptl_compile 105 import quixote.ptl_compile
102 except ImportError: 106 except ImportError:
103 return (0, None, None, None, None) 107 return (0, None, None, None, None)
104 template = quixote.ptl_compile.Template(codestring, file) 108 template = quixote.ptl_compile.Template(codestring, file)
105 template.compile() 109 template.compile()
106 codeobject = template.code 110 else:
107 else: 111 __builtin__.compile(codestring, file, 'exec')
108 codeobject = __builtin__.compile(codestring, file, 'exec')
109 except SyntaxError, detail: 112 except SyntaxError, detail:
110 lines = traceback.format_exception_only(SyntaxError, detail) 113 lines = traceback.format_exception_only(SyntaxError, detail)
111 match = re.match('\s*File "(.+)", line (\d+)', 114 match = re.match('\s*File "(.+)", line (\d+)',
112 lines[0].replace('<string>', '%s' % file)) 115 lines[0].replace('<string>', '%s' % file))
113 if match is not None: 116 if match is not None:
124 else: 127 else:
125 fn = detail.filename 128 fn = detail.filename
126 line = detail.lineno and detail.lineno or 1 129 line = detail.lineno and detail.lineno or 1
127 code = "" 130 code = ""
128 error = detail.msg 131 error = detail.msg
129 return (1, fn, line, code, error) 132 return (1, fn, line, code, error, codestring)
130 except ValueError, detail: 133 except ValueError, detail:
131 try: 134 try:
132 fn = detail.filename 135 fn = detail.filename
133 line = detail.lineno 136 line = detail.lineno
134 error = detail.msg 137 error = detail.msg
135 except AttributeError: 138 except AttributeError:
136 fn = file 139 fn = file
137 line = 1 140 line = 1
138 error = unicode(detail) 141 error = unicode(detail)
139 code = "" 142 code = ""
140 return (1, fn, line, code, error) 143 return (1, fn, line, code, error, codestring)
141 except StandardError, detail: 144 except StandardError, detail:
142 try: 145 try:
143 fn = detail.filename 146 fn = detail.filename
144 line = detail.lineno 147 line = detail.lineno
145 code = "" 148 code = ""
146 error = detail.msg 149 error = detail.msg
147 return (1, fn, line, code, error) 150 return (1, fn, line, code, error, codestring)
148 except: # this catchall is intentional 151 except: # this catchall is intentional
149 pass 152 pass
150 153
151 return (0, None, None, None, None) 154 return (0, None, None, None, None, codestring)
155
156 def flakesCheck(fileName, codestring, ignoreStarImportWarnings):
157 """
158 Function to perform a pyflakes check.
159
160 @param fileName name of the file (string)
161 @param codestring source code to be checked (string)
162 @param ignoreStarImportWarnings flag indicating to
163 ignore 'star import' warnings (boolean)
164 @return list of strings containing the warnings
165 (marker, file name, line number, message)
166 """
167 strings = []
168 lines = codestring.splitlines()
169 try:
170 warnings = Checker(codestring, fileName)
171 warnings.messages.sort(key = lambda a: a.lineno)
172 for warning in warnings.messages:
173 if ignoreStarImportWarnings and \
174 isinstance(warning, ImportStarUsed):
175 continue
176
177 _fn, lineno, message = warning.getMessageData()
178 if not lines[lineno - 1].strip()\
179 .endswith("__IGNORE_WARNING__"):
180 strings.extend(["FLAKES_WARNING", _fn, lineno, message])
181 except SyntaxError as err:
182 if err.text.strip():
183 msg = err.text.strip()
184 else:
185 msg = err.msg
186 strings.extend(["FLAKES_ERROR", fileName, err.lineno, msg])
187
188 return strings
152 189
153 if __name__ == "__main__": 190 if __name__ == "__main__":
154 if len(sys.argv) != 2: 191 if len(sys.argv) < 2 or \
192 len(sys.argv) > 3 or \
193 (len(sys.argv) == 3 and sys.argv[1] not in ["-fi", "-fs"]):
155 print "ERROR" 194 print "ERROR"
156 print "" 195 print ""
157 print "" 196 print ""
158 print "" 197 print ""
159 print "No file name given." 198 print "No file name given."
160 else: 199 else:
161 filename = sys.argv[1] 200 filename = sys.argv[-1]
162 res, fname, line, code, error = compile(filename) 201 syntaxerror, fname, line, code, error, codestring = compile(filename)
163 202
164 if res: 203 if syntaxerror:
165 print "ERROR" 204 print "ERROR"
166 else: 205 else:
167 print "NO_ERROR" 206 print "NO_ERROR"
168 print fname 207 print fname
169 print line 208 print line
170 print code 209 print code
171 print error 210 print error
211
212 if not syntaxerror and sys.argv[1] in ["-fi", "-fs"]:
213 # do pyflakes check
214 warningLines = flakesCheck(filename, codestring, sys.argv[1] == "-fi")
215 for warningLine in warningLines:
216 print warningLine
172 217
173 sys.exit(0) 218 sys.exit(0)
174 219
175 # 220 #
176 # eflag: FileType = Python2 221 # eflag: FileType = Python2

eric ide

mercurial