fix: resolve PEP 695 type aliases when walking annotations - #173
Open
Sanjays2402 wants to merge 2 commits into
Open
fix: resolve PEP 695 type aliases when walking annotations#173Sanjays2402 wants to merge 2 commits into
Sanjays2402 wants to merge 2 commits into
Conversation
Type aliases declared with Python 3.12's `type` statement are `TypeAliasType` objects, which are opaque to `typing.get_args()` and to `typenames.parse_type_tree()` - recursion stopped at the alias itself. A field annotated with such an alias therefore yielded no leaf types, so the referenced model was never discovered and no edge was drawn. Unwrap `TypeAliasType.__value__` (repeatedly, since aliases can chain) in `get_recursive_args`, `is_nullable_type`, and `_walk_type_tree`, so aliases are transparent for model discovery as well as for the cardinality and modality checks.
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes discovery of models referenced through PEP 695 (type X = ...) type aliases by unwrapping TypeAliasType.__value__ during annotation traversal, so aliases no longer stop recursion and cause missing edges/models in generated diagrams.
Changes:
- Add
_resolve_type_alias()and apply it inget_recursive_args(),is_nullable_type(), and_walk_type_tree()to make PEP 695 aliases transparent during type walking. - Add regression tests covering direct, chained, nested (e.g.,
List[Alias]), and optional aliases. - Document the fix in the unreleased changelog.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
erdantic/typing_utils.py |
Unwraps PEP 695 TypeAliasType while walking type trees / args so referenced models behind aliases are discovered. |
tests/test_typing_utils.py |
Adds regression tests ensuring alias unwrapping works for recursion, collection detection, and nullability checks. |
CHANGELOG.md |
Notes the PEP 695 alias resolution fix and links the tracked issue. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Aliases can be cyclic (type A = B / type B = A) or self-referential (type Rec = list[Rec]). The unwrap loop had no cycle detection and hung. Track the aliases already unwrapped on the current path and stop at the first repeat, returning that alias unresolved.
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.
Closes #118
type X = ...aliases areTypeAliasTypeobjects, which are opaque totyping.get_args()and totypenames.parse_type_tree(), so recursion stopped at the alias and the model behind it was never discovered — the field produced no edge and the inner model was missing from the diagram. Unwrapping__value__(in a loop, since aliases can chain) inget_recursive_args,is_nullable_type, and_walk_type_treemakes aliases transparent for discovery as well as for the cardinality/modality checks.test_pep695_type_aliasesfails on the current code and passes with the fix.TypeAliasTypeis imported fromtyping_extensionsbelow 3.12, which is already a dependency there.