69 flags = [f.strip() for f in comment.split() |
69 flags = [f.strip() for f in comment.split() |
70 if (f.startswith("__") and f.endswith("__"))] |
70 if (f.startswith("__") and f.endswith("__"))] |
71 return flags |
71 return flags |
72 |
72 |
73 |
73 |
74 def syntaxAndPyflakesCheck(filename, codestring="", checkFlakes=True, |
74 def syntaxAndPyflakesCheck(filename, codestring, checkFlakes=True, |
75 ignoreStarImportWarnings=False): |
75 ignoreStarImportWarnings=False): |
76 """ |
76 """ |
77 Function to compile one Python source file to Python bytecode |
77 Function to compile one Python source file to Python bytecode |
78 and to perform a pyflakes check. |
78 and to perform a pyflakes check. |
79 |
79 |
80 @param filename source filename (string) |
80 @param filename source filename (string) |
81 @keyparam codestring string containing the code to compile (string) |
81 @param codestring string containing the code to compile (string) |
82 @keyparam checkFlakes flag indicating to do a pyflakes check (boolean) |
82 @keyparam checkFlakes flag indicating to do a pyflakes check (boolean) |
83 @keyparam ignoreStarImportWarnings flag indicating to |
83 @keyparam ignoreStarImportWarnings flag indicating to |
84 ignore 'star import' warnings (boolean) |
84 ignore 'star import' warnings (boolean) |
85 @return A tuple indicating status (True = an error was found), the |
85 @return dictionary with the keys 'error' and 'warnings' which |
86 file name, the line number, the index number, the code string |
86 hold a list containing details about the error/ warnings |
87 and the error message (boolean, string, string, string, string, |
87 (file name, line number, column, codestring (only at syntax |
88 string). If checkFlakes is True, a list of strings containing the |
88 errors), the message, a list with arguments for the message) |
89 warnings (marker, file name, line number, message) |
|
90 The values are only valid, if the status is True. |
|
91 """ |
89 """ |
92 try: |
90 try: |
93 import builtins |
91 import builtins |
94 except ImportError: |
92 except ImportError: |
95 import __builtin__ as builtins #__IGNORE_WARNING__ |
93 import __builtin__ as builtins #__IGNORE_WARNING__ |
98 if sys.version_info[0] == 2: |
96 if sys.version_info[0] == 2: |
99 file_enc = filename.encode(sys.getfilesystemencoding()) |
97 file_enc = filename.encode(sys.getfilesystemencoding()) |
100 else: |
98 else: |
101 file_enc = filename |
99 file_enc = filename |
102 |
100 |
103 # It also encoded the code back to avoid 'Encoding declaration in |
101 # It also encode the code back to avoid 'Encoding declaration in |
104 # unicode string' exception on Python2 |
102 # unicode string' exception on Python2 |
105 codestring = normalizeCode(codestring) |
103 codestring = normalizeCode(codestring) |
106 |
104 |
107 if filename.endswith('.ptl'): |
105 if filename.endswith('.ptl'): |
108 try: |
106 try: |
109 import quixote.ptl_compile |
107 import quixote.ptl_compile |
110 except ImportError: |
108 except ImportError: |
111 return (True, filename, 0, 0, '', |
109 return [{'error': (filename, 0, 0, '', |
112 'Quixote plugin not found.', []) |
110 'Quixote plugin not found.')}] |
113 template = quixote.ptl_compile.Template(codestring, file_enc) |
111 template = quixote.ptl_compile.Template(codestring, file_enc) |
114 template.compile() |
112 template.compile() |
115 |
113 else: |
116 # ast.PyCF_ONLY_AST = 1024, speed optimisation |
114 # ast.PyCF_ONLY_AST = 1024, speed optimisation |
117 module = builtins.compile(codestring, file_enc, 'exec', 1024) |
115 module = builtins.compile(codestring, file_enc, 'exec', 1024) |
118 except SyntaxError as detail: |
116 except SyntaxError as detail: |
119 index = 0 |
117 index = 0 |
120 code = "" |
118 code = "" |
121 error = "" |
119 error = "" |
122 lines = traceback.format_exception_only(SyntaxError, detail) |
120 lines = traceback.format_exception_only(SyntaxError, detail) |
137 index = len(seLine.rstrip()) - 4 |
135 index = len(seLine.rstrip()) - 4 |
138 else: |
136 else: |
139 fn = detail.filename |
137 fn = detail.filename |
140 line = detail.lineno or 1 |
138 line = detail.lineno or 1 |
141 error = detail.msg |
139 error = detail.msg |
142 return (True, fn, int(line), index, code, error, []) |
140 return [{'error': (fn, int(line), index, code.strip(), error)}] |
143 except ValueError as detail: |
141 except ValueError as detail: |
144 try: |
142 try: |
145 fn = detail.filename |
143 fn = detail.filename |
146 line = detail.lineno |
144 line = detail.lineno |
147 error = detail.msg |
145 error = detail.msg |
148 except AttributeError: |
146 except AttributeError: |
149 fn = filename |
147 fn = filename |
150 line = 1 |
148 line = 1 |
151 error = str(detail) |
149 error = str(detail) |
152 return (True, fn, line, 0, "", error, []) |
150 return [{'error': (fn, line, 0, "", error)}] |
153 except Exception as detail: |
151 except Exception as detail: |
154 try: |
152 try: |
155 fn = detail.filename |
153 fn = detail.filename |
156 line = detail.lineno |
154 line = detail.lineno |
157 error = detail.msg |
155 error = detail.msg |
158 return (True, fn, line, 0, "", error, []) |
156 return [{'error': (fn, line, 0, "", error)}] |
159 except: # this catchall is intentional |
157 except: # this catchall is intentional |
160 pass |
158 pass |
161 |
159 |
162 # pyflakes |
160 # pyflakes |
163 if not checkFlakes: |
161 if not checkFlakes: |
164 return (False, "", -1, -1, "", "", []) |
162 return [{}] |
165 |
163 |
166 strings = [] |
164 results = [] |
167 lines = codestring.splitlines() |
165 lines = codestring.splitlines() |
168 try: |
166 try: |
169 warnings = Checker(module, filename) |
167 warnings = Checker(module, filename) |
170 warnings.messages.sort(key=lambda a: a.lineno) |
168 warnings.messages.sort(key=lambda a: a.lineno) |
171 for warning in warnings.messages: |
169 for warning in warnings.messages: |
174 continue |
172 continue |
175 |
173 |
176 _fn, lineno, col, message, msg_args = warning.getMessageData() |
174 _fn, lineno, col, message, msg_args = warning.getMessageData() |
177 if "__IGNORE_WARNING__" not in extractLineFlags( |
175 if "__IGNORE_WARNING__" not in extractLineFlags( |
178 lines[lineno - 1].strip()): |
176 lines[lineno - 1].strip()): |
179 strings.append([ |
177 results.append((_fn, lineno, col, "", message, msg_args)) |
180 "FLAKES_WARNING", _fn, lineno, col, message, msg_args]) |
|
181 except SyntaxError as err: |
178 except SyntaxError as err: |
182 if err.text.strip(): |
179 if err.text.strip(): |
183 msg = err.text.strip() |
180 msg = err.text.strip() |
184 else: |
181 else: |
185 msg = err.msg |
182 msg = err.msg |
186 strings.append(["FLAKES_ERROR", filename, err.lineno, 0, msg, ()]) |
183 results.append((filename, err.lineno, 0, "FLAKES_ERROR", msg, [])) |
187 |
184 |
188 return (False, "", -1, -1, "", "", strings) |
185 return [{'warnings': results}] |