Module already imported warning
When I run my tests using pytest==3.0.6 and pytest-cov==2.4.0, I see the following warning:
======================= pytest-warning summary ======================
WP1 None Module already imported so can not be re-written: pytest_cov
============ 1 passed, 1 pytest-warnings in 0.09 seconds ============
which unfortunately causes pytest to return a non-zero exit code and make the test suite as failing.
I don't see this warning with pytest==2.9.2.
If it helps, I found a similar issue reported in another library: https://github.com/philpep/testinfra/issues/125
Do you get other errors? AFAIK a mere warning can't change the exit code so the cause must be something else (some related exception somewhere?!)
I think I overstated the problem.
I'm running my tests using pytest-watch and its not continuing on to my onpass command after displaying the warning (whereas it does continue with pytest==2.9.2 when no warning is displayed).
Isn't that an issue in pytest-watch then?
About the warning's source - are you importing pytest_cov in your code or how can I reproduce it?
Sorry, I'm not really sure. 😄
I am not importing from pytest_cov or any other plugin, but pytest-cov is the only plugin reporting this warning.
Are you using xdist?
Hard to guess what the cause is. Can you make a reproducing example?
Just to clarify, that warning is happening because by the time pytest is importing pytest_cov as a plugin and attempting to rewrite asserts on it, it already has been imported by someone else. Perhaps that might give a clue about who's importing it.
At a glance, I think the order is:
- plugins specified by the
-poption; - plugins installed in the environment (setuptools entry points);
-
PYTEST_PLUGINSenvironment variable.
I've just started using xdist and running pytest -f and got the same error:
$ pip freeze | grep pytest
pytest==3.0.6
pytest-cov==2.4.0
pytest-django==3.1.2
pytest-mock==1.5.0
pytest-poo-fail==1.1
pytest-timeit==0.3.0
pytest-xdist==1.15.0
Also it created some new coverage files
$ git status
...
Untracked files:
(use "git add <file>..." to include in what will be committed)
.coverage.my_hostname.1219.136209
.coverage.my_hostname.1219.618935
I'm also getting wrong results when running with the -f flag
$ pytest -f
============================================================================================================================= test session starts =============================================================================================================================$
platform linux -- Python 3.5.3, pytest-3.0.6, py-1.4.32, pluggy-0.4.0
Django settings: config.settings.tests (from environment variable)
rootdir: /home/user/dev/sp/mad-project, inifile: pytest.ini
plugins: xdist-1.15.0, timeit-0.3.0, poo-fail-1.1, mock-1.5.0, django-3.1.2, cov-2.4.0, celery-4.0.2
collected 78 items
collected 78 items
mad/base/tests/test_admins.py .
mad/base/tests/test_consumers.py ..
mad/builds/tests/test_models.py ............
mad/builds/tests/test_serializers.py ........
mad/builds/tests/test_views.py ..............
mad/projects/tests/test_fields.py ...........
mad/projects/tests/test_models.py ...
mad/projects/tests/test_permissions.py ....
mad/projects/tests/test_serializers.py .........
mad/projects/tests/test_views.py ............
mad/users/tests/test_views.py ..
----------- coverage: platform linux, python 3.5.3-final-0 -----------
Name Stmts Miss Cover Missing
-----------------------------------------------------------
mad/base/views.py 4 0 100%
mad/builds/admin.py 5 5 0% 1-7
mad/builds/filters.py 7 0 100%
mad/builds/models.py 78 38 51% 1-26, 30-42, 45, 62, 70, 89, 131, 144
mad/builds/permissions.py 4 0 100%
mad/builds/serializers.py 46 0 100%
mad/builds/tasks.py 10 10 0% 1-16
mad/builds/views.py 64 0 100%
mad/consumers.py 4 0 100%
mad/downloads/models.py 9 9 0% 1-13
mad/projects/admin.py 8 8 0% 1-12
mad/projects/fields.py 41 0 100%
mad/projects/models.py 46 25 46% 1-20, 23, 46, 94-119
mad/projects/permissions.py 17 0 100%
mad/projects/serializers.py 57 0 100%
mad/projects/views.py 12 0 100%
mad/urls.py 9 0 100%
mad/users/views.py 10 0 100%
-----------------------------------------------------------
TOTAL 431 95 78%
============================================================================================================================ pytest-warning summary ===========================================================================================================================$
WP1 None Module already imported so can not be re-written: pytest_cov
================================================================================================================ 78 passed, 1 pytest-warnings in 14.63 seconds ================================================================================================================$
############################################################################################################################# waiting for changes #############################################################################################################################$
### Watching: /home/user/dev/sp/mad-project
$ pytest
============================================================================================================================= test session starts ==============================================================================================================================
platform linux -- Python 3.5.3, pytest-3.0.6, py-1.4.32, pluggy-0.4.0
Django settings: config.settings.tests (from ini file)
rootdir: /home/user/dev/sp/mad-project, inifile: pytest.ini
plugins: xdist-1.15.0, timeit-0.3.0, poo-fail-1.1, mock-1.5.0, django-3.1.2, cov-2.4.0, celery-4.0.2
collected 78 items
mad/base/tests/test_admins.py .
mad/base/tests/test_consumers.py ..
mad/builds/tests/test_models.py ............
mad/builds/tests/test_serializers.py ........
mad/builds/tests/test_views.py ..............
mad/projects/tests/test_fields.py ...........
mad/projects/tests/test_models.py ...
mad/projects/tests/test_permissions.py ....
mad/projects/tests/test_serializers.py .........
mad/projects/tests/test_views.py ............
mad/users/tests/test_views.py ..
----------- coverage: platform linux, python 3.5.3-final-0 -----------
Name Stmts Miss Cover Missing
-----------------------------------------------------------
mad/base/views.py 4 0 100%
mad/builds/admin.py 5 0 100%
mad/builds/filters.py 7 0 100%
mad/builds/models.py 78 0 100%
mad/builds/permissions.py 4 0 100%
mad/builds/serializers.py 46 0 100%
mad/builds/tasks.py 10 7 30% 7-16
mad/builds/views.py 64 0 100%
mad/consumers.py 4 0 100%
mad/downloads/models.py 9 0 100%
mad/projects/admin.py 8 0 100%
mad/projects/fields.py 41 0 100%
mad/projects/models.py 46 0 100%
mad/projects/permissions.py 17 0 100%
mad/projects/serializers.py 57 0 100%
mad/projects/views.py 12 0 100%
mad/urls.py 9 0 100%
mad/users/views.py 10 0 100%
-----------------------------------------------------------
TOTAL 431 7 98%
the content of pytest.ini:
[pytest]
DJANGO_SETTINGS_MODULE = config.settings.tests
python_functions = test_*
python_files = test_*
python_classes = *Tests
addopts = --poo --reuse-db -s --cov mad --cov-report=term-missing
norecursedirs = node_modules requirements web_client .git config venv
I'm getting the same error, if I use pytest-xdist and the --looponfail option
Here's the most minimal setup for reproducing this error:
$ pip freeze
apipkg==1.4
coverage==4.4.1
execnet==1.4.1
pkg-resources==0.0.0
py==1.4.34
pytest==3.2.1
pytest-cov==2.5.1
pytest-forked==0.2
pytest-xdist==1.20.0
Empty file a.py.
test.py with contents:
import a
Run:
$ py.test test.py --cov=a -f
============================= test session starts ==============================
platform linux -- Python 3.6.2, pytest-3.2.1, py-1.4.34, pluggy-0.4.0
rootdir: /home/fayaz/Programming, inifile:
plugins: xdist-1.20.0, forked-0.2, cov-2.5.1
collected 0 items
collected 0 items
----------- coverage: platform linux, python 3.6.2-final-0 -----------
Name Stmts Miss Cover
---------------------------
a.py 0 0 100%
=============================== warnings summary ===============================
None
Module already imported so can not be re-written: pytest_cov
-- Docs: http://doc.pytest.org/en/latest/warnings.html
========================== 1 warnings in 0.01 seconds ==========================
############################################################## waiting for changes ###############################################################
### Watching: /home/fayaz/Programming
@nicoddemus Can the internal warning be filtered after all? It gets emitted in https://github.com/pytest-dev/pytest/blob/3ed8e28ef31004d64ad992a914775fe3ff23b7cb/src/_pytest/assertion/rewrite.py#L202-L205, but then only hooks are called on it (empty in my case):
> …/pytest/src/_pytest/config/__init__.py(601)
599 def warn(self, code, message, fslocation=None, nodeid=None):
600 """ generate a warning for this test session. """
601 -> self.hook.pytest_logwarning.call_historic(
602 kwargs=dict(
603 code=code, message=message, fslocation=fslocation, nodeid=nodeid
604 )
605 )
It looks like this warning is internal, and filters are not applied to it?!
(see also #211)
@blueyed unfortunately, internal warnings were introduced before pytest-warnings was integrated into the core, so they cannot be filtered using standard warning mechanisms. We have plans to update the internal warnings system to use the standard warnings module (https://github.com/pytest-dev/pytest/issues/2452).
The internal warnings can be suppressed from the output with --disable-pytest-warnings only at the moment.
Found a workaround: https://github.com/pytest-dev/pytest-cov/pull/228
Minimal project to reproduce: https://github.com/ykvch/pytestwarning
In my case warning appears when package:
- installed (
git clone https://github.com/ykvch/pytestwarning && pip install -e pytestwarningfor package above in separate venv) - has namespace and
find_packages()inside__init__.pyLike here: https://packaging.python.org/guides/packaging-namespace-packages/#pkg-resources-style-namespace-packages
So when the test discovery happens (e.g.: pytest --collect-only pytestwarning/ptw/tests) import is duplicated.
Note: NOT reproduced when using native style namespace (without find_packages) OR package is not installed. Like here: https://packaging.python.org/guides/packaging-namespace-packages/#native-namespace-packages.
My solution: use native namespace package style.
So when the test discovery happens (e.g.:
pytest --collect-only pytestwarning/ptw/tests) import is duplicated.
Sounds like a pytest issue then, i.e. it should be improved there I guess.
At https://packaging.python.org/guides/packaging-namespace-packages they say: "While this approach is no longer recommended, it is widely present in most existing namespace packages." So, for me it's not quite that obvious on weather that's worth fixing at all. IMO since warning breaks nothing, and if someone wants nice pytest-asserts without warning, then it is a good motivation to update their project to use "brand new shiny recommended packaging style".
@ykvch Sure, I do not mean to use something that is not recommended, but since I've worked on the collection things in pytest I am certain it could be improved/fixed there. Unfortunately that code is not much fun to work on, duplicated unnecessarily etc. But a failing test for pytest and an issue with the details you've provided here already might be a good start.
@ykvch Given https://github.com/pytest-dev/pytest-cov/pull/228 however, there shouldn't be any warning anymore though with pytest-cov 2.6.1? But I assume you mean for this to happen in general?
@blueyed yes, general note for those, who still may experience this to show that there might be an alternative reason (and provide solution). You're right that comment above should be attached somewhere to pytest project as well.
@ykvch Investigated a bit.
pytestwarning/ptw/__init__.py gets not read even with only a single namespace_packages entry - only if there are multiple (https://github.com/pypa/setuptools/blob/d8b901bc15e2e365c7994cd65758f4181f3d9175/setuptools/command/build_py.py#L169-L184) - it then only checks for "declare_namespace" in there during setup.
With regard to pytest I've found an interesting note in this context: https://github.com/pypa/setuptools/blob/d8b901bc15e2e365c7994cd65758f4181f3d9175/docs/pkg_resources.txt#L162-L171 - created https://github.com/pytest-dev/pytest/pull/4980 for that.
Do we have a clear solution or workaround for this problem? I am facing this because I have a pytest plugin that is part of my module, which is causing import before pytest-cov is loaded. See https://github.com/ansible-community/ansible-lint/blob/main/conftest.py#L8
I cannot really move the plugin outside the module because the testing submodule is part of public API of my tool, as some need them for testing the stuff they build on top of.