Skip to content

Commit 92d5fd0

Browse files
committed
wip: implicit path mapping during reporting. #1212
1 parent ff9839f commit 92d5fd0

File tree

4 files changed

+132
-13
lines changed

4 files changed

+132
-13
lines changed

coverage/control.py

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,18 @@ def save(self):
733733
data = self.get_data()
734734
data.write()
735735

736+
def _make_aliases(self):
737+
"""Create a PathAliases from our configuration."""
738+
aliases = PathAliases(
739+
debugfn=(self._debug.write if self._debug.should("pathmap") else None),
740+
relative=self.config.relative_files,
741+
)
742+
for paths in self.config.paths.values():
743+
result = paths[0]
744+
for pattern in paths[1:]:
745+
aliases.add(pattern, result)
746+
return aliases
747+
736748
def combine(self, data_paths=None, strict=False, keep=False):
737749
"""Combine together a number of similarly-named coverage data files.
738750
@@ -764,18 +776,9 @@ def combine(self, data_paths=None, strict=False, keep=False):
764776
self._post_init()
765777
self.get_data()
766778

767-
aliases = PathAliases(
768-
debugfn=(self._debug.write if self._debug.should("pathmap") else None),
769-
relative=self.config.relative_files,
770-
)
771-
for paths in self.config.paths.values():
772-
result = paths[0]
773-
for pattern in paths[1:]:
774-
aliases.add(pattern, result)
775-
776779
combine_parallel_data(
777780
self._data,
778-
aliases=aliases,
781+
aliases=self._make_aliases(),
779782
data_paths=data_paths,
780783
strict=strict,
781784
keep=keep,
@@ -925,6 +928,13 @@ def _get_file_reporters(self, morfs=None):
925928
file_reporters = [self._get_file_reporter(morf) for morf in morfs]
926929
return file_reporters
927930

931+
def _prepare_data_for_reporting(self):
932+
"""Re-map data before reporting, to get implicit 'combine' behavior."""
933+
if self.config.paths:
934+
mapped_data = CoverageData(warn=self._warn, debug=self._debug, no_disk=True)
935+
mapped_data.update(self._data, aliases=self._make_aliases())
936+
self._data = mapped_data
937+
928938
def report(
929939
self,
930940
morfs=None,
@@ -990,6 +1000,7 @@ def report(
9901000
The `format` parameter.
9911001
9921002
"""
1003+
self._prepare_data_for_reporting()
9931004
with override_config(
9941005
self,
9951006
ignore_errors=ignore_errors,

coverage/sqldata.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -648,7 +648,12 @@ def update(self, other_data, aliases=None):
648648
"inner join file on file.id = line_bits.file_id " +
649649
"inner join context on context.id = line_bits.context_id"
650650
)
651-
lines = {(files[path], context): numbits for (path, context, numbits) in cur}
651+
lines = {}
652+
for path, context, numbits in cur:
653+
key = (files[path], context)
654+
if key in lines:
655+
numbits = numbits_union(lines[key], numbits)
656+
lines[key] = numbits
652657
cur.close()
653658

654659
# Get tracer data.

tests/coveragetest.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,11 +219,14 @@ def check_coverage(
219219

220220
return cov
221221

222-
def make_data_file(self, basename=None, suffix=None, lines=None, file_tracers=None):
222+
def make_data_file(self, basename=None, suffix=None, lines=None, arcs=None, file_tracers=None):
223223
"""Write some data into a coverage data file."""
224224
data = coverage.CoverageData(basename=basename, suffix=suffix)
225+
assert lines is None or arcs is None
225226
if lines:
226227
data.add_lines(lines)
228+
if arcs:
229+
data.add_arcs(arcs)
227230
if file_tracers:
228231
data.add_file_tracers(file_tracers)
229232
data.write()

tests/test_api.py

Lines changed: 101 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
from coverage.misc import import_local_file
2424

2525
from tests.coveragetest import CoverageTest, TESTS_DIR, UsingModulesMixin
26-
from tests.helpers import assert_count_equal, assert_coverage_warnings
26+
from tests.helpers import arcz_to_arcs, assert_count_equal, assert_coverage_warnings
2727
from tests.helpers import change_dir, nice_file, os_sep
2828

2929
BAD_SQLITE_REGEX = r"file( is encrypted or)? is not a database"
@@ -1456,3 +1456,103 @@ def test_combine_parallel_data_keep(self):
14561456
# After combining, the .coverage file & the original combined file should still be there.
14571457
self.assert_exists(".coverage")
14581458
self.assert_file_count(".coverage.*", 2)
1459+
1460+
1461+
class ReportMapsPathsTest(CoverageTest):
1462+
"""Check that reporting implicitly maps paths."""
1463+
1464+
def make_files(self, data="lines", settings=False):
1465+
"""Create the test files we need for line coverage."""
1466+
src = """\
1467+
if VER == 1:
1468+
print("line 2")
1469+
if VER == 2:
1470+
print("line 4")
1471+
if VER == 3:
1472+
print("line 6")
1473+
"""
1474+
self.make_file("src/program.py", src)
1475+
self.make_file("ver1/program.py", src)
1476+
self.make_file("ver2/program.py", src)
1477+
1478+
if data == "line":
1479+
self.make_data_file(
1480+
lines={
1481+
abs_file("ver1/program.py"): [1, 2, 3, 5],
1482+
abs_file("ver2/program.py"): [1, 3, 4, 5],
1483+
}
1484+
)
1485+
else:
1486+
self.make_data_file(
1487+
arcs={
1488+
abs_file("ver1/program.py"): arcz_to_arcs(".1 12 23 35 5."),
1489+
abs_file("ver2/program.py"): arcz_to_arcs(".1 13 34 45 5."),
1490+
}
1491+
)
1492+
1493+
if settings:
1494+
self.make_file(".coveragerc", """\
1495+
[paths]
1496+
source =
1497+
src
1498+
ver1
1499+
ver2
1500+
""")
1501+
1502+
def test_map_paths_during_line_report_without_setting(self):
1503+
self.make_files(data="line")
1504+
cov = coverage.Coverage()
1505+
cov.load()
1506+
cov.report(show_missing=True)
1507+
expected = textwrap.dedent(os_sep("""\
1508+
Name Stmts Miss Cover Missing
1509+
-----------------------------------------------
1510+
ver1/program.py 6 2 67% 4, 6
1511+
ver2/program.py 6 2 67% 2, 6
1512+
-----------------------------------------------
1513+
TOTAL 12 4 67%
1514+
"""))
1515+
assert expected == self.stdout()
1516+
1517+
def test_map_paths_during_line_report(self):
1518+
self.make_files(data="line", settings=True)
1519+
cov = coverage.Coverage()
1520+
cov.load()
1521+
cov.report(show_missing=True)
1522+
expected = textwrap.dedent(os_sep("""\
1523+
Name Stmts Miss Cover Missing
1524+
----------------------------------------------
1525+
src/program.py 6 1 83% 6
1526+
----------------------------------------------
1527+
TOTAL 6 1 83%
1528+
"""))
1529+
assert expected == self.stdout()
1530+
1531+
def test_map_paths_during_branch_report_without_setting(self):
1532+
self.make_files(data="arcs")
1533+
cov = coverage.Coverage(branch=True)
1534+
cov.load()
1535+
cov.report(show_missing=True)
1536+
expected = textwrap.dedent(os_sep("""\
1537+
Name Stmts Miss Branch BrPart Cover Missing
1538+
-------------------------------------------------------------
1539+
ver1/program.py 6 2 6 3 58% 1->3, 4, 6
1540+
ver2/program.py 6 2 6 3 58% 2, 3->5, 6
1541+
-------------------------------------------------------------
1542+
TOTAL 12 4 12 6 58%
1543+
"""))
1544+
assert expected == self.stdout()
1545+
1546+
def test_map_paths_during_branch_report(self):
1547+
self.make_files(data="arcs", settings=True)
1548+
cov = coverage.Coverage(branch=True)
1549+
cov.load()
1550+
cov.report(show_missing=True)
1551+
expected = textwrap.dedent(os_sep("""\
1552+
Name Stmts Miss Branch BrPart Cover Missing
1553+
------------------------------------------------------------
1554+
src/program.py 6 1 6 1 83% 6
1555+
------------------------------------------------------------
1556+
TOTAL 6 1 6 1 83%
1557+
"""))
1558+
assert expected == self.stdout()

0 commit comments

Comments
 (0)