-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixed the issue of causes KeyError
when using the parameter --import-mode=importlib
in pytest>=8.2 . (#12592)
#12752
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @dongfangtianyu, but I'm not sure this approach is correct (although the introduced test seems to indicate it works).
Perhaps it would be helpful to submit a snippet upstream that uses PathFinder.find_spec
and causes it to raise KeyError
to obtain advice.
Thank you for your response @nicoddemus . I’m also unsure if this approach is suitable. The main purpose of this PR is to request a review and discussion from the maintainers. I’ve tried various fixes, but all have failed. During this process, I’ve often thought that this issue should be fixed upstream. Since I’m not yet familiar with the lower-level aspects of Python, I’ve been avoiding creating an issue in the Python repository. However, you’re right. I will prepare a sample code later and seek advice from upstream. |
…in the namespace package causes a KeyError.(pytest-dev#12592)
098e5a6
to
7108bb9
Compare
Hi @nicoddemus , can you please re-review the code? Judging from the results, the effect of this modification:
Welcome any further suggestions. |
Hi @dongfangtianyu just to let you know I've been busy, but I will review this ASAP. 👍 |
Hi @dongfangtianyu, finally managed to find the time to look at this carefully, sorry for the long delay! Everything makes sense according to the docs and the tests are there to prove it. Took the liberty of tweaking some comments/docs/changelog and simplify the regression test to better reflect the issue, other than that this looks great! Again, thanks a lot for all the effort put here, we really appreciate it! |
I will merge this in the next few days. |
Backport to 8.3.x: 💚 backport PR created✅ Backport PR branch: Backported as #12843 🤖 @patchback |
Directories inside a namespace package with the same name as the namespace package would cause a `KeyError` with `--import-mode=importlib`. Fixes #12592 Co-authored-by: Bruno Oliveira <[email protected]> (cherry picked from commit 6486c3f)
#12843) Directories inside a namespace package with the same name as the namespace package would cause a `KeyError` with `--import-mode=importlib`. Fixes #12592 Co-authored-by: Bruno Oliveira <[email protected]> (cherry picked from commit 6486c3f) Co-authored-by: dongfangtianyu <[email protected]>
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.