reflex 0.5.7a1__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.
- reflex/.templates/web/utils/state.js +1 -1
- reflex/app.py +20 -2
- reflex/components/core/banner.py +14 -0
- reflex/components/core/banner.pyi +3 -3
- reflex/components/core/debounce.py +3 -0
- reflex/components/el/__init__.py +1 -0
- reflex/components/el/__init__.pyi +8 -5
- reflex/components/el/elements/__init__.py +3 -1
- reflex/components/el/elements/__init__.pyi +8 -6
- reflex/components/el/elements/media.py +98 -18
- reflex/components/el/elements/media.pyi +523 -18
- reflex/components/el/elements/metadata.py +5 -1
- reflex/components/radix/primitives/base.py +1 -1
- reflex/components/radix/themes/layout/list.py +0 -2
- reflex/components/recharts/cartesian.py +46 -20
- reflex/components/recharts/cartesian.pyi +26 -14
- reflex/components/recharts/charts.py +4 -0
- reflex/components/recharts/charts.pyi +3 -0
- reflex/components/recharts/general.py +23 -9
- reflex/components/recharts/general.pyi +6 -4
- reflex/components/recharts/polar.py +35 -11
- reflex/components/recharts/polar.pyi +35 -7
- reflex/components/sonner/toast.py +28 -2
- reflex/components/sonner/toast.pyi +14 -7
- reflex/constants/base.py +21 -0
- reflex/constants/event.py +2 -0
- reflex/experimental/vars/__init__.py +17 -0
- reflex/experimental/vars/base.py +282 -15
- reflex/experimental/vars/function.py +214 -0
- reflex/experimental/vars/number.py +1295 -0
- reflex/experimental/vars/sequence.py +1039 -0
- reflex/reflex.py +29 -2
- reflex/state.py +59 -10
- reflex/utils/imports.py +71 -8
- reflex/utils/prerequisites.py +115 -35
- reflex/utils/pyi_generator.py +2 -0
- reflex/utils/redir.py +52 -0
- reflex/vars.py +220 -11
- reflex/vars.pyi +20 -2
- {reflex-0.5.7a1.dist-info → reflex-0.5.8.dist-info}/METADATA +2 -2
- {reflex-0.5.7a1.dist-info → reflex-0.5.8.dist-info}/RECORD +44 -40
- {reflex-0.5.7a1.dist-info → reflex-0.5.8.dist-info}/LICENSE +0 -0
- {reflex-0.5.7a1.dist-info → reflex-0.5.8.dist-info}/WHEEL +0 -0
- {reflex-0.5.7a1.dist-info → reflex-0.5.8.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,1039 @@
|
|
|
1
|
+
"""Collection of string classes and utilities."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import dataclasses
|
|
6
|
+
import functools
|
|
7
|
+
import json
|
|
8
|
+
import re
|
|
9
|
+
import sys
|
|
10
|
+
from functools import cached_property
|
|
11
|
+
from typing import Any, List, Set, Tuple, Union
|
|
12
|
+
|
|
13
|
+
from reflex import constants
|
|
14
|
+
from reflex.constants.base import REFLEX_VAR_OPENING_TAG
|
|
15
|
+
from reflex.experimental.vars.base import (
|
|
16
|
+
ImmutableVar,
|
|
17
|
+
LiteralVar,
|
|
18
|
+
)
|
|
19
|
+
from reflex.experimental.vars.number import BooleanVar, NotEqualOperation, NumberVar
|
|
20
|
+
from reflex.vars import ImmutableVarData, Var, VarData, _global_vars
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class StringVar(ImmutableVar):
|
|
24
|
+
"""Base class for immutable string vars."""
|
|
25
|
+
|
|
26
|
+
def __add__(self, other: StringVar | str) -> ConcatVarOperation:
|
|
27
|
+
"""Concatenate two strings.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
other: The other string.
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
The string concatenation operation.
|
|
34
|
+
"""
|
|
35
|
+
return ConcatVarOperation(self, other)
|
|
36
|
+
|
|
37
|
+
def __radd__(self, other: StringVar | str) -> ConcatVarOperation:
|
|
38
|
+
"""Concatenate two strings.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
other: The other string.
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
The string concatenation operation.
|
|
45
|
+
"""
|
|
46
|
+
return ConcatVarOperation(other, self)
|
|
47
|
+
|
|
48
|
+
def __mul__(self, other: int) -> ConcatVarOperation:
|
|
49
|
+
"""Concatenate two strings.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
other: The other string.
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
The string concatenation operation.
|
|
56
|
+
"""
|
|
57
|
+
return ConcatVarOperation(*[self for _ in range(other)])
|
|
58
|
+
|
|
59
|
+
def __rmul__(self, other: int) -> ConcatVarOperation:
|
|
60
|
+
"""Concatenate two strings.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
other: The other string.
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
The string concatenation operation.
|
|
67
|
+
"""
|
|
68
|
+
return ConcatVarOperation(*[self for _ in range(other)])
|
|
69
|
+
|
|
70
|
+
def __getitem__(self, i: slice | int) -> StringSliceOperation | StringItemOperation:
|
|
71
|
+
"""Get a slice of the string.
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
i: The slice.
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
The string slice operation.
|
|
78
|
+
"""
|
|
79
|
+
if isinstance(i, slice):
|
|
80
|
+
return StringSliceOperation(self, i)
|
|
81
|
+
return StringItemOperation(self, i)
|
|
82
|
+
|
|
83
|
+
def length(self) -> StringLengthOperation:
|
|
84
|
+
"""Get the length of the string.
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
The string length operation.
|
|
88
|
+
"""
|
|
89
|
+
return StringLengthOperation(self)
|
|
90
|
+
|
|
91
|
+
def lower(self) -> StringLowerOperation:
|
|
92
|
+
"""Convert the string to lowercase.
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
The string lower operation.
|
|
96
|
+
"""
|
|
97
|
+
return StringLowerOperation(self)
|
|
98
|
+
|
|
99
|
+
def upper(self) -> StringUpperOperation:
|
|
100
|
+
"""Convert the string to uppercase.
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
The string upper operation.
|
|
104
|
+
"""
|
|
105
|
+
return StringUpperOperation(self)
|
|
106
|
+
|
|
107
|
+
def strip(self) -> StringStripOperation:
|
|
108
|
+
"""Strip the string.
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
The string strip operation.
|
|
112
|
+
"""
|
|
113
|
+
return StringStripOperation(self)
|
|
114
|
+
|
|
115
|
+
def bool(self) -> NotEqualOperation:
|
|
116
|
+
"""Boolean conversion.
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
The boolean value of the string.
|
|
120
|
+
"""
|
|
121
|
+
return NotEqualOperation(self.length(), 0)
|
|
122
|
+
|
|
123
|
+
def reversed(self) -> StringReverseOperation:
|
|
124
|
+
"""Reverse the string.
|
|
125
|
+
|
|
126
|
+
Returns:
|
|
127
|
+
The string reverse operation.
|
|
128
|
+
"""
|
|
129
|
+
return StringReverseOperation(self)
|
|
130
|
+
|
|
131
|
+
def contains(self, other: StringVar | str) -> StringContainsOperation:
|
|
132
|
+
"""Check if the string contains another string.
|
|
133
|
+
|
|
134
|
+
Args:
|
|
135
|
+
other: The other string.
|
|
136
|
+
|
|
137
|
+
Returns:
|
|
138
|
+
The string contains operation.
|
|
139
|
+
"""
|
|
140
|
+
return StringContainsOperation(self, other)
|
|
141
|
+
|
|
142
|
+
def split(self, separator: StringVar | str = "") -> StringSplitOperation:
|
|
143
|
+
"""Split the string.
|
|
144
|
+
|
|
145
|
+
Args:
|
|
146
|
+
separator: The separator.
|
|
147
|
+
|
|
148
|
+
Returns:
|
|
149
|
+
The string split operation.
|
|
150
|
+
"""
|
|
151
|
+
return StringSplitOperation(self, separator)
|
|
152
|
+
|
|
153
|
+
|
|
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
|
+
@dataclasses.dataclass(
|
|
234
|
+
eq=False,
|
|
235
|
+
frozen=True,
|
|
236
|
+
**{"slots": True} if sys.version_info >= (3, 10) else {},
|
|
237
|
+
)
|
|
238
|
+
class StringToStringOperation(StringVar):
|
|
239
|
+
"""Base class for immutable string vars that are the result of a string to string operation."""
|
|
240
|
+
|
|
241
|
+
a: StringVar = dataclasses.field(
|
|
242
|
+
default_factory=lambda: LiteralStringVar.create("")
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
def __init__(self, a: StringVar | str, _var_data: VarData | None = None):
|
|
246
|
+
"""Initialize the string to string operation var.
|
|
247
|
+
|
|
248
|
+
Args:
|
|
249
|
+
a: The string.
|
|
250
|
+
_var_data: Additional hooks and imports associated with the Var.
|
|
251
|
+
"""
|
|
252
|
+
super(StringToStringOperation, self).__init__(
|
|
253
|
+
_var_name="",
|
|
254
|
+
_var_type=str,
|
|
255
|
+
_var_data=ImmutableVarData.merge(_var_data),
|
|
256
|
+
)
|
|
257
|
+
object.__setattr__(
|
|
258
|
+
self, "a", a if isinstance(a, Var) else LiteralStringVar.create(a)
|
|
259
|
+
)
|
|
260
|
+
object.__delattr__(self, "_var_name")
|
|
261
|
+
|
|
262
|
+
@cached_property
|
|
263
|
+
def _cached_var_name(self) -> str:
|
|
264
|
+
"""The name of the var.
|
|
265
|
+
|
|
266
|
+
Raises:
|
|
267
|
+
NotImplementedError: Must be implemented by subclasses.
|
|
268
|
+
"""
|
|
269
|
+
raise NotImplementedError(
|
|
270
|
+
"StringToStringOperation must implement _cached_var_name"
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
def __getattr__(self, name: str) -> Any:
|
|
274
|
+
"""Get an attribute of the var.
|
|
275
|
+
|
|
276
|
+
Args:
|
|
277
|
+
name: The name of the attribute.
|
|
278
|
+
|
|
279
|
+
Returns:
|
|
280
|
+
The attribute value.
|
|
281
|
+
"""
|
|
282
|
+
if name == "_var_name":
|
|
283
|
+
return self._cached_var_name
|
|
284
|
+
getattr(super(StringToStringOperation, self), name)
|
|
285
|
+
|
|
286
|
+
@cached_property
|
|
287
|
+
def _cached_get_all_var_data(self) -> ImmutableVarData | None:
|
|
288
|
+
"""Get all VarData associated with the Var.
|
|
289
|
+
|
|
290
|
+
Returns:
|
|
291
|
+
The VarData of the components and all of its children.
|
|
292
|
+
"""
|
|
293
|
+
return ImmutableVarData.merge(
|
|
294
|
+
self.a._get_all_var_data() if isinstance(self.a, Var) else None,
|
|
295
|
+
self._var_data,
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
def _get_all_var_data(self) -> ImmutableVarData | None:
|
|
299
|
+
return self._cached_get_all_var_data
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
class StringLowerOperation(StringToStringOperation):
|
|
303
|
+
"""Base class for immutable string vars that are the result of a string lower operation."""
|
|
304
|
+
|
|
305
|
+
@cached_property
|
|
306
|
+
def _cached_var_name(self) -> str:
|
|
307
|
+
"""The name of the var.
|
|
308
|
+
|
|
309
|
+
Returns:
|
|
310
|
+
The name of the var.
|
|
311
|
+
"""
|
|
312
|
+
return f"{str(self.a)}.toLowerCase()"
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
class StringUpperOperation(StringToStringOperation):
|
|
316
|
+
"""Base class for immutable string vars that are the result of a string upper operation."""
|
|
317
|
+
|
|
318
|
+
@cached_property
|
|
319
|
+
def _cached_var_name(self) -> str:
|
|
320
|
+
"""The name of the var.
|
|
321
|
+
|
|
322
|
+
Returns:
|
|
323
|
+
The name of the var.
|
|
324
|
+
"""
|
|
325
|
+
return f"{str(self.a)}.toUpperCase()"
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
class StringStripOperation(StringToStringOperation):
|
|
329
|
+
"""Base class for immutable string vars that are the result of a string strip operation."""
|
|
330
|
+
|
|
331
|
+
@cached_property
|
|
332
|
+
def _cached_var_name(self) -> str:
|
|
333
|
+
"""The name of the var.
|
|
334
|
+
|
|
335
|
+
Returns:
|
|
336
|
+
The name of the var.
|
|
337
|
+
"""
|
|
338
|
+
return f"{str(self.a)}.trim()"
|
|
339
|
+
|
|
340
|
+
|
|
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
|
+
@dataclasses.dataclass(
|
|
355
|
+
eq=False,
|
|
356
|
+
frozen=True,
|
|
357
|
+
**{"slots": True} if sys.version_info >= (3, 10) else {},
|
|
358
|
+
)
|
|
359
|
+
class StringContainsOperation(BooleanVar):
|
|
360
|
+
"""Base class for immutable boolean vars that are the result of a string contains operation."""
|
|
361
|
+
|
|
362
|
+
a: StringVar = dataclasses.field(
|
|
363
|
+
default_factory=lambda: LiteralStringVar.create("")
|
|
364
|
+
)
|
|
365
|
+
b: StringVar = dataclasses.field(
|
|
366
|
+
default_factory=lambda: LiteralStringVar.create("")
|
|
367
|
+
)
|
|
368
|
+
|
|
369
|
+
def __init__(
|
|
370
|
+
self, a: StringVar | str, b: StringVar | str, _var_data: VarData | None = None
|
|
371
|
+
):
|
|
372
|
+
"""Initialize the string contains operation var.
|
|
373
|
+
|
|
374
|
+
Args:
|
|
375
|
+
a: The first string.
|
|
376
|
+
b: The second string.
|
|
377
|
+
_var_data: Additional hooks and imports associated with the Var.
|
|
378
|
+
"""
|
|
379
|
+
super(StringContainsOperation, self).__init__(
|
|
380
|
+
_var_name="",
|
|
381
|
+
_var_type=bool,
|
|
382
|
+
_var_data=ImmutableVarData.merge(_var_data),
|
|
383
|
+
)
|
|
384
|
+
object.__setattr__(
|
|
385
|
+
self, "a", a if isinstance(a, Var) else LiteralStringVar.create(a)
|
|
386
|
+
)
|
|
387
|
+
object.__setattr__(
|
|
388
|
+
self, "b", b if isinstance(b, Var) else LiteralStringVar.create(b)
|
|
389
|
+
)
|
|
390
|
+
object.__delattr__(self, "_var_name")
|
|
391
|
+
|
|
392
|
+
@cached_property
|
|
393
|
+
def _cached_var_name(self) -> str:
|
|
394
|
+
"""The name of the var.
|
|
395
|
+
|
|
396
|
+
Returns:
|
|
397
|
+
The name of the var.
|
|
398
|
+
"""
|
|
399
|
+
return f"{str(self.a)}.includes({str(self.b)})"
|
|
400
|
+
|
|
401
|
+
def __getattr__(self, name: str) -> Any:
|
|
402
|
+
"""Get an attribute of the var.
|
|
403
|
+
|
|
404
|
+
Args:
|
|
405
|
+
name: The name of the attribute.
|
|
406
|
+
|
|
407
|
+
Returns:
|
|
408
|
+
The attribute value.
|
|
409
|
+
"""
|
|
410
|
+
if name == "_var_name":
|
|
411
|
+
return self._cached_var_name
|
|
412
|
+
getattr(super(StringContainsOperation, self), name)
|
|
413
|
+
|
|
414
|
+
@cached_property
|
|
415
|
+
def _cached_get_all_var_data(self) -> ImmutableVarData | None:
|
|
416
|
+
"""Get all VarData associated with the Var.
|
|
417
|
+
|
|
418
|
+
Returns:
|
|
419
|
+
The VarData of the components and all of its children.
|
|
420
|
+
"""
|
|
421
|
+
return ImmutableVarData.merge(
|
|
422
|
+
self.a._get_all_var_data(), self.b._get_all_var_data(), self._var_data
|
|
423
|
+
)
|
|
424
|
+
|
|
425
|
+
def _get_all_var_data(self) -> ImmutableVarData | None:
|
|
426
|
+
return self._cached_get_all_var_data
|
|
427
|
+
|
|
428
|
+
|
|
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
|
+
@dataclasses.dataclass(
|
|
536
|
+
eq=False,
|
|
537
|
+
frozen=True,
|
|
538
|
+
**{"slots": True} if sys.version_info >= (3, 10) else {},
|
|
539
|
+
)
|
|
540
|
+
class StringItemOperation(StringVar):
|
|
541
|
+
"""Base class for immutable string vars that are the result of a string item operation."""
|
|
542
|
+
|
|
543
|
+
a: StringVar = dataclasses.field(
|
|
544
|
+
default_factory=lambda: LiteralStringVar.create("")
|
|
545
|
+
)
|
|
546
|
+
i: int = dataclasses.field(default=0)
|
|
547
|
+
|
|
548
|
+
def __init__(self, a: StringVar | str, i: int, _var_data: VarData | None = None):
|
|
549
|
+
"""Initialize the string item operation var.
|
|
550
|
+
|
|
551
|
+
Args:
|
|
552
|
+
a: The string.
|
|
553
|
+
i: The index.
|
|
554
|
+
_var_data: Additional hooks and imports associated with the Var.
|
|
555
|
+
"""
|
|
556
|
+
super(StringItemOperation, self).__init__(
|
|
557
|
+
_var_name="",
|
|
558
|
+
_var_type=str,
|
|
559
|
+
_var_data=ImmutableVarData.merge(_var_data),
|
|
560
|
+
)
|
|
561
|
+
object.__setattr__(
|
|
562
|
+
self, "a", a if isinstance(a, Var) else LiteralStringVar.create(a)
|
|
563
|
+
)
|
|
564
|
+
object.__setattr__(self, "i", i)
|
|
565
|
+
object.__delattr__(self, "_var_name")
|
|
566
|
+
|
|
567
|
+
@cached_property
|
|
568
|
+
def _cached_var_name(self) -> str:
|
|
569
|
+
"""The name of the var.
|
|
570
|
+
|
|
571
|
+
Returns:
|
|
572
|
+
The name of the var.
|
|
573
|
+
"""
|
|
574
|
+
return f"{str(self.a)}.at({str(self.i)})"
|
|
575
|
+
|
|
576
|
+
def __getattr__(self, name: str) -> Any:
|
|
577
|
+
"""Get an attribute of the var.
|
|
578
|
+
|
|
579
|
+
Args:
|
|
580
|
+
name: The name of the attribute.
|
|
581
|
+
|
|
582
|
+
Returns:
|
|
583
|
+
The attribute value.
|
|
584
|
+
"""
|
|
585
|
+
if name == "_var_name":
|
|
586
|
+
return self._cached_var_name
|
|
587
|
+
getattr(super(StringItemOperation, self), name)
|
|
588
|
+
|
|
589
|
+
@cached_property
|
|
590
|
+
def _cached_get_all_var_data(self) -> ImmutableVarData | None:
|
|
591
|
+
"""Get all VarData associated with the Var.
|
|
592
|
+
|
|
593
|
+
Returns:
|
|
594
|
+
The VarData of the components and all of its children.
|
|
595
|
+
"""
|
|
596
|
+
return ImmutableVarData.merge(self.a._get_all_var_data(), self._var_data)
|
|
597
|
+
|
|
598
|
+
def _get_all_var_data(self) -> ImmutableVarData | None:
|
|
599
|
+
return self._cached_get_all_var_data
|
|
600
|
+
|
|
601
|
+
|
|
602
|
+
class ArrayJoinOperation(StringVar):
|
|
603
|
+
"""Base class for immutable string vars that are the result of an array join operation."""
|
|
604
|
+
|
|
605
|
+
a: ArrayVar = dataclasses.field(default_factory=lambda: LiteralArrayVar([]))
|
|
606
|
+
b: StringVar = dataclasses.field(
|
|
607
|
+
default_factory=lambda: LiteralStringVar.create("")
|
|
608
|
+
)
|
|
609
|
+
|
|
610
|
+
def __init__(
|
|
611
|
+
self, a: ArrayVar | list, b: StringVar | str, _var_data: VarData | None = None
|
|
612
|
+
):
|
|
613
|
+
"""Initialize the array join operation var.
|
|
614
|
+
|
|
615
|
+
Args:
|
|
616
|
+
a: The array.
|
|
617
|
+
b: The separator.
|
|
618
|
+
_var_data: Additional hooks and imports associated with the Var.
|
|
619
|
+
"""
|
|
620
|
+
super(ArrayJoinOperation, self).__init__(
|
|
621
|
+
_var_name="",
|
|
622
|
+
_var_type=str,
|
|
623
|
+
_var_data=ImmutableVarData.merge(_var_data),
|
|
624
|
+
)
|
|
625
|
+
object.__setattr__(
|
|
626
|
+
self, "a", a if isinstance(a, Var) else LiteralArrayVar.create(a)
|
|
627
|
+
)
|
|
628
|
+
object.__setattr__(
|
|
629
|
+
self, "b", b if isinstance(b, Var) else LiteralStringVar.create(b)
|
|
630
|
+
)
|
|
631
|
+
object.__delattr__(self, "_var_name")
|
|
632
|
+
|
|
633
|
+
@cached_property
|
|
634
|
+
def _cached_var_name(self) -> str:
|
|
635
|
+
"""The name of the var.
|
|
636
|
+
|
|
637
|
+
Returns:
|
|
638
|
+
The name of the var.
|
|
639
|
+
"""
|
|
640
|
+
return f"{str(self.a)}.join({str(self.b)})"
|
|
641
|
+
|
|
642
|
+
def __getattr__(self, name: str) -> Any:
|
|
643
|
+
"""Get an attribute of the var.
|
|
644
|
+
|
|
645
|
+
Args:
|
|
646
|
+
name: The name of the attribute.
|
|
647
|
+
|
|
648
|
+
Returns:
|
|
649
|
+
The attribute value.
|
|
650
|
+
"""
|
|
651
|
+
if name == "_var_name":
|
|
652
|
+
return self._cached_var_name
|
|
653
|
+
getattr(super(ArrayJoinOperation, self), name)
|
|
654
|
+
|
|
655
|
+
@cached_property
|
|
656
|
+
def _cached_get_all_var_data(self) -> ImmutableVarData | None:
|
|
657
|
+
"""Get all VarData associated with the Var.
|
|
658
|
+
|
|
659
|
+
Returns:
|
|
660
|
+
The VarData of the components and all of its children.
|
|
661
|
+
"""
|
|
662
|
+
return ImmutableVarData.merge(
|
|
663
|
+
self.a._get_all_var_data(), self.b._get_all_var_data(), self._var_data
|
|
664
|
+
)
|
|
665
|
+
|
|
666
|
+
def _get_all_var_data(self) -> ImmutableVarData | None:
|
|
667
|
+
return self._cached_get_all_var_data
|
|
668
|
+
|
|
669
|
+
|
|
670
|
+
# Compile regex for finding reflex var tags.
|
|
671
|
+
_decode_var_pattern_re = (
|
|
672
|
+
rf"{constants.REFLEX_VAR_OPENING_TAG}(.*?){constants.REFLEX_VAR_CLOSING_TAG}"
|
|
673
|
+
)
|
|
674
|
+
_decode_var_pattern = re.compile(_decode_var_pattern_re, flags=re.DOTALL)
|
|
675
|
+
|
|
676
|
+
|
|
677
|
+
@dataclasses.dataclass(
|
|
678
|
+
eq=False,
|
|
679
|
+
frozen=True,
|
|
680
|
+
**{"slots": True} if sys.version_info >= (3, 10) else {},
|
|
681
|
+
)
|
|
682
|
+
class LiteralStringVar(LiteralVar, StringVar):
|
|
683
|
+
"""Base class for immutable literal string vars."""
|
|
684
|
+
|
|
685
|
+
_var_value: str = dataclasses.field(default="")
|
|
686
|
+
|
|
687
|
+
def __init__(
|
|
688
|
+
self,
|
|
689
|
+
_var_value: str,
|
|
690
|
+
_var_data: VarData | None = None,
|
|
691
|
+
):
|
|
692
|
+
"""Initialize the string var.
|
|
693
|
+
|
|
694
|
+
Args:
|
|
695
|
+
_var_value: The value of the var.
|
|
696
|
+
_var_data: Additional hooks and imports associated with the Var.
|
|
697
|
+
"""
|
|
698
|
+
super(LiteralStringVar, self).__init__(
|
|
699
|
+
_var_name=f'"{_var_value}"',
|
|
700
|
+
_var_type=str,
|
|
701
|
+
_var_data=ImmutableVarData.merge(_var_data),
|
|
702
|
+
)
|
|
703
|
+
object.__setattr__(self, "_var_value", _var_value)
|
|
704
|
+
|
|
705
|
+
@classmethod
|
|
706
|
+
def create(
|
|
707
|
+
cls,
|
|
708
|
+
value: str,
|
|
709
|
+
_var_data: VarData | None = None,
|
|
710
|
+
) -> LiteralStringVar | ConcatVarOperation:
|
|
711
|
+
"""Create a var from a string value.
|
|
712
|
+
|
|
713
|
+
Args:
|
|
714
|
+
value: The value to create the var from.
|
|
715
|
+
_var_data: Additional hooks and imports associated with the Var.
|
|
716
|
+
|
|
717
|
+
Returns:
|
|
718
|
+
The var.
|
|
719
|
+
"""
|
|
720
|
+
if REFLEX_VAR_OPENING_TAG in value:
|
|
721
|
+
strings_and_vals: list[Var | str] = []
|
|
722
|
+
offset = 0
|
|
723
|
+
|
|
724
|
+
# Initialize some methods for reading json.
|
|
725
|
+
var_data_config = VarData().__config__
|
|
726
|
+
|
|
727
|
+
def json_loads(s):
|
|
728
|
+
try:
|
|
729
|
+
return var_data_config.json_loads(s)
|
|
730
|
+
except json.decoder.JSONDecodeError:
|
|
731
|
+
return var_data_config.json_loads(
|
|
732
|
+
var_data_config.json_loads(f'"{s}"')
|
|
733
|
+
)
|
|
734
|
+
|
|
735
|
+
# Find all tags
|
|
736
|
+
while m := _decode_var_pattern.search(value):
|
|
737
|
+
start, end = m.span()
|
|
738
|
+
if start > 0:
|
|
739
|
+
strings_and_vals.append(value[:start])
|
|
740
|
+
|
|
741
|
+
serialized_data = m.group(1)
|
|
742
|
+
|
|
743
|
+
if serialized_data.isnumeric() or (
|
|
744
|
+
serialized_data[0] == "-" and serialized_data[1:].isnumeric()
|
|
745
|
+
):
|
|
746
|
+
# This is a global immutable var.
|
|
747
|
+
var = _global_vars[int(serialized_data)]
|
|
748
|
+
strings_and_vals.append(var)
|
|
749
|
+
value = value[(end + len(var._var_name)) :]
|
|
750
|
+
else:
|
|
751
|
+
data = json_loads(serialized_data)
|
|
752
|
+
string_length = data.pop("string_length", None)
|
|
753
|
+
var_data = VarData.parse_obj(data)
|
|
754
|
+
|
|
755
|
+
# Use string length to compute positions of interpolations.
|
|
756
|
+
if string_length is not None:
|
|
757
|
+
realstart = start + offset
|
|
758
|
+
var_data.interpolations = [
|
|
759
|
+
(realstart, realstart + string_length)
|
|
760
|
+
]
|
|
761
|
+
strings_and_vals.append(
|
|
762
|
+
ImmutableVar.create_safe(
|
|
763
|
+
value[end : (end + string_length)], _var_data=var_data
|
|
764
|
+
)
|
|
765
|
+
)
|
|
766
|
+
value = value[(end + string_length) :]
|
|
767
|
+
|
|
768
|
+
offset += end - start
|
|
769
|
+
|
|
770
|
+
if value:
|
|
771
|
+
strings_and_vals.append(value)
|
|
772
|
+
|
|
773
|
+
return ConcatVarOperation(*strings_and_vals, _var_data=_var_data)
|
|
774
|
+
|
|
775
|
+
return LiteralStringVar(
|
|
776
|
+
value,
|
|
777
|
+
_var_data=_var_data,
|
|
778
|
+
)
|
|
779
|
+
|
|
780
|
+
|
|
781
|
+
@dataclasses.dataclass(
|
|
782
|
+
eq=False,
|
|
783
|
+
frozen=True,
|
|
784
|
+
**{"slots": True} if sys.version_info >= (3, 10) else {},
|
|
785
|
+
)
|
|
786
|
+
class ConcatVarOperation(StringVar):
|
|
787
|
+
"""Representing a concatenation of literal string vars."""
|
|
788
|
+
|
|
789
|
+
_var_value: Tuple[Union[Var, str], ...] = dataclasses.field(default_factory=tuple)
|
|
790
|
+
|
|
791
|
+
def __init__(self, *value: Var | str, _var_data: VarData | None = None):
|
|
792
|
+
"""Initialize the operation of concatenating literal string vars.
|
|
793
|
+
|
|
794
|
+
Args:
|
|
795
|
+
value: The values to concatenate.
|
|
796
|
+
_var_data: Additional hooks and imports associated with the Var.
|
|
797
|
+
"""
|
|
798
|
+
super(ConcatVarOperation, self).__init__(
|
|
799
|
+
_var_name="", _var_data=ImmutableVarData.merge(_var_data), _var_type=str
|
|
800
|
+
)
|
|
801
|
+
object.__setattr__(self, "_var_value", value)
|
|
802
|
+
object.__delattr__(self, "_var_name")
|
|
803
|
+
|
|
804
|
+
def __getattr__(self, name):
|
|
805
|
+
"""Get an attribute of the var.
|
|
806
|
+
|
|
807
|
+
Args:
|
|
808
|
+
name: The name of the attribute.
|
|
809
|
+
|
|
810
|
+
Returns:
|
|
811
|
+
The attribute of the var.
|
|
812
|
+
"""
|
|
813
|
+
if name == "_var_name":
|
|
814
|
+
return self._cached_var_name
|
|
815
|
+
return super(type(self), self).__getattr__(name)
|
|
816
|
+
|
|
817
|
+
@cached_property
|
|
818
|
+
def _cached_var_name(self) -> str:
|
|
819
|
+
"""The name of the var.
|
|
820
|
+
|
|
821
|
+
Returns:
|
|
822
|
+
The name of the var.
|
|
823
|
+
"""
|
|
824
|
+
return (
|
|
825
|
+
"("
|
|
826
|
+
+ "+".join(
|
|
827
|
+
[
|
|
828
|
+
str(element) if isinstance(element, Var) else f'"{element}"'
|
|
829
|
+
for element in self._var_value
|
|
830
|
+
]
|
|
831
|
+
)
|
|
832
|
+
+ ")"
|
|
833
|
+
)
|
|
834
|
+
|
|
835
|
+
@cached_property
|
|
836
|
+
def _cached_get_all_var_data(self) -> ImmutableVarData | None:
|
|
837
|
+
"""Get all VarData associated with the Var.
|
|
838
|
+
|
|
839
|
+
Returns:
|
|
840
|
+
The VarData of the components and all of its children.
|
|
841
|
+
"""
|
|
842
|
+
return ImmutableVarData.merge(
|
|
843
|
+
*[
|
|
844
|
+
var._get_all_var_data()
|
|
845
|
+
for var in self._var_value
|
|
846
|
+
if isinstance(var, Var)
|
|
847
|
+
],
|
|
848
|
+
self._var_data,
|
|
849
|
+
)
|
|
850
|
+
|
|
851
|
+
def _get_all_var_data(self) -> ImmutableVarData | None:
|
|
852
|
+
"""Wrapper method for cached property.
|
|
853
|
+
|
|
854
|
+
Returns:
|
|
855
|
+
The VarData of the components and all of its children.
|
|
856
|
+
"""
|
|
857
|
+
return self._cached_get_all_var_data
|
|
858
|
+
|
|
859
|
+
def __post_init__(self):
|
|
860
|
+
"""Post-initialize the var."""
|
|
861
|
+
pass
|
|
862
|
+
|
|
863
|
+
|
|
864
|
+
class ArrayVar(ImmutableVar):
|
|
865
|
+
"""Base class for immutable array vars."""
|
|
866
|
+
|
|
867
|
+
from reflex.experimental.vars.sequence import StringVar
|
|
868
|
+
|
|
869
|
+
def join(self, sep: StringVar | str = "") -> ArrayJoinOperation:
|
|
870
|
+
"""Join the elements of the array.
|
|
871
|
+
|
|
872
|
+
Args:
|
|
873
|
+
sep: The separator between elements.
|
|
874
|
+
|
|
875
|
+
Returns:
|
|
876
|
+
The joined elements.
|
|
877
|
+
"""
|
|
878
|
+
from reflex.experimental.vars.sequence import ArrayJoinOperation
|
|
879
|
+
|
|
880
|
+
return ArrayJoinOperation(self, sep)
|
|
881
|
+
|
|
882
|
+
|
|
883
|
+
@dataclasses.dataclass(
|
|
884
|
+
eq=False,
|
|
885
|
+
frozen=True,
|
|
886
|
+
**{"slots": True} if sys.version_info >= (3, 10) else {},
|
|
887
|
+
)
|
|
888
|
+
class LiteralArrayVar(LiteralVar, ArrayVar):
|
|
889
|
+
"""Base class for immutable literal array vars."""
|
|
890
|
+
|
|
891
|
+
_var_value: Union[
|
|
892
|
+
List[Union[Var, Any]], Set[Union[Var, Any]], Tuple[Union[Var, Any], ...]
|
|
893
|
+
] = dataclasses.field(default_factory=list)
|
|
894
|
+
|
|
895
|
+
def __init__(
|
|
896
|
+
self,
|
|
897
|
+
_var_value: list[Var | Any] | tuple[Var | Any] | set[Var | Any],
|
|
898
|
+
_var_data: VarData | None = None,
|
|
899
|
+
):
|
|
900
|
+
"""Initialize the array var.
|
|
901
|
+
|
|
902
|
+
Args:
|
|
903
|
+
_var_value: The value of the var.
|
|
904
|
+
_var_data: Additional hooks and imports associated with the Var.
|
|
905
|
+
"""
|
|
906
|
+
super(LiteralArrayVar, self).__init__(
|
|
907
|
+
_var_name="",
|
|
908
|
+
_var_data=ImmutableVarData.merge(_var_data),
|
|
909
|
+
_var_type=list,
|
|
910
|
+
)
|
|
911
|
+
object.__setattr__(self, "_var_value", _var_value)
|
|
912
|
+
object.__delattr__(self, "_var_name")
|
|
913
|
+
|
|
914
|
+
def __getattr__(self, name):
|
|
915
|
+
"""Get an attribute of the var.
|
|
916
|
+
|
|
917
|
+
Args:
|
|
918
|
+
name: The name of the attribute.
|
|
919
|
+
|
|
920
|
+
Returns:
|
|
921
|
+
The attribute of the var.
|
|
922
|
+
"""
|
|
923
|
+
if name == "_var_name":
|
|
924
|
+
return self._cached_var_name
|
|
925
|
+
return super(type(self), self).__getattr__(name)
|
|
926
|
+
|
|
927
|
+
@functools.cached_property
|
|
928
|
+
def _cached_var_name(self) -> str:
|
|
929
|
+
"""The name of the var.
|
|
930
|
+
|
|
931
|
+
Returns:
|
|
932
|
+
The name of the var.
|
|
933
|
+
"""
|
|
934
|
+
return (
|
|
935
|
+
"["
|
|
936
|
+
+ ", ".join(
|
|
937
|
+
[str(LiteralVar.create(element)) for element in self._var_value]
|
|
938
|
+
)
|
|
939
|
+
+ "]"
|
|
940
|
+
)
|
|
941
|
+
|
|
942
|
+
@functools.cached_property
|
|
943
|
+
def _cached_get_all_var_data(self) -> ImmutableVarData | None:
|
|
944
|
+
"""Get all VarData associated with the Var.
|
|
945
|
+
|
|
946
|
+
Returns:
|
|
947
|
+
The VarData of the components and all of its children.
|
|
948
|
+
"""
|
|
949
|
+
return ImmutableVarData.merge(
|
|
950
|
+
*[
|
|
951
|
+
var._get_all_var_data()
|
|
952
|
+
for var in self._var_value
|
|
953
|
+
if isinstance(var, Var)
|
|
954
|
+
],
|
|
955
|
+
self._var_data,
|
|
956
|
+
)
|
|
957
|
+
|
|
958
|
+
def _get_all_var_data(self) -> ImmutableVarData | None:
|
|
959
|
+
"""Wrapper method for cached property.
|
|
960
|
+
|
|
961
|
+
Returns:
|
|
962
|
+
The VarData of the components and all of its children.
|
|
963
|
+
"""
|
|
964
|
+
return self._cached_get_all_var_data
|
|
965
|
+
|
|
966
|
+
|
|
967
|
+
@dataclasses.dataclass(
|
|
968
|
+
eq=False,
|
|
969
|
+
frozen=True,
|
|
970
|
+
**{"slots": True} if sys.version_info >= (3, 10) else {},
|
|
971
|
+
)
|
|
972
|
+
class StringSplitOperation(ArrayVar):
|
|
973
|
+
"""Base class for immutable array vars that are the result of a string split operation."""
|
|
974
|
+
|
|
975
|
+
a: StringVar = dataclasses.field(
|
|
976
|
+
default_factory=lambda: LiteralStringVar.create("")
|
|
977
|
+
)
|
|
978
|
+
b: StringVar = dataclasses.field(
|
|
979
|
+
default_factory=lambda: LiteralStringVar.create("")
|
|
980
|
+
)
|
|
981
|
+
|
|
982
|
+
def __init__(
|
|
983
|
+
self, a: StringVar | str, b: StringVar | str, _var_data: VarData | None = None
|
|
984
|
+
):
|
|
985
|
+
"""Initialize the string split operation var.
|
|
986
|
+
|
|
987
|
+
Args:
|
|
988
|
+
a: The string.
|
|
989
|
+
b: The separator.
|
|
990
|
+
_var_data: Additional hooks and imports associated with the Var.
|
|
991
|
+
"""
|
|
992
|
+
super(StringSplitOperation, self).__init__(
|
|
993
|
+
_var_name="",
|
|
994
|
+
_var_type=list,
|
|
995
|
+
_var_data=ImmutableVarData.merge(_var_data),
|
|
996
|
+
)
|
|
997
|
+
object.__setattr__(
|
|
998
|
+
self, "a", a if isinstance(a, Var) else LiteralStringVar.create(a)
|
|
999
|
+
)
|
|
1000
|
+
object.__setattr__(
|
|
1001
|
+
self, "b", b if isinstance(b, Var) else LiteralStringVar.create(b)
|
|
1002
|
+
)
|
|
1003
|
+
object.__delattr__(self, "_var_name")
|
|
1004
|
+
|
|
1005
|
+
@cached_property
|
|
1006
|
+
def _cached_var_name(self) -> str:
|
|
1007
|
+
"""The name of the var.
|
|
1008
|
+
|
|
1009
|
+
Returns:
|
|
1010
|
+
The name of the var.
|
|
1011
|
+
"""
|
|
1012
|
+
return f"{str(self.a)}.split({str(self.b)})"
|
|
1013
|
+
|
|
1014
|
+
def __getattr__(self, name: str) -> Any:
|
|
1015
|
+
"""Get an attribute of the var.
|
|
1016
|
+
|
|
1017
|
+
Args:
|
|
1018
|
+
name: The name of the attribute.
|
|
1019
|
+
|
|
1020
|
+
Returns:
|
|
1021
|
+
The attribute value.
|
|
1022
|
+
"""
|
|
1023
|
+
if name == "_var_name":
|
|
1024
|
+
return self._cached_var_name
|
|
1025
|
+
getattr(super(StringSplitOperation, self), name)
|
|
1026
|
+
|
|
1027
|
+
@cached_property
|
|
1028
|
+
def _cached_get_all_var_data(self) -> ImmutableVarData | None:
|
|
1029
|
+
"""Get all VarData associated with the Var.
|
|
1030
|
+
|
|
1031
|
+
Returns:
|
|
1032
|
+
The VarData of the components and all of its children.
|
|
1033
|
+
"""
|
|
1034
|
+
return ImmutableVarData.merge(
|
|
1035
|
+
self.a._get_all_var_data(), self.b._get_all_var_data(), self._var_data
|
|
1036
|
+
)
|
|
1037
|
+
|
|
1038
|
+
def _get_all_var_data(self) -> ImmutableVarData | None:
|
|
1039
|
+
return self._cached_get_all_var_data
|