Description
Regular Python functions have two limitations:
- They are evaluated directly so they cannot be used to construct a workflow before triggering the evaluation.
- They do not provide any details about the output variable names. Still these output variable names are helpful for the user to reuse part of the output of one function as an input for another function.
To address this challenge, all the different workflow frameworks have implemented Python decorators. Requiring the user to apply a decorator on the function before using it in combination with one of the workflow frameworks. As the decorators of all the different workflow frameworks are rather similar, it would be one suggestion for extending the Python Workflow Definition to provide a generalized decorator:
Inside the Python Workflow Definition we would add a module called decorator.py
:
status_dict = {
"aiida": False,
"jobflow": False,
"pyiron_base": False,
}
def selector(aiida=False, jobflow=False, pyiron_base=False):
parameter_sum = sum([aiida, jobflow, pyiron_base])
if parameter_sum > 1:
raise ValueError()
elif parameter_sum == 0:
raise ValueError()
else:
status_dict["aiida"] = aiida
status_dict["jobflow"] = jobflow
status_dict["pyiron_base"] = pyiron_base
def decorator(funct):
if not any(status_dict.values()):
return funct
elif sum(status_dict.values()) > 1:
raise ValueError()
elif status_dict["aiida"]:
from aiida_workgraph import task
return task()(funct)
elif status_dict["jobflow"]:
from jobflow import job
return job(funct)
elif status_dict["pyiron_base"]:
from pyiron_base import job
return job(funct)
else:
raise ValueError()
Then a user could use this module in their own workflow workflow.py
as:
from python_workflow_definition.decorator import decorator
@decorator
def my_sum(a, b):
return sum([a, b])
And then setup the corresponding workflow using:
from python_workflow_definition.decorator import selector
selector(jobflow=True)
from workflow import my_sum
By setting the jobflow=True
the jobflow
decorator is used and so on. Obviously this example still needs to be extended to also support output arguments, but the logic remains the same. By using the global dictionary we can switch between the different workflow frameworks.