Skip to content

Commit

Permalink
feat: Optionally comparing fields in Var.contains, e.g. on rx.Base ba…
Browse files Browse the repository at this point in the history
…sed types. (#3375)

* feat: Optionally comparing fields, e.g. on rx.Base based types.

* feat: Minimally invasive change.
Leave the current implementation as is. Added test.

* fix: Supporting old-school python versions.

* fix: Adding masenf's suggestions to use var instead of string.
  • Loading branch information
abulvenz authored May 25, 2024
1 parent 51d3b2c commit 7c2056e
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 8 deletions.
25 changes: 17 additions & 8 deletions reflex/vars.py
Original file line number Diff line number Diff line change
Expand Up @@ -838,19 +838,19 @@ def get_operand_full_name(operand):
if invoke_fn:
# invoke the function on left operand.
operation_name = (
f"{left_operand_full_name}.{fn}({right_operand_full_name})" # type: ignore
)
f"{left_operand_full_name}.{fn}({right_operand_full_name})"
) # type: ignore
else:
# pass the operands as arguments to the function.
operation_name = (
f"{left_operand_full_name} {op} {right_operand_full_name}" # type: ignore
)
f"{left_operand_full_name} {op} {right_operand_full_name}"
) # type: ignore
operation_name = f"{fn}({operation_name})"
else:
# apply operator to operands (left operand <operator> right_operand)
operation_name = (
f"{left_operand_full_name} {op} {right_operand_full_name}" # type: ignore
)
f"{left_operand_full_name} {op} {right_operand_full_name}"
) # type: ignore
operation_name = format.wrap(operation_name, "(")
else:
# apply operator to left operand (<operator> left_operand)
Expand Down Expand Up @@ -1353,11 +1353,12 @@ def __contains__(self, _: Any) -> Var:
"'in' operator not supported for Var types, use Var.contains() instead."
)

def contains(self, other: Any) -> Var:
def contains(self, other: Any, field: Union[Var, None] = None) -> Var:
"""Check if a var contains the object `other`.
Args:
other: The object to check.
field: Optionally specify a field to check on both object and the other var.
Raises:
VarTypeError: If the var is not a valid type: dict, list, tuple or str.
Expand Down Expand Up @@ -1393,8 +1394,16 @@ def contains(self, other: Any) -> Var:
raise VarTypeError(
f"'in <string>' requires string as left operand, not {other._var_type}"
)

_var_name = None
if field is None:
_var_name = f"{self._var_name}.includes({other._var_full_name})"
else:
field = Var.create_safe(field, _var_is_string=isinstance(field, str))
_var_name = f"{self._var_name}.some(e=>e[{field._var_name_unwrapped}]==={other._var_full_name})"

return self._replace(
_var_name=f"{self._var_name}.includes({other._var_full_name})",
_var_name=_var_name,
_var_type=bool,
_var_is_string=False,
merge_var_data=other._var_data,
Expand Down
3 changes: 3 additions & 0 deletions tests/test_var.py
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,9 @@ def test_str_contains(var, expected):
other_var = BaseVar(_var_name="other", _var_type=str)
assert str(var.contains(other_state_var)) == f"{{{expected}.includes(state.other)}}"
assert str(var.contains(other_var)) == f"{{{expected}.includes(other)}}"
assert (
str(var.contains("1", "hello")) == f'{{{expected}.some(e=>e[`hello`]==="1")}}'
)


@pytest.mark.parametrize(
Expand Down

0 comments on commit 7c2056e

Please sign in to comment.