Repository: PrefectHQ/prefect

Issue:
ifelse checks for True/False rather than truthy/falsy values
## Description
`prefect.tasks.control_flow.conditional.ifelse` should check for truthy/falsy values, but (relying on `switch`) checks for exact equality to `True` or `False`.

## Expected Behavior
[From the docs](https://docs.prefect.io/core/task_library/control_flow.html#if-else):

> If the condition evaluates True(ish), the true_task will run. If it evaluates False(ish), the false_task will run.

`ifelse` should run the `true_branch` for any value that evaluates to `True`: non-empty strings, dicts and lists, ints not equal to 0...

## Reproduction
```python
from prefect import Flow, task
from prefect.tasks.control_flow.conditional import ifelse, merge

@task
def run_if_truthy():
	return 'a'

@task
def run_if_falsy():
	return 'b'

@task
def return_truthy_value():
	# non-empty strings are truthy
	assert('c')
	return 'c'

with Flow('test-flow') as flow:
	branch_truthy = run_if_truthy()
	branch_falsy = run_if_falsy()
	ifelse(return_truthy_value(), branch_truthy, branch_falsy)
	merged_result = merge(branch_truthy, branch_falsy)

result = flow.run()
assert(not result.result.get(merged_result).is_skipped())
assert(result.result.get(merged_result)._result.value == 'a')
```
Output:
```
[2020-02-03 16:38:57,428] INFO - prefect.FlowRunner | Beginning Flow run for 'test-flow'
[2020-02-03 16:38:57,431] INFO - prefect.FlowRunner | Starting flow run.
[2020-02-03 16:38:57,441] INFO - prefect.TaskRunner | Task 'return_truthy_value': Starting task run...
[2020-02-03 16:38:57,445] INFO - prefect.TaskRunner | Task 'return_truthy_value': finished task run for task with final state: 'Success'
[2020-02-03 16:38:57,455] INFO - prefect.TaskRunner | Task 'CompareValue: "True"': Starting task run...
[2020-02-03 16:38:57,460] INFO - prefect.TaskRunner | Task 'CompareValue: "True"': finished task run for task with final state: 'Skipped'
[2020-02-03 16:38:57,470] INFO - prefect.TaskRunner | Task 'run_if_truthy': Starting task run...
[2020-02-03 16:38:57,474] INFO - prefect.TaskRunner | Task 'run_if_truthy': finished task run for task with final state: 'Skipped'
[2020-02-03 16:38:57,483] INFO - prefect.TaskRunner | Task 'CompareValue: "False"': Starting task run...
[2020-02-03 16:38:57,488] INFO - prefect.TaskRunner | Task 'CompareValue: "False"': finished task run for task with final state: 'Skipped'
[2020-02-03 16:38:57,497] INFO - prefect.TaskRunner | Task 'run_if_falsy': Starting task run...
[2020-02-03 16:38:57,501] INFO - prefect.TaskRunner | Task 'run_if_falsy': finished task run for task with final state: 'Skipped'
[2020-02-03 16:38:57,510] INFO - prefect.TaskRunner | Task 'Merge': Starting task run...
[2020-02-03 16:38:57,514] INFO - prefect.TaskRunner | Task 'Merge': finished task run for task with final state: 'Skipped'
[2020-02-03 16:38:57,516] INFO - prefect.FlowRunner | Flow run SUCCESS: all reference tasks succeeded
Traceback (most recent call last):
  File "/tmp/test-flow.py", line 25, in <module>
    assert(not result.result.get(merged_result).is_skipped())
AssertionError
```

## Environment
Prefect 0.9.2, Python 3.6, on Linux x64.



Discussion:

Resolving patch:
diff --git a/src/prefect/tasks/control_flow/conditional.py b/src/prefect/tasks/control_flow/conditional.py
--- a/src/prefect/tasks/control_flow/conditional.py
+++ b/src/prefect/tasks/control_flow/conditional.py
@@ -110,7 +110,11 @@ def ifelse(condition: Task, true_task: Task, false_task: Task) -> None:
         - false_task (Task): a task that will be executed if the condition is False
     """
 
-    switch(condition=condition, cases={True: true_task, False: false_task})
+    @prefect.task
+    def as_bool(x):
+        return bool(x)
+
+    switch(condition=as_bool(condition), cases={True: true_task, False: false_task})
 
 
 def merge(*tasks: Task) -> Task:


Test patch:
diff --git a/tests/tasks/test_control_flow.py b/tests/tasks/test_control_flow.py
--- a/tests/tasks/test_control_flow.py
+++ b/tests/tasks/test_control_flow.py
@@ -18,7 +18,7 @@ def run(self):
         return 1
 
 
-@pytest.mark.parametrize("condition_value", [True, False, "x"])
+@pytest.mark.parametrize("condition_value", [True, False])
 def test_ifelse(condition_value):
     condition = Condition()
     true_branch = SuccessTask(name="true branch")
@@ -26,7 +26,7 @@ def test_ifelse(condition_value):
 
     with Flow(name="test") as flow:
         cnd = ifelse(condition, true_branch, false_branch)
-        assert len(flow.tasks) == 5
+        assert len(flow.tasks) == 6
 
     with prefect.context(CONDITION=condition_value):
         state = flow.run()
@@ -39,6 +39,38 @@ def test_ifelse(condition_value):
     )
 
 
+@pytest.mark.parametrize("condition_value", [1, "a", "False", True, [1], {1: 2}])
+def test_ifelse_with_truthy_conditions(condition_value):
+    condition = Condition()
+    true_branch = SuccessTask(name="true branch")
+    false_branch = SuccessTask(name="false branch")
+
+    with Flow(name="test") as flow:
+        cnd = ifelse(condition, true_branch, false_branch)
+
+    with prefect.context(CONDITION=condition_value):
+        state = flow.run()
+
+    assert state.result[true_branch].is_successful()
+    assert state.result[false_branch].is_skipped()
+
+
+@pytest.mark.parametrize("condition_value", [0, "", None, False, [], {}])
+def test_ifelse_with_falsey_conditions(condition_value):
+    condition = Condition()
+    true_branch = SuccessTask(name="true branch")
+    false_branch = SuccessTask(name="false branch")
+
+    with Flow(name="test") as flow:
+        cnd = ifelse(condition, true_branch, false_branch)
+
+    with prefect.context(CONDITION=condition_value):
+        state = flow.run()
+
+    assert state.result[true_branch].is_skipped()
+    assert state.result[false_branch].is_successful()
+
+
 @pytest.mark.parametrize("condition_value", ["a", "b", "c", "d", "x"])
 def test_switch(condition_value):
     condition = Condition()
@@ -192,10 +224,6 @@ def false_branch():
         state = flow.run()
         assert state.result[merge_task].result == 0
 
-    with prefect.context(CONDITION=None):
-        state = flow.run()
-        assert state.result[merge_task].result is None
-
 
 def test_merge_can_distinguish_between_a_none_result_and_an_unrun_task():
     condition = Condition()