9 |
9 |
10 |
10 |
11 import os |
11 import os |
12 import fnmatch |
12 import fnmatch |
13 |
13 |
14 from PyQt5.QtCore import pyqtSlot, Qt, QTimer |
14 from PyQt5.QtCore import pyqtSlot, Qt, QTimer, QCoreApplication |
15 from PyQt5.QtGui import QIcon |
15 from PyQt5.QtGui import QIcon |
16 from PyQt5.QtWidgets import ( |
16 from PyQt5.QtWidgets import ( |
17 QDialog, QTreeWidgetItem, QAbstractButton, QDialogButtonBox, QApplication, |
17 QDialog, QTreeWidgetItem, QAbstractButton, QDialogButtonBox, QApplication, |
18 QHeaderView, QListWidgetItem |
18 QHeaderView, QListWidgetItem |
19 ) |
19 ) |
49 availableFutures = [ |
49 availableFutures = [ |
50 'division', 'absolute_import', 'with_statement', |
50 'division', 'absolute_import', 'with_statement', |
51 'print_function', 'unicode_literals', 'generator_stop', |
51 'print_function', 'unicode_literals', 'generator_stop', |
52 'annotations'] |
52 'annotations'] |
53 |
53 |
|
54 checkCategories = { |
|
55 "A": QCoreApplication.translate( |
|
56 "CheckerCategories", |
|
57 "Annotations"), |
|
58 "C": QCoreApplication.translate( |
|
59 "CheckerCategories", |
|
60 "Code Complexity"), |
|
61 "D": QCoreApplication.translate( |
|
62 "CheckerCategories", |
|
63 "Documentation"), |
|
64 "E": QCoreApplication.translate( |
|
65 "CheckerCategories", |
|
66 "Errors"), |
|
67 "M": QCoreApplication.translate( |
|
68 "CheckerCategories", |
|
69 "Miscellaneous"), |
|
70 "N": QCoreApplication.translate( |
|
71 "CheckerCategories", |
|
72 "Naming"), |
|
73 "W": QCoreApplication.translate( |
|
74 "CheckerCategories", |
|
75 "Warnings"), |
|
76 } |
|
77 |
54 noResults = 0 |
78 noResults = 0 |
55 noFiles = 1 |
79 noFiles = 1 |
56 hasResults = 2 |
80 hasResults = 2 |
57 |
81 |
58 def __init__(self, styleCheckService, parent=None): |
82 def __init__(self, styleCheckService, parent=None): |
59 """ |
83 """ |
60 Constructor |
84 Constructor |
61 |
85 |
62 @param styleCheckService reference to the service |
86 @param styleCheckService reference to the service |
63 (CodeStyleCheckService) |
87 @type CodeStyleCheckService |
64 @param parent reference to the parent widget (QWidget) |
88 @param parent reference to the parent widget |
|
89 @type QWidget |
65 """ |
90 """ |
66 super(CodeStyleCheckerDialog, self).__init__(parent) |
91 super(CodeStyleCheckerDialog, self).__init__(parent) |
67 self.setupUi(self) |
92 self.setupUi(self) |
68 self.setWindowFlags(Qt.Window) |
93 self.setWindowFlags(Qt.Window) |
69 |
94 |
78 self.noFixIssuesSelectButton.setIcon( |
103 self.noFixIssuesSelectButton.setIcon( |
79 UI.PixmapCache.getIcon("select")) |
104 UI.PixmapCache.getIcon("select")) |
80 |
105 |
81 self.docTypeComboBox.addItem(self.tr("PEP-257"), "pep257") |
106 self.docTypeComboBox.addItem(self.tr("PEP-257"), "pep257") |
82 self.docTypeComboBox.addItem(self.tr("Eric"), "eric") |
107 self.docTypeComboBox.addItem(self.tr("Eric"), "eric") |
|
108 |
|
109 for category, text in CodeStyleCheckerDialog.checkCategories.items(): |
|
110 itm = QListWidgetItem(text, self.categoriesList) |
|
111 itm.setData(Qt.UserRole, category) |
|
112 itm.setFlags(itm.flags() | Qt.ItemIsUserCheckable) |
|
113 itm.setCheckState(Qt.Unchecked) |
83 |
114 |
84 for future in CodeStyleCheckerDialog.availableFutures: |
115 for future in CodeStyleCheckerDialog.availableFutures: |
85 itm = QListWidgetItem(future, self.futuresList) |
116 itm = QListWidgetItem(future, self.futuresList) |
86 itm.setFlags(itm.flags() | Qt.ItemIsUserCheckable) |
117 itm.setFlags(itm.flags() | Qt.ItemIsUserCheckable) |
87 itm.setCheckState(Qt.Unchecked) |
118 itm.setCheckState(Qt.Unchecked) |
171 def __createResultItem(self, filename, line, pos, message, fixed, |
202 def __createResultItem(self, filename, line, pos, message, fixed, |
172 autofixing, ignored): |
203 autofixing, ignored): |
173 """ |
204 """ |
174 Private method to create an entry in the result list. |
205 Private method to create an entry in the result list. |
175 |
206 |
176 @param filename file name of the file (string) |
207 @param filename file name of the file |
177 @param line line number of issue (integer or string) |
208 @type str |
178 @param pos character position of issue (integer or string) |
209 @param line line number of issue |
179 @param message message text (string) |
210 @type int or str |
180 @param fixed flag indicating a fixed issue (boolean) |
211 @param pos character position of issue |
|
212 @type int or str |
|
213 @param message message text |
|
214 @type str |
|
215 @param fixed flag indicating a fixed issue |
|
216 @type bool |
181 @param autofixing flag indicating, that we are fixing issues |
217 @param autofixing flag indicating, that we are fixing issues |
182 automatically (boolean) |
218 automatically |
183 @param ignored flag indicating an ignored issue (boolean) |
219 @type bool |
184 @return reference to the created item (QTreeWidgetItem) |
220 @param ignored flag indicating an ignored issue |
|
221 @type bool |
|
222 @return reference to the created item |
|
223 @rtype QTreeWidgetItem |
185 """ |
224 """ |
186 from .CodeStyleFixer import FixableCodeStyleIssues |
225 from .CodeStyleFixer import FixableCodeStyleIssues |
187 |
226 |
188 if self.__lastFileItem is None: |
227 if self.__lastFileItem is None: |
189 # It's a new file |
228 # It's a new file |
198 itm = QTreeWidgetItem( |
237 itm = QTreeWidgetItem( |
199 self.__lastFileItem, |
238 self.__lastFileItem, |
200 ["{0:6}".format(line), code, message]) |
239 ["{0:6}".format(line), code, message]) |
201 if code.startswith(("W", "-", "C", "M")): |
240 if code.startswith(("W", "-", "C", "M")): |
202 itm.setIcon(1, UI.PixmapCache.getIcon("warning")) |
241 itm.setIcon(1, UI.PixmapCache.getIcon("warning")) |
203 elif code.startswith("N"): |
242 elif code.startswith(("A", "N")): |
204 itm.setIcon(1, UI.PixmapCache.getIcon("namingError")) |
243 itm.setIcon(1, UI.PixmapCache.getIcon("namingError")) |
205 elif code.startswith("D"): |
244 elif code.startswith("D"): |
206 itm.setIcon(1, UI.PixmapCache.getIcon("docstringError")) |
245 itm.setIcon(1, UI.PixmapCache.getIcon("docstringError")) |
207 else: |
246 else: |
208 itm.setIcon(1, UI.PixmapCache.getIcon("syntaxError")) |
247 itm.setIcon(1, UI.PixmapCache.getIcon("syntaxError")) |
241 def __modifyFixedResultItem(self, itm, text, fixed): |
280 def __modifyFixedResultItem(self, itm, text, fixed): |
242 """ |
281 """ |
243 Private method to modify a result list entry to show its |
282 Private method to modify a result list entry to show its |
244 positive fixed state. |
283 positive fixed state. |
245 |
284 |
246 @param itm reference to the item to modify (QTreeWidgetItem) |
285 @param itm reference to the item to modify |
247 @param text text to be appended (string) |
286 @type QTreeWidgetItem |
248 @param fixed flag indicating a fixed issue (boolean) |
287 @param text text to be appended |
|
288 @type str |
|
289 @param fixed flag indicating a fixed issue |
|
290 @type bool |
249 """ |
291 """ |
250 if fixed: |
292 if fixed: |
251 code, message = text.split(None, 1) |
293 code, message = text.split(None, 1) |
252 itm.setText(2, message) |
294 itm.setText(2, message) |
253 itm.setIcon(0, UI.PixmapCache.getIcon("issueFixed")) |
295 itm.setIcon(0, UI.PixmapCache.getIcon("issueFixed")) |
261 """ |
303 """ |
262 Private method to update the collected statistics. |
304 Private method to update the collected statistics. |
263 |
305 |
264 @param statistics dictionary of statistical data with |
306 @param statistics dictionary of statistical data with |
265 message code as key and message count as value |
307 message code as key and message count as value |
266 @param fixer reference to the code style fixer (CodeStyleFixer) |
308 @type dict |
267 @param ignoredErrors number of ignored errors (integer) |
309 @param fixer reference to the code style fixer |
|
310 @type CodeStyleFixer |
|
311 @param ignoredErrors number of ignored errors |
|
312 @type int |
268 """ |
313 """ |
269 self.__statistics["_FilesCount"] += 1 |
314 self.__statistics["_FilesCount"] += 1 |
270 stats = [k for k in statistics.keys() if k[0].isupper()] |
315 stats = [k for k in statistics.keys() if k[0].isupper()] |
271 if stats: |
316 if stats: |
272 self.__statistics["_FilesIssues"] += 1 |
317 self.__statistics["_FilesIssues"] += 1 |
298 |
344 |
299 def prepare(self, fileList, project): |
345 def prepare(self, fileList, project): |
300 """ |
346 """ |
301 Public method to prepare the dialog with a list of filenames. |
347 Public method to prepare the dialog with a list of filenames. |
302 |
348 |
303 @param fileList list of filenames (list of strings) |
349 @param fileList list of filenames |
304 @param project reference to the project object (Project) |
350 @type list of str |
|
351 @param project reference to the project object |
|
352 @type Project |
305 """ |
353 """ |
306 self.__fileOrFileList = fileList[:] |
354 self.__fileOrFileList = fileList[:] |
307 self.__project = project |
355 self.__project = project |
308 self.__forProject = True |
356 self.__forProject = True |
309 |
357 |
323 "IncludeMessages": "", |
371 "IncludeMessages": "", |
324 "RepeatMessages": False, |
372 "RepeatMessages": False, |
325 "FixCodes": "", |
373 "FixCodes": "", |
326 "FixIssues": False, |
374 "FixIssues": False, |
327 } |
375 } |
|
376 if "EnabledCheckerCategories" not in self.__data: |
|
377 self.__data["EnabledCheckerCategories"] = ",".join( |
|
378 CodeStyleCheckerDialog.checkCategories.keys()) |
328 if "MaxLineLength" not in self.__data: |
379 if "MaxLineLength" not in self.__data: |
329 self.__data["MaxLineLength"] = pycodestyle.MAX_LINE_LENGTH |
380 self.__data["MaxLineLength"] = pycodestyle.MAX_LINE_LENGTH |
330 if "MaxDocLineLength" not in self.__data: |
381 if "MaxDocLineLength" not in self.__data: |
331 # Use MAX_LINE_LENGTH to avoid messages on existing code |
382 # Use MAX_LINE_LENGTH to avoid messages on existing code |
332 self.__data["MaxDocLineLength"] = pycodestyle.MAX_LINE_LENGTH |
383 self.__data["MaxDocLineLength"] = pycodestyle.MAX_LINE_LENGTH |
370 self.__data["AnnotationsChecker"] = { |
421 self.__data["AnnotationsChecker"] = { |
371 "MinimumCoverage": 75, |
422 "MinimumCoverage": 75, |
372 "MaximumComplexity": 3, |
423 "MaximumComplexity": 3, |
373 } |
424 } |
374 |
425 |
|
426 self.__initCategoriesList(self.__data["EnabledCheckerCategories"]) |
375 self.excludeFilesEdit.setText(self.__data["ExcludeFiles"]) |
427 self.excludeFilesEdit.setText(self.__data["ExcludeFiles"]) |
376 self.excludeMessagesEdit.setText(self.__data["ExcludeMessages"]) |
428 self.excludeMessagesEdit.setText(self.__data["ExcludeMessages"]) |
377 self.includeMessagesEdit.setText(self.__data["IncludeMessages"]) |
429 self.includeMessagesEdit.setText(self.__data["IncludeMessages"]) |
378 self.repeatCheckBox.setChecked(self.__data["RepeatMessages"]) |
430 self.repeatCheckBox.setChecked(self.__data["RepeatMessages"]) |
379 self.fixIssuesEdit.setText(self.__data["FixCodes"]) |
431 self.fixIssuesEdit.setText(self.__data["FixCodes"]) |
401 self.__data["CommentedCodeChecker"]["Aggressive"]) |
453 self.__data["CommentedCodeChecker"]["Aggressive"]) |
402 self.minAnnotationsCoverageSpinBox.setValue( |
454 self.minAnnotationsCoverageSpinBox.setValue( |
403 self.__data["AnnotationsChecker"]["MinimumCoverage"]) |
455 self.__data["AnnotationsChecker"]["MinimumCoverage"]) |
404 self.maxAnnotationsComplexitySpinBox.setValue( |
456 self.maxAnnotationsComplexitySpinBox.setValue( |
405 self.__data["AnnotationsChecker"]["MaximumComplexity"]) |
457 self.__data["AnnotationsChecker"]["MaximumComplexity"]) |
|
458 |
|
459 self.__cleanupData() |
406 |
460 |
407 def start(self, fn, save=False, repeat=None): |
461 def start(self, fn, save=False, repeat=None): |
408 """ |
462 """ |
409 Public slot to start the code style check. |
463 Public slot to start the code style check. |
410 |
464 |
411 @param fn file or list of files or directory to be checked |
465 @param fn file or list of files or directory to be checked |
412 (string or list of strings) |
466 @type str or list of str |
413 @keyparam save flag indicating to save the given |
467 @param save flag indicating to save the given file/file list/directory |
414 file/file list/directory (boolean) |
468 @type bool |
415 @keyparam repeat state of the repeat check box if it is not None |
469 @param repeat state of the repeat check box if it is not None |
416 (None or boolean) |
470 @type None or bool |
417 """ |
471 """ |
418 if self.__project is None: |
472 if self.__project is None: |
419 self.__project = e5App().getObject("Project") |
473 self.__project = e5App().getObject("Project") |
420 |
474 |
421 self.mainWidget.setCurrentWidget(self.runTab) |
475 self.mainWidget.setCurrentWidget(self.runTab) |
461 ] |
515 ] |
462 |
516 |
463 self.__errorItem = None |
517 self.__errorItem = None |
464 self.__resetStatistics() |
518 self.__resetStatistics() |
465 self.__clearErrors(self.files) |
519 self.__clearErrors(self.files) |
|
520 self.__cleanupData() |
466 |
521 |
467 if len(self.files) > 0: |
522 if len(self.files) > 0: |
468 self.checkProgress.setMaximum(len(self.files)) |
523 self.checkProgress.setMaximum(len(self.files)) |
469 self.checkProgressLabel.setVisible(len(self.files) > 1) |
524 self.checkProgressLabel.setVisible(len(self.files) > 1) |
470 self.checkProgress.setVisible(len(self.files) > 1) |
525 self.checkProgress.setVisible(len(self.files) > 1) |
471 QApplication.processEvents() |
526 QApplication.processEvents() |
472 |
527 |
473 # extract the configuration values |
528 # extract the configuration values |
474 excludeMessages = self.excludeMessagesEdit.text() |
529 excludeMessages = self.__assembleExcludeMessages() |
475 includeMessages = self.includeMessagesEdit.text() |
530 includeMessages = self.includeMessagesEdit.text() |
476 repeatMessages = self.repeatCheckBox.isChecked() |
531 repeatMessages = self.repeatCheckBox.isChecked() |
477 fixCodes = self.fixIssuesEdit.text() |
532 fixCodes = self.fixIssuesEdit.text() |
478 noFixCodes = self.noFixIssuesEdit.text() |
533 noFixCodes = self.noFixIssuesEdit.text() |
479 self.__noFixCodesList = [ |
534 self.__noFixCodesList = [ |
542 |
597 |
543 This method looks for comment lines like '# eflag: noqa = M601' |
598 This method looks for comment lines like '# eflag: noqa = M601' |
544 at the end of the source in order to extend the list of excluded |
599 at the end of the source in order to extend the list of excluded |
545 messages for one file only. |
600 messages for one file only. |
546 |
601 |
547 @param source source text (list of str or str) |
602 @param source source text |
|
603 @type list of str or str |
548 @return list of checker options |
604 @return list of checker options |
|
605 @rtype list |
549 """ |
606 """ |
550 options = self.__options[:] |
607 options = self.__options[:] |
551 flags = Utilities.extractFlags(source) |
608 flags = Utilities.extractFlags(source) |
552 if "noqa" in flags and isinstance(flags["noqa"], basestring): |
609 if "noqa" in flags and isinstance(flags["noqa"], basestring): |
553 excludeMessages = options[0].strip().rstrip(",") |
610 excludeMessages = options[0].strip().rstrip(",") |
702 |
760 |
703 def __processResult(self, fn, codeStyleCheckerStats, fixes, results): |
761 def __processResult(self, fn, codeStyleCheckerStats, fixes, results): |
704 """ |
762 """ |
705 Private slot called after perfoming a style check on one file. |
763 Private slot called after perfoming a style check on one file. |
706 |
764 |
707 @param fn filename of the just checked file (str) |
765 @param fn filename of the just checked file |
708 @param codeStyleCheckerStats stats of style and name check (dict) |
766 @type str |
709 @param fixes number of applied fixes (int) |
767 @param codeStyleCheckerStats stats of style and name check |
|
768 @type dict |
|
769 @param fixes number of applied fixes |
|
770 @type int |
710 @param results tuple for each found violation of style (tuple of |
771 @param results tuple for each found violation of style (tuple of |
711 lineno (int), position (int), text (str), ignored (bool), |
772 lineno, position, text, ignored, fixed, autofixing) |
712 fixed (bool), autofixing (bool)) |
773 @type tuplt of tuple of (int, int, str, bool, bool, bool) |
713 """ |
774 """ |
714 if self.__finished: |
775 if self.__finished: |
715 return |
776 return |
716 |
777 |
717 # Check if it's the requested file, otherwise ignore signal if not |
778 # Check if it's the requested file, otherwise ignore signal if not |
819 @pyqtSlot() |
882 @pyqtSlot() |
820 def on_startButton_clicked(self): |
883 def on_startButton_clicked(self): |
821 """ |
884 """ |
822 Private slot to start a code style check run. |
885 Private slot to start a code style check run. |
823 """ |
886 """ |
|
887 self.__cleanupData() |
|
888 |
824 if self.__forProject: |
889 if self.__forProject: |
825 data = { |
890 data = { |
|
891 "EnabledCheckerCategories": self.__getCategories(True), |
826 "ExcludeFiles": self.excludeFilesEdit.text(), |
892 "ExcludeFiles": self.excludeFilesEdit.text(), |
827 "ExcludeMessages": self.excludeMessagesEdit.text(), |
893 "ExcludeMessages": self.excludeMessagesEdit.text(), |
828 "IncludeMessages": self.includeMessagesEdit.text(), |
894 "IncludeMessages": self.includeMessagesEdit.text(), |
829 "RepeatMessages": self.repeatCheckBox.isChecked(), |
895 "RepeatMessages": self.repeatCheckBox.isChecked(), |
830 "FixCodes": self.fixIssuesEdit.text(), |
896 "FixCodes": self.fixIssuesEdit.text(), |
874 """ |
940 """ |
875 Private slot to restart a code style check run. |
941 Private slot to restart a code style check run. |
876 """ |
942 """ |
877 self.on_startButton_clicked() |
943 self.on_startButton_clicked() |
878 |
944 |
879 def __selectCodes(self, edit, showFixCodes): |
945 def __selectCodes(self, edit, categories, showFixCodes): |
880 """ |
946 """ |
881 Private method to select message codes via a selection dialog. |
947 Private method to select message codes via a selection dialog. |
882 |
948 |
883 @param edit reference of the line edit to be populated (QLineEdit) |
949 @param edit reference of the line edit to be populated |
|
950 @type QLineEdit |
|
951 @param categories list of message categories to omit |
|
952 @type list of str |
884 @param showFixCodes flag indicating to show a list of fixable |
953 @param showFixCodes flag indicating to show a list of fixable |
885 issues (boolean) |
954 issues |
|
955 @type bool |
886 """ |
956 """ |
887 from .CodeStyleCodeSelectionDialog import CodeStyleCodeSelectionDialog |
957 from .CodeStyleCodeSelectionDialog import CodeStyleCodeSelectionDialog |
888 dlg = CodeStyleCodeSelectionDialog(edit.text(), showFixCodes, self) |
958 dlg = CodeStyleCodeSelectionDialog(edit.text(), categories, |
|
959 showFixCodes, self) |
889 if dlg.exec_() == QDialog.Accepted: |
960 if dlg.exec_() == QDialog.Accepted: |
890 edit.setText(dlg.getSelectedCodes()) |
961 edit.setText(dlg.getSelectedCodes()) |
891 |
962 |
892 @pyqtSlot() |
963 @pyqtSlot() |
893 def on_excludeMessagesSelectButton_clicked(self): |
964 def on_excludeMessagesSelectButton_clicked(self): |
894 """ |
965 """ |
895 Private slot to select the message codes to be excluded via a |
966 Private slot to select the message codes to be excluded via a |
896 selection dialog. |
967 selection dialog. |
897 """ |
968 """ |
898 self.__selectCodes(self.excludeMessagesEdit, False) |
969 self.__selectCodes(self.excludeMessagesEdit, |
|
970 self.__getCategories(False, asList=True), |
|
971 False) |
899 |
972 |
900 @pyqtSlot() |
973 @pyqtSlot() |
901 def on_includeMessagesSelectButton_clicked(self): |
974 def on_includeMessagesSelectButton_clicked(self): |
902 """ |
975 """ |
903 Private slot to select the message codes to be included via a |
976 Private slot to select the message codes to be included via a |
904 selection dialog. |
977 selection dialog. |
905 """ |
978 """ |
906 self.__selectCodes(self.includeMessagesEdit, False) |
979 self.__selectCodes(self.includeMessagesEdit, |
|
980 self.__getCategories(True, asList=True), |
|
981 False) |
907 |
982 |
908 @pyqtSlot() |
983 @pyqtSlot() |
909 def on_fixIssuesSelectButton_clicked(self): |
984 def on_fixIssuesSelectButton_clicked(self): |
910 """ |
985 """ |
911 Private slot to select the issue codes to be fixed via a |
986 Private slot to select the issue codes to be fixed via a |
912 selection dialog. |
987 selection dialog. |
913 """ |
988 """ |
914 self.__selectCodes(self.fixIssuesEdit, True) |
989 self.__selectCodes(self.fixIssuesEdit, [], True) |
915 |
990 |
916 @pyqtSlot() |
991 @pyqtSlot() |
917 def on_noFixIssuesSelectButton_clicked(self): |
992 def on_noFixIssuesSelectButton_clicked(self): |
918 """ |
993 """ |
919 Private slot to select the issue codes not to be fixed via a |
994 Private slot to select the issue codes not to be fixed via a |
920 selection dialog. |
995 selection dialog. |
921 """ |
996 """ |
922 self.__selectCodes(self.noFixIssuesEdit, True) |
997 self.__selectCodes(self.noFixIssuesEdit, [], True) |
923 |
998 |
924 @pyqtSlot(QTreeWidgetItem, int) |
999 @pyqtSlot(QTreeWidgetItem, int) |
925 def on_resultList_itemActivated(self, item, column): |
1000 def on_resultList_itemActivated(self, item, column): |
926 """ |
1001 """ |
927 Private slot to handle the activation of an item. |
1002 Private slot to handle the activation of an item. |
928 |
1003 |
929 @param item reference to the activated item (QTreeWidgetItem) |
1004 @param item reference to the activated item |
930 @param column column the item was activated in (integer) |
1005 @type QTreeWidgetItem |
|
1006 @param column column the item was activated in |
|
1007 @type int |
931 """ |
1008 """ |
932 if self.results != CodeStyleCheckerDialog.hasResults: |
1009 if self.results != CodeStyleCheckerDialog.hasResults: |
933 return |
1010 return |
934 |
1011 |
935 if item.parent(): |
1012 if item.parent(): |
1012 @pyqtSlot() |
1089 @pyqtSlot() |
1013 def on_loadDefaultButton_clicked(self): |
1090 def on_loadDefaultButton_clicked(self): |
1014 """ |
1091 """ |
1015 Private slot to load the default configuration values. |
1092 Private slot to load the default configuration values. |
1016 """ |
1093 """ |
|
1094 self.__initCategoriesList(Preferences.Prefs.settings.value( |
|
1095 "PEP8/EnabledCheckerCategories", |
|
1096 ",".join(CodeStyleCheckerDialog.checkCategories.keys()))) |
1017 self.excludeFilesEdit.setText(Preferences.Prefs.settings.value( |
1097 self.excludeFilesEdit.setText(Preferences.Prefs.settings.value( |
1018 "PEP8/ExcludeFilePatterns", "")) |
1098 "PEP8/ExcludeFilePatterns", "")) |
1019 self.excludeMessagesEdit.setText(Preferences.Prefs.settings.value( |
1099 self.excludeMessagesEdit.setText(Preferences.Prefs.settings.value( |
1020 "PEP8/ExcludeMessages", pycodestyle.DEFAULT_IGNORE)) |
1100 "PEP8/ExcludeMessages", pycodestyle.DEFAULT_IGNORE)) |
1021 self.includeMessagesEdit.setText(Preferences.Prefs.settings.value( |
1101 self.includeMessagesEdit.setText(Preferences.Prefs.settings.value( |
1073 Preferences.Prefs.settings.value( |
1153 Preferences.Prefs.settings.value( |
1074 "PEP8/MinimumAnnotationsCoverage", 75))) |
1154 "PEP8/MinimumAnnotationsCoverage", 75))) |
1075 self.maxAnnotationsComplexitySpinBox.setValue(int( |
1155 self.maxAnnotationsComplexitySpinBox.setValue(int( |
1076 Preferences.Prefs.settings.value( |
1156 Preferences.Prefs.settings.value( |
1077 "PEP8/MaximumAnnotationComplexity", 3))) |
1157 "PEP8/MaximumAnnotationComplexity", 3))) |
|
1158 |
|
1159 self.__cleanupData() |
1078 |
1160 |
1079 @pyqtSlot() |
1161 @pyqtSlot() |
1080 def on_storeDefaultButton_clicked(self): |
1162 def on_storeDefaultButton_clicked(self): |
1081 """ |
1163 """ |
1082 Private slot to store the current configuration values as |
1164 Private slot to store the current configuration values as |
1083 default values. |
1165 default values. |
1084 """ |
1166 """ |
1085 Preferences.Prefs.settings.setValue( |
1167 Preferences.Prefs.settings.setValue( |
|
1168 "PEP8/EnabledCheckerCategories", self.__getCategories(True)) |
|
1169 Preferences.Prefs.settings.setValue( |
1086 "PEP8/ExcludeFilePatterns", self.excludeFilesEdit.text()) |
1170 "PEP8/ExcludeFilePatterns", self.excludeFilesEdit.text()) |
1087 Preferences.Prefs.settings.setValue( |
1171 Preferences.Prefs.settings.setValue( |
1088 "PEP8/ExcludeMessages", self.excludeMessagesEdit.text()) |
1172 "PEP8/ExcludeMessages", self.excludeMessagesEdit.text()) |
1089 Preferences.Prefs.settings.setValue( |
1173 Preferences.Prefs.settings.setValue( |
1090 "PEP8/IncludeMessages", self.includeMessagesEdit.text()) |
1174 "PEP8/IncludeMessages", self.includeMessagesEdit.text()) |
1142 @pyqtSlot() |
1226 @pyqtSlot() |
1143 def on_resetDefaultButton_clicked(self): |
1227 def on_resetDefaultButton_clicked(self): |
1144 """ |
1228 """ |
1145 Private slot to reset the configuration values to their default values. |
1229 Private slot to reset the configuration values to their default values. |
1146 """ |
1230 """ |
|
1231 Preferences.Prefs.settings.setValue( |
|
1232 "PEP8/EnabledCheckerCategories", |
|
1233 ",".join(CodeStyleCheckerDialog.checkCategories.keys())) |
1147 Preferences.Prefs.settings.setValue("PEP8/ExcludeFilePatterns", "") |
1234 Preferences.Prefs.settings.setValue("PEP8/ExcludeFilePatterns", "") |
1148 Preferences.Prefs.settings.setValue( |
1235 Preferences.Prefs.settings.setValue( |
1149 "PEP8/ExcludeMessages", pycodestyle.DEFAULT_IGNORE) |
1236 "PEP8/ExcludeMessages", pycodestyle.DEFAULT_IGNORE) |
1150 Preferences.Prefs.settings.setValue("PEP8/IncludeMessages", "") |
1237 Preferences.Prefs.settings.setValue("PEP8/IncludeMessages", "") |
1151 Preferences.Prefs.settings.setValue("PEP8/RepeatMessages", False) |
1238 Preferences.Prefs.settings.setValue("PEP8/RepeatMessages", False) |
1276 |
1366 |
1277 def __itemFixable(self, itm): |
1367 def __itemFixable(self, itm): |
1278 """ |
1368 """ |
1279 Private method to check, if an item has a fixable issue. |
1369 Private method to check, if an item has a fixable issue. |
1280 |
1370 |
1281 @param itm item to be checked (QTreeWidgetItem) |
1371 @param itm item to be checked |
1282 @return flag indicating a fixable issue (boolean) |
1372 @type QTreeWidgetItem |
|
1373 @return flag indicating a fixable issue |
|
1374 @rtype bool |
1283 """ |
1375 """ |
1284 return (itm.data(0, self.fixableRole) and |
1376 return (itm.data(0, self.fixableRole) and |
1285 not itm.data(0, self.ignoredRole)) |
1377 not itm.data(0, self.ignoredRole)) |
1286 |
1378 |
1287 def __initFuturesList(self, selectedFutures): |
1379 def __initFuturesList(self, selectedFutures): |
1379 """ |
1471 """ |
1380 for itm in self.builtinsAssignmentList.selectedItems(): |
1472 for itm in self.builtinsAssignmentList.selectedItems(): |
1381 index = self.builtinsAssignmentList.indexOfTopLevelItem(itm) |
1473 index = self.builtinsAssignmentList.indexOfTopLevelItem(itm) |
1382 self.builtinsAssignmentList.takeTopLevelItem(index) |
1474 self.builtinsAssignmentList.takeTopLevelItem(index) |
1383 del itm |
1475 del itm |
|
1476 |
|
1477 def __initCategoriesList(self, enabledCategories): |
|
1478 """ |
|
1479 Private method to set the enabled status of the checker categories. |
|
1480 |
|
1481 @param enabledCategories comma separated list of enabled checker |
|
1482 categories |
|
1483 @type str |
|
1484 """ |
|
1485 if enabledCategories: |
|
1486 enabledCategoriesList = [ |
|
1487 c.strip() for c in enabledCategories.split(",") |
|
1488 if bool(c.strip())] |
|
1489 else: |
|
1490 enabledCategoriesList = list( |
|
1491 CodeStyleCheckerDialog.checkCategories.keys()) |
|
1492 for row in range(self.categoriesList.count()): |
|
1493 itm = self.categoriesList.item(row) |
|
1494 if itm.data(Qt.UserRole) in enabledCategoriesList: |
|
1495 itm.setCheckState(Qt.Checked) |
|
1496 else: |
|
1497 itm.setCheckState(Qt.Unchecked) |
|
1498 |
|
1499 def __getCategories(self, enabled, asList=False): |
|
1500 """ |
|
1501 Private method to get the enabled or disabled checker categories. |
|
1502 |
|
1503 @param enabled flag indicating to return enabled categories |
|
1504 @type bool |
|
1505 @param asList flag indicating to return the checker categories as a |
|
1506 Python list |
|
1507 @type bool |
|
1508 @return checker categories as a list or comma separated string |
|
1509 @rtype str or list of str |
|
1510 """ |
|
1511 state = Qt.Checked if enabled else Qt.Unchecked |
|
1512 |
|
1513 checkerList = [] |
|
1514 for row in range(self.categoriesList.count()): |
|
1515 itm = self.categoriesList.item(row) |
|
1516 if itm.checkState() == state: |
|
1517 checkerList.append(itm.data(Qt.UserRole)) |
|
1518 if asList: |
|
1519 return checkerList |
|
1520 else: |
|
1521 return ", ".join(checkerList) |
|
1522 |
|
1523 def __assembleExcludeMessages(self): |
|
1524 """ |
|
1525 Private method to assemble the list of excluded checks. |
|
1526 |
|
1527 @return list of excluded checks as a comma separated string. |
|
1528 @rtype str |
|
1529 """ |
|
1530 excludeMessages = self.excludeMessagesEdit.text() |
|
1531 disabledCategories = self.__getCategories(False) |
|
1532 |
|
1533 if excludeMessages and disabledCategories: |
|
1534 return disabledCategories + "," + excludeMessages |
|
1535 elif disabledCategories: |
|
1536 return disabledCategories |
|
1537 elif excludeMessages: |
|
1538 return excludeMessages |
|
1539 else: |
|
1540 return "" |
|
1541 |
|
1542 def __cleanupData(self): |
|
1543 """ |
|
1544 Private method to clean the loaded/entered data of redundant entries. |
|
1545 """ |
|
1546 # Migrate single letter exclude messages to disabled checker categories |
|
1547 # and delete them from exlude messages |
|
1548 excludedMessages = [ |
|
1549 m.strip() |
|
1550 for m in self.excludeMessagesEdit.text().split(",") |
|
1551 if bool(m) |
|
1552 ] |
|
1553 excludedMessageCategories = [ |
|
1554 c for c in excludedMessages if len(c) == 1 |
|
1555 ] |
|
1556 enabledCheckers = self.__getCategories(True, asList=True) |
|
1557 for category in excludedMessageCategories: |
|
1558 if category in enabledCheckers: |
|
1559 enabledCheckers.remove(category) |
|
1560 excludedMessages.remove(category) |
|
1561 |
|
1562 # Remove excluded messages of an already excluded category |
|
1563 disabledCheckers = self.__getCategories(False, asList=True) |
|
1564 for message in excludedMessages[:]: |
|
1565 if message[0] in disabledCheckers: |
|
1566 excludedMessages.remove(message) |
|
1567 |
|
1568 self.excludeMessagesEdit.setText(",".join(excludedMessages)) |
|
1569 self.__initCategoriesList(",".join(enabledCheckers)) |