reflex 0.5.7__py3-none-any.whl → 0.5.8__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 (44) hide show
  1. reflex/.templates/web/utils/state.js +1 -1
  2. reflex/app.py +20 -2
  3. reflex/components/core/banner.py +14 -0
  4. reflex/components/core/banner.pyi +3 -3
  5. reflex/components/core/debounce.py +3 -0
  6. reflex/components/el/__init__.py +1 -0
  7. reflex/components/el/__init__.pyi +8 -5
  8. reflex/components/el/elements/__init__.py +3 -1
  9. reflex/components/el/elements/__init__.pyi +8 -6
  10. reflex/components/el/elements/media.py +98 -18
  11. reflex/components/el/elements/media.pyi +523 -18
  12. reflex/components/el/elements/metadata.py +5 -1
  13. reflex/components/radix/primitives/base.py +1 -1
  14. reflex/components/radix/themes/layout/list.py +0 -2
  15. reflex/components/recharts/cartesian.py +46 -20
  16. reflex/components/recharts/cartesian.pyi +26 -14
  17. reflex/components/recharts/charts.py +4 -0
  18. reflex/components/recharts/charts.pyi +3 -0
  19. reflex/components/recharts/general.py +23 -9
  20. reflex/components/recharts/general.pyi +6 -4
  21. reflex/components/recharts/polar.py +35 -11
  22. reflex/components/recharts/polar.pyi +35 -7
  23. reflex/components/sonner/toast.py +28 -2
  24. reflex/components/sonner/toast.pyi +14 -7
  25. reflex/constants/base.py +21 -0
  26. reflex/constants/event.py +2 -0
  27. reflex/experimental/vars/__init__.py +17 -0
  28. reflex/experimental/vars/base.py +282 -15
  29. reflex/experimental/vars/function.py +214 -0
  30. reflex/experimental/vars/number.py +1295 -0
  31. reflex/experimental/vars/sequence.py +1039 -0
  32. reflex/reflex.py +29 -2
  33. reflex/state.py +59 -10
  34. reflex/utils/imports.py +71 -8
  35. reflex/utils/prerequisites.py +115 -35
  36. reflex/utils/pyi_generator.py +2 -0
  37. reflex/utils/redir.py +52 -0
  38. reflex/vars.py +220 -11
  39. reflex/vars.pyi +20 -2
  40. {reflex-0.5.7.dist-info → reflex-0.5.8.dist-info}/METADATA +2 -2
  41. {reflex-0.5.7.dist-info → reflex-0.5.8.dist-info}/RECORD +44 -40
  42. {reflex-0.5.7.dist-info → reflex-0.5.8.dist-info}/LICENSE +0 -0
  43. {reflex-0.5.7.dist-info → reflex-0.5.8.dist-info}/WHEEL +0 -0
  44. {reflex-0.5.7.dist-info → reflex-0.5.8.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,1295 @@
1
+ """Immutable number vars."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import dataclasses
6
+ import sys
7
+ from functools import cached_property
8
+ from typing import Any, Union
9
+
10
+ from reflex.experimental.vars.base import (
11
+ ImmutableVar,
12
+ LiteralVar,
13
+ )
14
+ from reflex.vars import ImmutableVarData, Var, VarData
15
+
16
+
17
+ class NumberVar(ImmutableVar):
18
+ """Base class for immutable number vars."""
19
+
20
+ def __add__(self, other: number_types | boolean_types) -> NumberAddOperation:
21
+ """Add two numbers.
22
+
23
+ Args:
24
+ other: The other number.
25
+
26
+ Returns:
27
+ The number addition operation.
28
+ """
29
+ return NumberAddOperation(self, +other)
30
+
31
+ def __radd__(self, other: number_types | boolean_types) -> NumberAddOperation:
32
+ """Add two numbers.
33
+
34
+ Args:
35
+ other: The other number.
36
+
37
+ Returns:
38
+ The number addition operation.
39
+ """
40
+ return NumberAddOperation(+other, self)
41
+
42
+ def __sub__(self, other: number_types | boolean_types) -> NumberSubtractOperation:
43
+ """Subtract two numbers.
44
+
45
+ Args:
46
+ other: The other number.
47
+
48
+ Returns:
49
+ The number subtraction operation.
50
+ """
51
+ return NumberSubtractOperation(self, +other)
52
+
53
+ def __rsub__(self, other: number_types | boolean_types) -> NumberSubtractOperation:
54
+ """Subtract two numbers.
55
+
56
+ Args:
57
+ other: The other number.
58
+
59
+ Returns:
60
+ The number subtraction operation.
61
+ """
62
+ return NumberSubtractOperation(+other, self)
63
+
64
+ def __abs__(self) -> NumberAbsoluteOperation:
65
+ """Get the absolute value of the number.
66
+
67
+ Returns:
68
+ The number absolute operation.
69
+ """
70
+ return NumberAbsoluteOperation(self)
71
+
72
+ def __mul__(self, other: number_types | boolean_types) -> NumberMultiplyOperation:
73
+ """Multiply two numbers.
74
+
75
+ Args:
76
+ other: The other number.
77
+
78
+ Returns:
79
+ The number multiplication operation.
80
+ """
81
+ return NumberMultiplyOperation(self, +other)
82
+
83
+ def __rmul__(self, other: number_types | boolean_types) -> NumberMultiplyOperation:
84
+ """Multiply two numbers.
85
+
86
+ Args:
87
+ other: The other number.
88
+
89
+ Returns:
90
+ The number multiplication operation.
91
+ """
92
+ return NumberMultiplyOperation(+other, self)
93
+
94
+ def __truediv__(self, other: number_types | boolean_types) -> NumberTrueDivision:
95
+ """Divide two numbers.
96
+
97
+ Args:
98
+ other: The other number.
99
+
100
+ Returns:
101
+ The number true division operation.
102
+ """
103
+ return NumberTrueDivision(self, +other)
104
+
105
+ def __rtruediv__(self, other: number_types | boolean_types) -> NumberTrueDivision:
106
+ """Divide two numbers.
107
+
108
+ Args:
109
+ other: The other number.
110
+
111
+ Returns:
112
+ The number true division operation.
113
+ """
114
+ return NumberTrueDivision(+other, self)
115
+
116
+ def __floordiv__(self, other: number_types | boolean_types) -> NumberFloorDivision:
117
+ """Floor divide two numbers.
118
+
119
+ Args:
120
+ other: The other number.
121
+
122
+ Returns:
123
+ The number floor division operation.
124
+ """
125
+ return NumberFloorDivision(self, +other)
126
+
127
+ def __rfloordiv__(self, other: number_types | boolean_types) -> NumberFloorDivision:
128
+ """Floor divide two numbers.
129
+
130
+ Args:
131
+ other: The other number.
132
+
133
+ Returns:
134
+ The number floor division operation.
135
+ """
136
+ return NumberFloorDivision(+other, self)
137
+
138
+ def __mod__(self, other: number_types | boolean_types) -> NumberModuloOperation:
139
+ """Modulo two numbers.
140
+
141
+ Args:
142
+ other: The other number.
143
+
144
+ Returns:
145
+ The number modulo operation.
146
+ """
147
+ return NumberModuloOperation(self, +other)
148
+
149
+ def __rmod__(self, other: number_types | boolean_types) -> NumberModuloOperation:
150
+ """Modulo two numbers.
151
+
152
+ Args:
153
+ other: The other number.
154
+
155
+ Returns:
156
+ The number modulo operation.
157
+ """
158
+ return NumberModuloOperation(+other, self)
159
+
160
+ def __pow__(self, other: number_types | boolean_types) -> NumberExponentOperation:
161
+ """Exponentiate two numbers.
162
+
163
+ Args:
164
+ other: The other number.
165
+
166
+ Returns:
167
+ The number exponent operation.
168
+ """
169
+ return NumberExponentOperation(self, +other)
170
+
171
+ def __rpow__(self, other: number_types | boolean_types) -> NumberExponentOperation:
172
+ """Exponentiate two numbers.
173
+
174
+ Args:
175
+ other: The other number.
176
+
177
+ Returns:
178
+ The number exponent operation.
179
+ """
180
+ return NumberExponentOperation(+other, self)
181
+
182
+ def __neg__(self) -> NumberNegateOperation:
183
+ """Negate the number.
184
+
185
+ Returns:
186
+ The number negation operation.
187
+ """
188
+ return NumberNegateOperation(self)
189
+
190
+ def __and__(self, other: number_types | boolean_types) -> BooleanAndOperation:
191
+ """Boolean AND two numbers.
192
+
193
+ Args:
194
+ other: The other number.
195
+
196
+ Returns:
197
+ The boolean AND operation.
198
+ """
199
+ boolified_other = other.bool() if isinstance(other, Var) else bool(other)
200
+ return BooleanAndOperation(self.bool(), boolified_other)
201
+
202
+ def __rand__(self, other: number_types | boolean_types) -> BooleanAndOperation:
203
+ """Boolean AND two numbers.
204
+
205
+ Args:
206
+ other: The other number.
207
+
208
+ Returns:
209
+ The boolean AND operation.
210
+ """
211
+ boolified_other = other.bool() if isinstance(other, Var) else bool(other)
212
+ return BooleanAndOperation(boolified_other, self.bool())
213
+
214
+ def __or__(self, other: number_types | boolean_types) -> BooleanOrOperation:
215
+ """Boolean OR two numbers.
216
+
217
+ Args:
218
+ other: The other number.
219
+
220
+ Returns:
221
+ The boolean OR operation.
222
+ """
223
+ boolified_other = other.bool() if isinstance(other, Var) else bool(other)
224
+ return BooleanOrOperation(self.bool(), boolified_other)
225
+
226
+ def __ror__(self, other: number_types | boolean_types) -> BooleanOrOperation:
227
+ """Boolean OR two numbers.
228
+
229
+ Args:
230
+ other: The other number.
231
+
232
+ Returns:
233
+ The boolean OR operation.
234
+ """
235
+ boolified_other = other.bool() if isinstance(other, Var) else bool(other)
236
+ return BooleanOrOperation(boolified_other, self.bool())
237
+
238
+ def __invert__(self) -> BooleanNotOperation:
239
+ """Boolean NOT the number.
240
+
241
+ Returns:
242
+ The boolean NOT operation.
243
+ """
244
+ return BooleanNotOperation(self.bool())
245
+
246
+ def __pos__(self) -> NumberVar:
247
+ """Positive the number.
248
+
249
+ Returns:
250
+ The number.
251
+ """
252
+ return self
253
+
254
+ def __round__(self) -> NumberRoundOperation:
255
+ """Round the number.
256
+
257
+ Returns:
258
+ The number round operation.
259
+ """
260
+ return NumberRoundOperation(self)
261
+
262
+ def __ceil__(self) -> NumberCeilOperation:
263
+ """Ceil the number.
264
+
265
+ Returns:
266
+ The number ceil operation.
267
+ """
268
+ return NumberCeilOperation(self)
269
+
270
+ def __floor__(self) -> NumberFloorOperation:
271
+ """Floor the number.
272
+
273
+ Returns:
274
+ The number floor operation.
275
+ """
276
+ return NumberFloorOperation(self)
277
+
278
+ def __trunc__(self) -> NumberTruncOperation:
279
+ """Trunc the number.
280
+
281
+ Returns:
282
+ The number trunc operation.
283
+ """
284
+ return NumberTruncOperation(self)
285
+
286
+ def __lt__(self, other: number_types | boolean_types) -> LessThanOperation:
287
+ """Less than comparison.
288
+
289
+ Args:
290
+ other: The other number.
291
+
292
+ Returns:
293
+ The result of the comparison.
294
+ """
295
+ return LessThanOperation(self, +other)
296
+
297
+ def __le__(self, other: number_types | boolean_types) -> LessThanOrEqualOperation:
298
+ """Less than or equal comparison.
299
+
300
+ Args:
301
+ other: The other number.
302
+
303
+ Returns:
304
+ The result of the comparison.
305
+ """
306
+ return LessThanOrEqualOperation(self, +other)
307
+
308
+ def __eq__(self, other: number_types | boolean_types) -> EqualOperation:
309
+ """Equal comparison.
310
+
311
+ Args:
312
+ other: The other number.
313
+
314
+ Returns:
315
+ The result of the comparison.
316
+ """
317
+ return EqualOperation(self, +other)
318
+
319
+ def __ne__(self, other: number_types | boolean_types) -> NotEqualOperation:
320
+ """Not equal comparison.
321
+
322
+ Args:
323
+ other: The other number.
324
+
325
+ Returns:
326
+ The result of the comparison.
327
+ """
328
+ return NotEqualOperation(self, +other)
329
+
330
+ def __gt__(self, other: number_types | boolean_types) -> GreaterThanOperation:
331
+ """Greater than comparison.
332
+
333
+ Args:
334
+ other: The other number.
335
+
336
+ Returns:
337
+ The result of the comparison.
338
+ """
339
+ return GreaterThanOperation(self, +other)
340
+
341
+ def __ge__(
342
+ self, other: number_types | boolean_types
343
+ ) -> GreaterThanOrEqualOperation:
344
+ """Greater than or equal comparison.
345
+
346
+ Args:
347
+ other: The other number.
348
+
349
+ Returns:
350
+ The result of the comparison.
351
+ """
352
+ return GreaterThanOrEqualOperation(self, +other)
353
+
354
+ def bool(self) -> NotEqualOperation:
355
+ """Boolean conversion.
356
+
357
+ Returns:
358
+ The boolean value of the number.
359
+ """
360
+ return NotEqualOperation(self, 0)
361
+
362
+
363
+ @dataclasses.dataclass(
364
+ eq=False,
365
+ frozen=True,
366
+ **{"slots": True} if sys.version_info >= (3, 10) else {},
367
+ )
368
+ class BinaryNumberOperation(NumberVar):
369
+ """Base class for immutable number vars that are the result of a binary operation."""
370
+
371
+ a: number_types = dataclasses.field(default=0)
372
+ b: number_types = dataclasses.field(default=0)
373
+
374
+ def __init__(
375
+ self,
376
+ a: number_types,
377
+ b: number_types,
378
+ _var_data: VarData | None = None,
379
+ ):
380
+ """Initialize the binary number operation var.
381
+
382
+ Args:
383
+ a: The first number.
384
+ b: The second number.
385
+ _var_data: Additional hooks and imports associated with the Var.
386
+ """
387
+ super(BinaryNumberOperation, self).__init__(
388
+ _var_name="",
389
+ _var_type=float,
390
+ _var_data=ImmutableVarData.merge(_var_data),
391
+ )
392
+ object.__setattr__(self, "a", a)
393
+ object.__setattr__(self, "b", b)
394
+ object.__delattr__(self, "_var_name")
395
+
396
+ @cached_property
397
+ def _cached_var_name(self) -> str:
398
+ """The name of the var.
399
+
400
+ Raises:
401
+ NotImplementedError: Must be implemented by subclasses
402
+ """
403
+ raise NotImplementedError(
404
+ "BinaryNumberOperation must implement _cached_var_name"
405
+ )
406
+
407
+ def __getattr__(self, name: str) -> Any:
408
+ """Get an attribute of the var.
409
+
410
+ Args:
411
+ name: The name of the attribute.
412
+
413
+ Returns:
414
+ The attribute value.
415
+ """
416
+ if name == "_var_name":
417
+ return self._cached_var_name
418
+ getattr(super(BinaryNumberOperation, self), name)
419
+
420
+ @cached_property
421
+ def _cached_get_all_var_data(self) -> ImmutableVarData | None:
422
+ """Get all VarData associated with the Var.
423
+
424
+ Returns:
425
+ The VarData of the components and all of its children.
426
+ """
427
+ first_value = self.a if isinstance(self.a, Var) else LiteralNumberVar(self.a)
428
+ second_value = self.b if isinstance(self.b, Var) else LiteralNumberVar(self.b)
429
+ return ImmutableVarData.merge(
430
+ first_value._get_all_var_data(),
431
+ second_value._get_all_var_data(),
432
+ self._var_data,
433
+ )
434
+
435
+ def _get_all_var_data(self) -> ImmutableVarData | None:
436
+ return self._cached_get_all_var_data
437
+
438
+
439
+ @dataclasses.dataclass(
440
+ eq=False,
441
+ frozen=True,
442
+ **{"slots": True} if sys.version_info >= (3, 10) else {},
443
+ )
444
+ class UnaryNumberOperation(NumberVar):
445
+ """Base class for immutable number vars that are the result of a unary operation."""
446
+
447
+ a: number_types = dataclasses.field(default=0)
448
+
449
+ def __init__(
450
+ self,
451
+ a: number_types,
452
+ _var_data: VarData | None = None,
453
+ ):
454
+ """Initialize the unary number operation var.
455
+
456
+ Args:
457
+ a: The number.
458
+ _var_data: Additional hooks and imports associated with the Var.
459
+ """
460
+ super(UnaryNumberOperation, self).__init__(
461
+ _var_name="",
462
+ _var_type=float,
463
+ _var_data=ImmutableVarData.merge(_var_data),
464
+ )
465
+ object.__setattr__(self, "a", a)
466
+ object.__delattr__(self, "_var_name")
467
+
468
+ @cached_property
469
+ def _cached_var_name(self) -> str:
470
+ """The name of the var.
471
+
472
+ Raises:
473
+ NotImplementedError: Must be implemented by subclasses.
474
+ """
475
+ raise NotImplementedError(
476
+ "UnaryNumberOperation must implement _cached_var_name"
477
+ )
478
+
479
+ def __getattr__(self, name: str) -> Any:
480
+ """Get an attribute of the var.
481
+
482
+ Args:
483
+ name: The name of the attribute.
484
+
485
+ Returns:
486
+ The attribute value.
487
+ """
488
+ if name == "_var_name":
489
+ return self._cached_var_name
490
+ getattr(super(UnaryNumberOperation, self), name)
491
+
492
+ @cached_property
493
+ def _cached_get_all_var_data(self) -> ImmutableVarData | None:
494
+ """Get all VarData associated with the Var.
495
+
496
+ Returns:
497
+ The VarData of the components and all of its children.
498
+ """
499
+ value = self.a if isinstance(self.a, Var) else LiteralNumberVar(self.a)
500
+ return ImmutableVarData.merge(value._get_all_var_data(), self._var_data)
501
+
502
+ def _get_all_var_data(self) -> ImmutableVarData | None:
503
+ return self._cached_get_all_var_data
504
+
505
+
506
+ class NumberAddOperation(BinaryNumberOperation):
507
+ """Base class for immutable number vars that are the result of an addition operation."""
508
+
509
+ @cached_property
510
+ def _cached_var_name(self) -> str:
511
+ """The name of the var.
512
+
513
+ Returns:
514
+ The name of the var.
515
+ """
516
+ first_value = self.a if isinstance(self.a, Var) else LiteralNumberVar(self.a)
517
+ second_value = self.b if isinstance(self.b, Var) else LiteralNumberVar(self.b)
518
+ return f"({str(first_value)} + {str(second_value)})"
519
+
520
+
521
+ class NumberSubtractOperation(BinaryNumberOperation):
522
+ """Base class for immutable number vars that are the result of a subtraction operation."""
523
+
524
+ @cached_property
525
+ def _cached_var_name(self) -> str:
526
+ """The name of the var.
527
+
528
+ Returns:
529
+ The name of the var.
530
+ """
531
+ first_value = self.a if isinstance(self.a, Var) else LiteralNumberVar(self.a)
532
+ second_value = self.b if isinstance(self.b, Var) else LiteralNumberVar(self.b)
533
+ return f"({str(first_value)} - {str(second_value)})"
534
+
535
+
536
+ class NumberAbsoluteOperation(UnaryNumberOperation):
537
+ """Base class for immutable number vars that are the result of an absolute operation."""
538
+
539
+ @cached_property
540
+ def _cached_var_name(self) -> str:
541
+ """The name of the var.
542
+
543
+ Returns:
544
+ The name of the var.
545
+ """
546
+ value = self.a if isinstance(self.a, Var) else LiteralNumberVar(self.a)
547
+ return f"Math.abs({str(value)})"
548
+
549
+
550
+ class NumberMultiplyOperation(BinaryNumberOperation):
551
+ """Base class for immutable number vars that are the result of a multiplication operation."""
552
+
553
+ @cached_property
554
+ def _cached_var_name(self) -> str:
555
+ """The name of the var.
556
+
557
+ Returns:
558
+ The name of the var.
559
+ """
560
+ first_value = self.a if isinstance(self.a, Var) else LiteralNumberVar(self.a)
561
+ second_value = self.b if isinstance(self.b, Var) else LiteralNumberVar(self.b)
562
+ return f"({str(first_value)} * {str(second_value)})"
563
+
564
+
565
+ class NumberNegateOperation(UnaryNumberOperation):
566
+ """Base class for immutable number vars that are the result of a negation operation."""
567
+
568
+ @cached_property
569
+ def _cached_var_name(self) -> str:
570
+ """The name of the var.
571
+
572
+ Returns:
573
+ The name of the var.
574
+ """
575
+ value = self.a if isinstance(self.a, Var) else LiteralNumberVar(self.a)
576
+ return f"-({str(value)})"
577
+
578
+
579
+ class NumberTrueDivision(BinaryNumberOperation):
580
+ """Base class for immutable number vars that are the result of a true division operation."""
581
+
582
+ @cached_property
583
+ def _cached_var_name(self) -> str:
584
+ """The name of the var.
585
+
586
+ Returns:
587
+ The name of the var.
588
+ """
589
+ first_value = self.a if isinstance(self.a, Var) else LiteralNumberVar(self.a)
590
+ second_value = self.b if isinstance(self.b, Var) else LiteralNumberVar(self.b)
591
+ return f"({str(first_value)} / {str(second_value)})"
592
+
593
+
594
+ class NumberFloorDivision(BinaryNumberOperation):
595
+ """Base class for immutable number vars that are the result of a floor division operation."""
596
+
597
+ @cached_property
598
+ def _cached_var_name(self) -> str:
599
+ """The name of the var.
600
+
601
+ Returns:
602
+ The name of the var.
603
+ """
604
+ first_value = self.a if isinstance(self.a, Var) else LiteralNumberVar(self.a)
605
+ second_value = self.b if isinstance(self.b, Var) else LiteralNumberVar(self.b)
606
+ return f"Math.floor({str(first_value)} / {str(second_value)})"
607
+
608
+
609
+ class NumberModuloOperation(BinaryNumberOperation):
610
+ """Base class for immutable number vars that are the result of a modulo operation."""
611
+
612
+ @cached_property
613
+ def _cached_var_name(self) -> str:
614
+ """The name of the var.
615
+
616
+ Returns:
617
+ The name of the var.
618
+ """
619
+ first_value = self.a if isinstance(self.a, Var) else LiteralNumberVar(self.a)
620
+ second_value = self.b if isinstance(self.b, Var) else LiteralNumberVar(self.b)
621
+ return f"({str(first_value)} % {str(second_value)})"
622
+
623
+
624
+ class NumberExponentOperation(BinaryNumberOperation):
625
+ """Base class for immutable number vars that are the result of an exponent operation."""
626
+
627
+ @cached_property
628
+ def _cached_var_name(self) -> str:
629
+ """The name of the var.
630
+
631
+ Returns:
632
+ The name of the var.
633
+ """
634
+ first_value = self.a if isinstance(self.a, Var) else LiteralNumberVar(self.a)
635
+ second_value = self.b if isinstance(self.b, Var) else LiteralNumberVar(self.b)
636
+ return f"({str(first_value)} ** {str(second_value)})"
637
+
638
+
639
+ class NumberRoundOperation(UnaryNumberOperation):
640
+ """Base class for immutable number vars that are the result of a round operation."""
641
+
642
+ @cached_property
643
+ def _cached_var_name(self) -> str:
644
+ """The name of the var.
645
+
646
+ Returns:
647
+ The name of the var.
648
+ """
649
+ value = self.a if isinstance(self.a, Var) else LiteralNumberVar(self.a)
650
+ return f"Math.round({str(value)})"
651
+
652
+
653
+ class NumberCeilOperation(UnaryNumberOperation):
654
+ """Base class for immutable number vars that are the result of a ceil operation."""
655
+
656
+ @cached_property
657
+ def _cached_var_name(self) -> str:
658
+ """The name of the var.
659
+
660
+ Returns:
661
+ The name of the var.
662
+ """
663
+ value = self.a if isinstance(self.a, Var) else LiteralNumberVar(self.a)
664
+ return f"Math.ceil({str(value)})"
665
+
666
+
667
+ class NumberFloorOperation(UnaryNumberOperation):
668
+ """Base class for immutable number vars that are the result of a floor operation."""
669
+
670
+ @cached_property
671
+ def _cached_var_name(self) -> str:
672
+ """The name of the var.
673
+
674
+ Returns:
675
+ The name of the var.
676
+ """
677
+ value = self.a if isinstance(self.a, Var) else LiteralNumberVar(self.a)
678
+ return f"Math.floor({str(value)})"
679
+
680
+
681
+ class NumberTruncOperation(UnaryNumberOperation):
682
+ """Base class for immutable number vars that are the result of a trunc operation."""
683
+
684
+ @cached_property
685
+ def _cached_var_name(self) -> str:
686
+ """The name of the var.
687
+
688
+ Returns:
689
+ The name of the var.
690
+ """
691
+ value = self.a if isinstance(self.a, Var) else LiteralNumberVar(self.a)
692
+ return f"Math.trunc({str(value)})"
693
+
694
+
695
+ class BooleanVar(ImmutableVar):
696
+ """Base class for immutable boolean vars."""
697
+
698
+ def __and__(self, other: bool) -> BooleanAndOperation:
699
+ """AND two booleans.
700
+
701
+ Args:
702
+ other: The other boolean.
703
+
704
+ Returns:
705
+ The boolean AND operation.
706
+ """
707
+ return BooleanAndOperation(self, other)
708
+
709
+ def __rand__(self, other: bool) -> BooleanAndOperation:
710
+ """AND two booleans.
711
+
712
+ Args:
713
+ other: The other boolean.
714
+
715
+ Returns:
716
+ The boolean AND operation.
717
+ """
718
+ return BooleanAndOperation(other, self)
719
+
720
+ def __or__(self, other: bool) -> BooleanOrOperation:
721
+ """OR two booleans.
722
+
723
+ Args:
724
+ other: The other boolean.
725
+
726
+ Returns:
727
+ The boolean OR operation.
728
+ """
729
+ return BooleanOrOperation(self, other)
730
+
731
+ def __ror__(self, other: bool) -> BooleanOrOperation:
732
+ """OR two booleans.
733
+
734
+ Args:
735
+ other: The other boolean.
736
+
737
+ Returns:
738
+ The boolean OR operation.
739
+ """
740
+ return BooleanOrOperation(other, self)
741
+
742
+ def __invert__(self) -> BooleanNotOperation:
743
+ """NOT the boolean.
744
+
745
+ Returns:
746
+ The boolean NOT operation.
747
+ """
748
+ return BooleanNotOperation(self)
749
+
750
+ def __int__(self) -> BooleanToIntOperation:
751
+ """Convert the boolean to an int.
752
+
753
+ Returns:
754
+ The boolean to int operation.
755
+ """
756
+ return BooleanToIntOperation(self)
757
+
758
+ def __pos__(self) -> BooleanToIntOperation:
759
+ """Convert the boolean to an int.
760
+
761
+ Returns:
762
+ The boolean to int operation.
763
+ """
764
+ return BooleanToIntOperation(self)
765
+
766
+ def bool(self) -> BooleanVar:
767
+ """Boolean conversion.
768
+
769
+ Returns:
770
+ The boolean value of the boolean.
771
+ """
772
+ return self
773
+
774
+ def __lt__(self, other: boolean_types | number_types) -> LessThanOperation:
775
+ """Less than comparison.
776
+
777
+ Args:
778
+ other: The other boolean.
779
+
780
+ Returns:
781
+ The result of the comparison.
782
+ """
783
+ return LessThanOperation(+self, +other)
784
+
785
+ def __le__(self, other: boolean_types | number_types) -> LessThanOrEqualOperation:
786
+ """Less than or equal comparison.
787
+
788
+ Args:
789
+ other: The other boolean.
790
+
791
+ Returns:
792
+ The result of the comparison.
793
+ """
794
+ return LessThanOrEqualOperation(+self, +other)
795
+
796
+ def __eq__(self, other: boolean_types | number_types) -> EqualOperation:
797
+ """Equal comparison.
798
+
799
+ Args:
800
+ other: The other boolean.
801
+
802
+ Returns:
803
+ The result of the comparison.
804
+ """
805
+ return EqualOperation(+self, +other)
806
+
807
+ def __ne__(self, other: boolean_types | number_types) -> NotEqualOperation:
808
+ """Not equal comparison.
809
+
810
+ Args:
811
+ other: The other boolean.
812
+
813
+ Returns:
814
+ The result of the comparison.
815
+ """
816
+ return NotEqualOperation(+self, +other)
817
+
818
+ def __gt__(self, other: boolean_types | number_types) -> GreaterThanOperation:
819
+ """Greater than comparison.
820
+
821
+ Args:
822
+ other: The other boolean.
823
+
824
+ Returns:
825
+ The result of the comparison.
826
+ """
827
+ return GreaterThanOperation(+self, +other)
828
+
829
+ def __ge__(
830
+ self, other: boolean_types | number_types
831
+ ) -> GreaterThanOrEqualOperation:
832
+ """Greater than or equal comparison.
833
+
834
+ Args:
835
+ other: The other boolean.
836
+
837
+ Returns:
838
+ The result of the comparison.
839
+ """
840
+ return GreaterThanOrEqualOperation(+self, +other)
841
+
842
+
843
+ @dataclasses.dataclass(
844
+ eq=False,
845
+ frozen=True,
846
+ **{"slots": True} if sys.version_info >= (3, 10) else {},
847
+ )
848
+ class BooleanToIntOperation(NumberVar):
849
+ """Base class for immutable number vars that are the result of a boolean to int operation."""
850
+
851
+ a: boolean_types = dataclasses.field(default=False)
852
+
853
+ def __init__(
854
+ self,
855
+ a: boolean_types,
856
+ _var_data: VarData | None = None,
857
+ ):
858
+ """Initialize the boolean to int operation var.
859
+
860
+ Args:
861
+ a: The boolean.
862
+ _var_data: Additional hooks and imports associated with the Var.
863
+ """
864
+ super(BooleanToIntOperation, self).__init__(
865
+ _var_name="",
866
+ _var_type=int,
867
+ _var_data=ImmutableVarData.merge(_var_data),
868
+ )
869
+ object.__setattr__(self, "a", a)
870
+ object.__delattr__(self, "_var_name")
871
+
872
+ @cached_property
873
+ def _cached_var_name(self) -> str:
874
+ """The name of the var.
875
+
876
+ Returns:
877
+ The name of the var.
878
+ """
879
+ return f"({str(self.a)} ? 1 : 0)"
880
+
881
+ def __getattr__(self, name: str) -> Any:
882
+ """Get an attribute of the var.
883
+
884
+ Args:
885
+ name: The name of the attribute.
886
+
887
+ Returns:
888
+ The attribute value.
889
+ """
890
+ if name == "_var_name":
891
+ return self._cached_var_name
892
+ getattr(super(BooleanToIntOperation, self), name)
893
+
894
+ @cached_property
895
+ def _cached_get_all_var_data(self) -> ImmutableVarData | None:
896
+ """Get all VarData associated with the Var.
897
+
898
+ Returns:
899
+ The VarData of the components and all of its children.
900
+ """
901
+ return ImmutableVarData.merge(
902
+ self.a._get_all_var_data() if isinstance(self.a, Var) else None,
903
+ self._var_data,
904
+ )
905
+
906
+ def _get_all_var_data(self) -> ImmutableVarData | None:
907
+ return self._cached_get_all_var_data
908
+
909
+
910
+ @dataclasses.dataclass(
911
+ eq=False,
912
+ frozen=True,
913
+ **{"slots": True} if sys.version_info >= (3, 10) else {},
914
+ )
915
+ class NumberComparisonOperation(BooleanVar):
916
+ """Base class for immutable boolean vars that are the result of a comparison operation."""
917
+
918
+ a: number_types = dataclasses.field(default=0)
919
+ b: number_types = dataclasses.field(default=0)
920
+
921
+ def __init__(
922
+ self,
923
+ a: number_types,
924
+ b: number_types,
925
+ _var_data: VarData | None = None,
926
+ ):
927
+ """Initialize the comparison operation var.
928
+
929
+ Args:
930
+ a: The first value.
931
+ b: The second value.
932
+ _var_data: Additional hooks and imports associated with the Var.
933
+ """
934
+ super(NumberComparisonOperation, self).__init__(
935
+ _var_name="",
936
+ _var_type=bool,
937
+ _var_data=ImmutableVarData.merge(_var_data),
938
+ )
939
+ object.__setattr__(self, "a", a)
940
+ object.__setattr__(self, "b", b)
941
+ object.__delattr__(self, "_var_name")
942
+
943
+ @cached_property
944
+ def _cached_var_name(self) -> str:
945
+ """The name of the var.
946
+
947
+ Raises:
948
+ NotImplementedError: Must be implemented by subclasses.
949
+ """
950
+ raise NotImplementedError("ComparisonOperation must implement _cached_var_name")
951
+
952
+ def __getattr__(self, name: str) -> Any:
953
+ """Get an attribute of the var.
954
+
955
+ Args:
956
+ name: The name of the attribute.
957
+
958
+ Returns:
959
+ The attribute value.
960
+ """
961
+ if name == "_var_name":
962
+ return self._cached_var_name
963
+ getattr(super(NumberComparisonOperation, self), name)
964
+
965
+ @cached_property
966
+ def _cached_get_all_var_data(self) -> ImmutableVarData | None:
967
+ """Get all VarData associated with the Var.
968
+
969
+ Returns:
970
+ The VarData of the components and all of its children.
971
+ """
972
+ first_value = self.a if isinstance(self.a, Var) else LiteralVar.create(self.a)
973
+ second_value = self.b if isinstance(self.b, Var) else LiteralVar.create(self.b)
974
+ return ImmutableVarData.merge(
975
+ first_value._get_all_var_data(), second_value._get_all_var_data()
976
+ )
977
+
978
+ def _get_all_var_data(self) -> ImmutableVarData | None:
979
+ return self._cached_get_all_var_data
980
+
981
+
982
+ class GreaterThanOperation(NumberComparisonOperation):
983
+ """Base class for immutable boolean vars that are the result of a greater than operation."""
984
+
985
+ @cached_property
986
+ def _cached_var_name(self) -> str:
987
+ """The name of the var.
988
+
989
+ Returns:
990
+ The name of the var.
991
+ """
992
+ first_value = self.a if isinstance(self.a, Var) else LiteralVar.create(self.a)
993
+ second_value = self.b if isinstance(self.b, Var) else LiteralVar.create(self.b)
994
+ return f"({str(first_value)} > {str(second_value)})"
995
+
996
+
997
+ class GreaterThanOrEqualOperation(NumberComparisonOperation):
998
+ """Base class for immutable boolean vars that are the result of a greater than or equal operation."""
999
+
1000
+ @cached_property
1001
+ def _cached_var_name(self) -> str:
1002
+ """The name of the var.
1003
+
1004
+ Returns:
1005
+ The name of the var.
1006
+ """
1007
+ first_value = self.a if isinstance(self.a, Var) else LiteralVar.create(self.a)
1008
+ second_value = self.b if isinstance(self.b, Var) else LiteralVar.create(self.b)
1009
+ return f"({str(first_value)} >= {str(second_value)})"
1010
+
1011
+
1012
+ class LessThanOperation(NumberComparisonOperation):
1013
+ """Base class for immutable boolean vars that are the result of a less than operation."""
1014
+
1015
+ @cached_property
1016
+ def _cached_var_name(self) -> str:
1017
+ """The name of the var.
1018
+
1019
+ Returns:
1020
+ The name of the var.
1021
+ """
1022
+ first_value = self.a if isinstance(self.a, Var) else LiteralVar.create(self.a)
1023
+ second_value = self.b if isinstance(self.b, Var) else LiteralVar.create(self.b)
1024
+ return f"({str(first_value)} < {str(second_value)})"
1025
+
1026
+
1027
+ class LessThanOrEqualOperation(NumberComparisonOperation):
1028
+ """Base class for immutable boolean vars that are the result of a less than or equal operation."""
1029
+
1030
+ @cached_property
1031
+ def _cached_var_name(self) -> str:
1032
+ """The name of the var.
1033
+
1034
+ Returns:
1035
+ The name of the var.
1036
+ """
1037
+ first_value = self.a if isinstance(self.a, Var) else LiteralVar.create(self.a)
1038
+ second_value = self.b if isinstance(self.b, Var) else LiteralVar.create(self.b)
1039
+ return f"({str(first_value)} <= {str(second_value)})"
1040
+
1041
+
1042
+ class EqualOperation(NumberComparisonOperation):
1043
+ """Base class for immutable boolean vars that are the result of an equal operation."""
1044
+
1045
+ @cached_property
1046
+ def _cached_var_name(self) -> str:
1047
+ """The name of the var.
1048
+
1049
+ Returns:
1050
+ The name of the var.
1051
+ """
1052
+ first_value = self.a if isinstance(self.a, Var) else LiteralVar.create(self.a)
1053
+ second_value = self.b if isinstance(self.b, Var) else LiteralVar.create(self.b)
1054
+ return f"({str(first_value)} == {str(second_value)})"
1055
+
1056
+
1057
+ class NotEqualOperation(NumberComparisonOperation):
1058
+ """Base class for immutable boolean vars that are the result of a not equal operation."""
1059
+
1060
+ @cached_property
1061
+ def _cached_var_name(self) -> str:
1062
+ """The name of the var.
1063
+
1064
+ Returns:
1065
+ The name of the var.
1066
+ """
1067
+ first_value = self.a if isinstance(self.a, Var) else LiteralVar.create(self.a)
1068
+ second_value = self.b if isinstance(self.b, Var) else LiteralVar.create(self.b)
1069
+ return f"({str(first_value)} != {str(second_value)})"
1070
+
1071
+
1072
+ @dataclasses.dataclass(
1073
+ eq=False,
1074
+ frozen=True,
1075
+ **{"slots": True} if sys.version_info >= (3, 10) else {},
1076
+ )
1077
+ class LogicalOperation(BooleanVar):
1078
+ """Base class for immutable boolean vars that are the result of a logical operation."""
1079
+
1080
+ a: boolean_types = dataclasses.field(default=False)
1081
+ b: boolean_types = dataclasses.field(default=False)
1082
+
1083
+ def __init__(
1084
+ self, a: boolean_types, b: boolean_types, _var_data: VarData | None = None
1085
+ ):
1086
+ """Initialize the logical operation var.
1087
+
1088
+ Args:
1089
+ a: The first value.
1090
+ b: The second value.
1091
+ _var_data: Additional hooks and imports associated with the Var.
1092
+ """
1093
+ super(LogicalOperation, self).__init__(
1094
+ _var_name="",
1095
+ _var_type=bool,
1096
+ _var_data=ImmutableVarData.merge(_var_data),
1097
+ )
1098
+ object.__setattr__(self, "a", a)
1099
+ object.__setattr__(self, "b", b)
1100
+ object.__delattr__(self, "_var_name")
1101
+
1102
+ @cached_property
1103
+ def _cached_var_name(self) -> str:
1104
+ """The name of the var.
1105
+
1106
+ Raises:
1107
+ NotImplementedError: Must be implemented by subclasses.
1108
+ """
1109
+ raise NotImplementedError("LogicalOperation must implement _cached_var_name")
1110
+
1111
+ def __getattr__(self, name: str) -> Any:
1112
+ """Get an attribute of the var.
1113
+
1114
+ Args:
1115
+ name: The name of the attribute.
1116
+
1117
+ Returns:
1118
+ The attribute value.
1119
+ """
1120
+ if name == "_var_name":
1121
+ return self._cached_var_name
1122
+ getattr(super(LogicalOperation, self), name)
1123
+
1124
+ @cached_property
1125
+ def _cached_get_all_var_data(self) -> ImmutableVarData | None:
1126
+ """Get all VarData associated with the Var.
1127
+
1128
+ Returns:
1129
+ The VarData of the components and all of its children.
1130
+ """
1131
+ first_value = self.a if isinstance(self.a, Var) else LiteralVar.create(self.a)
1132
+ second_value = self.b if isinstance(self.b, Var) else LiteralVar.create(self.b)
1133
+ return ImmutableVarData.merge(
1134
+ first_value._get_all_var_data(), second_value._get_all_var_data()
1135
+ )
1136
+
1137
+ def _get_all_var_data(self) -> ImmutableVarData | None:
1138
+ return self._cached_get_all_var_data
1139
+
1140
+
1141
+ class BooleanAndOperation(LogicalOperation):
1142
+ """Base class for immutable boolean vars that are the result of a logical AND operation."""
1143
+
1144
+ @cached_property
1145
+ def _cached_var_name(self) -> str:
1146
+ """The name of the var.
1147
+
1148
+ Returns:
1149
+ The name of the var.
1150
+ """
1151
+ first_value = self.a if isinstance(self.a, Var) else LiteralVar.create(self.a)
1152
+ second_value = self.b if isinstance(self.b, Var) else LiteralVar.create(self.b)
1153
+ return f"({str(first_value)} && {str(second_value)})"
1154
+
1155
+
1156
+ class BooleanOrOperation(LogicalOperation):
1157
+ """Base class for immutable boolean vars that are the result of a logical OR operation."""
1158
+
1159
+ @cached_property
1160
+ def _cached_var_name(self) -> str:
1161
+ """The name of the var.
1162
+
1163
+ Returns:
1164
+ The name of the var.
1165
+ """
1166
+ first_value = self.a if isinstance(self.a, Var) else LiteralVar.create(self.a)
1167
+ second_value = self.b if isinstance(self.b, Var) else LiteralVar.create(self.b)
1168
+ return f"({str(first_value)} || {str(second_value)})"
1169
+
1170
+
1171
+ class BooleanNotOperation(BooleanVar):
1172
+ """Base class for immutable boolean vars that are the result of a logical NOT operation."""
1173
+
1174
+ a: boolean_types = dataclasses.field()
1175
+
1176
+ def __init__(self, a: boolean_types, _var_data: VarData | None = None):
1177
+ """Initialize the logical NOT operation var.
1178
+
1179
+ Args:
1180
+ a: The value.
1181
+ _var_data: Additional hooks and imports associated with the Var.
1182
+ """
1183
+ super(BooleanNotOperation, self).__init__(
1184
+ _var_name="",
1185
+ _var_type=bool,
1186
+ _var_data=ImmutableVarData.merge(_var_data),
1187
+ )
1188
+ object.__setattr__(self, "a", a)
1189
+ object.__delattr__(self, "_var_name")
1190
+
1191
+ @cached_property
1192
+ def _cached_var_name(self) -> str:
1193
+ """The name of the var.
1194
+
1195
+ Returns:
1196
+ The name of the var.
1197
+ """
1198
+ value = self.a if isinstance(self.a, Var) else LiteralVar.create(self.a)
1199
+ return f"!({str(value)})"
1200
+
1201
+ def __getattr__(self, name: str) -> Any:
1202
+ """Get an attribute of the var.
1203
+
1204
+ Args:
1205
+ name: The name of the attribute.
1206
+
1207
+ Returns:
1208
+ The attribute value.
1209
+ """
1210
+ if name == "_var_name":
1211
+ return self._cached_var_name
1212
+ getattr(super(BooleanNotOperation, self), name)
1213
+
1214
+ @cached_property
1215
+ def _cached_get_all_var_data(self) -> ImmutableVarData | None:
1216
+ """Get all VarData associated with the Var.
1217
+
1218
+ Returns:
1219
+ The VarData of the components and all of its children.
1220
+ """
1221
+ value = self.a if isinstance(self.a, Var) else LiteralVar.create(self.a)
1222
+ return ImmutableVarData.merge(value._get_all_var_data())
1223
+
1224
+ def _get_all_var_data(self) -> ImmutableVarData | None:
1225
+ return self._cached_get_all_var_data
1226
+
1227
+
1228
+ @dataclasses.dataclass(
1229
+ eq=False,
1230
+ frozen=True,
1231
+ **{"slots": True} if sys.version_info >= (3, 10) else {},
1232
+ )
1233
+ class LiteralBooleanVar(LiteralVar, BooleanVar):
1234
+ """Base class for immutable literal boolean vars."""
1235
+
1236
+ _var_value: bool = dataclasses.field(default=False)
1237
+
1238
+ def __init__(
1239
+ self,
1240
+ _var_value: bool,
1241
+ _var_data: VarData | None = None,
1242
+ ):
1243
+ """Initialize the boolean var.
1244
+
1245
+ Args:
1246
+ _var_value: The value of the var.
1247
+ _var_data: Additional hooks and imports associated with the Var.
1248
+ """
1249
+ super(LiteralBooleanVar, self).__init__(
1250
+ _var_name="true" if _var_value else "false",
1251
+ _var_type=bool,
1252
+ _var_data=ImmutableVarData.merge(_var_data),
1253
+ )
1254
+ object.__setattr__(self, "_var_value", _var_value)
1255
+
1256
+
1257
+ @dataclasses.dataclass(
1258
+ eq=False,
1259
+ frozen=True,
1260
+ **{"slots": True} if sys.version_info >= (3, 10) else {},
1261
+ )
1262
+ class LiteralNumberVar(LiteralVar, NumberVar):
1263
+ """Base class for immutable literal number vars."""
1264
+
1265
+ _var_value: float | int = dataclasses.field(default=0)
1266
+
1267
+ def __init__(
1268
+ self,
1269
+ _var_value: float | int,
1270
+ _var_data: VarData | None = None,
1271
+ ):
1272
+ """Initialize the number var.
1273
+
1274
+ Args:
1275
+ _var_value: The value of the var.
1276
+ _var_data: Additional hooks and imports associated with the Var.
1277
+ """
1278
+ super(LiteralNumberVar, self).__init__(
1279
+ _var_name=str(_var_value),
1280
+ _var_type=type(_var_value),
1281
+ _var_data=ImmutableVarData.merge(_var_data),
1282
+ )
1283
+ object.__setattr__(self, "_var_value", _var_value)
1284
+
1285
+ def __hash__(self) -> int:
1286
+ """Hash the var.
1287
+
1288
+ Returns:
1289
+ The hash of the var.
1290
+ """
1291
+ return hash(self._var_value)
1292
+
1293
+
1294
+ number_types = Union[NumberVar, LiteralNumberVar, int, float]
1295
+ boolean_types = Union[BooleanVar, LiteralBooleanVar, bool]