PluginVulture.py

changeset 1
ea6aed49cd69
parent 0
9b743f8d436b
child 2
b517a1c5d5de
--- a/PluginVulture.py	Sat Oct 03 17:08:28 2015 +0200
+++ b/PluginVulture.py	Sat Oct 03 19:07:40 2015 +0200
@@ -0,0 +1,284 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2015 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing the radon code metrics plug-in.
+"""
+
+from __future__ import unicode_literals
+
+import os
+
+from PyQt5.QtCore import pyqtSignal, QObject, QTranslator
+
+from E5Gui.E5Application import e5App
+from E5Gui.E5Action import E5Action
+
+import Preferences
+
+# Start-Of-Header
+name = "PluginVulture"
+author = "Detlev Offenbach <detlev@die-offenbachs.de>"
+autoactivate = True
+deactivateable = True
+version = "0.1.0"
+className = "VulturePlugin"
+packageName = "VultureChecker"
+shortDescription = "Plug-in to detect unused code using the vulture library"
+longDescription = (
+    """Plug-in to detect unused code using the vulture library."""
+)
+needsRestart = False
+pyqtApi = 2
+python2Compatible = True
+# End-Of-Header
+
+error = ""
+    
+
+class VulturePlugin(QObject):
+    """
+    Class documentation goes here.
+    
+    @signal metricsDone(str, dict) emitted when the code metrics were
+        determined for a file
+    @signal error(str, str) emitted in case of an error
+    @signal batchFinished() emitted when a style check batch is done
+    """
+    batchFinished = pyqtSignal()
+    
+    def __init__(self, ui):
+        """
+        Constructor
+        
+        @param ui reference to the user interface object (UI.UserInterface)
+        """
+        super(VulturePlugin, self).__init__(ui)
+        self.__ui = ui
+        self.__initialize()
+        
+        self.backgroundService = e5App().getObject("BackgroundService")
+        
+        path = os.path.join(os.path.dirname(__file__), packageName)
+        try:
+            self.backgroundService.serviceConnect(
+                'vulture', 'Python2', path, 'VultureCheckerService',
+                self.vultureCheckDone,
+                onErrorCallback=self.serviceErrorPy2,
+                onBatchDone=self.batchJobDone)
+            self.backgroundService.serviceConnect(
+                'vulture', 'Python3', path, 'VultureCheckerService',
+                self.vultureCheckDone,
+                onErrorCallback=self.serviceErrorPy3,
+                onBatchDone=self.batchJobDone)
+        except TypeError:
+            # backward compatibility for eric 6.0
+            self.backgroundService.serviceConnect(
+                'vulture', 'Python2', path, 'VultureCheckerService',
+                self.vultureCheckDone,
+                onErrorCallback=self.serviceErrorPy2)
+            self.backgroundService.serviceConnect(
+                'vulture', 'Python3', path, 'VultureCheckerService',
+                self.vultureCheckDone,
+                onErrorCallback=self.serviceErrorPy3)
+        
+        self.queuedBatches = []
+        self.batchesFinished = True
+        
+        self.__translator = None
+        self.__loadTranslator()
+    
+    def __serviceError(self, fn, msg):
+        """
+        Private slot handling service errors.
+        
+        @param fn file name
+        @type str
+        @param msg message text
+        @type str
+        """
+        self.error.emit(fn, msg)
+    
+    def serviceErrorPy2(self, fx, lang, fn, msg):
+        """
+        Public slot handling service errors for Python 2.
+        
+        @param fx service name
+        @type str
+        @param lang language
+        @type str
+        @param fn file name
+        @type str
+        @param msg message text
+        @type str
+        """
+        if fx in ['vulture', 'batch_vulture'] and \
+                lang == 'Python2':
+            if fx == 'vulture':
+                self.__serviceError(fn, msg)
+            else:
+                self.__serviceError(self.tr("Python 2 batch job"), msg)
+                self.batchJobDone(fx, lang)
+    
+    def serviceErrorPy3(self, fx, lang, fn, msg):
+        """
+        Public slot handling service errors for Python 3.
+        
+        @param fx service name
+        @type str
+        @param lang language
+        @type str
+        @param fn file name
+        @type str
+        @param msg message text
+        @type str
+        """
+        if fx in ['vulture', 'batch_vulture'] and \
+                lang == 'Python3':
+            if fx == 'vulture':
+                self.__serviceError(fn, msg)
+            else:
+                self.__serviceError(self.tr("Python 3 batch job"), msg)
+                self.batchJobDone(fx, lang)
+    
+    def batchJobDone(self, fx, lang):
+        """
+        Public slot handling the completion of a batch job.
+        
+        @param fx service name
+        @type str
+        @param lang language
+        @type str
+        """
+        if fx in ['vulture', 'batch_vulture']:
+            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 plug-in.
+        """
+        self.__projectAct = None
+        self.__projectVultureCheckerDialog = None
+
+    def vultureCheck(self, lang, filenames):
+        """
+        Public method to prepare a vulture check for a Python project.
+
+        @param lang language of the files or None to determine by internal
+            algorithm
+        @type str or None
+        @param filenames list of file names to include in the check
+        @type list of str
+        """
+        # TODO: implement this
+    
+    def activate(self):
+        """
+        Public method to activate this plug-in.
+        
+        @return tuple of None and activation status (boolean)
+        """
+        global error
+        error = ""     # clear previous error
+        
+        menu = e5App().getObject("Project").getMenu("Checks")
+        if menu:
+            self.__projectAct = E5Action(
+                self.tr('Check Unused Code'),
+                self.tr('&Unused Code...'), 0, 0,
+                self, 'project_check_vulture')
+            self.__projectAct.setStatusTip(
+                self.tr('Check for unused code'))
+            self.__projectAct.setWhatsThis(self.tr(
+                """<b>Check Unused Code...</b>"""
+                """<p>This checks a Python project for unused code.</p>"""
+            ))
+            self.__projectAct.triggered.connect(
+                self.__projectVultureCheck)
+            e5App().getObject("Project").addE5Actions([self.__projectAct])
+            menu.addAction(self.__projectAct)
+        
+        e5App().getObject("Project").showMenu.connect(self.__projectShowMenu)
+        e5App().getObject("Project").projectClosed.connect(
+            self.__projectClosed)
+        
+        return None, True
+    
+    def deactivate(self):
+        """
+        Public method to deactivate this plug-in.
+        """
+        e5App().getObject("Project").showMenu.disconnect(
+            self.__projectShowMenu)
+        e5App().getObject("Project").projectClosed.disconnect(
+            self.__projectClosed)
+        
+        menu = e5App().getObject("Project").getMenu("Show")
+        if menu:
+            if self.__projectAct is not None:
+                menu.removeAction(self.__projectAct)
+            e5App().getObject("Project").removeE5Actions(
+                [self.self.__projectAct])
+    
+    def __loadTranslator(self):
+        """
+        Private method to load the translation file.
+        """
+        if self.__ui is not None:
+            loc = self.__ui.getLocale()
+            if loc and loc != "C":
+                locale_dir = os.path.join(
+                    os.path.dirname(__file__), "VultureChecker", "i18n")
+                translation = "vulture_{0}".format(loc)
+                translator = QTranslator(None)
+                loaded = translator.load(translation, locale_dir)
+                if loaded:
+                    self.__translator = translator
+                    e5App().installTranslator(self.__translator)
+                else:
+                    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
+        @type QMenu
+        """
+        if menuName == "Check":
+            if self.__projectAct is not None:
+                self.__projectAct.setEnabled(
+                    e5App().getObject("Project").getProjectLanguage() in
+                    ["Python3", "Python2", "Python"])
+    
+    def __projectVultureCheck(self):
+        """
+        Private slot used to check the project for unused code.
+        """
+        project = e5App().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")) +
+                     tuple(Preferences.getPython("PythonExtensions")))]
+        
+        if self.__projectVultureCheckerDialog is None:
+            from VultureChecker.VultureCheckerDialog import \
+                VultureCheckerDialog
+            self.__projectRawMetricsDialog = VultureCheckerDialog(self)
+        self.__projectVultureCheckerDialog.show()
+        self.__projectVultureCheckerDialog.prepare(files, project)

eric ide

mercurial