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