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 |