add var_operation and move some operations to the new style (#3841)
* add var_operations and move some operations to the new style * change bound style * can't assume int anymore * slice is not hashable (how did this work bef) * convert to int explicitly * move the rest of the operations to new style * fix bool guess type * forgot to precommit dangit * add type ignore to bool for now
This commit is contained in:
parent
f3426456ad
commit
c07a983f05
@ -9,7 +9,7 @@ from reflex.components.component import BaseComponent, Component, MemoizationLea
|
|||||||
from reflex.components.tags import CondTag, Tag
|
from reflex.components.tags import CondTag, Tag
|
||||||
from reflex.constants import Dirs
|
from reflex.constants import Dirs
|
||||||
from reflex.ivars.base import ImmutableVar, LiteralVar
|
from reflex.ivars.base import ImmutableVar, LiteralVar
|
||||||
from reflex.ivars.number import TernaryOperator
|
from reflex.ivars.number import ternary_operation
|
||||||
from reflex.style import LIGHT_COLOR_MODE, resolved_color_mode
|
from reflex.style import LIGHT_COLOR_MODE, resolved_color_mode
|
||||||
from reflex.utils.imports import ImportDict, ImportVar
|
from reflex.utils.imports import ImportDict, ImportVar
|
||||||
from reflex.vars import Var, VarData
|
from reflex.vars import Var, VarData
|
||||||
@ -163,11 +163,12 @@ def cond(condition: Any, c1: Any, c2: Any = None) -> Component | ImmutableVar:
|
|||||||
c2 = create_var(c2)
|
c2 = create_var(c2)
|
||||||
|
|
||||||
# Create the conditional var.
|
# Create the conditional var.
|
||||||
return TernaryOperator.create(
|
return ternary_operation(
|
||||||
condition=cond_var.to(bool), # type: ignore
|
cond_var.bool()._replace( # type: ignore
|
||||||
if_true=c1,
|
merge_var_data=VarData(imports=_IS_TRUE_IMPORT),
|
||||||
if_false=c2,
|
), # type: ignore
|
||||||
_var_data=VarData(imports=_IS_TRUE_IMPORT),
|
c1,
|
||||||
|
c2,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -12,7 +12,6 @@ from .number import LiteralNumberVar as LiteralNumberVar
|
|||||||
from .number import NumberVar as NumberVar
|
from .number import NumberVar as NumberVar
|
||||||
from .object import LiteralObjectVar as LiteralObjectVar
|
from .object import LiteralObjectVar as LiteralObjectVar
|
||||||
from .object import ObjectVar as ObjectVar
|
from .object import ObjectVar as ObjectVar
|
||||||
from .sequence import ArrayJoinOperation as ArrayJoinOperation
|
|
||||||
from .sequence import ArrayVar as ArrayVar
|
from .sequence import ArrayVar as ArrayVar
|
||||||
from .sequence import ConcatVarOperation as ConcatVarOperation
|
from .sequence import ConcatVarOperation as ConcatVarOperation
|
||||||
from .sequence import LiteralArrayVar as LiteralArrayVar
|
from .sequence import LiteralArrayVar as LiteralArrayVar
|
||||||
|
@ -20,6 +20,7 @@ from typing import (
|
|||||||
Generic,
|
Generic,
|
||||||
List,
|
List,
|
||||||
Literal,
|
Literal,
|
||||||
|
NoReturn,
|
||||||
Optional,
|
Optional,
|
||||||
Sequence,
|
Sequence,
|
||||||
Set,
|
Set,
|
||||||
@ -384,10 +385,18 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
|||||||
return self.to(BooleanVar, output)
|
return self.to(BooleanVar, output)
|
||||||
|
|
||||||
if issubclass(output, NumberVar):
|
if issubclass(output, NumberVar):
|
||||||
if fixed_type is not None and not issubclass(fixed_type, (int, float)):
|
if fixed_type is not None:
|
||||||
raise TypeError(
|
if fixed_type is Union:
|
||||||
f"Unsupported type {var_type} for NumberVar. Must be int or float."
|
inner_types = get_args(base_type)
|
||||||
)
|
if not all(issubclass(t, (int, float)) for t in inner_types):
|
||||||
|
raise TypeError(
|
||||||
|
f"Unsupported type {var_type} for NumberVar. Must be int or float."
|
||||||
|
)
|
||||||
|
|
||||||
|
elif not issubclass(fixed_type, (int, float)):
|
||||||
|
raise TypeError(
|
||||||
|
f"Unsupported type {var_type} for NumberVar. Must be int or float."
|
||||||
|
)
|
||||||
return ToNumberVarOperation.create(self, var_type or float)
|
return ToNumberVarOperation.create(self, var_type or float)
|
||||||
|
|
||||||
if issubclass(output, BooleanVar):
|
if issubclass(output, BooleanVar):
|
||||||
@ -440,7 +449,7 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
|||||||
Raises:
|
Raises:
|
||||||
TypeError: If the type is not supported for guessing.
|
TypeError: If the type is not supported for guessing.
|
||||||
"""
|
"""
|
||||||
from .number import NumberVar
|
from .number import BooleanVar, NumberVar
|
||||||
from .object import ObjectVar
|
from .object import ObjectVar
|
||||||
from .sequence import ArrayVar, StringVar
|
from .sequence import ArrayVar, StringVar
|
||||||
|
|
||||||
@ -454,11 +463,16 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
|||||||
fixed_type = get_origin(var_type) or var_type
|
fixed_type = get_origin(var_type) or var_type
|
||||||
|
|
||||||
if fixed_type is Union:
|
if fixed_type is Union:
|
||||||
|
inner_types = get_args(var_type)
|
||||||
|
if int in inner_types and float in inner_types:
|
||||||
|
return self.to(NumberVar, self._var_type)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
if not inspect.isclass(fixed_type):
|
if not inspect.isclass(fixed_type):
|
||||||
raise TypeError(f"Unsupported type {var_type} for guess_type.")
|
raise TypeError(f"Unsupported type {var_type} for guess_type.")
|
||||||
|
|
||||||
|
if issubclass(fixed_type, bool):
|
||||||
|
return self.to(BooleanVar, self._var_type)
|
||||||
if issubclass(fixed_type, (int, float)):
|
if issubclass(fixed_type, (int, float)):
|
||||||
return self.to(NumberVar, self._var_type)
|
return self.to(NumberVar, self._var_type)
|
||||||
if issubclass(fixed_type, dict):
|
if issubclass(fixed_type, dict):
|
||||||
@ -570,9 +584,9 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
|||||||
Returns:
|
Returns:
|
||||||
BooleanVar: A BooleanVar object representing the result of the equality check.
|
BooleanVar: A BooleanVar object representing the result of the equality check.
|
||||||
"""
|
"""
|
||||||
from .number import EqualOperation
|
from .number import equal_operation
|
||||||
|
|
||||||
return EqualOperation.create(self, other)
|
return equal_operation(self, other)
|
||||||
|
|
||||||
def __ne__(self, other: Var | Any) -> BooleanVar:
|
def __ne__(self, other: Var | Any) -> BooleanVar:
|
||||||
"""Check if the current object is not equal to the given object.
|
"""Check if the current object is not equal to the given object.
|
||||||
@ -583,9 +597,9 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
|||||||
Returns:
|
Returns:
|
||||||
BooleanVar: A BooleanVar object representing the result of the comparison.
|
BooleanVar: A BooleanVar object representing the result of the comparison.
|
||||||
"""
|
"""
|
||||||
from .number import EqualOperation
|
from .number import equal_operation
|
||||||
|
|
||||||
return ~EqualOperation.create(self, other)
|
return ~equal_operation(self, other)
|
||||||
|
|
||||||
def __gt__(self, other: Var | Any) -> BooleanVar:
|
def __gt__(self, other: Var | Any) -> BooleanVar:
|
||||||
"""Compare the current instance with another variable and return a BooleanVar representing the result of the greater than operation.
|
"""Compare the current instance with another variable and return a BooleanVar representing the result of the greater than operation.
|
||||||
@ -596,9 +610,9 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
|||||||
Returns:
|
Returns:
|
||||||
BooleanVar: A BooleanVar representing the result of the greater than operation.
|
BooleanVar: A BooleanVar representing the result of the greater than operation.
|
||||||
"""
|
"""
|
||||||
from .number import GreaterThanOperation
|
from .number import greater_than_operation
|
||||||
|
|
||||||
return GreaterThanOperation.create(self, other)
|
return greater_than_operation(self, other)
|
||||||
|
|
||||||
def __ge__(self, other: Var | Any) -> BooleanVar:
|
def __ge__(self, other: Var | Any) -> BooleanVar:
|
||||||
"""Check if the value of this variable is greater than or equal to the value of another variable or object.
|
"""Check if the value of this variable is greater than or equal to the value of another variable or object.
|
||||||
@ -609,9 +623,9 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
|||||||
Returns:
|
Returns:
|
||||||
BooleanVar: A BooleanVar object representing the result of the comparison.
|
BooleanVar: A BooleanVar object representing the result of the comparison.
|
||||||
"""
|
"""
|
||||||
from .number import GreaterThanOrEqualOperation
|
from .number import greater_than_or_equal_operation
|
||||||
|
|
||||||
return GreaterThanOrEqualOperation.create(self, other)
|
return greater_than_or_equal_operation(self, other)
|
||||||
|
|
||||||
def __lt__(self, other: Var | Any) -> BooleanVar:
|
def __lt__(self, other: Var | Any) -> BooleanVar:
|
||||||
"""Compare the current instance with another variable using the less than (<) operator.
|
"""Compare the current instance with another variable using the less than (<) operator.
|
||||||
@ -622,9 +636,9 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
|||||||
Returns:
|
Returns:
|
||||||
A `BooleanVar` object representing the result of the comparison.
|
A `BooleanVar` object representing the result of the comparison.
|
||||||
"""
|
"""
|
||||||
from .number import LessThanOperation
|
from .number import less_than_operation
|
||||||
|
|
||||||
return LessThanOperation.create(self, other)
|
return less_than_operation(self, other)
|
||||||
|
|
||||||
def __le__(self, other: Var | Any) -> BooleanVar:
|
def __le__(self, other: Var | Any) -> BooleanVar:
|
||||||
"""Compare if the current instance is less than or equal to the given value.
|
"""Compare if the current instance is less than or equal to the given value.
|
||||||
@ -635,9 +649,9 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
|||||||
Returns:
|
Returns:
|
||||||
A BooleanVar object representing the result of the comparison.
|
A BooleanVar object representing the result of the comparison.
|
||||||
"""
|
"""
|
||||||
from .number import LessThanOrEqualOperation
|
from .number import less_than_or_equal_operation
|
||||||
|
|
||||||
return LessThanOrEqualOperation.create(self, other)
|
return less_than_or_equal_operation(self, other)
|
||||||
|
|
||||||
def bool(self) -> BooleanVar:
|
def bool(self) -> BooleanVar:
|
||||||
"""Convert the var to a boolean.
|
"""Convert the var to a boolean.
|
||||||
@ -645,9 +659,9 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
|||||||
Returns:
|
Returns:
|
||||||
The boolean var.
|
The boolean var.
|
||||||
"""
|
"""
|
||||||
from .number import ToBooleanVarOperation
|
from .number import boolify
|
||||||
|
|
||||||
return ToBooleanVarOperation.create(self)
|
return boolify(self)
|
||||||
|
|
||||||
def __and__(self, other: Var | Any) -> ImmutableVar:
|
def __and__(self, other: Var | Any) -> ImmutableVar:
|
||||||
"""Perform a logical AND operation on the current instance and another variable.
|
"""Perform a logical AND operation on the current instance and another variable.
|
||||||
@ -658,7 +672,7 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
|||||||
Returns:
|
Returns:
|
||||||
A `BooleanVar` object representing the result of the logical AND operation.
|
A `BooleanVar` object representing the result of the logical AND operation.
|
||||||
"""
|
"""
|
||||||
return AndOperation.create(self, other)
|
return and_operation(self, other)
|
||||||
|
|
||||||
def __rand__(self, other: Var | Any) -> ImmutableVar:
|
def __rand__(self, other: Var | Any) -> ImmutableVar:
|
||||||
"""Perform a logical AND operation on the current instance and another variable.
|
"""Perform a logical AND operation on the current instance and another variable.
|
||||||
@ -669,7 +683,7 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
|||||||
Returns:
|
Returns:
|
||||||
A `BooleanVar` object representing the result of the logical AND operation.
|
A `BooleanVar` object representing the result of the logical AND operation.
|
||||||
"""
|
"""
|
||||||
return AndOperation.create(other, self)
|
return and_operation(other, self)
|
||||||
|
|
||||||
def __or__(self, other: Var | Any) -> ImmutableVar:
|
def __or__(self, other: Var | Any) -> ImmutableVar:
|
||||||
"""Perform a logical OR operation on the current instance and another variable.
|
"""Perform a logical OR operation on the current instance and another variable.
|
||||||
@ -680,7 +694,7 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
|||||||
Returns:
|
Returns:
|
||||||
A `BooleanVar` object representing the result of the logical OR operation.
|
A `BooleanVar` object representing the result of the logical OR operation.
|
||||||
"""
|
"""
|
||||||
return OrOperation.create(self, other)
|
return or_operation(self, other)
|
||||||
|
|
||||||
def __ror__(self, other: Var | Any) -> ImmutableVar:
|
def __ror__(self, other: Var | Any) -> ImmutableVar:
|
||||||
"""Perform a logical OR operation on the current instance and another variable.
|
"""Perform a logical OR operation on the current instance and another variable.
|
||||||
@ -691,7 +705,7 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
|||||||
Returns:
|
Returns:
|
||||||
A `BooleanVar` object representing the result of the logical OR operation.
|
A `BooleanVar` object representing the result of the logical OR operation.
|
||||||
"""
|
"""
|
||||||
return OrOperation.create(other, self)
|
return or_operation(other, self)
|
||||||
|
|
||||||
def __invert__(self) -> BooleanVar:
|
def __invert__(self) -> BooleanVar:
|
||||||
"""Perform a logical NOT operation on the current instance.
|
"""Perform a logical NOT operation on the current instance.
|
||||||
@ -699,9 +713,7 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
|||||||
Returns:
|
Returns:
|
||||||
A `BooleanVar` object representing the result of the logical NOT operation.
|
A `BooleanVar` object representing the result of the logical NOT operation.
|
||||||
"""
|
"""
|
||||||
from .number import BooleanNotOperation
|
return ~self.bool()
|
||||||
|
|
||||||
return BooleanNotOperation.create(self.bool())
|
|
||||||
|
|
||||||
def to_string(self) -> ImmutableVar:
|
def to_string(self) -> ImmutableVar:
|
||||||
"""Convert the var to a string.
|
"""Convert the var to a string.
|
||||||
@ -926,52 +938,92 @@ class LiteralVar(ImmutableVar):
|
|||||||
|
|
||||||
|
|
||||||
P = ParamSpec("P")
|
P = ParamSpec("P")
|
||||||
T = TypeVar("T", bound=ImmutableVar)
|
T = TypeVar("T")
|
||||||
|
|
||||||
|
|
||||||
def var_operation(*, output: Type[T]) -> Callable[[Callable[P, str]], Callable[P, T]]:
|
# NoReturn is used to match CustomVarOperationReturn with no type hint.
|
||||||
|
@overload
|
||||||
|
def var_operation(
|
||||||
|
func: Callable[P, CustomVarOperationReturn[NoReturn]],
|
||||||
|
) -> Callable[P, ImmutableVar]: ...
|
||||||
|
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def var_operation(
|
||||||
|
func: Callable[P, CustomVarOperationReturn[bool]],
|
||||||
|
) -> Callable[P, BooleanVar]: ...
|
||||||
|
|
||||||
|
|
||||||
|
NUMBER_T = TypeVar("NUMBER_T", int, float, Union[int, float])
|
||||||
|
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def var_operation(
|
||||||
|
func: Callable[P, CustomVarOperationReturn[NUMBER_T]],
|
||||||
|
) -> Callable[P, NumberVar[NUMBER_T]]: ...
|
||||||
|
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def var_operation(
|
||||||
|
func: Callable[P, CustomVarOperationReturn[str]],
|
||||||
|
) -> Callable[P, StringVar]: ...
|
||||||
|
|
||||||
|
|
||||||
|
LIST_T = TypeVar("LIST_T", bound=Union[List[Any], Tuple, Set])
|
||||||
|
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def var_operation(
|
||||||
|
func: Callable[P, CustomVarOperationReturn[LIST_T]],
|
||||||
|
) -> Callable[P, ArrayVar[LIST_T]]: ...
|
||||||
|
|
||||||
|
|
||||||
|
OBJECT_TYPE = TypeVar("OBJECT_TYPE", bound=Dict)
|
||||||
|
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def var_operation(
|
||||||
|
func: Callable[P, CustomVarOperationReturn[OBJECT_TYPE]],
|
||||||
|
) -> Callable[P, ObjectVar[OBJECT_TYPE]]: ...
|
||||||
|
|
||||||
|
|
||||||
|
def var_operation(
|
||||||
|
func: Callable[P, CustomVarOperationReturn[T]],
|
||||||
|
) -> Callable[P, ImmutableVar[T]]:
|
||||||
"""Decorator for creating a var operation.
|
"""Decorator for creating a var operation.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
```python
|
```python
|
||||||
@var_operation(output=NumberVar)
|
@var_operation
|
||||||
def add(a: NumberVar, b: NumberVar):
|
def add(a: NumberVar, b: NumberVar):
|
||||||
return f"({a} + {b})"
|
return custom_var_operation(f"{a} + {b}")
|
||||||
```
|
```
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
output: The output type of the operation.
|
func: The function to decorate.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The decorator.
|
The decorated function.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def decorator(func: Callable[P, str], output=output):
|
@functools.wraps(func)
|
||||||
@functools.wraps(func)
|
def wrapper(*args: P.args, **kwargs: P.kwargs) -> ImmutableVar[T]:
|
||||||
def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
|
func_args = list(inspect.signature(func).parameters)
|
||||||
args_vars = [
|
args_vars = {
|
||||||
LiteralVar.create(arg) if not isinstance(arg, Var) else arg
|
func_args[i]: (LiteralVar.create(arg) if not isinstance(arg, Var) else arg)
|
||||||
for arg in args
|
for i, arg in enumerate(args)
|
||||||
]
|
}
|
||||||
kwargs_vars = {
|
kwargs_vars = {
|
||||||
key: LiteralVar.create(value) if not isinstance(value, Var) else value
|
key: LiteralVar.create(value) if not isinstance(value, Var) else value
|
||||||
for key, value in kwargs.items()
|
for key, value in kwargs.items()
|
||||||
}
|
}
|
||||||
return output(
|
|
||||||
_var_name=func(*args_vars, **kwargs_vars), # type: ignore
|
|
||||||
_var_data=VarData.merge(
|
|
||||||
*[arg._get_all_var_data() for arg in args if isinstance(arg, Var)],
|
|
||||||
*[
|
|
||||||
arg._get_all_var_data()
|
|
||||||
for arg in kwargs.values()
|
|
||||||
if isinstance(arg, Var)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
return wrapper
|
return CustomVarOperation.create(
|
||||||
|
args=tuple(list(args_vars.items()) + list(kwargs_vars.items())),
|
||||||
|
return_var=func(*args_vars.values(), **kwargs_vars), # type: ignore
|
||||||
|
).guess_type()
|
||||||
|
|
||||||
return decorator
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
def unionize(*args: Type) -> Type:
|
def unionize(*args: Type) -> Type:
|
||||||
@ -1100,114 +1152,64 @@ class CachedVarOperation:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass(
|
def and_operation(a: Var | Any, b: Var | Any) -> ImmutableVar:
|
||||||
eq=False,
|
"""Perform a logical AND operation on two variables.
|
||||||
frozen=True,
|
|
||||||
**{"slots": True} if sys.version_info >= (3, 10) else {},
|
|
||||||
)
|
|
||||||
class AndOperation(CachedVarOperation, ImmutableVar):
|
|
||||||
"""Class for the logical AND operation."""
|
|
||||||
|
|
||||||
# The first var.
|
Args:
|
||||||
_var1: Var = dataclasses.field(default_factory=lambda: LiteralVar.create(None))
|
a: The first variable.
|
||||||
|
b: The second variable.
|
||||||
|
|
||||||
# The second var.
|
Returns:
|
||||||
_var2: Var = dataclasses.field(default_factory=lambda: LiteralVar.create(None))
|
The result of the logical AND operation.
|
||||||
|
"""
|
||||||
@cached_property_no_lock
|
return _and_operation(a, b) # type: ignore
|
||||||
def _cached_var_name(self) -> str:
|
|
||||||
"""Get the cached var name.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The cached var name.
|
|
||||||
"""
|
|
||||||
return f"({str(self._var1)} && {str(self._var2)})"
|
|
||||||
|
|
||||||
def __hash__(self) -> int:
|
|
||||||
"""Calculates the hash value of the object.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
int: The hash value of the object.
|
|
||||||
"""
|
|
||||||
return hash((self.__class__.__name__, self._var1, self._var2))
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def create(
|
|
||||||
cls, var1: Var | Any, var2: Var | Any, _var_data: VarData | None = None
|
|
||||||
) -> AndOperation:
|
|
||||||
"""Create an AndOperation.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
var1: The first var.
|
|
||||||
var2: The second var.
|
|
||||||
_var_data: Additional hooks and imports associated with the Var.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The AndOperation.
|
|
||||||
"""
|
|
||||||
var1, var2 = map(LiteralVar.create, (var1, var2))
|
|
||||||
return AndOperation(
|
|
||||||
_var_name="",
|
|
||||||
_var_type=unionize(var1._var_type, var2._var_type),
|
|
||||||
_var_data=ImmutableVarData.merge(_var_data),
|
|
||||||
_var1=var1,
|
|
||||||
_var2=var2,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass(
|
@var_operation
|
||||||
eq=False,
|
def _and_operation(a: ImmutableVar, b: ImmutableVar):
|
||||||
frozen=True,
|
"""Perform a logical AND operation on two variables.
|
||||||
**{"slots": True} if sys.version_info >= (3, 10) else {},
|
|
||||||
)
|
|
||||||
class OrOperation(CachedVarOperation, ImmutableVar):
|
|
||||||
"""Class for the logical OR operation."""
|
|
||||||
|
|
||||||
# The first var.
|
Args:
|
||||||
_var1: Var = dataclasses.field(default_factory=lambda: LiteralVar.create(None))
|
a: The first variable.
|
||||||
|
b: The second variable.
|
||||||
|
|
||||||
# The second var.
|
Returns:
|
||||||
_var2: Var = dataclasses.field(default_factory=lambda: LiteralVar.create(None))
|
The result of the logical AND operation.
|
||||||
|
"""
|
||||||
|
return var_operation_return(
|
||||||
|
js_expression=f"({a} && {b})",
|
||||||
|
var_type=unionize(a._var_type, b._var_type),
|
||||||
|
)
|
||||||
|
|
||||||
@cached_property_no_lock
|
|
||||||
def _cached_var_name(self) -> str:
|
|
||||||
"""Get the cached var name.
|
|
||||||
|
|
||||||
Returns:
|
def or_operation(a: Var | Any, b: Var | Any) -> ImmutableVar:
|
||||||
The cached var name.
|
"""Perform a logical OR operation on two variables.
|
||||||
"""
|
|
||||||
return f"({str(self._var1)} || {str(self._var2)})"
|
|
||||||
|
|
||||||
def __hash__(self) -> int:
|
Args:
|
||||||
"""Calculates the hash value for the object.
|
a: The first variable.
|
||||||
|
b: The second variable.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
int: The hash value of the object.
|
The result of the logical OR operation.
|
||||||
"""
|
"""
|
||||||
return hash((self.__class__.__name__, self._var1, self._var2))
|
return _or_operation(a, b) # type: ignore
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def create(
|
|
||||||
cls, var1: Var | Any, var2: Var | Any, _var_data: VarData | None = None
|
|
||||||
) -> OrOperation:
|
|
||||||
"""Create an OrOperation.
|
|
||||||
|
|
||||||
Args:
|
@var_operation
|
||||||
var1: The first var.
|
def _or_operation(a: ImmutableVar, b: ImmutableVar):
|
||||||
var2: The second var.
|
"""Perform a logical OR operation on two variables.
|
||||||
_var_data: Additional hooks and imports associated with the Var.
|
|
||||||
|
|
||||||
Returns:
|
Args:
|
||||||
The OrOperation.
|
a: The first variable.
|
||||||
"""
|
b: The second variable.
|
||||||
var1, var2 = map(LiteralVar.create, (var1, var2))
|
|
||||||
return OrOperation(
|
Returns:
|
||||||
_var_name="",
|
The result of the logical OR operation.
|
||||||
_var_type=unionize(var1._var_type, var2._var_type),
|
"""
|
||||||
_var_data=ImmutableVarData.merge(_var_data),
|
return var_operation_return(
|
||||||
_var1=var1,
|
js_expression=f"({a} || {b})",
|
||||||
_var2=var2,
|
var_type=unionize(a._var_type, b._var_type),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass(
|
@dataclasses.dataclass(
|
||||||
@ -1797,3 +1799,114 @@ def immutable_computed_var(
|
|||||||
)
|
)
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
RETURN = TypeVar("RETURN")
|
||||||
|
|
||||||
|
|
||||||
|
class CustomVarOperationReturn(ImmutableVar[RETURN]):
|
||||||
|
"""Base class for custom var operations."""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create(
|
||||||
|
cls,
|
||||||
|
js_expression: str,
|
||||||
|
_var_type: Type[RETURN] | None = None,
|
||||||
|
_var_data: VarData | None = None,
|
||||||
|
) -> CustomVarOperationReturn[RETURN]:
|
||||||
|
"""Create a CustomVarOperation.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
js_expression: The JavaScript expression to evaluate.
|
||||||
|
_var_type: The type of the var.
|
||||||
|
_var_data: Additional hooks and imports associated with the Var.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The CustomVarOperation.
|
||||||
|
"""
|
||||||
|
return CustomVarOperationReturn(
|
||||||
|
_var_name=js_expression,
|
||||||
|
_var_type=_var_type or Any,
|
||||||
|
_var_data=ImmutableVarData.merge(_var_data),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def var_operation_return(
|
||||||
|
js_expression: str,
|
||||||
|
var_type: Type[RETURN] | None = None,
|
||||||
|
) -> CustomVarOperationReturn[RETURN]:
|
||||||
|
"""Shortcut for creating a CustomVarOperationReturn.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
js_expression: The JavaScript expression to evaluate.
|
||||||
|
var_type: The type of the var.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The CustomVarOperationReturn.
|
||||||
|
"""
|
||||||
|
return CustomVarOperationReturn.create(js_expression, var_type)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclasses.dataclass(
|
||||||
|
eq=False,
|
||||||
|
frozen=True,
|
||||||
|
**{"slots": True} if sys.version_info >= (3, 10) else {},
|
||||||
|
)
|
||||||
|
class CustomVarOperation(CachedVarOperation, ImmutableVar[T]):
|
||||||
|
"""Base class for custom var operations."""
|
||||||
|
|
||||||
|
_args: Tuple[Tuple[str, Var], ...] = dataclasses.field(default_factory=tuple)
|
||||||
|
|
||||||
|
_return: CustomVarOperationReturn[T] = dataclasses.field(
|
||||||
|
default_factory=lambda: CustomVarOperationReturn.create("")
|
||||||
|
)
|
||||||
|
|
||||||
|
@cached_property_no_lock
|
||||||
|
def _cached_var_name(self) -> str:
|
||||||
|
"""Get the cached var name.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The cached var name.
|
||||||
|
"""
|
||||||
|
return str(self._return)
|
||||||
|
|
||||||
|
@cached_property_no_lock
|
||||||
|
def _cached_get_all_var_data(self) -> ImmutableVarData | None:
|
||||||
|
"""Get the cached VarData.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The cached VarData.
|
||||||
|
"""
|
||||||
|
return ImmutableVarData.merge(
|
||||||
|
*map(
|
||||||
|
lambda arg: arg[1]._get_all_var_data(),
|
||||||
|
self._args,
|
||||||
|
),
|
||||||
|
self._return._get_all_var_data(),
|
||||||
|
self._var_data,
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create(
|
||||||
|
cls,
|
||||||
|
args: Tuple[Tuple[str, Var], ...],
|
||||||
|
return_var: CustomVarOperationReturn[T],
|
||||||
|
_var_data: VarData | None = None,
|
||||||
|
) -> CustomVarOperation[T]:
|
||||||
|
"""Create a CustomVarOperation.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
args: The arguments to the operation.
|
||||||
|
return_var: The return var.
|
||||||
|
_var_data: Additional hooks and imports associated with the Var.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The CustomVarOperation.
|
||||||
|
"""
|
||||||
|
return CustomVarOperation(
|
||||||
|
_var_name="",
|
||||||
|
_var_type=return_var._var_type,
|
||||||
|
_var_data=ImmutableVarData.merge(_var_data),
|
||||||
|
_args=args,
|
||||||
|
_return=return_var,
|
||||||
|
)
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -30,6 +30,8 @@ from .base import (
|
|||||||
LiteralVar,
|
LiteralVar,
|
||||||
cached_property_no_lock,
|
cached_property_no_lock,
|
||||||
figure_out_type,
|
figure_out_type,
|
||||||
|
var_operation,
|
||||||
|
var_operation_return,
|
||||||
)
|
)
|
||||||
from .number import BooleanVar, NumberVar
|
from .number import BooleanVar, NumberVar
|
||||||
from .sequence import ArrayVar, StringVar
|
from .sequence import ArrayVar, StringVar
|
||||||
@ -56,7 +58,9 @@ class ObjectVar(ImmutableVar[OBJECT_TYPE]):
|
|||||||
return str
|
return str
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def _value_type(self: ObjectVar[Dict[KEY_TYPE, VALUE_TYPE]]) -> VALUE_TYPE: ...
|
def _value_type(
|
||||||
|
self: ObjectVar[Dict[KEY_TYPE, VALUE_TYPE]],
|
||||||
|
) -> Type[VALUE_TYPE]: ...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def _value_type(self) -> Type: ...
|
def _value_type(self) -> Type: ...
|
||||||
@ -79,7 +83,7 @@ class ObjectVar(ImmutableVar[OBJECT_TYPE]):
|
|||||||
Returns:
|
Returns:
|
||||||
The keys of the object.
|
The keys of the object.
|
||||||
"""
|
"""
|
||||||
return ObjectKeysOperation.create(self)
|
return object_keys_operation(self)
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def values(
|
def values(
|
||||||
@ -95,7 +99,7 @@ class ObjectVar(ImmutableVar[OBJECT_TYPE]):
|
|||||||
Returns:
|
Returns:
|
||||||
The values of the object.
|
The values of the object.
|
||||||
"""
|
"""
|
||||||
return ObjectValuesOperation.create(self)
|
return object_values_operation(self)
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def entries(
|
def entries(
|
||||||
@ -111,9 +115,9 @@ class ObjectVar(ImmutableVar[OBJECT_TYPE]):
|
|||||||
Returns:
|
Returns:
|
||||||
The entries of the object.
|
The entries of the object.
|
||||||
"""
|
"""
|
||||||
return ObjectEntriesOperation.create(self)
|
return object_entries_operation(self)
|
||||||
|
|
||||||
def merge(self, other: ObjectVar) -> ObjectMergeOperation:
|
def merge(self, other: ObjectVar):
|
||||||
"""Merge two objects.
|
"""Merge two objects.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -122,7 +126,7 @@ class ObjectVar(ImmutableVar[OBJECT_TYPE]):
|
|||||||
Returns:
|
Returns:
|
||||||
The merged object.
|
The merged object.
|
||||||
"""
|
"""
|
||||||
return ObjectMergeOperation.create(self, other)
|
return object_merge_operation(self, other)
|
||||||
|
|
||||||
# NoReturn is used here to catch when key value is Any
|
# NoReturn is used here to catch when key value is Any
|
||||||
@overload
|
@overload
|
||||||
@ -270,7 +274,7 @@ class ObjectVar(ImmutableVar[OBJECT_TYPE]):
|
|||||||
Returns:
|
Returns:
|
||||||
The result of the check.
|
The result of the check.
|
||||||
"""
|
"""
|
||||||
return ObjectHasOwnProperty.create(self, key)
|
return object_has_own_property_operation(self, key)
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass(
|
@dataclasses.dataclass(
|
||||||
@ -387,207 +391,72 @@ class LiteralObjectVar(CachedVarOperation, ObjectVar[OBJECT_TYPE], LiteralVar):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass(
|
@var_operation
|
||||||
eq=False,
|
def object_keys_operation(value: ObjectVar):
|
||||||
frozen=True,
|
"""Get the keys of an object.
|
||||||
**{"slots": True} if sys.version_info >= (3, 10) else {},
|
|
||||||
)
|
|
||||||
class ObjectToArrayOperation(CachedVarOperation, ArrayVar):
|
|
||||||
"""Base class for object to array operations."""
|
|
||||||
|
|
||||||
_value: ObjectVar = dataclasses.field(
|
Args:
|
||||||
default_factory=lambda: LiteralObjectVar.create({})
|
value: The object to get the keys from.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The keys of the object.
|
||||||
|
"""
|
||||||
|
return var_operation_return(
|
||||||
|
js_expression=f"Object.keys({value})",
|
||||||
|
var_type=List[str],
|
||||||
)
|
)
|
||||||
|
|
||||||
@cached_property_no_lock
|
|
||||||
def _cached_var_name(self) -> str:
|
|
||||||
"""The name of the operation.
|
|
||||||
|
|
||||||
Raises:
|
@var_operation
|
||||||
NotImplementedError: Must implement _cached_var_name.
|
def object_values_operation(value: ObjectVar):
|
||||||
"""
|
"""Get the values of an object.
|
||||||
raise NotImplementedError(
|
|
||||||
"ObjectToArrayOperation must implement _cached_var_name"
|
|
||||||
)
|
|
||||||
|
|
||||||
@classmethod
|
Args:
|
||||||
def create(
|
value: The object to get the values from.
|
||||||
cls,
|
|
||||||
value: ObjectVar,
|
|
||||||
_var_type: GenericType | None = None,
|
|
||||||
_var_data: VarData | None = None,
|
|
||||||
) -> ObjectToArrayOperation:
|
|
||||||
"""Create the object to array operation.
|
|
||||||
|
|
||||||
Args:
|
Returns:
|
||||||
value: The value of the operation.
|
The values of the object.
|
||||||
_var_data: Additional hooks and imports associated with the operation.
|
"""
|
||||||
|
return var_operation_return(
|
||||||
Returns:
|
js_expression=f"Object.values({value})",
|
||||||
The object to array operation.
|
var_type=List[value._value_type()],
|
||||||
"""
|
|
||||||
return cls(
|
|
||||||
_var_name="",
|
|
||||||
_var_type=list if _var_type is None else _var_type,
|
|
||||||
_var_data=ImmutableVarData.merge(_var_data),
|
|
||||||
_value=value,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class ObjectKeysOperation(ObjectToArrayOperation):
|
|
||||||
"""Operation to get the keys of an object."""
|
|
||||||
|
|
||||||
@cached_property_no_lock
|
|
||||||
def _cached_var_name(self) -> str:
|
|
||||||
"""The name of the operation.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The name of the operation.
|
|
||||||
"""
|
|
||||||
return f"Object.keys({str(self._value)})"
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def create(
|
|
||||||
cls,
|
|
||||||
value: ObjectVar,
|
|
||||||
_var_data: VarData | None = None,
|
|
||||||
) -> ObjectKeysOperation:
|
|
||||||
"""Create the object keys operation.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
value: The value of the operation.
|
|
||||||
_var_data: Additional hooks and imports associated with the operation.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The object keys operation.
|
|
||||||
"""
|
|
||||||
return cls(
|
|
||||||
_var_name="",
|
|
||||||
_var_type=List[str],
|
|
||||||
_var_data=ImmutableVarData.merge(_var_data),
|
|
||||||
_value=value,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class ObjectValuesOperation(ObjectToArrayOperation):
|
|
||||||
"""Operation to get the values of an object."""
|
|
||||||
|
|
||||||
@cached_property_no_lock
|
|
||||||
def _cached_var_name(self) -> str:
|
|
||||||
"""The name of the operation.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The name of the operation.
|
|
||||||
"""
|
|
||||||
return f"Object.values({str(self._value)})"
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def create(
|
|
||||||
cls,
|
|
||||||
value: ObjectVar,
|
|
||||||
_var_data: VarData | None = None,
|
|
||||||
) -> ObjectValuesOperation:
|
|
||||||
"""Create the object values operation.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
value: The value of the operation.
|
|
||||||
_var_data: Additional hooks and imports associated with the operation.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The object values operation.
|
|
||||||
"""
|
|
||||||
return cls(
|
|
||||||
_var_name="",
|
|
||||||
_var_type=List[value._value_type()],
|
|
||||||
_var_data=ImmutableVarData.merge(_var_data),
|
|
||||||
_value=value,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class ObjectEntriesOperation(ObjectToArrayOperation):
|
|
||||||
"""Operation to get the entries of an object."""
|
|
||||||
|
|
||||||
@cached_property_no_lock
|
|
||||||
def _cached_var_name(self) -> str:
|
|
||||||
"""The name of the operation.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The name of the operation.
|
|
||||||
"""
|
|
||||||
return f"Object.entries({str(self._value)})"
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def create(
|
|
||||||
cls,
|
|
||||||
value: ObjectVar,
|
|
||||||
_var_data: VarData | None = None,
|
|
||||||
) -> ObjectEntriesOperation:
|
|
||||||
"""Create the object entries operation.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
value: The value of the operation.
|
|
||||||
_var_data: Additional hooks and imports associated with the operation.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The object entries operation.
|
|
||||||
"""
|
|
||||||
return cls(
|
|
||||||
_var_name="",
|
|
||||||
_var_type=List[Tuple[str, value._value_type()]],
|
|
||||||
_var_data=ImmutableVarData.merge(_var_data),
|
|
||||||
_value=value,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass(
|
|
||||||
eq=False,
|
|
||||||
frozen=True,
|
|
||||||
**{"slots": True} if sys.version_info >= (3, 10) else {},
|
|
||||||
)
|
|
||||||
class ObjectMergeOperation(CachedVarOperation, ObjectVar):
|
|
||||||
"""Operation to merge two objects."""
|
|
||||||
|
|
||||||
_lhs: ObjectVar = dataclasses.field(
|
|
||||||
default_factory=lambda: LiteralObjectVar.create({})
|
|
||||||
)
|
|
||||||
_rhs: ObjectVar = dataclasses.field(
|
|
||||||
default_factory=lambda: LiteralObjectVar.create({})
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@cached_property_no_lock
|
|
||||||
def _cached_var_name(self) -> str:
|
|
||||||
"""The name of the operation.
|
|
||||||
|
|
||||||
Returns:
|
@var_operation
|
||||||
The name of the operation.
|
def object_entries_operation(value: ObjectVar):
|
||||||
"""
|
"""Get the entries of an object.
|
||||||
return f"({{...{str(self._lhs)}, ...{str(self._rhs)}}})"
|
|
||||||
|
|
||||||
@classmethod
|
Args:
|
||||||
def create(
|
value: The object to get the entries from.
|
||||||
cls,
|
|
||||||
lhs: ObjectVar,
|
|
||||||
rhs: ObjectVar,
|
|
||||||
_var_data: VarData | None = None,
|
|
||||||
) -> ObjectMergeOperation:
|
|
||||||
"""Create the object merge operation.
|
|
||||||
|
|
||||||
Args:
|
Returns:
|
||||||
lhs: The left object to merge.
|
The entries of the object.
|
||||||
rhs: The right object to merge.
|
"""
|
||||||
_var_data: Additional hooks and imports associated with the operation.
|
return var_operation_return(
|
||||||
|
js_expression=f"Object.entries({value})",
|
||||||
|
var_type=List[Tuple[str, value._value_type()]],
|
||||||
|
)
|
||||||
|
|
||||||
Returns:
|
|
||||||
The object merge operation.
|
@var_operation
|
||||||
"""
|
def object_merge_operation(lhs: ObjectVar, rhs: ObjectVar):
|
||||||
# TODO: Figure out how to merge the types
|
"""Merge two objects.
|
||||||
return cls(
|
|
||||||
_var_name="",
|
Args:
|
||||||
_var_type=lhs._var_type,
|
lhs: The first object to merge.
|
||||||
_var_data=ImmutableVarData.merge(_var_data),
|
rhs: The second object to merge.
|
||||||
_lhs=lhs,
|
|
||||||
_rhs=rhs,
|
Returns:
|
||||||
)
|
The merged object.
|
||||||
|
"""
|
||||||
|
return var_operation_return(
|
||||||
|
js_expression=f"({{...{lhs}, ...{rhs}}})",
|
||||||
|
var_type=Dict[
|
||||||
|
Union[lhs._key_type(), rhs._key_type()],
|
||||||
|
Union[lhs._value_type(), rhs._value_type()],
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass(
|
@dataclasses.dataclass(
|
||||||
@ -688,49 +557,18 @@ class ToObjectOperation(CachedVarOperation, ObjectVar):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass(
|
@var_operation
|
||||||
eq=False,
|
def object_has_own_property_operation(object: ObjectVar, key: Var):
|
||||||
frozen=True,
|
"""Check if an object has a key.
|
||||||
**{"slots": True} if sys.version_info >= (3, 10) else {},
|
|
||||||
)
|
|
||||||
class ObjectHasOwnProperty(CachedVarOperation, BooleanVar):
|
|
||||||
"""Operation to check if an object has a property."""
|
|
||||||
|
|
||||||
_object: ObjectVar = dataclasses.field(
|
Args:
|
||||||
default_factory=lambda: LiteralObjectVar.create({})
|
object: The object to check.
|
||||||
|
key: The key to check.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The result of the check.
|
||||||
|
"""
|
||||||
|
return var_operation_return(
|
||||||
|
js_expression=f"{object}.hasOwnProperty({key})",
|
||||||
|
var_type=bool,
|
||||||
)
|
)
|
||||||
_key: Var | Any = dataclasses.field(default_factory=lambda: LiteralVar.create(None))
|
|
||||||
|
|
||||||
@cached_property_no_lock
|
|
||||||
def _cached_var_name(self) -> str:
|
|
||||||
"""The name of the operation.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The name of the operation.
|
|
||||||
"""
|
|
||||||
return f"{str(self._object)}.hasOwnProperty({str(self._key)})"
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def create(
|
|
||||||
cls,
|
|
||||||
object: ObjectVar,
|
|
||||||
key: Var | Any,
|
|
||||||
_var_data: VarData | None = None,
|
|
||||||
) -> ObjectHasOwnProperty:
|
|
||||||
"""Create the object has own property operation.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
object: The object to check.
|
|
||||||
key: The key to check.
|
|
||||||
_var_data: Additional hooks and imports associated with the operation.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The object has own property operation.
|
|
||||||
"""
|
|
||||||
return cls(
|
|
||||||
_var_name="",
|
|
||||||
_var_type=bool,
|
|
||||||
_var_data=ImmutableVarData.merge(_var_data),
|
|
||||||
_object=object,
|
|
||||||
_key=key if isinstance(key, Var) else LiteralVar.create(key),
|
|
||||||
)
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -67,11 +67,11 @@ def test_color(color, expected):
|
|||||||
[
|
[
|
||||||
(
|
(
|
||||||
rx.cond(True, rx.color("mint"), rx.color("tomato", 5)),
|
rx.cond(True, rx.color("mint"), rx.color("tomato", 5)),
|
||||||
'(Boolean(true) ? "var(--mint-7)" : "var(--tomato-5)")',
|
'(true ? "var(--mint-7)" : "var(--tomato-5)")',
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
rx.cond(True, rx.color(ColorState.color), rx.color(ColorState.color, 5)), # type: ignore
|
rx.cond(True, rx.color(ColorState.color), rx.color(ColorState.color, 5)), # type: ignore
|
||||||
f'(Boolean(true) ? ("var(--"+{str(color_state_name)}.color+"-7)") : ("var(--"+{str(color_state_name)}.color+"-5)"))',
|
f'(true ? ("var(--"+{str(color_state_name)}.color+"-7)") : ("var(--"+{str(color_state_name)}.color+"-5)"))',
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
rx.match(
|
rx.match(
|
||||||
|
@ -23,7 +23,7 @@ def cond_state(request):
|
|||||||
def test_f_string_cond_interpolation():
|
def test_f_string_cond_interpolation():
|
||||||
# make sure backticks inside interpolation don't get escaped
|
# make sure backticks inside interpolation don't get escaped
|
||||||
var = LiteralVar.create(f"x {cond(True, 'a', 'b')}")
|
var = LiteralVar.create(f"x {cond(True, 'a', 'b')}")
|
||||||
assert str(var) == '("x "+(Boolean(true) ? "a" : "b"))'
|
assert str(var) == '("x "+(true ? "a" : "b"))'
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
@ -97,7 +97,7 @@ def test_prop_cond(c1: Any, c2: Any):
|
|||||||
c1 = json.dumps(c1)
|
c1 = json.dumps(c1)
|
||||||
if not isinstance(c2, Var):
|
if not isinstance(c2, Var):
|
||||||
c2 = json.dumps(c2)
|
c2 = json.dumps(c2)
|
||||||
assert str(prop_cond) == f"(Boolean(true) ? {c1} : {c2})"
|
assert str(prop_cond) == f"(true ? {c1} : {c2})"
|
||||||
|
|
||||||
|
|
||||||
def test_cond_no_mix():
|
def test_cond_no_mix():
|
||||||
@ -141,8 +141,7 @@ def test_cond_computed_var():
|
|||||||
|
|
||||||
state_name = format_state_name(CondStateComputed.get_full_name())
|
state_name = format_state_name(CondStateComputed.get_full_name())
|
||||||
assert (
|
assert (
|
||||||
str(comp)
|
str(comp) == f"(true ? {state_name}.computed_int : {state_name}.computed_str)"
|
||||||
== f"(Boolean(true) ? {state_name}.computed_int : {state_name}.computed_str)"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
assert comp._var_type == Union[int, str]
|
assert comp._var_type == Union[int, str]
|
||||||
|
@ -12,6 +12,7 @@ from reflex.ivars.base import (
|
|||||||
ImmutableVar,
|
ImmutableVar,
|
||||||
LiteralVar,
|
LiteralVar,
|
||||||
var_operation,
|
var_operation,
|
||||||
|
var_operation_return,
|
||||||
)
|
)
|
||||||
from reflex.ivars.function import ArgsFunctionOperation, FunctionStringVar
|
from reflex.ivars.function import ArgsFunctionOperation, FunctionStringVar
|
||||||
from reflex.ivars.number import (
|
from reflex.ivars.number import (
|
||||||
@ -925,9 +926,9 @@ def test_function_var():
|
|||||||
|
|
||||||
|
|
||||||
def test_var_operation():
|
def test_var_operation():
|
||||||
@var_operation(output=NumberVar)
|
@var_operation
|
||||||
def add(a: Union[NumberVar, int], b: Union[NumberVar, int]) -> str:
|
def add(a: Union[NumberVar, int], b: Union[NumberVar, int]):
|
||||||
return f"({a} + {b})"
|
return var_operation_return(js_expression=f"({a} + {b})", var_type=int)
|
||||||
|
|
||||||
assert str(add(1, 2)) == "(1 + 2)"
|
assert str(add(1, 2)) == "(1 + 2)"
|
||||||
assert str(add(a=4, b=-9)) == "(4 + -9)"
|
assert str(add(a=4, b=-9)) == "(4 + -9)"
|
||||||
@ -967,14 +968,14 @@ def test_all_number_operations():
|
|||||||
|
|
||||||
assert (
|
assert (
|
||||||
str(even_more_complicated_number)
|
str(even_more_complicated_number)
|
||||||
== "!(Boolean((Math.abs(Math.floor(((Math.floor(((-((-5.4 + 1)) * 2) / 3) / 2) % 3) ** 2))) || (2 && Math.round(((Math.floor(((-((-5.4 + 1)) * 2) / 3) / 2) % 3) ** 2))))))"
|
== "!(((Math.abs(Math.floor(((Math.floor(((-((-5.4 + 1)) * 2) / 3) / 2) % 3) ** 2))) || (2 && Math.round(((Math.floor(((-((-5.4 + 1)) * 2) / 3) / 2) % 3) ** 2)))) !== 0))"
|
||||||
)
|
)
|
||||||
|
|
||||||
assert str(LiteralNumberVar.create(5) > False) == "(5 > 0)"
|
assert str(LiteralNumberVar.create(5) > False) == "(5 > 0)"
|
||||||
assert str(LiteralBooleanVar.create(False) < 5) == "((false ? 1 : 0) < 5)"
|
assert str(LiteralBooleanVar.create(False) < 5) == "(Number(false) < 5)"
|
||||||
assert (
|
assert (
|
||||||
str(LiteralBooleanVar.create(False) < LiteralBooleanVar.create(True))
|
str(LiteralBooleanVar.create(False) < LiteralBooleanVar.create(True))
|
||||||
== "((false ? 1 : 0) < (true ? 1 : 0))"
|
== "(Number(false) < Number(true))"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user