summaryrefslogtreecommitdiff
path: root/coverage
diff options
context:
space:
mode:
Diffstat (limited to 'coverage')
-rw-r--r--coverage/config.py3
-rw-r--r--coverage/control.py19
-rw-r--r--coverage/results.py34
-rw-r--r--coverage/summary.py5
4 files changed, 48 insertions, 13 deletions
diff --git a/coverage/config.py b/coverage/config.py
index 7c22f64b..1f6a879f 100644
--- a/coverage/config.py
+++ b/coverage/config.py
@@ -27,6 +27,7 @@ class CoverageConfig(object):
self.ignore_errors = False
self.omit = None
self.include = None
+ self.precision = 0
# Defaults for [html]
self.html_dir = "htmlcov"
@@ -87,6 +88,8 @@ class CoverageConfig(object):
self.omit = self.get_list(cp, 'report', 'omit')
if cp.has_option('report', 'include'):
self.include = self.get_list(cp, 'report', 'include')
+ if cp.has_option('report', 'precision'):
+ self.precision = cp.getint('report', 'precision')
# [html]
if cp.has_option('html', 'directory'):
diff --git a/coverage/control.py b/coverage/control.py
index 59d237ea..7df608db 100644
--- a/coverage/control.py
+++ b/coverage/control.py
@@ -10,8 +10,8 @@ from coverage.config import CoverageConfig
from coverage.data import CoverageData
from coverage.files import FileLocator, TreeMatcher, FnmatchMatcher
from coverage.html import HtmlReporter
-from coverage.misc import bool_or_none
-from coverage.results import Analysis
+from coverage.misc import CoverageException, bool_or_none
+from coverage.results import Analysis, Numbers
from coverage.summary import SummaryReporter
from coverage.xmlreport import XmlReporter
@@ -76,7 +76,13 @@ class coverage(object):
if config_file:
if config_file is True:
config_file = ".coveragerc"
- self.config.from_file(config_file)
+ try:
+ self.config.from_file(config_file)
+ except ValueError:
+ _, err, _ = sys.exc_info()
+ raise CoverageException(
+ "Couldn't read config file %s: %s" % (config_file, err)
+ )
# 3: from environment variables:
self.config.from_environment('COVERAGE_OPTIONS')
@@ -163,8 +169,11 @@ class coverage(object):
# Only _harvest_data once per measurement cycle.
self._harvested = False
- # When tearing down the coverage object, modules can become None.
- # Saving the modules as object attributes avoids problems, but it is
+ # Set the reporting precision.
+ Numbers.set_precision(self.config.precision)
+
+ # When tearing down the coverage object, modules can become None.
+ # Saving the modules as object attributes avoids problems, but it is
# quite ad-hoc which modules need to be saved and which references
# need to use the object attributes.
self.socket = socket
diff --git a/coverage/results.py b/coverage/results.py
index a3bdec15..e6e39429 100644
--- a/coverage/results.py
+++ b/coverage/results.py
@@ -127,6 +127,12 @@ class Numbers(object):
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_missing_branches=0
):
@@ -137,6 +143,14 @@ class Numbers(object):
self.n_branches = n_branches
self.n_missing_branches = n_missing_branches
+ 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
+ set_precision = classmethod(set_precision)
+
def _get_n_executed(self):
"""Returns the number of executed statements."""
return self.n_statements - self.n_missing
@@ -165,15 +179,23 @@ class Numbers(object):
"""
pc = self.pc_covered
- if 0 < pc < 1:
- pc = 1.0
- elif 99 < pc < 100:
- pc = 99.0
+ if 0 < pc < self._near0:
+ pc = self._near0
+ elif self._near100 < pc < 100:
+ pc = self._near100
else:
- pc = round(pc)
- return "%.0f" % pc
+ pc = round(pc, self._precision)
+ return "%.*f" % (self._precision, pc)
pc_covered_str = property(_get_pc_covered_str)
+ def pc_str_width(cls):
+ """How many characters wide can pc_covered_str be?"""
+ width = 3 # "100"
+ if cls._precision > 0:
+ width += 1 + cls._precision
+ return width
+ pc_str_width = classmethod(pc_str_width)
+
def __add__(self, other):
nums = Numbers()
nums.n_files = self.n_files + other.n_files
diff --git a/coverage/summary.py b/coverage/summary.py
index 53c844d1..a1206af5 100644
--- a/coverage/summary.py
+++ b/coverage/summary.py
@@ -31,8 +31,9 @@ class SummaryReporter(Reporter):
if self.branches:
header += " Branch BrPart"
fmt_coverage += " %6d %6d"
- header += " Cover"
- fmt_coverage += " %5s%%"
+ width100 = Numbers.pc_str_width()
+ header += "%*s" % (width100+4, "Cover")
+ fmt_coverage += "%%%ds%%%%" % (width100+3,)
if self.show_missing:
header += " Missing"
fmt_coverage += " %s"