eric6/Plugins/CheckerPlugins/CodeStyleChecker/CodeStyleCheckerDialog.py

branch
maintenance
changeset 8273
698ae46f40a4
parent 8259
2bbec88047dd
equal deleted inserted replaced
8190:fb0ef164f536 8273:698ae46f40a4
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.
89 "CheckerCategories", 89 "CheckerCategories",
90 "Security"), 90 "Security"),
91 "W": QCoreApplication.translate( 91 "W": QCoreApplication.translate(
92 "CheckerCategories", 92 "CheckerCategories",
93 "Warnings"), 93 "Warnings"),
94 "Y": QCoreApplication.translate(
95 "CheckerCategories",
96 "Simplify Code"),
94 } 97 }
95 98
96 noResults = 0 99 noResults = 0
97 noFiles = 1 100 noFiles = 1
98 hasResults = 2 101 hasResults = 2
107 browser level 110 browser level
108 @type Project 111 @type Project
109 @param parent reference to the parent widget 112 @param parent reference to the parent widget
110 @type QWidget 113 @type QWidget
111 """ 114 """
112 super(CodeStyleCheckerDialog, self).__init__(parent) 115 super().__init__(parent)
113 self.setupUi(self) 116 self.setupUi(self)
114 self.setWindowFlags(Qt.WindowType.Window) 117 self.setWindowFlags(Qt.WindowType.Window)
115 118
116 self.__project = project 119 self.__project = project
117 120
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
1072 @param fn filename where to determine the line ending 1152 @param fn filename where to determine the line ending
1073 @type str 1153 @type str
1074 @return eol string 1154 @return eol string
1075 @rtype str 1155 @rtype str
1076 """ 1156 """
1077 if self.__project.isOpen() and self.__project.isProjectFile(fn): 1157 eol = (
1078 eol = self.__project.getEolString() 1158 self.__project.getEolString()
1079 else: 1159 if self.__project.isOpen() and self.__project.isProjectFile(fn)
1080 eol = Utilities.linesep() 1160 else Utilities.linesep()
1161 )
1081 return eol 1162 return eol
1082 1163
1083 @pyqtSlot() 1164 @pyqtSlot()
1084 def on_startButton_clicked(self): 1165 def on_startButton_clicked(self):
1085 """ 1166 """
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)

eric ide

mercurial