def test_task_failure_caches_inputs_automatically(client): @prefect.task(max_retries=2, retry_delay=timedelta(seconds=100)) def is_p_three(p): if p == 3: raise ValueError("No thank you.") with prefect.Flow("test") as f: p = prefect.Parameter("p") res = is_p_three(p) state = CloudFlowRunner(flow=f).run(return_tasks=[res], parameters=dict(p=3)) assert state.is_running() assert isinstance(state.result[res], Retrying) exp_res = Result(3, result_handler=JSONResultHandler()) assert not state.result[res].cached_inputs["p"] == exp_res exp_res.store_safe_value() assert state.result[res].cached_inputs["p"] == exp_res last_state = client.set_task_run_state.call_args_list[-1][-1]["state"] assert isinstance(last_state, Retrying) assert last_state.cached_inputs["p"] == exp_res
def test_task_failure_with_upstream_secrets_doesnt_store_secret_value_and_recompute_if_necessary( client, ): @prefect.task(max_retries=2, retry_delay=timedelta(seconds=100)) def is_p_three(p): if p == 3: raise ValueError("No thank you.") return p with prefect.Flow("test", result_handler=JSONResultHandler()) as f: p = prefect.tasks.secrets.Secret("p") res = is_p_three(p) with prefect.context(secrets=dict(p=3)): state = CloudFlowRunner(flow=f).run(return_tasks=[res]) assert state.is_running() assert isinstance(state.result[res], Retrying) exp_res = Result(3, result_handler=SecretResultHandler(p)) assert not state.result[res].cached_inputs["p"] == exp_res exp_res.store_safe_value() assert state.result[res].cached_inputs["p"] == exp_res ## here we set the result of the secret to a saferesult, ensuring ## it will get converted to a "true" result; ## we expect that the upstream value will actually get recomputed from context ## through the SecretResultHandler safe = SafeResult("p", result_handler=SecretResultHandler(p)) state.result[p] = Success(result=safe) state.result[res].start_time = pendulum.now("utc") state.result[res].cached_inputs = dict(p=safe) with prefect.context(secrets=dict(p=4)): new_state = CloudFlowRunner(flow=f).run(return_tasks=[res], task_states=state.result) assert new_state.is_successful() assert new_state.result[res].result == 4
def test_results_are_pickleable_with_their_safe_values(): res = Result(3, result_handler=JSONResultHandler()) res.store_safe_value() assert cloudpickle.loads(cloudpickle.dumps(res)) == res
def test_error_when_storing_with_no_handler(self): r = Result(value=42) with pytest.raises(AssertionError): r.store_safe_value()
def test_results_are_same_if_handled(self): r = Result("3", result_handler=JSONResultHandler()) s = Result("3", result_handler=JSONResultHandler()) r.store_safe_value() s.store_safe_value() assert s == r
def test_results_are_different_if_handled(self): r = Result("3", result_handler=JSONResultHandler()) s = Result("3", result_handler=JSONResultHandler()) s.store_safe_value() assert s != r
def test_storing_happens_once(self): r = Result(value=4, result_handler=JSONResultHandler()) safe_value = SafeResult(value="123", result_handler=JSONResultHandler()) r.safe_value = safe_value r.store_safe_value() assert r.safe_value is safe_value