19 from E5Gui.E5Application import e5App |
19 from E5Gui.E5Application import e5App |
20 |
20 |
21 from .Pep8Checker import Pep8Checker, Pep8Py2Checker |
21 from .Pep8Checker import Pep8Checker, Pep8Py2Checker |
22 from .Pep8CodeSelectionDialog import Pep8CodeSelectionDialog |
22 from .Pep8CodeSelectionDialog import Pep8CodeSelectionDialog |
23 from .Pep8StatisticsDialog import Pep8StatisticsDialog |
23 from .Pep8StatisticsDialog import Pep8StatisticsDialog |
|
24 from .Pep8Fixer import Pep8Fixer |
24 |
25 |
25 from .Ui_Pep8Dialog import Ui_Pep8Dialog |
26 from .Ui_Pep8Dialog import Ui_Pep8Dialog |
26 |
27 |
27 import UI.PixmapCache |
28 import UI.PixmapCache |
28 import Preferences |
29 import Preferences |
78 UI.PixmapCache.getIcon("clearLeft.png")) |
79 UI.PixmapCache.getIcon("clearLeft.png")) |
79 self.clearButtonExcludeMessages.setIcon( |
80 self.clearButtonExcludeMessages.setIcon( |
80 UI.PixmapCache.getIcon("clearLeft.png")) |
81 UI.PixmapCache.getIcon("clearLeft.png")) |
81 self.clearButtonIncludeMessages.setIcon( |
82 self.clearButtonIncludeMessages.setIcon( |
82 UI.PixmapCache.getIcon("clearLeft.png")) |
83 UI.PixmapCache.getIcon("clearLeft.png")) |
|
84 self.clearButtonFixIssues.setIcon( |
|
85 UI.PixmapCache.getIcon("clearLeft.png")) |
83 self.on_loadDefaultButton_clicked() |
86 self.on_loadDefaultButton_clicked() |
84 |
87 |
85 def __resort(self): |
88 def __resort(self): |
86 """ |
89 """ |
87 Private method to resort the tree. |
90 Private method to resort the tree. |
160 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True) |
163 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True) |
161 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False) |
164 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False) |
162 self.buttonBox.button(QDialogButtonBox.Close).setDefault(True) |
165 self.buttonBox.button(QDialogButtonBox.Close).setDefault(True) |
163 |
166 |
164 self.__data = self.__project.getData("CHECKERSPARMS", "Pep8Checker") |
167 self.__data = self.__project.getData("CHECKERSPARMS", "Pep8Checker") |
165 if self.__data is None or "ExcludeFiles" not in self.__data: |
168 if self.__data is None or \ |
|
169 "ExcludeFiles" not in self.__data or \ |
|
170 len(self.__data) != 6: |
166 # initialize the data structure |
171 # initialize the data structure |
167 self.__data = { |
172 self.__data = { |
168 "ExcludeFiles" : "", |
173 "ExcludeFiles" : "", |
169 "ExcludeMessages" : pep8.DEFAULT_IGNORE, |
174 "ExcludeMessages" : pep8.DEFAULT_IGNORE, |
170 "IncludeMessages" : "", |
175 "IncludeMessages" : "", |
171 "RepeatMessages" : False, |
176 "RepeatMessages" : False, |
|
177 "FixCodes" : "", |
|
178 "FixIssues" : False, |
172 } |
179 } |
173 self.excludeFilesEdit.setText(self.__data["ExcludeFiles"]) |
180 self.excludeFilesEdit.setText(self.__data["ExcludeFiles"]) |
174 self.excludeMessagesEdit.setText(self.__data["ExcludeMessages"]) |
181 self.excludeMessagesEdit.setText(self.__data["ExcludeMessages"]) |
175 self.includeMessagesEdit.setText(self.__data["IncludeMessages"]) |
182 self.includeMessagesEdit.setText(self.__data["IncludeMessages"]) |
176 self.repeatCheckBox.setChecked(self.__data["RepeatMessages"]) |
183 self.repeatCheckBox.setChecked(self.__data["RepeatMessages"]) |
177 |
184 self.fixIssuesEdit.setText(self.__data["FixCodes"]) |
178 def start(self, fn, codestring = "", save = False, repeat = None): |
185 self.fixIssuesCheckBox.setChecked(self.__data["FixIssues"]) |
|
186 |
|
187 def start(self, fn, save = False, repeat = None): |
179 """ |
188 """ |
180 Public slot to start the PEP 8 check. |
189 Public slot to start the PEP 8 check. |
181 |
190 |
182 @param fn file or list of files or directory to be checked |
191 @param fn file or list of files or directory to be checked |
183 (string or list of strings) |
192 (string or list of strings) |
184 @keyparam codestring string containing the code to be checked (string). |
|
185 If this is given, file must be a single file name. |
|
186 @keyparam save flag indicating to save the given |
193 @keyparam save flag indicating to save the given |
187 file/file list/directory (boolean) |
194 file/file list/directory (boolean) |
188 @keyparam repeat state of the repeat check box if it is not None |
195 @keyparam repeat state of the repeat check box if it is not None |
189 (None or boolean) |
196 (None or boolean) |
190 """ |
197 """ |
232 tuple(Preferences.getPython("Python3Extensions")))] |
239 tuple(Preferences.getPython("Python3Extensions")))] |
233 py2files = [f for f in files \ |
240 py2files = [f for f in files \ |
234 if f.endswith( |
241 if f.endswith( |
235 tuple(Preferences.getPython("PythonExtensions")))] |
242 tuple(Preferences.getPython("PythonExtensions")))] |
236 |
243 |
237 if (codestring and len(py3files) == 1) or \ |
244 if len(py3files) + len(py2files) > 0: |
238 (codestring and len(py2files) == 1) or \ |
|
239 (not codestring and len(py3files) + len(py2files) > 0): |
|
240 self.checkProgress.setMaximum(len(py3files) + len(py2files)) |
245 self.checkProgress.setMaximum(len(py3files) + len(py2files)) |
241 QApplication.processEvents() |
246 QApplication.processEvents() |
242 |
247 |
243 # extract the configuration values |
248 # extract the configuration values |
244 excludeMessages = self.excludeMessagesEdit.text() |
249 excludeMessages = self.excludeMessagesEdit.text() |
245 includeMessages = self.includeMessagesEdit.text() |
250 includeMessages = self.includeMessagesEdit.text() |
246 repeatMessages = self.repeatCheckBox.isChecked() |
251 repeatMessages = self.repeatCheckBox.isChecked() |
|
252 fixCodes = self.fixIssuesEdit.text() |
|
253 fixIssues = self.fixIssuesCheckBox.isChecked() and repeatMessages |
247 |
254 |
248 # now go through all the files |
255 # now go through all the files |
249 progress = 0 |
256 progress = 0 |
250 for file in py3files + py2files: |
257 for file in py3files + py2files: |
251 self.checkProgress.setValue(progress) |
258 self.checkProgress.setValue(progress) |
255 self.__resort() |
262 self.__resort() |
256 return |
263 return |
257 |
264 |
258 self.__lastFileItem = None |
265 self.__lastFileItem = None |
259 |
266 |
260 if codestring: |
267 try: |
261 source = codestring.splitlines(True) |
268 source, encoding = Utilities.readEncodedFile(file) |
262 else: |
269 source = source.splitlines(True) |
263 try: |
270 except (UnicodeError, IOError) as msg: |
264 source = Utilities.readEncodedFile(file)[0] |
271 self.noResults = False |
265 # convert eols |
272 self.__createResultItem(file, "1", "1", |
266 source = Utilities.convertLineEnds(source, "\n") |
273 self.trUtf8("Error: {0}").format(str(msg))\ |
267 source = source.splitlines(True) |
274 .rstrip()[1:-1]) |
268 except (UnicodeError, IOError) as msg: |
275 progress += 1 |
269 self.noResults = False |
276 continue |
270 self.__createResultItem(file, "1", "1", |
|
271 self.trUtf8("Error: {0}").format(str(msg))\ |
|
272 .rstrip()[1:-1]) |
|
273 progress += 1 |
|
274 continue |
|
275 |
277 |
276 flags = Utilities.extractFlags(source) |
278 flags = Utilities.extractFlags(source) |
277 ext = os.path.splitext(file)[1] |
279 ext = os.path.splitext(file)[1] |
|
280 if fixIssues: |
|
281 fixer = Pep8Fixer(self.__project, file, source, |
|
282 fixCodes, True) # always fix in place |
|
283 else: |
|
284 fixer = None |
278 if ("FileType" in flags and |
285 if ("FileType" in flags and |
279 flags["FileType"] in ["Python", "Python2"]) or \ |
286 flags["FileType"] in ["Python", "Python2"]) or \ |
280 file in py2files or \ |
287 file in py2files or \ |
281 (ext in [".py", ".pyw"] and \ |
288 (ext in [".py", ".pyw"] and \ |
282 Preferences.getProject("DeterminePyFromProject") and \ |
289 Preferences.getProject("DeterminePyFromProject") and \ |
298 for message in checker.messages: |
305 for message in checker.messages: |
299 fname, lineno, position, text = message |
306 fname, lineno, position, text = message |
300 if not source[lineno - 1].strip()\ |
307 if not source[lineno - 1].strip()\ |
301 .endswith("__IGNORE_WARNING__"): |
308 .endswith("__IGNORE_WARNING__"): |
302 self.noResults = False |
309 self.noResults = False |
|
310 if fixer: |
|
311 fixed, msg = fixer.fixIssue(lineno, position, text) |
|
312 if fixed: |
|
313 text += "\n" + \ |
|
314 self.trUtf8("Fix: {0}").format(msg) |
303 self.__createResultItem( |
315 self.__createResultItem( |
304 fname, lineno, position, text) |
316 fname, lineno, position, text) |
|
317 fixer and fixer.saveFile(encoding) |
305 self.__updateStatistics(checker.statistics) |
318 self.__updateStatistics(checker.statistics) |
306 progress += 1 |
319 progress += 1 |
307 self.checkProgress.setValue(progress) |
320 self.checkProgress.setValue(progress) |
308 QApplication.processEvents() |
321 QApplication.processEvents() |
309 self.__resort() |
322 self.__resort() |
343 data = { |
356 data = { |
344 "ExcludeFiles" : self.excludeFilesEdit.text(), |
357 "ExcludeFiles" : self.excludeFilesEdit.text(), |
345 "ExcludeMessages" : self.excludeMessagesEdit.text(), |
358 "ExcludeMessages" : self.excludeMessagesEdit.text(), |
346 "IncludeMessages" : self.includeMessagesEdit.text(), |
359 "IncludeMessages" : self.includeMessagesEdit.text(), |
347 "RepeatMessages" : self.repeatCheckBox.isChecked(), |
360 "RepeatMessages" : self.repeatCheckBox.isChecked(), |
|
361 "FixCodes" : self.fixIssuesEdit.text(), |
|
362 "FixIssues" : self.fixIssuesCheckBox.isChecked(), |
348 } |
363 } |
349 if data != self.__data: |
364 if data != self.__data: |
350 self.__data = data |
365 self.__data = data |
351 self.__project.setData("CHECKERSPARMS", "Pep8Checker", |
366 self.__project.setData("CHECKERSPARMS", "Pep8Checker", |
352 self.__data) |
367 self.__data) |
360 def on_excludeMessagesSelectButton_clicked(self): |
375 def on_excludeMessagesSelectButton_clicked(self): |
361 """ |
376 """ |
362 Private slot to select the message codes to be excluded via a |
377 Private slot to select the message codes to be excluded via a |
363 selection dialog. |
378 selection dialog. |
364 """ |
379 """ |
365 dlg = Pep8CodeSelectionDialog(self.excludeMessagesEdit.text(), self) |
380 dlg = Pep8CodeSelectionDialog( |
|
381 self.excludeMessagesEdit.text(), False, self) |
366 if dlg.exec_() == QDialog.Accepted: |
382 if dlg.exec_() == QDialog.Accepted: |
367 self.excludeMessagesEdit.setText(dlg.getSelectedCodes()) |
383 self.excludeMessagesEdit.setText(dlg.getSelectedCodes()) |
368 |
384 |
369 @pyqtSlot() |
385 @pyqtSlot() |
370 def on_includeMessagesSelectButton_clicked(self): |
386 def on_includeMessagesSelectButton_clicked(self): |
371 """ |
387 """ |
372 Private slot to select the message codes to be included via a |
388 Private slot to select the message codes to be included via a |
373 selection dialog. |
389 selection dialog. |
374 """ |
390 """ |
375 dlg = Pep8CodeSelectionDialog(self.includeMessagesEdit.text(), self) |
391 dlg = Pep8CodeSelectionDialog( |
|
392 self.includeMessagesEdit.text(), False, self) |
376 if dlg.exec_() == QDialog.Accepted: |
393 if dlg.exec_() == QDialog.Accepted: |
377 self.includeMessagesEdit.setText(dlg.getSelectedCodes()) |
394 self.includeMessagesEdit.setText(dlg.getSelectedCodes()) |
|
395 |
|
396 @pyqtSlot() |
|
397 def on_fixIssuesSelectButton_clicked(self): |
|
398 """ |
|
399 Private slot to select the issue codes to be fixed via a |
|
400 selection dialog. |
|
401 """ |
|
402 dlg = Pep8CodeSelectionDialog( |
|
403 self.fixIssuesEdit.text(), True, self) |
|
404 if dlg.exec_() == QDialog.Accepted: |
|
405 self.fixIssuesEdit.setText(dlg.getSelectedCodes()) |
378 |
406 |
379 @pyqtSlot(QTreeWidgetItem, int) |
407 @pyqtSlot(QTreeWidgetItem, int) |
380 def on_resultList_itemActivated(self, item, column): |
408 def on_resultList_itemActivated(self, item, column): |
381 """ |
409 """ |
382 Private slot to handle the activation of an item. |
410 Private slot to handle the activation of an item. |
456 "PEP8/ExcludeMessages", pep8.DEFAULT_IGNORE)) |
484 "PEP8/ExcludeMessages", pep8.DEFAULT_IGNORE)) |
457 self.includeMessagesEdit.setText(Preferences.Prefs.settings.value( |
485 self.includeMessagesEdit.setText(Preferences.Prefs.settings.value( |
458 "PEP8/IncludeMessages")) |
486 "PEP8/IncludeMessages")) |
459 ## self.repeatCheckBox.setChecked(Preferences.toBool( |
487 ## self.repeatCheckBox.setChecked(Preferences.toBool( |
460 ## Preferences.Prefs.settings.value("PEP8/RepeatMessages"))) |
488 ## Preferences.Prefs.settings.value("PEP8/RepeatMessages"))) |
|
489 self.fixIssuesEdit.setText(Preferences.Prefs.settings.value( |
|
490 "PEP8/FixCodes")) |
|
491 self.fixIssuesCheckBox.setChecked(Preferences.toBool( |
|
492 Preferences.Prefs.settings.value("PEP8/FixIssues"))) |
461 |
493 |
462 @pyqtSlot() |
494 @pyqtSlot() |
463 def on_storeDefaultButton_clicked(self): |
495 def on_storeDefaultButton_clicked(self): |
464 """ |
496 """ |
465 Private slot to store the current configuration values as |
497 Private slot to store the current configuration values as |
471 self.excludeMessagesEdit.text()) |
503 self.excludeMessagesEdit.text()) |
472 Preferences.Prefs.settings.setValue("PEP8/IncludeMessages", |
504 Preferences.Prefs.settings.setValue("PEP8/IncludeMessages", |
473 self.includeMessagesEdit.text()) |
505 self.includeMessagesEdit.text()) |
474 ## Preferences.Prefs.settings.setValue("PEP8/RepeatMessages", |
506 ## Preferences.Prefs.settings.setValue("PEP8/RepeatMessages", |
475 ## self.repeatCheckBox.isChecked()) |
507 ## self.repeatCheckBox.isChecked()) |
|
508 Preferences.Prefs.settings.setValue("PEP8/FixCodes", |
|
509 self.fixIssuesEdit.text()) |
|
510 Preferences.Prefs.settings.setValue("PEP8/FixIssues", |
|
511 self.fixIssuesCheckBox.isChecked()) |
476 |
512 |
477 @pyqtSlot(QAbstractButton) |
513 @pyqtSlot(QAbstractButton) |
478 def on_buttonBox_clicked(self, button): |
514 def on_buttonBox_clicked(self, button): |
479 """ |
515 """ |
480 Private slot called by a button of the button box clicked. |
516 Private slot called by a button of the button box clicked. |