简体   繁体   中英

pytest before 4.6 was able to import from a local package with the same name as an installed namespace package, and now it isn't. Is that a bug?

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?

Import your packages through sys as written in this project (using unittest not pytest)

import sys
sys.path.insert(0,"pkg_a")
sys.path.insert(0,"pkg_b")

#Test goes here

My project load test/testSpecie.py which tests files in src/...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM