reflex 0.6.4a2__py3-none-any.whl → 0.6.5__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/web/pages/custom_component.js.jinja2 +0 -14
- reflex/.templates/jinja/web/pages/utils.js.jinja2 +4 -8
- reflex/.templates/web/components/shiki/code.js +16 -11
- reflex/.templates/web/utils/state.js +29 -21
- reflex/__init__.py +4 -0
- reflex/__init__.pyi +4 -0
- reflex/app.py +148 -154
- reflex/app_mixins/lifespan.py +5 -1
- reflex/app_mixins/middleware.py +3 -1
- reflex/app_mixins/mixin.py +3 -2
- reflex/base.py +2 -4
- reflex/compiler/compiler.py +111 -37
- reflex/components/base/app_wrap.pyi +17 -17
- reflex/components/base/bare.py +72 -3
- reflex/components/base/body.pyi +17 -17
- reflex/components/base/document.pyi +81 -81
- reflex/components/base/error_boundary.pyi +25 -18
- reflex/components/base/fragment.pyi +17 -17
- reflex/components/base/head.pyi +33 -33
- reflex/components/base/link.pyi +33 -33
- reflex/components/base/meta.pyi +65 -65
- reflex/components/base/script.py +4 -4
- reflex/components/base/script.pyi +23 -20
- reflex/components/component.py +250 -31
- reflex/components/core/banner.py +1 -1
- reflex/components/core/banner.pyi +81 -81
- reflex/components/core/client_side_routing.pyi +33 -33
- reflex/components/core/clipboard.py +2 -2
- reflex/components/core/clipboard.pyi +24 -18
- reflex/components/core/debounce.py +2 -2
- reflex/components/core/debounce.pyi +18 -18
- reflex/components/core/html.pyi +17 -17
- reflex/components/core/upload.py +90 -28
- reflex/components/core/upload.pyi +128 -72
- reflex/components/datadisplay/code.py +55 -40
- reflex/components/datadisplay/code.pyi +46 -44
- reflex/components/datadisplay/dataeditor.py +21 -20
- reflex/components/datadisplay/dataeditor.pyi +103 -35
- reflex/components/datadisplay/shiki_code_block.py +60 -27
- reflex/components/datadisplay/shiki_code_block.pyi +86 -65
- reflex/components/dynamic.py +9 -5
- reflex/components/el/element.pyi +17 -17
- reflex/components/el/elements/base.pyi +17 -17
- reflex/components/el/elements/forms.py +12 -3
- reflex/components/el/elements/forms.pyi +293 -233
- reflex/components/el/elements/inline.pyi +449 -449
- reflex/components/el/elements/media.pyi +401 -401
- reflex/components/el/elements/metadata.pyi +97 -97
- reflex/components/el/elements/other.pyi +113 -113
- reflex/components/el/elements/scripts.pyi +49 -49
- reflex/components/el/elements/sectioning.pyi +241 -241
- reflex/components/el/elements/tables.pyi +161 -161
- reflex/components/el/elements/typography.pyi +241 -241
- reflex/components/gridjs/datatable.pyi +33 -33
- reflex/components/lucide/icon.py +1 -1
- reflex/components/lucide/icon.pyi +33 -33
- reflex/components/markdown/markdown.py +180 -49
- reflex/components/markdown/markdown.pyi +36 -19
- reflex/components/moment/moment.py +17 -21
- reflex/components/moment/moment.pyi +26 -21
- reflex/components/next/base.pyi +17 -17
- reflex/components/next/image.py +3 -3
- reflex/components/next/image.pyi +21 -19
- reflex/components/next/link.pyi +17 -17
- reflex/components/next/video.pyi +17 -17
- reflex/components/plotly/plotly.py +79 -78
- reflex/components/plotly/plotly.pyi +91 -41
- reflex/components/props.py +34 -0
- reflex/components/radix/primitives/accordion.py +15 -8
- reflex/components/radix/primitives/accordion.pyi +121 -118
- reflex/components/radix/primitives/base.pyi +33 -33
- reflex/components/radix/primitives/drawer.py +41 -20
- reflex/components/radix/primitives/drawer.pyi +279 -190
- reflex/components/radix/primitives/form.py +2 -2
- reflex/components/radix/primitives/form.pyi +200 -167
- reflex/components/radix/primitives/progress.pyi +81 -81
- reflex/components/radix/primitives/slider.pyi +89 -83
- reflex/components/radix/themes/base.py +30 -1
- reflex/components/radix/themes/base.pyi +286 -113
- reflex/components/radix/themes/color_mode.py +17 -9
- reflex/components/radix/themes/color_mode.pyi +68 -56
- reflex/components/radix/themes/components/alert_dialog.py +8 -5
- reflex/components/radix/themes/components/alert_dialog.pyi +125 -117
- reflex/components/radix/themes/components/aspect_ratio.pyi +17 -17
- reflex/components/radix/themes/components/avatar.py +1 -5
- reflex/components/radix/themes/components/avatar.pyi +17 -17
- reflex/components/radix/themes/components/badge.py +1 -5
- reflex/components/radix/themes/components/badge.pyi +17 -17
- reflex/components/radix/themes/components/button.pyi +18 -21
- reflex/components/radix/themes/components/callout.py +1 -4
- reflex/components/radix/themes/components/callout.pyi +81 -81
- reflex/components/radix/themes/components/card.py +1 -3
- reflex/components/radix/themes/components/card.pyi +17 -17
- reflex/components/radix/themes/components/checkbox.py +4 -8
- reflex/components/radix/themes/components/checkbox.pyi +61 -52
- reflex/components/radix/themes/components/checkbox_cards.pyi +33 -33
- reflex/components/radix/themes/components/checkbox_group.pyi +33 -33
- reflex/components/radix/themes/components/context_menu.py +121 -28
- reflex/components/radix/themes/components/context_menu.pyi +250 -147
- reflex/components/radix/themes/components/data_list.pyi +65 -65
- reflex/components/radix/themes/components/dialog.py +11 -11
- reflex/components/radix/themes/components/dialog.pyi +135 -120
- reflex/components/radix/themes/components/dropdown_menu.py +14 -25
- reflex/components/radix/themes/components/dropdown_menu.pyi +157 -145
- reflex/components/radix/themes/components/hover_card.py +19 -7
- reflex/components/radix/themes/components/hover_card.pyi +102 -67
- reflex/components/radix/themes/components/icon_button.pyi +18 -21
- reflex/components/radix/themes/components/inset.py +1 -3
- reflex/components/radix/themes/components/inset.pyi +17 -17
- reflex/components/radix/themes/components/popover.py +22 -13
- reflex/components/radix/themes/components/popover.pyi +98 -72
- reflex/components/radix/themes/components/progress.pyi +17 -17
- reflex/components/radix/themes/components/radio.pyi +17 -17
- reflex/components/radix/themes/components/radio_cards.py +2 -2
- reflex/components/radix/themes/components/radio_cards.pyi +37 -34
- reflex/components/radix/themes/components/radio_group.py +3 -7
- reflex/components/radix/themes/components/radio_group.pyi +69 -66
- reflex/components/radix/themes/components/scroll_area.py +1 -3
- reflex/components/radix/themes/components/scroll_area.pyi +17 -17
- reflex/components/radix/themes/components/segmented_control.pyi +37 -34
- reflex/components/radix/themes/components/select.py +7 -11
- reflex/components/radix/themes/components/select.pyi +175 -154
- reflex/components/radix/themes/components/separator.py +1 -4
- reflex/components/radix/themes/components/separator.pyi +17 -17
- reflex/components/radix/themes/components/skeleton.pyi +17 -17
- reflex/components/radix/themes/components/slider.py +12 -21
- reflex/components/radix/themes/components/slider.pyi +47 -25
- reflex/components/radix/themes/components/spinner.py +1 -4
- reflex/components/radix/themes/components/spinner.pyi +17 -17
- reflex/components/radix/themes/components/switch.py +3 -6
- reflex/components/radix/themes/components/switch.pyi +21 -18
- reflex/components/radix/themes/components/table.py +21 -5
- reflex/components/radix/themes/components/table.pyi +392 -116
- reflex/components/radix/themes/components/tabs.py +3 -6
- reflex/components/radix/themes/components/tabs.pyi +89 -83
- reflex/components/radix/themes/components/text_area.py +1 -5
- reflex/components/radix/themes/components/text_area.pyi +43 -20
- reflex/components/radix/themes/components/text_field.py +1 -5
- reflex/components/radix/themes/components/text_field.pyi +101 -55
- reflex/components/radix/themes/components/tooltip.py +5 -7
- reflex/components/radix/themes/components/tooltip.pyi +25 -22
- reflex/components/radix/themes/layout/base.py +2 -27
- reflex/components/radix/themes/layout/base.pyi +82 -82
- reflex/components/radix/themes/layout/box.pyi +17 -17
- reflex/components/radix/themes/layout/center.pyi +17 -17
- reflex/components/radix/themes/layout/container.pyi +17 -17
- reflex/components/radix/themes/layout/flex.py +1 -6
- reflex/components/radix/themes/layout/flex.pyi +17 -17
- reflex/components/radix/themes/layout/grid.py +1 -6
- reflex/components/radix/themes/layout/grid.pyi +17 -17
- reflex/components/radix/themes/layout/list.py +20 -15
- reflex/components/radix/themes/layout/list.pyi +175 -92
- reflex/components/radix/themes/layout/section.pyi +17 -17
- reflex/components/radix/themes/layout/spacer.pyi +17 -17
- reflex/components/radix/themes/layout/stack.py +6 -6
- reflex/components/radix/themes/layout/stack.pyi +91 -62
- reflex/components/radix/themes/typography/blockquote.py +2 -8
- reflex/components/radix/themes/typography/blockquote.pyi +17 -17
- reflex/components/radix/themes/typography/code.py +4 -10
- reflex/components/radix/themes/typography/code.pyi +19 -18
- reflex/components/radix/themes/typography/heading.py +4 -11
- reflex/components/radix/themes/typography/heading.pyi +19 -18
- reflex/components/radix/themes/typography/link.py +4 -10
- reflex/components/radix/themes/typography/link.pyi +19 -18
- reflex/components/radix/themes/typography/text.py +4 -11
- reflex/components/radix/themes/typography/text.pyi +115 -114
- reflex/components/react_player/audio.pyi +58 -33
- reflex/components/react_player/react_player.py +17 -17
- reflex/components/react_player/react_player.pyi +55 -33
- reflex/components/react_player/video.pyi +58 -33
- reflex/components/recharts/cartesian.py +45 -45
- reflex/components/recharts/cartesian.pyi +389 -304
- reflex/components/recharts/charts.py +22 -22
- reflex/components/recharts/charts.pyi +226 -179
- reflex/components/recharts/general.py +26 -27
- reflex/components/recharts/general.pyi +106 -99
- reflex/components/recharts/polar.py +33 -33
- reflex/components/recharts/polar.pyi +70 -64
- reflex/components/recharts/recharts.pyi +33 -33
- reflex/components/sonner/toast.py +9 -36
- reflex/components/sonner/toast.pyi +20 -24
- reflex/components/suneditor/editor.py +8 -8
- reflex/components/suneditor/editor.pyi +50 -25
- reflex/components/tags/iter_tag.py +1 -10
- reflex/components/tags/tag.py +1 -4
- reflex/config.py +252 -41
- reflex/constants/__init__.py +4 -16
- reflex/constants/base.py +7 -14
- reflex/constants/colors.py +0 -1
- reflex/constants/installer.py +12 -7
- reflex/constants/state.py +4 -0
- reflex/custom_components/custom_components.py +6 -6
- reflex/event.py +486 -241
- reflex/experimental/client_state.py +9 -9
- reflex/experimental/layout.py +2 -2
- reflex/experimental/layout.pyi +95 -87
- reflex/experimental/misc.py +1 -1
- reflex/istate/__init__.py +1 -0
- reflex/istate/proxy.py +33 -0
- reflex/istate/wrappers.py +27 -0
- reflex/model.py +7 -7
- reflex/page.py +2 -1
- reflex/reflex.py +142 -8
- reflex/state.py +133 -46
- reflex/testing.py +9 -7
- reflex/utils/console.py +0 -1
- reflex/utils/exceptions.py +31 -3
- reflex/utils/exec.py +33 -14
- reflex/utils/format.py +15 -12
- reflex/utils/net.py +1 -1
- reflex/utils/path_ops.py +2 -2
- reflex/utils/prerequisites.py +82 -46
- reflex/utils/pyi_generator.py +63 -20
- reflex/utils/registry.py +1 -1
- reflex/utils/serializers.py +75 -36
- reflex/utils/telemetry.py +3 -2
- reflex/utils/types.py +125 -10
- reflex/vars/base.py +131 -119
- reflex/vars/function.py +59 -12
- reflex/vars/number.py +3 -1
- reflex/vars/object.py +30 -24
- reflex/vars/sequence.py +7 -7
- {reflex-0.6.4a2.dist-info → reflex-0.6.5.dist-info}/METADATA +3 -3
- reflex-0.6.5.dist-info/RECORD +394 -0
- reflex-0.6.4a2.dist-info/RECORD +0 -391
- {reflex-0.6.4a2.dist-info → reflex-0.6.5.dist-info}/LICENSE +0 -0
- {reflex-0.6.4a2.dist-info → reflex-0.6.5.dist-info}/WHEEL +0 -0
- {reflex-0.6.4a2.dist-info → reflex-0.6.5.dist-info}/entry_points.txt +0 -0
reflex/event.py
CHANGED
|
@@ -10,6 +10,7 @@ import urllib.parse
|
|
|
10
10
|
from base64 import b64encode
|
|
11
11
|
from functools import partial
|
|
12
12
|
from typing import (
|
|
13
|
+
TYPE_CHECKING,
|
|
13
14
|
Any,
|
|
14
15
|
Callable,
|
|
15
16
|
Dict,
|
|
@@ -19,25 +20,32 @@ from typing import (
|
|
|
19
20
|
Sequence,
|
|
20
21
|
Tuple,
|
|
21
22
|
Type,
|
|
22
|
-
TypeVar,
|
|
23
23
|
Union,
|
|
24
24
|
get_type_hints,
|
|
25
25
|
overload,
|
|
26
26
|
)
|
|
27
27
|
|
|
28
|
-
from typing_extensions import
|
|
28
|
+
from typing_extensions import (
|
|
29
|
+
Concatenate,
|
|
30
|
+
ParamSpec,
|
|
31
|
+
Protocol,
|
|
32
|
+
TypeAliasType,
|
|
33
|
+
TypedDict,
|
|
34
|
+
TypeVar,
|
|
35
|
+
get_args,
|
|
36
|
+
get_origin,
|
|
37
|
+
)
|
|
29
38
|
|
|
30
39
|
from reflex import constants
|
|
40
|
+
from reflex.constants.state import FRONTEND_EVENT_STATE
|
|
31
41
|
from reflex.utils import console, format
|
|
32
|
-
from reflex.utils.exceptions import EventFnArgMismatch,
|
|
33
|
-
from reflex.utils.types import ArgsSpec, GenericType
|
|
42
|
+
from reflex.utils.exceptions import EventFnArgMismatch, EventHandlerArgTypeMismatch
|
|
43
|
+
from reflex.utils.types import ArgsSpec, GenericType, typehint_issubclass
|
|
34
44
|
from reflex.vars import VarData
|
|
35
|
-
from reflex.vars.base import
|
|
36
|
-
LiteralVar,
|
|
37
|
-
Var,
|
|
38
|
-
)
|
|
45
|
+
from reflex.vars.base import LiteralVar, Var
|
|
39
46
|
from reflex.vars.function import (
|
|
40
47
|
ArgsFunctionOperation,
|
|
48
|
+
FunctionArgs,
|
|
41
49
|
FunctionStringVar,
|
|
42
50
|
FunctionVar,
|
|
43
51
|
VarOperationCall,
|
|
@@ -83,7 +91,7 @@ class Event:
|
|
|
83
91
|
BACKGROUND_TASK_MARKER = "_reflex_background_task"
|
|
84
92
|
|
|
85
93
|
|
|
86
|
-
def background(fn):
|
|
94
|
+
def background(fn, *, __internal_reflex_call: bool = False):
|
|
87
95
|
"""Decorator to mark event handler as running in the background.
|
|
88
96
|
|
|
89
97
|
Args:
|
|
@@ -96,6 +104,13 @@ def background(fn):
|
|
|
96
104
|
Raises:
|
|
97
105
|
TypeError: If the function is not a coroutine function or async generator.
|
|
98
106
|
"""
|
|
107
|
+
if not __internal_reflex_call:
|
|
108
|
+
console.deprecate(
|
|
109
|
+
"background-decorator",
|
|
110
|
+
"Use `rx.event(background=True)` instead.",
|
|
111
|
+
"0.6.5",
|
|
112
|
+
"0.7.0",
|
|
113
|
+
)
|
|
99
114
|
if not inspect.iscoroutinefunction(fn) and not inspect.isasyncgenfunction(fn):
|
|
100
115
|
raise TypeError("Background task must be async function or generator.")
|
|
101
116
|
setattr(fn, BACKGROUND_TASK_MARKER, True)
|
|
@@ -394,7 +409,9 @@ class EventChain(EventActionsMixin):
|
|
|
394
409
|
default_factory=list
|
|
395
410
|
)
|
|
396
411
|
|
|
397
|
-
args_spec: Optional[Callable] = dataclasses.field(
|
|
412
|
+
args_spec: Optional[Union[Callable, Sequence[Callable]]] = dataclasses.field(
|
|
413
|
+
default=None
|
|
414
|
+
)
|
|
398
415
|
|
|
399
416
|
invocation: Optional[Var] = dataclasses.field(default=None)
|
|
400
417
|
|
|
@@ -427,6 +444,10 @@ class JavasciptKeyboardEvent:
|
|
|
427
444
|
"""Interface for a Javascript KeyboardEvent https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent."""
|
|
428
445
|
|
|
429
446
|
key: str = ""
|
|
447
|
+
altKey: bool = False
|
|
448
|
+
ctrlKey: bool = False
|
|
449
|
+
metaKey: bool = False
|
|
450
|
+
shiftKey: bool = False
|
|
430
451
|
|
|
431
452
|
|
|
432
453
|
def input_event(e: Var[JavascriptInputEvent]) -> Tuple[Var[str]]:
|
|
@@ -441,7 +462,16 @@ def input_event(e: Var[JavascriptInputEvent]) -> Tuple[Var[str]]:
|
|
|
441
462
|
return (e.target.value,)
|
|
442
463
|
|
|
443
464
|
|
|
444
|
-
|
|
465
|
+
class KeyInputInfo(TypedDict):
|
|
466
|
+
"""Information about a key input event."""
|
|
467
|
+
|
|
468
|
+
alt_key: bool
|
|
469
|
+
ctrl_key: bool
|
|
470
|
+
meta_key: bool
|
|
471
|
+
shift_key: bool
|
|
472
|
+
|
|
473
|
+
|
|
474
|
+
def key_event(e: Var[JavasciptKeyboardEvent]) -> Tuple[Var[str], Var[KeyInputInfo]]:
|
|
445
475
|
"""Get the key from a keyboard event.
|
|
446
476
|
|
|
447
477
|
Args:
|
|
@@ -450,10 +480,20 @@ def key_event(e: Var[JavasciptKeyboardEvent]) -> Tuple[Var[str]]:
|
|
|
450
480
|
Returns:
|
|
451
481
|
The key from the keyboard event.
|
|
452
482
|
"""
|
|
453
|
-
return (
|
|
483
|
+
return (
|
|
484
|
+
e.key,
|
|
485
|
+
Var.create(
|
|
486
|
+
{
|
|
487
|
+
"alt_key": e.altKey,
|
|
488
|
+
"ctrl_key": e.ctrlKey,
|
|
489
|
+
"meta_key": e.metaKey,
|
|
490
|
+
"shift_key": e.shiftKey,
|
|
491
|
+
},
|
|
492
|
+
),
|
|
493
|
+
)
|
|
454
494
|
|
|
455
495
|
|
|
456
|
-
def
|
|
496
|
+
def no_args_event_spec() -> Tuple[()]:
|
|
457
497
|
"""Empty event handler.
|
|
458
498
|
|
|
459
499
|
Returns:
|
|
@@ -463,43 +503,14 @@ def empty_event() -> Tuple[()]:
|
|
|
463
503
|
|
|
464
504
|
|
|
465
505
|
# These chains can be used for their side effects when no other events are desired.
|
|
466
|
-
stop_propagation = EventChain(events=[], args_spec=
|
|
467
|
-
prevent_default = EventChain(events=[], args_spec=
|
|
506
|
+
stop_propagation = EventChain(events=[], args_spec=no_args_event_spec).stop_propagation
|
|
507
|
+
prevent_default = EventChain(events=[], args_spec=no_args_event_spec).prevent_default
|
|
468
508
|
|
|
469
509
|
|
|
470
510
|
T = TypeVar("T")
|
|
471
511
|
U = TypeVar("U")
|
|
472
512
|
|
|
473
513
|
|
|
474
|
-
# def identity_event(event_type: Type[T]) -> Callable[[Var[T]], Tuple[Var[T]]]:
|
|
475
|
-
# """A helper function that returns the input event as output.
|
|
476
|
-
|
|
477
|
-
# Args:
|
|
478
|
-
# event_type: The type of the event.
|
|
479
|
-
|
|
480
|
-
# Returns:
|
|
481
|
-
# A function that returns the input event as output.
|
|
482
|
-
# """
|
|
483
|
-
|
|
484
|
-
# def inner(ev: Var[T]) -> Tuple[Var[T]]:
|
|
485
|
-
# return (ev,)
|
|
486
|
-
|
|
487
|
-
# inner.__signature__ = inspect.signature(inner).replace( # type: ignore
|
|
488
|
-
# parameters=[
|
|
489
|
-
# inspect.Parameter(
|
|
490
|
-
# "ev",
|
|
491
|
-
# kind=inspect.Parameter.POSITIONAL_OR_KEYWORD,
|
|
492
|
-
# annotation=Var[event_type],
|
|
493
|
-
# )
|
|
494
|
-
# ],
|
|
495
|
-
# return_annotation=Tuple[Var[event_type]],
|
|
496
|
-
# )
|
|
497
|
-
# inner.__annotations__["ev"] = Var[event_type]
|
|
498
|
-
# inner.__annotations__["return"] = Tuple[Var[event_type]]
|
|
499
|
-
|
|
500
|
-
# return inner
|
|
501
|
-
|
|
502
|
-
|
|
503
514
|
class IdentityEventReturn(Generic[T], Protocol):
|
|
504
515
|
"""Protocol for an identity event return."""
|
|
505
516
|
|
|
@@ -516,20 +527,22 @@ class IdentityEventReturn(Generic[T], Protocol):
|
|
|
516
527
|
|
|
517
528
|
|
|
518
529
|
@overload
|
|
519
|
-
def
|
|
530
|
+
def passthrough_event_spec(
|
|
531
|
+
event_type: Type[T], /
|
|
532
|
+
) -> Callable[[Var[T]], Tuple[Var[T]]]: ... # type: ignore
|
|
520
533
|
|
|
521
534
|
|
|
522
535
|
@overload
|
|
523
|
-
def
|
|
536
|
+
def passthrough_event_spec(
|
|
524
537
|
event_type_1: Type[T], event_type2: Type[U], /
|
|
525
538
|
) -> Callable[[Var[T], Var[U]], Tuple[Var[T], Var[U]]]: ...
|
|
526
539
|
|
|
527
540
|
|
|
528
541
|
@overload
|
|
529
|
-
def
|
|
542
|
+
def passthrough_event_spec(*event_types: Type[T]) -> IdentityEventReturn[T]: ...
|
|
530
543
|
|
|
531
544
|
|
|
532
|
-
def
|
|
545
|
+
def passthrough_event_spec(*event_types: Type[T]) -> IdentityEventReturn[T]: # type: ignore
|
|
533
546
|
"""A helper function that returns the input event as output.
|
|
534
547
|
|
|
535
548
|
Args:
|
|
@@ -676,7 +689,7 @@ def server_side(name: str, sig: inspect.Signature, **kwargs) -> EventSpec:
|
|
|
676
689
|
fn.__qualname__ = name
|
|
677
690
|
fn.__signature__ = sig
|
|
678
691
|
return EventSpec(
|
|
679
|
-
handler=EventHandler(fn=fn),
|
|
692
|
+
handler=EventHandler(fn=fn, state_full_name=FRONTEND_EVENT_STATE),
|
|
680
693
|
args=tuple(
|
|
681
694
|
(
|
|
682
695
|
Var(_js_expr=k),
|
|
@@ -720,7 +733,16 @@ def console_log(message: str | Var[str]) -> EventSpec:
|
|
|
720
733
|
Returns:
|
|
721
734
|
An event to log the message.
|
|
722
735
|
"""
|
|
723
|
-
return
|
|
736
|
+
return run_script(Var("console").to(dict).log.to(FunctionVar).call(message))
|
|
737
|
+
|
|
738
|
+
|
|
739
|
+
def noop() -> EventSpec:
|
|
740
|
+
"""Do nothing.
|
|
741
|
+
|
|
742
|
+
Returns:
|
|
743
|
+
An event to do nothing.
|
|
744
|
+
"""
|
|
745
|
+
return run_script(Var.create(None))
|
|
724
746
|
|
|
725
747
|
|
|
726
748
|
def back() -> EventSpec:
|
|
@@ -729,7 +751,9 @@ def back() -> EventSpec:
|
|
|
729
751
|
Returns:
|
|
730
752
|
An event to go back one page.
|
|
731
753
|
"""
|
|
732
|
-
return
|
|
754
|
+
return run_script(
|
|
755
|
+
Var("window").to(dict).history.to(dict).back.to(FunctionVar).call()
|
|
756
|
+
)
|
|
733
757
|
|
|
734
758
|
|
|
735
759
|
def window_alert(message: str | Var[str]) -> EventSpec:
|
|
@@ -741,7 +765,7 @@ def window_alert(message: str | Var[str]) -> EventSpec:
|
|
|
741
765
|
Returns:
|
|
742
766
|
An event to alert the message.
|
|
743
767
|
"""
|
|
744
|
-
return
|
|
768
|
+
return run_script(Var("window").to(dict).alert.to(FunctionVar).call(message))
|
|
745
769
|
|
|
746
770
|
|
|
747
771
|
def set_focus(ref: str) -> EventSpec:
|
|
@@ -760,18 +784,25 @@ def set_focus(ref: str) -> EventSpec:
|
|
|
760
784
|
)
|
|
761
785
|
|
|
762
786
|
|
|
763
|
-
def scroll_to(elem_id: str) -> EventSpec:
|
|
787
|
+
def scroll_to(elem_id: str, align_to_top: bool | Var[bool] = True) -> EventSpec:
|
|
764
788
|
"""Select the id of a html element for scrolling into view.
|
|
765
789
|
|
|
766
790
|
Args:
|
|
767
|
-
elem_id:
|
|
791
|
+
elem_id: The id of the element to scroll to.
|
|
792
|
+
align_to_top: Whether to scroll to the top (True) or bottom (False) of the element.
|
|
768
793
|
|
|
769
794
|
Returns:
|
|
770
795
|
An EventSpec to scroll the page to the selected element.
|
|
771
796
|
"""
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
return
|
|
797
|
+
get_element_by_id = FunctionStringVar.create("document.getElementById")
|
|
798
|
+
|
|
799
|
+
return run_script(
|
|
800
|
+
get_element_by_id(elem_id)
|
|
801
|
+
.call(elem_id)
|
|
802
|
+
.to(ObjectVar)
|
|
803
|
+
.scrollIntoView.to(FunctionVar)
|
|
804
|
+
.call(align_to_top),
|
|
805
|
+
)
|
|
775
806
|
|
|
776
807
|
|
|
777
808
|
def set_value(ref: str, value: Any) -> EventSpec:
|
|
@@ -877,10 +908,12 @@ def set_clipboard(content: str) -> EventSpec:
|
|
|
877
908
|
Returns:
|
|
878
909
|
EventSpec: An event to set some content in the clipboard.
|
|
879
910
|
"""
|
|
880
|
-
return
|
|
881
|
-
"
|
|
882
|
-
|
|
883
|
-
|
|
911
|
+
return run_script(
|
|
912
|
+
Var("navigator")
|
|
913
|
+
.to(dict)
|
|
914
|
+
.clipboard.to(dict)
|
|
915
|
+
.writeText.to(FunctionVar)
|
|
916
|
+
.call(content)
|
|
884
917
|
)
|
|
885
918
|
|
|
886
919
|
|
|
@@ -967,13 +1000,7 @@ def _callback_arg_spec(eval_result):
|
|
|
967
1000
|
|
|
968
1001
|
def call_script(
|
|
969
1002
|
javascript_code: str | Var[str],
|
|
970
|
-
callback:
|
|
971
|
-
EventSpec
|
|
972
|
-
| EventHandler
|
|
973
|
-
| Callable
|
|
974
|
-
| List[EventSpec | EventHandler | Callable]
|
|
975
|
-
| None
|
|
976
|
-
) = None,
|
|
1003
|
+
callback: EventType | None = None,
|
|
977
1004
|
) -> EventSpec:
|
|
978
1005
|
"""Create an event handler that executes arbitrary javascript code.
|
|
979
1006
|
|
|
@@ -987,12 +1014,10 @@ def call_script(
|
|
|
987
1014
|
callback_kwargs = {}
|
|
988
1015
|
if callback is not None:
|
|
989
1016
|
callback_kwargs = {
|
|
990
|
-
"callback":
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
),
|
|
995
|
-
),
|
|
1017
|
+
"callback": format.format_queue_events(
|
|
1018
|
+
callback,
|
|
1019
|
+
args_spec=lambda result: [result],
|
|
1020
|
+
)._js_expr,
|
|
996
1021
|
}
|
|
997
1022
|
if isinstance(javascript_code, str):
|
|
998
1023
|
# When there is VarData, include it and eval the JS code inline on the client.
|
|
@@ -1012,6 +1037,62 @@ def call_script(
|
|
|
1012
1037
|
)
|
|
1013
1038
|
|
|
1014
1039
|
|
|
1040
|
+
def call_function(
|
|
1041
|
+
javascript_code: str | Var,
|
|
1042
|
+
callback: EventType | None = None,
|
|
1043
|
+
) -> EventSpec:
|
|
1044
|
+
"""Create an event handler that executes arbitrary javascript code.
|
|
1045
|
+
|
|
1046
|
+
Args:
|
|
1047
|
+
javascript_code: The code to execute.
|
|
1048
|
+
callback: EventHandler that will receive the result of evaluating the javascript code.
|
|
1049
|
+
|
|
1050
|
+
Returns:
|
|
1051
|
+
EventSpec: An event that will execute the client side javascript.
|
|
1052
|
+
"""
|
|
1053
|
+
callback_kwargs = {}
|
|
1054
|
+
if callback is not None:
|
|
1055
|
+
callback_kwargs = {
|
|
1056
|
+
"callback": format.format_queue_events(
|
|
1057
|
+
callback,
|
|
1058
|
+
args_spec=lambda result: [result],
|
|
1059
|
+
),
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
javascript_code = (
|
|
1063
|
+
Var(javascript_code) if isinstance(javascript_code, str) else javascript_code
|
|
1064
|
+
)
|
|
1065
|
+
|
|
1066
|
+
return server_side(
|
|
1067
|
+
"_call_function",
|
|
1068
|
+
get_fn_signature(call_function),
|
|
1069
|
+
function=javascript_code,
|
|
1070
|
+
**callback_kwargs,
|
|
1071
|
+
)
|
|
1072
|
+
|
|
1073
|
+
|
|
1074
|
+
def run_script(
|
|
1075
|
+
javascript_code: str | Var,
|
|
1076
|
+
callback: EventType | None = None,
|
|
1077
|
+
) -> EventSpec:
|
|
1078
|
+
"""Create an event handler that executes arbitrary javascript code.
|
|
1079
|
+
|
|
1080
|
+
Args:
|
|
1081
|
+
javascript_code: The code to execute.
|
|
1082
|
+
callback: EventHandler that will receive the result of evaluating the javascript code.
|
|
1083
|
+
|
|
1084
|
+
Returns:
|
|
1085
|
+
EventSpec: An event that will execute the client side javascript.
|
|
1086
|
+
"""
|
|
1087
|
+
javascript_code = (
|
|
1088
|
+
Var(javascript_code) if isinstance(javascript_code, str) else javascript_code
|
|
1089
|
+
)
|
|
1090
|
+
|
|
1091
|
+
return call_function(
|
|
1092
|
+
ArgsFunctionOperation.create(tuple(), javascript_code), callback
|
|
1093
|
+
)
|
|
1094
|
+
|
|
1095
|
+
|
|
1015
1096
|
def get_event(state, event):
|
|
1016
1097
|
"""Get the event from the given state.
|
|
1017
1098
|
|
|
@@ -1038,8 +1119,9 @@ def get_hydrate_event(state) -> str:
|
|
|
1038
1119
|
|
|
1039
1120
|
|
|
1040
1121
|
def call_event_handler(
|
|
1041
|
-
|
|
1042
|
-
|
|
1122
|
+
event_callback: EventHandler | EventSpec,
|
|
1123
|
+
event_spec: ArgsSpec | Sequence[ArgsSpec],
|
|
1124
|
+
key: Optional[str] = None,
|
|
1043
1125
|
) -> EventSpec:
|
|
1044
1126
|
"""Call an event handler to get the event spec.
|
|
1045
1127
|
|
|
@@ -1048,33 +1130,135 @@ def call_event_handler(
|
|
|
1048
1130
|
Otherwise, the event handler will be called with no args.
|
|
1049
1131
|
|
|
1050
1132
|
Args:
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
Raises:
|
|
1055
|
-
EventHandlerArgMismatch: if number of arguments expected by event_handler doesn't match the spec.
|
|
1133
|
+
event_callback: The event handler.
|
|
1134
|
+
event_spec: The lambda that define the argument(s) to pass to the event handler.
|
|
1135
|
+
key: The key to pass to the event handler.
|
|
1056
1136
|
|
|
1057
1137
|
Returns:
|
|
1058
1138
|
The event spec from calling the event handler.
|
|
1059
|
-
"""
|
|
1060
|
-
parsed_args = parse_args_spec(arg_spec) # type: ignore
|
|
1061
1139
|
|
|
1062
|
-
|
|
1140
|
+
# noqa: DAR401 failure
|
|
1141
|
+
|
|
1142
|
+
"""
|
|
1143
|
+
event_spec_args = parse_args_spec(event_spec) # type: ignore
|
|
1144
|
+
|
|
1145
|
+
if isinstance(event_callback, EventSpec):
|
|
1146
|
+
check_fn_match_arg_spec(
|
|
1147
|
+
event_callback.handler.fn,
|
|
1148
|
+
event_spec,
|
|
1149
|
+
key,
|
|
1150
|
+
bool(event_callback.handler.state_full_name) + len(event_callback.args),
|
|
1151
|
+
event_callback.handler.fn.__qualname__,
|
|
1152
|
+
)
|
|
1063
1153
|
# Handle partial application of EventSpec args
|
|
1064
|
-
return
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1154
|
+
return event_callback.add_args(*event_spec_args)
|
|
1155
|
+
|
|
1156
|
+
check_fn_match_arg_spec(
|
|
1157
|
+
event_callback.fn,
|
|
1158
|
+
event_spec,
|
|
1159
|
+
key,
|
|
1160
|
+
bool(event_callback.state_full_name),
|
|
1161
|
+
event_callback.fn.__qualname__,
|
|
1162
|
+
)
|
|
1163
|
+
|
|
1164
|
+
all_acceptable_specs = (
|
|
1165
|
+
[event_spec] if not isinstance(event_spec, Sequence) else event_spec
|
|
1166
|
+
)
|
|
1167
|
+
|
|
1168
|
+
event_spec_return_types = list(
|
|
1169
|
+
filter(
|
|
1170
|
+
lambda event_spec_return_type: event_spec_return_type is not None
|
|
1171
|
+
and get_origin(event_spec_return_type) is tuple,
|
|
1172
|
+
(
|
|
1173
|
+
get_type_hints(arg_spec).get("return", None)
|
|
1174
|
+
for arg_spec in all_acceptable_specs
|
|
1175
|
+
),
|
|
1077
1176
|
)
|
|
1177
|
+
)
|
|
1178
|
+
|
|
1179
|
+
if event_spec_return_types:
|
|
1180
|
+
failures = []
|
|
1181
|
+
|
|
1182
|
+
event_callback_spec = inspect.getfullargspec(event_callback.fn)
|
|
1183
|
+
|
|
1184
|
+
for event_spec_index, event_spec_return_type in enumerate(
|
|
1185
|
+
event_spec_return_types
|
|
1186
|
+
):
|
|
1187
|
+
args = get_args(event_spec_return_type)
|
|
1188
|
+
|
|
1189
|
+
args_types_without_vars = [
|
|
1190
|
+
arg if get_origin(arg) is not Var else get_args(arg)[0] for arg in args
|
|
1191
|
+
]
|
|
1192
|
+
|
|
1193
|
+
try:
|
|
1194
|
+
type_hints_of_provided_callback = get_type_hints(event_callback.fn)
|
|
1195
|
+
except NameError:
|
|
1196
|
+
type_hints_of_provided_callback = {}
|
|
1197
|
+
|
|
1198
|
+
failed_type_check = False
|
|
1199
|
+
|
|
1200
|
+
# check that args of event handler are matching the spec if type hints are provided
|
|
1201
|
+
for i, arg in enumerate(event_callback_spec.args[1:]):
|
|
1202
|
+
if arg not in type_hints_of_provided_callback:
|
|
1203
|
+
continue
|
|
1204
|
+
|
|
1205
|
+
try:
|
|
1206
|
+
compare_result = typehint_issubclass(
|
|
1207
|
+
args_types_without_vars[i], type_hints_of_provided_callback[arg]
|
|
1208
|
+
)
|
|
1209
|
+
except TypeError:
|
|
1210
|
+
# TODO: In 0.7.0, remove this block and raise the exception
|
|
1211
|
+
# raise TypeError(
|
|
1212
|
+
# 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}."
|
|
1213
|
+
# ) from e
|
|
1214
|
+
console.warn(
|
|
1215
|
+
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}."
|
|
1216
|
+
)
|
|
1217
|
+
compare_result = False
|
|
1218
|
+
|
|
1219
|
+
if compare_result:
|
|
1220
|
+
continue
|
|
1221
|
+
else:
|
|
1222
|
+
failure = EventHandlerArgTypeMismatch(
|
|
1223
|
+
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."
|
|
1224
|
+
)
|
|
1225
|
+
failures.append(failure)
|
|
1226
|
+
failed_type_check = True
|
|
1227
|
+
break
|
|
1228
|
+
|
|
1229
|
+
if not failed_type_check:
|
|
1230
|
+
if event_spec_index:
|
|
1231
|
+
args = get_args(event_spec_return_types[0])
|
|
1232
|
+
|
|
1233
|
+
args_types_without_vars = [
|
|
1234
|
+
arg if get_origin(arg) is not Var else get_args(arg)[0]
|
|
1235
|
+
for arg in args
|
|
1236
|
+
]
|
|
1237
|
+
|
|
1238
|
+
expect_string = ", ".join(
|
|
1239
|
+
repr(arg) for arg in args_types_without_vars
|
|
1240
|
+
).replace("[", "\\[")
|
|
1241
|
+
|
|
1242
|
+
given_string = ", ".join(
|
|
1243
|
+
repr(type_hints_of_provided_callback.get(arg, Any))
|
|
1244
|
+
for arg in event_callback_spec.args[1:]
|
|
1245
|
+
).replace("[", "\\[")
|
|
1246
|
+
|
|
1247
|
+
console.warn(
|
|
1248
|
+
f"Event handler {key} expects ({expect_string}) -> () but got ({given_string}) -> () as annotated in {event_callback.fn.__qualname__} instead. "
|
|
1249
|
+
f"This may lead to unexpected behavior but is intentionally ignored for {key}."
|
|
1250
|
+
)
|
|
1251
|
+
return event_callback(*event_spec_args)
|
|
1252
|
+
|
|
1253
|
+
if failures:
|
|
1254
|
+
console.deprecate(
|
|
1255
|
+
"Mismatched event handler argument types",
|
|
1256
|
+
"\n".join([str(f) for f in failures]),
|
|
1257
|
+
"0.6.5",
|
|
1258
|
+
"0.7.0",
|
|
1259
|
+
)
|
|
1260
|
+
|
|
1261
|
+
return event_callback(*event_spec_args) # type: ignore
|
|
1078
1262
|
|
|
1079
1263
|
|
|
1080
1264
|
def unwrap_var_annotation(annotation: GenericType):
|
|
@@ -1114,7 +1298,7 @@ def resolve_annotation(annotations: dict[str, Any], arg_name: str):
|
|
|
1114
1298
|
return annotation
|
|
1115
1299
|
|
|
1116
1300
|
|
|
1117
|
-
def parse_args_spec(arg_spec: ArgsSpec):
|
|
1301
|
+
def parse_args_spec(arg_spec: ArgsSpec | Sequence[ArgsSpec]):
|
|
1118
1302
|
"""Parse the args provided in the ArgsSpec of an event trigger.
|
|
1119
1303
|
|
|
1120
1304
|
Args:
|
|
@@ -1123,6 +1307,8 @@ def parse_args_spec(arg_spec: ArgsSpec):
|
|
|
1123
1307
|
Returns:
|
|
1124
1308
|
The parsed args.
|
|
1125
1309
|
"""
|
|
1310
|
+
# if there's multiple, the first is the default
|
|
1311
|
+
arg_spec = arg_spec[0] if isinstance(arg_spec, Sequence) else arg_spec
|
|
1126
1312
|
spec = inspect.getfullargspec(arg_spec)
|
|
1127
1313
|
annotations = get_type_hints(arg_spec)
|
|
1128
1314
|
|
|
@@ -1138,39 +1324,49 @@ def parse_args_spec(arg_spec: ArgsSpec):
|
|
|
1138
1324
|
)
|
|
1139
1325
|
|
|
1140
1326
|
|
|
1141
|
-
def check_fn_match_arg_spec(
|
|
1327
|
+
def check_fn_match_arg_spec(
|
|
1328
|
+
user_func: Callable,
|
|
1329
|
+
arg_spec: ArgsSpec | Sequence[ArgsSpec],
|
|
1330
|
+
key: str | None = None,
|
|
1331
|
+
number_of_bound_args: int = 0,
|
|
1332
|
+
func_name: str | None = None,
|
|
1333
|
+
):
|
|
1142
1334
|
"""Ensures that the function signature matches the passed argument specification
|
|
1143
1335
|
or raises an EventFnArgMismatch if they do not.
|
|
1144
1336
|
|
|
1145
1337
|
Args:
|
|
1146
|
-
|
|
1338
|
+
user_func: The function to be validated.
|
|
1147
1339
|
arg_spec: The argument specification for the event trigger.
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
The
|
|
1340
|
+
key: The key of the event trigger.
|
|
1341
|
+
number_of_bound_args: The number of bound arguments to the function.
|
|
1342
|
+
func_name: The name of the function to be validated.
|
|
1151
1343
|
|
|
1152
1344
|
Raises:
|
|
1153
1345
|
EventFnArgMismatch: Raised if the number of mandatory arguments do not match
|
|
1154
1346
|
"""
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1347
|
+
user_args = inspect.getfullargspec(user_func).args
|
|
1348
|
+
user_default_args = inspect.getfullargspec(user_func).defaults
|
|
1349
|
+
number_of_user_args = len(user_args) - number_of_bound_args
|
|
1350
|
+
number_of_user_default_args = len(user_default_args) if user_default_args else 0
|
|
1351
|
+
|
|
1352
|
+
parsed_event_args = parse_args_spec(arg_spec)
|
|
1353
|
+
|
|
1354
|
+
number_of_event_args = len(parsed_event_args)
|
|
1355
|
+
|
|
1356
|
+
if number_of_user_args - number_of_user_default_args > number_of_event_args:
|
|
1163
1357
|
raise EventFnArgMismatch(
|
|
1164
|
-
"
|
|
1165
|
-
f"{
|
|
1166
|
-
"
|
|
1167
|
-
f"{[str(v) for v in parsed_args]}\n"
|
|
1358
|
+
f"Event {key} only provides {number_of_event_args} arguments, but "
|
|
1359
|
+
f"{func_name or user_func} requires at least {number_of_user_args - number_of_user_default_args} "
|
|
1360
|
+
"arguments to be passed to the event handler.\n"
|
|
1168
1361
|
"See https://reflex.dev/docs/events/event-arguments/"
|
|
1169
1362
|
)
|
|
1170
|
-
return parsed_args
|
|
1171
1363
|
|
|
1172
1364
|
|
|
1173
|
-
def call_event_fn(
|
|
1365
|
+
def call_event_fn(
|
|
1366
|
+
fn: Callable,
|
|
1367
|
+
arg_spec: ArgsSpec | Sequence[ArgsSpec],
|
|
1368
|
+
key: Optional[str] = None,
|
|
1369
|
+
) -> list[EventSpec] | Var:
|
|
1174
1370
|
"""Call a function to a list of event specs.
|
|
1175
1371
|
|
|
1176
1372
|
The function should return a single EventSpec, a list of EventSpecs, or a
|
|
@@ -1179,6 +1375,7 @@ def call_event_fn(fn: Callable, arg_spec: ArgsSpec) -> list[EventSpec] | Var:
|
|
|
1179
1375
|
Args:
|
|
1180
1376
|
fn: The function to call.
|
|
1181
1377
|
arg_spec: The argument spec for the event trigger.
|
|
1378
|
+
key: The key to pass to the event handler.
|
|
1182
1379
|
|
|
1183
1380
|
Returns:
|
|
1184
1381
|
The event specs from calling the function or a Var.
|
|
@@ -1191,10 +1388,14 @@ def call_event_fn(fn: Callable, arg_spec: ArgsSpec) -> list[EventSpec] | Var:
|
|
|
1191
1388
|
from reflex.utils.exceptions import EventHandlerValueError
|
|
1192
1389
|
|
|
1193
1390
|
# Check that fn signature matches arg_spec
|
|
1194
|
-
|
|
1391
|
+
check_fn_match_arg_spec(fn, arg_spec, key=key)
|
|
1392
|
+
|
|
1393
|
+
parsed_args = parse_args_spec(arg_spec)
|
|
1394
|
+
|
|
1395
|
+
number_of_fn_args = len(inspect.getfullargspec(fn).args)
|
|
1195
1396
|
|
|
1196
1397
|
# Call the function with the parsed args.
|
|
1197
|
-
out = fn(*parsed_args)
|
|
1398
|
+
out = fn(*[*parsed_args][:number_of_fn_args])
|
|
1198
1399
|
|
|
1199
1400
|
# If the function returns a Var, assume it's an EventChain and render it directly.
|
|
1200
1401
|
if isinstance(out, Var):
|
|
@@ -1209,7 +1410,7 @@ def call_event_fn(fn: Callable, arg_spec: ArgsSpec) -> list[EventSpec] | Var:
|
|
|
1209
1410
|
for e in out:
|
|
1210
1411
|
if isinstance(e, EventHandler):
|
|
1211
1412
|
# An un-called EventHandler gets all of the args of the event trigger.
|
|
1212
|
-
e = call_event_handler(e, arg_spec)
|
|
1413
|
+
e = call_event_handler(e, arg_spec, key=key)
|
|
1213
1414
|
|
|
1214
1415
|
# Make sure the event spec is valid.
|
|
1215
1416
|
if not isinstance(e, EventSpec):
|
|
@@ -1313,7 +1514,7 @@ def get_fn_signature(fn: Callable) -> inspect.Signature:
|
|
|
1313
1514
|
"""
|
|
1314
1515
|
signature = inspect.signature(fn)
|
|
1315
1516
|
new_param = inspect.Parameter(
|
|
1316
|
-
|
|
1517
|
+
FRONTEND_EVENT_STATE, inspect.Parameter.POSITIONAL_OR_KEYWORD, annotation=Any
|
|
1317
1518
|
)
|
|
1318
1519
|
return signature.replace(parameters=(new_param, *signature.parameters.values()))
|
|
1319
1520
|
|
|
@@ -1419,7 +1620,12 @@ class LiteralEventChainVar(ArgsFunctionOperation, LiteralVar, EventChainVar):
|
|
|
1419
1620
|
Returns:
|
|
1420
1621
|
The created LiteralEventChainVar instance.
|
|
1421
1622
|
"""
|
|
1422
|
-
|
|
1623
|
+
arg_spec = (
|
|
1624
|
+
value.args_spec[0]
|
|
1625
|
+
if isinstance(value.args_spec, Sequence)
|
|
1626
|
+
else value.args_spec
|
|
1627
|
+
)
|
|
1628
|
+
sig = inspect.signature(arg_spec) # type: ignore
|
|
1423
1629
|
if sig.parameters:
|
|
1424
1630
|
arg_def = tuple((f"_{p}" for p in sig.parameters))
|
|
1425
1631
|
arg_def_expr = LiteralVar.create([Var(_js_expr=arg) for arg in arg_def])
|
|
@@ -1438,7 +1644,7 @@ class LiteralEventChainVar(ArgsFunctionOperation, LiteralVar, EventChainVar):
|
|
|
1438
1644
|
_js_expr="",
|
|
1439
1645
|
_var_type=EventChain,
|
|
1440
1646
|
_var_data=_var_data,
|
|
1441
|
-
|
|
1647
|
+
_args=FunctionArgs(arg_def),
|
|
1442
1648
|
_return_expr=invocation.call(
|
|
1443
1649
|
LiteralVar.create([LiteralVar.create(event) for event in value.events]),
|
|
1444
1650
|
arg_def_expr,
|
|
@@ -1457,142 +1663,134 @@ V3 = TypeVar("V3")
|
|
|
1457
1663
|
V4 = TypeVar("V4")
|
|
1458
1664
|
V5 = TypeVar("V5")
|
|
1459
1665
|
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
Args:
|
|
1470
|
-
func: The function to be wrapped.
|
|
1471
|
-
"""
|
|
1472
|
-
self.func = func
|
|
1473
|
-
|
|
1474
|
-
@property
|
|
1475
|
-
def prevent_default(self):
|
|
1476
|
-
"""Prevent default behavior.
|
|
1477
|
-
|
|
1478
|
-
Returns:
|
|
1479
|
-
The event callback with prevent default behavior.
|
|
1480
|
-
"""
|
|
1481
|
-
return self
|
|
1482
|
-
|
|
1483
|
-
@property
|
|
1484
|
-
def stop_propagation(self):
|
|
1485
|
-
"""Stop event propagation.
|
|
1486
|
-
|
|
1487
|
-
Returns:
|
|
1488
|
-
The event callback with stop propagation behavior.
|
|
1489
|
-
"""
|
|
1490
|
-
return self
|
|
1491
|
-
|
|
1492
|
-
@overload
|
|
1493
|
-
def __call__(
|
|
1494
|
-
self: EventCallback[Q, T],
|
|
1495
|
-
) -> EventCallback[Q, T]: ...
|
|
1496
|
-
|
|
1497
|
-
@overload
|
|
1498
|
-
def __call__(
|
|
1499
|
-
self: EventCallback[Concatenate[V, Q], T], value: V | Var[V]
|
|
1500
|
-
) -> EventCallback[Q, T]: ...
|
|
1501
|
-
|
|
1502
|
-
@overload
|
|
1503
|
-
def __call__(
|
|
1504
|
-
self: EventCallback[Concatenate[V, V2, Q], T],
|
|
1505
|
-
value: V | Var[V],
|
|
1506
|
-
value2: V2 | Var[V2],
|
|
1507
|
-
) -> EventCallback[Q, T]: ...
|
|
1508
|
-
|
|
1509
|
-
@overload
|
|
1510
|
-
def __call__(
|
|
1511
|
-
self: EventCallback[Concatenate[V, V2, V3, Q], T],
|
|
1512
|
-
value: V | Var[V],
|
|
1513
|
-
value2: V2 | Var[V2],
|
|
1514
|
-
value3: V3 | Var[V3],
|
|
1515
|
-
) -> EventCallback[Q, T]: ...
|
|
1516
|
-
|
|
1517
|
-
@overload
|
|
1518
|
-
def __call__(
|
|
1519
|
-
self: EventCallback[Concatenate[V, V2, V3, V4, Q], T],
|
|
1520
|
-
value: V | Var[V],
|
|
1521
|
-
value2: V2 | Var[V2],
|
|
1522
|
-
value3: V3 | Var[V3],
|
|
1523
|
-
value4: V4 | Var[V4],
|
|
1524
|
-
) -> EventCallback[Q, T]: ...
|
|
1525
|
-
|
|
1526
|
-
def __call__(self, *values) -> EventCallback: # type: ignore
|
|
1527
|
-
"""Call the function with the values.
|
|
1528
|
-
|
|
1529
|
-
Args:
|
|
1530
|
-
*values: The values to call the function with.
|
|
1531
|
-
|
|
1532
|
-
Returns:
|
|
1533
|
-
The function with the values.
|
|
1534
|
-
"""
|
|
1535
|
-
return self.func(*values) # type: ignore
|
|
1536
|
-
|
|
1537
|
-
@overload
|
|
1538
|
-
def __get__(
|
|
1539
|
-
self: EventCallback[P, T], instance: None, owner
|
|
1540
|
-
) -> EventCallback[P, T]: ...
|
|
1541
|
-
|
|
1542
|
-
@overload
|
|
1543
|
-
def __get__(self, instance, owner) -> Callable[P, T]: ...
|
|
1544
|
-
|
|
1545
|
-
def __get__(self, instance, owner) -> Callable: # type: ignore
|
|
1546
|
-
"""Get the function with the instance bound to it.
|
|
1547
|
-
|
|
1548
|
-
Args:
|
|
1549
|
-
instance: The instance to bind to the function.
|
|
1550
|
-
owner: The owner of the function.
|
|
1551
|
-
|
|
1552
|
-
Returns:
|
|
1553
|
-
The function with the instance bound to it
|
|
1554
|
-
"""
|
|
1555
|
-
if instance is None:
|
|
1556
|
-
return self.func # type: ignore
|
|
1557
|
-
|
|
1558
|
-
return partial(self.func, instance) # type: ignore
|
|
1559
|
-
|
|
1560
|
-
def event_handler(func: Callable[Concatenate[Any, P], T]) -> EventCallback[P, T]:
|
|
1561
|
-
"""Wrap a function to be used as an event.
|
|
1666
|
+
background_event_decorator = background
|
|
1667
|
+
|
|
1668
|
+
|
|
1669
|
+
class EventCallback(Generic[P, T]):
|
|
1670
|
+
"""A descriptor that wraps a function to be used as an event."""
|
|
1671
|
+
|
|
1672
|
+
def __init__(self, func: Callable[Concatenate[Any, P], T]):
|
|
1673
|
+
"""Initialize the descriptor with the function to be wrapped.
|
|
1562
1674
|
|
|
1563
1675
|
Args:
|
|
1564
|
-
func: The function to
|
|
1676
|
+
func: The function to be wrapped.
|
|
1677
|
+
"""
|
|
1678
|
+
self.func = func
|
|
1679
|
+
|
|
1680
|
+
@property
|
|
1681
|
+
def prevent_default(self):
|
|
1682
|
+
"""Prevent default behavior.
|
|
1565
1683
|
|
|
1566
1684
|
Returns:
|
|
1567
|
-
The
|
|
1685
|
+
The event callback with prevent default behavior.
|
|
1568
1686
|
"""
|
|
1569
|
-
return
|
|
1570
|
-
else:
|
|
1687
|
+
return self
|
|
1571
1688
|
|
|
1572
|
-
|
|
1573
|
-
|
|
1689
|
+
@property
|
|
1690
|
+
def stop_propagation(self):
|
|
1691
|
+
"""Stop event propagation.
|
|
1574
1692
|
|
|
1575
|
-
|
|
1576
|
-
|
|
1693
|
+
Returns:
|
|
1694
|
+
The event callback with stop propagation behavior.
|
|
1695
|
+
"""
|
|
1696
|
+
return self
|
|
1697
|
+
|
|
1698
|
+
@overload
|
|
1699
|
+
def __call__(
|
|
1700
|
+
self: EventCallback[Q, T],
|
|
1701
|
+
) -> EventCallback[Q, T]: ...
|
|
1702
|
+
|
|
1703
|
+
@overload
|
|
1704
|
+
def __call__(
|
|
1705
|
+
self: EventCallback[Concatenate[V, Q], T], value: V | Var[V]
|
|
1706
|
+
) -> EventCallback[Q, T]: ...
|
|
1707
|
+
|
|
1708
|
+
@overload
|
|
1709
|
+
def __call__(
|
|
1710
|
+
self: EventCallback[Concatenate[V, V2, Q], T],
|
|
1711
|
+
value: V | Var[V],
|
|
1712
|
+
value2: V2 | Var[V2],
|
|
1713
|
+
) -> EventCallback[Q, T]: ...
|
|
1714
|
+
|
|
1715
|
+
@overload
|
|
1716
|
+
def __call__(
|
|
1717
|
+
self: EventCallback[Concatenate[V, V2, V3, Q], T],
|
|
1718
|
+
value: V | Var[V],
|
|
1719
|
+
value2: V2 | Var[V2],
|
|
1720
|
+
value3: V3 | Var[V3],
|
|
1721
|
+
) -> EventCallback[Q, T]: ...
|
|
1722
|
+
|
|
1723
|
+
@overload
|
|
1724
|
+
def __call__(
|
|
1725
|
+
self: EventCallback[Concatenate[V, V2, V3, V4, Q], T],
|
|
1726
|
+
value: V | Var[V],
|
|
1727
|
+
value2: V2 | Var[V2],
|
|
1728
|
+
value3: V3 | Var[V3],
|
|
1729
|
+
value4: V4 | Var[V4],
|
|
1730
|
+
) -> EventCallback[Q, T]: ...
|
|
1731
|
+
|
|
1732
|
+
def __call__(self, *values) -> EventCallback: # type: ignore
|
|
1733
|
+
"""Call the function with the values.
|
|
1577
1734
|
|
|
1578
1735
|
Args:
|
|
1579
|
-
|
|
1736
|
+
*values: The values to call the function with.
|
|
1580
1737
|
|
|
1581
1738
|
Returns:
|
|
1582
|
-
The
|
|
1739
|
+
The function with the values.
|
|
1740
|
+
"""
|
|
1741
|
+
return self.func(*values) # type: ignore
|
|
1742
|
+
|
|
1743
|
+
@overload
|
|
1744
|
+
def __get__(
|
|
1745
|
+
self: EventCallback[P, T], instance: None, owner
|
|
1746
|
+
) -> EventCallback[P, T]: ...
|
|
1747
|
+
|
|
1748
|
+
@overload
|
|
1749
|
+
def __get__(self, instance, owner) -> Callable[P, T]: ...
|
|
1750
|
+
|
|
1751
|
+
def __get__(self, instance, owner) -> Callable: # type: ignore
|
|
1752
|
+
"""Get the function with the instance bound to it.
|
|
1753
|
+
|
|
1754
|
+
Args:
|
|
1755
|
+
instance: The instance to bind to the function.
|
|
1756
|
+
owner: The owner of the function.
|
|
1757
|
+
|
|
1758
|
+
Returns:
|
|
1759
|
+
The function with the instance bound to it
|
|
1583
1760
|
"""
|
|
1584
|
-
|
|
1761
|
+
if instance is None:
|
|
1762
|
+
return self.func # type: ignore
|
|
1763
|
+
|
|
1764
|
+
return partial(self.func, instance) # type: ignore
|
|
1585
1765
|
|
|
1586
1766
|
|
|
1587
1767
|
G = ParamSpec("G")
|
|
1588
1768
|
|
|
1769
|
+
if TYPE_CHECKING:
|
|
1770
|
+
from reflex.state import BaseState
|
|
1771
|
+
|
|
1772
|
+
BASE_STATE = TypeVar("BASE_STATE", bound=BaseState)
|
|
1773
|
+
else:
|
|
1774
|
+
BASE_STATE = TypeVar("BASE_STATE")
|
|
1775
|
+
|
|
1776
|
+
StateCallable = TypeAliasType(
|
|
1777
|
+
"StateCallable",
|
|
1778
|
+
Callable[Concatenate[BASE_STATE, G], Any],
|
|
1779
|
+
type_params=(G, BASE_STATE),
|
|
1780
|
+
)
|
|
1781
|
+
|
|
1589
1782
|
IndividualEventType = Union[
|
|
1590
|
-
EventSpec,
|
|
1783
|
+
EventSpec,
|
|
1784
|
+
EventHandler,
|
|
1785
|
+
Callable[G, Any],
|
|
1786
|
+
StateCallable[G, BASE_STATE],
|
|
1787
|
+
EventCallback[G, Any],
|
|
1788
|
+
Var[Any],
|
|
1591
1789
|
]
|
|
1592
1790
|
|
|
1593
1791
|
ItemOrList = Union[V, List[V]]
|
|
1594
1792
|
|
|
1595
|
-
EventType = ItemOrList[IndividualEventType[G]]
|
|
1793
|
+
EventType = ItemOrList[IndividualEventType[G, BASE_STATE]]
|
|
1596
1794
|
|
|
1597
1795
|
|
|
1598
1796
|
class EventNamespace(types.SimpleNamespace):
|
|
@@ -1608,8 +1806,52 @@ class EventNamespace(types.SimpleNamespace):
|
|
|
1608
1806
|
EventChainVar = EventChainVar
|
|
1609
1807
|
LiteralEventChainVar = LiteralEventChainVar
|
|
1610
1808
|
EventType = EventType
|
|
1809
|
+
EventCallback = EventCallback
|
|
1810
|
+
|
|
1811
|
+
@overload
|
|
1812
|
+
@staticmethod
|
|
1813
|
+
def __call__(
|
|
1814
|
+
func: None = None, *, background: bool | None = None
|
|
1815
|
+
) -> Callable[[Callable[Concatenate[BASE_STATE, P], T]], EventCallback[P, T]]: ...
|
|
1816
|
+
|
|
1817
|
+
@overload
|
|
1818
|
+
@staticmethod
|
|
1819
|
+
def __call__(
|
|
1820
|
+
func: Callable[Concatenate[BASE_STATE, P], T],
|
|
1821
|
+
*,
|
|
1822
|
+
background: bool | None = None,
|
|
1823
|
+
) -> EventCallback[P, T]: ...
|
|
1824
|
+
|
|
1825
|
+
@staticmethod
|
|
1826
|
+
def __call__(
|
|
1827
|
+
func: Callable[Concatenate[BASE_STATE, P], T] | None = None,
|
|
1828
|
+
*,
|
|
1829
|
+
background: bool | None = None,
|
|
1830
|
+
) -> Union[
|
|
1831
|
+
EventCallback[P, T],
|
|
1832
|
+
Callable[[Callable[Concatenate[BASE_STATE, P], T]], EventCallback[P, T]],
|
|
1833
|
+
]:
|
|
1834
|
+
"""Wrap a function to be used as an event.
|
|
1835
|
+
|
|
1836
|
+
Args:
|
|
1837
|
+
func: The function to wrap.
|
|
1838
|
+
background: Whether the event should be run in the background. Defaults to False.
|
|
1839
|
+
|
|
1840
|
+
Returns:
|
|
1841
|
+
The wrapped function.
|
|
1842
|
+
"""
|
|
1843
|
+
|
|
1844
|
+
def wrapper(
|
|
1845
|
+
func: Callable[Concatenate[BASE_STATE, P], T],
|
|
1846
|
+
) -> EventCallback[P, T]:
|
|
1847
|
+
if background is True:
|
|
1848
|
+
return background_event_decorator(func, __internal_reflex_call=True) # type: ignore
|
|
1849
|
+
return func # type: ignore
|
|
1850
|
+
|
|
1851
|
+
if func is not None:
|
|
1852
|
+
return wrapper(func)
|
|
1853
|
+
return wrapper
|
|
1611
1854
|
|
|
1612
|
-
__call__ = staticmethod(event_handler)
|
|
1613
1855
|
get_event = staticmethod(get_event)
|
|
1614
1856
|
get_hydrate_event = staticmethod(get_hydrate_event)
|
|
1615
1857
|
fix_events = staticmethod(fix_events)
|
|
@@ -1619,13 +1861,14 @@ class EventNamespace(types.SimpleNamespace):
|
|
|
1619
1861
|
check_fn_match_arg_spec = staticmethod(check_fn_match_arg_spec)
|
|
1620
1862
|
resolve_annotation = staticmethod(resolve_annotation)
|
|
1621
1863
|
parse_args_spec = staticmethod(parse_args_spec)
|
|
1622
|
-
|
|
1864
|
+
passthrough_event_spec = staticmethod(passthrough_event_spec)
|
|
1623
1865
|
input_event = staticmethod(input_event)
|
|
1624
1866
|
key_event = staticmethod(key_event)
|
|
1625
|
-
|
|
1867
|
+
no_args_event_spec = staticmethod(no_args_event_spec)
|
|
1626
1868
|
server_side = staticmethod(server_side)
|
|
1627
1869
|
redirect = staticmethod(redirect)
|
|
1628
1870
|
console_log = staticmethod(console_log)
|
|
1871
|
+
noop = staticmethod(noop)
|
|
1629
1872
|
back = staticmethod(back)
|
|
1630
1873
|
window_alert = staticmethod(window_alert)
|
|
1631
1874
|
set_focus = staticmethod(set_focus)
|
|
@@ -1639,6 +1882,8 @@ class EventNamespace(types.SimpleNamespace):
|
|
|
1639
1882
|
set_clipboard = staticmethod(set_clipboard)
|
|
1640
1883
|
download = staticmethod(download)
|
|
1641
1884
|
call_script = staticmethod(call_script)
|
|
1885
|
+
call_function = staticmethod(call_function)
|
|
1886
|
+
run_script = staticmethod(run_script)
|
|
1642
1887
|
|
|
1643
1888
|
|
|
1644
1889
|
event = EventNamespace()
|