def make_workflow( f: Callable, description: str, initial_input_form: Optional[InputStepFunc], target: Optional[Target], steps: StepList, ) -> Workflow: @functools.wraps(f) def wrapping_function() -> NoReturn: raise Exception("This function should not be executed") wrapping_function = cast(Workflow, wrapping_function) wrapping_function.name = f.__name__ # default, will be changed by LazyWorkflowInstance wrapping_function.description = description if initial_input_form is None: # We always need a form to prevent starting a workflow when no input is needed. # This would happen on first post that is used to retrieve the first form page initial_input_form = cast(InputStepFunc, const(FormPage)) wrapping_function.initial_input_form = _handle_simple_input_form_generator( initial_input_form) wrapping_function.target = target wrapping_function.steps = steps wrapping_function.__doc__ = make_workflow_doc(wrapping_function) return wrapping_function
def test_failing_inputstep_with_form_state_params() -> None: @inputstep("Modify") def modify(subscription_id: UUIDstr) -> NoReturn: raise Exception("Something went wrong") class Form(FormPage): subscription_id: UUID @workflow("Workflow", initial_input_form=const(Form)) def inject_args_test_workflow(): return init >> modify >> done with WorkflowInstanceForTests(inject_args_test_workflow, "inject_args_test_workflow"): init_state = {"subscription_id": uuid4()} result, process, step_log = run_workflow("inject_args_test_workflow", init_state) assert_suspended(result) step_log_copy = deepcopy(step_log) with pytest.raises(Exception) as e: resume_workflow(process, step_log, {}) assert "Something went wrong" in str(e.value) assert step_log_copy == step_log # No steps have been logged because of the error
def overall_status(self) -> ProcessStatus: """Show overall status of process or task. >>> Success({}).overall_status <ProcessStatus.RUNNING: 'running'> >>> Skipped({}).overall_status <ProcessStatus.RUNNING: 'running'> >>> Suspend({}).overall_status <ProcessStatus.SUSPENDED: 'suspended'> >>> Waiting({}).overall_status <ProcessStatus.WAITING: 'waiting'> >>> Abort({}).overall_status <ProcessStatus.ABORTED: 'aborted'> >>> Failed({}).overall_status <ProcessStatus.FAILED: 'failed'> >>> Complete({}).overall_status <ProcessStatus.COMPLETED: 'completed'> """ return self._fold( const(ProcessStatus.RUNNING), const(ProcessStatus.RUNNING), const(ProcessStatus.SUSPENDED), const(ProcessStatus.WAITING), const(ProcessStatus.ABORTED), const(ProcessStatus.FAILED), const(ProcessStatus.COMPLETED), )
def iscomplete(self) -> bool: """Test if this instance is Complete. >>> Success('a').iscomplete() False >>> Skipped('a').iscomplete() False >>> Suspend('a').iscomplete() False >>> Waiting('a').iscomplete() False >>> Abort('a').iscomplete() False >>> Failed('a').iscomplete() False >>> Complete('a').iscomplete() True """ return self._fold(const(False), const(False), const(False), const(False), const(False), const(False), const(True))
def test_state() -> None: @inject_args def step_func_ok(one): assert one == STATE["one"] return {"prefix_id": 42} new_state = step_func_ok(STATE) assert "prefix_id" in new_state assert new_state["prefix_id"] == 42 @inject_args def step_func_fail(i_am_not_in_the_state): return {} with pytest.raises(KeyError): step_func_fail(STATE) @inject_args def step_func_opt_arg(opt: Optional[str] = None) -> None: assert opt is None step_func_opt_arg(STATE) @inject_args def step_func_default(default="bla"): assert default == "bla" step_func_default(STATE) step_func_const = inject_args(const({})) step_func_const(STATE) @inject_args def step_func_state(state, one): assert state == STATE assert one == STATE["one"] step_func_state(STATE) @inject_args def step_func_empty(): pass step_func_state(STATE)