summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2021-10-31 08:37:15 -0400
committerNed Batchelder <ned@nedbatchelder.com>2021-10-31 09:17:11 -0400
commit1a6844ae32781f2117d46363ece697d509f6935d (patch)
tree89709950f96dd70091b1f0896cc91ef3b8c2f0fa
parent7589066bfe18bd6f26200895cc2e569128fafead (diff)
downloadpython-coveragepy-git-1a6844ae32781f2117d46363ece697d509f6935d.tar.gz
fix: don't warn about already imported files for namespace packages #888
Ignore namespace packages in the already-imported check. #888
-rw-r--r--CHANGES.rst10
-rw-r--r--coverage/inorout.py4
-rw-r--r--lab/treetopy.sh6
-rw-r--r--tests/test_venv.py54
4 files changed, 70 insertions, 4 deletions
diff --git a/CHANGES.rst b/CHANGES.rst
index 7e9c6938..856731d0 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -22,10 +22,16 @@ This list is detailed and covers changes in each pre-release version.
Unreleased
----------
-- Fix: the sticky header on the HTML report didn't work unless you had branch
- coverage enabled. This is now fixed, the sticky header works for everyone.
+- Fix: The sticky header on the HTML report didn't work unless you had branch
+ coverage enabled. This is now fixed: the sticky header works for everyone.
(Do people still use coverage without branch measurement!? j/k)
+- Fix: When using explicitly declared namespace packages, the "already imported
+ a file that will be measured" warning would be issued (`issue 888`_). This
+ is now fixed.
+
+.. _issue 888: https://github.com/nedbat/coveragepy/issues/888
+
.. _changes_61:
diff --git a/coverage/inorout.py b/coverage/inorout.py
index 3bc7e54e..8badf4f7 100644
--- a/coverage/inorout.py
+++ b/coverage/inorout.py
@@ -479,6 +479,10 @@ class InOrOut:
if filename in warned:
continue
+ if len(getattr(mod, "__path__", ())) > 1:
+ # A namespace package, which confuses this code, so ignore it.
+ continue
+
disp = self.should_trace(filename)
if disp.has_dynamic_filename:
# A plugin with dynamic filenames: the Python file
diff --git a/lab/treetopy.sh b/lab/treetopy.sh
new file mode 100644
index 00000000..2dcf1cac
--- /dev/null
+++ b/lab/treetopy.sh
@@ -0,0 +1,6 @@
+# Turn a tree of Python files into a series of make_file calls.
+for f in **/*.py; do
+ echo 'make_file("'$1$f'", """\\'
+ sed -e 's/^/ /' <$f
+ echo ' """)'
+done
diff --git a/tests/test_venv.py b/tests/test_venv.py
index e6610337..c9c20497 100644
--- a/tests/test_venv.py
+++ b/tests/test_venv.py
@@ -84,7 +84,6 @@ def venv_world_fixture(tmp_path_factory):
def sixth(x):
return 6 * x
""")
- # The setup.py to install everything.
make_file("another_pkg/setup.py", """\
import setuptools
setuptools.setup(
@@ -93,9 +92,52 @@ def venv_world_fixture(tmp_path_factory):
)
""")
+ # Bug888 code.
+ make_file("bug888/app/setup.py", """\
+ from setuptools import setup
+ setup(
+ name='testcov',
+ packages=['testcov'],
+ namespace_packages=['testcov'],
+ )
+ """)
+ make_file("bug888/app/testcov/__init__.py", """\
+ try: # pragma: no cover
+ __import__('pkg_resources').declare_namespace(__name__)
+ except ImportError: # pragma: no cover
+ from pkgutil import extend_path
+ __path__ = extend_path(__path__, __name__)
+ """)
+ make_file("bug888/app/testcov/main.py", """\
+ import pkg_resources
+ for entry_point in pkg_resources.iter_entry_points('plugins'):
+ entry_point.load()()
+ """)
+ make_file("bug888/plugin/setup.py", """\
+ from setuptools import setup
+ setup(
+ name='testcov-plugin',
+ packages=['testcov'],
+ namespace_packages=['testcov'],
+ entry_points={'plugins': ['testp = testcov.plugin:testp']},
+ )
+ """)
+ make_file("bug888/plugin/testcov/__init__.py", """\
+ try: # pragma: no cover
+ __import__('pkg_resources').declare_namespace(__name__)
+ except ImportError: # pragma: no cover
+ from pkgutil import extend_path
+ __path__ = extend_path(__path__, __name__)
+ """)
+ make_file("bug888/plugin/testcov/plugin.py", """\
+ def testp():
+ print("Plugin here")
+ """)
+
# Install the third-party packages.
run_in_venv("python -m pip install --no-index ./third_pkg")
run_in_venv("python -m pip install --no-index -e ./another_pkg")
+ run_in_venv("python -m pip install --no-index -e ./bug888/app -e ./bug888/plugin")
shutil.rmtree("third_pkg")
# Install coverage.
@@ -141,7 +183,7 @@ class VirtualenvTest(CoverageTest):
yield
for fname in os.listdir("."):
- if fname not in {"venv", "another_pkg"}:
+ if fname not in {"venv", "another_pkg", "bug888"}:
os.remove(fname)
def get_trace_output(self):
@@ -274,3 +316,11 @@ class VirtualenvTest(CoverageTest):
assert "colorsys" not in out
assert "fifth" in out
assert "sixth" in out
+
+ def test_bug888(self, coverage_command):
+ out = run_in_venv(
+ coverage_command +
+ " run --source=bug888/app,bug888/plugin bug888/app/testcov/main.py"
+ )
+ # When the test fails, the output includes "Already imported a file that will be measured"
+ assert out == "Plugin here\n"