diff --git a/CHANGES.rst b/CHANGES.rst index 8e9963bba..3ce17d0f3 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -24,7 +24,12 @@ want to know what's different in 5.0 since 4.5.x, see :ref:`whatsnew5x`. Unreleased ---------- -- Nothing yet. +- Plugins (like the `Django coverage plugin`_) were generating "Already + imported a file that will be measured" warnings about Django itself. These + have been fixed, closing `issue 1150`_. + +.. _Django coverage plugin: https://pypi.org/project/django-coverage-plugin/ +.. _issue 1150: https://github.com/nedbat/coveragepy/issues/1150 .. _changes_56b1: diff --git a/coverage/inorout.py b/coverage/inorout.py index b023db0b3..532634ebe 100644 --- a/coverage/inorout.py +++ b/coverage/inorout.py @@ -481,6 +481,11 @@ def warn_already_imported_files(self): continue disp = self.should_trace(filename) + if disp.has_dynamic_filename: + # A plugin with dynamic filenames: the Python file + # shouldn't cause a warning, since it won't be the subject + # of tracing anyway. + continue if disp.trace: msg = "Already imported a file that will be measured: {}".format(filename) self.warn(msg, slug="already-imported") diff --git a/tests/plugin2.py b/tests/plugin2.py index c334628ad..60d16206b 100644 --- a/tests/plugin2.py +++ b/tests/plugin2.py @@ -7,6 +7,14 @@ import coverage +try: + import third.render # pylint: disable=unused-import +except ImportError: + # This plugin is used in a few tests. One of them has the third.render + # module, but most don't. We need to import it but not use it, so just + # try importing it and it's OK if the module doesn't exist. + pass + class Plugin(coverage.CoveragePlugin): """A file tracer plugin for testing.""" diff --git a/tests/test_process.py b/tests/test_process.py index 2447cffe3..9b451228f 100644 --- a/tests/test_process.py +++ b/tests/test_process.py @@ -1673,12 +1673,21 @@ def venv_world_fixture(tmp_path_factory): # Create a virtualenv. run_command("python -m virtualenv venv") - # A third-party package that installs two different packages. + # A third-party package that installs a few different packages. make_file("third_pkg/third/__init__.py", """\ import fourth def third(x): return 3 * x """) + # Use plugin2.py as third.plugin + with open(os.path.join(os.path.dirname(__file__), "plugin2.py")) as f: + make_file("third_pkg/third/plugin.py", f.read()) + # A render function for plugin2 to use for dynamic file names. + make_file("third_pkg/third/render.py", """\ + def render(filename, linenum): + return "HTML: {}@{}".format(filename, linenum) + """) + # Another package that third can use. make_file("third_pkg/fourth/__init__.py", """\ def fourth(x): return 4 * x @@ -1805,3 +1814,20 @@ def test_venv_isnt_measured(self, coverage_command): assert "third" not in out assert "coverage" not in out assert "colorsys" not in out + + @pytest.mark.skipif(not env.C_TRACER, reason="Plugins are only supported with the C tracer.") + def test_venv_with_dynamic_plugin(self, coverage_command): + # https://github.com/nedbat/coveragepy/issues/1150 + # Django coverage plugin was incorrectly getting warnings: + # "Already imported: ... django/template/blah.py" + # It happened because coverage imported the plugin, which imported + # Django, and then the Django files were reported as traceable. + self.make_file(".coveragerc", "[run]\nplugins=third.plugin\n") + self.make_file("myrender.py", """\ + import third.render + print(third.render.render("hello.html", 1723)) + """) + out = run_in_venv(coverage_command + " run --source=. myrender.py") + # The output should not have this warning: + # Already imported a file that will be measured: ...third/render.py (already-imported) + assert out == "HTML: hello.html@1723\n"