reflex 0.7.1a4__py3-none-any.whl → 0.7.2a1__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/utils/context.js.jinja2 +8 -8
- reflex/.templates/web/components/reflex/radix_themes_color_mode_provider.js +3 -3
- reflex/admin.py +1 -2
- reflex/app.py +46 -49
- reflex/app_mixins/lifespan.py +2 -2
- reflex/app_mixins/middleware.py +1 -2
- reflex/assets.py +1 -2
- reflex/base.py +2 -2
- reflex/compiler/compiler.py +51 -16
- reflex/compiler/utils.py +4 -13
- reflex/components/base/app_wrap.pyi +7 -7
- reflex/components/base/bare.py +3 -3
- reflex/components/base/body.pyi +7 -7
- reflex/components/base/document.py +1 -3
- reflex/components/base/document.pyi +32 -32
- reflex/components/base/error_boundary.py +2 -4
- reflex/components/base/error_boundary.pyi +11 -13
- reflex/components/base/fragment.pyi +7 -7
- reflex/components/base/head.pyi +13 -13
- reflex/components/base/link.pyi +22 -22
- reflex/components/base/meta.py +5 -7
- reflex/components/base/meta.pyi +40 -40
- reflex/components/base/script.pyi +11 -14
- reflex/components/base/strict_mode.pyi +7 -7
- reflex/components/component.py +188 -113
- reflex/components/core/auto_scroll.py +8 -1
- reflex/components/core/auto_scroll.pyi +183 -210
- reflex/components/core/banner.py +2 -4
- reflex/components/core/banner.pyi +390 -444
- reflex/components/core/breakpoints.py +5 -5
- reflex/components/core/client_side_routing.pyi +14 -14
- reflex/components/core/clipboard.py +4 -4
- reflex/components/core/clipboard.pyi +12 -14
- reflex/components/core/cond.py +17 -25
- reflex/components/core/debounce.py +3 -3
- reflex/components/core/debounce.pyi +14 -14
- reflex/components/core/foreach.py +7 -2
- reflex/components/core/html.py +1 -3
- reflex/components/core/html.pyi +184 -213
- reflex/components/core/match.py +15 -19
- reflex/components/core/sticky.pyi +930 -1078
- reflex/components/core/upload.py +4 -4
- reflex/components/core/upload.pyi +62 -62
- reflex/components/datadisplay/code.py +6 -6
- reflex/components/datadisplay/code.pyi +1159 -1165
- reflex/components/datadisplay/dataeditor.py +49 -49
- reflex/components/datadisplay/dataeditor.pyi +95 -123
- reflex/components/datadisplay/logo.py +1 -3
- reflex/components/datadisplay/shiki_code_block.py +8 -10
- reflex/components/datadisplay/shiki_code_block.pyi +1678 -1720
- reflex/components/el/element.pyi +7 -7
- reflex/components/el/elements/base.pyi +183 -210
- reflex/components/el/elements/forms.py +23 -23
- reflex/components/el/elements/forms.pyi +2571 -2933
- reflex/components/el/elements/inline.py +4 -4
- reflex/components/el/elements/inline.pyi +5191 -5953
- reflex/components/el/elements/media.py +47 -47
- reflex/components/el/elements/media.pyi +4802 -5500
- reflex/components/el/elements/metadata.py +1 -3
- reflex/components/el/elements/metadata.pyi +782 -896
- reflex/components/el/elements/other.pyi +1278 -1467
- reflex/components/el/elements/scripts.pyi +580 -667
- reflex/components/el/elements/sectioning.pyi +2761 -3166
- reflex/components/el/elements/tables.pyi +1840 -2119
- reflex/components/el/elements/typography.pyi +2772 -3179
- reflex/components/gridjs/datatable.py +7 -7
- reflex/components/gridjs/datatable.pyi +19 -19
- reflex/components/lucide/icon.pyi +21 -21
- reflex/components/markdown/markdown.py +2 -2
- reflex/components/markdown/markdown.pyi +9 -9
- reflex/components/moment/moment.py +11 -12
- reflex/components/moment/moment.pyi +44 -47
- reflex/components/next/base.pyi +7 -7
- reflex/components/next/image.py +3 -3
- reflex/components/next/image.pyi +19 -21
- reflex/components/next/link.pyi +9 -9
- reflex/components/next/video.py +1 -3
- reflex/components/next/video.pyi +9 -9
- reflex/components/plotly/plotly.py +22 -45
- reflex/components/plotly/plotly.pyi +164 -164
- reflex/components/radix/primitives/accordion.py +14 -14
- reflex/components/radix/primitives/accordion.pyi +439 -487
- reflex/components/radix/primitives/base.py +1 -3
- reflex/components/radix/primitives/base.pyi +15 -15
- reflex/components/radix/primitives/drawer.py +3 -3
- reflex/components/radix/primitives/drawer.pyi +110 -116
- reflex/components/radix/primitives/form.py +1 -1
- reflex/components/radix/primitives/form.pyi +668 -752
- reflex/components/radix/primitives/progress.py +6 -6
- reflex/components/radix/primitives/progress.pyi +225 -243
- reflex/components/radix/primitives/slider.py +6 -6
- reflex/components/radix/primitives/slider.pyi +52 -55
- reflex/components/radix/themes/base.py +3 -6
- reflex/components/radix/themes/base.pyi +197 -303
- reflex/components/radix/themes/color_mode.py +5 -5
- reflex/components/radix/themes/color_mode.pyi +366 -436
- reflex/components/radix/themes/components/alert_dialog.pyi +229 -262
- reflex/components/radix/themes/components/aspect_ratio.py +1 -3
- reflex/components/radix/themes/components/aspect_ratio.pyi +8 -8
- reflex/components/radix/themes/components/avatar.pyi +79 -94
- reflex/components/radix/themes/components/badge.pyi +252 -295
- reflex/components/radix/themes/components/button.pyi +269 -314
- reflex/components/radix/themes/components/callout.py +2 -2
- reflex/components/radix/themes/components/callout.pyi +1116 -1290
- reflex/components/radix/themes/components/card.pyi +194 -229
- reflex/components/radix/themes/components/checkbox.pyi +243 -278
- reflex/components/radix/themes/components/checkbox_cards.py +3 -7
- reflex/components/radix/themes/components/checkbox_cards.pyi +101 -135
- reflex/components/radix/themes/components/checkbox_group.py +2 -2
- reflex/components/radix/themes/components/checkbox_group.pyi +83 -96
- reflex/components/radix/themes/components/context_menu.py +18 -15
- reflex/components/radix/themes/components/context_menu.pyi +408 -458
- reflex/components/radix/themes/components/data_list.pyi +122 -147
- reflex/components/radix/themes/components/dialog.pyi +231 -264
- reflex/components/radix/themes/components/dropdown_menu.py +16 -13
- reflex/components/radix/themes/components/dropdown_menu.pyi +223 -246
- reflex/components/radix/themes/components/hover_card.py +2 -2
- reflex/components/radix/themes/components/hover_card.pyi +237 -282
- reflex/components/radix/themes/components/icon_button.pyi +269 -314
- reflex/components/radix/themes/components/inset.py +8 -8
- reflex/components/radix/themes/components/inset.pyi +232 -292
- reflex/components/radix/themes/components/popover.py +2 -2
- reflex/components/radix/themes/components/popover.pyi +229 -271
- reflex/components/radix/themes/components/progress.pyi +80 -96
- reflex/components/radix/themes/components/radio.pyi +73 -86
- reflex/components/radix/themes/components/radio_cards.py +4 -8
- reflex/components/radix/themes/components/radio_cards.pyi +117 -154
- reflex/components/radix/themes/components/radio_group.py +3 -3
- reflex/components/radix/themes/components/radio_group.pyi +250 -291
- reflex/components/radix/themes/components/scroll_area.pyi +14 -20
- reflex/components/radix/themes/components/segmented_control.py +6 -6
- reflex/components/radix/themes/components/segmented_control.pyi +89 -108
- reflex/components/radix/themes/components/select.py +7 -7
- reflex/components/radix/themes/components/select.pyi +376 -444
- reflex/components/radix/themes/components/separator.pyi +79 -93
- reflex/components/radix/themes/components/skeleton.pyi +32 -26
- reflex/components/radix/themes/components/slider.py +8 -8
- reflex/components/radix/themes/components/slider.pyi +99 -122
- reflex/components/radix/themes/components/spinner.pyi +12 -19
- reflex/components/radix/themes/components/switch.pyi +84 -99
- reflex/components/radix/themes/components/table.py +9 -9
- reflex/components/radix/themes/components/table.pyi +1440 -1794
- reflex/components/radix/themes/components/tabs.py +4 -4
- reflex/components/radix/themes/components/tabs.pyi +120 -132
- reflex/components/radix/themes/components/text_area.pyi +281 -331
- reflex/components/radix/themes/components/text_field.py +2 -2
- reflex/components/radix/themes/components/text_field.pyi +639 -734
- reflex/components/radix/themes/components/tooltip.py +6 -6
- reflex/components/radix/themes/components/tooltip.pyi +34 -43
- reflex/components/radix/themes/layout/base.pyi +85 -182
- reflex/components/radix/themes/layout/box.pyi +183 -210
- reflex/components/radix/themes/layout/center.pyi +225 -286
- reflex/components/radix/themes/layout/container.pyi +191 -224
- reflex/components/radix/themes/layout/flex.py +2 -2
- reflex/components/radix/themes/layout/flex.pyi +225 -286
- reflex/components/radix/themes/layout/grid.py +2 -2
- reflex/components/radix/themes/layout/grid.pyi +245 -315
- reflex/components/radix/themes/layout/list.py +2 -2
- reflex/components/radix/themes/layout/list.pyi +712 -815
- reflex/components/radix/themes/layout/section.pyi +187 -221
- reflex/components/radix/themes/layout/spacer.pyi +225 -286
- reflex/components/radix/themes/layout/stack.pyi +625 -768
- reflex/components/radix/themes/typography/blockquote.pyi +257 -299
- reflex/components/radix/themes/typography/code.pyi +259 -304
- reflex/components/radix/themes/typography/heading.pyi +272 -324
- reflex/components/radix/themes/typography/link.pyi +302 -358
- reflex/components/radix/themes/typography/text.pyi +1669 -1945
- reflex/components/react_player/audio.pyi +20 -22
- reflex/components/react_player/react_player.pyi +19 -19
- reflex/components/react_player/video.pyi +20 -22
- reflex/components/recharts/cartesian.py +100 -97
- reflex/components/recharts/cartesian.pyi +891 -1007
- reflex/components/recharts/charts.py +42 -42
- reflex/components/recharts/charts.pyi +212 -249
- reflex/components/recharts/general.py +22 -21
- reflex/components/recharts/general.pyi +198 -223
- reflex/components/recharts/polar.py +42 -45
- reflex/components/recharts/polar.pyi +254 -288
- reflex/components/recharts/recharts.pyi +13 -13
- reflex/components/sonner/toast.py +20 -20
- reflex/components/sonner/toast.pyi +58 -61
- reflex/components/suneditor/editor.py +9 -9
- reflex/components/suneditor/editor.pyi +78 -83
- reflex/components/tags/cond_tag.py +2 -2
- reflex/components/tags/iter_tag.py +10 -14
- reflex/components/tags/match_tag.py +2 -2
- reflex/components/tags/tag.py +10 -10
- reflex/config.py +36 -35
- reflex/constants/__init__.py +56 -53
- reflex/custom_components/custom_components.py +6 -7
- reflex/event.py +38 -42
- reflex/experimental/client_state.py +2 -4
- reflex/experimental/layout.py +2 -2
- reflex/experimental/layout.pyi +579 -663
- reflex/istate/data.py +4 -5
- reflex/middleware/hydrate_middleware.py +2 -2
- reflex/middleware/middleware.py +2 -2
- reflex/model.py +3 -5
- reflex/page.py +2 -2
- reflex/reflex.py +9 -10
- reflex/state.py +77 -49
- reflex/style.py +9 -3
- reflex/testing.py +21 -24
- reflex/utils/console.py +1 -1
- reflex/utils/decorator.py +26 -1
- reflex/utils/exec.py +6 -11
- reflex/utils/export.py +2 -3
- reflex/utils/format.py +4 -4
- reflex/utils/imports.py +12 -12
- reflex/utils/prerequisites.py +35 -84
- reflex/utils/processes.py +5 -5
- reflex/utils/pyi_generator.py +33 -22
- reflex/utils/serializers.py +60 -15
- reflex/utils/types.py +237 -56
- reflex/vars/base.py +122 -72
- reflex/vars/datetime.py +2 -2
- reflex/vars/function.py +52 -55
- reflex/vars/number.py +59 -5
- reflex/vars/object.py +57 -26
- reflex/vars/sequence.py +983 -958
- {reflex-0.7.1a4.dist-info → reflex-0.7.2a1.dist-info}/METADATA +3 -6
- reflex-0.7.2a1.dist-info/RECORD +405 -0
- {reflex-0.7.1a4.dist-info → reflex-0.7.2a1.dist-info}/WHEEL +1 -1
- reflex-0.7.1a4.dist-info/RECORD +0 -405
- {reflex-0.7.1a4.dist-info → reflex-0.7.2a1.dist-info}/LICENSE +0 -0
- {reflex-0.7.1a4.dist-info → reflex-0.7.2a1.dist-info}/entry_points.txt +0 -0
reflex/utils/pyi_generator.py
CHANGED
|
@@ -15,7 +15,7 @@ from inspect import getfullargspec
|
|
|
15
15
|
from itertools import chain
|
|
16
16
|
from multiprocessing import Pool, cpu_count
|
|
17
17
|
from pathlib import Path
|
|
18
|
-
from types import ModuleType, SimpleNamespace
|
|
18
|
+
from types import ModuleType, SimpleNamespace, UnionType
|
|
19
19
|
from typing import Any, Callable, Iterable, Sequence, Type, get_args, get_origin
|
|
20
20
|
|
|
21
21
|
from reflex.components.component import Component
|
|
@@ -61,9 +61,11 @@ DEFAULT_TYPING_IMPORTS = {
|
|
|
61
61
|
"Callable",
|
|
62
62
|
"Dict",
|
|
63
63
|
# "List",
|
|
64
|
+
"Sequence",
|
|
64
65
|
"Literal",
|
|
65
66
|
"Optional",
|
|
66
67
|
"Union",
|
|
68
|
+
"Annotated",
|
|
67
69
|
}
|
|
68
70
|
|
|
69
71
|
# TODO: fix import ordering and unused imports with ruff later
|
|
@@ -144,17 +146,17 @@ def _get_type_hint(
|
|
|
144
146
|
]
|
|
145
147
|
res_args.sort()
|
|
146
148
|
if len(res_args) == 1:
|
|
147
|
-
return f"
|
|
149
|
+
return f"{res_args[0]} | None"
|
|
148
150
|
else:
|
|
149
|
-
res = f"
|
|
150
|
-
return f"
|
|
151
|
+
res = f"{' | '.join(res_args)}"
|
|
152
|
+
return f"{res} | None"
|
|
151
153
|
|
|
152
154
|
res_args = [
|
|
153
155
|
_get_type_hint(arg, type_hint_globals, rx_types.is_optional(arg))
|
|
154
156
|
for arg in value.__args__
|
|
155
157
|
]
|
|
156
158
|
res_args.sort()
|
|
157
|
-
return f"
|
|
159
|
+
return f"{' | '.join(res_args)}"
|
|
158
160
|
|
|
159
161
|
if args:
|
|
160
162
|
inner_container_type_args = (
|
|
@@ -192,8 +194,8 @@ def _get_type_hint(
|
|
|
192
194
|
if arg is not type(None)
|
|
193
195
|
]
|
|
194
196
|
if len(types) > 1:
|
|
195
|
-
res = "
|
|
196
|
-
|
|
197
|
+
res = " | ".join(sorted(types))
|
|
198
|
+
|
|
197
199
|
elif isinstance(value, str):
|
|
198
200
|
ev = eval(value, type_hint_globals)
|
|
199
201
|
if rx_types.is_optional(ev):
|
|
@@ -204,7 +206,7 @@ def _get_type_hint(
|
|
|
204
206
|
_get_type_hint(arg, type_hint_globals, rx_types.is_optional(arg))
|
|
205
207
|
for arg in ev.__args__
|
|
206
208
|
]
|
|
207
|
-
return f"
|
|
209
|
+
return f"{' | '.join(res)}"
|
|
208
210
|
res = (
|
|
209
211
|
_get_type_hint(ev, type_hint_globals, is_optional=False)
|
|
210
212
|
if ev.__name__ == "Var"
|
|
@@ -212,8 +214,8 @@ def _get_type_hint(
|
|
|
212
214
|
)
|
|
213
215
|
else:
|
|
214
216
|
res = value.__name__
|
|
215
|
-
if is_optional and not res.startswith("Optional"):
|
|
216
|
-
res = f"
|
|
217
|
+
if is_optional and not res.startswith("Optional") and not res.endswith("| None"):
|
|
218
|
+
res = f"{res} | None"
|
|
217
219
|
return res
|
|
218
220
|
|
|
219
221
|
|
|
@@ -399,6 +401,8 @@ def type_to_ast(typ: Any, cls: type) -> ast.AST:
|
|
|
399
401
|
return ast.Name(id="None")
|
|
400
402
|
|
|
401
403
|
origin = get_origin(typ)
|
|
404
|
+
if origin is UnionType:
|
|
405
|
+
origin = typing.Union
|
|
402
406
|
|
|
403
407
|
# Handle plain types (int, str, custom classes, etc.)
|
|
404
408
|
if origin is None:
|
|
@@ -419,7 +423,7 @@ def type_to_ast(typ: Any, cls: type) -> ast.AST:
|
|
|
419
423
|
return ast.Name(id=str(typ))
|
|
420
424
|
|
|
421
425
|
# Get the base type name (List, Dict, Optional, etc.)
|
|
422
|
-
base_name =
|
|
426
|
+
base_name = getattr(origin, "_name", origin.__name__)
|
|
423
427
|
|
|
424
428
|
# Get type arguments
|
|
425
429
|
args = get_args(typ)
|
|
@@ -431,7 +435,7 @@ def type_to_ast(typ: Any, cls: type) -> ast.AST:
|
|
|
431
435
|
# Convert all type arguments recursively
|
|
432
436
|
arg_nodes = [type_to_ast(arg, cls) for arg in args]
|
|
433
437
|
|
|
434
|
-
# Special case for single-argument types (like
|
|
438
|
+
# Special case for single-argument types (like list[T] or Optional[T])
|
|
435
439
|
if len(arg_nodes) == 1:
|
|
436
440
|
slice_value = arg_nodes[0]
|
|
437
441
|
else:
|
|
@@ -525,12 +529,14 @@ def _generate_component_create_functiondef(
|
|
|
525
529
|
]
|
|
526
530
|
|
|
527
531
|
# Create EventType using the joined string
|
|
528
|
-
return ast.Name(
|
|
529
|
-
id=f"Union[{', '.join(map(ast.unparse, all_count_args_type))}]"
|
|
530
|
-
)
|
|
532
|
+
return ast.Name(id=f"{' | '.join(map(ast.unparse, all_count_args_type))}")
|
|
531
533
|
|
|
532
|
-
if isinstance(annotation, str) and annotation.startswith("
|
|
533
|
-
inside_of_tuple =
|
|
534
|
+
if isinstance(annotation, str) and annotation.lower().startswith("tuple["):
|
|
535
|
+
inside_of_tuple = (
|
|
536
|
+
annotation.removeprefix("tuple[")
|
|
537
|
+
.removeprefix("Tuple[")
|
|
538
|
+
.removesuffix("]")
|
|
539
|
+
)
|
|
534
540
|
|
|
535
541
|
if inside_of_tuple == "()":
|
|
536
542
|
return ast.Name(id="EventType[()]")
|
|
@@ -566,9 +572,7 @@ def _generate_component_create_functiondef(
|
|
|
566
572
|
for i in range(len(arguments) + 1)
|
|
567
573
|
]
|
|
568
574
|
|
|
569
|
-
return ast.Name(
|
|
570
|
-
id=f"Union[{', '.join(map(ast.unparse, all_count_args_type))}]"
|
|
571
|
-
)
|
|
575
|
+
return ast.Name(id=f"{' | '.join(map(ast.unparse, all_count_args_type))}")
|
|
572
576
|
return ast.Name(id="EventType[Any]")
|
|
573
577
|
|
|
574
578
|
event_triggers = clz().get_event_triggers()
|
|
@@ -882,6 +886,12 @@ class StubGenerator(ast.NodeTransformer):
|
|
|
882
886
|
call_definition = None
|
|
883
887
|
for child in node.body[:]:
|
|
884
888
|
found_call = False
|
|
889
|
+
if (
|
|
890
|
+
isinstance(child, ast.AnnAssign)
|
|
891
|
+
and isinstance(child.target, ast.Name)
|
|
892
|
+
and child.target.id.startswith("_")
|
|
893
|
+
):
|
|
894
|
+
node.body.remove(child)
|
|
885
895
|
if isinstance(child, ast.Assign):
|
|
886
896
|
for target in child.targets[:]:
|
|
887
897
|
if isinstance(target, ast.Name) and target.id == "__call__":
|
|
@@ -1190,8 +1200,9 @@ class PyiGenerator:
|
|
|
1190
1200
|
self._scan_files_multiprocess(file_targets)
|
|
1191
1201
|
|
|
1192
1202
|
# Fix generated pyi files with ruff.
|
|
1193
|
-
|
|
1194
|
-
|
|
1203
|
+
if self.written_files:
|
|
1204
|
+
subprocess.run(["ruff", "format", *self.written_files])
|
|
1205
|
+
subprocess.run(["ruff", "check", "--fix", *self.written_files])
|
|
1195
1206
|
|
|
1196
1207
|
# For some reason, we need to format the __init__.pyi files again after fixing...
|
|
1197
1208
|
init_files = [f for f in self.written_files if "/__init__.pyi" in f]
|
reflex/utils/serializers.py
CHANGED
|
@@ -5,6 +5,7 @@ from __future__ import annotations
|
|
|
5
5
|
import contextlib
|
|
6
6
|
import dataclasses
|
|
7
7
|
import functools
|
|
8
|
+
import inspect
|
|
8
9
|
import json
|
|
9
10
|
import warnings
|
|
10
11
|
from datetime import date, datetime, time, timedelta
|
|
@@ -13,24 +14,23 @@ from pathlib import Path
|
|
|
13
14
|
from typing import (
|
|
14
15
|
Any,
|
|
15
16
|
Callable,
|
|
16
|
-
List,
|
|
17
17
|
Literal,
|
|
18
|
-
|
|
18
|
+
Sequence,
|
|
19
19
|
Set,
|
|
20
|
-
Tuple,
|
|
21
20
|
Type,
|
|
22
21
|
TypeVar,
|
|
23
22
|
Union,
|
|
24
23
|
get_type_hints,
|
|
25
24
|
overload,
|
|
26
25
|
)
|
|
26
|
+
from uuid import UUID
|
|
27
27
|
|
|
28
28
|
from pydantic import BaseModel as BaseModelV2
|
|
29
29
|
from pydantic.v1 import BaseModel as BaseModelV1
|
|
30
30
|
|
|
31
31
|
from reflex.base import Base
|
|
32
32
|
from reflex.constants.colors import Color, format_color
|
|
33
|
-
from reflex.utils import types
|
|
33
|
+
from reflex.utils import console, types
|
|
34
34
|
|
|
35
35
|
# Mapping from type to a serializer.
|
|
36
36
|
# The serializer should convert the type to a JSON object.
|
|
@@ -50,6 +50,7 @@ SERIALIZED_FUNCTION = TypeVar("SERIALIZED_FUNCTION", bound=Serializer)
|
|
|
50
50
|
def serializer(
|
|
51
51
|
fn: None = None,
|
|
52
52
|
to: Type[SerializedType] | None = None,
|
|
53
|
+
overwrite: bool | None = None,
|
|
53
54
|
) -> Callable[[SERIALIZED_FUNCTION], SERIALIZED_FUNCTION]: ...
|
|
54
55
|
|
|
55
56
|
|
|
@@ -57,18 +58,21 @@ def serializer(
|
|
|
57
58
|
def serializer(
|
|
58
59
|
fn: SERIALIZED_FUNCTION,
|
|
59
60
|
to: Type[SerializedType] | None = None,
|
|
61
|
+
overwrite: bool | None = None,
|
|
60
62
|
) -> SERIALIZED_FUNCTION: ...
|
|
61
63
|
|
|
62
64
|
|
|
63
65
|
def serializer(
|
|
64
66
|
fn: SERIALIZED_FUNCTION | None = None,
|
|
65
67
|
to: Any = None,
|
|
68
|
+
overwrite: bool | None = None,
|
|
66
69
|
) -> SERIALIZED_FUNCTION | Callable[[SERIALIZED_FUNCTION], SERIALIZED_FUNCTION]:
|
|
67
70
|
"""Decorator to add a serializer for a given type.
|
|
68
71
|
|
|
69
72
|
Args:
|
|
70
73
|
fn: The function to decorate.
|
|
71
74
|
to: The type returned by the serializer. If this is `str`, then any Var created from this type will be treated as a string.
|
|
75
|
+
overwrite: Whether to overwrite the existing serializer.
|
|
72
76
|
|
|
73
77
|
Returns:
|
|
74
78
|
The decorated function.
|
|
@@ -88,9 +92,24 @@ def serializer(
|
|
|
88
92
|
|
|
89
93
|
# Make sure the type is not already registered.
|
|
90
94
|
registered_fn = SERIALIZERS.get(type_)
|
|
91
|
-
if registered_fn is not None and registered_fn != fn:
|
|
92
|
-
|
|
93
|
-
|
|
95
|
+
if registered_fn is not None and registered_fn != fn and overwrite is not True:
|
|
96
|
+
message = f"Overwriting serializer for type {type_} from {registered_fn.__module__}:{registered_fn.__qualname__} to {fn.__module__}:{fn.__qualname__}."
|
|
97
|
+
if overwrite is False:
|
|
98
|
+
raise ValueError(message)
|
|
99
|
+
caller_frame = next(
|
|
100
|
+
filter(
|
|
101
|
+
lambda frame: frame.filename != __file__,
|
|
102
|
+
inspect.getouterframes(inspect.currentframe()),
|
|
103
|
+
),
|
|
104
|
+
None,
|
|
105
|
+
)
|
|
106
|
+
file_info = (
|
|
107
|
+
f"(at {caller_frame.filename}:{caller_frame.lineno})"
|
|
108
|
+
if caller_frame
|
|
109
|
+
else ""
|
|
110
|
+
)
|
|
111
|
+
console.warn(
|
|
112
|
+
f"{message} Call rx.serializer with `overwrite=True` if this is intentional. {file_info}"
|
|
94
113
|
)
|
|
95
114
|
|
|
96
115
|
to_type = to or type_hints.get("return")
|
|
@@ -115,22 +134,22 @@ def serializer(
|
|
|
115
134
|
@overload
|
|
116
135
|
def serialize(
|
|
117
136
|
value: Any, get_type: Literal[True]
|
|
118
|
-
) ->
|
|
137
|
+
) -> tuple[SerializedType | None, types.GenericType | None]: ...
|
|
119
138
|
|
|
120
139
|
|
|
121
140
|
@overload
|
|
122
|
-
def serialize(value: Any, get_type: Literal[False]) ->
|
|
141
|
+
def serialize(value: Any, get_type: Literal[False]) -> SerializedType | None: ...
|
|
123
142
|
|
|
124
143
|
|
|
125
144
|
@overload
|
|
126
|
-
def serialize(value: Any) ->
|
|
145
|
+
def serialize(value: Any) -> SerializedType | None: ...
|
|
127
146
|
|
|
128
147
|
|
|
129
148
|
def serialize(
|
|
130
149
|
value: Any, get_type: bool = False
|
|
131
150
|
) -> Union[
|
|
132
|
-
|
|
133
|
-
|
|
151
|
+
SerializedType | None,
|
|
152
|
+
tuple[SerializedType | None, types.GenericType | None],
|
|
134
153
|
]:
|
|
135
154
|
"""Serialize the value to a JSON string.
|
|
136
155
|
|
|
@@ -164,7 +183,7 @@ def serialize(
|
|
|
164
183
|
|
|
165
184
|
|
|
166
185
|
@functools.lru_cache
|
|
167
|
-
def get_serializer(type_: Type) ->
|
|
186
|
+
def get_serializer(type_: Type) -> Serializer | None:
|
|
168
187
|
"""Get the serializer for the type.
|
|
169
188
|
|
|
170
189
|
Args:
|
|
@@ -188,7 +207,7 @@ def get_serializer(type_: Type) -> Optional[Serializer]:
|
|
|
188
207
|
|
|
189
208
|
|
|
190
209
|
@functools.lru_cache
|
|
191
|
-
def get_serializer_type(type_: Type) ->
|
|
210
|
+
def get_serializer_type(type_: Type) -> Type | None:
|
|
192
211
|
"""Get the converted type for the type after serializing.
|
|
193
212
|
|
|
194
213
|
Args:
|
|
@@ -315,6 +334,19 @@ def serialize_set(value: Set) -> list:
|
|
|
315
334
|
return list(value)
|
|
316
335
|
|
|
317
336
|
|
|
337
|
+
@serializer
|
|
338
|
+
def serialize_sequence(value: Sequence) -> list:
|
|
339
|
+
"""Serialize a sequence to a JSON serializable list.
|
|
340
|
+
|
|
341
|
+
Args:
|
|
342
|
+
value: The sequence to serialize.
|
|
343
|
+
|
|
344
|
+
Returns:
|
|
345
|
+
The serialized list.
|
|
346
|
+
"""
|
|
347
|
+
return list(value)
|
|
348
|
+
|
|
349
|
+
|
|
318
350
|
@serializer(to=str)
|
|
319
351
|
def serialize_datetime(dt: Union[date, datetime, time, timedelta]) -> str:
|
|
320
352
|
"""Serialize a datetime to a JSON string.
|
|
@@ -354,6 +386,19 @@ def serialize_enum(en: Enum) -> str:
|
|
|
354
386
|
return en.value
|
|
355
387
|
|
|
356
388
|
|
|
389
|
+
@serializer(to=str)
|
|
390
|
+
def serialize_uuid(uuid: UUID) -> str:
|
|
391
|
+
"""Serialize a UUID to a JSON string.
|
|
392
|
+
|
|
393
|
+
Args:
|
|
394
|
+
uuid: The UUID to serialize.
|
|
395
|
+
|
|
396
|
+
Returns:
|
|
397
|
+
The serialized UUID.
|
|
398
|
+
"""
|
|
399
|
+
return str(uuid)
|
|
400
|
+
|
|
401
|
+
|
|
357
402
|
@serializer(to=str)
|
|
358
403
|
def serialize_color(color: Color) -> str:
|
|
359
404
|
"""Serialize a color.
|
|
@@ -370,7 +415,7 @@ def serialize_color(color: Color) -> str:
|
|
|
370
415
|
with contextlib.suppress(ImportError):
|
|
371
416
|
from pandas import DataFrame
|
|
372
417
|
|
|
373
|
-
def format_dataframe_values(df: DataFrame) ->
|
|
418
|
+
def format_dataframe_values(df: DataFrame) -> list[list[Any]]:
|
|
374
419
|
"""Format dataframe values to a list of lists.
|
|
375
420
|
|
|
376
421
|
Args:
|