reflex 0.6.7a2__py3-none-any.whl → 0.6.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of reflex might be problematic. Click here for more details.
- reflex/.templates/jinja/web/pages/_app.js.jinja2 +2 -4
- reflex/.templates/jinja/web/pages/custom_component.js.jinja2 +3 -4
- reflex/.templates/jinja/web/pages/index.js.jinja2 +2 -3
- reflex/.templates/jinja/web/pages/macros.js.jinja2 +38 -0
- reflex/.templates/jinja/web/pages/stateful_component.js.jinja2 +4 -16
- reflex/.templates/jinja/web/utils/context.js.jinja2 +1 -1
- reflex/.templates/web/utils/state.js +9 -4
- reflex/app.py +12 -10
- reflex/compiler/compiler.py +2 -2
- reflex/compiler/templates.py +41 -0
- reflex/compiler/utils.py +1 -1
- reflex/components/base/bare.py +7 -3
- reflex/components/component.py +78 -116
- reflex/components/core/banner.py +1 -1
- reflex/components/core/breakpoints.py +1 -1
- reflex/components/datadisplay/code.py +14 -10
- reflex/components/datadisplay/dataeditor.py +1 -1
- reflex/components/datadisplay/dataeditor.pyi +1 -1
- reflex/components/el/elements/forms.py +7 -5
- reflex/components/el/elements/metadata.py +1 -1
- reflex/components/lucide/icon.py +142 -19
- reflex/components/lucide/icon.pyi +141 -18
- reflex/components/markdown/markdown.py +3 -2
- reflex/components/plotly/plotly.py +3 -3
- reflex/components/plotly/plotly.pyi +3 -3
- reflex/components/radix/primitives/slider.py +1 -1
- reflex/components/radix/themes/layout/center.pyi +1 -1
- reflex/components/radix/themes/layout/flex.py +1 -1
- reflex/components/radix/themes/layout/flex.pyi +1 -1
- reflex/components/radix/themes/layout/grid.py +1 -1
- reflex/components/radix/themes/layout/grid.pyi +1 -1
- reflex/components/radix/themes/layout/spacer.pyi +1 -1
- reflex/components/radix/themes/layout/stack.pyi +3 -3
- reflex/components/radix/themes/typography/link.py +1 -1
- reflex/components/recharts/cartesian.py +2 -2
- reflex/components/recharts/cartesian.pyi +6 -6
- reflex/components/recharts/charts.py +2 -2
- reflex/components/recharts/polar.py +2 -2
- reflex/components/recharts/polar.pyi +2 -2
- reflex/components/sonner/toast.py +1 -1
- reflex/constants/base.py +1 -1
- reflex/constants/compiler.py +1 -0
- reflex/event.py +96 -1
- reflex/experimental/client_state.py +42 -20
- reflex/istate/data.py +3 -3
- reflex/model.py +4 -5
- reflex/page.py +1 -1
- reflex/reflex.py +8 -1
- reflex/state.py +116 -9
- reflex/testing.py +3 -3
- reflex/utils/exceptions.py +4 -0
- reflex/utils/prerequisites.py +37 -20
- reflex/utils/processes.py +2 -2
- reflex/utils/pyi_generator.py +2 -2
- reflex/utils/telemetry.py +6 -4
- reflex/vars/base.py +15 -4
- reflex/vars/sequence.py +37 -0
- {reflex-0.6.7a2.dist-info → reflex-0.6.8.dist-info}/METADATA +2 -2
- {reflex-0.6.7a2.dist-info → reflex-0.6.8.dist-info}/RECORD +62 -61
- {reflex-0.6.7a2.dist-info → reflex-0.6.8.dist-info}/LICENSE +0 -0
- {reflex-0.6.7a2.dist-info → reflex-0.6.8.dist-info}/WHEEL +0 -0
- {reflex-0.6.7a2.dist-info → reflex-0.6.8.dist-info}/entry_points.txt +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
{% extends "web/pages/base_page.js.jinja2" %}
|
|
2
|
+
{% from "web/pages/macros.js.jinja2" import renderHooks %}
|
|
2
3
|
|
|
3
4
|
{% block early_imports %}
|
|
4
5
|
import '$/styles/styles.css'
|
|
@@ -18,10 +19,7 @@ import * as {{library_alias}} from "{{library_path}}";
|
|
|
18
19
|
|
|
19
20
|
{% block export %}
|
|
20
21
|
function AppWrap({children}) {
|
|
21
|
-
|
|
22
|
-
{% for hook in hooks %}
|
|
23
|
-
{{ hook }}
|
|
24
|
-
{% endfor %}
|
|
22
|
+
{{ renderHooks(hooks) }}
|
|
25
23
|
|
|
26
24
|
return (
|
|
27
25
|
{{utils.render(render, indent_width=0)}}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{% extends "web/pages/base_page.js.jinja2" %}
|
|
2
|
-
|
|
2
|
+
{% from "web/pages/macros.js.jinja2" import renderHooks %}
|
|
3
3
|
{% block export %}
|
|
4
4
|
{% for component in components %}
|
|
5
5
|
|
|
@@ -8,9 +8,8 @@
|
|
|
8
8
|
{% endfor %}
|
|
9
9
|
|
|
10
10
|
export const {{component.name}} = memo(({ {{-component.props|join(", ")-}} }) => {
|
|
11
|
-
{
|
|
12
|
-
|
|
13
|
-
{% endfor %}
|
|
11
|
+
{{ renderHooks(component.hooks) }}
|
|
12
|
+
|
|
14
13
|
return(
|
|
15
14
|
{{utils.render(component.render)}}
|
|
16
15
|
)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
{% extends "web/pages/base_page.js.jinja2" %}
|
|
2
|
+
{% from "web/pages/macros.js.jinja2" import renderHooks %}
|
|
2
3
|
|
|
3
4
|
{% block declaration %}
|
|
4
5
|
{% for custom_code in custom_codes %}
|
|
@@ -8,9 +9,7 @@
|
|
|
8
9
|
|
|
9
10
|
{% block export %}
|
|
10
11
|
export default function Component() {
|
|
11
|
-
|
|
12
|
-
{{ hook }}
|
|
13
|
-
{% endfor %}
|
|
12
|
+
{{ renderHooks(hooks)}}
|
|
14
13
|
|
|
15
14
|
return (
|
|
16
15
|
{{utils.render(render, indent_width=0)}}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{% macro renderHooks(hooks) %}
|
|
2
|
+
{% set sorted_hooks = sort_hooks(hooks) %}
|
|
3
|
+
|
|
4
|
+
{# Render the grouped hooks #}
|
|
5
|
+
{% for hook, _ in sorted_hooks[const.hook_position.INTERNAL] %}
|
|
6
|
+
{{ hook }}
|
|
7
|
+
{% endfor %}
|
|
8
|
+
|
|
9
|
+
{% for hook, _ in sorted_hooks[const.hook_position.PRE_TRIGGER] %}
|
|
10
|
+
{{ hook }}
|
|
11
|
+
{% endfor %}
|
|
12
|
+
|
|
13
|
+
{% for hook, _ in sorted_hooks[const.hook_position.POST_TRIGGER] %}
|
|
14
|
+
{{ hook }}
|
|
15
|
+
{% endfor %}
|
|
16
|
+
{% endmacro %}
|
|
17
|
+
|
|
18
|
+
{% macro renderHooksWithMemo(hooks, memo)%}
|
|
19
|
+
{% set sorted_hooks = sort_hooks(hooks) %}
|
|
20
|
+
|
|
21
|
+
{# Render the grouped hooks #}
|
|
22
|
+
{% for hook, _ in sorted_hooks[const.hook_position.INTERNAL] %}
|
|
23
|
+
{{ hook }}
|
|
24
|
+
{% endfor %}
|
|
25
|
+
|
|
26
|
+
{% for hook, _ in sorted_hooks[const.hook_position.PRE_TRIGGER] %}
|
|
27
|
+
{{ hook }}
|
|
28
|
+
{% endfor %}
|
|
29
|
+
|
|
30
|
+
{% for hook in memo %}
|
|
31
|
+
{{ hook }}
|
|
32
|
+
{% endfor %}
|
|
33
|
+
|
|
34
|
+
{% for hook, _ in sorted_hooks[const.hook_position.POST_TRIGGER] %}
|
|
35
|
+
{{ hook }}
|
|
36
|
+
{% endfor %}
|
|
37
|
+
|
|
38
|
+
{% endmacro %}
|
|
@@ -1,22 +1,10 @@
|
|
|
1
1
|
{% import 'web/pages/utils.js.jinja2' as utils %}
|
|
2
|
+
{% from 'web/pages/macros.js.jinja2' import renderHooksWithMemo %}
|
|
3
|
+
{% set all_hooks = component._get_all_hooks() %}
|
|
2
4
|
|
|
3
5
|
export function {{tag_name}} () {
|
|
4
|
-
{
|
|
5
|
-
|
|
6
|
-
{% endfor %}
|
|
7
|
-
|
|
8
|
-
{% for hook, data in component._get_all_hooks().items() if not data.position or data.position == const.hook_position.PRE_TRIGGER %}
|
|
9
|
-
{{ hook }}
|
|
10
|
-
{% endfor %}
|
|
11
|
-
|
|
12
|
-
{% for hook in memo_trigger_hooks %}
|
|
13
|
-
{{ hook }}
|
|
14
|
-
{% endfor %}
|
|
15
|
-
|
|
16
|
-
{% for hook, data in component._get_all_hooks().items() if data.position and data.position == const.hook_position.POST_TRIGGER %}
|
|
17
|
-
{{ hook }}
|
|
18
|
-
{% endfor %}
|
|
19
|
-
|
|
6
|
+
{{ renderHooksWithMemo(all_hooks, memo_trigger_hooks) }}
|
|
7
|
+
|
|
20
8
|
return (
|
|
21
9
|
{{utils.render(component.render(), indent_width=0)}}
|
|
22
10
|
)
|
|
@@ -28,7 +28,7 @@ export const state_name = "{{state_name}}"
|
|
|
28
28
|
|
|
29
29
|
export const exception_state_name = "{{const.frontend_exception_state}}"
|
|
30
30
|
|
|
31
|
-
//
|
|
31
|
+
// These events are triggered on initial load and each page navigation.
|
|
32
32
|
export const onLoadInternalEvent = () => {
|
|
33
33
|
const internal_events = [];
|
|
34
34
|
|
|
@@ -208,11 +208,16 @@ export const applyEvent = async (event, socket) => {
|
|
|
208
208
|
if (event.name == "_download") {
|
|
209
209
|
const a = document.createElement("a");
|
|
210
210
|
a.hidden = true;
|
|
211
|
+
a.href = event.payload.url;
|
|
211
212
|
// Special case when linking to uploaded files
|
|
212
|
-
a.href
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
213
|
+
if (a.href.includes("getBackendURL(env.UPLOAD)")) {
|
|
214
|
+
a.href = eval?.(
|
|
215
|
+
event.payload.url.replace(
|
|
216
|
+
"getBackendURL(env.UPLOAD)",
|
|
217
|
+
`"${getBackendURL(env.UPLOAD)}"`
|
|
218
|
+
)
|
|
219
|
+
);
|
|
220
|
+
}
|
|
216
221
|
a.download = event.payload.filename;
|
|
217
222
|
a.click();
|
|
218
223
|
a.remove();
|
reflex/app.py
CHANGED
|
@@ -1356,20 +1356,22 @@ async def health() -> JSONResponse:
|
|
|
1356
1356
|
health_status = {"status": True}
|
|
1357
1357
|
status_code = 200
|
|
1358
1358
|
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
)
|
|
1359
|
+
tasks = []
|
|
1360
|
+
|
|
1361
|
+
if prerequisites.check_db_used():
|
|
1362
|
+
tasks.append(get_db_status())
|
|
1363
|
+
if prerequisites.check_redis_used():
|
|
1364
|
+
tasks.append(prerequisites.get_redis_status())
|
|
1365
|
+
|
|
1366
|
+
results = await asyncio.gather(*tasks)
|
|
1362
1367
|
|
|
1363
|
-
|
|
1368
|
+
for result in results:
|
|
1369
|
+
health_status |= result
|
|
1364
1370
|
|
|
1365
|
-
if
|
|
1371
|
+
if "redis" in health_status and health_status["redis"] is None:
|
|
1366
1372
|
health_status["redis"] = False
|
|
1367
|
-
else:
|
|
1368
|
-
health_status["redis"] = redis_status
|
|
1369
1373
|
|
|
1370
|
-
if not health_status
|
|
1371
|
-
not health_status["redis"] and redis_status is not None
|
|
1372
|
-
):
|
|
1374
|
+
if not all(health_status.values()):
|
|
1373
1375
|
health_status["status"] = False
|
|
1374
1376
|
status_code = 503
|
|
1375
1377
|
|
reflex/compiler/compiler.py
CHANGED
|
@@ -75,7 +75,7 @@ def _compile_app(app_root: Component) -> str:
|
|
|
75
75
|
return templates.APP_ROOT.render(
|
|
76
76
|
imports=utils.compile_imports(app_root._get_all_imports()),
|
|
77
77
|
custom_codes=app_root._get_all_custom_code(),
|
|
78
|
-
hooks=
|
|
78
|
+
hooks=app_root._get_all_hooks(),
|
|
79
79
|
window_libraries=window_libraries,
|
|
80
80
|
render=app_root.render(),
|
|
81
81
|
)
|
|
@@ -149,7 +149,7 @@ def _compile_page(
|
|
|
149
149
|
imports=imports,
|
|
150
150
|
dynamic_imports=component._get_all_dynamic_imports(),
|
|
151
151
|
custom_codes=component._get_all_custom_code(),
|
|
152
|
-
hooks=
|
|
152
|
+
hooks=component._get_all_hooks(),
|
|
153
153
|
render=component.render(),
|
|
154
154
|
**kwargs,
|
|
155
155
|
)
|
reflex/compiler/templates.py
CHANGED
|
@@ -1,9 +1,46 @@
|
|
|
1
1
|
"""Templates to use in the reflex compiler."""
|
|
2
2
|
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
3
5
|
from jinja2 import Environment, FileSystemLoader, Template
|
|
4
6
|
|
|
5
7
|
from reflex import constants
|
|
8
|
+
from reflex.constants import Hooks
|
|
6
9
|
from reflex.utils.format import format_state_name, json_dumps
|
|
10
|
+
from reflex.vars.base import VarData
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _sort_hooks(hooks: dict[str, VarData | None]):
|
|
14
|
+
"""Sort the hooks by their position.
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
hooks: The hooks to sort.
|
|
18
|
+
|
|
19
|
+
Returns:
|
|
20
|
+
The sorted hooks.
|
|
21
|
+
"""
|
|
22
|
+
sorted_hooks = {
|
|
23
|
+
Hooks.HookPosition.INTERNAL: [],
|
|
24
|
+
Hooks.HookPosition.PRE_TRIGGER: [],
|
|
25
|
+
Hooks.HookPosition.POST_TRIGGER: [],
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
for hook, data in hooks.items():
|
|
29
|
+
if data and data.position and data.position == Hooks.HookPosition.INTERNAL:
|
|
30
|
+
sorted_hooks[Hooks.HookPosition.INTERNAL].append((hook, data))
|
|
31
|
+
elif not data or (
|
|
32
|
+
not data.position
|
|
33
|
+
or data.position == constants.Hooks.HookPosition.PRE_TRIGGER
|
|
34
|
+
):
|
|
35
|
+
sorted_hooks[Hooks.HookPosition.PRE_TRIGGER].append((hook, data))
|
|
36
|
+
elif (
|
|
37
|
+
data
|
|
38
|
+
and data.position
|
|
39
|
+
and data.position == constants.Hooks.HookPosition.POST_TRIGGER
|
|
40
|
+
):
|
|
41
|
+
sorted_hooks[Hooks.HookPosition.POST_TRIGGER].append((hook, data))
|
|
42
|
+
|
|
43
|
+
return sorted_hooks
|
|
7
44
|
|
|
8
45
|
|
|
9
46
|
class ReflexJinjaEnvironment(Environment):
|
|
@@ -47,6 +84,7 @@ class ReflexJinjaEnvironment(Environment):
|
|
|
47
84
|
"frontend_exception_state": constants.CompileVars.FRONTEND_EXCEPTION_STATE_FULL,
|
|
48
85
|
"hook_position": constants.Hooks.HookPosition,
|
|
49
86
|
}
|
|
87
|
+
self.globals["sort_hooks"] = _sort_hooks
|
|
50
88
|
|
|
51
89
|
|
|
52
90
|
def get_template(name: str) -> Template:
|
|
@@ -103,6 +141,9 @@ STYLE = get_template("web/styles/styles.css.jinja2")
|
|
|
103
141
|
# Code that generate the package json file
|
|
104
142
|
PACKAGE_JSON = get_template("web/package.json.jinja2")
|
|
105
143
|
|
|
144
|
+
# Template containing some macros used in the web pages.
|
|
145
|
+
MACROS = get_template("web/pages/macros.js.jinja2")
|
|
146
|
+
|
|
106
147
|
# Code that generate the pyproject.toml file for custom components.
|
|
107
148
|
CUSTOM_COMPONENTS_PYPROJECT_TOML = get_template(
|
|
108
149
|
"custom_components/pyproject.toml.jinja2"
|
reflex/compiler/utils.py
CHANGED
|
@@ -290,7 +290,7 @@ def compile_custom_component(
|
|
|
290
290
|
"name": component.tag,
|
|
291
291
|
"props": props,
|
|
292
292
|
"render": render.render(),
|
|
293
|
-
"hooks":
|
|
293
|
+
"hooks": render._get_all_hooks(),
|
|
294
294
|
"custom_code": render._get_all_custom_code(),
|
|
295
295
|
},
|
|
296
296
|
imports,
|
reflex/components/base/bare.py
CHANGED
|
@@ -9,6 +9,7 @@ from reflex.components.tags import Tag
|
|
|
9
9
|
from reflex.components.tags.tagless import Tagless
|
|
10
10
|
from reflex.utils.imports import ParsedImportDict
|
|
11
11
|
from reflex.vars import BooleanVar, ObjectVar, Var
|
|
12
|
+
from reflex.vars.base import VarData
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
class Bare(Component):
|
|
@@ -32,7 +33,7 @@ class Bare(Component):
|
|
|
32
33
|
contents = str(contents) if contents is not None else ""
|
|
33
34
|
return cls(contents=contents) # type: ignore
|
|
34
35
|
|
|
35
|
-
def _get_all_hooks_internal(self) -> dict[str, None]:
|
|
36
|
+
def _get_all_hooks_internal(self) -> dict[str, VarData | None]:
|
|
36
37
|
"""Include the hooks for the component.
|
|
37
38
|
|
|
38
39
|
Returns:
|
|
@@ -43,7 +44,7 @@ class Bare(Component):
|
|
|
43
44
|
hooks |= self.contents._var_value._get_all_hooks_internal()
|
|
44
45
|
return hooks
|
|
45
46
|
|
|
46
|
-
def _get_all_hooks(self) -> dict[str, None]:
|
|
47
|
+
def _get_all_hooks(self) -> dict[str, VarData | None]:
|
|
47
48
|
"""Include the hooks for the component.
|
|
48
49
|
|
|
49
50
|
Returns:
|
|
@@ -107,11 +108,14 @@ class Bare(Component):
|
|
|
107
108
|
return Tagless(contents=f"{{{self.contents!s}}}")
|
|
108
109
|
return Tagless(contents=str(self.contents))
|
|
109
110
|
|
|
110
|
-
def _get_vars(
|
|
111
|
+
def _get_vars(
|
|
112
|
+
self, include_children: bool = False, ignore_ids: set[int] | None = None
|
|
113
|
+
) -> Iterator[Var]:
|
|
111
114
|
"""Walk all Vars used in this component.
|
|
112
115
|
|
|
113
116
|
Args:
|
|
114
117
|
include_children: Whether to include Vars from children.
|
|
118
|
+
ignore_ids: The ids to ignore.
|
|
115
119
|
|
|
116
120
|
Yields:
|
|
117
121
|
The contents if it is a Var, otherwise nothing.
|