reflex 0.6.0__py3-none-any.whl → 0.6.0a1__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 +2 -2
- reflex/.templates/jinja/web/pages/_app.js.jinja2 +1 -1
- reflex/.templates/jinja/web/pages/utils.js.jinja2 +2 -2
- reflex/.templates/web/components/reflex/chakra_color_mode_provider.js +36 -0
- reflex/.templates/web/utils/state.js +1 -3
- reflex/__init__.py +2 -8
- reflex/__init__.pyi +1 -2
- reflex/app.py +2 -4
- reflex/app_module_for_backend.py +1 -1
- reflex/base.py +1 -1
- reflex/compiler/compiler.py +2 -2
- reflex/compiler/utils.py +3 -3
- reflex/components/base/app_wrap.py +2 -2
- reflex/components/base/app_wrap.pyi +27 -17
- reflex/components/base/bare.py +5 -4
- reflex/components/base/body.pyi +27 -17
- reflex/components/base/document.pyi +131 -81
- reflex/components/base/error_boundary.py +7 -6
- reflex/components/base/error_boundary.pyi +33 -20
- reflex/components/base/fragment.pyi +27 -17
- reflex/components/base/head.pyi +53 -33
- reflex/components/base/link.py +1 -1
- reflex/components/base/link.pyi +54 -33
- reflex/components/base/meta.pyi +105 -65
- reflex/components/base/script.py +2 -1
- reflex/components/base/script.pyi +38 -21
- reflex/components/component.py +47 -53
- reflex/components/core/banner.py +27 -23
- reflex/components/core/banner.pyi +171 -134
- reflex/components/core/client_side_routing.py +3 -2
- reflex/components/core/client_side_routing.pyi +54 -33
- reflex/components/core/clipboard.py +1 -2
- reflex/components/core/clipboard.pyi +33 -20
- reflex/components/core/cond.py +5 -5
- reflex/components/core/debounce.py +5 -5
- reflex/components/core/debounce.pyi +33 -20
- reflex/components/core/foreach.py +4 -3
- reflex/components/core/html.py +1 -1
- reflex/components/core/html.pyi +46 -35
- reflex/components/core/match.py +17 -17
- reflex/components/core/upload.py +23 -17
- reflex/components/core/upload.pyi +124 -78
- reflex/components/datadisplay/code.py +10 -9
- reflex/components/datadisplay/code.pyi +409 -299
- reflex/components/datadisplay/dataeditor.py +10 -8
- reflex/components/datadisplay/dataeditor.pyi +53 -40
- reflex/components/el/element.pyi +27 -17
- reflex/components/el/elements/base.py +1 -1
- reflex/components/el/elements/base.pyi +45 -34
- reflex/components/el/elements/forms.py +16 -16
- reflex/components/el/elements/forms.pyi +707 -554
- reflex/components/el/elements/inline.py +1 -1
- reflex/components/el/elements/inline.pyi +1218 -937
- reflex/components/el/elements/media.py +1 -1
- reflex/components/el/elements/media.pyi +997 -786
- reflex/components/el/elements/metadata.py +6 -3
- reflex/components/el/elements/metadata.pyi +242 -181
- reflex/components/el/elements/other.py +1 -1
- reflex/components/el/elements/other.pyi +306 -235
- reflex/components/el/elements/scripts.py +1 -1
- reflex/components/el/elements/scripts.pyi +140 -109
- reflex/components/el/elements/sectioning.py +2 -0
- reflex/components/el/elements/sectioning.pyi +647 -496
- reflex/components/el/elements/tables.py +1 -1
- reflex/components/el/elements/tables.pyi +452 -351
- reflex/components/el/elements/typography.py +1 -1
- reflex/components/el/elements/typography.pyi +657 -506
- reflex/components/gridjs/datatable.py +9 -6
- reflex/components/gridjs/datatable.pyi +56 -35
- reflex/components/lucide/icon.py +1 -1
- reflex/components/lucide/icon.pyi +54 -33
- reflex/components/markdown/markdown.py +31 -26
- reflex/components/markdown/markdown.pyi +37 -27
- reflex/components/moment/moment.py +12 -13
- reflex/components/moment/moment.pyi +35 -23
- reflex/components/next/base.pyi +27 -17
- reflex/components/next/image.py +1 -1
- reflex/components/next/image.pyi +37 -22
- reflex/components/next/link.py +1 -1
- reflex/components/next/link.pyi +28 -17
- reflex/components/next/video.py +1 -1
- reflex/components/next/video.pyi +28 -17
- reflex/components/plotly/plotly.py +13 -12
- reflex/components/plotly/plotly.pyi +54 -39
- reflex/components/props.py +1 -1
- reflex/components/radix/__init__.pyi +0 -1
- reflex/components/radix/primitives/__init__.pyi +0 -1
- reflex/components/radix/primitives/accordion.py +4 -4
- reflex/components/radix/primitives/accordion.pyi +495 -424
- reflex/components/radix/primitives/base.py +1 -1
- reflex/components/radix/primitives/base.pyi +54 -33
- reflex/components/radix/primitives/drawer.py +1 -1
- reflex/components/radix/primitives/drawer.pyi +273 -172
- reflex/components/radix/primitives/form.py +1 -1
- reflex/components/radix/primitives/form.pyi +364 -257
- reflex/components/radix/primitives/progress.py +1 -1
- reflex/components/radix/primitives/progress.pyi +282 -231
- reflex/components/radix/primitives/slider.py +1 -1
- reflex/components/radix/primitives/slider.pyi +138 -87
- reflex/components/radix/themes/base.py +24 -3
- reflex/components/radix/themes/base.pyi +250 -178
- reflex/components/radix/themes/color_mode.py +5 -5
- reflex/components/radix/themes/color_mode.pyi +220 -187
- reflex/components/radix/themes/components/alert_dialog.py +1 -1
- reflex/components/radix/themes/components/alert_dialog.pyi +207 -136
- reflex/components/radix/themes/components/aspect_ratio.py +1 -1
- reflex/components/radix/themes/components/aspect_ratio.pyi +28 -17
- reflex/components/radix/themes/components/avatar.py +1 -1
- reflex/components/radix/themes/components/avatar.pyi +81 -70
- reflex/components/radix/themes/components/badge.py +1 -1
- reflex/components/radix/themes/components/badge.pyi +99 -88
- reflex/components/radix/themes/components/button.py +1 -1
- reflex/components/radix/themes/components/button.pyi +109 -98
- reflex/components/radix/themes/components/callout.py +1 -1
- reflex/components/radix/themes/components/callout.pyi +373 -322
- reflex/components/radix/themes/components/card.py +1 -1
- reflex/components/radix/themes/components/card.pyi +49 -38
- reflex/components/radix/themes/components/checkbox.py +2 -1
- reflex/components/radix/themes/components/checkbox.pyi +245 -208
- reflex/components/radix/themes/components/checkbox_cards.py +1 -1
- reflex/components/radix/themes/components/checkbox_cards.pyi +115 -94
- reflex/components/radix/themes/components/checkbox_group.py +1 -1
- reflex/components/radix/themes/components/checkbox_group.pyi +107 -86
- reflex/components/radix/themes/components/context_menu.py +1 -1
- reflex/components/radix/themes/components/context_menu.pyi +319 -238
- reflex/components/radix/themes/components/data_list.py +1 -1
- reflex/components/radix/themes/components/data_list.pyi +171 -130
- reflex/components/radix/themes/components/dialog.py +1 -1
- reflex/components/radix/themes/components/dialog.pyi +210 -139
- reflex/components/radix/themes/components/dropdown_menu.py +1 -1
- reflex/components/radix/themes/components/dropdown_menu.pyi +332 -249
- reflex/components/radix/themes/components/hover_card.py +1 -1
- reflex/components/radix/themes/components/hover_card.pyi +131 -90
- reflex/components/radix/themes/components/icon_button.py +3 -2
- reflex/components/radix/themes/components/icon_button.pyi +109 -98
- reflex/components/radix/themes/components/inset.py +1 -1
- reflex/components/radix/themes/components/inset.pyi +58 -47
- reflex/components/radix/themes/components/popover.py +1 -1
- reflex/components/radix/themes/components/popover.pyi +136 -95
- reflex/components/radix/themes/components/progress.py +1 -1
- reflex/components/radix/themes/components/progress.pyi +82 -71
- reflex/components/radix/themes/components/radio.py +1 -1
- reflex/components/radix/themes/components/radio.pyi +80 -69
- reflex/components/radix/themes/components/radio_cards.py +1 -1
- reflex/components/radix/themes/components/radio_cards.pyi +119 -98
- reflex/components/radix/themes/components/radio_group.py +11 -8
- reflex/components/radix/themes/components/radio_group.pyi +271 -228
- reflex/components/radix/themes/components/scroll_area.py +1 -1
- reflex/components/radix/themes/components/scroll_area.pyi +32 -21
- reflex/components/radix/themes/components/segmented_control.py +1 -1
- reflex/components/radix/themes/components/segmented_control.pyi +113 -90
- reflex/components/radix/themes/components/select.py +3 -2
- reflex/components/radix/themes/components/select.pyi +471 -374
- reflex/components/radix/themes/components/separator.py +2 -1
- reflex/components/radix/themes/components/separator.pyi +80 -69
- reflex/components/radix/themes/components/skeleton.py +1 -1
- reflex/components/radix/themes/components/skeleton.pyi +34 -23
- reflex/components/radix/themes/components/slider.py +3 -2
- reflex/components/radix/themes/components/slider.pyi +88 -75
- reflex/components/radix/themes/components/spinner.py +1 -1
- reflex/components/radix/themes/components/spinner.pyi +30 -19
- reflex/components/radix/themes/components/switch.py +1 -1
- reflex/components/radix/themes/components/switch.pyi +84 -71
- reflex/components/radix/themes/components/table.py +1 -1
- reflex/components/radix/themes/components/table.pyi +332 -261
- reflex/components/radix/themes/components/tabs.py +1 -1
- reflex/components/radix/themes/components/tabs.pyi +194 -139
- reflex/components/radix/themes/components/text_area.py +1 -1
- reflex/components/radix/themes/components/text_area.pyi +111 -96
- reflex/components/radix/themes/components/text_field.py +1 -1
- reflex/components/radix/themes/components/text_field.pyi +286 -247
- reflex/components/radix/themes/components/tooltip.py +1 -1
- reflex/components/radix/themes/components/tooltip.pyi +37 -26
- reflex/components/radix/themes/layout/__init__.pyi +0 -1
- reflex/components/radix/themes/layout/base.py +1 -1
- reflex/components/radix/themes/layout/base.pyi +67 -56
- reflex/components/radix/themes/layout/box.pyi +45 -34
- reflex/components/radix/themes/layout/center.pyi +67 -56
- reflex/components/radix/themes/layout/container.py +2 -1
- reflex/components/radix/themes/layout/container.pyi +47 -36
- reflex/components/radix/themes/layout/flex.py +1 -1
- reflex/components/radix/themes/layout/flex.pyi +67 -56
- reflex/components/radix/themes/layout/grid.py +1 -1
- reflex/components/radix/themes/layout/grid.pyi +75 -64
- reflex/components/radix/themes/layout/list.py +6 -5
- reflex/components/radix/themes/layout/list.pyi +244 -193
- reflex/components/radix/themes/layout/section.py +2 -1
- reflex/components/radix/themes/layout/section.pyi +47 -36
- reflex/components/radix/themes/layout/spacer.pyi +67 -56
- reflex/components/radix/themes/layout/stack.py +1 -1
- reflex/components/radix/themes/layout/stack.pyi +159 -128
- reflex/components/radix/themes/typography/blockquote.py +1 -1
- reflex/components/radix/themes/typography/blockquote.pyi +100 -89
- reflex/components/radix/themes/typography/code.py +1 -1
- reflex/components/radix/themes/typography/code.pyi +101 -90
- reflex/components/radix/themes/typography/heading.py +1 -1
- reflex/components/radix/themes/typography/heading.pyi +107 -96
- reflex/components/radix/themes/typography/link.py +1 -1
- reflex/components/radix/themes/typography/link.pyi +113 -102
- reflex/components/radix/themes/typography/text.py +1 -1
- reflex/components/radix/themes/typography/text.pyi +572 -501
- reflex/components/react_player/audio.pyi +60 -33
- reflex/components/react_player/react_player.py +1 -1
- reflex/components/react_player/react_player.pyi +60 -33
- reflex/components/react_player/video.pyi +60 -33
- reflex/components/recharts/cartesian.py +3 -2
- reflex/components/recharts/cartesian.pyi +861 -678
- reflex/components/recharts/charts.py +5 -4
- reflex/components/recharts/charts.pyi +357 -252
- reflex/components/recharts/general.py +2 -1
- reflex/components/recharts/general.pyi +231 -180
- reflex/components/recharts/polar.py +5 -4
- reflex/components/recharts/polar.pyi +181 -144
- reflex/components/recharts/recharts.pyi +53 -33
- reflex/components/sonner/toast.py +17 -16
- reflex/components/sonner/toast.pyi +47 -36
- reflex/components/suneditor/editor.py +3 -2
- reflex/components/suneditor/editor.pyi +78 -55
- reflex/components/tags/cond_tag.py +4 -6
- reflex/components/tags/iter_tag.py +16 -28
- reflex/components/tags/match_tag.py +4 -6
- reflex/components/tags/tag.py +23 -40
- reflex/custom_components/custom_components.py +1 -3
- reflex/event.py +65 -113
- reflex/experimental/client_state.py +24 -25
- reflex/experimental/hooks.py +16 -16
- reflex/experimental/layout.py +5 -5
- reflex/experimental/layout.pyi +187 -136
- reflex/{vars → ivars}/__init__.py +2 -6
- reflex/{vars → ivars}/base.py +216 -599
- reflex/{vars → ivars}/function.py +19 -15
- reflex/{vars → ivars}/number.py +20 -41
- reflex/{vars → ivars}/object.py +30 -28
- reflex/{vars → ivars}/sequence.py +50 -53
- reflex/middleware/hydrate_middleware.py +0 -2
- reflex/middleware/middleware.py +3 -3
- reflex/state.py +82 -148
- reflex/style.py +22 -21
- reflex/utils/exceptions.py +0 -20
- reflex/utils/format.py +34 -54
- reflex/utils/imports.py +73 -16
- reflex/utils/prerequisites.py +15 -35
- reflex/utils/pyi_generator.py +8 -13
- reflex/utils/serializers.py +22 -12
- reflex/utils/telemetry.py +2 -3
- reflex/utils/types.py +5 -10
- reflex/vars.py +501 -0
- {reflex-0.6.0.dist-info → reflex-0.6.0a1.dist-info}/METADATA +5 -4
- reflex-0.6.0a1.dist-info/RECORD +384 -0
- reflex-0.6.0.dist-info/RECORD +0 -382
- {reflex-0.6.0.dist-info → reflex-0.6.0a1.dist-info}/LICENSE +0 -0
- {reflex-0.6.0.dist-info → reflex-0.6.0a1.dist-info}/WHEEL +0 -0
- {reflex-0.6.0.dist-info → reflex-0.6.0a1.dist-info}/entry_points.txt +0 -0
reflex/{vars → ivars}/base.py
RENAMED
|
@@ -9,11 +9,7 @@ import dis
|
|
|
9
9
|
import functools
|
|
10
10
|
import inspect
|
|
11
11
|
import json
|
|
12
|
-
import random
|
|
13
|
-
import re
|
|
14
|
-
import string
|
|
15
12
|
import sys
|
|
16
|
-
import warnings
|
|
17
13
|
from types import CodeType, FunctionType
|
|
18
14
|
from typing import (
|
|
19
15
|
TYPE_CHECKING,
|
|
@@ -21,7 +17,6 @@ from typing import (
|
|
|
21
17
|
Callable,
|
|
22
18
|
Dict,
|
|
23
19
|
Generic,
|
|
24
|
-
Iterable,
|
|
25
20
|
List,
|
|
26
21
|
Literal,
|
|
27
22
|
NoReturn,
|
|
@@ -48,14 +43,15 @@ from reflex.utils.exceptions import (
|
|
|
48
43
|
VarValueError,
|
|
49
44
|
)
|
|
50
45
|
from reflex.utils.format import format_state_name
|
|
51
|
-
from reflex.utils.imports import (
|
|
52
|
-
ImmutableParsedImportDict,
|
|
53
|
-
ImportDict,
|
|
54
|
-
ImportVar,
|
|
55
|
-
ParsedImportDict,
|
|
56
|
-
parse_imports,
|
|
57
|
-
)
|
|
58
46
|
from reflex.utils.types import GenericType, Self, get_origin
|
|
47
|
+
from reflex.vars import (
|
|
48
|
+
REPLACED_NAMES,
|
|
49
|
+
Var,
|
|
50
|
+
VarData,
|
|
51
|
+
_decode_var_immutable,
|
|
52
|
+
_extract_var_data,
|
|
53
|
+
_global_vars,
|
|
54
|
+
)
|
|
59
55
|
|
|
60
56
|
if TYPE_CHECKING:
|
|
61
57
|
from reflex.state import BaseState
|
|
@@ -71,20 +67,19 @@ if TYPE_CHECKING:
|
|
|
71
67
|
from .sequence import ArrayVar, StringVar, ToArrayOperation, ToStringOperation
|
|
72
68
|
|
|
73
69
|
|
|
74
|
-
VAR_TYPE = TypeVar("VAR_TYPE"
|
|
75
|
-
|
|
76
|
-
warnings.filterwarnings("ignore", message="fields may not start with an underscore")
|
|
70
|
+
VAR_TYPE = TypeVar("VAR_TYPE")
|
|
77
71
|
|
|
78
72
|
|
|
79
73
|
@dataclasses.dataclass(
|
|
80
74
|
eq=False,
|
|
81
75
|
frozen=True,
|
|
76
|
+
**{"slots": True} if sys.version_info >= (3, 10) else {},
|
|
82
77
|
)
|
|
83
|
-
class Var
|
|
78
|
+
class ImmutableVar(Var, Generic[VAR_TYPE]):
|
|
84
79
|
"""Base class for immutable vars."""
|
|
85
80
|
|
|
86
81
|
# The name of the var.
|
|
87
|
-
|
|
82
|
+
_var_name: str = dataclasses.field()
|
|
88
83
|
|
|
89
84
|
# The type of the var.
|
|
90
85
|
_var_type: types.GenericType = dataclasses.field(default=Any)
|
|
@@ -98,7 +93,7 @@ class Var(Generic[VAR_TYPE]):
|
|
|
98
93
|
Returns:
|
|
99
94
|
The name of the var.
|
|
100
95
|
"""
|
|
101
|
-
return self.
|
|
96
|
+
return self._var_name
|
|
102
97
|
|
|
103
98
|
@property
|
|
104
99
|
def _var_is_local(self) -> bool:
|
|
@@ -109,26 +104,6 @@ class Var(Generic[VAR_TYPE]):
|
|
|
109
104
|
"""
|
|
110
105
|
return False
|
|
111
106
|
|
|
112
|
-
@property
|
|
113
|
-
@deprecated("Use `_js_expr` instead.")
|
|
114
|
-
def _var_name(self) -> str:
|
|
115
|
-
"""The name of the var.
|
|
116
|
-
|
|
117
|
-
Returns:
|
|
118
|
-
The name of the var.
|
|
119
|
-
"""
|
|
120
|
-
return self._js_expr
|
|
121
|
-
|
|
122
|
-
@property
|
|
123
|
-
@deprecated("Use `_js_expr` instead.")
|
|
124
|
-
def _var_name_unwrapped(self) -> str:
|
|
125
|
-
"""The name of the var without extra curly braces.
|
|
126
|
-
|
|
127
|
-
Returns:
|
|
128
|
-
The name of the var.
|
|
129
|
-
"""
|
|
130
|
-
return self._js_expr
|
|
131
|
-
|
|
132
107
|
@property
|
|
133
108
|
def _var_is_string(self) -> bool:
|
|
134
109
|
"""Whether the var is a string literal.
|
|
@@ -141,11 +116,11 @@ class Var(Generic[VAR_TYPE]):
|
|
|
141
116
|
def __post_init__(self):
|
|
142
117
|
"""Post-initialize the var."""
|
|
143
118
|
# Decode any inline Var markup and apply it to the instance
|
|
144
|
-
_var_data,
|
|
119
|
+
_var_data, _var_name = _decode_var_immutable(self._var_name)
|
|
145
120
|
|
|
146
|
-
if _var_data or
|
|
121
|
+
if _var_data or _var_name != self._var_name:
|
|
147
122
|
self.__init__(
|
|
148
|
-
|
|
123
|
+
_var_name=_var_name,
|
|
149
124
|
_var_type=self._var_type,
|
|
150
125
|
_var_data=VarData.merge(self._var_data, _var_data),
|
|
151
126
|
)
|
|
@@ -156,7 +131,7 @@ class Var(Generic[VAR_TYPE]):
|
|
|
156
131
|
Returns:
|
|
157
132
|
The hash of the var.
|
|
158
133
|
"""
|
|
159
|
-
return hash((self.
|
|
134
|
+
return hash((self._var_name, self._var_type, self._var_data))
|
|
160
135
|
|
|
161
136
|
def _get_all_var_data(self) -> VarData | None:
|
|
162
137
|
"""Get all VarData associated with the Var.
|
|
@@ -166,7 +141,7 @@ class Var(Generic[VAR_TYPE]):
|
|
|
166
141
|
"""
|
|
167
142
|
return self._var_data
|
|
168
143
|
|
|
169
|
-
def equals(self, other:
|
|
144
|
+
def equals(self, other: ImmutableVar) -> bool:
|
|
170
145
|
"""Check if two vars are equal.
|
|
171
146
|
|
|
172
147
|
Args:
|
|
@@ -176,7 +151,7 @@ class Var(Generic[VAR_TYPE]):
|
|
|
176
151
|
Whether the vars are equal.
|
|
177
152
|
"""
|
|
178
153
|
return (
|
|
179
|
-
self.
|
|
154
|
+
self._var_name == other._var_name
|
|
180
155
|
and self._var_type == other._var_type
|
|
181
156
|
and self._get_all_var_data() == other._get_all_var_data()
|
|
182
157
|
)
|
|
@@ -189,20 +164,24 @@ class Var(Generic[VAR_TYPE]):
|
|
|
189
164
|
**kwargs: Var fields to update.
|
|
190
165
|
|
|
191
166
|
Returns:
|
|
192
|
-
A new
|
|
167
|
+
A new ImmutableVar with the updated fields overwriting the corresponding fields in this Var.
|
|
193
168
|
|
|
194
169
|
Raises:
|
|
195
170
|
TypeError: If _var_is_local, _var_is_string, or _var_full_name_needs_state_prefix is not None.
|
|
196
171
|
"""
|
|
197
172
|
if kwargs.get("_var_is_local", False) is not False:
|
|
198
|
-
raise TypeError(
|
|
173
|
+
raise TypeError(
|
|
174
|
+
"The _var_is_local argument is not supported for ImmutableVar."
|
|
175
|
+
)
|
|
199
176
|
|
|
200
177
|
if kwargs.get("_var_is_string", False) is not False:
|
|
201
|
-
raise TypeError(
|
|
178
|
+
raise TypeError(
|
|
179
|
+
"The _var_is_string argument is not supported for ImmutableVar."
|
|
180
|
+
)
|
|
202
181
|
|
|
203
182
|
if kwargs.get("_var_full_name_needs_state_prefix", False) is not False:
|
|
204
183
|
raise TypeError(
|
|
205
|
-
"The _var_full_name_needs_state_prefix argument is not supported for
|
|
184
|
+
"The _var_full_name_needs_state_prefix argument is not supported for ImmutableVar."
|
|
206
185
|
)
|
|
207
186
|
|
|
208
187
|
return dataclasses.replace(
|
|
@@ -220,7 +199,7 @@ class Var(Generic[VAR_TYPE]):
|
|
|
220
199
|
_var_is_local: bool | None = None,
|
|
221
200
|
_var_is_string: bool | None = None,
|
|
222
201
|
_var_data: VarData | None = None,
|
|
223
|
-
) ->
|
|
202
|
+
) -> ImmutableVar | None:
|
|
224
203
|
"""Create a var from a value.
|
|
225
204
|
|
|
226
205
|
Args:
|
|
@@ -231,57 +210,80 @@ class Var(Generic[VAR_TYPE]):
|
|
|
231
210
|
|
|
232
211
|
Returns:
|
|
233
212
|
The var.
|
|
213
|
+
|
|
214
|
+
Raises:
|
|
215
|
+
VarTypeError: If the value is JSON-unserializable.
|
|
216
|
+
TypeError: If _var_is_local or _var_is_string is not None.
|
|
234
217
|
"""
|
|
235
218
|
if _var_is_local is not None:
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
reason="The _var_is_local argument is not supported for Var."
|
|
239
|
-
"If you want to create a Var from a raw Javascript expression, use the constructor directly",
|
|
240
|
-
deprecation_version="0.6.0",
|
|
241
|
-
removal_version="0.7.0",
|
|
219
|
+
raise TypeError(
|
|
220
|
+
"The _var_is_local argument is not supported for ImmutableVar."
|
|
242
221
|
)
|
|
222
|
+
|
|
243
223
|
if _var_is_string is not None:
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
reason="The _var_is_string argument is not supported for Var."
|
|
247
|
-
"If you want to create a Var from a raw Javascript expression, use the constructor directly",
|
|
248
|
-
deprecation_version="0.6.0",
|
|
249
|
-
removal_version="0.7.0",
|
|
224
|
+
raise TypeError(
|
|
225
|
+
"The _var_is_string argument is not supported for ImmutableVar."
|
|
250
226
|
)
|
|
251
227
|
|
|
228
|
+
from reflex.utils import format
|
|
229
|
+
|
|
230
|
+
# Check for none values.
|
|
231
|
+
if value is None:
|
|
232
|
+
return None
|
|
233
|
+
|
|
252
234
|
# If the value is already a var, do nothing.
|
|
253
|
-
if isinstance(value,
|
|
235
|
+
if isinstance(value, ImmutableVar):
|
|
254
236
|
return value
|
|
255
237
|
|
|
256
238
|
# Try to pull the imports and hooks from contained values.
|
|
257
239
|
if not isinstance(value, str):
|
|
258
|
-
|
|
240
|
+
_var_data = VarData.merge(*_extract_var_data(value), _var_data)
|
|
259
241
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
242
|
+
# Try to serialize the value.
|
|
243
|
+
type_ = type(value)
|
|
244
|
+
if type_ in types.JSONType:
|
|
245
|
+
name = value
|
|
246
|
+
else:
|
|
247
|
+
name, _serialized_type = serializers.serialize(value, get_type=True)
|
|
248
|
+
if name is None:
|
|
249
|
+
raise VarTypeError(
|
|
250
|
+
f"No JSON serializer found for var {value} of type {type_}."
|
|
264
251
|
)
|
|
252
|
+
name = name if isinstance(name, str) else format.json_dumps(name)
|
|
265
253
|
|
|
266
|
-
return
|
|
254
|
+
return cls(
|
|
255
|
+
_var_name=name,
|
|
256
|
+
_var_type=type_,
|
|
257
|
+
_var_data=_var_data,
|
|
258
|
+
)
|
|
267
259
|
|
|
268
260
|
@classmethod
|
|
269
|
-
@deprecated("Use `.create()` instead.")
|
|
270
261
|
def create_safe(
|
|
271
262
|
cls,
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
263
|
+
value: Any,
|
|
264
|
+
_var_is_local: bool | None = None,
|
|
265
|
+
_var_is_string: bool | None = None,
|
|
266
|
+
_var_data: VarData | None = None,
|
|
267
|
+
) -> ImmutableVar:
|
|
268
|
+
"""Create a var from a value, asserting that it is not None.
|
|
276
269
|
|
|
277
270
|
Args:
|
|
278
|
-
|
|
279
|
-
|
|
271
|
+
value: The value to create the var from.
|
|
272
|
+
_var_is_local: Whether the var is local. Deprecated.
|
|
273
|
+
_var_is_string: Whether the var is a string literal. Deprecated.
|
|
274
|
+
_var_data: Additional hooks and imports associated with the Var.
|
|
280
275
|
|
|
281
276
|
Returns:
|
|
282
277
|
The var.
|
|
283
278
|
"""
|
|
284
|
-
|
|
279
|
+
var = cls.create(
|
|
280
|
+
value,
|
|
281
|
+
_var_is_local=_var_is_local,
|
|
282
|
+
_var_is_string=_var_is_string,
|
|
283
|
+
_var_data=_var_data,
|
|
284
|
+
)
|
|
285
|
+
assert var is not None
|
|
286
|
+
return var
|
|
285
287
|
|
|
286
288
|
def __format__(self, format_spec: str) -> str:
|
|
287
289
|
"""Format the var into a Javascript equivalent to an f-string.
|
|
@@ -297,7 +299,7 @@ class Var(Generic[VAR_TYPE]):
|
|
|
297
299
|
_global_vars[hashed_var] = self
|
|
298
300
|
|
|
299
301
|
# Encode the _var_data into the formatted output for tracking purposes.
|
|
300
|
-
return f"{constants.REFLEX_VAR_OPENING_TAG}{hashed_var}{constants.REFLEX_VAR_CLOSING_TAG}{self.
|
|
302
|
+
return f"{constants.REFLEX_VAR_OPENING_TAG}{hashed_var}{constants.REFLEX_VAR_CLOSING_TAG}{self._var_name}"
|
|
301
303
|
|
|
302
304
|
@overload
|
|
303
305
|
def to(self, output: Type[StringVar]) -> ToStringOperation: ...
|
|
@@ -341,7 +343,7 @@ class Var(Generic[VAR_TYPE]):
|
|
|
341
343
|
self,
|
|
342
344
|
output: Type[OUTPUT] | types.GenericType,
|
|
343
345
|
var_type: types.GenericType | None = None,
|
|
344
|
-
) ->
|
|
346
|
+
) -> ImmutableVar:
|
|
345
347
|
"""Convert the var to a different type.
|
|
346
348
|
|
|
347
349
|
Args:
|
|
@@ -385,12 +387,6 @@ class Var(Generic[VAR_TYPE]):
|
|
|
385
387
|
return self.to(BooleanVar, output)
|
|
386
388
|
if fixed_output_type is None:
|
|
387
389
|
return ToNoneOperation.create(self)
|
|
388
|
-
if issubclass(fixed_output_type, Base):
|
|
389
|
-
return self.to(ObjectVar, output)
|
|
390
|
-
if dataclasses.is_dataclass(fixed_output_type) and not issubclass(
|
|
391
|
-
fixed_output_type, Var
|
|
392
|
-
):
|
|
393
|
-
return self.to(ObjectVar, output)
|
|
394
390
|
|
|
395
391
|
if issubclass(output, BooleanVar):
|
|
396
392
|
return ToBooleanVarOperation.create(self)
|
|
@@ -425,9 +421,6 @@ class Var(Generic[VAR_TYPE]):
|
|
|
425
421
|
if issubclass(output, (ObjectVar, Base)):
|
|
426
422
|
return ToObjectOperation.create(self, var_type or dict)
|
|
427
423
|
|
|
428
|
-
if dataclasses.is_dataclass(output):
|
|
429
|
-
return ToObjectOperation.create(self, var_type or dict)
|
|
430
|
-
|
|
431
424
|
if issubclass(output, FunctionVar):
|
|
432
425
|
# if fixed_type is not None and not issubclass(fixed_type, Callable):
|
|
433
426
|
# raise TypeError(
|
|
@@ -454,11 +447,11 @@ class Var(Generic[VAR_TYPE]):
|
|
|
454
447
|
|
|
455
448
|
return self
|
|
456
449
|
|
|
457
|
-
def guess_type(self) ->
|
|
450
|
+
def guess_type(self) -> ImmutableVar:
|
|
458
451
|
"""Guesses the type of the variable based on its `_var_type` attribute.
|
|
459
452
|
|
|
460
453
|
Returns:
|
|
461
|
-
|
|
454
|
+
ImmutableVar: The guessed type of the variable.
|
|
462
455
|
|
|
463
456
|
Raises:
|
|
464
457
|
TypeError: If the type is not supported for guessing.
|
|
@@ -486,11 +479,7 @@ class Var(Generic[VAR_TYPE]):
|
|
|
486
479
|
):
|
|
487
480
|
return self.to(NumberVar, self._var_type)
|
|
488
481
|
|
|
489
|
-
if all(
|
|
490
|
-
inspect.isclass(t)
|
|
491
|
-
and (issubclass(t, Base) or dataclasses.is_dataclass(t))
|
|
492
|
-
for t in inner_types
|
|
493
|
-
):
|
|
482
|
+
if all(inspect.isclass(t) and issubclass(t, Base) for t in inner_types):
|
|
494
483
|
return self.to(ObjectVar, self._var_type)
|
|
495
484
|
|
|
496
485
|
return self
|
|
@@ -510,8 +499,6 @@ class Var(Generic[VAR_TYPE]):
|
|
|
510
499
|
return self.to(StringVar, self._var_type)
|
|
511
500
|
if issubclass(fixed_type, Base):
|
|
512
501
|
return self.to(ObjectVar, self._var_type)
|
|
513
|
-
if dataclasses.is_dataclass(fixed_type):
|
|
514
|
-
return self.to(ObjectVar, self._var_type)
|
|
515
502
|
return self
|
|
516
503
|
|
|
517
504
|
def get_default_value(self) -> Any:
|
|
@@ -566,7 +553,7 @@ class Var(Generic[VAR_TYPE]):
|
|
|
566
553
|
Returns:
|
|
567
554
|
The name of the setter function.
|
|
568
555
|
"""
|
|
569
|
-
var_name_parts = self.
|
|
556
|
+
var_name_parts = self._var_name.split(".")
|
|
570
557
|
setter = constants.SETTER_PREFIX + var_name_parts[-1]
|
|
571
558
|
var_data = self._get_all_var_data()
|
|
572
559
|
if var_data is None:
|
|
@@ -581,7 +568,7 @@ class Var(Generic[VAR_TYPE]):
|
|
|
581
568
|
Returns:
|
|
582
569
|
A function that that creates a setter for the var.
|
|
583
570
|
"""
|
|
584
|
-
actual_name = self.
|
|
571
|
+
actual_name = self._var_name.split(".")[-1]
|
|
585
572
|
|
|
586
573
|
def setter(state: BaseState, value: Any):
|
|
587
574
|
"""Get the setter for the var.
|
|
@@ -596,7 +583,7 @@ class Var(Generic[VAR_TYPE]):
|
|
|
596
583
|
setattr(state, actual_name, value)
|
|
597
584
|
except ValueError:
|
|
598
585
|
console.debug(
|
|
599
|
-
f"{type(state).__name__}.{self.
|
|
586
|
+
f"{type(state).__name__}.{self._var_name}: Failed conversion of {value} to '{self._var_type.__name__}'. Value not set.",
|
|
600
587
|
)
|
|
601
588
|
else:
|
|
602
589
|
setattr(state, actual_name, value)
|
|
@@ -626,11 +613,11 @@ class Var(Generic[VAR_TYPE]):
|
|
|
626
613
|
_var_data=VarData.merge(VarData.from_state(state), self._var_data),
|
|
627
614
|
).guess_type()
|
|
628
615
|
|
|
629
|
-
def __eq__(self, other:
|
|
616
|
+
def __eq__(self, other: ImmutableVar | Any) -> BooleanVar:
|
|
630
617
|
"""Check if the current variable is equal to the given variable.
|
|
631
618
|
|
|
632
619
|
Args:
|
|
633
|
-
other (
|
|
620
|
+
other (ImmutableVar | Any): The variable to compare with.
|
|
634
621
|
|
|
635
622
|
Returns:
|
|
636
623
|
BooleanVar: A BooleanVar object representing the result of the equality check.
|
|
@@ -639,11 +626,11 @@ class Var(Generic[VAR_TYPE]):
|
|
|
639
626
|
|
|
640
627
|
return equal_operation(self, other)
|
|
641
628
|
|
|
642
|
-
def __ne__(self, other:
|
|
629
|
+
def __ne__(self, other: ImmutableVar | Any) -> BooleanVar:
|
|
643
630
|
"""Check if the current object is not equal to the given object.
|
|
644
631
|
|
|
645
632
|
Parameters:
|
|
646
|
-
other (
|
|
633
|
+
other (ImmutableVar | Any): The object to compare with.
|
|
647
634
|
|
|
648
635
|
Returns:
|
|
649
636
|
BooleanVar: A BooleanVar object representing the result of the comparison.
|
|
@@ -662,7 +649,7 @@ class Var(Generic[VAR_TYPE]):
|
|
|
662
649
|
|
|
663
650
|
return boolify(self)
|
|
664
651
|
|
|
665
|
-
def __and__(self, other:
|
|
652
|
+
def __and__(self, other: ImmutableVar | Any) -> ImmutableVar:
|
|
666
653
|
"""Perform a logical AND operation on the current instance and another variable.
|
|
667
654
|
|
|
668
655
|
Args:
|
|
@@ -673,7 +660,7 @@ class Var(Generic[VAR_TYPE]):
|
|
|
673
660
|
"""
|
|
674
661
|
return and_operation(self, other)
|
|
675
662
|
|
|
676
|
-
def __rand__(self, other:
|
|
663
|
+
def __rand__(self, other: ImmutableVar | Any) -> ImmutableVar:
|
|
677
664
|
"""Perform a logical AND operation on the current instance and another variable.
|
|
678
665
|
|
|
679
666
|
Args:
|
|
@@ -684,7 +671,7 @@ class Var(Generic[VAR_TYPE]):
|
|
|
684
671
|
"""
|
|
685
672
|
return and_operation(other, self)
|
|
686
673
|
|
|
687
|
-
def __or__(self, other:
|
|
674
|
+
def __or__(self, other: ImmutableVar | Any) -> ImmutableVar:
|
|
688
675
|
"""Perform a logical OR operation on the current instance and another variable.
|
|
689
676
|
|
|
690
677
|
Args:
|
|
@@ -695,7 +682,7 @@ class Var(Generic[VAR_TYPE]):
|
|
|
695
682
|
"""
|
|
696
683
|
return or_operation(self, other)
|
|
697
684
|
|
|
698
|
-
def __ror__(self, other:
|
|
685
|
+
def __ror__(self, other: ImmutableVar | Any) -> ImmutableVar:
|
|
699
686
|
"""Perform a logical OR operation on the current instance and another variable.
|
|
700
687
|
|
|
701
688
|
Args:
|
|
@@ -725,7 +712,7 @@ class Var(Generic[VAR_TYPE]):
|
|
|
725
712
|
|
|
726
713
|
return JSON_STRINGIFY.call(self).to(StringVar)
|
|
727
714
|
|
|
728
|
-
def as_ref(self) ->
|
|
715
|
+
def as_ref(self) -> ImmutableVar:
|
|
729
716
|
"""Get a reference to the var.
|
|
730
717
|
|
|
731
718
|
Returns:
|
|
@@ -733,14 +720,14 @@ class Var(Generic[VAR_TYPE]):
|
|
|
733
720
|
"""
|
|
734
721
|
from .object import ObjectVar
|
|
735
722
|
|
|
736
|
-
refs =
|
|
737
|
-
|
|
723
|
+
refs = ImmutableVar(
|
|
724
|
+
_var_name="refs",
|
|
738
725
|
_var_data=VarData(
|
|
739
726
|
imports={
|
|
740
727
|
f"/{constants.Dirs.STATE_PATH}": [imports.ImportVar(tag="refs")]
|
|
741
728
|
}
|
|
742
729
|
),
|
|
743
|
-
).to(ObjectVar
|
|
730
|
+
).to(ObjectVar)
|
|
744
731
|
return refs[LiteralVar.create(str(self))]
|
|
745
732
|
|
|
746
733
|
@deprecated("Use `.js_type()` instead.")
|
|
@@ -826,8 +813,7 @@ class Var(Generic[VAR_TYPE]):
|
|
|
826
813
|
TypeError: If the var type is Any.
|
|
827
814
|
"""
|
|
828
815
|
if name.startswith("_"):
|
|
829
|
-
return self.__getattribute__(name)
|
|
830
|
-
|
|
816
|
+
return super(ImmutableVar, self).__getattribute__(name)
|
|
831
817
|
if self._var_type is Any:
|
|
832
818
|
raise TypeError(
|
|
833
819
|
f"You must provide an annotation for the state var `{str(self)}`. Annotation cannot be `{self._var_type}`."
|
|
@@ -871,85 +857,26 @@ class Var(Generic[VAR_TYPE]):
|
|
|
871
857
|
var_data = self._get_all_var_data()
|
|
872
858
|
return var_data.state if var_data else ""
|
|
873
859
|
|
|
874
|
-
@overload
|
|
875
|
-
@classmethod
|
|
876
|
-
def range(cls, stop: int | NumberVar, /) -> ArrayVar[List[int]]: ...
|
|
877
|
-
|
|
878
|
-
@overload
|
|
879
|
-
@classmethod
|
|
880
|
-
def range(
|
|
881
|
-
cls,
|
|
882
|
-
start: int | NumberVar,
|
|
883
|
-
end: int | NumberVar,
|
|
884
|
-
step: int | NumberVar = 1,
|
|
885
|
-
/,
|
|
886
|
-
) -> ArrayVar[List[int]]: ...
|
|
887
|
-
|
|
888
|
-
@classmethod
|
|
889
|
-
def range(
|
|
890
|
-
cls,
|
|
891
|
-
first_endpoint: int | NumberVar,
|
|
892
|
-
second_endpoint: int | NumberVar | None = None,
|
|
893
|
-
step: int | NumberVar | None = None,
|
|
894
|
-
) -> ArrayVar[List[int]]:
|
|
895
|
-
"""Create a range of numbers.
|
|
896
860
|
|
|
897
|
-
|
|
898
|
-
first_endpoint: The end of the range if second_endpoint is not provided, otherwise the start of the range.
|
|
899
|
-
second_endpoint: The end of the range.
|
|
900
|
-
step: The step of the range.
|
|
861
|
+
OUTPUT = TypeVar("OUTPUT", bound=ImmutableVar)
|
|
901
862
|
|
|
902
|
-
Returns:
|
|
903
|
-
The range of numbers.
|
|
904
|
-
"""
|
|
905
|
-
from .sequence import ArrayVar
|
|
906
863
|
|
|
907
|
-
|
|
864
|
+
def _encode_var(value: ImmutableVar) -> str:
|
|
865
|
+
"""Encode the state name into a formatted var.
|
|
908
866
|
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
Raises:
|
|
913
|
-
VarTypeError: when attempting to bool-ify the Var.
|
|
914
|
-
"""
|
|
915
|
-
raise VarTypeError(
|
|
916
|
-
f"Cannot convert Var {str(self)!r} to bool for use with `if`, `and`, `or`, and `not`. "
|
|
917
|
-
"Instead use `rx.cond` and bitwise operators `&` (and), `|` (or), `~` (invert)."
|
|
918
|
-
)
|
|
919
|
-
|
|
920
|
-
def __iter__(self) -> Any:
|
|
921
|
-
"""Raise exception if using Var in an iterable context.
|
|
922
|
-
|
|
923
|
-
Raises:
|
|
924
|
-
VarTypeError: when attempting to iterate over the Var.
|
|
925
|
-
"""
|
|
926
|
-
raise VarTypeError(
|
|
927
|
-
f"Cannot iterate over Var {str(self)!r}. Instead use `rx.foreach`."
|
|
928
|
-
)
|
|
929
|
-
|
|
930
|
-
def __contains__(self, _: Any) -> Var:
|
|
931
|
-
"""Override the 'in' operator to alert the user that it is not supported.
|
|
932
|
-
|
|
933
|
-
Raises:
|
|
934
|
-
VarTypeError: the operation is not supported
|
|
935
|
-
"""
|
|
936
|
-
raise VarTypeError(
|
|
937
|
-
"'in' operator not supported for Var types, use Var.contains() instead."
|
|
938
|
-
)
|
|
939
|
-
|
|
940
|
-
def json(self) -> str:
|
|
941
|
-
"""Serialize the var to a JSON string.
|
|
867
|
+
Args:
|
|
868
|
+
value: The value to encode the state name into.
|
|
942
869
|
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
870
|
+
Returns:
|
|
871
|
+
The encoded var.
|
|
872
|
+
"""
|
|
873
|
+
return f"{value}"
|
|
947
874
|
|
|
948
875
|
|
|
949
|
-
|
|
876
|
+
serializers.serializer(_encode_var)
|
|
950
877
|
|
|
951
878
|
|
|
952
|
-
class LiteralVar(
|
|
879
|
+
class LiteralVar(ImmutableVar):
|
|
953
880
|
"""Base class for immutable literal vars."""
|
|
954
881
|
|
|
955
882
|
@classmethod
|
|
@@ -957,7 +884,7 @@ class LiteralVar(Var):
|
|
|
957
884
|
cls,
|
|
958
885
|
value: Any,
|
|
959
886
|
_var_data: VarData | None = None,
|
|
960
|
-
) ->
|
|
887
|
+
) -> ImmutableVar:
|
|
961
888
|
"""Create a var from a value.
|
|
962
889
|
|
|
963
890
|
Args:
|
|
@@ -974,7 +901,7 @@ class LiteralVar(Var):
|
|
|
974
901
|
from .object import LiteralObjectVar
|
|
975
902
|
from .sequence import LiteralArrayVar, LiteralStringVar
|
|
976
903
|
|
|
977
|
-
if isinstance(value,
|
|
904
|
+
if isinstance(value, ImmutableVar):
|
|
978
905
|
if _var_data is None:
|
|
979
906
|
return value
|
|
980
907
|
return value._replace(merge_var_data=_var_data)
|
|
@@ -997,7 +924,7 @@ class LiteralVar(Var):
|
|
|
997
924
|
if value is None:
|
|
998
925
|
return LiteralNoneVar.create(_var_data=_var_data)
|
|
999
926
|
|
|
1000
|
-
from reflex.event import EventChain,
|
|
927
|
+
from reflex.event import EventChain, EventSpec
|
|
1001
928
|
from reflex.utils.format import get_event_handler_parts
|
|
1002
929
|
|
|
1003
930
|
from .function import ArgsFunctionOperation, FunctionStringVar
|
|
@@ -1021,12 +948,14 @@ class LiteralVar(Var):
|
|
|
1021
948
|
sig = inspect.signature(value.args_spec) # type: ignore
|
|
1022
949
|
if sig.parameters:
|
|
1023
950
|
arg_def = tuple((f"_{p}" for p in sig.parameters))
|
|
1024
|
-
arg_def_expr = LiteralVar.create(
|
|
951
|
+
arg_def_expr = LiteralVar.create(
|
|
952
|
+
[ImmutableVar.create_safe(arg) for arg in arg_def]
|
|
953
|
+
)
|
|
1025
954
|
else:
|
|
1026
955
|
# add a default argument for addEvents if none were specified in value.args_spec
|
|
1027
956
|
# used to trigger the preventDefault() on the event.
|
|
1028
957
|
arg_def = ("...args",)
|
|
1029
|
-
arg_def_expr =
|
|
958
|
+
arg_def_expr = ImmutableVar.create_safe("args")
|
|
1030
959
|
|
|
1031
960
|
return ArgsFunctionOperation.create(
|
|
1032
961
|
arg_def,
|
|
@@ -1039,8 +968,12 @@ class LiteralVar(Var):
|
|
|
1039
968
|
),
|
|
1040
969
|
)
|
|
1041
970
|
|
|
1042
|
-
if isinstance(value,
|
|
1043
|
-
return
|
|
971
|
+
if isinstance(value, Base):
|
|
972
|
+
return LiteralObjectVar.create(
|
|
973
|
+
{k: (None if callable(v) else v) for k, v in value.dict().items()},
|
|
974
|
+
_var_type=type(value),
|
|
975
|
+
_var_data=_var_data,
|
|
976
|
+
)
|
|
1044
977
|
|
|
1045
978
|
serialized_value = serializers.serialize(value)
|
|
1046
979
|
if serialized_value is not None:
|
|
@@ -1050,37 +983,8 @@ class LiteralVar(Var):
|
|
|
1050
983
|
_var_type=type(value),
|
|
1051
984
|
_var_data=_var_data,
|
|
1052
985
|
)
|
|
1053
|
-
if isinstance(serialized_value, str):
|
|
1054
|
-
return LiteralStringVar.create(
|
|
1055
|
-
serialized_value, _var_type=type(value), _var_data=_var_data
|
|
1056
|
-
)
|
|
1057
986
|
return LiteralVar.create(serialized_value, _var_data=_var_data)
|
|
1058
987
|
|
|
1059
|
-
if isinstance(value, Base):
|
|
1060
|
-
# get the fields of the pydantic class
|
|
1061
|
-
fields = value.__fields__.keys()
|
|
1062
|
-
one_level_dict = {field: getattr(value, field) for field in fields}
|
|
1063
|
-
|
|
1064
|
-
return LiteralObjectVar.create(
|
|
1065
|
-
{
|
|
1066
|
-
field: value
|
|
1067
|
-
for field, value in one_level_dict.items()
|
|
1068
|
-
if not callable(value)
|
|
1069
|
-
},
|
|
1070
|
-
_var_type=type(value),
|
|
1071
|
-
_var_data=_var_data,
|
|
1072
|
-
)
|
|
1073
|
-
|
|
1074
|
-
if dataclasses.is_dataclass(value) and not isinstance(value, type):
|
|
1075
|
-
return LiteralObjectVar.create(
|
|
1076
|
-
{
|
|
1077
|
-
k: (None if callable(v) else v)
|
|
1078
|
-
for k, v in dataclasses.asdict(value).items()
|
|
1079
|
-
},
|
|
1080
|
-
_var_type=type(value),
|
|
1081
|
-
_var_data=_var_data,
|
|
1082
|
-
)
|
|
1083
|
-
|
|
1084
988
|
raise TypeError(
|
|
1085
989
|
f"Unsupported type {type(value)} for LiteralVar. Tried to create a LiteralVar from {value}."
|
|
1086
990
|
)
|
|
@@ -1099,19 +1003,6 @@ class LiteralVar(Var):
|
|
|
1099
1003
|
)
|
|
1100
1004
|
|
|
1101
1005
|
|
|
1102
|
-
@serializers.serializer
|
|
1103
|
-
def serialize_literal(value: LiteralVar):
|
|
1104
|
-
"""Serialize a Literal type.
|
|
1105
|
-
|
|
1106
|
-
Args:
|
|
1107
|
-
value: The Literal to serialize.
|
|
1108
|
-
|
|
1109
|
-
Returns:
|
|
1110
|
-
The serialized Literal.
|
|
1111
|
-
"""
|
|
1112
|
-
return serializers.serialize(value._var_value)
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
1006
|
P = ParamSpec("P")
|
|
1116
1007
|
T = TypeVar("T")
|
|
1117
1008
|
|
|
@@ -1120,7 +1011,7 @@ T = TypeVar("T")
|
|
|
1120
1011
|
@overload
|
|
1121
1012
|
def var_operation(
|
|
1122
1013
|
func: Callable[P, CustomVarOperationReturn[NoReturn]],
|
|
1123
|
-
) -> Callable[P,
|
|
1014
|
+
) -> Callable[P, ImmutableVar]: ...
|
|
1124
1015
|
|
|
1125
1016
|
|
|
1126
1017
|
@overload
|
|
@@ -1164,7 +1055,7 @@ def var_operation(
|
|
|
1164
1055
|
|
|
1165
1056
|
def var_operation(
|
|
1166
1057
|
func: Callable[P, CustomVarOperationReturn[T]],
|
|
1167
|
-
) -> Callable[P,
|
|
1058
|
+
) -> Callable[P, ImmutableVar[T]]:
|
|
1168
1059
|
"""Decorator for creating a var operation.
|
|
1169
1060
|
|
|
1170
1061
|
Example:
|
|
@@ -1182,14 +1073,18 @@ def var_operation(
|
|
|
1182
1073
|
"""
|
|
1183
1074
|
|
|
1184
1075
|
@functools.wraps(func)
|
|
1185
|
-
def wrapper(*args: P.args, **kwargs: P.kwargs) ->
|
|
1076
|
+
def wrapper(*args: P.args, **kwargs: P.kwargs) -> ImmutableVar[T]:
|
|
1186
1077
|
func_args = list(inspect.signature(func).parameters)
|
|
1187
1078
|
args_vars = {
|
|
1188
|
-
func_args[i]: (
|
|
1079
|
+
func_args[i]: (
|
|
1080
|
+
LiteralVar.create(arg) if not isinstance(arg, ImmutableVar) else arg
|
|
1081
|
+
)
|
|
1189
1082
|
for i, arg in enumerate(args)
|
|
1190
1083
|
}
|
|
1191
1084
|
kwargs_vars = {
|
|
1192
|
-
key: LiteralVar.create(value)
|
|
1085
|
+
key: LiteralVar.create(value)
|
|
1086
|
+
if not isinstance(value, ImmutableVar)
|
|
1087
|
+
else value
|
|
1193
1088
|
for key, value in kwargs.items()
|
|
1194
1089
|
}
|
|
1195
1090
|
|
|
@@ -1212,13 +1107,10 @@ def unionize(*args: Type) -> Type:
|
|
|
1212
1107
|
"""
|
|
1213
1108
|
if not args:
|
|
1214
1109
|
return Any
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
midpoint = len(args) // 2
|
|
1220
|
-
first_half, second_half = args[:midpoint], args[midpoint:]
|
|
1221
|
-
return Union[unionize(*first_half), unionize(*second_half)]
|
|
1110
|
+
first, *rest = args
|
|
1111
|
+
if not rest:
|
|
1112
|
+
return first
|
|
1113
|
+
return Union[first, unionize(*rest)]
|
|
1222
1114
|
|
|
1223
1115
|
|
|
1224
1116
|
def figure_out_type(value: Any) -> types.GenericType:
|
|
@@ -1241,7 +1133,7 @@ def figure_out_type(value: Any) -> types.GenericType:
|
|
|
1241
1133
|
unionize(*(figure_out_type(k) for k in value)),
|
|
1242
1134
|
unionize(*(figure_out_type(v) for v in value.values())),
|
|
1243
1135
|
]
|
|
1244
|
-
if isinstance(value,
|
|
1136
|
+
if isinstance(value, ImmutableVar):
|
|
1245
1137
|
return value._var_type
|
|
1246
1138
|
return type(value)
|
|
1247
1139
|
|
|
@@ -1264,7 +1156,7 @@ class CachedVarOperation:
|
|
|
1264
1156
|
|
|
1265
1157
|
def __post_init__(self):
|
|
1266
1158
|
"""Post-initialize the CachedVarOperation."""
|
|
1267
|
-
object.__delattr__(self, "
|
|
1159
|
+
object.__delattr__(self, "_var_name")
|
|
1268
1160
|
|
|
1269
1161
|
def __getattr__(self, name: str) -> Any:
|
|
1270
1162
|
"""Get an attribute of the var.
|
|
@@ -1275,7 +1167,7 @@ class CachedVarOperation:
|
|
|
1275
1167
|
Returns:
|
|
1276
1168
|
The attribute.
|
|
1277
1169
|
"""
|
|
1278
|
-
if name == "
|
|
1170
|
+
if name == "_var_name":
|
|
1279
1171
|
return self._cached_var_name
|
|
1280
1172
|
|
|
1281
1173
|
parent_classes = inspect.getmro(self.__class__)
|
|
@@ -1302,7 +1194,9 @@ class CachedVarOperation:
|
|
|
1302
1194
|
return VarData.merge(
|
|
1303
1195
|
*map(
|
|
1304
1196
|
lambda value: (
|
|
1305
|
-
value._get_all_var_data()
|
|
1197
|
+
value._get_all_var_data()
|
|
1198
|
+
if isinstance(value, ImmutableVar)
|
|
1199
|
+
else None
|
|
1306
1200
|
),
|
|
1307
1201
|
map(
|
|
1308
1202
|
lambda field: getattr(self, field.name),
|
|
@@ -1324,13 +1218,13 @@ class CachedVarOperation:
|
|
|
1324
1218
|
*[
|
|
1325
1219
|
getattr(self, field.name)
|
|
1326
1220
|
for field in dataclasses.fields(self) # type: ignore
|
|
1327
|
-
if field.name not in ["
|
|
1221
|
+
if field.name not in ["_var_name", "_var_data", "_var_type"]
|
|
1328
1222
|
],
|
|
1329
1223
|
)
|
|
1330
1224
|
)
|
|
1331
1225
|
|
|
1332
1226
|
|
|
1333
|
-
def and_operation(a:
|
|
1227
|
+
def and_operation(a: ImmutableVar | Any, b: ImmutableVar | Any) -> ImmutableVar:
|
|
1334
1228
|
"""Perform a logical AND operation on two variables.
|
|
1335
1229
|
|
|
1336
1230
|
Args:
|
|
@@ -1344,7 +1238,7 @@ def and_operation(a: Var | Any, b: Var | Any) -> Var:
|
|
|
1344
1238
|
|
|
1345
1239
|
|
|
1346
1240
|
@var_operation
|
|
1347
|
-
def _and_operation(a:
|
|
1241
|
+
def _and_operation(a: ImmutableVar, b: ImmutableVar):
|
|
1348
1242
|
"""Perform a logical AND operation on two variables.
|
|
1349
1243
|
|
|
1350
1244
|
Args:
|
|
@@ -1360,7 +1254,7 @@ def _and_operation(a: Var, b: Var):
|
|
|
1360
1254
|
)
|
|
1361
1255
|
|
|
1362
1256
|
|
|
1363
|
-
def or_operation(a:
|
|
1257
|
+
def or_operation(a: ImmutableVar | Any, b: ImmutableVar | Any) -> ImmutableVar:
|
|
1364
1258
|
"""Perform a logical OR operation on two variables.
|
|
1365
1259
|
|
|
1366
1260
|
Args:
|
|
@@ -1374,7 +1268,7 @@ def or_operation(a: Var | Any, b: Var | Any) -> Var:
|
|
|
1374
1268
|
|
|
1375
1269
|
|
|
1376
1270
|
@var_operation
|
|
1377
|
-
def _or_operation(a:
|
|
1271
|
+
def _or_operation(a: ImmutableVar, b: ImmutableVar):
|
|
1378
1272
|
"""Perform a logical OR operation on two variables.
|
|
1379
1273
|
|
|
1380
1274
|
Args:
|
|
@@ -1395,36 +1289,36 @@ def _or_operation(a: Var, b: Var):
|
|
|
1395
1289
|
frozen=True,
|
|
1396
1290
|
**{"slots": True} if sys.version_info >= (3, 10) else {},
|
|
1397
1291
|
)
|
|
1398
|
-
class
|
|
1292
|
+
class ImmutableCallableVar(ImmutableVar):
|
|
1399
1293
|
"""Decorate a Var-returning function to act as both a Var and a function.
|
|
1400
1294
|
|
|
1401
1295
|
This is used as a compatibility shim for replacing Var objects in the
|
|
1402
1296
|
API with functions that return a family of Var.
|
|
1403
1297
|
"""
|
|
1404
1298
|
|
|
1405
|
-
fn: Callable[...,
|
|
1406
|
-
default_factory=lambda: lambda:
|
|
1299
|
+
fn: Callable[..., ImmutableVar] = dataclasses.field(
|
|
1300
|
+
default_factory=lambda: lambda: ImmutableVar(_var_name="undefined")
|
|
1407
1301
|
)
|
|
1408
|
-
original_var:
|
|
1409
|
-
default_factory=lambda:
|
|
1302
|
+
original_var: ImmutableVar = dataclasses.field(
|
|
1303
|
+
default_factory=lambda: ImmutableVar(_var_name="undefined")
|
|
1410
1304
|
)
|
|
1411
1305
|
|
|
1412
|
-
def __init__(self, fn: Callable[...,
|
|
1306
|
+
def __init__(self, fn: Callable[..., ImmutableVar]):
|
|
1413
1307
|
"""Initialize a CallableVar.
|
|
1414
1308
|
|
|
1415
1309
|
Args:
|
|
1416
1310
|
fn: The function to decorate (must return Var)
|
|
1417
1311
|
"""
|
|
1418
1312
|
original_var = fn()
|
|
1419
|
-
super(
|
|
1420
|
-
|
|
1313
|
+
super(ImmutableCallableVar, self).__init__(
|
|
1314
|
+
_var_name=original_var._var_name,
|
|
1421
1315
|
_var_type=original_var._var_type,
|
|
1422
1316
|
_var_data=VarData.merge(original_var._get_all_var_data()),
|
|
1423
1317
|
)
|
|
1424
1318
|
object.__setattr__(self, "fn", fn)
|
|
1425
1319
|
object.__setattr__(self, "original_var", original_var)
|
|
1426
1320
|
|
|
1427
|
-
def __call__(self, *args, **kwargs) ->
|
|
1321
|
+
def __call__(self, *args, **kwargs) -> ImmutableVar:
|
|
1428
1322
|
"""Call the decorated function.
|
|
1429
1323
|
|
|
1430
1324
|
Args:
|
|
@@ -1453,13 +1347,13 @@ DICT_VAL = TypeVar("DICT_VAL")
|
|
|
1453
1347
|
LIST_INSIDE = TypeVar("LIST_INSIDE")
|
|
1454
1348
|
|
|
1455
1349
|
|
|
1456
|
-
class FakeComputedVarBaseClass(property):
|
|
1350
|
+
class FakeComputedVarBaseClass(Var, property):
|
|
1457
1351
|
"""A fake base class for ComputedVar to avoid inheriting from property."""
|
|
1458
1352
|
|
|
1459
1353
|
__pydantic_run_validation__ = False
|
|
1460
1354
|
|
|
1461
1355
|
|
|
1462
|
-
def is_computed_var(obj: Any) -> TypeGuard[
|
|
1356
|
+
def is_computed_var(obj: Any) -> TypeGuard[ImmutableComputedVar]:
|
|
1463
1357
|
"""Check if the object is a ComputedVar.
|
|
1464
1358
|
|
|
1465
1359
|
Args:
|
|
@@ -1476,7 +1370,7 @@ def is_computed_var(obj: Any) -> TypeGuard[ComputedVar]:
|
|
|
1476
1370
|
frozen=True,
|
|
1477
1371
|
**{"slots": True} if sys.version_info >= (3, 10) else {},
|
|
1478
1372
|
)
|
|
1479
|
-
class
|
|
1373
|
+
class ImmutableComputedVar(ImmutableVar[RETURN_TYPE]):
|
|
1480
1374
|
"""A field with computed getters."""
|
|
1481
1375
|
|
|
1482
1376
|
# Whether to track dependencies and cache computed values
|
|
@@ -1506,7 +1400,7 @@ class ComputedVar(Var[RETURN_TYPE]):
|
|
|
1506
1400
|
fget: Callable[[BASE_STATE], RETURN_TYPE],
|
|
1507
1401
|
initial_value: RETURN_TYPE | types.Unset = types.Unset(),
|
|
1508
1402
|
cache: bool = False,
|
|
1509
|
-
deps: Optional[List[Union[str,
|
|
1403
|
+
deps: Optional[List[Union[str, ImmutableVar]]] = None,
|
|
1510
1404
|
auto_deps: bool = True,
|
|
1511
1405
|
interval: Optional[Union[int, datetime.timedelta]] = None,
|
|
1512
1406
|
backend: bool | None = None,
|
|
@@ -1530,12 +1424,12 @@ class ComputedVar(Var[RETURN_TYPE]):
|
|
|
1530
1424
|
hints = get_type_hints(fget)
|
|
1531
1425
|
hint = hints.get("return", Any)
|
|
1532
1426
|
|
|
1533
|
-
kwargs["
|
|
1427
|
+
kwargs["_var_name"] = kwargs.pop("_var_name", fget.__name__)
|
|
1534
1428
|
kwargs["_var_type"] = kwargs.pop("_var_type", hint)
|
|
1535
1429
|
|
|
1536
|
-
|
|
1430
|
+
ImmutableVar.__init__(
|
|
1537
1431
|
self,
|
|
1538
|
-
|
|
1432
|
+
_var_name=kwargs.pop("_var_name"),
|
|
1539
1433
|
_var_type=kwargs.pop("_var_type"),
|
|
1540
1434
|
_var_data=kwargs.pop("_var_data", None),
|
|
1541
1435
|
)
|
|
@@ -1556,7 +1450,7 @@ class ComputedVar(Var[RETURN_TYPE]):
|
|
|
1556
1450
|
deps = []
|
|
1557
1451
|
else:
|
|
1558
1452
|
for dep in deps:
|
|
1559
|
-
if isinstance(dep,
|
|
1453
|
+
if isinstance(dep, ImmutableVar):
|
|
1560
1454
|
continue
|
|
1561
1455
|
if isinstance(dep, str) and dep != "":
|
|
1562
1456
|
continue
|
|
@@ -1566,7 +1460,7 @@ class ComputedVar(Var[RETURN_TYPE]):
|
|
|
1566
1460
|
object.__setattr__(
|
|
1567
1461
|
self,
|
|
1568
1462
|
"_static_deps",
|
|
1569
|
-
{dep.
|
|
1463
|
+
{dep._var_name if isinstance(dep, ImmutableVar) else dep for dep in deps},
|
|
1570
1464
|
)
|
|
1571
1465
|
object.__setattr__(self, "_auto_deps", auto_deps)
|
|
1572
1466
|
|
|
@@ -1594,7 +1488,7 @@ class ComputedVar(Var[RETURN_TYPE]):
|
|
|
1594
1488
|
auto_deps=kwargs.pop("auto_deps", self._auto_deps),
|
|
1595
1489
|
interval=kwargs.pop("interval", self._update_interval),
|
|
1596
1490
|
backend=kwargs.pop("backend", self._backend),
|
|
1597
|
-
|
|
1491
|
+
_var_name=kwargs.pop("_var_name", self._var_name),
|
|
1598
1492
|
_var_type=kwargs.pop("_var_type", self._var_type),
|
|
1599
1493
|
_var_data=kwargs.pop(
|
|
1600
1494
|
"_var_data", VarData.merge(self._var_data, merge_var_data)
|
|
@@ -1614,7 +1508,7 @@ class ComputedVar(Var[RETURN_TYPE]):
|
|
|
1614
1508
|
Returns:
|
|
1615
1509
|
An attribute name.
|
|
1616
1510
|
"""
|
|
1617
|
-
return f"__cached_{self.
|
|
1511
|
+
return f"__cached_{self._var_name}"
|
|
1618
1512
|
|
|
1619
1513
|
@property
|
|
1620
1514
|
def _last_updated_attr(self) -> str:
|
|
@@ -1623,7 +1517,7 @@ class ComputedVar(Var[RETURN_TYPE]):
|
|
|
1623
1517
|
Returns:
|
|
1624
1518
|
An attribute name.
|
|
1625
1519
|
"""
|
|
1626
|
-
return f"__last_updated_{self.
|
|
1520
|
+
return f"__last_updated_{self._var_name}"
|
|
1627
1521
|
|
|
1628
1522
|
def needs_update(self, instance: BaseState) -> bool:
|
|
1629
1523
|
"""Check if the computed var needs to be updated.
|
|
@@ -1643,48 +1537,50 @@ class ComputedVar(Var[RETURN_TYPE]):
|
|
|
1643
1537
|
|
|
1644
1538
|
@overload
|
|
1645
1539
|
def __get__(
|
|
1646
|
-
self:
|
|
1540
|
+
self: ImmutableComputedVar[int] | ImmutableComputedVar[float],
|
|
1647
1541
|
instance: None,
|
|
1648
1542
|
owner: Type,
|
|
1649
1543
|
) -> NumberVar: ...
|
|
1650
1544
|
|
|
1651
1545
|
@overload
|
|
1652
1546
|
def __get__(
|
|
1653
|
-
self:
|
|
1547
|
+
self: ImmutableComputedVar[str],
|
|
1654
1548
|
instance: None,
|
|
1655
1549
|
owner: Type,
|
|
1656
1550
|
) -> StringVar: ...
|
|
1657
1551
|
|
|
1658
1552
|
@overload
|
|
1659
1553
|
def __get__(
|
|
1660
|
-
self:
|
|
1554
|
+
self: ImmutableComputedVar[dict[DICT_KEY, DICT_VAL]],
|
|
1661
1555
|
instance: None,
|
|
1662
1556
|
owner: Type,
|
|
1663
1557
|
) -> ObjectVar[dict[DICT_KEY, DICT_VAL]]: ...
|
|
1664
1558
|
|
|
1665
1559
|
@overload
|
|
1666
1560
|
def __get__(
|
|
1667
|
-
self:
|
|
1561
|
+
self: ImmutableComputedVar[list[LIST_INSIDE]],
|
|
1668
1562
|
instance: None,
|
|
1669
1563
|
owner: Type,
|
|
1670
1564
|
) -> ArrayVar[list[LIST_INSIDE]]: ...
|
|
1671
1565
|
|
|
1672
1566
|
@overload
|
|
1673
1567
|
def __get__(
|
|
1674
|
-
self:
|
|
1568
|
+
self: ImmutableComputedVar[set[LIST_INSIDE]],
|
|
1675
1569
|
instance: None,
|
|
1676
1570
|
owner: Type,
|
|
1677
1571
|
) -> ArrayVar[set[LIST_INSIDE]]: ...
|
|
1678
1572
|
|
|
1679
1573
|
@overload
|
|
1680
1574
|
def __get__(
|
|
1681
|
-
self:
|
|
1575
|
+
self: ImmutableComputedVar[tuple[LIST_INSIDE, ...]],
|
|
1682
1576
|
instance: None,
|
|
1683
1577
|
owner: Type,
|
|
1684
1578
|
) -> ArrayVar[tuple[LIST_INSIDE, ...]]: ...
|
|
1685
1579
|
|
|
1686
1580
|
@overload
|
|
1687
|
-
def __get__(
|
|
1581
|
+
def __get__(
|
|
1582
|
+
self, instance: None, owner: Type
|
|
1583
|
+
) -> ImmutableComputedVar[RETURN_TYPE]: ...
|
|
1688
1584
|
|
|
1689
1585
|
@overload
|
|
1690
1586
|
def __get__(self, instance: BaseState, owner: Type) -> RETURN_TYPE: ...
|
|
@@ -1703,13 +1599,13 @@ class ComputedVar(Var[RETURN_TYPE]):
|
|
|
1703
1599
|
"""
|
|
1704
1600
|
if instance is None:
|
|
1705
1601
|
state_where_defined = owner
|
|
1706
|
-
while self.
|
|
1602
|
+
while self.fget.__name__ in state_where_defined.inherited_vars:
|
|
1707
1603
|
state_where_defined = state_where_defined.get_parent_state()
|
|
1708
1604
|
|
|
1709
1605
|
return self._replace(
|
|
1710
|
-
|
|
1606
|
+
_var_name=format_state_name(state_where_defined.get_full_name())
|
|
1711
1607
|
+ "."
|
|
1712
|
-
+ self.
|
|
1608
|
+
+ self._var_name,
|
|
1713
1609
|
merge_var_data=VarData.from_state(state_where_defined),
|
|
1714
1610
|
).guess_type()
|
|
1715
1611
|
|
|
@@ -1809,7 +1705,7 @@ class ComputedVar(Var[RETURN_TYPE]):
|
|
|
1809
1705
|
)
|
|
1810
1706
|
# recurse into property fget functions
|
|
1811
1707
|
elif isinstance(ref_obj, property) and not isinstance(
|
|
1812
|
-
ref_obj,
|
|
1708
|
+
ref_obj, ImmutableComputedVar
|
|
1813
1709
|
):
|
|
1814
1710
|
d.update(
|
|
1815
1711
|
self._deps(
|
|
@@ -1877,7 +1773,7 @@ class ComputedVar(Var[RETURN_TYPE]):
|
|
|
1877
1773
|
return self._fget
|
|
1878
1774
|
|
|
1879
1775
|
|
|
1880
|
-
class DynamicRouteVar(
|
|
1776
|
+
class DynamicRouteVar(ImmutableComputedVar[Union[str, List[str]]]):
|
|
1881
1777
|
"""A ComputedVar that represents a dynamic route."""
|
|
1882
1778
|
|
|
1883
1779
|
pass
|
|
@@ -1888,41 +1784,45 @@ if TYPE_CHECKING:
|
|
|
1888
1784
|
|
|
1889
1785
|
|
|
1890
1786
|
@overload
|
|
1891
|
-
def
|
|
1787
|
+
def immutable_computed_var(
|
|
1892
1788
|
fget: None = None,
|
|
1893
1789
|
initial_value: Any | types.Unset = types.Unset(),
|
|
1894
1790
|
cache: bool = False,
|
|
1895
|
-
deps: Optional[List[Union[str,
|
|
1791
|
+
deps: Optional[List[Union[str, ImmutableVar]]] = None,
|
|
1896
1792
|
auto_deps: bool = True,
|
|
1897
1793
|
interval: Optional[Union[datetime.timedelta, int]] = None,
|
|
1898
1794
|
backend: bool | None = None,
|
|
1899
1795
|
**kwargs,
|
|
1900
|
-
) -> Callable[
|
|
1796
|
+
) -> Callable[
|
|
1797
|
+
[Callable[[BASE_STATE], RETURN_TYPE]], ImmutableComputedVar[RETURN_TYPE]
|
|
1798
|
+
]: ...
|
|
1901
1799
|
|
|
1902
1800
|
|
|
1903
1801
|
@overload
|
|
1904
|
-
def
|
|
1802
|
+
def immutable_computed_var(
|
|
1905
1803
|
fget: Callable[[BASE_STATE], RETURN_TYPE],
|
|
1906
1804
|
initial_value: RETURN_TYPE | types.Unset = types.Unset(),
|
|
1907
1805
|
cache: bool = False,
|
|
1908
|
-
deps: Optional[List[Union[str,
|
|
1806
|
+
deps: Optional[List[Union[str, ImmutableVar]]] = None,
|
|
1909
1807
|
auto_deps: bool = True,
|
|
1910
1808
|
interval: Optional[Union[datetime.timedelta, int]] = None,
|
|
1911
1809
|
backend: bool | None = None,
|
|
1912
1810
|
**kwargs,
|
|
1913
|
-
) ->
|
|
1811
|
+
) -> ImmutableComputedVar[RETURN_TYPE]: ...
|
|
1914
1812
|
|
|
1915
1813
|
|
|
1916
|
-
def
|
|
1814
|
+
def immutable_computed_var(
|
|
1917
1815
|
fget: Callable[[BASE_STATE], Any] | None = None,
|
|
1918
1816
|
initial_value: Any | types.Unset = types.Unset(),
|
|
1919
1817
|
cache: bool = False,
|
|
1920
|
-
deps: Optional[List[Union[str,
|
|
1818
|
+
deps: Optional[List[Union[str, ImmutableVar]]] = None,
|
|
1921
1819
|
auto_deps: bool = True,
|
|
1922
1820
|
interval: Optional[Union[datetime.timedelta, int]] = None,
|
|
1923
1821
|
backend: bool | None = None,
|
|
1924
1822
|
**kwargs,
|
|
1925
|
-
) ->
|
|
1823
|
+
) -> (
|
|
1824
|
+
ImmutableComputedVar | Callable[[Callable[[BASE_STATE], Any]], ImmutableComputedVar]
|
|
1825
|
+
):
|
|
1926
1826
|
"""A ComputedVar decorator with or without kwargs.
|
|
1927
1827
|
|
|
1928
1828
|
Args:
|
|
@@ -1949,10 +1849,10 @@ def computed_var(
|
|
|
1949
1849
|
raise VarDependencyError("Cannot track dependencies without caching.")
|
|
1950
1850
|
|
|
1951
1851
|
if fget is not None:
|
|
1952
|
-
return
|
|
1852
|
+
return ImmutableComputedVar(fget, cache=cache)
|
|
1953
1853
|
|
|
1954
|
-
def wrapper(fget: Callable[[BASE_STATE], Any]) ->
|
|
1955
|
-
return
|
|
1854
|
+
def wrapper(fget: Callable[[BASE_STATE], Any]) -> ImmutableComputedVar:
|
|
1855
|
+
return ImmutableComputedVar(
|
|
1956
1856
|
fget,
|
|
1957
1857
|
initial_value=initial_value,
|
|
1958
1858
|
cache=cache,
|
|
@@ -1969,7 +1869,7 @@ def computed_var(
|
|
|
1969
1869
|
RETURN = TypeVar("RETURN")
|
|
1970
1870
|
|
|
1971
1871
|
|
|
1972
|
-
class CustomVarOperationReturn(
|
|
1872
|
+
class CustomVarOperationReturn(ImmutableVar[RETURN]):
|
|
1973
1873
|
"""Base class for custom var operations."""
|
|
1974
1874
|
|
|
1975
1875
|
@classmethod
|
|
@@ -1990,7 +1890,7 @@ class CustomVarOperationReturn(Var[RETURN]):
|
|
|
1990
1890
|
The CustomVarOperation.
|
|
1991
1891
|
"""
|
|
1992
1892
|
return CustomVarOperationReturn(
|
|
1993
|
-
|
|
1893
|
+
_var_name=js_expression,
|
|
1994
1894
|
_var_type=_var_type or Any,
|
|
1995
1895
|
_var_data=_var_data,
|
|
1996
1896
|
)
|
|
@@ -1999,23 +1899,17 @@ class CustomVarOperationReturn(Var[RETURN]):
|
|
|
1999
1899
|
def var_operation_return(
|
|
2000
1900
|
js_expression: str,
|
|
2001
1901
|
var_type: Type[RETURN] | None = None,
|
|
2002
|
-
var_data: VarData | None = None,
|
|
2003
1902
|
) -> CustomVarOperationReturn[RETURN]:
|
|
2004
1903
|
"""Shortcut for creating a CustomVarOperationReturn.
|
|
2005
1904
|
|
|
2006
1905
|
Args:
|
|
2007
1906
|
js_expression: The JavaScript expression to evaluate.
|
|
2008
1907
|
var_type: The type of the var.
|
|
2009
|
-
var_data: Additional hooks and imports associated with the Var.
|
|
2010
1908
|
|
|
2011
1909
|
Returns:
|
|
2012
1910
|
The CustomVarOperationReturn.
|
|
2013
1911
|
"""
|
|
2014
|
-
return CustomVarOperationReturn.create(
|
|
2015
|
-
js_expression,
|
|
2016
|
-
var_type,
|
|
2017
|
-
var_data,
|
|
2018
|
-
)
|
|
1912
|
+
return CustomVarOperationReturn.create(js_expression, var_type)
|
|
2019
1913
|
|
|
2020
1914
|
|
|
2021
1915
|
@dataclasses.dataclass(
|
|
@@ -2023,10 +1917,12 @@ def var_operation_return(
|
|
|
2023
1917
|
frozen=True,
|
|
2024
1918
|
**{"slots": True} if sys.version_info >= (3, 10) else {},
|
|
2025
1919
|
)
|
|
2026
|
-
class CustomVarOperation(CachedVarOperation,
|
|
1920
|
+
class CustomVarOperation(CachedVarOperation, ImmutableVar[T]):
|
|
2027
1921
|
"""Base class for custom var operations."""
|
|
2028
1922
|
|
|
2029
|
-
_args: Tuple[Tuple[str,
|
|
1923
|
+
_args: Tuple[Tuple[str, ImmutableVar], ...] = dataclasses.field(
|
|
1924
|
+
default_factory=tuple
|
|
1925
|
+
)
|
|
2030
1926
|
|
|
2031
1927
|
_return: CustomVarOperationReturn[T] = dataclasses.field(
|
|
2032
1928
|
default_factory=lambda: CustomVarOperationReturn.create("")
|
|
@@ -2060,7 +1956,7 @@ class CustomVarOperation(CachedVarOperation, Var[T]):
|
|
|
2060
1956
|
@classmethod
|
|
2061
1957
|
def create(
|
|
2062
1958
|
cls,
|
|
2063
|
-
args: Tuple[Tuple[str,
|
|
1959
|
+
args: Tuple[Tuple[str, ImmutableVar], ...],
|
|
2064
1960
|
return_var: CustomVarOperationReturn[T],
|
|
2065
1961
|
_var_data: VarData | None = None,
|
|
2066
1962
|
) -> CustomVarOperation[T]:
|
|
@@ -2075,7 +1971,7 @@ class CustomVarOperation(CachedVarOperation, Var[T]):
|
|
|
2075
1971
|
The CustomVarOperation.
|
|
2076
1972
|
"""
|
|
2077
1973
|
return CustomVarOperation(
|
|
2078
|
-
|
|
1974
|
+
_var_name="",
|
|
2079
1975
|
_var_type=return_var._var_type,
|
|
2080
1976
|
_var_data=_var_data,
|
|
2081
1977
|
_args=args,
|
|
@@ -2083,7 +1979,7 @@ class CustomVarOperation(CachedVarOperation, Var[T]):
|
|
|
2083
1979
|
)
|
|
2084
1980
|
|
|
2085
1981
|
|
|
2086
|
-
class NoneVar(
|
|
1982
|
+
class NoneVar(ImmutableVar[None]):
|
|
2087
1983
|
"""A var representing None."""
|
|
2088
1984
|
|
|
2089
1985
|
|
|
@@ -2112,7 +2008,7 @@ class LiteralNoneVar(LiteralVar, NoneVar):
|
|
|
2112
2008
|
The var.
|
|
2113
2009
|
"""
|
|
2114
2010
|
return LiteralNoneVar(
|
|
2115
|
-
|
|
2011
|
+
_var_name="null",
|
|
2116
2012
|
_var_type=None,
|
|
2117
2013
|
_var_data=_var_data,
|
|
2118
2014
|
)
|
|
@@ -2155,7 +2051,7 @@ class ToNoneOperation(CachedVarOperation, NoneVar):
|
|
|
2155
2051
|
The ToNoneOperation.
|
|
2156
2052
|
"""
|
|
2157
2053
|
return ToNoneOperation(
|
|
2158
|
-
|
|
2054
|
+
_var_name="",
|
|
2159
2055
|
_var_type=None,
|
|
2160
2056
|
_var_data=_var_data,
|
|
2161
2057
|
_original_var=var,
|
|
@@ -2167,7 +2063,7 @@ class ToNoneOperation(CachedVarOperation, NoneVar):
|
|
|
2167
2063
|
frozen=True,
|
|
2168
2064
|
**{"slots": True} if sys.version_info >= (3, 10) else {},
|
|
2169
2065
|
)
|
|
2170
|
-
class StateOperation(CachedVarOperation,
|
|
2066
|
+
class StateOperation(CachedVarOperation, ImmutableVar):
|
|
2171
2067
|
"""A var operation that accesses a field on an object."""
|
|
2172
2068
|
|
|
2173
2069
|
_state_name: str = dataclasses.field(default="")
|
|
@@ -2191,7 +2087,7 @@ class StateOperation(CachedVarOperation, Var):
|
|
|
2191
2087
|
Returns:
|
|
2192
2088
|
The attribute.
|
|
2193
2089
|
"""
|
|
2194
|
-
if name == "
|
|
2090
|
+
if name == "_var_name":
|
|
2195
2091
|
return self._cached_var_name
|
|
2196
2092
|
|
|
2197
2093
|
return getattr(self._field, name)
|
|
@@ -2200,7 +2096,7 @@ class StateOperation(CachedVarOperation, Var):
|
|
|
2200
2096
|
def create(
|
|
2201
2097
|
cls,
|
|
2202
2098
|
state_name: str,
|
|
2203
|
-
field:
|
|
2099
|
+
field: ImmutableVar,
|
|
2204
2100
|
_var_data: VarData | None = None,
|
|
2205
2101
|
) -> StateOperation:
|
|
2206
2102
|
"""Create a DotOperation.
|
|
@@ -2214,7 +2110,7 @@ class StateOperation(CachedVarOperation, Var):
|
|
|
2214
2110
|
The DotOperation.
|
|
2215
2111
|
"""
|
|
2216
2112
|
return StateOperation(
|
|
2217
|
-
|
|
2113
|
+
_var_name="",
|
|
2218
2114
|
_var_type=field._var_type,
|
|
2219
2115
|
_var_data=_var_data,
|
|
2220
2116
|
_state_name=state_name,
|
|
@@ -2238,7 +2134,7 @@ class ToOperation:
|
|
|
2238
2134
|
|
|
2239
2135
|
def __post_init__(self):
|
|
2240
2136
|
"""Post initialization."""
|
|
2241
|
-
object.__delattr__(self, "
|
|
2137
|
+
object.__delattr__(self, "_var_name")
|
|
2242
2138
|
|
|
2243
2139
|
def __hash__(self) -> int:
|
|
2244
2140
|
"""Calculate the hash value of the object.
|
|
@@ -2277,287 +2173,8 @@ class ToOperation:
|
|
|
2277
2173
|
The ToOperation.
|
|
2278
2174
|
"""
|
|
2279
2175
|
return cls(
|
|
2280
|
-
|
|
2176
|
+
_var_name="", # type: ignore
|
|
2281
2177
|
_var_data=_var_data, # type: ignore
|
|
2282
2178
|
_var_type=_var_type or cls._default_var_type, # type: ignore
|
|
2283
2179
|
_original=value, # type: ignore
|
|
2284
2180
|
)
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
def get_uuid_string_var() -> Var:
|
|
2288
|
-
"""Return a Var that generates a single memoized UUID via .web/utils/state.js.
|
|
2289
|
-
|
|
2290
|
-
useMemo with an empty dependency array ensures that the generated UUID is
|
|
2291
|
-
consistent across re-renders of the component.
|
|
2292
|
-
|
|
2293
|
-
Returns:
|
|
2294
|
-
A Var that generates a UUID at runtime.
|
|
2295
|
-
"""
|
|
2296
|
-
from reflex.utils.imports import ImportVar
|
|
2297
|
-
from reflex.vars import Var
|
|
2298
|
-
|
|
2299
|
-
unique_uuid_var = get_unique_variable_name()
|
|
2300
|
-
unique_uuid_var_data = VarData(
|
|
2301
|
-
imports={
|
|
2302
|
-
f"/{constants.Dirs.STATE_PATH}": {ImportVar(tag="generateUUID")}, # type: ignore
|
|
2303
|
-
"react": "useMemo",
|
|
2304
|
-
},
|
|
2305
|
-
hooks={f"const {unique_uuid_var} = useMemo(generateUUID, [])": None},
|
|
2306
|
-
)
|
|
2307
|
-
|
|
2308
|
-
return Var(
|
|
2309
|
-
_js_expr=unique_uuid_var,
|
|
2310
|
-
_var_type=str,
|
|
2311
|
-
_var_data=unique_uuid_var_data,
|
|
2312
|
-
)
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
# Set of unique variable names.
|
|
2316
|
-
USED_VARIABLES = set()
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
def get_unique_variable_name() -> str:
|
|
2320
|
-
"""Get a unique variable name.
|
|
2321
|
-
|
|
2322
|
-
Returns:
|
|
2323
|
-
The unique variable name.
|
|
2324
|
-
"""
|
|
2325
|
-
name = "".join([random.choice(string.ascii_lowercase) for _ in range(8)])
|
|
2326
|
-
if name not in USED_VARIABLES:
|
|
2327
|
-
USED_VARIABLES.add(name)
|
|
2328
|
-
return name
|
|
2329
|
-
return get_unique_variable_name()
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
@dataclasses.dataclass(
|
|
2333
|
-
eq=True,
|
|
2334
|
-
frozen=True,
|
|
2335
|
-
)
|
|
2336
|
-
class VarData:
|
|
2337
|
-
"""Metadata associated with a x."""
|
|
2338
|
-
|
|
2339
|
-
# The name of the enclosing state.
|
|
2340
|
-
state: str = dataclasses.field(default="")
|
|
2341
|
-
|
|
2342
|
-
# Imports needed to render this var
|
|
2343
|
-
imports: ImmutableParsedImportDict = dataclasses.field(default_factory=tuple)
|
|
2344
|
-
|
|
2345
|
-
# Hooks that need to be present in the component to render this var
|
|
2346
|
-
hooks: Tuple[str, ...] = dataclasses.field(default_factory=tuple)
|
|
2347
|
-
|
|
2348
|
-
def __init__(
|
|
2349
|
-
self,
|
|
2350
|
-
state: str = "",
|
|
2351
|
-
imports: ImportDict | ParsedImportDict | None = None,
|
|
2352
|
-
hooks: dict[str, None] | None = None,
|
|
2353
|
-
):
|
|
2354
|
-
"""Initialize the var data.
|
|
2355
|
-
|
|
2356
|
-
Args:
|
|
2357
|
-
state: The name of the enclosing state.
|
|
2358
|
-
imports: Imports needed to render this var.
|
|
2359
|
-
hooks: Hooks that need to be present in the component to render this var.
|
|
2360
|
-
"""
|
|
2361
|
-
immutable_imports: ImmutableParsedImportDict = tuple(
|
|
2362
|
-
sorted(
|
|
2363
|
-
((k, tuple(sorted(v))) for k, v in parse_imports(imports or {}).items())
|
|
2364
|
-
)
|
|
2365
|
-
)
|
|
2366
|
-
object.__setattr__(self, "state", state)
|
|
2367
|
-
object.__setattr__(self, "imports", immutable_imports)
|
|
2368
|
-
object.__setattr__(self, "hooks", tuple(hooks or {}))
|
|
2369
|
-
|
|
2370
|
-
def old_school_imports(self) -> ImportDict:
|
|
2371
|
-
"""Return the imports as a mutable dict.
|
|
2372
|
-
|
|
2373
|
-
Returns:
|
|
2374
|
-
The imports as a mutable dict.
|
|
2375
|
-
"""
|
|
2376
|
-
return dict((k, list(v)) for k, v in self.imports)
|
|
2377
|
-
|
|
2378
|
-
@classmethod
|
|
2379
|
-
def merge(cls, *others: VarData | None) -> VarData | None:
|
|
2380
|
-
"""Merge multiple var data objects.
|
|
2381
|
-
|
|
2382
|
-
Args:
|
|
2383
|
-
*others: The var data objects to merge.
|
|
2384
|
-
|
|
2385
|
-
Returns:
|
|
2386
|
-
The merged var data object.
|
|
2387
|
-
"""
|
|
2388
|
-
state = ""
|
|
2389
|
-
_imports = {}
|
|
2390
|
-
hooks = {}
|
|
2391
|
-
for var_data in others:
|
|
2392
|
-
if var_data is None:
|
|
2393
|
-
continue
|
|
2394
|
-
state = state or var_data.state
|
|
2395
|
-
_imports = imports.merge_imports(_imports, var_data.imports)
|
|
2396
|
-
hooks.update(
|
|
2397
|
-
var_data.hooks
|
|
2398
|
-
if isinstance(var_data.hooks, dict)
|
|
2399
|
-
else {k: None for k in var_data.hooks}
|
|
2400
|
-
)
|
|
2401
|
-
|
|
2402
|
-
if state or _imports or hooks:
|
|
2403
|
-
return VarData(
|
|
2404
|
-
state=state,
|
|
2405
|
-
imports=_imports,
|
|
2406
|
-
hooks=hooks,
|
|
2407
|
-
)
|
|
2408
|
-
return None
|
|
2409
|
-
|
|
2410
|
-
def __bool__(self) -> bool:
|
|
2411
|
-
"""Check if the var data is non-empty.
|
|
2412
|
-
|
|
2413
|
-
Returns:
|
|
2414
|
-
True if any field is set to a non-default value.
|
|
2415
|
-
"""
|
|
2416
|
-
return bool(self.state or self.imports or self.hooks)
|
|
2417
|
-
|
|
2418
|
-
def __eq__(self, other: Any) -> bool:
|
|
2419
|
-
"""Check if two var data objects are equal.
|
|
2420
|
-
|
|
2421
|
-
Args:
|
|
2422
|
-
other: The other var data object to compare.
|
|
2423
|
-
|
|
2424
|
-
Returns:
|
|
2425
|
-
True if all fields are equal and collapsed imports are equal.
|
|
2426
|
-
"""
|
|
2427
|
-
if not isinstance(other, VarData):
|
|
2428
|
-
return False
|
|
2429
|
-
|
|
2430
|
-
# Don't compare interpolations - that's added in by the decoder, and
|
|
2431
|
-
# not part of the vardata itself.
|
|
2432
|
-
return (
|
|
2433
|
-
self.state == other.state
|
|
2434
|
-
and self.hooks
|
|
2435
|
-
== (
|
|
2436
|
-
other.hooks if isinstance(other, VarData) else tuple(other.hooks.keys())
|
|
2437
|
-
)
|
|
2438
|
-
and imports.collapse_imports(self.imports)
|
|
2439
|
-
== imports.collapse_imports(other.imports)
|
|
2440
|
-
)
|
|
2441
|
-
|
|
2442
|
-
@classmethod
|
|
2443
|
-
def from_state(cls, state: Type[BaseState] | str) -> VarData:
|
|
2444
|
-
"""Set the state of the var.
|
|
2445
|
-
|
|
2446
|
-
Args:
|
|
2447
|
-
state: The state to set or the full name of the state.
|
|
2448
|
-
|
|
2449
|
-
Returns:
|
|
2450
|
-
The var with the set state.
|
|
2451
|
-
"""
|
|
2452
|
-
from reflex.utils import format
|
|
2453
|
-
|
|
2454
|
-
state_name = state if isinstance(state, str) else state.get_full_name()
|
|
2455
|
-
new_var_data = VarData(
|
|
2456
|
-
state=state_name,
|
|
2457
|
-
hooks={
|
|
2458
|
-
"const {0} = useContext(StateContexts.{0})".format(
|
|
2459
|
-
format.format_state_name(state_name)
|
|
2460
|
-
): None
|
|
2461
|
-
},
|
|
2462
|
-
imports={
|
|
2463
|
-
f"/{constants.Dirs.CONTEXTS_PATH}": [ImportVar(tag="StateContexts")],
|
|
2464
|
-
"react": [ImportVar(tag="useContext")],
|
|
2465
|
-
},
|
|
2466
|
-
)
|
|
2467
|
-
return new_var_data
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
def _decode_var_immutable(value: str) -> tuple[VarData | None, str]:
|
|
2471
|
-
"""Decode the state name from a formatted var.
|
|
2472
|
-
|
|
2473
|
-
Args:
|
|
2474
|
-
value: The value to extract the state name from.
|
|
2475
|
-
|
|
2476
|
-
Returns:
|
|
2477
|
-
The extracted state name and the value without the state name.
|
|
2478
|
-
"""
|
|
2479
|
-
var_datas = []
|
|
2480
|
-
if isinstance(value, str):
|
|
2481
|
-
# fast path if there is no encoded VarData
|
|
2482
|
-
if constants.REFLEX_VAR_OPENING_TAG not in value:
|
|
2483
|
-
return None, value
|
|
2484
|
-
|
|
2485
|
-
offset = 0
|
|
2486
|
-
|
|
2487
|
-
# Find all tags.
|
|
2488
|
-
while m := _decode_var_pattern.search(value):
|
|
2489
|
-
start, end = m.span()
|
|
2490
|
-
value = value[:start] + value[end:]
|
|
2491
|
-
|
|
2492
|
-
serialized_data = m.group(1)
|
|
2493
|
-
|
|
2494
|
-
if serialized_data.isnumeric() or (
|
|
2495
|
-
serialized_data[0] == "-" and serialized_data[1:].isnumeric()
|
|
2496
|
-
):
|
|
2497
|
-
# This is a global immutable var.
|
|
2498
|
-
var = _global_vars[int(serialized_data)]
|
|
2499
|
-
var_data = var._get_all_var_data()
|
|
2500
|
-
|
|
2501
|
-
if var_data is not None:
|
|
2502
|
-
var_datas.append(var_data)
|
|
2503
|
-
offset += end - start
|
|
2504
|
-
|
|
2505
|
-
return VarData.merge(*var_datas) if var_datas else None, value
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
# Compile regex for finding reflex var tags.
|
|
2509
|
-
_decode_var_pattern_re = (
|
|
2510
|
-
rf"{constants.REFLEX_VAR_OPENING_TAG}(.*?){constants.REFLEX_VAR_CLOSING_TAG}"
|
|
2511
|
-
)
|
|
2512
|
-
_decode_var_pattern = re.compile(_decode_var_pattern_re, flags=re.DOTALL)
|
|
2513
|
-
|
|
2514
|
-
# Defined global immutable vars.
|
|
2515
|
-
_global_vars: Dict[int, Var] = {}
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
def _extract_var_data(value: Iterable) -> list[VarData | None]:
|
|
2519
|
-
"""Extract the var imports and hooks from an iterable containing a Var.
|
|
2520
|
-
|
|
2521
|
-
Args:
|
|
2522
|
-
value: The iterable to extract the VarData from
|
|
2523
|
-
|
|
2524
|
-
Returns:
|
|
2525
|
-
The extracted VarDatas.
|
|
2526
|
-
"""
|
|
2527
|
-
from reflex.style import Style
|
|
2528
|
-
from reflex.vars import Var
|
|
2529
|
-
|
|
2530
|
-
var_datas = []
|
|
2531
|
-
with contextlib.suppress(TypeError):
|
|
2532
|
-
for sub in value:
|
|
2533
|
-
if isinstance(sub, Var):
|
|
2534
|
-
var_datas.append(sub._var_data)
|
|
2535
|
-
elif not isinstance(sub, str):
|
|
2536
|
-
# Recurse into dict values.
|
|
2537
|
-
if hasattr(sub, "values") and callable(sub.values):
|
|
2538
|
-
var_datas.extend(_extract_var_data(sub.values()))
|
|
2539
|
-
# Recurse into iterable values (or dict keys).
|
|
2540
|
-
var_datas.extend(_extract_var_data(sub))
|
|
2541
|
-
|
|
2542
|
-
# Style objects should already have _var_data.
|
|
2543
|
-
if isinstance(value, Style):
|
|
2544
|
-
var_datas.append(value._var_data)
|
|
2545
|
-
else:
|
|
2546
|
-
# Recurse when value is a dict itself.
|
|
2547
|
-
values = getattr(value, "values", None)
|
|
2548
|
-
if callable(values):
|
|
2549
|
-
var_datas.extend(_extract_var_data(values()))
|
|
2550
|
-
return var_datas
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
# These names were changed in reflex 0.3.0
|
|
2554
|
-
REPLACED_NAMES = {
|
|
2555
|
-
"full_name": "_var_full_name",
|
|
2556
|
-
"name": "_js_expr",
|
|
2557
|
-
"state": "_var_data.state",
|
|
2558
|
-
"type_": "_var_type",
|
|
2559
|
-
"is_local": "_var_is_local",
|
|
2560
|
-
"is_string": "_var_is_string",
|
|
2561
|
-
"set_state": "_var_set_state",
|
|
2562
|
-
"deps": "_deps",
|
|
2563
|
-
}
|