diff options
author | Ned Batchelder <ned@nedbatchelder.com> | 2021-06-01 06:10:39 -0400 |
---|---|---|
committer | Ned Batchelder <ned@nedbatchelder.com> | 2021-06-01 06:10:39 -0400 |
commit | 5ed7c17b6f8e3a4b9b9826d2aa4459695b9e5a86 (patch) | |
tree | 197e95d7fce3c70df04d12e947302ed7dbade701 | |
parent | 1157999dc5c6c3aa3129a7cd4bf249fe73598501 (diff) | |
download | python-coveragepy-git-5ed7c17b6f8e3a4b9b9826d2aa4459695b9e5a86.tar.gz |
refactor: remove globals from Numbers
-rw-r--r-- | coverage/cmdline.py | 4 | ||||
-rw-r--r-- | coverage/control.py | 5 | ||||
-rw-r--r-- | coverage/html.py | 2 | ||||
-rw-r--r-- | coverage/jsonreport.py | 2 | ||||
-rw-r--r-- | coverage/results.py | 55 | ||||
-rw-r--r-- | coverage/summary.py | 4 | ||||
-rw-r--r-- | tests/test_results.py | 41 |
7 files changed, 46 insertions, 67 deletions
diff --git a/coverage/cmdline.py b/coverage/cmdline.py index 697d2960..3d8dcf85 100644 --- a/coverage/cmdline.py +++ b/coverage/cmdline.py @@ -656,7 +656,9 @@ class CoverageScript: precision = self.coverage.get_option("report:precision") if should_fail_under(total, fail_under, precision): msg = "total of {total} is less than fail-under={fail_under:.{p}f}".format( - total=Numbers.display_covered(total), fail_under=fail_under, p=precision, + total=Numbers(precision=precision).display_covered(total), + fail_under=fail_under, + p=precision, ) print("Coverage failure:", msg) return FAIL_UNDER diff --git a/coverage/control.py b/coverage/control.py index b13acf45..d609c8c7 100644 --- a/coverage/control.py +++ b/coverage/control.py @@ -32,7 +32,7 @@ from coverage.plugin import FileReporter from coverage.plugin_support import Plugins from coverage.python import PythonFileReporter from coverage.report import render_report -from coverage.results import Analysis, Numbers +from coverage.results import Analysis from coverage.summary import SummaryReporter from coverage.xmlreport import XmlReporter @@ -799,14 +799,13 @@ class Coverage: """ # All reporting comes through here, so do reporting initialization. self._init() - Numbers.set_precision(self.config.precision) self._post_init() data = self.get_data() if not isinstance(it, FileReporter): it = self._get_file_reporter(it) - return Analysis(data, it, self._file_mapper) + return Analysis(data, self.config.precision, it, self._file_mapper) def _get_file_reporter(self, morf): """Get a FileReporter for a module or file name.""" diff --git a/coverage/html.py b/coverage/html.py index 7626f54e..15f35a66 100644 --- a/coverage/html.py +++ b/coverage/html.py @@ -195,7 +195,7 @@ class HtmlReporter: self.all_files_nums = [] self.incr = IncrementalChecker(self.directory) self.datagen = HtmlDataGeneration(self.coverage) - self.totals = Numbers() + self.totals = Numbers(precision=self.config.precision) self.template_globals = { # Functions available in the templates. diff --git a/coverage/jsonreport.py b/coverage/jsonreport.py index 70ceb71f..b22ab10b 100644 --- a/coverage/jsonreport.py +++ b/coverage/jsonreport.py @@ -17,7 +17,7 @@ class JsonReporter: def __init__(self, coverage): self.coverage = coverage self.config = self.coverage.config - self.total = Numbers() + self.total = Numbers(self.config.precision) self.report_data = {} def report(self, morfs, outfile=None): diff --git a/coverage/results.py b/coverage/results.py index f7331b41..60ba4384 100644 --- a/coverage/results.py +++ b/coverage/results.py @@ -13,7 +13,7 @@ from coverage.misc import contract, nice_pair class Analysis: """The results of analyzing a FileReporter.""" - def __init__(self, data, file_reporter, file_mapper): + def __init__(self, data, precision, file_reporter, file_mapper): self.data = data self.file_reporter = file_reporter self.filename = file_mapper(self.file_reporter.filename) @@ -41,6 +41,7 @@ class Analysis: n_branches = n_partial_branches = n_missing_branches = 0 self.numbers = Numbers( + precision=precision, n_files=1, n_statements=len(self.statements), n_excluded=len(self.excluded), @@ -158,15 +159,16 @@ class Numbers(SimpleReprMixin): up statistics across files. """ - # A global to determine the precision on coverage percentages, the number - # of decimal places. - _precision = 0 - _near0 = 1.0 # These will change when _precision is changed. - _near100 = 99.0 - - def __init__(self, n_files=0, n_statements=0, n_excluded=0, n_missing=0, - n_branches=0, n_partial_branches=0, n_missing_branches=0 - ): + + def __init__(self, + precision=0, + n_files=0, n_statements=0, n_excluded=0, n_missing=0, + n_branches=0, n_partial_branches=0, n_missing_branches=0 + ): + assert 0 <= precision < 10 + self._precision = precision + self._near0 = 1.0 / 10**precision + self._near100 = 100.0 - self._near0 self.n_files = n_files self.n_statements = n_statements self.n_excluded = n_excluded @@ -178,18 +180,11 @@ class Numbers(SimpleReprMixin): def init_args(self): """Return a list for __init__(*args) to recreate this object.""" return [ + self._precision, self.n_files, self.n_statements, self.n_excluded, self.n_missing, self.n_branches, self.n_partial_branches, self.n_missing_branches, ] - @classmethod - def set_precision(cls, precision): - """Set the number of decimal places used to report percentages.""" - assert 0 <= precision < 10 - cls._precision = precision - cls._near0 = 1.0 / 10**precision - cls._near100 = 100.0 - cls._near0 - @property def n_executed(self): """Returns the number of executed statements.""" @@ -221,8 +216,7 @@ class Numbers(SimpleReprMixin): """ return self.display_covered(self.pc_covered) - @classmethod - def display_covered(cls, pc): + def display_covered(self, pc): """Return a displayable total percentage, as a string. Note that "0" is only returned when the value is truly zero, and "100" @@ -230,20 +224,19 @@ class Numbers(SimpleReprMixin): result in either "0" or "100". """ - if 0 < pc < cls._near0: - pc = cls._near0 - elif cls._near100 < pc < 100: - pc = cls._near100 + if 0 < pc < self._near0: + pc = self._near0 + elif self._near100 < pc < 100: + pc = self._near100 else: - pc = round(pc, cls._precision) - return "%.*f" % (cls._precision, pc) + pc = round(pc, self._precision) + return "%.*f" % (self._precision, pc) - @classmethod - def pc_str_width(cls): + def pc_str_width(self): """How many characters wide can pc_covered_str be?""" width = 3 # "100" - if cls._precision > 0: - width += 1 + cls._precision + if self._precision > 0: + width += 1 + self._precision return width @property @@ -254,7 +247,7 @@ class Numbers(SimpleReprMixin): return numerator, denominator def __add__(self, other): - nums = Numbers() + nums = Numbers(precision=self._precision) nums.n_files = self.n_files + other.n_files nums.n_statements = self.n_statements + other.n_statements nums.n_excluded = self.n_excluded + other.n_excluded diff --git a/coverage/summary.py b/coverage/summary.py index 0597a2aa..b7b172f8 100644 --- a/coverage/summary.py +++ b/coverage/summary.py @@ -21,7 +21,7 @@ class SummaryReporter: self.fr_analysis = [] self.skipped_count = 0 self.empty_count = 0 - self.total = Numbers() + self.total = Numbers(precision=self.config.precision) self.fmt_err = "%s %s: %s" def writeout(self, line): @@ -53,7 +53,7 @@ class SummaryReporter: if self.branches: header += " Branch BrPart" fmt_coverage += " %6d %6d" - width100 = Numbers.pc_str_width() + width100 = Numbers(precision=self.config.precision).pc_str_width() header += "%*s" % (width100+4, "Cover") fmt_coverage += "%%%ds%%%%" % (width100+3,) if self.config.show_missing: diff --git a/tests/test_results.py b/tests/test_results.py index fa239e92..02b1f963 100644 --- a/tests/test_results.py +++ b/tests/test_results.py @@ -43,30 +43,18 @@ class NumbersTest(CoverageTest): assert n3.n_missing == 28 assert round(abs(n3.pc_covered-86.666666666), 7) == 0 - def test_pc_covered_str(self): - # Numbers._precision is a global, which is bad. - Numbers.set_precision(0) - n0 = Numbers(n_files=1, n_statements=1000, n_missing=0) - n1 = Numbers(n_files=1, n_statements=1000, n_missing=1) - n999 = Numbers(n_files=1, n_statements=1000, n_missing=999) - n1000 = Numbers(n_files=1, n_statements=1000, n_missing=1000) - assert n0.pc_covered_str == "100" - assert n1.pc_covered_str == "99" - assert n999.pc_covered_str == "1" - assert n1000.pc_covered_str == "0" - - def test_pc_covered_str_precision(self): - # Numbers._precision is a global, which is bad. - Numbers.set_precision(1) - n0 = Numbers(n_files=1, n_statements=10000, n_missing=0) - n1 = Numbers(n_files=1, n_statements=10000, n_missing=1) - n9999 = Numbers(n_files=1, n_statements=10000, n_missing=9999) - n10000 = Numbers(n_files=1, n_statements=10000, n_missing=10000) - assert n0.pc_covered_str == "100.0" - assert n1.pc_covered_str == "99.9" - assert n9999.pc_covered_str == "0.1" - assert n10000.pc_covered_str == "0.0" - Numbers.set_precision(0) + @pytest.mark.parametrize("kwargs, res", [ + (dict(n_files=1, n_statements=1000, n_missing=0), "100"), + (dict(n_files=1, n_statements=1000, n_missing=1), "99"), + (dict(n_files=1, n_statements=1000, n_missing=999), "1"), + (dict(n_files=1, n_statements=1000, n_missing=1000), "0"), + (dict(precision=1, n_files=1, n_statements=10000, n_missing=0), "100.0"), + (dict(precision=1, n_files=1, n_statements=10000, n_missing=1), "99.9"), + (dict(precision=1, n_files=1, n_statements=10000, n_missing=9999), "0.1"), + (dict(precision=1, n_files=1, n_statements=10000, n_missing=10000), "0.0"), + ]) + def test_pc_covered_str(self, kwargs, res): + assert Numbers(**kwargs).pc_covered_str == res @pytest.mark.parametrize("prec, pc, res", [ (0, 47.87, "48"), @@ -75,10 +63,7 @@ class NumbersTest(CoverageTest): (2, 99.99995, "99.99"), ]) def test_display_covered(self, prec, pc, res): - # Numbers._precision is a global, which is bad. - Numbers.set_precision(prec) - assert Numbers.display_covered(pc) == res - Numbers.set_precision(0) + assert Numbers(precision=prec).display_covered(pc) == res def test_covered_ratio(self): n = Numbers(n_files=1, n_statements=200, n_missing=47) |