pytest-cov icon indicating copy to clipboard operation
pytest-cov copied to clipboard

Module already imported warning

Open jacebrowning opened this issue 9 years ago • 20 comments

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

jacebrowning avatar Jan 27 '17 20:01 jacebrowning

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?!)

ionelmc avatar Jan 27 '17 20:01 ionelmc

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).

jacebrowning avatar Jan 27 '17 20:01 jacebrowning

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?

ionelmc avatar Jan 27 '17 21:01 ionelmc

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.

jacebrowning avatar Jan 27 '17 22:01 jacebrowning

Are you using xdist?

Hard to guess what the cause is. Can you make a reproducing example?

ionelmc avatar Jan 27 '17 23:01 ionelmc

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:

  1. plugins specified by the -p option;
  2. plugins installed in the environment (setuptools entry points);
  3. PYTEST_PLUGINS environment variable.

nicoddemus avatar Jan 27 '17 23:01 nicoddemus

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 

alejandrodnm avatar Apr 06 '17 12:04 alejandrodnm

I'm getting the same error, if I use pytest-xdist and the --looponfail option

ucyo avatar Jul 05 '17 12:07 ucyo

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

fayazkhan avatar Aug 19 '17 06:08 fayazkhan

@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 avatar Jul 04 '18 19:07 blueyed

@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.

nicoddemus avatar Jul 04 '18 20:07 nicoddemus

Found a workaround: https://github.com/pytest-dev/pytest-cov/pull/228

blueyed avatar Sep 21 '18 06:09 blueyed

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 pytestwarning for package above in separate venv)
  • has namespace and find_packages() inside __init__.py Like 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.

ykvch avatar Mar 22 '19 09:03 ykvch

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.

blueyed avatar Mar 22 '19 09:03 blueyed

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 avatar Mar 22 '19 10:03 ykvch

@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.

blueyed avatar Mar 22 '19 11:03 blueyed

@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 avatar Mar 22 '19 11:03 blueyed

@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 avatar Mar 22 '19 12:03 ykvch

@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.

blueyed avatar Mar 24 '19 10:03 blueyed

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.

ssbarnea avatar Feb 12 '22 08:02 ssbarnea