Skip to content

Fix Python 3.14 event handler annotation resolution - #6896

Open
harsh21234i wants to merge 6 commits into
reflex-dev:mainfrom
harsh21234i:fix/6890-python314
Open

Fix Python 3.14 event handler annotation resolution#6896
harsh21234i wants to merge 6 commits into
reflex-dev:mainfrom
harsh21234i:fix/6890-python314

Conversation

@harsh21234i

@harsh21234i harsh21234i commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #6890.

Python 3.14 evaluates deferred method annotations using the owning class
namespace. Runtime attributes on a state class can therefore shadow builtin
annotation names such as dict.

This caused valid handlers like:

def on_event(self, event: dict):
...

to fail during event argument validation.

Changes

  • Cache annotations for state-bound event handlers before runtime class patches.
  • Use cached annotations for event and upload-handler validation.
  • Preserve partial-handler support and unresolved forward-reference fallback.
  • Avoid eager annotation resolution for unbound synthetic handlers.
  • Add Python 3.14 regression coverage.
  • Add changelog fragments.

Testing

  • Python 3.14 regression test passed
  • tests/units/test_event.py: 107 passed
  • Ruff check passed
  • Ruff format passed
  • Diff check passed

@harsh21234i
harsh21234i requested a review from a team as a code owner August 17, 2026 05:45
@harsh21234i

Copy link
Copy Markdown
Contributor Author

Hi, I created this clean replacement PR for #6890 from the latest main branch.

The previous PR included unrelated commits from #6841, so this PR contains only
the Python 3.14 event-handler annotation fix. I also adjusted the implementation
to avoid eager annotation work for unbound synthetic handlers after CodSpeed
reported a performance regression.

The Python 3.14 regression test and all 107 event unit tests pass, along with
Ruff formatting and lint checks.

@codspeed-hq

codspeed-hq Bot commented Aug 17, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 26 untouched benchmarks
⏩ 8 skipped benchmarks1


Comparing harsh21234i:fix/6890-python314 (d3092cb) with main (092aa4f)

Open in CodSpeed

Footnotes

  1. 8 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@greptile-apps

greptile-apps Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR caches successfully resolved state-handler annotations before runtime class patches and reuses them for event and upload validation. It also preserves retries for late-bound annotations and adds Python 3.14 regression coverage.

  • Adds an annotation cache to EventHandler.
  • Routes event and upload validation through the cached annotation helper.
  • Adds regression tests and changelog fragments.

Confidence Score: 4/5

The PR should not merge until unresolved handler annotations are protected from being retried against an already patched state-class namespace.

The permanent-cache regression is fixed, but the previously reported uncached fallback remains: an initial NameError leaves no stable annotation snapshot, and event or upload validation can later resolve the annotation after runtime class attributes begin shadowing names on Python 3.14.

Files Needing Attention: packages/reflex-base/src/reflex_base/event/init.py

Important Files Changed

Filename Overview
packages/reflex-base/src/reflex_base/event/init.py Centralizes annotation resolution and caching, but the uncached unresolved-annotation fallback still permits a later retry after state-class namespace patching.
tests/units/test_event.py Covers stable builtin resolution and successful late-bound retries, but not their combined sequence of initial failure followed by class patching.
news/6890.bugfix.md Accurately describes the intended Python 3.14 annotation-shadowing fix.
packages/reflex-base/news/6890.bugfix.md Adds the corresponding reflex-base bug-fix changelog fragment.

Reviews (4): Last reviewed commit: "Annotate deliberate unresolved type test" | Re-trigger Greptile

Comment thread packages/reflex-base/src/reflex_base/event/__init__.py

@cubic-dev-ai cubic-dev-ai Bot 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.

All reported issues were addressed

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread packages/reflex-base/src/reflex_base/event/__init__.py Outdated
Comment thread packages/reflex-base/src/reflex_base/event/__init__.py
Comment thread packages/reflex-base/src/reflex_base/event/__init__.py Outdated

@cubic-dev-ai cubic-dev-ai Bot 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.

All reported issues were addressed across 2 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread packages/reflex-base/src/reflex_base/event/__init__.py Outdated
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.

Python 3.14: event handler annotations resolve against the owning class namespace, breaking event: dict handlers

1 participant