Repository navigation
Stop recursive type alias expansion on Python 3.10 (0.2.4) - #18
Merged
Merged
Conversation
Since 0.2.1 (0da0ee8), resolved_class_annotations expanded nested type strings left by Python 3.10's get_type_hints with no stop. A recursive alias such as WireValue = str | list["WireValue"] | dict[str, "WireValue"] re-evaluated its own name forever and raised RecursionError in dataclass_from_mapping (seen in zmqruntime's progress decode test). Expansion now tracks the names being expanded and leaves a self-reference as a ForwardRef, the form get_type_hints returns on Python 3.11+. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Problem
On Python 3.10, zmqruntime's
tests/test_progress_annotation.py::test_progress_mapping_decode_preserves_wire_and_immutable_nested_valuesfails withRecursionError: maximum recursion depth exceeded in __instancecheck__once python-introspect 0.2.x is installed. Python 3.11 and later pass.Bisected from v0.1.16 to v0.2.3 with that test: the first bad commit is 0da0ee8 ("resolve recursive sequence declarations on Python 3.10", 0.2.1). PyPI first shipped it in 0.2.2.
Root cause
_resolve_nested_type_stringsevaluates the strings that 3.10'sget_type_hintsleaves inside PEP 585 aliases. A recursive alias (WireValue = str | ... | list["WireValue"] | dict[str, "WireValue"]) names itself. Each evaluation gives back the same strings, so expansion never ends. On 3.11 and later,get_type_hintsalready leaves the inner self-reference as aForwardRef, so the resolver never re-enters it.Fix
The resolver tracks the names it is currently expanding. When a name refers back to itself, it returns
ForwardRef(name), the same form 3.11+ produces, so the decoder sees the same declaration on every version. There is no version check.Tests
test_recursive_type_alias_decodes_nested_valuesreproduces the zmqruntime declaration. It fails on 3.10 without the fix.tests/test_progress_annotation.py: 5 passed, 2 skipped on 3.10 and on 3.11 (it failed on 3.10 before the fix).Version 0.2.4, with a CHANGELOG entry. Not tagged.
🤖 Generated with Claude Code