reflex 0.5.10a2__py3-none-any.whl → 0.6.0__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 (303) 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 +4 -4
  4. reflex/.templates/jinja/web/utils/context.js.jinja2 +1 -1
  5. reflex/.templates/jinja/web/utils/theme.js.jinja2 +1 -1
  6. reflex/.templates/web/utils/state.js +3 -1
  7. reflex/__init__.py +10 -3
  8. reflex/__init__.pyi +3 -2
  9. reflex/app.py +47 -11
  10. reflex/app_module_for_backend.py +1 -1
  11. reflex/base.py +3 -2
  12. reflex/compiler/compiler.py +5 -5
  13. reflex/compiler/utils.py +5 -3
  14. reflex/components/base/app_wrap.py +2 -4
  15. reflex/components/base/app_wrap.pyi +16 -26
  16. reflex/components/base/bare.py +6 -4
  17. reflex/components/base/body.pyi +16 -26
  18. reflex/components/base/document.pyi +76 -126
  19. reflex/components/base/error_boundary.py +9 -8
  20. reflex/components/base/error_boundary.pyi +18 -30
  21. reflex/components/base/fragment.pyi +16 -26
  22. reflex/components/base/head.pyi +31 -51
  23. reflex/components/base/link.py +1 -1
  24. reflex/components/base/link.pyi +31 -51
  25. reflex/components/base/meta.pyi +61 -101
  26. reflex/components/base/script.py +2 -2
  27. reflex/components/base/script.pyi +20 -36
  28. reflex/components/component.py +107 -130
  29. reflex/components/core/banner.py +61 -66
  30. reflex/components/core/banner.pyi +129 -230
  31. reflex/components/core/client_side_routing.py +2 -2
  32. reflex/components/core/client_side_routing.pyi +31 -51
  33. reflex/components/core/clipboard.py +4 -3
  34. reflex/components/core/clipboard.pyi +19 -31
  35. reflex/components/core/cond.py +21 -44
  36. reflex/components/core/debounce.py +7 -9
  37. reflex/components/core/debounce.pyi +19 -31
  38. reflex/components/core/foreach.py +4 -14
  39. reflex/components/core/html.py +1 -1
  40. reflex/components/core/html.pyi +34 -44
  41. reflex/components/core/match.py +36 -43
  42. reflex/components/core/upload.py +27 -26
  43. reflex/components/core/upload.pyi +81 -116
  44. reflex/components/datadisplay/code.py +55 -29
  45. reflex/components/datadisplay/code.pyi +303 -410
  46. reflex/components/datadisplay/dataeditor.py +13 -9
  47. reflex/components/datadisplay/dataeditor.pyi +39 -51
  48. reflex/components/el/__init__.py +0 -1
  49. reflex/components/el/__init__.pyi +0 -11
  50. reflex/components/el/element.pyi +16 -26
  51. reflex/components/el/elements/__init__.py +1 -7
  52. reflex/components/el/elements/__init__.pyi +1 -15
  53. reflex/components/el/elements/base.py +1 -1
  54. reflex/components/el/elements/base.pyi +33 -43
  55. reflex/components/el/elements/forms.py +26 -33
  56. reflex/components/el/elements/forms.pyi +542 -694
  57. reflex/components/el/elements/inline.py +1 -1
  58. reflex/components/el/elements/inline.pyi +909 -1189
  59. reflex/components/el/elements/media.py +1 -22
  60. reflex/components/el/elements/media.pyi +765 -975
  61. reflex/components/el/elements/metadata.py +3 -5
  62. reflex/components/el/elements/metadata.pyi +175 -235
  63. reflex/components/el/elements/other.py +1 -1
  64. reflex/components/el/elements/other.pyi +228 -298
  65. reflex/components/el/elements/scripts.py +1 -1
  66. reflex/components/el/elements/scripts.pyi +106 -136
  67. reflex/components/el/elements/sectioning.py +0 -2
  68. reflex/components/el/elements/sectioning.pyi +481 -631
  69. reflex/components/el/elements/tables.py +1 -1
  70. reflex/components/el/elements/tables.pyi +341 -441
  71. reflex/components/el/elements/typography.py +1 -1
  72. reflex/components/el/elements/typography.pyi +491 -641
  73. reflex/components/gridjs/datatable.py +9 -13
  74. reflex/components/gridjs/datatable.pyi +33 -53
  75. reflex/components/lucide/icon.py +3 -127
  76. reflex/components/lucide/icon.pyi +31 -160
  77. reflex/components/markdown/markdown.py +32 -42
  78. reflex/components/markdown/markdown.pyi +28 -41
  79. reflex/components/moment/moment.py +13 -12
  80. reflex/components/moment/moment.pyi +22 -33
  81. reflex/components/next/base.pyi +16 -26
  82. reflex/components/next/image.py +1 -5
  83. reflex/components/next/image.pyi +21 -35
  84. reflex/components/next/link.py +1 -1
  85. reflex/components/next/link.pyi +16 -26
  86. reflex/components/next/video.py +1 -1
  87. reflex/components/next/video.pyi +16 -26
  88. reflex/components/plotly/plotly.py +17 -30
  89. reflex/components/plotly/plotly.pyi +38 -52
  90. reflex/components/props.py +21 -10
  91. reflex/components/radix/__init__.pyi +2 -1
  92. reflex/components/radix/primitives/accordion.py +6 -7
  93. reflex/components/radix/primitives/accordion.pyi +415 -485
  94. reflex/components/radix/primitives/base.py +1 -1
  95. reflex/components/radix/primitives/base.pyi +31 -51
  96. reflex/components/radix/primitives/drawer.py +1 -1
  97. reflex/components/radix/primitives/drawer.pyi +162 -262
  98. reflex/components/radix/primitives/form.py +1 -1
  99. reflex/components/radix/primitives/form.pyi +247 -353
  100. reflex/components/radix/primitives/progress.py +1 -1
  101. reflex/components/radix/primitives/progress.pyi +226 -276
  102. reflex/components/radix/primitives/slider.py +1 -1
  103. reflex/components/radix/primitives/slider.pyi +82 -132
  104. reflex/components/radix/themes/base.py +8 -25
  105. reflex/components/radix/themes/base.pyi +171 -242
  106. reflex/components/radix/themes/color_mode.py +11 -20
  107. reflex/components/radix/themes/color_mode.pyi +198 -231
  108. reflex/components/radix/themes/components/__init__.pyi +1 -0
  109. reflex/components/radix/themes/components/alert_dialog.py +1 -1
  110. reflex/components/radix/themes/components/alert_dialog.pyi +129 -199
  111. reflex/components/radix/themes/components/aspect_ratio.py +1 -1
  112. reflex/components/radix/themes/components/aspect_ratio.pyi +16 -26
  113. reflex/components/radix/themes/components/avatar.py +1 -1
  114. reflex/components/radix/themes/components/avatar.pyi +69 -79
  115. reflex/components/radix/themes/components/badge.py +1 -1
  116. reflex/components/radix/themes/components/badge.pyi +87 -97
  117. reflex/components/radix/themes/components/button.py +1 -1
  118. reflex/components/radix/themes/components/button.pyi +97 -107
  119. reflex/components/radix/themes/components/callout.py +1 -1
  120. reflex/components/radix/themes/components/callout.pyi +317 -367
  121. reflex/components/radix/themes/components/card.py +1 -1
  122. reflex/components/radix/themes/components/card.pyi +37 -47
  123. reflex/components/radix/themes/components/checkbox.py +2 -4
  124. reflex/components/radix/themes/components/checkbox.pyi +205 -241
  125. reflex/components/radix/themes/components/checkbox_cards.py +1 -1
  126. reflex/components/radix/themes/components/checkbox_cards.pyi +92 -112
  127. reflex/components/radix/themes/components/checkbox_group.py +1 -1
  128. reflex/components/radix/themes/components/checkbox_group.pyi +84 -104
  129. reflex/components/radix/themes/components/context_menu.py +1 -1
  130. reflex/components/radix/themes/components/context_menu.pyi +230 -310
  131. reflex/components/radix/themes/components/data_list.py +6 -1
  132. reflex/components/radix/themes/components/data_list.pyi +131 -166
  133. reflex/components/radix/themes/components/dialog.py +1 -1
  134. reflex/components/radix/themes/components/dialog.pyi +132 -202
  135. reflex/components/radix/themes/components/dropdown_menu.py +1 -1
  136. reflex/components/radix/themes/components/dropdown_menu.pyi +241 -323
  137. reflex/components/radix/themes/components/hover_card.py +1 -1
  138. reflex/components/radix/themes/components/hover_card.pyi +86 -126
  139. reflex/components/radix/themes/components/icon_button.py +1 -1
  140. reflex/components/radix/themes/components/icon_button.pyi +97 -107
  141. reflex/components/radix/themes/components/inset.py +1 -1
  142. reflex/components/radix/themes/components/inset.pyi +46 -56
  143. reflex/components/radix/themes/components/popover.py +1 -1
  144. reflex/components/radix/themes/components/popover.pyi +91 -131
  145. reflex/components/radix/themes/components/progress.py +1 -1
  146. reflex/components/radix/themes/components/progress.pyi +70 -80
  147. reflex/components/radix/themes/components/radio.py +1 -1
  148. reflex/components/radix/themes/components/radio.pyi +68 -78
  149. reflex/components/radix/themes/components/radio_cards.py +1 -1
  150. reflex/components/radix/themes/components/radio_cards.pyi +96 -116
  151. reflex/components/radix/themes/components/radio_group.py +32 -31
  152. reflex/components/radix/themes/components/radio_group.pyi +230 -266
  153. reflex/components/radix/themes/components/scroll_area.py +1 -1
  154. reflex/components/radix/themes/components/scroll_area.pyi +20 -30
  155. reflex/components/radix/themes/components/segmented_control.py +1 -1
  156. reflex/components/radix/themes/components/segmented_control.pyi +88 -110
  157. reflex/components/radix/themes/components/select.py +1 -1
  158. reflex/components/radix/themes/components/select.pyi +365 -461
  159. reflex/components/radix/themes/components/separator.py +2 -4
  160. reflex/components/radix/themes/components/separator.pyi +68 -78
  161. reflex/components/radix/themes/components/skeleton.py +1 -1
  162. reflex/components/radix/themes/components/skeleton.pyi +22 -32
  163. reflex/components/radix/themes/components/slider.py +1 -1
  164. reflex/components/radix/themes/components/slider.pyi +74 -86
  165. reflex/components/radix/themes/components/spinner.py +1 -1
  166. reflex/components/radix/themes/components/spinner.pyi +18 -28
  167. reflex/components/radix/themes/components/switch.py +1 -1
  168. reflex/components/radix/themes/components/switch.pyi +70 -82
  169. reflex/components/radix/themes/components/table.py +1 -1
  170. reflex/components/radix/themes/components/table.pyi +254 -324
  171. reflex/components/radix/themes/components/tabs.py +1 -1
  172. reflex/components/radix/themes/components/tabs.pyi +134 -188
  173. reflex/components/radix/themes/components/text_area.py +1 -1
  174. reflex/components/radix/themes/components/text_area.pyi +95 -109
  175. reflex/components/radix/themes/components/text_field.py +1 -80
  176. reflex/components/radix/themes/components/text_field.pyi +245 -290
  177. reflex/components/radix/themes/components/tooltip.py +1 -1
  178. reflex/components/radix/themes/components/tooltip.pyi +25 -35
  179. reflex/components/radix/themes/layout/__init__.pyi +1 -0
  180. reflex/components/radix/themes/layout/base.py +1 -1
  181. reflex/components/radix/themes/layout/base.pyi +55 -65
  182. reflex/components/radix/themes/layout/box.pyi +33 -43
  183. reflex/components/radix/themes/layout/center.pyi +55 -65
  184. reflex/components/radix/themes/layout/container.py +2 -4
  185. reflex/components/radix/themes/layout/container.pyi +35 -45
  186. reflex/components/radix/themes/layout/flex.py +1 -1
  187. reflex/components/radix/themes/layout/flex.pyi +55 -65
  188. reflex/components/radix/themes/layout/grid.py +1 -1
  189. reflex/components/radix/themes/layout/grid.pyi +63 -73
  190. reflex/components/radix/themes/layout/list.py +1 -1
  191. reflex/components/radix/themes/layout/list.pyi +188 -238
  192. reflex/components/radix/themes/layout/section.py +2 -4
  193. reflex/components/radix/themes/layout/section.pyi +35 -45
  194. reflex/components/radix/themes/layout/spacer.pyi +55 -65
  195. reflex/components/radix/themes/layout/stack.py +1 -1
  196. reflex/components/radix/themes/layout/stack.pyi +125 -155
  197. reflex/components/radix/themes/typography/blockquote.py +1 -1
  198. reflex/components/radix/themes/typography/blockquote.pyi +88 -98
  199. reflex/components/radix/themes/typography/code.py +1 -1
  200. reflex/components/radix/themes/typography/code.pyi +89 -99
  201. reflex/components/radix/themes/typography/heading.py +1 -1
  202. reflex/components/radix/themes/typography/heading.pyi +95 -105
  203. reflex/components/radix/themes/typography/link.py +1 -1
  204. reflex/components/radix/themes/typography/link.pyi +101 -111
  205. reflex/components/radix/themes/typography/text.py +1 -1
  206. reflex/components/radix/themes/typography/text.pyi +494 -564
  207. reflex/components/react_player/audio.pyi +32 -58
  208. reflex/components/react_player/react_player.py +1 -1
  209. reflex/components/react_player/react_player.pyi +32 -58
  210. reflex/components/react_player/video.pyi +32 -58
  211. reflex/components/recharts/cartesian.py +22 -19
  212. reflex/components/recharts/cartesian.pyi +658 -840
  213. reflex/components/recharts/charts.py +3 -3
  214. reflex/components/recharts/charts.pyi +238 -342
  215. reflex/components/recharts/general.py +8 -8
  216. reflex/components/recharts/general.pyi +175 -225
  217. reflex/components/recharts/polar.py +11 -11
  218. reflex/components/recharts/polar.pyi +135 -171
  219. reflex/components/recharts/recharts.pyi +31 -51
  220. reflex/components/sonner/toast.py +27 -31
  221. reflex/components/sonner/toast.pyi +36 -45
  222. reflex/components/suneditor/editor.py +1 -1
  223. reflex/components/suneditor/editor.pyi +54 -76
  224. reflex/components/tags/cond_tag.py +6 -4
  225. reflex/components/tags/iter_tag.py +37 -25
  226. reflex/components/tags/match_tag.py +6 -4
  227. reflex/components/tags/tag.py +43 -28
  228. reflex/constants/base.py +3 -1
  229. reflex/constants/event.py +1 -0
  230. reflex/custom_components/custom_components.py +3 -1
  231. reflex/event.py +166 -108
  232. reflex/experimental/__init__.py +25 -6
  233. reflex/experimental/client_state.py +34 -57
  234. reflex/experimental/hooks.py +12 -17
  235. reflex/experimental/layout.py +4 -4
  236. reflex/experimental/layout.pyi +130 -180
  237. reflex/middleware/hydrate_middleware.py +2 -0
  238. reflex/middleware/middleware.py +3 -3
  239. reflex/model.py +22 -0
  240. reflex/reflex.py +4 -0
  241. reflex/state.py +491 -110
  242. reflex/style.py +56 -39
  243. reflex/testing.py +8 -3
  244. reflex/utils/exceptions.py +32 -0
  245. reflex/utils/exec.py +0 -14
  246. reflex/utils/format.py +80 -209
  247. reflex/utils/imports.py +16 -73
  248. reflex/utils/net.py +43 -0
  249. reflex/utils/path_ops.py +13 -1
  250. reflex/utils/prerequisites.py +81 -41
  251. reflex/utils/pyi_generator.py +12 -6
  252. reflex/utils/serializers.py +13 -41
  253. reflex/utils/telemetry.py +3 -2
  254. reflex/utils/types.py +47 -7
  255. reflex/{experimental/vars → vars}/__init__.py +6 -3
  256. reflex/vars/base.py +2563 -0
  257. reflex/vars/function.py +196 -0
  258. reflex/vars/number.py +1158 -0
  259. reflex/vars/object.py +562 -0
  260. reflex/vars/sequence.py +1604 -0
  261. {reflex-0.5.10a2.dist-info → reflex-0.6.0.dist-info}/METADATA +6 -9
  262. reflex-0.6.0.dist-info/RECORD +382 -0
  263. reflex/.templates/apps/demo/.gitignore +0 -4
  264. reflex/.templates/apps/demo/assets/favicon.ico +0 -0
  265. reflex/.templates/apps/demo/assets/github.svg +0 -10
  266. reflex/.templates/apps/demo/assets/icon.svg +0 -37
  267. reflex/.templates/apps/demo/assets/logo.svg +0 -68
  268. reflex/.templates/apps/demo/assets/paneleft.svg +0 -13
  269. reflex/.templates/apps/demo/code/__init__.py +0 -1
  270. reflex/.templates/apps/demo/code/demo.py +0 -127
  271. reflex/.templates/apps/demo/code/pages/__init__.py +0 -7
  272. reflex/.templates/apps/demo/code/pages/chatapp.py +0 -31
  273. reflex/.templates/apps/demo/code/pages/datatable.py +0 -360
  274. reflex/.templates/apps/demo/code/pages/forms.py +0 -257
  275. reflex/.templates/apps/demo/code/pages/graphing.py +0 -253
  276. reflex/.templates/apps/demo/code/pages/home.py +0 -56
  277. reflex/.templates/apps/demo/code/sidebar.py +0 -178
  278. reflex/.templates/apps/demo/code/state.py +0 -22
  279. reflex/.templates/apps/demo/code/states/form_state.py +0 -40
  280. reflex/.templates/apps/demo/code/states/pie_state.py +0 -47
  281. reflex/.templates/apps/demo/code/styles.py +0 -68
  282. reflex/.templates/apps/demo/code/webui/__init__.py +0 -0
  283. reflex/.templates/apps/demo/code/webui/components/__init__.py +0 -4
  284. reflex/.templates/apps/demo/code/webui/components/chat.py +0 -118
  285. reflex/.templates/apps/demo/code/webui/components/loading_icon.py +0 -19
  286. reflex/.templates/apps/demo/code/webui/components/modal.py +0 -56
  287. reflex/.templates/apps/demo/code/webui/components/navbar.py +0 -70
  288. reflex/.templates/apps/demo/code/webui/components/sidebar.py +0 -66
  289. reflex/.templates/apps/demo/code/webui/state.py +0 -146
  290. reflex/.templates/apps/demo/code/webui/styles.py +0 -88
  291. reflex/.templates/web/components/reflex/chakra_color_mode_provider.js +0 -36
  292. reflex/experimental/vars/base.py +0 -583
  293. reflex/experimental/vars/function.py +0 -290
  294. reflex/experimental/vars/number.py +0 -1458
  295. reflex/experimental/vars/object.py +0 -804
  296. reflex/experimental/vars/sequence.py +0 -1764
  297. reflex/utils/watch.py +0 -96
  298. reflex/vars.py +0 -2604
  299. reflex/vars.pyi +0 -218
  300. reflex-0.5.10a2.dist-info/RECORD +0 -413
  301. {reflex-0.5.10a2.dist-info → reflex-0.6.0.dist-info}/LICENSE +0 -0
  302. {reflex-0.5.10a2.dist-info → reflex-0.6.0.dist-info}/WHEEL +0 -0
  303. {reflex-0.5.10a2.dist-info → reflex-0.6.0.dist-info}/entry_points.txt +0 -0
@@ -1,583 +0,0 @@
1
- """Collection of base classes."""
2
-
3
- from __future__ import annotations
4
-
5
- import dataclasses
6
- import functools
7
- import inspect
8
- import sys
9
- from typing import (
10
- TYPE_CHECKING,
11
- Any,
12
- Callable,
13
- Dict,
14
- Generic,
15
- List,
16
- Optional,
17
- Set,
18
- Tuple,
19
- Type,
20
- TypeVar,
21
- Union,
22
- overload,
23
- )
24
-
25
- from typing_extensions import ParamSpec, get_origin
26
-
27
- from reflex import constants
28
- from reflex.base import Base
29
- from reflex.utils import serializers, types
30
- from reflex.utils.exceptions import VarTypeError
31
- from reflex.vars import (
32
- ImmutableVarData,
33
- Var,
34
- VarData,
35
- _decode_var_immutable,
36
- _extract_var_data,
37
- _global_vars,
38
- )
39
-
40
- if TYPE_CHECKING:
41
- from .function import FunctionVar, ToFunctionOperation
42
- from .number import (
43
- BooleanVar,
44
- NumberVar,
45
- ToBooleanVarOperation,
46
- ToNumberVarOperation,
47
- )
48
- from .object import ObjectVar, ToObjectOperation
49
- from .sequence import ArrayVar, StringVar, ToArrayOperation, ToStringOperation
50
-
51
- VAR_TYPE = TypeVar("VAR_TYPE")
52
-
53
-
54
- @dataclasses.dataclass(
55
- eq=False,
56
- frozen=True,
57
- **{"slots": True} if sys.version_info >= (3, 10) else {},
58
- )
59
- class ImmutableVar(Var, Generic[VAR_TYPE]):
60
- """Base class for immutable vars."""
61
-
62
- # The name of the var.
63
- _var_name: str = dataclasses.field()
64
-
65
- # The type of the var.
66
- _var_type: types.GenericType = dataclasses.field(default=Any)
67
-
68
- # Extra metadata associated with the Var
69
- _var_data: Optional[ImmutableVarData] = dataclasses.field(default=None)
70
-
71
- def __str__(self) -> str:
72
- """String representation of the var. Guaranteed to be a valid Javascript expression.
73
-
74
- Returns:
75
- The name of the var.
76
- """
77
- return self._var_name
78
-
79
- @property
80
- def _var_is_local(self) -> bool:
81
- """Whether this is a local javascript variable.
82
-
83
- Returns:
84
- False
85
- """
86
- return False
87
-
88
- @property
89
- def _var_is_string(self) -> bool:
90
- """Whether the var is a string literal.
91
-
92
- Returns:
93
- False
94
- """
95
- return False
96
-
97
- @property
98
- def _var_full_name_needs_state_prefix(self) -> bool:
99
- """Whether the full name of the var needs a _var_state prefix.
100
-
101
- Returns:
102
- False
103
- """
104
- return False
105
-
106
- def __post_init__(self):
107
- """Post-initialize the var."""
108
- # Decode any inline Var markup and apply it to the instance
109
- _var_data, _var_name = _decode_var_immutable(self._var_name)
110
-
111
- if _var_data or _var_name != self._var_name:
112
- self.__init__(
113
- _var_name=_var_name,
114
- _var_type=self._var_type,
115
- _var_data=ImmutableVarData.merge(self._var_data, _var_data),
116
- )
117
-
118
- def __hash__(self) -> int:
119
- """Define a hash function for the var.
120
-
121
- Returns:
122
- The hash of the var.
123
- """
124
- return hash((self._var_name, self._var_type, self._var_data))
125
-
126
- def _get_all_var_data(self) -> ImmutableVarData | None:
127
- """Get all VarData associated with the Var.
128
-
129
- Returns:
130
- The VarData of the components and all of its children.
131
- """
132
- return self._var_data
133
-
134
- def _replace(self, merge_var_data=None, **kwargs: Any):
135
- """Make a copy of this Var with updated fields.
136
-
137
- Args:
138
- merge_var_data: VarData to merge into the existing VarData.
139
- **kwargs: Var fields to update.
140
-
141
- Returns:
142
- A new ImmutableVar with the updated fields overwriting the corresponding fields in this Var.
143
-
144
- Raises:
145
- TypeError: If _var_is_local, _var_is_string, or _var_full_name_needs_state_prefix is not None.
146
- """
147
- if kwargs.get("_var_is_local", False) is not False:
148
- raise TypeError(
149
- "The _var_is_local argument is not supported for ImmutableVar."
150
- )
151
-
152
- if kwargs.get("_var_is_string", False) is not False:
153
- raise TypeError(
154
- "The _var_is_string argument is not supported for ImmutableVar."
155
- )
156
-
157
- if kwargs.get("_var_full_name_needs_state_prefix", False) is not False:
158
- raise TypeError(
159
- "The _var_full_name_needs_state_prefix argument is not supported for ImmutableVar."
160
- )
161
-
162
- field_values = dict(
163
- _var_name=kwargs.pop("_var_name", self._var_name),
164
- _var_type=kwargs.pop("_var_type", self._var_type),
165
- _var_data=ImmutableVarData.merge(
166
- kwargs.get("_var_data", self._var_data), merge_var_data
167
- ),
168
- )
169
- return type(self)(**field_values)
170
-
171
- @classmethod
172
- def create(
173
- cls,
174
- value: Any,
175
- _var_is_local: bool | None = None,
176
- _var_is_string: bool | None = None,
177
- _var_data: VarData | None = None,
178
- ) -> ImmutableVar | Var | None:
179
- """Create a var from a value.
180
-
181
- Args:
182
- value: The value to create the var from.
183
- _var_is_local: Whether the var is local. Deprecated.
184
- _var_is_string: Whether the var is a string literal. Deprecated.
185
- _var_data: Additional hooks and imports associated with the Var.
186
-
187
- Returns:
188
- The var.
189
-
190
- Raises:
191
- VarTypeError: If the value is JSON-unserializable.
192
- TypeError: If _var_is_local or _var_is_string is not None.
193
- """
194
- if _var_is_local is not None:
195
- raise TypeError(
196
- "The _var_is_local argument is not supported for ImmutableVar."
197
- )
198
-
199
- if _var_is_string is not None:
200
- raise TypeError(
201
- "The _var_is_string argument is not supported for ImmutableVar."
202
- )
203
-
204
- from reflex.utils import format
205
-
206
- # Check for none values.
207
- if value is None:
208
- return None
209
-
210
- # If the value is already a var, do nothing.
211
- if isinstance(value, Var):
212
- return value
213
-
214
- # Try to pull the imports and hooks from contained values.
215
- if not isinstance(value, str):
216
- _var_data = VarData.merge(*_extract_var_data(value), _var_data)
217
-
218
- # Try to serialize the value.
219
- type_ = type(value)
220
- if type_ in types.JSONType:
221
- name = value
222
- else:
223
- name, _serialized_type = serializers.serialize(value, get_type=True)
224
- if name is None:
225
- raise VarTypeError(
226
- f"No JSON serializer found for var {value} of type {type_}."
227
- )
228
- name = name if isinstance(name, str) else format.json_dumps(name)
229
-
230
- return cls(
231
- _var_name=name,
232
- _var_type=type_,
233
- _var_data=(
234
- ImmutableVarData(
235
- state=_var_data.state,
236
- imports=_var_data.imports,
237
- hooks=_var_data.hooks,
238
- )
239
- if _var_data
240
- else None
241
- ),
242
- )
243
-
244
- @classmethod
245
- def create_safe(
246
- cls,
247
- value: Any,
248
- _var_is_local: bool | None = None,
249
- _var_is_string: bool | None = None,
250
- _var_data: VarData | None = None,
251
- ) -> Var | ImmutableVar:
252
- """Create a var from a value, asserting that it is not None.
253
-
254
- Args:
255
- value: The value to create the var from.
256
- _var_is_local: Whether the var is local. Deprecated.
257
- _var_is_string: Whether the var is a string literal. Deprecated.
258
- _var_data: Additional hooks and imports associated with the Var.
259
-
260
- Returns:
261
- The var.
262
- """
263
- var = cls.create(
264
- value,
265
- _var_is_local=_var_is_local,
266
- _var_is_string=_var_is_string,
267
- _var_data=_var_data,
268
- )
269
- assert var is not None
270
- return var
271
-
272
- def __format__(self, format_spec: str) -> str:
273
- """Format the var into a Javascript equivalent to an f-string.
274
-
275
- Args:
276
- format_spec: The format specifier (Ignored for now).
277
-
278
- Returns:
279
- The formatted var.
280
- """
281
- hashed_var = hash(self)
282
-
283
- _global_vars[hashed_var] = self
284
-
285
- # Encode the _var_data into the formatted output for tracking purposes.
286
- return f"{constants.REFLEX_VAR_OPENING_TAG}{hashed_var}{constants.REFLEX_VAR_CLOSING_TAG}{self._var_name}"
287
-
288
- @overload
289
- def to(
290
- self, output: Type[NumberVar], var_type: type[int] | type[float] = float
291
- ) -> ToNumberVarOperation: ...
292
-
293
- @overload
294
- def to(self, output: Type[BooleanVar]) -> ToBooleanVarOperation: ...
295
-
296
- @overload
297
- def to(
298
- self,
299
- output: Type[ArrayVar],
300
- var_type: type[list] | type[tuple] | type[set] = list,
301
- ) -> ToArrayOperation: ...
302
-
303
- @overload
304
- def to(self, output: Type[StringVar]) -> ToStringOperation: ...
305
-
306
- @overload
307
- def to(
308
- self, output: Type[ObjectVar], var_type: types.GenericType = dict
309
- ) -> ToObjectOperation: ...
310
-
311
- @overload
312
- def to(
313
- self, output: Type[FunctionVar], var_type: Type[Callable] = Callable
314
- ) -> ToFunctionOperation: ...
315
-
316
- @overload
317
- def to(
318
- self, output: Type[OUTPUT], var_type: types.GenericType | None = None
319
- ) -> OUTPUT: ...
320
-
321
- def to(
322
- self, output: Type[OUTPUT], var_type: types.GenericType | None = None
323
- ) -> Var:
324
- """Convert the var to a different type.
325
-
326
- Args:
327
- output: The output type.
328
- var_type: The type of the var.
329
-
330
- Raises:
331
- TypeError: If the var_type is not a supported type for the output.
332
-
333
- Returns:
334
- The converted var.
335
- """
336
- from .number import (
337
- BooleanVar,
338
- NumberVar,
339
- ToBooleanVarOperation,
340
- ToNumberVarOperation,
341
- )
342
-
343
- fixed_type = (
344
- var_type
345
- if var_type is None or inspect.isclass(var_type)
346
- else get_origin(var_type)
347
- )
348
-
349
- if issubclass(output, NumberVar):
350
- if fixed_type is not None and not issubclass(fixed_type, (int, float)):
351
- raise TypeError(
352
- f"Unsupported type {var_type} for NumberVar. Must be int or float."
353
- )
354
- return ToNumberVarOperation(self, var_type or float)
355
- if issubclass(output, BooleanVar):
356
- return ToBooleanVarOperation(self)
357
-
358
- from .sequence import ArrayVar, StringVar, ToArrayOperation, ToStringOperation
359
-
360
- if issubclass(output, ArrayVar):
361
- if fixed_type is not None and not issubclass(
362
- fixed_type, (list, tuple, set)
363
- ):
364
- raise TypeError(
365
- f"Unsupported type {var_type} for ArrayVar. Must be list, tuple, or set."
366
- )
367
- return ToArrayOperation(self, var_type or list)
368
- if issubclass(output, StringVar):
369
- return ToStringOperation(self)
370
-
371
- from .object import ObjectVar, ToObjectOperation
372
-
373
- if issubclass(output, ObjectVar):
374
- return ToObjectOperation(self, var_type or dict)
375
-
376
- from .function import FunctionVar, ToFunctionOperation
377
-
378
- if issubclass(output, FunctionVar):
379
- if fixed_type is not None and not issubclass(fixed_type, Callable):
380
- raise TypeError(
381
- f"Unsupported type {var_type} for FunctionVar. Must be Callable."
382
- )
383
- return ToFunctionOperation(self, var_type or Callable)
384
-
385
- return output(
386
- _var_name=self._var_name,
387
- _var_type=self._var_type if var_type is None else var_type,
388
- _var_data=self._var_data,
389
- )
390
-
391
- def guess_type(self) -> ImmutableVar:
392
- """Guess the type of the var.
393
-
394
- Returns:
395
- The guessed type.
396
- """
397
- from .number import NumberVar
398
- from .object import ObjectVar
399
- from .sequence import ArrayVar, StringVar
400
-
401
- if self._var_type is Any:
402
- return self
403
-
404
- var_type = self._var_type
405
-
406
- fixed_type = var_type if inspect.isclass(var_type) else get_origin(var_type)
407
-
408
- if issubclass(fixed_type, (int, float)):
409
- return self.to(NumberVar, var_type)
410
- if issubclass(fixed_type, dict):
411
- return self.to(ObjectVar, var_type)
412
- if issubclass(fixed_type, (list, tuple, set)):
413
- return self.to(ArrayVar, var_type)
414
- if issubclass(fixed_type, str):
415
- return self.to(StringVar)
416
- if issubclass(fixed_type, Base):
417
- return self.to(ObjectVar, var_type)
418
- return self
419
-
420
-
421
- OUTPUT = TypeVar("OUTPUT", bound=ImmutableVar)
422
-
423
-
424
- class LiteralVar(ImmutableVar):
425
- """Base class for immutable literal vars."""
426
-
427
- @classmethod
428
- def create(
429
- cls,
430
- value: Any,
431
- _var_data: VarData | None = None,
432
- ) -> Var:
433
- """Create a var from a value.
434
-
435
- Args:
436
- value: The value to create the var from.
437
- _var_data: Additional hooks and imports associated with the Var.
438
-
439
- Returns:
440
- The var.
441
-
442
- Raises:
443
- TypeError: If the value is not a supported type for LiteralVar.
444
- """
445
- if isinstance(value, Var):
446
- if _var_data is None:
447
- return value
448
- return value._replace(merge_var_data=_var_data)
449
-
450
- if value is None:
451
- return ImmutableVar.create_safe("null", _var_data=_var_data)
452
-
453
- from .object import LiteralObjectVar
454
-
455
- if isinstance(value, Base):
456
- return LiteralObjectVar(
457
- value.dict(), _var_type=type(value), _var_data=_var_data
458
- )
459
-
460
- from .number import LiteralBooleanVar, LiteralNumberVar
461
- from .sequence import LiteralArrayVar, LiteralStringVar
462
-
463
- if isinstance(value, str):
464
- return LiteralStringVar.create(value, _var_data=_var_data)
465
-
466
- type_mapping = {
467
- int: LiteralNumberVar,
468
- float: LiteralNumberVar,
469
- bool: LiteralBooleanVar,
470
- dict: LiteralObjectVar,
471
- list: LiteralArrayVar,
472
- tuple: LiteralArrayVar,
473
- set: LiteralArrayVar,
474
- }
475
-
476
- constructor = type_mapping.get(type(value))
477
-
478
- if constructor is None:
479
- raise TypeError(f"Unsupported type {type(value)} for LiteralVar.")
480
-
481
- return constructor(value, _var_data=_var_data)
482
-
483
- def __post_init__(self):
484
- """Post-initialize the var."""
485
-
486
- def json(self) -> str:
487
- """Serialize the var to a JSON string.
488
-
489
- Raises:
490
- NotImplementedError: If the method is not implemented.
491
- """
492
- raise NotImplementedError(
493
- "LiteralVar subclasses must implement the json method."
494
- )
495
-
496
-
497
- P = ParamSpec("P")
498
- T = TypeVar("T", bound=ImmutableVar)
499
-
500
-
501
- def var_operation(*, output: Type[T]) -> Callable[[Callable[P, str]], Callable[P, T]]:
502
- """Decorator for creating a var operation.
503
-
504
- Example:
505
- ```python
506
- @var_operation(output=NumberVar)
507
- def add(a: NumberVar, b: NumberVar):
508
- return f"({a} + {b})"
509
- ```
510
-
511
- Args:
512
- output: The output type of the operation.
513
-
514
- Returns:
515
- The decorator.
516
- """
517
-
518
- def decorator(func: Callable[P, str], output=output):
519
- @functools.wraps(func)
520
- def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
521
- args_vars = [
522
- LiteralVar.create(arg) if not isinstance(arg, Var) else arg
523
- for arg in args
524
- ]
525
- kwargs_vars = {
526
- key: LiteralVar.create(value) if not isinstance(value, Var) else value
527
- for key, value in kwargs.items()
528
- }
529
- return output(
530
- _var_name=func(*args_vars, **kwargs_vars), # type: ignore
531
- _var_data=VarData.merge(
532
- *[arg._get_all_var_data() for arg in args if isinstance(arg, Var)],
533
- *[
534
- arg._get_all_var_data()
535
- for arg in kwargs.values()
536
- if isinstance(arg, Var)
537
- ],
538
- ),
539
- )
540
-
541
- return wrapper
542
-
543
- return decorator
544
-
545
-
546
- def unionize(*args: Type) -> Type:
547
- """Unionize the types.
548
-
549
- Args:
550
- args: The types to unionize.
551
-
552
- Returns:
553
- The unionized types.
554
- """
555
- if not args:
556
- return Any
557
- first, *rest = args
558
- if not rest:
559
- return first
560
- return Union[first, unionize(*rest)]
561
-
562
-
563
- def figure_out_type(value: Any) -> Type:
564
- """Figure out the type of the value.
565
-
566
- Args:
567
- value: The value to figure out the type of.
568
-
569
- Returns:
570
- The type of the value.
571
- """
572
- if isinstance(value, list):
573
- return List[unionize(*(figure_out_type(v) for v in value))]
574
- if isinstance(value, set):
575
- return Set[unionize(*(figure_out_type(v) for v in value))]
576
- if isinstance(value, tuple):
577
- return Tuple[unionize(*(figure_out_type(v) for v in value)), ...]
578
- if isinstance(value, dict):
579
- return Dict[
580
- unionize(*(figure_out_type(k) for k in value)),
581
- unionize(*(figure_out_type(v) for v in value.values())),
582
- ]
583
- return type(value)