fix crash resolving cross-refs to suppressed modules#20658
Open
cburroughs wants to merge 1 commit intopython:masterfrom
Open
fix crash resolving cross-refs to suppressed modules#20658cburroughs wants to merge 1 commit intopython:masterfrom
cburroughs wants to merge 1 commit intopython:masterfrom
Conversation
When a stub imports from a module without stubs (e.g., protobuf stubs
importing from google.protobuf when protobuf stubs aren't installed),
the import is suppressed but a cross-ref is cached. On cache reload,
resolving the cross-ref fails along the lines of:
AssertionError: Cannot find module for google
This occurs because the cross-ref points to a module that was suppressed
and therefore never loaded into manager.modules.
The fix passes the set of suppressed modules to fixup_module() and
checks if a cross-ref points to a suppressed module before attempting
lookup. If so, a placeholder node is used instead.
Before this change on my test setup (see python#20655) with 128 shards
iterating through different dependency combination, 29 crashed with
this error. With the change 0 do so. The reproduction at
Qiskit/qiskit-serverless#1787 also passes for
me with this change.
Fixes python#16214
Disclaimer: I don't have prior familiarity with the mypy codebase and
this change was heavily LLM assisted.
Contributor
|
According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅ |
jonaslb
reviewed
Feb 3, 2026
Comment on lines
+68
to
+73
| parts = name.split(".") | ||
| for i in range(len(parts), 0, -1): | ||
| prefix = ".".join(parts[:i]) | ||
| if prefix in suppressed: | ||
| return True | ||
| return False |
There was a problem hiding this comment.
Suggested change
| parts = name.split(".") | |
| for i in range(len(parts), 0, -1): | |
| prefix = ".".join(parts[:i]) | |
| if prefix in suppressed: | |
| return True | |
| return False | |
| idx = 0 | |
| while True: | |
| dot = name.find(".", idx) | |
| if dot == -1: | |
| return name in suppressed | |
| prefix = name[:dot] | |
| if prefix in suppressed: | |
| return True | |
| idx = dot + 1 |
(I'm not a mypy maintainer, I just noticed that you are building a new string a number of times, which would seem unnecessary, particularly for very.long.module.names.like.this._and.stuff)
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.
When a stub imports from a module without stubs (e.g., protobuf stubs importing from google.protobuf when protobuf stubs aren't installed), the import is suppressed but a cross-ref is cached. On cache reload, resolving the cross-ref fails along the lines of:
This occurs because the cross-ref points to a module that was suppressed and therefore never loaded into manager.modules.
The fix passes the set of suppressed modules to fixup_module() and checks if a cross-ref points to a suppressed module before attempting lookup. If so, a placeholder node is used instead.
Before this change on my test setup (see #20655) with 128 shards iterating through different dependency combination, 29 crashed with this error. With the change 0 do so. The reproduction at Qiskit/qiskit-serverless#1787 also passes for me with this change.
Fixes #16214
Disclaimer: I don't have prior familiarity with the mypy codebase and this change was heavily LLM assisted.