Plugins/CheckerPlugins/Pep8/Pep8Dialog.py

branch
Py2 comp.
changeset 2911
ce77f0b1ee67
parent 2847
1843ef6e2656
parent 2881
e942480a6130
child 3056
9986ec0e559a
equal deleted inserted replaced
2847:1843ef6e2656 2911:ce77f0b1ee67
9 9
10 from __future__ import unicode_literals # __IGNORE_WARNING__ 10 from __future__ import unicode_literals # __IGNORE_WARNING__
11 11
12 import os 12 import os
13 import fnmatch 13 import fnmatch
14 import tokenize
15 14
16 from PyQt4.QtCore import pyqtSlot, Qt 15 from PyQt4.QtCore import pyqtSlot, Qt
17 from PyQt4.QtGui import QDialog, QTreeWidgetItem, QAbstractButton, \ 16 from PyQt4.QtGui import QDialog, QTreeWidgetItem, QAbstractButton, \
18 QDialogButtonBox, QApplication, QHeaderView 17 QDialogButtonBox, QApplication, QHeaderView
19 18
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
177 else: 196 else:
178 self.__statistics[key] = statistics[key] 197 self.__statistics[key] = statistics[key]
179 if fixer: 198 if fixer:
180 self.__statistics["_IssuesFixed"] += fixer.fixed 199 self.__statistics["_IssuesFixed"] += fixer.fixed
181 200
201 def __updateFixerStatistics(self, fixer):
202 """
203 Private method to update the collected fixer related statistics.
204
205 @param fixer reference to the PEP 8 fixer (Pep8Fixer)
206 """
207 self.__statistics["_IssuesFixed"] += fixer.fixed
208
182 def __resetStatistics(self): 209 def __resetStatistics(self):
183 """ 210 """
184 Private slot to reset the statistics data. 211 Private slot to reset the statistics data.
185 """ 212 """
186 self.__statistics = {} 213 self.__statistics = {}
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)

eric ide

mercurial