summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2022-12-08 07:07:16 -0500
committerNed Batchelder <ned@nedbatchelder.com>2022-12-08 07:40:23 -0500
commit71050957c68a7e1eaece7134be256535173e9b85 (patch)
treed1a3ddf4878599479f51a5d9af5058e5aa059e5d
parent4bca0478723434ab16582f94840cb38fa6878cd8 (diff)
downloadpython-coveragepy-git-nedbat/picklable.tar.gz
refactor: don't hold data so that Analysis can be picklednedbat/picklable
-rw-r--r--coverage/html.py2
-rw-r--r--coverage/lcovreport.py2
-rw-r--r--coverage/results.py44
-rw-r--r--tests/coveragetest.py8
-rw-r--r--tests/test_plugins.py4
5 files changed, 23 insertions, 37 deletions
diff --git a/coverage/html.py b/coverage/html.py
index 21b5189e..d2409b38 100644
--- a/coverage/html.py
+++ b/coverage/html.py
@@ -63,7 +63,7 @@ class HtmlDataGeneration:
"""Produce the data needed for one file's report."""
if self.has_arcs:
missing_branch_arcs = analysis.missing_branch_arcs()
- arcs_executed = analysis.arcs_executed()
+ arcs_executed = analysis.arcs_executed
if self.config.show_contexts:
contexts_by_lineno = analysis.data.contexts_by_lineno(analysis.filename)
diff --git a/coverage/lcovreport.py b/coverage/lcovreport.py
index 4dc73c29..9791daed 100644
--- a/coverage/lcovreport.py
+++ b/coverage/lcovreport.py
@@ -96,7 +96,7 @@ class LcovReporter:
outfile.write(f"BRDA:{line_number},{block_number},{branch_number},1\n")
# Summary of the branch coverage.
- if analysis.has_arcs():
+ if analysis.has_arcs:
branch_stats = analysis.branch_stats()
brf = sum(t for t, k in branch_stats.values())
brh = brf - sum(t - k for t, k in branch_stats.values())
diff --git a/coverage/results.py b/coverage/results.py
index 2c97a18f..8316b252 100644
--- a/coverage/results.py
+++ b/coverage/results.py
@@ -14,20 +14,23 @@ class Analysis:
"""The results of analyzing a FileReporter."""
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)
self.statements = self.file_reporter.lines()
self.excluded = self.file_reporter.excluded_lines()
# Identify missing statements.
- executed = self.data.lines(self.filename) or []
+ executed = data.lines(self.filename) or []
executed = self.file_reporter.translate_lines(executed)
self.executed = executed
self.missing = self.statements - self.executed
- if self.data.has_arcs():
- self._arc_possibilities = sorted(self.file_reporter.arcs())
+ self.has_arcs = data.has_arcs()
+ if self.has_arcs:
+ self.arc_possibilities = sorted(self.file_reporter.arcs())
+ arcs_executed = data.arcs(self.filename) or []
+ arcs_executed = self.file_reporter.translate_arcs(arcs_executed)
+ self.arcs_executed = sorted(arcs_executed)
self.exit_counts = self.file_reporter.exit_counts()
self.no_branch = self.file_reporter.no_branch_lines()
n_branches = self._total_branches()
@@ -35,7 +38,8 @@ class Analysis:
n_partial_branches = sum(len(v) for k,v in mba.items() if k not in self.missing)
n_missing_branches = sum(len(v) for k,v in mba.items())
else:
- self._arc_possibilities = []
+ self.arc_possibilities = []
+ self.arcs_executed = set()
self.exit_counts = {}
self.no_branch = set()
n_branches = n_partial_branches = n_missing_branches = 0
@@ -59,34 +63,18 @@ class Analysis:
If `branches` is true, includes the missing branch arcs also.
"""
- if branches and self.has_arcs():
+ if branches and self.has_arcs:
arcs = self.missing_branch_arcs().items()
else:
arcs = None
return format_lines(self.statements, self.missing, arcs=arcs)
- def has_arcs(self):
- """Were arcs measured in this result?"""
- return self.data.has_arcs()
-
- @contract(returns='list(tuple(int, int))')
- def arc_possibilities(self):
- """Returns a sorted list of the arcs in the code."""
- return self._arc_possibilities
-
- @contract(returns='list(tuple(int, int))')
- def arcs_executed(self):
- """Returns a sorted list of the arcs actually executed in the code."""
- executed = self.data.arcs(self.filename) or []
- executed = self.file_reporter.translate_arcs(executed)
- return sorted(executed)
-
@contract(returns='list(tuple(int, int))')
def arcs_missing(self):
"""Returns a sorted list of the un-executed arcs in the code."""
- possible = self.arc_possibilities()
- executed = self.arcs_executed()
+ possible = self.arc_possibilities
+ executed = self.arcs_executed
missing = (
p for p in possible
if p not in executed
@@ -98,16 +86,14 @@ class Analysis:
@contract(returns='list(tuple(int, int))')
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.
# Also, generators can somehow cause arcs from "enter" to "exit", so
# make sure we have at least one positive value.
unpredicted = (
- e for e in executed
- if e not in possible
+ e for e in self.arcs_executed
+ if e not in self.arc_possibilities
and e[0] != e[1]
and (e[0] > 0 or e[1] > 0)
)
@@ -143,7 +129,7 @@ class Analysis:
Returns {l1:[l2a,l2b,...], ...}
"""
- executed = self.arcs_executed()
+ executed = self.arcs_executed
branch_lines = set(self._branch_lines())
eba = collections.defaultdict(list)
for l1, l2 in executed:
diff --git a/tests/coveragetest.py b/tests/coveragetest.py
index 56e78853..cc5f26f0 100644
--- a/tests/coveragetest.py
+++ b/tests/coveragetest.py
@@ -199,12 +199,12 @@ class CoverageTest(
if arcs is not None:
# print("Possible arcs:")
# print(" expected:", arcs)
- # print(" actual:", analysis.arc_possibilities())
+ # print(" actual:", analysis.arc_possibilities)
# print("Executed:")
- # print(" actual:", sorted(set(analysis.arcs_executed())))
+ # print(" actual:", sorted(set(analysis.arcs_executed)))
# TODO: this would be nicer with pytest-check, once we can run that.
msg = (
- self._check_arcs(arcs, analysis.arc_possibilities(), "Possible") +
+ self._check_arcs(arcs, analysis.arc_possibilities, "Possible") +
self._check_arcs(arcs_missing, analysis.arcs_missing(), "Missing") +
self._check_arcs(arcs_unpredicted, analysis.arcs_unpredicted(), "Unpredicted")
)
@@ -465,7 +465,7 @@ class CoverageTest(
# ugh, unexposed methods??
filename = self.last_module_name + ".py"
fr = cov._get_file_reporter(filename)
- arcs_executed = cov._analyze(filename).arcs_executed()
+ arcs_executed = cov._analyze(filename).arcs_executed
return fr.missing_arc_description(start, end, arcs_executed)
diff --git a/tests/test_plugins.py b/tests/test_plugins.py
index cd446441..a01904b2 100644
--- a/tests/test_plugins.py
+++ b/tests/test_plugins.py
@@ -395,8 +395,8 @@ class GoodFileTracerTest(FileTracerTest):
analysis = cov._analyze("foo_7.html")
assert analysis.statements == {1, 2, 3, 4, 5, 6, 7}
# Plugins don't do branch coverage yet.
- assert analysis.has_arcs() is True
- assert analysis.arc_possibilities() == []
+ assert analysis.has_arcs is True
+ assert analysis.arc_possibilities == []
assert analysis.missing == {1, 2, 3, 6, 7}