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/state.py CHANGED
@@ -5,7 +5,6 @@ from __future__ import annotations
5
5
  import asyncio
6
6
  import contextlib
7
7
  import copy
8
- import dataclasses
9
8
  import functools
10
9
  import inspect
11
10
  import os
@@ -35,11 +34,11 @@ import dill
35
34
  from sqlalchemy.orm import DeclarativeBase
36
35
 
37
36
  from reflex.config import get_config
38
- from reflex.vars.base import (
39
- ComputedVar,
37
+ from reflex.ivars.base import (
40
38
  DynamicRouteVar,
41
- Var,
42
- computed_var,
39
+ ImmutableComputedVar,
40
+ ImmutableVar,
41
+ immutable_computed_var,
43
42
  is_computed_var,
44
43
  )
45
44
 
@@ -63,10 +62,7 @@ from reflex.event import (
63
62
  )
64
63
  from reflex.utils import console, format, path_ops, prerequisites, types
65
64
  from reflex.utils.exceptions import (
66
- ComputedVarShadowsBaseVars,
67
- ComputedVarShadowsStateVar,
68
65
  DynamicRouteArgShadowsStateVar,
69
- EventHandlerShadowsBuiltInStateMethod,
70
66
  ImmutableStateError,
71
67
  LockExpiredError,
72
68
  )
@@ -80,22 +76,20 @@ if TYPE_CHECKING:
80
76
 
81
77
 
82
78
  Delta = Dict[str, Any]
83
- var = computed_var
79
+ var = immutable_computed_var
84
80
 
85
81
 
86
82
  # If the state is this large, it's considered a performance issue.
87
83
  TOO_LARGE_SERIALIZED_STATE = 100 * 1024 # 100kb
88
84
 
89
85
 
90
- @dataclasses.dataclass(frozen=True)
91
- class HeaderData:
86
+ class HeaderData(Base):
92
87
  """An object containing headers data."""
93
88
 
94
89
  host: str = ""
95
90
  origin: str = ""
96
91
  upgrade: str = ""
97
92
  connection: str = ""
98
- cookie: str = ""
99
93
  pragma: str = ""
100
94
  cache_control: str = ""
101
95
  user_agent: str = ""
@@ -111,16 +105,13 @@ class HeaderData:
111
105
  Args:
112
106
  router_data: the router_data dict.
113
107
  """
108
+ super().__init__()
114
109
  if router_data:
115
110
  for k, v in router_data.get(constants.RouteVar.HEADERS, {}).items():
116
- object.__setattr__(self, format.to_snake_case(k), v)
117
- else:
118
- for k in dataclasses.fields(self):
119
- object.__setattr__(self, k.name, "")
111
+ setattr(self, format.to_snake_case(k), v)
120
112
 
121
113
 
122
- @dataclasses.dataclass(frozen=True)
123
- class PageData:
114
+ class PageData(Base):
124
115
  """An object containing page data."""
125
116
 
126
117
  host: str = "" # repeated with self.headers.origin (remove or keep the duplicate?)
@@ -128,7 +119,7 @@ class PageData:
128
119
  raw_path: str = ""
129
120
  full_path: str = ""
130
121
  full_raw_path: str = ""
131
- params: dict = dataclasses.field(default_factory=dict)
122
+ params: dict = {}
132
123
 
133
124
  def __init__(self, router_data: Optional[dict] = None):
134
125
  """Initalize the PageData object based on router_data.
@@ -136,34 +127,17 @@ class PageData:
136
127
  Args:
137
128
  router_data: the router_data dict.
138
129
  """
130
+ super().__init__()
139
131
  if router_data:
140
- object.__setattr__(
141
- self,
142
- "host",
143
- router_data.get(constants.RouteVar.HEADERS, {}).get("origin", ""),
144
- )
145
- object.__setattr__(
146
- self, "path", router_data.get(constants.RouteVar.PATH, "")
147
- )
148
- object.__setattr__(
149
- self, "raw_path", router_data.get(constants.RouteVar.ORIGIN, "")
150
- )
151
- object.__setattr__(self, "full_path", f"{self.host}{self.path}")
152
- object.__setattr__(self, "full_raw_path", f"{self.host}{self.raw_path}")
153
- object.__setattr__(
154
- self, "params", router_data.get(constants.RouteVar.QUERY, {})
155
- )
156
- else:
157
- object.__setattr__(self, "host", "")
158
- object.__setattr__(self, "path", "")
159
- object.__setattr__(self, "raw_path", "")
160
- object.__setattr__(self, "full_path", "")
161
- object.__setattr__(self, "full_raw_path", "")
162
- object.__setattr__(self, "params", {})
132
+ self.host = router_data.get(constants.RouteVar.HEADERS, {}).get("origin")
133
+ self.path = router_data.get(constants.RouteVar.PATH, "")
134
+ self.raw_path = router_data.get(constants.RouteVar.ORIGIN, "")
135
+ self.full_path = f"{self.host}{self.path}"
136
+ self.full_raw_path = f"{self.host}{self.raw_path}"
137
+ self.params = router_data.get(constants.RouteVar.QUERY, {})
163
138
 
164
139
 
165
- @dataclasses.dataclass(frozen=True, init=False)
166
- class SessionData:
140
+ class SessionData(Base):
167
141
  """An object containing session data."""
168
142
 
169
143
  client_token: str = ""
@@ -176,24 +150,19 @@ class SessionData:
176
150
  Args:
177
151
  router_data: the router_data dict.
178
152
  """
153
+ super().__init__()
179
154
  if router_data:
180
- client_token = router_data.get(constants.RouteVar.CLIENT_TOKEN, "")
181
- client_ip = router_data.get(constants.RouteVar.CLIENT_IP, "")
182
- session_id = router_data.get(constants.RouteVar.SESSION_ID, "")
183
- else:
184
- client_token = client_ip = session_id = ""
185
- object.__setattr__(self, "client_token", client_token)
186
- object.__setattr__(self, "client_ip", client_ip)
187
- object.__setattr__(self, "session_id", session_id)
155
+ self.client_token = router_data.get(constants.RouteVar.CLIENT_TOKEN, "")
156
+ self.client_ip = router_data.get(constants.RouteVar.CLIENT_IP, "")
157
+ self.session_id = router_data.get(constants.RouteVar.SESSION_ID, "")
188
158
 
189
159
 
190
- @dataclasses.dataclass(frozen=True, init=False)
191
- class RouterData:
160
+ class RouterData(Base):
192
161
  """An object containing RouterData."""
193
162
 
194
- session: SessionData = dataclasses.field(default_factory=SessionData)
195
- headers: HeaderData = dataclasses.field(default_factory=HeaderData)
196
- page: PageData = dataclasses.field(default_factory=PageData)
163
+ session: SessionData = SessionData()
164
+ headers: HeaderData = HeaderData()
165
+ page: PageData = PageData()
197
166
 
198
167
  def __init__(self, router_data: Optional[dict] = None):
199
168
  """Initialize the RouterData object.
@@ -201,9 +170,10 @@ class RouterData:
201
170
  Args:
202
171
  router_data: the router_data dict.
203
172
  """
204
- object.__setattr__(self, "session", SessionData(router_data))
205
- object.__setattr__(self, "headers", HeaderData(router_data))
206
- object.__setattr__(self, "page", PageData(router_data))
173
+ super().__init__()
174
+ self.session = SessionData(router_data)
175
+ self.headers = HeaderData(router_data)
176
+ self.page = PageData(router_data)
207
177
 
208
178
 
209
179
  def _no_chain_background_task(
@@ -279,11 +249,10 @@ def _split_substate_key(substate_key: str) -> tuple[str, str]:
279
249
  return token, state_name
280
250
 
281
251
 
282
- @dataclasses.dataclass(frozen=True, init=False)
283
252
  class EventHandlerSetVar(EventHandler):
284
253
  """A special event handler to wrap setvar functionality."""
285
254
 
286
- state_cls: Type[BaseState] = dataclasses.field(init=False)
255
+ state_cls: Type[BaseState]
287
256
 
288
257
  def __init__(self, state_cls: Type[BaseState]):
289
258
  """Initialize the EventHandlerSetVar.
@@ -294,8 +263,8 @@ class EventHandlerSetVar(EventHandler):
294
263
  super().__init__(
295
264
  fn=type(self).setvar,
296
265
  state_full_name=state_cls.get_full_name(),
266
+ state_cls=state_cls, # type: ignore
297
267
  )
298
- object.__setattr__(self, "state_cls", state_cls)
299
268
 
300
269
  def setvar(self, var_name: str, value: Any):
301
270
  """Set the state variable to the value of the event.
@@ -340,16 +309,16 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
340
309
  """The state of the app."""
341
310
 
342
311
  # A map from the var name to the var.
343
- vars: ClassVar[Dict[str, Var]] = {}
312
+ vars: ClassVar[Dict[str, ImmutableVar]] = {}
344
313
 
345
314
  # The base vars of the class.
346
- base_vars: ClassVar[Dict[str, Var]] = {}
315
+ base_vars: ClassVar[Dict[str, ImmutableVar]] = {}
347
316
 
348
317
  # The computed vars of the class.
349
- computed_vars: ClassVar[Dict[str, ComputedVar]] = {}
318
+ computed_vars: ClassVar[Dict[str, ImmutableComputedVar]] = {}
350
319
 
351
320
  # Vars inherited by the parent state.
352
- inherited_vars: ClassVar[Dict[str, Var]] = {}
321
+ inherited_vars: ClassVar[Dict[str, ImmutableVar]] = {}
353
322
 
354
323
  # Backend base vars that are never sent to the client.
355
324
  backend_vars: ClassVar[Dict[str, Any]] = {}
@@ -459,7 +428,7 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
459
428
  return f"{self.__class__.__name__}({self.dict()})"
460
429
 
461
430
  @classmethod
462
- def _get_computed_vars(cls) -> list[ComputedVar]:
431
+ def _get_computed_vars(cls) -> list[ImmutableComputedVar]:
463
432
  """Helper function to get all computed vars of a instance.
464
433
 
465
434
  Returns:
@@ -556,8 +525,8 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
556
525
 
557
526
  # Set the base and computed vars.
558
527
  cls.base_vars = {
559
- f.name: Var(
560
- _js_expr=format.format_state_name(cls.get_full_name()) + "." + f.name,
528
+ f.name: ImmutableVar(
529
+ _var_name=format.format_state_name(cls.get_full_name()) + "." + f.name,
561
530
  _var_type=f.outer_type_,
562
531
  _var_data=VarData.from_state(cls),
563
532
  ).guess_type()
@@ -565,7 +534,7 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
565
534
  if f.name not in cls.get_skip_vars()
566
535
  }
567
536
  cls.computed_vars = {
568
- v._js_expr: v._replace(merge_var_data=VarData.from_state(cls))
537
+ v._var_name: v._replace(merge_var_data=VarData.from_state(cls))
569
538
  for v in computed_vars
570
539
  }
571
540
  cls.vars = {
@@ -595,8 +564,8 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
595
564
  newcv = value._replace(fget=fget, _var_data=VarData.from_state(cls))
596
565
  # cleanup refs to mixin cls in var_data
597
566
  setattr(cls, name, newcv)
598
- cls.computed_vars[newcv._js_expr] = newcv
599
- cls.vars[newcv._js_expr] = newcv
567
+ cls.computed_vars[newcv._var_name] = newcv
568
+ cls.vars[newcv._var_name] = newcv
600
569
  continue
601
570
  if types.is_backend_base_variable(name, mixin):
602
571
  cls.backend_vars[name] = copy.deepcopy(value)
@@ -736,7 +705,7 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
736
705
  """Check for shadow methods and raise error if any.
737
706
 
738
707
  Raises:
739
- EventHandlerShadowsBuiltInStateMethod: When an event handler shadows an inbuilt state method.
708
+ NameError: When an event handler shadows an inbuilt state method.
740
709
  """
741
710
  overridden_methods = set()
742
711
  state_base_functions = cls._get_base_functions()
@@ -750,7 +719,7 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
750
719
  overridden_methods.add(method.__name__)
751
720
 
752
721
  for method_name in overridden_methods:
753
- raise EventHandlerShadowsBuiltInStateMethod(
722
+ raise NameError(
754
723
  f"The event handler name `{method_name}` shadows a builtin State method; use a different name instead"
755
724
  )
756
725
 
@@ -759,12 +728,12 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
759
728
  """Check for shadow base vars and raise error if any.
760
729
 
761
730
  Raises:
762
- ComputedVarShadowsBaseVars: When a computed var shadows a base var.
731
+ NameError: When a computed var shadows a base var.
763
732
  """
764
733
  for computed_var_ in cls._get_computed_vars():
765
- if computed_var_._js_expr in cls.__annotations__:
766
- raise ComputedVarShadowsBaseVars(
767
- f"The computed var name `{computed_var_._js_expr}` shadows a base var in {cls.__module__}.{cls.__name__}; use a different name instead"
734
+ if computed_var_._var_name in cls.__annotations__:
735
+ raise NameError(
736
+ f"The computed var name `{computed_var_._var_name}` shadows a base var in {cls.__module__}.{cls.__name__}; use a different name instead"
768
737
  )
769
738
 
770
739
  @classmethod
@@ -772,15 +741,15 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
772
741
  """Check for shadow computed vars and raise error if any.
773
742
 
774
743
  Raises:
775
- ComputedVarShadowsStateVar: When a computed var shadows another.
744
+ NameError: When a computed var shadows another.
776
745
  """
777
746
  for name, cv in cls.__dict__.items():
778
747
  if not is_computed_var(cv):
779
748
  continue
780
- name = cv._js_expr
749
+ name = cv._var_name
781
750
  if name in cls.inherited_vars or name in cls.inherited_backend_vars:
782
- raise ComputedVarShadowsStateVar(
783
- f"The computed var name `{cv._js_expr}` shadows a var in {cls.__module__}.{cls.__name__}; use a different name instead"
751
+ raise NameError(
752
+ f"The computed var name `{cv._var_name}` shadows a var in {cls.__module__}.{cls.__name__}; use a different name instead"
784
753
  )
785
754
 
786
755
  @classmethod
@@ -902,7 +871,7 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
902
871
  return getattr(substate, name)
903
872
 
904
873
  @classmethod
905
- def _init_var(cls, prop: Var):
874
+ def _init_var(cls, prop: ImmutableVar):
906
875
  """Initialize a variable.
907
876
 
908
877
  Args:
@@ -918,7 +887,7 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
918
887
  "State vars must be primitive Python types, "
919
888
  "Plotly figures, Pandas dataframes, "
920
889
  "or subclasses of rx.Base. "
921
- f'Found var "{prop._js_expr}" with type {prop._var_type}.'
890
+ f'Found var "{prop._var_name}" with type {prop._var_type}.'
922
891
  )
923
892
  cls._set_var(prop)
924
893
  cls._create_setter(prop)
@@ -945,8 +914,8 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
945
914
  )
946
915
 
947
916
  # create the variable based on name and type
948
- var = Var(
949
- _js_expr=format.format_state_name(cls.get_full_name()) + "." + name,
917
+ var = ImmutableVar(
918
+ _var_name=format.format_state_name(cls.get_full_name()) + "." + name,
950
919
  _var_type=type_,
951
920
  _var_data=VarData.from_state(cls),
952
921
  ).guess_type()
@@ -968,14 +937,16 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
968
937
  cls._init_var_dependency_dicts()
969
938
 
970
939
  @classmethod
971
- def _set_var(cls, prop: Var):
940
+ def _set_var(cls, prop: ImmutableVar):
972
941
  """Set the var as a class member.
973
942
 
974
943
  Args:
975
944
  prop: The var instance to set.
976
945
  """
977
946
  acutal_var_name = (
978
- prop._js_expr if "." not in prop._js_expr else prop._js_expr.split(".")[-1]
947
+ prop._var_name
948
+ if "." not in prop._var_name
949
+ else prop._var_name.split(".")[-1]
979
950
  )
980
951
  setattr(cls, acutal_var_name, prop)
981
952
 
@@ -997,7 +968,7 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
997
968
  cls.setvar = cls.event_handlers["setvar"] = EventHandlerSetVar(state_cls=cls)
998
969
 
999
970
  @classmethod
1000
- def _create_setter(cls, prop: Var):
971
+ def _create_setter(cls, prop: ImmutableVar):
1001
972
  """Create a setter for the var.
1002
973
 
1003
974
  Args:
@@ -1010,17 +981,17 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
1010
981
  setattr(cls, setter_name, event_handler)
1011
982
 
1012
983
  @classmethod
1013
- def _set_default_value(cls, prop: Var):
984
+ def _set_default_value(cls, prop: ImmutableVar):
1014
985
  """Set the default value for the var.
1015
986
 
1016
987
  Args:
1017
988
  prop: The var to set the default value for.
1018
989
  """
1019
990
  # Get the pydantic field for the var.
1020
- if "." in prop._js_expr:
1021
- field = cls.get_fields()[prop._js_expr.split(".")[-1]]
991
+ if "." in prop._var_name:
992
+ field = cls.get_fields()[prop._var_name.split(".")[-1]]
1022
993
  else:
1023
- field = cls.get_fields()[prop._js_expr]
994
+ field = cls.get_fields()[prop._var_name]
1024
995
  if field.required:
1025
996
  default_value = prop.get_default_value()
1026
997
  if default_value is not None:
@@ -1047,27 +1018,6 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
1047
1018
  if not func[0].startswith("__")
1048
1019
  }
1049
1020
 
1050
- @classmethod
1051
- def _update_substate_inherited_vars(cls, vars_to_add: dict[str, Var]):
1052
- """Update the inherited vars of substates recursively when new vars are added.
1053
-
1054
- Also updates the var dependency tracking dicts after adding vars.
1055
-
1056
- Args:
1057
- vars_to_add: names to Var instances to add to substates
1058
- """
1059
- for substate_class in cls.class_subclasses:
1060
- for name, var in vars_to_add.items():
1061
- if types.is_backend_base_variable(name, cls):
1062
- substate_class.backend_vars.setdefault(name, var)
1063
- substate_class.inherited_backend_vars.setdefault(name, var)
1064
- else:
1065
- substate_class.vars.setdefault(name, var)
1066
- substate_class.inherited_vars.setdefault(name, var)
1067
- substate_class._update_substate_inherited_vars(vars_to_add)
1068
- # Reinitialize dependency tracking dicts.
1069
- cls._init_var_dependency_dicts()
1070
-
1071
1021
  @classmethod
1072
1022
  def setup_dynamic_args(cls, args: dict[str, str]):
1073
1023
  """Set up args for easy access in renderer.
@@ -1084,15 +1034,14 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
1084
1034
  def inner_func(self) -> str:
1085
1035
  return self.router.page.params.get(param, "")
1086
1036
 
1087
- return inner_func
1037
+ return DynamicRouteVar(fget=inner_func, cache=True)
1088
1038
 
1089
1039
  def arglist_factory(param):
1090
1040
  def inner_func(self) -> List[str]:
1091
1041
  return self.router.page.params.get(param, [])
1092
1042
 
1093
- return inner_func
1043
+ return DynamicRouteVar(fget=inner_func, cache=True)
1094
1044
 
1095
- dynamic_vars = {}
1096
1045
  for param, value in args.items():
1097
1046
  if value == constants.RouteArgType.SINGLE:
1098
1047
  func = argsingle_factory(param)
@@ -1100,18 +1049,16 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
1100
1049
  func = arglist_factory(param)
1101
1050
  else:
1102
1051
  continue
1103
- dynamic_vars[param] = DynamicRouteVar(
1104
- fget=func,
1105
- cache=True,
1106
- _js_expr=param,
1107
- _var_data=VarData.from_state(cls),
1052
+ # to allow passing as a prop, evade python frozen rules (bad practice)
1053
+ object.__setattr__(func, "_var_name", param)
1054
+ # cls.vars[param] = cls.computed_vars[param] = func._var_set_state(cls) # type: ignore
1055
+ cls.vars[param] = cls.computed_vars[param] = func._replace(
1056
+ _var_data=VarData.from_state(cls)
1108
1057
  )
1109
- setattr(cls, param, dynamic_vars[param])
1058
+ setattr(cls, param, func)
1110
1059
 
1111
- # Update tracking dicts.
1112
- cls.computed_vars.update(dynamic_vars)
1113
- cls.vars.update(dynamic_vars)
1114
- cls._update_substate_inherited_vars(dynamic_vars)
1060
+ # Reinitialize dependency tracking dicts.
1061
+ cls._init_var_dependency_dicts()
1115
1062
 
1116
1063
  @classmethod
1117
1064
  def _check_overwritten_dynamic_args(cls, args: list[str]):
@@ -1879,13 +1826,8 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
1879
1826
  self.dirty_vars.update(self._always_dirty_computed_vars)
1880
1827
  self._mark_dirty()
1881
1828
 
1882
- def dictify(value: Any):
1883
- if dataclasses.is_dataclass(value) and not isinstance(value, type):
1884
- return dataclasses.asdict(value)
1885
- return value
1886
-
1887
1829
  base_vars = {
1888
- prop_name: dictify(self.get_value(getattr(self, prop_name)))
1830
+ prop_name: self.get_value(getattr(self, prop_name))
1889
1831
  for prop_name in self.base_vars
1890
1832
  }
1891
1833
  if initial and include_computed:
@@ -1965,6 +1907,9 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
1965
1907
  return state
1966
1908
 
1967
1909
 
1910
+ EventHandlerSetVar.update_forward_refs()
1911
+
1912
+
1968
1913
  class State(BaseState):
1969
1914
  """The app Base State."""
1970
1915
 
@@ -2396,29 +2341,18 @@ class StateProxy(wrapt.ObjectProxy):
2396
2341
  self._self_mutable = original_mutable
2397
2342
 
2398
2343
 
2399
- @dataclasses.dataclass(
2400
- frozen=True,
2401
- )
2402
- class StateUpdate:
2344
+ class StateUpdate(Base):
2403
2345
  """A state update sent to the frontend."""
2404
2346
 
2405
2347
  # The state delta.
2406
- delta: Delta = dataclasses.field(default_factory=dict)
2348
+ delta: Delta = {}
2407
2349
 
2408
2350
  # Events to be added to the event queue.
2409
- events: List[Event] = dataclasses.field(default_factory=list)
2351
+ events: List[Event] = []
2410
2352
 
2411
2353
  # Whether this is the final state update for the event.
2412
2354
  final: bool = True
2413
2355
 
2414
- def json(self) -> str:
2415
- """Convert the state update to a JSON string.
2416
-
2417
- Returns:
2418
- The state update as a JSON string.
2419
- """
2420
- return format.json_dumps(dataclasses.asdict(self))
2421
-
2422
2356
 
2423
2357
  class StateManager(Base, ABC):
2424
2358
  """A class to manage many client states."""
reflex/style.py CHANGED
@@ -7,12 +7,12 @@ from typing import Any, Literal, Tuple, Type
7
7
  from reflex import constants
8
8
  from reflex.components.core.breakpoints import Breakpoints, breakpoints_values
9
9
  from reflex.event import EventChain, EventHandler
10
+ from reflex.ivars.base import ImmutableCallableVar, ImmutableVar, LiteralVar
11
+ from reflex.ivars.function import FunctionVar
10
12
  from reflex.utils import format
11
13
  from reflex.utils.exceptions import ReflexError
12
14
  from reflex.utils.imports import ImportVar
13
- from reflex.vars import VarData
14
- from reflex.vars.base import CallableVar, LiteralVar, Var
15
- from reflex.vars.function import FunctionVar
15
+ from reflex.vars import Var, VarData
16
16
 
17
17
  SYSTEM_COLOR_MODE: str = "system"
18
18
  LIGHT_COLOR_MODE: str = "light"
@@ -26,30 +26,30 @@ color_mode_imports = {
26
26
  }
27
27
 
28
28
 
29
- def _color_mode_var(_js_expr: str, _var_type: Type = str) -> Var:
30
- """Create a Var that destructs the _js_expr from ColorModeContext.
29
+ def _color_mode_var(_var_name: str, _var_type: Type = str) -> ImmutableVar:
30
+ """Create a Var that destructs the _var_name from ColorModeContext.
31
31
 
32
32
  Args:
33
- _js_expr: The name of the variable to get from ColorModeContext.
33
+ _var_name: The name of the variable to get from ColorModeContext.
34
34
  _var_type: The type of the Var.
35
35
 
36
36
  Returns:
37
37
  The Var that resolves to the color mode.
38
38
  """
39
- return Var(
40
- _js_expr=_js_expr,
39
+ return ImmutableVar(
40
+ _var_name=_var_name,
41
41
  _var_type=_var_type,
42
42
  _var_data=VarData(
43
43
  imports=color_mode_imports,
44
- hooks={f"const {{ {_js_expr} }} = useContext(ColorModeContext)": None},
44
+ hooks={f"const {{ {_var_name} }} = useContext(ColorModeContext)": None},
45
45
  ),
46
46
  ).guess_type()
47
47
 
48
48
 
49
- @CallableVar
49
+ @ImmutableCallableVar
50
50
  def set_color_mode(
51
51
  new_color_mode: LiteralColorMode | Var[LiteralColorMode] | None = None,
52
- ) -> Var[EventChain]:
52
+ ) -> ImmutableVar[EventChain]:
53
53
  """Create an EventChain Var that sets the color mode to a specific value.
54
54
 
55
55
  Note: `set_color_mode` is not a real event and cannot be triggered from a
@@ -62,16 +62,16 @@ def set_color_mode(
62
62
  The EventChain Var that can be passed to an event trigger.
63
63
  """
64
64
  base_setter = _color_mode_var(
65
- _js_expr=constants.ColorMode.SET,
65
+ _var_name=constants.ColorMode.SET,
66
66
  _var_type=EventChain,
67
67
  )
68
68
  if new_color_mode is None:
69
69
  return base_setter
70
70
 
71
- if not isinstance(new_color_mode, Var):
71
+ if not isinstance(new_color_mode, ImmutableVar):
72
72
  new_color_mode = LiteralVar.create(new_color_mode)
73
73
 
74
- return Var(
74
+ return ImmutableVar(
75
75
  f"() => {str(base_setter)}({str(new_color_mode)})",
76
76
  _var_data=VarData.merge(
77
77
  base_setter._get_all_var_data(), new_color_mode._get_all_var_data()
@@ -80,12 +80,12 @@ def set_color_mode(
80
80
 
81
81
 
82
82
  # Var resolves to the current color mode for the app ("light", "dark" or "system")
83
- color_mode = _color_mode_var(_js_expr=constants.ColorMode.NAME)
83
+ color_mode = _color_mode_var(_var_name=constants.ColorMode.NAME)
84
84
  # Var resolves to the resolved color mode for the app ("light" or "dark")
85
- resolved_color_mode = _color_mode_var(_js_expr=constants.ColorMode.RESOLVED_NAME)
85
+ resolved_color_mode = _color_mode_var(_var_name=constants.ColorMode.RESOLVED_NAME)
86
86
  # Var resolves to a function invocation that toggles the color mode
87
87
  toggle_color_mode = _color_mode_var(
88
- _js_expr=constants.ColorMode.TOGGLE,
88
+ _var_name=constants.ColorMode.TOGGLE,
89
89
  _var_type=EventChain,
90
90
  )
91
91
 
@@ -115,7 +115,7 @@ def media_query(breakpoint_expr: str):
115
115
 
116
116
  def convert_item(
117
117
  style_item: int | str | Var,
118
- ) -> tuple[str | Var, VarData | None]:
118
+ ) -> tuple[str | Var, VarData | VarData | None]:
119
119
  """Format a single value in a style dictionary.
120
120
 
121
121
  Args:
@@ -133,7 +133,7 @@ def convert_item(
133
133
  "Please use a Var or a literal value."
134
134
  )
135
135
 
136
- if isinstance(style_item, Var):
136
+ if isinstance(style_item, ImmutableVar):
137
137
  return style_item, style_item._get_all_var_data()
138
138
 
139
139
  # if isinstance(style_item, str) and REFLEX_VAR_OPENING_TAG not in style_item:
@@ -146,7 +146,7 @@ def convert_item(
146
146
 
147
147
 
148
148
  def convert_list(
149
- responsive_list: list[str | dict | Var],
149
+ responsive_list: list[str | dict | ImmutableVar],
150
150
  ) -> tuple[list[str | dict[str, Var | list | dict]], VarData | None]:
151
151
  """Format a responsive value list.
152
152
 
@@ -189,7 +189,7 @@ def convert(
189
189
 
190
190
  for key, value in style_dict.items():
191
191
  keys = format_style_key(key)
192
- if isinstance(value, Var):
192
+ if isinstance(value, ImmutableVar):
193
193
  return_val = value
194
194
  new_var_data = value._get_all_var_data()
195
195
  update_out_dict(return_val, keys)
@@ -290,6 +290,7 @@ def _format_emotion_style_pseudo_selector(key: str) -> str:
290
290
  """
291
291
  prefix = None
292
292
  if key.startswith("_"):
293
+ # Handle pseudo selectors in chakra style format.
293
294
  prefix = "&:"
294
295
  key = key[1:]
295
296
  if key.startswith(":"):
@@ -91,23 +91,3 @@ class EventFnArgMismatch(ReflexError, TypeError):
91
91
 
92
92
  class DynamicRouteArgShadowsStateVar(ReflexError, NameError):
93
93
  """Raised when a dynamic route arg shadows a state var."""
94
-
95
-
96
- class ComputedVarShadowsStateVar(ReflexError, NameError):
97
- """Raised when a computed var shadows a state var."""
98
-
99
-
100
- class ComputedVarShadowsBaseVars(ReflexError, NameError):
101
- """Raised when a computed var shadows a base var."""
102
-
103
-
104
- class EventHandlerShadowsBuiltInStateMethod(ReflexError, NameError):
105
- """Raised when an event handler shadows a built-in state method."""
106
-
107
-
108
- class GeneratedCodeHasNoFunctionDefs(ReflexError):
109
- """Raised when refactored code generated with flexgen has no functions defined."""
110
-
111
-
112
- class PrimitiveUnserializableToJSON(ReflexError, ValueError):
113
- """Raised when a primitive type is unserializable to JSON. Usually with NaN and Infinity."""