reflex 0.6.8a2__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 -129
- 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 -15
- 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 +221 -231
- 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 +29 -23
- reflex/utils/build.py +6 -2
- reflex/utils/codespaces.py +1 -4
- reflex/utils/compat.py +6 -5
- reflex/utils/console.py +71 -16
- 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.8a2.dist-info → reflex-0.7.0.dist-info}/METADATA +7 -8
- reflex-0.7.0.dist-info/RECORD +401 -0
- {reflex-0.6.8a2.dist-info → reflex-0.7.0.dist-info}/WHEEL +1 -1
- reflex/experimental/assets.py +0 -37
- reflex-0.6.8a2.dist-info/RECORD +0 -397
- {reflex-0.6.8a2.dist-info → reflex-0.7.0.dist-info}/LICENSE +0 -0
- {reflex-0.6.8a2.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
|
|
|
@@ -555,13 +535,13 @@ class JavasciptKeyboardEvent:
|
|
|
555
535
|
"""Interface for a Javascript KeyboardEvent https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent."""
|
|
556
536
|
|
|
557
537
|
key: str = ""
|
|
558
|
-
altKey: bool = False
|
|
559
|
-
ctrlKey: bool = False
|
|
560
|
-
metaKey: bool = False
|
|
561
|
-
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
|
|
562
542
|
|
|
563
543
|
|
|
564
|
-
def input_event(e:
|
|
544
|
+
def input_event(e: ObjectVar[JavascriptInputEvent]) -> Tuple[Var[str]]:
|
|
565
545
|
"""Get the value from an input event.
|
|
566
546
|
|
|
567
547
|
Args:
|
|
@@ -582,7 +562,9 @@ class KeyInputInfo(TypedDict):
|
|
|
582
562
|
shift_key: bool
|
|
583
563
|
|
|
584
564
|
|
|
585
|
-
def key_event(
|
|
565
|
+
def key_event(
|
|
566
|
+
e: ObjectVar[JavasciptKeyboardEvent],
|
|
567
|
+
) -> Tuple[Var[str], Var[KeyInputInfo]]:
|
|
586
568
|
"""Get the key from a keyboard event.
|
|
587
569
|
|
|
588
570
|
Args:
|
|
@@ -592,7 +574,7 @@ def key_event(e: Var[JavasciptKeyboardEvent]) -> Tuple[Var[str], Var[KeyInputInf
|
|
|
592
574
|
The key from the keyboard event.
|
|
593
575
|
"""
|
|
594
576
|
return (
|
|
595
|
-
e.key,
|
|
577
|
+
e.key.to(str),
|
|
596
578
|
Var.create(
|
|
597
579
|
{
|
|
598
580
|
"alt_key": e.altKey,
|
|
@@ -600,7 +582,7 @@ def key_event(e: Var[JavasciptKeyboardEvent]) -> Tuple[Var[str], Var[KeyInputInf
|
|
|
600
582
|
"meta_key": e.metaKey,
|
|
601
583
|
"shift_key": e.shiftKey,
|
|
602
584
|
},
|
|
603
|
-
),
|
|
585
|
+
).to(KeyInputInfo),
|
|
604
586
|
)
|
|
605
587
|
|
|
606
588
|
|
|
@@ -610,7 +592,7 @@ def no_args_event_spec() -> Tuple[()]:
|
|
|
610
592
|
Returns:
|
|
611
593
|
An empty tuple.
|
|
612
594
|
"""
|
|
613
|
-
return ()
|
|
595
|
+
return ()
|
|
614
596
|
|
|
615
597
|
|
|
616
598
|
# These chains can be used for their side effects when no other events are desired.
|
|
@@ -638,9 +620,9 @@ class IdentityEventReturn(Generic[T], Protocol):
|
|
|
638
620
|
|
|
639
621
|
|
|
640
622
|
@overload
|
|
641
|
-
def passthrough_event_spec(
|
|
623
|
+
def passthrough_event_spec( # pyright: ignore [reportOverlappingOverload]
|
|
642
624
|
event_type: Type[T], /
|
|
643
|
-
) -> Callable[[Var[T]], Tuple[Var[T]]]: ...
|
|
625
|
+
) -> Callable[[Var[T]], Tuple[Var[T]]]: ...
|
|
644
626
|
|
|
645
627
|
|
|
646
628
|
@overload
|
|
@@ -653,7 +635,7 @@ def passthrough_event_spec(
|
|
|
653
635
|
def passthrough_event_spec(*event_types: Type[T]) -> IdentityEventReturn[T]: ...
|
|
654
636
|
|
|
655
637
|
|
|
656
|
-
def passthrough_event_spec(*event_types: Type[T]) -> IdentityEventReturn[T]: #
|
|
638
|
+
def passthrough_event_spec(*event_types: Type[T]) -> IdentityEventReturn[T]: # pyright: ignore [reportInconsistentOverload]
|
|
657
639
|
"""A helper function that returns the input event as output.
|
|
658
640
|
|
|
659
641
|
Args:
|
|
@@ -667,9 +649,9 @@ def passthrough_event_spec(*event_types: Type[T]) -> IdentityEventReturn[T]: #
|
|
|
667
649
|
return values
|
|
668
650
|
|
|
669
651
|
inner_type = tuple(Var[event_type] for event_type in event_types)
|
|
670
|
-
return_annotation = Tuple[inner_type]
|
|
652
|
+
return_annotation = Tuple[inner_type]
|
|
671
653
|
|
|
672
|
-
inner.__signature__ = inspect.signature(inner).replace( #
|
|
654
|
+
inner.__signature__ = inspect.signature(inner).replace( # pyright: ignore [reportFunctionMemberAccess]
|
|
673
655
|
parameters=[
|
|
674
656
|
inspect.Parameter(
|
|
675
657
|
f"ev_{i}",
|
|
@@ -751,7 +733,7 @@ class FileUpload:
|
|
|
751
733
|
# Call the lambda to get the event chain.
|
|
752
734
|
events = call_event_fn(
|
|
753
735
|
on_upload_progress, self.on_upload_progress_args_spec
|
|
754
|
-
)
|
|
736
|
+
)
|
|
755
737
|
else:
|
|
756
738
|
raise ValueError(f"{on_upload_progress} is not a valid event handler.")
|
|
757
739
|
if isinstance(events, Var):
|
|
@@ -798,7 +780,7 @@ def server_side(name: str, sig: inspect.Signature, **kwargs) -> EventSpec:
|
|
|
798
780
|
return None
|
|
799
781
|
|
|
800
782
|
fn.__qualname__ = name
|
|
801
|
-
fn.__signature__ = sig
|
|
783
|
+
fn.__signature__ = sig # pyright: ignore [reportFunctionMemberAccess]
|
|
802
784
|
return EventSpec(
|
|
803
785
|
handler=EventHandler(fn=fn, state_full_name=FRONTEND_EVENT_STATE),
|
|
804
786
|
args=tuple(
|
|
@@ -811,29 +793,10 @@ def server_side(name: str, sig: inspect.Signature, **kwargs) -> EventSpec:
|
|
|
811
793
|
)
|
|
812
794
|
|
|
813
795
|
|
|
814
|
-
@overload
|
|
815
796
|
def redirect(
|
|
816
797
|
path: str | Var[str],
|
|
817
|
-
is_external:
|
|
798
|
+
is_external: bool = False,
|
|
818
799
|
replace: bool = False,
|
|
819
|
-
) -> EventSpec: ...
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
@overload
|
|
823
|
-
@typing_extensions.deprecated("`external` is deprecated use `is_external` instead")
|
|
824
|
-
def redirect(
|
|
825
|
-
path: str | Var[str],
|
|
826
|
-
is_external: Optional[bool] = None,
|
|
827
|
-
replace: bool = False,
|
|
828
|
-
external: Optional[bool] = None,
|
|
829
|
-
) -> EventSpec: ...
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
def redirect(
|
|
833
|
-
path: str | Var[str],
|
|
834
|
-
is_external: Optional[bool] = None,
|
|
835
|
-
replace: bool = False,
|
|
836
|
-
external: Optional[bool] = None,
|
|
837
800
|
) -> EventSpec:
|
|
838
801
|
"""Redirect to a new path.
|
|
839
802
|
|
|
@@ -841,26 +804,10 @@ def redirect(
|
|
|
841
804
|
path: The path to redirect to.
|
|
842
805
|
is_external: Whether to open in new tab or not.
|
|
843
806
|
replace: If True, the current page will not create a new history entry.
|
|
844
|
-
external(Deprecated): Whether to open in new tab or not.
|
|
845
807
|
|
|
846
808
|
Returns:
|
|
847
809
|
An event to redirect to the path.
|
|
848
810
|
"""
|
|
849
|
-
if external is not None:
|
|
850
|
-
console.deprecate(
|
|
851
|
-
"The `external` prop in `rx.redirect`",
|
|
852
|
-
"use `is_external` instead.",
|
|
853
|
-
"0.6.6",
|
|
854
|
-
"0.7.0",
|
|
855
|
-
)
|
|
856
|
-
|
|
857
|
-
# is_external should take precedence over external.
|
|
858
|
-
is_external = (
|
|
859
|
-
(False if external is None else external)
|
|
860
|
-
if is_external is None
|
|
861
|
-
else is_external
|
|
862
|
-
)
|
|
863
|
-
|
|
864
811
|
return server_side(
|
|
865
812
|
"_redirect",
|
|
866
813
|
get_fn_signature(redirect),
|
|
@@ -1106,13 +1053,13 @@ def download(
|
|
|
1106
1053
|
|
|
1107
1054
|
is_data_url = (data.js_type() == "string") & (
|
|
1108
1055
|
data.to(str).startswith("data:")
|
|
1109
|
-
)
|
|
1056
|
+
)
|
|
1110
1057
|
|
|
1111
1058
|
# If it's a data: URI, use it as is, otherwise convert the Var to JSON in a data: URI.
|
|
1112
|
-
url = cond(
|
|
1059
|
+
url = cond(
|
|
1113
1060
|
is_data_url,
|
|
1114
1061
|
data.to(str),
|
|
1115
|
-
"data:text/plain," + data.to_string(),
|
|
1062
|
+
"data:text/plain," + data.to_string(),
|
|
1116
1063
|
)
|
|
1117
1064
|
elif isinstance(data, bytes):
|
|
1118
1065
|
# Caller provided bytes, so base64 encode it as a data: URI.
|
|
@@ -1131,7 +1078,8 @@ def download(
|
|
|
1131
1078
|
)
|
|
1132
1079
|
|
|
1133
1080
|
|
|
1134
|
-
|
|
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):
|
|
1135
1083
|
"""ArgSpec for call_script callback function.
|
|
1136
1084
|
|
|
1137
1085
|
Args:
|
|
@@ -1145,7 +1093,7 @@ def _callback_arg_spec(eval_result):
|
|
|
1145
1093
|
|
|
1146
1094
|
def call_script(
|
|
1147
1095
|
javascript_code: str | Var[str],
|
|
1148
|
-
callback: EventType | None = None,
|
|
1096
|
+
callback: EventType[Any] | None = None,
|
|
1149
1097
|
) -> EventSpec:
|
|
1150
1098
|
"""Create an event handler that executes arbitrary javascript code.
|
|
1151
1099
|
|
|
@@ -1184,7 +1132,7 @@ def call_script(
|
|
|
1184
1132
|
|
|
1185
1133
|
def call_function(
|
|
1186
1134
|
javascript_code: str | Var,
|
|
1187
|
-
callback: EventType | None = None,
|
|
1135
|
+
callback: EventType[Any] | None = None,
|
|
1188
1136
|
) -> EventSpec:
|
|
1189
1137
|
"""Create an event handler that executes arbitrary javascript code.
|
|
1190
1138
|
|
|
@@ -1218,7 +1166,7 @@ def call_function(
|
|
|
1218
1166
|
|
|
1219
1167
|
def run_script(
|
|
1220
1168
|
javascript_code: str | Var,
|
|
1221
|
-
callback: EventType | None = None,
|
|
1169
|
+
callback: EventType[Any] | None = None,
|
|
1222
1170
|
) -> EventSpec:
|
|
1223
1171
|
"""Create an event handler that executes arbitrary javascript code.
|
|
1224
1172
|
|
|
@@ -1236,7 +1184,7 @@ def run_script(
|
|
|
1236
1184
|
return call_function(ArgsFunctionOperation.create((), javascript_code), callback)
|
|
1237
1185
|
|
|
1238
1186
|
|
|
1239
|
-
def get_event(state, event):
|
|
1187
|
+
def get_event(state: BaseState, event: str):
|
|
1240
1188
|
"""Get the event from the given state.
|
|
1241
1189
|
|
|
1242
1190
|
Args:
|
|
@@ -1249,7 +1197,7 @@ def get_event(state, event):
|
|
|
1249
1197
|
return f"{state.get_name()}.{event}"
|
|
1250
1198
|
|
|
1251
1199
|
|
|
1252
|
-
def get_hydrate_event(state) -> str:
|
|
1200
|
+
def get_hydrate_event(state: BaseState) -> str:
|
|
1253
1201
|
"""Get the name of the hydrate event for the state.
|
|
1254
1202
|
|
|
1255
1203
|
Args:
|
|
@@ -1277,13 +1225,16 @@ def call_event_handler(
|
|
|
1277
1225
|
event_spec: The lambda that define the argument(s) to pass to the event handler.
|
|
1278
1226
|
key: The key to pass to the event handler.
|
|
1279
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
|
+
|
|
1280
1232
|
Returns:
|
|
1281
1233
|
The event spec from calling the event handler.
|
|
1282
1234
|
|
|
1283
|
-
#
|
|
1284
|
-
|
|
1235
|
+
#noqa: DAR401
|
|
1285
1236
|
"""
|
|
1286
|
-
event_spec_args = parse_args_spec(event_spec)
|
|
1237
|
+
event_spec_args = parse_args_spec(event_spec)
|
|
1287
1238
|
|
|
1288
1239
|
if isinstance(event_callback, EventSpec):
|
|
1289
1240
|
check_fn_match_arg_spec(
|
|
@@ -1318,10 +1269,15 @@ def call_event_handler(
|
|
|
1318
1269
|
),
|
|
1319
1270
|
)
|
|
1320
1271
|
)
|
|
1272
|
+
type_match_found: dict[str, bool] = {}
|
|
1273
|
+
delayed_exceptions: list[EventHandlerArgTypeMismatchError] = []
|
|
1321
1274
|
|
|
1322
|
-
|
|
1323
|
-
|
|
1275
|
+
try:
|
|
1276
|
+
type_hints_of_provided_callback = get_type_hints(event_callback.fn)
|
|
1277
|
+
except NameError:
|
|
1278
|
+
type_hints_of_provided_callback = {}
|
|
1324
1279
|
|
|
1280
|
+
if event_spec_return_types:
|
|
1325
1281
|
event_callback_spec = inspect.getfullargspec(event_callback.fn)
|
|
1326
1282
|
|
|
1327
1283
|
for event_spec_index, event_spec_return_type in enumerate(
|
|
@@ -1333,43 +1289,35 @@ def call_event_handler(
|
|
|
1333
1289
|
arg if get_origin(arg) is not Var else get_args(arg)[0] for arg in args
|
|
1334
1290
|
]
|
|
1335
1291
|
|
|
1336
|
-
try:
|
|
1337
|
-
type_hints_of_provided_callback = get_type_hints(event_callback.fn)
|
|
1338
|
-
except NameError:
|
|
1339
|
-
type_hints_of_provided_callback = {}
|
|
1340
|
-
|
|
1341
|
-
failed_type_check = False
|
|
1342
|
-
|
|
1343
1292
|
# check that args of event handler are matching the spec if type hints are provided
|
|
1344
1293
|
for i, arg in enumerate(event_callback_spec.args[1:]):
|
|
1345
1294
|
if arg not in type_hints_of_provided_callback:
|
|
1346
1295
|
continue
|
|
1347
1296
|
|
|
1297
|
+
type_match_found.setdefault(arg, False)
|
|
1298
|
+
|
|
1348
1299
|
try:
|
|
1349
1300
|
compare_result = typehint_issubclass(
|
|
1350
1301
|
args_types_without_vars[i], type_hints_of_provided_callback[arg]
|
|
1351
1302
|
)
|
|
1352
|
-
except TypeError:
|
|
1353
|
-
|
|
1354
|
-
# raise TypeError(
|
|
1355
|
-
# 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
|
|
1356
|
-
# ) from e
|
|
1357
|
-
console.warn(
|
|
1303
|
+
except TypeError as te:
|
|
1304
|
+
raise TypeError(
|
|
1358
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}."
|
|
1359
|
-
)
|
|
1360
|
-
compare_result = False
|
|
1306
|
+
) from te
|
|
1361
1307
|
|
|
1362
1308
|
if compare_result:
|
|
1309
|
+
type_match_found[arg] = True
|
|
1363
1310
|
continue
|
|
1364
1311
|
else:
|
|
1365
|
-
|
|
1366
|
-
|
|
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
|
+
)
|
|
1367
1317
|
)
|
|
1368
|
-
failures.append(failure)
|
|
1369
|
-
failed_type_check = True
|
|
1370
|
-
break
|
|
1371
1318
|
|
|
1372
|
-
if
|
|
1319
|
+
if all(type_match_found.values()):
|
|
1320
|
+
delayed_exceptions.clear()
|
|
1373
1321
|
if event_spec_index:
|
|
1374
1322
|
args = get_args(event_spec_return_types[0])
|
|
1375
1323
|
|
|
@@ -1391,17 +1339,12 @@ def call_event_handler(
|
|
|
1391
1339
|
f"Event handler {key} expects ({expect_string}) -> () but got ({given_string}) -> () as annotated in {event_callback.fn.__qualname__} instead. "
|
|
1392
1340
|
f"This may lead to unexpected behavior but is intentionally ignored for {key}."
|
|
1393
1341
|
)
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
"Mismatched event handler argument types",
|
|
1399
|
-
"\n".join([str(f) for f in failures]),
|
|
1400
|
-
"0.6.5",
|
|
1401
|
-
"0.7.0",
|
|
1402
|
-
)
|
|
1342
|
+
break
|
|
1343
|
+
|
|
1344
|
+
if delayed_exceptions:
|
|
1345
|
+
raise delayed_exceptions[0]
|
|
1403
1346
|
|
|
1404
|
-
return event_callback(*event_spec_args)
|
|
1347
|
+
return event_callback(*event_spec_args)
|
|
1405
1348
|
|
|
1406
1349
|
|
|
1407
1350
|
def unwrap_var_annotation(annotation: GenericType):
|
|
@@ -1413,31 +1356,31 @@ def unwrap_var_annotation(annotation: GenericType):
|
|
|
1413
1356
|
Returns:
|
|
1414
1357
|
The unwrapped annotation.
|
|
1415
1358
|
"""
|
|
1416
|
-
if get_origin(annotation)
|
|
1359
|
+
if get_origin(annotation) in (Var, ObjectVar) and (args := get_args(annotation)):
|
|
1417
1360
|
return args[0]
|
|
1418
1361
|
return annotation
|
|
1419
1362
|
|
|
1420
1363
|
|
|
1421
|
-
def resolve_annotation(annotations: dict[str, Any], arg_name: str):
|
|
1364
|
+
def resolve_annotation(annotations: dict[str, Any], arg_name: str, spec: ArgsSpec):
|
|
1422
1365
|
"""Resolve the annotation for the given argument name.
|
|
1423
1366
|
|
|
1424
1367
|
Args:
|
|
1425
1368
|
annotations: The annotations.
|
|
1426
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.
|
|
1427
1374
|
|
|
1428
1375
|
Returns:
|
|
1429
1376
|
The resolved annotation.
|
|
1430
1377
|
"""
|
|
1431
1378
|
annotation = annotations.get(arg_name)
|
|
1432
1379
|
if annotation is None:
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
removal_version="0.7.0",
|
|
1438
|
-
)
|
|
1439
|
-
# Allow arbitrary attribute access two levels deep until removed.
|
|
1440
|
-
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]
|
|
1441
1384
|
return annotation
|
|
1442
1385
|
|
|
1443
1386
|
|
|
@@ -1459,7 +1402,13 @@ def parse_args_spec(arg_spec: ArgsSpec | Sequence[ArgsSpec]):
|
|
|
1459
1402
|
arg_spec(
|
|
1460
1403
|
*[
|
|
1461
1404
|
Var(f"_{l_arg}").to(
|
|
1462
|
-
unwrap_var_annotation(
|
|
1405
|
+
unwrap_var_annotation(
|
|
1406
|
+
resolve_annotation(
|
|
1407
|
+
annotations,
|
|
1408
|
+
l_arg,
|
|
1409
|
+
spec=arg_spec,
|
|
1410
|
+
)
|
|
1411
|
+
)
|
|
1463
1412
|
)
|
|
1464
1413
|
for l_arg in spec.args
|
|
1465
1414
|
]
|
|
@@ -1475,7 +1424,7 @@ def check_fn_match_arg_spec(
|
|
|
1475
1424
|
func_name: str | None = None,
|
|
1476
1425
|
):
|
|
1477
1426
|
"""Ensures that the function signature matches the passed argument specification
|
|
1478
|
-
or raises an
|
|
1427
|
+
or raises an EventFnArgMismatchError if they do not.
|
|
1479
1428
|
|
|
1480
1429
|
Args:
|
|
1481
1430
|
user_func: The function to be validated.
|
|
@@ -1485,7 +1434,7 @@ def check_fn_match_arg_spec(
|
|
|
1485
1434
|
func_name: The name of the function to be validated.
|
|
1486
1435
|
|
|
1487
1436
|
Raises:
|
|
1488
|
-
|
|
1437
|
+
EventFnArgMismatchError: Raised if the number of mandatory arguments do not match
|
|
1489
1438
|
"""
|
|
1490
1439
|
user_args = inspect.getfullargspec(user_func).args
|
|
1491
1440
|
# Drop the first argument if it's a bound method
|
|
@@ -1501,7 +1450,7 @@ def check_fn_match_arg_spec(
|
|
|
1501
1450
|
number_of_event_args = len(parsed_event_args)
|
|
1502
1451
|
|
|
1503
1452
|
if number_of_user_args - number_of_user_default_args > number_of_event_args:
|
|
1504
|
-
raise
|
|
1453
|
+
raise EventFnArgMismatchError(
|
|
1505
1454
|
f"Event {key} only provides {number_of_event_args} arguments, but "
|
|
1506
1455
|
f"{func_name or user_func} requires at least {number_of_user_args - number_of_user_default_args} "
|
|
1507
1456
|
"arguments to be passed to the event handler.\n"
|
|
@@ -1589,7 +1538,7 @@ def get_handler_args(
|
|
|
1589
1538
|
|
|
1590
1539
|
|
|
1591
1540
|
def fix_events(
|
|
1592
|
-
events: list[
|
|
1541
|
+
events: list[EventSpec | EventHandler] | None,
|
|
1593
1542
|
token: str,
|
|
1594
1543
|
router_data: dict[str, Any] | None = None,
|
|
1595
1544
|
) -> list[Event]:
|
|
@@ -1629,7 +1578,7 @@ def fix_events(
|
|
|
1629
1578
|
if not isinstance(e, EventSpec):
|
|
1630
1579
|
raise ValueError(f"Unexpected event type, {type(e)}.")
|
|
1631
1580
|
name = format.format_event_handler(e.handler)
|
|
1632
|
-
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}
|
|
1633
1582
|
|
|
1634
1583
|
# Filter router_data to reduce payload size
|
|
1635
1584
|
event_router_data = {
|
|
@@ -1673,12 +1622,12 @@ class EventVar(ObjectVar, python_types=EventSpec):
|
|
|
1673
1622
|
@dataclasses.dataclass(
|
|
1674
1623
|
eq=False,
|
|
1675
1624
|
frozen=True,
|
|
1676
|
-
|
|
1625
|
+
slots=True,
|
|
1677
1626
|
)
|
|
1678
1627
|
class LiteralEventVar(VarOperationCall, LiteralVar, EventVar):
|
|
1679
1628
|
"""A literal event var."""
|
|
1680
1629
|
|
|
1681
|
-
_var_value: EventSpec = dataclasses.field(default=None) #
|
|
1630
|
+
_var_value: EventSpec = dataclasses.field(default=None) # pyright: ignore [reportAssignmentType]
|
|
1682
1631
|
|
|
1683
1632
|
def __hash__(self) -> int:
|
|
1684
1633
|
"""Get the hash of the var.
|
|
@@ -1734,7 +1683,7 @@ class EventChainVar(BuilderFunctionVar, python_types=EventChain):
|
|
|
1734
1683
|
@dataclasses.dataclass(
|
|
1735
1684
|
eq=False,
|
|
1736
1685
|
frozen=True,
|
|
1737
|
-
|
|
1686
|
+
slots=True,
|
|
1738
1687
|
)
|
|
1739
1688
|
# Note: LiteralVar is second in the inheritance list allowing it act like a
|
|
1740
1689
|
# CachedVarOperation (ArgsFunctionOperation) and get the _js_expr from the
|
|
@@ -1742,7 +1691,7 @@ class EventChainVar(BuilderFunctionVar, python_types=EventChain):
|
|
|
1742
1691
|
class LiteralEventChainVar(ArgsFunctionOperationBuilder, LiteralVar, EventChainVar):
|
|
1743
1692
|
"""A literal event chain var."""
|
|
1744
1693
|
|
|
1745
|
-
_var_value: EventChain = dataclasses.field(default=None) #
|
|
1694
|
+
_var_value: EventChain = dataclasses.field(default=None) # pyright: ignore [reportAssignmentType]
|
|
1746
1695
|
|
|
1747
1696
|
def __hash__(self) -> int:
|
|
1748
1697
|
"""Get the hash of the var.
|
|
@@ -1766,13 +1715,16 @@ class LiteralEventChainVar(ArgsFunctionOperationBuilder, LiteralVar, EventChainV
|
|
|
1766
1715
|
|
|
1767
1716
|
Returns:
|
|
1768
1717
|
The created LiteralEventChainVar instance.
|
|
1718
|
+
|
|
1719
|
+
Raises:
|
|
1720
|
+
ValueError: If the invocation is not a FunctionVar.
|
|
1769
1721
|
"""
|
|
1770
1722
|
arg_spec = (
|
|
1771
1723
|
value.args_spec[0]
|
|
1772
1724
|
if isinstance(value.args_spec, Sequence)
|
|
1773
1725
|
else value.args_spec
|
|
1774
1726
|
)
|
|
1775
|
-
sig = inspect.signature(arg_spec) #
|
|
1727
|
+
sig = inspect.signature(arg_spec) # pyright: ignore [reportArgumentType]
|
|
1776
1728
|
if sig.parameters:
|
|
1777
1729
|
arg_def = tuple((f"_{p}" for p in sig.parameters))
|
|
1778
1730
|
arg_def_expr = LiteralVar.create([Var(_js_expr=arg) for arg in arg_def])
|
|
@@ -1783,10 +1735,21 @@ class LiteralEventChainVar(ArgsFunctionOperationBuilder, LiteralVar, EventChainV
|
|
|
1783
1735
|
arg_def_expr = Var(_js_expr="args")
|
|
1784
1736
|
|
|
1785
1737
|
if value.invocation is None:
|
|
1786
|
-
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
|
+
)
|
|
1787
1745
|
else:
|
|
1788
1746
|
invocation = value.invocation
|
|
1789
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
|
+
|
|
1790
1753
|
return cls(
|
|
1791
1754
|
_js_expr="",
|
|
1792
1755
|
_var_type=EventChain,
|
|
@@ -1801,8 +1764,8 @@ class LiteralEventChainVar(ArgsFunctionOperationBuilder, LiteralVar, EventChainV
|
|
|
1801
1764
|
)
|
|
1802
1765
|
|
|
1803
1766
|
|
|
1804
|
-
P =
|
|
1805
|
-
Q =
|
|
1767
|
+
P = TypeVarTuple("P")
|
|
1768
|
+
Q = TypeVarTuple("Q")
|
|
1806
1769
|
T = TypeVar("T")
|
|
1807
1770
|
V = TypeVar("V")
|
|
1808
1771
|
V2 = TypeVar("V2")
|
|
@@ -1810,13 +1773,11 @@ V3 = TypeVar("V3")
|
|
|
1810
1773
|
V4 = TypeVar("V4")
|
|
1811
1774
|
V5 = TypeVar("V5")
|
|
1812
1775
|
|
|
1813
|
-
background_event_decorator = background
|
|
1814
1776
|
|
|
1815
|
-
|
|
1816
|
-
class EventCallback(Generic[P, T]):
|
|
1777
|
+
class EventCallback(Generic[Unpack[P]], EventActionsMixin):
|
|
1817
1778
|
"""A descriptor that wraps a function to be used as an event."""
|
|
1818
1779
|
|
|
1819
|
-
def __init__(self, func: Callable[
|
|
1780
|
+
def __init__(self, func: Callable[[Any, Unpack[P]], Any]):
|
|
1820
1781
|
"""Initialize the descriptor with the function to be wrapped.
|
|
1821
1782
|
|
|
1822
1783
|
Args:
|
|
@@ -1824,59 +1785,41 @@ class EventCallback(Generic[P, T]):
|
|
|
1824
1785
|
"""
|
|
1825
1786
|
self.func = func
|
|
1826
1787
|
|
|
1827
|
-
@property
|
|
1828
|
-
def prevent_default(self):
|
|
1829
|
-
"""Prevent default behavior.
|
|
1830
|
-
|
|
1831
|
-
Returns:
|
|
1832
|
-
The event callback with prevent default behavior.
|
|
1833
|
-
"""
|
|
1834
|
-
return self
|
|
1835
|
-
|
|
1836
|
-
@property
|
|
1837
|
-
def stop_propagation(self):
|
|
1838
|
-
"""Stop event propagation.
|
|
1839
|
-
|
|
1840
|
-
Returns:
|
|
1841
|
-
The event callback with stop propagation behavior.
|
|
1842
|
-
"""
|
|
1843
|
-
return self
|
|
1844
|
-
|
|
1845
1788
|
@overload
|
|
1846
1789
|
def __call__(
|
|
1847
|
-
self: EventCallback[Q
|
|
1848
|
-
) -> EventCallback[Q
|
|
1790
|
+
self: EventCallback[Unpack[Q]],
|
|
1791
|
+
) -> EventCallback[Unpack[Q]]: ...
|
|
1849
1792
|
|
|
1850
1793
|
@overload
|
|
1851
1794
|
def __call__(
|
|
1852
|
-
self: EventCallback[
|
|
1853
|
-
) -> EventCallback[Q
|
|
1795
|
+
self: EventCallback[V, Unpack[Q]], value: V | Var[V]
|
|
1796
|
+
) -> EventCallback[Unpack[Q]]: ...
|
|
1854
1797
|
|
|
1855
1798
|
@overload
|
|
1856
1799
|
def __call__(
|
|
1857
|
-
self: EventCallback[
|
|
1800
|
+
self: EventCallback[V, V2, Unpack[Q]],
|
|
1858
1801
|
value: V | Var[V],
|
|
1859
1802
|
value2: V2 | Var[V2],
|
|
1860
|
-
) -> EventCallback[Q
|
|
1803
|
+
) -> EventCallback[Unpack[Q]]: ...
|
|
1861
1804
|
|
|
1862
1805
|
@overload
|
|
1863
1806
|
def __call__(
|
|
1864
|
-
self: EventCallback[
|
|
1807
|
+
self: EventCallback[V, V2, V3, Unpack[Q]],
|
|
1865
1808
|
value: V | Var[V],
|
|
1866
1809
|
value2: V2 | Var[V2],
|
|
1867
1810
|
value3: V3 | Var[V3],
|
|
1868
|
-
) -> EventCallback[Q
|
|
1811
|
+
) -> EventCallback[Unpack[Q]]: ...
|
|
1869
1812
|
|
|
1870
1813
|
@overload
|
|
1871
1814
|
def __call__(
|
|
1872
|
-
self: EventCallback[
|
|
1815
|
+
self: EventCallback[V, V2, V3, V4, Unpack[Q]],
|
|
1873
1816
|
value: V | Var[V],
|
|
1874
1817
|
value2: V2 | Var[V2],
|
|
1875
1818
|
value3: V3 | Var[V3],
|
|
1876
1819
|
value4: V4 | Var[V4],
|
|
1877
|
-
) -> EventCallback[Q
|
|
1820
|
+
) -> EventCallback[Unpack[Q]]: ...
|
|
1878
1821
|
|
|
1879
|
-
def __call__(self, *values) -> EventCallback: #
|
|
1822
|
+
def __call__(self, *values) -> EventCallback: # pyright: ignore [reportInconsistentOverload]
|
|
1880
1823
|
"""Call the function with the values.
|
|
1881
1824
|
|
|
1882
1825
|
Args:
|
|
@@ -1885,17 +1828,17 @@ class EventCallback(Generic[P, T]):
|
|
|
1885
1828
|
Returns:
|
|
1886
1829
|
The function with the values.
|
|
1887
1830
|
"""
|
|
1888
|
-
return self.func(*values) #
|
|
1831
|
+
return self.func(*values) # pyright: ignore [reportArgumentType]
|
|
1889
1832
|
|
|
1890
1833
|
@overload
|
|
1891
1834
|
def __get__(
|
|
1892
|
-
self: EventCallback[P
|
|
1893
|
-
) -> EventCallback[P
|
|
1835
|
+
self: EventCallback[Unpack[P]], instance: None, owner: Any
|
|
1836
|
+
) -> EventCallback[Unpack[P]]: ...
|
|
1894
1837
|
|
|
1895
1838
|
@overload
|
|
1896
|
-
def __get__(self, instance, owner) -> Callable[P
|
|
1839
|
+
def __get__(self, instance: Any, owner: Any) -> Callable[[Unpack[P]]]: ...
|
|
1897
1840
|
|
|
1898
|
-
def __get__(self, instance, owner) -> Callable:
|
|
1841
|
+
def __get__(self, instance: Any, owner: Any) -> Callable:
|
|
1899
1842
|
"""Get the function with the instance bound to it.
|
|
1900
1843
|
|
|
1901
1844
|
Args:
|
|
@@ -1906,38 +1849,74 @@ class EventCallback(Generic[P, T]):
|
|
|
1906
1849
|
The function with the instance bound to it
|
|
1907
1850
|
"""
|
|
1908
1851
|
if instance is None:
|
|
1909
|
-
return self.func
|
|
1852
|
+
return self.func
|
|
1910
1853
|
|
|
1911
|
-
return partial(self.func, instance)
|
|
1854
|
+
return partial(self.func, instance)
|
|
1912
1855
|
|
|
1913
1856
|
|
|
1914
|
-
|
|
1857
|
+
class LambdaEventCallback(Protocol[Unpack[P]]):
|
|
1858
|
+
"""A protocol for a lambda event callback."""
|
|
1915
1859
|
|
|
1916
|
-
|
|
1917
|
-
|
|
1860
|
+
@overload
|
|
1861
|
+
def __call__(self: LambdaEventCallback[()]) -> Any: ...
|
|
1918
1862
|
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
BASE_STATE = TypeVar("BASE_STATE")
|
|
1863
|
+
@overload
|
|
1864
|
+
def __call__(self: LambdaEventCallback[V], value: Var[V], /) -> Any: ...
|
|
1922
1865
|
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
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")
|
|
1889
|
+
|
|
1890
|
+
|
|
1891
|
+
LAMBDA_OR_STATE = TypeAliasType(
|
|
1892
|
+
"LAMBDA_OR_STATE",
|
|
1893
|
+
LambdaEventCallback[Unpack[ARGS]] | EventCallback[Unpack[ARGS]],
|
|
1894
|
+
type_params=(ARGS,),
|
|
1895
|
+
)
|
|
1896
|
+
|
|
1897
|
+
ItemOrList = V | List[V]
|
|
1898
|
+
|
|
1899
|
+
BASIC_EVENT_TYPES = TypeAliasType(
|
|
1900
|
+
"BASIC_EVENT_TYPES", EventSpec | EventHandler | Var[Any], type_params=()
|
|
1927
1901
|
)
|
|
1928
1902
|
|
|
1929
|
-
IndividualEventType =
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
EventCallback[G, Any],
|
|
1935
|
-
Var[Any],
|
|
1936
|
-
]
|
|
1903
|
+
IndividualEventType = TypeAliasType(
|
|
1904
|
+
"IndividualEventType",
|
|
1905
|
+
LAMBDA_OR_STATE[Unpack[ARGS]] | BASIC_EVENT_TYPES,
|
|
1906
|
+
type_params=(ARGS,),
|
|
1907
|
+
)
|
|
1937
1908
|
|
|
1938
|
-
|
|
1909
|
+
EventType = TypeAliasType(
|
|
1910
|
+
"EventType", ItemOrList[IndividualEventType[Unpack[ARGS]]], type_params=(ARGS,)
|
|
1911
|
+
)
|
|
1939
1912
|
|
|
1940
|
-
|
|
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")
|
|
1941
1920
|
|
|
1942
1921
|
|
|
1943
1922
|
class EventNamespace(types.SimpleNamespace):
|
|
@@ -1959,24 +1938,26 @@ class EventNamespace(types.SimpleNamespace):
|
|
|
1959
1938
|
@staticmethod
|
|
1960
1939
|
def __call__(
|
|
1961
1940
|
func: None = None, *, background: bool | None = None
|
|
1962
|
-
) -> Callable[
|
|
1941
|
+
) -> Callable[
|
|
1942
|
+
[Callable[[BASE_STATE, Unpack[P]], Any]], EventCallback[Unpack[P]] # pyright: ignore [reportInvalidTypeVarUse]
|
|
1943
|
+
]: ...
|
|
1963
1944
|
|
|
1964
1945
|
@overload
|
|
1965
1946
|
@staticmethod
|
|
1966
1947
|
def __call__(
|
|
1967
|
-
func: Callable[
|
|
1948
|
+
func: Callable[[BASE_STATE, Unpack[P]], Any],
|
|
1968
1949
|
*,
|
|
1969
1950
|
background: bool | None = None,
|
|
1970
|
-
) -> EventCallback[P
|
|
1951
|
+
) -> EventCallback[Unpack[P]]: ...
|
|
1971
1952
|
|
|
1972
1953
|
@staticmethod
|
|
1973
1954
|
def __call__(
|
|
1974
|
-
func: Callable[
|
|
1955
|
+
func: Callable[[BASE_STATE, Unpack[P]], Any] | None = None,
|
|
1975
1956
|
*,
|
|
1976
1957
|
background: bool | None = None,
|
|
1977
1958
|
) -> Union[
|
|
1978
|
-
EventCallback[P
|
|
1979
|
-
Callable[[Callable[
|
|
1959
|
+
EventCallback[Unpack[P]],
|
|
1960
|
+
Callable[[Callable[[BASE_STATE, Unpack[P]], Any]], EventCallback[Unpack[P]]],
|
|
1980
1961
|
]:
|
|
1981
1962
|
"""Wrap a function to be used as an event.
|
|
1982
1963
|
|
|
@@ -1984,16 +1965,25 @@ class EventNamespace(types.SimpleNamespace):
|
|
|
1984
1965
|
func: The function to wrap.
|
|
1985
1966
|
background: Whether the event should be run in the background. Defaults to False.
|
|
1986
1967
|
|
|
1968
|
+
Raises:
|
|
1969
|
+
TypeError: If background is True and the function is not a coroutine or async generator. # noqa: DAR402
|
|
1970
|
+
|
|
1987
1971
|
Returns:
|
|
1988
1972
|
The wrapped function.
|
|
1989
1973
|
"""
|
|
1990
1974
|
|
|
1991
1975
|
def wrapper(
|
|
1992
|
-
func: Callable[
|
|
1993
|
-
) -> EventCallback[P
|
|
1976
|
+
func: Callable[[BASE_STATE, Unpack[P]], T],
|
|
1977
|
+
) -> EventCallback[Unpack[P]]:
|
|
1994
1978
|
if background is True:
|
|
1995
|
-
|
|
1996
|
-
|
|
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]
|
|
1997
1987
|
|
|
1998
1988
|
if func is not None:
|
|
1999
1989
|
return wrapper(func)
|