Skip to content

Commit

Permalink
wip: implicit path mapping during reporting. #1212
Browse files Browse the repository at this point in the history
  • Loading branch information
nedbat committed Nov 26, 2022
1 parent ff9839f commit 92d5fd0
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 13 deletions.
31 changes: 21 additions & 10 deletions coverage/control.py
Expand Up @@ -733,6 +733,18 @@ def save(self):
data = self.get_data()
data.write()

def _make_aliases(self):
"""Create a PathAliases from our configuration."""
aliases = PathAliases(
debugfn=(self._debug.write if self._debug.should("pathmap") else None),
relative=self.config.relative_files,
)
for paths in self.config.paths.values():
result = paths[0]
for pattern in paths[1:]:
aliases.add(pattern, result)
return aliases

def combine(self, data_paths=None, strict=False, keep=False):
"""Combine together a number of similarly-named coverage data files.
Expand Down Expand Up @@ -764,18 +776,9 @@ def combine(self, data_paths=None, strict=False, keep=False):
self._post_init()
self.get_data()

aliases = PathAliases(
debugfn=(self._debug.write if self._debug.should("pathmap") else None),
relative=self.config.relative_files,
)
for paths in self.config.paths.values():
result = paths[0]
for pattern in paths[1:]:
aliases.add(pattern, result)

combine_parallel_data(
self._data,
aliases=aliases,
aliases=self._make_aliases(),
data_paths=data_paths,
strict=strict,
keep=keep,
Expand Down Expand Up @@ -925,6 +928,13 @@ def _get_file_reporters(self, morfs=None):
file_reporters = [self._get_file_reporter(morf) for morf in morfs]
return file_reporters

def _prepare_data_for_reporting(self):
"""Re-map data before reporting, to get implicit 'combine' behavior."""
if self.config.paths:
mapped_data = CoverageData(warn=self._warn, debug=self._debug, no_disk=True)
mapped_data.update(self._data, aliases=self._make_aliases())
self._data = mapped_data

def report(
self,
morfs=None,
Expand Down Expand Up @@ -990,6 +1000,7 @@ def report(
The `format` parameter.
"""
self._prepare_data_for_reporting()
with override_config(
self,
ignore_errors=ignore_errors,
Expand Down
7 changes: 6 additions & 1 deletion coverage/sqldata.py
Expand Up @@ -648,7 +648,12 @@ def update(self, other_data, aliases=None):
"inner join file on file.id = line_bits.file_id " +
"inner join context on context.id = line_bits.context_id"
)
lines = {(files[path], context): numbits for (path, context, numbits) in cur}
lines = {}
for path, context, numbits in cur:
key = (files[path], context)
if key in lines:
numbits = numbits_union(lines[key], numbits)
lines[key] = numbits
cur.close()

# Get tracer data.
Expand Down
5 changes: 4 additions & 1 deletion tests/coveragetest.py
Expand Up @@ -219,11 +219,14 @@ def check_coverage(

return cov

def make_data_file(self, basename=None, suffix=None, lines=None, file_tracers=None):
def make_data_file(self, basename=None, suffix=None, lines=None, arcs=None, file_tracers=None):
"""Write some data into a coverage data file."""
data = coverage.CoverageData(basename=basename, suffix=suffix)
assert lines is None or arcs is None
if lines:
data.add_lines(lines)
if arcs:
data.add_arcs(arcs)
if file_tracers:
data.add_file_tracers(file_tracers)
data.write()
Expand Down
102 changes: 101 additions & 1 deletion tests/test_api.py
Expand Up @@ -23,7 +23,7 @@
from coverage.misc import import_local_file

from tests.coveragetest import CoverageTest, TESTS_DIR, UsingModulesMixin
from tests.helpers import assert_count_equal, assert_coverage_warnings
from tests.helpers import arcz_to_arcs, assert_count_equal, assert_coverage_warnings
from tests.helpers import change_dir, nice_file, os_sep

BAD_SQLITE_REGEX = r"file( is encrypted or)? is not a database"
Expand Down Expand Up @@ -1456,3 +1456,103 @@ def test_combine_parallel_data_keep(self):
# After combining, the .coverage file & the original combined file should still be there.
self.assert_exists(".coverage")
self.assert_file_count(".coverage.*", 2)


class ReportMapsPathsTest(CoverageTest):
"""Check that reporting implicitly maps paths."""

def make_files(self, data="lines", settings=False):
"""Create the test files we need for line coverage."""
src = """\
if VER == 1:
print("line 2")
if VER == 2:
print("line 4")
if VER == 3:
print("line 6")
"""
self.make_file("src/program.py", src)
self.make_file("ver1/program.py", src)
self.make_file("ver2/program.py", src)

if data == "line":
self.make_data_file(
lines={
abs_file("ver1/program.py"): [1, 2, 3, 5],
abs_file("ver2/program.py"): [1, 3, 4, 5],
}
)
else:
self.make_data_file(
arcs={
abs_file("ver1/program.py"): arcz_to_arcs(".1 12 23 35 5."),
abs_file("ver2/program.py"): arcz_to_arcs(".1 13 34 45 5."),
}
)

if settings:
self.make_file(".coveragerc", """\
[paths]
source =
src
ver1
ver2
""")

def test_map_paths_during_line_report_without_setting(self):
self.make_files(data="line")
cov = coverage.Coverage()
cov.load()
cov.report(show_missing=True)
expected = textwrap.dedent(os_sep("""\
Name Stmts Miss Cover Missing
-----------------------------------------------
ver1/program.py 6 2 67% 4, 6
ver2/program.py 6 2 67% 2, 6
-----------------------------------------------
TOTAL 12 4 67%
"""))
assert expected == self.stdout()

def test_map_paths_during_line_report(self):
self.make_files(data="line", settings=True)
cov = coverage.Coverage()
cov.load()
cov.report(show_missing=True)
expected = textwrap.dedent(os_sep("""\
Name Stmts Miss Cover Missing
----------------------------------------------
src/program.py 6 1 83% 6
----------------------------------------------
TOTAL 6 1 83%
"""))
assert expected == self.stdout()

def test_map_paths_during_branch_report_without_setting(self):
self.make_files(data="arcs")
cov = coverage.Coverage(branch=True)
cov.load()
cov.report(show_missing=True)
expected = textwrap.dedent(os_sep("""\
Name Stmts Miss Branch BrPart Cover Missing
-------------------------------------------------------------
ver1/program.py 6 2 6 3 58% 1->3, 4, 6
ver2/program.py 6 2 6 3 58% 2, 3->5, 6
-------------------------------------------------------------
TOTAL 12 4 12 6 58%
"""))
assert expected == self.stdout()

def test_map_paths_during_branch_report(self):
self.make_files(data="arcs", settings=True)
cov = coverage.Coverage(branch=True)
cov.load()
cov.report(show_missing=True)
expected = textwrap.dedent(os_sep("""\
Name Stmts Miss Branch BrPart Cover Missing
------------------------------------------------------------
src/program.py 6 1 6 1 83% 6
------------------------------------------------------------
TOTAL 6 1 6 1 83%
"""))
assert expected == self.stdout()

0 comments on commit 92d5fd0

Please sign in to comment.