reflex 0.6.2a2__py3-none-any.whl → 0.6.3__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/__init__.py +3 -2
- reflex/__init__.pyi +3 -1
- reflex/components/base/app_wrap.pyi +17 -37
- reflex/components/base/body.pyi +17 -37
- reflex/components/base/document.pyi +77 -177
- reflex/components/base/error_boundary.pyi +18 -38
- reflex/components/base/fragment.pyi +17 -37
- reflex/components/base/head.pyi +32 -72
- reflex/components/base/link.pyi +32 -72
- reflex/components/base/meta.pyi +62 -142
- reflex/components/base/script.py +4 -4
- reflex/components/base/script.pyi +20 -40
- reflex/components/component.py +30 -19
- reflex/components/core/banner.pyi +77 -177
- reflex/components/core/client_side_routing.pyi +32 -72
- reflex/components/core/clipboard.py +3 -3
- reflex/components/core/clipboard.pyi +18 -38
- reflex/components/core/debounce.py +2 -2
- reflex/components/core/debounce.pyi +18 -38
- reflex/components/core/html.pyi +17 -37
- reflex/components/core/upload.py +4 -4
- reflex/components/core/upload.pyi +65 -145
- reflex/components/datadisplay/code.pyi +32 -72
- reflex/components/datadisplay/dataeditor.py +13 -13
- reflex/components/datadisplay/dataeditor.pyi +33 -83
- reflex/components/dynamic.py +6 -7
- reflex/components/el/__init__.pyi +1 -0
- reflex/components/el/element.pyi +17 -37
- reflex/components/el/elements/base.pyi +17 -37
- reflex/components/el/elements/forms.py +29 -14
- reflex/components/el/elements/forms.pyi +222 -504
- reflex/components/el/elements/inline.pyi +422 -982
- reflex/components/el/elements/media.pyi +377 -877
- reflex/components/el/elements/metadata.pyi +92 -212
- reflex/components/el/elements/other.pyi +107 -247
- reflex/components/el/elements/scripts.pyi +47 -107
- reflex/components/el/elements/sectioning.pyi +227 -527
- reflex/components/el/elements/tables.pyi +152 -352
- reflex/components/el/elements/typography.pyi +227 -527
- reflex/components/gridjs/datatable.py +2 -2
- reflex/components/gridjs/datatable.pyi +32 -72
- reflex/components/lucide/icon.pyi +32 -72
- reflex/components/markdown/markdown.pyi +16 -36
- reflex/components/moment/moment.py +2 -2
- reflex/components/moment/moment.pyi +18 -38
- reflex/components/next/base.pyi +17 -37
- reflex/components/next/image.py +3 -3
- reflex/components/next/image.pyi +19 -39
- reflex/components/next/link.pyi +17 -37
- reflex/components/next/video.pyi +17 -37
- reflex/components/plotly/plotly.py +1 -1
- reflex/components/plotly/plotly.pyi +35 -87
- reflex/components/radix/primitives/accordion.py +14 -2
- reflex/components/radix/primitives/accordion.pyi +110 -250
- reflex/components/radix/primitives/base.pyi +32 -72
- reflex/components/radix/primitives/drawer.py +30 -12
- reflex/components/radix/primitives/drawer.pyi +159 -373
- reflex/components/radix/primitives/form.py +3 -3
- reflex/components/radix/primitives/form.pyi +158 -364
- reflex/components/radix/primitives/progress.pyi +77 -177
- reflex/components/radix/primitives/slider.py +17 -3
- reflex/components/radix/primitives/slider.pyi +81 -183
- reflex/components/radix/themes/base.pyi +107 -247
- reflex/components/radix/themes/color_mode.pyi +48 -117
- reflex/components/radix/themes/components/alert_dialog.py +5 -5
- reflex/components/radix/themes/components/alert_dialog.pyi +111 -259
- reflex/components/radix/themes/components/aspect_ratio.pyi +17 -37
- reflex/components/radix/themes/components/avatar.pyi +17 -37
- reflex/components/radix/themes/components/badge.pyi +17 -37
- reflex/components/radix/themes/components/button.pyi +17 -37
- reflex/components/radix/themes/components/callout.pyi +77 -177
- reflex/components/radix/themes/components/card.pyi +17 -37
- reflex/components/radix/themes/components/checkbox.py +3 -3
- reflex/components/radix/themes/components/checkbox.pyi +50 -110
- reflex/components/radix/themes/components/checkbox_cards.pyi +32 -72
- reflex/components/radix/themes/components/checkbox_group.pyi +32 -72
- reflex/components/radix/themes/components/context_menu.py +11 -11
- reflex/components/radix/themes/components/context_menu.pyi +132 -312
- reflex/components/radix/themes/components/data_list.pyi +62 -142
- reflex/components/radix/themes/components/dialog.py +7 -7
- reflex/components/radix/themes/components/dialog.pyi +114 -268
- reflex/components/radix/themes/components/dropdown_menu.py +13 -13
- reflex/components/radix/themes/components/dropdown_menu.pyi +134 -316
- reflex/components/radix/themes/components/hover_card.py +2 -2
- reflex/components/radix/themes/components/hover_card.pyi +64 -148
- reflex/components/radix/themes/components/icon_button.pyi +17 -37
- reflex/components/radix/themes/components/inset.pyi +17 -37
- reflex/components/radix/themes/components/popover.py +8 -8
- reflex/components/radix/themes/components/popover.pyi +69 -163
- reflex/components/radix/themes/components/progress.pyi +17 -37
- reflex/components/radix/themes/components/radio.pyi +17 -37
- reflex/components/radix/themes/components/radio_cards.py +2 -2
- reflex/components/radix/themes/components/radio_cards.pyi +33 -75
- reflex/components/radix/themes/components/radio_group.py +4 -4
- reflex/components/radix/themes/components/radio_group.pyi +63 -143
- reflex/components/radix/themes/components/scroll_area.pyi +17 -37
- reflex/components/radix/themes/components/segmented_control.py +14 -2
- reflex/components/radix/themes/components/segmented_control.pyi +35 -73
- reflex/components/radix/themes/components/select.py +6 -5
- reflex/components/radix/themes/components/select.pyi +146 -338
- reflex/components/radix/themes/components/separator.pyi +17 -37
- reflex/components/radix/themes/components/skeleton.pyi +17 -37
- reflex/components/radix/themes/components/slider.py +19 -3
- reflex/components/radix/themes/components/slider.pyi +23 -41
- reflex/components/radix/themes/components/spinner.pyi +17 -37
- reflex/components/radix/themes/components/switch.py +2 -2
- reflex/components/radix/themes/components/switch.pyi +18 -38
- reflex/components/radix/themes/components/table.pyi +107 -247
- reflex/components/radix/themes/components/tabs.py +2 -2
- reflex/components/radix/themes/components/tabs.pyi +79 -179
- reflex/components/radix/themes/components/text_area.py +0 -16
- reflex/components/radix/themes/components/text_area.pyi +20 -42
- reflex/components/radix/themes/components/text_field.py +6 -6
- reflex/components/radix/themes/components/text_field.pyi +53 -117
- reflex/components/radix/themes/components/tooltip.py +4 -4
- reflex/components/radix/themes/components/tooltip.pyi +20 -46
- reflex/components/radix/themes/layout/base.pyi +17 -37
- reflex/components/radix/themes/layout/box.pyi +17 -37
- reflex/components/radix/themes/layout/center.pyi +17 -37
- reflex/components/radix/themes/layout/container.pyi +17 -37
- reflex/components/radix/themes/layout/flex.pyi +17 -37
- reflex/components/radix/themes/layout/grid.pyi +17 -37
- reflex/components/radix/themes/layout/list.pyi +77 -177
- reflex/components/radix/themes/layout/section.pyi +17 -37
- reflex/components/radix/themes/layout/spacer.pyi +17 -37
- reflex/components/radix/themes/layout/stack.pyi +47 -107
- reflex/components/radix/themes/typography/blockquote.pyi +17 -37
- reflex/components/radix/themes/typography/code.pyi +17 -37
- reflex/components/radix/themes/typography/heading.pyi +17 -37
- reflex/components/radix/themes/typography/link.pyi +17 -37
- reflex/components/radix/themes/typography/text.pyi +107 -247
- reflex/components/react_player/audio.pyi +33 -69
- reflex/components/react_player/react_player.py +17 -17
- reflex/components/react_player/react_player.pyi +33 -69
- reflex/components/react_player/video.pyi +33 -69
- reflex/components/recharts/cartesian.py +216 -186
- reflex/components/recharts/cartesian.pyi +623 -832
- reflex/components/recharts/charts.py +68 -65
- reflex/components/recharts/charts.pyi +213 -433
- reflex/components/recharts/general.py +27 -21
- reflex/components/recharts/general.pyi +94 -189
- reflex/components/recharts/polar.py +135 -97
- reflex/components/recharts/polar.pyi +219 -229
- reflex/components/recharts/recharts.py +5 -1
- reflex/components/recharts/recharts.pyi +37 -73
- reflex/components/sonner/toast.py +1 -1
- reflex/components/sonner/toast.pyi +17 -37
- reflex/components/suneditor/editor.pyi +26 -52
- reflex/components/tags/iter_tag.py +2 -2
- reflex/config.py +16 -0
- reflex/constants/__init__.py +2 -0
- reflex/constants/compiler.py +25 -0
- reflex/constants/installer.py +17 -16
- reflex/constants/state.py +11 -0
- reflex/constants/style.py +1 -1
- reflex/custom_components/custom_components.py +1 -1
- reflex/event.py +337 -84
- reflex/experimental/layout.pyi +78 -180
- reflex/istate/dynamic.py +3 -0
- reflex/state.py +197 -118
- reflex/style.py +5 -0
- reflex/testing.py +8 -5
- reflex/utils/compat.py +1 -3
- reflex/utils/exceptions.py +8 -0
- reflex/utils/path_ops.py +2 -2
- reflex/utils/prerequisites.py +2 -2
- reflex/utils/pyi_generator.py +44 -4
- reflex/utils/registry.py +17 -3
- reflex/utils/telemetry.py +1 -3
- reflex/utils/types.py +60 -16
- reflex/vars/__init__.py +2 -0
- reflex/vars/base.py +127 -72
- reflex/vars/object.py +5 -1
- reflex/vars/sequence.py +15 -3
- {reflex-0.6.2a2.dist-info → reflex-0.6.3.dist-info}/METADATA +3 -3
- {reflex-0.6.2a2.dist-info → reflex-0.6.3.dist-info}/RECORD +179 -177
- {reflex-0.6.2a2.dist-info → reflex-0.6.3.dist-info}/LICENSE +0 -0
- {reflex-0.6.2a2.dist-info → reflex-0.6.3.dist-info}/WHEEL +0 -0
- {reflex-0.6.2a2.dist-info → reflex-0.6.3.dist-info}/entry_points.txt +0 -0
reflex/utils/pyi_generator.py
CHANGED
|
@@ -70,7 +70,7 @@ DEFAULT_TYPING_IMPORTS = {
|
|
|
70
70
|
DEFAULT_IMPORTS = {
|
|
71
71
|
"typing": sorted(DEFAULT_TYPING_IMPORTS),
|
|
72
72
|
"reflex.components.core.breakpoints": ["Breakpoints"],
|
|
73
|
-
"reflex.event": ["EventChain", "EventHandler", "EventSpec"],
|
|
73
|
+
"reflex.event": ["EventChain", "EventHandler", "EventSpec", "EventType"],
|
|
74
74
|
"reflex.style": ["Style"],
|
|
75
75
|
"reflex.vars.base": ["Var"],
|
|
76
76
|
}
|
|
@@ -427,18 +427,58 @@ def _generate_component_create_functiondef(
|
|
|
427
427
|
all_props = [arg[0].arg for arg in prop_kwargs]
|
|
428
428
|
kwargs.extend(prop_kwargs)
|
|
429
429
|
|
|
430
|
+
def figure_out_return_type(annotation: Any):
|
|
431
|
+
if inspect.isclass(annotation) and issubclass(annotation, inspect._empty):
|
|
432
|
+
return ast.Name(id="Optional[EventType]")
|
|
433
|
+
if isinstance(annotation, str) and annotation.startswith("Tuple["):
|
|
434
|
+
inside_of_tuple = annotation.removeprefix("Tuple[").removesuffix("]")
|
|
435
|
+
|
|
436
|
+
if inside_of_tuple == "()":
|
|
437
|
+
return ast.Name(id="Optional[EventType[[]]]")
|
|
438
|
+
|
|
439
|
+
arguments: list[str] = [""]
|
|
440
|
+
|
|
441
|
+
bracket_count = 0
|
|
442
|
+
|
|
443
|
+
for char in inside_of_tuple:
|
|
444
|
+
if char == "[":
|
|
445
|
+
bracket_count += 1
|
|
446
|
+
elif char == "]":
|
|
447
|
+
bracket_count -= 1
|
|
448
|
+
|
|
449
|
+
if char == "," and bracket_count == 0:
|
|
450
|
+
arguments.append("")
|
|
451
|
+
else:
|
|
452
|
+
arguments[-1] += char
|
|
453
|
+
|
|
454
|
+
arguments = [argument.strip() for argument in arguments]
|
|
455
|
+
|
|
456
|
+
arguments_without_var = [
|
|
457
|
+
argument.removeprefix("Var[").removesuffix("]")
|
|
458
|
+
if argument.startswith("Var[")
|
|
459
|
+
else argument
|
|
460
|
+
for argument in arguments
|
|
461
|
+
]
|
|
462
|
+
|
|
463
|
+
return ast.Name(
|
|
464
|
+
id=f"Optional[EventType[{', '.join(arguments_without_var)}]]"
|
|
465
|
+
)
|
|
466
|
+
return ast.Name(id="Optional[EventType]")
|
|
467
|
+
|
|
468
|
+
event_triggers = clz().get_event_triggers()
|
|
469
|
+
|
|
430
470
|
# event handler kwargs
|
|
431
471
|
kwargs.extend(
|
|
432
472
|
(
|
|
433
473
|
ast.arg(
|
|
434
474
|
arg=trigger,
|
|
435
|
-
annotation=
|
|
436
|
-
|
|
475
|
+
annotation=figure_out_return_type(
|
|
476
|
+
inspect.signature(event_triggers[trigger]).return_annotation
|
|
437
477
|
),
|
|
438
478
|
),
|
|
439
479
|
ast.Constant(value=None),
|
|
440
480
|
)
|
|
441
|
-
for trigger in sorted(
|
|
481
|
+
for trigger in sorted(event_triggers)
|
|
442
482
|
)
|
|
443
483
|
logger.debug(f"Generated {clz.__name__}.create method with {len(kwargs)} kwargs")
|
|
444
484
|
create_args = ast.arguments(
|
reflex/utils/registry.py
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
"""Utilities for working with registries."""
|
|
2
2
|
|
|
3
|
+
import os
|
|
4
|
+
|
|
3
5
|
import httpx
|
|
4
6
|
|
|
5
|
-
from reflex.utils import console
|
|
7
|
+
from reflex.utils import console, net
|
|
6
8
|
|
|
7
9
|
|
|
8
10
|
def latency(registry: str) -> int:
|
|
@@ -15,7 +17,7 @@ def latency(registry: str) -> int:
|
|
|
15
17
|
int: The latency of the registry in microseconds.
|
|
16
18
|
"""
|
|
17
19
|
try:
|
|
18
|
-
return
|
|
20
|
+
return net.get(registry).elapsed.microseconds
|
|
19
21
|
except httpx.HTTPError:
|
|
20
22
|
console.info(f"Failed to connect to {registry}.")
|
|
21
23
|
return 10_000_000
|
|
@@ -34,7 +36,7 @@ def average_latency(registry, attempts: int = 3) -> int:
|
|
|
34
36
|
return sum(latency(registry) for _ in range(attempts)) // attempts
|
|
35
37
|
|
|
36
38
|
|
|
37
|
-
def
|
|
39
|
+
def get_best_registry() -> str:
|
|
38
40
|
"""Get the best registry based on latency.
|
|
39
41
|
|
|
40
42
|
Returns:
|
|
@@ -46,3 +48,15 @@ def _get_best_registry() -> str:
|
|
|
46
48
|
]
|
|
47
49
|
|
|
48
50
|
return min(registries, key=average_latency)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _get_npm_registry() -> str:
|
|
54
|
+
"""Get npm registry. If environment variable is set, use it first.
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
str:
|
|
58
|
+
"""
|
|
59
|
+
if npm_registry := os.environ.get("NPM_CONFIG_REGISTRY", ""):
|
|
60
|
+
return npm_registry
|
|
61
|
+
else:
|
|
62
|
+
return get_best_registry()
|
reflex/utils/telemetry.py
CHANGED
|
@@ -94,9 +94,7 @@ def _raise_on_missing_project_hash() -> bool:
|
|
|
94
94
|
False when compilation should be skipped (i.e. no .web directory is required).
|
|
95
95
|
Otherwise return True.
|
|
96
96
|
"""
|
|
97
|
-
|
|
98
|
-
return False
|
|
99
|
-
return True
|
|
97
|
+
return not should_skip_compile()
|
|
100
98
|
|
|
101
99
|
|
|
102
100
|
def _prepare_event(event: str, **kwargs) -> dict:
|
reflex/utils/types.py
CHANGED
|
@@ -18,6 +18,7 @@ from typing import (
|
|
|
18
18
|
List,
|
|
19
19
|
Literal,
|
|
20
20
|
Optional,
|
|
21
|
+
Sequence,
|
|
21
22
|
Tuple,
|
|
22
23
|
Type,
|
|
23
24
|
Union,
|
|
@@ -102,14 +103,14 @@ if TYPE_CHECKING:
|
|
|
102
103
|
|
|
103
104
|
# ArgsSpec = Callable[[Var], list[Var]]
|
|
104
105
|
ArgsSpec = (
|
|
105
|
-
Callable[[],
|
|
106
|
-
| Callable[[Var],
|
|
107
|
-
| Callable[[Var, Var],
|
|
108
|
-
| Callable[[Var, Var, Var],
|
|
109
|
-
| Callable[[Var, Var, Var, Var],
|
|
110
|
-
| Callable[[Var, Var, Var, Var, Var],
|
|
111
|
-
| Callable[[Var, Var, Var, Var, Var, Var],
|
|
112
|
-
| Callable[[Var, Var, Var, Var, Var, Var, Var],
|
|
106
|
+
Callable[[], Sequence[Var]]
|
|
107
|
+
| Callable[[Var], Sequence[Var]]
|
|
108
|
+
| Callable[[Var, Var], Sequence[Var]]
|
|
109
|
+
| Callable[[Var, Var, Var], Sequence[Var]]
|
|
110
|
+
| Callable[[Var, Var, Var, Var], Sequence[Var]]
|
|
111
|
+
| Callable[[Var, Var, Var, Var, Var], Sequence[Var]]
|
|
112
|
+
| Callable[[Var, Var, Var, Var, Var, Var], Sequence[Var]]
|
|
113
|
+
| Callable[[Var, Var, Var, Var, Var, Var, Var], Sequence[Var]]
|
|
113
114
|
)
|
|
114
115
|
else:
|
|
115
116
|
ArgsSpec = Callable[..., List[Any]]
|
|
@@ -182,6 +183,26 @@ def is_generic_alias(cls: GenericType) -> bool:
|
|
|
182
183
|
return isinstance(cls, GenericAliasTypes)
|
|
183
184
|
|
|
184
185
|
|
|
186
|
+
def unionize(*args: GenericType) -> Type:
|
|
187
|
+
"""Unionize the types.
|
|
188
|
+
|
|
189
|
+
Args:
|
|
190
|
+
args: The types to unionize.
|
|
191
|
+
|
|
192
|
+
Returns:
|
|
193
|
+
The unionized types.
|
|
194
|
+
"""
|
|
195
|
+
if not args:
|
|
196
|
+
return Any
|
|
197
|
+
if len(args) == 1:
|
|
198
|
+
return args[0]
|
|
199
|
+
# We are bisecting the args list here to avoid hitting the recursion limit
|
|
200
|
+
# In Python versions >= 3.11, we can simply do `return Union[*args]`
|
|
201
|
+
midpoint = len(args) // 2
|
|
202
|
+
first_half, second_half = args[:midpoint], args[midpoint:]
|
|
203
|
+
return Union[unionize(*first_half), unionize(*second_half)]
|
|
204
|
+
|
|
205
|
+
|
|
185
206
|
def is_none(cls: GenericType) -> bool:
|
|
186
207
|
"""Check if a class is None.
|
|
187
208
|
|
|
@@ -220,6 +241,27 @@ def is_literal(cls: GenericType) -> bool:
|
|
|
220
241
|
return get_origin(cls) is Literal
|
|
221
242
|
|
|
222
243
|
|
|
244
|
+
def has_args(cls) -> bool:
|
|
245
|
+
"""Check if the class has generic parameters.
|
|
246
|
+
|
|
247
|
+
Args:
|
|
248
|
+
cls: The class to check.
|
|
249
|
+
|
|
250
|
+
Returns:
|
|
251
|
+
Whether the class has generic
|
|
252
|
+
"""
|
|
253
|
+
if get_args(cls):
|
|
254
|
+
return True
|
|
255
|
+
|
|
256
|
+
# Check if the class inherits from a generic class (using __orig_bases__)
|
|
257
|
+
if hasattr(cls, "__orig_bases__"):
|
|
258
|
+
for base in cls.__orig_bases__:
|
|
259
|
+
if get_args(base):
|
|
260
|
+
return True
|
|
261
|
+
|
|
262
|
+
return False
|
|
263
|
+
|
|
264
|
+
|
|
223
265
|
def is_optional(cls: GenericType) -> bool:
|
|
224
266
|
"""Check if a class is an Optional.
|
|
225
267
|
|
|
@@ -337,11 +379,9 @@ def get_attribute_access_type(cls: GenericType, name: str) -> GenericType | None
|
|
|
337
379
|
return type_
|
|
338
380
|
elif is_union(cls):
|
|
339
381
|
# Check in each arg of the annotation.
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
# Return the first attribute type that is accessible.
|
|
344
|
-
return type_
|
|
382
|
+
return unionize(
|
|
383
|
+
*(get_attribute_access_type(arg, name) for arg in get_args(cls))
|
|
384
|
+
)
|
|
345
385
|
elif isinstance(cls, type):
|
|
346
386
|
# Bare class
|
|
347
387
|
if sys.version_info >= (3, 10):
|
|
@@ -374,7 +414,7 @@ def get_base_class(cls: GenericType) -> Type:
|
|
|
374
414
|
if is_literal(cls):
|
|
375
415
|
# only literals of the same type are supported.
|
|
376
416
|
arg_type = type(get_args(cls)[0])
|
|
377
|
-
if not all(type(arg)
|
|
417
|
+
if not all(type(arg) is arg_type for arg in get_args(cls)):
|
|
378
418
|
raise TypeError("only literals of the same type are supported")
|
|
379
419
|
return type(get_args(cls)[0])
|
|
380
420
|
|
|
@@ -525,7 +565,11 @@ def is_backend_base_variable(name: str, cls: Type) -> bool:
|
|
|
525
565
|
if name.startswith(f"_{cls.__name__}__"):
|
|
526
566
|
return False
|
|
527
567
|
|
|
528
|
-
|
|
568
|
+
# Extract the namespace of the original module if defined (dynamic substates).
|
|
569
|
+
if callable(getattr(cls, "_get_type_hints", None)):
|
|
570
|
+
hints = cls._get_type_hints()
|
|
571
|
+
else:
|
|
572
|
+
hints = get_type_hints(cls)
|
|
529
573
|
if name in hints:
|
|
530
574
|
hint = get_origin(hints[name])
|
|
531
575
|
if hint == ClassVar:
|
|
@@ -538,7 +582,7 @@ def is_backend_base_variable(name: str, cls: Type) -> bool:
|
|
|
538
582
|
|
|
539
583
|
if name in cls.__dict__:
|
|
540
584
|
value = cls.__dict__[name]
|
|
541
|
-
if type(value)
|
|
585
|
+
if type(value) is classmethod:
|
|
542
586
|
return False
|
|
543
587
|
if callable(value):
|
|
544
588
|
return False
|
reflex/vars/__init__.py
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
"""Immutable-Based Var System."""
|
|
2
2
|
|
|
3
|
+
from .base import Field as Field
|
|
3
4
|
from .base import LiteralVar as LiteralVar
|
|
4
5
|
from .base import Var as Var
|
|
5
6
|
from .base import VarData as VarData
|
|
7
|
+
from .base import field as field
|
|
6
8
|
from .base import get_unique_variable_name as get_unique_variable_name
|
|
7
9
|
from .base import get_uuid_string_var as get_uuid_string_var
|
|
8
10
|
from .base import var_operation as var_operation
|
reflex/vars/base.py
CHANGED
|
@@ -56,7 +56,7 @@ from reflex.utils.imports import (
|
|
|
56
56
|
ParsedImportDict,
|
|
57
57
|
parse_imports,
|
|
58
58
|
)
|
|
59
|
-
from reflex.utils.types import GenericType, Self, get_origin
|
|
59
|
+
from reflex.utils.types import GenericType, Self, get_origin, has_args, unionize
|
|
60
60
|
|
|
61
61
|
if TYPE_CHECKING:
|
|
62
62
|
from reflex.state import BaseState
|
|
@@ -239,7 +239,7 @@ class Var(Generic[VAR_TYPE]):
|
|
|
239
239
|
**kwargs,
|
|
240
240
|
)
|
|
241
241
|
|
|
242
|
-
if (js_expr := kwargs.get("_js_expr"
|
|
242
|
+
if (js_expr := kwargs.get("_js_expr")) is not None:
|
|
243
243
|
object.__setattr__(value_with_replaced, "_js_expr", js_expr)
|
|
244
244
|
|
|
245
245
|
return value_with_replaced
|
|
@@ -429,71 +429,75 @@ class Var(Generic[VAR_TYPE]):
|
|
|
429
429
|
return self.to(EventVar, output)
|
|
430
430
|
if fixed_output_type is EventChain:
|
|
431
431
|
return self.to(EventChainVar, output)
|
|
432
|
-
|
|
433
|
-
|
|
432
|
+
try:
|
|
433
|
+
if issubclass(fixed_output_type, Base):
|
|
434
|
+
return self.to(ObjectVar, output)
|
|
435
|
+
except TypeError:
|
|
436
|
+
pass
|
|
434
437
|
if dataclasses.is_dataclass(fixed_output_type) and not issubclass(
|
|
435
438
|
fixed_output_type, Var
|
|
436
439
|
):
|
|
437
440
|
return self.to(ObjectVar, output)
|
|
438
441
|
|
|
439
|
-
if
|
|
440
|
-
|
|
442
|
+
if inspect.isclass(output):
|
|
443
|
+
if issubclass(output, BooleanVar):
|
|
444
|
+
return ToBooleanVarOperation.create(self)
|
|
445
|
+
|
|
446
|
+
if issubclass(output, NumberVar):
|
|
447
|
+
if fixed_type is not None:
|
|
448
|
+
if fixed_type in types.UnionTypes:
|
|
449
|
+
inner_types = get_args(base_type)
|
|
450
|
+
if not all(issubclass(t, (int, float)) for t in inner_types):
|
|
451
|
+
raise TypeError(
|
|
452
|
+
f"Unsupported type {var_type} for NumberVar. Must be int or float."
|
|
453
|
+
)
|
|
441
454
|
|
|
442
|
-
|
|
443
|
-
if fixed_type is not None:
|
|
444
|
-
if fixed_type is Union:
|
|
445
|
-
inner_types = get_args(base_type)
|
|
446
|
-
if not all(issubclass(t, (int, float)) for t in inner_types):
|
|
455
|
+
elif not issubclass(fixed_type, (int, float)):
|
|
447
456
|
raise TypeError(
|
|
448
457
|
f"Unsupported type {var_type} for NumberVar. Must be int or float."
|
|
449
458
|
)
|
|
459
|
+
return ToNumberVarOperation.create(self, var_type or float)
|
|
450
460
|
|
|
451
|
-
|
|
461
|
+
if issubclass(output, ArrayVar):
|
|
462
|
+
if fixed_type is not None and not issubclass(
|
|
463
|
+
fixed_type, (list, tuple, set)
|
|
464
|
+
):
|
|
452
465
|
raise TypeError(
|
|
453
|
-
f"Unsupported type {var_type} for
|
|
466
|
+
f"Unsupported type {var_type} for ArrayVar. Must be list, tuple, or set."
|
|
454
467
|
)
|
|
455
|
-
|
|
468
|
+
return ToArrayOperation.create(self, var_type or list)
|
|
456
469
|
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
fixed_type, (list, tuple, set)
|
|
460
|
-
):
|
|
461
|
-
raise TypeError(
|
|
462
|
-
f"Unsupported type {var_type} for ArrayVar. Must be list, tuple, or set."
|
|
463
|
-
)
|
|
464
|
-
return ToArrayOperation.create(self, var_type or list)
|
|
470
|
+
if issubclass(output, StringVar):
|
|
471
|
+
return ToStringOperation.create(self, var_type or str)
|
|
465
472
|
|
|
466
|
-
|
|
467
|
-
|
|
473
|
+
if issubclass(output, EventVar):
|
|
474
|
+
return ToEventVarOperation.create(self, var_type or EventSpec)
|
|
468
475
|
|
|
469
|
-
|
|
470
|
-
|
|
476
|
+
if issubclass(output, EventChainVar):
|
|
477
|
+
return ToEventChainVarOperation.create(self, var_type or EventChain)
|
|
471
478
|
|
|
472
|
-
|
|
473
|
-
|
|
479
|
+
if issubclass(output, (ObjectVar, Base)):
|
|
480
|
+
return ToObjectOperation.create(self, var_type or dict)
|
|
474
481
|
|
|
475
|
-
|
|
476
|
-
|
|
482
|
+
if issubclass(output, FunctionVar):
|
|
483
|
+
# if fixed_type is not None and not issubclass(fixed_type, Callable):
|
|
484
|
+
# raise TypeError(
|
|
485
|
+
# f"Unsupported type {var_type} for FunctionVar. Must be Callable."
|
|
486
|
+
# )
|
|
487
|
+
return ToFunctionOperation.create(self, var_type or Callable)
|
|
477
488
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
# raise TypeError(
|
|
481
|
-
# f"Unsupported type {var_type} for FunctionVar. Must be Callable."
|
|
482
|
-
# )
|
|
483
|
-
return ToFunctionOperation.create(self, var_type or Callable)
|
|
484
|
-
|
|
485
|
-
if issubclass(output, NoneVar):
|
|
486
|
-
return ToNoneOperation.create(self)
|
|
489
|
+
if issubclass(output, NoneVar):
|
|
490
|
+
return ToNoneOperation.create(self)
|
|
487
491
|
|
|
488
|
-
|
|
489
|
-
|
|
492
|
+
if dataclasses.is_dataclass(output):
|
|
493
|
+
return ToObjectOperation.create(self, var_type or dict)
|
|
490
494
|
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
495
|
+
# If we can't determine the first argument, we just replace the _var_type.
|
|
496
|
+
if not issubclass(output, Var) or var_type is None:
|
|
497
|
+
return dataclasses.replace(
|
|
498
|
+
self,
|
|
499
|
+
_var_type=output,
|
|
500
|
+
)
|
|
497
501
|
|
|
498
502
|
# We couldn't determine the output type to be any other Var type, so we replace the _var_type.
|
|
499
503
|
if var_type is not None:
|
|
@@ -530,7 +534,7 @@ class Var(Generic[VAR_TYPE]):
|
|
|
530
534
|
|
|
531
535
|
fixed_type = get_origin(var_type) or var_type
|
|
532
536
|
|
|
533
|
-
if fixed_type
|
|
537
|
+
if fixed_type in types.UnionTypes:
|
|
534
538
|
inner_types = get_args(var_type)
|
|
535
539
|
|
|
536
540
|
if all(
|
|
@@ -568,8 +572,11 @@ class Var(Generic[VAR_TYPE]):
|
|
|
568
572
|
return self.to(EventVar, self._var_type)
|
|
569
573
|
if issubclass(fixed_type, EventChain):
|
|
570
574
|
return self.to(EventChainVar, self._var_type)
|
|
571
|
-
|
|
572
|
-
|
|
575
|
+
try:
|
|
576
|
+
if issubclass(fixed_type, Base):
|
|
577
|
+
return self.to(ObjectVar, self._var_type)
|
|
578
|
+
except TypeError:
|
|
579
|
+
pass
|
|
573
580
|
if dataclasses.is_dataclass(fixed_type):
|
|
574
581
|
return self.to(ObjectVar, self._var_type)
|
|
575
582
|
return self
|
|
@@ -1237,26 +1244,6 @@ def var_operation(
|
|
|
1237
1244
|
return wrapper
|
|
1238
1245
|
|
|
1239
1246
|
|
|
1240
|
-
def unionize(*args: Type) -> Type:
|
|
1241
|
-
"""Unionize the types.
|
|
1242
|
-
|
|
1243
|
-
Args:
|
|
1244
|
-
args: The types to unionize.
|
|
1245
|
-
|
|
1246
|
-
Returns:
|
|
1247
|
-
The unionized types.
|
|
1248
|
-
"""
|
|
1249
|
-
if not args:
|
|
1250
|
-
return Any
|
|
1251
|
-
if len(args) == 1:
|
|
1252
|
-
return args[0]
|
|
1253
|
-
# We are bisecting the args list here to avoid hitting the recursion limit
|
|
1254
|
-
# In Python versions >= 3.11, we can simply do `return Union[*args]`
|
|
1255
|
-
midpoint = len(args) // 2
|
|
1256
|
-
first_half, second_half = args[:midpoint], args[midpoint:]
|
|
1257
|
-
return Union[unionize(*first_half), unionize(*second_half)]
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
1247
|
def figure_out_type(value: Any) -> types.GenericType:
|
|
1261
1248
|
"""Figure out the type of the value.
|
|
1262
1249
|
|
|
@@ -1266,6 +1253,11 @@ def figure_out_type(value: Any) -> types.GenericType:
|
|
|
1266
1253
|
Returns:
|
|
1267
1254
|
The type of the value.
|
|
1268
1255
|
"""
|
|
1256
|
+
if isinstance(value, Var):
|
|
1257
|
+
return value._var_type
|
|
1258
|
+
type_ = type(value)
|
|
1259
|
+
if has_args(type_):
|
|
1260
|
+
return type_
|
|
1269
1261
|
if isinstance(value, list):
|
|
1270
1262
|
return List[unionize(*(figure_out_type(v) for v in value))]
|
|
1271
1263
|
if isinstance(value, set):
|
|
@@ -1277,8 +1269,6 @@ def figure_out_type(value: Any) -> types.GenericType:
|
|
|
1277
1269
|
unionize(*(figure_out_type(k) for k in value)),
|
|
1278
1270
|
unionize(*(figure_out_type(v) for v in value.values())),
|
|
1279
1271
|
]
|
|
1280
|
-
if isinstance(value, Var):
|
|
1281
|
-
return value._var_type
|
|
1282
1272
|
return type(value)
|
|
1283
1273
|
|
|
1284
1274
|
|
|
@@ -2832,3 +2822,68 @@ def dispatch(
|
|
|
2832
2822
|
_var_data=var_data,
|
|
2833
2823
|
_var_type=result_var_type,
|
|
2834
2824
|
).guess_type()
|
|
2825
|
+
|
|
2826
|
+
|
|
2827
|
+
V = TypeVar("V")
|
|
2828
|
+
|
|
2829
|
+
|
|
2830
|
+
class Field(Generic[T]):
|
|
2831
|
+
"""Shadow class for Var to allow for type hinting in the IDE."""
|
|
2832
|
+
|
|
2833
|
+
def __set__(self, instance, value: T):
|
|
2834
|
+
"""Set the Var.
|
|
2835
|
+
|
|
2836
|
+
Args:
|
|
2837
|
+
instance: The instance of the class setting the Var.
|
|
2838
|
+
value: The value to set the Var to.
|
|
2839
|
+
"""
|
|
2840
|
+
|
|
2841
|
+
@overload
|
|
2842
|
+
def __get__(self: Field[bool], instance: None, owner) -> BooleanVar: ...
|
|
2843
|
+
|
|
2844
|
+
@overload
|
|
2845
|
+
def __get__(self: Field[int], instance: None, owner) -> NumberVar: ...
|
|
2846
|
+
|
|
2847
|
+
@overload
|
|
2848
|
+
def __get__(self: Field[str], instance: None, owner) -> StringVar: ...
|
|
2849
|
+
|
|
2850
|
+
@overload
|
|
2851
|
+
def __get__(self: Field[None], instance: None, owner) -> NoneVar: ...
|
|
2852
|
+
|
|
2853
|
+
@overload
|
|
2854
|
+
def __get__(
|
|
2855
|
+
self: Field[List[V]] | Field[Set[V]] | Field[Tuple[V, ...]],
|
|
2856
|
+
instance: None,
|
|
2857
|
+
owner,
|
|
2858
|
+
) -> ArrayVar[List[V]]: ...
|
|
2859
|
+
|
|
2860
|
+
@overload
|
|
2861
|
+
def __get__(
|
|
2862
|
+
self: Field[Dict[str, V]], instance: None, owner
|
|
2863
|
+
) -> ObjectVar[Dict[str, V]]: ...
|
|
2864
|
+
|
|
2865
|
+
@overload
|
|
2866
|
+
def __get__(self, instance: None, owner) -> Var[T]: ...
|
|
2867
|
+
|
|
2868
|
+
@overload
|
|
2869
|
+
def __get__(self, instance, owner) -> T: ...
|
|
2870
|
+
|
|
2871
|
+
def __get__(self, instance, owner): # type: ignore
|
|
2872
|
+
"""Get the Var.
|
|
2873
|
+
|
|
2874
|
+
Args:
|
|
2875
|
+
instance: The instance of the class accessing the Var.
|
|
2876
|
+
owner: The class that the Var is attached to.
|
|
2877
|
+
"""
|
|
2878
|
+
|
|
2879
|
+
|
|
2880
|
+
def field(value: T) -> Field[T]:
|
|
2881
|
+
"""Create a Field with a value.
|
|
2882
|
+
|
|
2883
|
+
Args:
|
|
2884
|
+
value: The value of the Field.
|
|
2885
|
+
|
|
2886
|
+
Returns:
|
|
2887
|
+
The Field.
|
|
2888
|
+
"""
|
|
2889
|
+
return value # type: ignore
|
reflex/vars/object.py
CHANGED
|
@@ -119,6 +119,8 @@ class ObjectVar(Var[OBJECT_TYPE]):
|
|
|
119
119
|
"""
|
|
120
120
|
return object_entries_operation(self)
|
|
121
121
|
|
|
122
|
+
items = entries
|
|
123
|
+
|
|
122
124
|
def merge(self, other: ObjectVar):
|
|
123
125
|
"""Merge two objects.
|
|
124
126
|
|
|
@@ -260,7 +262,9 @@ class ObjectVar(Var[OBJECT_TYPE]):
|
|
|
260
262
|
var_type = get_args(var_type)[0]
|
|
261
263
|
|
|
262
264
|
fixed_type = var_type if isclass(var_type) else get_origin(var_type)
|
|
263
|
-
if isclass(fixed_type) and not issubclass(fixed_type, dict)
|
|
265
|
+
if (isclass(fixed_type) and not issubclass(fixed_type, dict)) or (
|
|
266
|
+
fixed_type in types.UnionTypes
|
|
267
|
+
):
|
|
264
268
|
attribute_type = get_attribute_access_type(var_type, name)
|
|
265
269
|
if attribute_type is None:
|
|
266
270
|
raise VarAttributeError(
|
reflex/vars/sequence.py
CHANGED
|
@@ -545,7 +545,7 @@ class LiteralStringVar(LiteralVar, StringVar):
|
|
|
545
545
|
def create(
|
|
546
546
|
cls,
|
|
547
547
|
value: str,
|
|
548
|
-
_var_type: GenericType | None =
|
|
548
|
+
_var_type: GenericType | None = None,
|
|
549
549
|
_var_data: VarData | None = None,
|
|
550
550
|
) -> StringVar:
|
|
551
551
|
"""Create a var from a string value.
|
|
@@ -558,6 +558,9 @@ class LiteralStringVar(LiteralVar, StringVar):
|
|
|
558
558
|
Returns:
|
|
559
559
|
The var.
|
|
560
560
|
"""
|
|
561
|
+
# Determine var type in case the value is inherited from str.
|
|
562
|
+
_var_type = _var_type or type(value) or str
|
|
563
|
+
|
|
561
564
|
if REFLEX_VAR_OPENING_TAG in value:
|
|
562
565
|
strings_and_vals: list[Var | str] = []
|
|
563
566
|
offset = 0
|
|
@@ -884,6 +887,12 @@ class ArrayVar(Var[ARRAY_VAR_TYPE]):
|
|
|
884
887
|
i: int | NumberVar,
|
|
885
888
|
) -> ArrayVar[Set[INNER_ARRAY_VAR]]: ...
|
|
886
889
|
|
|
890
|
+
@overload
|
|
891
|
+
def __getitem__(
|
|
892
|
+
self: ARRAY_VAR_OF_LIST_ELEMENT[Tuple[KEY_TYPE, VALUE_TYPE]],
|
|
893
|
+
i: int | NumberVar,
|
|
894
|
+
) -> ArrayVar[Tuple[KEY_TYPE, VALUE_TYPE]]: ...
|
|
895
|
+
|
|
887
896
|
@overload
|
|
888
897
|
def __getitem__(
|
|
889
898
|
self: ARRAY_VAR_OF_LIST_ELEMENT[Tuple[INNER_ARRAY_VAR, ...]],
|
|
@@ -1146,7 +1155,7 @@ class ArrayVar(Var[ARRAY_VAR_TYPE]):
|
|
|
1146
1155
|
function_var = ArgsFunctionOperation.create(tuple(), return_value)
|
|
1147
1156
|
else:
|
|
1148
1157
|
# generic number var
|
|
1149
|
-
number_var = Var("").to(NumberVar)
|
|
1158
|
+
number_var = Var("").to(NumberVar, int)
|
|
1150
1159
|
|
|
1151
1160
|
first_arg_type = self[number_var]._var_type
|
|
1152
1161
|
|
|
@@ -1158,7 +1167,10 @@ class ArrayVar(Var[ARRAY_VAR_TYPE]):
|
|
|
1158
1167
|
_var_type=first_arg_type,
|
|
1159
1168
|
).guess_type()
|
|
1160
1169
|
|
|
1161
|
-
function_var = ArgsFunctionOperation.create(
|
|
1170
|
+
function_var = ArgsFunctionOperation.create(
|
|
1171
|
+
(arg_name,),
|
|
1172
|
+
Var.create(fn(first_arg)),
|
|
1173
|
+
)
|
|
1162
1174
|
|
|
1163
1175
|
return map_array_operation(self, function_var)
|
|
1164
1176
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: reflex
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.3
|
|
4
4
|
Summary: Web apps in pure Python.
|
|
5
5
|
Home-page: https://reflex.dev
|
|
6
6
|
License: Apache-2.0
|
|
@@ -35,7 +35,7 @@ Requires-Dist: redis (>=4.3.5,<6.0)
|
|
|
35
35
|
Requires-Dist: reflex-chakra (>=0.6.0)
|
|
36
36
|
Requires-Dist: reflex-hosting-cli (>=0.1.2,<2.0)
|
|
37
37
|
Requires-Dist: rich (>=13.0.0,<14.0)
|
|
38
|
-
Requires-Dist: setuptools (>=
|
|
38
|
+
Requires-Dist: setuptools (>=75.0)
|
|
39
39
|
Requires-Dist: sqlmodel (>=0.0.14,<0.1)
|
|
40
40
|
Requires-Dist: starlette-admin (>=0.11.0,<1.0)
|
|
41
41
|
Requires-Dist: tomlkit (>=0.12.4,<1.0)
|
|
@@ -68,7 +68,7 @@ Description-Content-Type: text/markdown
|
|
|
68
68
|
|
|
69
69
|
---
|
|
70
70
|
|
|
71
|
-
[English](https://github.com/reflex-dev/reflex/blob/main/README.md) | [简体中文](https://github.com/reflex-dev/reflex/blob/main/docs/zh/zh_cn/README.md) | [繁體中文](https://github.com/reflex-dev/reflex/blob/main/docs/zh/zh_tw/README.md) | [Türkçe](https://github.com/reflex-dev/reflex/blob/main/docs/tr/README.md) | [हिंदी](https://github.com/reflex-dev/reflex/blob/main/docs/in/README.md) | [Português (Brasil)](https://github.com/reflex-dev/reflex/blob/main/docs/pt/pt_br/README.md) | [Italiano](https://github.com/reflex-dev/reflex/blob/main/docs/it/README.md) | [Español](https://github.com/reflex-dev/reflex/blob/main/docs/es/README.md) | [한국어](https://github.com/reflex-dev/reflex/blob/main/docs/kr/README.md) | [日本語](https://github.com/reflex-dev/reflex/blob/main/docs/ja/README.md) | [Deutsch](https://github.com/reflex-dev/reflex/blob/main/docs/de/README.md) | [Persian (پارسی)](https://github.com/reflex-dev/reflex/blob/main/docs/pe/README.md)
|
|
71
|
+
[English](https://github.com/reflex-dev/reflex/blob/main/README.md) | [简体中文](https://github.com/reflex-dev/reflex/blob/main/docs/zh/zh_cn/README.md) | [繁體中文](https://github.com/reflex-dev/reflex/blob/main/docs/zh/zh_tw/README.md) | [Türkçe](https://github.com/reflex-dev/reflex/blob/main/docs/tr/README.md) | [हिंदी](https://github.com/reflex-dev/reflex/blob/main/docs/in/README.md) | [Português (Brasil)](https://github.com/reflex-dev/reflex/blob/main/docs/pt/pt_br/README.md) | [Italiano](https://github.com/reflex-dev/reflex/blob/main/docs/it/README.md) | [Español](https://github.com/reflex-dev/reflex/blob/main/docs/es/README.md) | [한국어](https://github.com/reflex-dev/reflex/blob/main/docs/kr/README.md) | [日本語](https://github.com/reflex-dev/reflex/blob/main/docs/ja/README.md) | [Deutsch](https://github.com/reflex-dev/reflex/blob/main/docs/de/README.md) | [Persian (پارسی)](https://github.com/reflex-dev/reflex/blob/main/docs/pe/README.md) | [Tiếng Việt](https://github.com/reflex-dev/reflex/blob/main/docs/vi/README.md)
|
|
72
72
|
|
|
73
73
|
---
|
|
74
74
|
|