"Fossies" - the Fresh Open Source Software Archive

Member "eric6-20.9/eric/eric6/Plugins/CheckerPlugins/CodeStyleChecker/CodeStyleCheckerDialog.py" (4 Jul 2020, 76310 Bytes) of package /linux/misc/eric6-20.9.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "CodeStyleCheckerDialog.py" see the Fossies "Dox" file reference documentation.

    1 # -*- coding: utf-8 -*-
    2 
    3 # Copyright (c) 2011 - 2020 Detlev Offenbach <detlev@die-offenbachs.de>
    4 #
    5 
    6 """
    7 Module implementing a dialog to show the results of the code style check.
    8 """
    9 
   10 
   11 import os
   12 import fnmatch
   13 
   14 from PyQt5.QtCore import pyqtSlot, Qt, QTimer, QCoreApplication
   15 from PyQt5.QtGui import QIcon
   16 from PyQt5.QtWidgets import (
   17     QDialog, QTreeWidgetItem, QAbstractButton, QDialogButtonBox, QApplication,
   18     QHeaderView, QListWidgetItem
   19 )
   20 
   21 from E5Gui.E5Application import e5App
   22 
   23 from .Ui_CodeStyleCheckerDialog import Ui_CodeStyleCheckerDialog
   24 
   25 import UI.PixmapCache
   26 import Preferences
   27 import Utilities
   28 
   29 from . import pycodestyle
   30 
   31 try:
   32     basestring          # __IGNORE_WARNING__
   33 except Exception:
   34     basestring = str    # define for Python3
   35 
   36 
   37 class CodeStyleCheckerDialog(QDialog, Ui_CodeStyleCheckerDialog):
   38     """
   39     Class implementing a dialog to show the results of the code style check.
   40     """
   41     filenameRole = Qt.UserRole + 1
   42     lineRole = Qt.UserRole + 2
   43     positionRole = Qt.UserRole + 3
   44     messageRole = Qt.UserRole + 4
   45     fixableRole = Qt.UserRole + 5
   46     codeRole = Qt.UserRole + 6
   47     ignoredRole = Qt.UserRole + 7
   48     argsRole = Qt.UserRole + 8
   49     
   50     availableFutures = [
   51         'division', 'absolute_import', 'with_statement',
   52         'print_function', 'unicode_literals', 'generator_stop',
   53         'annotations']
   54     
   55     cryptoBitSelectionsDsaRsa = [
   56         "512", "1024", "2048", "4096", "8192", "16384", "32786",
   57     ]
   58     cryptoBitSelectionsEc = [
   59         "160", "224", "256", "384", "512",
   60     ]
   61     
   62     checkCategories = {
   63         "A": QCoreApplication.translate(
   64             "CheckerCategories",
   65             "Annotations"),
   66         "C": QCoreApplication.translate(
   67             "CheckerCategories",
   68             "Code Complexity"),
   69         "D": QCoreApplication.translate(
   70             "CheckerCategories",
   71             "Documentation"),
   72         "E": QCoreApplication.translate(
   73             "CheckerCategories",
   74             "Errors"),
   75         "M": QCoreApplication.translate(
   76             "CheckerCategories",
   77             "Miscellaneous"),
   78         "N": QCoreApplication.translate(
   79             "CheckerCategories",
   80             "Naming"),
   81         "S": QCoreApplication.translate(
   82             "CheckerCategories",
   83             "Security"),
   84         "W": QCoreApplication.translate(
   85             "CheckerCategories",
   86             "Warnings"),
   87     }
   88     
   89     noResults = 0
   90     noFiles = 1
   91     hasResults = 2
   92     
   93     def __init__(self, styleCheckService, project=None, parent=None):
   94         """
   95         Constructor
   96         
   97         @param styleCheckService reference to the service
   98         @type CodeStyleCheckService
   99         @param project reference to the project if called on project or project
  100             browser level
  101         @type Project
  102         @param parent reference to the parent widget
  103         @type QWidget
  104         """
  105         super(CodeStyleCheckerDialog, self).__init__(parent)
  106         self.setupUi(self)
  107         self.setWindowFlags(Qt.Window)
  108         
  109         self.__project = project
  110         
  111         self.optionsTabWidget.setCurrentIndex(0)
  112         
  113         self.excludeMessagesSelectButton.setIcon(
  114             UI.PixmapCache.getIcon("select"))
  115         self.includeMessagesSelectButton.setIcon(
  116             UI.PixmapCache.getIcon("select"))
  117         self.fixIssuesSelectButton.setIcon(
  118             UI.PixmapCache.getIcon("select"))
  119         self.noFixIssuesSelectButton.setIcon(
  120             UI.PixmapCache.getIcon("select"))
  121         
  122         self.docTypeComboBox.addItem(self.tr("PEP-257"), "pep257")
  123         self.docTypeComboBox.addItem(self.tr("Eric"), "eric")
  124         
  125         for category, text in CodeStyleCheckerDialog.checkCategories.items():
  126             itm = QListWidgetItem(text, self.categoriesList)
  127             itm.setData(Qt.UserRole, category)
  128             itm.setFlags(itm.flags() | Qt.ItemIsUserCheckable)
  129             itm.setCheckState(Qt.Unchecked)
  130         
  131         for future in CodeStyleCheckerDialog.availableFutures:
  132             itm = QListWidgetItem(future, self.futuresList)
  133             itm.setFlags(itm.flags() | Qt.ItemIsUserCheckable)
  134             itm.setCheckState(Qt.Unchecked)
  135         
  136         self.dsaHighRiskCombo.addItems(
  137             CodeStyleCheckerDialog.cryptoBitSelectionsDsaRsa)
  138         self.dsaMediumRiskCombo.addItems(
  139             CodeStyleCheckerDialog.cryptoBitSelectionsDsaRsa)
  140         self.rsaHighRiskCombo.addItems(
  141             CodeStyleCheckerDialog.cryptoBitSelectionsDsaRsa)
  142         self.rsaMediumRiskCombo.addItems(
  143             CodeStyleCheckerDialog.cryptoBitSelectionsDsaRsa)
  144         self.ecHighRiskCombo.addItems(
  145             CodeStyleCheckerDialog.cryptoBitSelectionsEc)
  146         self.ecMediumRiskCombo.addItems(
  147             CodeStyleCheckerDialog.cryptoBitSelectionsEc)
  148         
  149         self.statisticsButton.setEnabled(False)
  150         self.showButton.setEnabled(False)
  151         self.cancelButton.setEnabled(True)
  152         self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False)
  153         
  154         self.resultList.headerItem().setText(self.resultList.columnCount(), "")
  155         self.resultList.header().setSortIndicator(0, Qt.AscendingOrder)
  156         
  157         self.addBuiltinButton.setIcon(UI.PixmapCache.getIcon("plus"))
  158         self.deleteBuiltinButton.setIcon(UI.PixmapCache.getIcon("minus"))
  159         
  160         self.restartButton.setEnabled(False)
  161         self.fixButton.setEnabled(False)
  162         
  163         self.checkProgress.setVisible(False)
  164         self.checkProgressLabel.setVisible(False)
  165         self.checkProgressLabel.setMaximumWidth(600)
  166         
  167         self.styleCheckService = styleCheckService
  168         self.styleCheckService.styleChecked.connect(self.__processResult)
  169         self.styleCheckService.batchFinished.connect(self.__batchFinished)
  170         self.styleCheckService.error.connect(self.__processError)
  171         self.filename = None
  172         
  173         self.results = CodeStyleCheckerDialog.noResults
  174         self.cancelled = False
  175         self.__lastFileItem = None
  176         self.__batch = False
  177         self.__finished = True
  178         self.__errorItem = None
  179         
  180         self.__fileOrFileList = ""
  181         self.__project = None
  182         self.__forProject = False
  183         self.__data = {}
  184         self.__statistics = {}
  185         self.__onlyFixes = {}
  186         self.__noFixCodesList = []
  187         
  188         self.on_loadDefaultButton_clicked()
  189         
  190         self.mainWidget.setCurrentWidget(self.configureTab)
  191         self.optionsTabWidget.setCurrentWidget(self.globalOptionsTab)
  192     
  193     def __resort(self):
  194         """
  195         Private method to resort the tree.
  196         """
  197         self.resultList.sortItems(self.resultList.sortColumn(),
  198                                   self.resultList.header().sortIndicatorOrder()
  199                                   )
  200     
  201     def __createErrorItem(self, filename, message):
  202         """
  203         Private slot to create a new error item in the result list.
  204         
  205         @param filename name of the file
  206         @type str
  207         @param message error message
  208         @type str
  209         """
  210         if self.__errorItem is None:
  211             self.__errorItem = QTreeWidgetItem(self.resultList, [
  212                 self.tr("Errors")])
  213             self.__errorItem.setExpanded(True)
  214             self.__errorItem.setForeground(0, Qt.red)
  215         
  216         msg = "{0} ({1})".format(self.__project.getRelativePath(filename),
  217                                  message)
  218         if not self.resultList.findItems(msg, Qt.MatchExactly):
  219             itm = QTreeWidgetItem(self.__errorItem, [msg])
  220             itm.setForeground(0, Qt.red)
  221             itm.setFirstColumnSpanned(True)
  222     
  223     def __createFileErrorItem(self, filename, message):
  224         """
  225         Private method to create an error entry for a given file.
  226         
  227         @param filename file name of the file
  228         @type str
  229         @param message error message text
  230         @type str
  231         """
  232         result = {
  233             "file": filename,
  234             "line": 1,
  235             "offset": 1,
  236             "code": "",
  237             "args": [],
  238             "display": self.tr("Error: {0}").format(message).rstrip(),
  239             "fixed": False,
  240             "autofixing": False,
  241             "ignored": False,
  242         }
  243         self.__createResultItem(filename, result)
  244     
  245     def __createResultItem(self, filename, result):
  246         """
  247         Private method to create an entry in the result list.
  248         
  249         @param filename file name of the file
  250         @type str
  251         @param result dictionary containing check result data
  252         @type dict
  253         @return reference to the created item
  254         @rtype QTreeWidgetItem
  255         """
  256         from .CodeStyleFixer import FixableCodeStyleIssues
  257         
  258         if self.__lastFileItem is None:
  259             # It's a new file
  260             self.__lastFileItem = QTreeWidgetItem(self.resultList, [
  261                 self.__project.getRelativePath(filename)])
  262             self.__lastFileItem.setFirstColumnSpanned(True)
  263             self.__lastFileItem.setExpanded(True)
  264             self.__lastFileItem.setData(0, self.filenameRole, filename)
  265         
  266         msgCode = result["code"].split(".", 1)[0]
  267         
  268         fixable = False
  269         itm = QTreeWidgetItem(
  270             self.__lastFileItem, [
  271                 "{0:6}".format(result["line"]),
  272                 msgCode,
  273                 result["display"]
  274             ]
  275         )
  276         if msgCode.startswith(("W", "-", "C", "M")):
  277             itm.setIcon(1, UI.PixmapCache.getIcon("warning"))
  278         elif msgCode.startswith(("A", "N")):
  279             itm.setIcon(1, UI.PixmapCache.getIcon("namingError"))
  280         elif msgCode.startswith("D"):
  281             itm.setIcon(1, UI.PixmapCache.getIcon("docstringError"))
  282         elif msgCode.startswith("S"):
  283             if "severity" in result:
  284                 if result["severity"] == "H":
  285                     itm.setIcon(1, UI.PixmapCache.getIcon("securityLow"))
  286                 elif result["severity"] == "M":
  287                     itm.setIcon(1, UI.PixmapCache.getIcon("securityMedium"))
  288                 elif result["severity"] == "L":
  289                     itm.setIcon(1, UI.PixmapCache.getIcon("securityHigh"))
  290                 else:
  291                     itm.setIcon(1, UI.PixmapCache.getIcon("securityLow"))
  292             else:
  293                 itm.setIcon(1, UI.PixmapCache.getIcon("securityLow"))
  294         else:
  295             itm.setIcon(1, UI.PixmapCache.getIcon("syntaxError"))
  296         if result["fixed"]:
  297             itm.setIcon(0, UI.PixmapCache.getIcon("issueFixed"))
  298         elif (
  299             msgCode in FixableCodeStyleIssues and
  300             not result["autofixing"] and
  301             msgCode not in self.__noFixCodesList
  302         ):
  303             itm.setIcon(0, UI.PixmapCache.getIcon("issueFixable"))
  304             fixable = True
  305         
  306         itm.setTextAlignment(0, Qt.AlignRight)
  307         itm.setTextAlignment(1, Qt.AlignHCenter)
  308         
  309         itm.setTextAlignment(0, Qt.AlignVCenter)
  310         itm.setTextAlignment(1, Qt.AlignVCenter)
  311         itm.setTextAlignment(2, Qt.AlignVCenter)
  312         
  313         itm.setData(0, self.filenameRole, filename)
  314         itm.setData(0, self.lineRole, int(result["line"]))
  315         itm.setData(0, self.positionRole, int(result["offset"]))
  316         itm.setData(0, self.messageRole, result["display"])
  317         itm.setData(0, self.fixableRole, fixable)
  318         itm.setData(0, self.codeRole, msgCode)
  319         itm.setData(0, self.ignoredRole, result["ignored"])
  320         itm.setData(0, self.argsRole, result["args"])
  321         
  322         if result["ignored"]:
  323             font = itm.font(0)
  324             font.setItalic(True)
  325             for col in range(itm.columnCount()):
  326                 itm.setFont(col, font)
  327         
  328         return itm
  329     
  330     def __modifyFixedResultItem(self, itm, result):
  331         """
  332         Private method to modify a result list entry to show its
  333         positive fixed state.
  334         
  335         @param itm reference to the item to modify
  336         @type QTreeWidgetItem
  337         @param result dictionary containing check result data
  338         @type dict
  339         """
  340         if result["fixed"]:
  341             itm.setText(2, result["display"])
  342             itm.setIcon(0, UI.PixmapCache.getIcon("issueFixed"))
  343             
  344             itm.setData(0, self.messageRole, result["display"])
  345         else:
  346             itm.setIcon(0, QIcon())
  347         itm.setData(0, self.fixableRole, False)
  348     
  349     def __updateStatistics(self, statistics, fixer, ignoredErrors, securityOk):
  350         """
  351         Private method to update the collected statistics.
  352         
  353         @param statistics dictionary of statistical data with
  354             message code as key and message count as value
  355         @type dict
  356         @param fixer reference to the code style fixer
  357         @type CodeStyleFixer
  358         @param ignoredErrors number of ignored errors
  359         @type int
  360         @param securityOk number of acknowledged security reports
  361         @type int
  362         """
  363         self.__statistics["_FilesCount"] += 1
  364         stats = [k for k in statistics.keys() if k[0].isupper()]
  365         if stats:
  366             self.__statistics["_FilesIssues"] += 1
  367             for key in statistics:
  368                 if key in self.__statistics:
  369                     self.__statistics[key] += statistics[key]
  370                 else:
  371                     self.__statistics[key] = statistics[key]
  372         self.__statistics["_IssuesFixed"] += fixer
  373         self.__statistics["_IgnoredErrors"] += ignoredErrors
  374         self.__statistics["_SecurityOK"] += securityOk
  375     
  376     def __updateFixerStatistics(self, fixer):
  377         """
  378         Private method to update the collected fixer related statistics.
  379         
  380         @param fixer reference to the code style fixer
  381         @type CodeStyleFixer
  382         """
  383         self.__statistics["_IssuesFixed"] += fixer
  384     
  385     def __resetStatistics(self):
  386         """
  387         Private slot to reset the statistics data.
  388         """
  389         self.__statistics = {}
  390         self.__statistics["_FilesCount"] = 0
  391         self.__statistics["_FilesIssues"] = 0
  392         self.__statistics["_IssuesFixed"] = 0
  393         self.__statistics["_IgnoredErrors"] = 0
  394         self.__statistics["_SecurityOK"] = 0
  395     
  396     def prepare(self, fileList, project):
  397         """
  398         Public method to prepare the dialog with a list of filenames.
  399         
  400         @param fileList list of filenames
  401         @type list of str
  402         @param project reference to the project object
  403         @type Project
  404         """
  405         self.__fileOrFileList = fileList[:]
  406         self.__project = project
  407         self.__forProject = True
  408         
  409         self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True)
  410         self.buttonBox.button(QDialogButtonBox.Close).setDefault(True)
  411         self.cancelButton.setEnabled(False)
  412         
  413         self.__data = self.__project.getData("CHECKERSPARMS", "Pep8Checker")
  414         if (
  415             self.__data is None or
  416             len(self.__data) < 6
  417         ):
  418             # initialize the data structure
  419             self.__data = {
  420                 "ExcludeFiles": "",
  421                 "ExcludeMessages": pycodestyle.DEFAULT_IGNORE,
  422                 "IncludeMessages": "",
  423                 "RepeatMessages": False,
  424                 "FixCodes": "",
  425                 "FixIssues": False,
  426             }
  427         if "EnabledCheckerCategories" not in self.__data:
  428             self.__data["EnabledCheckerCategories"] = ",".join(
  429                 CodeStyleCheckerDialog.checkCategories.keys())
  430         if "MaxLineLength" not in self.__data:
  431             self.__data["MaxLineLength"] = pycodestyle.MAX_LINE_LENGTH
  432         if "MaxDocLineLength" not in self.__data:
  433             # Use MAX_LINE_LENGTH to avoid messages on existing code
  434             self.__data["MaxDocLineLength"] = pycodestyle.MAX_LINE_LENGTH
  435         if "BlankLines" not in self.__data:
  436             self.__data["BlankLines"] = (2, 1)
  437             # top level, method
  438         if "HangClosing" not in self.__data:
  439             self.__data["HangClosing"] = False
  440         if "NoFixCodes" not in self.__data:
  441             self.__data["NoFixCodes"] = "E501"
  442         if "DocstringType" not in self.__data:
  443             self.__data["DocstringType"] = "pep257"
  444         if "ShowIgnored" not in self.__data:
  445             self.__data["ShowIgnored"] = False
  446         if "MaxCodeComplexity" not in self.__data:
  447             self.__data["MaxCodeComplexity"] = 10
  448         if "LineComplexity" not in self.__data:
  449             self.__data["LineComplexity"] = 15
  450         if "LineComplexityScore" not in self.__data:
  451             self.__data["LineComplexityScore"] = 10
  452         if "ValidEncodings" not in self.__data:
  453             self.__data["ValidEncodings"] = "latin-1, utf-8"
  454         if (
  455             "CopyrightMinFileSize" not in self.__data or
  456             "CopyrightAuthor" not in self.__data
  457         ):
  458             self.__data["CopyrightMinFileSize"] = 0
  459             self.__data["CopyrightAuthor"] = ""
  460         if "FutureChecker" not in self.__data:
  461             self.__data["FutureChecker"] = ""
  462         if "BuiltinsChecker" not in self.__data:
  463             self.__data["BuiltinsChecker"] = {
  464                 "str": ["unicode", ],
  465                 "chr": ["unichr", ],
  466             }
  467         if "CommentedCodeChecker" not in self.__data:
  468             self.__data["CommentedCodeChecker"] = {
  469                 "Aggressive": False,
  470             }
  471         if "AnnotationsChecker" not in self.__data:
  472             self.__data["AnnotationsChecker"] = {
  473                 "MinimumCoverage": 75,
  474                 "MaximumComplexity": 3,
  475             }
  476         
  477         if "SecurityChecker" not in self.__data:
  478             from .Security.SecurityDefaults import SecurityDefaults
  479             self.__data["SecurityChecker"] = {
  480                 "HardcodedTmpDirectories":
  481                     SecurityDefaults["hardcoded_tmp_directories"],
  482                 "InsecureHashes":
  483                     SecurityDefaults["insecure_hashes"],
  484                 "InsecureSslProtocolVersions":
  485                     SecurityDefaults["insecure_ssl_protocol_versions"],
  486                 "WeakKeySizeDsaHigh":
  487                     str(SecurityDefaults["weak_key_size_dsa_high"]),
  488                 "WeakKeySizeDsaMedium":
  489                     str(SecurityDefaults["weak_key_size_dsa_medium"]),
  490                 "WeakKeySizeRsaHigh":
  491                     str(SecurityDefaults["weak_key_size_rsa_high"]),
  492                 "WeakKeySizeRsaMedium":
  493                     str(SecurityDefaults["weak_key_size_rsa_medium"]),
  494                 "WeakKeySizeEcHigh":
  495                     str(SecurityDefaults["weak_key_size_ec_high"]),
  496                 "WeakKeySizeEcMedium":
  497                     str(SecurityDefaults["weak_key_size_ec_medium"]),
  498                 "CheckTypedException":
  499                     SecurityDefaults["check_typed_exception"],
  500             }
  501         
  502         self.__initCategoriesList(self.__data["EnabledCheckerCategories"])
  503         self.excludeFilesEdit.setText(self.__data["ExcludeFiles"])
  504         self.excludeMessagesEdit.setText(self.__data["ExcludeMessages"])
  505         self.includeMessagesEdit.setText(self.__data["IncludeMessages"])
  506         self.repeatCheckBox.setChecked(self.__data["RepeatMessages"])
  507         self.fixIssuesEdit.setText(self.__data["FixCodes"])
  508         self.noFixIssuesEdit.setText(self.__data["NoFixCodes"])
  509         self.fixIssuesCheckBox.setChecked(self.__data["FixIssues"])
  510         self.ignoredCheckBox.setChecked(self.__data["ShowIgnored"])
  511         self.lineLengthSpinBox.setValue(self.__data["MaxLineLength"])
  512         self.docLineLengthSpinBox.setValue(self.__data["MaxDocLineLength"])
  513         self.blankBeforeTopLevelSpinBox.setValue(self.__data["BlankLines"][0])
  514         self.blankBeforeMethodSpinBox.setValue(self.__data["BlankLines"][1])
  515         self.hangClosingCheckBox.setChecked(self.__data["HangClosing"])
  516         self.docTypeComboBox.setCurrentIndex(
  517             self.docTypeComboBox.findData(self.__data["DocstringType"]))
  518         self.complexitySpinBox.setValue(self.__data["MaxCodeComplexity"])
  519         self.lineComplexitySpinBox.setValue(self.__data["LineComplexity"])
  520         self.lineComplexityScoreSpinBox.setValue(
  521             self.__data["LineComplexityScore"])
  522         self.encodingsEdit.setText(self.__data["ValidEncodings"])
  523         self.copyrightFileSizeSpinBox.setValue(
  524             self.__data["CopyrightMinFileSize"])
  525         self.copyrightAuthorEdit.setText(self.__data["CopyrightAuthor"])
  526         self.__initFuturesList(self.__data["FutureChecker"])
  527         self.__initBuiltinsIgnoreList(self.__data["BuiltinsChecker"])
  528         self.aggressiveCheckBox.setChecked(
  529             self.__data["CommentedCodeChecker"]["Aggressive"])
  530         self.minAnnotationsCoverageSpinBox.setValue(
  531             self.__data["AnnotationsChecker"]["MinimumCoverage"])
  532         self.maxAnnotationsComplexitySpinBox.setValue(
  533             self.__data["AnnotationsChecker"]["MaximumComplexity"])
  534         
  535         # security
  536         self.tmpDirectoriesEdit.setPlainText("\n".join(
  537             self.__data["SecurityChecker"]["HardcodedTmpDirectories"]))
  538         self.hashesEdit.setText(", ".join(
  539             self.__data["SecurityChecker"]["InsecureHashes"]))
  540         self.insecureSslProtocolsEdit.setPlainText("\n".join(
  541             self.__data["SecurityChecker"]["InsecureSslProtocolVersions"]))
  542         self.dsaHighRiskCombo.setCurrentText(
  543             self.__data["SecurityChecker"]["WeakKeySizeDsaHigh"])
  544         self.dsaMediumRiskCombo.setCurrentText(
  545             self.__data["SecurityChecker"]["WeakKeySizeDsaMedium"])
  546         self.rsaHighRiskCombo.setCurrentText(
  547             self.__data["SecurityChecker"]["WeakKeySizeRsaHigh"])
  548         self.rsaMediumRiskCombo.setCurrentText(
  549             self.__data["SecurityChecker"]["WeakKeySizeRsaMedium"])
  550         self.ecHighRiskCombo.setCurrentText(
  551             self.__data["SecurityChecker"]["WeakKeySizeEcHigh"])
  552         self.ecMediumRiskCombo.setCurrentText(
  553             self.__data["SecurityChecker"]["WeakKeySizeEcMedium"])
  554         self.typedExceptionsCheckBox.setChecked(
  555             self.__data["SecurityChecker"]["CheckTypedException"])
  556         
  557         self.__cleanupData()
  558     
  559     def __prepareProgress(self):
  560         """
  561         Private method to prepare the progress tab for the next run.
  562         """
  563         self.progressList.clear()
  564         if len(self.files) > 0:
  565             self.checkProgress.setMaximum(len(self.files))
  566             self.checkProgressLabel.setVisible(len(self.files) > 1)
  567             self.checkProgress.setVisible(len(self.files) > 1)
  568             if len(self.files) > 1:
  569                 if self.__project:
  570                     self.progressList.addItems([
  571                         os.path.join("...", self.__project.getRelativePath(f))
  572                         for f in self.files
  573                     ])
  574                 else:
  575                     self.progressList.addItems(self.files)
  576         
  577         QApplication.processEvents()
  578     
  579     def start(self, fn, save=False, repeat=None):
  580         """
  581         Public slot to start the code style check.
  582         
  583         @param fn file or list of files or directory to be checked
  584         @type str or list of str
  585         @param save flag indicating to save the given file/file list/directory
  586         @type bool
  587         @param repeat state of the repeat check box if it is not None
  588         @type None or bool
  589         """
  590         if self.__project is None:
  591             self.__project = e5App().getObject("Project")
  592         
  593         self.mainWidget.setCurrentWidget(self.progressTab)
  594         
  595         self.cancelled = False
  596         self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False)
  597         self.cancelButton.setEnabled(True)
  598         self.cancelButton.setDefault(True)
  599         self.statisticsButton.setEnabled(False)
  600         self.showButton.setEnabled(False)
  601         self.fixButton.setEnabled(False)
  602         self.startButton.setEnabled(False)
  603         self.restartButton.setEnabled(False)
  604         if repeat is not None:
  605             self.repeatCheckBox.setChecked(repeat)
  606         self.checkProgress.setVisible(True)
  607         QApplication.processEvents()
  608         
  609         if save:
  610             self.__fileOrFileList = fn
  611         
  612         if isinstance(fn, list):
  613             self.files = fn[:]
  614         elif os.path.isdir(fn):
  615             self.files = []
  616             extensions = set(Preferences.getPython("Python3Extensions"))
  617             for ext in extensions:
  618                 self.files.extend(Utilities.direntries(
  619                     fn, True, '*{0}'.format(ext), 0))
  620         else:
  621             self.files = [fn]
  622         
  623         # filter the list depending on the filter string
  624         if self.files:
  625             filterString = self.excludeFilesEdit.text()
  626             filterList = [f.strip() for f in filterString.split(",")
  627                           if f.strip()]
  628             for fileFilter in filterList:
  629                 self.files = [
  630                     f for f in self.files
  631                     if not fnmatch.fnmatch(f, fileFilter.strip())
  632                 ]
  633         
  634         self.__errorItem = None
  635         self.__resetStatistics()
  636         self.__clearErrors(self.files)
  637         self.__cleanupData()
  638         self.__prepareProgress()
  639         
  640         if len(self.files) > 0:
  641             self.securityNoteLabel.setVisible(
  642                 "S" in self.__getCategories(True, asList=True))
  643             
  644             # extract the configuration values
  645             excludeMessages = self.__assembleExcludeMessages()
  646             includeMessages = self.includeMessagesEdit.text()
  647             repeatMessages = self.repeatCheckBox.isChecked()
  648             fixCodes = self.fixIssuesEdit.text()
  649             noFixCodes = self.noFixIssuesEdit.text()
  650             self.__noFixCodesList = [
  651                 c.strip() for c in noFixCodes.split(",") if c.strip()
  652             ]
  653             fixIssues = self.fixIssuesCheckBox.isChecked() and repeatMessages
  654             self.showIgnored = (
  655                 self.ignoredCheckBox.isChecked() and repeatMessages
  656             )
  657             maxLineLength = self.lineLengthSpinBox.value()
  658             maxDocLineLength = self.docLineLengthSpinBox.value()
  659             blankLines = (
  660                 self.blankBeforeTopLevelSpinBox.value(),
  661                 self.blankBeforeMethodSpinBox.value()
  662             )
  663             hangClosing = self.hangClosingCheckBox.isChecked()
  664             docType = self.docTypeComboBox.itemData(
  665                 self.docTypeComboBox.currentIndex())
  666             codeComplexityArgs = {
  667                 "McCabeComplexity": self.complexitySpinBox.value(),
  668                 "LineComplexity": self.lineComplexitySpinBox.value(),
  669                 "LineComplexityScore": self.lineComplexityScoreSpinBox.value(),
  670             }
  671             miscellaneousArgs = {
  672                 "CodingChecker": self.encodingsEdit.text(),
  673                 "CopyrightChecker": {
  674                     "MinFilesize": self.copyrightFileSizeSpinBox.value(),
  675                     "Author": self.copyrightAuthorEdit.text(),
  676                 },
  677                 "FutureChecker": self.__getSelectedFutureImports(),
  678                 "BuiltinsChecker": self.__getBuiltinsIgnoreList(),
  679                 "CommentedCodeChecker": {
  680                     "Aggressive": self.aggressiveCheckBox.isChecked(),
  681                 }
  682             }
  683             annotationArgs = {
  684                 "MinimumCoverage":
  685                     self.minAnnotationsCoverageSpinBox.value(),
  686                 "MaximumComplexity":
  687                     self.maxAnnotationsComplexitySpinBox.value(),
  688             }
  689             
  690             securityArgs = {
  691                 "hardcoded_tmp_directories": [
  692                     t.strip()
  693                     for t in self.tmpDirectoriesEdit.toPlainText().splitlines()
  694                 ],
  695                 "insecure_hashes": [
  696                     h.strip()
  697                     for h in self.hashesEdit.text().split(",")
  698                 ],
  699                 "insecure_ssl_protocol_versions": [
  700                     p.strip()
  701                     for p in self.insecureSslProtocolsEdit.toPlainText()
  702                     .splitlines()
  703                 ],
  704                 "weak_key_size_dsa_high":
  705                     int(self.dsaHighRiskCombo.currentText()),
  706                 "weak_key_size_dsa_medium":
  707                     int(self.dsaMediumRiskCombo.currentText()),
  708                 "weak_key_size_rsa_high":
  709                     int(self.rsaHighRiskCombo.currentText()),
  710                 "weak_key_size_rsa_medium":
  711                     int(self.rsaMediumRiskCombo.currentText()),
  712                 "weak_key_size_ec_high":
  713                     int(self.ecHighRiskCombo.currentText()),
  714                 "weak_key_size_ec_medium":
  715                     int(self.ecMediumRiskCombo.currentText()),
  716                 "check_typed_exception":
  717                     self.typedExceptionsCheckBox.isChecked(),
  718             }
  719             
  720             self.__options = [excludeMessages, includeMessages, repeatMessages,
  721                               fixCodes, noFixCodes, fixIssues, maxLineLength,
  722                               maxDocLineLength, blankLines, hangClosing,
  723                               docType, codeComplexityArgs, miscellaneousArgs,
  724                               annotationArgs, securityArgs]
  725             
  726             # now go through all the files
  727             self.progress = 0
  728             self.files.sort()
  729             if len(self.files) == 1:
  730                 self.__batch = False
  731                 self.mainWidget.setCurrentWidget(self.resultsTab)
  732                 self.check()
  733             else:
  734                 self.__batch = True
  735                 self.checkBatch()
  736         else:
  737             self.results = CodeStyleCheckerDialog.noFiles
  738             self.__finished = False
  739             self.__finish()
  740     
  741     def __modifyOptions(self, source):
  742         """
  743         Private method to modify the options based on eflag: entries.
  744         
  745         This method looks for comment lines like '# eflag: noqa = M601'
  746         at the end of the source in order to extend the list of excluded
  747         messages for one file only.
  748         
  749         @param source source text
  750         @type list of str or str
  751         @return list of checker options
  752         @rtype list
  753         """
  754         options = self.__options[:]
  755         flags = Utilities.extractFlags(source)
  756         if "noqa" in flags and isinstance(flags["noqa"], basestring):
  757             excludeMessages = options[0].strip().rstrip(",")
  758             if excludeMessages:
  759                 excludeMessages += ","
  760             excludeMessages += flags["noqa"]
  761             options[0] = excludeMessages
  762         return options
  763     
  764     def check(self, codestring=''):
  765         """
  766         Public method to start a style check for one file.
  767         
  768         The results are reported to the __processResult slot.
  769         
  770         @param codestring optional sourcestring
  771         @type str
  772         """
  773         if not self.files:
  774             self.checkProgressLabel.setPath("")
  775             self.checkProgress.setMaximum(1)
  776             self.checkProgress.setValue(1)
  777             self.__finish()
  778             return
  779         
  780         self.filename = self.files.pop(0)
  781         self.checkProgress.setValue(self.progress)
  782         self.checkProgressLabel.setPath(self.filename)
  783         QApplication.processEvents()
  784 
  785         if self.cancelled:
  786             self.__resort()
  787             return
  788         
  789         self.__lastFileItem = None
  790         
  791         if codestring:
  792             source = codestring.splitlines(True)
  793             encoding = Utilities.get_coding(source)
  794         else:
  795             try:
  796                 source, encoding = Utilities.readEncodedFile(
  797                     self.filename)
  798                 source = source.splitlines(True)
  799             except (UnicodeError, IOError) as msg:
  800                 self.results = CodeStyleCheckerDialog.hasResults
  801                 self.__createFileErrorItem(self.filename, str(msg))
  802                 self.progress += 1
  803                 # Continue with next file
  804                 self.check()
  805                 return
  806         if encoding.endswith(
  807                 ('-selected', '-default', '-guessed', '-ignore')):
  808             encoding = encoding.rsplit('-', 1)[0]
  809         
  810         options = self.__modifyOptions(source)
  811         
  812         errors = []
  813         self.__itms = []
  814         for error, itm in self.__onlyFixes.pop(self.filename, []):
  815             errors.append(error)
  816             self.__itms.append(itm)
  817         
  818         eol = self.__getEol(self.filename)
  819         args = options + [
  820             errors, eol, encoding, Preferences.getEditor("CreateBackupFile")
  821         ]
  822         self.__finished = False
  823         self.styleCheckService.styleCheck(
  824             None, self.filename, source, args)
  825     
  826     def checkBatch(self):
  827         """
  828         Public method to start a style check batch job.
  829         
  830         The results are reported to the __processResult slot.
  831         """
  832         self.__lastFileItem = None
  833         
  834         self.checkProgressLabel.setPath(self.tr("Preparing files..."))
  835         progress = 0
  836         
  837         argumentsList = []
  838         for filename in self.files:
  839             progress += 1
  840             self.checkProgress.setValue(progress)
  841             QApplication.processEvents()
  842             
  843             try:
  844                 source, encoding = Utilities.readEncodedFile(
  845                     filename)
  846                 source = source.splitlines(True)
  847             except (UnicodeError, IOError) as msg:
  848                 self.results = CodeStyleCheckerDialog.hasResults
  849                 self.__createFileErrorItem(filename, str(msg))
  850                 continue
  851             
  852             if encoding.endswith(
  853                     ('-selected', '-default', '-guessed', '-ignore')):
  854                 encoding = encoding.rsplit('-', 1)[0]
  855             
  856             options = self.__modifyOptions(source)
  857             
  858             errors = []
  859             self.__itms = []
  860             for error, itm in self.__onlyFixes.pop(filename, []):
  861                 errors.append(error)
  862                 self.__itms.append(itm)
  863             
  864             eol = self.__getEol(filename)
  865             args = options + [
  866                 errors, eol, encoding,
  867                 Preferences.getEditor("CreateBackupFile")
  868             ]
  869             argumentsList.append((filename, source, args))
  870         
  871         # reset the progress bar to the checked files
  872         self.checkProgress.setValue(self.progress)
  873         self.checkProgressLabel.setPath(self.tr("Transferring data..."))
  874         QApplication.processEvents()
  875         
  876         self.__finished = False
  877         self.styleCheckService.styleBatchCheck(argumentsList)
  878     
  879     def __batchFinished(self):
  880         """
  881         Private slot handling the completion of a batch job.
  882         """
  883         self.checkProgressLabel.setPath("")
  884         self.checkProgress.setMaximum(1)
  885         self.checkProgress.setValue(1)
  886         self.__finish()
  887     
  888     def __processError(self, fn, msg):
  889         """
  890         Private slot to process an error indication from the service.
  891         
  892         @param fn filename of the file
  893         @type str
  894         @param msg error message
  895         @type str
  896         """
  897         self.__createErrorItem(fn, msg)
  898         
  899         if not self.__batch:
  900             self.check()
  901     
  902     def __processResult(self, fn, codeStyleCheckerStats, fixes, results):
  903         """
  904         Private slot called after perfoming a style check on one file.
  905         
  906         @param fn filename of the just checked file
  907         @type str
  908         @param codeStyleCheckerStats stats of style and name check
  909         @type dict
  910         @param fixes number of applied fixes
  911         @type int
  912         @param results dictionary containing check result data
  913         @type dict
  914         """
  915         if self.__finished:
  916             return
  917         
  918         # Check if it's the requested file, otherwise ignore signal if not
  919         # in batch mode
  920         if not self.__batch and fn != self.filename:
  921             return
  922         
  923         # disable updates of the list for speed
  924         self.resultList.setUpdatesEnabled(False)
  925         self.resultList.setSortingEnabled(False)
  926         
  927         fixed = None
  928         ignoredErrors = 0
  929         securityOk = 0
  930         if self.__itms:
  931             for itm, result in zip(self.__itms, results):
  932                 self.__modifyFixedResultItem(itm, result)
  933             self.__updateFixerStatistics(fixes)
  934         else:
  935             self.__lastFileItem = None
  936             
  937             for result in results:
  938                 if result["ignored"]:
  939                     ignoredErrors += 1
  940                     if self.showIgnored:
  941                         result["display"] = self.tr(
  942                             "{0} (ignored)"
  943                         ).format(result["display"])
  944                     else:
  945                         continue
  946                 
  947                 elif result["securityOk"]:
  948                     securityOk += 1
  949                     continue
  950                 
  951                 self.results = CodeStyleCheckerDialog.hasResults
  952                 self.__createResultItem(fn, result)
  953 
  954             self.__updateStatistics(
  955                 codeStyleCheckerStats, fixes, ignoredErrors, securityOk)
  956         
  957         if fixed:
  958             vm = e5App().getObject("ViewManager")
  959             editor = vm.getOpenEditor(fn)
  960             if editor:
  961                 editor.refresh()
  962         
  963         self.progress += 1
  964         
  965         self.__resort()
  966         # reenable updates of the list
  967         self.resultList.setSortingEnabled(True)
  968         self.resultList.setUpdatesEnabled(True)
  969         
  970         self.__updateProgress(fn)
  971         
  972         if not self.__batch:
  973             self.check()
  974     
  975     def __updateProgress(self, fn):
  976         """
  977         Private method to update the progress tab.
  978         
  979         @param fn filename of the just checked file
  980         @type str
  981         """
  982         if self.__project:
  983             fn = os.path.join("...", self.__project.getRelativePath(fn))
  984         
  985         self.checkProgress.setValue(self.progress)
  986         self.checkProgressLabel.setPath(fn)
  987         
  988         # remove file from the list of jobs to do
  989         fileItems = self.progressList.findItems(fn, Qt.MatchExactly)
  990         if fileItems:
  991             row = self.progressList.row(fileItems[0])
  992             self.progressList.takeItem(row)
  993         
  994         QApplication.processEvents()
  995     
  996     def __finish(self):
  997         """
  998         Private slot called when the code style check finished or the user
  999         pressed the cancel button.
 1000         """
 1001         if not self.__finished:
 1002             self.__finished = True
 1003             
 1004             self.cancelled = True
 1005             self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True)
 1006             self.buttonBox.button(QDialogButtonBox.Close).setDefault(True)
 1007             self.cancelButton.setEnabled(False)
 1008             self.statisticsButton.setEnabled(True)
 1009             self.showButton.setEnabled(True)
 1010             self.startButton.setEnabled(True)
 1011             self.restartButton.setEnabled(True)
 1012             
 1013             if self.results != CodeStyleCheckerDialog.hasResults:
 1014                 if self.results == CodeStyleCheckerDialog.noResults:
 1015                     QTreeWidgetItem(
 1016                         self.resultList, [self.tr('No issues found.')])
 1017                 else:
 1018                     QTreeWidgetItem(
 1019                         self.resultList,
 1020                         [self.tr('No files found (check your ignore list).')])
 1021                 QApplication.processEvents()
 1022                 self.showButton.setEnabled(False)
 1023             else:
 1024                 self.showButton.setEnabled(True)
 1025             self.resultList.header().resizeSections(
 1026                 QHeaderView.ResizeToContents)
 1027             self.resultList.header().setStretchLastSection(True)
 1028             
 1029             self.checkProgress.setVisible(False)
 1030             self.checkProgressLabel.setVisible(False)
 1031             
 1032             self.mainWidget.setCurrentWidget(self.resultsTab)
 1033     
 1034     def __getEol(self, fn):
 1035         """
 1036         Private method to get the applicable eol string.
 1037         
 1038         @param fn filename where to determine the line ending
 1039         @type str
 1040         @return eol string
 1041         @rtype str
 1042         """
 1043         if self.__project.isOpen() and self.__project.isProjectFile(fn):
 1044             eol = self.__project.getEolString()
 1045         else:
 1046             eol = Utilities.linesep()
 1047         return eol
 1048     
 1049     @pyqtSlot()
 1050     def on_startButton_clicked(self):
 1051         """
 1052         Private slot to start a code style check run.
 1053         """
 1054         self.__cleanupData()
 1055         
 1056         if self.__forProject:
 1057             data = {
 1058                 "EnabledCheckerCategories": self.__getCategories(True),
 1059                 "ExcludeFiles": self.excludeFilesEdit.text(),
 1060                 "ExcludeMessages": self.excludeMessagesEdit.text(),
 1061                 "IncludeMessages": self.includeMessagesEdit.text(),
 1062                 "RepeatMessages": self.repeatCheckBox.isChecked(),
 1063                 "FixCodes": self.fixIssuesEdit.text(),
 1064                 "NoFixCodes": self.noFixIssuesEdit.text(),
 1065                 "FixIssues": self.fixIssuesCheckBox.isChecked(),
 1066                 "ShowIgnored": self.ignoredCheckBox.isChecked(),
 1067                 "MaxLineLength": self.lineLengthSpinBox.value(),
 1068                 "MaxDocLineLength": self.docLineLengthSpinBox.value(),
 1069                 "BlankLines": (
 1070                     self.blankBeforeTopLevelSpinBox.value(),
 1071                     self.blankBeforeMethodSpinBox.value()
 1072                 ),
 1073                 "HangClosing": self.hangClosingCheckBox.isChecked(),
 1074                 "DocstringType": self.docTypeComboBox.itemData(
 1075                     self.docTypeComboBox.currentIndex()),
 1076                 "MaxCodeComplexity": self.complexitySpinBox.value(),
 1077                 "LineComplexity": self.lineComplexitySpinBox.value(),
 1078                 "LineComplexityScore": self.lineComplexityScoreSpinBox.value(),
 1079                 "ValidEncodings": self.encodingsEdit.text(),
 1080                 "CopyrightMinFileSize": self.copyrightFileSizeSpinBox.value(),
 1081                 "CopyrightAuthor": self.copyrightAuthorEdit.text(),
 1082                 "FutureChecker": self.__getSelectedFutureImports(),
 1083                 "BuiltinsChecker": self.__getBuiltinsIgnoreList(),
 1084                 "CommentedCodeChecker": {
 1085                     "Aggressive": self.aggressiveCheckBox.isChecked(),
 1086                 },
 1087                 "AnnotationsChecker": {
 1088                     "MinimumCoverage":
 1089                         self.minAnnotationsCoverageSpinBox.value(),
 1090                     "MaximumComplexity":
 1091                         self.maxAnnotationsComplexitySpinBox.value(),
 1092                 },
 1093                 "SecurityChecker": {
 1094                     "HardcodedTmpDirectories": [
 1095                         t.strip()
 1096                         for t in self.tmpDirectoriesEdit.toPlainText()
 1097                         .splitlines()
 1098                     ],
 1099                     "InsecureHashes": [
 1100                         h.strip()
 1101                         for h in self.hashesEdit.text().split(",")
 1102                     ],
 1103                     "InsecureSslProtocolVersions": [
 1104                         p.strip()
 1105                         for p in self.insecureSslProtocolsEdit.toPlainText()
 1106                         .splitlines()
 1107                     ],
 1108                     "WeakKeySizeDsaHigh":
 1109                         self.dsaHighRiskCombo.currentText(),
 1110                     "WeakKeySizeDsaMedium":
 1111                         self.dsaMediumRiskCombo.currentText(),
 1112                     "WeakKeySizeRsaHigh":
 1113                         self.rsaHighRiskCombo.currentText(),
 1114                     "WeakKeySizeRsaMedium":
 1115                         self.rsaMediumRiskCombo.currentText(),
 1116                     "WeakKeySizeEcHigh":
 1117                         self.ecHighRiskCombo.currentText(),
 1118                     "WeakKeySizeEcMedium":
 1119                         self.ecMediumRiskCombo.currentText(),
 1120                     "CheckTypedException":
 1121                         self.typedExceptionsCheckBox.isChecked(),
 1122                 },
 1123             }
 1124             if data != self.__data:
 1125                 self.__data = data
 1126                 self.__project.setData("CHECKERSPARMS", "Pep8Checker",
 1127                                        self.__data)
 1128         
 1129         self.resultList.clear()
 1130         self.results = CodeStyleCheckerDialog.noResults
 1131         self.cancelled = False
 1132         
 1133         self.start(self.__fileOrFileList)
 1134     
 1135     @pyqtSlot()
 1136     def on_restartButton_clicked(self):
 1137         """
 1138         Private slot to restart a code style check run.
 1139         """
 1140         self.on_startButton_clicked()
 1141     
 1142     def __selectCodes(self, edit, categories, showFixCodes):
 1143         """
 1144         Private method to select message codes via a selection dialog.
 1145         
 1146         @param edit reference of the line edit to be populated
 1147         @type QLineEdit
 1148         @param categories list of message categories to omit
 1149         @type list of str
 1150         @param showFixCodes flag indicating to show a list of fixable
 1151             issues
 1152         @type bool
 1153         """
 1154         from .CodeStyleCodeSelectionDialog import CodeStyleCodeSelectionDialog
 1155         dlg = CodeStyleCodeSelectionDialog(edit.text(), categories,
 1156                                            showFixCodes, self)
 1157         if dlg.exec_() == QDialog.Accepted:
 1158             edit.setText(dlg.getSelectedCodes())
 1159     
 1160     @pyqtSlot()
 1161     def on_excludeMessagesSelectButton_clicked(self):
 1162         """
 1163         Private slot to select the message codes to be excluded via a
 1164         selection dialog.
 1165         """
 1166         self.__selectCodes(self.excludeMessagesEdit,
 1167                            self.__getCategories(False, asList=True),
 1168                            False)
 1169     
 1170     @pyqtSlot()
 1171     def on_includeMessagesSelectButton_clicked(self):
 1172         """
 1173         Private slot to select the message codes to be included via a
 1174         selection dialog.
 1175         """
 1176         self.__selectCodes(self.includeMessagesEdit,
 1177                            self.__getCategories(True, asList=True),
 1178                            False)
 1179     
 1180     @pyqtSlot()
 1181     def on_fixIssuesSelectButton_clicked(self):
 1182         """
 1183         Private slot to select the issue codes to be fixed via a
 1184         selection dialog.
 1185         """
 1186         self.__selectCodes(self.fixIssuesEdit, [], True)
 1187     
 1188     @pyqtSlot()
 1189     def on_noFixIssuesSelectButton_clicked(self):
 1190         """
 1191         Private slot to select the issue codes not to be fixed via a
 1192         selection dialog.
 1193         """
 1194         self.__selectCodes(self.noFixIssuesEdit, [], True)
 1195     
 1196     @pyqtSlot(QTreeWidgetItem, int)
 1197     def on_resultList_itemActivated(self, item, column):
 1198         """
 1199         Private slot to handle the activation of an item.
 1200         
 1201         @param item reference to the activated item
 1202         @type QTreeWidgetItem
 1203         @param column column the item was activated in
 1204         @type int
 1205         """
 1206         if self.results != CodeStyleCheckerDialog.hasResults:
 1207             return
 1208         
 1209         if item.parent():
 1210             fn = Utilities.normabspath(item.data(0, self.filenameRole))
 1211             lineno = item.data(0, self.lineRole)
 1212             position = item.data(0, self.positionRole)
 1213             message = item.data(0, self.messageRole)
 1214             code = item.data(0, self.codeRole)
 1215             
 1216             vm = e5App().getObject("ViewManager")
 1217             vm.openSourceFile(fn, lineno=lineno, pos=position + 1)
 1218             editor = vm.getOpenEditor(fn)
 1219             
 1220             if code in ["E901", "E902"]:
 1221                 editor.toggleSyntaxError(lineno, 0, True, message, True)
 1222             else:
 1223                 editor.toggleWarning(
 1224                     lineno, 0, True, message, warningType=editor.WarningStyle)
 1225             
 1226             editor.updateVerticalScrollBar()
 1227     
 1228     @pyqtSlot()
 1229     def on_resultList_itemSelectionChanged(self):
 1230         """
 1231         Private slot to change the dialog state depending on the selection.
 1232         """
 1233         self.fixButton.setEnabled(len(self.__getSelectedFixableItems()) > 0)
 1234     
 1235     @pyqtSlot()
 1236     def on_showButton_clicked(self):
 1237         """
 1238         Private slot to handle the "Show" button press.
 1239         """
 1240         vm = e5App().getObject("ViewManager")
 1241         
 1242         selectedIndexes = []
 1243         for index in range(self.resultList.topLevelItemCount()):
 1244             if self.resultList.topLevelItem(index).isSelected():
 1245                 selectedIndexes.append(index)
 1246         if len(selectedIndexes) == 0:
 1247             selectedIndexes = list(range(self.resultList.topLevelItemCount()))
 1248         for index in selectedIndexes:
 1249             itm = self.resultList.topLevelItem(index)
 1250             fn = Utilities.normabspath(itm.data(0, self.filenameRole))
 1251             vm.openSourceFile(fn, 1)
 1252             editor = vm.getOpenEditor(fn)
 1253             editor.clearStyleWarnings()
 1254             for cindex in range(itm.childCount()):
 1255                 citm = itm.child(cindex)
 1256                 lineno = citm.data(0, self.lineRole)
 1257                 message = citm.data(0, self.messageRole)
 1258                 editor.toggleWarning(
 1259                     lineno, 0, True, message, warningType=editor.WarningStyle)
 1260         
 1261         # go through the list again to clear warning markers for files,
 1262         # that are ok
 1263         openFiles = vm.getOpenFilenames()
 1264         errorFiles = []
 1265         for index in range(self.resultList.topLevelItemCount()):
 1266             itm = self.resultList.topLevelItem(index)
 1267             errorFiles.append(
 1268                 Utilities.normabspath(itm.data(0, self.filenameRole)))
 1269         for file in openFiles:
 1270             if file not in errorFiles:
 1271                 editor = vm.getOpenEditor(file)
 1272                 editor.clearStyleWarnings()
 1273         
 1274         editor = vm.activeWindow()
 1275         editor.updateVerticalScrollBar()
 1276     
 1277     @pyqtSlot()
 1278     def on_statisticsButton_clicked(self):
 1279         """
 1280         Private slot to show the statistics dialog.
 1281         """
 1282         from .CodeStyleStatisticsDialog import CodeStyleStatisticsDialog
 1283         dlg = CodeStyleStatisticsDialog(self.__statistics, self)
 1284         dlg.exec_()
 1285     
 1286     @pyqtSlot()
 1287     def on_loadDefaultButton_clicked(self):
 1288         """
 1289         Private slot to load the default configuration values.
 1290         """
 1291         self.__initCategoriesList(Preferences.Prefs.settings.value(
 1292             "PEP8/EnabledCheckerCategories",
 1293             ",".join(CodeStyleCheckerDialog.checkCategories.keys())))
 1294         self.excludeFilesEdit.setText(Preferences.Prefs.settings.value(
 1295             "PEP8/ExcludeFilePatterns", ""))
 1296         self.excludeMessagesEdit.setText(Preferences.Prefs.settings.value(
 1297             "PEP8/ExcludeMessages", pycodestyle.DEFAULT_IGNORE))
 1298         self.includeMessagesEdit.setText(Preferences.Prefs.settings.value(
 1299             "PEP8/IncludeMessages", ""))
 1300         self.repeatCheckBox.setChecked(Preferences.toBool(
 1301             Preferences.Prefs.settings.value("PEP8/RepeatMessages", False)))
 1302         self.fixIssuesEdit.setText(Preferences.Prefs.settings.value(
 1303             "PEP8/FixCodes", ""))
 1304         self.noFixIssuesEdit.setText(Preferences.Prefs.settings.value(
 1305             "PEP8/NoFixCodes", "E501"))
 1306         self.fixIssuesCheckBox.setChecked(Preferences.toBool(
 1307             Preferences.Prefs.settings.value("PEP8/FixIssues", False)))
 1308         self.ignoredCheckBox.setChecked(Preferences.toBool(
 1309             Preferences.Prefs.settings.value("PEP8/ShowIgnored", False)))
 1310         self.lineLengthSpinBox.setValue(int(Preferences.Prefs.settings.value(
 1311             "PEP8/MaxLineLength", pycodestyle.MAX_LINE_LENGTH)))
 1312         # Use MAX_LINE_LENGTH to avoid messages on existing code
 1313         self.docLineLengthSpinBox.setValue(int(
 1314             Preferences.Prefs.settings.value(
 1315                 "PEP8/MaxDocLineLength", pycodestyle.MAX_LINE_LENGTH)))
 1316         self.blankBeforeTopLevelSpinBox.setValue(
 1317             int(Preferences.Prefs.settings.value(
 1318                 "PEP8/BlankLinesBeforeTopLevel", 2)))
 1319         self.blankBeforeMethodSpinBox.setValue(
 1320             int(Preferences.Prefs.settings.value(
 1321                 "PEP8/BlankLinesBeforeMethod", 1)))
 1322         self.hangClosingCheckBox.setChecked(Preferences.toBool(
 1323             Preferences.Prefs.settings.value("PEP8/HangClosing", False)))
 1324         self.docTypeComboBox.setCurrentIndex(self.docTypeComboBox.findData(
 1325             Preferences.Prefs.settings.value("PEP8/DocstringType", "pep257")))
 1326         self.complexitySpinBox.setValue(int(Preferences.Prefs.settings.value(
 1327             "PEP8/MaxCodeComplexity", 10)))
 1328         self.lineComplexitySpinBox.setValue(
 1329             int(Preferences.Prefs.settings.value(
 1330                 "PEP8/LineComplexity", 15)))
 1331         self.lineComplexityScoreSpinBox.setValue(
 1332             int(Preferences.Prefs.settings.value(
 1333                 "PEP8/LineComplexityScore", 10)))
 1334         self.encodingsEdit.setText(Preferences.Prefs.settings.value(
 1335             "PEP8/ValidEncodings", "latin-1, utf-8"))
 1336         self.copyrightFileSizeSpinBox.setValue(int(
 1337             Preferences.Prefs.settings.value("PEP8/CopyrightMinFileSize", 0)))
 1338         self.copyrightAuthorEdit.setText(
 1339             Preferences.Prefs.settings.value("PEP8/CopyrightAuthor", ""))
 1340         self.__initFuturesList(
 1341             Preferences.Prefs.settings.value("PEP8/FutureChecker", ""))
 1342         self.__initBuiltinsIgnoreList(Preferences.toDict(
 1343             Preferences.Prefs.settings.value("PEP8/BuiltinsChecker", {
 1344                 "str": ["unicode", ],
 1345                 "chr": ["unichr", ],
 1346             })))
 1347         self.aggressiveCheckBox.setChecked(Preferences.toBool(
 1348             Preferences.Prefs.settings.value("PEP8/AggressiveSearch", False)))
 1349         self.minAnnotationsCoverageSpinBox.setValue(int(
 1350             Preferences.Prefs.settings.value(
 1351                 "PEP8/MinimumAnnotationsCoverage", 75)))
 1352         self.maxAnnotationsComplexitySpinBox.setValue(int(
 1353             Preferences.Prefs.settings.value(
 1354                 "PEP8/MaximumAnnotationComplexity", 3)))
 1355         
 1356         # security
 1357         from .Security.SecurityDefaults import SecurityDefaults
 1358         self.tmpDirectoriesEdit.setPlainText("\n".join(
 1359             Preferences.toList(Preferences.Prefs.settings.value(
 1360                 "PEP8/HardcodedTmpDirectories",
 1361                 SecurityDefaults["hardcoded_tmp_directories"]))))
 1362         self.hashesEdit.setText(", ".join(
 1363             Preferences.toList(Preferences.Prefs.settings.value(
 1364                 "PEP8/InsecureHashes",
 1365                 SecurityDefaults["insecure_hashes"])))),
 1366         self.insecureSslProtocolsEdit.setPlainText("\n".join(
 1367             Preferences.toList(Preferences.Prefs.settings.value(
 1368                 "PEP8/InsecureSslProtocolVersions",
 1369                 SecurityDefaults["insecure_ssl_protocol_versions"])))),
 1370         self.dsaHighRiskCombo.setCurrentText(
 1371             Preferences.Prefs.settings.value(
 1372                 "PEP8/WeakKeySizeDsaHigh",
 1373                 str(SecurityDefaults["weak_key_size_dsa_high"])))
 1374         self.dsaMediumRiskCombo.setCurrentText(
 1375             Preferences.Prefs.settings.value(
 1376                 "PEP8/WeakKeySizeDsaMedium",
 1377                 str(SecurityDefaults["weak_key_size_dsa_medium"]))),
 1378         self.rsaHighRiskCombo.setCurrentText(
 1379             Preferences.Prefs.settings.value(
 1380                 "PEP8/WeakKeySizeRsaHigh",
 1381                 str(SecurityDefaults["weak_key_size_rsa_high"]))),
 1382         self.rsaMediumRiskCombo.setCurrentText(
 1383             Preferences.Prefs.settings.value(
 1384                 "PEP8/WeakKeySizeRsaMedium",
 1385                 str(SecurityDefaults["weak_key_size_rsa_medium"]))),
 1386         self.ecHighRiskCombo.setCurrentText(
 1387             Preferences.Prefs.settings.value(
 1388                 "PEP8/WeakKeySizeEcHigh",
 1389                 str(SecurityDefaults["weak_key_size_ec_high"]))),
 1390         self.ecMediumRiskCombo.setCurrentText(
 1391             Preferences.Prefs.settings.value(
 1392                 "PEP8/WeakKeySizeEcMedium",
 1393                 str(SecurityDefaults["weak_key_size_ec_medium"]))),
 1394         self.typedExceptionsCheckBox.setChecked(Preferences.toBool(
 1395             Preferences.Prefs.settings.value(
 1396                 "PEP8/CheckTypedException",
 1397                 SecurityDefaults["check_typed_exception"]))),
 1398         
 1399         self.__cleanupData()
 1400     
 1401     @pyqtSlot()
 1402     def on_storeDefaultButton_clicked(self):
 1403         """
 1404         Private slot to store the current configuration values as
 1405         default values.
 1406         """
 1407         Preferences.Prefs.settings.setValue(
 1408             "PEP8/EnabledCheckerCategories", self.__getCategories(True))
 1409         Preferences.Prefs.settings.setValue(
 1410             "PEP8/ExcludeFilePatterns", self.excludeFilesEdit.text())
 1411         Preferences.Prefs.settings.setValue(
 1412             "PEP8/ExcludeMessages", self.excludeMessagesEdit.text())
 1413         Preferences.Prefs.settings.setValue(
 1414             "PEP8/IncludeMessages", self.includeMessagesEdit.text())
 1415         Preferences.Prefs.settings.setValue(
 1416             "PEP8/RepeatMessages", self.repeatCheckBox.isChecked())
 1417         Preferences.Prefs.settings.setValue(
 1418             "PEP8/FixCodes", self.fixIssuesEdit.text())
 1419         Preferences.Prefs.settings.setValue(
 1420             "PEP8/NoFixCodes", self.noFixIssuesEdit.text())
 1421         Preferences.Prefs.settings.setValue(
 1422             "PEP8/FixIssues", self.fixIssuesCheckBox.isChecked())
 1423         Preferences.Prefs.settings.setValue(
 1424             "PEP8/ShowIgnored", self.ignoredCheckBox.isChecked())
 1425         Preferences.Prefs.settings.setValue(
 1426             "PEP8/MaxLineLength", self.lineLengthSpinBox.value())
 1427         Preferences.Prefs.settings.setValue(
 1428             "PEP8/MaxDocLineLength", self.docLineLengthSpinBox.value())
 1429         Preferences.Prefs.settings.setValue(
 1430             "PEP8/BlankLinesBeforeTopLevel",
 1431             self.blankBeforeTopLevelSpinBox.value())
 1432         Preferences.Prefs.settings.setValue(
 1433             "PEP8/BlankLinesBeforeMethod",
 1434             self.blankBeforeMethodSpinBox.value())
 1435         Preferences.Prefs.settings.setValue(
 1436             "PEP8/HangClosing", self.hangClosingCheckBox.isChecked())
 1437         Preferences.Prefs.settings.setValue(
 1438             "PEP8/DocstringType", self.docTypeComboBox.itemData(
 1439                 self.docTypeComboBox.currentIndex()))
 1440         Preferences.Prefs.settings.setValue(
 1441             "PEP8/MaxCodeComplexity", self.complexitySpinBox.value())
 1442         Preferences.Prefs.settings.setValue(
 1443             "PEP8/LineComplexity", self.lineComplexitySpinBox.value())
 1444         Preferences.Prefs.settings.setValue(
 1445             "PEP8/LineComplexityScore",
 1446             self.lineComplexityScoreSpinBox.value())
 1447         Preferences.Prefs.settings.setValue(
 1448             "PEP8/ValidEncodings", self.encodingsEdit.text())
 1449         Preferences.Prefs.settings.setValue(
 1450             "PEP8/CopyrightMinFileSize", self.copyrightFileSizeSpinBox.value())
 1451         Preferences.Prefs.settings.setValue(
 1452             "PEP8/CopyrightAuthor", self.copyrightAuthorEdit.text())
 1453         Preferences.Prefs.settings.setValue(
 1454             "PEP8/FutureChecker", self.__getSelectedFutureImports())
 1455         Preferences.Prefs.settings.setValue(
 1456             "PEP8/BuiltinsChecker", self.__getBuiltinsIgnoreList())
 1457         Preferences.Prefs.settings.setValue(
 1458             "PEP8/AggressiveSearch", self.aggressiveCheckBox.isChecked())
 1459         Preferences.Prefs.settings.setValue(
 1460             "PEP8/MinimumAnnotationsCoverage",
 1461             self.minAnnotationsCoverageSpinBox.value())
 1462         Preferences.Prefs.settings.setValue(
 1463             "PEP8/MaximumAnnotationComplexity",
 1464             self.maxAnnotationsComplexitySpinBox.value())
 1465         
 1466         # security
 1467         Preferences.Prefs.settings.setValue(
 1468             "PEP8/HardcodedTmpDirectories",
 1469             [t.strip()
 1470              for t in self.tmpDirectoriesEdit.toPlainText().splitlines()
 1471              ]),
 1472         Preferences.Prefs.settings.setValue(
 1473             "PEP8/InsecureHashes",
 1474             [h.strip()
 1475              for h in self.hashesEdit.text().split(",")
 1476              ]),
 1477         Preferences.Prefs.settings.setValue(
 1478             "PEP8/InsecureSslProtocolVersions",
 1479             [p.strip()
 1480              for p in self.insecureSslProtocolsEdit.toPlainText().splitlines()
 1481              ]),
 1482         Preferences.Prefs.settings.setValue(
 1483             "PEP8/WeakKeySizeDsaHigh",
 1484             self.dsaHighRiskCombo.currentText()),
 1485         Preferences.Prefs.settings.setValue(
 1486             "PEP8/WeakKeySizeDsaMedium",
 1487             self.dsaMediumRiskCombo.currentText()),
 1488         Preferences.Prefs.settings.setValue(
 1489             "PEP8/WeakKeySizeRsaHigh",
 1490             self.rsaHighRiskCombo.currentText()),
 1491         Preferences.Prefs.settings.setValue(
 1492             "PEP8/WeakKeySizeRsaMedium",
 1493             self.rsaMediumRiskCombo.currentText()),
 1494         Preferences.Prefs.settings.setValue(
 1495             "PEP8/WeakKeySizeEcHigh",
 1496             self.ecHighRiskCombo.currentText()),
 1497         Preferences.Prefs.settings.setValue(
 1498             "PEP8/WeakKeySizeEcMedium",
 1499             self.ecMediumRiskCombo.currentText()),
 1500         Preferences.Prefs.settings.setValue(
 1501             "PEP8/CheckTypedException",
 1502             self.typedExceptionsCheckBox.isChecked()),
 1503     
 1504     @pyqtSlot()
 1505     def on_resetDefaultButton_clicked(self):
 1506         """
 1507         Private slot to reset the configuration values to their default values.
 1508         """
 1509         Preferences.Prefs.settings.setValue(
 1510             "PEP8/EnabledCheckerCategories",
 1511             ",".join(CodeStyleCheckerDialog.checkCategories.keys()))
 1512         Preferences.Prefs.settings.setValue("PEP8/ExcludeFilePatterns", "")
 1513         Preferences.Prefs.settings.setValue(
 1514             "PEP8/ExcludeMessages", pycodestyle.DEFAULT_IGNORE)
 1515         Preferences.Prefs.settings.setValue("PEP8/IncludeMessages", "")
 1516         Preferences.Prefs.settings.setValue("PEP8/RepeatMessages", False)
 1517         Preferences.Prefs.settings.setValue("PEP8/FixCodes", "")
 1518         Preferences.Prefs.settings.setValue("PEP8/NoFixCodes", "E501")
 1519         Preferences.Prefs.settings.setValue("PEP8/FixIssues", False)
 1520         Preferences.Prefs.settings.setValue("PEP8/ShowIgnored", False)
 1521         Preferences.Prefs.settings.setValue(
 1522             "PEP8/MaxLineLength", pycodestyle.MAX_LINE_LENGTH)
 1523         # Hard reset to pycodestyle preferences
 1524         Preferences.Prefs.settings.setValue(
 1525             "PEP8/MaxDocLineLength", pycodestyle.MAX_DOC_LENGTH)
 1526         Preferences.Prefs.settings.setValue(
 1527             "PEP8/BlankLinesBeforeTopLevel", 2)
 1528         Preferences.Prefs.settings.setValue(
 1529             "PEP8/BlankLinesBeforeMethod", 1)
 1530         Preferences.Prefs.settings.setValue("PEP8/HangClosing", False)
 1531         Preferences.Prefs.settings.setValue("PEP8/DocstringType", "pep257")
 1532         Preferences.Prefs.settings.setValue("PEP8/MaxCodeComplexity", 10)
 1533         Preferences.Prefs.settings.setValue("PEP8/LineComplexity", 15)
 1534         Preferences.Prefs.settings.setValue("PEP8/LineComplexityScore", 10)
 1535         Preferences.Prefs.settings.setValue(
 1536             "PEP8/ValidEncodings", "latin-1, utf-8")
 1537         Preferences.Prefs.settings.setValue("PEP8/CopyrightMinFileSize", 0)
 1538         Preferences.Prefs.settings.setValue("PEP8/CopyrightAuthor", "")
 1539         Preferences.Prefs.settings.setValue("PEP8/FutureChecker", "")
 1540         Preferences.Prefs.settings.setValue("PEP8/BuiltinsChecker", {
 1541             "str": ["unicode", ],
 1542             "chr": ["unichr", ],
 1543         })
 1544         Preferences.Prefs.settings.setValue("PEP8/AggressiveSearch", False)
 1545         Preferences.Prefs.settings.setValue(
 1546             "PEP8/MinimumAnnotationsCoverage", 75)
 1547         Preferences.Prefs.settings.setValue(
 1548             "PEP8/MaximumAnnotationComplexity", 3)
 1549         
 1550         # security
 1551         from .Security.SecurityDefaults import SecurityDefaults
 1552         Preferences.Prefs.settings.setValue(
 1553             "PEP8/HardcodedTmpDirectories",
 1554             SecurityDefaults["hardcoded_tmp_directories"])
 1555         Preferences.Prefs.settings.setValue(
 1556             "PEP8/InsecureHashes",
 1557             SecurityDefaults["insecure_hashes"])
 1558         Preferences.Prefs.settings.setValue(
 1559             "PEP8/InsecureSslProtocolVersions",
 1560             SecurityDefaults["insecure_ssl_protocol_versions"])
 1561         Preferences.Prefs.settings.setValue(
 1562             "PEP8/WeakKeySizeDsaHigh",
 1563             str(SecurityDefaults["weak_key_size_dsa_high"]))
 1564         Preferences.Prefs.settings.setValue(
 1565             "PEP8/WeakKeySizeDsaMedium",
 1566             str(SecurityDefaults["weak_key_size_dsa_medium"]))
 1567         Preferences.Prefs.settings.setValue(
 1568             "PEP8/WeakKeySizeRsaHigh",
 1569             str(SecurityDefaults["weak_key_size_rsa_high"]))
 1570         Preferences.Prefs.settings.setValue(
 1571             "PEP8/WeakKeySizeRsaMedium",
 1572             str(SecurityDefaults["weak_key_size_rsa_medium"]))
 1573         Preferences.Prefs.settings.setValue(
 1574             "PEP8/WeakKeySizeEcHigh",
 1575             str(SecurityDefaults["weak_key_size_ec_high"]))
 1576         Preferences.Prefs.settings.setValue(
 1577             "PEP8/WeakKeySizeEcMedium",
 1578             str(SecurityDefaults["weak_key_size_ec_medium"]))
 1579         Preferences.Prefs.settings.setValue(
 1580             "PEP8/CheckTypedException",
 1581             SecurityDefaults["check_typed_exception"])
 1582         
 1583         # Update UI with default values
 1584         self.on_loadDefaultButton_clicked()
 1585     
 1586     @pyqtSlot()
 1587     def on_cancelButton_clicked(self):
 1588         """
 1589         Private slot to handle the "Cancel" button press.
 1590         """
 1591         if self.__batch:
 1592             self.styleCheckService.cancelStyleBatchCheck()
 1593             QTimer.singleShot(1000, self.__finish)
 1594         else:
 1595             self.__finish()
 1596     
 1597     @pyqtSlot(QAbstractButton)
 1598     def on_buttonBox_clicked(self, button):
 1599         """
 1600         Private slot called by a button of the button box clicked.
 1601         
 1602         @param button button that was clicked
 1603         @type QAbstractButton
 1604         """
 1605         if button == self.buttonBox.button(QDialogButtonBox.Close):
 1606             self.close()
 1607     
 1608     def __clearErrors(self, files):
 1609         """
 1610         Private method to clear all warning markers of open editors to be
 1611         checked.
 1612         
 1613         @param files list of files to be checked
 1614         @type list of str
 1615         """
 1616         vm = e5App().getObject("ViewManager")
 1617         openFiles = vm.getOpenFilenames()
 1618         for file in [f for f in openFiles if f in files]:
 1619             editor = vm.getOpenEditor(file)
 1620             editor.clearStyleWarnings()
 1621     
 1622     @pyqtSlot()
 1623     def on_fixButton_clicked(self):
 1624         """
 1625         Private slot to fix selected issues.
 1626         
 1627         Build a dictionary of issues to fix. Update the initialized __options.
 1628         Then call check with the dict as keyparam to fix selected issues.
 1629         """
 1630         fixableItems = self.__getSelectedFixableItems()
 1631         # dictionary of lists of tuples containing the issue and the item
 1632         fixesDict = {}
 1633         for itm in fixableItems:
 1634             filename = itm.data(0, self.filenameRole)
 1635             if filename not in fixesDict:
 1636                 fixesDict[filename] = []
 1637             fixesDict[filename].append((
 1638                 {
 1639                     "file": filename,
 1640                     "line": itm.data(0, self.lineRole),
 1641                     "offset": itm.data(0, self.positionRole),
 1642                     "code": itm.data(0, self.codeRole),
 1643                     "display": itm.data(0, self.messageRole),
 1644                     "args": itm.data(0, self.argsRole),
 1645                 },
 1646                 itm
 1647             ))
 1648     
 1649         # update the configuration values (3: fixCodes, 4: noFixCodes,
 1650         # 5: fixIssues, 6: maxLineLength)
 1651         self.__options[3] = self.fixIssuesEdit.text()
 1652         self.__options[4] = self.noFixIssuesEdit.text()
 1653         self.__options[5] = True
 1654         self.__options[6] = self.lineLengthSpinBox.value()
 1655         
 1656         self.files = list(fixesDict.keys())
 1657         # now go through all the files
 1658         self.progress = 0
 1659         self.files.sort()
 1660         self.cancelled = False
 1661         self.__onlyFixes = fixesDict
 1662         self.check()
 1663     
 1664     def __getSelectedFixableItems(self):
 1665         """
 1666         Private method to extract all selected items for fixable issues.
 1667         
 1668         @return selected items for fixable issues
 1669         @rtype list of QTreeWidgetItem
 1670         """
 1671         fixableItems = []
 1672         for itm in self.resultList.selectedItems():
 1673             if itm.childCount() > 0:
 1674                 for index in range(itm.childCount()):
 1675                     citm = itm.child(index)
 1676                     if self.__itemFixable(citm) and citm not in fixableItems:
 1677                         fixableItems.append(citm)
 1678             elif self.__itemFixable(itm) and itm not in fixableItems:
 1679                 fixableItems.append(itm)
 1680         
 1681         return fixableItems
 1682     
 1683     def __itemFixable(self, itm):
 1684         """
 1685         Private method to check, if an item has a fixable issue.
 1686         
 1687         @param itm item to be checked
 1688         @type QTreeWidgetItem
 1689         @return flag indicating a fixable issue
 1690         @rtype bool
 1691         """
 1692         return (itm.data(0, self.fixableRole) and
 1693                 not itm.data(0, self.ignoredRole))
 1694     
 1695     def __initFuturesList(self, selectedFutures):
 1696         """
 1697         Private method to set the selected status of the future imports.
 1698         
 1699         @param selectedFutures comma separated list of expected future imports
 1700         @type str
 1701         """
 1702         if selectedFutures:
 1703             expectedImports = [
 1704                 i.strip() for i in selectedFutures.split(",")
 1705                 if bool(i.strip())]
 1706         else:
 1707             expectedImports = []
 1708         for row in range(self.futuresList.count()):
 1709             itm = self.futuresList.item(row)
 1710             if itm.text() in expectedImports:
 1711                 itm.setCheckState(Qt.Checked)
 1712             else:
 1713                 itm.setCheckState(Qt.Unchecked)
 1714     
 1715     def __getSelectedFutureImports(self):
 1716         """
 1717         Private method to get the expected future imports.
 1718         
 1719         @return expected future imports as a comma separated string
 1720         @rtype str
 1721         """
 1722         selectedFutures = []
 1723         for row in range(self.futuresList.count()):
 1724             itm = self.futuresList.item(row)
 1725             if itm.checkState() == Qt.Checked:
 1726                 selectedFutures.append(itm.text())
 1727         return ", ".join(selectedFutures)
 1728     
 1729     def __initBuiltinsIgnoreList(self, builtinsIgnoreDict):
 1730         """
 1731         Private method to populate the list of shadowed builtins to be ignored.
 1732         
 1733         @param builtinsIgnoreDict dictionary containing the builtins
 1734             assignments to be ignored
 1735         @type dict of list of str
 1736         """
 1737         self.builtinsAssignmentList.clear()
 1738         for left, rightList in builtinsIgnoreDict.items():
 1739             for right in rightList:
 1740                 QTreeWidgetItem(self.builtinsAssignmentList, [left, right])
 1741         
 1742         self.on_builtinsAssignmentList_itemSelectionChanged()
 1743     
 1744     def __getBuiltinsIgnoreList(self):
 1745         """
 1746         Private method to get a dictionary containing the builtins assignments
 1747         to be ignored.
 1748         
 1749         @return dictionary containing the builtins assignments to be ignored
 1750         @rtype dict of list of str
 1751         """
 1752         builtinsIgnoreDict = {}
 1753         for row in range(self.builtinsAssignmentList.topLevelItemCount()):
 1754             itm = self.builtinsAssignmentList.topLevelItem(row)
 1755             left, right = itm.text(0), itm.text(1)
 1756             if left not in builtinsIgnoreDict:
 1757                 builtinsIgnoreDict[left] = []
 1758             builtinsIgnoreDict[left].append(right)
 1759         
 1760         return builtinsIgnoreDict
 1761     
 1762     @pyqtSlot()
 1763     def on_builtinsAssignmentList_itemSelectionChanged(self):
 1764         """
 1765         Private slot to react upon changes of the selected builtin assignments.
 1766         """
 1767         self.deleteBuiltinButton.setEnabled(
 1768             len(self.builtinsAssignmentList.selectedItems()) > 0)
 1769     
 1770     @pyqtSlot()
 1771     def on_addBuiltinButton_clicked(self):
 1772         """
 1773         Private slot to add a built-in assignment to be ignored.
 1774         """
 1775         from .CodeStyleAddBuiltinIgnoreDialog import (
 1776             CodeStyleAddBuiltinIgnoreDialog
 1777         )
 1778         dlg = CodeStyleAddBuiltinIgnoreDialog(self)
 1779         if dlg.exec_() == QDialog.Accepted:
 1780             left, right = dlg.getData()
 1781             QTreeWidgetItem(self.builtinsAssignmentList, [left, right])
 1782     
 1783     @pyqtSlot()
 1784     def on_deleteBuiltinButton_clicked(self):
 1785         """
 1786         Private slot to delete the selected items from the list.
 1787         """
 1788         for itm in self.builtinsAssignmentList.selectedItems():
 1789             index = self.builtinsAssignmentList.indexOfTopLevelItem(itm)
 1790             self.builtinsAssignmentList.takeTopLevelItem(index)
 1791             del itm
 1792     
 1793     def __initCategoriesList(self, enabledCategories):
 1794         """
 1795         Private method to set the enabled status of the checker categories.
 1796         
 1797         @param enabledCategories comma separated list of enabled checker
 1798             categories
 1799         @type str
 1800         """
 1801         if enabledCategories:
 1802             enabledCategoriesList = [
 1803                 c.strip() for c in enabledCategories.split(",")
 1804                 if bool(c.strip())]
 1805         else:
 1806             enabledCategoriesList = list(
 1807                 CodeStyleCheckerDialog.checkCategories.keys())
 1808         for row in range(self.categoriesList.count()):
 1809             itm = self.categoriesList.item(row)
 1810             if itm.data(Qt.UserRole) in enabledCategoriesList:
 1811                 itm.setCheckState(Qt.Checked)
 1812             else:
 1813                 itm.setCheckState(Qt.Unchecked)
 1814     
 1815     def __getCategories(self, enabled, asList=False):
 1816         """
 1817         Private method to get the enabled or disabled checker categories.
 1818         
 1819         @param enabled flag indicating to return enabled categories
 1820         @type bool
 1821         @param asList flag indicating to return the checker categories as a
 1822             Python list
 1823         @type bool
 1824         @return checker categories as a list or comma separated string
 1825         @rtype str or list of str
 1826         """
 1827         state = Qt.Checked if enabled else Qt.Unchecked
 1828         
 1829         checkerList = []
 1830         for row in range(self.categoriesList.count()):
 1831             itm = self.categoriesList.item(row)
 1832             if itm.checkState() == state:
 1833                 checkerList.append(itm.data(Qt.UserRole))
 1834         if asList:
 1835             return checkerList
 1836         else:
 1837             return ", ".join(checkerList)
 1838     
 1839     def __assembleExcludeMessages(self):
 1840         """
 1841         Private method to assemble the list of excluded checks.
 1842         
 1843         @return list of excluded checks as a comma separated string.
 1844         @rtype str
 1845         """
 1846         excludeMessages = self.excludeMessagesEdit.text()
 1847         disabledCategories = self.__getCategories(False)
 1848         
 1849         if excludeMessages and disabledCategories:
 1850             return disabledCategories + "," + excludeMessages
 1851         elif disabledCategories:
 1852             return disabledCategories
 1853         elif excludeMessages:
 1854             return excludeMessages
 1855         else:
 1856             return ""
 1857     
 1858     def __cleanupData(self):
 1859         """
 1860         Private method to clean the loaded/entered data of redundant entries.
 1861         """
 1862         # Migrate single letter exclude messages to disabled checker categories
 1863         # and delete them from exlude messages
 1864         excludedMessages = [
 1865             m.strip()
 1866             for m in self.excludeMessagesEdit.text().split(",")
 1867             if bool(m)
 1868         ]
 1869         excludedMessageCategories = [
 1870             c for c in excludedMessages if len(c) == 1
 1871         ]
 1872         enabledCheckers = self.__getCategories(True, asList=True)
 1873         for category in excludedMessageCategories:
 1874             if category in enabledCheckers:
 1875                 enabledCheckers.remove(category)
 1876             excludedMessages.remove(category)
 1877         
 1878         # Remove excluded messages of an already excluded category
 1879         disabledCheckers = self.__getCategories(False, asList=True)
 1880         for message in excludedMessages[:]:
 1881             if message[0] in disabledCheckers:
 1882                 excludedMessages.remove(message)
 1883         
 1884         self.excludeMessagesEdit.setText(",".join(excludedMessages))
 1885         self.__initCategoriesList(",".join(enabledCheckers))