summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2009-11-02 10:25:55 -0500
committerNed Batchelder <ned@nedbatchelder.com>2009-11-02 10:25:55 -0500
commit467eb680940b8653667751f4232a3d46f61d8350 (patch)
treedf15a42ada5e5d078db2293e7a8e9d17e7d66a99
parentbccde1765897a3881eaa5cff804464f71057826e (diff)
downloadpython-coveragepy-git-467eb680940b8653667751f4232a3d46f61d8350.tar.gz
Factor out Analysis and Numbers into their own file: imports were getting circular.
-rw-r--r--coverage/control.py145
-rw-r--r--coverage/results.py145
-rw-r--r--coverage/summary.py2
3 files changed, 148 insertions, 144 deletions
diff --git a/coverage/control.py b/coverage/control.py
index 8a3198a7..a9fe7b9a 100644
--- a/coverage/control.py
+++ b/coverage/control.py
@@ -3,14 +3,13 @@
import os, socket
from coverage.annotate import AnnotateReporter
-from coverage.backward import set, string_class # pylint: disable-msg=W0622
-from coverage.backward import sorted # pylint: disable-msg=W0622
+from coverage.backward import string_class # pylint: disable-msg=W0622
from coverage.codeunit import code_unit_factory, CodeUnit
from coverage.collector import Collector
from coverage.data import CoverageData
from coverage.files import FileLocator
from coverage.html import HtmlReporter
-from coverage.misc import format_lines, NoSource
+from coverage.results import Analysis
from coverage.summary import SummaryReporter
from coverage.xmlreport import XmlReporter
@@ -331,143 +330,3 @@ class coverage(object):
]),
]
return info
-
-
-class Analysis(object):
- """The results of analyzing a code unit."""
-
- def __init__(self, cov, code_unit):
- self.coverage = cov
- self.code_unit = code_unit
-
- from coverage.parser import CodeParser
-
- self.filename = self.code_unit.filename
- ext = os.path.splitext(self.filename)[1]
- source = None
- if ext == '.py':
- if not os.path.exists(self.filename):
- source = self.coverage.file_locator.get_zip_data(self.filename)
- if not source:
- raise NoSource("No source for code: %r" % self.filename)
-
- self.parser = CodeParser(
- text=source, filename=self.filename,
- exclude=self.coverage.exclude_re
- )
- self.statements, self.excluded = self.parser.parse_source()
-
- # Identify missing statements.
- self.missing = []
- self.executed = self.coverage.data.executed_lines(self.filename)
- exec1 = self.parser.first_lines(self.executed)
- self.missing = sorted(set(self.statements) - set(exec1))
-
- self.numbers = Numbers()
- self.numbers.n_files = 1
- self.numbers.n_statements = len(self.statements)
- self.numbers.n_excluded = len(self.excluded)
- self.numbers.n_missing = len(self.missing)
-
- def missing_formatted(self):
- """The missing line numbers, formatted nicely.
-
- Returns a string like "1-2, 5-11, 13-14".
-
- """
- return format_lines(self.statements, self.missing)
-
- def has_arcs(self):
- """Were arcs measured in this result?"""
- return self.coverage.data.has_arcs()
-
- def arc_possibilities(self):
- """Returns a sorted list of the arcs in the code."""
- return self.parser.arcs()
-
- def arcs_executed(self):
- """Returns a sorted list of the arcs actually executed in the code."""
- executed = self.coverage.data.executed_arcs(self.filename)
- m2fl = self.parser.first_line
- executed = [(m2fl(l1), m2fl(l2)) for (l1,l2) in executed]
- return sorted(executed)
-
- def arcs_missing(self):
- """Returns a sorted list of the arcs in the code not executed."""
- possible = self.arc_possibilities()
- executed = self.arcs_executed()
- missing = [p for p in possible if p not in executed]
- return sorted(missing)
-
- def arcs_unpredicted(self):
- """Returns a sorted list of the executed arcs missing from the code."""
- possible = self.arc_possibilities()
- executed = self.arcs_executed()
- # Exclude arcs here which connect a line to itself. They can occur
- # in executed data in some cases. This is where they can cause
- # trouble, and here is where it's the least burden to remove them.
- unpredicted = [
- e for e in executed
- if e not in possible and e[0] != e[1]
- ]
- return sorted(unpredicted)
-
- def branch_lines(self):
- """Returns lines that have more than one exit."""
- exit_counts = {}
- for l1,l2 in self.arc_possibilities():
- if l1 not in exit_counts:
- exit_counts[l1] = 0
- exit_counts[l1] += 1
-
- return [l1 for l1,count in exit_counts.items() if count > 1]
-
- def missing_branch_arcs(self):
- """Return arcs that weren't executed from branch lines.
-
- Returns {l1:[l2a,l2b,...], ...}
-
- """
- missing = self.arcs_missing()
- branch_lines = set(self.branch_lines())
- mba = {}
- for l1, l2 in missing:
- if l1 in branch_lines:
- if l1 not in mba:
- mba[l1] = []
- mba[l1].append(l2)
- return mba
-
-
-class Numbers(object):
- """The numerical results of measuring coverage.
-
- This holds the basic statistics from `Analysis`, and is used to roll
- up statistics across files.
-
- """
- def __init__(self):
- self.n_files = 0
- self.n_statements = 0
- self.n_excluded = 0
- self.n_missing = 0
-
- def _get_n_run(self):
- return self.n_statements - self.n_missing
- n_run = property(_get_n_run)
-
- def _get_percent_covered(self):
- """Returns a single percentage value for coverage."""
- if self.n_statements > 0:
- pc_cov = 100.0 * self.n_run / self.n_statements
- else:
- pc_cov = 100.0
- return pc_cov
- percent_covered = property(_get_percent_covered)
-
- def __iadd__(self, other):
- self.n_files += other.n_files
- self.n_statements += other.n_statements
- self.n_excluded += other.n_excluded
- self.n_missing += other.n_missing
- return self
diff --git a/coverage/results.py b/coverage/results.py
new file mode 100644
index 00000000..41102595
--- /dev/null
+++ b/coverage/results.py
@@ -0,0 +1,145 @@
+"""Results of coverage measurement."""
+
+import os
+
+from coverage.backward import set, sorted # pylint: disable-msg=W0622
+from coverage.misc import format_lines, NoSource
+from coverage.parser import CodeParser
+
+
+class Analysis(object):
+ """The results of analyzing a code unit."""
+
+ def __init__(self, cov, code_unit):
+ self.coverage = cov
+ self.code_unit = code_unit
+
+ self.filename = self.code_unit.filename
+ ext = os.path.splitext(self.filename)[1]
+ source = None
+ if ext == '.py':
+ if not os.path.exists(self.filename):
+ source = self.coverage.file_locator.get_zip_data(self.filename)
+ if not source:
+ raise NoSource("No source for code: %r" % self.filename)
+
+ self.parser = CodeParser(
+ text=source, filename=self.filename,
+ exclude=self.coverage.exclude_re
+ )
+ self.statements, self.excluded = self.parser.parse_source()
+
+ # Identify missing statements.
+ self.missing = []
+ self.executed = self.coverage.data.executed_lines(self.filename)
+ exec1 = self.parser.first_lines(self.executed)
+ self.missing = sorted(set(self.statements) - set(exec1))
+
+ self.numbers = Numbers()
+ self.numbers.n_files = 1
+ self.numbers.n_statements = len(self.statements)
+ self.numbers.n_excluded = len(self.excluded)
+ self.numbers.n_missing = len(self.missing)
+
+ def missing_formatted(self):
+ """The missing line numbers, formatted nicely.
+
+ Returns a string like "1-2, 5-11, 13-14".
+
+ """
+ return format_lines(self.statements, self.missing)
+
+ def has_arcs(self):
+ """Were arcs measured in this result?"""
+ return self.coverage.data.has_arcs()
+
+ def arc_possibilities(self):
+ """Returns a sorted list of the arcs in the code."""
+ return self.parser.arcs()
+
+ def arcs_executed(self):
+ """Returns a sorted list of the arcs actually executed in the code."""
+ executed = self.coverage.data.executed_arcs(self.filename)
+ m2fl = self.parser.first_line
+ executed = [(m2fl(l1), m2fl(l2)) for (l1,l2) in executed]
+ return sorted(executed)
+
+ def arcs_missing(self):
+ """Returns a sorted list of the arcs in the code not executed."""
+ possible = self.arc_possibilities()
+ executed = self.arcs_executed()
+ missing = [p for p in possible if p not in executed]
+ return sorted(missing)
+
+ def arcs_unpredicted(self):
+ """Returns a sorted list of the executed arcs missing from the code."""
+ possible = self.arc_possibilities()
+ executed = self.arcs_executed()
+ # Exclude arcs here which connect a line to itself. They can occur
+ # in executed data in some cases. This is where they can cause
+ # trouble, and here is where it's the least burden to remove them.
+ unpredicted = [
+ e for e in executed
+ if e not in possible and e[0] != e[1]
+ ]
+ return sorted(unpredicted)
+
+ def branch_lines(self):
+ """Returns lines that have more than one exit."""
+ exit_counts = {}
+ for l1,l2 in self.arc_possibilities():
+ if l1 not in exit_counts:
+ exit_counts[l1] = 0
+ exit_counts[l1] += 1
+
+ return [l1 for l1,count in exit_counts.items() if count > 1]
+
+ def missing_branch_arcs(self):
+ """Return arcs that weren't executed from branch lines.
+
+ Returns {l1:[l2a,l2b,...], ...}
+
+ """
+ missing = self.arcs_missing()
+ branch_lines = set(self.branch_lines())
+ mba = {}
+ for l1, l2 in missing:
+ if l1 in branch_lines:
+ if l1 not in mba:
+ mba[l1] = []
+ mba[l1].append(l2)
+ return mba
+
+
+class Numbers(object):
+ """The numerical results of measuring coverage.
+
+ This holds the basic statistics from `Analysis`, and is used to roll
+ up statistics across files.
+
+ """
+ def __init__(self):
+ self.n_files = 0
+ self.n_statements = 0
+ self.n_excluded = 0
+ self.n_missing = 0
+
+ def _get_n_run(self):
+ return self.n_statements - self.n_missing
+ n_run = property(_get_n_run)
+
+ def _get_percent_covered(self):
+ """Returns a single percentage value for coverage."""
+ if self.n_statements > 0:
+ pc_cov = 100.0 * self.n_run / self.n_statements
+ else:
+ pc_cov = 100.0
+ return pc_cov
+ percent_covered = property(_get_percent_covered)
+
+ def __iadd__(self, other):
+ self.n_files += other.n_files
+ self.n_statements += other.n_statements
+ self.n_excluded += other.n_excluded
+ self.n_missing += other.n_missing
+ return self
diff --git a/coverage/summary.py b/coverage/summary.py
index c0421986..c1440ec0 100644
--- a/coverage/summary.py
+++ b/coverage/summary.py
@@ -3,6 +3,7 @@
import sys
from coverage.report import Reporter
+from coverage.results import Numbers
class SummaryReporter(Reporter):
@@ -15,7 +16,6 @@ class SummaryReporter(Reporter):
def report(self, morfs, omit_prefixes=None, outfile=None):
"""Writes a report summarizing coverage statistics per module."""
- from coverage.control import Numbers
self.find_code_units(morfs, omit_prefixes)
# Prepare the formatting strings