Tue, 20 Sep 2022 17:16:37 +0200
Reformatted sources with 'Black'.
--- a/PluginPyLint.epj Tue Jun 28 08:21:17 2022 +0200 +++ b/PluginPyLint.epj Tue Sep 20 17:16:37 2022 +0200 @@ -1,19 +1,21 @@ { "header": { "comment": "eric project file for project PluginPyLint", - "copyright": "Copyright (C) 2021 Detlev Offenbach, detlev@die-offenbachs.de" + "copyright": "Copyright (C) 2022 Detlev Offenbach, detlev@die-offenbachs.de" }, "project": { "AUTHOR": "Detlev Offenbach", "CHECKERSPARMS": { "Pep8Checker": { "AnnotationsChecker": { + "AllowStarArgAny": false, "AllowUntypedDefs": false, "AllowUntypedNested": false, "DispatchDecorators": [ "singledispatch", "singledispatchmethod" ], + "ForceFutureAnnotations": false, "MaximumComplexity": 3, "MaximumLength": 7, "MinimumCoverage": 75, @@ -59,20 +61,25 @@ }, "CopyrightAuthor": "", "CopyrightMinFileSize": 0, - "DocstringType": "eric", + "DocstringType": "eric_black", "EnabledCheckerCategories": "C, D, E, M, N, S, Y, W", "ExcludeFiles": "*/Ui_*.py, */*_rc.py,", - "ExcludeMessages": "C101,E265,E266,E305,E402,M201,M301,M302,M303,M304,M305,M306,M307,M308,M311,M312,M313,M314,M315,M321,M701,M702,M811,M834,N802,N803,N807,N808,N821,W293,W504,Y119,Y401,Y402", + "ExcludeMessages": "C101,E265,E266,E305,E402,M201,M301,M302,M303,M304,M305,M306,M307,M308,M311,M312,M313,M314,M315,M321,M701,M702,M811,M834,N802,N803,N807,N808,N821,W293,W503,Y119,Y401,Y402", "FixCodes": "", "FixIssues": false, "FutureChecker": "", "HangClosing": false, + "ImportsChecker": { + "ApplicationPackageNames": [], + "BanRelativeImports": "", + "BannedModules": [] + }, "IncludeMessages": "", "LineComplexity": 25, "LineComplexityScore": 10, "MaxCodeComplexity": 10, - "MaxDocLineLength": 79, - "MaxLineLength": 79, + "MaxDocLineLength": 88, + "MaxLineLength": 88, "NoFixCodes": "E501", "RepeatMessages": true, "SecurityChecker": { @@ -128,6 +135,7 @@ } }, "EMAIL": "detlev@die-offenbachs.de", + "EMBEDDED_VENV": false, "EOL": 1, "FILETYPES": { "*.epj": "OTHERS", @@ -162,6 +170,7 @@ }, "INTERFACES": [], "LEXERASSOCS": {}, + "LICENSE": "GNU General Public License v3 or later (GPLv3+)", "MAINSCRIPT": "PluginPyLint.py", "MAKEPARAMS": { "MakeEnabled": false, @@ -176,12 +185,29 @@ ".hgignore", "ChangeLog", "PKGLIST", + "PluginPyLint.epj", "PluginPyLint.zip", - "PluginPyLint.epj", "PyLintInterface/Documentation/LICENSE.GPL3", "PyLintInterface/Documentation/source" ], - "OTHERTOOLSPARMS": {}, + "OTHERTOOLSPARMS": { + "Black": { + "exclude": "/(\\.direnv|\\.eggs|\\.git|\\.hg|\\.mypy_cache|\\.nox|\\.tox|\\.venv|venv|\\.svn|_build|buck-out|build|dist|__pypackages__)/", + "extend-exclude": "", + "force-exclude": "", + "line-length": 88, + "skip-magic-trailing-comma": false, + "skip-string-normalization": false, + "source": "project", + "target-version": [ + "py311", + "py310", + "py39", + "py38", + "py37" + ] + } + }, "PACKAGERSPARMS": {}, "PROGLANGUAGE": "Python3", "PROJECTTYPE": "E7Plugin", @@ -196,31 +222,32 @@ "RESOURCES": [], "SOURCES": [ "PluginPyLint.py", - "__init__.py", + "PyLintInterface/PyLintConfigDialog.py", + "PyLintInterface/PyLintExecDialog.py", "PyLintInterface/__init__.py", - "PyLintInterface/PyLintExecDialog.py", - "PyLintInterface/PyLintConfigDialog.py" + "__init__.py" ], "SPELLEXCLUDES": "", "SPELLLANGUAGE": "en_US", "SPELLWORDS": "", + "TESTING_FRAMEWORK": "", "TRANSLATIONEXCEPTIONS": [], "TRANSLATIONPATTERN": "PyLintInterface/i18n/pylint_%language%.ts", "TRANSLATIONS": [ + "PyLintInterface/i18n/pylint_cs.qm", + "PyLintInterface/i18n/pylint_cs.ts", "PyLintInterface/i18n/pylint_de.qm", - "PyLintInterface/i18n/pylint_pt.ts", - "PyLintInterface/i18n/pylint_ru.ts", - "PyLintInterface/i18n/pylint_fr.qm", + "PyLintInterface/i18n/pylint_de.ts", + "PyLintInterface/i18n/pylint_en.qm", + "PyLintInterface/i18n/pylint_en.ts", "PyLintInterface/i18n/pylint_es.qm", - "PyLintInterface/i18n/pylint_fr.ts", "PyLintInterface/i18n/pylint_es.ts", - "PyLintInterface/i18n/pylint_cs.qm", - "PyLintInterface/i18n/pylint_de.ts", - "PyLintInterface/i18n/pylint_ru.qm", + "PyLintInterface/i18n/pylint_fr.qm", + "PyLintInterface/i18n/pylint_fr.ts", "PyLintInterface/i18n/pylint_pt.qm", - "PyLintInterface/i18n/pylint_cs.ts", - "PyLintInterface/i18n/pylint_en.ts", - "PyLintInterface/i18n/pylint_en.qm" + "PyLintInterface/i18n/pylint_pt.ts", + "PyLintInterface/i18n/pylint_ru.qm", + "PyLintInterface/i18n/pylint_ru.ts" ], "TRANSLATIONSBINPATH": "", "UICPARAMS": {
--- a/PluginPyLint.py Tue Jun 28 08:21:17 2022 +0200 +++ b/PluginPyLint.py Tue Sep 20 17:16:37 2022 +0200 @@ -50,7 +50,7 @@ def exeDisplayDataList(): """ Public method to support the display of some executable info. - + @return list of dictionaries containing the data to query the presence of the executable @rtype list of dict @@ -58,11 +58,10 @@ dataList = [] data = { "programEntry": True, - "header": QCoreApplication.translate( - "PyLintPlugin", "Checkers - Pylint"), - "exe": 'dummypylint', - "versionCommand": '--version', - "versionStartsWith": 'dummypylint', + "header": QCoreApplication.translate("PyLintPlugin", "Checkers - Pylint"), + "exe": "dummypylint", + "versionCommand": "--version", + "versionStartsWith": "dummypylint", "versionPosition": -1, "version": "", "versionCleanup": None, @@ -81,7 +80,7 @@ def __getProgramVersion(exe): """ Private method to generate a program entry. - + @param exe name of the executable program @type str @return version string of detected version @@ -89,24 +88,24 @@ """ proc = QProcess() proc.setProcessChannelMode(QProcess.ProcessChannelMode.MergedChannels) - proc.start(exe, ['--version']) + proc.start(exe, ["--version"]) finished = proc.waitForFinished(10000) if finished: - output = str(proc.readAllStandardOutput(), - Preferences.getSystem("IOEncoding"), - 'replace') - versionRe = re.compile('^pylint', re.UNICODE) + output = str( + proc.readAllStandardOutput(), Preferences.getSystem("IOEncoding"), "replace" + ) + versionRe = re.compile("^pylint", re.UNICODE) for line in output.splitlines(): if versionRe.search(line): return line.split()[-1] - - return '0.0.0' + + return "0.0.0" def _findExecutable(majorVersion): """ Restricted function to determine the name and path of the executable. - + @param majorVersion major python version of the executables @type int @return path name of the executable @@ -117,7 +116,7 @@ minorVersions = range(10) else: return [] - + executables = set() if Utilities.isWindowsPlatform(): # @@ -126,65 +125,74 @@ try: import winreg except ImportError: - import _winreg as winreg # __IGNORE_WARNING__ - + import _winreg as winreg # __IGNORE_WARNING__ + def getExePath(branch, access, versionStr): exes = [] with contextlib.suppress(WindowsError, OSError): - software = winreg.OpenKey(branch, 'Software', 0, access) - python = winreg.OpenKey(software, 'Python', 0, access) - pcore = winreg.OpenKey(python, 'PythonCore', 0, access) + software = winreg.OpenKey(branch, "Software", 0, access) + python = winreg.OpenKey(software, "Python", 0, access) + pcore = winreg.OpenKey(python, "PythonCore", 0, access) version = winreg.OpenKey(pcore, versionStr, 0, access) - installpath = winreg.QueryValue(version, 'InstallPath') + installpath = winreg.QueryValue(version, "InstallPath") # Look for the batch script variant - exe = os.path.join(installpath, 'Scripts', 'pylint.bat') + exe = os.path.join(installpath, "Scripts", "pylint.bat") if os.access(exe, os.X_OK): exes.append(exe) # Look for the executable variant - exe = os.path.join(installpath, 'Scripts', 'pylint.exe') + exe = os.path.join(installpath, "Scripts", "pylint.exe") if os.access(exe, os.X_OK): exes.append(exe) return exes - + versionSuffixes = ["", "-32", "-64"] for minorVersion in minorVersions: for versionSuffix in versionSuffixes: - versionStr = '{0}.{1}{2}'.format(majorVersion, minorVersion, - versionSuffix) + versionStr = "{0}.{1}{2}".format( + majorVersion, minorVersion, versionSuffix + ) exePaths = getExePath( winreg.HKEY_CURRENT_USER, - winreg.KEY_WOW64_32KEY | winreg.KEY_READ, versionStr) + winreg.KEY_WOW64_32KEY | winreg.KEY_READ, + versionStr, + ) if exePaths: for exePath in exePaths: executables.add(exePath) - + exePaths = getExePath( winreg.HKEY_LOCAL_MACHINE, - winreg.KEY_WOW64_32KEY | winreg.KEY_READ, versionStr) + winreg.KEY_WOW64_32KEY | winreg.KEY_READ, + versionStr, + ) if exePaths: for exePath in exePaths: executables.add(exePath) - + # Even on Intel 64-bit machines it's 'AMD64' - if platform.machine() == 'AMD64': + if platform.machine() == "AMD64": exePaths = getExePath( winreg.HKEY_CURRENT_USER, - winreg.KEY_WOW64_64KEY | winreg.KEY_READ, versionStr) + winreg.KEY_WOW64_64KEY | winreg.KEY_READ, + versionStr, + ) if exePaths: for exePath in exePaths: executables.add(exePath) - + exePaths = getExePath( winreg.HKEY_LOCAL_MACHINE, - winreg.KEY_WOW64_64KEY | winreg.KEY_READ, versionStr) + winreg.KEY_WOW64_64KEY | winreg.KEY_READ, + versionStr, + ) if exePaths: for exePath in exePaths: executables.add(exePath) - + if not executables and majorVersion >= 3: # check the PATH environment variable if nothing was found # Python 3 only - path = Utilities.getEnvironmentEntry('PATH') + path = Utilities.getEnvironmentEntry("PATH") if path: dirs = path.split(os.pathsep) for directory in dirs: @@ -195,21 +203,21 @@ else: # # Linux, Unix ... - pylintScript = 'pylint' - scriptSuffixes = ["", - "-python{0}".format(majorVersion), - "{0}".format(majorVersion), - ] + pylintScript = "pylint" + scriptSuffixes = [ + "", + "-python{0}".format(majorVersion), + "{0}".format(majorVersion), + ] for minorVersion in minorVersions: - scriptSuffixes.append( - "-python{0}.{1}".format(majorVersion, minorVersion)) + scriptSuffixes.append("-python{0}.{1}".format(majorVersion, minorVersion)) # There could be multiple pylint executables in the path # e.g. for different python variants - path = Utilities.getEnvironmentEntry('PATH') + path = Utilities.getEnvironmentEntry("PATH") # environment variable not defined if path is None: return [] - + # step 1: determine possible candidates exes = [] dirs = path.split(os.pathsep) @@ -218,7 +226,7 @@ exe = os.path.join(directory, pylintScript + suffix) if os.access(exe, os.X_OK): exes.append(exe) - + # step 2: determine the Python variant _exePy3 = set() versionArgs = ["-c", "import sys; print(sys.version_info[0])"] @@ -231,15 +239,15 @@ process.waitForFinished(5000) # get a QByteArray of the output versionBytes = process.readAllStandardOutput() - versionStr = str(versionBytes, encoding='utf-8').strip() + versionStr = str(versionBytes, encoding="utf-8").strip() if versionStr == "3": _exePy3.add(exe) - + executables = _exePy3 - + # Find the executable with the highest version number - maxVersion = '0.0.0' - maxExe = '' + maxVersion = "0.0.0" + maxExe = "" for executable in list(executables): version = __getProgramVersion(executable) if version > maxVersion: @@ -252,16 +260,17 @@ def _checkProgram(): """ Restricted function to check the availability of pylint. - + @return flag indicating availability @rtype bool """ global error, exePy3 - + exePy3 = _findExecutable(3) - if exePy3[0] == '': + if exePy3[0] == "": error = QCoreApplication.translate( - "PyLintPlugin", "The pylint executable could not be found.") + "PyLintPlugin", "The pylint executable could not be found." + ) return False else: return True @@ -271,20 +280,21 @@ """ Class implementing the PyLint plug-in. """ + def __init__(self, ui): """ Constructor - + @param ui reference to the user interface object @type UserInterface """ QObject.__init__(self, ui) self.__ui = ui self.__initialize() - + self.__translator = None self.__loadTranslator() - + def __initialize(self): """ Private slot to (re)initialize the plugin. @@ -292,12 +302,12 @@ self.__projectAct = None self.__projectShowAct = None self.__pylintPDialog = None - + self.__projectBrowserAct = None self.__projectBrowserShowAct = None self.__projectBrowserMenu = None self.__pylintPsbDialog = None - + self.__editors = [] self.__editorAct = None self.__editorPylintDialog = None @@ -306,74 +316,86 @@ def activate(self): """ Public method to activate this plugin. - + @return tuple of None and activation status @rtype tuple of (None, bool) """ global error - + # There is already an error, don't activate if error: return None, False # pylint is only activated if it is available if not _checkProgram(): return None, False - + menu = ericApp().getObject("Project").getMenu("Checks") if menu: self.__projectAct = EricAction( - self.tr('Run PyLint'), - self.tr('Run &PyLint...'), 0, 0, - self, 'project_check_pylint') + self.tr("Run PyLint"), + self.tr("Run &PyLint..."), + 0, + 0, + self, + "project_check_pylint", + ) self.__projectAct.setStatusTip( - self.tr('Check project, packages or modules with pylint.')) - self.__projectAct.setWhatsThis(self.tr( - """<b>Run PyLint...</b>""" - """<p>This checks the project, packages or modules using""" - """ pylint.</p>""" - )) + self.tr("Check project, packages or modules with pylint.") + ) + self.__projectAct.setWhatsThis( + self.tr( + """<b>Run PyLint...</b>""" + """<p>This checks the project, packages or modules using""" + """ pylint.</p>""" + ) + ) self.__projectAct.triggered.connect(self.__projectPylint) ericApp().getObject("Project").addEricActions([self.__projectAct]) menu.addAction(self.__projectAct) - + self.__projectShowAct = EricAction( - self.tr('Show PyLint Dialog'), - self.tr('Show Py&Lint Dialog...'), 0, 0, - self, 'project_check_pylintshow') - self.__projectShowAct.setStatusTip(self.tr( - 'Show the PyLint dialog with the results of the last run.')) - self.__projectShowAct.setWhatsThis(self.tr( - """<b>Show PyLint Dialog...</b>""" - """<p>This shows the PyLint dialog with the results""" - """ of the last run.</p>""" - )) - self.__projectShowAct.triggered.connect( - self.__projectPylintShow) - ericApp().getObject("Project").addEricActions( - [self.__projectShowAct]) + self.tr("Show PyLint Dialog"), + self.tr("Show Py&Lint Dialog..."), + 0, + 0, + self, + "project_check_pylintshow", + ) + self.__projectShowAct.setStatusTip( + self.tr("Show the PyLint dialog with the results of the last run.") + ) + self.__projectShowAct.setWhatsThis( + self.tr( + """<b>Show PyLint Dialog...</b>""" + """<p>This shows the PyLint dialog with the results""" + """ of the last run.</p>""" + ) + ) + self.__projectShowAct.triggered.connect(self.__projectPylintShow) + ericApp().getObject("Project").addEricActions([self.__projectShowAct]) menu.addAction(self.__projectShowAct) - + self.__editorAct = EricAction( - self.tr('Run PyLint'), - self.tr('Run &PyLint...'), 0, 0, - self, "") - self.__editorAct.setWhatsThis(self.tr( - """<b>Run PyLint...</b>""" - """<p>This checks the loaded module using pylint.</p>""" - )) + self.tr("Run PyLint"), self.tr("Run &PyLint..."), 0, 0, self, "" + ) + self.__editorAct.setWhatsThis( + self.tr( + """<b>Run PyLint...</b>""" + """<p>This checks the loaded module using pylint.</p>""" + ) + ) self.__editorAct.triggered.connect(self.__editorPylint) - + ericApp().getObject("Project").showMenu.connect(self.__projectShowMenu) ericApp().getObject("ProjectBrowser").getProjectBrowser( - "sources").showMenu.connect(self.__projectBrowserShowMenu) - ericApp().getObject("ViewManager").editorOpenedEd.connect( - self.__editorOpened) - ericApp().getObject("ViewManager").editorClosedEd.connect( - self.__editorClosed) - + "sources" + ).showMenu.connect(self.__projectBrowserShowMenu) + ericApp().getObject("ViewManager").editorOpenedEd.connect(self.__editorOpened) + ericApp().getObject("ViewManager").editorClosedEd.connect(self.__editorClosed) + for editor in ericApp().getObject("ViewManager").getOpenEditors(): self.__editorOpened(editor) - + error = "" return None, True @@ -381,42 +403,42 @@ """ Public method to deactivate this plugin. """ - ericApp().getObject("Project").showMenu.disconnect( - self.__projectShowMenu) + ericApp().getObject("Project").showMenu.disconnect(self.__projectShowMenu) ericApp().getObject("ProjectBrowser").getProjectBrowser( - "sources").showMenu.disconnect(self.__projectBrowserShowMenu) + "sources" + ).showMenu.disconnect(self.__projectBrowserShowMenu) ericApp().getObject("ViewManager").editorOpenedEd.disconnect( - self.__editorOpened) + self.__editorOpened + ) ericApp().getObject("ViewManager").editorClosedEd.disconnect( - self.__editorClosed) - + self.__editorClosed + ) + menu = ericApp().getObject("Project").getMenu("Checks") if menu: if self.__projectAct: menu.removeAction(self.__projectAct) - ericApp().getObject("Project").removeEricActions( - [self.__projectAct]) + ericApp().getObject("Project").removeEricActions([self.__projectAct]) if self.__projectShowAct: menu.removeAction(self.__projectShowAct) ericApp().getObject("Project").removeEricActions( - [self.__projectShowAct]) - + [self.__projectShowAct] + ) + if self.__projectBrowserMenu: if self.__projectBrowserAct: - self.__projectBrowserMenu.removeAction( - self.__projectBrowserAct) + self.__projectBrowserMenu.removeAction(self.__projectBrowserAct) if self.__projectBrowserShowAct: - self.__projectBrowserMenu.removeAction( - self.__projectBrowserShowAct) - + self.__projectBrowserMenu.removeAction(self.__projectBrowserShowAct) + for editor in self.__editors: editor.showMenu.disconnect(self.__editorShowMenu) menu = editor.getMenu("Checks") if menu is not None: menu.removeAction(self.__editorAct) - + self.__initialize() - + def __loadTranslator(self): """ Private method to load the translation file. @@ -424,8 +446,9 @@ if self.__ui is not None: loc = self.__ui.getLocale() if loc and loc != "C": - locale_dir = os.path.join(os.path.dirname(__file__), - "PyLintInterface", "i18n") + locale_dir = os.path.join( + os.path.dirname(__file__), "PyLintInterface", "i18n" + ) translation = "pylint_{0}".format(loc) translator = QTranslator(None) loaded = translator.load(translation, locale_dir) @@ -433,15 +456,17 @@ self.__translator = translator ericApp().installTranslator(self.__translator) else: - print("Warning: translation file '{0}' could not be" - " loaded.".format(translation)) + print( + "Warning: translation file '{0}' could not be" + " loaded.".format(translation) + ) print("Using default.") - + def __projectShowMenu(self, menuName, menu): """ Private slot called, when the the project menu or a submenu is about to be shown. - + @param menuName name of the menu to be shown @type str @param menu reference to the menu @@ -454,66 +479,75 @@ if self.__projectShowAct is not None: self.__projectShowAct.setEnabled(lang.startswith("Python")) self.__projectShowAct.setEnabled(self.__pylintPDialog is not None) - + def __projectBrowserShowMenu(self, menuName, menu): """ Private slot called, when the the project browser menu or a submenu is about to be shown. - + @param menuName name of the menu to be shown @type str @param menu reference to the menu @type QMenu """ - if ( - menuName == "Checks" and - ericApp().getObject("Project").getProjectLanguage() - .startswith("Python") - ): + if menuName == "Checks" and ericApp().getObject( + "Project" + ).getProjectLanguage().startswith("Python"): self.__projectBrowserMenu = menu if self.__projectBrowserAct is None: self.__projectBrowserAct = EricAction( - self.tr('Run PyLint'), - self.tr('Run &PyLint...'), 0, 0, - self, '') - self.__projectBrowserAct.setWhatsThis(self.tr( - """<b>Run PyLint...</b>""" - """<p>This checks the project, packages or modules""" - """ using pylint.</p>""" - )) - self.__projectBrowserAct.triggered.connect( - self.__projectBrowserPylint) - + self.tr("Run PyLint"), self.tr("Run &PyLint..."), 0, 0, self, "" + ) + self.__projectBrowserAct.setWhatsThis( + self.tr( + """<b>Run PyLint...</b>""" + """<p>This checks the project, packages or modules""" + """ using pylint.</p>""" + ) + ) + self.__projectBrowserAct.triggered.connect(self.__projectBrowserPylint) + if self.__projectBrowserShowAct is None: self.__projectBrowserShowAct = EricAction( - self.tr('Show PyLint Dialog'), - self.tr('Show Py&Lint Dialog...'), 0, 0, - self, '') - self.__projectBrowserShowAct.setWhatsThis(self.tr( - """<b>Show PyLint Dialog...</b>""" - """<p>This shows the PyLint dialog with the results""" - """ of the last run.</p>""" - )) + self.tr("Show PyLint Dialog"), + self.tr("Show Py&Lint Dialog..."), + 0, + 0, + self, + "", + ) + self.__projectBrowserShowAct.setWhatsThis( + self.tr( + """<b>Show PyLint Dialog...</b>""" + """<p>This shows the PyLint dialog with the results""" + """ of the last run.</p>""" + ) + ) self.__projectBrowserShowAct.triggered.connect( - self.__projectBrowserPylintShow) - + self.__projectBrowserPylintShow + ) + if self.__projectBrowserAct not in menu.actions(): menu.addAction(self.__projectBrowserAct) if self.__projectBrowserShowAct not in menu.actions(): menu.addAction(self.__projectBrowserShowAct) - + enable = ( - ericApp().getObject("ProjectBrowser") + ericApp() + .getObject("ProjectBrowser") .getProjectBrowser("sources") - .getSelectedItemsCount([ProjectBrowserFileItem]) == 1) + .getSelectedItemsCount([ProjectBrowserFileItem]) + == 1 + ) self.__projectBrowserAct.setEnabled(enable) self.__projectBrowserShowAct.setEnabled( - enable and self.__pylintPsbDialog is not None) - + enable and self.__pylintPsbDialog is not None + ) + def __pyLint(self, project, mpName, forProject, forEditor=False): """ Private method used to perform a PyLint run. - + @param project reference to the Project object @type Project @param mpName name of module or package to be checked @@ -528,30 +562,32 @@ editor = ericApp().getObject("ViewManager").getOpenEditor(mpName) majorVersionStr = editor.getLanguage() else: - parms = project.getData('CHECKERSPARMS', "PYLINT") + parms = project.getData("CHECKERSPARMS", "PYLINT") majorVersionStr = project.getProjectLanguage() exe, version = {"Python3": exePy3}.get(majorVersionStr) - if exe == '': + if exe == "": EricMessageBox.critical( None, self.tr("pylint"), - self.tr("""The pylint executable could not be found.""")) + self.tr("""The pylint executable could not be found."""), + ) return - + from PyLintInterface.PyLintConfigDialog import PyLintConfigDialog + dlg = PyLintConfigDialog(project.getProjectPath(), exe, parms, version) if dlg.exec() == QDialog.DialogCode.Accepted: args, parms = dlg.generateParameters() self.__editorParms = copy.deepcopy(parms) if not forEditor: - project.setData('CHECKERSPARMS', "PYLINT", parms) - + project.setData("CHECKERSPARMS", "PYLINT", parms) + # now do the call from PyLintInterface.PyLintExecDialog import PyLintExecDialog + dlg2 = PyLintExecDialog() - reportFile = parms.get('reportFile', None) - res = dlg2.start(args, mpName, reportFile, - project.getProjectPath()) + reportFile = parms.get("reportFile", None) + res = dlg2.start(args, mpName, reportFile, project.getProjectPath()) if res: dlg2.show() if forProject: @@ -560,7 +596,7 @@ self.__editorPylintDialog = dlg2 else: self.__pylintPsbDialog = dlg2 - + def __projectPylint(self): """ Private slot used to check the project files with Pylint. @@ -568,7 +604,7 @@ project = ericApp().getObject("Project") project.saveAllScripts() self.__pyLint(project, project.getProjectPath(), True) - + def __projectPylintShow(self): """ Private slot to show the PyLint dialog with the results of the last @@ -576,23 +612,21 @@ """ if self.__pylintPDialog is not None: self.__pylintPDialog.show() - + def __projectBrowserPylint(self): """ Private method to handle the Pylint context menu action of the project sources browser. """ project = ericApp().getObject("Project") - browser = ( - ericApp().getObject("ProjectBrowser").getProjectBrowser("sources") - ) + browser = ericApp().getObject("ProjectBrowser").getProjectBrowser("sources") itm = browser.model().item(browser.currentIndex()) try: fn = itm.fileName() except AttributeError: fn = itm.dirName() self.__pyLint(project, fn, False) - + def __projectBrowserPylintShow(self): """ Private slot to show the PyLint dialog with the results of the last @@ -600,11 +634,11 @@ """ if self.__pylintPsbDialog is not None: self.__pylintPsbDialog.show() - + def __editorOpened(self, editor): """ Private slot called, when a new editor was opened. - + @param editor reference to the new editor @type Editor """ @@ -613,22 +647,22 @@ menu.addAction(self.__editorAct) editor.showMenu.connect(self.__editorShowMenu) self.__editors.append(editor) - + def __editorClosed(self, editor): """ Private slot called, when an editor was closed. - + @param editor reference to the editor @type Editor """ with contextlib.suppress(ValueError): self.__editors.remove(editor) - + def __editorShowMenu(self, menuName, menu, editor): """ Private slot called, when the the editor context menu or a submenu is about to be shown. - + @param menuName name of the menu to be shown @type str @param menu reference to the menu @@ -640,18 +674,15 @@ if self.__editorAct not in menu.actions(): menu.addAction(self.__editorAct) self.__editorAct.setEnabled(editor.isPyFile()) - + def __editorPylint(self): """ Private slot to handle the Pylint context menu action of the editors. """ editor = ericApp().getObject("ViewManager").activeWindow() - if ( - editor is not None and - not editor.checkDirty() - ): + if editor is not None and not editor.checkDirty(): return - + fn = editor.getFileName() project = ericApp().getObject("Project") self.__pyLint(project, fn, False, True) @@ -660,14 +691,15 @@ def installDependencies(pipInstall): """ Function to install dependencies of this plug-in. - + @param pipInstall function to be called with a list of package names. @type function """ try: - import pylint # __IGNORE_WARNING__ + import pylint # __IGNORE_WARNING__ except ImportError: pipInstall(["pylint"]) + # # eflag: noqa = M801
--- a/PyLintInterface/PyLintConfigDialog.py Tue Jun 28 08:21:17 2022 +0200 +++ b/PyLintInterface/PyLintConfigDialog.py Tue Sep 20 17:16:37 2022 +0200 @@ -26,10 +26,11 @@ """ Class implementing a dialog to configure the PyLint process. """ + def __init__(self, ppath, exe, parms, version): """ Constructor - + @param ppath project path; used to set the default path for the rcfile picker @type str @@ -42,245 +43,237 @@ """ super().__init__(None) self.setupUi(self) - + self.__version = version self.__pylintProc = None self.__lint = exe - + self.__initializeDefaults() - + # get a copy of the defaults to store the user settings self.parameters = copy.deepcopy(self.defaults) - + # combine it with the values of parms if parms is not None: self.parameters.update(parms) - - self.configfilePicker.setWindowTitle( - self.tr("Select configuration file")) + + self.configfilePicker.setWindowTitle(self.tr("Select configuration file")) self.configfilePicker.setMode(EricPathPickerModes.OPEN_FILE_MODE) - self.configfilePicker.setFilters(self.tr( - "Configuration Files (*.cfg *.cnf *.rc);;" - "All Files (*)" - )) + self.configfilePicker.setFilters( + self.tr("Configuration Files (*.cfg *.cnf *.rc);;" "All Files (*)") + ) self.configfilePicker.setDefaultDirectory(ppath) - - self.reportfilePicker.setWindowTitle( - self.tr("Select report file")) + + self.reportfilePicker.setWindowTitle(self.tr("Select report file")) self.reportfilePicker.setMode(EricPathPickerModes.SAVE_FILE_MODE) - self.reportfilePicker.setFilters(self.tr( - "HTML Files (*.html);;" - "Report Files (*.rpt);;" - "Text Files (*.txt);;" - "All Files (*)" - )) - + self.reportfilePicker.setFilters( + self.tr( + "HTML Files (*.html);;" + "Report Files (*.rpt);;" + "Text Files (*.txt);;" + "All Files (*)" + ) + ) + # initialize general tab - self.configfilePicker.setText(self.parameters['configFile']) - self.txtOutputButton.setChecked(self.parameters['txtReport']) - self.htmlOutputButton.setChecked(self.parameters['htmlReport']) - self.dialogOutputButton.setChecked(self.parameters['dialogReport']) - self.reportfilePicker.setText(self.parameters['reportFile']) - + self.configfilePicker.setText(self.parameters["configFile"]) + self.txtOutputButton.setChecked(self.parameters["txtReport"]) + self.htmlOutputButton.setChecked(self.parameters["htmlReport"]) + self.dialogOutputButton.setChecked(self.parameters["dialogReport"]) + self.reportfilePicker.setText(self.parameters["reportFile"]) + # initialize checkers tab - self.basicCheckBox.setChecked(self.parameters['enableBasic']) - self.classesCheckBox.setChecked(self.parameters['enableClasses']) - self.designCheckBox.setChecked(self.parameters['enableDesign']) - self.exceptionsCheckBox.setChecked(self.parameters['enableExceptions']) - self.formatCheckBox.setChecked(self.parameters['enableFormat']) - self.importsCheckBox.setChecked(self.parameters['enableImports']) - self.metricsCheckBox.setChecked(self.parameters['enableMetrics']) - self.miscellaneousCheckBox.setChecked( - self.parameters['enableMiscellaneous']) - self.newstyleCheckBox.setChecked(self.parameters['enableNewstyle']) - self.similaritiesCheckBox.setChecked( - self.parameters['enableSimilarities']) - self.typecheckCheckBox.setChecked(self.parameters['enableTypecheck']) - self.variablesCheckBox.setChecked(self.parameters['enableVariables']) - self.loggingCheckBox.setChecked(self.parameters['enableLogging']) - self.stringFormatCheckBox.setChecked( - self.parameters['enableStringFormat']) - + self.basicCheckBox.setChecked(self.parameters["enableBasic"]) + self.classesCheckBox.setChecked(self.parameters["enableClasses"]) + self.designCheckBox.setChecked(self.parameters["enableDesign"]) + self.exceptionsCheckBox.setChecked(self.parameters["enableExceptions"]) + self.formatCheckBox.setChecked(self.parameters["enableFormat"]) + self.importsCheckBox.setChecked(self.parameters["enableImports"]) + self.metricsCheckBox.setChecked(self.parameters["enableMetrics"]) + self.miscellaneousCheckBox.setChecked(self.parameters["enableMiscellaneous"]) + self.newstyleCheckBox.setChecked(self.parameters["enableNewstyle"]) + self.similaritiesCheckBox.setChecked(self.parameters["enableSimilarities"]) + self.typecheckCheckBox.setChecked(self.parameters["enableTypecheck"]) + self.variablesCheckBox.setChecked(self.parameters["enableVariables"]) + self.loggingCheckBox.setChecked(self.parameters["enableLogging"]) + self.stringFormatCheckBox.setChecked(self.parameters["enableStringFormat"]) + # initialize messages tab - self.enabledMessagesEdit.setText(self.parameters['enabledMessages']) - self.disabledMessagesEdit.setText(self.parameters['disabledMessages']) + self.enabledMessagesEdit.setText(self.parameters["enabledMessages"]) + self.disabledMessagesEdit.setText(self.parameters["disabledMessages"]) def __initializeDefaults(self): """ Private method to set the default values. - + These are needed later on to generate the commandline parameters. """ self.defaults = { # general options - 'configFile': '', - 'reportFile': '', - 'txtReport': False, - 'htmlReport': True, - 'dialogReport': False, - + "configFile": "", + "reportFile": "", + "txtReport": False, + "htmlReport": True, + "dialogReport": False, # enabled checkers - 'enableBasic': True, - 'enableClasses': True, - 'enableDesign': True, - 'enableExceptions': True, - 'enableFormat': False, - 'enableImports': False, - 'enableLogging': True, - 'enableMetrics': True, - 'enableMiscellaneous': True, - 'enableNewstyle': True, - 'enableSimilarities': True, - 'enableStringFormat': True, - 'enableTypecheck': True, - 'enableVariables': True, - + "enableBasic": True, + "enableClasses": True, + "enableDesign": True, + "enableExceptions": True, + "enableFormat": False, + "enableImports": False, + "enableLogging": True, + "enableMetrics": True, + "enableMiscellaneous": True, + "enableNewstyle": True, + "enableSimilarities": True, + "enableStringFormat": True, + "enableTypecheck": True, + "enableVariables": True, # messages - 'enabledMessages': '', - 'disabledMessages': '', + "enabledMessages": "", + "disabledMessages": "", } def generateParameters(self): """ Public method that generates the commandline parameters. - + It generates a list of strings to be used to set the QProcess arguments for the pylint call and a list containing the non default parameters. The second list can be passed back upon object generation to overwrite the default settings. - + <b>Note</b>: The arguments list contains the name of the pylint executable as the first parameter. - + @return a tuple of the commandline parameters and non default parameters @rtype tuple of (list of str, dict) """ parms = {} args = [] - + # 1. the program name args.append(self.__lint) - + # 2. the commandline options # 2.1 general options - if self.parameters['configFile'] != self.defaults['configFile']: - parms['configFile'] = self.parameters['configFile'] - args.append('--rcfile={0}'.format(self.parameters['configFile'])) - parms['txtReport'] = self.parameters['txtReport'] - parms['htmlReport'] = self.parameters['htmlReport'] - parms['dialogReport'] = self.parameters['dialogReport'] - if self.parameters['htmlReport']: - args.append('--output-format=html') - elif self.parameters['dialogReport']: - args.append('--output-format=parseable') - args.append('--reports=n') + if self.parameters["configFile"] != self.defaults["configFile"]: + parms["configFile"] = self.parameters["configFile"] + args.append("--rcfile={0}".format(self.parameters["configFile"])) + parms["txtReport"] = self.parameters["txtReport"] + parms["htmlReport"] = self.parameters["htmlReport"] + parms["dialogReport"] = self.parameters["dialogReport"] + if self.parameters["htmlReport"]: + args.append("--output-format=html") + elif self.parameters["dialogReport"]: + args.append("--output-format=parseable") + args.append("--reports=n") else: - args.append('--output-format=text') - if self.parameters['reportFile'] != self.defaults['reportFile']: - parms['reportFile'] = self.parameters['reportFile'] - + args.append("--output-format=text") + if self.parameters["reportFile"] != self.defaults["reportFile"]: + parms["reportFile"] = self.parameters["reportFile"] + # 2.2 checkers options - parms['enableBasic'] = self.parameters['enableBasic'] - parms['enableClasses'] = self.parameters['enableClasses'] - parms['enableDesign'] = self.parameters['enableDesign'] - parms['enableExceptions'] = self.parameters['enableExceptions'] - parms['enableFormat'] = self.parameters['enableFormat'] - parms['enableImports'] = self.parameters['enableImports'] - parms['enableMetrics'] = self.parameters['enableMetrics'] - parms['enableMiscellaneous'] = self.parameters['enableMiscellaneous'] - parms['enableNewstyle'] = self.parameters['enableNewstyle'] - parms['enableSimilarities'] = self.parameters['enableSimilarities'] - parms['enableTypecheck'] = self.parameters['enableTypecheck'] - parms['enableVariables'] = self.parameters['enableVariables'] - parms['enableLogging'] = self.parameters['enableLogging'] - parms['enableStringFormat'] = self.parameters['enableStringFormat'] - + parms["enableBasic"] = self.parameters["enableBasic"] + parms["enableClasses"] = self.parameters["enableClasses"] + parms["enableDesign"] = self.parameters["enableDesign"] + parms["enableExceptions"] = self.parameters["enableExceptions"] + parms["enableFormat"] = self.parameters["enableFormat"] + parms["enableImports"] = self.parameters["enableImports"] + parms["enableMetrics"] = self.parameters["enableMetrics"] + parms["enableMiscellaneous"] = self.parameters["enableMiscellaneous"] + parms["enableNewstyle"] = self.parameters["enableNewstyle"] + parms["enableSimilarities"] = self.parameters["enableSimilarities"] + parms["enableTypecheck"] = self.parameters["enableTypecheck"] + parms["enableVariables"] = self.parameters["enableVariables"] + parms["enableLogging"] = self.parameters["enableLogging"] + parms["enableStringFormat"] = self.parameters["enableStringFormat"] + checkers = [] - if self.parameters['enableBasic']: - checkers.append('basic') - if self.parameters['enableClasses']: - checkers.append('classes') - if self.parameters['enableDesign']: - checkers.append('design') - if self.parameters['enableExceptions']: - checkers.append('exceptions') - if self.parameters['enableFormat']: - checkers.append('format') - if self.parameters['enableImports']: - checkers.append('imports') - if self.parameters['enableMetrics']: - checkers.append('metrics') - if self.parameters['enableMiscellaneous']: - checkers.append('miscellaneous') - if self.parameters['enableNewstyle']: - checkers.append('newstyle') - if self.parameters['enableSimilarities']: - checkers.append('similarities') - if self.parameters['enableTypecheck']: - checkers.append('typecheck') - if self.parameters['enableVariables']: - checkers.append('variables') - if self.parameters['enableLogging']: - checkers.append('logging') - if self.parameters['enableStringFormat']: - checkers.append('string') - - args.append('--disable=all') + if self.parameters["enableBasic"]: + checkers.append("basic") + if self.parameters["enableClasses"]: + checkers.append("classes") + if self.parameters["enableDesign"]: + checkers.append("design") + if self.parameters["enableExceptions"]: + checkers.append("exceptions") + if self.parameters["enableFormat"]: + checkers.append("format") + if self.parameters["enableImports"]: + checkers.append("imports") + if self.parameters["enableMetrics"]: + checkers.append("metrics") + if self.parameters["enableMiscellaneous"]: + checkers.append("miscellaneous") + if self.parameters["enableNewstyle"]: + checkers.append("newstyle") + if self.parameters["enableSimilarities"]: + checkers.append("similarities") + if self.parameters["enableTypecheck"]: + checkers.append("typecheck") + if self.parameters["enableVariables"]: + checkers.append("variables") + if self.parameters["enableLogging"]: + checkers.append("logging") + if self.parameters["enableStringFormat"]: + checkers.append("string") + + args.append("--disable=all") if checkers: - args.append('--enable={0}'.format(','.join(checkers))) - + args.append("--enable={0}".format(",".join(checkers))) + # 2.3 messages options - parms['enabledMessages'] = self.parameters['enabledMessages'] - parms['disabledMessages'] = self.parameters['disabledMessages'] - if parms['enabledMessages']: - args.append('--enable={0}'.format(parms['enabledMessages'])) - if parms['disabledMessages']: - args.append('--disable={0}'.format(parms['disabledMessages'])) - + parms["enabledMessages"] = self.parameters["enabledMessages"] + parms["disabledMessages"] = self.parameters["disabledMessages"] + if parms["enabledMessages"]: + args.append("--enable={0}".format(parms["enabledMessages"])) + if parms["disabledMessages"]: + args.append("--disable={0}".format(parms["disabledMessages"])) + return (args, parms) def accept(self): """ Public slot called by the Ok button. - + It saves the values in the parameters dictionary. """ # get data of general tab - self.parameters['configFile'] = self.configfilePicker.text() - self.parameters['txtReport'] = self.txtOutputButton.isChecked() - self.parameters['htmlReport'] = self.htmlOutputButton.isChecked() - self.parameters['dialogReport'] = self.dialogOutputButton.isChecked() - self.parameters['reportFile'] = self.reportfilePicker.text() - + self.parameters["configFile"] = self.configfilePicker.text() + self.parameters["txtReport"] = self.txtOutputButton.isChecked() + self.parameters["htmlReport"] = self.htmlOutputButton.isChecked() + self.parameters["dialogReport"] = self.dialogOutputButton.isChecked() + self.parameters["reportFile"] = self.reportfilePicker.text() + # get data of checkers tab - self.parameters['enableBasic'] = self.basicCheckBox.isChecked() - self.parameters['enableClasses'] = self.classesCheckBox.isChecked() - self.parameters['enableDesign'] = self.designCheckBox.isChecked() - self.parameters['enableExceptions'] = ( - self.exceptionsCheckBox.isChecked()) - self.parameters['enableFormat'] = self.formatCheckBox.isChecked() - self.parameters['enableImports'] = self.importsCheckBox.isChecked() - self.parameters['enableMetrics'] = self.metricsCheckBox.isChecked() - self.parameters['enableMiscellaneous'] = ( - self.miscellaneousCheckBox.isChecked()) - self.parameters['enableNewstyle'] = self.newstyleCheckBox.isChecked() - self.parameters['enableSimilarities'] = ( - self.similaritiesCheckBox.isChecked()) - self.parameters['enableTypecheck'] = self.typecheckCheckBox.isChecked() - self.parameters['enableVariables'] = self.variablesCheckBox.isChecked() - self.parameters['enableLogging'] = self.loggingCheckBox.isChecked() - self.parameters['enableStringFormat'] = ( - self.stringFormatCheckBox.isChecked()) - + self.parameters["enableBasic"] = self.basicCheckBox.isChecked() + self.parameters["enableClasses"] = self.classesCheckBox.isChecked() + self.parameters["enableDesign"] = self.designCheckBox.isChecked() + self.parameters["enableExceptions"] = self.exceptionsCheckBox.isChecked() + self.parameters["enableFormat"] = self.formatCheckBox.isChecked() + self.parameters["enableImports"] = self.importsCheckBox.isChecked() + self.parameters["enableMetrics"] = self.metricsCheckBox.isChecked() + self.parameters["enableMiscellaneous"] = self.miscellaneousCheckBox.isChecked() + self.parameters["enableNewstyle"] = self.newstyleCheckBox.isChecked() + self.parameters["enableSimilarities"] = self.similaritiesCheckBox.isChecked() + self.parameters["enableTypecheck"] = self.typecheckCheckBox.isChecked() + self.parameters["enableVariables"] = self.variablesCheckBox.isChecked() + self.parameters["enableLogging"] = self.loggingCheckBox.isChecked() + self.parameters["enableStringFormat"] = self.stringFormatCheckBox.isChecked() + # get data of messages tab - self.parameters['enabledMessages'] = ','.join( - [m.strip() for m in self.enabledMessagesEdit.text().split(',')]) - self.parameters['disabledMessages'] = ','.join( - [m.strip() for m in self.disabledMessagesEdit.text().split(',')]) - + self.parameters["enabledMessages"] = ",".join( + [m.strip() for m in self.enabledMessagesEdit.text().split(",")] + ) + self.parameters["disabledMessages"] = ",".join( + [m.strip() for m in self.disabledMessagesEdit.text().split(",")] + ) + # call the accept slot of the base class super().accept() @@ -296,15 +289,15 @@ self.buf = "" self.__pylintProc = QProcess() args = [] - + self.__ioEncoding = Preferences.getSystem("IOEncoding") - - args.append('--generate-rcfile') - + + args.append("--generate-rcfile") + self.__pylintProc.readyReadStandardOutput.connect(self.__readStdout) self.__pylintProc.readyReadStandardError.connect(self.__readStderr) self.__pylintProc.finished.connect(self.__createConfigDone) - + self.__pylintProc.start(self.__lint, args) procStarted = self.__pylintProc.waitForStarted() if procStarted: @@ -312,16 +305,16 @@ else: EricMessageBox.critical( self, - self.tr('Process Generation Error'), + self.tr("Process Generation Error"), self.tr( - 'Could not start {0}.<br>' - 'Ensure that it is in the search path.' - ).format(self.__lint)) - + "Could not start {0}.<br>" "Ensure that it is in the search path." + ).format(self.__lint), + ) + def __createConfigDone(self, exitCode, exitStatus): """ Private slot to handle the the finished signal of the pylint process. - + @param exitCode exit code of the process @type int @param exitStatus exit status of the process @@ -333,9 +326,9 @@ vm.newEditor() aw = vm.activeWindow() aw.insertAt(self.buf, 0, 0) - aw.setLanguage('dummy.rc') + aw.setLanguage("dummy.rc") self.reject() - + def __readStdout(self): """ Private slot to handle the readyReadStandardOutput signal of the @@ -343,15 +336,15 @@ """ if self.__pylintProc is None: return - - self.__pylintProc.setReadChannel( - QProcess.ProcessChannel.StandardOutput) - + + self.__pylintProc.setReadChannel(QProcess.ProcessChannel.StandardOutput) + while self.__pylintProc and self.__pylintProc.canReadLine(): - line = str(self.__pylintProc.readLine(), self.__ioEncoding, - "replace").rstrip() + line = str( + self.__pylintProc.readLine(), self.__ioEncoding, "replace" + ).rstrip() self.buf += line + os.linesep - + def __readStderr(self): """ Private slot to handle the readyReadStandardError signal of the @@ -359,10 +352,10 @@ """ if self.__pylintProc is None: return - - self.__pylintProc.setReadChannel( - QProcess.ProcessChannel.StandardError) + + self.__pylintProc.setReadChannel(QProcess.ProcessChannel.StandardError) while self.__pylintProc and self.__pylintProc.canReadLine(): - s = 'pylint: ' + str( - self.__pylintProc.readLine(), self.__ioEncoding, "replace") + s = "pylint: " + str( + self.__pylintProc.readLine(), self.__ioEncoding, "replace" + ) ericApp().getObject("UserInterface").appendStderr.emit(s)
--- a/PyLintInterface/PyLintExecDialog.py Tue Jun 28 08:21:17 2022 +0200 +++ b/PyLintInterface/PyLintExecDialog.py Tue Sep 20 17:16:37 2022 +0200 @@ -12,7 +12,11 @@ from PyQt6.QtCore import pyqtSlot, Qt, QTimer, QProcess from PyQt6.QtGui import QTextCursor from PyQt6.QtWidgets import ( - QWidget, QHeaderView, QApplication, QDialogButtonBox, QTreeWidgetItem + QWidget, + QHeaderView, + QApplication, + QDialogButtonBox, + QTreeWidgetItem, ) from EricGui.EricOverrideCursor import EricOverrideCursorProcess @@ -29,60 +33,58 @@ class PyLintExecDialog(QWidget, Ui_PyLintExecDialog): """ Class implementing a dialog to show the results of the PyLint run. - + This class starts a QProcess and displays a dialog that shows the results of the PyLint command process. """ + filenameRole = Qt.ItemDataRole.UserRole + 1 - + def __init__(self, parent=None): """ Constructor - + @param parent parent widget of this dialog @type QWidget """ QWidget.__init__(self, parent) self.setupUi(self) - + self.saveButton = self.buttonBox.addButton( - self.tr("Save Report..."), QDialogButtonBox.ButtonRole.ActionRole) - self.saveButton.setToolTip( - self.tr("Press to save the report to a file")) + self.tr("Save Report..."), QDialogButtonBox.ButtonRole.ActionRole + ) + self.saveButton.setToolTip(self.tr("Press to save the report to a file")) self.saveButton.setEnabled(False) - + self.refreshButton = self.buttonBox.addButton( - self.tr("Refresh"), QDialogButtonBox.ButtonRole.ActionRole) - self.refreshButton.setToolTip(self.tr( - "Press to refresh the result display")) + self.tr("Refresh"), QDialogButtonBox.ButtonRole.ActionRole + ) + self.refreshButton.setToolTip(self.tr("Press to refresh the result display")) self.refreshButton.setEnabled(False) - - self.buttonBox.button( - QDialogButtonBox.StandardButton.Close).setEnabled(False) - self.buttonBox.button( - QDialogButtonBox.StandardButton.Cancel).setDefault(True) - - self.messageList.header().setSortIndicator( - 0, Qt.SortOrder.AscendingOrder) - + + self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(False) + self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setDefault(True) + + self.messageList.header().setSortIndicator(0, Qt.SortOrder.AscendingOrder) + self.process = None self.noResults = True self.htmlOutput = False self.parsedOutput = False self.__scrollPosition = -1 # illegal value - + self.typeDict = { - 'C': self.tr('Convention'), - 'R': self.tr('Refactor'), - 'W': self.tr('Warning'), - 'E': self.tr('Error'), - 'F': self.tr('Fatal'), + "C": self.tr("Convention"), + "R": self.tr("Refactor"), + "W": self.tr("Warning"), + "E": self.tr("Error"), + "F": self.tr("Fatal"), } - + def start(self, args, fn, reportFile, ppath): """ Public slot to start PyLint. - + @param args commandline arguments for documentation programPyLint @type list of str @param fn filename or dirname to be processed by PyLint @@ -95,99 +97,93 @@ @rtype bool """ self.errorGroup.hide() - + self.args = args[:] self.fn = fn self.reportFile = reportFile self.ppath = ppath - + self.pathname = os.path.dirname(fn) self.filename = os.path.basename(fn) - + self.contents.clear() self.errors.clear() self.messageList.clear() - - self.buttonBox.button( - QDialogButtonBox.StandardButton.Close).setEnabled(False) - self.buttonBox.button( - QDialogButtonBox.StandardButton.Cancel).setEnabled(True) - self.buttonBox.button( - QDialogButtonBox.StandardButton.Cancel).setDefault(True) + + self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(False) + self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setEnabled(True) + self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setDefault(True) self.saveButton.setEnabled(False) self.refreshButton.setEnabled(False) - + program = args[0] del args[0] args.append(self.filename) - + self.process = EricOverrideCursorProcess() self.process.setWorkingDirectory(self.pathname) - + self.process.readyReadStandardError.connect(self.__readStderr) self.process.finished.connect(self.__finish) - + self.__ioEncoding = Preferences.getSystem("IOEncoding") if "--output-format=parseable" in args: self.reportFile = None self.contents.hide() - self.process.readyReadStandardOutput.connect( - self.__readParseStdout) + self.process.readyReadStandardOutput.connect(self.__readParseStdout) self.parsedOutput = True else: self.process.readyReadStandardOutput.connect(self.__readStdout) self.messageList.hide() if "--output-format=html" in args: self.contents.setAcceptRichText(True) - self.contents.setHtml('<b>Processing your request...</b>') + self.contents.setHtml("<b>Processing your request...</b>") self.htmlOutput = True else: self.contents.setAcceptRichText(False) self.contents.setCurrentFont( - Preferences.getEditorOtherFonts("MonospacedFont")) + Preferences.getEditorOtherFonts("MonospacedFont") + ) self.htmlOutput = False self.parsedOutput = False self.noResults = True - + self.buf = "" self.__lastFileItem = None - + self.process.start(program, args) procStarted = self.process.waitForStarted() if not procStarted: EricMessageBox.critical( self, - self.tr('Process Generation Error'), + self.tr("Process Generation Error"), self.tr( - 'The process {0} could not be started. ' - 'Ensure, that it is in the search path.' - ).format(program)) + "The process {0} could not be started. " + "Ensure, that it is in the search path." + ).format(program), + ) return procStarted - + def on_buttonBox_clicked(self, button): """ Private slot called by a button of the button box clicked. - + @param button button that was clicked @type QAbstractButton """ - if button == self.buttonBox.button( - QDialogButtonBox.StandardButton.Close - ): + if button == self.buttonBox.button(QDialogButtonBox.StandardButton.Close): self.close() - elif button == self.buttonBox.button( - QDialogButtonBox.StandardButton.Cancel - ): + elif button == self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel): self.__finish() elif button == self.saveButton: self.on_saveButton_clicked() elif button == self.refreshButton: self.on_refreshButton_clicked() - + def __finish(self): """ Private slot called when the process finished. - + It is called when the process finished or the user pressed the button. """ if self.htmlOutput: @@ -196,46 +192,43 @@ cursor = self.contents.textCursor() cursor.movePosition(QTextCursor.MoveOperation.Start) self.contents.setTextCursor(cursor) - + if ( - self.process is not None and - self.process.state() != QProcess.ProcessState.NotRunning + self.process is not None + and self.process.state() != QProcess.ProcessState.NotRunning ): self.process.terminate() QTimer.singleShot(2000, self.process.kill) self.process.waitForFinished(3000) - - self.buttonBox.button( - QDialogButtonBox.StandardButton.Close).setEnabled(True) - self.buttonBox.button( - QDialogButtonBox.StandardButton.Cancel).setEnabled(False) - self.buttonBox.button( - QDialogButtonBox.StandardButton.Close).setDefault(True) + + self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(True) + self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setEnabled(False) + self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setDefault(True) self.refreshButton.setEnabled(True) if self.parsedOutput: QApplication.processEvents() self.messageList.sortItems( self.messageList.sortColumn(), - self.messageList.header().sortIndicatorOrder()) + self.messageList.header().sortIndicatorOrder(), + ) self.messageList.header().resizeSections( - QHeaderView.ResizeMode.ResizeToContents) + QHeaderView.ResizeMode.ResizeToContents + ) self.messageList.header().setStretchLastSection(True) else: if self.__scrollPosition != -1: - self.contents.verticalScrollBar().setValue( - self.__scrollPosition) - + self.contents.verticalScrollBar().setValue(self.__scrollPosition) + self.process = None - + if self.reportFile: self.__writeReport() elif not self.parsedOutput: self.saveButton.setEnabled(True) - + if self.noResults: - self.__createItem( - self.tr('No PyLint errors found.'), "", "", "") - + self.__createItem(self.tr("No PyLint errors found."), "", "", "") + @pyqtSlot() def on_refreshButton_clicked(self): """ @@ -243,27 +236,27 @@ """ self.__scrollPosition = self.contents.verticalScrollBar().value() self.start(self.args, self.fn, self.reportFile, self.ppath) - + def __readStdout(self): """ Private slot to handle the readyReadStandardOutput signal. - + It reads the output of the process, formats it and inserts it into the contents pane. """ self.process.setReadChannel(QProcess.ProcessChannel.StandardOutput) - + while self.process.canReadLine(): - s = str(self.process.readLine(), self.__ioEncoding, 'replace') + s = str(self.process.readLine(), self.__ioEncoding, "replace") self.buf += s + os.linesep if not self.htmlOutput: self.contents.insertPlainText(s) self.contents.ensureCursorVisible() - + def __createItem(self, file, line, type_, message): """ Private method to create an entry in the message list. - + @param file filename of file @type str @param line linenumber of message @@ -277,7 +270,7 @@ matchFlags = Qt.MatchFlag.MatchFixedString if not Utilities.isWindowsPlatform(): matchFlags |= Qt.MatchFlag.MatchCaseSensitive - + itmList = self.messageList.findItems(file, matchFlags) if itmList: self.__lastFileItem = itmList[0] @@ -287,67 +280,70 @@ self.__lastFileItem.setFirstColumnSpanned(True) self.__lastFileItem.setExpanded(True) self.__lastFileItem.setData(0, self.filenameRole, file) - + itm = QTreeWidgetItem(self.__lastFileItem, [str(line), type_, message]) itm.setTextAlignment(0, Qt.AlignmentFlag.AlignRight) itm.setTextAlignment(1, Qt.AlignmentFlag.AlignHCenter) itm.setData(0, self.filenameRole, file) - + def __readParseStdout(self): """ Private slot to handle the readyReadStandardOutput signal for parseable output. - + It reads the output of the process, formats it and inserts it into the message list pane. """ self.process.setReadChannel(QProcess.ProcessChannel.StandardOutput) - + while self.process.canReadLine(): - s = str(self.process.readLine(), self.__ioEncoding, 'replace') + s = str(self.process.readLine(), self.__ioEncoding, "replace") if s: try: if Utilities.isWindowsPlatform(): drive, s = os.path.splitdrive(s) - fname, lineno, fullmessage = s.split(':') + fname, lineno, fullmessage = s.split(":") fname = drive + fname else: - fname, lineno, fullmessage = s.split(':') - type_, message = fullmessage.strip().split(']', 1) - type_ = type_.strip()[1:].split(',', 1)[0] + fname, lineno, fullmessage = s.split(":") + type_, message = fullmessage.strip().split("]", 1) + type_ = type_.strip()[1:].split(",", 1)[0] message = message.strip() if type_ and type_[0] in self.typeDict: if len(type_) == 1: self.__createItem( - fname, lineno, self.typeDict[type_], message) + fname, lineno, self.typeDict[type_], message + ) else: self.__createItem( - fname, lineno, "{0} {1}".format( - self.typeDict[type_[0]], type_[1:]), - message) + fname, + lineno, + "{0} {1}".format(self.typeDict[type_[0]], type_[1:]), + message, + ) self.noResults = False except ValueError: continue - + def __readStderr(self): """ Private slot to handle the readyReadStandardError signal. - + It reads the error output of the process and inserts it into the error pane. """ self.process.setReadChannel(QProcess.ProcessChannel.StandardError) - + while self.process.canReadLine(): self.errorGroup.show() - s = str(self.process.readLine(), self.__ioEncoding, 'replace') + s = str(self.process.readLine(), self.__ioEncoding, "replace") self.errors.insertPlainText(s) self.errors.ensureCursorVisible() - + def on_messageList_itemActivated(self, itm, column): """ Private slot to handle the itemActivated signal of the message list. - + @param itm The message item that was activated @type QTreeWidgetItem @param column column the item was activated in @@ -355,17 +351,17 @@ """ if self.noResults: return - + if itm.parent(): fn = os.path.join(self.pathname, itm.data(0, self.filenameRole)) lineno = int(itm.text(0)) - + vm = ericApp().getObject("ViewManager") vm.openSourceFile(fn, lineno) editor = vm.getOpenEditor(fn) editor.toggleWarning( - lineno, 0, True, - "{0} | {1}".format(itm.text(1), itm.text(2))) + lineno, 0, True, "{0} | {1}".format(itm.text(1), itm.text(2)) + ) else: fn = os.path.join(self.pathname, itm.data(0, self.filenameRole)) vm = ericApp().getObject("ViewManager") @@ -375,9 +371,9 @@ citm = itm.child(index) lineno = int(citm.text(0)) editor.toggleWarning( - lineno, 0, True, - "{0} | {1}".format(citm.text(1), citm.text(2))) - + lineno, 0, True, "{0} | {1}".format(citm.text(1), citm.text(2)) + ) + def __writeReport(self): """ Private slot to write the report to a report file. @@ -389,24 +385,27 @@ self.tr("PyLint Report"), self.tr( """<p>The PyLint report file <b>{0}</b> already""" - """ exists.</p>""") - .format(self.reportFile), - EricMessageBox.Cancel | - EricMessageBox.Ignore, - EricMessageBox.Cancel) + """ exists.</p>""" + ).format(self.reportFile), + EricMessageBox.Cancel | EricMessageBox.Ignore, + EricMessageBox.Cancel, + ) if res == EricMessageBox.Cancel: return - + try: - with open(self.reportFile, 'w') as f: + with open(self.reportFile, "w") as f: f.write(self.buf) except OSError as why: EricMessageBox.critical( - self, self.tr('PyLint Report'), - self.tr('<p>The PyLint report file <b>{0}</b> could not' - ' be written.<br>Reason: {1}</p>') - .format(self.reportFile, str(why))) - + self, + self.tr("PyLint Report"), + self.tr( + "<p>The PyLint report file <b>{0}</b> could not" + " be written.<br>Reason: {1}</p>" + ).format(self.reportFile, str(why)), + ) + @pyqtSlot() def on_saveButton_clicked(self): """ @@ -414,15 +413,16 @@ """ fileFilter = ( self.tr("HTML Files (*.html);;All Files (*)") - if self.htmlOutput else - self.tr("Report Files (*.rpt);;Text Files (*.txt);;All Files (*)") + if self.htmlOutput + else self.tr("Report Files (*.rpt);;Text Files (*.txt);;All Files (*)") ) - + self.reportFile = EricFileDialog.getSaveFileName( self, self.tr("PyLint Report"), self.ppath, fileFilter, - EricFileDialog.DontConfirmOverwrite) + EricFileDialog.DontConfirmOverwrite, + ) if self.reportFile: self.__writeReport()