From 802f18e7e5075668d3bb250d65a1669a5e2b3331 Mon Sep 17 00:00:00 2001 From: Adam Waldenberg Date: Sun, 1 Nov 2015 03:36:40 +0100 Subject: [PATCH] The metrics module now supports multiple repositories (See issue #24). --- gitinspector/gitinspector.py | 8 ++- gitinspector/metrics.py | 9 ++++ gitinspector/output/metricsoutput.py | 75 +++++++++++++--------------- 3 files changed, 52 insertions(+), 40 deletions(-) diff --git a/gitinspector/gitinspector.py b/gitinspector/gitinspector.py index e9ad743..ad4aff3 100644 --- a/gitinspector/gitinspector.py +++ b/gitinspector/gitinspector.py @@ -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)) diff --git a/gitinspector/metrics.py b/gitinspector/metrics.py index 8a35084..d683e28 100644 --- a/gitinspector/metrics.py +++ b/gitinspector/metrics.py @@ -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 diff --git a/gitinspector/output/metricsoutput.py b/gitinspector/output/metricsoutput.py index 3f69348..af6b7ac 100644 --- a/gitinspector/output/metricsoutput.py +++ b/gitinspector/output/metricsoutput.py @@ -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 = "
" - 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 += "

" + _(METRICS_MISSING_INFO_TEXT) + ".

" - if metrics_logic.eloc: + if self.metrics.eloc: metrics_xml += "

" + _(ELOC_INFO_TEXT) + ".

" - for num, i in enumerate(sorted(set([(j, i) for (i, j) in metrics_logic.eloc.items()]), reverse=True)): - metrics_xml += "
" if num % 2 == 1 else "\">") + \ _("{0} ({1} estimated lines of code)").format(i[1], str(i[0])) + "
" metrics_xml += "
" - if metrics_logic.cyclomatic_complexity: + if self.metrics.cyclomatic_complexity: metrics_xml += "

" + _(CYCLOMATIC_COMPLEXITY_TEXT) + "

" - for num, i in enumerate(sorted(set([(j, i) for (i, j) in metrics_logic.cyclomatic_complexity.items()]), reverse=True)): - metrics_xml += "
" if num % 2 == 1 else "\">") + \ _("{0} ({1} in cyclomatic complexity)").format(i[1], str(i[0])) + "
" metrics_xml += "
" - if metrics_logic.cyclomatic_complexity_density: + if self.metrics.cyclomatic_complexity_density: metrics_xml += "

" + _(CYCLOMATIC_COMPLEXITY_DENSITY_TEXT) + "

" - for num, i in enumerate(sorted(set([(j, i) for (i, j) in metrics_logic.cyclomatic_complexity_density.items()]), reverse=True)): - metrics_xml += "
" if num % 2 == 1 else "\">") + \ _("{0} ({1:.3f} in cyclomatic complexity density)").format(i[1], i[0]) + "
" metrics_xml += "
" @@ -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\n\t\t" + _(METRICS_MISSING_INFO_TEXT) + "\n\t") 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\n" eloc_xml += "\t\t\t\t" + i[1] + "\n" eloc_xml += "\t\t\t\t" + str(i[0]) + "\n" eloc_xml += "\t\t\t\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\n" eloc_xml += "\t\t\t\t" + i[1] + "\n" eloc_xml += "\t\t\t\t" + str(i[0]) + "\n" eloc_xml += "\t\t\t\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\n" eloc_xml += "\t\t\t\t" + i[1] + "\n" eloc_xml += "\t\t\t\t{0:.3f}\n".format(i[0])