Repository: PrefectHQ/prefect

Issue:
Operator task behavior is unintuitive/misleading
The docstrings for the various logical `Operator` tasks suggest that they just call the corresponding Python operator. So I would expect `Or(x, y)` to return `x or y` instead of `bool(x or y)`: https://github.com/PrefectHQ/prefect/blob/07cb6c20342c4053a3eaaaf885670ae5dfd6e74d/src/prefect/tasks/core/operators.py#L233-L254.

If there's a specific reason why these have to return boolean results, then at least the docstrings should probably be updated to reflect that.


Discussion:
To be completely honest, the reason for this is that when I put these together I only consider the logical operator case and not the more general case. 

Upon giving this some though, I think it is *nice* to have operators with a constant return type (`bool`) but I immediately see the benefit of supporting the generic `or` - for example, for merging two branches together. I'd support relaxing the `bool` cast.

Resolving patch:
diff --git a/src/prefect/tasks/core/operators.py b/src/prefect/tasks/core/operators.py
--- a/src/prefect/tasks/core/operators.py
+++ b/src/prefect/tasks/core/operators.py
@@ -218,16 +218,16 @@ class And(Task):
     def __init__(self, *args: Any, **kwargs: Any):
         super().__init__(*args, **kwargs)
 
-    def run(self, x: Any, y: Any) -> bool:  # type: ignore
+    def run(self, x: Any, y: Any) -> Any:  # type: ignore
         """
         Args:
             - x (Any): a value
             - y (Any): a value
 
         Returns:
-            - bool
+            - Any
         """
-        return bool(x and y)
+        return x and y
 
 
 class Or(Task):
@@ -242,16 +242,16 @@ class Or(Task):
     def __init__(self, *args: Any, **kwargs: Any):
         super().__init__(*args, **kwargs)
 
-    def run(self, x: Any, y: Any) -> bool:  # type: ignore
+    def run(self, x: Any, y: Any) -> Any:  # type: ignore
         """
         Args:
             - x (Any): a value
             - y (Any): a value
 
         Returns:
-            - bool
+            - Any
         """
-        return bool(x or y)
+        return x or y
 
 
 class Not(Task):
@@ -274,7 +274,7 @@ def run(self, x: Any) -> bool:  # type: ignore
         Returns:
             - bool
         """
-        return bool(not (x))
+        return not x
 
 
 class Equal(Task):
@@ -289,16 +289,16 @@ class Equal(Task):
     def __init__(self, *args: Any, **kwargs: Any):
         super().__init__(*args, **kwargs)
 
-    def run(self, x: Any, y: Any) -> bool:  # type: ignore
+    def run(self, x: Any, y: Any) -> Any:  # type: ignore
         """
         Args:
             - x (Any): a value
             - y (Any): a value
 
         Returns:
-            - bool
+            - Any
         """
-        return bool(x == y)
+        return x == y
 
 
 class NotEqual(Task):
@@ -313,16 +313,16 @@ class NotEqual(Task):
     def __init__(self, *args: Any, **kwargs: Any):
         super().__init__(*args, **kwargs)
 
-    def run(self, x: Any, y: Any) -> bool:  # type: ignore
+    def run(self, x: Any, y: Any) -> Any:  # type: ignore
         """
         Args:
             - x (Any): a value
             - y (Any): a value
 
         Returns:
-            - bool
+            - Any
         """
-        return bool(x != y)
+        return x != y
 
 
 class GreaterThanOrEqual(Task):
@@ -337,16 +337,16 @@ class GreaterThanOrEqual(Task):
     def __init__(self, *args: Any, **kwargs: Any):
         super().__init__(*args, **kwargs)
 
-    def run(self, x: Any, y: Any) -> bool:  # type: ignore
+    def run(self, x: Any, y: Any) -> Any:  # type: ignore
         """
         Args:
             - x (Any): a value
             - y (Any): a value
 
         Returns:
-            - bool
+            - Any
         """
-        return bool(x >= y)
+        return x >= y
 
 
 class GreaterThan(Task):
@@ -361,16 +361,16 @@ class GreaterThan(Task):
     def __init__(self, *args: Any, **kwargs: Any):
         super().__init__(*args, **kwargs)
 
-    def run(self, x: Any, y: Any) -> bool:  # type: ignore
+    def run(self, x: Any, y: Any) -> Any:  # type: ignore
         """
         Args:
             - x (Any): a value
             - y (Any): a value
 
         Returns:
-            - bool
+            - Any
         """
-        return bool(x > y)
+        return x > y
 
 
 class LessThanOrEqual(Task):
@@ -385,16 +385,16 @@ class LessThanOrEqual(Task):
     def __init__(self, *args: Any, **kwargs: Any):
         super().__init__(*args, **kwargs)
 
-    def run(self, x: Any, y: Any) -> bool:  # type: ignore
+    def run(self, x: Any, y: Any) -> Any:  # type: ignore
         """
         Args:
             - x (Any): a value
             - y (Any): a value
 
         Returns:
-            - bool
+            - Any
         """
-        return bool(x <= y)
+        return x <= y
 
 
 class LessThan(Task):
@@ -409,13 +409,13 @@ class LessThan(Task):
     def __init__(self, *args: Any, **kwargs: Any):
         super().__init__(*args, **kwargs)
 
-    def run(self, x: Any, y: Any) -> bool:  # type: ignore
+    def run(self, x: Any, y: Any) -> Any:  # type: ignore
         """
         Args:
             - x (Any): a value
             - y (Any): a value
 
         Returns:
-            - bool
+            - Any
         """
-        return bool(x < y)
+        return x < y


Test patch: