diff --git a/docs/tutorials/conditional_example.wic b/docs/tutorials/conditional_example.wic new file mode 100644 index 00000000..95f9f5e8 --- /dev/null +++ b/docs/tutorials/conditional_example.wic @@ -0,0 +1,10 @@ +steps: + toString: + in: + input: !ii 27 + out: + - output: !& string_int + echo: + when: '$(inputs.message < "27")' + in: + message: !* string_int \ No newline at end of file diff --git a/examples/scripts/when_pyapi.py b/examples/scripts/when_pyapi.py new file mode 100644 index 00000000..55aee45e --- /dev/null +++ b/examples/scripts/when_pyapi.py @@ -0,0 +1,31 @@ +from wic.api.pythonapi import Step, Workflow + + +def workflow() -> Workflow: + # conditional on input + # step toString + toString = Step(clt_path='../../cwl_adapters/toString.cwl') + toString.input = 27 + # step echo + echo = Step(clt_path='../../cwl_adapters/echo.cwl') + echo.message = toString.output + # add a when clause + # alternate js syntax + # echo.when = '$(inputs["message"] < 27)' + echo.when = '$(inputs.message < 27)' + # since the condition is not met the echo step is skipped! + + # arrange steps + steps = [toString, echo] + + # create workflow + filename = 'when_pyapi_py' # .yml + wkflw = Workflow(steps, filename) + return wkflw + + +# Do NOT .run() here + +if __name__ == '__main__': + when_wic = workflow() + when_wic.run() # .run() here inside main diff --git a/src/wic/api/pythonapi.py b/src/wic/api/pythonapi.py index fd396455..ac2c667c 100644 --- a/src/wic/api/pythonapi.py +++ b/src/wic/api/pythonapi.py @@ -260,6 +260,8 @@ class Step(BaseModel): # pylint: disable=too-few-public-methods # these are not part of 'clt data' scatter: list[ProcessInput] = [] scatterMethod: str = '' + # use when tag to enable conditional steps + when: str = '' _input_names: list[str] = PrivateAttr(default_factory=list) _output_names: list[str] = PrivateAttr(default_factory=list) @@ -367,6 +369,11 @@ def __setattr__(self, __name: str, __value: Any) -> Any: if not all([isinstance(x, ProcessInput) for x in __value]): raise TypeError("all scatter inputs must be ProcessInput type") return super().__setattr__(__name, __value) + if __name == "when": + if (isinstance(__value, str)) and __value.startswith('$(') and __value.endswith(')'): + return super().__setattr__(__name, __value) + else: + raise ValueError("Invalid input to when.The js string must start with '$(' and end with ')'") if hasattr(self, "_input_names") and __name in self._input_names: set_input_Step_Workflow(self, __name, __value) @@ -443,6 +450,9 @@ def _yml(self) -> dict: if '' == self.scatterMethod: self.scatterMethod = ScatterMethod.dotproduct.value d["scatterMethod"] = self.scatterMethod + # when operates on step + if self.when != '': + d["when"] = self.when return d def _save_cwl(self, path: Path) -> None: