reflex 0.7.4a2__py3-none-any.whl → 0.7.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of reflex might be problematic. Click here for more details.
- reflex/__init__.py +1 -0
- reflex/__init__.pyi +1 -0
- reflex/app.py +10 -8
- reflex/app_mixins/middleware.py +13 -20
- reflex/compiler/compiler.py +10 -3
- reflex/compiler/utils.py +4 -4
- reflex/components/base/app_wrap.pyi +7 -3
- reflex/components/base/body.pyi +7 -3
- reflex/components/base/document.pyi +27 -7
- reflex/components/base/error_boundary.pyi +7 -3
- reflex/components/base/fragment.pyi +7 -3
- reflex/components/base/head.pyi +12 -4
- reflex/components/base/link.pyi +12 -4
- reflex/components/base/meta.pyi +22 -6
- reflex/components/base/script.pyi +7 -3
- reflex/components/base/strict_mode.pyi +7 -3
- reflex/components/component.py +64 -23
- reflex/components/core/auto_scroll.pyi +7 -3
- reflex/components/core/banner.py +6 -2
- reflex/components/core/banner.pyi +32 -8
- reflex/components/core/client_side_routing.pyi +12 -4
- reflex/components/core/clipboard.pyi +7 -3
- reflex/components/core/debounce.pyi +7 -3
- reflex/components/core/foreach.py +5 -1
- reflex/components/core/html.pyi +7 -3
- reflex/components/core/match.py +5 -5
- reflex/components/core/sticky.pyi +21 -6
- reflex/components/core/upload.pyi +27 -7
- reflex/components/datadisplay/code.pyi +12 -4
- reflex/components/datadisplay/dataeditor.py +2 -2
- reflex/components/datadisplay/dataeditor.pyi +17 -3
- reflex/components/datadisplay/shiki_code_block.pyi +17 -4
- reflex/components/el/__init__.pyi +1 -1
- reflex/components/el/element.pyi +7 -3
- reflex/components/el/elements/__init__.py +3 -1
- reflex/components/el/elements/__init__.pyi +3 -2
- reflex/components/el/elements/base.pyi +7 -3
- reflex/components/el/elements/forms.py +1 -1
- reflex/components/el/elements/forms.pyi +72 -16
- reflex/components/el/elements/inline.pyi +142 -30
- reflex/components/el/elements/media.pyi +127 -27
- reflex/components/el/elements/metadata.pyi +32 -8
- reflex/components/el/elements/other.pyi +37 -9
- reflex/components/el/elements/scripts.pyi +17 -5
- reflex/components/el/elements/sectioning.pyi +77 -17
- reflex/components/el/elements/tables.pyi +52 -12
- reflex/components/el/elements/typography.pyi +77 -17
- reflex/components/gridjs/datatable.py +2 -2
- reflex/components/gridjs/datatable.pyi +12 -4
- reflex/components/lucide/icon.py +7 -6
- reflex/components/lucide/icon.pyi +22 -7
- reflex/components/markdown/markdown.py +1 -1
- reflex/components/markdown/markdown.pyi +7 -3
- reflex/components/moment/moment.pyi +7 -3
- reflex/components/next/base.pyi +7 -3
- reflex/components/next/image.pyi +7 -3
- reflex/components/next/link.pyi +7 -3
- reflex/components/next/video.pyi +7 -3
- reflex/components/plotly/plotly.pyi +47 -11
- reflex/components/radix/primitives/accordion.pyi +37 -9
- reflex/components/radix/primitives/base.pyi +12 -4
- reflex/components/radix/primitives/drawer.pyi +57 -13
- reflex/components/radix/primitives/form.pyi +52 -12
- reflex/components/radix/primitives/progress.pyi +27 -7
- reflex/components/radix/primitives/slider.pyi +27 -7
- reflex/components/radix/themes/base.pyi +41 -10
- reflex/components/radix/themes/color_mode.py +2 -2
- reflex/components/radix/themes/color_mode.pyi +17 -5
- reflex/components/radix/themes/components/alert_dialog.pyi +36 -9
- reflex/components/radix/themes/components/aspect_ratio.pyi +7 -3
- reflex/components/radix/themes/components/avatar.pyi +6 -3
- reflex/components/radix/themes/components/badge.pyi +6 -3
- reflex/components/radix/themes/components/button.pyi +6 -3
- reflex/components/radix/themes/components/callout.pyi +26 -7
- reflex/components/radix/themes/components/card.pyi +6 -3
- reflex/components/radix/themes/components/checkbox.pyi +16 -5
- reflex/components/radix/themes/components/checkbox_cards.pyi +11 -4
- reflex/components/radix/themes/components/checkbox_group.pyi +11 -4
- reflex/components/radix/themes/components/context_menu.pyi +66 -15
- reflex/components/radix/themes/components/data_list.pyi +21 -6
- reflex/components/radix/themes/components/dialog.pyi +36 -9
- reflex/components/radix/themes/components/dropdown_menu.pyi +41 -10
- reflex/components/radix/themes/components/hover_card.pyi +21 -6
- reflex/components/radix/themes/components/icon_button.pyi +6 -3
- reflex/components/radix/themes/components/inset.pyi +6 -3
- reflex/components/radix/themes/components/popover.pyi +21 -6
- reflex/components/radix/themes/components/progress.pyi +6 -3
- reflex/components/radix/themes/components/radio.pyi +6 -3
- reflex/components/radix/themes/components/radio_cards.pyi +11 -4
- reflex/components/radix/themes/components/radio_group.py +6 -1
- reflex/components/radix/themes/components/radio_group.pyi +21 -6
- reflex/components/radix/themes/components/scroll_area.pyi +7 -3
- reflex/components/radix/themes/components/segmented_control.pyi +11 -4
- reflex/components/radix/themes/components/select.pyi +46 -11
- reflex/components/radix/themes/components/separator.pyi +6 -3
- reflex/components/radix/themes/components/skeleton.pyi +6 -3
- reflex/components/radix/themes/components/slider.pyi +6 -3
- reflex/components/radix/themes/components/spinner.pyi +6 -3
- reflex/components/radix/themes/components/switch.pyi +6 -3
- reflex/components/radix/themes/components/table.pyi +36 -9
- reflex/components/radix/themes/components/tabs.pyi +26 -7
- reflex/components/radix/themes/components/text_area.pyi +6 -3
- reflex/components/radix/themes/components/text_field.py +3 -2
- reflex/components/radix/themes/components/text_field.pyi +16 -5
- reflex/components/radix/themes/components/tooltip.pyi +7 -3
- reflex/components/radix/themes/layout/base.pyi +6 -3
- reflex/components/radix/themes/layout/box.pyi +7 -3
- reflex/components/radix/themes/layout/center.pyi +6 -3
- reflex/components/radix/themes/layout/container.pyi +6 -3
- reflex/components/radix/themes/layout/flex.pyi +6 -3
- reflex/components/radix/themes/layout/grid.pyi +6 -3
- reflex/components/radix/themes/layout/list.pyi +27 -7
- reflex/components/radix/themes/layout/section.pyi +6 -3
- reflex/components/radix/themes/layout/spacer.pyi +6 -3
- reflex/components/radix/themes/layout/stack.pyi +16 -5
- reflex/components/radix/themes/typography/blockquote.pyi +6 -3
- reflex/components/radix/themes/typography/code.pyi +6 -3
- reflex/components/radix/themes/typography/heading.pyi +6 -3
- reflex/components/radix/themes/typography/link.pyi +6 -3
- reflex/components/radix/themes/typography/text.pyi +36 -9
- reflex/components/react_player/audio.pyi +7 -3
- reflex/components/react_player/react_player.pyi +7 -3
- reflex/components/react_player/video.pyi +7 -3
- reflex/components/recharts/cartesian.pyi +97 -21
- reflex/components/recharts/charts.pyi +62 -14
- reflex/components/recharts/general.pyi +32 -8
- reflex/components/recharts/polar.py +1 -1
- reflex/components/recharts/polar.pyi +33 -9
- reflex/components/recharts/recharts.pyi +12 -4
- reflex/components/sonner/toast.pyi +7 -2
- reflex/components/suneditor/editor.pyi +7 -3
- reflex/config.py +18 -1
- reflex/constants/installer.py +22 -1
- reflex/custom_components/custom_components.py +12 -7
- reflex/event.py +26 -10
- reflex/experimental/__init__.py +17 -6
- reflex/experimental/layout.pyi +27 -7
- reflex/model.py +3 -3
- reflex/reflex.py +33 -18
- reflex/state.py +4 -4
- reflex/style.py +2 -2
- reflex/testing.py +17 -5
- reflex/utils/console.py +2 -3
- reflex/utils/exec.py +4 -0
- reflex/utils/imports.py +14 -7
- reflex/utils/net.py +107 -18
- reflex/utils/prerequisites.py +92 -13
- reflex/utils/processes.py +52 -19
- reflex/utils/pyi_generator.py +66 -53
- reflex/utils/redir.py +3 -1
- reflex/utils/registry.py +15 -5
- reflex/utils/serializers.py +1 -2
- reflex/utils/types.py +4 -4
- reflex/vars/base.py +58 -22
- reflex/vars/number.py +23 -6
- reflex/vars/sequence.py +2 -0
- {reflex-0.7.4a2.dist-info → reflex-0.7.5.dist-info}/METADATA +2 -2
- {reflex-0.7.4a2.dist-info → reflex-0.7.5.dist-info}/RECORD +162 -162
- /reflex/{experimental → utils}/misc.py +0 -0
- {reflex-0.7.4a2.dist-info → reflex-0.7.5.dist-info}/WHEEL +0 -0
- {reflex-0.7.4a2.dist-info → reflex-0.7.5.dist-info}/entry_points.txt +0 -0
- {reflex-0.7.4a2.dist-info → reflex-0.7.5.dist-info}/licenses/LICENSE +0 -0
reflex/utils/registry.py
CHANGED
|
@@ -4,6 +4,7 @@ import httpx
|
|
|
4
4
|
|
|
5
5
|
from reflex.config import environment
|
|
6
6
|
from reflex.utils import console, net
|
|
7
|
+
from reflex.utils.decorator import once
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
def latency(registry: str) -> int:
|
|
@@ -16,10 +17,13 @@ def latency(registry: str) -> int:
|
|
|
16
17
|
int: The latency of the registry in microseconds.
|
|
17
18
|
"""
|
|
18
19
|
try:
|
|
19
|
-
|
|
20
|
+
time_to_respond = net.get(registry, timeout=2).elapsed.microseconds
|
|
20
21
|
except httpx.HTTPError:
|
|
21
22
|
console.info(f"Failed to connect to {registry}.")
|
|
22
23
|
return 10_000_000
|
|
24
|
+
else:
|
|
25
|
+
console.debug(f"Latency of {registry}: {time_to_respond}")
|
|
26
|
+
return time_to_respond
|
|
23
27
|
|
|
24
28
|
|
|
25
29
|
def average_latency(registry: str, attempts: int = 3) -> int:
|
|
@@ -32,7 +36,9 @@ def average_latency(registry: str, attempts: int = 3) -> int:
|
|
|
32
36
|
Returns:
|
|
33
37
|
The average latency of the registry in microseconds.
|
|
34
38
|
"""
|
|
35
|
-
|
|
39
|
+
registry_latency = sum(latency(registry) for _ in range(attempts)) // attempts
|
|
40
|
+
console.debug(f"Average latency of {registry}: {registry_latency}")
|
|
41
|
+
return registry_latency
|
|
36
42
|
|
|
37
43
|
|
|
38
44
|
def _get_best_registry() -> str:
|
|
@@ -41,14 +47,18 @@ def _get_best_registry() -> str:
|
|
|
41
47
|
Returns:
|
|
42
48
|
The best registry.
|
|
43
49
|
"""
|
|
50
|
+
console.debug("Getting best registry...")
|
|
44
51
|
registries = [
|
|
45
|
-
"https://registry.npmjs.org",
|
|
46
|
-
"https://
|
|
52
|
+
("https://registry.npmjs.org", 1),
|
|
53
|
+
("https://registry.npmmirror.com", 2),
|
|
47
54
|
]
|
|
48
55
|
|
|
49
|
-
|
|
56
|
+
best_registry = min(registries, key=lambda x: average_latency(x[0]) * x[1])[0]
|
|
57
|
+
console.debug(f"Best registry: {best_registry}")
|
|
58
|
+
return best_registry
|
|
50
59
|
|
|
51
60
|
|
|
61
|
+
@once
|
|
52
62
|
def get_npm_registry() -> str:
|
|
53
63
|
"""Get npm registry. If environment variable is set, use it first.
|
|
54
64
|
|
reflex/utils/serializers.py
CHANGED
|
@@ -16,7 +16,6 @@ from typing import (
|
|
|
16
16
|
Callable,
|
|
17
17
|
Literal,
|
|
18
18
|
Sequence,
|
|
19
|
-
Set,
|
|
20
19
|
Type,
|
|
21
20
|
TypeVar,
|
|
22
21
|
Union,
|
|
@@ -322,7 +321,7 @@ if BaseModelV1 is not BaseModelV2:
|
|
|
322
321
|
|
|
323
322
|
|
|
324
323
|
@serializer
|
|
325
|
-
def serialize_set(value:
|
|
324
|
+
def serialize_set(value: set) -> list:
|
|
326
325
|
"""Serialize a set to a JSON serializable list.
|
|
327
326
|
|
|
328
327
|
Args:
|
reflex/utils/types.py
CHANGED
|
@@ -140,7 +140,7 @@ def is_generic_alias(cls: GenericType) -> bool:
|
|
|
140
140
|
Returns:
|
|
141
141
|
Whether the class is a generic alias.
|
|
142
142
|
"""
|
|
143
|
-
return isinstance(cls, GenericAliasTypes)
|
|
143
|
+
return isinstance(cls, GenericAliasTypes)
|
|
144
144
|
|
|
145
145
|
|
|
146
146
|
@lru_cache()
|
|
@@ -923,7 +923,7 @@ StateBases = get_base_class(StateVar)
|
|
|
923
923
|
StateIterBases = get_base_class(StateIterVar)
|
|
924
924
|
|
|
925
925
|
|
|
926
|
-
def safe_issubclass(cls:
|
|
926
|
+
def safe_issubclass(cls: Any, cls_check: Any | tuple[Any, ...]):
|
|
927
927
|
"""Check if a class is a subclass of another class. Returns False if internal error occurs.
|
|
928
928
|
|
|
929
929
|
Args:
|
|
@@ -1047,8 +1047,8 @@ def typehint_issubclass(
|
|
|
1047
1047
|
|
|
1048
1048
|
# Check if the origin of both types is the same (e.g., list for list[int])
|
|
1049
1049
|
if not safe_issubclass(
|
|
1050
|
-
provided_type_origin or possible_subclass,
|
|
1051
|
-
accepted_type_origin or possible_superclass,
|
|
1050
|
+
provided_type_origin or possible_subclass,
|
|
1051
|
+
accepted_type_origin or possible_superclass,
|
|
1052
1052
|
):
|
|
1053
1053
|
return False
|
|
1054
1054
|
|
reflex/vars/base.py
CHANGED
|
@@ -30,6 +30,7 @@ from typing import (
|
|
|
30
30
|
Mapping,
|
|
31
31
|
NoReturn,
|
|
32
32
|
ParamSpec,
|
|
33
|
+
Protocol,
|
|
33
34
|
Sequence,
|
|
34
35
|
Set,
|
|
35
36
|
Tuple,
|
|
@@ -59,10 +60,11 @@ from reflex.utils.exceptions import (
|
|
|
59
60
|
)
|
|
60
61
|
from reflex.utils.format import format_state_name
|
|
61
62
|
from reflex.utils.imports import (
|
|
63
|
+
ImmutableImportDict,
|
|
62
64
|
ImmutableParsedImportDict,
|
|
63
65
|
ImportDict,
|
|
64
66
|
ImportVar,
|
|
65
|
-
|
|
67
|
+
ParsedImportTuple,
|
|
66
68
|
parse_imports,
|
|
67
69
|
)
|
|
68
70
|
from reflex.utils.types import (
|
|
@@ -122,7 +124,7 @@ class VarData:
|
|
|
122
124
|
field_name: str = dataclasses.field(default="")
|
|
123
125
|
|
|
124
126
|
# Imports needed to render this var
|
|
125
|
-
imports:
|
|
127
|
+
imports: ParsedImportTuple = dataclasses.field(default_factory=tuple)
|
|
126
128
|
|
|
127
129
|
# Hooks that need to be present in the component to render this var
|
|
128
130
|
hooks: tuple[str, ...] = dataclasses.field(default_factory=tuple)
|
|
@@ -140,7 +142,7 @@ class VarData:
|
|
|
140
142
|
self,
|
|
141
143
|
state: str = "",
|
|
142
144
|
field_name: str = "",
|
|
143
|
-
imports:
|
|
145
|
+
imports: ImmutableImportDict | ImmutableParsedImportDict | None = None,
|
|
144
146
|
hooks: Mapping[str, VarData | None] | Sequence[str] | str | None = None,
|
|
145
147
|
deps: list[Var] | None = None,
|
|
146
148
|
position: Hooks.HookPosition | None = None,
|
|
@@ -161,7 +163,7 @@ class VarData:
|
|
|
161
163
|
hooks = [hooks]
|
|
162
164
|
if not isinstance(hooks, dict):
|
|
163
165
|
hooks = dict.fromkeys(hooks or [])
|
|
164
|
-
immutable_imports:
|
|
166
|
+
immutable_imports: ParsedImportTuple = tuple(
|
|
165
167
|
(k, tuple(v)) for k, v in parse_imports(imports or {}).items()
|
|
166
168
|
)
|
|
167
169
|
object.__setattr__(self, "state", state)
|
|
@@ -988,7 +990,7 @@ class Var(Generic[VAR_TYPE]):
|
|
|
988
990
|
setattr(state, actual_name, value)
|
|
989
991
|
except ValueError:
|
|
990
992
|
console.debug(
|
|
991
|
-
f"{type(state).__name__}.{self._js_expr}: Failed conversion of {value} to '{self._var_type.__name__}'. Value not set.",
|
|
993
|
+
f"{type(state).__name__}.{self._js_expr}: Failed conversion of {value!s} to '{self._var_type.__name__}'. Value not set.",
|
|
992
994
|
)
|
|
993
995
|
else:
|
|
994
996
|
setattr(state, actual_name, value)
|
|
@@ -1058,7 +1060,9 @@ class Var(Generic[VAR_TYPE]):
|
|
|
1058
1060
|
|
|
1059
1061
|
return boolify(self)
|
|
1060
1062
|
|
|
1061
|
-
def __and__(
|
|
1063
|
+
def __and__(
|
|
1064
|
+
self, other: Var[OTHER_VAR_TYPE] | Any
|
|
1065
|
+
) -> Var[VAR_TYPE | OTHER_VAR_TYPE]:
|
|
1062
1066
|
"""Perform a logical AND operation on the current instance and another variable.
|
|
1063
1067
|
|
|
1064
1068
|
Args:
|
|
@@ -1069,7 +1073,9 @@ class Var(Generic[VAR_TYPE]):
|
|
|
1069
1073
|
"""
|
|
1070
1074
|
return and_operation(self, other)
|
|
1071
1075
|
|
|
1072
|
-
def __rand__(
|
|
1076
|
+
def __rand__(
|
|
1077
|
+
self, other: Var[OTHER_VAR_TYPE] | Any
|
|
1078
|
+
) -> Var[VAR_TYPE | OTHER_VAR_TYPE]:
|
|
1073
1079
|
"""Perform a logical AND operation on the current instance and another variable.
|
|
1074
1080
|
|
|
1075
1081
|
Args:
|
|
@@ -1080,7 +1086,9 @@ class Var(Generic[VAR_TYPE]):
|
|
|
1080
1086
|
"""
|
|
1081
1087
|
return and_operation(other, self)
|
|
1082
1088
|
|
|
1083
|
-
def __or__(
|
|
1089
|
+
def __or__(
|
|
1090
|
+
self, other: Var[OTHER_VAR_TYPE] | Any
|
|
1091
|
+
) -> Var[VAR_TYPE | OTHER_VAR_TYPE]:
|
|
1084
1092
|
"""Perform a logical OR operation on the current instance and another variable.
|
|
1085
1093
|
|
|
1086
1094
|
Args:
|
|
@@ -1091,7 +1099,9 @@ class Var(Generic[VAR_TYPE]):
|
|
|
1091
1099
|
"""
|
|
1092
1100
|
return or_operation(self, other)
|
|
1093
1101
|
|
|
1094
|
-
def __ror__(
|
|
1102
|
+
def __ror__(
|
|
1103
|
+
self, other: Var[OTHER_VAR_TYPE] | Any
|
|
1104
|
+
) -> Var[VAR_TYPE | OTHER_VAR_TYPE]:
|
|
1095
1105
|
"""Perform a logical OR operation on the current instance and another variable.
|
|
1096
1106
|
|
|
1097
1107
|
Args:
|
|
@@ -1478,7 +1488,7 @@ class LiteralVar(Var):
|
|
|
1478
1488
|
_var_literal_subclasses.append((cls, var_subclass))
|
|
1479
1489
|
|
|
1480
1490
|
@classmethod
|
|
1481
|
-
def
|
|
1491
|
+
def _create_literal_var(
|
|
1482
1492
|
cls,
|
|
1483
1493
|
value: Any,
|
|
1484
1494
|
_var_data: VarData | None = None,
|
|
@@ -1559,6 +1569,9 @@ class LiteralVar(Var):
|
|
|
1559
1569
|
f"Unsupported type {type(value)} for LiteralVar. Tried to create a LiteralVar from {value}."
|
|
1560
1570
|
)
|
|
1561
1571
|
|
|
1572
|
+
if not TYPE_CHECKING:
|
|
1573
|
+
create = _create_literal_var
|
|
1574
|
+
|
|
1562
1575
|
def __post_init__(self):
|
|
1563
1576
|
"""Post-initialize the var."""
|
|
1564
1577
|
|
|
@@ -1835,6 +1848,21 @@ class cached_property: # noqa: N801
|
|
|
1835
1848
|
cached_property_no_lock = cached_property
|
|
1836
1849
|
|
|
1837
1850
|
|
|
1851
|
+
class VarProtocol(Protocol):
|
|
1852
|
+
"""A protocol for Var."""
|
|
1853
|
+
|
|
1854
|
+
__dataclass_fields__: ClassVar[dict[str, dataclasses.Field[Any]]]
|
|
1855
|
+
|
|
1856
|
+
@property
|
|
1857
|
+
def _js_expr(self) -> str: ...
|
|
1858
|
+
|
|
1859
|
+
@property
|
|
1860
|
+
def _var_type(self) -> types.GenericType: ...
|
|
1861
|
+
|
|
1862
|
+
@property
|
|
1863
|
+
def _var_data(self) -> VarData: ...
|
|
1864
|
+
|
|
1865
|
+
|
|
1838
1866
|
class CachedVarOperation:
|
|
1839
1867
|
"""Base class for cached var operations to lower boilerplate code."""
|
|
1840
1868
|
|
|
@@ -1869,7 +1897,7 @@ class CachedVarOperation:
|
|
|
1869
1897
|
return self._cached_get_all_var_data
|
|
1870
1898
|
|
|
1871
1899
|
@cached_property_no_lock
|
|
1872
|
-
def _cached_get_all_var_data(self) -> VarData | None:
|
|
1900
|
+
def _cached_get_all_var_data(self: VarProtocol) -> VarData | None:
|
|
1873
1901
|
"""Get the cached VarData.
|
|
1874
1902
|
|
|
1875
1903
|
Returns:
|
|
@@ -1879,14 +1907,13 @@ class CachedVarOperation:
|
|
|
1879
1907
|
*(
|
|
1880
1908
|
value._get_all_var_data() if isinstance(value, Var) else None
|
|
1881
1909
|
for value in (
|
|
1882
|
-
getattr(self, field.name)
|
|
1883
|
-
for field in dataclasses.fields(self) # pyright: ignore [reportArgumentType]
|
|
1910
|
+
getattr(self, field.name) for field in dataclasses.fields(self)
|
|
1884
1911
|
)
|
|
1885
1912
|
),
|
|
1886
1913
|
self._var_data,
|
|
1887
1914
|
)
|
|
1888
1915
|
|
|
1889
|
-
def __hash__(self) -> int:
|
|
1916
|
+
def __hash__(self: DataclassInstance) -> int:
|
|
1890
1917
|
"""Calculate the hash of the object.
|
|
1891
1918
|
|
|
1892
1919
|
Returns:
|
|
@@ -1897,14 +1924,16 @@ class CachedVarOperation:
|
|
|
1897
1924
|
type(self).__name__,
|
|
1898
1925
|
*[
|
|
1899
1926
|
getattr(self, field.name)
|
|
1900
|
-
for field in dataclasses.fields(self)
|
|
1927
|
+
for field in dataclasses.fields(self)
|
|
1901
1928
|
if field.name not in ["_js_expr", "_var_data", "_var_type"]
|
|
1902
1929
|
],
|
|
1903
1930
|
)
|
|
1904
1931
|
)
|
|
1905
1932
|
|
|
1906
1933
|
|
|
1907
|
-
def and_operation(
|
|
1934
|
+
def and_operation(
|
|
1935
|
+
a: Var[VAR_TYPE] | Any, b: Var[OTHER_VAR_TYPE] | Any
|
|
1936
|
+
) -> Var[VAR_TYPE | OTHER_VAR_TYPE]:
|
|
1908
1937
|
"""Perform a logical AND operation on two variables.
|
|
1909
1938
|
|
|
1910
1939
|
Args:
|
|
@@ -1934,7 +1963,9 @@ def _and_operation(a: Var, b: Var):
|
|
|
1934
1963
|
)
|
|
1935
1964
|
|
|
1936
1965
|
|
|
1937
|
-
def or_operation(
|
|
1966
|
+
def or_operation(
|
|
1967
|
+
a: Var[VAR_TYPE] | Any, b: Var[OTHER_VAR_TYPE] | Any
|
|
1968
|
+
) -> Var[VAR_TYPE | OTHER_VAR_TYPE]:
|
|
1938
1969
|
"""Perform a logical OR operation on two variables.
|
|
1939
1970
|
|
|
1940
1971
|
Args:
|
|
@@ -2340,7 +2371,7 @@ class ComputedVar(Var[RETURN_TYPE]):
|
|
|
2340
2371
|
if not _isinstance(value, self._var_type, nested=1, treat_var_as_type=False):
|
|
2341
2372
|
console.error(
|
|
2342
2373
|
f"Computed var '{type(instance).__name__}.{self._js_expr}' must return"
|
|
2343
|
-
f" a value of type '{self._var_type}', got '{value}' of type {type(value)}."
|
|
2374
|
+
f" a value of type '{self._var_type}', got '{value!s}' of type {type(value)}."
|
|
2344
2375
|
)
|
|
2345
2376
|
|
|
2346
2377
|
def _deps(
|
|
@@ -2976,7 +3007,7 @@ def get_uuid_string_var() -> Var:
|
|
|
2976
3007
|
unique_uuid_var = get_unique_variable_name()
|
|
2977
3008
|
unique_uuid_var_data = VarData(
|
|
2978
3009
|
imports={
|
|
2979
|
-
f"$/{constants.Dirs.STATE_PATH}":
|
|
3010
|
+
f"$/{constants.Dirs.STATE_PATH}": ImportVar(tag="generateUUID"),
|
|
2980
3011
|
"react": "useMemo",
|
|
2981
3012
|
},
|
|
2982
3013
|
hooks={f"const {unique_uuid_var} = useMemo(generateUUID, [])": None},
|
|
@@ -3286,10 +3317,15 @@ class Field(Generic[FIELD_TYPE]):
|
|
|
3286
3317
|
|
|
3287
3318
|
@overload
|
|
3288
3319
|
def __get__(
|
|
3289
|
-
self: Field[int]
|
|
3290
|
-
|
|
3320
|
+
self: Field[int] | Field[int | None],
|
|
3321
|
+
instance: None,
|
|
3322
|
+
owner: Any,
|
|
3323
|
+
) -> NumberVar[int]: ...
|
|
3324
|
+
|
|
3325
|
+
@overload
|
|
3326
|
+
def __get__(
|
|
3327
|
+
self: Field[float]
|
|
3291
3328
|
| Field[int | float]
|
|
3292
|
-
| Field[int | None]
|
|
3293
3329
|
| Field[float | None]
|
|
3294
3330
|
| Field[int | float | None],
|
|
3295
3331
|
instance: None,
|
reflex/vars/number.py
CHANGED
|
@@ -16,6 +16,8 @@ from typing import (
|
|
|
16
16
|
overload,
|
|
17
17
|
)
|
|
18
18
|
|
|
19
|
+
from typing_extensions import TypeVar as TypeVarExt
|
|
20
|
+
|
|
19
21
|
from reflex.constants.base import Dirs
|
|
20
22
|
from reflex.utils.exceptions import (
|
|
21
23
|
PrimitiveUnserializableToJSONError,
|
|
@@ -35,7 +37,9 @@ from .base import (
|
|
|
35
37
|
var_operation_return,
|
|
36
38
|
)
|
|
37
39
|
|
|
38
|
-
NUMBER_T =
|
|
40
|
+
NUMBER_T = TypeVarExt(
|
|
41
|
+
"NUMBER_T", bound=(int | float), default=(int | float), covariant=True
|
|
42
|
+
)
|
|
39
43
|
|
|
40
44
|
if TYPE_CHECKING:
|
|
41
45
|
from .sequence import ArrayVar
|
|
@@ -313,13 +317,19 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
|
|
|
313
317
|
"""
|
|
314
318
|
return self
|
|
315
319
|
|
|
316
|
-
def __round__(self):
|
|
320
|
+
def __round__(self, ndigits: int | NumberVar = 0) -> NumberVar:
|
|
317
321
|
"""Round the number.
|
|
318
322
|
|
|
323
|
+
Args:
|
|
324
|
+
ndigits: The number of digits to round.
|
|
325
|
+
|
|
319
326
|
Returns:
|
|
320
327
|
The number round operation.
|
|
321
328
|
"""
|
|
322
|
-
|
|
329
|
+
if not isinstance(ndigits, NUMBER_TYPES):
|
|
330
|
+
raise_unsupported_operand_types("round", (type(self), type(ndigits)))
|
|
331
|
+
|
|
332
|
+
return number_round_operation(self, +ndigits)
|
|
323
333
|
|
|
324
334
|
def __ceil__(self):
|
|
325
335
|
"""Ceil the number.
|
|
@@ -653,16 +663,23 @@ def number_exponent_operation(lhs: NumberVar, rhs: NumberVar):
|
|
|
653
663
|
|
|
654
664
|
|
|
655
665
|
@var_operation
|
|
656
|
-
def number_round_operation(value: NumberVar):
|
|
666
|
+
def number_round_operation(value: NumberVar, ndigits: NumberVar | int):
|
|
657
667
|
"""Round the number.
|
|
658
668
|
|
|
659
669
|
Args:
|
|
660
670
|
value: The number.
|
|
671
|
+
ndigits: The number of digits.
|
|
661
672
|
|
|
662
673
|
Returns:
|
|
663
674
|
The number round operation.
|
|
664
675
|
"""
|
|
665
|
-
|
|
676
|
+
if (isinstance(ndigits, LiteralNumberVar) and ndigits._var_value == 0) or (
|
|
677
|
+
isinstance(ndigits, int) and ndigits == 0
|
|
678
|
+
):
|
|
679
|
+
return var_operation_return(js_expression=f"Math.round({value})", var_type=int)
|
|
680
|
+
return var_operation_return(
|
|
681
|
+
js_expression=f"(+{value}.toFixed({ndigits}))", var_type=float
|
|
682
|
+
)
|
|
666
683
|
|
|
667
684
|
|
|
668
685
|
@var_operation
|
|
@@ -1064,7 +1081,7 @@ U = TypeVar("U")
|
|
|
1064
1081
|
|
|
1065
1082
|
@var_operation
|
|
1066
1083
|
def ternary_operation(
|
|
1067
|
-
condition:
|
|
1084
|
+
condition: Var[bool], if_true: Var[T], if_false: Var[U]
|
|
1068
1085
|
) -> CustomVarOperationReturn[T | U]:
|
|
1069
1086
|
"""Create a ternary operation.
|
|
1070
1087
|
|
reflex/vars/sequence.py
CHANGED
|
@@ -1604,6 +1604,8 @@ def _determine_value_of_array_index(
|
|
|
1604
1604
|
return args[0] if args else Any
|
|
1605
1605
|
if origin_var_type is tuple:
|
|
1606
1606
|
args = get_args(var_type)
|
|
1607
|
+
if len(args) == 2 and args[1] is ...:
|
|
1608
|
+
return args[0]
|
|
1607
1609
|
return (
|
|
1608
1610
|
args[int(index) % len(args)]
|
|
1609
1611
|
if args and index is not None
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: reflex
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.5
|
|
4
4
|
Summary: Web apps in pure Python.
|
|
5
5
|
Project-URL: homepage, https://reflex.dev
|
|
6
6
|
Project-URL: repository, https://github.com/reflex-dev/reflex
|
|
@@ -23,7 +23,7 @@ Requires-Dist: build<2.0,>=1.0.3
|
|
|
23
23
|
Requires-Dist: charset-normalizer<4.0,>=3.3.2
|
|
24
24
|
Requires-Dist: distro<2.0,>=1.8.0; platform_system == 'Linux'
|
|
25
25
|
Requires-Dist: fastapi!=0.111.0,!=0.111.1,>=0.96.0
|
|
26
|
-
Requires-Dist: granian[reload]>=2.
|
|
26
|
+
Requires-Dist: granian[reload]>=2.2.0
|
|
27
27
|
Requires-Dist: gunicorn<24.0.0,>=23.0.0
|
|
28
28
|
Requires-Dist: httpx<1.0,>=0.25.1
|
|
29
29
|
Requires-Dist: jinja2<4.0,>=3.1.2
|