[PR #12752/6486c3f3 backport][8.3.x] Fixed the issue of causes KeyError
when using the parameter --import-mode=importlib
in pytest>=8.2 . (#12592)
#12843
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This is a backport of PR #12752 as merged into main (6486c3f).
closes #12592
Reproduction Steps:
Create a namespace package in a non-root directory and include a test file.
Create a directory with the same name in that location.
Directory Structure:
Execution Results:
Through tracing, it was discovered that the error occurs during the second call to
pathlib._import_module_using_spec
.This is the entire call process when the exception occurs.
In simple terms, when executing
PathFinder.find_spec('a.b.c', ['/app/a/b/c'])
:Python assumes that we are trying to import a module named
c
(the tail module).At this point, there happens to be a directory
c
in/app/a/b/c
, which is then treated as a namespace.According to convention, its parent module
a.b
should already exist insys.modules
, and it is accessed directly using the item method.However, when pytest uses the
importlib
mode, it doesn't follow this convention, leading to aKeyError
.So, from the observable behavior, it seems to be an upstream issue.
However, from a deeper perspective, there might also be a problem with pytest's handling of parent module imports.
I noticed that
_import_module_using_spec
attempts to follow the convention of importing the parent module, but the error occurs precisely during this process:https://github.com/pytest-dev/pytest/blob/main/src/_pytest/pathlib.py#L634-L656
I searched for the usage of 'importlib', and the example provided in the Python documentation can import of any module or namespace package in this case:
https://docs.python.org/3/library/importlib.html#approximating-importlib-import-module.
Unlike
_import_module_using_spec
, the example function in the documentation first ensures that the necessary parent modules are present insys.modules
, and then imports the target module (or target namespace package).Based on this, I attempted to modify the execution process in
_import_module_using_spec
, moving the import of the parent module to afterinsert_missing_modules()
to avoid aKeyError
due tosys.modules
not being ready.From the test results, it works quite well, but I'm not sure if there are potential flaws or better solutions (in fact, I've tried and discarded many solutions).
Welcome any further suggestions.