optimize var operation output

This commit is contained in:
Khaleel Al-Adhami 2025-01-23 11:54:45 -08:00
parent 6604784ca1
commit d3b12a84fa
8 changed files with 202 additions and 253 deletions

View File

@ -9,8 +9,7 @@ from reflex.components.component import BaseComponent, Component
from reflex.style import LIGHT_COLOR_MODE, resolved_color_mode
from reflex.utils import types
from reflex.utils.types import safe_issubclass
from reflex.vars.base import LiteralVar, ReflexCallable, Var
from reflex.vars.function import ArgsFunctionOperation
from reflex.vars.base import LiteralVar, Var
from reflex.vars.number import ternary_operation
@ -53,23 +52,12 @@ def cond(condition: Any, c1: Any, c2: Any = None) -> Component | Var:
if c2 is None:
raise ValueError("For conditional vars, the second argument must be set.")
c1 = Var.create(c1)
c2 = Var.create(c2)
# Create the conditional var.
return ternary_operation(
cond_var.bool(),
ArgsFunctionOperation.create(
(),
c1,
_var_type=ReflexCallable[[], c1._var_type],
),
ArgsFunctionOperation.create(
(),
c2,
_var_type=ReflexCallable[[], c2._var_type],
),
).call()
c1,
c2,
)
@overload

View File

@ -1788,7 +1788,7 @@ def var_operation(
```python
@var_operation
def add(a: Var[int], b: Var[int]):
return custom_var_operation(f"{a} + {b}")
return var_operation_return(f"{a} + {b}")
```
Args:
@ -1854,6 +1854,9 @@ def var_operation(
custom_operation_return = func(*arg_vars)
def simplified_operation(*args):
return func(*args)._js_expr
args_operation = ArgsFunctionOperation.create(
tuple(map(str, arg_vars)),
custom_operation_return,
@ -1867,6 +1870,7 @@ def var_operation(
function_name=func_name,
type_computer=custom_operation_return._type_computer,
_raw_js_function=custom_operation_return._raw_js_function,
_original_var_operation=simplified_operation,
_var_type=ReflexCallable[
tuple(
arg_python_type
@ -3222,15 +3226,7 @@ def and_operation(a: Var | Any, b: Var | Any) -> Var:
Returns:
The result of the logical AND operation.
"""
from .function import ArgsFunctionOperation
a = Var.create(a)
b = Var.create(b)
return _and_func_operation(
ArgsFunctionOperation.create((), a, _var_type=ReflexCallable[[], a._var_type]),
ArgsFunctionOperation.create((), b, _var_type=ReflexCallable[[], b._var_type]),
)
return _and_operation(a, b)
def or_operation(a: Var | Any, b: Var | Any) -> Var:
@ -3243,99 +3239,7 @@ def or_operation(a: Var | Any, b: Var | Any) -> Var:
Returns:
The result of the logical OR operation.
"""
from .function import ArgsFunctionOperation
a = Var.create(a)
b = Var.create(b)
return _or_func_operation(
ArgsFunctionOperation.create((), a, _var_type=ReflexCallable[[], a._var_type]),
ArgsFunctionOperation.create((), b, _var_type=ReflexCallable[[], b._var_type]),
)
T_LOGICAL = TypeVar("T_LOGICAL")
U_LOGICAL = TypeVar("U_LOGICAL")
@var_operation
def _and_func_operation(
a: Var[ReflexCallable[[], T_LOGICAL]], b: Var[ReflexCallable[[], U_LOGICAL]]
) -> CustomVarOperationReturn[ReflexCallable[[], Union[T_LOGICAL, U_LOGICAL]]]:
"""Perform a logical AND operation on two variables.
Args:
a: The first variable.
b: The second variable.
Returns:
The result of the logical AND operation.
"""
def type_computer(*args: Var):
if not args:
return (
ReflexCallable[[ReflexCallable[[], Any], ReflexCallable[[], Any]], Any],
type_computer,
)
if len(args) == 1:
return (
ReflexCallable[[ReflexCallable[[], Any]], Any],
functools.partial(type_computer, args[0]),
)
a_return_type = unwrap_reflex_callalbe(args[0]._var_type)[1]
b_return_type = unwrap_reflex_callalbe(args[1]._var_type)[1]
return (
ReflexCallable[[], unionize(a_return_type, b_return_type)],
None,
)
return var_operation_return(
js_expression=f"({a}() && {b}())",
type_computer=type_computer,
)
@var_operation
def _or_func_operation(
a: Var[ReflexCallable[[], T_LOGICAL]], b: Var[ReflexCallable[[], U_LOGICAL]]
) -> CustomVarOperationReturn[ReflexCallable[[], Union[T_LOGICAL, U_LOGICAL]]]:
"""Perform a logical OR operation on two variables.
Args:
a: The first variable.
b: The second variable.
Returns:
The result of the logical OR operation.
"""
def type_computer(*args: Var):
if not args:
return (
ReflexCallable[[ReflexCallable[[], Any], ReflexCallable[[], Any]], Any],
type_computer,
)
if len(args) == 1:
return (
ReflexCallable[[ReflexCallable[[], Any]], Any],
functools.partial(type_computer, args[0]),
)
a_return_type = unwrap_reflex_callalbe(args[0]._var_type)[1]
b_return_type = unwrap_reflex_callalbe(args[1]._var_type)[1]
return (
ReflexCallable[[], unionize(a_return_type, b_return_type)],
None,
)
return var_operation_return(
js_expression=f"({a}() || {b}())",
type_computer=type_computer,
)
return _or_operation(a, b)
def passthrough_unary_type_computer(no_args: GenericType) -> TypeComputer:
@ -3402,3 +3306,59 @@ def nary_type_computer(
)
return type_computer
T_LOGICAL = TypeVar("T_LOGICAL")
U_LOGICAL = TypeVar("U_LOGICAL")
@var_operation
def _and_operation(
a: Var[T_LOGICAL], b: Var[U_LOGICAL]
) -> CustomVarOperationReturn[Union[T_LOGICAL, U_LOGICAL]]:
"""Perform a logical AND operation on two variables.
Args:
a: The first variable.
b: The second variable.
Returns:
The result of the logical AND operation.
"""
return var_operation_return(
js_expression=f"({a} && {b})",
type_computer=nary_type_computer(
ReflexCallable[[Any, Any], Any],
ReflexCallable[[Any], Any],
computer=lambda args: unionize(
args[0]._var_type,
args[1]._var_type,
),
),
)
@var_operation
def _or_operation(
a: Var[T_LOGICAL], b: Var[U_LOGICAL]
) -> CustomVarOperationReturn[Union[T_LOGICAL, U_LOGICAL]]:
"""Perform a logical OR operation on two variables.
Args:
a: The first variable.
b: The second variable.
Returns:
The result ocomputerf the logical OR operation.
"""
return var_operation_return(
js_expression=f"({a} || {b})",
type_computer=nary_type_computer(
ReflexCallable[[Any, Any], Any],
ReflexCallable[[Any], Any],
computer=lambda args: unionize(
args[0]._var_type,
args[1]._var_type,
),
),
)

View File

@ -1219,19 +1219,26 @@ class FunctionVar(
args = tuple(map(LiteralVar.create, args))
self._pre_check(*args)
return_type = self._return_type(*args)
if (
isinstance(self, (ArgsFunctionOperation, ArgsFunctionOperationBuilder))
and self._raw_js_function
if arg_len == len(args) and isinstance(
self, (ArgsFunctionOperation, ArgsFunctionOperationBuilder)
):
return VarOperationCall.create(
FunctionStringVar.create(
self._raw_js_function,
_var_type=self._var_type,
if self._raw_js_function is not None:
return VarOperationCall.create(
FunctionStringVar.create(
self._raw_js_function,
_var_type=self._var_type,
_var_data=self._get_all_var_data(),
),
*args,
_var_type=return_type,
).guess_type()
if self._original_var_operation is not None:
return ExpressionCall.create(
self._original_var_operation,
*args,
_var_data=self._get_all_var_data(),
),
*args,
_var_type=return_type,
).guess_type()
_var_type=return_type,
).guess_type()
return VarOperationCall.create(self, *args, _var_type=return_type).guess_type()
@ -1361,6 +1368,61 @@ class FunctionVar(
__call__ = call
@dataclasses.dataclass(frozen=True)
class ExpressionCall(CachedVarOperation, Var[R]):
"""Class for expression calls."""
_original_var_operation: Callable = dataclasses.field(default=lambda *args: "")
_args: Tuple[Var, ...] = dataclasses.field(default_factory=tuple)
@cached_property_no_lock
def _cached_var_name(self) -> str:
"""The name of the var.
Returns:
The name of the var.
"""
return self._original_var_operation(*self._args)
@cached_property_no_lock
def _cached_get_all_var_data(self) -> VarData | None:
"""Get all the var data associated with the var.
Returns:
All the var data associated with the var.
"""
return VarData.merge(
*[arg._get_all_var_data() for arg in self._args],
self._var_data,
)
@classmethod
def create(
cls,
_original_var_operation: Callable,
*args: Var | Any,
_var_type: GenericType = Any,
_var_data: VarData | None = None,
) -> ExpressionCall:
"""Create a new expression call.
Args:
_original_var_operation: The original var operation.
*args: The arguments to call the expression with.
_var_data: Additional hooks and imports associated with the Var.
Returns:
The expression call var.
"""
return ExpressionCall(
_js_expr="",
_var_type=_var_type,
_var_data=_var_data,
_original_var_operation=_original_var_operation,
_args=args,
)
class BuilderFunctionVar(
FunctionVar[CALLABLE_TYPE], default_type=ReflexCallable[Any, Any]
):
@ -1600,6 +1662,7 @@ class ArgsFunctionOperation(CachedVarOperation, FunctionVar[CALLABLE_TYPE]):
_type_computer: Optional[TypeComputer] = dataclasses.field(default=None)
_explicit_return: bool = dataclasses.field(default=False)
_raw_js_function: str | None = dataclasses.field(default=None)
_original_var_operation: Callable | None = dataclasses.field(default=None)
_cached_var_name = cached_property_no_lock(format_args_function_operation)
@ -1619,6 +1682,7 @@ class ArgsFunctionOperation(CachedVarOperation, FunctionVar[CALLABLE_TYPE]):
explicit_return: bool = False,
type_computer: Optional[TypeComputer] = None,
_raw_js_function: str | None = None,
_original_var_operation: Callable | None = None,
_var_type: GenericType = Callable,
_var_data: VarData | None = None,
):
@ -1634,6 +1698,7 @@ class ArgsFunctionOperation(CachedVarOperation, FunctionVar[CALLABLE_TYPE]):
explicit_return: Whether to use explicit return syntax.
type_computer: A function to compute the return type.
_raw_js_function: If provided, it will be used when the operation is being called with all of its arguments at once.
_original_var_operation: The original var operation, if any.
_var_type: The type of the var.
_var_data: Additional hooks and imports associated with the Var.
@ -1647,6 +1712,7 @@ class ArgsFunctionOperation(CachedVarOperation, FunctionVar[CALLABLE_TYPE]):
_var_data=_var_data,
_args=FunctionArgs(args=tuple(args_names), rest=rest),
_raw_js_function=_raw_js_function,
_original_var_operation=_original_var_operation,
_default_values=tuple(default_values),
_function_name=function_name,
_validators=tuple(validators),
@ -1678,6 +1744,7 @@ class ArgsFunctionOperationBuilder(
_type_computer: Optional[TypeComputer] = dataclasses.field(default=None)
_explicit_return: bool = dataclasses.field(default=False)
_raw_js_function: str | None = dataclasses.field(default=None)
_original_var_operation: Callable | None = dataclasses.field(default=None)
_cached_var_name = cached_property_no_lock(format_args_function_operation)
@ -1697,6 +1764,7 @@ class ArgsFunctionOperationBuilder(
explicit_return: bool = False,
type_computer: Optional[TypeComputer] = None,
_raw_js_function: str | None = None,
_original_var_operation: Callable | None = None,
_var_type: GenericType = Callable,
_var_data: VarData | None = None,
):
@ -1711,9 +1779,10 @@ class ArgsFunctionOperationBuilder(
function_name: The name of the function.
explicit_return: Whether to use explicit return syntax.
type_computer: A function to compute the return type.
_raw_js_function: If provided, it will be used when the operation is being called with all of its arguments at once.
_original_var_operation: The original var operation, if any.
_var_type: The type of the var.
_var_data: Additional hooks and imports associated with the Var.
_raw_js_function: If provided, it will be used when the operation is being called with all of its arguments at once.
Returns:
The function var.
@ -1725,6 +1794,7 @@ class ArgsFunctionOperationBuilder(
_var_data=_var_data,
_args=FunctionArgs(args=tuple(args_names), rest=rest),
_raw_js_function=_raw_js_function,
_original_var_operation=_original_var_operation,
_default_values=tuple(default_values),
_function_name=function_name,
_validators=tuple(validators),

View File

@ -39,7 +39,7 @@ def create_color_var(color):
create_color_var(
rx.color(ColorState.color, ColorState.shade, ColorState.alpha) # type: ignore
),
f'("var(--"+{color_state_name!s}.color+"-"+(((_condition, _if_true, _if_false) => (_condition ? _if_true : _if_false))({color_state_name!s}.alpha, "a", ""))+(((__to_string) => __to_string.toString())({color_state_name!s}.shade))+")")',
f'("var(--"+{color_state_name!s}.color+"-"+({color_state_name!s}.alpha ? "a" : "")+(((__to_string) => __to_string.toString())({color_state_name!s}.shade))+")")',
Color,
),
(
@ -78,11 +78,11 @@ def test_color(color, expected, expected_type: Union[Type[str], Type[Color]]):
[
(
rx.cond(True, rx.color("mint"), rx.color("tomato", 5)),
'((((_condition, _if_true, _if_false) => (_condition ? _if_true : _if_false))(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
f'((((_condition, _if_true, _if_false) => (_condition ? _if_true : _if_false))(true, (() => ("var(--"+{color_state_name!s}.color+"-7)")), (() => ("var(--"+{color_state_name!s}.color+"-5)"))))())',
f'(true ? ("var(--"+{color_state_name!s}.color+"-7)") : ("var(--"+{color_state_name!s}.color+"-5)"))',
),
(
rx.match(

View File

@ -23,7 +23,7 @@ def test_f_string_cond_interpolation():
var = LiteralVar.create(f"x {cond(True, 'a', 'b')}")
assert (
str(var)
== '("x "+((((_condition, _if_true, _if_false) => (_condition ? _if_true : _if_false))(true, (() => "a"), (() => "b")))()))'
== '("x "+(true ? "a" : "b"))'
)
@ -53,7 +53,7 @@ def test_validate_cond(cond_state: BaseState):
assert isinstance(cond_var, Var)
assert (
str(cond_var)
== f'((((_condition, _if_true, _if_false) => (_condition ? _if_true : _if_false))({cond_state.value.bool()!s}, (() => (jsx(RadixThemesText, ({{ ["as"] : "p" }}), (jsx(Fragment, ({{ }}), "cond is True"))))), (() => (jsx(RadixThemesText, ({{ ["as"] : "p" }}), (jsx(Fragment, ({{ }}), "cond is False")))))))())'
== f'({cond_state.value.bool()!s} ? (jsx(RadixThemesText, ({{ ["as"] : "p" }}), (jsx(Fragment, ({{ }}), "cond is True")))) : (jsx(RadixThemesText, ({{ ["as"] : "p" }}), (jsx(Fragment, ({{ }}), "cond is False")))))'
)
var_data = cond_var._get_all_var_data()
@ -89,10 +89,7 @@ def test_prop_cond(c1: Any, c2: Any):
c1 = json.dumps(c1)
if not isinstance(c2, Var):
c2 = json.dumps(c2)
assert (
str(prop_cond)
== f"((((_condition, _if_true, _if_false) => (_condition ? _if_true : _if_false))(true, (() => {c1!s}), (() => {c2!s})))())"
)
assert str(prop_cond) == f"(true ? {c1!s} : {c2!s})"
def test_cond_mix():
@ -101,7 +98,7 @@ def test_cond_mix():
assert isinstance(x, Var)
assert (
str(x)
== '((((_condition, _if_true, _if_false) => (_condition ? _if_true : _if_false))(true, (() => "hello"), (() => (jsx(RadixThemesText, ({ ["as"] : "p" }), (jsx(Fragment, ({ }), "world")))))))())'
== '(true ? "hello" : (jsx(RadixThemesText, ({ ["as"] : "p" }), (jsx(Fragment, ({ }), "world")))))'
)
@ -112,7 +109,7 @@ def test_cond_no_else():
assert isinstance(comp, Var)
assert (
str(comp)
== '((((_condition, _if_true, _if_false) => (_condition ? _if_true : _if_false))(true, (() => (jsx(RadixThemesText, ({ ["as"] : "p" }), (jsx(Fragment, ({ }), "hello"))))), (() => (jsx(Fragment, ({ }))))))())'
== '(true ? (jsx(RadixThemesText, ({ ["as"] : "p" }), (jsx(Fragment, ({ }), "hello")))) : (jsx(Fragment, ({ }))))'
)
# Props do not support the use of cond without else
@ -139,8 +136,7 @@ def test_cond_computed_var():
state_name = format_state_name(CondStateComputed.get_full_name())
assert (
str(comp)
== f"((((_condition, _if_true, _if_false) => (_condition ? _if_true : _if_false))(true, (() => {state_name}.computed_int), (() => {state_name}.computed_str)))())"
str(comp) == f"(true ? {state_name}.computed_int : {state_name}.computed_str)"
)
assert comp._var_type == Union[int, str]

View File

@ -36,7 +36,7 @@ class MatchState(BaseState):
f'(() => {{ switch (JSON.stringify({MatchState.get_name()}.value)) {{case JSON.stringify(1): return ("first"); break;case JSON.stringify(2): case JSON.stringify(3): return '
'("second value"); break;case JSON.stringify([1, 2]): return ("third-value"); break;case JSON.stringify("random"): '
'return ("fourth_value"); break;case JSON.stringify(({ ["foo"] : "bar" })): return ("fifth value"); '
f'break;case JSON.stringify((((_lhs, _rhs) => (_lhs + _rhs))({MatchState.get_name()}.num, 1))): return ("sixth value"); break;case JSON.stringify(({MatchState.get_name()}.value+" - string")): '
f'break;case JSON.stringify(({MatchState.get_name()}.num + 1)): return ("sixth value"); break;case JSON.stringify(({MatchState.get_name()}.value+" - string")): '
f'return ({MatchState.get_name()}.string); break;case JSON.stringify({MatchState.get_name()}.string): return (({MatchState.get_name()}.value+" - string")); break;default: '
'return ("default value"); break;};})()',
),
@ -55,7 +55,7 @@ class MatchState(BaseState):
f'(() => {{ switch (JSON.stringify({MatchState.get_name()}.value)) {{case JSON.stringify(1): return ("first"); break;case JSON.stringify(2): case JSON.stringify(3): return '
'("second value"); break;case JSON.stringify([1, 2]): return ("third-value"); break;case JSON.stringify("random"): '
'return ("fourth_value"); break;case JSON.stringify(({ ["foo"] : "bar" })): return ("fifth value"); '
f'break;case JSON.stringify((((_lhs, _rhs) => (_lhs + _rhs))({MatchState.get_name()}.num, 1))): return ("sixth value"); break;case JSON.stringify(({MatchState.get_name()}.value+" - string")): '
f'break;case JSON.stringify(({MatchState.get_name()}.num + 1)): return ("sixth value"); break;case JSON.stringify(({MatchState.get_name()}.value+" - string")): '
f'return ({MatchState.get_name()}.string); break;case JSON.stringify({MatchState.get_name()}.string): return (({MatchState.get_name()}.value+" - string")); break;default: '
f"return ({MatchState.get_name()}.string); break;}};}})()",
),

View File

@ -148,7 +148,7 @@ def test_create_map_fn_var_subclass(cls, fn_body, fn_args, explicit_return, expe
(
"code",
{},
'(({node, inline, className, children, ...props}) => { const match = (className || \'\').match(/language-(?<lang>.*)/); const _language = match ? match[1] : \'\'; if (_language) { (async () => { try { const module = await import(`react-syntax-highlighter/dist/cjs/languages/prism/${_language}`); SyntaxHighlighter.registerLanguage(_language, module.default); } catch (error) { console.error(`Error importing language module for ${_language}:`, error); } })(); } ; return inline ? ( <RadixThemesCode {...props}>{children}</RadixThemesCode> ) : ( <SyntaxHighlighter children={(((_condition, _if_true, _if_false) => (_condition ? _if_true : _if_false))((Array.isArray(children)), (((...args) => (((_array, _sep = "") => Array.prototype.join.apply(_array,[_sep]))(children, ...args)))("\\n")), children))} css={({ ["marginTop"] : "1em", ["marginBottom"] : "1em" })} customStyle={({ ["marginTop"] : "1em", ["marginBottom"] : "1em" })} language={_language} style={((((_condition, _if_true, _if_false) => (_condition ? _if_true : _if_false))((((_lhs, _rhs) => (_lhs === _rhs))(resolvedColorMode, "light")), (() => oneLight), (() => oneDark)))())} wrapLongLines={true} {...props}/> ); })',
r"""(({node, inline, className, children, ...props}) => { const match = (className || '').match(/language-(?<lang>.*)/); const _language = match ? match[1] : ''; if (_language) { (async () => { try { const module = await import(`react-syntax-highlighter/dist/cjs/languages/prism/${_language}`); SyntaxHighlighter.registerLanguage(_language, module.default); } catch (error) { console.error(`Error importing language module for ${_language}:`, error); } })(); } ; return inline ? ( <RadixThemesCode {...props}>{children}</RadixThemesCode> ) : ( <SyntaxHighlighter children={((Array.isArray(children)) ? (((...args) => (((_array, _sep = "") => Array.prototype.join.apply(_array,[_sep]))(children, ...args)))("\n")) : children)} css={({ ["marginTop"] : "1em", ["marginBottom"] : "1em" })} customStyle={({ ["marginTop"] : "1em", ["marginBottom"] : "1em" })} language={_language} style={((resolvedColorMode === "light") ? oneLight : oneDark)} wrapLongLines={true} {...props}/> ); })"""
),
(
"code",
@ -157,7 +157,7 @@ def test_create_map_fn_var_subclass(cls, fn_body, fn_args, explicit_return, expe
value, **props
)
},
'(({node, inline, className, children, ...props}) => { const match = (className || \'\').match(/language-(?<lang>.*)/); const _language = match ? match[1] : \'\'; ; return inline ? ( <RadixThemesCode {...props}>{children}</RadixThemesCode> ) : ( <RadixThemesBox css={({ ["pre"] : ({ ["margin"] : "0", ["padding"] : "24px", ["background"] : "transparent", ["overflow-x"] : "auto", ["border-radius"] : "6px" }) })} {...props}><ShikiCode code={(((_condition, _if_true, _if_false) => (_condition ? _if_true : _if_false))((Array.isArray(children)), (((...args) => (((_array, _sep = "") => Array.prototype.join.apply(_array,[_sep]))(children, ...args)))("\\n")), children))} decorations={[]} language={_language} theme={((((_condition, _if_true, _if_false) => (_condition ? _if_true : _if_false))((((_lhs, _rhs) => (_lhs === _rhs))(resolvedColorMode, "light")), (() => "one-light"), (() => "one-dark-pro")))())} transformers={[]}/></RadixThemesBox> ); })',
r"""(({node, inline, className, children, ...props}) => { const match = (className || '').match(/language-(?<lang>.*)/); const _language = match ? match[1] : ''; ; return inline ? ( <RadixThemesCode {...props}>{children}</RadixThemesCode> ) : ( <RadixThemesBox css={({ ["pre"] : ({ ["margin"] : "0", ["padding"] : "24px", ["background"] : "transparent", ["overflow-x"] : "auto", ["border-radius"] : "6px" }) })} {...props}><ShikiCode code={((Array.isArray(children)) ? (((...args) => (((_array, _sep = "") => Array.prototype.join.apply(_array,[_sep]))(children, ...args)))("\n")) : children)} decorations={[]} language={_language} theme={((resolvedColorMode === "light") ? "one-light" : "one-dark-pro")} transformers={[]}/></RadixThemesBox> ); })"""
),
(
"h1",
@ -171,7 +171,7 @@ def test_create_map_fn_var_subclass(cls, fn_body, fn_args, explicit_return, expe
(
"code",
{"codeblock": syntax_highlighter_memoized_component(CodeBlock)},
"(({node, inline, className, children, ...props}) => { const match = (className || '').match(/language-(?<lang>.*)/); const _language = match ? match[1] : ''; if (_language) { (async () => { try { const module = await import(`react-syntax-highlighter/dist/cjs/languages/prism/${_language}`); SyntaxHighlighter.registerLanguage(_language, module.default); } catch (error) { console.error(`Error importing language module for ${_language}:`, error); } })(); } ; return inline ? ( <RadixThemesCode {...props}>{children}</RadixThemesCode> ) : ( <CodeBlock code={(((_condition, _if_true, _if_false) => (_condition ? _if_true : _if_false))((Array.isArray(children)), (((...args) => (((_array, _sep = \"\") => Array.prototype.join.apply(_array,[_sep]))(children, ...args)))(\"\\n\")), children))} language={_language} {...props}/> ); })",
r"""(({node, inline, className, children, ...props}) => { const match = (className || '').match(/language-(?<lang>.*)/); const _language = match ? match[1] : ''; if (_language) { (async () => { try { const module = await import(`react-syntax-highlighter/dist/cjs/languages/prism/${_language}`); SyntaxHighlighter.registerLanguage(_language, module.default); } catch (error) { console.error(`Error importing language module for ${_language}:`, error); } })(); } ; return inline ? ( <RadixThemesCode {...props}>{children}</RadixThemesCode> ) : ( <CodeBlock code={((Array.isArray(children)) ? (((...args) => (((_array, _sep = "") => Array.prototype.join.apply(_array,[_sep]))(children, ...args)))("\n")) : children)} language={_language} {...props}/> ); })""",
),
(
"code",
@ -180,7 +180,7 @@ def test_create_map_fn_var_subclass(cls, fn_body, fn_args, explicit_return, expe
ShikiHighLevelCodeBlock
)
},
"""(({node, inline, className, children, ...props}) => { const match = (className || '').match(/language-(?<lang>.*)/); const _language = match ? match[1] : ''; ; return inline ? ( <RadixThemesCode {...props}>{children}</RadixThemesCode> ) : ( <CodeBlock code={(((_condition, _if_true, _if_false) => (_condition ? _if_true : _if_false))((Array.isArray(children)), (((...args) => (((_array, _sep = "") => Array.prototype.join.apply(_array,[_sep]))(children, ...args)))("\\n")), children))} language={_language} {...props}/> ); })""",
r"""(({node, inline, className, children, ...props}) => { const match = (className || '').match(/language-(?<lang>.*)/); const _language = match ? match[1] : ''; ; return inline ? ( <RadixThemesCode {...props}>{children}</RadixThemesCode> ) : ( <CodeBlock code={((Array.isArray(children)) ? (((...args) => (((_array, _sep = "") => Array.prototype.join.apply(_array,[_sep]))(children, ...args)))("\n")) : children)} language={_language} {...props}/> ); })""",
),
],
)

View File

@ -310,53 +310,21 @@ def test_basic_operations(TestObj):
Args:
TestObj: The test object.
"""
assert str(v(1) == v(2)) == "(((_lhs, _rhs) => (_lhs === _rhs))(1, 2))"
assert str(v(1) != v(2)) == "(((_lhs, _rhs) => (_lhs !== _rhs))(1, 2))"
assert (
str(LiteralNumberVar.create(1) < 2) == "(((_lhs, _rhs) => (_lhs < _rhs))(1, 2))"
)
assert (
str(LiteralNumberVar.create(1) <= 2)
== "(((_lhs, _rhs) => (_lhs <= _rhs))(1, 2))"
)
assert (
str(LiteralNumberVar.create(1) > 2) == "(((_lhs, _rhs) => (_lhs > _rhs))(1, 2))"
)
assert (
str(LiteralNumberVar.create(1) >= 2)
== "(((_lhs, _rhs) => (_lhs >= _rhs))(1, 2))"
)
assert (
str(LiteralNumberVar.create(1) + 2) == "(((_lhs, _rhs) => (_lhs + _rhs))(1, 2))"
)
assert (
str(LiteralNumberVar.create(1) - 2) == "(((_lhs, _rhs) => (_lhs - _rhs))(1, 2))"
)
assert (
str(LiteralNumberVar.create(1) * 2) == "(((_lhs, _rhs) => (_lhs * _rhs))(1, 2))"
)
assert (
str(LiteralNumberVar.create(1) / 2) == "(((_lhs, _rhs) => (_lhs / _rhs))(1, 2))"
)
assert (
str(LiteralNumberVar.create(1) // 2)
== "(((_lhs, _rhs) => Math.floor(_lhs / _rhs))(1, 2))"
)
assert (
str(LiteralNumberVar.create(1) % 2) == "(((_lhs, _rhs) => (_lhs % _rhs))(1, 2))"
)
assert (
str(LiteralNumberVar.create(1) ** 2)
== "(((_lhs, _rhs) => (_lhs ** _rhs))(1, 2))"
)
assert (
str(LiteralNumberVar.create(1) & v(2))
== "(((_a, _b) => (_a() && _b()))((() => 1), (() => 2)))"
)
assert (
str(LiteralNumberVar.create(1) | v(2))
== "(((_a, _b) => (_a() || _b()))((() => 1), (() => 2)))"
)
assert str(v(1) == v(2)) == "(1 === 2)"
assert str(v(1) != v(2)) == "(1 !== 2)"
assert str(LiteralNumberVar.create(1) < 2) == "(1 < 2)"
assert str(LiteralNumberVar.create(1) <= 2) == "(1 <= 2)"
assert str(LiteralNumberVar.create(1) > 2) == "(1 > 2)"
assert str(LiteralNumberVar.create(1) >= 2) == "(1 >= 2)"
assert str(LiteralNumberVar.create(1) + 2) == "(1 + 2)"
assert str(LiteralNumberVar.create(1) - 2) == "(1 - 2)"
assert str(LiteralNumberVar.create(1) * 2) == "(1 * 2)"
assert str(LiteralNumberVar.create(1) / 2) == "(1 / 2)"
assert str(LiteralNumberVar.create(1) // 2) == "Math.floor(1 / 2)"
assert str(LiteralNumberVar.create(1) % 2) == "(1 % 2)"
assert str(LiteralNumberVar.create(1) ** 2) == "(1 ** 2)"
assert str(LiteralNumberVar.create(1) & v(2)) == "(1 && 2)"
assert str(LiteralNumberVar.create(1) | v(2)) == "(1 || 2)"
assert (
str(LiteralArrayVar.create([1, 2, 3])[0])
== "(((...args) => (((_array, _index_or_slice) => atSliceOrIndex(_array, _index_or_slice))([1, 2, 3], ...args)))(0))"
@ -365,16 +333,10 @@ def test_basic_operations(TestObj):
str(LiteralObjectVar.create({"a": 1, "b": 2})["a"])
== '({ ["a"] : 1, ["b"] : 2 })["a"]'
)
assert str(v("foo") == v("bar")) == '("foo" === "bar")'
assert str(Var(_js_expr="foo") == Var(_js_expr="bar")) == "(foo === bar)"
assert (
str(v("foo") == v("bar")) == '(((_lhs, _rhs) => (_lhs === _rhs))("foo", "bar"))'
)
assert (
str(Var(_js_expr="foo") == Var(_js_expr="bar"))
== "(((_lhs, _rhs) => (_lhs === _rhs))(foo, bar))"
)
assert (
str(LiteralVar.create("foo") == LiteralVar.create("bar"))
== '(((_lhs, _rhs) => (_lhs === _rhs))("foo", "bar"))'
str(LiteralVar.create("foo") == LiteralVar.create("bar")) == '("foo" === "bar")'
)
print(Var(_js_expr="foo").to(ObjectVar, TestObj)._var_set_state("state"))
assert (
@ -382,7 +344,7 @@ def test_basic_operations(TestObj):
Var(_js_expr="foo").to(ObjectVar, TestObj)._var_set_state("state").bar
== LiteralVar.create("bar")
)
== '(((_lhs, _rhs) => (_lhs === _rhs))(state.foo["bar"], "bar"))'
== '(state.foo["bar"] === "bar")'
)
assert (
str(Var(_js_expr="foo").to(ObjectVar, TestObj)._var_set_state("state").bar)
@ -543,32 +505,17 @@ def test_str_contains(var, expected):
],
)
def test_dict_contains(var, expected):
assert (
str(var.contains(1))
== f"(((_object, _key) => _object.hasOwnProperty(_key))({expected!s}, 1))"
)
assert (
str(var.contains("1"))
== f'(((_object, _key) => _object.hasOwnProperty(_key))({expected!s}, "1"))'
)
assert (
str(var.contains(v(1)))
== f"(((_object, _key) => _object.hasOwnProperty(_key))({expected!s}, 1))"
)
assert (
str(var.contains(v("1")))
== f'(((_object, _key) => _object.hasOwnProperty(_key))({expected!s}, "1"))'
)
assert str(var.contains(1)) == f"{expected!s}.hasOwnProperty(1)"
assert str(var.contains("1")) == f'{expected!s}.hasOwnProperty("1")'
assert str(var.contains(v(1))) == f"{expected!s}.hasOwnProperty(1)"
assert str(var.contains(v("1"))) == f'{expected!s}.hasOwnProperty("1")'
other_state_var = Var(_js_expr="other")._var_set_state("state").to(str)
other_var = Var(_js_expr="other").to(str)
assert (
str(var.contains(other_state_var))
== f"(((_object, _key) => _object.hasOwnProperty(_key))({expected!s}, state.other))"
)
assert (
str(var.contains(other_var))
== f"(((_object, _key) => _object.hasOwnProperty(_key))({expected!s}, other))"
== f"{expected!s}.hasOwnProperty(state.other)"
)
assert str(var.contains(other_var)) == f"{expected!s}.hasOwnProperty(other)"
@pytest.mark.parametrize(
@ -1108,8 +1055,8 @@ def test_var_operation():
def add(a: Var[int], b: Var[int]):
return var_operation_return(js_expression=f"({a} + {b})", var_type=int)
assert str(add(1, 2)) == "(((_a, _b) => (_a + _b))(1, 2))"
assert str(add(4, -9)) == "(((_a, _b) => (_a + _b))(4, -9))"
assert str(add(1, 2)) == "(1 + 2)"
assert str(add(4, -9)) == "(4 + -9)"
five = LiteralNumberVar.create(5)
seven = add(2, five)
@ -1153,7 +1100,7 @@ def test_all_number_operations():
assert (
str(complicated_number)
== "(((_lhs, _rhs) => (_lhs ** _rhs))((((_lhs, _rhs) => (_lhs % _rhs))((((_lhs, _rhs) => Math.floor(_lhs / _rhs))((((_lhs, _rhs) => (_lhs / _rhs))((((_lhs, _rhs) => (_lhs * _rhs))((((_value) => -(_value))((((_lhs, _rhs) => (_lhs + _rhs))(-5.4, 1)))), 2)), 3)), 2)), 3)), 2))"
== "((Math.floor(((-((-5.4 + 1)) * 2) / 3) / 2) % 3) ** 2)"
)
even_more_complicated_number = ~(
@ -1162,20 +1109,14 @@ def test_all_number_operations():
assert (
str(even_more_complicated_number)
== "(((_value) => !(_value))((isTrue((((_a, _b) => (_a() || _b()))((() => (Math.abs((Math.floor((((_lhs, _rhs) => (_lhs ** _rhs))((((_lhs, _rhs) => (_lhs % _rhs))((((_lhs, _rhs) => Math.floor(_lhs / _rhs))((((_lhs, _rhs) => (_lhs / _rhs))((((_lhs, _rhs) => (_lhs * _rhs))((((_value) => -(_value))((((_lhs, _rhs) => (_lhs + _rhs))(-5.4, 1)))), 2)), 3)), 2)), 3)), 2))))))), (() => (((_a, _b) => (_a() && _b()))((() => 2), (() => (((_value) => Math.round(_value))((((_lhs, _rhs) => (_lhs ** _rhs))((((_lhs, _rhs) => (_lhs % _rhs))((((_lhs, _rhs) => Math.floor(_lhs / _rhs))((((_lhs, _rhs) => (_lhs / _rhs))((((_lhs, _rhs) => (_lhs * _rhs))((((_value) => -(_value))((((_lhs, _rhs) => (_lhs + _rhs))(-5.4, 1)))), 2)), 3)), 2)), 3)), 2))))))))))))))"
== "!((isTrue(((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)))))))"
)
assert (
str(LiteralNumberVar.create(5) > False)
== "(((_lhs, _rhs) => (_lhs > _rhs))(5, 0))"
)
assert (
str(LiteralBooleanVar.create(False) < 5)
== "(((_lhs, _rhs) => (_lhs < _rhs))((Number(false)), 5))"
)
assert str(LiteralNumberVar.create(5) > False) == "(5 > 0)"
assert str(LiteralBooleanVar.create(False) < 5) == "((Number(false)) < 5)"
assert (
str(LiteralBooleanVar.create(False) < LiteralBooleanVar.create(True))
== "(((_lhs, _rhs) => (_lhs < _rhs))((Number(false)), (Number(true))))"
== "((Number(false)) < (Number(true)))"
)
@ -1218,7 +1159,7 @@ def test_index_operation():
)
assert (
str(array_var[0].to(NumberVar) + 9)
== "(((_lhs, _rhs) => (_lhs + _rhs))((((...args) => (((_array, _index_or_slice) => atSliceOrIndex(_array, _index_or_slice))([1, 2, 3, 4, 5], ...args)))(0)), 9))"
== "((((...args) => (((_array, _index_or_slice) => atSliceOrIndex(_array, _index_or_slice))([1, 2, 3, 4, 5], ...args)))(0)) + 9)"
)
@ -1261,14 +1202,8 @@ def test_array_operations():
str(ArrayVar.range(1, 10))
== "(((_e1, _e2 = null, _step = 1) => [...range(_e1, _e2, _step)])(1, 10))"
)
assert (
str(ArrayVar.range(1, 10, 2))
== "(((_e1, _e2 = null, _step = 1) => [...range(_e1, _e2, _step)])(1, 10, 2))"
)
assert (
str(ArrayVar.range(1, 10, -1))
== "(((_e1, _e2 = null, _step = 1) => [...range(_e1, _e2, _step)])(1, 10, -1))"
)
assert str(ArrayVar.range(1, 10, 2)) == "[...range(1, 10, 2)]"
assert str(ArrayVar.range(1, 10, -1)) == "[...range(1, 10, -1)]"
def test_object_operations():
@ -1289,7 +1224,7 @@ def test_object_operations():
assert str(object_var["a"]) == '({ ["a"] : 1, ["b"] : 2, ["c"] : 3 })["a"]'
assert (
str(object_var.merge(LiteralObjectVar.create({"c": 4, "d": 5})))
== '(((_lhs, _rhs) => ({..._lhs, ..._rhs}))(({ ["a"] : 1, ["b"] : 2, ["c"] : 3 }), ({ ["c"] : 4, ["d"] : 5 })))'
== '({...({ ["a"] : 1, ["b"] : 2, ["c"] : 3 }), ...({ ["c"] : 4, ["d"] : 5 })})'
)
@ -1329,11 +1264,11 @@ def test_type_chains():
)
assert (
str(object_var.entries()[1][1] - 1) # type: ignore
== '(((_lhs, _rhs) => (_lhs - _rhs))((((...args) => (((_array, _index_or_slice) => atSliceOrIndex(_array, _index_or_slice))((((...args) => (((_array, _index_or_slice) => atSliceOrIndex(_array, _index_or_slice))((Object.entries(({ ["a"] : 1, ["b"] : 2, ["c"] : 3 }))), ...args)))(1)), ...args)))(1)), 1))'
== '((((...args) => (((_array, _index_or_slice) => atSliceOrIndex(_array, _index_or_slice))((((...args) => (((_array, _index_or_slice) => atSliceOrIndex(_array, _index_or_slice))((Object.entries(({ ["a"] : 1, ["b"] : 2, ["c"] : 3 }))), ...args)))(1)), ...args)))(1)) - 1)'
)
assert (
str(object_var["c"] + object_var["b"]) # type: ignore
== '(((_lhs, _rhs) => (_lhs + _rhs))(({ ["a"] : 1, ["b"] : 2, ["c"] : 3 })["c"], ({ ["a"] : 1, ["b"] : 2, ["c"] : 3 })["b"]))'
== '(({ ["a"] : 1, ["b"] : 2, ["c"] : 3 })["c"] + ({ ["a"] : 1, ["b"] : 2, ["c"] : 3 })["b"])'
)