Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: don’t measure all third-party packages if source is in third-party location #1560

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
25 changes: 13 additions & 12 deletions coverage/inorout.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ def _debug(msg: str) -> None:
# Check if the source we want to measure has been installed as a
# third-party package.
# Is the source inside a third-party area?
self.source_in_third = False
self.source_in_third_paths = set()
with sys_modules_saved():
for pkg in self.source_pkgs:
try:
Expand All @@ -274,22 +274,23 @@ def _debug(msg: str) -> None:
if modfile:
if self.third_match.match(modfile):
_debug(
f"Source is in third-party because of source_pkg {pkg!r} at {modfile!r}"
f"Source in third-party: source_pkg {pkg!r} at {modfile!r}"
)
self.source_in_third = True
self.source_in_third_paths.add(canonical_path(source_for_file(modfile)))
else:
for pathdir in path:
if self.third_match.match(pathdir):
_debug(
f"Source is in third-party because of {pkg!r} path directory " +
f"at {pathdir!r}"
f"Source in third-party: {pkg!r} path directory at {pathdir!r}"
)
self.source_in_third = True
self.source_in_third_paths.add(pathdir)

for src in self.source:
if self.third_match.match(src):
_debug(f"Source is in third-party because of source directory {src!r}")
self.source_in_third = True
_debug(f"Source in third-party: source directory {src!r}")
self.source_in_third_paths.add(src)
self.source_in_third_match = TreeMatcher(self.source_in_third_paths, "source_in_third")
_debug(f"Source in third-party matching: {self.source_in_third_match}")

self.plugins: Plugins
self.disp_class: Type[TFileDisposition] = FileDisposition
Expand Down Expand Up @@ -419,9 +420,8 @@ def check_include_omit_etc(self, filename: str, frame: Optional[FrameType]) -> O
ok = True
if not ok:
return extra + "falls outside the --source spec"
if not self.source_in_third:
if self.third_match.match(filename):
return "inside --source, but is third-party"
if self.third_match.match(filename) and not self.source_in_third_match.match(filename):
return "inside --source, but is third-party"
elif self.include_match:
if not self.include_match.match(filename):
return "falls outside the --include trees"
Expand Down Expand Up @@ -576,12 +576,13 @@ def sys_info(self) -> Iterable[Tuple[str, Any]]:
("coverage_paths", self.cover_paths),
("stdlib_paths", self.pylib_paths),
("third_party_paths", self.third_paths),
("source_in_third_party_paths", self.source_in_third_paths),
]

matcher_names = [
'source_match', 'source_pkgs_match',
'include_match', 'omit_match',
'cover_match', 'pylib_match', 'third_match',
'cover_match', 'pylib_match', 'third_match', 'source_in_third_match',
]

for matcher_name in matcher_names:
Expand Down
26 changes: 23 additions & 3 deletions tests/test_venv.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,28 @@ def get_trace_output(self) -> str:
with open("debug_out.txt") as f:
return f.read()

def test_third_party_venv_isnt_measured(self, coverage_command: str) -> None:
out = run_in_venv(coverage_command + " run --source=. myproduct.py")
@pytest.mark.parametrize('install_source_in_venv', [True, False])
def test_third_party_venv_isnt_measured(
self, coverage_command: str, install_source_in_venv: bool
) -> None:
if install_source_in_venv:
make_file("setup.py", """\
import setuptools
setuptools.setup(
name="myproduct",
py_modules = ["myproduct"],
)
""")
try:
run_in_venv("python -m pip install .")
finally:
shutil.rmtree("build")
shutil.rmtree("myproduct.egg-info")
# Ensure that coverage doesn't run the non-installed module.
os.remove('myproduct.py')
out = run_in_venv(coverage_command + " run --source=.,myproduct -m myproduct")
else:
out = run_in_venv(coverage_command + " run --source=. myproduct.py")
# In particular, this warning doesn't appear:
# Already imported a file that will be measured: .../coverage/__main__.py
assert out == self.expected_stdout
Expand All @@ -213,7 +233,7 @@ def test_third_party_venv_isnt_measured(self, coverage_command: str) -> None:
)
assert re_lines(r"^Tracing .*\bmyproduct.py", debug_out)
assert re_lines(
r"^Not tracing .*\bcolorsys.py': falls outside the --source spec",
r"^Not tracing .*\bcolorsys.py': (module 'colorsys' |)?falls outside the --source spec",
debug_out,
)

Expand Down