1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123 |
- """Immutable number vars."""
- from __future__ import annotations
- import dataclasses
- import decimal
- import json
- import math
- from collections.abc import Callable
- from typing import TYPE_CHECKING, Any, NoReturn, TypeVar, overload
- from typing_extensions import TypeVar as TypeVarExt
- from reflex.constants.base import Dirs
- from reflex.utils.exceptions import (
- PrimitiveUnserializableToJSONError,
- VarTypeError,
- VarValueError,
- )
- from reflex.utils.imports import ImportDict, ImportVar
- from reflex.utils.types import safe_issubclass
- from .base import (
- CustomVarOperationReturn,
- LiteralVar,
- Var,
- VarData,
- unionize,
- var_operation,
- var_operation_return,
- )
- NUMBER_T = TypeVarExt(
- "NUMBER_T",
- bound=(int | float | decimal.Decimal),
- default=(int | float | decimal.Decimal),
- covariant=True,
- )
- if TYPE_CHECKING:
- from .sequence import ArrayVar
- def raise_unsupported_operand_types(
- operator: str, operands_types: tuple[type, ...]
- ) -> NoReturn:
- """Raise an unsupported operand types error.
- Args:
- operator: The operator.
- operands_types: The types of the operands.
- Raises:
- VarTypeError: The operand types are unsupported.
- """
- raise VarTypeError(
- f"Unsupported Operand type(s) for {operator}: {', '.join(t.__name__ for t in operands_types)}"
- )
- class NumberVar(Var[NUMBER_T], python_types=(int, float, decimal.Decimal)):
- """Base class for immutable number vars."""
- def __add__(self, other: number_types) -> NumberVar:
- """Add two numbers.
- Args:
- other: The other number.
- Returns:
- The number addition operation.
- """
- if not isinstance(other, NUMBER_TYPES):
- raise_unsupported_operand_types("+", (type(self), type(other)))
- return number_add_operation(self, +other)
- def __radd__(self, other: number_types) -> NumberVar:
- """Add two numbers.
- Args:
- other: The other number.
- Returns:
- The number addition operation.
- """
- if not isinstance(other, NUMBER_TYPES):
- raise_unsupported_operand_types("+", (type(other), type(self)))
- return number_add_operation(+other, self)
- def __sub__(self, other: number_types) -> NumberVar:
- """Subtract two numbers.
- Args:
- other: The other number.
- Returns:
- The number subtraction operation.
- """
- if not isinstance(other, NUMBER_TYPES):
- raise_unsupported_operand_types("-", (type(self), type(other)))
- return number_subtract_operation(self, +other)
- def __rsub__(self, other: number_types) -> NumberVar:
- """Subtract two numbers.
- Args:
- other: The other number.
- Returns:
- The number subtraction operation.
- """
- if not isinstance(other, NUMBER_TYPES):
- raise_unsupported_operand_types("-", (type(other), type(self)))
- return number_subtract_operation(+other, self)
- def __abs__(self):
- """Get the absolute value of the number.
- Returns:
- The number absolute operation.
- """
- return number_abs_operation(self)
- @overload
- def __mul__(self, other: number_types | boolean_types) -> NumberVar: ...
- @overload
- def __mul__(self, other: list | tuple | set | ArrayVar) -> ArrayVar: ...
- def __mul__(self, other: Any):
- """Multiply two numbers.
- Args:
- other: The other number.
- Returns:
- The number multiplication operation.
- """
- from .sequence import ArrayVar, LiteralArrayVar
- if isinstance(other, (list, tuple, ArrayVar)):
- if isinstance(other, ArrayVar):
- return other * self
- return LiteralArrayVar.create(other) * self
- if not isinstance(other, NUMBER_TYPES):
- raise_unsupported_operand_types("*", (type(self), type(other)))
- return number_multiply_operation(self, +other)
- @overload
- def __rmul__(self, other: number_types | boolean_types) -> NumberVar: ...
- @overload
- def __rmul__(self, other: list | tuple | set | ArrayVar) -> ArrayVar: ...
- def __rmul__(self, other: Any):
- """Multiply two numbers.
- Args:
- other: The other number.
- Returns:
- The number multiplication operation.
- """
- from .sequence import ArrayVar, LiteralArrayVar
- if isinstance(other, (list, tuple, ArrayVar)):
- if isinstance(other, ArrayVar):
- return other * self
- return LiteralArrayVar.create(other) * self
- if not isinstance(other, NUMBER_TYPES):
- raise_unsupported_operand_types("*", (type(other), type(self)))
- return number_multiply_operation(+other, self)
- def __truediv__(self, other: number_types) -> NumberVar:
- """Divide two numbers.
- Args:
- other: The other number.
- Returns:
- The number true division operation.
- """
- if not isinstance(other, NUMBER_TYPES):
- raise_unsupported_operand_types("/", (type(self), type(other)))
- return number_true_division_operation(self, +other)
- def __rtruediv__(self, other: number_types) -> NumberVar:
- """Divide two numbers.
- Args:
- other: The other number.
- Returns:
- The number true division operation.
- """
- if not isinstance(other, NUMBER_TYPES):
- raise_unsupported_operand_types("/", (type(other), type(self)))
- return number_true_division_operation(+other, self)
- def __floordiv__(self, other: number_types) -> NumberVar:
- """Floor divide two numbers.
- Args:
- other: The other number.
- Returns:
- The number floor division operation.
- """
- if not isinstance(other, NUMBER_TYPES):
- raise_unsupported_operand_types("//", (type(self), type(other)))
- return number_floor_division_operation(self, +other)
- def __rfloordiv__(self, other: number_types) -> NumberVar:
- """Floor divide two numbers.
- Args:
- other: The other number.
- Returns:
- The number floor division operation.
- """
- if not isinstance(other, NUMBER_TYPES):
- raise_unsupported_operand_types("//", (type(other), type(self)))
- return number_floor_division_operation(+other, self)
- def __mod__(self, other: number_types) -> NumberVar:
- """Modulo two numbers.
- Args:
- other: The other number.
- Returns:
- The number modulo operation.
- """
- if not isinstance(other, NUMBER_TYPES):
- raise_unsupported_operand_types("%", (type(self), type(other)))
- return number_modulo_operation(self, +other)
- def __rmod__(self, other: number_types) -> NumberVar:
- """Modulo two numbers.
- Args:
- other: The other number.
- Returns:
- The number modulo operation.
- """
- if not isinstance(other, NUMBER_TYPES):
- raise_unsupported_operand_types("%", (type(other), type(self)))
- return number_modulo_operation(+other, self)
- def __pow__(self, other: number_types) -> NumberVar:
- """Exponentiate two numbers.
- Args:
- other: The other number.
- Returns:
- The number exponent operation.
- """
- if not isinstance(other, NUMBER_TYPES):
- raise_unsupported_operand_types("**", (type(self), type(other)))
- return number_exponent_operation(self, +other)
- def __rpow__(self, other: number_types) -> NumberVar:
- """Exponentiate two numbers.
- Args:
- other: The other number.
- Returns:
- The number exponent operation.
- """
- if not isinstance(other, NUMBER_TYPES):
- raise_unsupported_operand_types("**", (type(other), type(self)))
- return number_exponent_operation(+other, self)
- def __neg__(self) -> NumberVar:
- """Negate the number.
- Returns:
- The number negation operation.
- """
- return number_negate_operation(self) # pyright: ignore [reportReturnType]
- def __invert__(self):
- """Boolean NOT the number.
- Returns:
- The boolean NOT operation.
- """
- return boolean_not_operation(self.bool())
- def __pos__(self) -> NumberVar:
- """Positive the number.
- Returns:
- The number.
- """
- return self
- def __round__(self, ndigits: int | NumberVar = 0) -> NumberVar:
- """Round the number.
- Args:
- ndigits: The number of digits to round.
- Returns:
- The number round operation.
- """
- if not isinstance(ndigits, NUMBER_TYPES):
- raise_unsupported_operand_types("round", (type(self), type(ndigits)))
- return number_round_operation(self, +ndigits)
- def __ceil__(self):
- """Ceil the number.
- Returns:
- The number ceil operation.
- """
- return number_ceil_operation(self)
- def __floor__(self):
- """Floor the number.
- Returns:
- The number floor operation.
- """
- return number_floor_operation(self)
- def __trunc__(self):
- """Trunc the number.
- Returns:
- The number trunc operation.
- """
- return number_trunc_operation(self)
- def __lt__(self, other: number_types) -> BooleanVar:
- """Less than comparison.
- Args:
- other: The other number.
- Returns:
- The result of the comparison.
- """
- if not isinstance(other, NUMBER_TYPES):
- raise_unsupported_operand_types("<", (type(self), type(other)))
- return less_than_operation(+self, +other)
- def __le__(self, other: number_types) -> BooleanVar:
- """Less than or equal comparison.
- Args:
- other: The other number.
- Returns:
- The result of the comparison.
- """
- if not isinstance(other, NUMBER_TYPES):
- raise_unsupported_operand_types("<=", (type(self), type(other)))
- return less_than_or_equal_operation(+self, +other)
- def __eq__(self, other: Any):
- """Equal comparison.
- Args:
- other: The other number.
- Returns:
- The result of the comparison.
- """
- if isinstance(other, NUMBER_TYPES):
- return equal_operation(+self, +other)
- return equal_operation(self, other)
- def __ne__(self, other: Any):
- """Not equal comparison.
- Args:
- other: The other number.
- Returns:
- The result of the comparison.
- """
- if isinstance(other, NUMBER_TYPES):
- return not_equal_operation(+self, +other)
- return not_equal_operation(self, other)
- def __gt__(self, other: number_types) -> BooleanVar:
- """Greater than comparison.
- Args:
- other: The other number.
- Returns:
- The result of the comparison.
- """
- if not isinstance(other, NUMBER_TYPES):
- raise_unsupported_operand_types(">", (type(self), type(other)))
- return greater_than_operation(+self, +other)
- def __ge__(self, other: number_types) -> BooleanVar:
- """Greater than or equal comparison.
- Args:
- other: The other number.
- Returns:
- The result of the comparison.
- """
- if not isinstance(other, NUMBER_TYPES):
- raise_unsupported_operand_types(">=", (type(self), type(other)))
- return greater_than_or_equal_operation(+self, +other)
- def _is_strict_float(self) -> bool:
- """Check if the number is a float.
- Returns:
- bool: True if the number is a float.
- """
- return safe_issubclass(self._var_type, float)
- def _is_strict_int(self) -> bool:
- """Check if the number is an int.
- Returns:
- bool: True if the number is an int.
- """
- return safe_issubclass(self._var_type, int)
- def __format__(self, format_spec: str) -> str:
- """Format the number.
- Args:
- format_spec: The format specifier.
- Returns:
- The formatted number.
- Raises:
- VarValueError: If the format specifier is not supported.
- """
- from .sequence import (
- get_decimal_string_operation,
- get_decimal_string_separator_operation,
- )
- separator = ""
- if format_spec and format_spec[:1] == ",":
- separator = ","
- format_spec = format_spec[1:]
- elif format_spec and format_spec[:1] == "_":
- separator = "_"
- format_spec = format_spec[1:]
- if (
- format_spec
- and format_spec[-1] == "f"
- and format_spec[0] == "."
- and format_spec[1:-1].isdigit()
- ):
- how_many_decimals = int(format_spec[1:-1])
- return f"{get_decimal_string_operation(self, Var.create(how_many_decimals), Var.create(separator))}"
- if not format_spec and separator:
- return (
- f"{get_decimal_string_separator_operation(self, Var.create(separator))}"
- )
- if format_spec:
- raise VarValueError(
- f"Unknown format code '{format_spec}' for object of type 'NumberVar'. It is only supported to use ',', '_', and '.f' for float numbers."
- "If possible, use computed variables instead: https://reflex.dev/docs/vars/computed-vars/"
- )
- return super().__format__(format_spec)
- def binary_number_operation(
- func: Callable[[NumberVar, NumberVar], str],
- ) -> Callable[[number_types, number_types], NumberVar]:
- """Decorator to create a binary number operation.
- Args:
- func: The binary number operation function.
- Returns:
- The binary number operation.
- """
- @var_operation
- def operation(lhs: NumberVar, rhs: NumberVar):
- return var_operation_return(
- js_expression=func(lhs, rhs),
- var_type=unionize(lhs._var_type, rhs._var_type),
- )
- def wrapper(lhs: number_types, rhs: number_types) -> NumberVar:
- """Create the binary number operation.
- Args:
- lhs: The first number.
- rhs: The second number.
- Returns:
- The binary number operation.
- """
- return operation(lhs, rhs) # pyright: ignore [reportReturnType, reportArgumentType]
- return wrapper
- @binary_number_operation
- def number_add_operation(lhs: NumberVar, rhs: NumberVar):
- """Add two numbers.
- Args:
- lhs: The first number.
- rhs: The second number.
- Returns:
- The number addition operation.
- """
- return f"({lhs} + {rhs})"
- @binary_number_operation
- def number_subtract_operation(lhs: NumberVar, rhs: NumberVar):
- """Subtract two numbers.
- Args:
- lhs: The first number.
- rhs: The second number.
- Returns:
- The number subtraction operation.
- """
- return f"({lhs} - {rhs})"
- @var_operation
- def number_abs_operation(value: NumberVar):
- """Get the absolute value of the number.
- Args:
- value: The number.
- Returns:
- The number absolute operation.
- """
- return var_operation_return(
- js_expression=f"Math.abs({value})", var_type=value._var_type
- )
- @binary_number_operation
- def number_multiply_operation(lhs: NumberVar, rhs: NumberVar):
- """Multiply two numbers.
- Args:
- lhs: The first number.
- rhs: The second number.
- Returns:
- The number multiplication operation.
- """
- return f"({lhs} * {rhs})"
- @var_operation
- def number_negate_operation(
- value: NumberVar[NUMBER_T],
- ) -> CustomVarOperationReturn[NUMBER_T]:
- """Negate the number.
- Args:
- value: The number.
- Returns:
- The number negation operation.
- """
- return var_operation_return(js_expression=f"-({value})", var_type=value._var_type)
- @binary_number_operation
- def number_true_division_operation(lhs: NumberVar, rhs: NumberVar):
- """Divide two numbers.
- Args:
- lhs: The first number.
- rhs: The second number.
- Returns:
- The number true division operation.
- """
- return f"({lhs} / {rhs})"
- @binary_number_operation
- def number_floor_division_operation(lhs: NumberVar, rhs: NumberVar):
- """Floor divide two numbers.
- Args:
- lhs: The first number.
- rhs: The second number.
- Returns:
- The number floor division operation.
- """
- return f"Math.floor({lhs} / {rhs})"
- @binary_number_operation
- def number_modulo_operation(lhs: NumberVar, rhs: NumberVar):
- """Modulo two numbers.
- Args:
- lhs: The first number.
- rhs: The second number.
- Returns:
- The number modulo operation.
- """
- return f"({lhs} % {rhs})"
- @binary_number_operation
- def number_exponent_operation(lhs: NumberVar, rhs: NumberVar):
- """Exponentiate two numbers.
- Args:
- lhs: The first number.
- rhs: The second number.
- Returns:
- The number exponent operation.
- """
- return f"({lhs} ** {rhs})"
- @var_operation
- def number_round_operation(value: NumberVar, ndigits: NumberVar | int):
- """Round the number.
- Args:
- value: The number.
- ndigits: The number of digits.
- Returns:
- The number round operation.
- """
- if (isinstance(ndigits, LiteralNumberVar) and ndigits._var_value == 0) or (
- isinstance(ndigits, int) and ndigits == 0
- ):
- return var_operation_return(js_expression=f"Math.round({value})", var_type=int)
- return var_operation_return(
- js_expression=f"(+{value}.toFixed({ndigits}))", var_type=float
- )
- @var_operation
- def number_ceil_operation(value: NumberVar):
- """Ceil the number.
- Args:
- value: The number.
- Returns:
- The number ceil operation.
- """
- return var_operation_return(js_expression=f"Math.ceil({value})", var_type=int)
- @var_operation
- def number_floor_operation(value: NumberVar):
- """Floor the number.
- Args:
- value: The number.
- Returns:
- The number floor operation.
- """
- return var_operation_return(js_expression=f"Math.floor({value})", var_type=int)
- @var_operation
- def number_trunc_operation(value: NumberVar):
- """Trunc the number.
- Args:
- value: The number.
- Returns:
- The number trunc operation.
- """
- return var_operation_return(js_expression=f"Math.trunc({value})", var_type=int)
- class BooleanVar(NumberVar[bool], python_types=bool):
- """Base class for immutable boolean vars."""
- def __invert__(self):
- """NOT the boolean.
- Returns:
- The boolean NOT operation.
- """
- return boolean_not_operation(self)
- def __int__(self):
- """Convert the boolean to an int.
- Returns:
- The boolean to int operation.
- """
- return boolean_to_number_operation(self)
- def __pos__(self):
- """Convert the boolean to an int.
- Returns:
- The boolean to int operation.
- """
- return boolean_to_number_operation(self)
- def bool(self) -> BooleanVar:
- """Boolean conversion.
- Returns:
- The boolean value of the boolean.
- """
- return self
- def __lt__(self, other: Any):
- """Less than comparison.
- Args:
- other: The other boolean.
- Returns:
- The result of the comparison.
- """
- return +self < other
- def __le__(self, other: Any):
- """Less than or equal comparison.
- Args:
- other: The other boolean.
- Returns:
- The result of the comparison.
- """
- return +self <= other
- def __gt__(self, other: Any):
- """Greater than comparison.
- Args:
- other: The other boolean.
- Returns:
- The result of the comparison.
- """
- return +self > other
- def __ge__(self, other: Any):
- """Greater than or equal comparison.
- Args:
- other: The other boolean.
- Returns:
- The result of the comparison.
- """
- return +self >= other
- @var_operation
- def boolean_to_number_operation(value: BooleanVar):
- """Convert the boolean to a number.
- Args:
- value: The boolean.
- Returns:
- The boolean to number operation.
- """
- return var_operation_return(js_expression=f"Number({value})", var_type=int)
- def comparison_operator(
- func: Callable[[Var, Var], str],
- ) -> Callable[[Var | Any, Var | Any], BooleanVar]:
- """Decorator to create a comparison operation.
- Args:
- func: The comparison operation function.
- Returns:
- The comparison operation.
- """
- @var_operation
- def operation(lhs: Var, rhs: Var):
- return var_operation_return(
- js_expression=func(lhs, rhs),
- var_type=bool,
- )
- def wrapper(lhs: Var | Any, rhs: Var | Any) -> BooleanVar:
- """Create the comparison operation.
- Args:
- lhs: The first value.
- rhs: The second value.
- Returns:
- The comparison operation.
- """
- return operation(lhs, rhs)
- return wrapper
- @comparison_operator
- def greater_than_operation(lhs: Var, rhs: Var):
- """Greater than comparison.
- Args:
- lhs: The first value.
- rhs: The second value.
- Returns:
- The result of the comparison.
- """
- return f"({lhs} > {rhs})"
- @comparison_operator
- def greater_than_or_equal_operation(lhs: Var, rhs: Var):
- """Greater than or equal comparison.
- Args:
- lhs: The first value.
- rhs: The second value.
- Returns:
- The result of the comparison.
- """
- return f"({lhs} >= {rhs})"
- @comparison_operator
- def less_than_operation(lhs: Var, rhs: Var):
- """Less than comparison.
- Args:
- lhs: The first value.
- rhs: The second value.
- Returns:
- The result of the comparison.
- """
- return f"({lhs} < {rhs})"
- @comparison_operator
- def less_than_or_equal_operation(lhs: Var, rhs: Var):
- """Less than or equal comparison.
- Args:
- lhs: The first value.
- rhs: The second value.
- Returns:
- The result of the comparison.
- """
- return f"({lhs} <= {rhs})"
- @comparison_operator
- def equal_operation(lhs: Var, rhs: Var):
- """Equal comparison.
- Args:
- lhs: The first value.
- rhs: The second value.
- Returns:
- The result of the comparison.
- """
- return f"({lhs} === {rhs})"
- @comparison_operator
- def not_equal_operation(lhs: Var, rhs: Var):
- """Not equal comparison.
- Args:
- lhs: The first value.
- rhs: The second value.
- Returns:
- The result of the comparison.
- """
- return f"({lhs} !== {rhs})"
- @var_operation
- def boolean_not_operation(value: BooleanVar):
- """Boolean NOT the boolean.
- Args:
- value: The boolean.
- Returns:
- The boolean NOT operation.
- """
- return var_operation_return(js_expression=f"!({value})", var_type=bool)
- @dataclasses.dataclass(
- eq=False,
- frozen=True,
- slots=True,
- )
- class LiteralNumberVar(LiteralVar, NumberVar[NUMBER_T]):
- """Base class for immutable literal number vars."""
- _var_value: float | int | decimal.Decimal = dataclasses.field(default=0)
- def json(self) -> str:
- """Get the JSON representation of the var.
- Returns:
- The JSON representation of the var.
- Raises:
- PrimitiveUnserializableToJSONError: If the var is unserializable to JSON.
- """
- if isinstance(self._var_value, decimal.Decimal):
- return json.dumps(float(self._var_value))
- if math.isinf(self._var_value) or math.isnan(self._var_value):
- raise PrimitiveUnserializableToJSONError(
- f"No valid JSON representation for {self}"
- )
- return json.dumps(self._var_value)
- def __hash__(self) -> int:
- """Calculate the hash value of the object.
- Returns:
- int: The hash value of the object.
- """
- return hash((type(self).__name__, self._var_value))
- @classmethod
- def create(
- cls, value: float | int | decimal.Decimal, _var_data: VarData | None = None
- ):
- """Create the number var.
- Args:
- value: The value of the var.
- _var_data: Additional hooks and imports associated with the Var.
- Returns:
- The number var.
- """
- if math.isinf(value):
- js_expr = "Infinity" if value > 0 else "-Infinity"
- elif math.isnan(value):
- js_expr = "NaN"
- else:
- js_expr = str(value)
- return cls(
- _js_expr=js_expr,
- _var_type=type(value),
- _var_data=_var_data,
- _var_value=value,
- )
- @dataclasses.dataclass(
- eq=False,
- frozen=True,
- slots=True,
- )
- class LiteralBooleanVar(LiteralVar, BooleanVar):
- """Base class for immutable literal boolean vars."""
- _var_value: bool = dataclasses.field(default=False)
- def json(self) -> str:
- """Get the JSON representation of the var.
- Returns:
- The JSON representation of the var.
- """
- return "true" if self._var_value else "false"
- def __hash__(self) -> int:
- """Calculate the hash value of the object.
- Returns:
- int: The hash value of the object.
- """
- return hash((type(self).__name__, self._var_value))
- @classmethod
- def create(cls, value: bool, _var_data: VarData | None = None):
- """Create the boolean var.
- Args:
- value: The value of the var.
- _var_data: Additional hooks and imports associated with the Var.
- Returns:
- The boolean var.
- """
- return cls(
- _js_expr="true" if value else "false",
- _var_type=bool,
- _var_data=_var_data,
- _var_value=value,
- )
- number_types = NumberVar | int | float | decimal.Decimal
- boolean_types = BooleanVar | bool
- _IS_TRUE_IMPORT: ImportDict = {
- f"$/{Dirs.STATE_PATH}": [ImportVar(tag="isTrue")],
- }
- _IS_NOT_NULL_OR_UNDEFINED_IMPORT: ImportDict = {
- f"$/{Dirs.STATE_PATH}": [ImportVar(tag="isNotNullOrUndefined")],
- }
- @var_operation
- def boolify(value: Var):
- """Convert the value to a boolean.
- Args:
- value: The value.
- Returns:
- The boolean value.
- """
- return var_operation_return(
- js_expression=f"isTrue({value})",
- var_type=bool,
- var_data=VarData(imports=_IS_TRUE_IMPORT),
- )
- @var_operation
- def is_not_none_operation(value: Var):
- """Check if the value is not None.
- Args:
- value: The value.
- Returns:
- The boolean value.
- """
- return var_operation_return(
- js_expression=f"isNotNullOrUndefined({value})",
- var_type=bool,
- var_data=VarData(imports=_IS_NOT_NULL_OR_UNDEFINED_IMPORT),
- )
- T = TypeVar("T")
- U = TypeVar("U")
- @var_operation
- def ternary_operation(
- condition: Var[bool], if_true: Var[T], if_false: Var[U]
- ) -> CustomVarOperationReturn[T | U]:
- """Create a ternary operation.
- Args:
- condition: The condition.
- if_true: The value if the condition is true.
- if_false: The value if the condition is false.
- Returns:
- The ternary operation.
- """
- type_value: type[T] | type[U] = unionize(if_true._var_type, if_false._var_type)
- value: CustomVarOperationReturn[T | U] = var_operation_return(
- js_expression=f"({condition} ? {if_true} : {if_false})",
- var_type=type_value,
- )
- return value
- NUMBER_TYPES = (int, float, decimal.Decimal, NumberVar)
|