24 from .Ui_Pep8Dialog import Ui_Pep8Dialog |
23 from .Ui_Pep8Dialog import Ui_Pep8Dialog |
25 |
24 |
26 import UI.PixmapCache |
25 import UI.PixmapCache |
27 import Preferences |
26 import Preferences |
28 import Utilities |
27 import Utilities |
|
28 |
|
29 |
|
30 class Pep8Report(pep8.BaseReport): |
|
31 """ |
|
32 Class implementing a special report to be used with our dialog. |
|
33 """ |
|
34 def __init__(self, options): |
|
35 """ |
|
36 Constructor |
|
37 |
|
38 @param options options for the report (optparse.Values) |
|
39 """ |
|
40 super(Pep8Report, self).__init__(options) |
|
41 |
|
42 self.__repeat = options.repeat |
|
43 self.errors = [] |
|
44 |
|
45 def error_args(self, line_number, offset, code, check, *args): |
|
46 """ |
|
47 Public method to collect the error messages. |
|
48 |
|
49 @param line_number line number of the issue (integer) |
|
50 @param offset position within line of the issue (integer) |
|
51 @param code message code (string) |
|
52 @param check reference to the checker function (function) |
|
53 @param args arguments for the message (list) |
|
54 """ |
|
55 code = super(Pep8Report, self).error_args(line_number, offset, code, check, *args) |
|
56 if code and (self.counters[code] == 1 or self.__repeat): |
|
57 text = pep8.getMessage(code, *args) |
|
58 self.errors.append( |
|
59 (self.filename, line_number, offset, text) |
|
60 ) |
|
61 return code |
29 |
62 |
30 |
63 |
31 class Pep8Dialog(QDialog, Ui_Pep8Dialog): |
64 class Pep8Dialog(QDialog, Ui_Pep8Dialog): |
32 """ |
65 """ |
33 Class implementing a dialog to show the results of the PEP 8 check. |
66 Class implementing a dialog to show the results of the PEP 8 check. |
34 """ |
67 """ |
35 filenameRole = Qt.UserRole + 1 |
68 filenameRole = Qt.UserRole + 1 |
36 lineRole = Qt.UserRole + 2 |
69 lineRole = Qt.UserRole + 2 |
37 positionRole = Qt.UserRole + 3 |
70 positionRole = Qt.UserRole + 3 |
38 messageRole = Qt.UserRole + 4 |
71 messageRole = Qt.UserRole + 4 |
39 |
72 fixableRole = Qt.UserRole + 5 |
40 settingsKey = "PEP8/" |
73 codeRole = Qt.UserRole + 6 |
41 |
74 |
42 def __init__(self, parent=None): |
75 def __init__(self, parent=None): |
43 """ |
76 """ |
44 Constructor |
77 Constructor |
45 |
78 |
101 self.__lastFileItem = QTreeWidgetItem(self.resultList, [file]) |
134 self.__lastFileItem = QTreeWidgetItem(self.resultList, [file]) |
102 self.__lastFileItem.setFirstColumnSpanned(True) |
135 self.__lastFileItem.setFirstColumnSpanned(True) |
103 self.__lastFileItem.setExpanded(True) |
136 self.__lastFileItem.setExpanded(True) |
104 self.__lastFileItem.setData(0, self.filenameRole, file) |
137 self.__lastFileItem.setData(0, self.filenameRole, file) |
105 |
138 |
|
139 fixable = False |
106 code, message = message.split(None, 1) |
140 code, message = message.split(None, 1) |
107 itm = QTreeWidgetItem(self.__lastFileItem, |
141 itm = QTreeWidgetItem(self.__lastFileItem, |
108 ["{0:6}".format(line), code, message]) |
142 ["{0:6}".format(line), code, message]) |
109 if code.startswith("W"): |
143 if code.startswith("W"): |
110 itm.setIcon(1, UI.PixmapCache.getIcon("warning.png")) |
144 itm.setIcon(1, UI.PixmapCache.getIcon("warning.png")) |
112 itm.setIcon(1, UI.PixmapCache.getIcon("syntaxError.png")) |
146 itm.setIcon(1, UI.PixmapCache.getIcon("syntaxError.png")) |
113 if fixed: |
147 if fixed: |
114 itm.setIcon(0, UI.PixmapCache.getIcon("issueFixed.png")) |
148 itm.setIcon(0, UI.PixmapCache.getIcon("issueFixed.png")) |
115 elif code in Pep8FixableIssues: |
149 elif code in Pep8FixableIssues: |
116 itm.setIcon(0, UI.PixmapCache.getIcon("issueFixable.png")) |
150 itm.setIcon(0, UI.PixmapCache.getIcon("issueFixable.png")) |
|
151 fixable = True |
117 |
152 |
118 itm.setTextAlignment(0, Qt.AlignRight) |
153 itm.setTextAlignment(0, Qt.AlignRight) |
119 itm.setTextAlignment(1, Qt.AlignHCenter) |
154 itm.setTextAlignment(1, Qt.AlignHCenter) |
120 |
155 |
121 itm.setTextAlignment(0, Qt.AlignVCenter) |
156 itm.setTextAlignment(0, Qt.AlignVCenter) |
124 |
159 |
125 itm.setData(0, self.filenameRole, file) |
160 itm.setData(0, self.filenameRole, file) |
126 itm.setData(0, self.lineRole, int(line)) |
161 itm.setData(0, self.lineRole, int(line)) |
127 itm.setData(0, self.positionRole, int(pos)) |
162 itm.setData(0, self.positionRole, int(pos)) |
128 itm.setData(0, self.messageRole, message) |
163 itm.setData(0, self.messageRole, message) |
129 |
164 itm.setData(0, self.fixableRole, fixable) |
130 def __createErrorItem(self, file, line, pos, message): |
165 itm.setData(0, self.codeRole, code) |
131 """ |
166 |
132 Private method to create an entry in the result list. |
167 def __modifyFixedResultItem(self, itm, text): |
133 |
168 """ |
134 @param file file name of the file (string) |
169 Private method to modify a result list entry to show its |
135 @param line line number of issue (integer or string) |
170 positive fixed state. |
136 @param pos character position of issue (integer or string) |
171 |
137 @param message message text (string) |
172 @param itm reference to the item to modify (QTreeWidgetItem) |
138 @param fixed flag indicating a fixed issue (boolean) |
173 @param text text to be appended (string) |
139 """ |
174 """ |
140 if self.__lastFileItem is None: |
175 message = itm.data(0, self.messageRole) + text |
141 # It's a new file |
176 itm.setText(2, message) |
142 self.__lastFileItem = QTreeWidgetItem(self.resultList, [file]) |
177 itm.setIcon(0, UI.PixmapCache.getIcon("issueFixed.png")) |
143 self.__lastFileItem.setFirstColumnSpanned(True) |
178 |
144 self.__lastFileItem.setExpanded(True) |
|
145 self.__lastFileItem.setData(0, self.filenameRole, file) |
|
146 |
|
147 itm = QTreeWidgetItem(self.__lastFileItem, |
|
148 ["{0:6}".format(line), '', message]) |
|
149 itm.setIcon(0, UI.PixmapCache.getIcon("syntaxError.png")) |
|
150 |
|
151 itm.setTextAlignment(0, Qt.AlignRight) |
|
152 itm.setTextAlignment(1, Qt.AlignHCenter) |
|
153 |
|
154 itm.setTextAlignment(0, Qt.AlignVCenter) |
|
155 itm.setTextAlignment(1, Qt.AlignVCenter) |
|
156 itm.setTextAlignment(2, Qt.AlignVCenter) |
|
157 |
|
158 itm.setData(0, self.filenameRole, file) |
|
159 itm.setData(0, self.lineRole, int(line)) |
|
160 itm.setData(0, self.positionRole, int(pos)) |
|
161 itm.setData(0, self.messageRole, message) |
179 itm.setData(0, self.messageRole, message) |
162 |
180 itm.setData(0, self.fixableRole, False) |
|
181 |
163 def __updateStatistics(self, statistics, fixer): |
182 def __updateStatistics(self, statistics, fixer): |
164 """ |
183 """ |
165 Private method to update the collected statistics. |
184 Private method to update the collected statistics. |
166 |
185 |
167 @param statistics dictionary of statistical data with |
186 @param statistics dictionary of statistical data with |
203 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False) |
230 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False) |
204 self.buttonBox.button(QDialogButtonBox.Close).setDefault(True) |
231 self.buttonBox.button(QDialogButtonBox.Close).setDefault(True) |
205 |
232 |
206 self.__data = self.__project.getData("CHECKERSPARMS", "Pep8Checker") |
233 self.__data = self.__project.getData("CHECKERSPARMS", "Pep8Checker") |
207 if self.__data is None or \ |
234 if self.__data is None or \ |
208 "ExcludeFiles" not in self.__data or \ |
235 len(self.__data) < 6: |
209 len(self.__data) != 6: |
|
210 # initialize the data structure |
236 # initialize the data structure |
211 self.__data = { |
237 self.__data = { |
212 "ExcludeFiles": "", |
238 "ExcludeFiles": "", |
213 "ExcludeMessages": pep8.DEFAULT_IGNORE, |
239 "ExcludeMessages": pep8.DEFAULT_IGNORE, |
214 "IncludeMessages": "", |
240 "IncludeMessages": "", |
215 "RepeatMessages": False, |
241 "RepeatMessages": False, |
216 "FixCodes": "", |
242 "FixCodes": "", |
217 "FixIssues": False, |
243 "FixIssues": False, |
218 } |
244 } |
|
245 if "MaxLineLength" not in self.__data: |
|
246 self.__data["MaxLineLength"] = pep8.MAX_LINE_LENGTH |
|
247 if "HangClosing" not in self.__data: |
|
248 self.__data["HangClosing"] = False |
|
249 if "NoFixCodes" not in self.__data: |
|
250 self.__data["NoFixCodes"] = "E501" |
|
251 |
219 self.excludeFilesEdit.setText(self.__data["ExcludeFiles"]) |
252 self.excludeFilesEdit.setText(self.__data["ExcludeFiles"]) |
220 self.excludeMessagesEdit.setText(self.__data["ExcludeMessages"]) |
253 self.excludeMessagesEdit.setText(self.__data["ExcludeMessages"]) |
221 self.includeMessagesEdit.setText(self.__data["IncludeMessages"]) |
254 self.includeMessagesEdit.setText(self.__data["IncludeMessages"]) |
222 self.repeatCheckBox.setChecked(self.__data["RepeatMessages"]) |
255 self.repeatCheckBox.setChecked(self.__data["RepeatMessages"]) |
223 self.fixIssuesEdit.setText(self.__data["FixCodes"]) |
256 self.fixIssuesEdit.setText(self.__data["FixCodes"]) |
|
257 self.noFixIssuesEdit.setText(self.__data["NoFixCodes"]) |
224 self.fixIssuesCheckBox.setChecked(self.__data["FixIssues"]) |
258 self.fixIssuesCheckBox.setChecked(self.__data["FixIssues"]) |
|
259 self.lineLengthSpinBox.setValue(self.__data["MaxLineLength"]) |
|
260 self.hangClosingCheckBox.setChecked(self.__data["HangClosing"]) |
225 |
261 |
226 def start(self, fn, save=False, repeat=None): |
262 def start(self, fn, save=False, repeat=None): |
227 """ |
263 """ |
228 Public slot to start the PEP 8 check. |
264 Public slot to start the PEP 8 check. |
229 |
265 |
241 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False) |
277 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False) |
242 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(True) |
278 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(True) |
243 self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True) |
279 self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True) |
244 self.statisticsButton.setEnabled(False) |
280 self.statisticsButton.setEnabled(False) |
245 self.showButton.setEnabled(False) |
281 self.showButton.setEnabled(False) |
|
282 self.fixButton.setEnabled(False) |
246 if repeat is not None: |
283 if repeat is not None: |
247 self.repeatCheckBox.setChecked(repeat) |
284 self.repeatCheckBox.setChecked(repeat) |
248 QApplication.processEvents() |
285 QApplication.processEvents() |
249 |
286 |
250 self.__resetStatistics() |
287 self.__resetStatistics() |
280 # extract the configuration values |
317 # extract the configuration values |
281 excludeMessages = self.excludeMessagesEdit.text() |
318 excludeMessages = self.excludeMessagesEdit.text() |
282 includeMessages = self.includeMessagesEdit.text() |
319 includeMessages = self.includeMessagesEdit.text() |
283 repeatMessages = self.repeatCheckBox.isChecked() |
320 repeatMessages = self.repeatCheckBox.isChecked() |
284 fixCodes = self.fixIssuesEdit.text() |
321 fixCodes = self.fixIssuesEdit.text() |
|
322 noFixCodes = self.noFixIssuesEdit.text() |
285 fixIssues = self.fixIssuesCheckBox.isChecked() and repeatMessages |
323 fixIssues = self.fixIssuesCheckBox.isChecked() and repeatMessages |
|
324 maxLineLength = self.lineLengthSpinBox.value() |
|
325 hangClosing = self.hangClosingCheckBox.isChecked() |
286 |
326 |
287 try: |
327 try: |
288 # disable updates of the list for speed |
328 # disable updates of the list for speed |
289 self.resultList.setUpdatesEnabled(False) |
329 self.resultList.setUpdatesEnabled(False) |
290 self.resultList.setSortingEnabled(False) |
330 self.resultList.setSortingEnabled(False) |
313 continue |
353 continue |
314 |
354 |
315 if fixIssues: |
355 if fixIssues: |
316 from .Pep8Fixer import Pep8Fixer |
356 from .Pep8Fixer import Pep8Fixer |
317 fixer = Pep8Fixer(self.__project, file, source, |
357 fixer = Pep8Fixer(self.__project, file, source, |
318 fixCodes, True) # always fix in place |
358 fixCodes, noFixCodes, maxLineLength, |
|
359 True) # always fix in place |
319 else: |
360 else: |
320 fixer = None |
361 fixer = None |
321 from .Pep8Checker import Pep8Checker |
362 if includeMessages: |
322 checker = Pep8Checker(file, source, |
363 select = [s.strip() for s in includeMessages.split(',') |
|
364 if s.strip()] |
|
365 else: |
|
366 select = [] |
|
367 if excludeMessages: |
|
368 ignore = [i.strip() for i in excludeMessages.split(',') |
|
369 if i.strip()] |
|
370 else: |
|
371 ignore = [] |
|
372 styleGuide = pep8.StyleGuide( |
|
373 reporter=Pep8Report, |
323 repeat=repeatMessages, |
374 repeat=repeatMessages, |
324 select=includeMessages, |
375 select=select, |
325 ignore=excludeMessages) |
376 ignore=ignore, |
326 try: |
377 max_line_length=maxLineLength, |
327 checker.check_all() |
378 hang_closing=hangClosing, |
328 except tokenize.TokenError as msg: |
379 ) |
329 self.noResults = False |
380 report = styleGuide.check_files([file]) |
330 self.__createErrorItem(file, 1, -1, |
381 report.errors.sort(key=lambda a: a[1]) |
331 self.trUtf8("Token Error: {0}".format(str(msg)))) |
382 |
332 except IndentationError as err: |
383 for fname, lineno, position, text in report.errors: |
333 self.noResults = False |
384 if lineno > len(source): |
334 self.__createErrorItem(file, err.lineno, -1, |
385 lineno = len(source) |
335 self.trUtf8("Indentation Error: {0}".format(str(err.msg)))) |
386 if "__IGNORE_WARNING__" not in Utilities.extractLineFlags( |
336 except Exception as err: |
387 source[lineno - 1].strip()): |
337 self.noResults = False |
388 self.noResults = False |
338 self.__createErrorItem(file, 1, -1, |
389 fixed = False |
339 self.trUtf8("Unspecific Error: {0}".format(str(err)))) |
390 if fixer: |
340 else: |
391 fixed, msg = fixer.fixIssue(lineno, position, text) |
341 checker.messages.sort(key=lambda a: a[1]) |
392 if fixed: |
342 for message in checker.messages: |
393 text += "\n" + \ |
343 fname, lineno, position, text = message |
394 self.trUtf8("Fix: {0}").format(msg) |
344 if lineno > len(source): |
395 self.__createResultItem( |
345 lineno = len(source) |
396 fname, lineno, position, text, fixed) |
346 if "__IGNORE_WARNING__" not in Utilities.extractLineFlags( |
397 if fixer: |
347 source[lineno - 1].strip()): |
398 fixer.saveFile(encoding) |
348 self.noResults = False |
399 self.__updateStatistics(report.counters, fixer) |
349 fixed = False |
400 progress += 1 |
350 if fixer: |
|
351 fixed, msg = fixer.fixIssue(lineno, position, text) |
|
352 if fixed: |
|
353 text += "\n" + \ |
|
354 self.trUtf8("Fix: {0}").format(msg) |
|
355 self.__createResultItem( |
|
356 fname, lineno, position, text, fixed) |
|
357 if fixer: |
|
358 fixer.saveFile(encoding) |
|
359 self.__updateStatistics(checker.statistics, fixer) |
|
360 finally: |
|
361 progress += 1 |
|
362 finally: |
401 finally: |
363 # reenable updates of the list |
402 # reenable updates of the list |
364 self.resultList.setSortingEnabled(True) |
403 self.resultList.setSortingEnabled(True) |
365 self.resultList.setUpdatesEnabled(True) |
404 self.resultList.setUpdatesEnabled(True) |
366 self.checkProgress.setValue(progress) |
405 self.checkProgress.setValue(progress) |
405 "ExcludeFiles": self.excludeFilesEdit.text(), |
444 "ExcludeFiles": self.excludeFilesEdit.text(), |
406 "ExcludeMessages": self.excludeMessagesEdit.text(), |
445 "ExcludeMessages": self.excludeMessagesEdit.text(), |
407 "IncludeMessages": self.includeMessagesEdit.text(), |
446 "IncludeMessages": self.includeMessagesEdit.text(), |
408 "RepeatMessages": self.repeatCheckBox.isChecked(), |
447 "RepeatMessages": self.repeatCheckBox.isChecked(), |
409 "FixCodes": self.fixIssuesEdit.text(), |
448 "FixCodes": self.fixIssuesEdit.text(), |
|
449 "NoFixCodes": self.noFixIssuesEdit.text(), |
410 "FixIssues": self.fixIssuesCheckBox.isChecked(), |
450 "FixIssues": self.fixIssuesCheckBox.isChecked(), |
|
451 "MaxLineLength": self.lineLengthSpinBox.value(), |
|
452 "HangClosing": self.hangClosingCheckBox.isChecked(), |
411 } |
453 } |
412 if data != self.__data: |
454 if data != self.__data: |
413 self.__data = data |
455 self.__data = data |
414 self.__project.setData("CHECKERSPARMS", "Pep8Checker", |
456 self.__project.setData("CHECKERSPARMS", "Pep8Checker", |
415 self.__data) |
457 self.__data) |
417 self.resultList.clear() |
459 self.resultList.clear() |
418 self.noResults = True |
460 self.noResults = True |
419 self.cancelled = False |
461 self.cancelled = False |
420 self.start(self.__fileOrFileList) |
462 self.start(self.__fileOrFileList) |
421 |
463 |
|
464 def __selectCodes(self, edit, showFixCodes): |
|
465 """ |
|
466 Private method to select message codes via a selection dialog. |
|
467 |
|
468 @param edit reference of the line edit to be populated (QLineEdit) |
|
469 @param showFixCodes flag indicating to show a list of fixable |
|
470 issues (boolean) |
|
471 """ |
|
472 from .Pep8CodeSelectionDialog import Pep8CodeSelectionDialog |
|
473 dlg = Pep8CodeSelectionDialog(edit.text(), showFixCodes, self) |
|
474 if dlg.exec_() == QDialog.Accepted: |
|
475 edit.setText(dlg.getSelectedCodes()) |
|
476 |
422 @pyqtSlot() |
477 @pyqtSlot() |
423 def on_excludeMessagesSelectButton_clicked(self): |
478 def on_excludeMessagesSelectButton_clicked(self): |
424 """ |
479 """ |
425 Private slot to select the message codes to be excluded via a |
480 Private slot to select the message codes to be excluded via a |
426 selection dialog. |
481 selection dialog. |
427 """ |
482 """ |
428 from .Pep8CodeSelectionDialog import Pep8CodeSelectionDialog |
483 self.__selectCodes(self.excludeMessagesEdit, False) |
429 dlg = Pep8CodeSelectionDialog( |
|
430 self.excludeMessagesEdit.text(), False, self) |
|
431 if dlg.exec_() == QDialog.Accepted: |
|
432 self.excludeMessagesEdit.setText(dlg.getSelectedCodes()) |
|
433 |
484 |
434 @pyqtSlot() |
485 @pyqtSlot() |
435 def on_includeMessagesSelectButton_clicked(self): |
486 def on_includeMessagesSelectButton_clicked(self): |
436 """ |
487 """ |
437 Private slot to select the message codes to be included via a |
488 Private slot to select the message codes to be included via a |
438 selection dialog. |
489 selection dialog. |
439 """ |
490 """ |
440 from .Pep8CodeSelectionDialog import Pep8CodeSelectionDialog |
491 self.__selectCodes(self.includeMessagesEdit, False) |
441 dlg = Pep8CodeSelectionDialog( |
|
442 self.includeMessagesEdit.text(), False, self) |
|
443 if dlg.exec_() == QDialog.Accepted: |
|
444 self.includeMessagesEdit.setText(dlg.getSelectedCodes()) |
|
445 |
492 |
446 @pyqtSlot() |
493 @pyqtSlot() |
447 def on_fixIssuesSelectButton_clicked(self): |
494 def on_fixIssuesSelectButton_clicked(self): |
448 """ |
495 """ |
449 Private slot to select the issue codes to be fixed via a |
496 Private slot to select the issue codes to be fixed via a |
450 selection dialog. |
497 selection dialog. |
451 """ |
498 """ |
452 from .Pep8CodeSelectionDialog import Pep8CodeSelectionDialog |
499 self.__selectCodes(self.fixIssuesEdit, True) |
453 dlg = Pep8CodeSelectionDialog( |
500 |
454 self.fixIssuesEdit.text(), True, self) |
501 @pyqtSlot() |
455 if dlg.exec_() == QDialog.Accepted: |
502 def on_noFixIssuesSelectButton_clicked(self): |
456 self.fixIssuesEdit.setText(dlg.getSelectedCodes()) |
503 """ |
|
504 Private slot to select the issue codes not to be fixed via a |
|
505 selection dialog. |
|
506 """ |
|
507 self.__selectCodes(self.noFixIssuesEdit, True) |
457 |
508 |
458 @pyqtSlot(QTreeWidgetItem, int) |
509 @pyqtSlot(QTreeWidgetItem, int) |
459 def on_resultList_itemActivated(self, item, column): |
510 def on_resultList_itemActivated(self, item, column): |
460 """ |
511 """ |
461 Private slot to handle the activation of an item. |
512 Private slot to handle the activation of an item. |
471 lineno = item.data(0, self.lineRole) |
522 lineno = item.data(0, self.lineRole) |
472 position = item.data(0, self.positionRole) |
523 position = item.data(0, self.positionRole) |
473 message = item.data(0, self.messageRole) |
524 message = item.data(0, self.messageRole) |
474 |
525 |
475 vm = e5App().getObject("ViewManager") |
526 vm = e5App().getObject("ViewManager") |
476 vm.openSourceFile(fn, lineno=lineno, pos=position) |
527 vm.openSourceFile(fn, lineno=lineno, pos=position + 1) |
477 editor = vm.getOpenEditor(fn) |
528 editor = vm.getOpenEditor(fn) |
478 |
529 |
479 if position > 0: |
530 editor.toggleFlakesWarning(lineno, True, message) |
480 editor.toggleFlakesWarning(lineno, True, message) |
531 |
481 else: |
532 @pyqtSlot() |
482 error = message.split(':', 1)[-1] |
533 def on_resultList_itemSelectionChanged(self): |
483 editor.toggleSyntaxError(lineno, 1, True, error.strip(), show=True) |
534 """ |
|
535 Private slot to change the dialog state depending on the selection. |
|
536 """ |
|
537 self.fixButton.setEnabled(len(self.__getSelectedFixableItems()) > 0) |
484 |
538 |
485 @pyqtSlot() |
539 @pyqtSlot() |
486 def on_showButton_clicked(self): |
540 def on_showButton_clicked(self): |
487 """ |
541 """ |
488 Private slot to handle the "Show" button press. |
542 Private slot to handle the "Show" button press. |
538 "PEP8/ExcludeFilePatterns")) |
592 "PEP8/ExcludeFilePatterns")) |
539 self.excludeMessagesEdit.setText(Preferences.Prefs.settings.value( |
593 self.excludeMessagesEdit.setText(Preferences.Prefs.settings.value( |
540 "PEP8/ExcludeMessages", pep8.DEFAULT_IGNORE)) |
594 "PEP8/ExcludeMessages", pep8.DEFAULT_IGNORE)) |
541 self.includeMessagesEdit.setText(Preferences.Prefs.settings.value( |
595 self.includeMessagesEdit.setText(Preferences.Prefs.settings.value( |
542 "PEP8/IncludeMessages")) |
596 "PEP8/IncludeMessages")) |
|
597 self.repeatCheckBox.setChecked(Preferences.toBool( |
|
598 Preferences.Prefs.settings.value("PEP8/RepeatMessages"))) |
543 self.fixIssuesEdit.setText(Preferences.Prefs.settings.value( |
599 self.fixIssuesEdit.setText(Preferences.Prefs.settings.value( |
544 "PEP8/FixCodes")) |
600 "PEP8/FixCodes")) |
|
601 self.noFixIssuesEdit.setText(Preferences.Prefs.settings.value( |
|
602 "PEP8/NoFixCodes", "E501")) |
545 self.fixIssuesCheckBox.setChecked(Preferences.toBool( |
603 self.fixIssuesCheckBox.setChecked(Preferences.toBool( |
546 Preferences.Prefs.settings.value("PEP8/FixIssues"))) |
604 Preferences.Prefs.settings.value("PEP8/FixIssues"))) |
|
605 self.lineLengthSpinBox.setValue(int(Preferences.Prefs.settings.value( |
|
606 "PEP8/MaxLineLength", pep8.MAX_LINE_LENGTH))) |
|
607 self.hangClosingCheckBox.setChecked(Preferences.toBool( |
|
608 Preferences.Prefs.settings.value("PEP8/HangClosing"))) |
547 |
609 |
548 @pyqtSlot() |
610 @pyqtSlot() |
549 def on_storeDefaultButton_clicked(self): |
611 def on_storeDefaultButton_clicked(self): |
550 """ |
612 """ |
551 Private slot to store the current configuration values as |
613 Private slot to store the current configuration values as |
555 self.excludeFilesEdit.text()) |
617 self.excludeFilesEdit.text()) |
556 Preferences.Prefs.settings.setValue("PEP8/ExcludeMessages", |
618 Preferences.Prefs.settings.setValue("PEP8/ExcludeMessages", |
557 self.excludeMessagesEdit.text()) |
619 self.excludeMessagesEdit.text()) |
558 Preferences.Prefs.settings.setValue("PEP8/IncludeMessages", |
620 Preferences.Prefs.settings.setValue("PEP8/IncludeMessages", |
559 self.includeMessagesEdit.text()) |
621 self.includeMessagesEdit.text()) |
|
622 Preferences.Prefs.settings.setValue("PEP8/RepeatMessages", |
|
623 self.repeatCheckBox.isChecked()) |
560 Preferences.Prefs.settings.setValue("PEP8/FixCodes", |
624 Preferences.Prefs.settings.setValue("PEP8/FixCodes", |
561 self.fixIssuesEdit.text()) |
625 self.fixIssuesEdit.text()) |
|
626 Preferences.Prefs.settings.setValue("PEP8/NoFixCodes", |
|
627 self.noFixIssuesEdit.text()) |
562 Preferences.Prefs.settings.setValue("PEP8/FixIssues", |
628 Preferences.Prefs.settings.setValue("PEP8/FixIssues", |
563 self.fixIssuesCheckBox.isChecked()) |
629 self.fixIssuesCheckBox.isChecked()) |
|
630 Preferences.Prefs.settings.setValue("PEP8/MaxLineLength", |
|
631 self.lineLengthSpinBox.value()) |
|
632 Preferences.Prefs.settings.setValue("PEP8/HangClosing", |
|
633 self.hangClosingCheckBox.isChecked()) |
|
634 |
|
635 @pyqtSlot() |
|
636 def on_resetDefaultButton_clicked(self): |
|
637 """ |
|
638 Slot documentation goes here. |
|
639 """ |
|
640 raise NotImplementedError |
|
641 Preferences.Prefs.settings.setValue("PEP8/ExcludeFilePatterns", "") |
|
642 Preferences.Prefs.settings.setValue("PEP8/ExcludeMessages", |
|
643 pep8.DEFAULT_IGNORE) |
|
644 Preferences.Prefs.settings.setValue("PEP8/IncludeMessages", "") |
|
645 Preferences.Prefs.settings.setValue("PEP8/RepeatMessages", False) |
|
646 Preferences.Prefs.settings.setValue("PEP8/FixCodes", "") |
|
647 Preferences.Prefs.settings.setValue("PEP8/NoFixCodes", "E501") |
|
648 Preferences.Prefs.settings.setValue("PEP8/FixIssues", False) |
|
649 Preferences.Prefs.settings.setValue("PEP8/MaxLineLength", |
|
650 pep8.MAX_LINE_LENGTH) |
|
651 Preferences.Prefs.settings.setValue("PEP8/HangClosing", False) |
564 |
652 |
565 @pyqtSlot(QAbstractButton) |
653 @pyqtSlot(QAbstractButton) |
566 def on_buttonBox_clicked(self, button): |
654 def on_buttonBox_clicked(self, button): |
567 """ |
655 """ |
568 Private slot called by a button of the button box clicked. |
656 Private slot called by a button of the button box clicked. |
585 vm = e5App().getObject("ViewManager") |
673 vm = e5App().getObject("ViewManager") |
586 openFiles = vm.getOpenFilenames() |
674 openFiles = vm.getOpenFilenames() |
587 for file in openFiles: |
675 for file in openFiles: |
588 editor = vm.getOpenEditor(file) |
676 editor = vm.getOpenEditor(file) |
589 editor.clearFlakesWarnings() |
677 editor.clearFlakesWarnings() |
|
678 |
|
679 @pyqtSlot() |
|
680 def on_fixButton_clicked(self): |
|
681 """ |
|
682 Private slot to fix selected issues. |
|
683 """ |
|
684 # TODO: test this |
|
685 from .Pep8Fixer import Pep8Fixer |
|
686 |
|
687 # build a dictionary of issues to fix |
|
688 fixableItems = self.__getSelectedFixableItems() |
|
689 fixesDict = {} # dictionary of lists of tuples containing |
|
690 # the issue and the item |
|
691 for itm in fixableItems: |
|
692 filename = itm.data(0, self.filenameRole) |
|
693 if filename not in fixesDict: |
|
694 fixesDict[filename] = [] |
|
695 fixesDict[filename].append(( |
|
696 (itm.data(0, self.lineRole), |
|
697 itm.data(0, self.positionRole), |
|
698 "{0} {1}".format(itm.data(0, self.codeRole), |
|
699 itm.data(0, self.messageRole))), |
|
700 itm |
|
701 )) |
|
702 |
|
703 # extract the configuration values |
|
704 fixCodes = self.fixIssuesEdit.text() |
|
705 noFixCodes = self.noFixIssuesEdit.text() |
|
706 maxLineLength = self.lineLengthSpinBox.value() |
|
707 |
|
708 # now go through all the files |
|
709 if fixesDict: |
|
710 self.checkProgress.setMaximum(len(fixesDict)) |
|
711 progress = 0 |
|
712 for file in fixesDict: |
|
713 self.checkProgress.setValue(progress) |
|
714 QApplication.processEvents() |
|
715 |
|
716 try: |
|
717 source, encoding = Utilities.readEncodedFile(file) |
|
718 source = source.splitlines(True) |
|
719 except (UnicodeError, IOError) as msg: |
|
720 # skip silently because that should not happen |
|
721 progress += 1 |
|
722 continue |
|
723 |
|
724 fixer = Pep8Fixer(self.__project, file, source, |
|
725 fixCodes, noFixCodes, maxLineLength, |
|
726 True) # always fix in place |
|
727 errors = fixesDict[file] |
|
728 errors.sort(key=lambda a: a[0][0]) |
|
729 for error in errors: |
|
730 (lineno, position, text), itm = error |
|
731 if lineno > len(source): |
|
732 lineno = len(source) |
|
733 fixed, msg = fixer.fixIssue(lineno, position, text) |
|
734 if fixed: |
|
735 text = "\n" + self.trUtf8("Fix: {0}").format(msg) |
|
736 self.__modifyFixedResultItem(itm, text) |
|
737 fixer.saveFile(encoding) |
|
738 |
|
739 self.__updateFixerStatistics(fixer) |
|
740 progress += 1 |
|
741 |
|
742 self.checkProgress.setValue(progress) |
|
743 QApplication.processEvents() |
|
744 |
|
745 def __getSelectedFixableItems(self): |
|
746 """ |
|
747 Private method to extract all selected items for fixable issues. |
|
748 |
|
749 @return selected items for fixable issues (list of QTreeWidgetItem) |
|
750 """ |
|
751 fixableItems = [] |
|
752 for itm in self.resultList.selectedItems(): |
|
753 if itm.childCount() > 0: |
|
754 for index in range(itm.childCount()): |
|
755 citm = itm.child(index) |
|
756 if self.__itemFixable(citm) and not citm in fixableItems: |
|
757 fixableItems.append(citm) |
|
758 elif self.__itemFixable(itm) and not itm in fixableItems: |
|
759 fixableItems.append(itm) |
|
760 |
|
761 return fixableItems |
|
762 |
|
763 def __itemFixable(self, itm): |
|
764 """ |
|
765 Private method to check, if an item has a fixable issue. |
|
766 |
|
767 @param itm item to be checked (QTreeWidgetItem) |
|
768 @return flag indicating a fixable issue (boolean) |
|
769 """ |
|
770 return itm.data(0, self.fixableRole) |