reflex 0.6.8a1__py3-none-any.whl → 0.7.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of reflex might be problematic. Click here for more details.
- reflex/.templates/jinja/custom_components/pyproject.toml.jinja2 +1 -1
- reflex/.templates/jinja/web/pages/_app.js.jinja2 +7 -7
- reflex/.templates/jinja/web/pages/utils.js.jinja2 +3 -3
- reflex/.templates/web/components/reflex/radix_themes_color_mode_provider.js +1 -4
- reflex/.templates/web/utils/state.js +65 -36
- reflex/__init__.py +4 -17
- reflex/__init__.pyi +1 -2
- reflex/app.py +286 -135
- reflex/app_mixins/lifespan.py +9 -9
- reflex/app_mixins/middleware.py +6 -6
- reflex/app_module_for_backend.py +3 -7
- reflex/base.py +7 -7
- reflex/compiler/compiler.py +8 -0
- reflex/compiler/utils.py +57 -18
- reflex/components/base/app_wrap.pyi +16 -16
- reflex/components/base/bare.py +1 -1
- reflex/components/base/body.pyi +16 -16
- reflex/components/base/document.pyi +76 -76
- reflex/components/base/error_boundary.py +2 -1
- reflex/components/base/error_boundary.pyi +19 -22
- reflex/components/base/fragment.pyi +16 -16
- reflex/components/base/head.pyi +31 -31
- reflex/components/base/link.pyi +31 -31
- reflex/components/base/meta.py +2 -2
- reflex/components/base/meta.pyi +61 -61
- reflex/components/base/script.pyi +19 -19
- reflex/components/base/strict_mode.py +10 -0
- reflex/components/base/strict_mode.pyi +57 -0
- reflex/components/component.py +38 -77
- reflex/components/core/banner.py +159 -4
- reflex/components/core/banner.pyi +162 -76
- reflex/components/core/breakpoints.py +3 -1
- reflex/components/core/client_side_routing.py +1 -1
- reflex/components/core/client_side_routing.pyi +32 -32
- reflex/components/core/clipboard.pyi +17 -20
- reflex/components/core/cond.py +9 -10
- reflex/components/core/debounce.py +1 -1
- reflex/components/core/debounce.pyi +17 -17
- reflex/components/core/foreach.py +28 -3
- reflex/components/core/html.py +1 -1
- reflex/components/core/html.pyi +16 -16
- reflex/components/core/match.py +5 -5
- reflex/components/core/sticky.py +134 -0
- reflex/components/core/sticky.pyi +449 -0
- reflex/components/core/upload.py +2 -2
- reflex/components/core/upload.pyi +80 -88
- reflex/components/datadisplay/code.py +5 -14
- reflex/components/datadisplay/code.pyi +31 -31
- reflex/components/datadisplay/dataeditor.py +7 -4
- reflex/components/datadisplay/dataeditor.pyi +40 -54
- reflex/components/datadisplay/logo.py +13 -8
- reflex/components/datadisplay/shiki_code_block.py +14 -9
- reflex/components/datadisplay/shiki_code_block.pyi +46 -46
- reflex/components/dynamic.py +22 -3
- reflex/components/el/constants/reflex.py +1 -1
- reflex/components/el/element.py +1 -1
- reflex/components/el/element.pyi +16 -16
- reflex/components/el/elements/base.pyi +16 -16
- reflex/components/el/elements/forms.py +4 -4
- reflex/components/el/elements/forms.pyi +224 -258
- reflex/components/el/elements/inline.pyi +421 -421
- reflex/components/el/elements/media.pyi +376 -376
- reflex/components/el/elements/metadata.pyi +91 -91
- reflex/components/el/elements/other.pyi +106 -106
- reflex/components/el/elements/scripts.pyi +46 -46
- reflex/components/el/elements/sectioning.pyi +226 -226
- reflex/components/el/elements/tables.pyi +151 -151
- reflex/components/el/elements/typography.pyi +226 -226
- reflex/components/gridjs/datatable.pyi +31 -31
- reflex/components/lucide/icon.py +46 -8
- reflex/components/lucide/icon.pyi +85 -31
- reflex/components/markdown/markdown.py +10 -8
- reflex/components/markdown/markdown.pyi +16 -16
- reflex/components/moment/moment.py +2 -2
- reflex/components/moment/moment.pyi +17 -19
- reflex/components/next/base.pyi +16 -16
- reflex/components/next/image.py +16 -4
- reflex/components/next/image.pyi +22 -20
- reflex/components/next/link.py +1 -1
- reflex/components/next/link.pyi +16 -16
- reflex/components/next/video.pyi +16 -16
- reflex/components/plotly/__init__.py +29 -2
- reflex/components/plotly/plotly.py +240 -5
- reflex/components/plotly/plotly.pyi +799 -44
- reflex/components/props.py +3 -3
- reflex/components/radix/__init__.pyi +1 -1
- reflex/components/radix/primitives/accordion.py +9 -5
- reflex/components/radix/primitives/accordion.pyi +110 -108
- reflex/components/radix/primitives/base.pyi +31 -31
- reflex/components/radix/primitives/drawer.py +5 -2
- reflex/components/radix/primitives/drawer.pyi +179 -187
- reflex/components/radix/primitives/form.pyi +160 -172
- reflex/components/radix/primitives/progress.py +1 -1
- reflex/components/radix/primitives/progress.pyi +76 -76
- reflex/components/radix/primitives/slider.py +1 -1
- reflex/components/radix/primitives/slider.pyi +78 -82
- reflex/components/radix/themes/base.pyi +121 -121
- reflex/components/radix/themes/color_mode.py +11 -9
- reflex/components/radix/themes/color_mode.pyi +47 -49
- reflex/components/radix/themes/components/alert_dialog.py +3 -0
- reflex/components/radix/themes/components/alert_dialog.pyi +110 -112
- reflex/components/radix/themes/components/aspect_ratio.pyi +16 -16
- reflex/components/radix/themes/components/avatar.pyi +16 -16
- reflex/components/radix/themes/components/badge.pyi +16 -16
- reflex/components/radix/themes/components/button.pyi +16 -16
- reflex/components/radix/themes/components/callout.pyi +76 -76
- reflex/components/radix/themes/components/card.py +1 -1
- reflex/components/radix/themes/components/card.pyi +17 -17
- reflex/components/radix/themes/components/checkbox.pyi +49 -55
- reflex/components/radix/themes/components/checkbox_cards.pyi +31 -31
- reflex/components/radix/themes/components/checkbox_group.pyi +31 -31
- reflex/components/radix/themes/components/context_menu.py +5 -0
- reflex/components/radix/themes/components/context_menu.pyi +149 -155
- reflex/components/radix/themes/components/data_list.pyi +61 -61
- reflex/components/radix/themes/components/dialog.py +3 -0
- reflex/components/radix/themes/components/dialog.pyi +113 -117
- reflex/components/radix/themes/components/dropdown_menu.py +5 -0
- reflex/components/radix/themes/components/dropdown_menu.pyi +133 -137
- reflex/components/radix/themes/components/hover_card.py +3 -0
- reflex/components/radix/themes/components/hover_card.pyi +63 -67
- reflex/components/radix/themes/components/icon_button.py +2 -2
- reflex/components/radix/themes/components/icon_button.pyi +17 -16
- reflex/components/radix/themes/components/inset.pyi +16 -16
- reflex/components/radix/themes/components/popover.py +3 -0
- reflex/components/radix/themes/components/popover.pyi +68 -70
- reflex/components/radix/themes/components/progress.pyi +16 -16
- reflex/components/radix/themes/components/radio.pyi +16 -16
- reflex/components/radix/themes/components/radio_cards.py +2 -0
- reflex/components/radix/themes/components/radio_cards.pyi +32 -34
- reflex/components/radix/themes/components/radio_group.py +1 -1
- reflex/components/radix/themes/components/radio_group.pyi +62 -64
- reflex/components/radix/themes/components/scroll_area.pyi +16 -16
- reflex/components/radix/themes/components/segmented_control.pyi +32 -35
- reflex/components/radix/themes/components/select.py +4 -0
- reflex/components/radix/themes/components/select.pyi +145 -157
- reflex/components/radix/themes/components/separator.pyi +16 -16
- reflex/components/radix/themes/components/skeleton.py +3 -0
- reflex/components/radix/themes/components/skeleton.pyi +16 -16
- reflex/components/radix/themes/components/slider.pyi +22 -28
- reflex/components/radix/themes/components/spinner.pyi +16 -16
- reflex/components/radix/themes/components/switch.pyi +17 -19
- reflex/components/radix/themes/components/table.pyi +106 -106
- reflex/components/radix/themes/components/tabs.py +3 -0
- reflex/components/radix/themes/components/tabs.pyi +78 -82
- reflex/components/radix/themes/components/text_area.py +12 -0
- reflex/components/radix/themes/components/text_area.pyi +21 -33
- reflex/components/radix/themes/components/text_field.py +1 -1
- reflex/components/radix/themes/components/text_field.pyi +52 -80
- reflex/components/radix/themes/components/tooltip.py +6 -1
- reflex/components/radix/themes/components/tooltip.pyi +20 -21
- reflex/components/radix/themes/layout/__init__.pyi +1 -1
- reflex/components/radix/themes/layout/base.pyi +16 -16
- reflex/components/radix/themes/layout/box.pyi +16 -16
- reflex/components/radix/themes/layout/center.pyi +16 -16
- reflex/components/radix/themes/layout/container.pyi +16 -16
- reflex/components/radix/themes/layout/flex.pyi +16 -16
- reflex/components/radix/themes/layout/grid.pyi +16 -16
- reflex/components/radix/themes/layout/list.py +2 -2
- reflex/components/radix/themes/layout/list.pyi +76 -76
- reflex/components/radix/themes/layout/section.pyi +16 -16
- reflex/components/radix/themes/layout/spacer.pyi +16 -16
- reflex/components/radix/themes/layout/stack.py +2 -2
- reflex/components/radix/themes/layout/stack.pyi +46 -46
- reflex/components/radix/themes/typography/blockquote.pyi +16 -16
- reflex/components/radix/themes/typography/code.pyi +16 -16
- reflex/components/radix/themes/typography/heading.pyi +16 -16
- reflex/components/radix/themes/typography/link.py +1 -1
- reflex/components/radix/themes/typography/link.pyi +16 -16
- reflex/components/radix/themes/typography/text.py +2 -2
- reflex/components/radix/themes/typography/text.pyi +106 -106
- reflex/components/react_player/audio.pyi +33 -39
- reflex/components/react_player/react_player.py +1 -1
- reflex/components/react_player/react_player.pyi +32 -38
- reflex/components/react_player/video.pyi +33 -39
- reflex/components/recharts/__init__.py +2 -0
- reflex/components/recharts/__init__.pyi +2 -0
- reflex/components/recharts/cartesian.pyi +282 -282
- reflex/components/recharts/charts.py +15 -15
- reflex/components/recharts/charts.pyi +164 -164
- reflex/components/recharts/general.py +19 -4
- reflex/components/recharts/general.pyi +132 -81
- reflex/components/recharts/polar.py +2 -2
- reflex/components/recharts/polar.pyi +55 -55
- reflex/components/recharts/recharts.py +4 -4
- reflex/components/recharts/recharts.pyi +31 -31
- reflex/components/sonner/toast.py +15 -13
- reflex/components/sonner/toast.pyi +22 -22
- reflex/components/suneditor/editor.py +6 -4
- reflex/components/suneditor/editor.pyi +26 -40
- reflex/components/tags/iter_tag.py +3 -3
- reflex/components/tags/tag.py +25 -3
- reflex/config.py +48 -20
- reflex/constants/__init__.py +1 -0
- reflex/constants/base.py +4 -1
- reflex/constants/compiler.py +5 -2
- reflex/constants/config.py +8 -1
- reflex/constants/installer.py +9 -9
- reflex/constants/style.py +1 -1
- reflex/custom_components/custom_components.py +18 -10
- reflex/event.py +228 -233
- reflex/experimental/__init__.py +19 -11
- reflex/experimental/client_state.py +53 -28
- reflex/experimental/hooks.py +5 -5
- reflex/experimental/layout.py +8 -5
- reflex/experimental/layout.pyi +79 -83
- reflex/experimental/misc.py +3 -3
- reflex/istate/wrappers.py +1 -1
- reflex/middleware/hydrate_middleware.py +2 -2
- reflex/model.py +11 -6
- reflex/page.py +5 -5
- reflex/reflex.py +104 -26
- reflex/route.py +1 -1
- reflex/state.py +358 -401
- reflex/style.py +27 -3
- reflex/testing.py +34 -39
- reflex/utils/build.py +6 -2
- reflex/utils/codespaces.py +1 -4
- reflex/utils/compat.py +6 -5
- reflex/utils/console.py +71 -21
- reflex/utils/exceptions.py +89 -26
- reflex/utils/exec.py +69 -74
- reflex/utils/export.py +6 -1
- reflex/utils/format.py +8 -40
- reflex/utils/imports.py +5 -2
- reflex/utils/lazy_loader.py +7 -1
- reflex/utils/path_ops.py +74 -14
- reflex/utils/prerequisites.py +345 -68
- reflex/utils/processes.py +45 -32
- reflex/utils/pyi_generator.py +39 -33
- reflex/utils/registry.py +4 -4
- reflex/utils/serializers.py +1 -1
- reflex/utils/telemetry.py +5 -4
- reflex/utils/types.py +42 -18
- reflex/vars/base.py +695 -330
- reflex/vars/datetime.py +6 -7
- reflex/vars/dep_tracking.py +344 -0
- reflex/vars/function.py +11 -5
- reflex/vars/number.py +31 -43
- reflex/vars/object.py +74 -64
- reflex/vars/sequence.py +79 -67
- {reflex-0.6.8a1.dist-info → reflex-0.7.0.dist-info}/METADATA +7 -10
- reflex-0.7.0.dist-info/RECORD +401 -0
- {reflex-0.6.8a1.dist-info → reflex-0.7.0.dist-info}/WHEEL +1 -1
- reflex/experimental/assets.py +0 -37
- reflex/proxy.py +0 -119
- reflex-0.6.8a1.dist-info/RECORD +0 -398
- {reflex-0.6.8a1.dist-info → reflex-0.7.0.dist-info}/LICENSE +0 -0
- {reflex-0.6.8a1.dist-info → reflex-0.7.0.dist-info}/entry_points.txt +0 -0
reflex/event.py
CHANGED
|
@@ -4,7 +4,6 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import dataclasses
|
|
6
6
|
import inspect
|
|
7
|
-
import sys
|
|
8
7
|
import types
|
|
9
8
|
import urllib.parse
|
|
10
9
|
from base64 import b64encode
|
|
@@ -25,22 +24,27 @@ from typing import (
|
|
|
25
24
|
overload,
|
|
26
25
|
)
|
|
27
26
|
|
|
28
|
-
import typing_extensions
|
|
29
27
|
from typing_extensions import (
|
|
30
|
-
Concatenate,
|
|
31
|
-
ParamSpec,
|
|
32
28
|
Protocol,
|
|
29
|
+
Self,
|
|
33
30
|
TypeAliasType,
|
|
34
31
|
TypedDict,
|
|
35
32
|
TypeVar,
|
|
33
|
+
TypeVarTuple,
|
|
34
|
+
Unpack,
|
|
36
35
|
get_args,
|
|
37
36
|
get_origin,
|
|
38
37
|
)
|
|
39
38
|
|
|
40
39
|
from reflex import constants
|
|
40
|
+
from reflex.constants.compiler import CompileVars, Hooks, Imports
|
|
41
41
|
from reflex.constants.state import FRONTEND_EVENT_STATE
|
|
42
42
|
from reflex.utils import console, format
|
|
43
|
-
from reflex.utils.exceptions import
|
|
43
|
+
from reflex.utils.exceptions import (
|
|
44
|
+
EventFnArgMismatchError,
|
|
45
|
+
EventHandlerArgTypeMismatchError,
|
|
46
|
+
MissingAnnotationError,
|
|
47
|
+
)
|
|
44
48
|
from reflex.utils.types import ArgsSpec, GenericType, typehint_issubclass
|
|
45
49
|
from reflex.vars import VarData
|
|
46
50
|
from reflex.vars.base import LiteralVar, Var
|
|
@@ -91,33 +95,9 @@ class Event:
|
|
|
91
95
|
return f"{self.token}_{substate}"
|
|
92
96
|
|
|
93
97
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
def background(fn, *, __internal_reflex_call: bool = False):
|
|
98
|
-
"""Decorator to mark event handler as running in the background.
|
|
99
|
-
|
|
100
|
-
Args:
|
|
101
|
-
fn: The function to decorate.
|
|
102
|
-
|
|
103
|
-
Returns:
|
|
104
|
-
The same function, but with a marker set.
|
|
105
|
-
|
|
98
|
+
_EVENT_FIELDS: set[str] = {f.name for f in dataclasses.fields(Event)}
|
|
106
99
|
|
|
107
|
-
|
|
108
|
-
TypeError: If the function is not a coroutine function or async generator.
|
|
109
|
-
"""
|
|
110
|
-
if not __internal_reflex_call:
|
|
111
|
-
console.deprecate(
|
|
112
|
-
"background-decorator",
|
|
113
|
-
"Use `rx.event(background=True)` instead.",
|
|
114
|
-
"0.6.5",
|
|
115
|
-
"0.7.0",
|
|
116
|
-
)
|
|
117
|
-
if not inspect.iscoroutinefunction(fn) and not inspect.isasyncgenfunction(fn):
|
|
118
|
-
raise TypeError("Background task must be async function or generator.")
|
|
119
|
-
setattr(fn, BACKGROUND_TASK_MARKER, True)
|
|
120
|
-
return fn
|
|
100
|
+
BACKGROUND_TASK_MARKER = "_reflex_background_task"
|
|
121
101
|
|
|
122
102
|
|
|
123
103
|
@dataclasses.dataclass(
|
|
@@ -131,7 +111,7 @@ class EventActionsMixin:
|
|
|
131
111
|
event_actions: Dict[str, Union[bool, int]] = dataclasses.field(default_factory=dict)
|
|
132
112
|
|
|
133
113
|
@property
|
|
134
|
-
def stop_propagation(self):
|
|
114
|
+
def stop_propagation(self) -> Self:
|
|
135
115
|
"""Stop the event from bubbling up the DOM tree.
|
|
136
116
|
|
|
137
117
|
Returns:
|
|
@@ -143,7 +123,7 @@ class EventActionsMixin:
|
|
|
143
123
|
)
|
|
144
124
|
|
|
145
125
|
@property
|
|
146
|
-
def prevent_default(self):
|
|
126
|
+
def prevent_default(self) -> Self:
|
|
147
127
|
"""Prevent the default behavior of the event.
|
|
148
128
|
|
|
149
129
|
Returns:
|
|
@@ -154,7 +134,7 @@ class EventActionsMixin:
|
|
|
154
134
|
event_actions={"preventDefault": True, **self.event_actions},
|
|
155
135
|
)
|
|
156
136
|
|
|
157
|
-
def throttle(self, limit_ms: int):
|
|
137
|
+
def throttle(self, limit_ms: int) -> Self:
|
|
158
138
|
"""Throttle the event handler.
|
|
159
139
|
|
|
160
140
|
Args:
|
|
@@ -168,7 +148,7 @@ class EventActionsMixin:
|
|
|
168
148
|
event_actions={"throttle": limit_ms, **self.event_actions},
|
|
169
149
|
)
|
|
170
150
|
|
|
171
|
-
def debounce(self, delay_ms: int):
|
|
151
|
+
def debounce(self, delay_ms: int) -> Self:
|
|
172
152
|
"""Debounce the event handler.
|
|
173
153
|
|
|
174
154
|
Args:
|
|
@@ -183,7 +163,7 @@ class EventActionsMixin:
|
|
|
183
163
|
)
|
|
184
164
|
|
|
185
165
|
@property
|
|
186
|
-
def temporal(self):
|
|
166
|
+
def temporal(self) -> Self:
|
|
187
167
|
"""Do not queue the event if the backend is down.
|
|
188
168
|
|
|
189
169
|
Returns:
|
|
@@ -264,7 +244,7 @@ class EventHandler(EventActionsMixin):
|
|
|
264
244
|
raise EventHandlerTypeError(
|
|
265
245
|
f"Arguments to event handlers must be Vars or JSON-serializable. Got {arg} of type {type(arg)}."
|
|
266
246
|
) from e
|
|
267
|
-
payload = tuple(zip(fn_args, values))
|
|
247
|
+
payload = tuple(zip(fn_args, values, strict=False))
|
|
268
248
|
|
|
269
249
|
# Return the event spec.
|
|
270
250
|
return EventSpec(
|
|
@@ -284,7 +264,7 @@ class EventSpec(EventActionsMixin):
|
|
|
284
264
|
"""
|
|
285
265
|
|
|
286
266
|
# The event handler.
|
|
287
|
-
handler: EventHandler = dataclasses.field(default=None) #
|
|
267
|
+
handler: EventHandler = dataclasses.field(default=None) # pyright: ignore [reportAssignmentType]
|
|
288
268
|
|
|
289
269
|
# The handler on the client to process event.
|
|
290
270
|
client_handler_name: str = dataclasses.field(default="")
|
|
@@ -353,12 +333,12 @@ class EventSpec(EventActionsMixin):
|
|
|
353
333
|
arg = None
|
|
354
334
|
try:
|
|
355
335
|
for arg in args:
|
|
356
|
-
values.append(LiteralVar.create(value=arg)) # noqa: PERF401
|
|
336
|
+
values.append(LiteralVar.create(value=arg)) # noqa: PERF401, RUF100
|
|
357
337
|
except TypeError as e:
|
|
358
338
|
raise EventHandlerTypeError(
|
|
359
339
|
f"Arguments to event handlers must be Vars or JSON-serializable. Got {arg} of type {type(arg)}."
|
|
360
340
|
) from e
|
|
361
|
-
new_payload = tuple(zip(fn_args, values))
|
|
341
|
+
new_payload = tuple(zip(fn_args, values, strict=False))
|
|
362
342
|
return self.with_args(self.args + new_payload)
|
|
363
343
|
|
|
364
344
|
|
|
@@ -437,6 +417,7 @@ class EventChain(EventActionsMixin):
|
|
|
437
417
|
value: EventType,
|
|
438
418
|
args_spec: ArgsSpec | Sequence[ArgsSpec],
|
|
439
419
|
key: Optional[str] = None,
|
|
420
|
+
**event_chain_kwargs,
|
|
440
421
|
) -> Union[EventChain, Var]:
|
|
441
422
|
"""Create an event chain from a variety of input types.
|
|
442
423
|
|
|
@@ -444,6 +425,7 @@ class EventChain(EventActionsMixin):
|
|
|
444
425
|
value: The value to create the event chain from.
|
|
445
426
|
args_spec: The args_spec of the event trigger being bound.
|
|
446
427
|
key: The key of the event trigger being bound.
|
|
428
|
+
**event_chain_kwargs: Additional kwargs to pass to the EventChain constructor.
|
|
447
429
|
|
|
448
430
|
Returns:
|
|
449
431
|
The event chain.
|
|
@@ -462,6 +444,7 @@ class EventChain(EventActionsMixin):
|
|
|
462
444
|
value=value.guess_type(),
|
|
463
445
|
args_spec=args_spec,
|
|
464
446
|
key=key,
|
|
447
|
+
**event_chain_kwargs,
|
|
465
448
|
)
|
|
466
449
|
else:
|
|
467
450
|
raise ValueError(
|
|
@@ -501,7 +484,9 @@ class EventChain(EventActionsMixin):
|
|
|
501
484
|
result = call_event_fn(value, args_spec, key=key)
|
|
502
485
|
if isinstance(result, Var):
|
|
503
486
|
# Recursively call this function if the lambda returned an EventChain Var.
|
|
504
|
-
return cls.create(
|
|
487
|
+
return cls.create(
|
|
488
|
+
value=result, args_spec=args_spec, key=key, **event_chain_kwargs
|
|
489
|
+
)
|
|
505
490
|
events = [*result]
|
|
506
491
|
|
|
507
492
|
# Otherwise, raise an error.
|
|
@@ -518,7 +503,7 @@ class EventChain(EventActionsMixin):
|
|
|
518
503
|
return cls(
|
|
519
504
|
events=events,
|
|
520
505
|
args_spec=args_spec,
|
|
521
|
-
|
|
506
|
+
**event_chain_kwargs,
|
|
522
507
|
)
|
|
523
508
|
|
|
524
509
|
|
|
@@ -550,13 +535,13 @@ class JavasciptKeyboardEvent:
|
|
|
550
535
|
"""Interface for a Javascript KeyboardEvent https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent."""
|
|
551
536
|
|
|
552
537
|
key: str = ""
|
|
553
|
-
altKey: bool = False
|
|
554
|
-
ctrlKey: bool = False
|
|
555
|
-
metaKey: bool = False
|
|
556
|
-
shiftKey: bool = False
|
|
538
|
+
altKey: bool = False # noqa: N815
|
|
539
|
+
ctrlKey: bool = False # noqa: N815
|
|
540
|
+
metaKey: bool = False # noqa: N815
|
|
541
|
+
shiftKey: bool = False # noqa: N815
|
|
557
542
|
|
|
558
543
|
|
|
559
|
-
def input_event(e:
|
|
544
|
+
def input_event(e: ObjectVar[JavascriptInputEvent]) -> Tuple[Var[str]]:
|
|
560
545
|
"""Get the value from an input event.
|
|
561
546
|
|
|
562
547
|
Args:
|
|
@@ -577,7 +562,9 @@ class KeyInputInfo(TypedDict):
|
|
|
577
562
|
shift_key: bool
|
|
578
563
|
|
|
579
564
|
|
|
580
|
-
def key_event(
|
|
565
|
+
def key_event(
|
|
566
|
+
e: ObjectVar[JavasciptKeyboardEvent],
|
|
567
|
+
) -> Tuple[Var[str], Var[KeyInputInfo]]:
|
|
581
568
|
"""Get the key from a keyboard event.
|
|
582
569
|
|
|
583
570
|
Args:
|
|
@@ -587,7 +574,7 @@ def key_event(e: Var[JavasciptKeyboardEvent]) -> Tuple[Var[str], Var[KeyInputInf
|
|
|
587
574
|
The key from the keyboard event.
|
|
588
575
|
"""
|
|
589
576
|
return (
|
|
590
|
-
e.key,
|
|
577
|
+
e.key.to(str),
|
|
591
578
|
Var.create(
|
|
592
579
|
{
|
|
593
580
|
"alt_key": e.altKey,
|
|
@@ -595,7 +582,7 @@ def key_event(e: Var[JavasciptKeyboardEvent]) -> Tuple[Var[str], Var[KeyInputInf
|
|
|
595
582
|
"meta_key": e.metaKey,
|
|
596
583
|
"shift_key": e.shiftKey,
|
|
597
584
|
},
|
|
598
|
-
),
|
|
585
|
+
).to(KeyInputInfo),
|
|
599
586
|
)
|
|
600
587
|
|
|
601
588
|
|
|
@@ -605,7 +592,7 @@ def no_args_event_spec() -> Tuple[()]:
|
|
|
605
592
|
Returns:
|
|
606
593
|
An empty tuple.
|
|
607
594
|
"""
|
|
608
|
-
return ()
|
|
595
|
+
return ()
|
|
609
596
|
|
|
610
597
|
|
|
611
598
|
# These chains can be used for their side effects when no other events are desired.
|
|
@@ -633,9 +620,9 @@ class IdentityEventReturn(Generic[T], Protocol):
|
|
|
633
620
|
|
|
634
621
|
|
|
635
622
|
@overload
|
|
636
|
-
def passthrough_event_spec(
|
|
623
|
+
def passthrough_event_spec( # pyright: ignore [reportOverlappingOverload]
|
|
637
624
|
event_type: Type[T], /
|
|
638
|
-
) -> Callable[[Var[T]], Tuple[Var[T]]]: ...
|
|
625
|
+
) -> Callable[[Var[T]], Tuple[Var[T]]]: ...
|
|
639
626
|
|
|
640
627
|
|
|
641
628
|
@overload
|
|
@@ -648,7 +635,7 @@ def passthrough_event_spec(
|
|
|
648
635
|
def passthrough_event_spec(*event_types: Type[T]) -> IdentityEventReturn[T]: ...
|
|
649
636
|
|
|
650
637
|
|
|
651
|
-
def passthrough_event_spec(*event_types: Type[T]) -> IdentityEventReturn[T]: #
|
|
638
|
+
def passthrough_event_spec(*event_types: Type[T]) -> IdentityEventReturn[T]: # pyright: ignore [reportInconsistentOverload]
|
|
652
639
|
"""A helper function that returns the input event as output.
|
|
653
640
|
|
|
654
641
|
Args:
|
|
@@ -662,9 +649,9 @@ def passthrough_event_spec(*event_types: Type[T]) -> IdentityEventReturn[T]: #
|
|
|
662
649
|
return values
|
|
663
650
|
|
|
664
651
|
inner_type = tuple(Var[event_type] for event_type in event_types)
|
|
665
|
-
return_annotation = Tuple[inner_type]
|
|
652
|
+
return_annotation = Tuple[inner_type]
|
|
666
653
|
|
|
667
|
-
inner.__signature__ = inspect.signature(inner).replace( #
|
|
654
|
+
inner.__signature__ = inspect.signature(inner).replace( # pyright: ignore [reportFunctionMemberAccess]
|
|
668
655
|
parameters=[
|
|
669
656
|
inspect.Parameter(
|
|
670
657
|
f"ev_{i}",
|
|
@@ -746,7 +733,7 @@ class FileUpload:
|
|
|
746
733
|
# Call the lambda to get the event chain.
|
|
747
734
|
events = call_event_fn(
|
|
748
735
|
on_upload_progress, self.on_upload_progress_args_spec
|
|
749
|
-
)
|
|
736
|
+
)
|
|
750
737
|
else:
|
|
751
738
|
raise ValueError(f"{on_upload_progress} is not a valid event handler.")
|
|
752
739
|
if isinstance(events, Var):
|
|
@@ -793,7 +780,7 @@ def server_side(name: str, sig: inspect.Signature, **kwargs) -> EventSpec:
|
|
|
793
780
|
return None
|
|
794
781
|
|
|
795
782
|
fn.__qualname__ = name
|
|
796
|
-
fn.__signature__ = sig
|
|
783
|
+
fn.__signature__ = sig # pyright: ignore [reportFunctionMemberAccess]
|
|
797
784
|
return EventSpec(
|
|
798
785
|
handler=EventHandler(fn=fn, state_full_name=FRONTEND_EVENT_STATE),
|
|
799
786
|
args=tuple(
|
|
@@ -806,29 +793,10 @@ def server_side(name: str, sig: inspect.Signature, **kwargs) -> EventSpec:
|
|
|
806
793
|
)
|
|
807
794
|
|
|
808
795
|
|
|
809
|
-
@overload
|
|
810
|
-
def redirect(
|
|
811
|
-
path: str | Var[str],
|
|
812
|
-
is_external: Optional[bool] = None,
|
|
813
|
-
replace: bool = False,
|
|
814
|
-
) -> EventSpec: ...
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
@overload
|
|
818
|
-
@typing_extensions.deprecated("`external` is deprecated use `is_external` instead")
|
|
819
|
-
def redirect(
|
|
820
|
-
path: str | Var[str],
|
|
821
|
-
is_external: Optional[bool] = None,
|
|
822
|
-
replace: bool = False,
|
|
823
|
-
external: Optional[bool] = None,
|
|
824
|
-
) -> EventSpec: ...
|
|
825
|
-
|
|
826
|
-
|
|
827
796
|
def redirect(
|
|
828
797
|
path: str | Var[str],
|
|
829
|
-
is_external:
|
|
798
|
+
is_external: bool = False,
|
|
830
799
|
replace: bool = False,
|
|
831
|
-
external: Optional[bool] = None,
|
|
832
800
|
) -> EventSpec:
|
|
833
801
|
"""Redirect to a new path.
|
|
834
802
|
|
|
@@ -836,26 +804,10 @@ def redirect(
|
|
|
836
804
|
path: The path to redirect to.
|
|
837
805
|
is_external: Whether to open in new tab or not.
|
|
838
806
|
replace: If True, the current page will not create a new history entry.
|
|
839
|
-
external(Deprecated): Whether to open in new tab or not.
|
|
840
807
|
|
|
841
808
|
Returns:
|
|
842
809
|
An event to redirect to the path.
|
|
843
810
|
"""
|
|
844
|
-
if external is not None:
|
|
845
|
-
console.deprecate(
|
|
846
|
-
"The `external` prop in `rx.redirect`",
|
|
847
|
-
"use `is_external` instead.",
|
|
848
|
-
"0.6.6",
|
|
849
|
-
"0.7.0",
|
|
850
|
-
)
|
|
851
|
-
|
|
852
|
-
# is_external should take precedence over external.
|
|
853
|
-
is_external = (
|
|
854
|
-
(False if external is None else external)
|
|
855
|
-
if is_external is None
|
|
856
|
-
else is_external
|
|
857
|
-
)
|
|
858
|
-
|
|
859
811
|
return server_side(
|
|
860
812
|
"_redirect",
|
|
861
813
|
get_fn_signature(redirect),
|
|
@@ -1101,13 +1053,13 @@ def download(
|
|
|
1101
1053
|
|
|
1102
1054
|
is_data_url = (data.js_type() == "string") & (
|
|
1103
1055
|
data.to(str).startswith("data:")
|
|
1104
|
-
)
|
|
1056
|
+
)
|
|
1105
1057
|
|
|
1106
1058
|
# If it's a data: URI, use it as is, otherwise convert the Var to JSON in a data: URI.
|
|
1107
|
-
url = cond(
|
|
1059
|
+
url = cond(
|
|
1108
1060
|
is_data_url,
|
|
1109
1061
|
data.to(str),
|
|
1110
|
-
"data:text/plain," + data.to_string(),
|
|
1062
|
+
"data:text/plain," + data.to_string(),
|
|
1111
1063
|
)
|
|
1112
1064
|
elif isinstance(data, bytes):
|
|
1113
1065
|
# Caller provided bytes, so base64 encode it as a data: URI.
|
|
@@ -1126,7 +1078,8 @@ def download(
|
|
|
1126
1078
|
)
|
|
1127
1079
|
|
|
1128
1080
|
|
|
1129
|
-
|
|
1081
|
+
# This function seems unused. Check if we still need it. If not, remove in 0.7.0
|
|
1082
|
+
def _callback_arg_spec(eval_result: Any):
|
|
1130
1083
|
"""ArgSpec for call_script callback function.
|
|
1131
1084
|
|
|
1132
1085
|
Args:
|
|
@@ -1140,7 +1093,7 @@ def _callback_arg_spec(eval_result):
|
|
|
1140
1093
|
|
|
1141
1094
|
def call_script(
|
|
1142
1095
|
javascript_code: str | Var[str],
|
|
1143
|
-
callback: EventType | None = None,
|
|
1096
|
+
callback: EventType[Any] | None = None,
|
|
1144
1097
|
) -> EventSpec:
|
|
1145
1098
|
"""Create an event handler that executes arbitrary javascript code.
|
|
1146
1099
|
|
|
@@ -1179,7 +1132,7 @@ def call_script(
|
|
|
1179
1132
|
|
|
1180
1133
|
def call_function(
|
|
1181
1134
|
javascript_code: str | Var,
|
|
1182
|
-
callback: EventType | None = None,
|
|
1135
|
+
callback: EventType[Any] | None = None,
|
|
1183
1136
|
) -> EventSpec:
|
|
1184
1137
|
"""Create an event handler that executes arbitrary javascript code.
|
|
1185
1138
|
|
|
@@ -1213,7 +1166,7 @@ def call_function(
|
|
|
1213
1166
|
|
|
1214
1167
|
def run_script(
|
|
1215
1168
|
javascript_code: str | Var,
|
|
1216
|
-
callback: EventType | None = None,
|
|
1169
|
+
callback: EventType[Any] | None = None,
|
|
1217
1170
|
) -> EventSpec:
|
|
1218
1171
|
"""Create an event handler that executes arbitrary javascript code.
|
|
1219
1172
|
|
|
@@ -1231,7 +1184,7 @@ def run_script(
|
|
|
1231
1184
|
return call_function(ArgsFunctionOperation.create((), javascript_code), callback)
|
|
1232
1185
|
|
|
1233
1186
|
|
|
1234
|
-
def get_event(state, event):
|
|
1187
|
+
def get_event(state: BaseState, event: str):
|
|
1235
1188
|
"""Get the event from the given state.
|
|
1236
1189
|
|
|
1237
1190
|
Args:
|
|
@@ -1244,7 +1197,7 @@ def get_event(state, event):
|
|
|
1244
1197
|
return f"{state.get_name()}.{event}"
|
|
1245
1198
|
|
|
1246
1199
|
|
|
1247
|
-
def get_hydrate_event(state) -> str:
|
|
1200
|
+
def get_hydrate_event(state: BaseState) -> str:
|
|
1248
1201
|
"""Get the name of the hydrate event for the state.
|
|
1249
1202
|
|
|
1250
1203
|
Args:
|
|
@@ -1272,13 +1225,16 @@ def call_event_handler(
|
|
|
1272
1225
|
event_spec: The lambda that define the argument(s) to pass to the event handler.
|
|
1273
1226
|
key: The key to pass to the event handler.
|
|
1274
1227
|
|
|
1228
|
+
Raises:
|
|
1229
|
+
EventHandlerArgTypeMismatchError: If the event handler arguments do not match the event spec. #noqa: DAR402
|
|
1230
|
+
TypeError: If the event handler arguments are invalid.
|
|
1231
|
+
|
|
1275
1232
|
Returns:
|
|
1276
1233
|
The event spec from calling the event handler.
|
|
1277
1234
|
|
|
1278
|
-
#
|
|
1279
|
-
|
|
1235
|
+
#noqa: DAR401
|
|
1280
1236
|
"""
|
|
1281
|
-
event_spec_args = parse_args_spec(event_spec)
|
|
1237
|
+
event_spec_args = parse_args_spec(event_spec)
|
|
1282
1238
|
|
|
1283
1239
|
if isinstance(event_callback, EventSpec):
|
|
1284
1240
|
check_fn_match_arg_spec(
|
|
@@ -1313,10 +1269,15 @@ def call_event_handler(
|
|
|
1313
1269
|
),
|
|
1314
1270
|
)
|
|
1315
1271
|
)
|
|
1272
|
+
type_match_found: dict[str, bool] = {}
|
|
1273
|
+
delayed_exceptions: list[EventHandlerArgTypeMismatchError] = []
|
|
1316
1274
|
|
|
1317
|
-
|
|
1318
|
-
|
|
1275
|
+
try:
|
|
1276
|
+
type_hints_of_provided_callback = get_type_hints(event_callback.fn)
|
|
1277
|
+
except NameError:
|
|
1278
|
+
type_hints_of_provided_callback = {}
|
|
1319
1279
|
|
|
1280
|
+
if event_spec_return_types:
|
|
1320
1281
|
event_callback_spec = inspect.getfullargspec(event_callback.fn)
|
|
1321
1282
|
|
|
1322
1283
|
for event_spec_index, event_spec_return_type in enumerate(
|
|
@@ -1328,43 +1289,35 @@ def call_event_handler(
|
|
|
1328
1289
|
arg if get_origin(arg) is not Var else get_args(arg)[0] for arg in args
|
|
1329
1290
|
]
|
|
1330
1291
|
|
|
1331
|
-
try:
|
|
1332
|
-
type_hints_of_provided_callback = get_type_hints(event_callback.fn)
|
|
1333
|
-
except NameError:
|
|
1334
|
-
type_hints_of_provided_callback = {}
|
|
1335
|
-
|
|
1336
|
-
failed_type_check = False
|
|
1337
|
-
|
|
1338
1292
|
# check that args of event handler are matching the spec if type hints are provided
|
|
1339
1293
|
for i, arg in enumerate(event_callback_spec.args[1:]):
|
|
1340
1294
|
if arg not in type_hints_of_provided_callback:
|
|
1341
1295
|
continue
|
|
1342
1296
|
|
|
1297
|
+
type_match_found.setdefault(arg, False)
|
|
1298
|
+
|
|
1343
1299
|
try:
|
|
1344
1300
|
compare_result = typehint_issubclass(
|
|
1345
1301
|
args_types_without_vars[i], type_hints_of_provided_callback[arg]
|
|
1346
1302
|
)
|
|
1347
|
-
except TypeError:
|
|
1348
|
-
|
|
1349
|
-
# raise TypeError(
|
|
1350
|
-
# f"Could not compare types {args_types_without_vars[i]} and {type_hints_of_provided_callback[arg]} for argument {arg} of {event_handler.fn.__qualname__} provided for {key}." # noqa: ERA001
|
|
1351
|
-
# ) from e
|
|
1352
|
-
console.warn(
|
|
1303
|
+
except TypeError as te:
|
|
1304
|
+
raise TypeError(
|
|
1353
1305
|
f"Could not compare types {args_types_without_vars[i]} and {type_hints_of_provided_callback[arg]} for argument {arg} of {event_callback.fn.__qualname__} provided for {key}."
|
|
1354
|
-
)
|
|
1355
|
-
compare_result = False
|
|
1306
|
+
) from te
|
|
1356
1307
|
|
|
1357
1308
|
if compare_result:
|
|
1309
|
+
type_match_found[arg] = True
|
|
1358
1310
|
continue
|
|
1359
1311
|
else:
|
|
1360
|
-
|
|
1361
|
-
|
|
1312
|
+
type_match_found[arg] = False
|
|
1313
|
+
delayed_exceptions.append(
|
|
1314
|
+
EventHandlerArgTypeMismatchError(
|
|
1315
|
+
f"Event handler {key} expects {args_types_without_vars[i]} for argument {arg} but got {type_hints_of_provided_callback[arg]} as annotated in {event_callback.fn.__qualname__} instead."
|
|
1316
|
+
)
|
|
1362
1317
|
)
|
|
1363
|
-
failures.append(failure)
|
|
1364
|
-
failed_type_check = True
|
|
1365
|
-
break
|
|
1366
1318
|
|
|
1367
|
-
if
|
|
1319
|
+
if all(type_match_found.values()):
|
|
1320
|
+
delayed_exceptions.clear()
|
|
1368
1321
|
if event_spec_index:
|
|
1369
1322
|
args = get_args(event_spec_return_types[0])
|
|
1370
1323
|
|
|
@@ -1386,17 +1339,12 @@ def call_event_handler(
|
|
|
1386
1339
|
f"Event handler {key} expects ({expect_string}) -> () but got ({given_string}) -> () as annotated in {event_callback.fn.__qualname__} instead. "
|
|
1387
1340
|
f"This may lead to unexpected behavior but is intentionally ignored for {key}."
|
|
1388
1341
|
)
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
if failures:
|
|
1392
|
-
console.deprecate(
|
|
1393
|
-
"Mismatched event handler argument types",
|
|
1394
|
-
"\n".join([str(f) for f in failures]),
|
|
1395
|
-
"0.6.5",
|
|
1396
|
-
"0.7.0",
|
|
1397
|
-
)
|
|
1342
|
+
break
|
|
1398
1343
|
|
|
1399
|
-
|
|
1344
|
+
if delayed_exceptions:
|
|
1345
|
+
raise delayed_exceptions[0]
|
|
1346
|
+
|
|
1347
|
+
return event_callback(*event_spec_args)
|
|
1400
1348
|
|
|
1401
1349
|
|
|
1402
1350
|
def unwrap_var_annotation(annotation: GenericType):
|
|
@@ -1408,31 +1356,31 @@ def unwrap_var_annotation(annotation: GenericType):
|
|
|
1408
1356
|
Returns:
|
|
1409
1357
|
The unwrapped annotation.
|
|
1410
1358
|
"""
|
|
1411
|
-
if get_origin(annotation)
|
|
1359
|
+
if get_origin(annotation) in (Var, ObjectVar) and (args := get_args(annotation)):
|
|
1412
1360
|
return args[0]
|
|
1413
1361
|
return annotation
|
|
1414
1362
|
|
|
1415
1363
|
|
|
1416
|
-
def resolve_annotation(annotations: dict[str, Any], arg_name: str):
|
|
1364
|
+
def resolve_annotation(annotations: dict[str, Any], arg_name: str, spec: ArgsSpec):
|
|
1417
1365
|
"""Resolve the annotation for the given argument name.
|
|
1418
1366
|
|
|
1419
1367
|
Args:
|
|
1420
1368
|
annotations: The annotations.
|
|
1421
1369
|
arg_name: The argument name.
|
|
1370
|
+
spec: The specs which the annotations come from.
|
|
1371
|
+
|
|
1372
|
+
Raises:
|
|
1373
|
+
MissingAnnotationError: If the annotation is missing for non-lambda methods.
|
|
1422
1374
|
|
|
1423
1375
|
Returns:
|
|
1424
1376
|
The resolved annotation.
|
|
1425
1377
|
"""
|
|
1426
1378
|
annotation = annotations.get(arg_name)
|
|
1427
1379
|
if annotation is None:
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
removal_version="0.7.0",
|
|
1433
|
-
)
|
|
1434
|
-
# Allow arbitrary attribute access two levels deep until removed.
|
|
1435
|
-
return Dict[str, dict]
|
|
1380
|
+
if not isinstance(spec, types.LambdaType):
|
|
1381
|
+
raise MissingAnnotationError(var_name=arg_name)
|
|
1382
|
+
else:
|
|
1383
|
+
return dict[str, dict]
|
|
1436
1384
|
return annotation
|
|
1437
1385
|
|
|
1438
1386
|
|
|
@@ -1454,7 +1402,13 @@ def parse_args_spec(arg_spec: ArgsSpec | Sequence[ArgsSpec]):
|
|
|
1454
1402
|
arg_spec(
|
|
1455
1403
|
*[
|
|
1456
1404
|
Var(f"_{l_arg}").to(
|
|
1457
|
-
unwrap_var_annotation(
|
|
1405
|
+
unwrap_var_annotation(
|
|
1406
|
+
resolve_annotation(
|
|
1407
|
+
annotations,
|
|
1408
|
+
l_arg,
|
|
1409
|
+
spec=arg_spec,
|
|
1410
|
+
)
|
|
1411
|
+
)
|
|
1458
1412
|
)
|
|
1459
1413
|
for l_arg in spec.args
|
|
1460
1414
|
]
|
|
@@ -1470,7 +1424,7 @@ def check_fn_match_arg_spec(
|
|
|
1470
1424
|
func_name: str | None = None,
|
|
1471
1425
|
):
|
|
1472
1426
|
"""Ensures that the function signature matches the passed argument specification
|
|
1473
|
-
or raises an
|
|
1427
|
+
or raises an EventFnArgMismatchError if they do not.
|
|
1474
1428
|
|
|
1475
1429
|
Args:
|
|
1476
1430
|
user_func: The function to be validated.
|
|
@@ -1480,7 +1434,7 @@ def check_fn_match_arg_spec(
|
|
|
1480
1434
|
func_name: The name of the function to be validated.
|
|
1481
1435
|
|
|
1482
1436
|
Raises:
|
|
1483
|
-
|
|
1437
|
+
EventFnArgMismatchError: Raised if the number of mandatory arguments do not match
|
|
1484
1438
|
"""
|
|
1485
1439
|
user_args = inspect.getfullargspec(user_func).args
|
|
1486
1440
|
# Drop the first argument if it's a bound method
|
|
@@ -1496,7 +1450,7 @@ def check_fn_match_arg_spec(
|
|
|
1496
1450
|
number_of_event_args = len(parsed_event_args)
|
|
1497
1451
|
|
|
1498
1452
|
if number_of_user_args - number_of_user_default_args > number_of_event_args:
|
|
1499
|
-
raise
|
|
1453
|
+
raise EventFnArgMismatchError(
|
|
1500
1454
|
f"Event {key} only provides {number_of_event_args} arguments, but "
|
|
1501
1455
|
f"{func_name or user_func} requires at least {number_of_user_args - number_of_user_default_args} "
|
|
1502
1456
|
"arguments to be passed to the event handler.\n"
|
|
@@ -1584,7 +1538,7 @@ def get_handler_args(
|
|
|
1584
1538
|
|
|
1585
1539
|
|
|
1586
1540
|
def fix_events(
|
|
1587
|
-
events: list[
|
|
1541
|
+
events: list[EventSpec | EventHandler] | None,
|
|
1588
1542
|
token: str,
|
|
1589
1543
|
router_data: dict[str, Any] | None = None,
|
|
1590
1544
|
) -> list[Event]:
|
|
@@ -1624,7 +1578,7 @@ def fix_events(
|
|
|
1624
1578
|
if not isinstance(e, EventSpec):
|
|
1625
1579
|
raise ValueError(f"Unexpected event type, {type(e)}.")
|
|
1626
1580
|
name = format.format_event_handler(e.handler)
|
|
1627
|
-
payload = {k._js_expr: v._decode() for k, v in e.args}
|
|
1581
|
+
payload = {k._js_expr: v._decode() for k, v in e.args}
|
|
1628
1582
|
|
|
1629
1583
|
# Filter router_data to reduce payload size
|
|
1630
1584
|
event_router_data = {
|
|
@@ -1668,12 +1622,12 @@ class EventVar(ObjectVar, python_types=EventSpec):
|
|
|
1668
1622
|
@dataclasses.dataclass(
|
|
1669
1623
|
eq=False,
|
|
1670
1624
|
frozen=True,
|
|
1671
|
-
|
|
1625
|
+
slots=True,
|
|
1672
1626
|
)
|
|
1673
1627
|
class LiteralEventVar(VarOperationCall, LiteralVar, EventVar):
|
|
1674
1628
|
"""A literal event var."""
|
|
1675
1629
|
|
|
1676
|
-
_var_value: EventSpec = dataclasses.field(default=None) #
|
|
1630
|
+
_var_value: EventSpec = dataclasses.field(default=None) # pyright: ignore [reportAssignmentType]
|
|
1677
1631
|
|
|
1678
1632
|
def __hash__(self) -> int:
|
|
1679
1633
|
"""Get the hash of the var.
|
|
@@ -1729,7 +1683,7 @@ class EventChainVar(BuilderFunctionVar, python_types=EventChain):
|
|
|
1729
1683
|
@dataclasses.dataclass(
|
|
1730
1684
|
eq=False,
|
|
1731
1685
|
frozen=True,
|
|
1732
|
-
|
|
1686
|
+
slots=True,
|
|
1733
1687
|
)
|
|
1734
1688
|
# Note: LiteralVar is second in the inheritance list allowing it act like a
|
|
1735
1689
|
# CachedVarOperation (ArgsFunctionOperation) and get the _js_expr from the
|
|
@@ -1737,7 +1691,7 @@ class EventChainVar(BuilderFunctionVar, python_types=EventChain):
|
|
|
1737
1691
|
class LiteralEventChainVar(ArgsFunctionOperationBuilder, LiteralVar, EventChainVar):
|
|
1738
1692
|
"""A literal event chain var."""
|
|
1739
1693
|
|
|
1740
|
-
_var_value: EventChain = dataclasses.field(default=None) #
|
|
1694
|
+
_var_value: EventChain = dataclasses.field(default=None) # pyright: ignore [reportAssignmentType]
|
|
1741
1695
|
|
|
1742
1696
|
def __hash__(self) -> int:
|
|
1743
1697
|
"""Get the hash of the var.
|
|
@@ -1761,13 +1715,16 @@ class LiteralEventChainVar(ArgsFunctionOperationBuilder, LiteralVar, EventChainV
|
|
|
1761
1715
|
|
|
1762
1716
|
Returns:
|
|
1763
1717
|
The created LiteralEventChainVar instance.
|
|
1718
|
+
|
|
1719
|
+
Raises:
|
|
1720
|
+
ValueError: If the invocation is not a FunctionVar.
|
|
1764
1721
|
"""
|
|
1765
1722
|
arg_spec = (
|
|
1766
1723
|
value.args_spec[0]
|
|
1767
1724
|
if isinstance(value.args_spec, Sequence)
|
|
1768
1725
|
else value.args_spec
|
|
1769
1726
|
)
|
|
1770
|
-
sig = inspect.signature(arg_spec) #
|
|
1727
|
+
sig = inspect.signature(arg_spec) # pyright: ignore [reportArgumentType]
|
|
1771
1728
|
if sig.parameters:
|
|
1772
1729
|
arg_def = tuple((f"_{p}" for p in sig.parameters))
|
|
1773
1730
|
arg_def_expr = LiteralVar.create([Var(_js_expr=arg) for arg in arg_def])
|
|
@@ -1778,10 +1735,21 @@ class LiteralEventChainVar(ArgsFunctionOperationBuilder, LiteralVar, EventChainV
|
|
|
1778
1735
|
arg_def_expr = Var(_js_expr="args")
|
|
1779
1736
|
|
|
1780
1737
|
if value.invocation is None:
|
|
1781
|
-
invocation = FunctionStringVar.create(
|
|
1738
|
+
invocation = FunctionStringVar.create(
|
|
1739
|
+
CompileVars.ADD_EVENTS,
|
|
1740
|
+
_var_data=VarData(
|
|
1741
|
+
imports=Imports.EVENTS,
|
|
1742
|
+
hooks={Hooks.EVENTS: None},
|
|
1743
|
+
),
|
|
1744
|
+
)
|
|
1782
1745
|
else:
|
|
1783
1746
|
invocation = value.invocation
|
|
1784
1747
|
|
|
1748
|
+
if invocation is not None and not isinstance(invocation, FunctionVar):
|
|
1749
|
+
raise ValueError(
|
|
1750
|
+
f"EventChain invocation must be a FunctionVar, got {invocation!s} of type {invocation._var_type!s}."
|
|
1751
|
+
)
|
|
1752
|
+
|
|
1785
1753
|
return cls(
|
|
1786
1754
|
_js_expr="",
|
|
1787
1755
|
_var_type=EventChain,
|
|
@@ -1796,8 +1764,8 @@ class LiteralEventChainVar(ArgsFunctionOperationBuilder, LiteralVar, EventChainV
|
|
|
1796
1764
|
)
|
|
1797
1765
|
|
|
1798
1766
|
|
|
1799
|
-
P =
|
|
1800
|
-
Q =
|
|
1767
|
+
P = TypeVarTuple("P")
|
|
1768
|
+
Q = TypeVarTuple("Q")
|
|
1801
1769
|
T = TypeVar("T")
|
|
1802
1770
|
V = TypeVar("V")
|
|
1803
1771
|
V2 = TypeVar("V2")
|
|
@@ -1805,13 +1773,11 @@ V3 = TypeVar("V3")
|
|
|
1805
1773
|
V4 = TypeVar("V4")
|
|
1806
1774
|
V5 = TypeVar("V5")
|
|
1807
1775
|
|
|
1808
|
-
background_event_decorator = background
|
|
1809
|
-
|
|
1810
1776
|
|
|
1811
|
-
class EventCallback(Generic[P,
|
|
1777
|
+
class EventCallback(Generic[Unpack[P]], EventActionsMixin):
|
|
1812
1778
|
"""A descriptor that wraps a function to be used as an event."""
|
|
1813
1779
|
|
|
1814
|
-
def __init__(self, func: Callable[
|
|
1780
|
+
def __init__(self, func: Callable[[Any, Unpack[P]], Any]):
|
|
1815
1781
|
"""Initialize the descriptor with the function to be wrapped.
|
|
1816
1782
|
|
|
1817
1783
|
Args:
|
|
@@ -1819,59 +1785,41 @@ class EventCallback(Generic[P, T]):
|
|
|
1819
1785
|
"""
|
|
1820
1786
|
self.func = func
|
|
1821
1787
|
|
|
1822
|
-
@property
|
|
1823
|
-
def prevent_default(self):
|
|
1824
|
-
"""Prevent default behavior.
|
|
1825
|
-
|
|
1826
|
-
Returns:
|
|
1827
|
-
The event callback with prevent default behavior.
|
|
1828
|
-
"""
|
|
1829
|
-
return self
|
|
1830
|
-
|
|
1831
|
-
@property
|
|
1832
|
-
def stop_propagation(self):
|
|
1833
|
-
"""Stop event propagation.
|
|
1834
|
-
|
|
1835
|
-
Returns:
|
|
1836
|
-
The event callback with stop propagation behavior.
|
|
1837
|
-
"""
|
|
1838
|
-
return self
|
|
1839
|
-
|
|
1840
1788
|
@overload
|
|
1841
1789
|
def __call__(
|
|
1842
|
-
self: EventCallback[Q
|
|
1843
|
-
) -> EventCallback[Q
|
|
1790
|
+
self: EventCallback[Unpack[Q]],
|
|
1791
|
+
) -> EventCallback[Unpack[Q]]: ...
|
|
1844
1792
|
|
|
1845
1793
|
@overload
|
|
1846
1794
|
def __call__(
|
|
1847
|
-
self: EventCallback[
|
|
1848
|
-
) -> EventCallback[Q
|
|
1795
|
+
self: EventCallback[V, Unpack[Q]], value: V | Var[V]
|
|
1796
|
+
) -> EventCallback[Unpack[Q]]: ...
|
|
1849
1797
|
|
|
1850
1798
|
@overload
|
|
1851
1799
|
def __call__(
|
|
1852
|
-
self: EventCallback[
|
|
1800
|
+
self: EventCallback[V, V2, Unpack[Q]],
|
|
1853
1801
|
value: V | Var[V],
|
|
1854
1802
|
value2: V2 | Var[V2],
|
|
1855
|
-
) -> EventCallback[Q
|
|
1803
|
+
) -> EventCallback[Unpack[Q]]: ...
|
|
1856
1804
|
|
|
1857
1805
|
@overload
|
|
1858
1806
|
def __call__(
|
|
1859
|
-
self: EventCallback[
|
|
1807
|
+
self: EventCallback[V, V2, V3, Unpack[Q]],
|
|
1860
1808
|
value: V | Var[V],
|
|
1861
1809
|
value2: V2 | Var[V2],
|
|
1862
1810
|
value3: V3 | Var[V3],
|
|
1863
|
-
) -> EventCallback[Q
|
|
1811
|
+
) -> EventCallback[Unpack[Q]]: ...
|
|
1864
1812
|
|
|
1865
1813
|
@overload
|
|
1866
1814
|
def __call__(
|
|
1867
|
-
self: EventCallback[
|
|
1815
|
+
self: EventCallback[V, V2, V3, V4, Unpack[Q]],
|
|
1868
1816
|
value: V | Var[V],
|
|
1869
1817
|
value2: V2 | Var[V2],
|
|
1870
1818
|
value3: V3 | Var[V3],
|
|
1871
1819
|
value4: V4 | Var[V4],
|
|
1872
|
-
) -> EventCallback[Q
|
|
1820
|
+
) -> EventCallback[Unpack[Q]]: ...
|
|
1873
1821
|
|
|
1874
|
-
def __call__(self, *values) -> EventCallback: #
|
|
1822
|
+
def __call__(self, *values) -> EventCallback: # pyright: ignore [reportInconsistentOverload]
|
|
1875
1823
|
"""Call the function with the values.
|
|
1876
1824
|
|
|
1877
1825
|
Args:
|
|
@@ -1880,17 +1828,17 @@ class EventCallback(Generic[P, T]):
|
|
|
1880
1828
|
Returns:
|
|
1881
1829
|
The function with the values.
|
|
1882
1830
|
"""
|
|
1883
|
-
return self.func(*values) #
|
|
1831
|
+
return self.func(*values) # pyright: ignore [reportArgumentType]
|
|
1884
1832
|
|
|
1885
1833
|
@overload
|
|
1886
1834
|
def __get__(
|
|
1887
|
-
self: EventCallback[P
|
|
1888
|
-
) -> EventCallback[P
|
|
1835
|
+
self: EventCallback[Unpack[P]], instance: None, owner: Any
|
|
1836
|
+
) -> EventCallback[Unpack[P]]: ...
|
|
1889
1837
|
|
|
1890
1838
|
@overload
|
|
1891
|
-
def __get__(self, instance, owner) -> Callable[P
|
|
1839
|
+
def __get__(self, instance: Any, owner: Any) -> Callable[[Unpack[P]]]: ...
|
|
1892
1840
|
|
|
1893
|
-
def __get__(self, instance, owner) -> Callable:
|
|
1841
|
+
def __get__(self, instance: Any, owner: Any) -> Callable:
|
|
1894
1842
|
"""Get the function with the instance bound to it.
|
|
1895
1843
|
|
|
1896
1844
|
Args:
|
|
@@ -1901,38 +1849,74 @@ class EventCallback(Generic[P, T]):
|
|
|
1901
1849
|
The function with the instance bound to it
|
|
1902
1850
|
"""
|
|
1903
1851
|
if instance is None:
|
|
1904
|
-
return self.func
|
|
1852
|
+
return self.func
|
|
1905
1853
|
|
|
1906
|
-
return partial(self.func, instance)
|
|
1854
|
+
return partial(self.func, instance)
|
|
1907
1855
|
|
|
1908
1856
|
|
|
1909
|
-
|
|
1857
|
+
class LambdaEventCallback(Protocol[Unpack[P]]):
|
|
1858
|
+
"""A protocol for a lambda event callback."""
|
|
1910
1859
|
|
|
1911
|
-
|
|
1912
|
-
|
|
1860
|
+
@overload
|
|
1861
|
+
def __call__(self: LambdaEventCallback[()]) -> Any: ...
|
|
1913
1862
|
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1863
|
+
@overload
|
|
1864
|
+
def __call__(self: LambdaEventCallback[V], value: Var[V], /) -> Any: ...
|
|
1865
|
+
|
|
1866
|
+
@overload
|
|
1867
|
+
def __call__(
|
|
1868
|
+
self: LambdaEventCallback[V, V2], value: Var[V], value2: Var[V2], /
|
|
1869
|
+
) -> Any: ...
|
|
1870
|
+
|
|
1871
|
+
@overload
|
|
1872
|
+
def __call__(
|
|
1873
|
+
self: LambdaEventCallback[V, V2, V3],
|
|
1874
|
+
value: Var[V],
|
|
1875
|
+
value2: Var[V2],
|
|
1876
|
+
value3: Var[V3],
|
|
1877
|
+
/,
|
|
1878
|
+
) -> Any: ...
|
|
1879
|
+
|
|
1880
|
+
def __call__(self, *args: Var) -> Any:
|
|
1881
|
+
"""Call the lambda with the args.
|
|
1882
|
+
|
|
1883
|
+
Args:
|
|
1884
|
+
*args: The args to call the lambda with.
|
|
1885
|
+
"""
|
|
1886
|
+
|
|
1887
|
+
|
|
1888
|
+
ARGS = TypeVarTuple("ARGS")
|
|
1917
1889
|
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1890
|
+
|
|
1891
|
+
LAMBDA_OR_STATE = TypeAliasType(
|
|
1892
|
+
"LAMBDA_OR_STATE",
|
|
1893
|
+
LambdaEventCallback[Unpack[ARGS]] | EventCallback[Unpack[ARGS]],
|
|
1894
|
+
type_params=(ARGS,),
|
|
1922
1895
|
)
|
|
1923
1896
|
|
|
1924
|
-
|
|
1925
|
-
EventSpec,
|
|
1926
|
-
EventHandler,
|
|
1927
|
-
Callable[G, Any],
|
|
1928
|
-
StateCallable[G, BASE_STATE],
|
|
1929
|
-
EventCallback[G, Any],
|
|
1930
|
-
Var[Any],
|
|
1931
|
-
]
|
|
1897
|
+
ItemOrList = V | List[V]
|
|
1932
1898
|
|
|
1933
|
-
|
|
1899
|
+
BASIC_EVENT_TYPES = TypeAliasType(
|
|
1900
|
+
"BASIC_EVENT_TYPES", EventSpec | EventHandler | Var[Any], type_params=()
|
|
1901
|
+
)
|
|
1934
1902
|
|
|
1935
|
-
|
|
1903
|
+
IndividualEventType = TypeAliasType(
|
|
1904
|
+
"IndividualEventType",
|
|
1905
|
+
LAMBDA_OR_STATE[Unpack[ARGS]] | BASIC_EVENT_TYPES,
|
|
1906
|
+
type_params=(ARGS,),
|
|
1907
|
+
)
|
|
1908
|
+
|
|
1909
|
+
EventType = TypeAliasType(
|
|
1910
|
+
"EventType", ItemOrList[IndividualEventType[Unpack[ARGS]]], type_params=(ARGS,)
|
|
1911
|
+
)
|
|
1912
|
+
|
|
1913
|
+
|
|
1914
|
+
if TYPE_CHECKING:
|
|
1915
|
+
from reflex.state import BaseState
|
|
1916
|
+
|
|
1917
|
+
BASE_STATE = TypeVar("BASE_STATE", bound=BaseState)
|
|
1918
|
+
else:
|
|
1919
|
+
BASE_STATE = TypeVar("BASE_STATE")
|
|
1936
1920
|
|
|
1937
1921
|
|
|
1938
1922
|
class EventNamespace(types.SimpleNamespace):
|
|
@@ -1954,24 +1938,26 @@ class EventNamespace(types.SimpleNamespace):
|
|
|
1954
1938
|
@staticmethod
|
|
1955
1939
|
def __call__(
|
|
1956
1940
|
func: None = None, *, background: bool | None = None
|
|
1957
|
-
) -> Callable[
|
|
1941
|
+
) -> Callable[
|
|
1942
|
+
[Callable[[BASE_STATE, Unpack[P]], Any]], EventCallback[Unpack[P]] # pyright: ignore [reportInvalidTypeVarUse]
|
|
1943
|
+
]: ...
|
|
1958
1944
|
|
|
1959
1945
|
@overload
|
|
1960
1946
|
@staticmethod
|
|
1961
1947
|
def __call__(
|
|
1962
|
-
func: Callable[
|
|
1948
|
+
func: Callable[[BASE_STATE, Unpack[P]], Any],
|
|
1963
1949
|
*,
|
|
1964
1950
|
background: bool | None = None,
|
|
1965
|
-
) -> EventCallback[P
|
|
1951
|
+
) -> EventCallback[Unpack[P]]: ...
|
|
1966
1952
|
|
|
1967
1953
|
@staticmethod
|
|
1968
1954
|
def __call__(
|
|
1969
|
-
func: Callable[
|
|
1955
|
+
func: Callable[[BASE_STATE, Unpack[P]], Any] | None = None,
|
|
1970
1956
|
*,
|
|
1971
1957
|
background: bool | None = None,
|
|
1972
1958
|
) -> Union[
|
|
1973
|
-
EventCallback[P
|
|
1974
|
-
Callable[[Callable[
|
|
1959
|
+
EventCallback[Unpack[P]],
|
|
1960
|
+
Callable[[Callable[[BASE_STATE, Unpack[P]], Any]], EventCallback[Unpack[P]]],
|
|
1975
1961
|
]:
|
|
1976
1962
|
"""Wrap a function to be used as an event.
|
|
1977
1963
|
|
|
@@ -1979,16 +1965,25 @@ class EventNamespace(types.SimpleNamespace):
|
|
|
1979
1965
|
func: The function to wrap.
|
|
1980
1966
|
background: Whether the event should be run in the background. Defaults to False.
|
|
1981
1967
|
|
|
1968
|
+
Raises:
|
|
1969
|
+
TypeError: If background is True and the function is not a coroutine or async generator. # noqa: DAR402
|
|
1970
|
+
|
|
1982
1971
|
Returns:
|
|
1983
1972
|
The wrapped function.
|
|
1984
1973
|
"""
|
|
1985
1974
|
|
|
1986
1975
|
def wrapper(
|
|
1987
|
-
func: Callable[
|
|
1988
|
-
) -> EventCallback[P
|
|
1976
|
+
func: Callable[[BASE_STATE, Unpack[P]], T],
|
|
1977
|
+
) -> EventCallback[Unpack[P]]:
|
|
1989
1978
|
if background is True:
|
|
1990
|
-
|
|
1991
|
-
|
|
1979
|
+
if not inspect.iscoroutinefunction(
|
|
1980
|
+
func
|
|
1981
|
+
) and not inspect.isasyncgenfunction(func):
|
|
1982
|
+
raise TypeError(
|
|
1983
|
+
"Background task must be async function or generator."
|
|
1984
|
+
)
|
|
1985
|
+
setattr(func, BACKGROUND_TASK_MARKER, True)
|
|
1986
|
+
return func # pyright: ignore [reportReturnType]
|
|
1992
1987
|
|
|
1993
1988
|
if func is not None:
|
|
1994
1989
|
return wrapper(func)
|