The metrics module now supports multiple repositories (See issue #24).

This commit is contained in:
Adam Waldenberg 2015-11-01 03:36:40 +01:00
parent 7acf871ab1
commit 802f18e7e5
3 changed files with 52 additions and 40 deletions

View File

@ -26,6 +26,7 @@ import sys
from .blame import Blame
from .changes import Changes
from .config import GitConfig
from .metrics import MetricsLogic
from . import (basedir, clone, extensions, filtering, format, help, interval,
localization, optval, terminal, version)
from .output import outputable
@ -59,8 +60,10 @@ class Runner(object):
terminal.skip_escapes(not sys.stdout.isatty())
terminal.set_stdout_encoding()
previous_directory = os.getcwd()
summed_blames = None
summed_changes = None
summed_metrics = None
for repo in repos:
os.chdir(previous_directory)
@ -70,6 +73,9 @@ class Runner(object):
summed_blames = Blame(self.hard, self.useweeks, changes) + summed_blames
summed_changes = changes + summed_changes
if self.include_metrics:
summed_metrics = MetricsLogic() + summed_metrics
if sys.stdout.isatty() and format.is_interactive_format():
terminal.clear_row()
@ -85,7 +91,7 @@ class Runner(object):
outputable.output(TimelineOutput(summed_changes, self.useweeks))
if self.include_metrics:
outputable.output(MetricsOutput())
outputable.output(MetricsOutput(summed_metrics))
if self.responsibilities:
outputable.output(ResponsibilitiesOutput(summed_changes, summed_blames))

View File

@ -69,6 +69,15 @@ class MetricsLogic(object):
if lines > 0 and METRIC_CYCLOMATIC_COMPLEXITY_DENSITY_THRESHOLD < cycc / float(lines):
self.cyclomatic_complexity_density[i.strip()] = cycc / float(lines)
def __add__(self, other):
if other == None:
return self
self.eloc.update(other.eloc)
self.cyclomatic_complexity.update(other.cyclomatic_complexity)
self.cyclomatic_complexity_density.update(other.cyclomatic_complexity_density)
return self
@staticmethod
def get_cyclomatic_complexity(file_r, extension):
is_inside_comment = False

View File

@ -21,7 +21,7 @@ from __future__ import print_function
from __future__ import unicode_literals
from ..changes import FileDiff
from ..localization import N_
from .. import metrics
from ..metrics import (__metric_eloc__, METRIC_CYCLOMATIC_COMPLEXITY_THRESHOLD, METRIC_CYCLOMATIC_COMPLEXITY_DENSITY_THRESHOLD)
from .outputable import Outputable
ELOC_INFO_TEXT = N_("The following files are suspiciously big (in order of severity)")
@ -38,54 +38,55 @@ def __get_metrics_score__(ceiling, value):
return i[1]
class MetricsOutput(Outputable):
def output_text(self):
metrics_logic = metrics.MetricsLogic()
def __init__(self, metrics):
self.metrics = metrics
Outputable.__init__(self)
if not metrics_logic.eloc and not metrics_logic.cyclomatic_complexity and not metrics_logic.cyclomatic_complexity_density:
def output_text(self):
if not self.metrics.eloc and not self.metrics.cyclomatic_complexity and not self.metrics.cyclomatic_complexity_density:
print("\n" + _(METRICS_MISSING_INFO_TEXT) + ".")
if metrics_logic.eloc:
if self.metrics.eloc:
print("\n" + _(ELOC_INFO_TEXT) + ":")
for i in sorted(set([(j, i) for (i, j) in metrics_logic.eloc.items()]), reverse=True):
for i in sorted(set([(j, i) for (i, j) in self.metrics.eloc.items()]), reverse=True):
print(_("{0} ({1} estimated lines of code)").format(i[1], str(i[0])))
if metrics_logic.cyclomatic_complexity:
if self.metrics.cyclomatic_complexity:
print("\n" + _(CYCLOMATIC_COMPLEXITY_TEXT) + ":")
for i in sorted(set([(j, i) for (i, j) in metrics_logic.cyclomatic_complexity.items()]), reverse=True):
for i in sorted(set([(j, i) for (i, j) in self.metrics.cyclomatic_complexity.items()]), reverse=True):
print(_("{0} ({1} in cyclomatic complexity)").format(i[1], str(i[0])))
if metrics_logic.cyclomatic_complexity_density:
if self.metrics.cyclomatic_complexity_density:
print("\n" + _(CYCLOMATIC_COMPLEXITY_DENSITY_TEXT) + ":")
for i in sorted(set([(j, i) for (i, j) in metrics_logic.cyclomatic_complexity_density.items()]), reverse=True):
for i in sorted(set([(j, i) for (i, j) in self.metrics.cyclomatic_complexity_density.items()]), reverse=True):
print(_("{0} ({1:.3f} in cyclomatic complexity density)").format(i[1], i[0]))
def output_html(self):
metrics_logic = metrics.MetricsLogic()
metrics_xml = "<div><div class=\"box\" id=\"metrics\">"
if not metrics_logic.eloc and not metrics_logic.cyclomatic_complexity and not metrics_logic.cyclomatic_complexity_density:
if not self.metrics.eloc and not self.metrics.cyclomatic_complexity and not self.metrics.cyclomatic_complexity_density:
metrics_xml += "<p>" + _(METRICS_MISSING_INFO_TEXT) + ".</p>"
if metrics_logic.eloc:
if self.metrics.eloc:
metrics_xml += "<div><h4>" + _(ELOC_INFO_TEXT) + ".</h4>"
for num, i in enumerate(sorted(set([(j, i) for (i, j) in metrics_logic.eloc.items()]), reverse=True)):
metrics_xml += "<div class=\"" + __get_metrics_score__(metrics.__metric_eloc__[FileDiff.get_extension(i[1])], i[0]) + \
for num, i in enumerate(sorted(set([(j, i) for (i, j) in self.metrics.eloc.items()]), reverse=True)):
metrics_xml += "<div class=\"" + __get_metrics_score__(__metric_eloc__[FileDiff.get_extension(i[1])], i[0]) + \
(" odd\">" if num % 2 == 1 else "\">") + \
_("{0} ({1} estimated lines of code)").format(i[1], str(i[0])) + "</div>"
metrics_xml += "</div>"
if metrics_logic.cyclomatic_complexity:
if self.metrics.cyclomatic_complexity:
metrics_xml += "<div><h4>" + _(CYCLOMATIC_COMPLEXITY_TEXT) + "</h4>"
for num, i in enumerate(sorted(set([(j, i) for (i, j) in metrics_logic.cyclomatic_complexity.items()]), reverse=True)):
metrics_xml += "<div class=\"" + __get_metrics_score__(metrics.METRIC_CYCLOMATIC_COMPLEXITY_THRESHOLD, i[0]) + \
for num, i in enumerate(sorted(set([(j, i) for (i, j) in self.metrics.cyclomatic_complexity.items()]), reverse=True)):
metrics_xml += "<div class=\"" + __get_metrics_score__(METRIC_CYCLOMATIC_COMPLEXITY_THRESHOLD, i[0]) + \
(" odd\">" if num % 2 == 1 else "\">") + \
_("{0} ({1} in cyclomatic complexity)").format(i[1], str(i[0])) + "</div>"
metrics_xml += "</div>"
if metrics_logic.cyclomatic_complexity_density:
if self.metrics.cyclomatic_complexity_density:
metrics_xml += "<div><h4>" + _(CYCLOMATIC_COMPLEXITY_DENSITY_TEXT) + "</h4>"
for num, i in enumerate(sorted(set([(j, i) for (i, j) in metrics_logic.cyclomatic_complexity_density.items()]), reverse=True)):
metrics_xml += "<div class=\"" + __get_metrics_score__(metrics.METRIC_CYCLOMATIC_COMPLEXITY_DENSITY_THRESHOLD, i[0]) + \
for num, i in enumerate(sorted(set([(j, i) for (i, j) in self.metrics.cyclomatic_complexity_density.items()]), reverse=True)):
metrics_xml += "<div class=\"" + __get_metrics_score__(METRIC_CYCLOMATIC_COMPLEXITY_DENSITY_THRESHOLD, i[0]) + \
(" odd\">" if num % 2 == 1 else "\">") + \
_("{0} ({1:.3f} in cyclomatic complexity density)").format(i[1], i[0]) + "</div>"
metrics_xml += "</div>"
@ -94,15 +95,13 @@ class MetricsOutput(Outputable):
print(metrics_xml)
def output_json(self):
metrics_logic = metrics.MetricsLogic()
if not metrics_logic.eloc and not metrics_logic.cyclomatic_complexity and not metrics_logic.cyclomatic_complexity_density:
if not self.metrics.eloc and not self.metrics.cyclomatic_complexity and not self.metrics.cyclomatic_complexity_density:
print(",\n\t\t\"metrics\": {\n\t\t\t\"message\": \"" + _(METRICS_MISSING_INFO_TEXT) + "\"\n\t\t}", end="")
else:
eloc_xml = ""
if metrics_logic.eloc:
for i in sorted(set([(j, i) for (i, j) in metrics_logic.eloc.items()]), reverse=True):
if self.metrics.eloc:
for i in sorted(set([(j, i) for (i, j) in self.metrics.eloc.items()]), reverse=True):
eloc_xml += "{\n\t\t\t\t\"type\": \"estimated-lines-of-code\",\n"
eloc_xml += "\t\t\t\t\"file-name\": \"" + i[1] + "\",\n"
eloc_xml += "\t\t\t\t\"value\": " + str(i[0]) + "\n"
@ -110,8 +109,8 @@ class MetricsOutput(Outputable):
else:
eloc_xml = eloc_xml[:-1]
if metrics_logic.cyclomatic_complexity:
for i in sorted(set([(j, i) for (i, j) in metrics_logic.cyclomatic_complexity.items()]), reverse=True):
if self.metrics.cyclomatic_complexity:
for i in sorted(set([(j, i) for (i, j) in self.metrics.cyclomatic_complexity.items()]), reverse=True):
eloc_xml += "{\n\t\t\t\t\"type\": \"cyclomatic-complexity\",\n"
eloc_xml += "\t\t\t\t\"file-name\": \"" + i[1] + "\",\n"
eloc_xml += "\t\t\t\t\"value\": " + str(i[0]) + "\n"
@ -119,8 +118,8 @@ class MetricsOutput(Outputable):
else:
eloc_xml = eloc_xml[:-1]
if metrics_logic.cyclomatic_complexity_density:
for i in sorted(set([(j, i) for (i, j) in metrics_logic.cyclomatic_complexity_density.items()]), reverse=True):
if self.metrics.cyclomatic_complexity_density:
for i in sorted(set([(j, i) for (i, j) in self.metrics.cyclomatic_complexity_density.items()]), reverse=True):
eloc_xml += "{\n\t\t\t\t\"type\": \"cyclomatic-complexity-density\",\n"
eloc_xml += "\t\t\t\t\"file-name\": \"" + i[1] + "\",\n"
eloc_xml += "\t\t\t\t\"value\": {0:.3f} \"\n".format(i[0])
@ -130,29 +129,27 @@ class MetricsOutput(Outputable):
print(",\n\t\t\"metrics\": {\n\t\t\t\"violations\": [\n\t\t\t" + eloc_xml + "]\n\t\t}", end="")
def output_xml(self):
metrics_logic = metrics.MetricsLogic()
if not metrics_logic.eloc and not metrics_logic.cyclomatic_complexity and not metrics_logic.cyclomatic_complexity_density:
if not self.metrics.eloc and not self.metrics.cyclomatic_complexity and not self.metrics.cyclomatic_complexity_density:
print("\t<metrics>\n\t\t<message>" + _(METRICS_MISSING_INFO_TEXT) + "</message>\n\t</metrics>")
else:
eloc_xml = ""
if metrics_logic.eloc:
for i in sorted(set([(j, i) for (i, j) in metrics_logic.eloc.items()]), reverse=True):
if self.metrics.eloc:
for i in sorted(set([(j, i) for (i, j) in self.metrics.eloc.items()]), reverse=True):
eloc_xml += "\t\t\t<estimated-lines-of-code>\n"
eloc_xml += "\t\t\t\t<file-name>" + i[1] + "</file-name>\n"
eloc_xml += "\t\t\t\t<value>" + str(i[0]) + "</value>\n"
eloc_xml += "\t\t\t</estimated-lines-of-code>\n"
if metrics_logic.cyclomatic_complexity:
for i in sorted(set([(j, i) for (i, j) in metrics_logic.cyclomatic_complexity.items()]), reverse=True):
if self.metrics.cyclomatic_complexity:
for i in sorted(set([(j, i) for (i, j) in self.metrics.cyclomatic_complexity.items()]), reverse=True):
eloc_xml += "\t\t\t<cyclomatic-complexity>\n"
eloc_xml += "\t\t\t\t<file-name>" + i[1] + "</file-name>\n"
eloc_xml += "\t\t\t\t<value>" + str(i[0]) + "</value>\n"
eloc_xml += "\t\t\t</cyclomatic-complexity>\n"
if metrics_logic.cyclomatic_complexity_density:
for i in sorted(set([(j, i) for (i, j) in metrics_logic.cyclomatic_complexity_density.items()]), reverse=True):
if self.metrics.cyclomatic_complexity_density:
for i in sorted(set([(j, i) for (i, j) in self.metrics.cyclomatic_complexity_density.items()]), reverse=True):
eloc_xml += "\t\t\t<cyclomatic-complexity-density>\n"
eloc_xml += "\t\t\t\t<file-name>" + i[1] + "</file-name>\n"
eloc_xml += "\t\t\t\t<value>{0:.3f}</value>\n".format(i[0])