summaryrefslogtreecommitdiff
path: root/coverage/inorout.py
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2021-10-10 20:21:19 -0400
committerNed Batchelder <ned@nedbatchelder.com>2021-10-10 20:44:45 -0400
commit9b54389d91c68b27913ded2898f3a03df7e8e90d (patch)
tree636cc18f20b610c56b959e71216927d89b64a2fe /coverage/inorout.py
parent27db7b4e9eb4a7f8115af207a21374fdd2e6d8c7 (diff)
downloadpython-coveragepy-git-9b54389d91c68b27913ded2898f3a03df7e8e90d.tar.gz
fix: make third-party detection work with namespace packages. #1231
Diffstat (limited to 'coverage/inorout.py')
-rw-r--r--coverage/inorout.py41
1 files changed, 32 insertions, 9 deletions
diff --git a/coverage/inorout.py b/coverage/inorout.py
index 496ced35..c90e3d59 100644
--- a/coverage/inorout.py
+++ b/coverage/inorout.py
@@ -107,17 +107,26 @@ def module_has_file(mod):
return os.path.exists(mod__file__)
-def file_for_module(modulename):
- """Find the file for `modulename`, or return None."""
+def file_and_path_for_module(modulename):
+ """Find the file and search path for `modulename`.
+
+ Returns:
+ filename: The filename of the module, or None.
+ path: A list (possibly empty) of directories to find submodules in.
+
+ """
filename = None
+ path = []
try:
spec = importlib.util.find_spec(modulename)
except ImportError:
pass
else:
if spec is not None:
- filename = spec.origin
- return filename
+ if spec.origin != "namespace":
+ filename = spec.origin
+ path = list(spec.submodule_search_locations or ())
+ return filename, path
def add_stdlib_paths(paths):
@@ -263,15 +272,29 @@ class InOrOut:
# third-party package.
for pkg in self.source_pkgs:
try:
- modfile = file_for_module(pkg)
- debug(f"Imported {pkg} as {modfile}")
+ modfile, path = file_and_path_for_module(pkg)
+ debug(f"Imported source package {pkg!r} as {modfile!r}")
except CoverageException as exc:
- debug(f"Couldn't import {pkg}: {exc}")
+ debug(f"Couldn't import source package {pkg!r}: {exc}")
continue
- if modfile and self.third_match.match(modfile):
- self.source_in_third = True
+ if modfile:
+ if self.third_match.match(modfile):
+ debug(
+ f"Source is in third-party because of source_pkg {pkg!r} at {modfile!r}"
+ )
+ self.source_in_third = True
+ 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}"
+ )
+ self.source_in_third = True
+
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
def should_trace(self, filename, frame=None):