Sat, 22 Mar 2014 09:45:56 +0100
Tabnanny ported to use the background service.
--- a/Plugins/CheckerPlugins/Tabnanny/Tabnanny.py Sat Mar 22 09:12:19 2014 +0100 +++ b/Plugins/CheckerPlugins/Tabnanny/Tabnanny.py Sat Mar 22 09:45:56 2014 +0100 @@ -49,14 +49,21 @@ except (ImportError): import io # __IGNORE_WARNING__ -import Utilities - if not hasattr(tokenize, 'NL'): raise ValueError("tokenize.NL doesn't exist -- tokenize module too old") __all__ = ["check", "NannyNag", "process_tokens"] +def initService(): + """ + Initialize the service and return the entry point. + + @return the entry point for the background client (function) + """ + return check + + class NannyNag(Exception): """ Class implementing an exception for indentation issues. @@ -114,34 +121,29 @@ global indents, check_equal indents = [Whitespace("")] check_equal = 0 - if not text: - try: - text = Utilities.readEncodedFile(file)[0] - text = Utilities.normalizeCode(text) - except (UnicodeError, IOError) as msg: - return (True, file, "1", "Error: {0}".format(str(msg))) + return (True, "1", "Error: source code missing.") source = io.StringIO(text) try: process_tokens(tokenize.generate_tokens(source.readline)) except tokenize.TokenError as msg: - return (True, file, "1", "Token Error: {0}".format(str(msg))) + return (True, "1", "Token Error: {0}".format(str(msg))) except IndentationError as err: - return (True, file, err.lineno, + return (True, str(err.lineno), "Indentation Error: {0}".format(str(err.msg))) except NannyNag as nag: badline = nag.get_lineno() line = nag.get_line() - return (True, file, str(badline), line) + return (True, str(badline), line) except Exception as err: - return (True, file, "1", "Unspecific Error: {0}".format(str(err))) + return (True, "1", "Unspecific Error: {0}".format(str(err))) - return (False, None, None, None) + return (False, None, None) class Whitespace(object):
--- a/Plugins/CheckerPlugins/Tabnanny/TabnannyDialog.py Sat Mar 22 09:12:19 2014 +0100 +++ b/Plugins/CheckerPlugins/Tabnanny/TabnannyDialog.py Sat Mar 22 09:45:56 2014 +0100 @@ -10,7 +10,7 @@ from __future__ import unicode_literals try: - str = unicode # __IGNORE_WARNING__ + str = unicode except (NameError): pass @@ -33,10 +33,11 @@ """ Class implementing a dialog to show the results of the tabnanny check run. """ - def __init__(self, parent=None): + def __init__(self, indentCheckService, parent=None): """ Constructor + @param indentCheckService reference to the service (IndentCheckService) @param parent The parent widget (QWidget). """ super(TabnannyDialog, self).__init__(parent) @@ -48,6 +49,10 @@ self.resultList.headerItem().setText(self.resultList.columnCount(), "") self.resultList.header().setSortIndicator(0, Qt.AscendingOrder) + self.indentCheckService = indentCheckService + self.indentCheckService.indentChecked.connect(self.__processResult) + self.filename = None + self.noResults = True self.cancelled = False @@ -120,61 +125,91 @@ QApplication.processEvents() if isinstance(fn, list): - files = fn + self.files = fn elif os.path.isdir(fn): - files = [] + self.files = [] extensions = set(Preferences.getPython("PythonExtensions") + Preferences.getPython("Python3Extensions")) for ext in extensions: - files.extend( + self.files.extend( Utilities.direntries(fn, True, '*{0}'.format(ext), 0)) else: - files = [fn] + self.files = [fn] - if len(files) > 0: - self.checkProgress.setMaximum(len(files)) - self.checkProgress.setVisible(len(files) > 1) - self.checkProgressLabel.setVisible(len(files) > 1) + if len(self.files) > 0: + self.checkProgress.setMaximum(len(self.files)) + self.checkProgress.setVisible(len(self.files) > 1) + self.checkProgressLabel.setVisible(len(self.files) > 1) QApplication.processEvents() - - # now go through all the files - progress = 0 - for file in files: - self.checkProgress.setValue(progress) - self.checkProgressLabel.setPath(file) - QApplication.processEvents() - self.__resort() - - if self.cancelled: - return - - try: - source = Utilities.readEncodedFile(file)[0] - source = Utilities.normalizeCode(source) - except (UnicodeError, IOError) as msg: - self.noResults = False - self.__createResultItem( - file, 1, - "Error: {0}".format(str(msg)).rstrip()[1:-1]) - progress += 1 - continue + + # now go through all the files + self.progress = 0 + self.check() - from . import Tabnanny - nok, fname, line, error = Tabnanny.check(file, source) - if nok: - self.noResults = False - self.__createResultItem(fname, line, error.rstrip()) - progress += 1 - - self.checkProgress.setValue(progress) + def check(self, codestring=''): + """ + Start a style check for one file. + + The results are reported to the __processResult slot. + @keyparam codestring optional sourcestring (str) + """ + if not self.files: self.checkProgressLabel.setPath("") - QApplication.processEvents() - self.__resort() - else: self.checkProgress.setMaximum(1) self.checkProgress.setValue(1) - self.__finish() + self.__finish() + return + + self.filename = self.files.pop(0) + self.checkProgress.setValue(self.progress) + self.checkProgressLabel.setPath(self.filename) + QApplication.processEvents() + self.__resort() + + if self.cancelled: + return + try: + self.source = Utilities.readEncodedFile(self.filename)[0] + self.source = Utilities.normalizeCode(self.source) + except (UnicodeError, IOError) as msg: + self.noResults = False + self.__createResultItem( + self.filename, 1, + "Error: {0}".format(str(msg)).rstrip()) + self.progress += 1 + # Continue with next file + self.check() + return + + self.indentCheckService.indentCheck( + None, self.filename, self.source) + + def __processResult(self, fn, nok, line, error): + """ + Privat slot called after perfoming a style check on one file. + + @param fn filename of the just checked file (str) + @param nok flag if a problem was found (bool) + @param line line number (str) + @param error text of the problem (str) + """ + # Check if it's the requested file, otherwise ignore signal + if fn != self.filename: + return + + if nok: + self.noResults = False + self.__createResultItem(fn, line, error.rstrip()) + self.progress += 1 + + self.checkProgress.setValue(self.progress) + self.checkProgressLabel.setPath("") + QApplication.processEvents() + self.__resort() + + self.check() + def __finish(self): """ Private slot called when the action or the user pressed the button.
--- a/Plugins/PluginTabnanny.py Sat Mar 22 09:12:19 2014 +0100 +++ b/Plugins/PluginTabnanny.py Sat Mar 22 09:45:56 2014 +0100 @@ -11,12 +11,12 @@ import os -from PyQt4.QtCore import QObject +from PyQt4.QtCore import QObject, pyqtSignal from E5Gui.E5Application import e5App - from E5Gui.E5Action import E5Action +from Utilities import determinePythonVersion import Preferences # Start-Of-Header @@ -40,7 +40,12 @@ class TabnannyPlugin(QObject): """ Class implementing the Tabnanny plugin. + + @signal indentChecked(str, bool, str, str) emited when the indent + check was done. """ + indentChecked = pyqtSignal(str, bool, str, str) + def __init__(self, ui): """ Constructor @@ -51,6 +56,17 @@ self.__ui = ui self.__initialize() + self.backgroundService = e5App().getObject("BackgroundService") + + path = os.path.join( + os.path.dirname(__file__), 'CheckerPlugins', 'Tabnanny') + for lang in ['Python2', 'Python3']: + self.backgroundService.serviceConnect( + 'indent', lang, path, 'Tabnanny', + lambda *args: self.indentChecked.emit(*args), + lambda fx, fn, ver, msg: self.indentChecked.emit( + fn, True, "1", msg)) + def __initialize(self): """ Private slot to (re)initialize the plugin. @@ -66,6 +82,24 @@ self.__editorAct = None self.__editorTabnannyDialog = None + def indentCheck(self, lang, filename, source): + """ + Method to prepare a style check on one Python source file in another + task. + + @param lang language of the file or None to determine by internal + algorithm (str or None) + @param filename source filename (string) + @param source string containing the code to check (string) + """ + if lang is None: + lang = 'Python{0}'.format(determinePythonVersion(filename, source)) + if lang not in ['Python2', 'Python3']: + return + + self.backgroundService.enqueueRequest( + 'indent', lang, filename, [source]) + def activate(self): """ Public method to activate this plugin. @@ -197,7 +231,7 @@ tuple(Preferences.getPython("PythonExtensions")))] from CheckerPlugins.Tabnanny.TabnannyDialog import TabnannyDialog - self.__projectTabnannyDialog = TabnannyDialog() + self.__projectTabnannyDialog = TabnannyDialog(self) self.__projectTabnannyDialog.show() self.__projectTabnannyDialog.prepare(files, project) @@ -215,7 +249,7 @@ fn = itm.dirName() from CheckerPlugins.Tabnanny.TabnannyDialog import TabnannyDialog - self.__projectBrowserTabnannyDialog = TabnannyDialog() + self.__projectBrowserTabnannyDialog = TabnannyDialog(self) self.__projectBrowserTabnannyDialog.show() self.__projectBrowserTabnannyDialog.start(fn) @@ -266,6 +300,6 @@ if editor.checkDirty() and editor.getFileName() is not None: from CheckerPlugins.Tabnanny.TabnannyDialog import \ TabnannyDialog - self.__editorTabnannyDialog = TabnannyDialog() + self.__editorTabnannyDialog = TabnannyDialog(self) self.__editorTabnannyDialog.show() self.__editorTabnannyDialog.start(editor.getFileName())