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.

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