Skip to content

[Suggestion] Generalized Decorator #114

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
jan-janssen opened this issue May 24, 2025 · 0 comments
Open

[Suggestion] Generalized Decorator #114

jan-janssen opened this issue May 24, 2025 · 0 comments

Comments

@jan-janssen
Copy link
Member

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant