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
reflex/vars/object.py ADDED
@@ -0,0 +1,562 @@
1
+ """Classes for immutable object vars."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import dataclasses
6
+ import sys
7
+ import typing
8
+ from inspect import isclass
9
+ from typing import (
10
+ Any,
11
+ ClassVar,
12
+ Dict,
13
+ List,
14
+ NoReturn,
15
+ Tuple,
16
+ Type,
17
+ TypeVar,
18
+ Union,
19
+ get_args,
20
+ overload,
21
+ )
22
+
23
+ from reflex.utils import types
24
+ from reflex.utils.exceptions import VarAttributeError
25
+ from reflex.utils.types import GenericType, get_attribute_access_type, get_origin
26
+
27
+ from .base import (
28
+ CachedVarOperation,
29
+ LiteralVar,
30
+ ToOperation,
31
+ Var,
32
+ VarData,
33
+ cached_property_no_lock,
34
+ figure_out_type,
35
+ var_operation,
36
+ var_operation_return,
37
+ )
38
+ from .number import BooleanVar, NumberVar, raise_unsupported_operand_types
39
+ from .sequence import ArrayVar, StringVar
40
+
41
+ OBJECT_TYPE = TypeVar("OBJECT_TYPE", bound=Dict)
42
+
43
+ KEY_TYPE = TypeVar("KEY_TYPE")
44
+ VALUE_TYPE = TypeVar("VALUE_TYPE")
45
+
46
+ ARRAY_INNER_TYPE = TypeVar("ARRAY_INNER_TYPE")
47
+
48
+ OTHER_KEY_TYPE = TypeVar("OTHER_KEY_TYPE")
49
+
50
+
51
+ class ObjectVar(Var[OBJECT_TYPE]):
52
+ """Base class for immutable object vars."""
53
+
54
+ def _key_type(self) -> Type:
55
+ """Get the type of the keys of the object.
56
+
57
+ Returns:
58
+ The type of the keys of the object.
59
+ """
60
+ return str
61
+
62
+ @overload
63
+ def _value_type(
64
+ self: ObjectVar[Dict[KEY_TYPE, VALUE_TYPE]],
65
+ ) -> Type[VALUE_TYPE]: ...
66
+
67
+ @overload
68
+ def _value_type(self) -> Type: ...
69
+
70
+ def _value_type(self) -> Type:
71
+ """Get the type of the values of the object.
72
+
73
+ Returns:
74
+ The type of the values of the object.
75
+ """
76
+ fixed_type = get_origin(self._var_type) or self._var_type
77
+ if not isclass(fixed_type):
78
+ return Any
79
+ args = get_args(self._var_type) if issubclass(fixed_type, dict) else ()
80
+ return args[1] if args else Any
81
+
82
+ def keys(self) -> ArrayVar[List[str]]:
83
+ """Get the keys of the object.
84
+
85
+ Returns:
86
+ The keys of the object.
87
+ """
88
+ return object_keys_operation(self)
89
+
90
+ @overload
91
+ def values(
92
+ self: ObjectVar[Dict[KEY_TYPE, VALUE_TYPE]],
93
+ ) -> ArrayVar[List[VALUE_TYPE]]: ...
94
+
95
+ @overload
96
+ def values(self) -> ArrayVar: ...
97
+
98
+ def values(self) -> ArrayVar:
99
+ """Get the values of the object.
100
+
101
+ Returns:
102
+ The values of the object.
103
+ """
104
+ return object_values_operation(self)
105
+
106
+ @overload
107
+ def entries(
108
+ self: ObjectVar[Dict[KEY_TYPE, VALUE_TYPE]],
109
+ ) -> ArrayVar[List[Tuple[str, VALUE_TYPE]]]: ...
110
+
111
+ @overload
112
+ def entries(self) -> ArrayVar: ...
113
+
114
+ def entries(self) -> ArrayVar:
115
+ """Get the entries of the object.
116
+
117
+ Returns:
118
+ The entries of the object.
119
+ """
120
+ return object_entries_operation(self)
121
+
122
+ def merge(self, other: ObjectVar):
123
+ """Merge two objects.
124
+
125
+ Args:
126
+ other: The other object to merge.
127
+
128
+ Returns:
129
+ The merged object.
130
+ """
131
+ return object_merge_operation(self, other)
132
+
133
+ # NoReturn is used here to catch when key value is Any
134
+ @overload
135
+ def __getitem__(
136
+ self: ObjectVar[Dict[KEY_TYPE, NoReturn]],
137
+ key: Var | Any,
138
+ ) -> Var: ...
139
+
140
+ @overload
141
+ def __getitem__(
142
+ self: (
143
+ ObjectVar[Dict[KEY_TYPE, int]]
144
+ | ObjectVar[Dict[KEY_TYPE, float]]
145
+ | ObjectVar[Dict[KEY_TYPE, int | float]]
146
+ ),
147
+ key: Var | Any,
148
+ ) -> NumberVar: ...
149
+
150
+ @overload
151
+ def __getitem__(
152
+ self: ObjectVar[Dict[KEY_TYPE, str]],
153
+ key: Var | Any,
154
+ ) -> StringVar: ...
155
+
156
+ @overload
157
+ def __getitem__(
158
+ self: ObjectVar[Dict[KEY_TYPE, list[ARRAY_INNER_TYPE]]],
159
+ key: Var | Any,
160
+ ) -> ArrayVar[list[ARRAY_INNER_TYPE]]: ...
161
+
162
+ @overload
163
+ def __getitem__(
164
+ self: ObjectVar[Dict[KEY_TYPE, set[ARRAY_INNER_TYPE]]],
165
+ key: Var | Any,
166
+ ) -> ArrayVar[set[ARRAY_INNER_TYPE]]: ...
167
+
168
+ @overload
169
+ def __getitem__(
170
+ self: ObjectVar[Dict[KEY_TYPE, tuple[ARRAY_INNER_TYPE, ...]]],
171
+ key: Var | Any,
172
+ ) -> ArrayVar[tuple[ARRAY_INNER_TYPE, ...]]: ...
173
+
174
+ @overload
175
+ def __getitem__(
176
+ self: ObjectVar[Dict[KEY_TYPE, dict[OTHER_KEY_TYPE, VALUE_TYPE]]],
177
+ key: Var | Any,
178
+ ) -> ObjectVar[dict[OTHER_KEY_TYPE, VALUE_TYPE]]: ...
179
+
180
+ def __getitem__(self, key: Var | Any) -> Var:
181
+ """Get an item from the object.
182
+
183
+ Args:
184
+ key: The key to get from the object.
185
+
186
+ Returns:
187
+ The item from the object.
188
+ """
189
+ if not isinstance(key, (StringVar, str, int, NumberVar)) or (
190
+ isinstance(key, NumberVar) and key._is_strict_float()
191
+ ):
192
+ raise_unsupported_operand_types("[]", (type(self), type(key)))
193
+ return ObjectItemOperation.create(self, key).guess_type()
194
+
195
+ # NoReturn is used here to catch when key value is Any
196
+ @overload
197
+ def __getattr__(
198
+ self: ObjectVar[Dict[KEY_TYPE, NoReturn]],
199
+ name: str,
200
+ ) -> Var: ...
201
+
202
+ @overload
203
+ def __getattr__(
204
+ self: (
205
+ ObjectVar[Dict[KEY_TYPE, int]]
206
+ | ObjectVar[Dict[KEY_TYPE, float]]
207
+ | ObjectVar[Dict[KEY_TYPE, int | float]]
208
+ ),
209
+ name: str,
210
+ ) -> NumberVar: ...
211
+
212
+ @overload
213
+ def __getattr__(
214
+ self: ObjectVar[Dict[KEY_TYPE, str]],
215
+ name: str,
216
+ ) -> StringVar: ...
217
+
218
+ @overload
219
+ def __getattr__(
220
+ self: ObjectVar[Dict[KEY_TYPE, list[ARRAY_INNER_TYPE]]],
221
+ name: str,
222
+ ) -> ArrayVar[list[ARRAY_INNER_TYPE]]: ...
223
+
224
+ @overload
225
+ def __getattr__(
226
+ self: ObjectVar[Dict[KEY_TYPE, set[ARRAY_INNER_TYPE]]],
227
+ name: str,
228
+ ) -> ArrayVar[set[ARRAY_INNER_TYPE]]: ...
229
+
230
+ @overload
231
+ def __getattr__(
232
+ self: ObjectVar[Dict[KEY_TYPE, tuple[ARRAY_INNER_TYPE, ...]]],
233
+ name: str,
234
+ ) -> ArrayVar[tuple[ARRAY_INNER_TYPE, ...]]: ...
235
+
236
+ @overload
237
+ def __getattr__(
238
+ self: ObjectVar[Dict[KEY_TYPE, dict[OTHER_KEY_TYPE, VALUE_TYPE]]],
239
+ name: str,
240
+ ) -> ObjectVar[dict[OTHER_KEY_TYPE, VALUE_TYPE]]: ...
241
+
242
+ def __getattr__(self, name) -> Var:
243
+ """Get an attribute of the var.
244
+
245
+ Args:
246
+ name: The name of the attribute.
247
+
248
+ Raises:
249
+ VarAttributeError: The State var has no such attribute or may have been annotated wrongly.
250
+
251
+ Returns:
252
+ The attribute of the var.
253
+ """
254
+ if name.startswith("__") and name.endswith("__"):
255
+ return getattr(super(type(self), self), name)
256
+
257
+ var_type = self._var_type
258
+
259
+ if types.is_optional(var_type):
260
+ var_type = get_args(var_type)[0]
261
+
262
+ fixed_type = var_type if isclass(var_type) else get_origin(var_type)
263
+ if isclass(fixed_type) and not issubclass(fixed_type, dict):
264
+ attribute_type = get_attribute_access_type(var_type, name)
265
+ if attribute_type is None:
266
+ raise VarAttributeError(
267
+ f"The State var `{str(self)}` has no attribute '{name}' or may have been annotated "
268
+ f"wrongly."
269
+ )
270
+ return ObjectItemOperation.create(self, name, attribute_type).guess_type()
271
+ else:
272
+ return ObjectItemOperation.create(self, name).guess_type()
273
+
274
+ def contains(self, key: Var | Any) -> BooleanVar:
275
+ """Check if the object contains a key.
276
+
277
+ Args:
278
+ key: The key to check.
279
+
280
+ Returns:
281
+ The result of the check.
282
+ """
283
+ return object_has_own_property_operation(self, key)
284
+
285
+
286
+ @dataclasses.dataclass(
287
+ eq=False,
288
+ frozen=True,
289
+ **{"slots": True} if sys.version_info >= (3, 10) else {},
290
+ )
291
+ class LiteralObjectVar(CachedVarOperation, ObjectVar[OBJECT_TYPE], LiteralVar):
292
+ """Base class for immutable literal object vars."""
293
+
294
+ _var_value: Dict[Union[Var, Any], Union[Var, Any]] = dataclasses.field(
295
+ default_factory=dict
296
+ )
297
+
298
+ def _key_type(self) -> Type:
299
+ """Get the type of the keys of the object.
300
+
301
+ Returns:
302
+ The type of the keys of the object.
303
+ """
304
+ args_list = typing.get_args(self._var_type)
305
+ return args_list[0] if args_list else Any
306
+
307
+ def _value_type(self) -> Type:
308
+ """Get the type of the values of the object.
309
+
310
+ Returns:
311
+ The type of the values of the object.
312
+ """
313
+ args_list = typing.get_args(self._var_type)
314
+ return args_list[1] if args_list else Any
315
+
316
+ @cached_property_no_lock
317
+ def _cached_var_name(self) -> str:
318
+ """The name of the var.
319
+
320
+ Returns:
321
+ The name of the var.
322
+ """
323
+ return (
324
+ "({ "
325
+ + ", ".join(
326
+ [
327
+ f"[{str(LiteralVar.create(key))}] : {str(LiteralVar.create(value))}"
328
+ for key, value in self._var_value.items()
329
+ ]
330
+ )
331
+ + " })"
332
+ )
333
+
334
+ def json(self) -> str:
335
+ """Get the JSON representation of the object.
336
+
337
+ Returns:
338
+ The JSON representation of the object.
339
+ """
340
+ return (
341
+ "{"
342
+ + ", ".join(
343
+ [
344
+ f"{LiteralVar.create(key).json()}:{LiteralVar.create(value).json()}"
345
+ for key, value in self._var_value.items()
346
+ ]
347
+ )
348
+ + "}"
349
+ )
350
+
351
+ def __hash__(self) -> int:
352
+ """Get the hash of the var.
353
+
354
+ Returns:
355
+ The hash of the var.
356
+ """
357
+ return hash((self.__class__.__name__, self._js_expr))
358
+
359
+ @cached_property_no_lock
360
+ def _cached_get_all_var_data(self) -> VarData | None:
361
+ """Get all the var data.
362
+
363
+ Returns:
364
+ The var data.
365
+ """
366
+ return VarData.merge(
367
+ *[LiteralVar.create(var)._get_all_var_data() for var in self._var_value],
368
+ *[
369
+ LiteralVar.create(var)._get_all_var_data()
370
+ for var in self._var_value.values()
371
+ ],
372
+ self._var_data,
373
+ )
374
+
375
+ @classmethod
376
+ def create(
377
+ cls,
378
+ _var_value: OBJECT_TYPE,
379
+ _var_type: GenericType | None = None,
380
+ _var_data: VarData | None = None,
381
+ ) -> LiteralObjectVar[OBJECT_TYPE]:
382
+ """Create the literal object var.
383
+
384
+ Args:
385
+ _var_value: The value of the var.
386
+ _var_type: The type of the var.
387
+ _var_data: Additional hooks and imports associated with the Var.
388
+
389
+ Returns:
390
+ The literal object var.
391
+ """
392
+ return LiteralObjectVar(
393
+ _js_expr="",
394
+ _var_type=(figure_out_type(_var_value) if _var_type is None else _var_type),
395
+ _var_data=_var_data,
396
+ _var_value=_var_value,
397
+ )
398
+
399
+
400
+ @var_operation
401
+ def object_keys_operation(value: ObjectVar):
402
+ """Get the keys of an object.
403
+
404
+ Args:
405
+ value: The object to get the keys from.
406
+
407
+ Returns:
408
+ The keys of the object.
409
+ """
410
+ return var_operation_return(
411
+ js_expression=f"Object.keys({value})",
412
+ var_type=List[str],
413
+ )
414
+
415
+
416
+ @var_operation
417
+ def object_values_operation(value: ObjectVar):
418
+ """Get the values of an object.
419
+
420
+ Args:
421
+ value: The object to get the values from.
422
+
423
+ Returns:
424
+ The values of the object.
425
+ """
426
+ return var_operation_return(
427
+ js_expression=f"Object.values({value})",
428
+ var_type=List[value._value_type()],
429
+ )
430
+
431
+
432
+ @var_operation
433
+ def object_entries_operation(value: ObjectVar):
434
+ """Get the entries of an object.
435
+
436
+ Args:
437
+ value: The object to get the entries from.
438
+
439
+ Returns:
440
+ The entries of the object.
441
+ """
442
+ return var_operation_return(
443
+ js_expression=f"Object.entries({value})",
444
+ var_type=List[Tuple[str, value._value_type()]],
445
+ )
446
+
447
+
448
+ @var_operation
449
+ def object_merge_operation(lhs: ObjectVar, rhs: ObjectVar):
450
+ """Merge two objects.
451
+
452
+ Args:
453
+ lhs: The first object to merge.
454
+ rhs: The second object to merge.
455
+
456
+ Returns:
457
+ The merged object.
458
+ """
459
+ return var_operation_return(
460
+ js_expression=f"({{...{lhs}, ...{rhs}}})",
461
+ var_type=Dict[
462
+ Union[lhs._key_type(), rhs._key_type()],
463
+ Union[lhs._value_type(), rhs._value_type()],
464
+ ],
465
+ )
466
+
467
+
468
+ @dataclasses.dataclass(
469
+ eq=False,
470
+ frozen=True,
471
+ **{"slots": True} if sys.version_info >= (3, 10) else {},
472
+ )
473
+ class ObjectItemOperation(CachedVarOperation, Var):
474
+ """Operation to get an item from an object."""
475
+
476
+ _object: ObjectVar = dataclasses.field(
477
+ default_factory=lambda: LiteralObjectVar.create({})
478
+ )
479
+ _key: Var | Any = dataclasses.field(default_factory=lambda: LiteralVar.create(None))
480
+
481
+ @cached_property_no_lock
482
+ def _cached_var_name(self) -> str:
483
+ """The name of the operation.
484
+
485
+ Returns:
486
+ The name of the operation.
487
+ """
488
+ if types.is_optional(self._object._var_type):
489
+ return f"{str(self._object)}?.[{str(self._key)}]"
490
+ return f"{str(self._object)}[{str(self._key)}]"
491
+
492
+ @classmethod
493
+ def create(
494
+ cls,
495
+ object: ObjectVar,
496
+ key: Var | Any,
497
+ _var_type: GenericType | None = None,
498
+ _var_data: VarData | None = None,
499
+ ) -> ObjectItemOperation:
500
+ """Create the object item operation.
501
+
502
+ Args:
503
+ object: The object to get the item from.
504
+ key: The key to get from the object.
505
+ _var_type: The type of the item.
506
+ _var_data: Additional hooks and imports associated with the operation.
507
+
508
+ Returns:
509
+ The object item operation.
510
+ """
511
+ return cls(
512
+ _js_expr="",
513
+ _var_type=object._value_type() if _var_type is None else _var_type,
514
+ _var_data=_var_data,
515
+ _object=object,
516
+ _key=key if isinstance(key, Var) else LiteralVar.create(key),
517
+ )
518
+
519
+
520
+ @dataclasses.dataclass(
521
+ eq=False,
522
+ frozen=True,
523
+ **{"slots": True} if sys.version_info >= (3, 10) else {},
524
+ )
525
+ class ToObjectOperation(ToOperation, ObjectVar):
526
+ """Operation to convert a var to an object."""
527
+
528
+ _original: Var = dataclasses.field(
529
+ default_factory=lambda: LiteralObjectVar.create({})
530
+ )
531
+
532
+ _default_var_type: ClassVar[GenericType] = dict
533
+
534
+ def __getattr__(self, name: str) -> Any:
535
+ """Get an attribute of the var.
536
+
537
+ Args:
538
+ name: The name of the attribute.
539
+
540
+ Returns:
541
+ The attribute of the var.
542
+ """
543
+ if name == "_js_expr":
544
+ return self._original._js_expr
545
+ return ObjectVar.__getattr__(self, name)
546
+
547
+
548
+ @var_operation
549
+ def object_has_own_property_operation(object: ObjectVar, key: Var):
550
+ """Check if an object has a key.
551
+
552
+ Args:
553
+ object: The object to check.
554
+ key: The key to check.
555
+
556
+ Returns:
557
+ The result of the check.
558
+ """
559
+ return var_operation_return(
560
+ js_expression=f"{object}.hasOwnProperty({key})",
561
+ var_type=bool,
562
+ )