reflex 0.8.16a1__py3-none-any.whl → 0.8.17a1__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/web/utils/state.js +3 -1
- reflex/app.py +11 -3
- reflex/compiler/templates.py +12 -2
- reflex/components/core/window_events.py +30 -9
- reflex/components/core/window_events.pyi +6 -5
- reflex/components/lucide/icon.py +2 -1
- reflex/components/plotly/plotly.py +9 -9
- reflex/components/recharts/recharts.py +2 -2
- reflex/constants/installer.py +2 -2
- reflex/environment.py +31 -0
- reflex/istate/manager/__init__.py +24 -2
- reflex/istate/manager/disk.py +15 -5
- reflex/istate/manager/memory.py +13 -4
- reflex/istate/manager/redis.py +27 -6
- reflex/istate/proxy.py +14 -12
- reflex/plugins/tailwind_v4.py +2 -2
- reflex/state.py +41 -11
- reflex/utils/frontend_skeleton.py +2 -0
- {reflex-0.8.16a1.dist-info → reflex-0.8.17a1.dist-info}/METADATA +40 -11
- {reflex-0.8.16a1.dist-info → reflex-0.8.17a1.dist-info}/RECORD +23 -23
- {reflex-0.8.16a1.dist-info → reflex-0.8.17a1.dist-info}/WHEEL +0 -0
- {reflex-0.8.16a1.dist-info → reflex-0.8.17a1.dist-info}/entry_points.txt +0 -0
- {reflex-0.8.16a1.dist-info → reflex-0.8.17a1.dist-info}/licenses/LICENSE +0 -0
|
@@ -665,7 +665,9 @@ export const connect = async (
|
|
|
665
665
|
}
|
|
666
666
|
}
|
|
667
667
|
applyClientStorageDelta(client_storage, update.delta);
|
|
668
|
-
|
|
668
|
+
if (update.final !== null) {
|
|
669
|
+
event_processing = !update.final;
|
|
670
|
+
}
|
|
669
671
|
if (update.events) {
|
|
670
672
|
queueEvents(update.events, socket, false, navigate, params);
|
|
671
673
|
}
|
reflex/app.py
CHANGED
|
@@ -1556,11 +1556,14 @@ class App(MiddlewareMixin, LifespanMixin):
|
|
|
1556
1556
|
)
|
|
1557
1557
|
|
|
1558
1558
|
@contextlib.asynccontextmanager
|
|
1559
|
-
async def modify_state(
|
|
1559
|
+
async def modify_state(
|
|
1560
|
+
self, token: str, background: bool = False
|
|
1561
|
+
) -> AsyncIterator[BaseState]:
|
|
1560
1562
|
"""Modify the state out of band.
|
|
1561
1563
|
|
|
1562
1564
|
Args:
|
|
1563
1565
|
token: The token to modify the state for.
|
|
1566
|
+
background: Whether the modification is happening in a background task.
|
|
1564
1567
|
|
|
1565
1568
|
Yields:
|
|
1566
1569
|
The state to modify.
|
|
@@ -1581,7 +1584,10 @@ class App(MiddlewareMixin, LifespanMixin):
|
|
|
1581
1584
|
# When the state is modified reset dirty status and emit the delta to the frontend.
|
|
1582
1585
|
state._clean()
|
|
1583
1586
|
await self.event_namespace.emit_update(
|
|
1584
|
-
update=StateUpdate(
|
|
1587
|
+
update=StateUpdate(
|
|
1588
|
+
delta=delta,
|
|
1589
|
+
final=True if not background else None,
|
|
1590
|
+
),
|
|
1585
1591
|
token=token,
|
|
1586
1592
|
)
|
|
1587
1593
|
|
|
@@ -1758,7 +1764,9 @@ async def process(
|
|
|
1758
1764
|
constants.RouteVar.CLIENT_IP: client_ip,
|
|
1759
1765
|
})
|
|
1760
1766
|
# Get the state for the session exclusively.
|
|
1761
|
-
async with app.state_manager.modify_state(
|
|
1767
|
+
async with app.state_manager.modify_state(
|
|
1768
|
+
event.substate_token, event=event
|
|
1769
|
+
) as state:
|
|
1762
1770
|
# When this is a brand new instance of the state, signal the
|
|
1763
1771
|
# frontend to reload before processing it.
|
|
1764
1772
|
if (
|
reflex/compiler/templates.py
CHANGED
|
@@ -4,7 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import json
|
|
6
6
|
from collections.abc import Iterable, Mapping
|
|
7
|
-
from typing import TYPE_CHECKING, Any
|
|
7
|
+
from typing import TYPE_CHECKING, Any, Literal
|
|
8
8
|
|
|
9
9
|
from reflex import constants
|
|
10
10
|
from reflex.constants import Hooks
|
|
@@ -492,13 +492,21 @@ def package_json_template(
|
|
|
492
492
|
})
|
|
493
493
|
|
|
494
494
|
|
|
495
|
-
def vite_config_template(
|
|
495
|
+
def vite_config_template(
|
|
496
|
+
base: str,
|
|
497
|
+
hmr: bool,
|
|
498
|
+
force_full_reload: bool,
|
|
499
|
+
experimental_hmr: bool,
|
|
500
|
+
sourcemap: bool | Literal["inline", "hidden"],
|
|
501
|
+
):
|
|
496
502
|
"""Template for vite.config.js.
|
|
497
503
|
|
|
498
504
|
Args:
|
|
499
505
|
base: The base path for the Vite config.
|
|
500
506
|
hmr: Whether to enable hot module replacement.
|
|
501
507
|
force_full_reload: Whether to force a full reload on changes.
|
|
508
|
+
experimental_hmr: Whether to enable experimental HMR features.
|
|
509
|
+
sourcemap: The sourcemap configuration.
|
|
502
510
|
|
|
503
511
|
Returns:
|
|
504
512
|
Rendered vite.config.js content as string.
|
|
@@ -550,6 +558,7 @@ export default defineConfig((config) => ({{
|
|
|
550
558
|
].concat({"[fullReload()]" if force_full_reload else "[]"}),
|
|
551
559
|
build: {{
|
|
552
560
|
assetsDir: "{base}assets".slice(1),
|
|
561
|
+
sourcemap: {"true" if sourcemap is True else "false" if sourcemap is False else repr(sourcemap)},
|
|
553
562
|
rollupOptions: {{
|
|
554
563
|
onwarn(warning, warn) {{
|
|
555
564
|
if (warning.code === "EVAL" && warning.id && warning.id.endsWith("state.js")) return;
|
|
@@ -570,6 +579,7 @@ export default defineConfig((config) => ({{
|
|
|
570
579
|
}},
|
|
571
580
|
experimental: {{
|
|
572
581
|
enableNativePlugin: false,
|
|
582
|
+
hmr: {"true" if experimental_hmr else "false"},
|
|
573
583
|
}},
|
|
574
584
|
server: {{
|
|
575
585
|
port: process.env.PORT,
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
"""Window event listener component for Reflex."""
|
|
2
2
|
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any, cast
|
|
6
|
+
|
|
3
7
|
import reflex as rx
|
|
4
8
|
from reflex.components.base.fragment import Fragment
|
|
9
|
+
from reflex.components.component import StatefulComponent, field
|
|
5
10
|
from reflex.constants.compiler import Hooks
|
|
6
11
|
from reflex.event import key_event, no_args_event_spec
|
|
7
12
|
from reflex.vars.base import Var, VarData
|
|
@@ -61,6 +66,23 @@ class WindowEventListener(Fragment):
|
|
|
61
66
|
on_popstate: rx.EventHandler[no_args_event_spec]
|
|
62
67
|
on_storage: rx.EventHandler[_on_storage_spec]
|
|
63
68
|
|
|
69
|
+
hooks: list[str] = field(default_factory=list, is_javascript_property=False)
|
|
70
|
+
|
|
71
|
+
@classmethod
|
|
72
|
+
def create(cls, **props) -> WindowEventListener:
|
|
73
|
+
"""Create a WindowEventListener component.
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
**props: The props to set on the component.
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
The created component.
|
|
80
|
+
"""
|
|
81
|
+
real_component = cast("WindowEventListener", super().create(**props))
|
|
82
|
+
hooks = StatefulComponent._fix_event_triggers(real_component)
|
|
83
|
+
real_component.hooks = hooks
|
|
84
|
+
return real_component
|
|
85
|
+
|
|
64
86
|
def _exclude_props(self) -> list[str]:
|
|
65
87
|
"""Exclude event handler props from being passed to Fragment.
|
|
66
88
|
|
|
@@ -69,31 +91,30 @@ class WindowEventListener(Fragment):
|
|
|
69
91
|
"""
|
|
70
92
|
return [*super()._exclude_props(), *self.event_triggers.keys()]
|
|
71
93
|
|
|
72
|
-
def add_hooks(self) -> list[str | Var[
|
|
94
|
+
def add_hooks(self) -> list[str | Var[Any]]:
|
|
73
95
|
"""Add hooks to register window event listeners.
|
|
74
96
|
|
|
75
97
|
Returns:
|
|
76
98
|
The hooks to add to the component.
|
|
77
99
|
"""
|
|
78
|
-
hooks = []
|
|
100
|
+
hooks: list[str | Var[Any]] = [*self.hooks]
|
|
79
101
|
|
|
80
102
|
for prop_name, event_trigger in self.event_triggers.items():
|
|
81
103
|
# Get JS event name: remove on_ prefix and underscores
|
|
82
104
|
event_name = prop_name.removeprefix("on_").replace("_", "")
|
|
83
105
|
|
|
84
106
|
hook_expr = f"""
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
107
|
+
useEffect(() => {{
|
|
108
|
+
if (typeof window === 'undefined') return;
|
|
109
|
+
const fn = {Var.create(event_trigger)};
|
|
110
|
+
window.addEventListener('{event_name}', fn);
|
|
111
|
+
return () => window.removeEventListener('{event_name}', fn);
|
|
112
|
+
}}, []);
|
|
91
113
|
"""
|
|
92
114
|
|
|
93
115
|
hooks.append(
|
|
94
116
|
Var(
|
|
95
117
|
hook_expr,
|
|
96
|
-
_var_type="str",
|
|
97
118
|
_var_data=VarData(position=Hooks.HookPosition.POST_TRIGGER),
|
|
98
119
|
)
|
|
99
120
|
)
|
|
@@ -12,11 +12,11 @@ from reflex.event import EventType, KeyInputInfo, PointerEventInfo
|
|
|
12
12
|
from reflex.vars.base import Var
|
|
13
13
|
|
|
14
14
|
class WindowEventListener(Fragment):
|
|
15
|
-
def add_hooks(self) -> list[str | Var[str]]: ...
|
|
16
15
|
@classmethod
|
|
17
16
|
def create(
|
|
18
17
|
cls,
|
|
19
18
|
*children,
|
|
19
|
+
hooks: list[str] | None = None,
|
|
20
20
|
style: Sequence[Mapping[str, Any]]
|
|
21
21
|
| Mapping[str, Any]
|
|
22
22
|
| Var[Mapping[str, Any]]
|
|
@@ -62,10 +62,9 @@ class WindowEventListener(Fragment):
|
|
|
62
62
|
on_visibility_change: EventType[()] | EventType[bool] | None = None,
|
|
63
63
|
**props,
|
|
64
64
|
) -> WindowEventListener:
|
|
65
|
-
"""Create
|
|
65
|
+
"""Create a WindowEventListener component.
|
|
66
66
|
|
|
67
67
|
Args:
|
|
68
|
-
*children: The children of the component.
|
|
69
68
|
on_resize: Event handlers
|
|
70
69
|
style: The style of the component.
|
|
71
70
|
key: A unique key for the component.
|
|
@@ -73,10 +72,12 @@ class WindowEventListener(Fragment):
|
|
|
73
72
|
ref: The Var to pass as the ref to the component.
|
|
74
73
|
class_name: The class name for the component.
|
|
75
74
|
custom_attrs: custom attribute
|
|
76
|
-
**props: The props
|
|
75
|
+
**props: The props to set on the component.
|
|
77
76
|
|
|
78
77
|
Returns:
|
|
79
|
-
The component.
|
|
78
|
+
The created component.
|
|
80
79
|
"""
|
|
81
80
|
|
|
81
|
+
def add_hooks(self) -> list[str | Var[Any]]: ...
|
|
82
|
+
|
|
82
83
|
window_event_listener = WindowEventListener.create
|
reflex/components/lucide/icon.py
CHANGED
|
@@ -6,7 +6,7 @@ from reflex.utils.imports import ImportVar
|
|
|
6
6
|
from reflex.vars.base import LiteralVar, Var
|
|
7
7
|
from reflex.vars.sequence import LiteralStringVar, StringVar
|
|
8
8
|
|
|
9
|
-
LUCIDE_LIBRARY = "lucide-react@0.
|
|
9
|
+
LUCIDE_LIBRARY = "lucide-react@0.546.0"
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class LucideIconComponent(Component):
|
|
@@ -1115,6 +1115,7 @@ LUCIDE_ICON_LIST = [
|
|
|
1115
1115
|
"minimize",
|
|
1116
1116
|
"minus",
|
|
1117
1117
|
"monitor_check",
|
|
1118
|
+
"monitor_cloud",
|
|
1118
1119
|
"monitor_cog",
|
|
1119
1120
|
"monitor_dot",
|
|
1120
1121
|
"monitor_down",
|
|
@@ -72,7 +72,7 @@ class Plotly(NoSSRComponent):
|
|
|
72
72
|
|
|
73
73
|
library = "react-plotly.js@2.6.0"
|
|
74
74
|
|
|
75
|
-
lib_dependencies: list[str] = ["plotly.js@3.1.
|
|
75
|
+
lib_dependencies: list[str] = ["plotly.js@3.1.2"]
|
|
76
76
|
|
|
77
77
|
tag = "Plot"
|
|
78
78
|
|
|
@@ -303,7 +303,7 @@ class PlotlyBasic(Plotly):
|
|
|
303
303
|
|
|
304
304
|
library = "react-plotly.js@2.6.0"
|
|
305
305
|
|
|
306
|
-
lib_dependencies: list[str] = ["plotly.js-basic-dist-min@3.1.
|
|
306
|
+
lib_dependencies: list[str] = ["plotly.js-basic-dist-min@3.1.2"]
|
|
307
307
|
|
|
308
308
|
def add_imports(self) -> ImportDict | list[ImportDict]:
|
|
309
309
|
"""Add imports for the plotly basic component.
|
|
@@ -329,7 +329,7 @@ class PlotlyCartesian(Plotly):
|
|
|
329
329
|
|
|
330
330
|
library = "react-plotly.js@2.6.0"
|
|
331
331
|
|
|
332
|
-
lib_dependencies: list[str] = ["plotly.js-cartesian-dist-min@3.1.
|
|
332
|
+
lib_dependencies: list[str] = ["plotly.js-cartesian-dist-min@3.1.2"]
|
|
333
333
|
|
|
334
334
|
def add_imports(self) -> ImportDict | list[ImportDict]:
|
|
335
335
|
"""Add imports for the plotly cartesian component.
|
|
@@ -355,7 +355,7 @@ class PlotlyGeo(Plotly):
|
|
|
355
355
|
|
|
356
356
|
library = "react-plotly.js@2.6.0"
|
|
357
357
|
|
|
358
|
-
lib_dependencies: list[str] = ["plotly.js-geo-dist-min@3.1.
|
|
358
|
+
lib_dependencies: list[str] = ["plotly.js-geo-dist-min@3.1.2"]
|
|
359
359
|
|
|
360
360
|
def add_imports(self) -> ImportDict | list[ImportDict]:
|
|
361
361
|
"""Add imports for the plotly geo component.
|
|
@@ -381,7 +381,7 @@ class PlotlyGl3d(Plotly):
|
|
|
381
381
|
|
|
382
382
|
library = "react-plotly.js@2.6.0"
|
|
383
383
|
|
|
384
|
-
lib_dependencies: list[str] = ["plotly.js-gl3d-dist-min@3.1.
|
|
384
|
+
lib_dependencies: list[str] = ["plotly.js-gl3d-dist-min@3.1.2"]
|
|
385
385
|
|
|
386
386
|
def add_imports(self) -> ImportDict | list[ImportDict]:
|
|
387
387
|
"""Add imports for the plotly 3d component.
|
|
@@ -407,7 +407,7 @@ class PlotlyGl2d(Plotly):
|
|
|
407
407
|
|
|
408
408
|
library = "react-plotly.js@2.6.0"
|
|
409
409
|
|
|
410
|
-
lib_dependencies: list[str] = ["plotly.js-gl2d-dist-min@3.1.
|
|
410
|
+
lib_dependencies: list[str] = ["plotly.js-gl2d-dist-min@3.1.2"]
|
|
411
411
|
|
|
412
412
|
def add_imports(self) -> ImportDict | list[ImportDict]:
|
|
413
413
|
"""Add imports for the plotly 2d component.
|
|
@@ -433,7 +433,7 @@ class PlotlyMapbox(Plotly):
|
|
|
433
433
|
|
|
434
434
|
library = "react-plotly.js@2.6.0"
|
|
435
435
|
|
|
436
|
-
lib_dependencies: list[str] = ["plotly.js-mapbox-dist-min@3.1.
|
|
436
|
+
lib_dependencies: list[str] = ["plotly.js-mapbox-dist-min@3.1.2"]
|
|
437
437
|
|
|
438
438
|
def add_imports(self) -> ImportDict | list[ImportDict]:
|
|
439
439
|
"""Add imports for the plotly mapbox component.
|
|
@@ -459,7 +459,7 @@ class PlotlyFinance(Plotly):
|
|
|
459
459
|
|
|
460
460
|
library = "react-plotly.js@2.6.0"
|
|
461
461
|
|
|
462
|
-
lib_dependencies: list[str] = ["plotly.js-finance-dist-min@3.1.
|
|
462
|
+
lib_dependencies: list[str] = ["plotly.js-finance-dist-min@3.1.2"]
|
|
463
463
|
|
|
464
464
|
def add_imports(self) -> ImportDict | list[ImportDict]:
|
|
465
465
|
"""Add imports for the plotly finance component.
|
|
@@ -485,7 +485,7 @@ class PlotlyStrict(Plotly):
|
|
|
485
485
|
|
|
486
486
|
library = "react-plotly.js@2.6.0"
|
|
487
487
|
|
|
488
|
-
lib_dependencies: list[str] = ["plotly.js-strict-dist-min@3.1.
|
|
488
|
+
lib_dependencies: list[str] = ["plotly.js-strict-dist-min@3.1.2"]
|
|
489
489
|
|
|
490
490
|
def add_imports(self) -> ImportDict | list[ImportDict]:
|
|
491
491
|
"""Add imports for the plotly strict component.
|
|
@@ -8,7 +8,7 @@ from reflex.components.component import Component, MemoizationLeaf, NoSSRCompone
|
|
|
8
8
|
class Recharts(Component):
|
|
9
9
|
"""A component that wraps a recharts lib."""
|
|
10
10
|
|
|
11
|
-
library = "recharts@3.
|
|
11
|
+
library = "recharts@3.3.0"
|
|
12
12
|
|
|
13
13
|
def _get_style(self) -> dict:
|
|
14
14
|
return {"wrapperStyle": self.style}
|
|
@@ -17,7 +17,7 @@ class Recharts(Component):
|
|
|
17
17
|
class RechartsCharts(NoSSRComponent, MemoizationLeaf):
|
|
18
18
|
"""A component that wraps a recharts lib."""
|
|
19
19
|
|
|
20
|
-
library = "recharts@3.
|
|
20
|
+
library = "recharts@3.3.0"
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
LiteralAnimationEasing = Literal["ease", "ease-in", "ease-out", "ease-in-out", "linear"]
|
reflex/constants/installer.py
CHANGED
|
@@ -143,11 +143,11 @@ class PackageJson(SimpleNamespace):
|
|
|
143
143
|
"postcss-import": "16.1.1",
|
|
144
144
|
"@react-router/dev": _react_router_version,
|
|
145
145
|
"@react-router/fs-routes": _react_router_version,
|
|
146
|
-
"vite": "npm:rolldown-vite@7.1.
|
|
146
|
+
"vite": "npm:rolldown-vite@7.1.18",
|
|
147
147
|
}
|
|
148
148
|
OVERRIDES = {
|
|
149
149
|
# This should always match the `react` version in DEPENDENCIES for recharts compatibility.
|
|
150
150
|
"react-is": _react_version,
|
|
151
151
|
"cookie": "1.0.2",
|
|
152
|
-
"vite": "npm:rolldown-vite@7.1.
|
|
152
|
+
"vite": "npm:rolldown-vite@7.1.18",
|
|
153
153
|
}
|
reflex/environment.py
CHANGED
|
@@ -17,6 +17,7 @@ from typing import (
|
|
|
17
17
|
Annotated,
|
|
18
18
|
Any,
|
|
19
19
|
Generic,
|
|
20
|
+
Literal,
|
|
20
21
|
TypeVar,
|
|
21
22
|
get_args,
|
|
22
23
|
get_origin,
|
|
@@ -256,6 +257,27 @@ def interpret_env_var_value(
|
|
|
256
257
|
return interpret_existing_path_env(value, field_name)
|
|
257
258
|
if field_type is Plugin:
|
|
258
259
|
return interpret_plugin_env(value, field_name)
|
|
260
|
+
if get_origin(field_type) is Literal:
|
|
261
|
+
literal_values = get_args(field_type)
|
|
262
|
+
for literal_value in literal_values:
|
|
263
|
+
if isinstance(literal_value, str) and literal_value == value:
|
|
264
|
+
return literal_value
|
|
265
|
+
if isinstance(literal_value, bool):
|
|
266
|
+
try:
|
|
267
|
+
interpreted_bool = interpret_boolean_env(value, field_name)
|
|
268
|
+
if interpreted_bool == literal_value:
|
|
269
|
+
return interpreted_bool
|
|
270
|
+
except EnvironmentVarValueError:
|
|
271
|
+
continue
|
|
272
|
+
if isinstance(literal_value, int):
|
|
273
|
+
try:
|
|
274
|
+
interpreted_int = interpret_int_env(value, field_name)
|
|
275
|
+
if interpreted_int == literal_value:
|
|
276
|
+
return interpreted_int
|
|
277
|
+
except EnvironmentVarValueError:
|
|
278
|
+
continue
|
|
279
|
+
msg = f"Invalid literal value: {value!r} for {field_name}, expected one of {literal_values}"
|
|
280
|
+
raise EnvironmentVarValueError(msg)
|
|
259
281
|
if get_origin(field_type) in (list, Sequence):
|
|
260
282
|
return [
|
|
261
283
|
interpret_env_var_value(
|
|
@@ -687,6 +709,12 @@ class EnvironmentVariables:
|
|
|
687
709
|
# Whether to force a full reload on changes.
|
|
688
710
|
VITE_FORCE_FULL_RELOAD: EnvVar[bool] = env_var(False)
|
|
689
711
|
|
|
712
|
+
# Whether to enable Rolldown's experimental HMR.
|
|
713
|
+
VITE_EXPERIMENTAL_HMR: EnvVar[bool] = env_var(False)
|
|
714
|
+
|
|
715
|
+
# Whether to generate sourcemaps for the frontend.
|
|
716
|
+
VITE_SOURCEMAP: EnvVar[Literal[False, True, "inline", "hidden"]] = env_var(False) # noqa: RUF038
|
|
717
|
+
|
|
690
718
|
# Whether to enable SSR for the frontend.
|
|
691
719
|
REFLEX_SSR: EnvVar[bool] = env_var(True)
|
|
692
720
|
|
|
@@ -696,6 +724,9 @@ class EnvironmentVariables:
|
|
|
696
724
|
# How long to delay writing updated states to disk. (Higher values mean less writes, but more chance of lost data.)
|
|
697
725
|
REFLEX_STATE_MANAGER_DISK_DEBOUNCE_SECONDS: EnvVar[float] = env_var(2.0)
|
|
698
726
|
|
|
727
|
+
# How long to wait between automatic reload on frontend error to avoid reload loops.
|
|
728
|
+
REFLEX_AUTO_RELOAD_COOLDOWN_TIME_MS: EnvVar[int] = env_var(10_000)
|
|
729
|
+
|
|
699
730
|
|
|
700
731
|
environment = EnvironmentVariables()
|
|
701
732
|
|
|
@@ -4,14 +4,27 @@ import contextlib
|
|
|
4
4
|
import dataclasses
|
|
5
5
|
from abc import ABC, abstractmethod
|
|
6
6
|
from collections.abc import AsyncIterator
|
|
7
|
+
from typing import TypedDict
|
|
8
|
+
|
|
9
|
+
from typing_extensions import ReadOnly, Unpack
|
|
7
10
|
|
|
8
11
|
from reflex import constants
|
|
9
12
|
from reflex.config import get_config
|
|
13
|
+
from reflex.event import Event
|
|
10
14
|
from reflex.state import BaseState
|
|
11
15
|
from reflex.utils import console, prerequisites
|
|
12
16
|
from reflex.utils.exceptions import InvalidStateManagerModeError
|
|
13
17
|
|
|
14
18
|
|
|
19
|
+
class StateModificationContext(TypedDict, total=False):
|
|
20
|
+
"""The context for modifying state."""
|
|
21
|
+
|
|
22
|
+
event: ReadOnly[Event]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
EmptyContext = StateModificationContext()
|
|
26
|
+
|
|
27
|
+
|
|
15
28
|
@dataclasses.dataclass
|
|
16
29
|
class StateManager(ABC):
|
|
17
30
|
"""A class to manage many client states."""
|
|
@@ -71,21 +84,30 @@ class StateManager(ABC):
|
|
|
71
84
|
"""
|
|
72
85
|
|
|
73
86
|
@abstractmethod
|
|
74
|
-
async def set_state(
|
|
87
|
+
async def set_state(
|
|
88
|
+
self,
|
|
89
|
+
token: str,
|
|
90
|
+
state: BaseState,
|
|
91
|
+
**context: Unpack[StateModificationContext],
|
|
92
|
+
):
|
|
75
93
|
"""Set the state for a token.
|
|
76
94
|
|
|
77
95
|
Args:
|
|
78
96
|
token: The token to set the state for.
|
|
79
97
|
state: The state to set.
|
|
98
|
+
context: The state modification context.
|
|
80
99
|
"""
|
|
81
100
|
|
|
82
101
|
@abstractmethod
|
|
83
102
|
@contextlib.asynccontextmanager
|
|
84
|
-
async def modify_state(
|
|
103
|
+
async def modify_state(
|
|
104
|
+
self, token: str, **context: Unpack[StateModificationContext]
|
|
105
|
+
) -> AsyncIterator[BaseState]:
|
|
85
106
|
"""Modify the state for a token while holding exclusive lock.
|
|
86
107
|
|
|
87
108
|
Args:
|
|
88
109
|
token: The token to modify the state for.
|
|
110
|
+
context: The state modification context.
|
|
89
111
|
|
|
90
112
|
Yields:
|
|
91
113
|
The state for the token.
|
reflex/istate/manager/disk.py
CHANGED
|
@@ -9,10 +9,14 @@ from collections.abc import AsyncIterator
|
|
|
9
9
|
from hashlib import md5
|
|
10
10
|
from pathlib import Path
|
|
11
11
|
|
|
12
|
-
from typing_extensions import override
|
|
12
|
+
from typing_extensions import Unpack, override
|
|
13
13
|
|
|
14
14
|
from reflex.environment import environment
|
|
15
|
-
from reflex.istate.manager import
|
|
15
|
+
from reflex.istate.manager import (
|
|
16
|
+
StateManager,
|
|
17
|
+
StateModificationContext,
|
|
18
|
+
_default_token_expiration,
|
|
19
|
+
)
|
|
16
20
|
from reflex.state import BaseState, _split_substate_key, _substate_key
|
|
17
21
|
from reflex.utils import console, path_ops, prerequisites
|
|
18
22
|
from reflex.utils.misc import run_in_thread
|
|
@@ -301,12 +305,15 @@ class StateManagerDisk(StateManager):
|
|
|
301
305
|
await asyncio.sleep(0) # Yield to allow the task to start.
|
|
302
306
|
|
|
303
307
|
@override
|
|
304
|
-
async def set_state(
|
|
308
|
+
async def set_state(
|
|
309
|
+
self, token: str, state: BaseState, **context: Unpack[StateModificationContext]
|
|
310
|
+
):
|
|
305
311
|
"""Set the state for a token.
|
|
306
312
|
|
|
307
313
|
Args:
|
|
308
314
|
token: The token to set the state for.
|
|
309
315
|
state: The state to set.
|
|
316
|
+
context: The state modification context.
|
|
310
317
|
"""
|
|
311
318
|
client_token, _ = _split_substate_key(token)
|
|
312
319
|
if self._write_debounce_seconds > 0:
|
|
@@ -325,11 +332,14 @@ class StateManagerDisk(StateManager):
|
|
|
325
332
|
|
|
326
333
|
@override
|
|
327
334
|
@contextlib.asynccontextmanager
|
|
328
|
-
async def modify_state(
|
|
335
|
+
async def modify_state(
|
|
336
|
+
self, token: str, **context: Unpack[StateModificationContext]
|
|
337
|
+
) -> AsyncIterator[BaseState]:
|
|
329
338
|
"""Modify the state for a token while holding exclusive lock.
|
|
330
339
|
|
|
331
340
|
Args:
|
|
332
341
|
token: The token to modify the state for.
|
|
342
|
+
context: The state modification context.
|
|
333
343
|
|
|
334
344
|
Yields:
|
|
335
345
|
The state for the token.
|
|
@@ -344,7 +354,7 @@ class StateManagerDisk(StateManager):
|
|
|
344
354
|
async with self._states_locks[client_token]:
|
|
345
355
|
state = await self.get_state(token)
|
|
346
356
|
yield state
|
|
347
|
-
await self.set_state(token, state)
|
|
357
|
+
await self.set_state(token, state, **context)
|
|
348
358
|
|
|
349
359
|
async def close(self):
|
|
350
360
|
"""Close the state manager, flushing any pending writes to disk."""
|
reflex/istate/manager/memory.py
CHANGED
|
@@ -5,9 +5,9 @@ import contextlib
|
|
|
5
5
|
import dataclasses
|
|
6
6
|
from collections.abc import AsyncIterator
|
|
7
7
|
|
|
8
|
-
from typing_extensions import override
|
|
8
|
+
from typing_extensions import Unpack, override
|
|
9
9
|
|
|
10
|
-
from reflex.istate.manager import StateManager
|
|
10
|
+
from reflex.istate.manager import StateManager, StateModificationContext
|
|
11
11
|
from reflex.state import BaseState, _split_substate_key
|
|
12
12
|
|
|
13
13
|
|
|
@@ -43,23 +43,32 @@ class StateManagerMemory(StateManager):
|
|
|
43
43
|
return self.states[token]
|
|
44
44
|
|
|
45
45
|
@override
|
|
46
|
-
async def set_state(
|
|
46
|
+
async def set_state(
|
|
47
|
+
self,
|
|
48
|
+
token: str,
|
|
49
|
+
state: BaseState,
|
|
50
|
+
**context: Unpack[StateModificationContext],
|
|
51
|
+
):
|
|
47
52
|
"""Set the state for a token.
|
|
48
53
|
|
|
49
54
|
Args:
|
|
50
55
|
token: The token to set the state for.
|
|
51
56
|
state: The state to set.
|
|
57
|
+
context: The state modification context.
|
|
52
58
|
"""
|
|
53
59
|
token = _split_substate_key(token)[0]
|
|
54
60
|
self.states[token] = state
|
|
55
61
|
|
|
56
62
|
@override
|
|
57
63
|
@contextlib.asynccontextmanager
|
|
58
|
-
async def modify_state(
|
|
64
|
+
async def modify_state(
|
|
65
|
+
self, token: str, **context: Unpack[StateModificationContext]
|
|
66
|
+
) -> AsyncIterator[BaseState]:
|
|
59
67
|
"""Modify the state for a token while holding exclusive lock.
|
|
60
68
|
|
|
61
69
|
Args:
|
|
62
70
|
token: The token to modify the state for.
|
|
71
|
+
context: The state modification context.
|
|
63
72
|
|
|
64
73
|
Yields:
|
|
65
74
|
The state for the token.
|
reflex/istate/manager/redis.py
CHANGED
|
@@ -10,11 +10,15 @@ from collections.abc import AsyncIterator
|
|
|
10
10
|
from redis import ResponseError
|
|
11
11
|
from redis.asyncio import Redis
|
|
12
12
|
from redis.asyncio.client import PubSub
|
|
13
|
-
from typing_extensions import override
|
|
13
|
+
from typing_extensions import Unpack, override
|
|
14
14
|
|
|
15
15
|
from reflex.config import get_config
|
|
16
16
|
from reflex.environment import environment
|
|
17
|
-
from reflex.istate.manager import
|
|
17
|
+
from reflex.istate.manager import (
|
|
18
|
+
StateManager,
|
|
19
|
+
StateModificationContext,
|
|
20
|
+
_default_token_expiration,
|
|
21
|
+
)
|
|
18
22
|
from reflex.state import BaseState, _split_substate_key, _substate_key
|
|
19
23
|
from reflex.utils import console
|
|
20
24
|
from reflex.utils.exceptions import (
|
|
@@ -261,7 +265,9 @@ class StateManagerRedis(StateManager):
|
|
|
261
265
|
self,
|
|
262
266
|
token: str,
|
|
263
267
|
state: BaseState,
|
|
268
|
+
*,
|
|
264
269
|
lock_id: bytes | None = None,
|
|
270
|
+
**context: Unpack[StateModificationContext],
|
|
265
271
|
):
|
|
266
272
|
"""Set the state for a token.
|
|
267
273
|
|
|
@@ -269,6 +275,7 @@ class StateManagerRedis(StateManager):
|
|
|
269
275
|
token: The token to set the state for.
|
|
270
276
|
state: The state to set.
|
|
271
277
|
lock_id: If provided, the lock_key must be set to this value to set the state.
|
|
278
|
+
context: The event context.
|
|
272
279
|
|
|
273
280
|
Raises:
|
|
274
281
|
LockExpiredError: If lock_id is provided and the lock for the token is not held by that ID.
|
|
@@ -283,6 +290,11 @@ class StateManagerRedis(StateManager):
|
|
|
283
290
|
f"Lock expired for token {token} while processing. Consider increasing "
|
|
284
291
|
f"`app.state_manager.lock_expiration` (currently {self.lock_expiration}) "
|
|
285
292
|
"or use `@rx.event(background=True)` decorator for long-running tasks."
|
|
293
|
+
+ (
|
|
294
|
+
f" Happened in event: {event.name}"
|
|
295
|
+
if (event := context.get("event")) is not None
|
|
296
|
+
else ""
|
|
297
|
+
)
|
|
286
298
|
)
|
|
287
299
|
raise LockExpiredError(msg)
|
|
288
300
|
if lock_id is not None:
|
|
@@ -292,7 +304,12 @@ class StateManagerRedis(StateManager):
|
|
|
292
304
|
if time_taken > self.lock_warning_threshold / 1000:
|
|
293
305
|
console.warn(
|
|
294
306
|
f"Lock for token {token} was held too long {time_taken=}s, "
|
|
295
|
-
f"use `@rx.event(background=True)` decorator for long-running tasks."
|
|
307
|
+
f"use `@rx.event(background=True)` decorator for long-running tasks."
|
|
308
|
+
+ (
|
|
309
|
+
f" Happened in event: {event.name}"
|
|
310
|
+
if (event := context.get("event")) is not None
|
|
311
|
+
else ""
|
|
312
|
+
),
|
|
296
313
|
dedupe=True,
|
|
297
314
|
)
|
|
298
315
|
|
|
@@ -308,7 +325,8 @@ class StateManagerRedis(StateManager):
|
|
|
308
325
|
self.set_state(
|
|
309
326
|
_substate_key(client_token, substate),
|
|
310
327
|
substate,
|
|
311
|
-
lock_id,
|
|
328
|
+
lock_id=lock_id,
|
|
329
|
+
**context,
|
|
312
330
|
),
|
|
313
331
|
name=f"reflex_set_state|{client_token}|{substate.get_full_name()}",
|
|
314
332
|
)
|
|
@@ -330,11 +348,14 @@ class StateManagerRedis(StateManager):
|
|
|
330
348
|
|
|
331
349
|
@override
|
|
332
350
|
@contextlib.asynccontextmanager
|
|
333
|
-
async def modify_state(
|
|
351
|
+
async def modify_state(
|
|
352
|
+
self, token: str, **context: Unpack[StateModificationContext]
|
|
353
|
+
) -> AsyncIterator[BaseState]:
|
|
334
354
|
"""Modify the state for a token while holding exclusive lock.
|
|
335
355
|
|
|
336
356
|
Args:
|
|
337
357
|
token: The token to modify the state for.
|
|
358
|
+
context: The state modification context.
|
|
338
359
|
|
|
339
360
|
Yields:
|
|
340
361
|
The state for the token.
|
|
@@ -342,7 +363,7 @@ class StateManagerRedis(StateManager):
|
|
|
342
363
|
async with self._lock(token) as lock_id:
|
|
343
364
|
state = await self.get_state(token)
|
|
344
365
|
yield state
|
|
345
|
-
await self.set_state(token, state, lock_id)
|
|
366
|
+
await self.set_state(token, state, lock_id=lock_id, **context)
|
|
346
367
|
|
|
347
368
|
@staticmethod
|
|
348
369
|
def _lock_key(token: str) -> bytes:
|
reflex/istate/proxy.py
CHANGED
|
@@ -131,7 +131,9 @@ class StateProxy(wrapt.ObjectProxy):
|
|
|
131
131
|
|
|
132
132
|
await self._self_actx_lock.acquire()
|
|
133
133
|
self._self_actx_lock_holder = current_task
|
|
134
|
-
self._self_actx = self._self_app.modify_state(
|
|
134
|
+
self._self_actx = self._self_app.modify_state(
|
|
135
|
+
token=self._self_substate_token, background=True
|
|
136
|
+
)
|
|
135
137
|
mutable_state = await self._self_actx.__aenter__()
|
|
136
138
|
super().__setattr__(
|
|
137
139
|
"__wrapped__", mutable_state.get_substate(self._self_substate_path)
|
|
@@ -198,7 +200,7 @@ class StateProxy(wrapt.ObjectProxy):
|
|
|
198
200
|
)
|
|
199
201
|
raise ImmutableStateError(msg)
|
|
200
202
|
|
|
201
|
-
value = super().__getattr__(name)
|
|
203
|
+
value = super().__getattr__(name) # pyright: ignore[reportAttributeAccessIssue]
|
|
202
204
|
if not name.startswith("_self_") and isinstance(value, MutableProxy):
|
|
203
205
|
# ensure mutations to these containers are blocked unless proxy is _mutable
|
|
204
206
|
return ImmutableMutableProxy(
|
|
@@ -397,7 +399,7 @@ class MutableProxy(wrapt.ObjectProxy):
|
|
|
397
399
|
}
|
|
398
400
|
|
|
399
401
|
# Dynamically generated classes for tracking dataclass mutations.
|
|
400
|
-
__dataclass_proxies__: dict[
|
|
402
|
+
__dataclass_proxies__: dict[str, type] = {}
|
|
401
403
|
|
|
402
404
|
def __new__(cls, wrapped: Any, *args, **kwargs) -> MutableProxy:
|
|
403
405
|
"""Create a proxy instance for a mutable object that tracks changes.
|
|
@@ -427,7 +429,7 @@ class MutableProxy(wrapt.ObjectProxy):
|
|
|
427
429
|
},
|
|
428
430
|
)
|
|
429
431
|
cls = cls.__dataclass_proxies__[wrapper_cls_name]
|
|
430
|
-
return super().__new__(cls)
|
|
432
|
+
return super().__new__(cls) # pyright: ignore[reportArgumentType]
|
|
431
433
|
|
|
432
434
|
def __init__(self, wrapped: Any, state: BaseState, field_name: str):
|
|
433
435
|
"""Create a proxy for a mutable object that tracks changes.
|
|
@@ -543,7 +545,7 @@ class MutableProxy(wrapt.ObjectProxy):
|
|
|
543
545
|
Returns:
|
|
544
546
|
The attribute value.
|
|
545
547
|
"""
|
|
546
|
-
value = super().__getattr__(__name)
|
|
548
|
+
value = super().__getattr__(__name) # pyright: ignore[reportAttributeAccessIssue]
|
|
547
549
|
|
|
548
550
|
if callable(value):
|
|
549
551
|
if __name in self.__mark_dirty_attrs__:
|
|
@@ -554,7 +556,7 @@ class MutableProxy(wrapt.ObjectProxy):
|
|
|
554
556
|
# Wrap methods that may return mutable objects tied to the state.
|
|
555
557
|
value = wrapt.FunctionWrapper(
|
|
556
558
|
value,
|
|
557
|
-
self._wrap_recursive_decorator,
|
|
559
|
+
self._wrap_recursive_decorator, # pyright: ignore[reportArgumentType]
|
|
558
560
|
)
|
|
559
561
|
|
|
560
562
|
if (
|
|
@@ -564,8 +566,8 @@ class MutableProxy(wrapt.ObjectProxy):
|
|
|
564
566
|
):
|
|
565
567
|
# Wrap methods called on Base subclasses, which might do _anything_
|
|
566
568
|
return wrapt.FunctionWrapper(
|
|
567
|
-
functools.partial(value.__func__, self), # pyright: ignore [reportFunctionMemberAccess]
|
|
568
|
-
self._wrap_recursive_decorator,
|
|
569
|
+
functools.partial(value.__func__, self), # pyright: ignore [reportFunctionMemberAccess, reportAttributeAccessIssue]
|
|
570
|
+
self._wrap_recursive_decorator, # pyright: ignore[reportArgumentType]
|
|
569
571
|
)
|
|
570
572
|
|
|
571
573
|
if is_mutable_type(type(value)) and __name not in (
|
|
@@ -587,7 +589,7 @@ class MutableProxy(wrapt.ObjectProxy):
|
|
|
587
589
|
Returns:
|
|
588
590
|
The item value.
|
|
589
591
|
"""
|
|
590
|
-
value = super().__getitem__(key)
|
|
592
|
+
value = super().__getitem__(key) # pyright: ignore[reportAttributeAccessIssue]
|
|
591
593
|
if isinstance(key, slice) and isinstance(value, list):
|
|
592
594
|
return [self._wrap_recursive(item) for item in value]
|
|
593
595
|
# Recursively wrap mutable items retrieved through this proxy.
|
|
@@ -599,7 +601,7 @@ class MutableProxy(wrapt.ObjectProxy):
|
|
|
599
601
|
Yields:
|
|
600
602
|
Each item value (possibly wrapped in MutableProxy).
|
|
601
603
|
"""
|
|
602
|
-
for value in super().__iter__():
|
|
604
|
+
for value in super().__iter__(): # pyright: ignore[reportAttributeAccessIssue]
|
|
603
605
|
# Recursively wrap mutable items retrieved through this proxy.
|
|
604
606
|
yield self._wrap_recursive(value)
|
|
605
607
|
|
|
@@ -617,7 +619,7 @@ class MutableProxy(wrapt.ObjectProxy):
|
|
|
617
619
|
Args:
|
|
618
620
|
key: The key of the item.
|
|
619
621
|
"""
|
|
620
|
-
self._mark_dirty(super().__delitem__, args=(key,))
|
|
622
|
+
self._mark_dirty(super().__delitem__, args=(key,)) # pyright: ignore[reportAttributeAccessIssue]
|
|
621
623
|
|
|
622
624
|
def __setitem__(self, key: str, value: Any):
|
|
623
625
|
"""Set the item on the proxied object and mark state dirty.
|
|
@@ -626,7 +628,7 @@ class MutableProxy(wrapt.ObjectProxy):
|
|
|
626
628
|
key: The key of the item.
|
|
627
629
|
value: The value of the item.
|
|
628
630
|
"""
|
|
629
|
-
self._mark_dirty(super().__setitem__, args=(key, value))
|
|
631
|
+
self._mark_dirty(super().__setitem__, args=(key, value)) # pyright: ignore[reportAttributeAccessIssue]
|
|
630
632
|
|
|
631
633
|
def __setattr__(self, name: str, value: Any):
|
|
632
634
|
"""Set the attribute on the proxied object and mark state dirty.
|
reflex/plugins/tailwind_v4.py
CHANGED
|
@@ -17,7 +17,7 @@ class Constants(SimpleNamespace):
|
|
|
17
17
|
"""Tailwind constants."""
|
|
18
18
|
|
|
19
19
|
# The Tailwindcss version
|
|
20
|
-
VERSION = "tailwindcss@4.1.
|
|
20
|
+
VERSION = "tailwindcss@4.1.15"
|
|
21
21
|
# The Tailwind config.
|
|
22
22
|
CONFIG = "tailwind.config.js"
|
|
23
23
|
# Default Tailwind content paths
|
|
@@ -156,7 +156,7 @@ class TailwindV4Plugin(TailwindPlugin):
|
|
|
156
156
|
return [
|
|
157
157
|
*super().get_frontend_development_dependencies(**context),
|
|
158
158
|
Constants.VERSION,
|
|
159
|
-
"@tailwindcss/postcss@4.1.
|
|
159
|
+
"@tailwindcss/postcss@4.1.15",
|
|
160
160
|
]
|
|
161
161
|
|
|
162
162
|
def pre_compile(self, **context):
|
reflex/state.py
CHANGED
|
@@ -11,11 +11,12 @@ import datetime
|
|
|
11
11
|
import functools
|
|
12
12
|
import inspect
|
|
13
13
|
import pickle
|
|
14
|
+
import re
|
|
14
15
|
import sys
|
|
15
16
|
import time
|
|
16
17
|
import typing
|
|
17
18
|
import warnings
|
|
18
|
-
from collections.abc import AsyncIterator, Callable, Sequence
|
|
19
|
+
from collections.abc import AsyncIterator, Callable, Iterator, Sequence
|
|
19
20
|
from enum import Enum
|
|
20
21
|
from hashlib import md5
|
|
21
22
|
from importlib.util import find_spec
|
|
@@ -34,6 +35,7 @@ from reflex.event import (
|
|
|
34
35
|
Event,
|
|
35
36
|
EventHandler,
|
|
36
37
|
EventSpec,
|
|
38
|
+
call_script,
|
|
37
39
|
fix_events,
|
|
38
40
|
)
|
|
39
41
|
from reflex.istate import HANDLED_PICKLE_ERRORS, debug_failed_pickles
|
|
@@ -523,15 +525,17 @@ class BaseState(EvenMoreBasicBaseState):
|
|
|
523
525
|
|
|
524
526
|
new_backend_vars = {
|
|
525
527
|
name: value if not isinstance(value, Field) else value.default_value()
|
|
526
|
-
for
|
|
527
|
-
|
|
528
|
+
for mixin_cls in [*cls._mixins(), cls]
|
|
529
|
+
for name, value in list(mixin_cls.__dict__.items())
|
|
530
|
+
if types.is_backend_base_variable(name, mixin_cls)
|
|
528
531
|
}
|
|
529
532
|
# Add annotated backend vars that may not have a default value.
|
|
530
533
|
new_backend_vars.update({
|
|
531
534
|
name: cls._get_var_default(name, annotation_value)
|
|
532
|
-
for
|
|
535
|
+
for mixin_cls in [*cls._mixins(), cls]
|
|
536
|
+
for name, annotation_value in mixin_cls._get_type_hints().items()
|
|
533
537
|
if name not in new_backend_vars
|
|
534
|
-
and types.is_backend_base_variable(name,
|
|
538
|
+
and types.is_backend_base_variable(name, mixin_cls)
|
|
535
539
|
})
|
|
536
540
|
|
|
537
541
|
cls.backend_vars = {
|
|
@@ -579,9 +583,6 @@ class BaseState(EvenMoreBasicBaseState):
|
|
|
579
583
|
cls.computed_vars[name] = newcv
|
|
580
584
|
cls.vars[name] = newcv
|
|
581
585
|
continue
|
|
582
|
-
if types.is_backend_base_variable(name, mixin_cls):
|
|
583
|
-
cls.backend_vars[name] = copy.deepcopy(value)
|
|
584
|
-
continue
|
|
585
586
|
if events.get(name) is not None:
|
|
586
587
|
continue
|
|
587
588
|
if not cls._item_is_event_handler(name, value):
|
|
@@ -1779,7 +1780,7 @@ class BaseState(EvenMoreBasicBaseState):
|
|
|
1779
1780
|
return StateUpdate(
|
|
1780
1781
|
delta=delta,
|
|
1781
1782
|
events=fixed_events,
|
|
1782
|
-
final=final if not handler.is_background else
|
|
1783
|
+
final=final if not handler.is_background else None,
|
|
1783
1784
|
)
|
|
1784
1785
|
except Exception as ex:
|
|
1785
1786
|
state._clean()
|
|
@@ -2471,11 +2472,26 @@ def dynamic(func: Callable[[T], Component]):
|
|
|
2471
2472
|
return wrapper
|
|
2472
2473
|
|
|
2473
2474
|
|
|
2475
|
+
# sessionStorage key holding the ms timestamp of the last reload on error
|
|
2476
|
+
LAST_RELOADED_KEY = "reflex_last_reloaded_on_error"
|
|
2477
|
+
|
|
2478
|
+
|
|
2474
2479
|
class FrontendEventExceptionState(State):
|
|
2475
2480
|
"""Substate for handling frontend exceptions."""
|
|
2476
2481
|
|
|
2482
|
+
# If the frontend error message contains any of these strings, automatically reload the page.
|
|
2483
|
+
auto_reload_on_errors: ClassVar[list[re.Pattern]] = [
|
|
2484
|
+
re.compile( # Chrome/Edge
|
|
2485
|
+
re.escape("TypeError: Cannot read properties of null")
|
|
2486
|
+
),
|
|
2487
|
+
re.compile(re.escape("TypeError: null is not an object")), # Safari
|
|
2488
|
+
re.compile(r"TypeError: can't access property \".*\" of null"), # Firefox
|
|
2489
|
+
]
|
|
2490
|
+
|
|
2477
2491
|
@event
|
|
2478
|
-
def handle_frontend_exception(
|
|
2492
|
+
def handle_frontend_exception(
|
|
2493
|
+
self, info: str, component_stack: str
|
|
2494
|
+
) -> Iterator[EventSpec]:
|
|
2479
2495
|
"""Handle frontend exceptions.
|
|
2480
2496
|
|
|
2481
2497
|
If a frontend exception handler is provided, it will be called.
|
|
@@ -2485,7 +2501,21 @@ class FrontendEventExceptionState(State):
|
|
|
2485
2501
|
info: The exception information.
|
|
2486
2502
|
component_stack: The stack trace of the component where the exception occurred.
|
|
2487
2503
|
|
|
2504
|
+
Yields:
|
|
2505
|
+
Optional auto-reload event for certain errors outside cooldown period.
|
|
2488
2506
|
"""
|
|
2507
|
+
# Handle automatic reload for certain errors.
|
|
2508
|
+
if type(self).auto_reload_on_errors and any(
|
|
2509
|
+
error.search(info) for error in type(self).auto_reload_on_errors
|
|
2510
|
+
):
|
|
2511
|
+
yield call_script(
|
|
2512
|
+
f"const last_reload = parseInt(window.sessionStorage.getItem('{LAST_RELOADED_KEY}')) || 0;"
|
|
2513
|
+
f"if (Date.now() - last_reload > {environment.REFLEX_AUTO_RELOAD_COOLDOWN_TIME_MS.get()})"
|
|
2514
|
+
"{"
|
|
2515
|
+
f"window.sessionStorage.setItem('{LAST_RELOADED_KEY}', Date.now().toString());"
|
|
2516
|
+
"window.location.reload();"
|
|
2517
|
+
"}"
|
|
2518
|
+
)
|
|
2489
2519
|
prerequisites.get_and_validate_app().app.frontend_exception_handler(
|
|
2490
2520
|
Exception(info)
|
|
2491
2521
|
)
|
|
@@ -2684,7 +2714,7 @@ class StateUpdate:
|
|
|
2684
2714
|
events: list[Event] = dataclasses.field(default_factory=list)
|
|
2685
2715
|
|
|
2686
2716
|
# Whether this is the final state update for the event.
|
|
2687
|
-
final: bool = True
|
|
2717
|
+
final: bool | None = True
|
|
2688
2718
|
|
|
2689
2719
|
def json(self) -> str:
|
|
2690
2720
|
"""Convert the state update to a JSON string.
|
|
@@ -195,6 +195,8 @@ def _compile_vite_config(config: Config):
|
|
|
195
195
|
base=base,
|
|
196
196
|
hmr=environment.VITE_HMR.get(),
|
|
197
197
|
force_full_reload=environment.VITE_FORCE_FULL_RELOAD.get(),
|
|
198
|
+
experimental_hmr=environment.VITE_EXPERIMENTAL_HMR.get(),
|
|
199
|
+
sourcemap=environment.VITE_SOURCEMAP.get(),
|
|
198
200
|
)
|
|
199
201
|
|
|
200
202
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: reflex
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.17a1
|
|
4
4
|
Summary: Web apps in pure Python.
|
|
5
5
|
Project-URL: homepage, https://reflex.dev
|
|
6
6
|
Project-URL: repository, https://github.com/reflex-dev/reflex
|
|
@@ -31,12 +31,12 @@ Requires-Dist: pydantic<3.0,>=1.10.21
|
|
|
31
31
|
Requires-Dist: python-multipart<1.0,>=0.0.20
|
|
32
32
|
Requires-Dist: python-socketio<6.0,>=5.12.0
|
|
33
33
|
Requires-Dist: redis<7.0,>=5.2.1
|
|
34
|
-
Requires-Dist: reflex-hosting-cli>=0.1.
|
|
34
|
+
Requires-Dist: reflex-hosting-cli>=0.1.57
|
|
35
35
|
Requires-Dist: rich<15,>=13
|
|
36
36
|
Requires-Dist: sqlmodel<0.1,>=0.0.27
|
|
37
37
|
Requires-Dist: starlette>=0.47.0
|
|
38
38
|
Requires-Dist: typing-extensions>=4.13.0
|
|
39
|
-
Requires-Dist: wrapt<
|
|
39
|
+
Requires-Dist: wrapt<3.0,>=1.17.0
|
|
40
40
|
Provides-Extra: db
|
|
41
41
|
Requires-Dist: alembic<2.0,>=1.15.2; extra == 'db'
|
|
42
42
|
Requires-Dist: pydantic<3.0,>=1.10.21; extra == 'db'
|
|
@@ -86,25 +86,50 @@ See our [architecture page](https://reflex.dev/blog/2024-03-21-reflex-architectu
|
|
|
86
86
|
|
|
87
87
|
## ⚙️ Installation
|
|
88
88
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
```bash
|
|
92
|
-
pip install reflex
|
|
93
|
-
```
|
|
89
|
+
**Important:** We strongly recommend using a virtual environment to ensure the `reflex` command is available in your PATH.
|
|
94
90
|
|
|
95
91
|
## 🥳 Create your first app
|
|
96
92
|
|
|
97
|
-
|
|
93
|
+
### 1. Create the project directory
|
|
98
94
|
|
|
99
|
-
|
|
95
|
+
Replace `my_app_name` with your project name:
|
|
100
96
|
|
|
101
97
|
```bash
|
|
102
98
|
mkdir my_app_name
|
|
103
99
|
cd my_app_name
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### 2. Set up a virtual environment
|
|
103
|
+
|
|
104
|
+
Create and activate virtual environment
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
# On Windows:
|
|
108
|
+
python -m venv .venv
|
|
109
|
+
.venv\Scripts\activate
|
|
110
|
+
|
|
111
|
+
# On macOS/Linux:
|
|
112
|
+
python3 -m venv .venv
|
|
113
|
+
source .venv/bin/activate
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### 3. Install Reflex
|
|
117
|
+
|
|
118
|
+
Reflex is available as a pip package (Requires Python 3.10+):
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
pip install reflex
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### 4. Initialize the project
|
|
125
|
+
|
|
126
|
+
This command initializes a template app in your new directory:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
104
129
|
reflex init
|
|
105
130
|
```
|
|
106
131
|
|
|
107
|
-
|
|
132
|
+
### 5. Run the app
|
|
108
133
|
|
|
109
134
|
You can run this app in development mode:
|
|
110
135
|
|
|
@@ -116,6 +141,10 @@ You should see your app running at http://localhost:3000.
|
|
|
116
141
|
|
|
117
142
|
Now you can modify the source code in `my_app_name/my_app_name.py`. Reflex has fast refreshes so you can see your changes instantly when you save your code.
|
|
118
143
|
|
|
144
|
+
### Troubleshooting
|
|
145
|
+
|
|
146
|
+
If you installed Reflex without a virtual environment and the `reflex` command is not found, you can run commands using: `python3 -m reflex init` and `python3 -m reflex run`
|
|
147
|
+
|
|
119
148
|
## 🫧 Example App
|
|
120
149
|
|
|
121
150
|
Let's go over an example: creating an image generation UI around [DALL·E](https://platform.openai.com/docs/guides/images/image-generation?context=node). For simplicity, we just call the [OpenAI API](https://platform.openai.com/docs/api-reference/authentication), but you could replace this with an ML model run locally.
|
|
@@ -2,18 +2,18 @@ reflex/__init__.py,sha256=7iJASSyU1dxLM-l6q6gFAkw6FniXvawAekgfwN5zKjM,10328
|
|
|
2
2
|
reflex/__init__.pyi,sha256=Yy3exOO_7-O7fCjTKO1VDFbjPyeMM7F12WBnEXWx_tk,10428
|
|
3
3
|
reflex/__main__.py,sha256=6cVrGEyT3j3tEvlEVUatpaYfbB5EF3UVY-6vc_Z7-hw,108
|
|
4
4
|
reflex/admin.py,sha256=Nbc38y-M8iaRBvh1W6DQu_D3kEhO8JFvxrog4q2cB_E,434
|
|
5
|
-
reflex/app.py,sha256=
|
|
5
|
+
reflex/app.py,sha256=s3Grrt3p_Lsk9I1gOhEaxyMj0Zj0IgmfFOzmqlQU3IM,79352
|
|
6
6
|
reflex/assets.py,sha256=l5O_mlrTprC0lF7Rc_McOe3a0OtSLnRdNl_PqCpDCBA,3431
|
|
7
7
|
reflex/base.py,sha256=ROoDZCLWyEdVqfYKnhYKPZINklTl5nHKWo2x0J4MfoE,2327
|
|
8
8
|
reflex/config.py,sha256=LsHAtdH4nkSn3q_Ie-KNdOGdflLXrFICUQov29oFjVk,21229
|
|
9
|
-
reflex/environment.py,sha256
|
|
9
|
+
reflex/environment.py,sha256=-RpVj3yM8lX4c8T7Z3YAAX0PV92DHILEuHkbxWwq0kk,26460
|
|
10
10
|
reflex/event.py,sha256=8vaqS2MBVTQwMVEemtKpjLlMxdlM95IO8u8U9YB_31Q,76443
|
|
11
11
|
reflex/model.py,sha256=d9qCuIEK0mscG2Ng3HTsEgS39rXOfzqXzLZOl3DG_fc,22487
|
|
12
12
|
reflex/page.py,sha256=ssCbMVFuIy60vH-YhJUzN0OxzUwXFCCD3ej56dVjp3g,3525
|
|
13
13
|
reflex/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
14
|
reflex/reflex.py,sha256=urU9hMWIkmVl6BPuw_-NmfaE8Zlls4s_t31ueFl4uBo,25915
|
|
15
15
|
reflex/route.py,sha256=TnS4m6Hm-b3LfGFpm37iAMEd-_JISAouPW5FqUxTAfU,7858
|
|
16
|
-
reflex/state.py,sha256=
|
|
16
|
+
reflex/state.py,sha256=IT4IxfpKfvuqKeGX6aqj1DhfJWnRJB8dgUIYxe9jnPk,96723
|
|
17
17
|
reflex/style.py,sha256=q5Zyc16ULY9xw9CKPPawknrBXIcNNdaSLALXAgdcm2g,13298
|
|
18
18
|
reflex/testing.py,sha256=EzFAVOD9iRfTlQ805NJG6vUynRt1TEkPxId5aCK8eAQ,41974
|
|
19
19
|
reflex/.templates/apps/blank/assets/favicon.ico,sha256=baxxgDAQ2V4-G5Q4S2yK5uUJTUGkv-AOWBQ0xd6myUo,4286
|
|
@@ -30,7 +30,7 @@ reflex/.templates/web/components/reflex/radix_themes_color_mode_provider.js,sha2
|
|
|
30
30
|
reflex/.templates/web/components/shiki/code.js,sha256=4Es1pxsr-lX4hTQ5mglrwwC6O_SI-z-O60k03z8VFzQ,1144
|
|
31
31
|
reflex/.templates/web/styles/__reflex_style_reset.css,sha256=qbC6JIT643YEsvSQ0D7xBmWE5vXy94JGrKNihRuEjnA,8913
|
|
32
32
|
reflex/.templates/web/utils/react-theme.js,sha256=Aa-RND3ooGCXW6Zavzitc-v0ciKlcQDTFlDtE4mPkFI,2713
|
|
33
|
-
reflex/.templates/web/utils/state.js,sha256=
|
|
33
|
+
reflex/.templates/web/utils/state.js,sha256=4vbzLxusJhiFLvmODxX5gB7drCtNtgSXzc5j3MLW_Cs,34899
|
|
34
34
|
reflex/.templates/web/utils/helpers/dataeditor.js,sha256=pG6MgsHuStDR7-qPipzfiK32j9bKDBa-4hZ0JSUo4JM,1623
|
|
35
35
|
reflex/.templates/web/utils/helpers/debounce.js,sha256=xGhtTRtS_xIcaeqnYVvYJNseLgQVk-DW-eFiHJYO9As,528
|
|
36
36
|
reflex/.templates/web/utils/helpers/paste.js,sha256=ef30HsR83jRzzvZnl8yV79yqFP8TC_u8SlN99cCS_OM,1799
|
|
@@ -43,7 +43,7 @@ reflex/app_mixins/middleware.py,sha256=BKhe0jUFO1_TylEC48LUZyaeYyPmAYW-NV4H5Rw22
|
|
|
43
43
|
reflex/app_mixins/mixin.py,sha256=R1YncalqDrbdPZvpKVbm72ZKmQZxYAWfuFq9JknzTqQ,305
|
|
44
44
|
reflex/compiler/__init__.py,sha256=r8jqmDSFf09iV2lHlNhfc9XrTLjNxfDNwPYlxS4cmHE,27
|
|
45
45
|
reflex/compiler/compiler.py,sha256=aaAgnbplyzkTWSfRKkvtT70l72qkbDdwQut-5OPWbL0,29114
|
|
46
|
-
reflex/compiler/templates.py,sha256=
|
|
46
|
+
reflex/compiler/templates.py,sha256=vIpdW0j0Ti1h3VnWmrS6S4OtDRglYHynTT7959sHI5w,20987
|
|
47
47
|
reflex/compiler/utils.py,sha256=TvVSVhlYPpNEH3-PUnih-RMpHa4HmgGCSCnUxASdzFE,19633
|
|
48
48
|
reflex/components/__init__.py,sha256=eWpgWFbSQDj2TpGp6StEbxU7roQgzY7ZM0XIcIc5RE8,588
|
|
49
49
|
reflex/components/__init__.pyi,sha256=7VFHtJGIjvGtD3IiPk848IPWYSCcPRT1EyPGljLhYlU,736
|
|
@@ -97,8 +97,8 @@ reflex/components/core/sticky.py,sha256=UD5x4cHqRkwUY87L5tmKwQYqW-j5fELqiPaozoSQ
|
|
|
97
97
|
reflex/components/core/sticky.pyi,sha256=_iqFMzHRaHcL23TYy0sL4x7Sdc5rEcp5W2ESTOFlPdc,10282
|
|
98
98
|
reflex/components/core/upload.py,sha256=NbcpZ_zNltvBQFBQ-sJNriQg3Bw9Q8VwUL7cKY2kKIU,15165
|
|
99
99
|
reflex/components/core/upload.pyi,sha256=TQVUHt47YsfleD_O-gbLJMzie5slnjft-KVs_7jjRtQ,16820
|
|
100
|
-
reflex/components/core/window_events.py,sha256=
|
|
101
|
-
reflex/components/core/window_events.pyi,sha256=
|
|
100
|
+
reflex/components/core/window_events.py,sha256=21IX9CqdkpLuExnxhYOmwj9FJORLJXLz09uF8Hn7wKc,3954
|
|
101
|
+
reflex/components/core/window_events.pyi,sha256=RWE1wTGGERr8dSmdyfHtyEUJXXEHN_rR5ZM7WzeTD4g,3226
|
|
102
102
|
reflex/components/core/layout/__init__.py,sha256=znldZaj_NGt8qCZDG70GMwjMTskcvCf_2N_EjCAHwdc,30
|
|
103
103
|
reflex/components/datadisplay/__init__.py,sha256=L8pWWKNHWdUD2fbZRoEKjd_8c_hpDdGYO463hwkoIi4,438
|
|
104
104
|
reflex/components/datadisplay/__init__.pyi,sha256=H3LZkWdrw3RTv_csaIT8qoClgAJTonlGZ5ZMeGMV0Bs,551
|
|
@@ -139,7 +139,7 @@ reflex/components/gridjs/__init__.py,sha256=xJwDm1AZ70L5-t9LLqZwGUtDpijbf1KuMYDT
|
|
|
139
139
|
reflex/components/gridjs/datatable.py,sha256=7JKrRw1zkpFB0_wwoaIhrVrldsm7-dyi3PASgqLq8Hc,4224
|
|
140
140
|
reflex/components/gridjs/datatable.pyi,sha256=kFgv82vCgfdWZaUq4bZ73G8X3mkw6ecvSRkZ9G9-28E,5185
|
|
141
141
|
reflex/components/lucide/__init__.py,sha256=EggTK2MuQKQeOBLKW-mF0VaDK9zdWBImu1HO2dvHZbE,73
|
|
142
|
-
reflex/components/lucide/icon.py,sha256=
|
|
142
|
+
reflex/components/lucide/icon.py,sha256=WLEzDeVlS68XWj1y4F0DV6pa8S19g-vwuZxMe6BT2Yo,35396
|
|
143
143
|
reflex/components/lucide/icon.pyi,sha256=oFXjvb5SBULQlbeGDY4K5WWkqemktGIaCsiyrentjKY,37987
|
|
144
144
|
reflex/components/markdown/__init__.py,sha256=Dfl1At5uYoY7H4ufZU_RY2KOGQDLtj75dsZ2BTqqAns,87
|
|
145
145
|
reflex/components/markdown/markdown.py,sha256=Sg3AioKZsNn27KdOzR3o53k1bHzPa2pjpHFVYbxBgCg,16464
|
|
@@ -148,7 +148,7 @@ reflex/components/moment/__init__.py,sha256=jGnZgRBivYJQPIcFgtLaXFteCeIG3gGH5ACX
|
|
|
148
148
|
reflex/components/moment/moment.py,sha256=fhhzrun9USb8J30btpyyDD3JuXF_N7EL5Dou3x7NQYw,4080
|
|
149
149
|
reflex/components/moment/moment.pyi,sha256=3CQSmhMF4MetFCrjuds9wpz7FnFeXdXzR39A8n3nhy0,2872
|
|
150
150
|
reflex/components/plotly/__init__.py,sha256=6B_woBJhkrVA9O_AbOTbsA_SxWsqjicYHmLA9FLjGfU,650
|
|
151
|
-
reflex/components/plotly/plotly.py,sha256=
|
|
151
|
+
reflex/components/plotly/plotly.py,sha256=xy9MNprtmO67RIrFkc2D9QfbjzP8eX4Tkk4UfPz5JBM,15172
|
|
152
152
|
reflex/components/plotly/plotly.pyi,sha256=5Nhph2PL9eIb-Xd6CUZHQf79P-tOazy1alwRQl7CKWw,46821
|
|
153
153
|
reflex/components/radix/__init__.py,sha256=fRsLvIO3MrTtPOXtmnxYDB9phvzlcbyB_utgpafYMho,474
|
|
154
154
|
reflex/components/radix/__init__.pyi,sha256=ke_dGrpFMNHd3MgQ9qiStSQDlGcJ39KVSrpIxayBU3c,3927
|
|
@@ -301,7 +301,7 @@ reflex/components/recharts/general.py,sha256=c3SRcKzNvSeKcbVInl-zNrDxNe0Lgejqcbl
|
|
|
301
301
|
reflex/components/recharts/general.pyi,sha256=e77vGL8lo-t1jI79h0O12qSK5e9wbjerPslCxQQgSBw,23462
|
|
302
302
|
reflex/components/recharts/polar.py,sha256=zocHpwWQ0lbg4BTnEBwQ6J9SSJsOYRwZGf9UPzxoNKs,15682
|
|
303
303
|
reflex/components/recharts/polar.pyi,sha256=8ShEcGK9KJyu0FN6KPys1kgAYrzOZ6wtiRuytHJ--38,26937
|
|
304
|
-
reflex/components/recharts/recharts.py,sha256=
|
|
304
|
+
reflex/components/recharts/recharts.py,sha256=8GJIjIcJMHQCFV5gkHOhqa1L9DzSFO_bBIgzIichyx0,3221
|
|
305
305
|
reflex/components/recharts/recharts.pyi,sha256=9j8cVSMqyBkkOBBrx9pzDpP1clnbM9kD0TTViTUGDYc,7084
|
|
306
306
|
reflex/components/sonner/__init__.py,sha256=L_mdRIy7-ccRGSz5VK6J8O-c-e-D1p9xWw29_ErrvGg,68
|
|
307
307
|
reflex/components/sonner/toast.py,sha256=VBtoRnxBhKD029njAjhbLeYtiUSL3aNPOSmA9Lmsqvg,12512
|
|
@@ -319,7 +319,7 @@ reflex/constants/compiler.py,sha256=1FXPYQNotaSrTwWcOspA1gCVmEdoiWkNMbbrz_qU0YU,
|
|
|
319
319
|
reflex/constants/config.py,sha256=8OIjiBdZZJrRVHsNBheMwopE9AwBFFzau0SXqXKcrPg,1715
|
|
320
320
|
reflex/constants/custom_components.py,sha256=joJt4CEt1yKy7wsBH6vYo7_QRW0O_fWXrrTf0VY2q14,1317
|
|
321
321
|
reflex/constants/event.py,sha256=tgoynWQi2L0_Kqc3XhXo7XXL76A-OKhJGHRrNjm7gFw,2885
|
|
322
|
-
reflex/constants/installer.py,sha256=
|
|
322
|
+
reflex/constants/installer.py,sha256=iZvdnTIl2zh0_fPr1G-RsOiHbA4vnnse8ykPJVFBUbE,4191
|
|
323
323
|
reflex/constants/route.py,sha256=UBjqaAOxiUxlDZCSY4O2JJChKvA4MZrhUU0E5rNvKbM,2682
|
|
324
324
|
reflex/constants/state.py,sha256=VrEeYxXfE9ss8RmOHIXD4T6EGsV9PDqbtMCQMmZxW3I,383
|
|
325
325
|
reflex/constants/utils.py,sha256=e1ChEvbHfmE_V2UJvCSUhD_qTVAIhEGPpRJSqdSd6PA,780
|
|
@@ -331,13 +331,13 @@ reflex/experimental/hooks.py,sha256=CHYGrAE5t8riltrJmDFgJ4D2Vhmhw-y3B3MSGNlOQow,
|
|
|
331
331
|
reflex/istate/__init__.py,sha256=afq_pCS5B_REC-Kl3Rbaa538uWi59xNz4INeuENcWnk,2039
|
|
332
332
|
reflex/istate/data.py,sha256=ZT7uW_Ish3A0V4x2Lu8PD__GkiOd3nHY0lAeGcghp68,7872
|
|
333
333
|
reflex/istate/dynamic.py,sha256=xOQ9upZVPf6ngqcLQZ9HdAAYmoWwJ8kRFPH34Q5HTiM,91
|
|
334
|
-
reflex/istate/proxy.py,sha256=
|
|
334
|
+
reflex/istate/proxy.py,sha256=nqL-MPWp2Ldo8GsjCdzfeWK1wQ9LK-fUoB8XyIZfJwQ,26458
|
|
335
335
|
reflex/istate/storage.py,sha256=gCPoiZxuG-Rw0y-Pz3OC7rv4o08dQ_jK1fE2u8Jhxqg,4339
|
|
336
336
|
reflex/istate/wrappers.py,sha256=p8uuioXRbR5hperwbOJHUcWdu7hukLikQdoR7qrnKsI,909
|
|
337
|
-
reflex/istate/manager/__init__.py,sha256=
|
|
338
|
-
reflex/istate/manager/disk.py,sha256=
|
|
339
|
-
reflex/istate/manager/memory.py,sha256=
|
|
340
|
-
reflex/istate/manager/redis.py,sha256=
|
|
337
|
+
reflex/istate/manager/__init__.py,sha256=hTg5uqxVbz-xayUZNin-wP51PfAkz1CHDez-jncXTTg,4406
|
|
338
|
+
reflex/istate/manager/disk.py,sha256=RVWDnPt4d2a0El8RBnWDVCksLKv7rPuWbkUPR6Y7Szc,13736
|
|
339
|
+
reflex/istate/manager/memory.py,sha256=tnK2JzJNcEbiXAdGIT5tNA0U1-mQZoeXKF8XNJCfnts,2760
|
|
340
|
+
reflex/istate/manager/redis.py,sha256=LGR8ilvrCZmxKznhIKBHP4-Oe_JT5htcoJldVH53MlU,19020
|
|
341
341
|
reflex/middleware/__init__.py,sha256=x7xTeDuc73Hjj43k1J63naC9x8vzFxl4sq7cCFBX7sk,111
|
|
342
342
|
reflex/middleware/hydrate_middleware.py,sha256=1ch7bx2ZhojOR15b-LHD2JztrWCnpPJjTe8MWHJe-5Y,1510
|
|
343
343
|
reflex/middleware/middleware.py,sha256=p5VVoIgQ_NwOg_GOY6g0S4fmrV76_VE1zt-HiwbMw-s,1158
|
|
@@ -347,7 +347,7 @@ reflex/plugins/base.py,sha256=5BgzCM7boj9kJ6FGzVzVlgQk-crJuVmOLCl1PXvv4-E,3372
|
|
|
347
347
|
reflex/plugins/shared_tailwind.py,sha256=XPnswswPW3UIeEu5ghecdEeYtpikG5ksD92sM-VwKYM,7221
|
|
348
348
|
reflex/plugins/sitemap.py,sha256=X_CtH5B1w3CZno-gdPj1rp63WjOuNjFnX4B3fx_-VFQ,6135
|
|
349
349
|
reflex/plugins/tailwind_v3.py,sha256=jCEZ5UYdr706Mw48L-WSHOUB6O55o1C3uG6AMwXqZoI,4810
|
|
350
|
-
reflex/plugins/tailwind_v4.py,sha256=
|
|
350
|
+
reflex/plugins/tailwind_v4.py,sha256=Cjp3vJnrZDYiflwm4imj4SEI0pYBv36mLvmpbI6olao,5230
|
|
351
351
|
reflex/utils/__init__.py,sha256=y-AHKiRQAhk2oAkvn7W8cRVTZVK625ff8tTwvZtO7S4,24
|
|
352
352
|
reflex/utils/build.py,sha256=j-OY90O7gMP_bclVt_6J3Q2GFgOHQH_uFpTfdaWmuqU,9746
|
|
353
353
|
reflex/utils/codespaces.py,sha256=SIATnmlGCABPvjvRIENUCwP-fcjqKhdoOYiFY_Eua6M,4339
|
|
@@ -358,7 +358,7 @@ reflex/utils/exceptions.py,sha256=Wwu7Ji2xgq521bJKtU2NgjwhmFfnG8erirEVN2h8S-g,88
|
|
|
358
358
|
reflex/utils/exec.py,sha256=xMwRnCd9SyTbvwBPS5i3C6ZcorLSFViqB_fOoCqsDEc,22833
|
|
359
359
|
reflex/utils/export.py,sha256=dR8Q7OymxcS8PCvx5zV2kOZmjKgOmuAfKfL8XifHJd4,2907
|
|
360
360
|
reflex/utils/format.py,sha256=BAq-BO0ON5ionaDaO0yJIZ3Y1YT7hhpYlGHZ5-x9w4o,20981
|
|
361
|
-
reflex/utils/frontend_skeleton.py,sha256=
|
|
361
|
+
reflex/utils/frontend_skeleton.py,sha256=Tr3GUsvJoA6PceVt1jHhowtObgrnRvaeJc4ABTrfv18,8887
|
|
362
362
|
reflex/utils/imports.py,sha256=SlQfMTbJasXHxrpcHdWKPWiIZ1Kn2-tulMF32_YA2ek,4262
|
|
363
363
|
reflex/utils/js_runtimes.py,sha256=Xia4pIyWGwUmNnTgELm04oxVQobwdQvmK87AHTr3B1o,13542
|
|
364
364
|
reflex/utils/lazy_loader.py,sha256=BiY9OvmAJDCz10qpuyTYv9duXgMFQa6RXKQmTO9hqKU,4453
|
|
@@ -387,8 +387,8 @@ reflex/vars/number.py,sha256=Cejba-47shtQt-j0uD_HRfTGOm1IF1uZ1WwpWSrcLSE,28865
|
|
|
387
387
|
reflex/vars/object.py,sha256=j3b-j66Qa0XDJofMkcJtb8e-TdNx2_hjyEPnrGJEaFY,17833
|
|
388
388
|
reflex/vars/sequence.py,sha256=OyCfMsv50Zr6W26DMISWjLX6FzK3rbxNcgKepgYr7Pk,52326
|
|
389
389
|
scripts/hatch_build.py,sha256=-4pxcLSFmirmujGpQX9UUxjhIC03tQ_fIQwVbHu9kc0,1861
|
|
390
|
-
reflex-0.8.
|
|
391
|
-
reflex-0.8.
|
|
392
|
-
reflex-0.8.
|
|
393
|
-
reflex-0.8.
|
|
394
|
-
reflex-0.8.
|
|
390
|
+
reflex-0.8.17a1.dist-info/METADATA,sha256=iH8TN8Ktq1RI_4JtlJBly7yBfM4JMREcj_aFY9DrE3Q,13102
|
|
391
|
+
reflex-0.8.17a1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
392
|
+
reflex-0.8.17a1.dist-info/entry_points.txt,sha256=Rxt4dXc7MLBNt5CSHTehVPuSe9Xqow4HLX55nD9tQQ0,45
|
|
393
|
+
reflex-0.8.17a1.dist-info/licenses/LICENSE,sha256=dw3zLrp9f5ObD7kqS32vWfhcImfO52PMmRqvtxq_YEE,11358
|
|
394
|
+
reflex-0.8.17a1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|