Closed
Description
As first noted in #12074, below is an example project structure with two packages under the ns
namespace that now fail to import after the changes introduced in 8.1.x
:
ns
└── python
├── bar
│ ├── ns
│ │ ├── bar
│ │ └── test
│ │ ├── __init__.py
│ │ ├── bar.py
│ │ └── test_bar.py
│ └── pyproject.toml
└── foo
├── ns
│ ├── foo
│ └── test
│ ├── __init__.py
│ ├── foo.py
│ └── test_foo.py
└── pyproject.toml
Below are the contents of test_foo.py
and foo.py
. test_bar.py
and bar.py
look nearly identical.
# python/foo/ns/test/test_foo.py
from .foo import value
def test_foo():
assert value == "foo"
# python/foo/ns/test/foo.py
value = "foo"
In pytest==8.0.2
, python -m pytest --import-mode=importlib
correctly discovers and runs the tests from the top level ns
directory. In pytest==8.1.1
, python -m pytest --import-mode=importlib -o "consider_namespace_packages=true"
, results in the following error during collection:
========================== test session starts ===========================
platform darwin -- Python 3.9.16, pytest-8.1.1, pluggy-1.4.0
rootdir: /home/user/pytest-12074
collected 0 items / 2 errors
================================= ERRORS =================================
____________ ERROR collecting python/bar/ns/test/test_bar.py _____________
ImportError while importing test module '/home/user/pytest-12074/python/bar/ns/test/test_bar.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
python/bar/ns/test/test_bar.py:1: in <module>
from .bar import value
E ModuleNotFoundError: No module named 'test.bar'
____________ ERROR collecting python/foo/ns/test/test_foo.py _____________
ImportError while importing test module '/home/user/pytest-12074/python/foo/ns/test/test_foo.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
python/foo/ns/test/test_foo.py:1: in <module>
from .foo import value
E ModuleNotFoundError: No module named 'test.foo'
======================== short test summary info =========================
ERROR python/bar/ns/test/test_bar.py
ERROR python/foo/ns/test/test_foo.py
!!!!!!!!!!!!!!!! Interrupted: 2 errors during collection !!!!!!!!!!!!!!!!!
=========================== 2 errors in 0.04s ============================
To reproduce the issue clone https://github.com/aaraney/pytest-12074, pip install ns.foo
and ns.bar
, pip install the different versions of pytest
and run with the aforementioned commands.
Activity
pytest~=8.0.0
until pytest/12074 is fixed NOAA-OWP/DMOD#542nicoddemus commentedon Mar 12, 2024
Thanks @aaraney for the report, I will take a look ASAP. 👍
nicoddemus commentedon Mar 12, 2024
@aaraney,
How are you setting up your
PYTHONPATH
? I managed to get your example to work by puttingns/python/bar
andns/python/foo
in thePYTHONPATH
, which seems to be the recommendation for using namespace packages.One thing you can use to check if your namespace package is working is to import it inside Python directly:
Can you try the above and show what you get?
joshbode commentedon Mar 13, 2024
I am seeing something similar - I think it is because there is effectively a collision between
ns.test
in each subpackage.I deleted the
__init__.py
and following that it ran successfully using:Without
consider_namespace_packages
if still failed, though.BTW, @aaraney, there's a typo in the original command above - a missing
g
(consider_namespace_packaes
), which may help :)joshbode commentedon Mar 13, 2024
Also, and this may be a different bug, but if I run
python -m pytest ...
instead of thepytest ...
command directly then I don't need to delete the__init__.py
in the test directories, though either way I do require theconsider_namespace_packages
option.With
pytest==8.0.2
it works fine either way (with/without running viapython -m pytest
) but it fails without the__init__.py
for a different reason (relative imports within the test directory don't work).nicoddemus commentedon Mar 13, 2024
I suggest to also test using the Python REPL to import the namespace packages, taking pytest out of the picture, to ensure your configuration is correct.
aaraney commentedon Mar 13, 2024
@nicoddemus, thanks again for looking into this! The example I provided was incomplete. When I adding
__init__.py
files topython/ns/bar/ns/bar/__init__.py
andpython/ns/foo/ns/foo/__init__.py
, so python / setuptools would recognize them as actual submodules (as you alluded to)pytest
ran successfully!In the project I thought I discovered this bug in, it turns out there was an erroneous
__init__.py
file at the same level as a submodule'spyproject.toml
/setup.py
/setup.cfg
(e.g.python/ns/bar/__init__.py
). For some reasonpytest==8.0.2
did not balk at this and collected correctly, however withpytest==8.1.1
, I receivedImportError: attempted relative import beyond top-level package
andModuleNotFoundError: No module named 'some-module'
errors. I think that is the correct behavior per PEP 420.@joshbode, great catch! Just fixed it!
nicoddemus commentedon Mar 13, 2024
@aaraney thanks for the clarification!
aaraney commentedon Mar 13, 2024
@nicoddemus, I think this can be closed unless you feel the need for it to stay open. It seems that it was a false alarm on my part. Thanks again for looking into this!
nicoddemus commentedon Mar 13, 2024
If somebody sees this and is not working as expected, please try importing your modules using the Python REPL first, to ensure the configuration is correct. 👍
I'm closing this for now then, with "working as intended".
Thanks everyone!
joshbode commentedon Mar 13, 2024
The REPL tip is a good one - it helped me figure out that my imports were being masked and that it wasn't being treated correctly as a namespace package, even before it hit
pytest
Pin to pytest<8.1; workaround for pytest-dev/pytest#12112.
Pin to pytest<8.1; workaround for pytest-dev/pytest#12112.
40 remaining items