Skip to content

Commit 1a6844a

Browse files
committed
fix: don't warn about already imported files for namespace packages #888
Ignore namespace packages in the already-imported check. #888
1 parent 7589066 commit 1a6844a

File tree

4 files changed

+70
-4
lines changed

4 files changed

+70
-4
lines changed

CHANGES.rst

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,16 @@ This list is detailed and covers changes in each pre-release version.
2222
Unreleased
2323
----------
2424

25-
- Fix: the sticky header on the HTML report didn't work unless you had branch
26-
coverage enabled. This is now fixed, the sticky header works for everyone.
25+
- Fix: The sticky header on the HTML report didn't work unless you had branch
26+
coverage enabled. This is now fixed: the sticky header works for everyone.
2727
(Do people still use coverage without branch measurement!? j/k)
2828

29+
- Fix: When using explicitly declared namespace packages, the "already imported
30+
a file that will be measured" warning would be issued (`issue 888`_). This
31+
is now fixed.
32+
33+
.. _issue 888: https://github.com/nedbat/coveragepy/issues/888
34+
2935

3036
.. _changes_61:
3137

coverage/inorout.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,10 @@ def warn_already_imported_files(self):
479479
if filename in warned:
480480
continue
481481

482+
if len(getattr(mod, "__path__", ())) > 1:
483+
# A namespace package, which confuses this code, so ignore it.
484+
continue
485+
482486
disp = self.should_trace(filename)
483487
if disp.has_dynamic_filename:
484488
# A plugin with dynamic filenames: the Python file

lab/treetopy.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Turn a tree of Python files into a series of make_file calls.
2+
for f in **/*.py; do
3+
echo 'make_file("'$1$f'", """\\'
4+
sed -e 's/^/ /' <$f
5+
echo ' """)'
6+
done

tests/test_venv.py

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ def fifth(x):
8484
def sixth(x):
8585
return 6 * x
8686
""")
87-
# The setup.py to install everything.
8887
make_file("another_pkg/setup.py", """\
8988
import setuptools
9089
setuptools.setup(
@@ -93,9 +92,52 @@ def sixth(x):
9392
)
9493
""")
9594

95+
# Bug888 code.
96+
make_file("bug888/app/setup.py", """\
97+
from setuptools import setup
98+
setup(
99+
name='testcov',
100+
packages=['testcov'],
101+
namespace_packages=['testcov'],
102+
)
103+
""")
104+
make_file("bug888/app/testcov/__init__.py", """\
105+
try: # pragma: no cover
106+
__import__('pkg_resources').declare_namespace(__name__)
107+
except ImportError: # pragma: no cover
108+
from pkgutil import extend_path
109+
__path__ = extend_path(__path__, __name__)
110+
""")
111+
make_file("bug888/app/testcov/main.py", """\
112+
import pkg_resources
113+
for entry_point in pkg_resources.iter_entry_points('plugins'):
114+
entry_point.load()()
115+
""")
116+
make_file("bug888/plugin/setup.py", """\
117+
from setuptools import setup
118+
setup(
119+
name='testcov-plugin',
120+
packages=['testcov'],
121+
namespace_packages=['testcov'],
122+
entry_points={'plugins': ['testp = testcov.plugin:testp']},
123+
)
124+
""")
125+
make_file("bug888/plugin/testcov/__init__.py", """\
126+
try: # pragma: no cover
127+
__import__('pkg_resources').declare_namespace(__name__)
128+
except ImportError: # pragma: no cover
129+
from pkgutil import extend_path
130+
__path__ = extend_path(__path__, __name__)
131+
""")
132+
make_file("bug888/plugin/testcov/plugin.py", """\
133+
def testp():
134+
print("Plugin here")
135+
""")
136+
96137
# Install the third-party packages.
97138
run_in_venv("python -m pip install --no-index ./third_pkg")
98139
run_in_venv("python -m pip install --no-index -e ./another_pkg")
140+
run_in_venv("python -m pip install --no-index -e ./bug888/app -e ./bug888/plugin")
99141
shutil.rmtree("third_pkg")
100142

101143
# Install coverage.
@@ -141,7 +183,7 @@ def in_venv_world_fixture(self, venv_world):
141183
yield
142184

143185
for fname in os.listdir("."):
144-
if fname not in {"venv", "another_pkg"}:
186+
if fname not in {"venv", "another_pkg", "bug888"}:
145187
os.remove(fname)
146188

147189
def get_trace_output(self):
@@ -274,3 +316,11 @@ def test_installed_namespace_packages(self, coverage_command):
274316
assert "colorsys" not in out
275317
assert "fifth" in out
276318
assert "sixth" in out
319+
320+
def test_bug888(self, coverage_command):
321+
out = run_in_venv(
322+
coverage_command +
323+
" run --source=bug888/app,bug888/plugin bug888/app/testcov/main.py"
324+
)
325+
# When the test fails, the output includes "Already imported a file that will be measured"
326+
assert out == "Plugin here\n"

0 commit comments

Comments
 (0)