reflex 0.7.0a5__py3-none-any.whl → 0.7.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of reflex might be problematic. Click here for more details.
- reflex/.templates/jinja/web/package.json.jinja2 +7 -1
- reflex/.templates/web/components/reflex/radix_themes_color_mode_provider.js +3 -1
- reflex/__init__.py +1 -0
- reflex/__init__.pyi +1 -0
- reflex/app.py +268 -85
- reflex/base.py +4 -10
- reflex/compiler/compiler.py +46 -12
- reflex/compiler/templates.py +1 -2
- reflex/compiler/utils.py +23 -14
- reflex/components/base/bare.py +109 -16
- reflex/components/component.py +179 -124
- reflex/components/core/__init__.py +1 -0
- reflex/components/core/__init__.pyi +1 -0
- reflex/components/core/auto_scroll.py +114 -0
- reflex/components/core/auto_scroll.pyi +284 -0
- reflex/components/core/banner.py +40 -9
- reflex/components/core/banner.pyi +400 -87
- reflex/components/core/breakpoints.py +1 -1
- reflex/components/core/cond.py +0 -8
- reflex/components/core/foreach.py +12 -2
- reflex/components/core/html.pyi +200 -19
- reflex/components/core/match.py +4 -4
- reflex/components/core/sticky.pyi +874 -90
- reflex/components/core/upload.py +3 -5
- reflex/components/core/upload.pyi +2 -4
- reflex/components/datadisplay/code.py +36 -10
- reflex/components/datadisplay/code.pyi +1 -1
- reflex/components/datadisplay/dataeditor.py +1 -3
- reflex/components/datadisplay/dataeditor.pyi +1 -3
- reflex/components/el/elements/base.py +95 -17
- reflex/components/el/elements/base.pyi +278 -19
- reflex/components/el/elements/forms.py +124 -102
- reflex/components/el/elements/forms.pyi +2787 -365
- reflex/components/el/elements/inline.py +24 -15
- reflex/components/el/elements/inline.pyi +5655 -546
- reflex/components/el/elements/media.py +79 -95
- reflex/components/el/elements/media.pyi +5167 -565
- reflex/components/el/elements/metadata.py +19 -17
- reflex/components/el/elements/metadata.pyi +841 -89
- reflex/components/el/elements/other.py +3 -5
- reflex/components/el/elements/other.pyi +1404 -137
- reflex/components/el/elements/scripts.py +10 -13
- reflex/components/el/elements/scripts.pyi +634 -65
- reflex/components/el/elements/sectioning.pyi +3001 -286
- reflex/components/el/elements/tables.py +14 -35
- reflex/components/el/elements/tables.pyi +2029 -218
- reflex/components/el/elements/typography.py +10 -13
- reflex/components/el/elements/typography.pyi +3014 -297
- reflex/components/lucide/icon.py +22 -6
- reflex/components/markdown/markdown.py +30 -10
- reflex/components/markdown/markdown.pyi +3 -2
- reflex/components/plotly/plotly.py +1 -3
- reflex/components/plotly/plotly.pyi +1 -3
- reflex/components/radix/primitives/form.pyi +624 -93
- reflex/components/radix/themes/color_mode.py +1 -1
- reflex/components/radix/themes/color_mode.pyi +213 -31
- reflex/components/radix/themes/components/alert_dialog.pyi +199 -18
- reflex/components/radix/themes/components/badge.pyi +199 -18
- reflex/components/radix/themes/components/button.pyi +213 -31
- reflex/components/radix/themes/components/callout.pyi +1000 -95
- reflex/components/radix/themes/components/card.pyi +199 -18
- reflex/components/radix/themes/components/context_menu.py +79 -1
- reflex/components/radix/themes/components/context_menu.pyi +320 -1
- reflex/components/radix/themes/components/dialog.pyi +199 -18
- reflex/components/radix/themes/components/hover_card.pyi +199 -18
- reflex/components/radix/themes/components/icon_button.pyi +213 -31
- reflex/components/radix/themes/components/inset.pyi +199 -18
- reflex/components/radix/themes/components/popover.pyi +199 -18
- reflex/components/radix/themes/components/table.pyi +1437 -154
- reflex/components/radix/themes/components/text_area.py +2 -2
- reflex/components/radix/themes/components/text_area.pyi +201 -20
- reflex/components/radix/themes/components/text_field.py +1 -1
- reflex/components/radix/themes/components/text_field.pyi +444 -88
- reflex/components/radix/themes/layout/box.pyi +200 -19
- reflex/components/radix/themes/layout/center.pyi +199 -18
- reflex/components/radix/themes/layout/container.pyi +199 -18
- reflex/components/radix/themes/layout/flex.pyi +199 -18
- reflex/components/radix/themes/layout/grid.pyi +199 -18
- reflex/components/radix/themes/layout/list.pyi +604 -57
- reflex/components/radix/themes/layout/section.pyi +199 -18
- reflex/components/radix/themes/layout/spacer.pyi +199 -18
- reflex/components/radix/themes/layout/stack.pyi +597 -54
- reflex/components/radix/themes/typography/blockquote.pyi +200 -19
- reflex/components/radix/themes/typography/code.pyi +199 -18
- reflex/components/radix/themes/typography/heading.pyi +199 -18
- reflex/components/radix/themes/typography/link.pyi +238 -28
- reflex/components/radix/themes/typography/text.pyi +1394 -127
- reflex/components/react_player/react_player.py +1 -1
- reflex/components/react_player/react_player.pyi +1 -3
- reflex/components/sonner/toast.py +41 -12
- reflex/components/sonner/toast.pyi +20 -6
- reflex/components/tags/iter_tag.py +4 -0
- reflex/components/tags/tag.py +3 -3
- reflex/config.py +187 -28
- reflex/constants/__init__.py +2 -0
- reflex/constants/base.py +6 -0
- reflex/constants/compiler.py +9 -0
- reflex/constants/event.py +1 -0
- reflex/constants/installer.py +8 -5
- reflex/constants/utils.py +1 -3
- reflex/event.py +7 -16
- reflex/experimental/layout.pyi +597 -54
- reflex/py.typed +0 -0
- reflex/reflex.py +30 -41
- reflex/state.py +49 -44
- reflex/style.py +15 -22
- reflex/testing.py +2 -0
- reflex/utils/build.py +12 -0
- reflex/utils/console.py +4 -0
- reflex/utils/decorator.py +25 -0
- reflex/utils/exec.py +92 -34
- reflex/utils/format.py +35 -6
- reflex/utils/path_ops.py +16 -1
- reflex/utils/prerequisites.py +25 -33
- reflex/utils/processes.py +12 -13
- reflex/utils/serializers.py +20 -43
- reflex/utils/telemetry.py +4 -15
- reflex/utils/types.py +36 -66
- reflex/vars/base.py +53 -76
- reflex/vars/function.py +17 -5
- reflex/vars/number.py +1 -1
- reflex/vars/sequence.py +80 -4
- {reflex-0.7.0a5.dist-info → reflex-0.7.1.dist-info}/METADATA +4 -5
- {reflex-0.7.0a5.dist-info → reflex-0.7.1.dist-info}/RECORD +127 -123
- {reflex-0.7.0a5.dist-info → reflex-0.7.1.dist-info}/LICENSE +0 -0
- {reflex-0.7.0a5.dist-info → reflex-0.7.1.dist-info}/WHEEL +0 -0
- {reflex-0.7.0a5.dist-info → reflex-0.7.1.dist-info}/entry_points.txt +0 -0
reflex/utils/types.py
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
import contextlib
|
|
6
5
|
import dataclasses
|
|
7
6
|
import inspect
|
|
8
7
|
import sys
|
|
9
8
|
import types
|
|
10
9
|
from functools import cached_property, lru_cache, wraps
|
|
10
|
+
from types import GenericAlias
|
|
11
11
|
from typing import (
|
|
12
12
|
TYPE_CHECKING,
|
|
13
13
|
Any,
|
|
@@ -25,66 +25,29 @@ from typing import (
|
|
|
25
25
|
Type,
|
|
26
26
|
Union,
|
|
27
27
|
_GenericAlias, # pyright: ignore [reportAttributeAccessIssue]
|
|
28
|
+
_SpecialGenericAlias, # pyright: ignore [reportAttributeAccessIssue]
|
|
28
29
|
get_args,
|
|
29
30
|
get_type_hints,
|
|
30
31
|
)
|
|
31
32
|
from typing import get_origin as get_origin_og
|
|
32
33
|
|
|
33
34
|
import sqlalchemy
|
|
34
|
-
from
|
|
35
|
-
|
|
36
|
-
import reflex
|
|
37
|
-
from reflex.components.core.breakpoints import Breakpoints
|
|
38
|
-
|
|
39
|
-
try:
|
|
40
|
-
from pydantic.v1.fields import ModelField
|
|
41
|
-
except ModuleNotFoundError:
|
|
42
|
-
from pydantic.fields import (
|
|
43
|
-
ModelField, # pyright: ignore [reportAttributeAccessIssue]
|
|
44
|
-
)
|
|
45
|
-
|
|
35
|
+
from pydantic.v1.fields import ModelField
|
|
46
36
|
from sqlalchemy.ext.associationproxy import AssociationProxyInstance
|
|
47
37
|
from sqlalchemy.ext.hybrid import hybrid_property
|
|
48
38
|
from sqlalchemy.orm import DeclarativeBase, Mapped, QueryableAttribute, Relationship
|
|
39
|
+
from typing_extensions import Self as Self
|
|
40
|
+
from typing_extensions import is_typeddict
|
|
41
|
+
from typing_extensions import override as override
|
|
49
42
|
|
|
43
|
+
import reflex
|
|
50
44
|
from reflex import constants
|
|
51
45
|
from reflex.base import Base
|
|
46
|
+
from reflex.components.core.breakpoints import Breakpoints
|
|
52
47
|
from reflex.utils import console
|
|
53
48
|
|
|
54
|
-
if sys.version_info >= (3, 12):
|
|
55
|
-
from typing import override as override
|
|
56
|
-
else:
|
|
57
|
-
|
|
58
|
-
def override(func: Callable) -> Callable:
|
|
59
|
-
"""Fallback for @override decorator.
|
|
60
|
-
|
|
61
|
-
Args:
|
|
62
|
-
func: The function to decorate.
|
|
63
|
-
|
|
64
|
-
Returns:
|
|
65
|
-
The unmodified function.
|
|
66
|
-
"""
|
|
67
|
-
return func
|
|
68
|
-
|
|
69
|
-
|
|
70
49
|
# Potential GenericAlias types for isinstance checks.
|
|
71
|
-
GenericAliasTypes =
|
|
72
|
-
|
|
73
|
-
with contextlib.suppress(ImportError):
|
|
74
|
-
# For newer versions of Python.
|
|
75
|
-
from types import GenericAlias
|
|
76
|
-
|
|
77
|
-
GenericAliasTypes.append(GenericAlias)
|
|
78
|
-
|
|
79
|
-
with contextlib.suppress(ImportError):
|
|
80
|
-
# For older versions of Python.
|
|
81
|
-
from typing import (
|
|
82
|
-
_SpecialGenericAlias, # pyright: ignore [reportAttributeAccessIssue]
|
|
83
|
-
)
|
|
84
|
-
|
|
85
|
-
GenericAliasTypes.append(_SpecialGenericAlias)
|
|
86
|
-
|
|
87
|
-
GenericAliasTypes = tuple(GenericAliasTypes)
|
|
50
|
+
GenericAliasTypes = (_GenericAlias, GenericAlias, _SpecialGenericAlias)
|
|
88
51
|
|
|
89
52
|
# Potential Union types for isinstance checks (UnionType added in py3.10).
|
|
90
53
|
UnionTypes = (Union, types.UnionType) if hasattr(types, "UnionType") else (Union,)
|
|
@@ -95,6 +58,7 @@ GenericType = Union[Type, _GenericAlias]
|
|
|
95
58
|
# Valid state var types.
|
|
96
59
|
JSONType = {str, int, float, bool}
|
|
97
60
|
PrimitiveType = Union[int, float, bool, str, list, dict, set, tuple]
|
|
61
|
+
PrimitiveTypes = (int, float, bool, str, list, dict, set, tuple)
|
|
98
62
|
StateVar = Union[PrimitiveType, Base, None]
|
|
99
63
|
StateIterVar = Union[list, set, tuple]
|
|
100
64
|
|
|
@@ -127,11 +91,6 @@ RESERVED_BACKEND_VAR_NAMES = {
|
|
|
127
91
|
"_was_touched",
|
|
128
92
|
}
|
|
129
93
|
|
|
130
|
-
if sys.version_info >= (3, 11):
|
|
131
|
-
from typing import Self as Self
|
|
132
|
-
else:
|
|
133
|
-
from typing_extensions import Self as Self
|
|
134
|
-
|
|
135
94
|
|
|
136
95
|
class Unset:
|
|
137
96
|
"""A class to represent an unset value.
|
|
@@ -551,13 +510,13 @@ def does_obj_satisfy_typed_dict(obj: Any, cls: GenericType) -> bool:
|
|
|
551
510
|
return required_keys.issubset(required_keys)
|
|
552
511
|
|
|
553
512
|
|
|
554
|
-
def _isinstance(obj: Any, cls: GenericType, nested:
|
|
513
|
+
def _isinstance(obj: Any, cls: GenericType, nested: int = 0) -> bool:
|
|
555
514
|
"""Check if an object is an instance of a class.
|
|
556
515
|
|
|
557
516
|
Args:
|
|
558
517
|
obj: The object to check.
|
|
559
518
|
cls: The class to check against.
|
|
560
|
-
nested:
|
|
519
|
+
nested: How many levels deep to check.
|
|
561
520
|
|
|
562
521
|
Returns:
|
|
563
522
|
Whether the object is an instance of the class.
|
|
@@ -565,15 +524,24 @@ def _isinstance(obj: Any, cls: GenericType, nested: bool = False) -> bool:
|
|
|
565
524
|
if cls is Any:
|
|
566
525
|
return True
|
|
567
526
|
|
|
527
|
+
from reflex.vars import LiteralVar, Var
|
|
528
|
+
|
|
529
|
+
if cls is Var:
|
|
530
|
+
return isinstance(obj, Var)
|
|
531
|
+
if isinstance(obj, LiteralVar):
|
|
532
|
+
return _isinstance(obj._var_value, cls, nested=nested)
|
|
533
|
+
if isinstance(obj, Var):
|
|
534
|
+
return _issubclass(obj._var_type, cls)
|
|
535
|
+
|
|
568
536
|
if cls is None or cls is type(None):
|
|
569
537
|
return obj is None
|
|
570
538
|
|
|
539
|
+
if cls and is_union(cls):
|
|
540
|
+
return any(_isinstance(obj, arg, nested=nested) for arg in get_args(cls))
|
|
541
|
+
|
|
571
542
|
if is_literal(cls):
|
|
572
543
|
return obj in get_args(cls)
|
|
573
544
|
|
|
574
|
-
if is_union(cls):
|
|
575
|
-
return any(_isinstance(obj, arg) for arg in get_args(cls))
|
|
576
|
-
|
|
577
545
|
origin = get_origin(cls)
|
|
578
546
|
|
|
579
547
|
if origin is None:
|
|
@@ -596,38 +564,40 @@ def _isinstance(obj: Any, cls: GenericType, nested: bool = False) -> bool:
|
|
|
596
564
|
# cls is a simple generic class
|
|
597
565
|
return isinstance(obj, origin)
|
|
598
566
|
|
|
599
|
-
if nested and args:
|
|
567
|
+
if nested > 0 and args:
|
|
600
568
|
if origin is list:
|
|
601
569
|
return isinstance(obj, list) and all(
|
|
602
|
-
_isinstance(item, args[0]) for item in obj
|
|
570
|
+
_isinstance(item, args[0], nested=nested - 1) for item in obj
|
|
603
571
|
)
|
|
604
572
|
if origin is tuple:
|
|
605
573
|
if args[-1] is Ellipsis:
|
|
606
574
|
return isinstance(obj, tuple) and all(
|
|
607
|
-
_isinstance(item, args[0]) for item in obj
|
|
575
|
+
_isinstance(item, args[0], nested=nested - 1) for item in obj
|
|
608
576
|
)
|
|
609
577
|
return (
|
|
610
578
|
isinstance(obj, tuple)
|
|
611
579
|
and len(obj) == len(args)
|
|
612
580
|
and all(
|
|
613
|
-
_isinstance(item, arg
|
|
581
|
+
_isinstance(item, arg, nested=nested - 1)
|
|
582
|
+
for item, arg in zip(obj, args, strict=True)
|
|
614
583
|
)
|
|
615
584
|
)
|
|
616
|
-
if origin in (dict, Breakpoints):
|
|
617
|
-
return isinstance(obj,
|
|
618
|
-
_isinstance(key, args[0]
|
|
585
|
+
if origin in (dict, Mapping, Breakpoints):
|
|
586
|
+
return isinstance(obj, Mapping) and all(
|
|
587
|
+
_isinstance(key, args[0], nested=nested - 1)
|
|
588
|
+
and _isinstance(value, args[1], nested=nested - 1)
|
|
619
589
|
for key, value in obj.items()
|
|
620
590
|
)
|
|
621
591
|
if origin is set:
|
|
622
592
|
return isinstance(obj, set) and all(
|
|
623
|
-
_isinstance(item, args[0]) for item in obj
|
|
593
|
+
_isinstance(item, args[0], nested=nested - 1) for item in obj
|
|
624
594
|
)
|
|
625
595
|
|
|
626
596
|
if args:
|
|
627
597
|
from reflex.vars import Field
|
|
628
598
|
|
|
629
599
|
if origin is Field:
|
|
630
|
-
return _isinstance(obj, args[0])
|
|
600
|
+
return _isinstance(obj, args[0], nested=nested)
|
|
631
601
|
|
|
632
602
|
return isinstance(obj, get_base_class(cls))
|
|
633
603
|
|
|
@@ -749,7 +719,7 @@ def check_prop_in_allowed_types(prop: Any, allowed_types: Iterable) -> bool:
|
|
|
749
719
|
"""
|
|
750
720
|
from reflex.vars import Var
|
|
751
721
|
|
|
752
|
-
type_ = prop._var_type if
|
|
722
|
+
type_ = prop._var_type if isinstance(prop, Var) else type(prop)
|
|
753
723
|
return type_ in allowed_types
|
|
754
724
|
|
|
755
725
|
|
reflex/vars/base.py
CHANGED
|
@@ -29,19 +29,22 @@ from typing import (
|
|
|
29
29
|
Mapping,
|
|
30
30
|
NoReturn,
|
|
31
31
|
Optional,
|
|
32
|
+
ParamSpec,
|
|
32
33
|
Sequence,
|
|
33
34
|
Set,
|
|
34
35
|
Tuple,
|
|
35
36
|
Type,
|
|
37
|
+
TypeGuard,
|
|
36
38
|
TypeVar,
|
|
37
39
|
Union,
|
|
38
40
|
cast,
|
|
39
41
|
get_args,
|
|
42
|
+
get_type_hints,
|
|
40
43
|
overload,
|
|
41
44
|
)
|
|
42
45
|
|
|
43
46
|
from sqlalchemy.orm import DeclarativeBase
|
|
44
|
-
from typing_extensions import
|
|
47
|
+
from typing_extensions import deprecated, override
|
|
45
48
|
|
|
46
49
|
from reflex import constants
|
|
47
50
|
from reflex.base import Base
|
|
@@ -73,11 +76,12 @@ from reflex.utils.types import (
|
|
|
73
76
|
)
|
|
74
77
|
|
|
75
78
|
if TYPE_CHECKING:
|
|
79
|
+
from reflex.components.component import BaseComponent
|
|
76
80
|
from reflex.state import BaseState
|
|
77
81
|
|
|
78
|
-
from .number import BooleanVar, NumberVar
|
|
79
|
-
from .object import ObjectVar
|
|
80
|
-
from .sequence import ArrayVar, StringVar
|
|
82
|
+
from .number import BooleanVar, LiteralBooleanVar, LiteralNumberVar, NumberVar
|
|
83
|
+
from .object import LiteralObjectVar, ObjectVar
|
|
84
|
+
from .sequence import ArrayVar, LiteralArrayVar, LiteralStringVar, StringVar
|
|
81
85
|
|
|
82
86
|
|
|
83
87
|
VAR_TYPE = TypeVar("VAR_TYPE", covariant=True)
|
|
@@ -129,6 +133,9 @@ class VarData:
|
|
|
129
133
|
# Position of the hook in the component
|
|
130
134
|
position: Hooks.HookPosition | None = None
|
|
131
135
|
|
|
136
|
+
# Components that are part of this var
|
|
137
|
+
components: Tuple[BaseComponent, ...] = dataclasses.field(default_factory=tuple)
|
|
138
|
+
|
|
132
139
|
def __init__(
|
|
133
140
|
self,
|
|
134
141
|
state: str = "",
|
|
@@ -137,6 +144,7 @@ class VarData:
|
|
|
137
144
|
hooks: Mapping[str, VarData | None] | Sequence[str] | str | None = None,
|
|
138
145
|
deps: list[Var] | None = None,
|
|
139
146
|
position: Hooks.HookPosition | None = None,
|
|
147
|
+
components: Iterable[BaseComponent] | None = None,
|
|
140
148
|
):
|
|
141
149
|
"""Initialize the var data.
|
|
142
150
|
|
|
@@ -147,6 +155,7 @@ class VarData:
|
|
|
147
155
|
hooks: Hooks that need to be present in the component to render this var.
|
|
148
156
|
deps: Dependencies of the var for useCallback.
|
|
149
157
|
position: Position of the hook in the component.
|
|
158
|
+
components: Components that are part of this var.
|
|
150
159
|
"""
|
|
151
160
|
if isinstance(hooks, str):
|
|
152
161
|
hooks = [hooks]
|
|
@@ -161,6 +170,7 @@ class VarData:
|
|
|
161
170
|
object.__setattr__(self, "hooks", tuple(hooks or {}))
|
|
162
171
|
object.__setattr__(self, "deps", tuple(deps or []))
|
|
163
172
|
object.__setattr__(self, "position", position or None)
|
|
173
|
+
object.__setattr__(self, "components", tuple(components or []))
|
|
164
174
|
|
|
165
175
|
if hooks and any(hooks.values()):
|
|
166
176
|
merged_var_data = VarData.merge(self, *hooks.values())
|
|
@@ -171,6 +181,7 @@ class VarData:
|
|
|
171
181
|
object.__setattr__(self, "hooks", merged_var_data.hooks)
|
|
172
182
|
object.__setattr__(self, "deps", merged_var_data.deps)
|
|
173
183
|
object.__setattr__(self, "position", merged_var_data.position)
|
|
184
|
+
object.__setattr__(self, "components", merged_var_data.components)
|
|
174
185
|
|
|
175
186
|
def old_school_imports(self) -> ImportDict:
|
|
176
187
|
"""Return the imports as a mutable dict.
|
|
@@ -239,17 +250,19 @@ class VarData:
|
|
|
239
250
|
else:
|
|
240
251
|
position = None
|
|
241
252
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
field_name=field_name,
|
|
246
|
-
imports=_imports,
|
|
247
|
-
hooks=hooks,
|
|
248
|
-
deps=deps,
|
|
249
|
-
position=position,
|
|
250
|
-
)
|
|
253
|
+
components = tuple(
|
|
254
|
+
component for var_data in all_var_datas for component in var_data.components
|
|
255
|
+
)
|
|
251
256
|
|
|
252
|
-
return
|
|
257
|
+
return VarData(
|
|
258
|
+
state=state,
|
|
259
|
+
field_name=field_name,
|
|
260
|
+
imports=_imports,
|
|
261
|
+
hooks=hooks,
|
|
262
|
+
deps=deps,
|
|
263
|
+
position=position,
|
|
264
|
+
components=components,
|
|
265
|
+
)
|
|
253
266
|
|
|
254
267
|
def __bool__(self) -> bool:
|
|
255
268
|
"""Check if the var data is non-empty.
|
|
@@ -264,6 +277,7 @@ class VarData:
|
|
|
264
277
|
or self.field_name
|
|
265
278
|
or self.deps
|
|
266
279
|
or self.position
|
|
280
|
+
or self.components
|
|
267
281
|
)
|
|
268
282
|
|
|
269
283
|
@classmethod
|
|
@@ -573,13 +587,21 @@ class Var(Generic[VAR_TYPE]):
|
|
|
573
587
|
|
|
574
588
|
return value_with_replaced
|
|
575
589
|
|
|
590
|
+
@overload
|
|
591
|
+
@classmethod
|
|
592
|
+
def create( # pyright: ignore[reportOverlappingOverload]
|
|
593
|
+
cls,
|
|
594
|
+
value: NoReturn,
|
|
595
|
+
_var_data: VarData | None = None,
|
|
596
|
+
) -> Var[Any]: ...
|
|
597
|
+
|
|
576
598
|
@overload
|
|
577
599
|
@classmethod
|
|
578
600
|
def create( # pyright: ignore[reportOverlappingOverload]
|
|
579
601
|
cls,
|
|
580
602
|
value: bool,
|
|
581
603
|
_var_data: VarData | None = None,
|
|
582
|
-
) ->
|
|
604
|
+
) -> LiteralBooleanVar: ...
|
|
583
605
|
|
|
584
606
|
@overload
|
|
585
607
|
@classmethod
|
|
@@ -587,7 +609,7 @@ class Var(Generic[VAR_TYPE]):
|
|
|
587
609
|
cls,
|
|
588
610
|
value: int,
|
|
589
611
|
_var_data: VarData | None = None,
|
|
590
|
-
) ->
|
|
612
|
+
) -> LiteralNumberVar[int]: ...
|
|
591
613
|
|
|
592
614
|
@overload
|
|
593
615
|
@classmethod
|
|
@@ -595,7 +617,15 @@ class Var(Generic[VAR_TYPE]):
|
|
|
595
617
|
cls,
|
|
596
618
|
value: float,
|
|
597
619
|
_var_data: VarData | None = None,
|
|
598
|
-
) ->
|
|
620
|
+
) -> LiteralNumberVar[float]: ...
|
|
621
|
+
|
|
622
|
+
@overload
|
|
623
|
+
@classmethod
|
|
624
|
+
def create( # pyright: ignore [reportOverlappingOverload]
|
|
625
|
+
cls,
|
|
626
|
+
value: str,
|
|
627
|
+
_var_data: VarData | None = None,
|
|
628
|
+
) -> LiteralStringVar: ...
|
|
599
629
|
|
|
600
630
|
@overload
|
|
601
631
|
@classmethod
|
|
@@ -611,7 +641,7 @@ class Var(Generic[VAR_TYPE]):
|
|
|
611
641
|
cls,
|
|
612
642
|
value: None,
|
|
613
643
|
_var_data: VarData | None = None,
|
|
614
|
-
) ->
|
|
644
|
+
) -> LiteralNoneVar: ...
|
|
615
645
|
|
|
616
646
|
@overload
|
|
617
647
|
@classmethod
|
|
@@ -619,7 +649,7 @@ class Var(Generic[VAR_TYPE]):
|
|
|
619
649
|
cls,
|
|
620
650
|
value: MAPPING_TYPE,
|
|
621
651
|
_var_data: VarData | None = None,
|
|
622
|
-
) ->
|
|
652
|
+
) -> LiteralObjectVar[MAPPING_TYPE]: ...
|
|
623
653
|
|
|
624
654
|
@overload
|
|
625
655
|
@classmethod
|
|
@@ -627,7 +657,7 @@ class Var(Generic[VAR_TYPE]):
|
|
|
627
657
|
cls,
|
|
628
658
|
value: SEQUENCE_TYPE,
|
|
629
659
|
_var_data: VarData | None = None,
|
|
630
|
-
) ->
|
|
660
|
+
) -> LiteralArrayVar[SEQUENCE_TYPE]: ...
|
|
631
661
|
|
|
632
662
|
@overload
|
|
633
663
|
@classmethod
|
|
@@ -935,7 +965,7 @@ class Var(Generic[VAR_TYPE]):
|
|
|
935
965
|
"""
|
|
936
966
|
actual_name = self._var_field_name
|
|
937
967
|
|
|
938
|
-
def setter(state:
|
|
968
|
+
def setter(state: Any, value: Any):
|
|
939
969
|
"""Get the setter for the var.
|
|
940
970
|
|
|
941
971
|
Args:
|
|
@@ -953,6 +983,8 @@ class Var(Generic[VAR_TYPE]):
|
|
|
953
983
|
else:
|
|
954
984
|
setattr(state, actual_name, value)
|
|
955
985
|
|
|
986
|
+
setter.__annotations__["value"] = self._var_type
|
|
987
|
+
|
|
956
988
|
setter.__qualname__ = self._get_setter_name()
|
|
957
989
|
|
|
958
990
|
return setter
|
|
@@ -1885,61 +1917,6 @@ def _or_operation(a: Var, b: Var):
|
|
|
1885
1917
|
)
|
|
1886
1918
|
|
|
1887
1919
|
|
|
1888
|
-
@dataclasses.dataclass(
|
|
1889
|
-
eq=False,
|
|
1890
|
-
frozen=True,
|
|
1891
|
-
slots=True,
|
|
1892
|
-
)
|
|
1893
|
-
class CallableVar(Var):
|
|
1894
|
-
"""Decorate a Var-returning function to act as both a Var and a function.
|
|
1895
|
-
|
|
1896
|
-
This is used as a compatibility shim for replacing Var objects in the
|
|
1897
|
-
API with functions that return a family of Var.
|
|
1898
|
-
"""
|
|
1899
|
-
|
|
1900
|
-
fn: Callable[..., Var] = dataclasses.field(
|
|
1901
|
-
default_factory=lambda: lambda: Var(_js_expr="undefined")
|
|
1902
|
-
)
|
|
1903
|
-
original_var: Var = dataclasses.field(
|
|
1904
|
-
default_factory=lambda: Var(_js_expr="undefined")
|
|
1905
|
-
)
|
|
1906
|
-
|
|
1907
|
-
def __init__(self, fn: Callable[..., Var]):
|
|
1908
|
-
"""Initialize a CallableVar.
|
|
1909
|
-
|
|
1910
|
-
Args:
|
|
1911
|
-
fn: The function to decorate (must return Var)
|
|
1912
|
-
"""
|
|
1913
|
-
original_var = fn()
|
|
1914
|
-
super(CallableVar, self).__init__(
|
|
1915
|
-
_js_expr=original_var._js_expr,
|
|
1916
|
-
_var_type=original_var._var_type,
|
|
1917
|
-
_var_data=VarData.merge(original_var._get_all_var_data()),
|
|
1918
|
-
)
|
|
1919
|
-
object.__setattr__(self, "fn", fn)
|
|
1920
|
-
object.__setattr__(self, "original_var", original_var)
|
|
1921
|
-
|
|
1922
|
-
def __call__(self, *args: Any, **kwargs: Any) -> Var:
|
|
1923
|
-
"""Call the decorated function.
|
|
1924
|
-
|
|
1925
|
-
Args:
|
|
1926
|
-
*args: The args to pass to the function.
|
|
1927
|
-
**kwargs: The kwargs to pass to the function.
|
|
1928
|
-
|
|
1929
|
-
Returns:
|
|
1930
|
-
The Var returned from calling the function.
|
|
1931
|
-
"""
|
|
1932
|
-
return self.fn(*args, **kwargs)
|
|
1933
|
-
|
|
1934
|
-
def __hash__(self) -> int:
|
|
1935
|
-
"""Calculate the hash of the object.
|
|
1936
|
-
|
|
1937
|
-
Returns:
|
|
1938
|
-
The hash of the object.
|
|
1939
|
-
"""
|
|
1940
|
-
return hash((type(self).__name__, self.original_var))
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
1920
|
RETURN_TYPE = TypeVar("RETURN_TYPE")
|
|
1944
1921
|
|
|
1945
1922
|
DICT_KEY = TypeVar("DICT_KEY")
|
reflex/vars/function.py
CHANGED
|
@@ -4,9 +4,21 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import dataclasses
|
|
6
6
|
import sys
|
|
7
|
-
from typing import
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
from typing import (
|
|
8
|
+
Any,
|
|
9
|
+
Callable,
|
|
10
|
+
Concatenate,
|
|
11
|
+
Generic,
|
|
12
|
+
Optional,
|
|
13
|
+
ParamSpec,
|
|
14
|
+
Protocol,
|
|
15
|
+
Sequence,
|
|
16
|
+
Tuple,
|
|
17
|
+
Type,
|
|
18
|
+
TypeVar,
|
|
19
|
+
Union,
|
|
20
|
+
overload,
|
|
21
|
+
)
|
|
10
22
|
|
|
11
23
|
from reflex.utils import format
|
|
12
24
|
from reflex.utils.types import GenericType
|
|
@@ -29,9 +41,9 @@ class ReflexCallable(Protocol[P, R]):
|
|
|
29
41
|
__call__: Callable[P, R]
|
|
30
42
|
|
|
31
43
|
|
|
32
|
-
CALLABLE_TYPE = TypeVar("CALLABLE_TYPE", bound=ReflexCallable,
|
|
44
|
+
CALLABLE_TYPE = TypeVar("CALLABLE_TYPE", bound=ReflexCallable, covariant=True)
|
|
33
45
|
OTHER_CALLABLE_TYPE = TypeVar(
|
|
34
|
-
"OTHER_CALLABLE_TYPE", bound=ReflexCallable,
|
|
46
|
+
"OTHER_CALLABLE_TYPE", bound=ReflexCallable, covariant=True
|
|
35
47
|
)
|
|
36
48
|
|
|
37
49
|
|
reflex/vars/number.py
CHANGED
|
@@ -974,7 +974,7 @@ def boolean_not_operation(value: BooleanVar):
|
|
|
974
974
|
frozen=True,
|
|
975
975
|
slots=True,
|
|
976
976
|
)
|
|
977
|
-
class LiteralNumberVar(LiteralVar, NumberVar):
|
|
977
|
+
class LiteralNumberVar(LiteralVar, NumberVar[NUMBER_T]):
|
|
978
978
|
"""Base class for immutable literal number vars."""
|
|
979
979
|
|
|
980
980
|
_var_value: float | int = dataclasses.field(default=0)
|
reflex/vars/sequence.py
CHANGED
|
@@ -17,11 +17,12 @@ from typing import (
|
|
|
17
17
|
Sequence,
|
|
18
18
|
Tuple,
|
|
19
19
|
Type,
|
|
20
|
+
TypeVar,
|
|
20
21
|
Union,
|
|
21
22
|
overload,
|
|
22
23
|
)
|
|
23
24
|
|
|
24
|
-
from typing_extensions import TypeVar
|
|
25
|
+
from typing_extensions import TypeVar as TypingExtensionsTypeVar
|
|
25
26
|
|
|
26
27
|
from reflex import constants
|
|
27
28
|
from reflex.constants.base import REFLEX_VAR_OPENING_TAG
|
|
@@ -58,7 +59,7 @@ if TYPE_CHECKING:
|
|
|
58
59
|
from .object import ObjectVar
|
|
59
60
|
|
|
60
61
|
|
|
61
|
-
STRING_TYPE =
|
|
62
|
+
STRING_TYPE = TypingExtensionsTypeVar("STRING_TYPE", default=str)
|
|
62
63
|
|
|
63
64
|
|
|
64
65
|
class StringVar(Var[STRING_TYPE], python_types=str):
|
|
@@ -191,6 +192,22 @@ class StringVar(Var[STRING_TYPE], python_types=str):
|
|
|
191
192
|
"""
|
|
192
193
|
return string_upper_operation(self)
|
|
193
194
|
|
|
195
|
+
def title(self) -> StringVar:
|
|
196
|
+
"""Convert the string to title case.
|
|
197
|
+
|
|
198
|
+
Returns:
|
|
199
|
+
The string title operation.
|
|
200
|
+
"""
|
|
201
|
+
return string_title_operation(self)
|
|
202
|
+
|
|
203
|
+
def capitalize(self) -> StringVar:
|
|
204
|
+
"""Capitalize the string.
|
|
205
|
+
|
|
206
|
+
Returns:
|
|
207
|
+
The string capitalize operation.
|
|
208
|
+
"""
|
|
209
|
+
return string_capitalize_operation(self)
|
|
210
|
+
|
|
194
211
|
def strip(self) -> StringVar:
|
|
195
212
|
"""Strip the string.
|
|
196
213
|
|
|
@@ -372,6 +389,33 @@ class StringVar(Var[STRING_TYPE], python_types=str):
|
|
|
372
389
|
|
|
373
390
|
return string_ge_operation(self, other)
|
|
374
391
|
|
|
392
|
+
@overload
|
|
393
|
+
def replace( # pyright: ignore [reportOverlappingOverload]
|
|
394
|
+
self, search_value: StringVar | str, new_value: StringVar | str
|
|
395
|
+
) -> StringVar: ...
|
|
396
|
+
|
|
397
|
+
@overload
|
|
398
|
+
def replace(
|
|
399
|
+
self, search_value: Any, new_value: Any
|
|
400
|
+
) -> CustomVarOperationReturn[StringVar]: ...
|
|
401
|
+
|
|
402
|
+
def replace(self, search_value: Any, new_value: Any) -> StringVar: # pyright: ignore [reportInconsistentOverload]
|
|
403
|
+
"""Replace a string with a value.
|
|
404
|
+
|
|
405
|
+
Args:
|
|
406
|
+
search_value: The string to search.
|
|
407
|
+
new_value: The value to be replaced with.
|
|
408
|
+
|
|
409
|
+
Returns:
|
|
410
|
+
The string replace operation.
|
|
411
|
+
"""
|
|
412
|
+
if not isinstance(search_value, (StringVar, str)):
|
|
413
|
+
raise_unsupported_operand_types("replace", (type(self), type(search_value)))
|
|
414
|
+
if not isinstance(new_value, (StringVar, str)):
|
|
415
|
+
raise_unsupported_operand_types("replace", (type(self), type(new_value)))
|
|
416
|
+
|
|
417
|
+
return string_replace_operation(self, search_value, new_value)
|
|
418
|
+
|
|
375
419
|
|
|
376
420
|
@var_operation
|
|
377
421
|
def string_lt_operation(lhs: StringVar[Any] | str, rhs: StringVar[Any] | str):
|
|
@@ -455,6 +499,38 @@ def string_upper_operation(string: StringVar[Any]):
|
|
|
455
499
|
return var_operation_return(js_expression=f"{string}.toUpperCase()", var_type=str)
|
|
456
500
|
|
|
457
501
|
|
|
502
|
+
@var_operation
|
|
503
|
+
def string_title_operation(string: StringVar[Any]):
|
|
504
|
+
"""Convert a string to title case.
|
|
505
|
+
|
|
506
|
+
Args:
|
|
507
|
+
string: The string to convert.
|
|
508
|
+
|
|
509
|
+
Returns:
|
|
510
|
+
The title case string.
|
|
511
|
+
"""
|
|
512
|
+
return var_operation_return(
|
|
513
|
+
js_expression=f"{string}.split(' ').map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(' ')",
|
|
514
|
+
var_type=str,
|
|
515
|
+
)
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
@var_operation
|
|
519
|
+
def string_capitalize_operation(string: StringVar[Any]):
|
|
520
|
+
"""Capitalize a string.
|
|
521
|
+
|
|
522
|
+
Args:
|
|
523
|
+
string: The string to capitalize.
|
|
524
|
+
|
|
525
|
+
Returns:
|
|
526
|
+
The capitalized string.
|
|
527
|
+
"""
|
|
528
|
+
return var_operation_return(
|
|
529
|
+
js_expression=f"(((s) => s.charAt(0).toUpperCase() + s.slice(1).toLowerCase())({string}))",
|
|
530
|
+
var_type=str,
|
|
531
|
+
)
|
|
532
|
+
|
|
533
|
+
|
|
458
534
|
@var_operation
|
|
459
535
|
def string_strip_operation(string: StringVar[Any]):
|
|
460
536
|
"""Strip a string.
|
|
@@ -570,7 +646,7 @@ def array_join_operation(array: ArrayVar, sep: StringVar[Any] | str = ""):
|
|
|
570
646
|
|
|
571
647
|
@var_operation
|
|
572
648
|
def string_replace_operation(
|
|
573
|
-
string: StringVar, search_value: StringVar | str, new_value: StringVar | str
|
|
649
|
+
string: StringVar[Any], search_value: StringVar | str, new_value: StringVar | str
|
|
574
650
|
):
|
|
575
651
|
"""Replace a string with a value.
|
|
576
652
|
|
|
@@ -583,7 +659,7 @@ def string_replace_operation(
|
|
|
583
659
|
The string replace operation.
|
|
584
660
|
"""
|
|
585
661
|
return var_operation_return(
|
|
586
|
-
js_expression=f"{string}.
|
|
662
|
+
js_expression=f"{string}.replaceAll({search_value}, {new_value})",
|
|
587
663
|
var_type=str,
|
|
588
664
|
)
|
|
589
665
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: reflex
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.1
|
|
4
4
|
Summary: Web apps in pure Python.
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
Keywords: web,framework
|
|
@@ -26,7 +26,7 @@ Requires-Dist: lazy_loader (>=0.4)
|
|
|
26
26
|
Requires-Dist: packaging (>=23.1,<25.0)
|
|
27
27
|
Requires-Dist: platformdirs (>=3.10.0,<5.0)
|
|
28
28
|
Requires-Dist: psutil (>=5.9.4,<7.0)
|
|
29
|
-
Requires-Dist: pydantic (>=1.10.
|
|
29
|
+
Requires-Dist: pydantic (>=1.10.21,<3.0)
|
|
30
30
|
Requires-Dist: python-engineio (!=4.6.0)
|
|
31
31
|
Requires-Dist: python-multipart (>=0.0.5,<0.1)
|
|
32
32
|
Requires-Dist: python-socketio (>=5.7.0,<6.0)
|
|
@@ -38,12 +38,11 @@ Requires-Dist: sqlmodel (>=0.0.14,<0.1)
|
|
|
38
38
|
Requires-Dist: starlette-admin (>=0.11.0,<1.0)
|
|
39
39
|
Requires-Dist: tomlkit (>=0.12.4,<1.0)
|
|
40
40
|
Requires-Dist: twine (>=4.0.0,<7.0)
|
|
41
|
-
Requires-Dist: typer (>=0.
|
|
41
|
+
Requires-Dist: typer (>=0.15.1,<1.0)
|
|
42
42
|
Requires-Dist: typing_extensions (>=4.6.0)
|
|
43
43
|
Requires-Dist: uvicorn (>=0.20.0)
|
|
44
44
|
Requires-Dist: wheel (>=0.42.0,<1.0)
|
|
45
|
-
Requires-Dist: wrapt (>=1.
|
|
46
|
-
Requires-Dist: wrapt (>=1.14.0,<2.0) ; python_version >= "3.11"
|
|
45
|
+
Requires-Dist: wrapt (>=1.17.0,<2.0)
|
|
47
46
|
Project-URL: Documentation, https://reflex.dev/docs/getting-started/introduction
|
|
48
47
|
Project-URL: Homepage, https://reflex.dev
|
|
49
48
|
Project-URL: Repository, https://github.com/reflex-dev/reflex
|