reflex 0.5.10a3__py3-none-any.whl → 0.6.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of reflex might be problematic. Click here for more details.
- reflex/.templates/jinja/custom_components/pyproject.toml.jinja2 +2 -2
- reflex/.templates/jinja/web/pages/_app.js.jinja2 +1 -1
- reflex/.templates/jinja/web/pages/utils.js.jinja2 +4 -4
- reflex/.templates/jinja/web/utils/context.js.jinja2 +1 -1
- reflex/.templates/jinja/web/utils/theme.js.jinja2 +1 -1
- reflex/.templates/web/utils/state.js +3 -1
- reflex/__init__.py +10 -3
- reflex/__init__.pyi +3 -2
- reflex/app.py +47 -11
- reflex/app_module_for_backend.py +1 -1
- reflex/base.py +3 -2
- reflex/compiler/compiler.py +5 -5
- reflex/compiler/utils.py +5 -3
- reflex/components/base/app_wrap.py +2 -4
- reflex/components/base/app_wrap.pyi +16 -26
- reflex/components/base/bare.py +6 -4
- reflex/components/base/body.pyi +16 -26
- reflex/components/base/document.pyi +76 -126
- reflex/components/base/error_boundary.py +9 -8
- reflex/components/base/error_boundary.pyi +18 -30
- reflex/components/base/fragment.pyi +16 -26
- reflex/components/base/head.pyi +31 -51
- reflex/components/base/link.py +1 -1
- reflex/components/base/link.pyi +31 -51
- reflex/components/base/meta.pyi +61 -101
- reflex/components/base/script.py +2 -2
- reflex/components/base/script.pyi +20 -36
- reflex/components/component.py +107 -130
- reflex/components/core/banner.py +61 -66
- reflex/components/core/banner.pyi +129 -230
- reflex/components/core/client_side_routing.py +2 -2
- reflex/components/core/client_side_routing.pyi +31 -51
- reflex/components/core/clipboard.py +4 -3
- reflex/components/core/clipboard.pyi +19 -31
- reflex/components/core/cond.py +21 -44
- reflex/components/core/debounce.py +7 -9
- reflex/components/core/debounce.pyi +19 -31
- reflex/components/core/foreach.py +4 -14
- reflex/components/core/html.py +1 -1
- reflex/components/core/html.pyi +34 -44
- reflex/components/core/match.py +36 -43
- reflex/components/core/upload.py +27 -26
- reflex/components/core/upload.pyi +81 -116
- reflex/components/datadisplay/code.py +55 -29
- reflex/components/datadisplay/code.pyi +303 -410
- reflex/components/datadisplay/dataeditor.py +13 -9
- reflex/components/datadisplay/dataeditor.pyi +39 -51
- reflex/components/el/__init__.py +0 -1
- reflex/components/el/__init__.pyi +0 -11
- reflex/components/el/element.pyi +16 -26
- reflex/components/el/elements/__init__.py +1 -7
- reflex/components/el/elements/__init__.pyi +1 -15
- reflex/components/el/elements/base.py +1 -1
- reflex/components/el/elements/base.pyi +33 -43
- reflex/components/el/elements/forms.py +26 -33
- reflex/components/el/elements/forms.pyi +542 -694
- reflex/components/el/elements/inline.py +1 -1
- reflex/components/el/elements/inline.pyi +909 -1189
- reflex/components/el/elements/media.py +1 -22
- reflex/components/el/elements/media.pyi +765 -975
- reflex/components/el/elements/metadata.py +3 -5
- reflex/components/el/elements/metadata.pyi +175 -235
- reflex/components/el/elements/other.py +1 -1
- reflex/components/el/elements/other.pyi +228 -298
- reflex/components/el/elements/scripts.py +1 -1
- reflex/components/el/elements/scripts.pyi +106 -136
- reflex/components/el/elements/sectioning.py +0 -2
- reflex/components/el/elements/sectioning.pyi +481 -631
- reflex/components/el/elements/tables.py +1 -1
- reflex/components/el/elements/tables.pyi +341 -441
- reflex/components/el/elements/typography.py +1 -1
- reflex/components/el/elements/typography.pyi +491 -641
- reflex/components/gridjs/datatable.py +9 -13
- reflex/components/gridjs/datatable.pyi +33 -53
- reflex/components/lucide/icon.py +3 -127
- reflex/components/lucide/icon.pyi +31 -160
- reflex/components/markdown/markdown.py +32 -42
- reflex/components/markdown/markdown.pyi +28 -41
- reflex/components/moment/moment.py +13 -12
- reflex/components/moment/moment.pyi +22 -33
- reflex/components/next/base.pyi +16 -26
- reflex/components/next/image.py +1 -5
- reflex/components/next/image.pyi +21 -35
- reflex/components/next/link.py +1 -1
- reflex/components/next/link.pyi +16 -26
- reflex/components/next/video.py +1 -1
- reflex/components/next/video.pyi +16 -26
- reflex/components/plotly/plotly.py +17 -30
- reflex/components/plotly/plotly.pyi +38 -52
- reflex/components/props.py +21 -10
- reflex/components/radix/__init__.pyi +2 -1
- reflex/components/radix/primitives/accordion.py +6 -7
- reflex/components/radix/primitives/accordion.pyi +415 -485
- reflex/components/radix/primitives/base.py +1 -1
- reflex/components/radix/primitives/base.pyi +31 -51
- reflex/components/radix/primitives/drawer.py +1 -1
- reflex/components/radix/primitives/drawer.pyi +162 -262
- reflex/components/radix/primitives/form.py +1 -1
- reflex/components/radix/primitives/form.pyi +247 -353
- reflex/components/radix/primitives/progress.py +1 -1
- reflex/components/radix/primitives/progress.pyi +226 -276
- reflex/components/radix/primitives/slider.py +1 -1
- reflex/components/radix/primitives/slider.pyi +82 -132
- reflex/components/radix/themes/base.py +8 -25
- reflex/components/radix/themes/base.pyi +171 -242
- reflex/components/radix/themes/color_mode.py +11 -20
- reflex/components/radix/themes/color_mode.pyi +198 -231
- reflex/components/radix/themes/components/__init__.pyi +1 -0
- reflex/components/radix/themes/components/alert_dialog.py +1 -1
- reflex/components/radix/themes/components/alert_dialog.pyi +129 -199
- reflex/components/radix/themes/components/aspect_ratio.py +1 -1
- reflex/components/radix/themes/components/aspect_ratio.pyi +16 -26
- reflex/components/radix/themes/components/avatar.py +1 -1
- reflex/components/radix/themes/components/avatar.pyi +69 -79
- reflex/components/radix/themes/components/badge.py +1 -1
- reflex/components/radix/themes/components/badge.pyi +87 -97
- reflex/components/radix/themes/components/button.py +1 -1
- reflex/components/radix/themes/components/button.pyi +97 -107
- reflex/components/radix/themes/components/callout.py +1 -1
- reflex/components/radix/themes/components/callout.pyi +317 -367
- reflex/components/radix/themes/components/card.py +1 -1
- reflex/components/radix/themes/components/card.pyi +37 -47
- reflex/components/radix/themes/components/checkbox.py +2 -4
- reflex/components/radix/themes/components/checkbox.pyi +205 -241
- reflex/components/radix/themes/components/checkbox_cards.py +1 -1
- reflex/components/radix/themes/components/checkbox_cards.pyi +92 -112
- reflex/components/radix/themes/components/checkbox_group.py +1 -1
- reflex/components/radix/themes/components/checkbox_group.pyi +84 -104
- reflex/components/radix/themes/components/context_menu.py +1 -1
- reflex/components/radix/themes/components/context_menu.pyi +230 -310
- reflex/components/radix/themes/components/data_list.py +6 -1
- reflex/components/radix/themes/components/data_list.pyi +131 -166
- reflex/components/radix/themes/components/dialog.py +1 -1
- reflex/components/radix/themes/components/dialog.pyi +132 -202
- reflex/components/radix/themes/components/dropdown_menu.py +1 -1
- reflex/components/radix/themes/components/dropdown_menu.pyi +241 -323
- reflex/components/radix/themes/components/hover_card.py +1 -1
- reflex/components/radix/themes/components/hover_card.pyi +86 -126
- reflex/components/radix/themes/components/icon_button.py +1 -1
- reflex/components/radix/themes/components/icon_button.pyi +97 -107
- reflex/components/radix/themes/components/inset.py +1 -1
- reflex/components/radix/themes/components/inset.pyi +46 -56
- reflex/components/radix/themes/components/popover.py +1 -1
- reflex/components/radix/themes/components/popover.pyi +91 -131
- reflex/components/radix/themes/components/progress.py +1 -1
- reflex/components/radix/themes/components/progress.pyi +70 -80
- reflex/components/radix/themes/components/radio.py +1 -1
- reflex/components/radix/themes/components/radio.pyi +68 -78
- reflex/components/radix/themes/components/radio_cards.py +1 -1
- reflex/components/radix/themes/components/radio_cards.pyi +96 -116
- reflex/components/radix/themes/components/radio_group.py +32 -31
- reflex/components/radix/themes/components/radio_group.pyi +230 -266
- reflex/components/radix/themes/components/scroll_area.py +1 -1
- reflex/components/radix/themes/components/scroll_area.pyi +20 -30
- reflex/components/radix/themes/components/segmented_control.py +1 -1
- reflex/components/radix/themes/components/segmented_control.pyi +88 -110
- reflex/components/radix/themes/components/select.py +1 -1
- reflex/components/radix/themes/components/select.pyi +365 -461
- reflex/components/radix/themes/components/separator.py +2 -4
- reflex/components/radix/themes/components/separator.pyi +68 -78
- reflex/components/radix/themes/components/skeleton.py +1 -1
- reflex/components/radix/themes/components/skeleton.pyi +22 -32
- reflex/components/radix/themes/components/slider.py +1 -1
- reflex/components/radix/themes/components/slider.pyi +74 -86
- reflex/components/radix/themes/components/spinner.py +1 -1
- reflex/components/radix/themes/components/spinner.pyi +18 -28
- reflex/components/radix/themes/components/switch.py +1 -1
- reflex/components/radix/themes/components/switch.pyi +70 -82
- reflex/components/radix/themes/components/table.py +1 -1
- reflex/components/radix/themes/components/table.pyi +254 -324
- reflex/components/radix/themes/components/tabs.py +1 -1
- reflex/components/radix/themes/components/tabs.pyi +134 -188
- reflex/components/radix/themes/components/text_area.py +1 -1
- reflex/components/radix/themes/components/text_area.pyi +95 -109
- reflex/components/radix/themes/components/text_field.py +1 -80
- reflex/components/radix/themes/components/text_field.pyi +245 -290
- reflex/components/radix/themes/components/tooltip.py +1 -1
- reflex/components/radix/themes/components/tooltip.pyi +25 -35
- reflex/components/radix/themes/layout/__init__.pyi +1 -0
- reflex/components/radix/themes/layout/base.py +1 -1
- reflex/components/radix/themes/layout/base.pyi +55 -65
- reflex/components/radix/themes/layout/box.pyi +33 -43
- reflex/components/radix/themes/layout/center.pyi +55 -65
- reflex/components/radix/themes/layout/container.py +2 -4
- reflex/components/radix/themes/layout/container.pyi +35 -45
- reflex/components/radix/themes/layout/flex.py +1 -1
- reflex/components/radix/themes/layout/flex.pyi +55 -65
- reflex/components/radix/themes/layout/grid.py +1 -1
- reflex/components/radix/themes/layout/grid.pyi +63 -73
- reflex/components/radix/themes/layout/list.py +1 -1
- reflex/components/radix/themes/layout/list.pyi +188 -238
- reflex/components/radix/themes/layout/section.py +2 -4
- reflex/components/radix/themes/layout/section.pyi +35 -45
- reflex/components/radix/themes/layout/spacer.pyi +55 -65
- reflex/components/radix/themes/layout/stack.py +1 -1
- reflex/components/radix/themes/layout/stack.pyi +125 -155
- reflex/components/radix/themes/typography/blockquote.py +1 -1
- reflex/components/radix/themes/typography/blockquote.pyi +88 -98
- reflex/components/radix/themes/typography/code.py +1 -1
- reflex/components/radix/themes/typography/code.pyi +89 -99
- reflex/components/radix/themes/typography/heading.py +1 -1
- reflex/components/radix/themes/typography/heading.pyi +95 -105
- reflex/components/radix/themes/typography/link.py +1 -1
- reflex/components/radix/themes/typography/link.pyi +101 -111
- reflex/components/radix/themes/typography/text.py +1 -1
- reflex/components/radix/themes/typography/text.pyi +494 -564
- reflex/components/react_player/audio.pyi +32 -58
- reflex/components/react_player/react_player.py +1 -1
- reflex/components/react_player/react_player.pyi +32 -58
- reflex/components/react_player/video.pyi +32 -58
- reflex/components/recharts/cartesian.py +22 -19
- reflex/components/recharts/cartesian.pyi +658 -840
- reflex/components/recharts/charts.py +3 -3
- reflex/components/recharts/charts.pyi +238 -342
- reflex/components/recharts/general.py +8 -8
- reflex/components/recharts/general.pyi +175 -225
- reflex/components/recharts/polar.py +11 -11
- reflex/components/recharts/polar.pyi +135 -171
- reflex/components/recharts/recharts.pyi +31 -51
- reflex/components/sonner/toast.py +27 -31
- reflex/components/sonner/toast.pyi +36 -45
- reflex/components/suneditor/editor.py +1 -1
- reflex/components/suneditor/editor.pyi +54 -76
- reflex/components/tags/cond_tag.py +6 -4
- reflex/components/tags/iter_tag.py +37 -25
- reflex/components/tags/match_tag.py +6 -4
- reflex/components/tags/tag.py +43 -28
- reflex/constants/base.py +3 -1
- reflex/constants/event.py +1 -0
- reflex/custom_components/custom_components.py +3 -1
- reflex/event.py +166 -108
- reflex/experimental/__init__.py +25 -6
- reflex/experimental/client_state.py +34 -57
- reflex/experimental/hooks.py +12 -17
- reflex/experimental/layout.py +4 -4
- reflex/experimental/layout.pyi +130 -180
- reflex/middleware/hydrate_middleware.py +2 -0
- reflex/middleware/middleware.py +3 -3
- reflex/model.py +22 -0
- reflex/reflex.py +4 -0
- reflex/state.py +491 -110
- reflex/style.py +56 -39
- reflex/testing.py +8 -3
- reflex/utils/exceptions.py +32 -0
- reflex/utils/exec.py +0 -14
- reflex/utils/format.py +80 -209
- reflex/utils/imports.py +16 -73
- reflex/utils/net.py +43 -0
- reflex/utils/path_ops.py +13 -1
- reflex/utils/prerequisites.py +81 -41
- reflex/utils/pyi_generator.py +12 -6
- reflex/utils/serializers.py +13 -41
- reflex/utils/telemetry.py +3 -2
- reflex/utils/types.py +47 -7
- reflex/{experimental/vars → vars}/__init__.py +6 -3
- reflex/vars/base.py +2563 -0
- reflex/vars/function.py +196 -0
- reflex/vars/number.py +1158 -0
- reflex/vars/object.py +562 -0
- reflex/vars/sequence.py +1604 -0
- {reflex-0.5.10a3.dist-info → reflex-0.6.0.dist-info}/METADATA +6 -9
- reflex-0.6.0.dist-info/RECORD +382 -0
- reflex/.templates/apps/demo/.gitignore +0 -4
- reflex/.templates/apps/demo/assets/favicon.ico +0 -0
- reflex/.templates/apps/demo/assets/github.svg +0 -10
- reflex/.templates/apps/demo/assets/icon.svg +0 -37
- reflex/.templates/apps/demo/assets/logo.svg +0 -68
- reflex/.templates/apps/demo/assets/paneleft.svg +0 -13
- reflex/.templates/apps/demo/code/__init__.py +0 -1
- reflex/.templates/apps/demo/code/demo.py +0 -127
- reflex/.templates/apps/demo/code/pages/__init__.py +0 -7
- reflex/.templates/apps/demo/code/pages/chatapp.py +0 -31
- reflex/.templates/apps/demo/code/pages/datatable.py +0 -360
- reflex/.templates/apps/demo/code/pages/forms.py +0 -257
- reflex/.templates/apps/demo/code/pages/graphing.py +0 -253
- reflex/.templates/apps/demo/code/pages/home.py +0 -56
- reflex/.templates/apps/demo/code/sidebar.py +0 -178
- reflex/.templates/apps/demo/code/state.py +0 -22
- reflex/.templates/apps/demo/code/states/form_state.py +0 -40
- reflex/.templates/apps/demo/code/states/pie_state.py +0 -47
- reflex/.templates/apps/demo/code/styles.py +0 -68
- reflex/.templates/apps/demo/code/webui/__init__.py +0 -0
- reflex/.templates/apps/demo/code/webui/components/__init__.py +0 -4
- reflex/.templates/apps/demo/code/webui/components/chat.py +0 -118
- reflex/.templates/apps/demo/code/webui/components/loading_icon.py +0 -19
- reflex/.templates/apps/demo/code/webui/components/modal.py +0 -56
- reflex/.templates/apps/demo/code/webui/components/navbar.py +0 -70
- reflex/.templates/apps/demo/code/webui/components/sidebar.py +0 -66
- reflex/.templates/apps/demo/code/webui/state.py +0 -146
- reflex/.templates/apps/demo/code/webui/styles.py +0 -88
- reflex/.templates/web/components/reflex/chakra_color_mode_provider.js +0 -36
- reflex/experimental/vars/base.py +0 -583
- reflex/experimental/vars/function.py +0 -290
- reflex/experimental/vars/number.py +0 -1458
- reflex/experimental/vars/object.py +0 -804
- reflex/experimental/vars/sequence.py +0 -1764
- reflex/utils/watch.py +0 -96
- reflex/vars.py +0 -2604
- reflex/vars.pyi +0 -218
- reflex-0.5.10a3.dist-info/RECORD +0 -413
- {reflex-0.5.10a3.dist-info → reflex-0.6.0.dist-info}/LICENSE +0 -0
- {reflex-0.5.10a3.dist-info → reflex-0.6.0.dist-info}/WHEEL +0 -0
- {reflex-0.5.10a3.dist-info → reflex-0.6.0.dist-info}/entry_points.txt +0 -0
reflex/utils/prerequisites.py
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import dataclasses
|
|
5
6
|
import functools
|
|
6
7
|
import glob
|
|
7
8
|
import importlib
|
|
@@ -28,20 +29,21 @@ import typer
|
|
|
28
29
|
from alembic.util.exc import CommandError
|
|
29
30
|
from packaging import version
|
|
30
31
|
from redis import Redis as RedisSync
|
|
32
|
+
from redis import exceptions
|
|
31
33
|
from redis.asyncio import Redis
|
|
32
34
|
|
|
33
35
|
from reflex import constants, model
|
|
34
|
-
from reflex.base import Base
|
|
35
36
|
from reflex.compiler import templates
|
|
36
37
|
from reflex.config import Config, get_config
|
|
37
|
-
from reflex.utils import console, path_ops, processes
|
|
38
|
+
from reflex.utils import console, net, path_ops, processes
|
|
38
39
|
from reflex.utils.format import format_library_name
|
|
39
40
|
from reflex.utils.registry import _get_best_registry
|
|
40
41
|
|
|
41
42
|
CURRENTLY_INSTALLING_NODE = False
|
|
42
43
|
|
|
43
44
|
|
|
44
|
-
|
|
45
|
+
@dataclasses.dataclass(frozen=True)
|
|
46
|
+
class Template:
|
|
45
47
|
"""A template for a Reflex app."""
|
|
46
48
|
|
|
47
49
|
name: str
|
|
@@ -50,7 +52,8 @@ class Template(Base):
|
|
|
50
52
|
demo_url: str
|
|
51
53
|
|
|
52
54
|
|
|
53
|
-
|
|
55
|
+
@dataclasses.dataclass(frozen=True)
|
|
56
|
+
class CpuInfo:
|
|
54
57
|
"""Model to save cpu info."""
|
|
55
58
|
|
|
56
59
|
manufacturer_id: Optional[str]
|
|
@@ -70,6 +73,18 @@ def get_web_dir() -> Path:
|
|
|
70
73
|
return workdir
|
|
71
74
|
|
|
72
75
|
|
|
76
|
+
def _python_version_check():
|
|
77
|
+
"""Emit deprecation warning for deprecated python versions."""
|
|
78
|
+
# Check for end-of-life python versions.
|
|
79
|
+
if sys.version_info < (3, 10):
|
|
80
|
+
console.deprecate(
|
|
81
|
+
feature_name="Support for Python 3.9 and older",
|
|
82
|
+
reason="please upgrade to Python 3.10 or newer",
|
|
83
|
+
deprecation_version="0.6.0",
|
|
84
|
+
removal_version="0.7.0",
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
|
|
73
88
|
def check_latest_package_version(package_name: str):
|
|
74
89
|
"""Check if the latest version of the package is installed.
|
|
75
90
|
|
|
@@ -80,17 +95,18 @@ def check_latest_package_version(package_name: str):
|
|
|
80
95
|
# Get the latest version from PyPI
|
|
81
96
|
current_version = importlib.metadata.version(package_name)
|
|
82
97
|
url = f"https://pypi.org/pypi/{package_name}/json"
|
|
83
|
-
response =
|
|
98
|
+
response = net.get(url)
|
|
84
99
|
latest_version = response.json()["info"]["version"]
|
|
85
|
-
if (
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
):
|
|
89
|
-
#
|
|
90
|
-
# the last_version_check_datetime is not set in reflex.json
|
|
100
|
+
if get_or_set_last_reflex_version_check_datetime():
|
|
101
|
+
# Versions were already checked and saved in reflex.json, no need to warn again
|
|
102
|
+
return
|
|
103
|
+
if version.parse(current_version) < version.parse(latest_version):
|
|
104
|
+
# Show a warning when the host version is older than PyPI version
|
|
91
105
|
console.warn(
|
|
92
106
|
f"Your version ({current_version}) of {package_name} is out of date. Upgrade to {latest_version} with 'pip install {package_name} --upgrade'"
|
|
93
107
|
)
|
|
108
|
+
# Check for depreacted python versions
|
|
109
|
+
_python_version_check()
|
|
94
110
|
except Exception:
|
|
95
111
|
pass
|
|
96
112
|
|
|
@@ -287,7 +303,7 @@ def get_compiled_app(reload: bool = False, export: bool = False) -> ModuleType:
|
|
|
287
303
|
"""
|
|
288
304
|
app_module = get_app(reload=reload)
|
|
289
305
|
app = getattr(app_module, constants.CompileVars.APP)
|
|
290
|
-
# For py3.
|
|
306
|
+
# For py3.9 compatibility when redis is used, we MUST add any decorator pages
|
|
291
307
|
# before compiling the app in a thread to avoid event loop error (REF-2172).
|
|
292
308
|
app._apply_decorated_pages()
|
|
293
309
|
app._compile(export=export)
|
|
@@ -324,24 +340,43 @@ def parse_redis_url() -> str | dict | None:
|
|
|
324
340
|
"""Parse the REDIS_URL in config if applicable.
|
|
325
341
|
|
|
326
342
|
Returns:
|
|
327
|
-
If
|
|
343
|
+
If url is non-empty, return the URL as it is.
|
|
344
|
+
|
|
345
|
+
Raises:
|
|
346
|
+
ValueError: If the REDIS_URL is not a supported scheme.
|
|
328
347
|
"""
|
|
329
348
|
config = get_config()
|
|
330
349
|
if not config.redis_url:
|
|
331
350
|
return None
|
|
332
|
-
if config.redis_url.startswith(("redis://", "rediss://", "unix://")):
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
351
|
+
if not config.redis_url.startswith(("redis://", "rediss://", "unix://")):
|
|
352
|
+
raise ValueError(
|
|
353
|
+
"REDIS_URL must start with 'redis://', 'rediss://', or 'unix://'."
|
|
354
|
+
)
|
|
355
|
+
return config.redis_url
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
async def get_redis_status() -> bool | None:
|
|
359
|
+
"""Checks the status of the Redis connection.
|
|
360
|
+
|
|
361
|
+
Attempts to connect to Redis and send a ping command to verify connectivity.
|
|
362
|
+
|
|
363
|
+
Returns:
|
|
364
|
+
bool or None: The status of the Redis connection:
|
|
365
|
+
- True: Redis is accessible and responding.
|
|
366
|
+
- False: Redis is not accessible due to a connection error.
|
|
367
|
+
- None: Redis not used i.e redis_url is not set in rxconfig.
|
|
368
|
+
"""
|
|
369
|
+
try:
|
|
370
|
+
status = True
|
|
371
|
+
redis_client = get_redis_sync()
|
|
372
|
+
if redis_client is not None:
|
|
373
|
+
redis_client.ping()
|
|
374
|
+
else:
|
|
375
|
+
status = None
|
|
376
|
+
except exceptions.RedisError:
|
|
377
|
+
status = False
|
|
378
|
+
|
|
379
|
+
return status
|
|
345
380
|
|
|
346
381
|
|
|
347
382
|
def validate_app_name(app_name: str | None = None) -> str:
|
|
@@ -670,7 +705,7 @@ def download_and_run(url: str, *args, show_status: bool = False, **env):
|
|
|
670
705
|
"""
|
|
671
706
|
# Download the script
|
|
672
707
|
console.debug(f"Downloading {url}")
|
|
673
|
-
response =
|
|
708
|
+
response = net.get(url)
|
|
674
709
|
if response.status_code != httpx.codes.OK:
|
|
675
710
|
response.raise_for_status()
|
|
676
711
|
|
|
@@ -700,11 +735,11 @@ def download_and_extract_fnm_zip():
|
|
|
700
735
|
try:
|
|
701
736
|
# Download the FNM zip release.
|
|
702
737
|
# TODO: show progress to improve UX
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
738
|
+
response = net.get(url, follow_redirects=True)
|
|
739
|
+
response.raise_for_status()
|
|
740
|
+
with open(fnm_zip_file, "wb") as output_file:
|
|
741
|
+
for chunk in response.iter_bytes():
|
|
742
|
+
output_file.write(chunk)
|
|
708
743
|
|
|
709
744
|
# Extract the downloaded zip file.
|
|
710
745
|
with zipfile.ZipFile(fnm_zip_file, "r") as zip_ref:
|
|
@@ -1222,7 +1257,7 @@ def fetch_app_templates(version: str) -> dict[str, Template]:
|
|
|
1222
1257
|
"""
|
|
1223
1258
|
|
|
1224
1259
|
def get_release_by_tag(tag: str) -> dict | None:
|
|
1225
|
-
response =
|
|
1260
|
+
response = net.get(constants.Reflex.RELEASES_URL)
|
|
1226
1261
|
response.raise_for_status()
|
|
1227
1262
|
releases = response.json()
|
|
1228
1263
|
for release in releases:
|
|
@@ -1243,7 +1278,7 @@ def fetch_app_templates(version: str) -> dict[str, Template]:
|
|
|
1243
1278
|
else:
|
|
1244
1279
|
templates_url = asset["browser_download_url"]
|
|
1245
1280
|
|
|
1246
|
-
templates_data =
|
|
1281
|
+
templates_data = net.get(templates_url, follow_redirects=True).json()["templates"]
|
|
1247
1282
|
|
|
1248
1283
|
for template in templates_data:
|
|
1249
1284
|
if template["name"] == "blank":
|
|
@@ -1257,11 +1292,16 @@ def fetch_app_templates(version: str) -> dict[str, Template]:
|
|
|
1257
1292
|
),
|
|
1258
1293
|
None,
|
|
1259
1294
|
)
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
if
|
|
1264
|
-
|
|
1295
|
+
|
|
1296
|
+
filtered_templates = {}
|
|
1297
|
+
for tp in templates_data:
|
|
1298
|
+
if tp["hidden"] or tp["code_url"] is None:
|
|
1299
|
+
continue
|
|
1300
|
+
known_fields = set(f.name for f in dataclasses.fields(Template))
|
|
1301
|
+
filtered_templates[tp["name"]] = Template(
|
|
1302
|
+
**{k: v for k, v in tp.items() if k in known_fields}
|
|
1303
|
+
)
|
|
1304
|
+
return filtered_templates
|
|
1265
1305
|
|
|
1266
1306
|
|
|
1267
1307
|
def create_config_init_app_from_remote_template(app_name: str, template_url: str):
|
|
@@ -1286,7 +1326,7 @@ def create_config_init_app_from_remote_template(app_name: str, template_url: str
|
|
|
1286
1326
|
zip_file_path = Path(temp_dir) / "template.zip"
|
|
1287
1327
|
try:
|
|
1288
1328
|
# Note: following redirects can be risky. We only allow this for reflex built templates at the moment.
|
|
1289
|
-
response =
|
|
1329
|
+
response = net.get(template_url, follow_redirects=True)
|
|
1290
1330
|
console.debug(f"Server responded download request: {response}")
|
|
1291
1331
|
response.raise_for_status()
|
|
1292
1332
|
except httpx.HTTPError as he:
|
|
@@ -1417,7 +1457,7 @@ def initialize_main_module_index_from_generation(app_name: str, generation_hash:
|
|
|
1417
1457
|
generation_hash: The generation hash from reflex.build.
|
|
1418
1458
|
"""
|
|
1419
1459
|
# Download the reflex code for the generation.
|
|
1420
|
-
resp =
|
|
1460
|
+
resp = net.get(
|
|
1421
1461
|
constants.Templates.REFLEX_BUILD_CODE_URL.format(
|
|
1422
1462
|
generation_hash=generation_hash
|
|
1423
1463
|
)
|
reflex/utils/pyi_generator.py
CHANGED
|
@@ -20,7 +20,7 @@ from typing import Any, Callable, Iterable, Type, get_args
|
|
|
20
20
|
|
|
21
21
|
from reflex.components.component import Component
|
|
22
22
|
from reflex.utils import types as rx_types
|
|
23
|
-
from reflex.vars import Var
|
|
23
|
+
from reflex.vars.base import Var
|
|
24
24
|
|
|
25
25
|
logger = logging.getLogger("pyi_generator")
|
|
26
26
|
|
|
@@ -69,10 +69,10 @@ DEFAULT_TYPING_IMPORTS = {
|
|
|
69
69
|
# TODO: fix import ordering and unused imports with ruff later
|
|
70
70
|
DEFAULT_IMPORTS = {
|
|
71
71
|
"typing": sorted(DEFAULT_TYPING_IMPORTS),
|
|
72
|
-
"reflex.vars": ["Var", "BaseVar", "ComputedVar"],
|
|
73
72
|
"reflex.components.core.breakpoints": ["Breakpoints"],
|
|
74
73
|
"reflex.event": ["EventChain", "EventHandler", "EventSpec"],
|
|
75
74
|
"reflex.style": ["Style"],
|
|
75
|
+
"reflex.vars.base": ["Var"],
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
|
|
@@ -150,7 +150,7 @@ def _get_type_hint(value, type_hint_globals, is_optional=True) -> str:
|
|
|
150
150
|
|
|
151
151
|
if args:
|
|
152
152
|
inner_container_type_args = (
|
|
153
|
-
|
|
153
|
+
sorted((repr(arg) for arg in args))
|
|
154
154
|
if rx_types.is_literal(value)
|
|
155
155
|
else [
|
|
156
156
|
_get_type_hint(arg, type_hint_globals, is_optional=False)
|
|
@@ -184,7 +184,7 @@ def _get_type_hint(value, type_hint_globals, is_optional=True) -> str:
|
|
|
184
184
|
if arg is not type(None)
|
|
185
185
|
]
|
|
186
186
|
if len(types) > 1:
|
|
187
|
-
res = ", ".join(types)
|
|
187
|
+
res = ", ".join(sorted(types))
|
|
188
188
|
res = f"Union[{res}]"
|
|
189
189
|
elif isinstance(value, str):
|
|
190
190
|
ev = eval(value, type_hint_globals)
|
|
@@ -433,7 +433,7 @@ def _generate_component_create_functiondef(
|
|
|
433
433
|
ast.arg(
|
|
434
434
|
arg=trigger,
|
|
435
435
|
annotation=ast.Name(
|
|
436
|
-
id="Optional[Union[EventHandler, EventSpec, list, Callable,
|
|
436
|
+
id="Optional[Union[EventHandler, EventSpec, list, Callable, Var]]"
|
|
437
437
|
),
|
|
438
438
|
),
|
|
439
439
|
ast.Constant(value=None),
|
|
@@ -902,7 +902,13 @@ class PyiGenerator:
|
|
|
902
902
|
# construct the import statement and handle special cases for aliases
|
|
903
903
|
sub_mod_attrs_imports = [
|
|
904
904
|
f"from .{path} import {mod if not isinstance(mod, tuple) else mod[0]} as {mod if not isinstance(mod, tuple) else mod[1]}"
|
|
905
|
-
+ (
|
|
905
|
+
+ (
|
|
906
|
+
" # type: ignore"
|
|
907
|
+
if mod in pyright_ignore_imports
|
|
908
|
+
else " # noqa" # ignore ruff formatting here for cases like rx.list.
|
|
909
|
+
if isinstance(mod, tuple)
|
|
910
|
+
else ""
|
|
911
|
+
)
|
|
906
912
|
for mod, path in sub_mod_attrs.items()
|
|
907
913
|
]
|
|
908
914
|
sub_mod_attrs_imports.append("")
|
reflex/utils/serializers.py
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import dataclasses
|
|
5
6
|
import functools
|
|
6
7
|
import json
|
|
7
|
-
import types as builtin_types
|
|
8
8
|
import warnings
|
|
9
9
|
from datetime import date, datetime, time, timedelta
|
|
10
10
|
from enum import Enum
|
|
@@ -26,11 +26,11 @@ from typing import (
|
|
|
26
26
|
|
|
27
27
|
from reflex.base import Base
|
|
28
28
|
from reflex.constants.colors import Color, format_color
|
|
29
|
-
from reflex.utils import
|
|
29
|
+
from reflex.utils import types
|
|
30
30
|
|
|
31
31
|
# Mapping from type to a serializer.
|
|
32
32
|
# The serializer should convert the type to a JSON object.
|
|
33
|
-
SerializedType = Union[str, bool, int, float, list, dict]
|
|
33
|
+
SerializedType = Union[str, bool, int, float, list, dict, None]
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
Serializer = Callable[[Type], SerializedType]
|
|
@@ -125,6 +125,8 @@ def serialize(
|
|
|
125
125
|
|
|
126
126
|
# If there is no serializer, return None.
|
|
127
127
|
if serializer is None:
|
|
128
|
+
if dataclasses.is_dataclass(value) and not isinstance(value, type):
|
|
129
|
+
return serialize(dataclasses.asdict(value))
|
|
128
130
|
if get_type:
|
|
129
131
|
return None, None
|
|
130
132
|
return None
|
|
@@ -226,7 +228,7 @@ def serialize_str(value: str) -> str:
|
|
|
226
228
|
|
|
227
229
|
|
|
228
230
|
@serializer
|
|
229
|
-
def serialize_primitive(value: Union[bool, int, float, None])
|
|
231
|
+
def serialize_primitive(value: Union[bool, int, float, None]):
|
|
230
232
|
"""Serialize a primitive type.
|
|
231
233
|
|
|
232
234
|
Args:
|
|
@@ -235,13 +237,11 @@ def serialize_primitive(value: Union[bool, int, float, None]) -> str:
|
|
|
235
237
|
Returns:
|
|
236
238
|
The serialized number/bool/None.
|
|
237
239
|
"""
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
return format.json_dumps(value)
|
|
240
|
+
return value
|
|
241
241
|
|
|
242
242
|
|
|
243
243
|
@serializer
|
|
244
|
-
def serialize_base(value: Base) ->
|
|
244
|
+
def serialize_base(value: Base) -> dict:
|
|
245
245
|
"""Serialize a Base instance.
|
|
246
246
|
|
|
247
247
|
Args:
|
|
@@ -250,11 +250,11 @@ def serialize_base(value: Base) -> str:
|
|
|
250
250
|
Returns:
|
|
251
251
|
The serialized Base.
|
|
252
252
|
"""
|
|
253
|
-
return value.
|
|
253
|
+
return {k: serialize(v) for k, v in value.dict().items() if not callable(v)}
|
|
254
254
|
|
|
255
255
|
|
|
256
256
|
@serializer
|
|
257
|
-
def serialize_list(value: Union[List, Tuple, Set]) ->
|
|
257
|
+
def serialize_list(value: Union[List, Tuple, Set]) -> list:
|
|
258
258
|
"""Serialize a list to a JSON string.
|
|
259
259
|
|
|
260
260
|
Args:
|
|
@@ -263,17 +263,11 @@ def serialize_list(value: Union[List, Tuple, Set]) -> str:
|
|
|
263
263
|
Returns:
|
|
264
264
|
The serialized list.
|
|
265
265
|
"""
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
# Dump the list to a string.
|
|
269
|
-
fprop = format.json_dumps(list(value))
|
|
270
|
-
|
|
271
|
-
# Unwrap var values.
|
|
272
|
-
return format.unwrap_vars(fprop)
|
|
266
|
+
return [serialize(item) for item in value]
|
|
273
267
|
|
|
274
268
|
|
|
275
269
|
@serializer
|
|
276
|
-
def serialize_dict(prop: Dict[str, Any]) ->
|
|
270
|
+
def serialize_dict(prop: Dict[str, Any]) -> dict:
|
|
277
271
|
"""Serialize a dictionary to a JSON string.
|
|
278
272
|
|
|
279
273
|
Args:
|
|
@@ -281,30 +275,8 @@ def serialize_dict(prop: Dict[str, Any]) -> str:
|
|
|
281
275
|
|
|
282
276
|
Returns:
|
|
283
277
|
The serialized dictionary.
|
|
284
|
-
|
|
285
|
-
Raises:
|
|
286
|
-
InvalidStylePropError: If the style prop is invalid.
|
|
287
278
|
"""
|
|
288
|
-
|
|
289
|
-
from reflex.event import EventHandler
|
|
290
|
-
from reflex.utils import format
|
|
291
|
-
|
|
292
|
-
prop_dict = {}
|
|
293
|
-
|
|
294
|
-
for key, value in prop.items():
|
|
295
|
-
if types._issubclass(type(value), Callable):
|
|
296
|
-
raise exceptions.InvalidStylePropError(
|
|
297
|
-
f"The style prop `{format.to_snake_case(key)}` cannot have " # type: ignore
|
|
298
|
-
f"`{value.fn.__qualname__ if isinstance(value, EventHandler) else value.__qualname__ if isinstance(value, builtin_types.FunctionType) else value}`, "
|
|
299
|
-
f"an event handler or callable as its value"
|
|
300
|
-
)
|
|
301
|
-
prop_dict[key] = value
|
|
302
|
-
|
|
303
|
-
# Dump the dict to a string.
|
|
304
|
-
fprop = format.json_dumps(prop_dict)
|
|
305
|
-
|
|
306
|
-
# Unwrap var values.
|
|
307
|
-
return format.unwrap_vars(fprop)
|
|
279
|
+
return {k: serialize(v) for k, v in prop.items()}
|
|
308
280
|
|
|
309
281
|
|
|
310
282
|
@serializer(to=str)
|
reflex/utils/telemetry.py
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import asyncio
|
|
6
|
+
import dataclasses
|
|
6
7
|
import multiprocessing
|
|
7
8
|
import platform
|
|
8
9
|
import warnings
|
|
@@ -120,7 +121,7 @@ def _prepare_event(event: str, **kwargs) -> dict:
|
|
|
120
121
|
return {}
|
|
121
122
|
|
|
122
123
|
if UTC is None:
|
|
123
|
-
# for python 3.
|
|
124
|
+
# for python 3.9 & 3.10
|
|
124
125
|
stamp = datetime.utcnow().isoformat()
|
|
125
126
|
else:
|
|
126
127
|
# for python 3.11 & 3.12
|
|
@@ -144,7 +145,7 @@ def _prepare_event(event: str, **kwargs) -> dict:
|
|
|
144
145
|
"python_version": get_python_version(),
|
|
145
146
|
"cpu_count": get_cpu_count(),
|
|
146
147
|
"memory": get_memory(),
|
|
147
|
-
"cpu_info":
|
|
148
|
+
"cpu_info": dataclasses.asdict(cpuinfo) if cpuinfo else {},
|
|
148
149
|
**additional_fields,
|
|
149
150
|
},
|
|
150
151
|
"timestamp": stamp,
|
reflex/utils/types.py
CHANGED
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import contextlib
|
|
6
|
+
import dataclasses
|
|
6
7
|
import inspect
|
|
7
8
|
import sys
|
|
8
9
|
import types
|
|
9
|
-
from functools import cached_property, wraps
|
|
10
|
+
from functools import cached_property, lru_cache, wraps
|
|
10
11
|
from typing import (
|
|
11
12
|
Any,
|
|
12
13
|
Callable,
|
|
@@ -21,9 +22,11 @@ from typing import (
|
|
|
21
22
|
Union,
|
|
22
23
|
_GenericAlias, # type: ignore
|
|
23
24
|
get_args,
|
|
24
|
-
get_origin,
|
|
25
25
|
get_type_hints,
|
|
26
26
|
)
|
|
27
|
+
from typing import (
|
|
28
|
+
get_origin as get_origin_og,
|
|
29
|
+
)
|
|
27
30
|
|
|
28
31
|
import sqlalchemy
|
|
29
32
|
|
|
@@ -109,6 +112,11 @@ RESERVED_BACKEND_VAR_NAMES = {
|
|
|
109
112
|
"_was_touched",
|
|
110
113
|
}
|
|
111
114
|
|
|
115
|
+
if sys.version_info >= (3, 11):
|
|
116
|
+
from typing import Self as Self
|
|
117
|
+
else:
|
|
118
|
+
from typing_extensions import Self as Self
|
|
119
|
+
|
|
112
120
|
|
|
113
121
|
class Unset:
|
|
114
122
|
"""A class to represent an unset value.
|
|
@@ -133,6 +141,20 @@ class Unset:
|
|
|
133
141
|
return False
|
|
134
142
|
|
|
135
143
|
|
|
144
|
+
@lru_cache()
|
|
145
|
+
def get_origin(tp):
|
|
146
|
+
"""Get the origin of a class.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
tp: The class to get the origin of.
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
The origin of the class.
|
|
153
|
+
"""
|
|
154
|
+
return get_origin_og(tp)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
@lru_cache()
|
|
136
158
|
def is_generic_alias(cls: GenericType) -> bool:
|
|
137
159
|
"""Check whether the class is a generic alias.
|
|
138
160
|
|
|
@@ -157,6 +179,7 @@ def is_none(cls: GenericType) -> bool:
|
|
|
157
179
|
return cls is type(None) or cls is None
|
|
158
180
|
|
|
159
181
|
|
|
182
|
+
@lru_cache()
|
|
160
183
|
def is_union(cls: GenericType) -> bool:
|
|
161
184
|
"""Check if a class is a Union.
|
|
162
185
|
|
|
@@ -169,6 +192,7 @@ def is_union(cls: GenericType) -> bool:
|
|
|
169
192
|
return get_origin(cls) in UnionTypes
|
|
170
193
|
|
|
171
194
|
|
|
195
|
+
@lru_cache()
|
|
172
196
|
def is_literal(cls: GenericType) -> bool:
|
|
173
197
|
"""Check if a class is a Literal.
|
|
174
198
|
|
|
@@ -222,9 +246,14 @@ def get_attribute_access_type(cls: GenericType, name: str) -> GenericType | None
|
|
|
222
246
|
"""
|
|
223
247
|
from reflex.model import Model
|
|
224
248
|
|
|
225
|
-
|
|
249
|
+
try:
|
|
250
|
+
attr = getattr(cls, name, None)
|
|
251
|
+
except NotImplementedError:
|
|
252
|
+
attr = None
|
|
253
|
+
|
|
226
254
|
if hint := get_property_hint(attr):
|
|
227
255
|
return hint
|
|
256
|
+
|
|
228
257
|
if (
|
|
229
258
|
hasattr(cls, "__fields__")
|
|
230
259
|
and name in cls.__fields__
|
|
@@ -314,6 +343,7 @@ def get_attribute_access_type(cls: GenericType, name: str) -> GenericType | None
|
|
|
314
343
|
return None # Attribute is not accessible.
|
|
315
344
|
|
|
316
345
|
|
|
346
|
+
@lru_cache()
|
|
317
347
|
def get_base_class(cls: GenericType) -> Type:
|
|
318
348
|
"""Get the base class of a class.
|
|
319
349
|
|
|
@@ -451,7 +481,11 @@ def is_valid_var_type(type_: Type) -> bool:
|
|
|
451
481
|
|
|
452
482
|
if is_union(type_):
|
|
453
483
|
return all((is_valid_var_type(arg) for arg in get_args(type_)))
|
|
454
|
-
return
|
|
484
|
+
return (
|
|
485
|
+
_issubclass(type_, StateVar)
|
|
486
|
+
or serializers.has_serializer(type_)
|
|
487
|
+
or dataclasses.is_dataclass(type_)
|
|
488
|
+
)
|
|
455
489
|
|
|
456
490
|
|
|
457
491
|
def is_backend_base_variable(name: str, cls: Type) -> bool:
|
|
@@ -485,17 +519,23 @@ def is_backend_base_variable(name: str, cls: Type) -> bool:
|
|
|
485
519
|
if name in cls.inherited_backend_vars:
|
|
486
520
|
return False
|
|
487
521
|
|
|
522
|
+
from reflex.vars.base import is_computed_var
|
|
523
|
+
|
|
488
524
|
if name in cls.__dict__:
|
|
489
525
|
value = cls.__dict__[name]
|
|
490
526
|
if type(value) == classmethod:
|
|
491
527
|
return False
|
|
492
528
|
if callable(value):
|
|
493
529
|
return False
|
|
494
|
-
from reflex.vars import ComputedVar
|
|
495
530
|
|
|
496
531
|
if isinstance(
|
|
497
|
-
value,
|
|
498
|
-
|
|
532
|
+
value,
|
|
533
|
+
(
|
|
534
|
+
types.FunctionType,
|
|
535
|
+
property,
|
|
536
|
+
cached_property,
|
|
537
|
+
),
|
|
538
|
+
) or is_computed_var(value):
|
|
499
539
|
return False
|
|
500
540
|
|
|
501
541
|
return True
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Immutable-Based Var System."""
|
|
2
2
|
|
|
3
|
-
from .base import ImmutableVar as ImmutableVar
|
|
4
3
|
from .base import LiteralVar as LiteralVar
|
|
4
|
+
from .base import Var as Var
|
|
5
|
+
from .base import VarData as VarData
|
|
6
|
+
from .base import get_unique_variable_name as get_unique_variable_name
|
|
7
|
+
from .base import get_uuid_string_var as get_uuid_string_var
|
|
5
8
|
from .base import var_operation as var_operation
|
|
9
|
+
from .base import var_operation_return as var_operation_return
|
|
6
10
|
from .function import FunctionStringVar as FunctionStringVar
|
|
7
11
|
from .function import FunctionVar as FunctionVar
|
|
8
12
|
from .function import VarOperationCall as VarOperationCall
|
|
@@ -12,7 +16,6 @@ from .number import LiteralNumberVar as LiteralNumberVar
|
|
|
12
16
|
from .number import NumberVar as NumberVar
|
|
13
17
|
from .object import LiteralObjectVar as LiteralObjectVar
|
|
14
18
|
from .object import ObjectVar as ObjectVar
|
|
15
|
-
from .sequence import ArrayJoinOperation as ArrayJoinOperation
|
|
16
19
|
from .sequence import ArrayVar as ArrayVar
|
|
17
20
|
from .sequence import ConcatVarOperation as ConcatVarOperation
|
|
18
21
|
from .sequence import LiteralArrayVar as LiteralArrayVar
|