reflex 0.7.13a2__py3-none-any.whl → 0.7.14a2__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 +64 -69
- 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 +49 -41
- 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 +14 -15
- reflex/components/el/elements/forms.pyi +15 -32
- 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.pyi +0 -7
- reflex/components/radix/primitives/base.py +1 -3
- reflex/components/radix/primitives/base.pyi +0 -2
- reflex/components/radix/primitives/drawer.pyi +0 -11
- reflex/components/radix/primitives/form.py +4 -8
- 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 +2 -4
- 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 +8 -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 +20 -2
- 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.13a2.dist-info → reflex-0.7.14a2.dist-info}/METADATA +1 -1
- reflex-0.7.14a2.dist-info/RECORD +407 -0
- reflex-0.7.13a2.dist-info/RECORD +0 -407
- {reflex-0.7.13a2.dist-info → reflex-0.7.14a2.dist-info}/WHEEL +0 -0
- {reflex-0.7.13a2.dist-info → reflex-0.7.14a2.dist-info}/entry_points.txt +0 -0
- {reflex-0.7.13a2.dist-info → reflex-0.7.14a2.dist-info}/licenses/LICENSE +0 -0
reflex/istate/proxy.py
CHANGED
|
@@ -122,9 +122,8 @@ class StateProxy(wrapt.ObjectProxy):
|
|
|
122
122
|
self._self_actx_lock.locked()
|
|
123
123
|
and current_task == self._self_actx_lock_holder
|
|
124
124
|
):
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
)
|
|
125
|
+
msg = "The state is already mutable. Do not nest `async with self` blocks."
|
|
126
|
+
raise ImmutableStateError(msg)
|
|
128
127
|
|
|
129
128
|
from reflex.state import _substate_key
|
|
130
129
|
|
|
@@ -173,7 +172,8 @@ class StateProxy(wrapt.ObjectProxy):
|
|
|
173
172
|
Raises:
|
|
174
173
|
TypeError: always, because only async contextmanager protocol is supported.
|
|
175
174
|
"""
|
|
176
|
-
|
|
175
|
+
msg = "Background task must use `async with self` to modify state."
|
|
176
|
+
raise TypeError(msg)
|
|
177
177
|
|
|
178
178
|
def __exit__(self, *exc_info: Any) -> None:
|
|
179
179
|
"""Exit the regular context manager protocol.
|
|
@@ -181,7 +181,6 @@ class StateProxy(wrapt.ObjectProxy):
|
|
|
181
181
|
Args:
|
|
182
182
|
exc_info: The exception info tuple.
|
|
183
183
|
"""
|
|
184
|
-
pass
|
|
185
184
|
|
|
186
185
|
def __getattr__(self, name: str) -> Any:
|
|
187
186
|
"""Get the attribute from the underlying state instance.
|
|
@@ -196,10 +195,11 @@ class StateProxy(wrapt.ObjectProxy):
|
|
|
196
195
|
ImmutableStateError: If the state is not in mutable mode.
|
|
197
196
|
"""
|
|
198
197
|
if name in ["substates", "parent_state"] and not self._is_mutable():
|
|
199
|
-
|
|
198
|
+
msg = (
|
|
200
199
|
"Background task StateProxy is immutable outside of a context "
|
|
201
200
|
"manager. Use `async with self` to modify state."
|
|
202
201
|
)
|
|
202
|
+
raise ImmutableStateError(msg)
|
|
203
203
|
|
|
204
204
|
value = super().__getattr__(name)
|
|
205
205
|
if not name.startswith("_self_") and isinstance(value, MutableProxy):
|
|
@@ -243,10 +243,11 @@ class StateProxy(wrapt.ObjectProxy):
|
|
|
243
243
|
super().__setattr__(name, value)
|
|
244
244
|
return
|
|
245
245
|
|
|
246
|
-
|
|
246
|
+
msg = (
|
|
247
247
|
"Background task StateProxy is immutable outside of a context "
|
|
248
248
|
"manager. Use `async with self` to modify state."
|
|
249
249
|
)
|
|
250
|
+
raise ImmutableStateError(msg)
|
|
250
251
|
|
|
251
252
|
def get_substate(self, path: Sequence[str]) -> BaseState:
|
|
252
253
|
"""Only allow substate access with lock held.
|
|
@@ -261,10 +262,11 @@ class StateProxy(wrapt.ObjectProxy):
|
|
|
261
262
|
ImmutableStateError: If the state is not in mutable mode.
|
|
262
263
|
"""
|
|
263
264
|
if not self._is_mutable():
|
|
264
|
-
|
|
265
|
+
msg = (
|
|
265
266
|
"Background task StateProxy is immutable outside of a context "
|
|
266
267
|
"manager. Use `async with self` to modify state."
|
|
267
268
|
)
|
|
269
|
+
raise ImmutableStateError(msg)
|
|
268
270
|
return self.__wrapped__.get_substate(path)
|
|
269
271
|
|
|
270
272
|
async def get_state(self, state_cls: type[BaseState]) -> BaseState:
|
|
@@ -280,10 +282,11 @@ class StateProxy(wrapt.ObjectProxy):
|
|
|
280
282
|
ImmutableStateError: If the state is not in mutable mode.
|
|
281
283
|
"""
|
|
282
284
|
if not self._is_mutable():
|
|
283
|
-
|
|
285
|
+
msg = (
|
|
284
286
|
"Background task StateProxy is immutable outside of a context "
|
|
285
287
|
"manager. Use `async with self` to modify state."
|
|
286
288
|
)
|
|
289
|
+
raise ImmutableStateError(msg)
|
|
287
290
|
return type(self)(
|
|
288
291
|
await self.__wrapped__.get_state(state_cls), parent_state_proxy=self
|
|
289
292
|
)
|
|
@@ -323,7 +326,8 @@ class ReadOnlyStateProxy(StateProxy):
|
|
|
323
326
|
# Special case attributes of the proxy itself, not applied to the wrapped object.
|
|
324
327
|
super().__setattr__(name, value)
|
|
325
328
|
return
|
|
326
|
-
|
|
329
|
+
msg = "This is a read-only state proxy."
|
|
330
|
+
raise NotImplementedError(msg)
|
|
327
331
|
|
|
328
332
|
def mark_dirty(self):
|
|
329
333
|
"""Mark the state as dirty.
|
|
@@ -331,7 +335,8 @@ class ReadOnlyStateProxy(StateProxy):
|
|
|
331
335
|
Raises:
|
|
332
336
|
NotImplementedError: Always raised when trying to mark the proxied state as dirty.
|
|
333
337
|
"""
|
|
334
|
-
|
|
338
|
+
msg = "This is a read-only state proxy."
|
|
339
|
+
raise NotImplementedError(msg)
|
|
335
340
|
|
|
336
341
|
|
|
337
342
|
class MutableProxy(wrapt.ObjectProxy):
|
|
@@ -460,6 +465,7 @@ class MutableProxy(wrapt.ObjectProxy):
|
|
|
460
465
|
self._self_state._mark_dirty()
|
|
461
466
|
if wrapped is not None:
|
|
462
467
|
return wrapped(*args, **(kwargs or {}))
|
|
468
|
+
return None
|
|
463
469
|
|
|
464
470
|
@classmethod
|
|
465
471
|
def _is_mutable_type(cls, value: Any) -> bool:
|
|
@@ -748,10 +754,11 @@ class ImmutableMutableProxy(MutableProxy):
|
|
|
748
754
|
ImmutableStateError: if the StateProxy is not mutable.
|
|
749
755
|
"""
|
|
750
756
|
if not self._self_state._is_mutable():
|
|
751
|
-
|
|
757
|
+
msg = (
|
|
752
758
|
"Background task StateProxy is immutable outside of a context "
|
|
753
759
|
"manager. Use `async with self` to modify state."
|
|
754
760
|
)
|
|
761
|
+
raise ImmutableStateError(msg)
|
|
755
762
|
return super()._mark_dirty(
|
|
756
763
|
wrapped=wrapped, instance=instance, args=args, kwargs=kwargs
|
|
757
764
|
)
|
reflex/model.py
CHANGED
|
@@ -83,7 +83,8 @@ def get_engine(url: str | None = None) -> sqlalchemy.engine.Engine:
|
|
|
83
83
|
conf = get_config()
|
|
84
84
|
url = url or conf.db_url
|
|
85
85
|
if url is None:
|
|
86
|
-
|
|
86
|
+
msg = "No database url configured"
|
|
87
|
+
raise ValueError(msg)
|
|
87
88
|
|
|
88
89
|
global _ENGINE
|
|
89
90
|
if url in _ENGINE:
|
|
@@ -125,7 +126,8 @@ def get_async_engine(url: str | None) -> sqlalchemy.ext.asyncio.AsyncEngine:
|
|
|
125
126
|
f"db_url `{_safe_db_url_for_logging(conf.db_url)}`."
|
|
126
127
|
)
|
|
127
128
|
if url is None:
|
|
128
|
-
|
|
129
|
+
msg = "No async database url configured"
|
|
130
|
+
raise ValueError(msg)
|
|
129
131
|
|
|
130
132
|
global _ASYNC_ENGINE
|
|
131
133
|
if url in _ASYNC_ENGINE:
|
|
@@ -271,7 +273,7 @@ class Model(Base, sqlmodel.SQLModel): # pyright: ignore [reportGeneralTypeIssue
|
|
|
271
273
|
"""
|
|
272
274
|
if hasattr(value, "dict"):
|
|
273
275
|
return value.dict()
|
|
274
|
-
|
|
276
|
+
if isinstance(value, list):
|
|
275
277
|
return [cls._dict_recursive(item) for item in value]
|
|
276
278
|
return value
|
|
277
279
|
|
|
@@ -481,7 +483,7 @@ class Model(Base, sqlmodel.SQLModel): # pyright: ignore [reportGeneralTypeIssue
|
|
|
481
483
|
None - indicating the process was skipped.
|
|
482
484
|
"""
|
|
483
485
|
if not environment.ALEMBIC_CONFIG.get().exists():
|
|
484
|
-
return
|
|
486
|
+
return None
|
|
485
487
|
|
|
486
488
|
with cls.get_db_engine().connect() as connection:
|
|
487
489
|
cls._alembic_upgrade(connection=connection)
|
reflex/plugins/base.py
CHANGED
|
@@ -99,3 +99,11 @@ class Plugin:
|
|
|
99
99
|
Args:
|
|
100
100
|
context: The context for the plugin.
|
|
101
101
|
"""
|
|
102
|
+
|
|
103
|
+
def __repr__(self):
|
|
104
|
+
"""Return a string representation of the plugin.
|
|
105
|
+
|
|
106
|
+
Returns:
|
|
107
|
+
A string representation of the plugin.
|
|
108
|
+
"""
|
|
109
|
+
return f"{self.__class__.__name__}()"
|
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
|
@@ -256,3 +256,11 @@ class Plugin(PluginBase):
|
|
|
256
256
|
str(Path(Dirs.STYLES) / (PageNames.STYLESHEET_ROOT + Ext.CSS)),
|
|
257
257
|
add_tailwind_to_css_file,
|
|
258
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)
|