reflex 0.6.0__py3-none-any.whl → 0.6.0a1__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 (253) hide show
  1. reflex/.templates/jinja/custom_components/pyproject.toml.jinja2 +2 -2
  2. reflex/.templates/jinja/web/pages/_app.js.jinja2 +1 -1
  3. reflex/.templates/jinja/web/pages/utils.js.jinja2 +2 -2
  4. reflex/.templates/web/components/reflex/chakra_color_mode_provider.js +36 -0
  5. reflex/.templates/web/utils/state.js +1 -3
  6. reflex/__init__.py +2 -8
  7. reflex/__init__.pyi +1 -2
  8. reflex/app.py +2 -4
  9. reflex/app_module_for_backend.py +1 -1
  10. reflex/base.py +1 -1
  11. reflex/compiler/compiler.py +2 -2
  12. reflex/compiler/utils.py +3 -3
  13. reflex/components/base/app_wrap.py +2 -2
  14. reflex/components/base/app_wrap.pyi +27 -17
  15. reflex/components/base/bare.py +5 -4
  16. reflex/components/base/body.pyi +27 -17
  17. reflex/components/base/document.pyi +131 -81
  18. reflex/components/base/error_boundary.py +7 -6
  19. reflex/components/base/error_boundary.pyi +33 -20
  20. reflex/components/base/fragment.pyi +27 -17
  21. reflex/components/base/head.pyi +53 -33
  22. reflex/components/base/link.py +1 -1
  23. reflex/components/base/link.pyi +54 -33
  24. reflex/components/base/meta.pyi +105 -65
  25. reflex/components/base/script.py +2 -1
  26. reflex/components/base/script.pyi +38 -21
  27. reflex/components/component.py +47 -53
  28. reflex/components/core/banner.py +27 -23
  29. reflex/components/core/banner.pyi +171 -134
  30. reflex/components/core/client_side_routing.py +3 -2
  31. reflex/components/core/client_side_routing.pyi +54 -33
  32. reflex/components/core/clipboard.py +1 -2
  33. reflex/components/core/clipboard.pyi +33 -20
  34. reflex/components/core/cond.py +5 -5
  35. reflex/components/core/debounce.py +5 -5
  36. reflex/components/core/debounce.pyi +33 -20
  37. reflex/components/core/foreach.py +4 -3
  38. reflex/components/core/html.py +1 -1
  39. reflex/components/core/html.pyi +46 -35
  40. reflex/components/core/match.py +17 -17
  41. reflex/components/core/upload.py +23 -17
  42. reflex/components/core/upload.pyi +124 -78
  43. reflex/components/datadisplay/code.py +10 -9
  44. reflex/components/datadisplay/code.pyi +409 -299
  45. reflex/components/datadisplay/dataeditor.py +10 -8
  46. reflex/components/datadisplay/dataeditor.pyi +53 -40
  47. reflex/components/el/element.pyi +27 -17
  48. reflex/components/el/elements/base.py +1 -1
  49. reflex/components/el/elements/base.pyi +45 -34
  50. reflex/components/el/elements/forms.py +16 -16
  51. reflex/components/el/elements/forms.pyi +707 -554
  52. reflex/components/el/elements/inline.py +1 -1
  53. reflex/components/el/elements/inline.pyi +1218 -937
  54. reflex/components/el/elements/media.py +1 -1
  55. reflex/components/el/elements/media.pyi +997 -786
  56. reflex/components/el/elements/metadata.py +6 -3
  57. reflex/components/el/elements/metadata.pyi +242 -181
  58. reflex/components/el/elements/other.py +1 -1
  59. reflex/components/el/elements/other.pyi +306 -235
  60. reflex/components/el/elements/scripts.py +1 -1
  61. reflex/components/el/elements/scripts.pyi +140 -109
  62. reflex/components/el/elements/sectioning.py +2 -0
  63. reflex/components/el/elements/sectioning.pyi +647 -496
  64. reflex/components/el/elements/tables.py +1 -1
  65. reflex/components/el/elements/tables.pyi +452 -351
  66. reflex/components/el/elements/typography.py +1 -1
  67. reflex/components/el/elements/typography.pyi +657 -506
  68. reflex/components/gridjs/datatable.py +9 -6
  69. reflex/components/gridjs/datatable.pyi +56 -35
  70. reflex/components/lucide/icon.py +1 -1
  71. reflex/components/lucide/icon.pyi +54 -33
  72. reflex/components/markdown/markdown.py +31 -26
  73. reflex/components/markdown/markdown.pyi +37 -27
  74. reflex/components/moment/moment.py +12 -13
  75. reflex/components/moment/moment.pyi +35 -23
  76. reflex/components/next/base.pyi +27 -17
  77. reflex/components/next/image.py +1 -1
  78. reflex/components/next/image.pyi +37 -22
  79. reflex/components/next/link.py +1 -1
  80. reflex/components/next/link.pyi +28 -17
  81. reflex/components/next/video.py +1 -1
  82. reflex/components/next/video.pyi +28 -17
  83. reflex/components/plotly/plotly.py +13 -12
  84. reflex/components/plotly/plotly.pyi +54 -39
  85. reflex/components/props.py +1 -1
  86. reflex/components/radix/__init__.pyi +0 -1
  87. reflex/components/radix/primitives/__init__.pyi +0 -1
  88. reflex/components/radix/primitives/accordion.py +4 -4
  89. reflex/components/radix/primitives/accordion.pyi +495 -424
  90. reflex/components/radix/primitives/base.py +1 -1
  91. reflex/components/radix/primitives/base.pyi +54 -33
  92. reflex/components/radix/primitives/drawer.py +1 -1
  93. reflex/components/radix/primitives/drawer.pyi +273 -172
  94. reflex/components/radix/primitives/form.py +1 -1
  95. reflex/components/radix/primitives/form.pyi +364 -257
  96. reflex/components/radix/primitives/progress.py +1 -1
  97. reflex/components/radix/primitives/progress.pyi +282 -231
  98. reflex/components/radix/primitives/slider.py +1 -1
  99. reflex/components/radix/primitives/slider.pyi +138 -87
  100. reflex/components/radix/themes/base.py +24 -3
  101. reflex/components/radix/themes/base.pyi +250 -178
  102. reflex/components/radix/themes/color_mode.py +5 -5
  103. reflex/components/radix/themes/color_mode.pyi +220 -187
  104. reflex/components/radix/themes/components/alert_dialog.py +1 -1
  105. reflex/components/radix/themes/components/alert_dialog.pyi +207 -136
  106. reflex/components/radix/themes/components/aspect_ratio.py +1 -1
  107. reflex/components/radix/themes/components/aspect_ratio.pyi +28 -17
  108. reflex/components/radix/themes/components/avatar.py +1 -1
  109. reflex/components/radix/themes/components/avatar.pyi +81 -70
  110. reflex/components/radix/themes/components/badge.py +1 -1
  111. reflex/components/radix/themes/components/badge.pyi +99 -88
  112. reflex/components/radix/themes/components/button.py +1 -1
  113. reflex/components/radix/themes/components/button.pyi +109 -98
  114. reflex/components/radix/themes/components/callout.py +1 -1
  115. reflex/components/radix/themes/components/callout.pyi +373 -322
  116. reflex/components/radix/themes/components/card.py +1 -1
  117. reflex/components/radix/themes/components/card.pyi +49 -38
  118. reflex/components/radix/themes/components/checkbox.py +2 -1
  119. reflex/components/radix/themes/components/checkbox.pyi +245 -208
  120. reflex/components/radix/themes/components/checkbox_cards.py +1 -1
  121. reflex/components/radix/themes/components/checkbox_cards.pyi +115 -94
  122. reflex/components/radix/themes/components/checkbox_group.py +1 -1
  123. reflex/components/radix/themes/components/checkbox_group.pyi +107 -86
  124. reflex/components/radix/themes/components/context_menu.py +1 -1
  125. reflex/components/radix/themes/components/context_menu.pyi +319 -238
  126. reflex/components/radix/themes/components/data_list.py +1 -1
  127. reflex/components/radix/themes/components/data_list.pyi +171 -130
  128. reflex/components/radix/themes/components/dialog.py +1 -1
  129. reflex/components/radix/themes/components/dialog.pyi +210 -139
  130. reflex/components/radix/themes/components/dropdown_menu.py +1 -1
  131. reflex/components/radix/themes/components/dropdown_menu.pyi +332 -249
  132. reflex/components/radix/themes/components/hover_card.py +1 -1
  133. reflex/components/radix/themes/components/hover_card.pyi +131 -90
  134. reflex/components/radix/themes/components/icon_button.py +3 -2
  135. reflex/components/radix/themes/components/icon_button.pyi +109 -98
  136. reflex/components/radix/themes/components/inset.py +1 -1
  137. reflex/components/radix/themes/components/inset.pyi +58 -47
  138. reflex/components/radix/themes/components/popover.py +1 -1
  139. reflex/components/radix/themes/components/popover.pyi +136 -95
  140. reflex/components/radix/themes/components/progress.py +1 -1
  141. reflex/components/radix/themes/components/progress.pyi +82 -71
  142. reflex/components/radix/themes/components/radio.py +1 -1
  143. reflex/components/radix/themes/components/radio.pyi +80 -69
  144. reflex/components/radix/themes/components/radio_cards.py +1 -1
  145. reflex/components/radix/themes/components/radio_cards.pyi +119 -98
  146. reflex/components/radix/themes/components/radio_group.py +11 -8
  147. reflex/components/radix/themes/components/radio_group.pyi +271 -228
  148. reflex/components/radix/themes/components/scroll_area.py +1 -1
  149. reflex/components/radix/themes/components/scroll_area.pyi +32 -21
  150. reflex/components/radix/themes/components/segmented_control.py +1 -1
  151. reflex/components/radix/themes/components/segmented_control.pyi +113 -90
  152. reflex/components/radix/themes/components/select.py +3 -2
  153. reflex/components/radix/themes/components/select.pyi +471 -374
  154. reflex/components/radix/themes/components/separator.py +2 -1
  155. reflex/components/radix/themes/components/separator.pyi +80 -69
  156. reflex/components/radix/themes/components/skeleton.py +1 -1
  157. reflex/components/radix/themes/components/skeleton.pyi +34 -23
  158. reflex/components/radix/themes/components/slider.py +3 -2
  159. reflex/components/radix/themes/components/slider.pyi +88 -75
  160. reflex/components/radix/themes/components/spinner.py +1 -1
  161. reflex/components/radix/themes/components/spinner.pyi +30 -19
  162. reflex/components/radix/themes/components/switch.py +1 -1
  163. reflex/components/radix/themes/components/switch.pyi +84 -71
  164. reflex/components/radix/themes/components/table.py +1 -1
  165. reflex/components/radix/themes/components/table.pyi +332 -261
  166. reflex/components/radix/themes/components/tabs.py +1 -1
  167. reflex/components/radix/themes/components/tabs.pyi +194 -139
  168. reflex/components/radix/themes/components/text_area.py +1 -1
  169. reflex/components/radix/themes/components/text_area.pyi +111 -96
  170. reflex/components/radix/themes/components/text_field.py +1 -1
  171. reflex/components/radix/themes/components/text_field.pyi +286 -247
  172. reflex/components/radix/themes/components/tooltip.py +1 -1
  173. reflex/components/radix/themes/components/tooltip.pyi +37 -26
  174. reflex/components/radix/themes/layout/__init__.pyi +0 -1
  175. reflex/components/radix/themes/layout/base.py +1 -1
  176. reflex/components/radix/themes/layout/base.pyi +67 -56
  177. reflex/components/radix/themes/layout/box.pyi +45 -34
  178. reflex/components/radix/themes/layout/center.pyi +67 -56
  179. reflex/components/radix/themes/layout/container.py +2 -1
  180. reflex/components/radix/themes/layout/container.pyi +47 -36
  181. reflex/components/radix/themes/layout/flex.py +1 -1
  182. reflex/components/radix/themes/layout/flex.pyi +67 -56
  183. reflex/components/radix/themes/layout/grid.py +1 -1
  184. reflex/components/radix/themes/layout/grid.pyi +75 -64
  185. reflex/components/radix/themes/layout/list.py +6 -5
  186. reflex/components/radix/themes/layout/list.pyi +244 -193
  187. reflex/components/radix/themes/layout/section.py +2 -1
  188. reflex/components/radix/themes/layout/section.pyi +47 -36
  189. reflex/components/radix/themes/layout/spacer.pyi +67 -56
  190. reflex/components/radix/themes/layout/stack.py +1 -1
  191. reflex/components/radix/themes/layout/stack.pyi +159 -128
  192. reflex/components/radix/themes/typography/blockquote.py +1 -1
  193. reflex/components/radix/themes/typography/blockquote.pyi +100 -89
  194. reflex/components/radix/themes/typography/code.py +1 -1
  195. reflex/components/radix/themes/typography/code.pyi +101 -90
  196. reflex/components/radix/themes/typography/heading.py +1 -1
  197. reflex/components/radix/themes/typography/heading.pyi +107 -96
  198. reflex/components/radix/themes/typography/link.py +1 -1
  199. reflex/components/radix/themes/typography/link.pyi +113 -102
  200. reflex/components/radix/themes/typography/text.py +1 -1
  201. reflex/components/radix/themes/typography/text.pyi +572 -501
  202. reflex/components/react_player/audio.pyi +60 -33
  203. reflex/components/react_player/react_player.py +1 -1
  204. reflex/components/react_player/react_player.pyi +60 -33
  205. reflex/components/react_player/video.pyi +60 -33
  206. reflex/components/recharts/cartesian.py +3 -2
  207. reflex/components/recharts/cartesian.pyi +861 -678
  208. reflex/components/recharts/charts.py +5 -4
  209. reflex/components/recharts/charts.pyi +357 -252
  210. reflex/components/recharts/general.py +2 -1
  211. reflex/components/recharts/general.pyi +231 -180
  212. reflex/components/recharts/polar.py +5 -4
  213. reflex/components/recharts/polar.pyi +181 -144
  214. reflex/components/recharts/recharts.pyi +53 -33
  215. reflex/components/sonner/toast.py +17 -16
  216. reflex/components/sonner/toast.pyi +47 -36
  217. reflex/components/suneditor/editor.py +3 -2
  218. reflex/components/suneditor/editor.pyi +78 -55
  219. reflex/components/tags/cond_tag.py +4 -6
  220. reflex/components/tags/iter_tag.py +16 -28
  221. reflex/components/tags/match_tag.py +4 -6
  222. reflex/components/tags/tag.py +23 -40
  223. reflex/custom_components/custom_components.py +1 -3
  224. reflex/event.py +65 -113
  225. reflex/experimental/client_state.py +24 -25
  226. reflex/experimental/hooks.py +16 -16
  227. reflex/experimental/layout.py +5 -5
  228. reflex/experimental/layout.pyi +187 -136
  229. reflex/{vars → ivars}/__init__.py +2 -6
  230. reflex/{vars → ivars}/base.py +216 -599
  231. reflex/{vars → ivars}/function.py +19 -15
  232. reflex/{vars → ivars}/number.py +20 -41
  233. reflex/{vars → ivars}/object.py +30 -28
  234. reflex/{vars → ivars}/sequence.py +50 -53
  235. reflex/middleware/hydrate_middleware.py +0 -2
  236. reflex/middleware/middleware.py +3 -3
  237. reflex/state.py +82 -148
  238. reflex/style.py +22 -21
  239. reflex/utils/exceptions.py +0 -20
  240. reflex/utils/format.py +34 -54
  241. reflex/utils/imports.py +73 -16
  242. reflex/utils/prerequisites.py +15 -35
  243. reflex/utils/pyi_generator.py +8 -13
  244. reflex/utils/serializers.py +22 -12
  245. reflex/utils/telemetry.py +2 -3
  246. reflex/utils/types.py +5 -10
  247. reflex/vars.py +501 -0
  248. {reflex-0.6.0.dist-info → reflex-0.6.0a1.dist-info}/METADATA +5 -4
  249. reflex-0.6.0a1.dist-info/RECORD +384 -0
  250. reflex-0.6.0.dist-info/RECORD +0 -382
  251. {reflex-0.6.0.dist-info → reflex-0.6.0a1.dist-info}/LICENSE +0 -0
  252. {reflex-0.6.0.dist-info → reflex-0.6.0a1.dist-info}/WHEEL +0 -0
  253. {reflex-0.6.0.dist-info → reflex-0.6.0a1.dist-info}/entry_points.txt +0 -0
reflex/utils/format.py CHANGED
@@ -10,7 +10,7 @@ from typing import TYPE_CHECKING, Any, Callable, List, Optional, Union
10
10
 
11
11
  from reflex import constants
12
12
  from reflex.utils import exceptions, types
13
- from reflex.utils.console import deprecate
13
+ from reflex.vars import Var
14
14
 
15
15
  if TYPE_CHECKING:
16
16
  from reflex.components.component import ComponentStyle
@@ -298,9 +298,9 @@ def format_route(route: str, format_case=True) -> str:
298
298
 
299
299
 
300
300
  def format_match(
301
- cond: str | Var,
302
- match_cases: List[List[Var]],
303
- default: Var,
301
+ cond: str | ImmutableVar,
302
+ match_cases: List[List[ImmutableVar]],
303
+ default: ImmutableVar,
304
304
  ) -> str:
305
305
  """Format a match expression whose return type is a Var.
306
306
 
@@ -332,7 +332,7 @@ def format_match(
332
332
 
333
333
 
334
334
  def format_prop(
335
- prop: Union[Var, EventChain, ComponentStyle, str],
335
+ prop: Union[ImmutableVar, EventChain, ComponentStyle, str],
336
336
  ) -> Union[int, float, str]:
337
337
  """Format a prop.
338
338
 
@@ -348,12 +348,12 @@ def format_prop(
348
348
  """
349
349
  # import here to avoid circular import.
350
350
  from reflex.event import EventChain
351
+ from reflex.ivars import ImmutableVar
351
352
  from reflex.utils import serializers
352
- from reflex.vars import Var
353
353
 
354
354
  try:
355
355
  # Handle var props.
356
- if isinstance(prop, Var):
356
+ if isinstance(prop, ImmutableVar):
357
357
  return str(prop)
358
358
 
359
359
  # Handle event props.
@@ -406,15 +406,26 @@ def format_props(*single_props, **key_value_props) -> list[str]:
406
406
  The formatted props list.
407
407
  """
408
408
  # Format all the props.
409
- from reflex.vars.base import LiteralVar, Var
409
+ from reflex.ivars.base import ImmutableVar, LiteralVar
410
410
 
411
411
  return [
412
412
  (
413
- f"{name}={{{format_prop(prop if isinstance(prop, Var) else LiteralVar.create(prop))}}}"
413
+ f"{name}={format_prop(prop)}"
414
+ if isinstance(prop, ImmutableVar) and not isinstance(prop, ImmutableVar)
415
+ else (
416
+ f"{name}={{{format_prop(prop if isinstance(prop, ImmutableVar) else LiteralVar.create(prop))}}}"
417
+ )
414
418
  )
415
419
  for name, prop in sorted(key_value_props.items())
416
420
  if prop is not None
417
- ] + [(f"{str(LiteralVar.create(prop))}") for prop in single_props]
421
+ ] + [
422
+ (
423
+ str(prop)
424
+ if isinstance(prop, ImmutableVar) and not isinstance(prop, ImmutableVar)
425
+ else f"{str(LiteralVar.create(prop))}"
426
+ )
427
+ for prop in single_props
428
+ ]
418
429
 
419
430
 
420
431
  def get_event_handler_parts(handler: EventHandler) -> tuple[str, str]:
@@ -475,10 +486,10 @@ def format_event(event_spec: EventSpec) -> str:
475
486
  [
476
487
  ":".join(
477
488
  (
478
- name._js_expr,
489
+ name._var_name,
479
490
  (
480
491
  wrap(
481
- json.dumps(val._js_expr).strip('"').replace("`", "\\`"),
492
+ json.dumps(val._var_name).strip('"').replace("`", "\\`"),
482
493
  "`",
483
494
  )
484
495
  if val._var_is_string
@@ -500,38 +511,7 @@ def format_event(event_spec: EventSpec) -> str:
500
511
 
501
512
 
502
513
  if TYPE_CHECKING:
503
- from reflex.vars import Var
504
-
505
-
506
- def format_event_chain(
507
- event_chain: EventChain | Var[EventChain],
508
- event_arg: Var | None = None,
509
- ) -> str:
510
- """DEPRECATED: format an event chain as a javascript invocation.
511
-
512
- Use str(rx.Var.create(event_chain)) instead.
513
-
514
- Args:
515
- event_chain: The event chain to format.
516
- event_arg: this argument is ignored.
517
-
518
- Returns:
519
- Compiled javascript code to queue the given event chain on the frontend.
520
- """
521
- deprecate(
522
- feature_name="format_event_chain",
523
- reason="Use str(rx.Var.create(event_chain)) instead",
524
- deprecation_version="0.6.0",
525
- removal_version="0.7.0",
526
- )
527
-
528
- from reflex.vars import Var
529
- from reflex.vars.function import ArgsFunctionOperation
530
-
531
- result = Var.create(event_chain)
532
- if isinstance(result, ArgsFunctionOperation):
533
- result = result._return_expr
534
- return str(result)
514
+ from reflex.ivars import ImmutableVar
535
515
 
536
516
 
537
517
  def format_queue_events(
@@ -543,7 +523,7 @@ def format_queue_events(
543
523
  | None
544
524
  ) = None,
545
525
  args_spec: Optional[ArgsSpec] = None,
546
- ) -> Var[EventChain]:
526
+ ) -> ImmutableVar[EventChain]:
547
527
  """Format a list of event handler / event spec as a javascript callback.
548
528
 
549
529
  The resulting code can be passed to interfaces that expect a callback
@@ -569,10 +549,10 @@ def format_queue_events(
569
549
  call_event_fn,
570
550
  call_event_handler,
571
551
  )
572
- from reflex.vars import FunctionVar, Var
552
+ from reflex.ivars import FunctionVar, ImmutableVar
573
553
 
574
554
  if not events:
575
- return Var("(() => null)").to(FunctionVar, EventChain) # type: ignore
555
+ return ImmutableVar("(() => null)").to(FunctionVar, EventChain) # type: ignore
576
556
 
577
557
  # If no spec is provided, the function will take no arguments.
578
558
  def _default_args_spec():
@@ -597,7 +577,7 @@ def format_queue_events(
597
577
  specs = [call_event_handler(spec, args_spec or _default_args_spec)]
598
578
  elif isinstance(spec, type(lambda: None)):
599
579
  specs = call_event_fn(spec, args_spec or _default_args_spec) # type: ignore
600
- if isinstance(specs, Var):
580
+ if isinstance(specs, ImmutableVar):
601
581
  raise ValueError(
602
582
  f"Invalid event spec: {specs}. Expected a list of EventSpecs."
603
583
  )
@@ -605,7 +585,7 @@ def format_queue_events(
605
585
 
606
586
  # Return the final code snippet, expecting queueEvents, processEvent, and socket to be in scope.
607
587
  # Typically this snippet will _only_ run from within an rx.call_script eval context.
608
- return Var(
588
+ return ImmutableVar(
609
589
  f"{arg_def} => {{queueEvents([{','.join(payloads)}], {constants.CompileVars.SOCKET}); "
610
590
  f"processEvent({constants.CompileVars.SOCKET})}}",
611
591
  ).to(FunctionVar, EventChain) # type: ignore
@@ -747,7 +727,7 @@ def collect_form_dict_names(form_dict: dict[str, Any]) -> dict[str, Any]:
747
727
  return collapsed
748
728
 
749
729
 
750
- def format_array_ref(refs: str, idx: Var | None) -> str:
730
+ def format_array_ref(refs: str, idx: ImmutableVar | None) -> str:
751
731
  """Format a ref accessed by array.
752
732
 
753
733
  Args:
@@ -776,7 +756,7 @@ def format_data_editor_column(col: str | dict):
776
756
  Returns:
777
757
  The formatted column.
778
758
  """
779
- from reflex.vars import Var
759
+ from reflex.ivars import ImmutableVar
780
760
 
781
761
  if isinstance(col, str):
782
762
  return {"title": col, "id": col.lower(), "type": "str"}
@@ -790,7 +770,7 @@ def format_data_editor_column(col: str | dict):
790
770
  col["overlayIcon"] = None
791
771
  return col
792
772
 
793
- if isinstance(col, Var):
773
+ if isinstance(col, ImmutableVar):
794
774
  return col
795
775
 
796
776
  raise ValueError(
@@ -807,9 +787,9 @@ def format_data_editor_cell(cell: Any):
807
787
  Returns:
808
788
  The formatted cell.
809
789
  """
810
- from reflex.vars.base import Var
790
+ from reflex.ivars.base import ImmutableVar
811
791
 
812
792
  return {
813
- "kind": Var(_js_expr="GridCellKind.Text"),
793
+ "kind": ImmutableVar.create("GridCellKind.Text"),
814
794
  "data": cell,
815
795
  }
reflex/utils/imports.py CHANGED
@@ -2,9 +2,10 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- import dataclasses
6
5
  from collections import defaultdict
7
- from typing import DefaultDict, Dict, List, Optional, Tuple, Union
6
+ from typing import Dict, List, Optional, Tuple, Union
7
+
8
+ from reflex.base import Base
8
9
 
9
10
 
10
11
  def merge_imports(
@@ -18,22 +19,12 @@ def merge_imports(
18
19
  Returns:
19
20
  The merged import dicts.
20
21
  """
21
- all_imports: DefaultDict[str, List[ImportVar]] = defaultdict(list)
22
+ all_imports = defaultdict(list)
22
23
  for import_dict in imports:
23
24
  for lib, fields in (
24
25
  import_dict if isinstance(import_dict, tuple) else import_dict.items()
25
26
  ):
26
- if isinstance(fields, (list, tuple, set)):
27
- all_imports[lib].extend(
28
- (
29
- ImportVar(field) if isinstance(field, str) else field
30
- for field in fields
31
- )
32
- )
33
- else:
34
- all_imports[lib].append(
35
- ImportVar(fields) if isinstance(fields, str) else fields
36
- )
27
+ all_imports[lib].extend(fields)
37
28
  return all_imports
38
29
 
39
30
 
@@ -84,8 +75,7 @@ def collapse_imports(
84
75
  }
85
76
 
86
77
 
87
- @dataclasses.dataclass(order=True, frozen=True)
88
- class ImportVar:
78
+ class ImportVar(Base):
89
79
  """An import var."""
90
80
 
91
81
  # The name of the import tag.
@@ -121,6 +111,73 @@ class ImportVar:
121
111
  else:
122
112
  return self.tag or ""
123
113
 
114
+ def __lt__(self, other: ImportVar) -> bool:
115
+ """Compare two ImportVar objects.
116
+
117
+ Args:
118
+ other: The other ImportVar object to compare.
119
+
120
+ Returns:
121
+ Whether this ImportVar object is less than the other.
122
+ """
123
+ return (
124
+ self.tag,
125
+ self.is_default,
126
+ self.alias,
127
+ self.install,
128
+ self.render,
129
+ self.transpile,
130
+ ) < (
131
+ other.tag,
132
+ other.is_default,
133
+ other.alias,
134
+ other.install,
135
+ other.render,
136
+ other.transpile,
137
+ )
138
+
139
+ def __eq__(self, other: ImportVar) -> bool:
140
+ """Check if two ImportVar objects are equal.
141
+
142
+ Args:
143
+ other: The other ImportVar object to compare.
144
+
145
+ Returns:
146
+ Whether the two ImportVar objects are equal.
147
+ """
148
+ return (
149
+ self.tag,
150
+ self.is_default,
151
+ self.alias,
152
+ self.install,
153
+ self.render,
154
+ self.transpile,
155
+ ) == (
156
+ other.tag,
157
+ other.is_default,
158
+ other.alias,
159
+ other.install,
160
+ other.render,
161
+ other.transpile,
162
+ )
163
+
164
+ def __hash__(self) -> int:
165
+ """Hash the ImportVar object.
166
+
167
+ Returns:
168
+ The hash of the ImportVar object.
169
+ """
170
+ return hash(
171
+ (
172
+ self.tag,
173
+ self.is_default,
174
+ self.alias,
175
+ self.install,
176
+ self.render,
177
+ self.transpile,
178
+ )
179
+ )
180
+
124
181
 
125
182
  ImportTypes = Union[str, ImportVar, List[Union[str, ImportVar]], List[ImportVar]]
126
183
  ImportDict = Dict[str, ImportTypes]
@@ -2,7 +2,6 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- import dataclasses
6
5
  import functools
7
6
  import glob
8
7
  import importlib
@@ -33,6 +32,7 @@ from redis import exceptions
33
32
  from redis.asyncio import Redis
34
33
 
35
34
  from reflex import constants, model
35
+ from reflex.base import Base
36
36
  from reflex.compiler import templates
37
37
  from reflex.config import Config, get_config
38
38
  from reflex.utils import console, net, path_ops, processes
@@ -42,8 +42,7 @@ from reflex.utils.registry import _get_best_registry
42
42
  CURRENTLY_INSTALLING_NODE = False
43
43
 
44
44
 
45
- @dataclasses.dataclass(frozen=True)
46
- class Template:
45
+ class Template(Base):
47
46
  """A template for a Reflex app."""
48
47
 
49
48
  name: str
@@ -52,8 +51,7 @@ class Template:
52
51
  demo_url: str
53
52
 
54
53
 
55
- @dataclasses.dataclass(frozen=True)
56
- class CpuInfo:
54
+ class CpuInfo(Base):
57
55
  """Model to save cpu info."""
58
56
 
59
57
  manufacturer_id: Optional[str]
@@ -73,18 +71,6 @@ def get_web_dir() -> Path:
73
71
  return workdir
74
72
 
75
73
 
76
- def _python_version_check():
77
- """Emit deprecation warning for deprecated python versions."""
78
- # Check for end-of-life python versions.
79
- if sys.version_info < (3, 10):
80
- console.deprecate(
81
- feature_name="Support for Python 3.9 and older",
82
- reason="please upgrade to Python 3.10 or newer",
83
- deprecation_version="0.6.0",
84
- removal_version="0.7.0",
85
- )
86
-
87
-
88
74
  def check_latest_package_version(package_name: str):
89
75
  """Check if the latest version of the package is installed.
90
76
 
@@ -97,16 +83,15 @@ def check_latest_package_version(package_name: str):
97
83
  url = f"https://pypi.org/pypi/{package_name}/json"
98
84
  response = net.get(url)
99
85
  latest_version = response.json()["info"]["version"]
100
- if get_or_set_last_reflex_version_check_datetime():
101
- # Versions were already checked and saved in reflex.json, no need to warn again
102
- return
103
- if version.parse(current_version) < version.parse(latest_version):
104
- # Show a warning when the host version is older than PyPI version
86
+ if (
87
+ version.parse(current_version) < version.parse(latest_version)
88
+ and not get_or_set_last_reflex_version_check_datetime()
89
+ ):
90
+ # only show a warning when the host version is outdated and
91
+ # the last_version_check_datetime is not set in reflex.json
105
92
  console.warn(
106
93
  f"Your version ({current_version}) of {package_name} is out of date. Upgrade to {latest_version} with 'pip install {package_name} --upgrade'"
107
94
  )
108
- # Check for depreacted python versions
109
- _python_version_check()
110
95
  except Exception:
111
96
  pass
112
97
 
@@ -303,7 +288,7 @@ def get_compiled_app(reload: bool = False, export: bool = False) -> ModuleType:
303
288
  """
304
289
  app_module = get_app(reload=reload)
305
290
  app = getattr(app_module, constants.CompileVars.APP)
306
- # For py3.9 compatibility when redis is used, we MUST add any decorator pages
291
+ # For py3.8 and py3.9 compatibility when redis is used, we MUST add any decorator pages
307
292
  # before compiling the app in a thread to avoid event loop error (REF-2172).
308
293
  app._apply_decorated_pages()
309
294
  app._compile(export=export)
@@ -1292,16 +1277,11 @@ def fetch_app_templates(version: str) -> dict[str, Template]:
1292
1277
  ),
1293
1278
  None,
1294
1279
  )
1295
-
1296
- filtered_templates = {}
1297
- for tp in templates_data:
1298
- if tp["hidden"] or tp["code_url"] is None:
1299
- continue
1300
- known_fields = set(f.name for f in dataclasses.fields(Template))
1301
- filtered_templates[tp["name"]] = Template(
1302
- **{k: v for k, v in tp.items() if k in known_fields}
1303
- )
1304
- return filtered_templates
1280
+ return {
1281
+ tp["name"]: Template.parse_obj(tp)
1282
+ for tp in templates_data
1283
+ if not tp["hidden"] and tp["code_url"] is not None
1284
+ }
1305
1285
 
1306
1286
 
1307
1287
  def create_config_init_app_from_remote_template(app_name: str, template_url: str):
@@ -19,8 +19,8 @@ from types import ModuleType, SimpleNamespace
19
19
  from typing import Any, Callable, Iterable, Type, get_args
20
20
 
21
21
  from reflex.components.component import Component
22
+ from reflex.ivars.base import ImmutableVar
22
23
  from reflex.utils import types as rx_types
23
- from reflex.vars.base import Var
24
24
 
25
25
  logger = logging.getLogger("pyi_generator")
26
26
 
@@ -69,10 +69,11 @@ DEFAULT_TYPING_IMPORTS = {
69
69
  # TODO: fix import ordering and unused imports with ruff later
70
70
  DEFAULT_IMPORTS = {
71
71
  "typing": sorted(DEFAULT_TYPING_IMPORTS),
72
+ "reflex.vars": ["Var"],
72
73
  "reflex.components.core.breakpoints": ["Breakpoints"],
73
74
  "reflex.event": ["EventChain", "EventHandler", "EventSpec"],
74
75
  "reflex.style": ["Style"],
75
- "reflex.vars.base": ["Var"],
76
+ "reflex.ivars.base": ["ImmutableVar"],
76
77
  }
77
78
 
78
79
 
@@ -150,7 +151,7 @@ def _get_type_hint(value, type_hint_globals, is_optional=True) -> str:
150
151
 
151
152
  if args:
152
153
  inner_container_type_args = (
153
- sorted((repr(arg) for arg in args))
154
+ [repr(arg) for arg in args]
154
155
  if rx_types.is_literal(value)
155
156
  else [
156
157
  _get_type_hint(arg, type_hint_globals, is_optional=False)
@@ -184,7 +185,7 @@ def _get_type_hint(value, type_hint_globals, is_optional=True) -> str:
184
185
  if arg is not type(None)
185
186
  ]
186
187
  if len(types) > 1:
187
- res = ", ".join(sorted(types))
188
+ res = ", ".join(types)
188
189
  res = f"Union[{res}]"
189
190
  elif isinstance(value, str):
190
191
  ev = eval(value, type_hint_globals)
@@ -355,7 +356,7 @@ def _extract_class_props_as_ast_nodes(
355
356
  with contextlib.suppress(AttributeError, KeyError):
356
357
  # Try to get default from pydantic field definition.
357
358
  default = target_class.__fields__[name].default
358
- if isinstance(default, Var):
359
+ if isinstance(default, ImmutableVar):
359
360
  default = default._decode() # type: ignore
360
361
 
361
362
  kwargs.append(
@@ -433,7 +434,7 @@ def _generate_component_create_functiondef(
433
434
  ast.arg(
434
435
  arg=trigger,
435
436
  annotation=ast.Name(
436
- id="Optional[Union[EventHandler, EventSpec, list, Callable, Var]]"
437
+ id="Optional[Union[EventHandler, EventSpec, list, Callable, ImmutableVar]]"
437
438
  ),
438
439
  ),
439
440
  ast.Constant(value=None),
@@ -902,13 +903,7 @@ class PyiGenerator:
902
903
  # construct the import statement and handle special cases for aliases
903
904
  sub_mod_attrs_imports = [
904
905
  f"from .{path} import {mod if not isinstance(mod, tuple) else mod[0]} as {mod if not isinstance(mod, tuple) else mod[1]}"
905
- + (
906
- " # type: ignore"
907
- if mod in pyright_ignore_imports
908
- else " # noqa" # ignore ruff formatting here for cases like rx.list.
909
- if isinstance(mod, tuple)
910
- else ""
911
- )
906
+ + (" # type: ignore" if mod in pyright_ignore_imports else "")
912
907
  for mod, path in sub_mod_attrs.items()
913
908
  ]
914
909
  sub_mod_attrs_imports.append("")
@@ -2,7 +2,6 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- import dataclasses
6
5
  import functools
7
6
  import json
8
7
  import warnings
@@ -30,7 +29,7 @@ from reflex.utils import types
30
29
 
31
30
  # Mapping from type to a serializer.
32
31
  # The serializer should convert the type to a JSON object.
33
- SerializedType = Union[str, bool, int, float, list, dict, None]
32
+ SerializedType = Union[str, bool, int, float, list, dict]
34
33
 
35
34
 
36
35
  Serializer = Callable[[Type], SerializedType]
@@ -125,8 +124,6 @@ def serialize(
125
124
 
126
125
  # If there is no serializer, return None.
127
126
  if serializer is None:
128
- if dataclasses.is_dataclass(value) and not isinstance(value, type):
129
- return serialize(dataclasses.asdict(value))
130
127
  if get_type:
131
128
  return None, None
132
129
  return None
@@ -228,7 +225,7 @@ def serialize_str(value: str) -> str:
228
225
 
229
226
 
230
227
  @serializer
231
- def serialize_primitive(value: Union[bool, int, float, None]):
228
+ def serialize_primitive(value: Union[bool, int, float, None]) -> str:
232
229
  """Serialize a primitive type.
233
230
 
234
231
  Args:
@@ -237,11 +234,13 @@ def serialize_primitive(value: Union[bool, int, float, None]):
237
234
  Returns:
238
235
  The serialized number/bool/None.
239
236
  """
240
- return value
237
+ from reflex.utils import format
238
+
239
+ return format.json_dumps(value)
241
240
 
242
241
 
243
242
  @serializer
244
- def serialize_base(value: Base) -> dict:
243
+ def serialize_base(value: Base) -> str:
245
244
  """Serialize a Base instance.
246
245
 
247
246
  Args:
@@ -250,11 +249,18 @@ def serialize_base(value: Base) -> dict:
250
249
  Returns:
251
250
  The serialized Base.
252
251
  """
253
- return {k: serialize(v) for k, v in value.dict().items() if not callable(v)}
252
+ from reflex.ivars import LiteralObjectVar
253
+
254
+ return str(
255
+ LiteralObjectVar.create(
256
+ {k: (None if callable(v) else v) for k, v in value.dict().items()},
257
+ _var_type=type(value),
258
+ )
259
+ )
254
260
 
255
261
 
256
262
  @serializer
257
- def serialize_list(value: Union[List, Tuple, Set]) -> list:
263
+ def serialize_list(value: Union[List, Tuple, Set]) -> str:
258
264
  """Serialize a list to a JSON string.
259
265
 
260
266
  Args:
@@ -263,11 +269,13 @@ def serialize_list(value: Union[List, Tuple, Set]) -> list:
263
269
  Returns:
264
270
  The serialized list.
265
271
  """
266
- return [serialize(item) for item in value]
272
+ from reflex.ivars import LiteralArrayVar
273
+
274
+ return str(LiteralArrayVar.create(value))
267
275
 
268
276
 
269
277
  @serializer
270
- def serialize_dict(prop: Dict[str, Any]) -> dict:
278
+ def serialize_dict(prop: Dict[str, Any]) -> str:
271
279
  """Serialize a dictionary to a JSON string.
272
280
 
273
281
  Args:
@@ -276,7 +284,9 @@ def serialize_dict(prop: Dict[str, Any]) -> dict:
276
284
  Returns:
277
285
  The serialized dictionary.
278
286
  """
279
- return {k: serialize(v) for k, v in prop.items()}
287
+ from reflex.ivars import LiteralObjectVar
288
+
289
+ return str(LiteralObjectVar.create(prop))
280
290
 
281
291
 
282
292
  @serializer(to=str)
reflex/utils/telemetry.py CHANGED
@@ -3,7 +3,6 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import asyncio
6
- import dataclasses
7
6
  import multiprocessing
8
7
  import platform
9
8
  import warnings
@@ -121,7 +120,7 @@ def _prepare_event(event: str, **kwargs) -> dict:
121
120
  return {}
122
121
 
123
122
  if UTC is None:
124
- # for python 3.9 & 3.10
123
+ # for python 3.8, 3.9 & 3.10
125
124
  stamp = datetime.utcnow().isoformat()
126
125
  else:
127
126
  # for python 3.11 & 3.12
@@ -145,7 +144,7 @@ def _prepare_event(event: str, **kwargs) -> dict:
145
144
  "python_version": get_python_version(),
146
145
  "cpu_count": get_cpu_count(),
147
146
  "memory": get_memory(),
148
- "cpu_info": dataclasses.asdict(cpuinfo) if cpuinfo else {},
147
+ "cpu_info": dict(cpuinfo) if cpuinfo else {},
149
148
  **additional_fields,
150
149
  },
151
150
  "timestamp": stamp,
reflex/utils/types.py CHANGED
@@ -3,7 +3,6 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import contextlib
6
- import dataclasses
7
6
  import inspect
8
7
  import sys
9
8
  import types
@@ -96,7 +95,7 @@ PrimitiveType = Union[int, float, bool, str, list, dict, set, tuple]
96
95
  StateVar = Union[PrimitiveType, Base, None]
97
96
  StateIterVar = Union[list, set, tuple]
98
97
 
99
- # ArgsSpec = Callable[[Var], list[Var]]
98
+ # ArgsSpec = Callable[[ImmutableVar], list[ImmutableVar]]
100
99
  ArgsSpec = Callable
101
100
 
102
101
 
@@ -481,11 +480,7 @@ def is_valid_var_type(type_: Type) -> bool:
481
480
 
482
481
  if is_union(type_):
483
482
  return all((is_valid_var_type(arg) for arg in get_args(type_)))
484
- return (
485
- _issubclass(type_, StateVar)
486
- or serializers.has_serializer(type_)
487
- or dataclasses.is_dataclass(type_)
488
- )
483
+ return _issubclass(type_, StateVar) or serializers.has_serializer(type_)
489
484
 
490
485
 
491
486
  def is_backend_base_variable(name: str, cls: Type) -> bool:
@@ -519,7 +514,7 @@ def is_backend_base_variable(name: str, cls: Type) -> bool:
519
514
  if name in cls.inherited_backend_vars:
520
515
  return False
521
516
 
522
- from reflex.vars.base import is_computed_var
517
+ from reflex.ivars.base import is_computed_var
523
518
 
524
519
  if name in cls.__dict__:
525
520
  value = cls.__dict__[name]
@@ -595,11 +590,11 @@ def validate_literal(key: str, value: Any, expected_type: Type, comp_name: str):
595
590
  Raises:
596
591
  ValueError: When the value is not a valid literal.
597
592
  """
598
- from reflex.vars import Var
593
+ from reflex.ivars import ImmutableVar
599
594
 
600
595
  if (
601
596
  is_literal(expected_type)
602
- and not isinstance(value, Var) # validating vars is not supported yet.
597
+ and not isinstance(value, ImmutableVar) # validating vars is not supported yet.
603
598
  and not is_encoded_fstring(value) # f-strings are not supported.
604
599
  and value not in expected_type.__args__
605
600
  ):