reflex 0.5.8a1__py3-none-any.whl → 0.5.9a1__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.
- reflex/.templates/web/utils/client_side_routing.js +6 -1
- reflex/.templates/web/utils/state.js +7 -2
- reflex/components/component.py +7 -0
- reflex/components/el/elements/metadata.py +26 -1
- reflex/components/el/elements/metadata.pyi +13 -0
- reflex/experimental/vars/__init__.py +2 -2
- reflex/experimental/vars/base.py +204 -98
- reflex/experimental/vars/function.py +78 -2
- reflex/experimental/vars/number.py +166 -3
- reflex/experimental/vars/object.py +804 -0
- reflex/experimental/vars/sequence.py +946 -221
- reflex/state.py +2 -2
- reflex/utils/format.py +5 -4
- reflex/vars.py +9 -1
- reflex/vars.pyi +3 -2
- {reflex-0.5.8a1.dist-info → reflex-0.5.9a1.dist-info}/METADATA +1 -1
- {reflex-0.5.8a1.dist-info → reflex-0.5.9a1.dist-info}/RECORD +20 -19
- {reflex-0.5.8a1.dist-info → reflex-0.5.9a1.dist-info}/LICENSE +0 -0
- {reflex-0.5.8a1.dist-info → reflex-0.5.9a1.dist-info}/WHEEL +0 -0
- {reflex-0.5.8a1.dist-info → reflex-0.5.9a1.dist-info}/entry_points.txt +0 -0
|
@@ -4,23 +4,49 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import dataclasses
|
|
6
6
|
import functools
|
|
7
|
+
import inspect
|
|
7
8
|
import json
|
|
8
9
|
import re
|
|
9
10
|
import sys
|
|
11
|
+
import typing
|
|
10
12
|
from functools import cached_property
|
|
11
|
-
from typing import
|
|
13
|
+
from typing import (
|
|
14
|
+
TYPE_CHECKING,
|
|
15
|
+
Any,
|
|
16
|
+
Dict,
|
|
17
|
+
List,
|
|
18
|
+
Literal,
|
|
19
|
+
Set,
|
|
20
|
+
Tuple,
|
|
21
|
+
TypeVar,
|
|
22
|
+
Union,
|
|
23
|
+
overload,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
from typing_extensions import get_origin
|
|
12
27
|
|
|
13
28
|
from reflex import constants
|
|
14
29
|
from reflex.constants.base import REFLEX_VAR_OPENING_TAG
|
|
15
30
|
from reflex.experimental.vars.base import (
|
|
16
31
|
ImmutableVar,
|
|
17
32
|
LiteralVar,
|
|
33
|
+
figure_out_type,
|
|
34
|
+
unionize,
|
|
18
35
|
)
|
|
19
|
-
from reflex.experimental.vars.number import
|
|
36
|
+
from reflex.experimental.vars.number import (
|
|
37
|
+
BooleanVar,
|
|
38
|
+
LiteralNumberVar,
|
|
39
|
+
NotEqualOperation,
|
|
40
|
+
NumberVar,
|
|
41
|
+
)
|
|
42
|
+
from reflex.utils.types import GenericType
|
|
20
43
|
from reflex.vars import ImmutableVarData, Var, VarData, _global_vars
|
|
21
44
|
|
|
45
|
+
if TYPE_CHECKING:
|
|
46
|
+
from .object import ObjectVar
|
|
47
|
+
|
|
22
48
|
|
|
23
|
-
class StringVar(ImmutableVar):
|
|
49
|
+
class StringVar(ImmutableVar[str]):
|
|
24
50
|
"""Base class for immutable string vars."""
|
|
25
51
|
|
|
26
52
|
def __add__(self, other: StringVar | str) -> ConcatVarOperation:
|
|
@@ -67,7 +93,15 @@ class StringVar(ImmutableVar):
|
|
|
67
93
|
"""
|
|
68
94
|
return ConcatVarOperation(*[self for _ in range(other)])
|
|
69
95
|
|
|
70
|
-
|
|
96
|
+
@overload
|
|
97
|
+
def __getitem__(self, i: slice) -> ArrayJoinOperation: ...
|
|
98
|
+
|
|
99
|
+
@overload
|
|
100
|
+
def __getitem__(self, i: int | NumberVar) -> StringItemOperation: ...
|
|
101
|
+
|
|
102
|
+
def __getitem__(
|
|
103
|
+
self, i: slice | int | NumberVar
|
|
104
|
+
) -> ArrayJoinOperation | StringItemOperation:
|
|
71
105
|
"""Get a slice of the string.
|
|
72
106
|
|
|
73
107
|
Args:
|
|
@@ -77,16 +111,16 @@ class StringVar(ImmutableVar):
|
|
|
77
111
|
The string slice operation.
|
|
78
112
|
"""
|
|
79
113
|
if isinstance(i, slice):
|
|
80
|
-
return
|
|
114
|
+
return self.split()[i].join()
|
|
81
115
|
return StringItemOperation(self, i)
|
|
82
116
|
|
|
83
|
-
def length(self) ->
|
|
117
|
+
def length(self) -> NumberVar:
|
|
84
118
|
"""Get the length of the string.
|
|
85
119
|
|
|
86
120
|
Returns:
|
|
87
121
|
The string length operation.
|
|
88
122
|
"""
|
|
89
|
-
return
|
|
123
|
+
return self.split().length()
|
|
90
124
|
|
|
91
125
|
def lower(self) -> StringLowerOperation:
|
|
92
126
|
"""Convert the string to lowercase.
|
|
@@ -120,13 +154,13 @@ class StringVar(ImmutableVar):
|
|
|
120
154
|
"""
|
|
121
155
|
return NotEqualOperation(self.length(), 0)
|
|
122
156
|
|
|
123
|
-
def reversed(self) ->
|
|
157
|
+
def reversed(self) -> ArrayJoinOperation:
|
|
124
158
|
"""Reverse the string.
|
|
125
159
|
|
|
126
160
|
Returns:
|
|
127
161
|
The string reverse operation.
|
|
128
162
|
"""
|
|
129
|
-
return
|
|
163
|
+
return self.split().reverse().join()
|
|
130
164
|
|
|
131
165
|
def contains(self, other: StringVar | str) -> StringContainsOperation:
|
|
132
166
|
"""Check if the string contains another string.
|
|
@@ -151,85 +185,6 @@ class StringVar(ImmutableVar):
|
|
|
151
185
|
return StringSplitOperation(self, separator)
|
|
152
186
|
|
|
153
187
|
|
|
154
|
-
@dataclasses.dataclass(
|
|
155
|
-
eq=False,
|
|
156
|
-
frozen=True,
|
|
157
|
-
**{"slots": True} if sys.version_info >= (3, 10) else {},
|
|
158
|
-
)
|
|
159
|
-
class StringToNumberOperation(NumberVar):
|
|
160
|
-
"""Base class for immutable number vars that are the result of a string to number operation."""
|
|
161
|
-
|
|
162
|
-
a: StringVar = dataclasses.field(
|
|
163
|
-
default_factory=lambda: LiteralStringVar.create("")
|
|
164
|
-
)
|
|
165
|
-
|
|
166
|
-
def __init__(self, a: StringVar | str, _var_data: VarData | None = None):
|
|
167
|
-
"""Initialize the string to number operation var.
|
|
168
|
-
|
|
169
|
-
Args:
|
|
170
|
-
a: The string.
|
|
171
|
-
_var_data: Additional hooks and imports associated with the Var.
|
|
172
|
-
"""
|
|
173
|
-
super(StringToNumberOperation, self).__init__(
|
|
174
|
-
_var_name="",
|
|
175
|
-
_var_type=float,
|
|
176
|
-
_var_data=ImmutableVarData.merge(_var_data),
|
|
177
|
-
)
|
|
178
|
-
object.__setattr__(
|
|
179
|
-
self, "a", a if isinstance(a, Var) else LiteralStringVar.create(a)
|
|
180
|
-
)
|
|
181
|
-
object.__delattr__(self, "_var_name")
|
|
182
|
-
|
|
183
|
-
@cached_property
|
|
184
|
-
def _cached_var_name(self) -> str:
|
|
185
|
-
"""The name of the var.
|
|
186
|
-
|
|
187
|
-
Raises:
|
|
188
|
-
NotImplementedError: Must be implemented by subclasses.
|
|
189
|
-
"""
|
|
190
|
-
raise NotImplementedError(
|
|
191
|
-
"StringToNumberOperation must implement _cached_var_name"
|
|
192
|
-
)
|
|
193
|
-
|
|
194
|
-
def __getattr__(self, name: str) -> Any:
|
|
195
|
-
"""Get an attribute of the var.
|
|
196
|
-
|
|
197
|
-
Args:
|
|
198
|
-
name: The name of the attribute.
|
|
199
|
-
|
|
200
|
-
Returns:
|
|
201
|
-
The attribute value.
|
|
202
|
-
"""
|
|
203
|
-
if name == "_var_name":
|
|
204
|
-
return self._cached_var_name
|
|
205
|
-
getattr(super(StringToNumberOperation, self), name)
|
|
206
|
-
|
|
207
|
-
@cached_property
|
|
208
|
-
def _cached_get_all_var_data(self) -> ImmutableVarData | None:
|
|
209
|
-
"""Get all VarData associated with the Var.
|
|
210
|
-
|
|
211
|
-
Returns:
|
|
212
|
-
The VarData of the components and all of its children.
|
|
213
|
-
"""
|
|
214
|
-
return ImmutableVarData.merge(self.a._get_all_var_data(), self._var_data)
|
|
215
|
-
|
|
216
|
-
def _get_all_var_data(self) -> ImmutableVarData | None:
|
|
217
|
-
return self._cached_get_all_var_data
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
class StringLengthOperation(StringToNumberOperation):
|
|
221
|
-
"""Base class for immutable number vars that are the result of a string length operation."""
|
|
222
|
-
|
|
223
|
-
@cached_property
|
|
224
|
-
def _cached_var_name(self) -> str:
|
|
225
|
-
"""The name of the var.
|
|
226
|
-
|
|
227
|
-
Returns:
|
|
228
|
-
The name of the var.
|
|
229
|
-
"""
|
|
230
|
-
return f"{str(self.a)}.length"
|
|
231
|
-
|
|
232
|
-
|
|
233
188
|
@dataclasses.dataclass(
|
|
234
189
|
eq=False,
|
|
235
190
|
frozen=True,
|
|
@@ -338,19 +293,6 @@ class StringStripOperation(StringToStringOperation):
|
|
|
338
293
|
return f"{str(self.a)}.trim()"
|
|
339
294
|
|
|
340
295
|
|
|
341
|
-
class StringReverseOperation(StringToStringOperation):
|
|
342
|
-
"""Base class for immutable string vars that are the result of a string reverse operation."""
|
|
343
|
-
|
|
344
|
-
@cached_property
|
|
345
|
-
def _cached_var_name(self) -> str:
|
|
346
|
-
"""The name of the var.
|
|
347
|
-
|
|
348
|
-
Returns:
|
|
349
|
-
The name of the var.
|
|
350
|
-
"""
|
|
351
|
-
return f"{str(self.a)}.split('').reverse().join('')"
|
|
352
|
-
|
|
353
|
-
|
|
354
296
|
@dataclasses.dataclass(
|
|
355
297
|
eq=False,
|
|
356
298
|
frozen=True,
|
|
@@ -426,112 +368,6 @@ class StringContainsOperation(BooleanVar):
|
|
|
426
368
|
return self._cached_get_all_var_data
|
|
427
369
|
|
|
428
370
|
|
|
429
|
-
@dataclasses.dataclass(
|
|
430
|
-
eq=False,
|
|
431
|
-
frozen=True,
|
|
432
|
-
**{"slots": True} if sys.version_info >= (3, 10) else {},
|
|
433
|
-
)
|
|
434
|
-
class StringSliceOperation(StringVar):
|
|
435
|
-
"""Base class for immutable string vars that are the result of a string slice operation."""
|
|
436
|
-
|
|
437
|
-
a: StringVar = dataclasses.field(
|
|
438
|
-
default_factory=lambda: LiteralStringVar.create("")
|
|
439
|
-
)
|
|
440
|
-
_slice: slice = dataclasses.field(default_factory=lambda: slice(None, None, None))
|
|
441
|
-
|
|
442
|
-
def __init__(
|
|
443
|
-
self, a: StringVar | str, _slice: slice, _var_data: VarData | None = None
|
|
444
|
-
):
|
|
445
|
-
"""Initialize the string slice operation var.
|
|
446
|
-
|
|
447
|
-
Args:
|
|
448
|
-
a: The string.
|
|
449
|
-
_slice: The slice.
|
|
450
|
-
_var_data: Additional hooks and imports associated with the Var.
|
|
451
|
-
"""
|
|
452
|
-
super(StringSliceOperation, self).__init__(
|
|
453
|
-
_var_name="",
|
|
454
|
-
_var_type=str,
|
|
455
|
-
_var_data=ImmutableVarData.merge(_var_data),
|
|
456
|
-
)
|
|
457
|
-
object.__setattr__(
|
|
458
|
-
self, "a", a if isinstance(a, Var) else LiteralStringVar.create(a)
|
|
459
|
-
)
|
|
460
|
-
object.__setattr__(self, "_slice", _slice)
|
|
461
|
-
object.__delattr__(self, "_var_name")
|
|
462
|
-
|
|
463
|
-
@cached_property
|
|
464
|
-
def _cached_var_name(self) -> str:
|
|
465
|
-
"""The name of the var.
|
|
466
|
-
|
|
467
|
-
Returns:
|
|
468
|
-
The name of the var.
|
|
469
|
-
|
|
470
|
-
Raises:
|
|
471
|
-
ValueError: If the slice step is zero.
|
|
472
|
-
"""
|
|
473
|
-
start, end, step = self._slice.start, self._slice.stop, self._slice.step
|
|
474
|
-
|
|
475
|
-
if step is not None and step < 0:
|
|
476
|
-
actual_start = end + 1 if end is not None else 0
|
|
477
|
-
actual_end = start + 1 if start is not None else self.a.length()
|
|
478
|
-
return str(
|
|
479
|
-
StringSliceOperation(
|
|
480
|
-
StringReverseOperation(
|
|
481
|
-
StringSliceOperation(self.a, slice(actual_start, actual_end))
|
|
482
|
-
),
|
|
483
|
-
slice(None, None, -step),
|
|
484
|
-
)
|
|
485
|
-
)
|
|
486
|
-
|
|
487
|
-
start = (
|
|
488
|
-
LiteralVar.create(start)
|
|
489
|
-
if start is not None
|
|
490
|
-
else ImmutableVar.create_safe("undefined")
|
|
491
|
-
)
|
|
492
|
-
end = (
|
|
493
|
-
LiteralVar.create(end)
|
|
494
|
-
if end is not None
|
|
495
|
-
else ImmutableVar.create_safe("undefined")
|
|
496
|
-
)
|
|
497
|
-
|
|
498
|
-
if step is None:
|
|
499
|
-
return f"{str(self.a)}.slice({str(start)}, {str(end)})"
|
|
500
|
-
if step == 0:
|
|
501
|
-
raise ValueError("slice step cannot be zero")
|
|
502
|
-
return f"{str(self.a)}.slice({str(start)}, {str(end)}).split('').filter((_, i) => i % {str(step)} === 0).join('')"
|
|
503
|
-
|
|
504
|
-
def __getattr__(self, name: str) -> Any:
|
|
505
|
-
"""Get an attribute of the var.
|
|
506
|
-
|
|
507
|
-
Args:
|
|
508
|
-
name: The name of the attribute.
|
|
509
|
-
|
|
510
|
-
Returns:
|
|
511
|
-
The attribute value.
|
|
512
|
-
"""
|
|
513
|
-
if name == "_var_name":
|
|
514
|
-
return self._cached_var_name
|
|
515
|
-
getattr(super(StringSliceOperation, self), name)
|
|
516
|
-
|
|
517
|
-
@cached_property
|
|
518
|
-
def _cached_get_all_var_data(self) -> ImmutableVarData | None:
|
|
519
|
-
"""Get all VarData associated with the Var.
|
|
520
|
-
|
|
521
|
-
Returns:
|
|
522
|
-
The VarData of the components and all of its children.
|
|
523
|
-
"""
|
|
524
|
-
return ImmutableVarData.merge(
|
|
525
|
-
self.a._get_all_var_data(),
|
|
526
|
-
self.start._get_all_var_data(),
|
|
527
|
-
self.end._get_all_var_data(),
|
|
528
|
-
self._var_data,
|
|
529
|
-
)
|
|
530
|
-
|
|
531
|
-
def _get_all_var_data(self) -> ImmutableVarData | None:
|
|
532
|
-
return self._cached_get_all_var_data
|
|
533
|
-
|
|
534
|
-
|
|
535
371
|
@dataclasses.dataclass(
|
|
536
372
|
eq=False,
|
|
537
373
|
frozen=True,
|
|
@@ -543,9 +379,11 @@ class StringItemOperation(StringVar):
|
|
|
543
379
|
a: StringVar = dataclasses.field(
|
|
544
380
|
default_factory=lambda: LiteralStringVar.create("")
|
|
545
381
|
)
|
|
546
|
-
i:
|
|
382
|
+
i: NumberVar = dataclasses.field(default_factory=lambda: LiteralNumberVar(0))
|
|
547
383
|
|
|
548
|
-
def __init__(
|
|
384
|
+
def __init__(
|
|
385
|
+
self, a: StringVar | str, i: int | NumberVar, _var_data: VarData | None = None
|
|
386
|
+
):
|
|
549
387
|
"""Initialize the string item operation var.
|
|
550
388
|
|
|
551
389
|
Args:
|
|
@@ -561,7 +399,7 @@ class StringItemOperation(StringVar):
|
|
|
561
399
|
object.__setattr__(
|
|
562
400
|
self, "a", a if isinstance(a, Var) else LiteralStringVar.create(a)
|
|
563
401
|
)
|
|
564
|
-
object.__setattr__(self, "i", i)
|
|
402
|
+
object.__setattr__(self, "i", i if isinstance(i, Var) else LiteralNumberVar(i))
|
|
565
403
|
object.__delattr__(self, "_var_name")
|
|
566
404
|
|
|
567
405
|
@cached_property
|
|
@@ -593,7 +431,9 @@ class StringItemOperation(StringVar):
|
|
|
593
431
|
Returns:
|
|
594
432
|
The VarData of the components and all of its children.
|
|
595
433
|
"""
|
|
596
|
-
return ImmutableVarData.merge(
|
|
434
|
+
return ImmutableVarData.merge(
|
|
435
|
+
self.a._get_all_var_data(), self.i._get_all_var_data(), self._var_data
|
|
436
|
+
)
|
|
597
437
|
|
|
598
438
|
def _get_all_var_data(self) -> ImmutableVarData | None:
|
|
599
439
|
return self._cached_get_all_var_data
|
|
@@ -608,7 +448,7 @@ class ArrayJoinOperation(StringVar):
|
|
|
608
448
|
)
|
|
609
449
|
|
|
610
450
|
def __init__(
|
|
611
|
-
self, a: ArrayVar
|
|
451
|
+
self, a: ArrayVar, b: StringVar | str, _var_data: VarData | None = None
|
|
612
452
|
):
|
|
613
453
|
"""Initialize the array join operation var.
|
|
614
454
|
|
|
@@ -622,9 +462,7 @@ class ArrayJoinOperation(StringVar):
|
|
|
622
462
|
_var_type=str,
|
|
623
463
|
_var_data=ImmutableVarData.merge(_var_data),
|
|
624
464
|
)
|
|
625
|
-
object.__setattr__(
|
|
626
|
-
self, "a", a if isinstance(a, Var) else LiteralArrayVar.create(a)
|
|
627
|
-
)
|
|
465
|
+
object.__setattr__(self, "a", a)
|
|
628
466
|
object.__setattr__(
|
|
629
467
|
self, "b", b if isinstance(b, Var) else LiteralStringVar.create(b)
|
|
630
468
|
)
|
|
@@ -777,6 +615,22 @@ class LiteralStringVar(LiteralVar, StringVar):
|
|
|
777
615
|
_var_data=_var_data,
|
|
778
616
|
)
|
|
779
617
|
|
|
618
|
+
def __hash__(self) -> int:
|
|
619
|
+
"""Get the hash of the var.
|
|
620
|
+
|
|
621
|
+
Returns:
|
|
622
|
+
The hash of the var.
|
|
623
|
+
"""
|
|
624
|
+
return hash((self.__class__.__name__, self._var_value))
|
|
625
|
+
|
|
626
|
+
def json(self) -> str:
|
|
627
|
+
"""Get the JSON representation of the var.
|
|
628
|
+
|
|
629
|
+
Returns:
|
|
630
|
+
The JSON representation of the var.
|
|
631
|
+
"""
|
|
632
|
+
return json.dumps(self._var_value)
|
|
633
|
+
|
|
780
634
|
|
|
781
635
|
@dataclasses.dataclass(
|
|
782
636
|
eq=False,
|
|
@@ -861,7 +715,17 @@ class ConcatVarOperation(StringVar):
|
|
|
861
715
|
pass
|
|
862
716
|
|
|
863
717
|
|
|
864
|
-
|
|
718
|
+
ARRAY_VAR_TYPE = TypeVar("ARRAY_VAR_TYPE", bound=Union[List, Tuple, Set])
|
|
719
|
+
|
|
720
|
+
OTHER_TUPLE = TypeVar("OTHER_TUPLE")
|
|
721
|
+
|
|
722
|
+
INNER_ARRAY_VAR = TypeVar("INNER_ARRAY_VAR")
|
|
723
|
+
|
|
724
|
+
KEY_TYPE = TypeVar("KEY_TYPE")
|
|
725
|
+
VALUE_TYPE = TypeVar("VALUE_TYPE")
|
|
726
|
+
|
|
727
|
+
|
|
728
|
+
class ArrayVar(ImmutableVar[ARRAY_VAR_TYPE]):
|
|
865
729
|
"""Base class for immutable array vars."""
|
|
866
730
|
|
|
867
731
|
from reflex.experimental.vars.sequence import StringVar
|
|
@@ -879,13 +743,194 @@ class ArrayVar(ImmutableVar):
|
|
|
879
743
|
|
|
880
744
|
return ArrayJoinOperation(self, sep)
|
|
881
745
|
|
|
746
|
+
def reverse(self) -> ArrayVar[ARRAY_VAR_TYPE]:
|
|
747
|
+
"""Reverse the array.
|
|
748
|
+
|
|
749
|
+
Returns:
|
|
750
|
+
The reversed array.
|
|
751
|
+
"""
|
|
752
|
+
return ArrayReverseOperation(self)
|
|
753
|
+
|
|
754
|
+
@overload
|
|
755
|
+
def __getitem__(self, i: slice) -> ArrayVar[ARRAY_VAR_TYPE]: ...
|
|
756
|
+
|
|
757
|
+
@overload
|
|
758
|
+
def __getitem__(
|
|
759
|
+
self: (
|
|
760
|
+
ArrayVar[Tuple[int, OTHER_TUPLE]]
|
|
761
|
+
| ArrayVar[Tuple[float, OTHER_TUPLE]]
|
|
762
|
+
| ArrayVar[Tuple[int | float, OTHER_TUPLE]]
|
|
763
|
+
),
|
|
764
|
+
i: Literal[0, -2],
|
|
765
|
+
) -> NumberVar: ...
|
|
766
|
+
|
|
767
|
+
@overload
|
|
768
|
+
def __getitem__(
|
|
769
|
+
self: (
|
|
770
|
+
ArrayVar[Tuple[OTHER_TUPLE, int]]
|
|
771
|
+
| ArrayVar[Tuple[OTHER_TUPLE, float]]
|
|
772
|
+
| ArrayVar[Tuple[OTHER_TUPLE, int | float]]
|
|
773
|
+
),
|
|
774
|
+
i: Literal[1, -1],
|
|
775
|
+
) -> NumberVar: ...
|
|
776
|
+
|
|
777
|
+
@overload
|
|
778
|
+
def __getitem__(
|
|
779
|
+
self: ArrayVar[Tuple[str, OTHER_TUPLE]], i: Literal[0, -2]
|
|
780
|
+
) -> StringVar: ...
|
|
781
|
+
|
|
782
|
+
@overload
|
|
783
|
+
def __getitem__(
|
|
784
|
+
self: ArrayVar[Tuple[OTHER_TUPLE, str]], i: Literal[1, -1]
|
|
785
|
+
) -> StringVar: ...
|
|
786
|
+
|
|
787
|
+
@overload
|
|
788
|
+
def __getitem__(
|
|
789
|
+
self: ArrayVar[Tuple[bool, OTHER_TUPLE]], i: Literal[0, -2]
|
|
790
|
+
) -> BooleanVar: ...
|
|
791
|
+
|
|
792
|
+
@overload
|
|
793
|
+
def __getitem__(
|
|
794
|
+
self: ArrayVar[Tuple[OTHER_TUPLE, bool]], i: Literal[1, -1]
|
|
795
|
+
) -> BooleanVar: ...
|
|
796
|
+
|
|
797
|
+
@overload
|
|
798
|
+
def __getitem__(
|
|
799
|
+
self: (
|
|
800
|
+
ARRAY_VAR_OF_LIST_ELEMENT[int]
|
|
801
|
+
| ARRAY_VAR_OF_LIST_ELEMENT[float]
|
|
802
|
+
| ARRAY_VAR_OF_LIST_ELEMENT[int | float]
|
|
803
|
+
),
|
|
804
|
+
i: int | NumberVar,
|
|
805
|
+
) -> NumberVar: ...
|
|
806
|
+
|
|
807
|
+
@overload
|
|
808
|
+
def __getitem__(
|
|
809
|
+
self: ARRAY_VAR_OF_LIST_ELEMENT[str], i: int | NumberVar
|
|
810
|
+
) -> StringVar: ...
|
|
811
|
+
|
|
812
|
+
@overload
|
|
813
|
+
def __getitem__(
|
|
814
|
+
self: ARRAY_VAR_OF_LIST_ELEMENT[bool], i: int | NumberVar
|
|
815
|
+
) -> BooleanVar: ...
|
|
816
|
+
|
|
817
|
+
@overload
|
|
818
|
+
def __getitem__(
|
|
819
|
+
self: ARRAY_VAR_OF_LIST_ELEMENT[List[INNER_ARRAY_VAR]],
|
|
820
|
+
i: int | NumberVar,
|
|
821
|
+
) -> ArrayVar[List[INNER_ARRAY_VAR]]: ...
|
|
822
|
+
|
|
823
|
+
@overload
|
|
824
|
+
def __getitem__(
|
|
825
|
+
self: ARRAY_VAR_OF_LIST_ELEMENT[Set[INNER_ARRAY_VAR]],
|
|
826
|
+
i: int | NumberVar,
|
|
827
|
+
) -> ArrayVar[Set[INNER_ARRAY_VAR]]: ...
|
|
828
|
+
|
|
829
|
+
@overload
|
|
830
|
+
def __getitem__(
|
|
831
|
+
self: ARRAY_VAR_OF_LIST_ELEMENT[Tuple[INNER_ARRAY_VAR, ...]],
|
|
832
|
+
i: int | NumberVar,
|
|
833
|
+
) -> ArrayVar[Tuple[INNER_ARRAY_VAR, ...]]: ...
|
|
834
|
+
|
|
835
|
+
@overload
|
|
836
|
+
def __getitem__(
|
|
837
|
+
self: ARRAY_VAR_OF_LIST_ELEMENT[Dict[KEY_TYPE, VALUE_TYPE]],
|
|
838
|
+
i: int | NumberVar,
|
|
839
|
+
) -> ObjectVar[Dict[KEY_TYPE, VALUE_TYPE]]: ...
|
|
840
|
+
|
|
841
|
+
@overload
|
|
842
|
+
def __getitem__(self, i: int | NumberVar) -> ImmutableVar: ...
|
|
843
|
+
|
|
844
|
+
def __getitem__(
|
|
845
|
+
self, i: slice | int | NumberVar
|
|
846
|
+
) -> ArrayVar[ARRAY_VAR_TYPE] | ImmutableVar:
|
|
847
|
+
"""Get a slice of the array.
|
|
848
|
+
|
|
849
|
+
Args:
|
|
850
|
+
i: The slice.
|
|
851
|
+
|
|
852
|
+
Returns:
|
|
853
|
+
The array slice operation.
|
|
854
|
+
"""
|
|
855
|
+
if isinstance(i, slice):
|
|
856
|
+
return ArraySliceOperation(self, i)
|
|
857
|
+
return ArrayItemOperation(self, i).guess_type()
|
|
858
|
+
|
|
859
|
+
def length(self) -> NumberVar:
|
|
860
|
+
"""Get the length of the array.
|
|
861
|
+
|
|
862
|
+
Returns:
|
|
863
|
+
The length of the array.
|
|
864
|
+
"""
|
|
865
|
+
return ArrayLengthOperation(self)
|
|
866
|
+
|
|
867
|
+
@overload
|
|
868
|
+
@classmethod
|
|
869
|
+
def range(cls, stop: int | NumberVar, /) -> ArrayVar[List[int]]: ...
|
|
870
|
+
|
|
871
|
+
@overload
|
|
872
|
+
@classmethod
|
|
873
|
+
def range(
|
|
874
|
+
cls,
|
|
875
|
+
start: int | NumberVar,
|
|
876
|
+
end: int | NumberVar,
|
|
877
|
+
step: int | NumberVar = 1,
|
|
878
|
+
/,
|
|
879
|
+
) -> ArrayVar[List[int]]: ...
|
|
880
|
+
|
|
881
|
+
@classmethod
|
|
882
|
+
def range(
|
|
883
|
+
cls,
|
|
884
|
+
first_endpoint: int | NumberVar,
|
|
885
|
+
second_endpoint: int | NumberVar | None = None,
|
|
886
|
+
step: int | NumberVar | None = None,
|
|
887
|
+
) -> ArrayVar[List[int]]:
|
|
888
|
+
"""Create a range of numbers.
|
|
889
|
+
|
|
890
|
+
Args:
|
|
891
|
+
first_endpoint: The end of the range if second_endpoint is not provided, otherwise the start of the range.
|
|
892
|
+
second_endpoint: The end of the range.
|
|
893
|
+
step: The step of the range.
|
|
894
|
+
|
|
895
|
+
Returns:
|
|
896
|
+
The range of numbers.
|
|
897
|
+
"""
|
|
898
|
+
if second_endpoint is None:
|
|
899
|
+
start = 0
|
|
900
|
+
end = first_endpoint
|
|
901
|
+
else:
|
|
902
|
+
start = first_endpoint
|
|
903
|
+
end = second_endpoint
|
|
904
|
+
|
|
905
|
+
return RangeOperation(start, end, step or 1)
|
|
906
|
+
|
|
907
|
+
def contains(self, other: Any) -> BooleanVar:
|
|
908
|
+
"""Check if the array contains an element.
|
|
909
|
+
|
|
910
|
+
Args:
|
|
911
|
+
other: The element to check for.
|
|
912
|
+
|
|
913
|
+
Returns:
|
|
914
|
+
The array contains operation.
|
|
915
|
+
"""
|
|
916
|
+
return ArrayContainsOperation(self, other)
|
|
917
|
+
|
|
918
|
+
|
|
919
|
+
LIST_ELEMENT = TypeVar("LIST_ELEMENT")
|
|
920
|
+
|
|
921
|
+
ARRAY_VAR_OF_LIST_ELEMENT = Union[
|
|
922
|
+
ArrayVar[List[LIST_ELEMENT]],
|
|
923
|
+
ArrayVar[Set[LIST_ELEMENT]],
|
|
924
|
+
ArrayVar[Tuple[LIST_ELEMENT, ...]],
|
|
925
|
+
]
|
|
926
|
+
|
|
882
927
|
|
|
883
928
|
@dataclasses.dataclass(
|
|
884
929
|
eq=False,
|
|
885
930
|
frozen=True,
|
|
886
931
|
**{"slots": True} if sys.version_info >= (3, 10) else {},
|
|
887
932
|
)
|
|
888
|
-
class LiteralArrayVar(LiteralVar, ArrayVar):
|
|
933
|
+
class LiteralArrayVar(LiteralVar, ArrayVar[ARRAY_VAR_TYPE]):
|
|
889
934
|
"""Base class for immutable literal array vars."""
|
|
890
935
|
|
|
891
936
|
_var_value: Union[
|
|
@@ -893,20 +938,22 @@ class LiteralArrayVar(LiteralVar, ArrayVar):
|
|
|
893
938
|
] = dataclasses.field(default_factory=list)
|
|
894
939
|
|
|
895
940
|
def __init__(
|
|
896
|
-
self,
|
|
897
|
-
_var_value:
|
|
941
|
+
self: LiteralArrayVar[ARRAY_VAR_TYPE],
|
|
942
|
+
_var_value: ARRAY_VAR_TYPE,
|
|
943
|
+
_var_type: type[ARRAY_VAR_TYPE] | None = None,
|
|
898
944
|
_var_data: VarData | None = None,
|
|
899
945
|
):
|
|
900
946
|
"""Initialize the array var.
|
|
901
947
|
|
|
902
948
|
Args:
|
|
903
949
|
_var_value: The value of the var.
|
|
950
|
+
_var_type: The type of the var.
|
|
904
951
|
_var_data: Additional hooks and imports associated with the Var.
|
|
905
952
|
"""
|
|
906
953
|
super(LiteralArrayVar, self).__init__(
|
|
907
954
|
_var_name="",
|
|
908
955
|
_var_data=ImmutableVarData.merge(_var_data),
|
|
909
|
-
_var_type=
|
|
956
|
+
_var_type=(figure_out_type(_var_value) if _var_type is None else _var_type),
|
|
910
957
|
)
|
|
911
958
|
object.__setattr__(self, "_var_value", _var_value)
|
|
912
959
|
object.__delattr__(self, "_var_name")
|
|
@@ -963,6 +1010,28 @@ class LiteralArrayVar(LiteralVar, ArrayVar):
|
|
|
963
1010
|
"""
|
|
964
1011
|
return self._cached_get_all_var_data
|
|
965
1012
|
|
|
1013
|
+
def __hash__(self) -> int:
|
|
1014
|
+
"""Get the hash of the var.
|
|
1015
|
+
|
|
1016
|
+
Returns:
|
|
1017
|
+
The hash of the var.
|
|
1018
|
+
"""
|
|
1019
|
+
return hash((self.__class__.__name__, self._var_name))
|
|
1020
|
+
|
|
1021
|
+
def json(self) -> str:
|
|
1022
|
+
"""Get the JSON representation of the var.
|
|
1023
|
+
|
|
1024
|
+
Returns:
|
|
1025
|
+
The JSON representation of the var.
|
|
1026
|
+
"""
|
|
1027
|
+
return (
|
|
1028
|
+
"["
|
|
1029
|
+
+ ", ".join(
|
|
1030
|
+
[LiteralVar.create(element).json() for element in self._var_value]
|
|
1031
|
+
)
|
|
1032
|
+
+ "]"
|
|
1033
|
+
)
|
|
1034
|
+
|
|
966
1035
|
|
|
967
1036
|
@dataclasses.dataclass(
|
|
968
1037
|
eq=False,
|
|
@@ -991,7 +1060,7 @@ class StringSplitOperation(ArrayVar):
|
|
|
991
1060
|
"""
|
|
992
1061
|
super(StringSplitOperation, self).__init__(
|
|
993
1062
|
_var_name="",
|
|
994
|
-
_var_type=
|
|
1063
|
+
_var_type=List[str],
|
|
995
1064
|
_var_data=ImmutableVarData.merge(_var_data),
|
|
996
1065
|
)
|
|
997
1066
|
object.__setattr__(
|
|
@@ -1037,3 +1106,659 @@ class StringSplitOperation(ArrayVar):
|
|
|
1037
1106
|
|
|
1038
1107
|
def _get_all_var_data(self) -> ImmutableVarData | None:
|
|
1039
1108
|
return self._cached_get_all_var_data
|
|
1109
|
+
|
|
1110
|
+
|
|
1111
|
+
@dataclasses.dataclass(
|
|
1112
|
+
eq=False,
|
|
1113
|
+
frozen=True,
|
|
1114
|
+
**{"slots": True} if sys.version_info >= (3, 10) else {},
|
|
1115
|
+
)
|
|
1116
|
+
class ArrayToArrayOperation(ArrayVar):
|
|
1117
|
+
"""Base class for immutable array vars that are the result of an array to array operation."""
|
|
1118
|
+
|
|
1119
|
+
a: ArrayVar = dataclasses.field(default_factory=lambda: LiteralArrayVar([]))
|
|
1120
|
+
|
|
1121
|
+
def __init__(self, a: ArrayVar, _var_data: VarData | None = None):
|
|
1122
|
+
"""Initialize the array to array operation var.
|
|
1123
|
+
|
|
1124
|
+
Args:
|
|
1125
|
+
a: The string.
|
|
1126
|
+
_var_data: Additional hooks and imports associated with the Var.
|
|
1127
|
+
"""
|
|
1128
|
+
super(ArrayToArrayOperation, self).__init__(
|
|
1129
|
+
_var_name="",
|
|
1130
|
+
_var_type=a._var_type,
|
|
1131
|
+
_var_data=ImmutableVarData.merge(_var_data),
|
|
1132
|
+
)
|
|
1133
|
+
object.__setattr__(self, "a", a)
|
|
1134
|
+
object.__delattr__(self, "_var_name")
|
|
1135
|
+
|
|
1136
|
+
@cached_property
|
|
1137
|
+
def _cached_var_name(self) -> str:
|
|
1138
|
+
"""The name of the var.
|
|
1139
|
+
|
|
1140
|
+
Raises:
|
|
1141
|
+
NotImplementedError: Must be implemented by subclasses.
|
|
1142
|
+
"""
|
|
1143
|
+
raise NotImplementedError(
|
|
1144
|
+
"ArrayToArrayOperation must implement _cached_var_name"
|
|
1145
|
+
)
|
|
1146
|
+
|
|
1147
|
+
def __getattr__(self, name: str) -> Any:
|
|
1148
|
+
"""Get an attribute of the var.
|
|
1149
|
+
|
|
1150
|
+
Args:
|
|
1151
|
+
name: The name of the attribute.
|
|
1152
|
+
|
|
1153
|
+
Returns:
|
|
1154
|
+
The attribute value.
|
|
1155
|
+
"""
|
|
1156
|
+
if name == "_var_name":
|
|
1157
|
+
return self._cached_var_name
|
|
1158
|
+
getattr(super(ArrayToArrayOperation, self), name)
|
|
1159
|
+
|
|
1160
|
+
@cached_property
|
|
1161
|
+
def _cached_get_all_var_data(self) -> ImmutableVarData | None:
|
|
1162
|
+
"""Get all VarData associated with the Var.
|
|
1163
|
+
|
|
1164
|
+
Returns:
|
|
1165
|
+
The VarData of the components and all of its children.
|
|
1166
|
+
"""
|
|
1167
|
+
return ImmutableVarData.merge(
|
|
1168
|
+
self.a._get_all_var_data() if isinstance(self.a, Var) else None,
|
|
1169
|
+
self._var_data,
|
|
1170
|
+
)
|
|
1171
|
+
|
|
1172
|
+
def _get_all_var_data(self) -> ImmutableVarData | None:
|
|
1173
|
+
return self._cached_get_all_var_data
|
|
1174
|
+
|
|
1175
|
+
|
|
1176
|
+
@dataclasses.dataclass(
|
|
1177
|
+
eq=False,
|
|
1178
|
+
frozen=True,
|
|
1179
|
+
**{"slots": True} if sys.version_info >= (3, 10) else {},
|
|
1180
|
+
)
|
|
1181
|
+
class ArraySliceOperation(ArrayVar):
|
|
1182
|
+
"""Base class for immutable string vars that are the result of a string slice operation."""
|
|
1183
|
+
|
|
1184
|
+
a: ArrayVar = dataclasses.field(default_factory=lambda: LiteralArrayVar([]))
|
|
1185
|
+
_slice: slice = dataclasses.field(default_factory=lambda: slice(None, None, None))
|
|
1186
|
+
|
|
1187
|
+
def __init__(self, a: ArrayVar, _slice: slice, _var_data: VarData | None = None):
|
|
1188
|
+
"""Initialize the string slice operation var.
|
|
1189
|
+
|
|
1190
|
+
Args:
|
|
1191
|
+
a: The string.
|
|
1192
|
+
_slice: The slice.
|
|
1193
|
+
_var_data: Additional hooks and imports associated with the Var.
|
|
1194
|
+
"""
|
|
1195
|
+
super(ArraySliceOperation, self).__init__(
|
|
1196
|
+
_var_name="",
|
|
1197
|
+
_var_type=a._var_type,
|
|
1198
|
+
_var_data=ImmutableVarData.merge(_var_data),
|
|
1199
|
+
)
|
|
1200
|
+
object.__setattr__(self, "a", a)
|
|
1201
|
+
object.__setattr__(self, "_slice", _slice)
|
|
1202
|
+
object.__delattr__(self, "_var_name")
|
|
1203
|
+
|
|
1204
|
+
@cached_property
|
|
1205
|
+
def _cached_var_name(self) -> str:
|
|
1206
|
+
"""The name of the var.
|
|
1207
|
+
|
|
1208
|
+
Returns:
|
|
1209
|
+
The name of the var.
|
|
1210
|
+
|
|
1211
|
+
Raises:
|
|
1212
|
+
ValueError: If the slice step is zero.
|
|
1213
|
+
"""
|
|
1214
|
+
start, end, step = self._slice.start, self._slice.stop, self._slice.step
|
|
1215
|
+
|
|
1216
|
+
normalized_start = (
|
|
1217
|
+
LiteralVar.create(start)
|
|
1218
|
+
if start is not None
|
|
1219
|
+
else ImmutableVar.create_safe("undefined")
|
|
1220
|
+
)
|
|
1221
|
+
normalized_end = (
|
|
1222
|
+
LiteralVar.create(end)
|
|
1223
|
+
if end is not None
|
|
1224
|
+
else ImmutableVar.create_safe("undefined")
|
|
1225
|
+
)
|
|
1226
|
+
if step is None:
|
|
1227
|
+
return (
|
|
1228
|
+
f"{str(self.a)}.slice({str(normalized_start)}, {str(normalized_end)})"
|
|
1229
|
+
)
|
|
1230
|
+
if not isinstance(step, Var):
|
|
1231
|
+
if step < 0:
|
|
1232
|
+
actual_start = end + 1 if end is not None else 0
|
|
1233
|
+
actual_end = start + 1 if start is not None else self.a.length()
|
|
1234
|
+
return str(
|
|
1235
|
+
ArraySliceOperation(
|
|
1236
|
+
ArrayReverseOperation(
|
|
1237
|
+
ArraySliceOperation(self.a, slice(actual_start, actual_end))
|
|
1238
|
+
),
|
|
1239
|
+
slice(None, None, -step),
|
|
1240
|
+
)
|
|
1241
|
+
)
|
|
1242
|
+
if step == 0:
|
|
1243
|
+
raise ValueError("slice step cannot be zero")
|
|
1244
|
+
return f"{str(self.a)}.slice({str(normalized_start)}, {str(normalized_end)}).filter((_, i) => i % {str(step)} === 0)"
|
|
1245
|
+
|
|
1246
|
+
actual_start_reverse = end + 1 if end is not None else 0
|
|
1247
|
+
actual_end_reverse = start + 1 if start is not None else self.a.length()
|
|
1248
|
+
|
|
1249
|
+
return f"{str(self.step)} > 0 ? {str(self.a)}.slice({str(normalized_start)}, {str(normalized_end)}).filter((_, i) => i % {str(step)} === 0) : {str(self.a)}.slice({str(actual_start_reverse)}, {str(actual_end_reverse)}).reverse().filter((_, i) => i % {str(-step)} === 0)"
|
|
1250
|
+
|
|
1251
|
+
def __getattr__(self, name: str) -> Any:
|
|
1252
|
+
"""Get an attribute of the var.
|
|
1253
|
+
|
|
1254
|
+
Args:
|
|
1255
|
+
name: The name of the attribute.
|
|
1256
|
+
|
|
1257
|
+
Returns:
|
|
1258
|
+
The attribute value.
|
|
1259
|
+
"""
|
|
1260
|
+
if name == "_var_name":
|
|
1261
|
+
return self._cached_var_name
|
|
1262
|
+
getattr(super(ArraySliceOperation, self), name)
|
|
1263
|
+
|
|
1264
|
+
@cached_property
|
|
1265
|
+
def _cached_get_all_var_data(self) -> ImmutableVarData | None:
|
|
1266
|
+
"""Get all VarData associated with the Var.
|
|
1267
|
+
|
|
1268
|
+
Returns:
|
|
1269
|
+
The VarData of the components and all of its children.
|
|
1270
|
+
"""
|
|
1271
|
+
return ImmutableVarData.merge(
|
|
1272
|
+
self.a._get_all_var_data(),
|
|
1273
|
+
*[
|
|
1274
|
+
slice_value._get_all_var_data()
|
|
1275
|
+
for slice_value in (
|
|
1276
|
+
self._slice.start,
|
|
1277
|
+
self._slice.stop,
|
|
1278
|
+
self._slice.step,
|
|
1279
|
+
)
|
|
1280
|
+
if slice_value is not None and isinstance(slice_value, Var)
|
|
1281
|
+
],
|
|
1282
|
+
self._var_data,
|
|
1283
|
+
)
|
|
1284
|
+
|
|
1285
|
+
def _get_all_var_data(self) -> ImmutableVarData | None:
|
|
1286
|
+
return self._cached_get_all_var_data
|
|
1287
|
+
|
|
1288
|
+
|
|
1289
|
+
class ArrayReverseOperation(ArrayToArrayOperation):
|
|
1290
|
+
"""Base class for immutable string vars that are the result of a string reverse operation."""
|
|
1291
|
+
|
|
1292
|
+
@cached_property
|
|
1293
|
+
def _cached_var_name(self) -> str:
|
|
1294
|
+
"""The name of the var.
|
|
1295
|
+
|
|
1296
|
+
Returns:
|
|
1297
|
+
The name of the var.
|
|
1298
|
+
"""
|
|
1299
|
+
return f"{str(self.a)}.reverse()"
|
|
1300
|
+
|
|
1301
|
+
|
|
1302
|
+
@dataclasses.dataclass(
|
|
1303
|
+
eq=False,
|
|
1304
|
+
frozen=True,
|
|
1305
|
+
**{"slots": True} if sys.version_info >= (3, 10) else {},
|
|
1306
|
+
)
|
|
1307
|
+
class ArrayToNumberOperation(NumberVar):
|
|
1308
|
+
"""Base class for immutable number vars that are the result of an array to number operation."""
|
|
1309
|
+
|
|
1310
|
+
a: ArrayVar = dataclasses.field(
|
|
1311
|
+
default_factory=lambda: LiteralArrayVar([]),
|
|
1312
|
+
)
|
|
1313
|
+
|
|
1314
|
+
def __init__(self, a: ArrayVar, _var_data: VarData | None = None):
|
|
1315
|
+
"""Initialize the string to number operation var.
|
|
1316
|
+
|
|
1317
|
+
Args:
|
|
1318
|
+
a: The array.
|
|
1319
|
+
_var_data: Additional hooks and imports associated with the Var.
|
|
1320
|
+
"""
|
|
1321
|
+
super(ArrayToNumberOperation, self).__init__(
|
|
1322
|
+
_var_name="",
|
|
1323
|
+
_var_type=int,
|
|
1324
|
+
_var_data=ImmutableVarData.merge(_var_data),
|
|
1325
|
+
)
|
|
1326
|
+
object.__setattr__(self, "a", a if isinstance(a, Var) else LiteralArrayVar(a))
|
|
1327
|
+
object.__delattr__(self, "_var_name")
|
|
1328
|
+
|
|
1329
|
+
@cached_property
|
|
1330
|
+
def _cached_var_name(self) -> str:
|
|
1331
|
+
"""The name of the var.
|
|
1332
|
+
|
|
1333
|
+
Raises:
|
|
1334
|
+
NotImplementedError: Must be implemented by subclasses.
|
|
1335
|
+
"""
|
|
1336
|
+
raise NotImplementedError(
|
|
1337
|
+
"StringToNumberOperation must implement _cached_var_name"
|
|
1338
|
+
)
|
|
1339
|
+
|
|
1340
|
+
def __getattr__(self, name: str) -> Any:
|
|
1341
|
+
"""Get an attribute of the var.
|
|
1342
|
+
|
|
1343
|
+
Args:
|
|
1344
|
+
name: The name of the attribute.
|
|
1345
|
+
|
|
1346
|
+
Returns:
|
|
1347
|
+
The attribute value.
|
|
1348
|
+
"""
|
|
1349
|
+
if name == "_var_name":
|
|
1350
|
+
return self._cached_var_name
|
|
1351
|
+
getattr(super(ArrayToNumberOperation, self), name)
|
|
1352
|
+
|
|
1353
|
+
@cached_property
|
|
1354
|
+
def _cached_get_all_var_data(self) -> ImmutableVarData | None:
|
|
1355
|
+
"""Get all VarData associated with the Var.
|
|
1356
|
+
|
|
1357
|
+
Returns:
|
|
1358
|
+
The VarData of the components and all of its children.
|
|
1359
|
+
"""
|
|
1360
|
+
return ImmutableVarData.merge(self.a._get_all_var_data(), self._var_data)
|
|
1361
|
+
|
|
1362
|
+
def _get_all_var_data(self) -> ImmutableVarData | None:
|
|
1363
|
+
return self._cached_get_all_var_data
|
|
1364
|
+
|
|
1365
|
+
|
|
1366
|
+
class ArrayLengthOperation(ArrayToNumberOperation):
|
|
1367
|
+
"""Base class for immutable number vars that are the result of an array length operation."""
|
|
1368
|
+
|
|
1369
|
+
@cached_property
|
|
1370
|
+
def _cached_var_name(self) -> str:
|
|
1371
|
+
"""The name of the var.
|
|
1372
|
+
|
|
1373
|
+
Returns:
|
|
1374
|
+
The name of the var.
|
|
1375
|
+
"""
|
|
1376
|
+
return f"{str(self.a)}.length"
|
|
1377
|
+
|
|
1378
|
+
|
|
1379
|
+
def is_tuple_type(t: GenericType) -> bool:
|
|
1380
|
+
"""Check if a type is a tuple type.
|
|
1381
|
+
|
|
1382
|
+
Args:
|
|
1383
|
+
t: The type to check.
|
|
1384
|
+
|
|
1385
|
+
Returns:
|
|
1386
|
+
Whether the type is a tuple type.
|
|
1387
|
+
"""
|
|
1388
|
+
if inspect.isclass(t):
|
|
1389
|
+
return issubclass(t, tuple)
|
|
1390
|
+
return get_origin(t) is tuple
|
|
1391
|
+
|
|
1392
|
+
|
|
1393
|
+
@dataclasses.dataclass(
|
|
1394
|
+
eq=False,
|
|
1395
|
+
frozen=True,
|
|
1396
|
+
**{"slots": True} if sys.version_info >= (3, 10) else {},
|
|
1397
|
+
)
|
|
1398
|
+
class ArrayItemOperation(ImmutableVar):
|
|
1399
|
+
"""Base class for immutable array vars that are the result of an array item operation."""
|
|
1400
|
+
|
|
1401
|
+
a: ArrayVar = dataclasses.field(default_factory=lambda: LiteralArrayVar([]))
|
|
1402
|
+
i: NumberVar = dataclasses.field(default_factory=lambda: LiteralNumberVar(0))
|
|
1403
|
+
|
|
1404
|
+
def __init__(
|
|
1405
|
+
self,
|
|
1406
|
+
a: ArrayVar,
|
|
1407
|
+
i: NumberVar | int,
|
|
1408
|
+
_var_data: VarData | None = None,
|
|
1409
|
+
):
|
|
1410
|
+
"""Initialize the array item operation var.
|
|
1411
|
+
|
|
1412
|
+
Args:
|
|
1413
|
+
a: The array.
|
|
1414
|
+
i: The index.
|
|
1415
|
+
_var_data: Additional hooks and imports associated with the Var.
|
|
1416
|
+
"""
|
|
1417
|
+
args = typing.get_args(a._var_type)
|
|
1418
|
+
if args and isinstance(i, int) and is_tuple_type(a._var_type):
|
|
1419
|
+
element_type = args[i % len(args)]
|
|
1420
|
+
else:
|
|
1421
|
+
element_type = unionize(*args)
|
|
1422
|
+
super(ArrayItemOperation, self).__init__(
|
|
1423
|
+
_var_name="",
|
|
1424
|
+
_var_type=element_type,
|
|
1425
|
+
_var_data=ImmutableVarData.merge(_var_data),
|
|
1426
|
+
)
|
|
1427
|
+
object.__setattr__(self, "a", a if isinstance(a, Var) else LiteralArrayVar(a))
|
|
1428
|
+
object.__setattr__(
|
|
1429
|
+
self,
|
|
1430
|
+
"i",
|
|
1431
|
+
i if isinstance(i, Var) else LiteralNumberVar(i),
|
|
1432
|
+
)
|
|
1433
|
+
object.__delattr__(self, "_var_name")
|
|
1434
|
+
|
|
1435
|
+
@cached_property
|
|
1436
|
+
def _cached_var_name(self) -> str:
|
|
1437
|
+
"""The name of the var.
|
|
1438
|
+
|
|
1439
|
+
Returns:
|
|
1440
|
+
The name of the var.
|
|
1441
|
+
"""
|
|
1442
|
+
return f"{str(self.a)}.at({str(self.i)})"
|
|
1443
|
+
|
|
1444
|
+
def __getattr__(self, name: str) -> Any:
|
|
1445
|
+
"""Get an attribute of the var.
|
|
1446
|
+
|
|
1447
|
+
Args:
|
|
1448
|
+
name: The name of the attribute.
|
|
1449
|
+
|
|
1450
|
+
Returns:
|
|
1451
|
+
The attribute value.
|
|
1452
|
+
"""
|
|
1453
|
+
if name == "_var_name":
|
|
1454
|
+
return self._cached_var_name
|
|
1455
|
+
getattr(super(ArrayItemOperation, self), name)
|
|
1456
|
+
|
|
1457
|
+
@cached_property
|
|
1458
|
+
def _cached_get_all_var_data(self) -> ImmutableVarData | None:
|
|
1459
|
+
"""Get all VarData associated with the Var.
|
|
1460
|
+
|
|
1461
|
+
Returns:
|
|
1462
|
+
The VarData of the components and all of its children.
|
|
1463
|
+
"""
|
|
1464
|
+
return ImmutableVarData.merge(
|
|
1465
|
+
self.a._get_all_var_data(), self.i._get_all_var_data(), self._var_data
|
|
1466
|
+
)
|
|
1467
|
+
|
|
1468
|
+
def _get_all_var_data(self) -> ImmutableVarData | None:
|
|
1469
|
+
return self._cached_get_all_var_data
|
|
1470
|
+
|
|
1471
|
+
|
|
1472
|
+
@dataclasses.dataclass(
|
|
1473
|
+
eq=False,
|
|
1474
|
+
frozen=True,
|
|
1475
|
+
**{"slots": True} if sys.version_info >= (3, 10) else {},
|
|
1476
|
+
)
|
|
1477
|
+
class RangeOperation(ArrayVar):
|
|
1478
|
+
"""Base class for immutable array vars that are the result of a range operation."""
|
|
1479
|
+
|
|
1480
|
+
start: NumberVar = dataclasses.field(default_factory=lambda: LiteralNumberVar(0))
|
|
1481
|
+
end: NumberVar = dataclasses.field(default_factory=lambda: LiteralNumberVar(0))
|
|
1482
|
+
step: NumberVar = dataclasses.field(default_factory=lambda: LiteralNumberVar(1))
|
|
1483
|
+
|
|
1484
|
+
def __init__(
|
|
1485
|
+
self,
|
|
1486
|
+
start: NumberVar | int,
|
|
1487
|
+
end: NumberVar | int,
|
|
1488
|
+
step: NumberVar | int,
|
|
1489
|
+
_var_data: VarData | None = None,
|
|
1490
|
+
):
|
|
1491
|
+
"""Initialize the range operation var.
|
|
1492
|
+
|
|
1493
|
+
Args:
|
|
1494
|
+
start: The start of the range.
|
|
1495
|
+
end: The end of the range.
|
|
1496
|
+
step: The step of the range.
|
|
1497
|
+
_var_data: Additional hooks and imports associated with the Var.
|
|
1498
|
+
"""
|
|
1499
|
+
super(RangeOperation, self).__init__(
|
|
1500
|
+
_var_name="",
|
|
1501
|
+
_var_type=List[int],
|
|
1502
|
+
_var_data=ImmutableVarData.merge(_var_data),
|
|
1503
|
+
)
|
|
1504
|
+
object.__setattr__(
|
|
1505
|
+
self,
|
|
1506
|
+
"start",
|
|
1507
|
+
start if isinstance(start, Var) else LiteralNumberVar(start),
|
|
1508
|
+
)
|
|
1509
|
+
object.__setattr__(
|
|
1510
|
+
self,
|
|
1511
|
+
"end",
|
|
1512
|
+
end if isinstance(end, Var) else LiteralNumberVar(end),
|
|
1513
|
+
)
|
|
1514
|
+
object.__setattr__(
|
|
1515
|
+
self,
|
|
1516
|
+
"step",
|
|
1517
|
+
step if isinstance(step, Var) else LiteralNumberVar(step),
|
|
1518
|
+
)
|
|
1519
|
+
object.__delattr__(self, "_var_name")
|
|
1520
|
+
|
|
1521
|
+
@cached_property
|
|
1522
|
+
def _cached_var_name(self) -> str:
|
|
1523
|
+
"""The name of the var.
|
|
1524
|
+
|
|
1525
|
+
Returns:
|
|
1526
|
+
The name of the var.
|
|
1527
|
+
"""
|
|
1528
|
+
start, end, step = self.start, self.end, self.step
|
|
1529
|
+
return f"Array.from({{ length: ({str(end)} - {str(start)}) / {str(step)} }}, (_, i) => {str(start)} + i * {str(step)})"
|
|
1530
|
+
|
|
1531
|
+
def __getattr__(self, name: str) -> Any:
|
|
1532
|
+
"""Get an attribute of the var.
|
|
1533
|
+
|
|
1534
|
+
Args:
|
|
1535
|
+
name: The name of the attribute.
|
|
1536
|
+
|
|
1537
|
+
Returns:
|
|
1538
|
+
The attribute value.
|
|
1539
|
+
"""
|
|
1540
|
+
if name == "_var_name":
|
|
1541
|
+
return self._cached_var_name
|
|
1542
|
+
getattr(super(RangeOperation, self), name)
|
|
1543
|
+
|
|
1544
|
+
@cached_property
|
|
1545
|
+
def _cached_get_all_var_data(self) -> ImmutableVarData | None:
|
|
1546
|
+
"""Get all VarData associated with the Var.
|
|
1547
|
+
|
|
1548
|
+
Returns:
|
|
1549
|
+
The VarData of the components and all of its children.
|
|
1550
|
+
"""
|
|
1551
|
+
return ImmutableVarData.merge(
|
|
1552
|
+
self.start._get_all_var_data(),
|
|
1553
|
+
self.end._get_all_var_data(),
|
|
1554
|
+
self.step._get_all_var_data(),
|
|
1555
|
+
self._var_data,
|
|
1556
|
+
)
|
|
1557
|
+
|
|
1558
|
+
def _get_all_var_data(self) -> ImmutableVarData | None:
|
|
1559
|
+
return self._cached_get_all_var_data
|
|
1560
|
+
|
|
1561
|
+
|
|
1562
|
+
@dataclasses.dataclass(
|
|
1563
|
+
eq=False,
|
|
1564
|
+
frozen=True,
|
|
1565
|
+
**{"slots": True} if sys.version_info >= (3, 10) else {},
|
|
1566
|
+
)
|
|
1567
|
+
class ArrayContainsOperation(BooleanVar):
|
|
1568
|
+
"""Base class for immutable boolean vars that are the result of an array contains operation."""
|
|
1569
|
+
|
|
1570
|
+
a: ArrayVar = dataclasses.field(default_factory=lambda: LiteralArrayVar([]))
|
|
1571
|
+
b: Var = dataclasses.field(default_factory=lambda: LiteralVar.create(None))
|
|
1572
|
+
|
|
1573
|
+
def __init__(self, a: ArrayVar, b: Any | Var, _var_data: VarData | None = None):
|
|
1574
|
+
"""Initialize the array contains operation var.
|
|
1575
|
+
|
|
1576
|
+
Args:
|
|
1577
|
+
a: The array.
|
|
1578
|
+
b: The element to check for.
|
|
1579
|
+
_var_data: Additional hooks and imports associated with the Var.
|
|
1580
|
+
"""
|
|
1581
|
+
super(ArrayContainsOperation, self).__init__(
|
|
1582
|
+
_var_name="",
|
|
1583
|
+
_var_type=bool,
|
|
1584
|
+
_var_data=ImmutableVarData.merge(_var_data),
|
|
1585
|
+
)
|
|
1586
|
+
object.__setattr__(self, "a", a)
|
|
1587
|
+
object.__setattr__(self, "b", b if isinstance(b, Var) else LiteralVar.create(b))
|
|
1588
|
+
object.__delattr__(self, "_var_name")
|
|
1589
|
+
|
|
1590
|
+
@cached_property
|
|
1591
|
+
def _cached_var_name(self) -> str:
|
|
1592
|
+
"""The name of the var.
|
|
1593
|
+
|
|
1594
|
+
Returns:
|
|
1595
|
+
The name of the var.
|
|
1596
|
+
"""
|
|
1597
|
+
return f"{str(self.a)}.includes({str(self.b)})"
|
|
1598
|
+
|
|
1599
|
+
def __getattr__(self, name: str) -> Any:
|
|
1600
|
+
"""Get an attribute of the var.
|
|
1601
|
+
|
|
1602
|
+
Args:
|
|
1603
|
+
name: The name of the attribute.
|
|
1604
|
+
|
|
1605
|
+
Returns:
|
|
1606
|
+
The attribute value.
|
|
1607
|
+
"""
|
|
1608
|
+
if name == "_var_name":
|
|
1609
|
+
return self._cached_var_name
|
|
1610
|
+
getattr(super(ArrayContainsOperation, self), name)
|
|
1611
|
+
|
|
1612
|
+
@cached_property
|
|
1613
|
+
def _cached_get_all_var_data(self) -> ImmutableVarData | None:
|
|
1614
|
+
"""Get all VarData associated with the Var.
|
|
1615
|
+
|
|
1616
|
+
Returns:
|
|
1617
|
+
The VarData of the components and all of its children.
|
|
1618
|
+
"""
|
|
1619
|
+
return ImmutableVarData.merge(
|
|
1620
|
+
self.a._get_all_var_data(), self.b._get_all_var_data(), self._var_data
|
|
1621
|
+
)
|
|
1622
|
+
|
|
1623
|
+
def _get_all_var_data(self) -> ImmutableVarData | None:
|
|
1624
|
+
return self._cached_get_all_var_data
|
|
1625
|
+
|
|
1626
|
+
|
|
1627
|
+
@dataclasses.dataclass(
|
|
1628
|
+
eq=False,
|
|
1629
|
+
frozen=True,
|
|
1630
|
+
**{"slots": True} if sys.version_info >= (3, 10) else {},
|
|
1631
|
+
)
|
|
1632
|
+
class ToStringOperation(StringVar):
|
|
1633
|
+
"""Base class for immutable string vars that are the result of a to string operation."""
|
|
1634
|
+
|
|
1635
|
+
original_var: Var = dataclasses.field(
|
|
1636
|
+
default_factory=lambda: LiteralStringVar.create("")
|
|
1637
|
+
)
|
|
1638
|
+
|
|
1639
|
+
def __init__(self, original_var: Var, _var_data: VarData | None = None):
|
|
1640
|
+
"""Initialize the to string operation var.
|
|
1641
|
+
|
|
1642
|
+
Args:
|
|
1643
|
+
original_var: The original var.
|
|
1644
|
+
_var_data: Additional hooks and imports associated with the Var.
|
|
1645
|
+
"""
|
|
1646
|
+
super(ToStringOperation, self).__init__(
|
|
1647
|
+
_var_name="",
|
|
1648
|
+
_var_type=str,
|
|
1649
|
+
_var_data=ImmutableVarData.merge(_var_data),
|
|
1650
|
+
)
|
|
1651
|
+
object.__setattr__(
|
|
1652
|
+
self,
|
|
1653
|
+
"original_var",
|
|
1654
|
+
original_var,
|
|
1655
|
+
)
|
|
1656
|
+
object.__delattr__(self, "_var_name")
|
|
1657
|
+
|
|
1658
|
+
@cached_property
|
|
1659
|
+
def _cached_var_name(self) -> str:
|
|
1660
|
+
"""The name of the var.
|
|
1661
|
+
|
|
1662
|
+
Returns:
|
|
1663
|
+
The name of the var.
|
|
1664
|
+
"""
|
|
1665
|
+
return str(self.original_var)
|
|
1666
|
+
|
|
1667
|
+
def __getattr__(self, name: str) -> Any:
|
|
1668
|
+
"""Get an attribute of the var.
|
|
1669
|
+
|
|
1670
|
+
Args:
|
|
1671
|
+
name: The name of the attribute.
|
|
1672
|
+
|
|
1673
|
+
Returns:
|
|
1674
|
+
The attribute value.
|
|
1675
|
+
"""
|
|
1676
|
+
if name == "_var_name":
|
|
1677
|
+
return self._cached_var_name
|
|
1678
|
+
getattr(super(ToStringOperation, self), name)
|
|
1679
|
+
|
|
1680
|
+
@cached_property
|
|
1681
|
+
def _cached_get_all_var_data(self) -> ImmutableVarData | None:
|
|
1682
|
+
"""Get all VarData associated with the Var.
|
|
1683
|
+
|
|
1684
|
+
Returns:
|
|
1685
|
+
The VarData of the components and all of its children.
|
|
1686
|
+
"""
|
|
1687
|
+
return ImmutableVarData.merge(
|
|
1688
|
+
self.original_var._get_all_var_data(), self._var_data
|
|
1689
|
+
)
|
|
1690
|
+
|
|
1691
|
+
def _get_all_var_data(self) -> ImmutableVarData | None:
|
|
1692
|
+
return self._cached_get_all_var_data
|
|
1693
|
+
|
|
1694
|
+
|
|
1695
|
+
@dataclasses.dataclass(
|
|
1696
|
+
eq=False,
|
|
1697
|
+
frozen=True,
|
|
1698
|
+
**{"slots": True} if sys.version_info >= (3, 10) else {},
|
|
1699
|
+
)
|
|
1700
|
+
class ToArrayOperation(ArrayVar):
|
|
1701
|
+
"""Base class for immutable array vars that are the result of a to array operation."""
|
|
1702
|
+
|
|
1703
|
+
original_var: Var = dataclasses.field(default_factory=lambda: LiteralArrayVar([]))
|
|
1704
|
+
|
|
1705
|
+
def __init__(
|
|
1706
|
+
self,
|
|
1707
|
+
original_var: Var,
|
|
1708
|
+
_var_type: type[list] | type[set] | type[tuple] = list,
|
|
1709
|
+
_var_data: VarData | None = None,
|
|
1710
|
+
):
|
|
1711
|
+
"""Initialize the to array operation var.
|
|
1712
|
+
|
|
1713
|
+
Args:
|
|
1714
|
+
original_var: The original var.
|
|
1715
|
+
_var_type: The type of the array.
|
|
1716
|
+
_var_data: Additional hooks and imports associated with the Var.
|
|
1717
|
+
"""
|
|
1718
|
+
super(ToArrayOperation, self).__init__(
|
|
1719
|
+
_var_name="",
|
|
1720
|
+
_var_type=_var_type,
|
|
1721
|
+
_var_data=ImmutableVarData.merge(_var_data),
|
|
1722
|
+
)
|
|
1723
|
+
object.__setattr__(
|
|
1724
|
+
self,
|
|
1725
|
+
"original_var",
|
|
1726
|
+
original_var,
|
|
1727
|
+
)
|
|
1728
|
+
object.__delattr__(self, "_var_name")
|
|
1729
|
+
|
|
1730
|
+
@cached_property
|
|
1731
|
+
def _cached_var_name(self) -> str:
|
|
1732
|
+
"""The name of the var.
|
|
1733
|
+
|
|
1734
|
+
Returns:
|
|
1735
|
+
The name of the var.
|
|
1736
|
+
"""
|
|
1737
|
+
return str(self.original_var)
|
|
1738
|
+
|
|
1739
|
+
def __getattr__(self, name: str) -> Any:
|
|
1740
|
+
"""Get an attribute of the var.
|
|
1741
|
+
|
|
1742
|
+
Args:
|
|
1743
|
+
name: The name of the attribute.
|
|
1744
|
+
|
|
1745
|
+
Returns:
|
|
1746
|
+
The attribute value.
|
|
1747
|
+
"""
|
|
1748
|
+
if name == "_var_name":
|
|
1749
|
+
return self._cached_var_name
|
|
1750
|
+
getattr(super(ToArrayOperation, self), name)
|
|
1751
|
+
|
|
1752
|
+
@cached_property
|
|
1753
|
+
def _cached_get_all_var_data(self) -> ImmutableVarData | None:
|
|
1754
|
+
"""Get all VarData associated with the Var.
|
|
1755
|
+
|
|
1756
|
+
Returns:
|
|
1757
|
+
The VarData of the components and all of its children.
|
|
1758
|
+
"""
|
|
1759
|
+
return ImmutableVarData.merge(
|
|
1760
|
+
self.original_var._get_all_var_data(), self._var_data
|
|
1761
|
+
)
|
|
1762
|
+
|
|
1763
|
+
def _get_all_var_data(self) -> ImmutableVarData | None:
|
|
1764
|
+
return self._cached_get_all_var_data
|