Continued implementing the raw code metrics stuff.

Tue, 15 Sep 2015 19:22:38 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Tue, 15 Sep 2015 19:22:38 +0200
changeset 4
9ac53bf21182
parent 3
7150ed890fd5
child 5
db25d1d5cc3a

Continued implementing the raw code metrics stuff.

PluginMetricsRadon.py file | annotate | diff | comparison | revisions
RadonMetrics/CodeMetricsCalculator.py file | annotate | diff | comparison | revisions
RadonMetrics/RawMetricsDialog.py file | annotate | diff | comparison | revisions
RadonMetrics/RawMetricsDialog.ui file | annotate | diff | comparison | revisions
--- a/PluginMetricsRadon.py	Mon Sep 14 20:18:39 2015 +0200
+++ b/PluginMetricsRadon.py	Tue Sep 15 19:22:38 2015 +0200
@@ -47,12 +47,12 @@
     """
     Class implementing the radon code metrics plug-in.
     
-    @signal metricsDone(str, list) emitted when the code metrics were
+    @signal metricsDone(str, dict) emitted when the code metrics were
         determined for a file
     @signal metricsError(str, str) emitted in case of an error
     @signal batchFinished() emitted when a code metrics batch is done
     """
-    metricsDone = pyqtSignal(str, list)
+    metricsDone = pyqtSignal(str, dict)
     metricsError = pyqtSignal(str, str)
     batchFinished = pyqtSignal()
     
@@ -70,16 +70,28 @@
         self.backgroundService = e5App().getObject("BackgroundService")
         
         path = os.path.join(os.path.dirname(__file__), packageName)
-        self.backgroundService.serviceConnect(
-            'radon', 'Python2', path, 'CodeMetricsCalculator',
-            lambda *args: self.metricsDone.emit(*args),
-            onErrorCallback=self.serviceErrorPy2,
-            onBatchDone=self.batchJobDone)
-        self.backgroundService.serviceConnect(
-            'radon', 'Python3', path, 'CodeMetricsCalculator',
-            lambda *args: self.metricsDone.emit(*args),
-            onErrorCallback=self.serviceErrorPy3,
-            onBatchDone=self.batchJobDone)
+        try:
+            self.backgroundService.serviceConnect(
+                'radon', 'Python2', path, 'CodeMetricsCalculator',
+                lambda *args: self.metricsDone.emit(*args),
+                onErrorCallback=self.serviceErrorPy2,
+                onBatchDone=self.batchJobDone)
+            self.backgroundService.serviceConnect(
+                'radon', 'Python3', path, 'CodeMetricsCalculator',
+                lambda *args: self.metricsDone.emit(*args),
+                onErrorCallback=self.serviceErrorPy3,
+                onBatchDone=self.batchJobDone)
+            self.hasBatch = True
+        except TypeError:
+            self.backgroundService.serviceConnect(
+                'radon', 'Python2', path, 'CodeMetricsCalculator',
+                lambda *args: self.metricsDone.emit(*args),
+                onErrorCallback=self.serviceErrorPy2)
+            self.backgroundService.serviceConnect(
+                'radon', 'Python3', path, 'CodeMetricsCalculator',
+                lambda *args: self.metricsDone.emit(*args),
+                onErrorCallback=self.serviceErrorPy3)
+            self.hasBatch = False
         
         self.queuedBatches = []
         self.batchesFinished = True
--- a/RadonMetrics/CodeMetricsCalculator.py	Mon Sep 14 20:18:39 2015 +0200
+++ b/RadonMetrics/CodeMetricsCalculator.py	Tue Sep 15 19:22:38 2015 +0200
@@ -5,6 +5,11 @@
 
 from __future__ import unicode_literals
 
+try:
+    str = unicode       # __IGNORE_EXCEPTION __IGNORE_WARNING__
+except NameError:
+    pass
+
 import multiprocessing
 
 
@@ -122,5 +127,26 @@
     @rtype (list)
     """
     from radon.raw import analyze
-    res = analyze(text)
+    try:
+        res = __raw2Dict(analyze(text))
+    except Exception as err:
+        res = {"error": str(err)}
     return (res, )
+
+
+def __raw2Dict(obj):
+    """
+    Private function to convert an object holding raw analysis results into a
+    dictionary.
+    
+    @param obj object as returned from analyze()
+    @type radon.raw.Module
+    @return conversion result
+    @rtype dict
+    """
+    result = {}
+    for a in obj._fields:
+        v = getattr(obj, a, None)
+        if v is not None:
+            result[a] = v
+    return result
--- a/RadonMetrics/RawMetricsDialog.py	Mon Sep 14 20:18:39 2015 +0200
+++ b/RadonMetrics/RawMetricsDialog.py	Tue Sep 15 19:22:38 2015 +0200
@@ -20,10 +20,13 @@
 
 from .Ui_RawMetricsDialog import Ui_RawMetricsDialog
 
+from E5Gui.E5Application import e5App
+
 import Preferences
 import Utilities
 
-
+# TODO: add summary table
+# TODO: add column explanations
 class RawMetricsDialog(QDialog, Ui_RawMetricsDialog):
     """
     Class implementing a dialog to show raw code metrics.
@@ -53,6 +56,8 @@
         
         self.cancelled = False
         
+        self.__project = e5App().getObject("Project")
+        
         self.__menu = QMenu(self)
         self.__menu.addAction(self.tr("Collapse all"),
                               self.__resultCollapse)
@@ -62,7 +67,6 @@
             self.__showContextMenu)
         
         self.__fileList = []
-        self.__project = None
         self.filterFrame.setVisible(False)
     
     def __resizeResultColumns(self):
@@ -76,23 +80,40 @@
         """
         Private slot to create a new item in the result list.
         
-        @param parent parent of the new item
-        @type QTreeWidget or QTreeWidgetItem
+        @param filename name of the file
+        @type str
         @param values values to be displayed
-        @type list
-        @return the generated item
-        @rtype QTreeWidgetItem
+        @type dict
         """
-        data = [filename]
-        for value in values:
+        data = [self.__project.getRelativePath(filename)]
+        for key in ['loc', 'sloc', 'lloc', 'comments', 'multi', 'blank']:
             try:
-                data.append("{0:5}".format(int(value)))
+                data.append("{0:5}".format(int(values[key])))
             except ValueError:
-                data.append(value)
+                data.append(values[key])
+            except KeyError:
+                data.append("")
+        data.append("{0:3.0%}".format(
+            values["comments"] / (float(values["loc"]) or 1)))
+        data.append("{0:3.0%}".format(
+            values["comments"] / (float(values["sloc"]) or 1)))
+        data.append("{0:3.0%}".format(
+            (values["comments"] + values["multi"]) / 
+            (float(values["loc"]) or 1)))
         itm = QTreeWidgetItem(self.resultList, data)
-        for col in range(1, 6):
+        for col in range(1, 10):
             itm.setTextAlignment(col, Qt.Alignment(Qt.AlignRight))
-        return itm
+    
+    def __createErrorItem(self, filename, message):
+        """
+        Private slot to create a new error item in the result list.
+        
+        @param filename name of the file
+        @type str
+        @param message error message
+        @type str
+        """
+        # TODO: implement this
     
     def prepare(self, fileList, project):
         """
@@ -149,6 +170,10 @@
                 self.files.remove(f)
         
         if len(self.files) > 0:
+            # disable updates of the list for speed
+            self.resultList.setUpdatesEnabled(False)
+            self.resultList.setSortingEnabled(False)
+            
             self.checkProgress.setMaximum(len(self.files))
             self.checkProgress.setVisible(len(self.files) > 1)
             self.checkProgressLabel.setVisible(len(self.files) > 1)
@@ -157,7 +182,7 @@
             # now go through all the files
             self.progress = 0
             self.files.sort()
-            if len(self.files) == 1:
+            if len(self.files) == 1 or not self.radonService.hasBatch:
                 self.__batch = False
                 self.rawMetrics()
             else:
@@ -261,8 +286,8 @@
         
         @param fn filename of the file
         @type str
-        @param result result list
-        @type list
+        @param result result dict
+        @type dict
         """
         if self.__finished:
             return
@@ -272,7 +297,10 @@
         if not self.__batch and fn != self.filename:
             return
         
-        self.__createResultItem(fn, result)
+        if "error" in result:
+            self.__createErrorItem(fn, result["error"])
+        else:
+            self.__createResultItem(fn, result)
         
         self.progress += 1
         
@@ -290,6 +318,10 @@
         if not self.__finished:
             self.__finished = True
             
+            # reenable updates of the list
+            self.resultList.setSortingEnabled(True)
+            self.resultList.setUpdatesEnabled(True)
+            
             self.cancelled = True
             self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True)
             self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False)
--- a/RadonMetrics/RawMetricsDialog.ui	Mon Sep 14 20:18:39 2015 +0200
+++ b/RadonMetrics/RawMetricsDialog.ui	Tue Sep 15 19:22:38 2015 +0200
@@ -100,12 +100,12 @@
      </column>
      <column>
       <property name="text">
-       <string>LLOC</string>
+       <string>SLOC</string>
       </property>
      </column>
      <column>
       <property name="text">
-       <string>SLOC</string>
+       <string>LLOC</string>
       </property>
      </column>
      <column>
@@ -123,6 +123,21 @@
        <string>Empty</string>
       </property>
      </column>
+     <column>
+      <property name="text">
+       <string>C % L</string>
+      </property>
+     </column>
+     <column>
+      <property name="text">
+       <string>C % S</string>
+      </property>
+     </column>
+     <column>
+      <property name="text">
+       <string>C + M % L</string>
+      </property>
+     </column>
     </widget>
    </item>
    <item>

eric ide

mercurial