Ver código fonte

fix and and or

Khaleel Al-Adhami 4 meses atrás
pai
commit
076cfea6ae
3 arquivos alterados com 72 adições e 26 exclusões
  1. 8 2
      reflex/utils/types.py
  2. 62 24
      reflex/vars/base.py
  3. 2 0
      reflex/vars/function.py

+ 8 - 2
reflex/utils/types.py

@@ -860,6 +860,10 @@ def infallible_issubclass(cls: Any, class_or_tuple: Any, /) -> bool:
     Returns:
         Whether the class is a subclass of the other class or tuple of classes.
     """
+    if cls is class_or_tuple or (
+        isinstance(class_or_tuple, tuple) and cls in class_or_tuple
+    ):
+        return True
     try:
         return issubclass(cls, class_or_tuple)
     except TypeError:
@@ -876,6 +880,8 @@ def typehint_issubclass(possible_subclass: Any, possible_superclass: Any) -> boo
     Returns:
         Whether the type hint is a subclass of the other type hint.
     """
+    if possible_subclass is possible_superclass:
+        return True
     if possible_superclass is Any:
         return True
     if possible_subclass is Any:
@@ -956,7 +962,7 @@ def typehint_issubclass(possible_subclass: Any, possible_superclass: Any) -> boo
         return True
 
     # Check if the origin of both types is the same (e.g., list for List[int])
-    if not safe_issubclass(
+    if not infallible_issubclass(
         provided_type_origin or possible_subclass,
         accepted_type_origin or possible_superclass,
     ):
@@ -968,5 +974,5 @@ def typehint_issubclass(possible_subclass: Any, possible_superclass: Any) -> boo
     return all(
         typehint_issubclass(provided_arg, accepted_arg)
         for provided_arg, accepted_arg in zip(provided_args, accepted_args)
-        if accepted_arg is not Any
+        if accepted_arg is not Any and not isinstance(accepted_arg, TypeVar)
     )

+ 62 - 24
reflex/vars/base.py

@@ -3261,11 +3261,46 @@ def and_operation(a: Var | Any, b: Var | Any) -> Var:
     Returns:
         The result of the logical AND operation.
     """
-    return _and_operation(a, b)  # type: ignore
+    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]),
+    )
+
+
+def or_operation(a: Var | Any, b: Var | Any) -> Var:
+    """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.
+    """
+    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_operation(a: Var, b: Var):
+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:
@@ -3278,38 +3313,34 @@ def _and_operation(a: Var, b: Var):
 
     def type_computer(*args: Var):
         if not args:
-            return (ReflexCallable[[Any, Any], Any], type_computer)
+            return (
+                ReflexCallable[[ReflexCallable[[], Any], ReflexCallable[[], Any]], Any],
+                type_computer,
+            )
         if len(args) == 1:
             return (
-                ReflexCallable[[Any], Any],
+                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(args[0]._var_type, args[1]._var_type)],
+            ReflexCallable[[], unionize(a_return_type, b_return_type)],
             None,
         )
 
     return var_operation_return(
-        js_expression=f"({a} && {b})",
+        js_expression=f"({a}() && {b}())",
         type_computer=type_computer,
     )
 
 
-def or_operation(a: Var | Any, b: Var | Any) -> Var:
-    """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.
-    """
-    return _or_operation(a, b)  # type: ignore
-
-
 @var_operation
-def _or_operation(a: Var, b: Var):
+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:
@@ -3322,19 +3353,26 @@ def _or_operation(a: Var, b: Var):
 
     def type_computer(*args: Var):
         if not args:
-            return (ReflexCallable[[Any, Any], Any], type_computer)
+            return (
+                ReflexCallable[[ReflexCallable[[], Any], ReflexCallable[[], Any]], Any],
+                type_computer,
+            )
         if len(args) == 1:
             return (
-                ReflexCallable[[Any], Any],
+                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(args[0]._var_type, args[1]._var_type)],
+            ReflexCallable[[], unionize(a_return_type, b_return_type)],
             None,
         )
 
     return var_operation_return(
-        js_expression=f"({a} || {b})",
+        js_expression=f"({a}() || {b}())",
         type_computer=type_computer,
     )
 

+ 2 - 0
reflex/vars/function.py

@@ -751,6 +751,7 @@ class ArgsFunctionOperation(CachedVarOperation, FunctionVar[CALLABLE_TYPE]):
         Returns:
             The function var.
         """
+        return_expr = Var.create(return_expr)
         return cls(
             _js_expr="",
             _var_type=_var_type,
@@ -829,6 +830,7 @@ class ArgsFunctionOperationBuilder(
         Returns:
             The function var.
         """
+        return_expr = Var.create(return_expr)
         return cls(
             _js_expr="",
             _var_type=_var_type,