reflex 0.8.15a1__py3-none-any.whl → 0.8.16__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 +68 -8
- reflex/app.py +45 -51
- reflex/app_mixins/lifespan.py +12 -5
- reflex/base.py +1 -0
- reflex/compiler/compiler.py +4 -6
- reflex/compiler/templates.py +25 -31
- reflex/compiler/utils.py +6 -5
- reflex/components/base/body.pyi +1 -195
- reflex/components/base/link.pyi +1 -407
- reflex/components/base/meta.pyi +1 -405
- reflex/components/base/script.pyi +1 -237
- reflex/components/component.py +41 -46
- reflex/components/core/auto_scroll.pyi +1 -195
- reflex/components/core/banner.pyi +1 -391
- reflex/components/core/breakpoints.py +14 -18
- reflex/components/core/html.pyi +1 -197
- reflex/components/core/match.py +2 -2
- reflex/components/core/sticky.py +11 -15
- reflex/components/core/sticky.pyi +0 -788
- reflex/components/core/upload.py +1 -3
- reflex/components/core/window_events.pyi +6 -5
- reflex/components/datadisplay/code.pyi +1 -0
- reflex/components/datadisplay/dataeditor.py +4 -6
- reflex/components/datadisplay/shiki_code_block.py +106 -110
- reflex/components/dynamic.py +4 -6
- reflex/components/el/elements/__init__.py +5 -7
- reflex/components/el/elements/__init__.pyi +5 -7
- reflex/components/el/elements/base.py +1 -1
- reflex/components/el/elements/base.pyi +1 -195
- reflex/components/el/elements/forms.py +7 -9
- reflex/components/el/elements/forms.pyi +12 -3112
- reflex/components/el/elements/inline.pyi +0 -5481
- reflex/components/el/elements/media.pyi +0 -10280
- reflex/components/el/elements/metadata.pyi +1 -835
- reflex/components/el/elements/other.pyi +1 -1365
- reflex/components/el/elements/scripts.pyi +1 -625
- reflex/components/el/elements/sectioning.pyi +1 -2911
- reflex/components/el/elements/tables.pyi +1 -1973
- reflex/components/el/elements/typography.pyi +1 -3125
- reflex/components/lucide/icon.py +4 -4
- reflex/components/lucide/icon.pyi +0 -4
- reflex/components/markdown/markdown.py +15 -19
- reflex/components/markdown/markdown.pyi +1 -0
- reflex/components/moment/moment.pyi +0 -49
- reflex/components/props.py +3 -3
- reflex/components/radix/primitives/accordion.py +4 -6
- reflex/components/radix/primitives/accordion.pyi +0 -14
- reflex/components/radix/primitives/base.pyi +0 -5
- reflex/components/radix/primitives/dialog.py +2 -0
- reflex/components/radix/primitives/dialog.pyi +1 -233
- reflex/components/radix/primitives/drawer.pyi +0 -18
- reflex/components/radix/primitives/form.pyi +30 -632
- reflex/components/radix/primitives/progress.pyi +0 -10
- reflex/components/radix/primitives/slider.pyi +0 -10
- reflex/components/radix/themes/color_mode.pyi +1 -284
- reflex/components/radix/themes/components/alert_dialog.pyi +0 -207
- reflex/components/radix/themes/components/aspect_ratio.pyi +0 -2
- reflex/components/radix/themes/components/avatar.pyi +0 -80
- reflex/components/radix/themes/components/badge.pyi +1 -270
- reflex/components/radix/themes/components/button.pyi +1 -274
- reflex/components/radix/themes/components/callout.pyi +0 -1197
- reflex/components/radix/themes/components/card.pyi +1 -209
- reflex/components/radix/themes/components/checkbox.pyi +0 -261
- reflex/components/radix/themes/components/checkbox_cards.pyi +1 -96
- reflex/components/radix/themes/components/checkbox_group.pyi +1 -80
- reflex/components/radix/themes/components/context_menu.pyi +13 -321
- reflex/components/radix/themes/components/data_list.pyi +1 -107
- reflex/components/radix/themes/components/dialog.pyi +1 -210
- reflex/components/radix/themes/components/dropdown_menu.pyi +0 -209
- reflex/components/radix/themes/components/hover_card.pyi +1 -246
- reflex/components/radix/themes/components/icon_button.pyi +1 -195
- reflex/components/radix/themes/components/inset.pyi +0 -252
- reflex/components/radix/themes/components/popover.pyi +1 -234
- reflex/components/radix/themes/components/progress.pyi +1 -84
- reflex/components/radix/themes/components/radio.pyi +1 -72
- reflex/components/radix/themes/components/radio_cards.pyi +1 -123
- reflex/components/radix/themes/components/scroll_area.pyi +1 -11
- reflex/components/radix/themes/components/select.pyi +1 -376
- reflex/components/radix/themes/components/separator.pyi +0 -77
- reflex/components/radix/themes/components/skeleton.pyi +0 -30
- reflex/components/radix/themes/components/slider.py +3 -5
- reflex/components/radix/themes/components/spinner.pyi +0 -5
- reflex/components/radix/themes/components/switch.pyi +0 -89
- reflex/components/radix/themes/components/table.pyi +0 -1453
- reflex/components/radix/themes/components/text_area.pyi +7 -282
- reflex/components/radix/themes/components/text_field.pyi +6 -392
- reflex/components/radix/themes/components/tooltip.pyi +0 -42
- reflex/components/radix/themes/layout/box.pyi +1 -195
- reflex/components/radix/themes/layout/center.pyi +0 -194
- reflex/components/radix/themes/layout/container.pyi +0 -178
- reflex/components/radix/themes/layout/flex.pyi +0 -194
- reflex/components/radix/themes/layout/grid.pyi +0 -194
- reflex/components/radix/themes/layout/list.pyi +0 -978
- reflex/components/radix/themes/layout/section.pyi +0 -194
- reflex/components/radix/themes/layout/spacer.pyi +0 -194
- reflex/components/radix/themes/layout/stack.pyi +0 -582
- reflex/components/radix/themes/typography/blockquote.pyi +0 -196
- reflex/components/radix/themes/typography/code.pyi +0 -194
- reflex/components/radix/themes/typography/heading.pyi +0 -194
- reflex/components/radix/themes/typography/link.pyi +0 -237
- reflex/components/radix/themes/typography/text.pyi +0 -1360
- reflex/components/react_router/dom.pyi +0 -237
- reflex/components/recharts/cartesian.py +12 -18
- reflex/components/recharts/general.py +12 -18
- reflex/constants/installer.py +5 -5
- reflex/custom_components/custom_components.py +6 -5
- reflex/environment.py +30 -7
- reflex/event.py +14 -12
- reflex/experimental/client_state.py +11 -12
- reflex/istate/data.py +8 -10
- reflex/istate/manager/__init__.py +3 -0
- reflex/istate/manager/disk.py +151 -5
- reflex/model.py +1 -1
- reflex/plugins/_screenshot.py +2 -2
- reflex/plugins/shared_tailwind.py +9 -14
- reflex/reflex.py +7 -9
- reflex/state.py +30 -37
- reflex/style.py +6 -6
- reflex/testing.py +54 -30
- reflex/utils/codespaces.py +31 -2
- reflex/utils/compat.py +1 -0
- reflex/utils/decorator.py +3 -3
- reflex/utils/format.py +18 -22
- reflex/utils/prerequisites.py +1 -1
- reflex/utils/pyi_generator.py +51 -57
- reflex/utils/serializers.py +1 -1
- reflex/utils/telemetry.py +1 -1
- reflex/utils/templates.py +4 -4
- reflex/utils/types.py +11 -4
- reflex/vars/base.py +26 -29
- reflex/vars/color.py +6 -8
- reflex/vars/dep_tracking.py +5 -3
- reflex/vars/function.py +3 -3
- reflex/vars/object.py +9 -13
- reflex/vars/sequence.py +18 -24
- {reflex-0.8.15a1.dist-info → reflex-0.8.16.dist-info}/METADATA +1 -1
- {reflex-0.8.15a1.dist-info → reflex-0.8.16.dist-info}/RECORD +140 -140
- {reflex-0.8.15a1.dist-info → reflex-0.8.16.dist-info}/WHEEL +0 -0
- {reflex-0.8.15a1.dist-info → reflex-0.8.16.dist-info}/entry_points.txt +0 -0
- {reflex-0.8.15a1.dist-info → reflex-0.8.16.dist-info}/licenses/LICENSE +0 -0
reflex/utils/codespaces.py
CHANGED
|
@@ -26,11 +26,40 @@ def redirect_script() -> str:
|
|
|
26
26
|
const thisUrl = new URL(window.location.href);
|
|
27
27
|
const params = new URLSearchParams(thisUrl.search)
|
|
28
28
|
|
|
29
|
+
function sameHostnameDifferentPort(one, two) {{
|
|
30
|
+
const hostnameOne = one.hostname;
|
|
31
|
+
const hostnameTwo = two.hostname;
|
|
32
|
+
const partsOne = hostnameOne.split(".");
|
|
33
|
+
const partsTwo = hostnameTwo.split(".");
|
|
34
|
+
if (partsOne.length !== partsTwo.length) {{ return false; }}
|
|
35
|
+
for (let i = 1; i < partsOne.length; i++) {{
|
|
36
|
+
if (partsOne[i] !== partsTwo[i]) {{ return false; }}
|
|
37
|
+
}}
|
|
38
|
+
const uniqueNameOne = partsOne[0];
|
|
39
|
+
const uniqueNameTwo = partsTwo[0];
|
|
40
|
+
const uniqueNamePartsOne = uniqueNameOne.split("-");
|
|
41
|
+
const uniqueNamePartsTwo = uniqueNameTwo.split("-");
|
|
42
|
+
if (uniqueNamePartsOne.length !== uniqueNamePartsTwo.length) {{ return false; }}
|
|
43
|
+
for (let i = 0; i < uniqueNamePartsOne.length - 1; i++) {{
|
|
44
|
+
if (uniqueNamePartsOne[i] !== uniqueNamePartsTwo[i]) {{ return false; }}
|
|
45
|
+
}}
|
|
46
|
+
return true;
|
|
47
|
+
}}
|
|
48
|
+
|
|
29
49
|
function doRedirect(url) {{
|
|
30
50
|
if (!window.sessionStorage.getItem("authenticated_github_codespaces")) {{
|
|
31
51
|
const a = document.createElement("a");
|
|
32
52
|
if (params.has("redirect_to")) {{
|
|
33
|
-
|
|
53
|
+
const redirect_to = new URL(params.get("redirect_to"));
|
|
54
|
+
if (!sameHostnameDifferentPort(thisUrl, redirect_to)) {{
|
|
55
|
+
console.warn("Reflex: Not redirecting to different hostname");
|
|
56
|
+
return;
|
|
57
|
+
}}
|
|
58
|
+
if (!redirect_to.hostname.endsWith(".app.github.dev")) {{
|
|
59
|
+
console.warn("Reflex: Not redirecting to non .app.github.dev hostname");
|
|
60
|
+
return;
|
|
61
|
+
}}
|
|
62
|
+
a.href = redirect_to.href;
|
|
34
63
|
}} else if (!window.location.href.startsWith(url)) {{
|
|
35
64
|
a.href = url + `?redirect_to=${{window.location.href}}`
|
|
36
65
|
}} else {{
|
|
@@ -75,7 +104,7 @@ def codespaces_auto_redirect() -> list[Component]:
|
|
|
75
104
|
return []
|
|
76
105
|
|
|
77
106
|
|
|
78
|
-
|
|
107
|
+
def auth_codespace(_request: Request) -> HTMLResponse:
|
|
79
108
|
"""Page automatically redirecting back to the app after authenticating a codespace port forward.
|
|
80
109
|
|
|
81
110
|
Args:
|
reflex/utils/compat.py
CHANGED
|
@@ -74,6 +74,7 @@ if find_spec("pydantic") and find_spec("pydantic.v1"):
|
|
|
74
74
|
"""
|
|
75
75
|
namespace["__annotations__"] = annotations_from_namespace(namespace)
|
|
76
76
|
return super().__new__(mcs, name, bases, namespace, **kwargs)
|
|
77
|
+
|
|
77
78
|
else:
|
|
78
79
|
ModelMetaclassLazyAnnotations = type # type: ignore[assignment]
|
|
79
80
|
|
reflex/utils/decorator.py
CHANGED
|
@@ -110,14 +110,14 @@ def cached_procedure(
|
|
|
110
110
|
|
|
111
111
|
def _inner_decorator(func: Callable[P, Picklable]) -> Callable[P, Picklable]:
|
|
112
112
|
def _inner(*args: P.args, **kwargs: P.kwargs) -> Picklable:
|
|
113
|
-
|
|
113
|
+
cache_file = cache_file_path()
|
|
114
114
|
|
|
115
|
-
payload, value = _read_cached_procedure_file(
|
|
115
|
+
payload, value = _read_cached_procedure_file(cache_file)
|
|
116
116
|
new_payload = payload_fn(*args, **kwargs)
|
|
117
117
|
|
|
118
118
|
if payload != new_payload:
|
|
119
119
|
new_value = func(*args, **kwargs)
|
|
120
|
-
_write_cached_procedure_file(new_payload,
|
|
120
|
+
_write_cached_procedure_file(new_payload, cache_file, new_value)
|
|
121
121
|
return new_value
|
|
122
122
|
|
|
123
123
|
from reflex.utils import console
|
reflex/utils/format.py
CHANGED
|
@@ -165,8 +165,8 @@ def to_snake_case(text: str) -> str:
|
|
|
165
165
|
Returns:
|
|
166
166
|
The snake case string.
|
|
167
167
|
"""
|
|
168
|
-
s1 = re.sub("(.)([A-Z][a-z]+)", r"\1_\2", text)
|
|
169
|
-
return re.sub("([a-z0-9])([A-Z])", r"\1_\2", s1).lower().replace("-", "_")
|
|
168
|
+
s1 = re.sub(r"(.)([A-Z][a-z]+)", r"\1_\2", text)
|
|
169
|
+
return re.sub(r"([a-z0-9])([A-Z])", r"\1_\2", s1).lower().replace("-", "_")
|
|
170
170
|
|
|
171
171
|
|
|
172
172
|
def to_camel_case(text: str, treat_hyphens_as_underscores: bool = True) -> str:
|
|
@@ -349,9 +349,9 @@ def format_match(
|
|
|
349
349
|
for case in match_cases:
|
|
350
350
|
conditions, return_value = case
|
|
351
351
|
|
|
352
|
-
case_conditions = " ".join(
|
|
353
|
-
|
|
354
|
-
)
|
|
352
|
+
case_conditions = " ".join([
|
|
353
|
+
f"case JSON.stringify({condition!s}):" for condition in conditions
|
|
354
|
+
])
|
|
355
355
|
case_code = f"{case_conditions} return ({return_value!s}); break;"
|
|
356
356
|
switch_code += case_code
|
|
357
357
|
|
|
@@ -493,24 +493,20 @@ def format_event(event_spec: EventSpec) -> str:
|
|
|
493
493
|
Returns:
|
|
494
494
|
The compiled event.
|
|
495
495
|
"""
|
|
496
|
-
args = ",".join(
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
(
|
|
502
|
-
|
|
503
|
-
json.dumps(val._js_expr).strip('"').replace("`", "\\`"),
|
|
504
|
-
"`",
|
|
505
|
-
)
|
|
506
|
-
if val._var_is_string
|
|
507
|
-
else str(val)
|
|
508
|
-
),
|
|
496
|
+
args = ",".join([
|
|
497
|
+
":".join((
|
|
498
|
+
name._js_expr,
|
|
499
|
+
(
|
|
500
|
+
wrap(
|
|
501
|
+
json.dumps(val._js_expr).strip('"').replace("`", "\\`"),
|
|
502
|
+
"`",
|
|
509
503
|
)
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
504
|
+
if val._var_is_string
|
|
505
|
+
else str(val)
|
|
506
|
+
),
|
|
507
|
+
))
|
|
508
|
+
for name, val in event_spec.args
|
|
509
|
+
])
|
|
514
510
|
event_args = [
|
|
515
511
|
wrap(format_event_handler(event_spec.handler), '"'),
|
|
516
512
|
]
|
reflex/utils/prerequisites.py
CHANGED
|
@@ -458,7 +458,7 @@ def validate_app_name(app_name: str | None = None) -> str:
|
|
|
458
458
|
Raises:
|
|
459
459
|
SystemExit: if the app directory name is reflex or if the name is not standard for a python package name.
|
|
460
460
|
"""
|
|
461
|
-
app_name = app_name
|
|
461
|
+
app_name = app_name or Path.cwd().name.replace("-", "_")
|
|
462
462
|
# Make sure the app is not named "reflex".
|
|
463
463
|
if app_name.lower() == constants.Reflex.MODULE_NAME:
|
|
464
464
|
console.error(
|
reflex/utils/pyi_generator.py
CHANGED
|
@@ -193,9 +193,9 @@ def _get_type_hint(
|
|
|
193
193
|
|
|
194
194
|
if value.__name__ == "Var":
|
|
195
195
|
args = list(
|
|
196
|
-
chain.from_iterable(
|
|
197
|
-
|
|
198
|
-
)
|
|
196
|
+
chain.from_iterable([
|
|
197
|
+
get_args(arg) if rx_types.is_union(arg) else [arg] for arg in args
|
|
198
|
+
])
|
|
199
199
|
)
|
|
200
200
|
|
|
201
201
|
# For Var types, Union with the inner args so they can be passed directly.
|
|
@@ -270,7 +270,7 @@ def _generate_docstrings(clzs: list[type[Component]], props: list[str]) -> str:
|
|
|
270
270
|
comments = []
|
|
271
271
|
for clz in clzs:
|
|
272
272
|
for line in inspect.getsource(clz).splitlines():
|
|
273
|
-
reached_functions = re.search("def ", line)
|
|
273
|
+
reached_functions = re.search(r"def ", line)
|
|
274
274
|
if reached_functions:
|
|
275
275
|
# We've reached the functions, so stop.
|
|
276
276
|
break
|
|
@@ -288,7 +288,7 @@ def _generate_docstrings(clzs: list[type[Component]], props: list[str]) -> str:
|
|
|
288
288
|
continue
|
|
289
289
|
|
|
290
290
|
# Check if this line has a prop.
|
|
291
|
-
match = re.search("
|
|
291
|
+
match = re.search(r"\w+:", line)
|
|
292
292
|
if match is None:
|
|
293
293
|
# This line doesn't have a var, so continue.
|
|
294
294
|
continue
|
|
@@ -307,9 +307,9 @@ def _generate_docstrings(clzs: list[type[Component]], props: list[str]) -> str:
|
|
|
307
307
|
for line in (clz.create.__doc__ or "").splitlines():
|
|
308
308
|
if "**" in line:
|
|
309
309
|
indent = line.split("**")[0]
|
|
310
|
-
new_docstring.extend(
|
|
311
|
-
|
|
312
|
-
)
|
|
310
|
+
new_docstring.extend([
|
|
311
|
+
f"{indent}{n}:{' '.join(c)}" for n, c in props_comments.items()
|
|
312
|
+
])
|
|
313
313
|
new_docstring.append(line)
|
|
314
314
|
return "\n".join(new_docstring)
|
|
315
315
|
|
|
@@ -394,23 +394,21 @@ def _extract_class_props_as_ast_nodes(
|
|
|
394
394
|
for module in modules:
|
|
395
395
|
available_vars.update(sys.modules[module].__dict__)
|
|
396
396
|
|
|
397
|
-
kwargs.append(
|
|
398
|
-
(
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
)
|
|
409
|
-
),
|
|
397
|
+
kwargs.append((
|
|
398
|
+
ast.arg(
|
|
399
|
+
arg=name,
|
|
400
|
+
annotation=ast.Name(
|
|
401
|
+
id=OVERWRITE_TYPES.get(
|
|
402
|
+
name,
|
|
403
|
+
_get_type_hint(
|
|
404
|
+
value,
|
|
405
|
+
type_hint_globals | available_vars,
|
|
406
|
+
),
|
|
407
|
+
)
|
|
410
408
|
),
|
|
411
|
-
|
|
412
|
-
)
|
|
413
|
-
)
|
|
409
|
+
),
|
|
410
|
+
ast.Constant(value=default), # pyright: ignore [reportArgumentType]
|
|
411
|
+
))
|
|
414
412
|
return kwargs
|
|
415
413
|
|
|
416
414
|
|
|
@@ -489,7 +487,7 @@ def type_to_ast(typ: Any, cls: type) -> ast.expr:
|
|
|
489
487
|
|
|
490
488
|
|
|
491
489
|
def _get_parent_imports(func: Callable):
|
|
492
|
-
|
|
490
|
+
imports_ = {"reflex.vars": ["Var"]}
|
|
493
491
|
for type_hint in inspect.get_annotations(func).values():
|
|
494
492
|
try:
|
|
495
493
|
match = re.match(r"\w+\[([\w\d]+)\]", type_hint)
|
|
@@ -498,8 +496,8 @@ def _get_parent_imports(func: Callable):
|
|
|
498
496
|
if match:
|
|
499
497
|
type_hint = match.group(1)
|
|
500
498
|
if type_hint in importlib.import_module(func.__module__).__dir__():
|
|
501
|
-
|
|
502
|
-
return
|
|
499
|
+
imports_.setdefault(func.__module__, []).append(type_hint)
|
|
500
|
+
return imports_
|
|
503
501
|
|
|
504
502
|
|
|
505
503
|
def _generate_component_create_functiondef(
|
|
@@ -527,13 +525,13 @@ def _generate_component_create_functiondef(
|
|
|
527
525
|
raise TypeError(msg)
|
|
528
526
|
|
|
529
527
|
# add the imports needed by get_type_hint later
|
|
530
|
-
type_hint_globals.update(
|
|
531
|
-
|
|
532
|
-
)
|
|
528
|
+
type_hint_globals.update({
|
|
529
|
+
name: getattr(typing, name) for name in DEFAULT_TYPING_IMPORTS
|
|
530
|
+
})
|
|
533
531
|
|
|
534
532
|
if clz.__module__ != clz.create.__module__:
|
|
535
|
-
|
|
536
|
-
for name, values in
|
|
533
|
+
imports_ = _get_parent_imports(clz.create)
|
|
534
|
+
for name, values in imports_.items():
|
|
537
535
|
exec(f"from {name} import {','.join(values)}", type_hint_globals)
|
|
538
536
|
|
|
539
537
|
kwargs = _extract_func_kwargs_as_ast_nodes(clz.create, type_hint_globals)
|
|
@@ -637,16 +635,12 @@ def _generate_component_create_functiondef(
|
|
|
637
635
|
)
|
|
638
636
|
else ast.Subscript(
|
|
639
637
|
ast.Name("Union"),
|
|
640
|
-
ast.Tuple(
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
)
|
|
647
|
-
for event_spec in event_specs
|
|
648
|
-
]
|
|
649
|
-
),
|
|
638
|
+
ast.Tuple([
|
|
639
|
+
figure_out_return_type(
|
|
640
|
+
inspect.signature(event_spec).return_annotation
|
|
641
|
+
)
|
|
642
|
+
for event_spec in event_specs
|
|
643
|
+
]),
|
|
650
644
|
)
|
|
651
645
|
)
|
|
652
646
|
),
|
|
@@ -759,9 +753,9 @@ def _generate_namespace_call_functiondef(
|
|
|
759
753
|
The create functiondef node for the ast.
|
|
760
754
|
"""
|
|
761
755
|
# add the imports needed by get_type_hint later
|
|
762
|
-
type_hint_globals.update(
|
|
763
|
-
|
|
764
|
-
)
|
|
756
|
+
type_hint_globals.update({
|
|
757
|
+
name: getattr(typing, name) for name in DEFAULT_TYPING_IMPORTS
|
|
758
|
+
})
|
|
765
759
|
|
|
766
760
|
clz = classes[clz_name]
|
|
767
761
|
|
|
@@ -1093,15 +1087,13 @@ class PyiGenerator:
|
|
|
1093
1087
|
def _write_pyi_file(self, module_path: Path, source: str) -> str:
|
|
1094
1088
|
relpath = str(_relative_to_pwd(module_path)).replace("\\", "/")
|
|
1095
1089
|
pyi_content = (
|
|
1096
|
-
"\n".join(
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
]
|
|
1104
|
-
)
|
|
1090
|
+
"\n".join([
|
|
1091
|
+
f'"""Stub file for {relpath}"""',
|
|
1092
|
+
"# ------------------- DO NOT EDIT ----------------------",
|
|
1093
|
+
"# This file was generated by `reflex/utils/pyi_generator.py`!",
|
|
1094
|
+
"# ------------------------------------------------------",
|
|
1095
|
+
"",
|
|
1096
|
+
])
|
|
1105
1097
|
+ source
|
|
1106
1098
|
)
|
|
1107
1099
|
|
|
@@ -1159,9 +1151,11 @@ class PyiGenerator:
|
|
|
1159
1151
|
|
|
1160
1152
|
text = (
|
|
1161
1153
|
"\n"
|
|
1162
|
-
+ "\n".join(
|
|
1163
|
-
|
|
1164
|
-
|
|
1154
|
+
+ "\n".join([
|
|
1155
|
+
*sub_mods_imports,
|
|
1156
|
+
*sub_mod_attrs_imports,
|
|
1157
|
+
*extra_mappings_imports,
|
|
1158
|
+
])
|
|
1165
1159
|
+ "\n"
|
|
1166
1160
|
)
|
|
1167
1161
|
text += ast.unparse(new_tree) + "\n\n"
|
reflex/utils/serializers.py
CHANGED
|
@@ -137,7 +137,7 @@ def serialize(value: Any) -> SerializedType | None: ...
|
|
|
137
137
|
|
|
138
138
|
def serialize(
|
|
139
139
|
value: Any, get_type: bool = False
|
|
140
|
-
) -> SerializedType |
|
|
140
|
+
) -> SerializedType | tuple[SerializedType | None, types.GenericType | None] | None:
|
|
141
141
|
"""Serialize the value to a JSON string.
|
|
142
142
|
|
|
143
143
|
Args:
|
reflex/utils/telemetry.py
CHANGED
|
@@ -346,7 +346,7 @@ def send(event: str, telemetry_enabled: bool | None = None, **kwargs):
|
|
|
346
346
|
kwargs: Additional data to send with the event.
|
|
347
347
|
"""
|
|
348
348
|
|
|
349
|
-
async def async_send(event: str, telemetry_enabled: bool | None, **kwargs):
|
|
349
|
+
async def async_send(event: str, telemetry_enabled: bool | None, **kwargs): # noqa: RUF029
|
|
350
350
|
return _send(event, telemetry_enabled, **kwargs)
|
|
351
351
|
|
|
352
352
|
try:
|
reflex/utils/templates.py
CHANGED
|
@@ -285,9 +285,9 @@ def fetch_app_templates(version: str) -> dict[str, Template]:
|
|
|
285
285
|
if tp["hidden"] or tp["code_url"] is None:
|
|
286
286
|
continue
|
|
287
287
|
known_fields = {f.name for f in dataclasses.fields(Template)}
|
|
288
|
-
filtered_templates[tp["name"]] = Template(
|
|
289
|
-
|
|
290
|
-
)
|
|
288
|
+
filtered_templates[tp["name"]] = Template(**{
|
|
289
|
+
k: v for k, v in tp.items() if k in known_fields
|
|
290
|
+
})
|
|
291
291
|
return filtered_templates
|
|
292
292
|
|
|
293
293
|
|
|
@@ -383,7 +383,7 @@ def initialize_app(app_name: str, template: str | None = None) -> str | None:
|
|
|
383
383
|
templates: dict[str, Template] = {}
|
|
384
384
|
|
|
385
385
|
# Don't fetch app templates if the user directly asked for DEFAULT.
|
|
386
|
-
if template is not None and
|
|
386
|
+
if template is not None and template != constants.Templates.DEFAULT:
|
|
387
387
|
template, templates = fetch_remote_templates(template)
|
|
388
388
|
|
|
389
389
|
if template is None:
|
reflex/utils/types.py
CHANGED
|
@@ -443,6 +443,13 @@ def get_attribute_access_type(cls: GenericType, name: str) -> GenericType | None
|
|
|
443
443
|
|
|
444
444
|
from reflex.model import Model
|
|
445
445
|
|
|
446
|
+
if find_spec("sqlmodel"):
|
|
447
|
+
from sqlmodel import SQLModel
|
|
448
|
+
|
|
449
|
+
sqlmodel_types = (Model, SQLModel)
|
|
450
|
+
else:
|
|
451
|
+
sqlmodel_types = (Model,)
|
|
452
|
+
|
|
446
453
|
if isinstance(cls, type) and issubclass(cls, DeclarativeBase):
|
|
447
454
|
insp = sqlalchemy.inspect(cls)
|
|
448
455
|
if name in insp.columns:
|
|
@@ -486,7 +493,7 @@ def get_attribute_access_type(cls: GenericType, name: str) -> GenericType | None
|
|
|
486
493
|
elif (
|
|
487
494
|
isinstance(cls, type)
|
|
488
495
|
and not is_generic_alias(cls)
|
|
489
|
-
and issubclass(cls,
|
|
496
|
+
and issubclass(cls, sqlmodel_types)
|
|
490
497
|
):
|
|
491
498
|
# Check in the annotations directly (for sqlmodel.Relationship)
|
|
492
499
|
hints = get_type_hints(cls) # pyright: ignore [reportArgumentType]
|
|
@@ -984,9 +991,9 @@ def validate_literal(key: str, value: Any, expected_type: type, comp_name: str):
|
|
|
984
991
|
):
|
|
985
992
|
allowed_values = expected_type.__args__
|
|
986
993
|
if value not in allowed_values:
|
|
987
|
-
allowed_value_str = ",".join(
|
|
988
|
-
|
|
989
|
-
)
|
|
994
|
+
allowed_value_str = ",".join([
|
|
995
|
+
str(v) if not isinstance(v, str) else f"'{v}'" for v in allowed_values
|
|
996
|
+
])
|
|
990
997
|
value_str = f"'{value}'" if isinstance(value, str) else value
|
|
991
998
|
msg = f"prop value for {key!s} of the `{comp_name}` component should be one of the following: {allowed_value_str}. Got {value_str} instead"
|
|
992
999
|
raise ValueError(msg)
|
reflex/vars/base.py
CHANGED
|
@@ -233,7 +233,7 @@ class VarData:
|
|
|
233
233
|
hook: None for var_data in all_var_datas for hook in var_data.hooks
|
|
234
234
|
}
|
|
235
235
|
|
|
236
|
-
|
|
236
|
+
imports_ = imports.merge_imports(
|
|
237
237
|
*(var_data.imports for var_data in all_var_datas)
|
|
238
238
|
)
|
|
239
239
|
|
|
@@ -261,7 +261,7 @@ class VarData:
|
|
|
261
261
|
return VarData(
|
|
262
262
|
state=state,
|
|
263
263
|
field_name=field_name,
|
|
264
|
-
imports=
|
|
264
|
+
imports=imports_,
|
|
265
265
|
hooks=hooks,
|
|
266
266
|
deps=deps,
|
|
267
267
|
position=position,
|
|
@@ -488,13 +488,13 @@ class Var(Generic[VAR_TYPE], metaclass=MetaclassVar):
|
|
|
488
488
|
raise TypeError(msg)
|
|
489
489
|
|
|
490
490
|
# Decode any inline Var markup and apply it to the instance
|
|
491
|
-
|
|
491
|
+
var_data_, js_expr_ = _decode_var_immutable(self._js_expr)
|
|
492
492
|
|
|
493
|
-
if
|
|
493
|
+
if var_data_ or js_expr_ != self._js_expr:
|
|
494
494
|
self.__init__(
|
|
495
|
-
_js_expr=
|
|
495
|
+
_js_expr=js_expr_,
|
|
496
496
|
_var_type=self._var_type,
|
|
497
|
-
_var_data=VarData.merge(self._var_data,
|
|
497
|
+
_var_data=VarData.merge(self._var_data, var_data_),
|
|
498
498
|
)
|
|
499
499
|
|
|
500
500
|
def __hash__(self) -> int:
|
|
@@ -1590,12 +1590,10 @@ class LiteralVar(Var):
|
|
|
1590
1590
|
)
|
|
1591
1591
|
|
|
1592
1592
|
if dataclasses.is_dataclass(value) and not isinstance(value, type):
|
|
1593
|
-
return LiteralObjectVar._get_all_var_data_without_creating_var(
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
}
|
|
1598
|
-
)
|
|
1593
|
+
return LiteralObjectVar._get_all_var_data_without_creating_var({
|
|
1594
|
+
k: (None if callable(v) else v)
|
|
1595
|
+
for k, v in dataclasses.asdict(value).items()
|
|
1596
|
+
})
|
|
1599
1597
|
|
|
1600
1598
|
if isinstance(value, range):
|
|
1601
1599
|
return None
|
|
@@ -1949,16 +1947,14 @@ class CachedVarOperation:
|
|
|
1949
1947
|
Returns:
|
|
1950
1948
|
The hash of the object.
|
|
1951
1949
|
"""
|
|
1952
|
-
return hash(
|
|
1953
|
-
(
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
)
|
|
1961
|
-
)
|
|
1950
|
+
return hash((
|
|
1951
|
+
type(self).__name__,
|
|
1952
|
+
*[
|
|
1953
|
+
getattr(self, field.name)
|
|
1954
|
+
for field in dataclasses.fields(self)
|
|
1955
|
+
if field.name not in ["_js_expr", "_var_data", "_var_type"]
|
|
1956
|
+
],
|
|
1957
|
+
))
|
|
1962
1958
|
|
|
1963
1959
|
|
|
1964
1960
|
def and_operation(
|
|
@@ -2171,11 +2167,11 @@ class ComputedVar(Var[RETURN_TYPE]):
|
|
|
2171
2167
|
if isinstance(deps, dict):
|
|
2172
2168
|
# Assume a dict is coming from _replace, so no special processing.
|
|
2173
2169
|
return deps
|
|
2174
|
-
|
|
2170
|
+
static_deps = {}
|
|
2175
2171
|
if deps is not None:
|
|
2176
2172
|
for dep in deps:
|
|
2177
|
-
|
|
2178
|
-
return
|
|
2173
|
+
static_deps = self._add_static_dep(dep, static_deps)
|
|
2174
|
+
return static_deps
|
|
2179
2175
|
|
|
2180
2176
|
def _add_static_dep(
|
|
2181
2177
|
self, dep: str | Var, deps: dict[str | None, set[str]] | None = None
|
|
@@ -2494,9 +2490,10 @@ class ComputedVar(Var[RETURN_TYPE]):
|
|
|
2494
2490
|
self._static_deps.setdefault(state_name, set()).add(var_name)
|
|
2495
2491
|
objclass.get_root_state().get_class_substate(
|
|
2496
2492
|
state_name
|
|
2497
|
-
)._var_dependencies.setdefault(var_name, set()).add(
|
|
2498
|
-
|
|
2499
|
-
|
|
2493
|
+
)._var_dependencies.setdefault(var_name, set()).add((
|
|
2494
|
+
objclass.get_full_name(),
|
|
2495
|
+
self._name,
|
|
2496
|
+
))
|
|
2500
2497
|
return
|
|
2501
2498
|
msg = (
|
|
2502
2499
|
"ComputedVar dependencies must be Var instances with a state and "
|
|
@@ -2538,7 +2535,7 @@ class DynamicRouteVar(ComputedVar[str | list[str]]):
|
|
|
2538
2535
|
"""A ComputedVar that represents a dynamic route."""
|
|
2539
2536
|
|
|
2540
2537
|
|
|
2541
|
-
async def _default_async_computed_var(_self: BaseState) -> Any:
|
|
2538
|
+
async def _default_async_computed_var(_self: BaseState) -> Any: # noqa: RUF029
|
|
2542
2539
|
return None
|
|
2543
2540
|
|
|
2544
2541
|
|
reflex/vars/color.py
CHANGED
|
@@ -76,14 +76,12 @@ class LiteralColorVar(CachedVarOperation, LiteralVar, ColorVar):
|
|
|
76
76
|
Returns:
|
|
77
77
|
The hash of the var.
|
|
78
78
|
"""
|
|
79
|
-
return hash(
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
)
|
|
86
|
-
)
|
|
79
|
+
return hash((
|
|
80
|
+
self.__class__.__name__,
|
|
81
|
+
self._var_value.color,
|
|
82
|
+
self._var_value.alpha,
|
|
83
|
+
self._var_value.shade,
|
|
84
|
+
))
|
|
87
85
|
|
|
88
86
|
@cached_property_no_lock
|
|
89
87
|
def _cached_var_name(self) -> str:
|
reflex/vars/dep_tracking.py
CHANGED
|
@@ -255,9 +255,11 @@ class DependencyTracker:
|
|
|
255
255
|
source = inspect.getsource(module).splitlines(True)[start_line - 1 : end_line]
|
|
256
256
|
# Create a python source string snippet.
|
|
257
257
|
if len(source) > 1:
|
|
258
|
-
snipped_source = "".join(
|
|
259
|
-
|
|
260
|
-
|
|
258
|
+
snipped_source = "".join([
|
|
259
|
+
*source[0][start_column:],
|
|
260
|
+
*source[1:-1],
|
|
261
|
+
*source[-1][:end_column],
|
|
262
|
+
])
|
|
261
263
|
else:
|
|
262
264
|
snipped_source = source[0][start_column:end_column]
|
|
263
265
|
# Evaluate the string in the context of the function's globals and closure.
|
reflex/vars/function.py
CHANGED
|
@@ -331,9 +331,9 @@ def format_args_function_operation(
|
|
|
331
331
|
Returns:
|
|
332
332
|
The formatted args function operation.
|
|
333
333
|
"""
|
|
334
|
-
arg_names_str = ", ".join(
|
|
335
|
-
|
|
336
|
-
) + (f", ...{args.rest}" if args.rest else "")
|
|
334
|
+
arg_names_str = ", ".join([
|
|
335
|
+
arg if isinstance(arg, str) else arg.to_javascript() for arg in args.args
|
|
336
|
+
]) + (f", ...{args.rest}" if args.rest else "")
|
|
337
337
|
|
|
338
338
|
return_expr_str = str(LiteralVar.create(return_expr))
|
|
339
339
|
|
reflex/vars/object.py
CHANGED
|
@@ -56,13 +56,11 @@ def _determine_value_type(var_type: GenericType):
|
|
|
56
56
|
origin_var_type = get_origin(var_type) or var_type
|
|
57
57
|
|
|
58
58
|
if origin_var_type in types.UnionTypes:
|
|
59
|
-
return unionize(
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
]
|
|
65
|
-
)
|
|
59
|
+
return unionize(*[
|
|
60
|
+
_determine_value_type(arg)
|
|
61
|
+
for arg in get_args(var_type)
|
|
62
|
+
if arg is not type(None)
|
|
63
|
+
])
|
|
66
64
|
|
|
67
65
|
if is_typeddict(origin_var_type) or dataclasses.is_dataclass(origin_var_type):
|
|
68
66
|
annotations = get_type_hints(origin_var_type)
|
|
@@ -401,12 +399,10 @@ class LiteralObjectVar(CachedVarOperation, ObjectVar[OBJECT_TYPE], LiteralVar):
|
|
|
401
399
|
"""
|
|
402
400
|
return (
|
|
403
401
|
"({ "
|
|
404
|
-
+ ", ".join(
|
|
405
|
-
[
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
]
|
|
409
|
-
)
|
|
402
|
+
+ ", ".join([
|
|
403
|
+
f"[{LiteralVar.create(key)!s}] : {LiteralVar.create(value)!s}"
|
|
404
|
+
for key, value in self._var_value.items()
|
|
405
|
+
])
|
|
410
406
|
+ " })"
|
|
411
407
|
)
|
|
412
408
|
|