Skip to content

[Suggestion] Generalized Decorator #114

Open
@jan-janssen

Description

@jan-janssen

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions