I clone this toy repository that demonstrates how namespace packages work:
C:\workspace>git clone https://github.com/pypa/sample-namespace-packages.git
Specifically, I'll use its pkg_resources directory, which has the structure
pkg_a/
setup.py
example_pkg/
__init__.py
a/
__init__.py
pkg_b/
setup.py
example_pkg/
__init__.py
b/
__init__.py
The example_pkg
package is a pkg_resources-style namespace package (explained here).
I set up my python environment:
C:\workspace>\Python35\python.exe -m venv localpython
C:\workspace>localpython\Scripts\activate.bat
(localpython) C:\workspace>python -m pip install --upgrade pip setuptools
I install pkg_a from the toy repository:
(localpython) C:\workspace>python -m pip install c:\workspace\sample-namespace-packages\pkg_resources\pkg_a
I put pkg_b from the toy repository on my PYTHONPATH:
(localpython) C:\workspace>set PYTHONPATH=c:\workspace\sample-namespace-packages\pkg_resources\pkg_b
I write a test suite for pkg_b, consisting of one line:
(localpython) C:\workspace>echo import example_pkg.b > test_b.py
Now, if I run that test suite in pytest 4.5 or less, it succeeds:
(localpython) C:\workspace>python -m pip install pytest==4.5.0
Collecting pytest==4.5.0
...
(localpython) C:\workspace>pytest test_b.py
================================================= test session starts =================================================
platform win32 -- Python 3.5.2, pytest-4.5.0, py-1.8.0, pluggy-0.12.0
rootdir: C:\workspace
collected 0 items
============================================ no tests ran in 0.02 seconds =============================================
But if I run it in pytest 4.6 or greater, it errors:
(localpython) C:\workspace>python -m pip install pytest==4.6.0
Collecting pytest==4.6.0
...
(localpython) C:\workspace>pytest test_b.py
================================================= test session starts =================================================
platform win32 -- Python 3.5.2, pytest-4.6.0, py-1.8.0, pluggy-0.12.0
rootdir: C:\workspace
collected 0 items / 1 errors
======================================================= ERRORS ========================================================
_____________________________________________ ERROR collecting test_b.py ______________________________________________
ImportError while importing test module 'C:\workspace\test_b.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
test_b.py:1: in <module>
import example_pkg.b
E ImportError: No module named 'example_pkg.b'
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
=============================================== 1 error in 0.08 seconds ===============================================
The import error is understandable: It's presumably looking in the example_pkg
in the site-packages and therefore not finding the b
package, which is under the example_pkg
on the PYTHONPATH.
Yet pytest 4.5 or earlier manages to find example_pkg.b
.
Edit: According to a comment, the relevant difference is that pytest 4.5 and earlier imported pkg_resources
. Indeed, if I add the line
import pkg_resources
at the top of my test file, test_b.py, then the test succeeds even in pytest 4.6 or greater. Furthermore, if I have multiple test files that try to import example_pkg.b
, then it's necessary and sufficient to import pkg_resources
in whichever of them pytest happens to run first.
That means that some side effect of importing pkg_resources
makes example_pkg.b
importable. What exactly does pkg_resources
do that achieves that effect, and can I do it directly instead of getting it as a side effect of a seemingly unused import? And does my needing that side effect mean the setup is invalid?