summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--coverage/annotate.py6
-rw-r--r--coverage/control.py90
-rw-r--r--coverage/html.py16
-rw-r--r--coverage/report.py3
-rw-r--r--coverage/summary.py8
-rw-r--r--coverage/xmlreport.py10
6 files changed, 74 insertions, 59 deletions
diff --git a/coverage/annotate.py b/coverage/annotate.py
index 3130c001..2fa9d5cf 100644
--- a/coverage/annotate.py
+++ b/coverage/annotate.py
@@ -37,7 +37,7 @@ class AnnotateReporter(Reporter):
"""Run the report."""
self.report_files(self.annotate_file, morfs, directory, omit_prefixes)
- def annotate_file(self, cu, statements, excluded, missing):
+ def annotate_file(self, cu, analysis):
"""Annotate a single file.
`cu` is the CodeUnit for the file to annotate.
@@ -55,6 +55,10 @@ class AnnotateReporter(Reporter):
dest_file = filename + ",cover"
dest = open(dest_file, 'w')
+ statements = analysis.statements
+ missing = analysis.missing
+ excluded = analysis.excluded
+
lineno = 0
i = 0
j = 0
diff --git a/coverage/control.py b/coverage/control.py
index 275e21ed..0db77ec1 100644
--- a/coverage/control.py
+++ b/coverage/control.py
@@ -242,51 +242,16 @@ class coverage:
"""
code_unit = code_unit_factory(morf, self.file_locator)[0]
- st, ex, m, mf = self._analyze(code_unit)
- return code_unit.filename, st, ex, m, mf
+ analysis = self._analyze(code_unit)
+ return code_unit.filename, analysis.statements, analysis.excluded, analysis.missing, analysis.missing_formatted()
def _analyze(self, code_unit):
"""Analyze a single code unit.
- Returns a 4-tuple: (statements, excluded, missing, missing formatted).
+ Returns an `Analysis` object.
"""
- from coverage.parser import CodeParser
-
- filename = code_unit.filename
- ext = os.path.splitext(filename)[1]
- source = None
- if ext == '.py':
- if not os.path.exists(filename):
- source = self.file_locator.get_zip_data(filename)
- if not source:
- raise CoverageException(
- "No source for code '%s'." % code_unit.filename
- )
-
- parser = CodeParser(
- text=source, filename=filename, exclude=self.exclude_re
- )
- statements, excluded, line_map = parser.parse_source()
-
- # Identify missing statements.
- missing = []
- execed = self.data.executed_lines(filename)
- for line in statements:
- lines = line_map.get(line)
- if lines:
- for l in range(lines[0], lines[1]+1):
- if l in execed:
- break
- else:
- missing.append(line)
- else:
- if line not in execed:
- missing.append(line)
-
- return (
- statements, excluded, missing, format_lines(statements, missing)
- )
+ return Analysis(self, code_unit)
def report(self, morfs=None, show_missing=True, ignore_errors=False,
file=None, omit_prefixes=None): # pylint: disable-msg=W0622
@@ -357,3 +322,50 @@ class coverage:
]),
]
return info
+
+
+class Analysis:
+ """The results of analyzing a code unit."""
+
+ def __init__(self, cov, code_unit):
+ self.code_unit = code_unit
+
+ from coverage.parser import CodeParser
+
+ filename = code_unit.filename
+ ext = os.path.splitext(filename)[1]
+ source = None
+ if ext == '.py':
+ if not os.path.exists(filename):
+ source = cov.file_locator.get_zip_data(filename)
+ if not source:
+ raise CoverageException(
+ "No source for code '%s'." % code_unit.filename
+ )
+
+ parser = CodeParser(
+ text=source, filename=filename, exclude=cov.exclude_re
+ )
+ self.statements, self.excluded, line_map = parser.parse_source()
+
+ # Identify missing statements.
+ self.missing = []
+ execed = cov.data.executed_lines(filename)
+ for line in self.statements:
+ lines = line_map.get(line)
+ if lines:
+ for l in range(lines[0], lines[1]+1):
+ if l in execed:
+ break
+ else:
+ self.missing.append(line)
+ else:
+ if line not in execed:
+ self.missing.append(line)
+
+ def missing_formatted(self):
+ return format_lines(self.statements, self.missing)
+
+ #return (
+ # statements, excluded, missing, format_lines(statements, missing)
+ # )
diff --git a/coverage/html.py b/coverage/html.py
index f096c728..d5811317 100644
--- a/coverage/html.py
+++ b/coverage/html.py
@@ -82,15 +82,15 @@ class HtmlReporter(Reporter):
os.path.join(directory, "jquery-1.3.2.min.js")
)
- def html_file(self, cu, statements, excluded, missing):
+ def html_file(self, cu, analysis):
"""Generate an HTML file for one source file."""
source = cu.source_file().read().expandtabs(4)
source_lines = source.split("\n")
- n_stm = len(statements)
- n_exc = len(excluded)
- n_mis = len(missing)
+ n_stm = len(analysis.statements)
+ n_exc = len(analysis.excluded)
+ n_mis = len(analysis.missing)
n_run = n_stm - n_mis
if n_stm > 0:
pc_cov = 100.0 * n_run / n_stm
@@ -114,13 +114,13 @@ class HtmlReporter(Reporter):
if part == '\n':
line_class = ""
- if lineno in statements:
+ if lineno in analysis.statements:
line_class += " stm"
- if lineno not in missing and lineno not in excluded:
+ if lineno not in analysis.missing and lineno not in analysis.excluded:
line_class += c_run
- if lineno in excluded:
+ if lineno in analysis.excluded:
line_class += c_exc
- if lineno in missing:
+ if lineno in analysis.missing:
line_class += c_mis
lineinfo = {
diff --git a/coverage/report.py b/coverage/report.py
index 0ae4ce64..8b069d7a 100644
--- a/coverage/report.py
+++ b/coverage/report.py
@@ -50,8 +50,7 @@ class Reporter(object):
for cu in self.code_units:
try:
- statements, excluded, missing, _ = self.coverage._analyze(cu)
- report_fn(cu, statements, excluded, missing)
+ report_fn(cu, self.coverage._analyze(cu))
except KeyboardInterrupt:
raise
except:
diff --git a/coverage/summary.py b/coverage/summary.py
index 916b41e7..989256fc 100644
--- a/coverage/summary.py
+++ b/coverage/summary.py
@@ -41,16 +41,16 @@ class SummaryReporter(Reporter):
for cu in self.code_units:
try:
- statements, _, missing, readable = self.coverage._analyze(cu)
- n = len(statements)
- m = n - len(missing)
+ analysis = self.coverage._analyze(cu)
+ n = len(analysis.statements)
+ m = n - len(analysis.missing)
if n > 0:
pc = 100.0 * m / n
else:
pc = 100.0
args = (cu.name, n, m, pc)
if self.show_missing:
- args = args + (readable,)
+ args = args + (analysis.missing_formatted(),)
outfile.write(fmt_coverage % args)
total_units += 1
total_statements = total_statements + n
diff --git a/coverage/xmlreport.py b/coverage/xmlreport.py
index 9898e7e1..155f7bf5 100644
--- a/coverage/xmlreport.py
+++ b/coverage/xmlreport.py
@@ -80,7 +80,7 @@ class XmlReporter(Reporter):
# Use the DOM to write the output file.
outfile.write(self.xml_out.toprettyxml())
- def xml_file(self, cu, statements, excluded_unused, missing):
+ def xml_file(self, cu, analysis):
"""Add to the XML report for a single file."""
# Create the 'lines' and 'package' XML elements, which
@@ -101,14 +101,14 @@ class XmlReporter(Reporter):
xclass.setAttribute("complexity", "0.0")
# For each statement, create an XML 'line' element.
- for line in statements:
+ for line in analysis.statements:
l = self.xml_out.createElement("line")
l.setAttribute("number", str(line))
# Q: can we get info about the number of times
# a statement is executed? If so, that should be
# recorded here.
- l.setAttribute("hits", str(int(not line in missing)))
+ l.setAttribute("hits", str(int(not line in analysis.missing)))
# Q: can we get info about whether this statement
# is a branch? If so, that data should be
@@ -116,8 +116,8 @@ class XmlReporter(Reporter):
#l.setAttribute("branch", "false")
xlines.appendChild(l)
- class_lines = 1.0 * len(statements)
- class_hits = class_lines - len(missing)
+ class_lines = 1.0 * len(analysis.statements)
+ class_hits = class_lines - len(analysis.missing)
class_branches = 0.0
class_branch_hits = 0.0