Skip to content

feat(event): accept any sequence of events where a list of them is accepted - #7402

Merged
FarhanAliRaza merged 18 commits into
reflex-dev:mainfrom
benedikt-bartscher:event-sequences
Oct 15, 2026
Merged

FarhanAliRaza merged 18 commits into
reflex-dev:mainfrom
benedikt-bartscher:event-sequences

Conversation

@benedikt-bartscher

@benedikt-bartscher benedikt-bartscher commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

An event prop accepted a list literal of events, but not a list variable:

events: list[EventSpec] = [rx.redirect("/x"), rx.console_log("y")]
rx.button(on_click=events)  # rejected by pyright and ty

EventType spelled its list form list[...] of every kind of event, and lists are
invariant, so a list[EventSpec] or a list[EventCallback[()]] is not one of those.
At runtime the same holds for tuples: EventChain.create, format_queue_events,
Event.from_event_type and fix_events only took a list, while call_event_fn
already took a tuple from a lambda and _check_valid_yield already let a handler
return a tuple (return a, b), which from_event_type then rejected as an
unexpected event type.

EventType now spells it Sequence[...], which is covariant, and those places
take any sequence other than a string through is_non_string_sequence, a TypeIs
helper in reflex_base.utils.types, so the runtime accepts exactly what the type
does. A Var is not a Sequence, so nothing that was a single event becomes a
sequence. A page's on_load (App._commit_page) reads the value the same way, so
on_load=(a, b) registers both events instead of one tuple. The internal demo and
intro forms check their on_submit against Sequence directly, since their
declared reflex floor predates the helper, and reject a string up front.

from_event_type runs for every event a handler returns, so it checks the single
event kinds before the Sequence ABC, as _check_valid_yield does: a single
Event, EventSpec or callable costs what it did with the list check.

tests/type_checking/event.py passes a list[EventSpec] variable and a tuple of
handlers to an EventType[()] parameter; it fails under pyright and ty before this
change. Unit tests cover a tuple in each of the runtime places, the full unit suite
and pyright pass.

@greptile-apps

greptile-apps Bot commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The PR appears safe to merge; the dependency-floor change addresses the outstanding import failure.

Summary

The PR lets event props, returned events, page loaders, and internal forms accept non-string sequences.

  • Event props and handler results accept any non-string sequence of events.
  • Pages register every event in an on_load tuple.
  • The demo and intro forms accept tuple submit events.

Reviews (15) · Last reviewed commit: "build(internal): require the reflex that..." · Reviewed by Greptile

@codspeed

codspeed Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Merging this PR will degrade performance by 4.05%

⚠️ 12 benchmarks spent significant time in system calls

System calls cannot be consistently instrumented, so they are not included in the measure, which understates the real cost. Please switch to the Walltime instrument to accurately measure system calls.

Measurement and system calls

❌ 1 regressed benchmark
✅ 147 untouched benchmarks

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
❌ test_hydration_snapshot[200] 8.6 ms 8.9 ms -4.05%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing benedikt-bartscher:event-sequences (dc13e2e) with main (81f463b)

Open in CodSpeed

@benedikt-bartscher
benedikt-bartscher marked this pull request as ready for review October 3, 2026 12:34
@benedikt-bartscher
benedikt-bartscher requested a review from a team as a code owner October 3, 2026 12:34

@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 13 files

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

Re-trigger cubic

@masenf masenf added the on deck PRs lined up to review / merge next label Oct 5, 2026
Comment thread packages/reflex-base/src/reflex_base/event/__init__.py
call_event_fn only split a list or tuple, so a lambda returning another
sequence such as a UserList was wrapped as one event and rejected.
Comment thread packages/reflex-base/src/reflex_base/utils/types.py Outdated
Comment thread packages/reflex-base/src/reflex_base/event/__init__.py Outdated
is_non_string_sequence checks list and tuple before the Sequence ABC, and
excludes bytes as well as str. _check_valid_yield uses it instead of its own
copy of the check.

from_event_type, fix_events and call_event_fn wrap a single event through
one _event_sequence helper. EventChain.create keeps its own branches, so a
bad top-level value still reports "Invalid event chain".

The demo and intro forms drop the string guard: the type already excludes
a str, and the event chain rejects one anyway.

Tests cover a handler that returns or yields a tuple through the event
processor, and which values count as a sequence.
FarhanAliRaza
FarhanAliRaza previously approved these changes Oct 13, 2026

@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 10 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

View guided diff | Re-trigger cubic

Comment thread packages/reflex-base/src/reflex_base/event/__init__.py
Comment thread tests/units/test_event.py
Comment thread reflex/app.py
Comment thread tests/type_checking/event.py
reflex/app.py imports is_non_string_sequence, which reflex-base 0.10.0 lacks.
…_sequence"

pin-exact rewrites the reflex-base requirement to == <version> at build time, so
a released reflex never installs with an older reflex-base.
The demo and intro forms turn their on_submit into a list of events with
reflex_base.event.event_sequence instead of their own isinstance check.
# Conflicts:
#	packages/reflex-components-internal/src/reflex_components_internal/blocks/demo_form.py
#	tests/type_checking/event.py
#	tests/units/reflex_components_internal/blocks/test_demo_form.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 across 5 files (changes from recent commits).

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

View guided diff | Re-trigger cubic

The demo and intro forms import event_sequence, which reflex 0.10.0 and older lack.
@FarhanAliRaza
FarhanAliRaza merged commit 2f71cdf into reflex-dev:main Oct 15, 2026
143 of 144 checks passed
@benedikt-bartscher
benedikt-bartscher deleted the event-sequences branch October 16, 2026 09:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

on deck PRs lined up to review / merge next

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants