Skip to content

fix: resolve PEP 695 type aliases when walking annotations - #173

Open
Sanjays2402 wants to merge 2 commits into
drivendataorg:mainfrom
Sanjays2402:fix/pep695-type-aliases
Open

fix: resolve PEP 695 type aliases when walking annotations#173
Sanjays2402 wants to merge 2 commits into
drivendataorg:mainfrom
Sanjays2402:fix/pep695-type-aliases

Conversation

@Sanjays2402

Copy link
Copy Markdown

Closes #118

type X = ... aliases are TypeAliasType objects, which are opaque to typing.get_args() and to typenames.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) in get_recursive_args, is_nullable_type, and _walk_type_tree makes aliases transparent for discovery as well as for the cardinality/modality checks.

test_pep695_type_aliases fails on the current code and passes with the fix. TypeAliasType is imported from typing_extensions below 3.12, which is already a dependency there.

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.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 in get_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.

Comment thread erdantic/typing_utils.py Outdated
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support Python 3.12's type statements for declaring type aliases

3 participants