reflex 0.7.13a1__py3-none-any.whl → 0.7.14a1__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/apps/blank/code/blank.py +0 -2
- reflex/app.py +79 -72
- reflex/app_mixins/lifespan.py +2 -3
- reflex/app_mixins/middleware.py +1 -0
- reflex/app_mixins/mixin.py +0 -1
- reflex/assets.py +6 -3
- reflex/base.py +3 -2
- reflex/compiler/compiler.py +77 -64
- reflex/compiler/utils.py +8 -6
- reflex/components/base/app_wrap.pyi +0 -1
- reflex/components/base/bare.py +5 -7
- reflex/components/base/body.pyi +0 -1
- reflex/components/base/document.pyi +0 -5
- reflex/components/base/error_boundary.pyi +0 -1
- reflex/components/base/fragment.pyi +0 -1
- reflex/components/base/head.pyi +0 -2
- reflex/components/base/link.pyi +0 -2
- reflex/components/base/meta.py +2 -1
- reflex/components/base/meta.pyi +0 -4
- reflex/components/base/script.py +2 -1
- reflex/components/base/script.pyi +0 -1
- reflex/components/base/strict_mode.pyi +0 -1
- reflex/components/component.py +38 -40
- reflex/components/core/auto_scroll.pyi +0 -1
- reflex/components/core/banner.pyi +0 -6
- reflex/components/core/breakpoints.py +9 -11
- reflex/components/core/client_side_routing.pyi +0 -2
- reflex/components/core/clipboard.pyi +0 -1
- reflex/components/core/colors.py +10 -7
- reflex/components/core/cond.py +4 -2
- reflex/components/core/debounce.py +5 -3
- reflex/components/core/debounce.pyi +0 -1
- reflex/components/core/foreach.py +8 -6
- reflex/components/core/html.py +3 -3
- reflex/components/core/html.pyi +0 -1
- reflex/components/core/match.py +19 -17
- reflex/components/core/sticky.pyi +0 -4
- reflex/components/core/upload.pyi +0 -5
- reflex/components/datadisplay/code.py +1 -2
- reflex/components/datadisplay/code.pyi +0 -2
- reflex/components/datadisplay/dataeditor.py +7 -10
- reflex/components/datadisplay/dataeditor.pyi +0 -1
- reflex/components/datadisplay/logo.py +3 -4
- reflex/components/datadisplay/shiki_code_block.py +8 -11
- reflex/components/datadisplay/shiki_code_block.pyi +0 -3
- reflex/components/dynamic.py +2 -3
- reflex/components/el/__init__.pyi +2 -0
- reflex/components/el/element.pyi +0 -1
- reflex/components/el/elements/__init__.py +1 -0
- reflex/components/el/elements/__init__.pyi +3 -0
- reflex/components/el/elements/base.pyi +0 -1
- reflex/components/el/elements/forms.py +3 -4
- reflex/components/el/elements/forms.pyi +1 -18
- reflex/components/el/elements/inline.pyi +0 -28
- reflex/components/el/elements/media.py +26 -0
- reflex/components/el/elements/media.pyi +259 -25
- reflex/components/el/elements/metadata.py +0 -1
- reflex/components/el/elements/metadata.pyi +0 -6
- reflex/components/el/elements/other.pyi +0 -7
- reflex/components/el/elements/scripts.pyi +0 -3
- reflex/components/el/elements/sectioning.pyi +0 -15
- reflex/components/el/elements/tables.pyi +0 -10
- reflex/components/el/elements/typography.pyi +0 -15
- reflex/components/gridjs/datatable.py +10 -13
- reflex/components/gridjs/datatable.pyi +0 -2
- reflex/components/lucide/icon.py +10 -9
- reflex/components/lucide/icon.pyi +0 -3
- reflex/components/markdown/markdown.py +6 -8
- reflex/components/markdown/markdown.pyi +0 -1
- reflex/components/moment/moment.pyi +0 -1
- reflex/components/next/base.py +0 -2
- reflex/components/next/base.pyi +0 -3
- reflex/components/next/image.pyi +0 -1
- reflex/components/next/link.pyi +0 -1
- reflex/components/next/video.pyi +0 -1
- reflex/components/plotly/plotly.pyi +0 -9
- reflex/components/props.py +4 -3
- reflex/components/radix/primitives/accordion.py +1 -1
- reflex/components/radix/primitives/accordion.pyi +0 -7
- reflex/components/radix/primitives/base.py +1 -3
- reflex/components/radix/primitives/base.pyi +0 -2
- reflex/components/radix/primitives/drawer.py +1 -1
- reflex/components/radix/primitives/drawer.pyi +0 -11
- reflex/components/radix/primitives/form.py +5 -9
- reflex/components/radix/primitives/form.pyi +0 -12
- reflex/components/radix/primitives/progress.py +1 -1
- reflex/components/radix/primitives/progress.pyi +0 -5
- reflex/components/radix/primitives/slider.py +1 -1
- reflex/components/radix/primitives/slider.pyi +0 -5
- reflex/components/radix/themes/base.pyi +0 -8
- reflex/components/radix/themes/color_mode.pyi +0 -3
- reflex/components/radix/themes/components/alert_dialog.py +4 -2
- reflex/components/radix/themes/components/alert_dialog.pyi +4 -9
- reflex/components/radix/themes/components/aspect_ratio.py +1 -2
- reflex/components/radix/themes/components/aspect_ratio.pyi +1 -3
- reflex/components/radix/themes/components/avatar.py +5 -2
- reflex/components/radix/themes/components/avatar.pyi +1 -3
- reflex/components/radix/themes/components/badge.py +5 -2
- reflex/components/radix/themes/components/badge.pyi +1 -3
- reflex/components/radix/themes/components/button.py +2 -3
- reflex/components/radix/themes/components/button.pyi +1 -3
- reflex/components/radix/themes/components/callout.py +1 -2
- reflex/components/radix/themes/components/callout.pyi +1 -7
- reflex/components/radix/themes/components/card.py +1 -2
- reflex/components/radix/themes/components/card.pyi +1 -3
- reflex/components/radix/themes/components/checkbox.py +7 -4
- reflex/components/radix/themes/components/checkbox.pyi +1 -5
- reflex/components/radix/themes/components/checkbox_cards.py +1 -2
- reflex/components/radix/themes/components/checkbox_cards.pyi +1 -4
- reflex/components/radix/themes/components/checkbox_group.py +1 -2
- reflex/components/radix/themes/components/checkbox_group.pyi +1 -4
- reflex/components/radix/themes/components/context_menu.py +1 -1
- reflex/components/radix/themes/components/context_menu.pyi +1 -14
- reflex/components/radix/themes/components/data_list.py +1 -2
- reflex/components/radix/themes/components/data_list.pyi +1 -6
- reflex/components/radix/themes/components/dialog.py +4 -2
- reflex/components/radix/themes/components/dialog.pyi +4 -9
- reflex/components/radix/themes/components/dropdown_menu.py +5 -2
- reflex/components/radix/themes/components/dropdown_menu.pyi +4 -10
- reflex/components/radix/themes/components/hover_card.py +4 -2
- reflex/components/radix/themes/components/hover_card.pyi +4 -6
- reflex/components/radix/themes/components/icon_button.py +7 -8
- reflex/components/radix/themes/components/icon_button.pyi +1 -3
- reflex/components/radix/themes/components/inset.py +1 -2
- reflex/components/radix/themes/components/inset.pyi +1 -3
- reflex/components/radix/themes/components/popover.py +4 -2
- reflex/components/radix/themes/components/popover.pyi +4 -6
- reflex/components/radix/themes/components/progress.py +1 -2
- reflex/components/radix/themes/components/progress.pyi +1 -3
- reflex/components/radix/themes/components/radio.py +1 -2
- reflex/components/radix/themes/components/radio.pyi +1 -3
- reflex/components/radix/themes/components/radio_cards.py +1 -2
- reflex/components/radix/themes/components/radio_cards.pyi +1 -4
- reflex/components/radix/themes/components/radio_group.py +7 -5
- reflex/components/radix/themes/components/radio_group.pyi +1 -6
- reflex/components/radix/themes/components/scroll_area.py +1 -2
- reflex/components/radix/themes/components/scroll_area.pyi +1 -3
- reflex/components/radix/themes/components/segmented_control.py +1 -2
- reflex/components/radix/themes/components/segmented_control.pyi +1 -4
- reflex/components/radix/themes/components/select.py +5 -2
- reflex/components/radix/themes/components/select.pyi +1 -11
- reflex/components/radix/themes/components/separator.py +1 -2
- reflex/components/radix/themes/components/separator.pyi +1 -3
- reflex/components/radix/themes/components/skeleton.py +1 -2
- reflex/components/radix/themes/components/skeleton.pyi +1 -3
- reflex/components/radix/themes/components/slider.py +1 -2
- reflex/components/radix/themes/components/slider.pyi +1 -3
- reflex/components/radix/themes/components/spinner.py +1 -2
- reflex/components/radix/themes/components/spinner.pyi +1 -3
- reflex/components/radix/themes/components/switch.py +1 -2
- reflex/components/radix/themes/components/switch.pyi +1 -3
- reflex/components/radix/themes/components/table.py +1 -2
- reflex/components/radix/themes/components/table.pyi +1 -9
- reflex/components/radix/themes/components/tabs.py +1 -2
- reflex/components/radix/themes/components/tabs.pyi +1 -7
- reflex/components/radix/themes/components/text_area.py +5 -2
- reflex/components/radix/themes/components/text_area.pyi +1 -3
- reflex/components/radix/themes/components/text_field.py +5 -2
- reflex/components/radix/themes/components/text_field.pyi +1 -5
- reflex/components/radix/themes/components/tooltip.py +1 -2
- reflex/components/radix/themes/components/tooltip.pyi +1 -3
- reflex/components/radix/themes/layout/base.py +5 -2
- reflex/components/radix/themes/layout/base.pyi +5 -3
- reflex/components/radix/themes/layout/box.py +1 -2
- reflex/components/radix/themes/layout/box.pyi +1 -3
- reflex/components/radix/themes/layout/center.pyi +0 -1
- reflex/components/radix/themes/layout/container.py +1 -2
- reflex/components/radix/themes/layout/container.pyi +1 -3
- reflex/components/radix/themes/layout/flex.py +6 -2
- reflex/components/radix/themes/layout/flex.pyi +1 -3
- reflex/components/radix/themes/layout/grid.py +6 -2
- reflex/components/radix/themes/layout/grid.pyi +1 -3
- reflex/components/radix/themes/layout/list.py +2 -1
- reflex/components/radix/themes/layout/list.pyi +0 -5
- reflex/components/radix/themes/layout/section.py +1 -2
- reflex/components/radix/themes/layout/section.pyi +1 -3
- reflex/components/radix/themes/layout/spacer.pyi +0 -1
- reflex/components/radix/themes/layout/stack.py +1 -1
- reflex/components/radix/themes/layout/stack.pyi +0 -3
- reflex/components/radix/themes/typography/blockquote.py +1 -1
- reflex/components/radix/themes/typography/blockquote.pyi +1 -3
- reflex/components/radix/themes/typography/code.py +5 -1
- reflex/components/radix/themes/typography/code.pyi +1 -3
- reflex/components/radix/themes/typography/heading.py +1 -1
- reflex/components/radix/themes/typography/heading.pyi +1 -3
- reflex/components/radix/themes/typography/link.py +3 -2
- reflex/components/radix/themes/typography/link.pyi +1 -3
- reflex/components/radix/themes/typography/text.py +1 -1
- reflex/components/radix/themes/typography/text.pyi +1 -9
- reflex/components/react_player/audio.py +0 -2
- reflex/components/react_player/audio.pyi +0 -3
- reflex/components/react_player/react_player.pyi +0 -1
- reflex/components/react_player/video.py +0 -2
- reflex/components/react_player/video.pyi +0 -3
- reflex/components/recharts/__init__.py +1 -1
- reflex/components/recharts/__init__.pyi +1 -1
- reflex/components/recharts/cartesian.py +20 -25
- reflex/components/recharts/cartesian.pyi +20 -37
- reflex/components/recharts/charts.py +2 -1
- reflex/components/recharts/charts.pyi +0 -12
- reflex/components/recharts/general.pyi +0 -6
- reflex/components/recharts/polar.py +5 -4
- reflex/components/recharts/polar.pyi +4 -10
- reflex/components/recharts/recharts.py +12 -10
- reflex/components/recharts/recharts.pyi +10 -11
- reflex/components/sonner/toast.py +2 -2
- reflex/components/sonner/toast.pyi +0 -2
- reflex/components/suneditor/editor.py +2 -1
- reflex/components/suneditor/editor.pyi +0 -1
- reflex/components/tags/iter_tag.py +4 -2
- reflex/config.py +47 -35
- reflex/constants/base.py +3 -3
- reflex/constants/compiler.py +8 -6
- reflex/constants/installer.py +24 -15
- reflex/custom_components/custom_components.py +1 -2
- reflex/event.py +58 -60
- reflex/experimental/__init__.py +2 -2
- reflex/experimental/client_state.py +9 -4
- reflex/experimental/layout.pyi +0 -5
- reflex/istate/manager.py +15 -19
- reflex/istate/proxy.py +19 -12
- reflex/model.py +6 -4
- reflex/plugins/base.py +8 -0
- reflex/plugins/tailwind_v3.py +8 -0
- reflex/plugins/tailwind_v4.py +9 -0
- reflex/reflex.py +9 -11
- reflex/route.py +7 -9
- reflex/state.py +66 -70
- reflex/style.py +3 -1
- reflex/testing.py +46 -29
- reflex/utils/build.py +2 -1
- reflex/utils/console.py +9 -17
- reflex/utils/exec.py +9 -11
- reflex/utils/format.py +21 -24
- reflex/utils/imports.py +4 -3
- reflex/utils/lazy_loader.py +3 -3
- reflex/utils/misc.py +2 -1
- reflex/utils/net.py +2 -2
- reflex/utils/path_ops.py +2 -1
- reflex/utils/prerequisites.py +67 -38
- reflex/utils/processes.py +4 -6
- reflex/utils/pyi_generator.py +46 -41
- reflex/utils/redir.py +1 -1
- reflex/utils/serializers.py +4 -4
- reflex/utils/telemetry.py +42 -4
- reflex/utils/types.py +16 -13
- reflex/vars/base.py +96 -109
- reflex/vars/datetime.py +2 -1
- reflex/vars/dep_tracking.py +19 -28
- reflex/vars/number.py +6 -7
- reflex/vars/object.py +5 -6
- reflex/vars/sequence.py +11 -11
- {reflex-0.7.13a1.dist-info → reflex-0.7.14a1.dist-info}/METADATA +1 -1
- reflex-0.7.14a1.dist-info/RECORD +407 -0
- reflex-0.7.13a1.dist-info/RECORD +0 -407
- {reflex-0.7.13a1.dist-info → reflex-0.7.14a1.dist-info}/WHEEL +0 -0
- {reflex-0.7.13a1.dist-info → reflex-0.7.14a1.dist-info}/entry_points.txt +0 -0
- {reflex-0.7.13a1.dist-info → reflex-0.7.14a1.dist-info}/licenses/LICENSE +0 -0
reflex/plugins/tailwind_v3.py
CHANGED
|
@@ -253,3 +253,11 @@ class Plugin(PluginBase):
|
|
|
253
253
|
str(Path(Dirs.STYLES) / (PageNames.STYLESHEET_ROOT + Ext.CSS)),
|
|
254
254
|
add_tailwind_to_css_file,
|
|
255
255
|
)
|
|
256
|
+
|
|
257
|
+
def __repr__(self):
|
|
258
|
+
"""Return a string representation of the plugin.
|
|
259
|
+
|
|
260
|
+
Returns:
|
|
261
|
+
A string representation of the plugin.
|
|
262
|
+
"""
|
|
263
|
+
return "TailwindV3Plugin()"
|
reflex/plugins/tailwind_v4.py
CHANGED
|
@@ -23,6 +23,7 @@ class Constants(SimpleNamespace):
|
|
|
23
23
|
|
|
24
24
|
# Content of the style content.
|
|
25
25
|
ROOT_STYLE_CONTENT = """@layer theme, base, components, utilities;
|
|
26
|
+
@config "../tailwind.config.js";
|
|
26
27
|
@import "tailwindcss/theme.css" layer(theme);
|
|
27
28
|
@import "tailwindcss/preflight.css" layer(base);
|
|
28
29
|
@import "{radix_url}" layer(components);
|
|
@@ -255,3 +256,11 @@ class Plugin(PluginBase):
|
|
|
255
256
|
str(Path(Dirs.STYLES) / (PageNames.STYLESHEET_ROOT + Ext.CSS)),
|
|
256
257
|
add_tailwind_to_css_file,
|
|
257
258
|
)
|
|
259
|
+
|
|
260
|
+
def __repr__(self):
|
|
261
|
+
"""Return a string representation of the plugin.
|
|
262
|
+
|
|
263
|
+
Returns:
|
|
264
|
+
A string representation of the plugin.
|
|
265
|
+
"""
|
|
266
|
+
return "TailwindV4Plugin()"
|
reflex/reflex.py
CHANGED
|
@@ -36,7 +36,6 @@ def set_loglevel(ctx: click.Context, self: click.Parameter, value: str | None):
|
|
|
36
36
|
@click.version_option(constants.Reflex.VERSION, message="%(version)s")
|
|
37
37
|
def cli():
|
|
38
38
|
"""Reflex CLI to create, run, and deploy apps."""
|
|
39
|
-
pass
|
|
40
39
|
|
|
41
40
|
|
|
42
41
|
loglevel_option = click.option(
|
|
@@ -202,6 +201,9 @@ def _run(
|
|
|
202
201
|
# Get the app module.
|
|
203
202
|
app_task = prerequisites.compile_or_validate_app
|
|
204
203
|
args = (frontend,)
|
|
204
|
+
kwargs = {
|
|
205
|
+
"check_if_schema_up_to_date": True,
|
|
206
|
+
}
|
|
205
207
|
|
|
206
208
|
# Granian fails if the app is already imported.
|
|
207
209
|
if should_use_granian():
|
|
@@ -210,16 +212,15 @@ def _run(
|
|
|
210
212
|
compile_future = concurrent.futures.ProcessPoolExecutor(max_workers=1).submit(
|
|
211
213
|
app_task,
|
|
212
214
|
*args,
|
|
215
|
+
**kwargs,
|
|
213
216
|
)
|
|
214
217
|
validation_result = compile_future.result()
|
|
215
218
|
else:
|
|
216
|
-
validation_result = app_task(*args)
|
|
219
|
+
validation_result = app_task(*args, **kwargs)
|
|
220
|
+
|
|
217
221
|
if not validation_result:
|
|
218
222
|
raise click.exceptions.Exit(1)
|
|
219
223
|
|
|
220
|
-
# Warn if schema is not up to date.
|
|
221
|
-
prerequisites.check_schema_up_to_date()
|
|
222
|
-
|
|
223
224
|
# Get the frontend and backend commands, based on the environment.
|
|
224
225
|
setup_frontend = frontend_cmd = backend_cmd = None
|
|
225
226
|
if env == constants.Env.DEV:
|
|
@@ -235,7 +236,8 @@ def _run(
|
|
|
235
236
|
exec.run_backend_prod,
|
|
236
237
|
)
|
|
237
238
|
if not setup_frontend or not frontend_cmd or not backend_cmd:
|
|
238
|
-
|
|
239
|
+
msg = f"Invalid env: {env}. Must be DEV or PROD."
|
|
240
|
+
raise ValueError(msg)
|
|
239
241
|
|
|
240
242
|
# Post a telemetry event.
|
|
241
243
|
telemetry.send(f"run-{env.value}")
|
|
@@ -481,13 +483,11 @@ def logout():
|
|
|
481
483
|
@click.group
|
|
482
484
|
def db_cli():
|
|
483
485
|
"""Subcommands for managing the database schema."""
|
|
484
|
-
pass
|
|
485
486
|
|
|
486
487
|
|
|
487
488
|
@click.group
|
|
488
489
|
def script_cli():
|
|
489
490
|
"""Subcommands for running helper scripts."""
|
|
490
|
-
pass
|
|
491
491
|
|
|
492
492
|
|
|
493
493
|
def _skip_compile():
|
|
@@ -531,9 +531,7 @@ def migrate():
|
|
|
531
531
|
from reflex import model
|
|
532
532
|
from reflex.utils import prerequisites
|
|
533
533
|
|
|
534
|
-
|
|
535
|
-
_skip_compile()
|
|
536
|
-
prerequisites.get_compiled_app()
|
|
534
|
+
prerequisites.get_app()
|
|
537
535
|
if not prerequisites.check_db_initialized():
|
|
538
536
|
return
|
|
539
537
|
model.Model.migrate()
|
reflex/route.py
CHANGED
|
@@ -18,11 +18,13 @@ def verify_route_validity(route: str) -> None:
|
|
|
18
18
|
"""
|
|
19
19
|
pattern = catchall_in_route(route)
|
|
20
20
|
if pattern and not route.endswith(pattern):
|
|
21
|
-
|
|
21
|
+
msg = f"Catch-all must be the last part of the URL: {route}"
|
|
22
|
+
raise ValueError(msg)
|
|
22
23
|
if route == "api" or route.startswith("api/"):
|
|
23
|
-
|
|
24
|
+
msg = (
|
|
24
25
|
f"Cannot have a route prefixed with 'api/': {route} (conflicts with NextJS)"
|
|
25
26
|
)
|
|
27
|
+
raise ValueError(msg)
|
|
26
28
|
|
|
27
29
|
|
|
28
30
|
def get_route_args(route: str) -> dict[str, str]:
|
|
@@ -48,9 +50,8 @@ def get_route_args(route: str) -> dict[str, str]:
|
|
|
48
50
|
"""
|
|
49
51
|
arg_name = match.groups()[0]
|
|
50
52
|
if arg_name in args:
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
)
|
|
53
|
+
msg = f"Arg name [{arg_name}] is used more than once in this URL"
|
|
54
|
+
raise ValueError(msg)
|
|
54
55
|
args[arg_name] = type_
|
|
55
56
|
|
|
56
57
|
# Regex to check for route args.
|
|
@@ -136,7 +137,4 @@ def replace_brackets_with_keywords(input_string: str) -> str:
|
|
|
136
137
|
r"\[\[.+?\]\]", constants.RouteRegex.DOUBLE_SEGMENT, output_string
|
|
137
138
|
)
|
|
138
139
|
# Replace [<slug>] with __SINGLE_SEGMENT__
|
|
139
|
-
|
|
140
|
-
r"\[.+?\]", constants.RouteRegex.SINGLE_SEGMENT, output_string
|
|
141
|
-
)
|
|
142
|
-
return output_string
|
|
140
|
+
return re.sub(r"\[.+?\]", constants.RouteRegex.SINGLE_SEGMENT, output_string)
|
reflex/state.py
CHANGED
|
@@ -148,7 +148,8 @@ def _no_chain_background_task(
|
|
|
148
148
|
|
|
149
149
|
return _no_chain_background_task_gen
|
|
150
150
|
|
|
151
|
-
|
|
151
|
+
msg = f"{fn} is marked as a background task, but is not async."
|
|
152
|
+
raise TypeError(msg)
|
|
152
153
|
|
|
153
154
|
|
|
154
155
|
def _substate_key(
|
|
@@ -233,22 +234,19 @@ class EventHandlerSetVar(EventHandler):
|
|
|
233
234
|
|
|
234
235
|
if args:
|
|
235
236
|
if not isinstance(args[0], str):
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
)
|
|
237
|
+
msg = f"Var name must be passed as a string, got {args[0]!r}"
|
|
238
|
+
raise EventHandlerValueError(msg)
|
|
239
239
|
|
|
240
240
|
handler = getattr(self.state_cls, constants.SETTER_PREFIX + args[0], None)
|
|
241
241
|
|
|
242
242
|
# Check that the requested Var setter exists on the State at compile time.
|
|
243
243
|
if handler is None:
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
)
|
|
244
|
+
msg = f"Variable `{args[0]}` cannot be set on `{self.state_cls.get_full_name()}`"
|
|
245
|
+
raise AttributeError(msg)
|
|
247
246
|
|
|
248
247
|
if asyncio.iscoroutinefunction(handler.fn):
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
)
|
|
248
|
+
msg = f"Setter for {args[0]} is async, which is not supported."
|
|
249
|
+
raise NotImplementedError(msg)
|
|
252
250
|
|
|
253
251
|
return super().__call__(*args)
|
|
254
252
|
|
|
@@ -406,14 +404,14 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|
|
406
404
|
from reflex.utils.exceptions import ReflexRuntimeError
|
|
407
405
|
|
|
408
406
|
if not _reflex_internal_init and not is_testing_env():
|
|
409
|
-
|
|
407
|
+
msg = (
|
|
410
408
|
"State classes should not be instantiated directly in a Reflex app. "
|
|
411
409
|
"See https://reflex.dev/docs/state/ for further information."
|
|
412
410
|
)
|
|
411
|
+
raise ReflexRuntimeError(msg)
|
|
413
412
|
if type(self)._mixin:
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
)
|
|
413
|
+
msg = f"{type(self).__name__} is a state mixin and cannot be instantiated directly."
|
|
414
|
+
raise ReflexRuntimeError(msg)
|
|
417
415
|
kwargs["parent_state"] = parent_state
|
|
418
416
|
super().__init__()
|
|
419
417
|
for name, value in kwargs.items():
|
|
@@ -462,10 +460,11 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|
|
462
460
|
NameError: If the module name is invalid.
|
|
463
461
|
"""
|
|
464
462
|
if "___" in cls.__module__:
|
|
465
|
-
|
|
463
|
+
msg = (
|
|
466
464
|
"The module name of a State class cannot contain '___'. "
|
|
467
465
|
"Please rename the module."
|
|
468
466
|
)
|
|
467
|
+
raise NameError(msg)
|
|
469
468
|
|
|
470
469
|
@classmethod
|
|
471
470
|
def __init_subclass__(cls, mixin: bool = False, **kwargs):
|
|
@@ -515,10 +514,11 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|
|
515
514
|
# Check if another substate class with the same name has already been defined.
|
|
516
515
|
if cls.get_name() in {c.get_name() for c in parent_state.class_subclasses}:
|
|
517
516
|
# This should not happen, since we have added module prefix to state names in #3214
|
|
518
|
-
|
|
517
|
+
msg = (
|
|
519
518
|
f"The substate class '{cls.get_name()}' has been defined multiple times. "
|
|
520
519
|
"Shadowing substate classes is not allowed."
|
|
521
520
|
)
|
|
521
|
+
raise StateValueError(msg)
|
|
522
522
|
# Track this new subclass in the parent state's subclasses set.
|
|
523
523
|
parent_state.class_subclasses.add(cls)
|
|
524
524
|
|
|
@@ -832,9 +832,8 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|
|
832
832
|
overridden_methods.add(method.__name__)
|
|
833
833
|
|
|
834
834
|
for method_name in overridden_methods:
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
)
|
|
835
|
+
msg = f"The event handler name `{method_name}` shadows a builtin State method; use a different name instead"
|
|
836
|
+
raise EventHandlerShadowsBuiltInStateMethodError(msg)
|
|
838
837
|
|
|
839
838
|
@classmethod
|
|
840
839
|
def _check_overridden_basevars(cls):
|
|
@@ -845,9 +844,8 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|
|
845
844
|
"""
|
|
846
845
|
for computed_var_ in cls._get_computed_vars():
|
|
847
846
|
if computed_var_._js_expr in cls.__annotations__:
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
)
|
|
847
|
+
msg = f"The computed var name `{computed_var_._js_expr}` shadows a base var in {cls.__module__}.{cls.__name__}; use a different name instead"
|
|
848
|
+
raise ComputedVarShadowsBaseVarsError(msg)
|
|
851
849
|
|
|
852
850
|
@classmethod
|
|
853
851
|
def _check_overridden_computed_vars(cls) -> None:
|
|
@@ -861,9 +859,8 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|
|
861
859
|
continue
|
|
862
860
|
name = cv._js_expr
|
|
863
861
|
if name in cls.inherited_vars or name in cls.inherited_backend_vars:
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
)
|
|
862
|
+
msg = f"The computed var name `{cv._js_expr}` shadows a var in {cls.__module__}.{cls.__name__}; use a different name instead"
|
|
863
|
+
raise ComputedVarShadowsStateVarError(msg)
|
|
867
864
|
|
|
868
865
|
@classmethod
|
|
869
866
|
def get_skip_vars(cls) -> set[str]:
|
|
@@ -901,7 +898,8 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|
|
901
898
|
if issubclass(base, BaseState) and base is not BaseState and not base._mixin
|
|
902
899
|
]
|
|
903
900
|
if len(parent_states) >= 2:
|
|
904
|
-
|
|
901
|
+
msg = f"Only one parent state is allowed {parent_states}."
|
|
902
|
+
raise ValueError(msg)
|
|
905
903
|
# The first non-mixin state in the mro is our parent.
|
|
906
904
|
for base in cls.mro()[1:]:
|
|
907
905
|
if not issubclass(base, BaseState) or base._mixin:
|
|
@@ -953,7 +951,7 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|
|
953
951
|
name = cls.get_name()
|
|
954
952
|
parent_state = cls.get_parent_state()
|
|
955
953
|
if parent_state is not None:
|
|
956
|
-
name =
|
|
954
|
+
name = parent_state.get_full_name() + "." + name
|
|
957
955
|
return name
|
|
958
956
|
|
|
959
957
|
@classmethod
|
|
@@ -982,7 +980,8 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|
|
982
980
|
for substate in cls.get_substates():
|
|
983
981
|
if path[0] == substate.get_name():
|
|
984
982
|
return substate.get_class_substate(path[1:])
|
|
985
|
-
|
|
983
|
+
msg = f"Invalid path: {path}"
|
|
984
|
+
raise ValueError(msg)
|
|
986
985
|
|
|
987
986
|
@classmethod
|
|
988
987
|
def get_class_var(cls, path: Sequence[str]) -> Any:
|
|
@@ -1000,7 +999,8 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|
|
1000
999
|
path, name = path[:-1], path[-1]
|
|
1001
1000
|
substate = cls.get_class_substate(tuple(path))
|
|
1002
1001
|
if not hasattr(substate, name):
|
|
1003
|
-
|
|
1002
|
+
msg = f"Invalid path: {path}"
|
|
1003
|
+
raise ValueError(msg)
|
|
1004
1004
|
return getattr(substate, name)
|
|
1005
1005
|
|
|
1006
1006
|
@classmethod
|
|
@@ -1029,12 +1029,13 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|
|
1029
1029
|
from reflex.utils.exceptions import VarTypeError
|
|
1030
1030
|
|
|
1031
1031
|
if not types.is_valid_var_type(prop._var_type):
|
|
1032
|
-
|
|
1032
|
+
msg = (
|
|
1033
1033
|
"State vars must be of a serializable type. "
|
|
1034
1034
|
"Valid types include strings, numbers, booleans, lists, "
|
|
1035
1035
|
"dictionaries, dataclasses, datetime objects, and pydantic models. "
|
|
1036
1036
|
f'Found var "{prop._js_expr}" with type {prop._var_type}.'
|
|
1037
1037
|
)
|
|
1038
|
+
raise VarTypeError(msg)
|
|
1038
1039
|
cls._set_var(prop)
|
|
1039
1040
|
if cls.is_user_defined() and get_config().state_auto_setters:
|
|
1040
1041
|
cls._create_setter(prop)
|
|
@@ -1056,9 +1057,8 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|
|
1056
1057
|
NameError: if a variable of this name already exists
|
|
1057
1058
|
"""
|
|
1058
1059
|
if name in cls.__fields__:
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
)
|
|
1060
|
+
msg = f"The variable '{name}' already exist. Use a different name"
|
|
1061
|
+
raise NameError(msg)
|
|
1062
1062
|
|
|
1063
1063
|
# create the variable based on name and type
|
|
1064
1064
|
var = Var(
|
|
@@ -1260,9 +1260,8 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|
|
1260
1260
|
arg in cls.computed_vars
|
|
1261
1261
|
and not isinstance(cls.computed_vars[arg], DynamicRouteVar)
|
|
1262
1262
|
) or arg in cls.base_vars:
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
)
|
|
1263
|
+
msg = f"Dynamic route arg '{arg}' is shadowing an existing var in {cls.__module__}.{cls.__name__}"
|
|
1264
|
+
raise DynamicRouteArgShadowsStateVarError(msg)
|
|
1266
1265
|
for substate in cls.get_substates():
|
|
1267
1266
|
substate._check_overwritten_dynamic_args(args)
|
|
1268
1267
|
|
|
@@ -1363,10 +1362,11 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|
|
1363
1362
|
f"_{getattr(type(self), '__original_name__', type(self).__name__)}__"
|
|
1364
1363
|
)
|
|
1365
1364
|
):
|
|
1366
|
-
|
|
1365
|
+
msg = (
|
|
1367
1366
|
f"The state variable '{name}' has not been defined in '{type(self).__name__}'. "
|
|
1368
1367
|
f"All state variables must be declared before they can be set."
|
|
1369
1368
|
)
|
|
1369
|
+
raise SetUndefinedStateVarError(msg)
|
|
1370
1370
|
|
|
1371
1371
|
fields = self.get_fields()
|
|
1372
1372
|
|
|
@@ -1470,7 +1470,8 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|
|
1470
1470
|
return self
|
|
1471
1471
|
path = path[1:]
|
|
1472
1472
|
if path[0] not in self.substates:
|
|
1473
|
-
|
|
1473
|
+
msg = f"Invalid path: {path}"
|
|
1474
|
+
raise ValueError(msg)
|
|
1474
1475
|
return self.substates[path[0]].get_substate(path[1:])
|
|
1475
1476
|
|
|
1476
1477
|
@classmethod
|
|
@@ -1517,10 +1518,11 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|
|
1517
1518
|
# Then get the target state and all its substates.
|
|
1518
1519
|
state_manager = get_state_manager()
|
|
1519
1520
|
if not isinstance(state_manager, StateManagerRedis):
|
|
1520
|
-
|
|
1521
|
+
msg = (
|
|
1521
1522
|
f"Requested state {state_cls.get_full_name()} is not cached and cannot be accessed without redis. "
|
|
1522
|
-
"(All states should already be available -- this is likely a bug)."
|
|
1523
|
+
"(All states should already be available -- this is likely a bug)."
|
|
1523
1524
|
)
|
|
1525
|
+
raise RuntimeError(msg)
|
|
1524
1526
|
state_in_redis = await state_manager.get_state(
|
|
1525
1527
|
token=_substate_key(self.router.session.client_token, state_cls),
|
|
1526
1528
|
top_level=False,
|
|
@@ -1528,9 +1530,8 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|
|
1528
1530
|
)
|
|
1529
1531
|
|
|
1530
1532
|
if not isinstance(state_in_redis, state_cls):
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
)
|
|
1533
|
+
msg = f"Searched for state {state_cls.get_full_name()} but found {state_in_redis}."
|
|
1534
|
+
raise StateMismatchError(msg)
|
|
1534
1535
|
|
|
1535
1536
|
return state_in_redis
|
|
1536
1537
|
|
|
@@ -1549,9 +1550,10 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|
|
1549
1550
|
root_state = self._get_root_state()
|
|
1550
1551
|
substate = root_state.get_substate(state_cls.get_full_name().split("."))
|
|
1551
1552
|
if not isinstance(substate, state_cls):
|
|
1552
|
-
|
|
1553
|
+
msg = (
|
|
1553
1554
|
f"Searched for state {state_cls.get_full_name()} but found {substate}."
|
|
1554
1555
|
)
|
|
1556
|
+
raise StateMismatchError(msg)
|
|
1555
1557
|
return substate
|
|
1556
1558
|
|
|
1557
1559
|
async def get_state(self, state_cls: type[T_STATE]) -> T_STATE:
|
|
@@ -1601,9 +1603,8 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|
|
1601
1603
|
|
|
1602
1604
|
var_data = var._get_all_var_data()
|
|
1603
1605
|
if var_data is None or not var_data.state:
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
)
|
|
1606
|
+
msg = f"Unable to retrieve value for {var._js_expr}: not associated with any state."
|
|
1607
|
+
raise UnretrievableVarValueError(msg)
|
|
1607
1608
|
# Fastish case: this var belongs to this state
|
|
1608
1609
|
if var_data.state == self.get_full_name():
|
|
1609
1610
|
return getattr(self, var_data.field_name)
|
|
@@ -1634,9 +1635,8 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|
|
1634
1635
|
path, name = path[:-1], path[-1]
|
|
1635
1636
|
substate = self.get_substate(path)
|
|
1636
1637
|
if not substate:
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
)
|
|
1638
|
+
msg = "The value of state cannot be None when processing an event."
|
|
1639
|
+
raise ValueError(msg)
|
|
1640
1640
|
handler = substate.event_handlers[name]
|
|
1641
1641
|
|
|
1642
1642
|
# For background tasks, proxy the state
|
|
@@ -1702,10 +1702,11 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|
|
1702
1702
|
"ignore", message=f"coroutine '{coroutine_name}' was never awaited"
|
|
1703
1703
|
)
|
|
1704
1704
|
|
|
1705
|
-
|
|
1705
|
+
msg = (
|
|
1706
1706
|
f"Your handler {handler.fn.__qualname__} must only return/yield: None, Events or other EventHandlers referenced by their class (i.e. using `type(self)` or other class references)."
|
|
1707
1707
|
f" Returned events of types {', '.join(map(str, map(type, events)))!s}."
|
|
1708
1708
|
)
|
|
1709
|
+
raise TypeError(msg)
|
|
1709
1710
|
|
|
1710
1711
|
async def _as_state_update(
|
|
1711
1712
|
self,
|
|
@@ -1834,9 +1835,8 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|
|
1834
1835
|
try:
|
|
1835
1836
|
payload[arg] = hinted_args(value)
|
|
1836
1837
|
except ValueError:
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
) from None
|
|
1838
|
+
msg = f"Received a string value ({value}) for {arg} but expected a {hinted_args}"
|
|
1839
|
+
raise ValueError(msg) from None
|
|
1840
1840
|
else:
|
|
1841
1841
|
console.warn(
|
|
1842
1842
|
f"Received a string value ({value}) for {arg} but expected a {hinted_args}. A simple conversion was successful."
|
|
@@ -2123,9 +2123,8 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|
|
2123
2123
|
Raises:
|
|
2124
2124
|
TypeError: always, because async contextmanager protocol is only supported for background task.
|
|
2125
2125
|
"""
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
)
|
|
2126
|
+
msg = "Only background task should use `async with self` to modify state."
|
|
2127
|
+
raise TypeError(msg)
|
|
2129
2128
|
|
|
2130
2129
|
async def __aexit__(self, *exc_info: Any) -> None:
|
|
2131
2130
|
"""Exit the async context manager protocol.
|
|
@@ -2136,7 +2135,6 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|
|
2136
2135
|
Args:
|
|
2137
2136
|
exc_info: The exception info tuple.
|
|
2138
2137
|
"""
|
|
2139
|
-
pass
|
|
2140
2138
|
|
|
2141
2139
|
def __getstate__(self):
|
|
2142
2140
|
"""Get the state for redis serialization.
|
|
@@ -2298,9 +2296,10 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|
|
2298
2296
|
elif fp is not None and data is None:
|
|
2299
2297
|
(substate_schema, state) = pickle.load(fp)
|
|
2300
2298
|
else:
|
|
2301
|
-
|
|
2299
|
+
msg = "Only one of `data` or `fp` must be provided"
|
|
2300
|
+
raise ValueError(msg)
|
|
2302
2301
|
if substate_schema != state._to_schema():
|
|
2303
|
-
raise StateSchemaMismatchError
|
|
2302
|
+
raise StateSchemaMismatchError
|
|
2304
2303
|
return state
|
|
2305
2304
|
|
|
2306
2305
|
|
|
@@ -2377,14 +2376,12 @@ def dynamic(func: Callable[[T], Component]):
|
|
|
2377
2376
|
values = list(func_signature.values())
|
|
2378
2377
|
|
|
2379
2378
|
if number_of_parameters != 1:
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
)
|
|
2379
|
+
msg = "The function must have exactly one parameter, which is the state class."
|
|
2380
|
+
raise DynamicComponentInvalidSignatureError(msg)
|
|
2383
2381
|
|
|
2384
2382
|
if len(values) != 1:
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
)
|
|
2383
|
+
msg = "You must provide a type hint for the state class in the function."
|
|
2384
|
+
raise DynamicComponentInvalidSignatureError(msg)
|
|
2388
2385
|
|
|
2389
2386
|
state_class: type[T] = values[0]
|
|
2390
2387
|
|
|
@@ -2457,7 +2454,7 @@ class OnLoadInternalState(State):
|
|
|
2457
2454
|
)
|
|
2458
2455
|
if not load_events:
|
|
2459
2456
|
self.is_hydrated = True
|
|
2460
|
-
return # Fast path for navigation with no on_load events defined.
|
|
2457
|
+
return None # Fast path for navigation with no on_load events defined.
|
|
2461
2458
|
self.is_hydrated = False
|
|
2462
2459
|
return [
|
|
2463
2460
|
*fix_events(
|
|
@@ -2549,9 +2546,8 @@ class ComponentState(State, mixin=True):
|
|
|
2549
2546
|
Raises:
|
|
2550
2547
|
NotImplementedError: if the subclass does not override this method.
|
|
2551
2548
|
"""
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
)
|
|
2549
|
+
msg = f"{cls.__name__} must implement get_component to return the component instance."
|
|
2550
|
+
raise NotImplementedError(msg)
|
|
2555
2551
|
|
|
2556
2552
|
@classmethod
|
|
2557
2553
|
def create(cls, *children, **props) -> Component:
|
reflex/style.py
CHANGED
|
@@ -121,10 +121,11 @@ def convert_item(
|
|
|
121
121
|
ReflexError: If an EventHandler is used as a style value
|
|
122
122
|
"""
|
|
123
123
|
if isinstance(style_item, EventHandler):
|
|
124
|
-
|
|
124
|
+
msg = (
|
|
125
125
|
"EventHandlers cannot be used as style values. "
|
|
126
126
|
"Please use a Var or a literal value."
|
|
127
127
|
)
|
|
128
|
+
raise ReflexError(msg)
|
|
128
129
|
|
|
129
130
|
if isinstance(style_item, Var):
|
|
130
131
|
return style_item, style_item._get_all_var_data()
|
|
@@ -381,6 +382,7 @@ def format_as_emotion(style_dict: dict[str, Any]) -> Style | None:
|
|
|
381
382
|
if _var_data is not None:
|
|
382
383
|
emotion_style._var_data = VarData.merge(emotion_style._var_data, _var_data)
|
|
383
384
|
return emotion_style
|
|
385
|
+
return None
|
|
384
386
|
|
|
385
387
|
|
|
386
388
|
def convert_dict_to_style_and_format_emotion(
|