reflex 0.5.10a3__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 (237) hide show
  1. reflex/.templates/jinja/web/pages/utils.js.jinja2 +4 -4
  2. reflex/.templates/jinja/web/utils/context.js.jinja2 +1 -1
  3. reflex/.templates/jinja/web/utils/theme.js.jinja2 +1 -1
  4. reflex/__init__.py +3 -2
  5. reflex/__init__.pyi +2 -2
  6. reflex/app.py +43 -9
  7. reflex/base.py +3 -2
  8. reflex/compiler/compiler.py +6 -6
  9. reflex/compiler/utils.py +5 -3
  10. reflex/components/base/app_wrap.py +2 -4
  11. reflex/components/base/app_wrap.pyi +17 -17
  12. reflex/components/base/bare.py +7 -4
  13. reflex/components/base/body.pyi +17 -17
  14. reflex/components/base/document.pyi +81 -81
  15. reflex/components/base/error_boundary.py +10 -8
  16. reflex/components/base/error_boundary.pyi +20 -19
  17. reflex/components/base/fragment.pyi +17 -17
  18. reflex/components/base/head.pyi +33 -33
  19. reflex/components/base/link.pyi +34 -33
  20. reflex/components/base/meta.pyi +65 -65
  21. reflex/components/base/script.py +2 -1
  22. reflex/components/base/script.pyi +21 -20
  23. reflex/components/component.py +116 -145
  24. reflex/components/core/banner.py +59 -60
  25. reflex/components/core/banner.pyi +86 -150
  26. reflex/components/core/client_side_routing.py +2 -1
  27. reflex/components/core/client_side_routing.pyi +34 -33
  28. reflex/components/core/clipboard.py +2 -2
  29. reflex/components/core/clipboard.pyi +19 -18
  30. reflex/components/core/cond.py +21 -44
  31. reflex/components/core/debounce.py +6 -8
  32. reflex/components/core/debounce.pyi +19 -18
  33. reflex/components/core/foreach.py +5 -14
  34. reflex/components/core/html.pyi +18 -17
  35. reflex/components/core/match.py +36 -43
  36. reflex/components/core/upload.py +32 -25
  37. reflex/components/core/upload.pyi +84 -73
  38. reflex/components/datadisplay/code.py +55 -28
  39. reflex/components/datadisplay/code.pyi +20 -17
  40. reflex/components/datadisplay/dataeditor.py +17 -11
  41. reflex/components/datadisplay/dataeditor.pyi +34 -33
  42. reflex/components/el/__init__.py +0 -1
  43. reflex/components/el/__init__.pyi +0 -11
  44. reflex/components/el/element.pyi +17 -17
  45. reflex/components/el/elements/__init__.py +1 -7
  46. reflex/components/el/elements/__init__.pyi +1 -15
  47. reflex/components/el/elements/base.pyi +18 -17
  48. reflex/components/el/elements/forms.py +24 -31
  49. reflex/components/el/elements/forms.pyi +237 -236
  50. reflex/components/el/elements/inline.pyi +450 -449
  51. reflex/components/el/elements/media.py +0 -21
  52. reflex/components/el/elements/media.pyi +338 -337
  53. reflex/components/el/elements/metadata.py +3 -2
  54. reflex/components/el/elements/metadata.pyi +98 -97
  55. reflex/components/el/elements/other.pyi +114 -113
  56. reflex/components/el/elements/scripts.pyi +50 -49
  57. reflex/components/el/elements/sectioning.pyi +242 -241
  58. reflex/components/el/elements/tables.pyi +162 -161
  59. reflex/components/el/elements/typography.pyi +242 -241
  60. reflex/components/gridjs/datatable.py +13 -14
  61. reflex/components/gridjs/datatable.pyi +34 -33
  62. reflex/components/lucide/icon.py +2 -126
  63. reflex/components/lucide/icon.pyi +34 -142
  64. reflex/components/markdown/markdown.py +30 -35
  65. reflex/components/markdown/markdown.pyi +29 -32
  66. reflex/components/moment/moment.pyi +19 -18
  67. reflex/components/next/base.pyi +17 -17
  68. reflex/components/next/image.py +0 -4
  69. reflex/components/next/image.pyi +20 -19
  70. reflex/components/next/link.pyi +18 -17
  71. reflex/components/next/video.pyi +18 -17
  72. reflex/components/plotly/plotly.py +16 -28
  73. reflex/components/plotly/plotly.pyi +36 -35
  74. reflex/components/props.py +21 -10
  75. reflex/components/radix/__init__.pyi +1 -1
  76. reflex/components/radix/primitives/__init__.pyi +0 -1
  77. reflex/components/radix/primitives/accordion.py +7 -8
  78. reflex/components/radix/primitives/accordion.pyi +117 -116
  79. reflex/components/radix/primitives/base.pyi +34 -33
  80. reflex/components/radix/primitives/drawer.pyi +169 -168
  81. reflex/components/radix/primitives/form.pyi +168 -167
  82. reflex/components/radix/primitives/progress.pyi +82 -81
  83. reflex/components/radix/primitives/slider.pyi +84 -83
  84. reflex/components/radix/themes/base.py +8 -4
  85. reflex/components/radix/themes/base.pyi +114 -113
  86. reflex/components/radix/themes/color_mode.py +12 -21
  87. reflex/components/radix/themes/color_mode.pyi +67 -67
  88. reflex/components/radix/themes/components/__init__.pyi +1 -0
  89. reflex/components/radix/themes/components/alert_dialog.pyi +118 -117
  90. reflex/components/radix/themes/components/aspect_ratio.pyi +18 -17
  91. reflex/components/radix/themes/components/avatar.pyi +18 -17
  92. reflex/components/radix/themes/components/badge.pyi +18 -17
  93. reflex/components/radix/themes/components/button.pyi +18 -17
  94. reflex/components/radix/themes/components/callout.pyi +82 -81
  95. reflex/components/radix/themes/components/card.pyi +18 -17
  96. reflex/components/radix/themes/components/checkbox.py +2 -3
  97. reflex/components/radix/themes/components/checkbox.pyi +53 -52
  98. reflex/components/radix/themes/components/checkbox_cards.pyi +34 -33
  99. reflex/components/radix/themes/components/checkbox_group.pyi +34 -33
  100. reflex/components/radix/themes/components/context_menu.pyi +140 -139
  101. reflex/components/radix/themes/components/data_list.py +5 -0
  102. reflex/components/radix/themes/components/data_list.pyi +71 -65
  103. reflex/components/radix/themes/components/dialog.pyi +121 -120
  104. reflex/components/radix/themes/components/dropdown_menu.pyi +142 -141
  105. reflex/components/radix/themes/components/hover_card.pyi +68 -67
  106. reflex/components/radix/themes/components/icon_button.py +2 -1
  107. reflex/components/radix/themes/components/icon_button.pyi +18 -17
  108. reflex/components/radix/themes/components/inset.pyi +18 -17
  109. reflex/components/radix/themes/components/popover.pyi +73 -72
  110. reflex/components/radix/themes/components/progress.pyi +18 -17
  111. reflex/components/radix/themes/components/radio.pyi +18 -17
  112. reflex/components/radix/themes/components/radio_cards.pyi +35 -34
  113. reflex/components/radix/themes/components/radio_group.py +35 -31
  114. reflex/components/radix/themes/components/radio_group.pyi +73 -66
  115. reflex/components/radix/themes/components/scroll_area.pyi +18 -17
  116. reflex/components/radix/themes/components/segmented_control.pyi +35 -34
  117. reflex/components/radix/themes/components/select.py +2 -1
  118. reflex/components/radix/themes/components/select.pyi +155 -154
  119. reflex/components/radix/themes/components/separator.py +2 -3
  120. reflex/components/radix/themes/components/separator.pyi +18 -17
  121. reflex/components/radix/themes/components/skeleton.pyi +18 -17
  122. reflex/components/radix/themes/components/slider.py +2 -1
  123. reflex/components/radix/themes/components/slider.pyi +20 -19
  124. reflex/components/radix/themes/components/spinner.pyi +18 -17
  125. reflex/components/radix/themes/components/switch.pyi +19 -18
  126. reflex/components/radix/themes/components/table.pyi +114 -113
  127. reflex/components/radix/themes/components/tabs.pyi +84 -83
  128. reflex/components/radix/themes/components/text_area.pyi +21 -20
  129. reflex/components/radix/themes/components/text_field.py +0 -79
  130. reflex/components/radix/themes/components/text_field.pyi +57 -63
  131. reflex/components/radix/themes/components/tooltip.pyi +21 -20
  132. reflex/components/radix/themes/layout/base.pyi +18 -17
  133. reflex/components/radix/themes/layout/box.pyi +18 -17
  134. reflex/components/radix/themes/layout/center.pyi +18 -17
  135. reflex/components/radix/themes/layout/container.py +2 -3
  136. reflex/components/radix/themes/layout/container.pyi +18 -17
  137. reflex/components/radix/themes/layout/flex.pyi +18 -17
  138. reflex/components/radix/themes/layout/grid.pyi +18 -17
  139. reflex/components/radix/themes/layout/list.py +5 -4
  140. reflex/components/radix/themes/layout/list.pyi +86 -85
  141. reflex/components/radix/themes/layout/section.py +2 -3
  142. reflex/components/radix/themes/layout/section.pyi +18 -17
  143. reflex/components/radix/themes/layout/spacer.pyi +18 -17
  144. reflex/components/radix/themes/layout/stack.pyi +50 -49
  145. reflex/components/radix/themes/typography/blockquote.pyi +18 -17
  146. reflex/components/radix/themes/typography/code.pyi +18 -17
  147. reflex/components/radix/themes/typography/heading.pyi +18 -17
  148. reflex/components/radix/themes/typography/link.pyi +18 -17
  149. reflex/components/radix/themes/typography/text.pyi +114 -113
  150. reflex/components/react_player/audio.pyi +34 -33
  151. reflex/components/react_player/react_player.pyi +34 -33
  152. reflex/components/react_player/video.pyi +34 -33
  153. reflex/components/recharts/cartesian.py +23 -19
  154. reflex/components/recharts/cartesian.pyi +297 -296
  155. reflex/components/recharts/charts.py +6 -5
  156. reflex/components/recharts/charts.pyi +179 -178
  157. reflex/components/recharts/general.py +8 -7
  158. reflex/components/recharts/general.pyi +82 -81
  159. reflex/components/recharts/polar.py +14 -13
  160. reflex/components/recharts/polar.pyi +76 -75
  161. reflex/components/recharts/recharts.pyi +33 -33
  162. reflex/components/sonner/toast.py +30 -33
  163. reflex/components/sonner/toast.pyi +27 -25
  164. reflex/components/suneditor/editor.py +2 -1
  165. reflex/components/suneditor/editor.pyi +27 -26
  166. reflex/components/tags/iter_tag.py +16 -16
  167. reflex/components/tags/tag.py +8 -10
  168. reflex/constants/base.py +3 -1
  169. reflex/constants/event.py +1 -0
  170. reflex/event.py +89 -79
  171. reflex/experimental/__init__.py +25 -6
  172. reflex/experimental/client_state.py +34 -58
  173. reflex/experimental/hooks.py +13 -18
  174. reflex/experimental/layout.py +5 -5
  175. reflex/experimental/layout.pyi +84 -83
  176. reflex/{experimental/vars → ivars}/__init__.py +0 -1
  177. reflex/ivars/base.py +2180 -0
  178. reflex/ivars/function.py +200 -0
  179. reflex/ivars/number.py +1137 -0
  180. reflex/ivars/object.py +564 -0
  181. reflex/ivars/sequence.py +1601 -0
  182. reflex/model.py +22 -0
  183. reflex/reflex.py +4 -0
  184. reflex/state.py +388 -73
  185. reflex/style.py +52 -34
  186. reflex/testing.py +8 -3
  187. reflex/utils/exceptions.py +12 -0
  188. reflex/utils/exec.py +0 -14
  189. reflex/utils/format.py +74 -223
  190. reflex/utils/net.py +43 -0
  191. reflex/utils/path_ops.py +13 -1
  192. reflex/utils/prerequisites.py +46 -26
  193. reflex/utils/pyi_generator.py +5 -4
  194. reflex/utils/serializers.py +13 -31
  195. reflex/utils/types.py +44 -9
  196. reflex/vars.py +127 -2230
  197. {reflex-0.5.10a3.dist-info → reflex-0.6.0a1.dist-info}/METADATA +4 -6
  198. reflex-0.6.0a1.dist-info/RECORD +384 -0
  199. reflex/.templates/apps/demo/.gitignore +0 -4
  200. reflex/.templates/apps/demo/assets/favicon.ico +0 -0
  201. reflex/.templates/apps/demo/assets/github.svg +0 -10
  202. reflex/.templates/apps/demo/assets/icon.svg +0 -37
  203. reflex/.templates/apps/demo/assets/logo.svg +0 -68
  204. reflex/.templates/apps/demo/assets/paneleft.svg +0 -13
  205. reflex/.templates/apps/demo/code/__init__.py +0 -1
  206. reflex/.templates/apps/demo/code/demo.py +0 -127
  207. reflex/.templates/apps/demo/code/pages/__init__.py +0 -7
  208. reflex/.templates/apps/demo/code/pages/chatapp.py +0 -31
  209. reflex/.templates/apps/demo/code/pages/datatable.py +0 -360
  210. reflex/.templates/apps/demo/code/pages/forms.py +0 -257
  211. reflex/.templates/apps/demo/code/pages/graphing.py +0 -253
  212. reflex/.templates/apps/demo/code/pages/home.py +0 -56
  213. reflex/.templates/apps/demo/code/sidebar.py +0 -178
  214. reflex/.templates/apps/demo/code/state.py +0 -22
  215. reflex/.templates/apps/demo/code/states/form_state.py +0 -40
  216. reflex/.templates/apps/demo/code/states/pie_state.py +0 -47
  217. reflex/.templates/apps/demo/code/styles.py +0 -68
  218. reflex/.templates/apps/demo/code/webui/__init__.py +0 -0
  219. reflex/.templates/apps/demo/code/webui/components/__init__.py +0 -4
  220. reflex/.templates/apps/demo/code/webui/components/chat.py +0 -118
  221. reflex/.templates/apps/demo/code/webui/components/loading_icon.py +0 -19
  222. reflex/.templates/apps/demo/code/webui/components/modal.py +0 -56
  223. reflex/.templates/apps/demo/code/webui/components/navbar.py +0 -70
  224. reflex/.templates/apps/demo/code/webui/components/sidebar.py +0 -66
  225. reflex/.templates/apps/demo/code/webui/state.py +0 -146
  226. reflex/.templates/apps/demo/code/webui/styles.py +0 -88
  227. reflex/experimental/vars/base.py +0 -583
  228. reflex/experimental/vars/function.py +0 -290
  229. reflex/experimental/vars/number.py +0 -1458
  230. reflex/experimental/vars/object.py +0 -804
  231. reflex/experimental/vars/sequence.py +0 -1764
  232. reflex/utils/watch.py +0 -96
  233. reflex/vars.pyi +0 -218
  234. reflex-0.5.10a3.dist-info/RECORD +0 -413
  235. {reflex-0.5.10a3.dist-info → reflex-0.6.0a1.dist-info}/LICENSE +0 -0
  236. {reflex-0.5.10a3.dist-info → reflex-0.6.0a1.dist-info}/WHEEL +0 -0
  237. {reflex-0.5.10a3.dist-info → reflex-0.6.0a1.dist-info}/entry_points.txt +0 -0
reflex/ivars/object.py ADDED
@@ -0,0 +1,564 @@
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
+ from reflex.vars import VarData
27
+
28
+ from .base import (
29
+ CachedVarOperation,
30
+ ImmutableVar,
31
+ LiteralVar,
32
+ ToOperation,
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(ImmutableVar[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: ImmutableVar | Any,
138
+ ) -> ImmutableVar: ...
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: ImmutableVar | Any,
148
+ ) -> NumberVar: ...
149
+
150
+ @overload
151
+ def __getitem__(
152
+ self: ObjectVar[Dict[KEY_TYPE, str]],
153
+ key: ImmutableVar | Any,
154
+ ) -> StringVar: ...
155
+
156
+ @overload
157
+ def __getitem__(
158
+ self: ObjectVar[Dict[KEY_TYPE, list[ARRAY_INNER_TYPE]]],
159
+ key: ImmutableVar | 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: ImmutableVar | 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: ImmutableVar | 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: ImmutableVar | Any,
178
+ ) -> ObjectVar[dict[OTHER_KEY_TYPE, VALUE_TYPE]]: ...
179
+
180
+ def __getitem__(self, key: ImmutableVar | Any) -> ImmutableVar:
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
+ ) -> ImmutableVar: ...
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) -> ImmutableVar:
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: ImmutableVar | 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[ImmutableVar, Any], Union[ImmutableVar, Any]] = (
295
+ dataclasses.field(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._var_name))
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
+ _var_name="",
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, ImmutableVar):
474
+ """Operation to get an item from an object."""
475
+
476
+ _object: ObjectVar = dataclasses.field(
477
+ default_factory=lambda: LiteralObjectVar.create({})
478
+ )
479
+ _key: ImmutableVar | Any = dataclasses.field(
480
+ default_factory=lambda: LiteralVar.create(None)
481
+ )
482
+
483
+ @cached_property_no_lock
484
+ def _cached_var_name(self) -> str:
485
+ """The name of the operation.
486
+
487
+ Returns:
488
+ The name of the operation.
489
+ """
490
+ if types.is_optional(self._object._var_type):
491
+ return f"{str(self._object)}?.[{str(self._key)}]"
492
+ return f"{str(self._object)}[{str(self._key)}]"
493
+
494
+ @classmethod
495
+ def create(
496
+ cls,
497
+ object: ObjectVar,
498
+ key: ImmutableVar | Any,
499
+ _var_type: GenericType | None = None,
500
+ _var_data: VarData | None = None,
501
+ ) -> ObjectItemOperation:
502
+ """Create the object item operation.
503
+
504
+ Args:
505
+ object: The object to get the item from.
506
+ key: The key to get from the object.
507
+ _var_type: The type of the item.
508
+ _var_data: Additional hooks and imports associated with the operation.
509
+
510
+ Returns:
511
+ The object item operation.
512
+ """
513
+ return cls(
514
+ _var_name="",
515
+ _var_type=object._value_type() if _var_type is None else _var_type,
516
+ _var_data=_var_data,
517
+ _object=object,
518
+ _key=key if isinstance(key, ImmutableVar) else LiteralVar.create(key),
519
+ )
520
+
521
+
522
+ @dataclasses.dataclass(
523
+ eq=False,
524
+ frozen=True,
525
+ **{"slots": True} if sys.version_info >= (3, 10) else {},
526
+ )
527
+ class ToObjectOperation(ToOperation, ObjectVar):
528
+ """Operation to convert a var to an object."""
529
+
530
+ _original: ImmutableVar = dataclasses.field(
531
+ default_factory=lambda: LiteralObjectVar.create({})
532
+ )
533
+
534
+ _default_var_type: ClassVar[GenericType] = dict
535
+
536
+ def __getattr__(self, name: str) -> Any:
537
+ """Get an attribute of the var.
538
+
539
+ Args:
540
+ name: The name of the attribute.
541
+
542
+ Returns:
543
+ The attribute of the var.
544
+ """
545
+ if name == "_var_name":
546
+ return self._original._var_name
547
+ return ObjectVar.__getattr__(self, name)
548
+
549
+
550
+ @var_operation
551
+ def object_has_own_property_operation(object: ObjectVar, key: ImmutableVar):
552
+ """Check if an object has a key.
553
+
554
+ Args:
555
+ object: The object to check.
556
+ key: The key to check.
557
+
558
+ Returns:
559
+ The result of the check.
560
+ """
561
+ return var_operation_return(
562
+ js_expression=f"{object}.hasOwnProperty({key})",
563
+ var_type=bool,
564
+ )