gh-153888: Resolve lazy imports before using them as a mock spec - #157768
Merged
Merged
Conversation
unittest.mock.patch() reads the attribute it replaces out of target.__dict__, which for an unresolved lazy import holds a types.LazyImportType placeholder. spec=True, spec_set=True and autospec=True then specced the placeholder, so patching a function produced a NonCallableMagicMock. Reimplementation of python#153977, open since July 2026: - Resolve in _patch.__enter__(), and only when the spec is taken from the original, rather than unconditionally in get_original(). Resolving on every patch() breaks patch("mod.dep", new=...) for a lazy import of a module that is not installed. - Test spec and spec_set as well as autospec, as asked for in review. - Build the lazy binding in the test instead of importing json lazily at module level: "lazy from" binds eagerly when the module is already imported, so that test passed without the fix too. Reported as pythongh-153888.
Contributor
Author
|
cc @encukou |
Member
|
This looks good to me -- though I'm not an expert on lazy modules or mock. It is a behaviour change though. Is it possible that someone would mock out a lazy import because it's not importable in the test scenario? @hugovk, does this fit in 3.15? |
Member
|
Yes, this can go into 3.15.0. |
|
Thanks @brittanyrey for the PR, and @encukou for merging it 🌮🎉.. I'm working now to backport this PR to: 3.15. |
|
GH-158396 is a backport of this pull request to the 3.15 branch. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
unittest.mock.patch()reads the attribute it replaces out oftarget.__dict__, which for an unresolved lazy import holds atypes.LazyImportType placeholder.spec=True,spec_set=Trueandautospec=Truethen specced the placeholder, so patching a function produced aNonCallableMagicMock.Reimplementation of #153977, open since July 2026 + some additional tests and one extra check.
_patch.__enter__(), and only when the spec is taken from the original, rather than unconditionally inget_original(). Resolving on everypatch()breakspatch("mod.dep", new=...)for a lazy import of a module that is not installed.autospecdoesn't work with lazy-imported symbols #153888