reflex 0.7.1a4__py3-none-any.whl → 0.7.2a2__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.

Files changed (227) hide show
  1. reflex/.templates/jinja/web/utils/context.js.jinja2 +8 -8
  2. reflex/.templates/web/components/reflex/radix_themes_color_mode_provider.js +3 -3
  3. reflex/.templates/web/utils/state.js +18 -18
  4. reflex/admin.py +1 -2
  5. reflex/app.py +46 -49
  6. reflex/app_mixins/lifespan.py +2 -2
  7. reflex/app_mixins/middleware.py +1 -2
  8. reflex/assets.py +1 -2
  9. reflex/base.py +2 -2
  10. reflex/compiler/compiler.py +51 -16
  11. reflex/compiler/utils.py +4 -13
  12. reflex/components/base/app_wrap.pyi +7 -7
  13. reflex/components/base/bare.py +3 -3
  14. reflex/components/base/body.pyi +7 -7
  15. reflex/components/base/document.py +1 -3
  16. reflex/components/base/document.pyi +32 -32
  17. reflex/components/base/error_boundary.py +2 -4
  18. reflex/components/base/error_boundary.pyi +11 -13
  19. reflex/components/base/fragment.pyi +7 -7
  20. reflex/components/base/head.pyi +13 -13
  21. reflex/components/base/link.pyi +22 -22
  22. reflex/components/base/meta.py +5 -7
  23. reflex/components/base/meta.pyi +40 -40
  24. reflex/components/base/script.pyi +11 -14
  25. reflex/components/base/strict_mode.pyi +7 -7
  26. reflex/components/component.py +188 -113
  27. reflex/components/core/auto_scroll.py +8 -1
  28. reflex/components/core/auto_scroll.pyi +183 -210
  29. reflex/components/core/banner.py +2 -4
  30. reflex/components/core/banner.pyi +390 -444
  31. reflex/components/core/breakpoints.py +5 -5
  32. reflex/components/core/client_side_routing.pyi +14 -14
  33. reflex/components/core/clipboard.py +4 -4
  34. reflex/components/core/clipboard.pyi +12 -14
  35. reflex/components/core/cond.py +17 -25
  36. reflex/components/core/debounce.py +3 -3
  37. reflex/components/core/debounce.pyi +14 -14
  38. reflex/components/core/foreach.py +7 -2
  39. reflex/components/core/html.py +1 -3
  40. reflex/components/core/html.pyi +184 -213
  41. reflex/components/core/match.py +15 -19
  42. reflex/components/core/sticky.pyi +930 -1078
  43. reflex/components/core/upload.py +4 -4
  44. reflex/components/core/upload.pyi +62 -62
  45. reflex/components/datadisplay/code.py +6 -6
  46. reflex/components/datadisplay/code.pyi +1159 -1165
  47. reflex/components/datadisplay/dataeditor.py +49 -49
  48. reflex/components/datadisplay/dataeditor.pyi +95 -123
  49. reflex/components/datadisplay/logo.py +1 -3
  50. reflex/components/datadisplay/shiki_code_block.py +8 -10
  51. reflex/components/datadisplay/shiki_code_block.pyi +1678 -1720
  52. reflex/components/el/element.pyi +7 -7
  53. reflex/components/el/elements/base.pyi +183 -210
  54. reflex/components/el/elements/forms.py +24 -24
  55. reflex/components/el/elements/forms.pyi +2572 -2934
  56. reflex/components/el/elements/inline.py +4 -4
  57. reflex/components/el/elements/inline.pyi +5191 -5953
  58. reflex/components/el/elements/media.py +47 -47
  59. reflex/components/el/elements/media.pyi +4802 -5500
  60. reflex/components/el/elements/metadata.py +1 -3
  61. reflex/components/el/elements/metadata.pyi +782 -896
  62. reflex/components/el/elements/other.pyi +1278 -1467
  63. reflex/components/el/elements/scripts.pyi +580 -667
  64. reflex/components/el/elements/sectioning.pyi +2761 -3166
  65. reflex/components/el/elements/tables.pyi +1840 -2119
  66. reflex/components/el/elements/typography.pyi +2772 -3179
  67. reflex/components/gridjs/datatable.py +7 -7
  68. reflex/components/gridjs/datatable.pyi +19 -19
  69. reflex/components/lucide/icon.pyi +21 -21
  70. reflex/components/markdown/markdown.py +2 -2
  71. reflex/components/markdown/markdown.pyi +9 -9
  72. reflex/components/moment/moment.py +11 -12
  73. reflex/components/moment/moment.pyi +44 -47
  74. reflex/components/next/base.pyi +7 -7
  75. reflex/components/next/image.py +3 -3
  76. reflex/components/next/image.pyi +19 -21
  77. reflex/components/next/link.pyi +9 -9
  78. reflex/components/next/video.py +1 -3
  79. reflex/components/next/video.pyi +9 -9
  80. reflex/components/plotly/plotly.py +22 -45
  81. reflex/components/plotly/plotly.pyi +164 -164
  82. reflex/components/radix/primitives/accordion.py +14 -14
  83. reflex/components/radix/primitives/accordion.pyi +439 -487
  84. reflex/components/radix/primitives/base.py +1 -3
  85. reflex/components/radix/primitives/base.pyi +15 -15
  86. reflex/components/radix/primitives/drawer.py +3 -3
  87. reflex/components/radix/primitives/drawer.pyi +110 -116
  88. reflex/components/radix/primitives/form.py +1 -1
  89. reflex/components/radix/primitives/form.pyi +668 -752
  90. reflex/components/radix/primitives/progress.py +6 -6
  91. reflex/components/radix/primitives/progress.pyi +225 -243
  92. reflex/components/radix/primitives/slider.py +6 -6
  93. reflex/components/radix/primitives/slider.pyi +52 -55
  94. reflex/components/radix/themes/base.py +3 -6
  95. reflex/components/radix/themes/base.pyi +197 -303
  96. reflex/components/radix/themes/color_mode.py +5 -5
  97. reflex/components/radix/themes/color_mode.pyi +366 -436
  98. reflex/components/radix/themes/components/alert_dialog.pyi +229 -262
  99. reflex/components/radix/themes/components/aspect_ratio.py +1 -3
  100. reflex/components/radix/themes/components/aspect_ratio.pyi +8 -8
  101. reflex/components/radix/themes/components/avatar.pyi +79 -94
  102. reflex/components/radix/themes/components/badge.pyi +252 -295
  103. reflex/components/radix/themes/components/button.pyi +269 -314
  104. reflex/components/radix/themes/components/callout.py +2 -2
  105. reflex/components/radix/themes/components/callout.pyi +1116 -1290
  106. reflex/components/radix/themes/components/card.pyi +194 -229
  107. reflex/components/radix/themes/components/checkbox.pyi +243 -278
  108. reflex/components/radix/themes/components/checkbox_cards.py +3 -7
  109. reflex/components/radix/themes/components/checkbox_cards.pyi +101 -135
  110. reflex/components/radix/themes/components/checkbox_group.py +2 -2
  111. reflex/components/radix/themes/components/checkbox_group.pyi +83 -96
  112. reflex/components/radix/themes/components/context_menu.py +18 -15
  113. reflex/components/radix/themes/components/context_menu.pyi +408 -458
  114. reflex/components/radix/themes/components/data_list.pyi +122 -147
  115. reflex/components/radix/themes/components/dialog.pyi +231 -264
  116. reflex/components/radix/themes/components/dropdown_menu.py +16 -13
  117. reflex/components/radix/themes/components/dropdown_menu.pyi +223 -246
  118. reflex/components/radix/themes/components/hover_card.py +2 -2
  119. reflex/components/radix/themes/components/hover_card.pyi +237 -282
  120. reflex/components/radix/themes/components/icon_button.pyi +269 -314
  121. reflex/components/radix/themes/components/inset.py +8 -8
  122. reflex/components/radix/themes/components/inset.pyi +232 -292
  123. reflex/components/radix/themes/components/popover.py +2 -2
  124. reflex/components/radix/themes/components/popover.pyi +229 -271
  125. reflex/components/radix/themes/components/progress.pyi +80 -96
  126. reflex/components/radix/themes/components/radio.pyi +73 -86
  127. reflex/components/radix/themes/components/radio_cards.py +4 -8
  128. reflex/components/radix/themes/components/radio_cards.pyi +117 -154
  129. reflex/components/radix/themes/components/radio_group.py +3 -3
  130. reflex/components/radix/themes/components/radio_group.pyi +250 -291
  131. reflex/components/radix/themes/components/scroll_area.pyi +14 -20
  132. reflex/components/radix/themes/components/segmented_control.py +6 -6
  133. reflex/components/radix/themes/components/segmented_control.pyi +89 -108
  134. reflex/components/radix/themes/components/select.py +7 -7
  135. reflex/components/radix/themes/components/select.pyi +376 -444
  136. reflex/components/radix/themes/components/separator.pyi +79 -93
  137. reflex/components/radix/themes/components/skeleton.pyi +32 -26
  138. reflex/components/radix/themes/components/slider.py +8 -8
  139. reflex/components/radix/themes/components/slider.pyi +99 -122
  140. reflex/components/radix/themes/components/spinner.pyi +12 -19
  141. reflex/components/radix/themes/components/switch.pyi +84 -99
  142. reflex/components/radix/themes/components/table.py +9 -9
  143. reflex/components/radix/themes/components/table.pyi +1440 -1794
  144. reflex/components/radix/themes/components/tabs.py +4 -4
  145. reflex/components/radix/themes/components/tabs.pyi +120 -132
  146. reflex/components/radix/themes/components/text_area.pyi +281 -331
  147. reflex/components/radix/themes/components/text_field.py +2 -2
  148. reflex/components/radix/themes/components/text_field.pyi +639 -734
  149. reflex/components/radix/themes/components/tooltip.py +6 -6
  150. reflex/components/radix/themes/components/tooltip.pyi +34 -43
  151. reflex/components/radix/themes/layout/base.pyi +85 -182
  152. reflex/components/radix/themes/layout/box.pyi +183 -210
  153. reflex/components/radix/themes/layout/center.pyi +225 -286
  154. reflex/components/radix/themes/layout/container.pyi +191 -224
  155. reflex/components/radix/themes/layout/flex.py +2 -2
  156. reflex/components/radix/themes/layout/flex.pyi +225 -286
  157. reflex/components/radix/themes/layout/grid.py +2 -2
  158. reflex/components/radix/themes/layout/grid.pyi +245 -315
  159. reflex/components/radix/themes/layout/list.py +2 -2
  160. reflex/components/radix/themes/layout/list.pyi +712 -815
  161. reflex/components/radix/themes/layout/section.pyi +187 -221
  162. reflex/components/radix/themes/layout/spacer.pyi +225 -286
  163. reflex/components/radix/themes/layout/stack.pyi +625 -768
  164. reflex/components/radix/themes/typography/blockquote.pyi +257 -299
  165. reflex/components/radix/themes/typography/code.pyi +259 -304
  166. reflex/components/radix/themes/typography/heading.pyi +272 -324
  167. reflex/components/radix/themes/typography/link.pyi +302 -358
  168. reflex/components/radix/themes/typography/text.pyi +1669 -1945
  169. reflex/components/react_player/audio.pyi +20 -22
  170. reflex/components/react_player/react_player.pyi +19 -19
  171. reflex/components/react_player/video.pyi +20 -22
  172. reflex/components/recharts/cartesian.py +100 -97
  173. reflex/components/recharts/cartesian.pyi +891 -1007
  174. reflex/components/recharts/charts.py +42 -42
  175. reflex/components/recharts/charts.pyi +212 -249
  176. reflex/components/recharts/general.py +22 -21
  177. reflex/components/recharts/general.pyi +198 -223
  178. reflex/components/recharts/polar.py +42 -45
  179. reflex/components/recharts/polar.pyi +254 -288
  180. reflex/components/recharts/recharts.pyi +13 -13
  181. reflex/components/sonner/toast.py +20 -20
  182. reflex/components/sonner/toast.pyi +58 -61
  183. reflex/components/suneditor/editor.py +9 -9
  184. reflex/components/suneditor/editor.pyi +78 -83
  185. reflex/components/tags/cond_tag.py +2 -2
  186. reflex/components/tags/iter_tag.py +10 -14
  187. reflex/components/tags/match_tag.py +2 -2
  188. reflex/components/tags/tag.py +10 -10
  189. reflex/config.py +36 -35
  190. reflex/constants/__init__.py +56 -53
  191. reflex/custom_components/custom_components.py +6 -7
  192. reflex/event.py +38 -42
  193. reflex/experimental/client_state.py +2 -4
  194. reflex/experimental/layout.py +2 -2
  195. reflex/experimental/layout.pyi +579 -663
  196. reflex/istate/data.py +4 -5
  197. reflex/middleware/hydrate_middleware.py +2 -2
  198. reflex/middleware/middleware.py +2 -2
  199. reflex/model.py +3 -5
  200. reflex/page.py +2 -2
  201. reflex/reflex.py +9 -10
  202. reflex/state.py +77 -49
  203. reflex/style.py +9 -3
  204. reflex/testing.py +21 -24
  205. reflex/utils/console.py +1 -1
  206. reflex/utils/decorator.py +26 -1
  207. reflex/utils/exec.py +6 -11
  208. reflex/utils/export.py +2 -3
  209. reflex/utils/format.py +4 -4
  210. reflex/utils/imports.py +12 -12
  211. reflex/utils/prerequisites.py +35 -84
  212. reflex/utils/processes.py +5 -5
  213. reflex/utils/pyi_generator.py +33 -22
  214. reflex/utils/serializers.py +60 -15
  215. reflex/utils/types.py +237 -56
  216. reflex/vars/base.py +122 -72
  217. reflex/vars/datetime.py +2 -2
  218. reflex/vars/function.py +52 -55
  219. reflex/vars/number.py +59 -5
  220. reflex/vars/object.py +57 -26
  221. reflex/vars/sequence.py +983 -958
  222. {reflex-0.7.1a4.dist-info → reflex-0.7.2a2.dist-info}/METADATA +3 -6
  223. reflex-0.7.2a2.dist-info/RECORD +405 -0
  224. {reflex-0.7.1a4.dist-info → reflex-0.7.2a2.dist-info}/WHEEL +1 -1
  225. reflex-0.7.1a4.dist-info/RECORD +0 -405
  226. {reflex-0.7.1a4.dist-info → reflex-0.7.2a2.dist-info}/LICENSE +0 -0
  227. {reflex-0.7.1a4.dist-info → reflex-0.7.2a2.dist-info}/entry_points.txt +0 -0
@@ -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"Optional[{res_args[0]}]"
149
+ return f"{res_args[0]} | None"
148
150
  else:
149
- res = f"Union[{', '.join(res_args)}]"
150
- return f"Optional[{res}]"
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"Union[{', '.join(res_args)}]"
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 = ", ".join(sorted(types))
196
- res = f"Union[{res}]"
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"Union[{', '.join(res)}]"
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"Optional[{res}]"
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 = origin._name if hasattr(origin, "_name") else origin.__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 List[T] or Optional[T])
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("Tuple["):
533
- inside_of_tuple = annotation.removeprefix("Tuple[").removesuffix("]")
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
- subprocess.run(["ruff", "format", *self.written_files])
1194
- subprocess.run(["ruff", "check", "--fix", *self.written_files])
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]
@@ -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
- Optional,
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
- raise ValueError(
93
- f"Serializer for type {type_} is already registered as {registered_fn.__qualname__}."
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
- ) -> Tuple[Optional[SerializedType], Optional[types.GenericType]]: ...
137
+ ) -> tuple[SerializedType | None, types.GenericType | None]: ...
119
138
 
120
139
 
121
140
  @overload
122
- def serialize(value: Any, get_type: Literal[False]) -> Optional[SerializedType]: ...
141
+ def serialize(value: Any, get_type: Literal[False]) -> SerializedType | None: ...
123
142
 
124
143
 
125
144
  @overload
126
- def serialize(value: Any) -> Optional[SerializedType]: ...
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
- Optional[SerializedType],
133
- Tuple[Optional[SerializedType], Optional[types.GenericType]],
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) -> Optional[Serializer]:
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) -> Optional[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) -> List[List[Any]]:
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: