Skip to content

feat[eve]: resolve PEP 695 type aliases in runtime annotation introspection - #2753

Closed
egparedes wants to merge 4 commits into
mainfrom
pep695-a-eve-type-alias-resolution
Closed

feat[eve]: resolve PEP 695 type aliases in runtime annotation introspection#2753
egparedes wants to merge 4 commits into
mainfrom
pep695-a-eve-type-alias-resolution

Conversation

@egparedes

Copy link
Copy Markdown
Contributor

Description

First PR in a stack adding PEP 695 (type X = ...) type-alias support, now that the Python floor is 3.12 (#2326).

GT4Py introspects annotations at runtime in several places, and none of them understand TypeAliasType. On current main a type alias fails at class-definition time:

type MyAlias = int

class Model(eve.datamodels.DataModel):
    x: MyAlias          # EveValueError: MyAlias type annotation is not supported.
    y: list[MyAlias]    # ... nested fails too

This PR fixes that for gt4py.eve. The follow-up PRs in the stack fix the user-facing gt4py.next DSL path (where the same gap produces a bare ValueError with no source location) and add diagnostics for PEP 695 syntax written inside GT4Py functions.

Note that PEP 695 generics (class Model[T](DataModel)) already work unchanged and are not touched here — only the alias form was broken.

What changed

  • eve.extended_typing: new is_type_alias() and eval_type_alias(). The latter follows alias chains, substitutes type parameters for parametrized aliases (MyAlias[int]), returns the identical object for non-aliases, and raises TypeError on recursive aliases (type A = A) via a depth cap.
  • eve.type_validation: one branch in the annotation dispatch of SimpleTypeValidatorFactory.__call__. Since that function already recurses into type arguments, nesting is handled for free.
  • eve.datamodels: alias unwrapping in _make_type_converter (for Coerced[...] fields), and deferral of not-yet-resolvable aliases in field_type_validator_factory.
  • ADR docs/development/ADRs/eve/0001 (new eve/ ADR subsystem directory).

Two things worth a reviewer's attention

xtyping.TypeAliasType is a trap. Because extended_typing star-imports both typing and typing_extensions, that name resolves to the typing_extensions class — and a native type X = ... alias is not an instance of it:

isinstance(Native, xtyping.TypeAliasType)   # False  <-- the obvious check silently never matches
isinstance(Native, typing.TypeAliasType)    # True

hasattr(x, "__value__") is the other trap: it is True for MyAlias[int] by attribute proxying to the origin, while isinstance() is False. Hence a single is_type_alias() predicate checking both classes, rather than isinstance checks spread over call sites. This is the main thing the ADR records.

NameError is a signal, not an error. Alias values are evaluated lazily, so type LazyAlias = DefinedLater raises NameError until DefinedLater exists. type_validation deliberately lets it propagate and datamodels catches it to install the existing ForwardRefValidator, deferring validation to first instantiation — the same treatment string forward references already get. Accepted consequence: that field's errors surface later, and report the bare field name rather than the qualified Model.field, matching existing forward-reference behavior.

Requirements

  • All fixes and/or new features come with corresponding tests.
  • Important design decisions have been documented in the appropriate ADR inside the docs/development/ADRs/ folder.

Validation

  • uv run pytest tests/eve_tests -q -n 4 — 390 passed
  • uv run pytest --doctest-modules -q src/gt4py/eve — 54 passed
  • uv run mypy src/ — no issues in 358 source files
  • uv run tach check — all modules validated
  • uv run pre-commit run --files <changed> — all hooks pass

@egparedes
egparedes marked this pull request as draft August 6, 2026 06:31
@egparedes

Copy link
Copy Markdown
Contributor Author

Superseded by #2754.

This PR covered only the eve half of the PEP 695 work and was the bottom of a two-PR stack. #2754 replaces it with the complete change on a single branch: the same four commits, plus the gt4py.next side (alias resolution in from_type_hint, and annotation failures reported as located DSL diagnostics), plus a fix for a third annotation-dispatch funnel — get_represented_types — that this PR left out and that fails silently rather than raising.

The bugs found alongside it, which are independent of PEP 695, are in #2755.

@egparedes egparedes closed this Aug 6, 2026
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.

1 participant