8 """ |
8 """ |
9 |
9 |
10 import os |
10 import os |
11 import fnmatch |
11 import fnmatch |
12 import copy |
12 import copy |
|
13 import collections |
|
14 import json |
13 |
15 |
14 from PyQt5.QtCore import pyqtSlot, Qt, QTimer, QCoreApplication |
16 from PyQt5.QtCore import pyqtSlot, Qt, QTimer, QCoreApplication |
15 from PyQt5.QtGui import QIcon |
17 from PyQt5.QtGui import QIcon |
16 from PyQt5.QtWidgets import ( |
18 from PyQt5.QtWidgets import ( |
17 QDialog, QTreeWidgetItem, QAbstractButton, QDialogButtonBox, QApplication, |
19 QDialog, QTreeWidgetItem, QAbstractButton, QDialogButtonBox, QApplication, |
29 from . import pycodestyle |
31 from . import pycodestyle |
30 |
32 |
31 from .Miscellaneous.MiscellaneousDefaults import ( |
33 from .Miscellaneous.MiscellaneousDefaults import ( |
32 MiscellaneousCheckerDefaultArgs |
34 MiscellaneousCheckerDefaultArgs |
33 ) |
35 ) |
34 |
36 from .Annotations.AnnotationsCheckerDefaults import ( |
35 try: |
37 AnnotationsCheckerDefaultArgs |
36 basestring # __IGNORE_WARNING__ |
38 ) |
37 except Exception: |
|
38 basestring = str # define for Python3 |
|
39 |
39 |
40 |
40 |
41 class CodeStyleCheckerDialog(QDialog, Ui_CodeStyleCheckerDialog): |
41 class CodeStyleCheckerDialog(QDialog, Ui_CodeStyleCheckerDialog): |
42 """ |
42 """ |
43 Class implementing a dialog to show the results of the code style check. |
43 Class implementing a dialog to show the results of the code style check. |
190 |
193 |
191 self.__fileOrFileList = "" |
194 self.__fileOrFileList = "" |
192 self.__project = None |
195 self.__project = None |
193 self.__forProject = False |
196 self.__forProject = False |
194 self.__data = {} |
197 self.__data = {} |
195 self.__statistics = {} |
198 self.__statistics = collections.defaultdict(self.__defaultStatistics) |
196 self.__onlyFixes = {} |
199 self.__onlyFixes = {} |
197 self.__noFixCodesList = [] |
200 self.__noFixCodesList = [] |
|
201 self.__detectedCodes = [] |
198 |
202 |
199 self.on_loadDefaultButton_clicked() |
203 self.on_loadDefaultButton_clicked() |
200 |
204 |
201 self.mainWidget.setCurrentWidget(self.configureTab) |
205 self.mainWidget.setCurrentWidget(self.configureTab) |
202 self.optionsTabWidget.setCurrentWidget(self.globalOptionsTab) |
206 self.optionsTabWidget.setCurrentWidget(self.globalOptionsTab) |
|
207 |
|
208 def __defaultStatistics(self): |
|
209 """ |
|
210 Private method to return the default statistics entry. |
|
211 |
|
212 @return dictionary with default statistics entry |
|
213 @rtype dict |
|
214 """ |
|
215 return { |
|
216 "total": 0, |
|
217 "ignored": 0, |
|
218 } |
203 |
219 |
204 def __resort(self): |
220 def __resort(self): |
205 """ |
221 """ |
206 Private method to resort the tree. |
222 Private method to resort the tree. |
207 """ |
223 """ |
273 self.__lastFileItem.setFirstColumnSpanned(True) |
289 self.__lastFileItem.setFirstColumnSpanned(True) |
274 self.__lastFileItem.setExpanded(True) |
290 self.__lastFileItem.setExpanded(True) |
275 self.__lastFileItem.setData(0, self.filenameRole, filename) |
291 self.__lastFileItem.setData(0, self.filenameRole, filename) |
276 |
292 |
277 msgCode = result["code"].split(".", 1)[0] |
293 msgCode = result["code"].split(".", 1)[0] |
|
294 self.__detectedCodes.append(msgCode) |
278 |
295 |
279 fixable = False |
296 fixable = False |
280 itm = QTreeWidgetItem( |
297 itm = QTreeWidgetItem( |
281 self.__lastFileItem, [ |
298 self.__lastFileItem, [ |
282 "{0:6}".format(result["line"]), |
299 "{0:6}".format(result["line"]), |
290 itm.setIcon(1, UI.PixmapCache.getIcon("namingError")) |
307 itm.setIcon(1, UI.PixmapCache.getIcon("namingError")) |
291 elif msgCode.startswith("D"): |
308 elif msgCode.startswith("D"): |
292 itm.setIcon(1, UI.PixmapCache.getIcon("docstringError")) |
309 itm.setIcon(1, UI.PixmapCache.getIcon("docstringError")) |
293 elif msgCode.startswith("P"): |
310 elif msgCode.startswith("P"): |
294 itm.setIcon(1, UI.PixmapCache.getIcon("dirClosed")) |
311 itm.setIcon(1, UI.PixmapCache.getIcon("dirClosed")) |
|
312 elif msgCode.startswith("Y"): |
|
313 itm.setIcon(1, UI.PixmapCache.getIcon("filePython")) |
295 elif msgCode.startswith("S"): |
314 elif msgCode.startswith("S"): |
296 if "severity" in result: |
315 if "severity" in result: |
297 if result["severity"] == "H": |
316 if result["severity"] == "H": |
298 itm.setIcon(1, UI.PixmapCache.getIcon("securityLow")) |
317 itm.setIcon(1, UI.PixmapCache.getIcon("securityLow")) |
299 elif result["severity"] == "M": |
318 elif result["severity"] == "M": |
372 @type int |
391 @type int |
373 @param securityOk number of acknowledged security reports |
392 @param securityOk number of acknowledged security reports |
374 @type int |
393 @type int |
375 """ |
394 """ |
376 self.__statistics["_FilesCount"] += 1 |
395 self.__statistics["_FilesCount"] += 1 |
377 stats = [k for k in statistics.keys() if k[0].isupper()] |
396 stats = [k for k in statistics if k[0].isupper()] |
378 if stats: |
397 if stats: |
379 self.__statistics["_FilesIssues"] += 1 |
398 self.__statistics["_FilesIssues"] += 1 |
380 for key in statistics: |
399 for key in stats: |
381 if key in self.__statistics: |
400 self.__statistics[key]["total"] += statistics[key] |
382 self.__statistics[key] += statistics[key] |
401 for key in ignoredErrors: |
383 else: |
402 self.__statistics[key]["ignored"] += ignoredErrors[key] |
384 self.__statistics[key] = statistics[key] |
|
385 self.__statistics["_IssuesFixed"] += fixer |
403 self.__statistics["_IssuesFixed"] += fixer |
386 self.__statistics["_IgnoredErrors"] += ignoredErrors |
|
387 self.__statistics["_SecurityOK"] += securityOk |
404 self.__statistics["_SecurityOK"] += securityOk |
388 |
405 |
389 def __updateFixerStatistics(self, fixer): |
406 def __updateFixerStatistics(self, fixer): |
390 """ |
407 """ |
391 Private method to update the collected fixer related statistics. |
408 Private method to update the collected fixer related statistics. |
397 |
414 |
398 def __resetStatistics(self): |
415 def __resetStatistics(self): |
399 """ |
416 """ |
400 Private slot to reset the statistics data. |
417 Private slot to reset the statistics data. |
401 """ |
418 """ |
402 self.__statistics = {} |
419 self.__statistics.clear() |
403 self.__statistics["_FilesCount"] = 0 |
420 self.__statistics["_FilesCount"] = 0 |
404 self.__statistics["_FilesIssues"] = 0 |
421 self.__statistics["_FilesIssues"] = 0 |
405 self.__statistics["_IssuesFixed"] = 0 |
422 self.__statistics["_IssuesFixed"] = 0 |
406 self.__statistics["_IgnoredErrors"] = 0 |
|
407 self.__statistics["_SecurityOK"] = 0 |
423 self.__statistics["_SecurityOK"] = 0 |
408 |
424 |
409 def prepare(self, fileList, project): |
425 def prepare(self, fileList, project): |
410 """ |
426 """ |
411 Public method to prepare the dialog with a list of filenames. |
427 Public method to prepare the dialog with a list of filenames. |
495 MiscellaneousCheckerDefaultArgs[ |
511 MiscellaneousCheckerDefaultArgs[ |
496 "CommentedCodeChecker"]["WhiteList"][:] |
512 "CommentedCodeChecker"]["WhiteList"][:] |
497 ) |
513 ) |
498 |
514 |
499 if "AnnotationsChecker" not in self.__data: |
515 if "AnnotationsChecker" not in self.__data: |
500 self.__data["AnnotationsChecker"] = { |
516 self.__data["AnnotationsChecker"] = copy.deepcopy( |
501 "MinimumCoverage": 75, |
517 AnnotationsCheckerDefaultArgs) |
502 "MaximumComplexity": 3, |
518 else: |
503 } |
519 # We are upgrading from an older data structure |
|
520 if "MaximumLength" not in self.__data["AnnotationsChecker"]: |
|
521 # MaximumLength is the sentinel for the first extension |
|
522 self.__data["AnnotationsChecker"].update({ |
|
523 "MaximumLength": |
|
524 AnnotationsCheckerDefaultArgs["MaximumLength"], |
|
525 "SuppressNoneReturning": |
|
526 AnnotationsCheckerDefaultArgs["SuppressNoneReturning"], |
|
527 "SuppressDummyArgs": |
|
528 AnnotationsCheckerDefaultArgs["SuppressDummyArgs"], |
|
529 "AllowUntypedDefs": |
|
530 AnnotationsCheckerDefaultArgs["AllowUntypedDefs"], |
|
531 "AllowUntypedNested": |
|
532 AnnotationsCheckerDefaultArgs["AllowUntypedNested"], |
|
533 "MypyInitReturn": |
|
534 AnnotationsCheckerDefaultArgs["MypyInitReturn"], |
|
535 "DispatchDecorators": |
|
536 AnnotationsCheckerDefaultArgs["DispatchDecorators"], |
|
537 "OverloadDecorators": |
|
538 AnnotationsCheckerDefaultArgs["OverloadDecorators"], |
|
539 }) |
504 |
540 |
505 if "SecurityChecker" not in self.__data: |
541 if "SecurityChecker" not in self.__data: |
506 from .Security.SecurityDefaults import SecurityDefaults |
542 from .Security.SecurityDefaults import SecurityDefaults |
507 self.__data["SecurityChecker"] = { |
543 self.__data["SecurityChecker"] = { |
508 "HardcodedTmpDirectories": |
544 "HardcodedTmpDirectories": |
555 self.__initBuiltinsIgnoreList(self.__data["BuiltinsChecker"]) |
591 self.__initBuiltinsIgnoreList(self.__data["BuiltinsChecker"]) |
556 self.aggressiveCheckBox.setChecked( |
592 self.aggressiveCheckBox.setChecked( |
557 self.__data["CommentedCodeChecker"]["Aggressive"]) |
593 self.__data["CommentedCodeChecker"]["Aggressive"]) |
558 self.__initCommentedCodeCheckerWhiteList( |
594 self.__initCommentedCodeCheckerWhiteList( |
559 self.__data["CommentedCodeChecker"]["WhiteList"]) |
595 self.__data["CommentedCodeChecker"]["WhiteList"]) |
|
596 |
|
597 # type annotations |
560 self.minAnnotationsCoverageSpinBox.setValue( |
598 self.minAnnotationsCoverageSpinBox.setValue( |
561 self.__data["AnnotationsChecker"]["MinimumCoverage"]) |
599 self.__data["AnnotationsChecker"]["MinimumCoverage"]) |
562 self.maxAnnotationsComplexitySpinBox.setValue( |
600 self.maxAnnotationsComplexitySpinBox.setValue( |
563 self.__data["AnnotationsChecker"]["MaximumComplexity"]) |
601 self.__data["AnnotationsChecker"]["MaximumComplexity"]) |
|
602 self.maxAnnotationsLengthSpinBox.setValue( |
|
603 self.__data["AnnotationsChecker"]["MaximumLength"]) |
|
604 self.suppressNoneReturningCheckBox.setChecked( |
|
605 self.__data["AnnotationsChecker"]["SuppressNoneReturning"]) |
|
606 self.suppressDummyArgsCheckBox.setChecked( |
|
607 self.__data["AnnotationsChecker"]["SuppressDummyArgs"]) |
|
608 self.allowUntypedDefsCheckBox.setChecked( |
|
609 self.__data["AnnotationsChecker"]["AllowUntypedDefs"]) |
|
610 self.allowUntypedNestedCheckBox.setChecked( |
|
611 self.__data["AnnotationsChecker"]["AllowUntypedNested"]) |
|
612 self.mypyInitReturnCheckBox.setChecked( |
|
613 self.__data["AnnotationsChecker"]["MypyInitReturn"]) |
|
614 self.dispatchDecoratorEdit.setText( |
|
615 ", ".join( |
|
616 self.__data["AnnotationsChecker"]["DispatchDecorators"])) |
|
617 self.overloadDecoratorEdit.setText( |
|
618 ", ".join( |
|
619 self.__data["AnnotationsChecker"]["OverloadDecorators"])) |
564 |
620 |
565 # security |
621 # security |
566 self.tmpDirectoriesEdit.setPlainText("\n".join( |
622 self.tmpDirectoriesEdit.setPlainText("\n".join( |
567 self.__data["SecurityChecker"]["HardcodedTmpDirectories"])) |
623 self.__data["SecurityChecker"]["HardcodedTmpDirectories"])) |
568 self.hashesEdit.setText(", ".join( |
624 self.hashesEdit.setText(", ".join( |
710 "CommentedCodeChecker": { |
766 "CommentedCodeChecker": { |
711 "Aggressive": self.aggressiveCheckBox.isChecked(), |
767 "Aggressive": self.aggressiveCheckBox.isChecked(), |
712 "WhiteList": self.__getCommentedCodeCheckerWhiteList(), |
768 "WhiteList": self.__getCommentedCodeCheckerWhiteList(), |
713 } |
769 } |
714 } |
770 } |
|
771 |
715 annotationArgs = { |
772 annotationArgs = { |
716 "MinimumCoverage": |
773 "MinimumCoverage": |
717 self.minAnnotationsCoverageSpinBox.value(), |
774 self.minAnnotationsCoverageSpinBox.value(), |
718 "MaximumComplexity": |
775 "MaximumComplexity": |
719 self.maxAnnotationsComplexitySpinBox.value(), |
776 self.maxAnnotationsComplexitySpinBox.value(), |
|
777 "MaximumLength": |
|
778 self.maxAnnotationsLengthSpinBox.value(), |
|
779 "SuppressNoneReturning": |
|
780 self.suppressNoneReturningCheckBox.isChecked(), |
|
781 "SuppressDummyArgs": |
|
782 self.suppressDummyArgsCheckBox.isChecked(), |
|
783 "AllowUntypedDefs": |
|
784 self.allowUntypedDefsCheckBox.isChecked(), |
|
785 "AllowUntypedNested": |
|
786 self.allowUntypedNestedCheckBox.isChecked(), |
|
787 "MypyInitReturn": |
|
788 self.mypyInitReturnCheckBox.isChecked(), |
|
789 "DispatchDecorators": |
|
790 [d.strip() |
|
791 for d in self.dispatchDecoratorEdit.text().split(",")], |
|
792 "OverloadDecorators": |
|
793 [d.strip() |
|
794 for d in self.overloadDecoratorEdit.text().split(",")], |
720 } |
795 } |
721 |
796 |
722 securityArgs = { |
797 securityArgs = { |
723 "hardcoded_tmp_directories": [ |
798 "hardcoded_tmp_directories": [ |
724 t.strip() |
799 t.strip() |
783 @return list of checker options |
858 @return list of checker options |
784 @rtype list |
859 @rtype list |
785 """ |
860 """ |
786 options = self.__options[:] |
861 options = self.__options[:] |
787 flags = Utilities.extractFlags(source) |
862 flags = Utilities.extractFlags(source) |
788 if "noqa" in flags and isinstance(flags["noqa"], basestring): |
863 if "noqa" in flags and isinstance(flags["noqa"], str): |
789 excludeMessages = options[0].strip().rstrip(",") |
864 excludeMessages = options[0].strip().rstrip(",") |
790 if excludeMessages: |
865 if excludeMessages: |
791 excludeMessages += "," |
866 excludeMessages += "," |
792 excludeMessages += flags["noqa"] |
867 excludeMessages += flags["noqa"] |
793 options[0] = excludeMessages |
868 options[0] = excludeMessages |
862 The results are reported to the __processResult slot. |
937 The results are reported to the __processResult slot. |
863 """ |
938 """ |
864 self.__lastFileItem = None |
939 self.__lastFileItem = None |
865 |
940 |
866 self.checkProgressLabel.setPath(self.tr("Preparing files...")) |
941 self.checkProgressLabel.setPath(self.tr("Preparing files...")) |
867 progress = 0 |
|
868 |
942 |
869 argumentsList = [] |
943 argumentsList = [] |
870 for filename in self.files: |
944 for progress, filename in enumerate(self.files, start=1): |
871 progress += 1 |
|
872 self.checkProgress.setValue(progress) |
945 self.checkProgress.setValue(progress) |
873 QApplication.processEvents() |
946 QApplication.processEvents() |
874 |
947 |
875 try: |
948 try: |
876 source, encoding = Utilities.readEncodedFile( |
949 source, encoding = Utilities.readEncodedFile( |
955 # disable updates of the list for speed |
1028 # disable updates of the list for speed |
956 self.resultList.setUpdatesEnabled(False) |
1029 self.resultList.setUpdatesEnabled(False) |
957 self.resultList.setSortingEnabled(False) |
1030 self.resultList.setSortingEnabled(False) |
958 |
1031 |
959 fixed = None |
1032 fixed = None |
960 ignoredErrors = 0 |
1033 ignoredErrors = collections.defaultdict(int) |
961 securityOk = 0 |
1034 securityOk = 0 |
962 if self.__itms: |
1035 if self.__itms: |
963 for itm, result in zip(self.__itms, results): |
1036 for itm, result in zip(self.__itms, results): |
964 self.__modifyFixedResultItem(itm, result) |
1037 self.__modifyFixedResultItem(itm, result) |
965 self.__updateFixerStatistics(fixes) |
1038 self.__updateFixerStatistics(fixes) |
966 else: |
1039 else: |
967 self.__lastFileItem = None |
1040 self.__lastFileItem = None |
968 |
1041 |
969 for result in results: |
1042 for result in results: |
970 if result["ignored"]: |
1043 if result["ignored"]: |
971 ignoredErrors += 1 |
1044 ignoredErrors[result["code"]] += 1 |
972 if self.showIgnored: |
1045 if self.showIgnored: |
973 result["display"] = self.tr( |
1046 result["display"] = self.tr( |
974 "{0} (ignored)" |
1047 "{0} (ignored)" |
975 ).format(result["display"]) |
1048 ).format(result["display"]) |
976 else: |
1049 else: |
977 continue |
1050 continue |
978 |
1051 |
979 elif result["securityOk"]: |
1052 elif result["securityOk"]: |
980 securityOk += 1 |
1053 securityOk += 1 |
981 continue |
1054 if result["code"].startswith("S"): |
|
1055 continue |
982 |
1056 |
983 self.results = CodeStyleCheckerDialog.hasResults |
1057 self.results = CodeStyleCheckerDialog.hasResults |
984 self.__createResultItem(fn, result) |
1058 self.__createResultItem(fn, result) |
985 |
1059 |
986 self.__updateStatistics( |
1060 self.__updateStatistics( |
987 codeStyleCheckerStats, fixes, ignoredErrors, securityOk) |
1061 codeStyleCheckerStats, fixes, ignoredErrors, securityOk) |
988 |
1062 |
989 if fixed: |
1063 if fixed: |
990 vm = e5App().getObject("ViewManager") |
1064 vm = e5App().getObject("ViewManager") |
1058 self.showButton.setEnabled(True) |
1132 self.showButton.setEnabled(True) |
1059 self.resultList.header().resizeSections( |
1133 self.resultList.header().resizeSections( |
1060 QHeaderView.ResizeMode.ResizeToContents) |
1134 QHeaderView.ResizeMode.ResizeToContents) |
1061 self.resultList.header().setStretchLastSection(True) |
1135 self.resultList.header().setStretchLastSection(True) |
1062 |
1136 |
|
1137 if self.__detectedCodes: |
|
1138 self.filterComboBox.addItem("") |
|
1139 self.filterComboBox.addItems(sorted(set(self.__detectedCodes))) |
|
1140 self.filterComboBox.setEnabled(True) |
|
1141 self.filterButton.setEnabled(True) |
|
1142 |
1063 self.checkProgress.setVisible(False) |
1143 self.checkProgress.setVisible(False) |
1064 self.checkProgressLabel.setVisible(False) |
1144 self.checkProgressLabel.setVisible(False) |
1065 |
1145 |
1066 self.mainWidget.setCurrentWidget(self.resultsTab) |
1146 self.mainWidget.setCurrentWidget(self.resultsTab) |
1067 |
1147 |
1122 "AnnotationsChecker": { |
1203 "AnnotationsChecker": { |
1123 "MinimumCoverage": |
1204 "MinimumCoverage": |
1124 self.minAnnotationsCoverageSpinBox.value(), |
1205 self.minAnnotationsCoverageSpinBox.value(), |
1125 "MaximumComplexity": |
1206 "MaximumComplexity": |
1126 self.maxAnnotationsComplexitySpinBox.value(), |
1207 self.maxAnnotationsComplexitySpinBox.value(), |
|
1208 "MaximumLength": |
|
1209 self.maxAnnotationsLengthSpinBox.value(), |
|
1210 "SuppressNoneReturning": |
|
1211 self.suppressNoneReturningCheckBox.isChecked(), |
|
1212 "SuppressDummyArgs": |
|
1213 self.suppressDummyArgsCheckBox.isChecked(), |
|
1214 "AllowUntypedDefs": |
|
1215 self.allowUntypedDefsCheckBox.isChecked(), |
|
1216 "AllowUntypedNested": |
|
1217 self.allowUntypedNestedCheckBox.isChecked(), |
|
1218 "MypyInitReturn": |
|
1219 self.mypyInitReturnCheckBox.isChecked(), |
|
1220 "DispatchDecorators": |
|
1221 [d.strip() |
|
1222 for d in self.dispatchDecoratorEdit.text().split(",") |
|
1223 ], |
|
1224 "OverloadDecorators": |
|
1225 [d.strip() |
|
1226 for d in self.overloadDecoratorEdit.text().split(",") |
|
1227 ], |
1127 }, |
1228 }, |
1128 "SecurityChecker": { |
1229 "SecurityChecker": { |
1129 "HardcodedTmpDirectories": [ |
1230 "HardcodedTmpDirectories": [ |
1130 t.strip() |
1231 t.strip() |
1131 for t in self.tmpDirectoriesEdit.toPlainText() |
1232 for t in self.tmpDirectoriesEdit.toPlainText() |
1154 self.ecMediumRiskCombo.currentText(), |
1255 self.ecMediumRiskCombo.currentText(), |
1155 "CheckTypedException": |
1256 "CheckTypedException": |
1156 self.typedExceptionsCheckBox.isChecked(), |
1257 self.typedExceptionsCheckBox.isChecked(), |
1157 }, |
1258 }, |
1158 } |
1259 } |
1159 if data != self.__data: |
1260 if ( |
|
1261 json.dumps(data, sort_keys=True) != |
|
1262 json.dumps(self.__data, sort_keys=True) |
|
1263 ): |
1160 self.__data = data |
1264 self.__data = data |
1161 self.__project.setData("CHECKERSPARMS", "Pep8Checker", |
1265 self.__project.setData("CHECKERSPARMS", "Pep8Checker", |
1162 self.__data) |
1266 self.__data) |
1163 |
1267 |
1164 self.resultList.clear() |
1268 self.resultList.clear() |
1165 self.results = CodeStyleCheckerDialog.noResults |
1269 self.results = CodeStyleCheckerDialog.noResults |
1166 self.cancelled = False |
1270 self.cancelled = False |
|
1271 self.__detectedCodes.clear() |
|
1272 self.filterComboBox.clear() |
|
1273 self.filterComboBox.setEnabled(False) |
|
1274 self.filterButton.setEnabled(False) |
1167 |
1275 |
1168 self.start(self.__fileOrFileList) |
1276 self.start(self.__fileOrFileList) |
1169 |
1277 |
1170 @pyqtSlot() |
1278 @pyqtSlot() |
1171 def on_restartButton_clicked(self): |
1279 def on_restartButton_clicked(self): |
1402 "PEP8/CommentedCodeWhitelist", |
1510 "PEP8/CommentedCodeWhitelist", |
1403 MiscellaneousCheckerDefaultArgs[ |
1511 MiscellaneousCheckerDefaultArgs[ |
1404 "CommentedCodeChecker"]["WhiteList"] |
1512 "CommentedCodeChecker"]["WhiteList"] |
1405 ) |
1513 ) |
1406 )) |
1514 )) |
|
1515 |
|
1516 # type annotations |
1407 self.minAnnotationsCoverageSpinBox.setValue(int( |
1517 self.minAnnotationsCoverageSpinBox.setValue(int( |
1408 Preferences.Prefs.settings.value( |
1518 Preferences.Prefs.settings.value( |
1409 "PEP8/MinimumAnnotationsCoverage", 75))) |
1519 "PEP8/MinimumAnnotationsCoverage", |
|
1520 AnnotationsCheckerDefaultArgs["MinimumCoverage"]))) |
1410 self.maxAnnotationsComplexitySpinBox.setValue(int( |
1521 self.maxAnnotationsComplexitySpinBox.setValue(int( |
1411 Preferences.Prefs.settings.value( |
1522 Preferences.Prefs.settings.value( |
1412 "PEP8/MaximumAnnotationComplexity", 3))) |
1523 "PEP8/MaximumAnnotationComplexity", |
|
1524 AnnotationsCheckerDefaultArgs["MaximumComplexity"]))) |
|
1525 self.maxAnnotationsLengthSpinBox.setValue(int( |
|
1526 Preferences.Prefs.settings.value( |
|
1527 "PEP8/MaximumAnnotationLength", |
|
1528 AnnotationsCheckerDefaultArgs["MaximumLength"]))) |
|
1529 self.suppressNoneReturningCheckBox.setChecked(Preferences.toBool( |
|
1530 Preferences.Prefs.settings.value( |
|
1531 "PEP8/SuppressNoneReturning", |
|
1532 AnnotationsCheckerDefaultArgs["SuppressNoneReturning"]))) |
|
1533 self.suppressDummyArgsCheckBox.setChecked(Preferences.toBool( |
|
1534 Preferences.Prefs.settings.value( |
|
1535 "PEP8/SuppressDummyArgs", |
|
1536 AnnotationsCheckerDefaultArgs["SuppressDummyArgs"]))) |
|
1537 self.allowUntypedDefsCheckBox.setChecked(Preferences.toBool( |
|
1538 Preferences.Prefs.settings.value( |
|
1539 "PEP8/AllowUntypedDefs", |
|
1540 AnnotationsCheckerDefaultArgs["AllowUntypedDefs"]))) |
|
1541 self.allowUntypedNestedCheckBox.setChecked(Preferences.toBool( |
|
1542 Preferences.Prefs.settings.value( |
|
1543 "PEP8/AllowUntypedNested", |
|
1544 AnnotationsCheckerDefaultArgs["AllowUntypedNested"]))) |
|
1545 self.mypyInitReturnCheckBox.setChecked(Preferences.toBool( |
|
1546 Preferences.Prefs.settings.value( |
|
1547 "PEP8/MypyInitReturn", |
|
1548 AnnotationsCheckerDefaultArgs["MypyInitReturn"]))) |
|
1549 self.dispatchDecoratorEdit.setText(", ".join(Preferences.toList( |
|
1550 Preferences.Prefs.settings.value( |
|
1551 "PEP8/DispatchDecorators", |
|
1552 AnnotationsCheckerDefaultArgs["DispatchDecorators"])))) |
|
1553 self.overloadDecoratorEdit.setText(", ".join(Preferences.toList( |
|
1554 Preferences.Prefs.settings.value( |
|
1555 "PEP8/OverloadDecorators", |
|
1556 AnnotationsCheckerDefaultArgs["OverloadDecorators"])))) |
1413 |
1557 |
1414 # security |
1558 # security |
1415 from .Security.SecurityDefaults import SecurityDefaults |
1559 from .Security.SecurityDefaults import SecurityDefaults |
1416 self.tmpDirectoriesEdit.setPlainText("\n".join( |
1560 self.tmpDirectoriesEdit.setPlainText("\n".join( |
1417 Preferences.toList(Preferences.Prefs.settings.value( |
1561 Preferences.toList(Preferences.Prefs.settings.value( |
1515 Preferences.Prefs.settings.setValue( |
1659 Preferences.Prefs.settings.setValue( |
1516 "PEP8/AggressiveSearch", self.aggressiveCheckBox.isChecked()) |
1660 "PEP8/AggressiveSearch", self.aggressiveCheckBox.isChecked()) |
1517 Preferences.Prefs.settings.setValue( |
1661 Preferences.Prefs.settings.setValue( |
1518 "PEP8/CommentedCodeWhitelist", |
1662 "PEP8/CommentedCodeWhitelist", |
1519 self.__getCommentedCodeCheckerWhiteList()) |
1663 self.__getCommentedCodeCheckerWhiteList()) |
|
1664 |
|
1665 # type annotations |
1520 Preferences.Prefs.settings.setValue( |
1666 Preferences.Prefs.settings.setValue( |
1521 "PEP8/MinimumAnnotationsCoverage", |
1667 "PEP8/MinimumAnnotationsCoverage", |
1522 self.minAnnotationsCoverageSpinBox.value()) |
1668 self.minAnnotationsCoverageSpinBox.value()) |
1523 Preferences.Prefs.settings.setValue( |
1669 Preferences.Prefs.settings.setValue( |
1524 "PEP8/MaximumAnnotationComplexity", |
1670 "PEP8/MaximumAnnotationComplexity", |
1525 self.maxAnnotationsComplexitySpinBox.value()) |
1671 self.maxAnnotationsComplexitySpinBox.value()) |
|
1672 Preferences.Prefs.settings.setValue( |
|
1673 "PEP8/MaximumAnnotationLength", |
|
1674 self.maxAnnotationsLengthSpinBox.value()) |
|
1675 Preferences.Prefs.settings.setValue( |
|
1676 "PEP8/SuppressNoneReturning", |
|
1677 self.suppressNoneReturningCheckBox.isChecked()) |
|
1678 Preferences.Prefs.settings.setValue( |
|
1679 "PEP8/SuppressDummyArgs", |
|
1680 self.suppressDummyArgsCheckBox.isChecked()) |
|
1681 Preferences.Prefs.settings.setValue( |
|
1682 "PEP8/AllowUntypedDefs", |
|
1683 self.allowUntypedDefsCheckBox.isChecked()) |
|
1684 Preferences.Prefs.settings.setValue( |
|
1685 "PEP8/AllowUntypedNested", |
|
1686 self.allowUntypedNestedCheckBox.isChecked()) |
|
1687 Preferences.Prefs.settings.setValue( |
|
1688 "PEP8/MypyInitReturn", |
|
1689 self.mypyInitReturnCheckBox.isChecked()) |
|
1690 Preferences.Prefs.settings.setValue( |
|
1691 "PEP8/DispatchDecorators", |
|
1692 [d.strip() |
|
1693 for d in self.dispatchDecoratorEdit.text().split(",")]) |
|
1694 Preferences.Prefs.settings.setValue( |
|
1695 "PEP8/OverloadDecorators", |
|
1696 [d.strip() |
|
1697 for d in self.overloadDecoratorEdit.text().split(",")]) |
1526 |
1698 |
1527 # security |
1699 # security |
1528 Preferences.Prefs.settings.setValue( |
1700 Preferences.Prefs.settings.setValue( |
1529 "PEP8/HardcodedTmpDirectories", |
1701 "PEP8/HardcodedTmpDirectories", |
1530 [t.strip() |
1702 [t.strip() |
1618 Preferences.Prefs.settings.setValue( |
1790 Preferences.Prefs.settings.setValue( |
1619 "PEP8/CommentedCodeWhitelist", |
1791 "PEP8/CommentedCodeWhitelist", |
1620 MiscellaneousCheckerDefaultArgs[ |
1792 MiscellaneousCheckerDefaultArgs[ |
1621 "CommentedCodeChecker"]["WhiteList"] |
1793 "CommentedCodeChecker"]["WhiteList"] |
1622 ) |
1794 ) |
1623 Preferences.Prefs.settings.setValue( |
1795 |
1624 "PEP8/MinimumAnnotationsCoverage", 75) |
1796 # type annotations |
1625 Preferences.Prefs.settings.setValue( |
1797 Preferences.Prefs.settings.setValue( |
1626 "PEP8/MaximumAnnotationComplexity", 3) |
1798 "PEP8/MinimumAnnotationsCoverage", |
|
1799 AnnotationsCheckerDefaultArgs["MinimumCoverage"]) |
|
1800 Preferences.Prefs.settings.setValue( |
|
1801 "PEP8/MaximumAnnotationComplexity", |
|
1802 AnnotationsCheckerDefaultArgs["MaximumComplexity"]) |
|
1803 Preferences.Prefs.settings.setValue( |
|
1804 "PEP8/MaximumAnnotationLength", |
|
1805 AnnotationsCheckerDefaultArgs["MaximumLength"]) |
|
1806 Preferences.Prefs.settings.setValue( |
|
1807 "PEP8/SuppressNoneReturning", |
|
1808 AnnotationsCheckerDefaultArgs["SuppressNoneReturning"]) |
|
1809 Preferences.Prefs.settings.setValue( |
|
1810 "PEP8/SuppressDummyArgs", |
|
1811 AnnotationsCheckerDefaultArgs["SuppressDummyArgs"]) |
|
1812 Preferences.Prefs.settings.setValue( |
|
1813 "PEP8/AllowUntypedDefs", |
|
1814 AnnotationsCheckerDefaultArgs["AllowUntypedDefs"]) |
|
1815 Preferences.Prefs.settings.setValue( |
|
1816 "PEP8/AllowUntypedNested", |
|
1817 AnnotationsCheckerDefaultArgs["AllowUntypedNested"]) |
|
1818 Preferences.Prefs.settings.setValue( |
|
1819 "PEP8/MypyInitReturn", |
|
1820 AnnotationsCheckerDefaultArgs["MypyInitReturn"]) |
|
1821 Preferences.Prefs.settings.setValue( |
|
1822 "PEP8/DispatchDecorators", |
|
1823 AnnotationsCheckerDefaultArgs["DispatchDecorators"]) |
|
1824 Preferences.Prefs.settings.setValue( |
|
1825 "PEP8/OverloadDecorators", |
|
1826 AnnotationsCheckerDefaultArgs["OverloadDecorators"]) |
1627 |
1827 |
1628 # security |
1828 # security |
1629 from .Security.SecurityDefaults import SecurityDefaults |
1829 from .Security.SecurityDefaults import SecurityDefaults |
1630 Preferences.Prefs.settings.setValue( |
1830 Preferences.Prefs.settings.setValue( |
1631 "PEP8/HardcodedTmpDirectories", |
1831 "PEP8/HardcodedTmpDirectories", |
1777 Private method to set the selected status of the future imports. |
1977 Private method to set the selected status of the future imports. |
1778 |
1978 |
1779 @param selectedFutures comma separated list of expected future imports |
1979 @param selectedFutures comma separated list of expected future imports |
1780 @type str |
1980 @type str |
1781 """ |
1981 """ |
1782 if selectedFutures: |
1982 expectedImports = ( |
1783 expectedImports = [ |
1983 [i.strip() for i in selectedFutures.split(",") if bool(i.strip())] |
1784 i.strip() for i in selectedFutures.split(",") |
1984 if selectedFutures else |
1785 if bool(i.strip())] |
1985 [] |
1786 else: |
1986 ) |
1787 expectedImports = [] |
|
1788 for row in range(self.futuresList.count()): |
1987 for row in range(self.futuresList.count()): |
1789 itm = self.futuresList.item(row) |
1988 itm = self.futuresList.item(row) |
1790 if itm.text() in expectedImports: |
1989 if itm.text() in expectedImports: |
1791 itm.setCheckState(Qt.CheckState.Checked) |
1990 itm.setCheckState(Qt.CheckState.Checked) |
1792 else: |
1991 else: |
1876 |
2075 |
1877 @param enabledCategories comma separated list of enabled checker |
2076 @param enabledCategories comma separated list of enabled checker |
1878 categories |
2077 categories |
1879 @type str |
2078 @type str |
1880 """ |
2079 """ |
1881 if enabledCategories: |
2080 enabledCategoriesList = ( |
1882 enabledCategoriesList = [ |
2081 [c.strip() for c in enabledCategories.split(",") |
1883 c.strip() for c in enabledCategories.split(",") |
2082 if bool(c.strip())] |
1884 if bool(c.strip())] |
2083 if enabledCategories else |
1885 else: |
2084 list(CodeStyleCheckerDialog.checkCategories.keys()) |
1886 enabledCategoriesList = list( |
2085 ) |
1887 CodeStyleCheckerDialog.checkCategories.keys()) |
|
1888 for row in range(self.categoriesList.count()): |
2086 for row in range(self.categoriesList.count()): |
1889 itm = self.categoriesList.item(row) |
2087 itm = self.categoriesList.item(row) |
1890 if itm.data(Qt.ItemDataRole.UserRole) in enabledCategoriesList: |
2088 if itm.data(Qt.ItemDataRole.UserRole) in enabledCategoriesList: |
1891 itm.setCheckState(Qt.CheckState.Checked) |
2089 itm.setCheckState(Qt.CheckState.Checked) |
1892 else: |
2090 else: |
2021 """ |
2219 """ |
2022 for itm in self.whitelistWidget.selectedItems(): |
2220 for itm in self.whitelistWidget.selectedItems(): |
2023 row = self.whitelistWidget.row(itm) |
2221 row = self.whitelistWidget.row(itm) |
2024 self.whitelistWidget.takeItem(row) |
2222 self.whitelistWidget.takeItem(row) |
2025 del itm |
2223 del itm |
|
2224 |
|
2225 @pyqtSlot() |
|
2226 def on_filterButton_clicked(self): |
|
2227 """ |
|
2228 Private slot to filter the list of messages based on selected message |
|
2229 code. |
|
2230 """ |
|
2231 selectedMessageCode = self.filterComboBox.currentText() |
|
2232 |
|
2233 for topRow in range(self.resultList.topLevelItemCount()): |
|
2234 topItem = self.resultList.topLevelItem(topRow) |
|
2235 topItem.setExpanded(True) |
|
2236 visibleChildren = topItem.childCount() |
|
2237 for childIndex in range(topItem.childCount()): |
|
2238 childItem = topItem.child(childIndex) |
|
2239 hideChild = ( |
|
2240 childItem.data(0, self.codeRole) != selectedMessageCode |
|
2241 if selectedMessageCode else |
|
2242 False |
|
2243 ) |
|
2244 childItem.setHidden(hideChild) |
|
2245 if hideChild: |
|
2246 visibleChildren -= 1 |
|
2247 topItem.setHidden(visibleChildren == 0) |