forked from pytest-dev/pytest
-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Description
User's report
5.1.2 ImportError while loading conftest (windows import folder casing issues)
5.1.1 works fine. after upgrade to 5.1.2, the path was converted to lower case
Installing collected packages: pytest
Found existing installation: pytest 5.1.1
Uninstalling pytest-5.1.1:
Successfully uninstalled pytest-5.1.1
Successfully installed pytest-5.1.2
PS C:\Azure\KMS\ComponentTest\Python> pytest --collect-only .\PIsys -m smoke
ImportError while loading conftest 'c:\azure\kms\componenttest\python\pisys\conftest.py'.
ModuleNotFoundError: No module named 'python'
PS C:\Azure\KMS\ComponentTest\Python>
Additional context from affected users
- Importing from package with uppercase components (e.g.,
muepy.imageProcessing.wafer.sawStreets) fails withModuleNotFoundError: No module named 'muepy.imageprocessing'(note the lowercasep). - This occurs after upgrading from pytest 5.1.1 to 5.1.2 on Windows 10.
pytest output
(%PREFIX%) %SRC_DIR%>pytest --pyargs muepy
============================= test session starts =============================
platform win32 -- Python 3.6.7, pytest-5.1.2, py-1.8.0, pluggy-0.12.0
rootdir: %SRC_DIR%
collected 0 items / 1 errors
=================================== ERRORS ====================================
________________________ ERROR collecting test session ________________________
..\_test_env\lib\site-packages\_pytest\config\__init__.py:440: in _importconftest
return self._conftestpath2mod[conftestpath]
E KeyError: local('c:\\users\\angelo.peronio\\appdata\\local\\continuum\\miniconda3\\envs\\packaging\\conda-bld\\muepy_1567627432048\\_test_env\\lib\\site-packages\\muepy\\imageprocessing\\wafer\\sawstreets\\tests\\conftest.py')
During handling of the above exception, another exception occurred:
..\_test_env\lib\site-packages\_pytest\config\__init__.py:446: in _importconftest
mod = conftestpath.pyimport()
..\_test_env\lib\site-packages\py\_path\local.py:701: in pyimport
__import__(modname)
E ModuleNotFoundError: No module named 'muepy.imageprocessing'
During handling of the above exception, another exception occurred:
..\_test_env\lib\site-packages\py\_path\common.py:377: in visit
for x in Visitor(fil, rec, ignore, bf, sort).gen(self):
..\_test_env\lib\site-packages\py\_path\common.py:429: in gen
for p in self.gen(subdir):
..\_test_env\lib\site-packages\py\_path\common.py:429: in gen
for p in self.gen(subdir):
..\_test_env\lib\site-packages\py\_path\common.py:429: in gen
for p in self.gen(subdir):
..\_test_env\lib\site-packages\py\_path\common.py:418: in gen
dirs = self.optsort([p for p in entries
..\_test_env\lib\site-packages\py\_path\common.py:419: in <listcomp>
if p.check(dir=1) and (rec is None or rec(p))])
..\_test_env\lib\site-packages\_pytest\main.py:606: in _recurse
ihook = self.gethookproxy(dirpath)
..\_test_env\lib\site-packages\_pytest\main.py:424: in gethookproxy
my_conftestmodules = pm._getconftestmodules(fspath)
..\_test_env\lib\site-packages\_pytest\config\__init__.py:420: in _getconftestmodules
mod = self._importconftest(conftestpath)
..\_test_env\lib\site-packages\_pytest\config\__init__.py:454: in _importconftest
raise ConftestImportFailure(conftestpath, sys.exc_info())
E _pytest.config.ConftestImportFailure: (local('c:\\users\\angelo.peronio\\appdata\\local\\continuum\\miniconda3\\envs\\packaging\\conda-bld\\muepy_1567627432048\\_test_env\\lib\\site-packages\\muepy\\imageprocessing\\wafer\\sawstreets\\tests\\conftest.py'), (<class 'ModuleNotFoundError'>, ModuleNotFoundError("No module named 'muepy.imageprocessing'",), <traceback object at 0x0000018F0D6C9A48>))
!!!!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!!!
============================== 1 error in 1.32s ===============================
Specification (by Emerson Gray)
Root cause:
- Regression introduced by using
os.path.normcasein path normalization (PR 5792), which lowercases paths on Windows. - Lowercased paths are used during conftest import, causing module-name derivation in lowercase and mismatches when conftest imports packages using case-preserved names (e.g.,
imageProcessing).
Fix strategy:
- Continue using
unique_path(normcase) for cache/dedup keys to avoid duplicate conftest loading across differently cased paths. - Use a case-preserving real path for the actual import operations:
- In
_pytest/config/__init__.py::PytestPluginManager._importconftest, derivepkgpathand callpyimport()usingconftestpath.realpath()(case-preserving) while keepingunique_path(conftestpath)only for internal caches.
- In
Proposed code changes:
- File:
pytest/src/_pytest/config/__init__.py - Function:
PytestPluginManager._importconftest - Changes:
- Replace direct use of
unique_path(conftestpath)forpyimportwith two variables:conftestpath_key = unique_path(conftestpath)(normcased, for caches)real_conftestpath = conftestpath.realpath()(case-preserving, for import)
- Use
real_conftestpath.pypkgpath()andreal_conftestpath.pyimport()for module import. - Store
modin_conftestpath2modkeyed byconftestpath_key. - Update
_dirpath2confmodskeyed byconftestpath_key.dirpath(). - Raise
ConftestImportFailurewithreal_conftestpathfor clearer error output.
- Replace direct use of
Regression test:
- File:
pytest/testing/test_windows_conftest_import_casing.py - Behavior:
- Skip on non-Windows.
- Create a package
imageProcessing/subpkg/helper.pywithFOO = 1. - In
conftest.py, importimageProcessing.subpkg.helper(mixed case) and asserthelper.FOO == 1. - Add a trivial test to trigger conftest import; ensure collection succeeds.
Backward compatibility:
- Retains deduplication benefits of
unique_pathwhile restoring correct module-name derivation on Windows. - Non-Windows behavior unchanged.
Reproduction steps
- On Windows, create a package with uppercase letters in directory names.
- Use a
conftest.pythat imports a submodule using the mixed-case package name. - Run
pytestto collect tests; observeImportError while loading conftestin 5.1.2. - With the proposed fix, collection should succeed.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels