--- 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