resolve type aliases - #6944
Conversation
Greptile SummaryThe PR adds support for resolving native and backported
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| packages/reflex-base/src/reflex_base/utils/types.py | Adds recursive type-alias resolution and generic parameter substitution helpers. |
| packages/reflex-base/src/reflex_base/vars/base.py | Resolves aliases before applying the existing Var.guess_type dispatch. |
| tests/units/reflex_base/utils/test_types.py | Covers ParamSpec substitution alongside a variadic type parameter. |
| tests/units/reflex_base/vars/test_base.py | Places the new alias-resolution tests in the required source-corresponding suite and covers bare, parameterized, variadic, optional, and state-field aliases. |
Reviews (10): Last reviewed commit: "fix: resolve subscripted, variadic and P..." | Re-trigger Greptile
Merging this PR will not alter performance
Comparing Footnotes
|
572b04c to
fb3c49e
Compare
There was a problem hiding this comment.
All reported issues were addressed across 4 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
There was a problem hiding this comment.
All reported issues were addressed across 3 files (changes from recent commits).
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
|
welp, i marked approve before i saw the py3.10 regression; thanks for the quick fixup |
|
yeah, i sadly missed this yesterday, because main has been red.. |
There was a problem hiding this comment.
All reported issues were addressed across 1 file (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
pydantic_optional (#6786): bare/pydantic/db extras and the in-place upgrade path all verified end-to-end in the browser; no regressions vs 0.9.8. Two low-severity error-message papercuts recorded. typing_python (#6944/#6890/#6846): PEP 695 aliases compile and render on 3.11-3.14, and Python 3.14 builtin-annotation handling passes fully. Found: runtime assignment to an alias-annotated state var raises TypeError in State.__setattr__ (high — mutating handlers die), and an uncalled handler with an alias-annotated arg crashes page compile. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EMjBXPozsNeQNSBZecNH8x
19 confirmed issues (1 high, 9 medium, 9 low) with repro steps, verifier root-cause analysis, and verification notes; 2 refuted claims; and per-cluster summaries for all 11 feature-exploration clusters (32 agents, 0 errors). Headline confirmed issues: PEP695 alias state vars cannot be mutated at runtime (#6944 gap); background-task on_load cancelled on navigation (undocumented behavior change); client_error no-arg TypeError; upload sanitizer '..' traversal; react-router-dom custom components silently install RR7 in dev; reflex run hangs after fatal node-version error; breaking API removals give bare errors. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EMjBXPozsNeQNSBZecNH8x
PR reflex-dev#6944 added resolve_type_alias() but wired it only into Var.guess_type, so alias-annotated state vars compiled while every runtime path that re-checks the raw annotation still choked on the TypeAliasType: - State.__setattr__ validates assignments through _isinstance(), which fell through to the bare isinstance() call and raised "TypeError: isinstance() arg 2 must be a type" on every assignment to an alias-annotated var, aborting the event handler instead of at most logging a mismatch (0.9.9a1 pre-release FINDING-002). - Passing an event handler with an alias-annotated argument uncalled to an event trigger crashed page compile: typehint_issubclass() reached the bare issubclass() for a plain alias and failed the origin comparison for a subscripted one, escalating to a fatal error (FINDING-006). Resolve the alias at the entry of both functions, reusing resolve_type_alias(), which already handles parameterized aliases (Items[str]) and aliases nested in unions (Key | None). Alias-annotated vars now behave exactly like their resolved annotations at runtime. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EMjBXPozsNeQNSBZecNH8x
PR #6944 added resolve_type_alias() but wired it only into Var.guess_type, so alias-annotated state vars compiled while every runtime path that re-checks the raw annotation still choked on the TypeAliasType: - State.__setattr__ validates assignments through _isinstance(), which fell through to the bare isinstance() call and raised "TypeError: isinstance() arg 2 must be a type" on every assignment to an alias-annotated var, aborting the event handler instead of at most logging a mismatch (0.9.9a1 pre-release FINDING-002). - Passing an event handler with an alias-annotated argument uncalled to an event trigger crashed page compile: typehint_issubclass() reached the bare issubclass() for a plain alias and failed the origin comparison for a subscripted one, escalating to a fatal error (FINDING-006). Resolve the alias at the entry of both functions, reusing resolve_type_alias(), which already handles parameterized aliases (Items[str]) and aliases nested in unions (Key | None). Alias-annotated vars now behave exactly like their resolved annotations at runtime. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EMjBXPozsNeQNSBZecNH8x
…6986) * Resolve PEP 695 type aliases in _isinstance and typehint_issubclass PR #6944 added resolve_type_alias() but wired it only into Var.guess_type, so alias-annotated state vars compiled while every runtime path that re-checks the raw annotation still choked on the TypeAliasType: - State.__setattr__ validates assignments through _isinstance(), which fell through to the bare isinstance() call and raised "TypeError: isinstance() arg 2 must be a type" on every assignment to an alias-annotated var, aborting the event handler instead of at most logging a mismatch (0.9.9a1 pre-release FINDING-002). - Passing an event handler with an alias-annotated argument uncalled to an event trigger crashed page compile: typehint_issubclass() reached the bare issubclass() for a plain alias and failed the origin comparison for a subscripted one, escalating to a fatal error (FINDING-006). Resolve the alias at the entry of both functions, reusing resolve_type_alias(), which already handles parameterized aliases (Items[str]) and aliases nested in unions (Key | None). Alias-annotated vars now behave exactly like their resolved annotations at runtime. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EMjBXPozsNeQNSBZecNH8x * Make PEP 695 alias resolution zero-cost on alias-free type checks The unconditional resolve_type_alias() at the entry of _isinstance and typehint_issubclass ran on every recursive per-item and per-member call, regressing event processing by ~28% (local pytest-benchmark mean; CodSpeed -13.6%) even though no alias was present. Move resolution to the exact points where an alias becomes opaque: - _isinstance: catch the TypeError from isinstance() on a bare alias (zero-cost try on the hot path, mirroring safe_issubclass) and check the already-computed origin for subscripted aliases; union and Literal branches resolve alias members through their existing per-member recursion. - typehint_issubclass: same try/except in the non-generic issubclass branch, a one-sided check before each union decomposition (so an alias of a union keeps union semantics), and a two-sided check before the final origin comparison. - resolve_type_alias: rebuild a union only when a member actually resolved, instead of allocating a resolved tuple on every call (also helps Var.guess_type, which calls it unconditionally). Local microbench (20k-iter timeit, best of runs) vs origin/main: _isinstance('x', str|None) 1.61us -> 1.62us (was 4.78us), typehint_issubclass(str, str|None) 1.81us -> 1.89us (was 5.98us), _isinstance(list(range(20)), list[int], nested=1) 16.4us -> 16.7us (was 26.9us). test_process_event mean back inside main's noise band (2.78-2.96ms main, 2.87-3.09ms fixed, 3.72-3.79ms before). Also add the review-requested regression test for uncalled alias-annotated handlers through call_event_handler (previously the opaque "Could not compare types" TypeError at page compile), alias-of- union coverage locking the guard placement, and the missing docstring on _type_alias_types() in the types tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EMjBXPozsNeQNSBZecNH8x * Check subscripted-alias origin lazily in _isinstance's fallback CodSpeed still flagged test_isinstance_container[list_dict] (-7.58%): the isinstance(origin, TypeAliasTypes) probe ran on every generic check before the args dispatch. Move it into the final fallback's TypeError handler — a subscripted alias matches none of the container branches and get_base_class hands the opaque alias back, so the existing isinstance there raises deterministically. Alias-free generic checks now pay nothing; interleaved local A/B puts this at parity with main (8.4ms vs 8.45ms; previous head 9.07ms) on the flagged benchmark. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EMjBXPozsNeQNSBZecNH8x --------- Co-authored-by: Claude <noreply@anthropic.com>
A ~29s 1920x1080 motion graphic covering the end-user-facing changes in 0.9.9, sourced from the 0.9.9a1 and 0.9.9a2 changelog entries across reflex, reflex-base, the component packages and reflex-hosting-cli. Nine beats: the dev-mode main-thread win (#6905), call-site auto-memoization of @rx.memo (#6949), the move to React Router 8 (#6854), DevTools component naming (#6945), stdlib logging with --json plus the client_error report (#6863, #6865, #6827), the cloud CLI's whoami/token and autoscaling flags (#6918, #6884, #6948), and a grid of the smaller fixes a user would notice (#6786, #6593, #6944, #6971, #6790, #6920). Styled to match reflex.dev by reusing its design system rather than approximating it: the dark violet/slate scales, wave-line motif, radial bloom and type scale come from reflex-site-shared, and the fonts are the same @fontsource-variable Instrument Sans and JetBrains Mono files the site serves. Source only — the rendered mp4 is a build artifact, regenerated by `npm run build` and ignored. Lives outside the packaged tree (hatch only includes /reflex), so it does not affect the published wheel or sdist. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016arkVKmoogzUtZNfZZSvSo
Uh oh!
There was an error while loading. Please reload this page.