--- a/src/eric7/Plugins/PluginCodeStyleChecker.py Wed Jul 13 11:16:20 2022 +0200 +++ b/src/eric7/Plugins/PluginCodeStyleChecker.py Wed Jul 13 14:55:47 2022 +0200 @@ -48,92 +48,98 @@ class CodeStyleCheckerPlugin(QObject): """ Class implementing the code style checker plug-in. - + @signal styleChecked(str, dict, int, list) emitted when the style check was done for a file. @signal batchFinished() emitted when a style check batch is done @signal error(str, str) emitted in case of an error """ + styleChecked = pyqtSignal(str, dict, int, list) batchFinished = pyqtSignal() error = pyqtSignal(str, str) - + def __init__(self, ui): """ Constructor - + @param ui reference to the user interface object (UI.UserInterface) """ super().__init__(ui) self.__ui = ui self.__initialize() - + self.backgroundService = ericApp().getObject("BackgroundService") - + path = os.path.join( - os.path.dirname(__file__), 'CheckerPlugins', 'CodeStyleChecker') + os.path.dirname(__file__), "CheckerPlugins", "CodeStyleChecker" + ) self.backgroundService.serviceConnect( - 'style', 'Python3', path, 'CodeStyleChecker', + "style", + "Python3", + path, + "CodeStyleChecker", self.__translateStyleCheck, onErrorCallback=self.serviceErrorPy3, - onBatchDone=self.batchJobDone) - + onBatchDone=self.batchJobDone, + ) + self.queuedBatches = [] self.batchesFinished = True - + self.__wrapper = textwrap.TextWrapper(width=80) - + def __serviceError(self, fn, msg): """ Private slot handling service errors. - + @param fn file name (string) @param msg message text (string) """ self.error.emit(fn, msg) - + def serviceErrorPy3(self, fx, lang, fn, msg): """ Public slot handling service errors for Python 3. - + @param fx service name (string) @param lang language (string) @param fn file name (string) @param msg message text (string) """ - if fx in ['style', 'batch_style'] and lang == 'Python3': - if fx == 'style': + if fx in ["style", "batch_style"] and lang == "Python3": + if fx == "style": self.__serviceError(fn, msg) else: self.__serviceError(self.tr("Python 3 batch check"), msg) self.batchJobDone(fx, lang) - + def batchJobDone(self, fx, lang): """ Public slot handling the completion of a batch job. - + @param fx service name (string) @param lang language (string) """ - if fx in ['style', 'batch_style']: + if fx in ["style", "batch_style"]: if lang in self.queuedBatches: self.queuedBatches.remove(lang) # prevent sending the signal multiple times if len(self.queuedBatches) == 0 and not self.batchesFinished: self.batchFinished.emit() self.batchesFinished = True - + def __initialize(self): """ Private slot to (re)initialize the plugin. """ self.__projectAct = None self.__projectCodeStyleCheckerDialog = None - + self.__projectBrowserAct = None self.__projectBrowserMenu = None self.__projectBrowserCodeStyleCheckerDialog = None - + self.__editors = [] self.__editorAct = None self.__editorCodeStyleCheckerDialog = None @@ -158,17 +164,17 @@ bool, str, dict, dict, list of str, str, str, bool) """ if lang is None: - lang = 'Python{0}'.format(determinePythonVersion(filename, source)) - if lang != 'Python3': + lang = "Python{0}".format(determinePythonVersion(filename, source)) + if lang != "Python3": return - + data = [source, args] - self.backgroundService.enqueueRequest('style', lang, filename, data) - + self.backgroundService.enqueueRequest("style", lang, filename, data) + def styleBatchCheck(self, argumentsList): """ Public method to prepare a style check on multiple Python source files. - + @param argumentsList list of arguments tuples with each tuple containing filename, source and args as given in styleCheck() method @@ -178,29 +184,30 @@ "Python3": [], } for filename, source, args in argumentsList: - lang = 'Python{0}'.format(determinePythonVersion(filename, source)) - if lang != 'Python3': + lang = "Python{0}".format(determinePythonVersion(filename, source)) + if lang != "Python3": continue else: data[lang].append((filename, source, args)) - + self.queuedBatches = [] - if data['Python3']: - self.queuedBatches.append('Python3') - self.backgroundService.enqueueRequest('batch_style', 'Python3', "", - data['Python3']) + if data["Python3"]: + self.queuedBatches.append("Python3") + self.backgroundService.enqueueRequest( + "batch_style", "Python3", "", data["Python3"] + ) self.batchesFinished = False - + def cancelStyleBatchCheck(self): """ Public method to cancel all batch jobs. """ - self.backgroundService.requestCancel('batch_style', 'Python3') - + self.backgroundService.requestCancel("batch_style", "Python3") + def __translateStyleCheck(self, fn, codeStyleCheckerStats, results): """ Private slot called after performing a style check on one file. - + @param fn filename of the just checked file @type str @param codeStyleCheckerStats stats of style and name check @@ -209,144 +216,153 @@ (see CodesStyleChecker.__checkCodeStyle for details) @type dict """ - from CheckerPlugins.CodeStyleChecker.translations import ( - getTranslatedMessage - ) - + from CheckerPlugins.CodeStyleChecker.translations import getTranslatedMessage + fixes = 0 for result in results: msg = getTranslatedMessage(result["code"], result["args"]) - + if result["fixcode"]: fixes += 1 - trFixedMsg = getTranslatedMessage(result["fixcode"], - result["fixargs"]) - + trFixedMsg = getTranslatedMessage(result["fixcode"], result["fixargs"]) + msg += "\n" + QCoreApplication.translate( - 'CodeStyleCheckerDialog', "Fix: {0}").format(trFixedMsg) - + "CodeStyleCheckerDialog", "Fix: {0}" + ).format(trFixedMsg) + result["display"] = "\n".join(self.__wrapper.wrap(msg)) self.styleChecked.emit(fn, codeStyleCheckerStats, fixes, results) def activate(self): """ Public method to activate this plugin. - + @return tuple of None and activation status (boolean) """ menu = ericApp().getObject("Project").getMenu("Checks") if menu: self.__projectAct = EricAction( - self.tr('Check Code Style'), - self.tr('&Code Style...'), 0, 0, - self, 'project_check_pep8') - self.__projectAct.setStatusTip( - self.tr('Check code style.')) - self.__projectAct.setWhatsThis(self.tr( + self.tr("Check Code Style"), + self.tr("&Code Style..."), + 0, + 0, + self, + "project_check_pep8", + ) + self.__projectAct.setStatusTip(self.tr("Check code style.")) + self.__projectAct.setWhatsThis( + self.tr( + """<b>Check Code Style...</b>""" + """<p>This checks Python files for compliance to the""" + """ code style conventions given in various PEPs.</p>""" + ) + ) + self.__projectAct.triggered.connect(self.__projectCodeStyleCheck) + ericApp().getObject("Project").addEricActions([self.__projectAct]) + menu.addAction(self.__projectAct) + + self.__editorAct = EricAction( + self.tr("Check Code Style"), self.tr("&Code Style..."), 0, 0, self, "" + ) + self.__editorAct.setWhatsThis( + self.tr( """<b>Check Code Style...</b>""" """<p>This checks Python files for compliance to the""" """ code style conventions given in various PEPs.</p>""" - )) - self.__projectAct.triggered.connect( - self.__projectCodeStyleCheck) - ericApp().getObject("Project").addEricActions([self.__projectAct]) - menu.addAction(self.__projectAct) - - self.__editorAct = EricAction( - self.tr('Check Code Style'), - self.tr('&Code Style...'), 0, 0, - self, "") - self.__editorAct.setWhatsThis(self.tr( - """<b>Check Code Style...</b>""" - """<p>This checks Python files for compliance to the""" - """ code style conventions given in various PEPs.</p>""" - )) + ) + ) self.__editorAct.triggered.connect(self.__editorCodeStyleCheck) - + 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) - + return None, True def deactivate(self): """ 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: menu.removeAction(self.__projectAct) - + if self.__projectBrowserMenu and self.__projectBrowserAct: - self.__projectBrowserMenu.removeAction( - self.__projectBrowserAct) - + self.__projectBrowserMenu.removeAction(self.__projectBrowserAct) + 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 __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 (string) @param menu reference to the menu (QMenu) """ if menuName == "Checks" and self.__projectAct is not None: self.__projectAct.setEnabled( - ericApp().getObject("Project").getProjectLanguage() in - ["Python3", "MicroPython"]) - + ericApp().getObject("Project").getProjectLanguage() + in ["Python3", "MicroPython"] + ) + 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 (string) @param menu reference to the menu (QMenu) """ - if ( - menuName == "Checks" and - ericApp().getObject("Project").getProjectLanguage() in - ["Python3", "MicroPython"] - ): + if menuName == "Checks" and ericApp().getObject( + "Project" + ).getProjectLanguage() in ["Python3", "MicroPython"]: self.__projectBrowserMenu = menu if self.__projectBrowserAct is None: self.__projectBrowserAct = EricAction( - self.tr('Check Code Style'), - self.tr('&Code Style...'), 0, 0, - self, "") - self.__projectBrowserAct.setWhatsThis(self.tr( - """<b>Check Code Style...</b>""" - """<p>This checks Python files for compliance to the""" - """ code style conventions given in various PEPs.</p>""" - )) + self.tr("Check Code Style"), + self.tr("&Code Style..."), + 0, + 0, + self, + "", + ) + self.__projectBrowserAct.setWhatsThis( + self.tr( + """<b>Check Code Style...</b>""" + """<p>This checks Python files for compliance to the""" + """ code style conventions given in various PEPs.</p>""" + ) + ) self.__projectBrowserAct.triggered.connect( - self.__projectBrowserCodeStyleCheck) + self.__projectBrowserCodeStyleCheck + ) if self.__projectBrowserAct not in menu.actions(): menu.addAction(self.__projectBrowserAct) - + def __projectCodeStyleCheck(self): """ Private slot used to check the project files for code style. @@ -354,26 +370,26 @@ project = ericApp().getObject("Project") project.saveAllScripts() ppath = project.getProjectPath() - files = [os.path.join(ppath, file) - for file in project.pdata["SOURCES"] - if file.endswith( - tuple(Preferences.getPython("Python3Extensions")))] - + files = [ + os.path.join(ppath, file) + for file in project.pdata["SOURCES"] + if file.endswith(tuple(Preferences.getPython("Python3Extensions"))) + ] + from CheckerPlugins.CodeStyleChecker import CodeStyleCheckerDialog + self.__projectCodeStyleCheckerDialog = ( CodeStyleCheckerDialog.CodeStyleCheckerDialog(self) ) self.__projectCodeStyleCheckerDialog.show() self.__projectCodeStyleCheckerDialog.prepare(files, project) - + def __projectBrowserCodeStyleCheck(self): """ Private method to handle the code style check context menu action of the project sources browser. """ - browser = ( - ericApp().getObject("ProjectBrowser").getProjectBrowser("sources") - ) + browser = ericApp().getObject("ProjectBrowser").getProjectBrowser("sources") if browser.getSelectedItemsCount([ProjectBrowserFileItem]) > 1: fn = [] for itm in browser.getSelectedItems([ProjectBrowserFileItem]): @@ -387,23 +403,24 @@ except AttributeError: fn = itm.dirName() isDir = True - + from CheckerPlugins.CodeStyleChecker import CodeStyleCheckerDialog + self.__projectBrowserCodeStyleCheckerDialog = ( CodeStyleCheckerDialog.CodeStyleCheckerDialog(self) ) self.__projectBrowserCodeStyleCheckerDialog.show() if isDir: - self.__projectBrowserCodeStyleCheckerDialog.start( - fn, save=True) + self.__projectBrowserCodeStyleCheckerDialog.start(fn, save=True) else: self.__projectBrowserCodeStyleCheckerDialog.start( - fn, save=True, repeat=True) - + fn, save=True, repeat=True + ) + def __editorOpened(self, editor): """ Private slot called, when a new editor was opened. - + @param editor reference to the new editor (QScintilla.Editor) """ menu = editor.getMenu("Checks") @@ -411,21 +428,21 @@ 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 (QScintilla.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 (string) @param menu reference to the menu (QMenu) @param editor reference to the editor @@ -434,7 +451,7 @@ if self.__editorAct not in menu.actions(): menu.addAction(self.__editorAct) self.__editorAct.setEnabled(editor.isPyFile()) - + def __editorCodeStyleCheck(self): """ Private slot to handle the code style check context menu action @@ -442,18 +459,16 @@ """ editor = ericApp().getObject("ViewManager").activeWindow() if ( - editor is not None and - editor.checkDirty() and - editor.getFileName() is not None + editor is not None + and editor.checkDirty() + and editor.getFileName() is not None ): - from CheckerPlugins.CodeStyleChecker import ( - CodeStyleCheckerDialog - ) + from CheckerPlugins.CodeStyleChecker import CodeStyleCheckerDialog + self.__editorCodeStyleCheckerDialog = ( CodeStyleCheckerDialog.CodeStyleCheckerDialog(self) ) self.__editorCodeStyleCheckerDialog.show() self.__editorCodeStyleCheckerDialog.start( - editor.getFileName(), - save=True, - repeat=True) + editor.getFileName(), save=True, repeat=True + )