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/number.py ADDED
@@ -0,0 +1,1137 @@
1
+ """Immutable number vars."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import dataclasses
6
+ import json
7
+ import sys
8
+ from typing import (
9
+ TYPE_CHECKING,
10
+ Any,
11
+ Callable,
12
+ ClassVar,
13
+ NoReturn,
14
+ Type,
15
+ TypeVar,
16
+ Union,
17
+ overload,
18
+ )
19
+
20
+ from reflex.utils.exceptions import VarTypeError
21
+ from reflex.vars import Var, VarData
22
+
23
+ from .base import (
24
+ CustomVarOperationReturn,
25
+ ImmutableVar,
26
+ LiteralNoneVar,
27
+ LiteralVar,
28
+ ToOperation,
29
+ unionize,
30
+ var_operation,
31
+ var_operation_return,
32
+ )
33
+
34
+ NUMBER_T = TypeVar("NUMBER_T", int, float, Union[int, float], bool)
35
+
36
+ if TYPE_CHECKING:
37
+ from .sequence import ArrayVar
38
+
39
+
40
+ def raise_unsupported_operand_types(
41
+ operator: str, operands_types: tuple[type, ...]
42
+ ) -> NoReturn:
43
+ """Raise an unsupported operand types error.
44
+
45
+ Args:
46
+ operator: The operator.
47
+ operands_types: The types of the operands.
48
+
49
+ Raises:
50
+ VarTypeError: The operand types are unsupported.
51
+ """
52
+ raise VarTypeError(
53
+ f"Unsupported Operand type(s) for {operator}: {', '.join(map(lambda t: t.__name__, operands_types))}"
54
+ )
55
+
56
+
57
+ class NumberVar(ImmutableVar[NUMBER_T]):
58
+ """Base class for immutable number vars."""
59
+
60
+ @overload
61
+ def __add__(self, other: number_types) -> NumberVar: ...
62
+
63
+ @overload
64
+ def __add__(self, other: NoReturn) -> NoReturn: ...
65
+
66
+ def __add__(self, other: Any):
67
+ """Add two numbers.
68
+
69
+ Args:
70
+ other: The other number.
71
+
72
+ Returns:
73
+ The number addition operation.
74
+ """
75
+ if not isinstance(other, NUMBER_TYPES):
76
+ raise_unsupported_operand_types("+", (type(self), type(other)))
77
+ return number_add_operation(self, +other)
78
+
79
+ @overload
80
+ def __radd__(self, other: number_types) -> NumberVar: ...
81
+
82
+ @overload
83
+ def __radd__(self, other: NoReturn) -> NoReturn: ...
84
+
85
+ def __radd__(self, other: Any):
86
+ """Add two numbers.
87
+
88
+ Args:
89
+ other: The other number.
90
+
91
+ Returns:
92
+ The number addition operation.
93
+ """
94
+ if not isinstance(other, NUMBER_TYPES):
95
+ raise_unsupported_operand_types("+", (type(other), type(self)))
96
+ return number_add_operation(+other, self)
97
+
98
+ @overload
99
+ def __sub__(self, other: number_types) -> NumberVar: ...
100
+
101
+ @overload
102
+ def __sub__(self, other: NoReturn) -> NoReturn: ...
103
+
104
+ def __sub__(self, other: Any):
105
+ """Subtract two numbers.
106
+
107
+ Args:
108
+ other: The other number.
109
+
110
+ Returns:
111
+ The number subtraction operation.
112
+ """
113
+ if not isinstance(other, NUMBER_TYPES):
114
+ raise_unsupported_operand_types("-", (type(self), type(other)))
115
+
116
+ return number_subtract_operation(self, +other)
117
+
118
+ @overload
119
+ def __rsub__(self, other: number_types) -> NumberVar: ...
120
+
121
+ @overload
122
+ def __rsub__(self, other: NoReturn) -> NoReturn: ...
123
+
124
+ def __rsub__(self, other: Any):
125
+ """Subtract two numbers.
126
+
127
+ Args:
128
+ other: The other number.
129
+
130
+ Returns:
131
+ The number subtraction operation.
132
+ """
133
+ if not isinstance(other, NUMBER_TYPES):
134
+ raise_unsupported_operand_types("-", (type(other), type(self)))
135
+
136
+ return number_subtract_operation(+other, self)
137
+
138
+ def __abs__(self):
139
+ """Get the absolute value of the number.
140
+
141
+ Returns:
142
+ The number absolute operation.
143
+ """
144
+ return number_abs_operation(self)
145
+
146
+ @overload
147
+ def __mul__(self, other: number_types | boolean_types) -> NumberVar: ...
148
+
149
+ @overload
150
+ def __mul__(self, other: list | tuple | set | ArrayVar) -> ArrayVar: ...
151
+
152
+ def __mul__(self, other: Any):
153
+ """Multiply two numbers.
154
+
155
+ Args:
156
+ other: The other number.
157
+
158
+ Returns:
159
+ The number multiplication operation.
160
+ """
161
+ from .sequence import ArrayVar, LiteralArrayVar
162
+
163
+ if isinstance(other, (list, tuple, set, ArrayVar)):
164
+ if isinstance(other, ArrayVar):
165
+ return other * self
166
+ return LiteralArrayVar.create(other) * self
167
+
168
+ if not isinstance(other, NUMBER_TYPES):
169
+ raise_unsupported_operand_types("*", (type(self), type(other)))
170
+
171
+ return number_multiply_operation(self, +other)
172
+
173
+ @overload
174
+ def __rmul__(self, other: number_types | boolean_types) -> NumberVar: ...
175
+
176
+ @overload
177
+ def __rmul__(self, other: list | tuple | set | ArrayVar) -> ArrayVar: ...
178
+
179
+ def __rmul__(self, other: Any):
180
+ """Multiply two numbers.
181
+
182
+ Args:
183
+ other: The other number.
184
+
185
+ Returns:
186
+ The number multiplication operation.
187
+ """
188
+ from .sequence import ArrayVar, LiteralArrayVar
189
+
190
+ if isinstance(other, (list, tuple, set, ArrayVar)):
191
+ if isinstance(other, ArrayVar):
192
+ return other * self
193
+ return LiteralArrayVar.create(other) * self
194
+
195
+ if not isinstance(other, NUMBER_TYPES):
196
+ raise_unsupported_operand_types("*", (type(other), type(self)))
197
+
198
+ return number_multiply_operation(+other, self)
199
+
200
+ @overload
201
+ def __truediv__(self, other: number_types) -> NumberVar: ...
202
+
203
+ @overload
204
+ def __truediv__(self, other: NoReturn) -> NoReturn: ...
205
+
206
+ def __truediv__(self, other: Any):
207
+ """Divide two numbers.
208
+
209
+ Args:
210
+ other: The other number.
211
+
212
+ Returns:
213
+ The number true division operation.
214
+ """
215
+ if not isinstance(other, NUMBER_TYPES):
216
+ raise_unsupported_operand_types("/", (type(self), type(other)))
217
+
218
+ return number_true_division_operation(self, +other)
219
+
220
+ @overload
221
+ def __rtruediv__(self, other: number_types) -> NumberVar: ...
222
+
223
+ @overload
224
+ def __rtruediv__(self, other: NoReturn) -> NoReturn: ...
225
+
226
+ def __rtruediv__(self, other: Any):
227
+ """Divide two numbers.
228
+
229
+ Args:
230
+ other: The other number.
231
+
232
+ Returns:
233
+ The number true division operation.
234
+ """
235
+ if not isinstance(other, NUMBER_TYPES):
236
+ raise_unsupported_operand_types("/", (type(other), type(self)))
237
+
238
+ return number_true_division_operation(+other, self)
239
+
240
+ @overload
241
+ def __floordiv__(self, other: number_types) -> NumberVar: ...
242
+
243
+ @overload
244
+ def __floordiv__(self, other: NoReturn) -> NoReturn: ...
245
+
246
+ def __floordiv__(self, other: Any):
247
+ """Floor divide two numbers.
248
+
249
+ Args:
250
+ other: The other number.
251
+
252
+ Returns:
253
+ The number floor division operation.
254
+ """
255
+ if not isinstance(other, NUMBER_TYPES):
256
+ raise_unsupported_operand_types("//", (type(self), type(other)))
257
+
258
+ return number_floor_division_operation(self, +other)
259
+
260
+ @overload
261
+ def __rfloordiv__(self, other: number_types) -> NumberVar: ...
262
+
263
+ @overload
264
+ def __rfloordiv__(self, other: NoReturn) -> NoReturn: ...
265
+
266
+ def __rfloordiv__(self, other: Any):
267
+ """Floor divide two numbers.
268
+
269
+ Args:
270
+ other: The other number.
271
+
272
+ Returns:
273
+ The number floor division operation.
274
+ """
275
+ if not isinstance(other, NUMBER_TYPES):
276
+ raise_unsupported_operand_types("//", (type(other), type(self)))
277
+
278
+ return number_floor_division_operation(+other, self)
279
+
280
+ @overload
281
+ def __mod__(self, other: number_types) -> NumberVar: ...
282
+
283
+ @overload
284
+ def __mod__(self, other: NoReturn) -> NoReturn: ...
285
+
286
+ def __mod__(self, other: Any):
287
+ """Modulo two numbers.
288
+
289
+ Args:
290
+ other: The other number.
291
+
292
+ Returns:
293
+ The number modulo operation.
294
+ """
295
+ if not isinstance(other, NUMBER_TYPES):
296
+ raise_unsupported_operand_types("%", (type(self), type(other)))
297
+
298
+ return number_modulo_operation(self, +other)
299
+
300
+ @overload
301
+ def __rmod__(self, other: number_types) -> NumberVar: ...
302
+
303
+ @overload
304
+ def __rmod__(self, other: NoReturn) -> NoReturn: ...
305
+
306
+ def __rmod__(self, other: Any):
307
+ """Modulo two numbers.
308
+
309
+ Args:
310
+ other: The other number.
311
+
312
+ Returns:
313
+ The number modulo operation.
314
+ """
315
+ if not isinstance(other, NUMBER_TYPES):
316
+ raise_unsupported_operand_types("%", (type(other), type(self)))
317
+
318
+ return number_modulo_operation(+other, self)
319
+
320
+ @overload
321
+ def __pow__(self, other: number_types) -> NumberVar: ...
322
+
323
+ @overload
324
+ def __pow__(self, other: NoReturn) -> NoReturn: ...
325
+
326
+ def __pow__(self, other: Any):
327
+ """Exponentiate two numbers.
328
+
329
+ Args:
330
+ other: The other number.
331
+
332
+ Returns:
333
+ The number exponent operation.
334
+ """
335
+ if not isinstance(other, NUMBER_TYPES):
336
+ raise_unsupported_operand_types("**", (type(self), type(other)))
337
+
338
+ return number_exponent_operation(self, +other)
339
+
340
+ @overload
341
+ def __rpow__(self, other: number_types) -> NumberVar: ...
342
+
343
+ @overload
344
+ def __rpow__(self, other: NoReturn) -> NoReturn: ...
345
+
346
+ def __rpow__(self, other: Any):
347
+ """Exponentiate two numbers.
348
+
349
+ Args:
350
+ other: The other number.
351
+
352
+ Returns:
353
+ The number exponent operation.
354
+ """
355
+ if not isinstance(other, NUMBER_TYPES):
356
+ raise_unsupported_operand_types("**", (type(other), type(self)))
357
+
358
+ return number_exponent_operation(+other, self)
359
+
360
+ def __neg__(self):
361
+ """Negate the number.
362
+
363
+ Returns:
364
+ The number negation operation.
365
+ """
366
+ return number_negate_operation(self)
367
+
368
+ def __invert__(self):
369
+ """Boolean NOT the number.
370
+
371
+ Returns:
372
+ The boolean NOT operation.
373
+ """
374
+ return boolean_not_operation(self.bool())
375
+
376
+ def __pos__(self) -> NumberVar:
377
+ """Positive the number.
378
+
379
+ Returns:
380
+ The number.
381
+ """
382
+ return self
383
+
384
+ def __round__(self):
385
+ """Round the number.
386
+
387
+ Returns:
388
+ The number round operation.
389
+ """
390
+ return number_round_operation(self)
391
+
392
+ def __ceil__(self):
393
+ """Ceil the number.
394
+
395
+ Returns:
396
+ The number ceil operation.
397
+ """
398
+ return number_ceil_operation(self)
399
+
400
+ def __floor__(self):
401
+ """Floor the number.
402
+
403
+ Returns:
404
+ The number floor operation.
405
+ """
406
+ return number_floor_operation(self)
407
+
408
+ def __trunc__(self):
409
+ """Trunc the number.
410
+
411
+ Returns:
412
+ The number trunc operation.
413
+ """
414
+ return number_trunc_operation(self)
415
+
416
+ @overload
417
+ def __lt__(self, other: number_types) -> BooleanVar: ...
418
+
419
+ @overload
420
+ def __lt__(self, other: NoReturn) -> NoReturn: ...
421
+
422
+ def __lt__(self, other: Any):
423
+ """Less than comparison.
424
+
425
+ Args:
426
+ other: The other number.
427
+
428
+ Returns:
429
+ The result of the comparison.
430
+ """
431
+ if not isinstance(other, NUMBER_TYPES):
432
+ raise_unsupported_operand_types("<", (type(self), type(other)))
433
+ return less_than_operation(self, +other)
434
+
435
+ @overload
436
+ def __le__(self, other: number_types) -> BooleanVar: ...
437
+
438
+ @overload
439
+ def __le__(self, other: NoReturn) -> NoReturn: ...
440
+
441
+ def __le__(self, other: Any):
442
+ """Less than or equal comparison.
443
+
444
+ Args:
445
+ other: The other number.
446
+
447
+ Returns:
448
+ The result of the comparison.
449
+ """
450
+ if not isinstance(other, NUMBER_TYPES):
451
+ raise_unsupported_operand_types("<=", (type(self), type(other)))
452
+ return less_than_or_equal_operation(self, +other)
453
+
454
+ def __eq__(self, other: Any):
455
+ """Equal comparison.
456
+
457
+ Args:
458
+ other: The other number.
459
+
460
+ Returns:
461
+ The result of the comparison.
462
+ """
463
+ if isinstance(other, NUMBER_TYPES):
464
+ return equal_operation(self, +other)
465
+ return equal_operation(self, other)
466
+
467
+ def __ne__(self, other: Any):
468
+ """Not equal comparison.
469
+
470
+ Args:
471
+ other: The other number.
472
+
473
+ Returns:
474
+ The result of the comparison.
475
+ """
476
+ if isinstance(other, NUMBER_TYPES):
477
+ return not_equal_operation(self, +other)
478
+ return not_equal_operation(self, other)
479
+
480
+ @overload
481
+ def __gt__(self, other: number_types) -> BooleanVar: ...
482
+
483
+ @overload
484
+ def __gt__(self, other: NoReturn) -> NoReturn: ...
485
+
486
+ def __gt__(self, other: Any):
487
+ """Greater than comparison.
488
+
489
+ Args:
490
+ other: The other number.
491
+
492
+ Returns:
493
+ The result of the comparison.
494
+ """
495
+ if not isinstance(other, NUMBER_TYPES):
496
+ raise_unsupported_operand_types(">", (type(self), type(other)))
497
+ return greater_than_operation(self, +other)
498
+
499
+ @overload
500
+ def __ge__(self, other: number_types) -> BooleanVar: ...
501
+
502
+ @overload
503
+ def __ge__(self, other: NoReturn) -> NoReturn: ...
504
+
505
+ def __ge__(self, other: Any):
506
+ """Greater than or equal comparison.
507
+
508
+ Args:
509
+ other: The other number.
510
+
511
+ Returns:
512
+ The result of the comparison.
513
+ """
514
+ if not isinstance(other, NUMBER_TYPES):
515
+ raise_unsupported_operand_types(">=", (type(self), type(other)))
516
+ return greater_than_or_equal_operation(self, +other)
517
+
518
+ def bool(self):
519
+ """Boolean conversion.
520
+
521
+ Returns:
522
+ The boolean value of the number.
523
+ """
524
+ return self != 0
525
+
526
+ def _is_strict_float(self) -> bool:
527
+ """Check if the number is a float.
528
+
529
+ Returns:
530
+ bool: True if the number is a float.
531
+ """
532
+ return issubclass(self._var_type, float)
533
+
534
+ def _is_strict_int(self) -> bool:
535
+ """Check if the number is an int.
536
+
537
+ Returns:
538
+ bool: True if the number is an int.
539
+ """
540
+ return issubclass(self._var_type, int)
541
+
542
+
543
+ def binary_number_operation(
544
+ func: Callable[[NumberVar, NumberVar], str],
545
+ ) -> Callable[[number_types, number_types], NumberVar]:
546
+ """Decorator to create a binary number operation.
547
+
548
+ Args:
549
+ func: The binary number operation function.
550
+
551
+ Returns:
552
+ The binary number operation.
553
+ """
554
+
555
+ @var_operation
556
+ def operation(lhs: NumberVar, rhs: NumberVar):
557
+ return var_operation_return(
558
+ js_expression=func(lhs, rhs),
559
+ var_type=unionize(lhs._var_type, rhs._var_type),
560
+ )
561
+
562
+ def wrapper(lhs: number_types, rhs: number_types) -> NumberVar:
563
+ """Create the binary number operation.
564
+
565
+ Args:
566
+ lhs: The first number.
567
+ rhs: The second number.
568
+
569
+ Returns:
570
+ The binary number operation.
571
+ """
572
+ return operation(lhs, rhs) # type: ignore
573
+
574
+ return wrapper
575
+
576
+
577
+ @binary_number_operation
578
+ def number_add_operation(lhs: NumberVar, rhs: NumberVar):
579
+ """Add two numbers.
580
+
581
+ Args:
582
+ lhs: The first number.
583
+ rhs: The second number.
584
+
585
+ Returns:
586
+ The number addition operation.
587
+ """
588
+ return f"({lhs} + {rhs})"
589
+
590
+
591
+ @binary_number_operation
592
+ def number_subtract_operation(lhs: NumberVar, rhs: NumberVar):
593
+ """Subtract two numbers.
594
+
595
+ Args:
596
+ lhs: The first number.
597
+ rhs: The second number.
598
+
599
+ Returns:
600
+ The number subtraction operation.
601
+ """
602
+ return f"({lhs} - {rhs})"
603
+
604
+
605
+ @var_operation
606
+ def number_abs_operation(value: NumberVar):
607
+ """Get the absolute value of the number.
608
+
609
+ Args:
610
+ value: The number.
611
+
612
+ Returns:
613
+ The number absolute operation.
614
+ """
615
+ return var_operation_return(
616
+ js_expression=f"Math.abs({value})", var_type=value._var_type
617
+ )
618
+
619
+
620
+ @binary_number_operation
621
+ def number_multiply_operation(lhs: NumberVar, rhs: NumberVar):
622
+ """Multiply two numbers.
623
+
624
+ Args:
625
+ lhs: The first number.
626
+ rhs: The second number.
627
+
628
+ Returns:
629
+ The number multiplication operation.
630
+ """
631
+ return f"({lhs} * {rhs})"
632
+
633
+
634
+ @var_operation
635
+ def number_negate_operation(
636
+ value: NumberVar[NUMBER_T],
637
+ ) -> CustomVarOperationReturn[NUMBER_T]:
638
+ """Negate the number.
639
+
640
+ Args:
641
+ value: The number.
642
+
643
+ Returns:
644
+ The number negation operation.
645
+ """
646
+ return var_operation_return(js_expression=f"-({value})", var_type=value._var_type)
647
+
648
+
649
+ @binary_number_operation
650
+ def number_true_division_operation(lhs: NumberVar, rhs: NumberVar):
651
+ """Divide two numbers.
652
+
653
+ Args:
654
+ lhs: The first number.
655
+ rhs: The second number.
656
+
657
+ Returns:
658
+ The number true division operation.
659
+ """
660
+ return f"({lhs} / {rhs})"
661
+
662
+
663
+ @binary_number_operation
664
+ def number_floor_division_operation(lhs: NumberVar, rhs: NumberVar):
665
+ """Floor divide two numbers.
666
+
667
+ Args:
668
+ lhs: The first number.
669
+ rhs: The second number.
670
+
671
+ Returns:
672
+ The number floor division operation.
673
+ """
674
+ return f"Math.floor({lhs} / {rhs})"
675
+
676
+
677
+ @binary_number_operation
678
+ def number_modulo_operation(lhs: NumberVar, rhs: NumberVar):
679
+ """Modulo two numbers.
680
+
681
+ Args:
682
+ lhs: The first number.
683
+ rhs: The second number.
684
+
685
+ Returns:
686
+ The number modulo operation.
687
+ """
688
+ return f"({lhs} % {rhs})"
689
+
690
+
691
+ @binary_number_operation
692
+ def number_exponent_operation(lhs: NumberVar, rhs: NumberVar):
693
+ """Exponentiate two numbers.
694
+
695
+ Args:
696
+ lhs: The first number.
697
+ rhs: The second number.
698
+
699
+ Returns:
700
+ The number exponent operation.
701
+ """
702
+ return f"({lhs} ** {rhs})"
703
+
704
+
705
+ @var_operation
706
+ def number_round_operation(value: NumberVar):
707
+ """Round the number.
708
+
709
+ Args:
710
+ value: The number.
711
+
712
+ Returns:
713
+ The number round operation.
714
+ """
715
+ return var_operation_return(js_expression=f"Math.round({value})", var_type=int)
716
+
717
+
718
+ @var_operation
719
+ def number_ceil_operation(value: NumberVar):
720
+ """Ceil the number.
721
+
722
+ Args:
723
+ value: The number.
724
+
725
+ Returns:
726
+ The number ceil operation.
727
+ """
728
+ return var_operation_return(js_expression=f"Math.ceil({value})", var_type=int)
729
+
730
+
731
+ @var_operation
732
+ def number_floor_operation(value: NumberVar):
733
+ """Floor the number.
734
+
735
+ Args:
736
+ value: The number.
737
+
738
+ Returns:
739
+ The number floor operation.
740
+ """
741
+ return var_operation_return(js_expression=f"Math.floor({value})", var_type=int)
742
+
743
+
744
+ @var_operation
745
+ def number_trunc_operation(value: NumberVar):
746
+ """Trunc the number.
747
+
748
+ Args:
749
+ value: The number.
750
+
751
+ Returns:
752
+ The number trunc operation.
753
+ """
754
+ return var_operation_return(js_expression=f"Math.trunc({value})", var_type=int)
755
+
756
+
757
+ class BooleanVar(NumberVar[bool]):
758
+ """Base class for immutable boolean vars."""
759
+
760
+ def __invert__(self):
761
+ """NOT the boolean.
762
+
763
+ Returns:
764
+ The boolean NOT operation.
765
+ """
766
+ return boolean_not_operation(self)
767
+
768
+ def __int__(self):
769
+ """Convert the boolean to an int.
770
+
771
+ Returns:
772
+ The boolean to int operation.
773
+ """
774
+ return boolean_to_number_operation(self)
775
+
776
+ def __pos__(self):
777
+ """Convert the boolean to an int.
778
+
779
+ Returns:
780
+ The boolean to int operation.
781
+ """
782
+ return boolean_to_number_operation(self)
783
+
784
+ def bool(self) -> BooleanVar:
785
+ """Boolean conversion.
786
+
787
+ Returns:
788
+ The boolean value of the boolean.
789
+ """
790
+ return self
791
+
792
+ def __lt__(self, other: Any):
793
+ """Less than comparison.
794
+
795
+ Args:
796
+ other: The other boolean.
797
+
798
+ Returns:
799
+ The result of the comparison.
800
+ """
801
+ return +self < other
802
+
803
+ def __le__(self, other: Any):
804
+ """Less than or equal comparison.
805
+
806
+ Args:
807
+ other: The other boolean.
808
+
809
+ Returns:
810
+ The result of the comparison.
811
+ """
812
+ return +self <= other
813
+
814
+ def __gt__(self, other: Any):
815
+ """Greater than comparison.
816
+
817
+ Args:
818
+ other: The other boolean.
819
+
820
+ Returns:
821
+ The result of the comparison.
822
+ """
823
+ return +self > other
824
+
825
+ def __ge__(self, other: Any):
826
+ """Greater than or equal comparison.
827
+
828
+ Args:
829
+ other: The other boolean.
830
+
831
+ Returns:
832
+ The result of the comparison.
833
+ """
834
+ return +self >= other
835
+
836
+
837
+ @var_operation
838
+ def boolean_to_number_operation(value: BooleanVar):
839
+ """Convert the boolean to a number.
840
+
841
+ Args:
842
+ value: The boolean.
843
+
844
+ Returns:
845
+ The boolean to number operation.
846
+ """
847
+ return var_operation_return(js_expression=f"Number({value})", var_type=int)
848
+
849
+
850
+ def comparison_operator(
851
+ func: Callable[[ImmutableVar, ImmutableVar], str],
852
+ ) -> Callable[[ImmutableVar | Any, ImmutableVar | Any], BooleanVar]:
853
+ """Decorator to create a comparison operation.
854
+
855
+ Args:
856
+ func: The comparison operation function.
857
+
858
+ Returns:
859
+ The comparison operation.
860
+ """
861
+
862
+ @var_operation
863
+ def operation(lhs: ImmutableVar, rhs: ImmutableVar):
864
+ return var_operation_return(
865
+ js_expression=func(lhs, rhs),
866
+ var_type=bool,
867
+ )
868
+
869
+ def wrapper(lhs: ImmutableVar | Any, rhs: ImmutableVar | Any) -> BooleanVar:
870
+ """Create the comparison operation.
871
+
872
+ Args:
873
+ lhs: The first value.
874
+ rhs: The second value.
875
+
876
+ Returns:
877
+ The comparison operation.
878
+ """
879
+ return operation(lhs, rhs)
880
+
881
+ return wrapper
882
+
883
+
884
+ @comparison_operator
885
+ def greater_than_operation(lhs: ImmutableVar, rhs: ImmutableVar):
886
+ """Greater than comparison.
887
+
888
+ Args:
889
+ lhs: The first value.
890
+ rhs: The second value.
891
+
892
+ Returns:
893
+ The result of the comparison.
894
+ """
895
+ return f"({lhs} > {rhs})"
896
+
897
+
898
+ @comparison_operator
899
+ def greater_than_or_equal_operation(lhs: ImmutableVar, rhs: ImmutableVar):
900
+ """Greater than or equal comparison.
901
+
902
+ Args:
903
+ lhs: The first value.
904
+ rhs: The second value.
905
+
906
+ Returns:
907
+ The result of the comparison.
908
+ """
909
+ return f"({lhs} >= {rhs})"
910
+
911
+
912
+ @comparison_operator
913
+ def less_than_operation(lhs: ImmutableVar, rhs: ImmutableVar):
914
+ """Less than comparison.
915
+
916
+ Args:
917
+ lhs: The first value.
918
+ rhs: The second value.
919
+
920
+ Returns:
921
+ The result of the comparison.
922
+ """
923
+ return f"({lhs} < {rhs})"
924
+
925
+
926
+ @comparison_operator
927
+ def less_than_or_equal_operation(lhs: ImmutableVar, rhs: ImmutableVar):
928
+ """Less than or equal comparison.
929
+
930
+ Args:
931
+ lhs: The first value.
932
+ rhs: The second value.
933
+
934
+ Returns:
935
+ The result of the comparison.
936
+ """
937
+ return f"({lhs} <= {rhs})"
938
+
939
+
940
+ @comparison_operator
941
+ def equal_operation(lhs: ImmutableVar, rhs: ImmutableVar):
942
+ """Equal comparison.
943
+
944
+ Args:
945
+ lhs: The first value.
946
+ rhs: The second value.
947
+
948
+ Returns:
949
+ The result of the comparison.
950
+ """
951
+ return f"({lhs} === {rhs})"
952
+
953
+
954
+ @comparison_operator
955
+ def not_equal_operation(lhs: ImmutableVar, rhs: ImmutableVar):
956
+ """Not equal comparison.
957
+
958
+ Args:
959
+ lhs: The first value.
960
+ rhs: The second value.
961
+
962
+ Returns:
963
+ The result of the comparison.
964
+ """
965
+ return f"({lhs} !== {rhs})"
966
+
967
+
968
+ @var_operation
969
+ def boolean_not_operation(value: BooleanVar):
970
+ """Boolean NOT the boolean.
971
+
972
+ Args:
973
+ value: The boolean.
974
+
975
+ Returns:
976
+ The boolean NOT operation.
977
+ """
978
+ return var_operation_return(js_expression=f"!({value})", var_type=bool)
979
+
980
+
981
+ @dataclasses.dataclass(
982
+ eq=False,
983
+ frozen=True,
984
+ **{"slots": True} if sys.version_info >= (3, 10) else {},
985
+ )
986
+ class LiteralBooleanVar(LiteralVar, BooleanVar):
987
+ """Base class for immutable literal boolean vars."""
988
+
989
+ _var_value: bool = dataclasses.field(default=False)
990
+
991
+ def json(self) -> str:
992
+ """Get the JSON representation of the var.
993
+
994
+ Returns:
995
+ The JSON representation of the var.
996
+ """
997
+ return "true" if self._var_value else "false"
998
+
999
+ def __hash__(self) -> int:
1000
+ """Calculate the hash value of the object.
1001
+
1002
+ Returns:
1003
+ int: The hash value of the object.
1004
+ """
1005
+ return hash((self.__class__.__name__, self._var_value))
1006
+
1007
+ @classmethod
1008
+ def create(cls, value: bool, _var_data: VarData | None = None):
1009
+ """Create the boolean var.
1010
+
1011
+ Args:
1012
+ value: The value of the var.
1013
+ _var_data: Additional hooks and imports associated with the Var.
1014
+
1015
+ Returns:
1016
+ The boolean var.
1017
+ """
1018
+ return cls(
1019
+ _var_name="true" if value else "false",
1020
+ _var_type=bool,
1021
+ _var_data=_var_data,
1022
+ _var_value=value,
1023
+ )
1024
+
1025
+
1026
+ @dataclasses.dataclass(
1027
+ eq=False,
1028
+ frozen=True,
1029
+ **{"slots": True} if sys.version_info >= (3, 10) else {},
1030
+ )
1031
+ class LiteralNumberVar(LiteralVar, NumberVar):
1032
+ """Base class for immutable literal number vars."""
1033
+
1034
+ _var_value: float | int = dataclasses.field(default=0)
1035
+
1036
+ def json(self) -> str:
1037
+ """Get the JSON representation of the var.
1038
+
1039
+ Returns:
1040
+ The JSON representation of the var.
1041
+ """
1042
+ return json.dumps(self._var_value)
1043
+
1044
+ def __hash__(self) -> int:
1045
+ """Calculate the hash value of the object.
1046
+
1047
+ Returns:
1048
+ int: The hash value of the object.
1049
+ """
1050
+ return hash((self.__class__.__name__, self._var_value))
1051
+
1052
+ @classmethod
1053
+ def create(cls, value: float | int, _var_data: VarData | None = None):
1054
+ """Create the number var.
1055
+
1056
+ Args:
1057
+ value: The value of the var.
1058
+ _var_data: Additional hooks and imports associated with the Var.
1059
+
1060
+ Returns:
1061
+ The number var.
1062
+ """
1063
+ return cls(
1064
+ _var_name=str(value),
1065
+ _var_type=type(value),
1066
+ _var_data=_var_data,
1067
+ _var_value=value,
1068
+ )
1069
+
1070
+
1071
+ number_types = Union[NumberVar, int, float]
1072
+ boolean_types = Union[BooleanVar, bool]
1073
+
1074
+
1075
+ @dataclasses.dataclass(
1076
+ eq=False,
1077
+ frozen=True,
1078
+ **{"slots": True} if sys.version_info >= (3, 10) else {},
1079
+ )
1080
+ class ToNumberVarOperation(ToOperation, NumberVar):
1081
+ """Base class for immutable number vars that are the result of a number operation."""
1082
+
1083
+ _original: Var = dataclasses.field(default_factory=lambda: LiteralNoneVar.create())
1084
+
1085
+ _default_var_type: ClassVar[Type] = float
1086
+
1087
+
1088
+ @dataclasses.dataclass(
1089
+ eq=False,
1090
+ frozen=True,
1091
+ **{"slots": True} if sys.version_info >= (3, 10) else {},
1092
+ )
1093
+ class ToBooleanVarOperation(ToOperation, BooleanVar):
1094
+ """Base class for immutable boolean vars that are the result of a boolean operation."""
1095
+
1096
+ _original: Var = dataclasses.field(default_factory=lambda: LiteralNoneVar.create())
1097
+
1098
+ _default_var_type: ClassVar[Type] = bool
1099
+
1100
+
1101
+ @var_operation
1102
+ def boolify(value: Var):
1103
+ """Convert the value to a boolean.
1104
+
1105
+ Args:
1106
+ value: The value.
1107
+
1108
+ Returns:
1109
+ The boolean value.
1110
+ """
1111
+ return var_operation_return(
1112
+ js_expression=f"Boolean({value})",
1113
+ var_type=bool,
1114
+ )
1115
+
1116
+
1117
+ @var_operation
1118
+ def ternary_operation(
1119
+ condition: BooleanVar, if_true: ImmutableVar, if_false: ImmutableVar
1120
+ ):
1121
+ """Create a ternary operation.
1122
+
1123
+ Args:
1124
+ condition: The condition.
1125
+ if_true: The value if the condition is true.
1126
+ if_false: The value if the condition is false.
1127
+
1128
+ Returns:
1129
+ The ternary operation.
1130
+ """
1131
+ return var_operation_return(
1132
+ js_expression=f"({condition} ? {if_true} : {if_false})",
1133
+ var_type=unionize(if_true._var_type, if_false._var_type),
1134
+ )
1135
+
1136
+
1137
+ NUMBER_TYPES = (int, float, NumberVar)