Skip to content

feat: Tasks returning multiple results #15

@AncientPatata

Description

@AncientPatata

Make it possible for tasks to return multiple results (as in, return different object handles), this will allow for more granulare control in certain scenarios; This can be done with a simple multiple method that takes in the different object handles to create

@task
def my_task(x):
    if x:
        return multiple(1,2,4)
    else: 
        return multiple(1,2,3)
    

When the task decorator detects this it doesn't create an Armonik result handle and just uses the already created ones.
We can also give names to the different results multiple((1,2),(3,4), names=["a","b"]) but ideally the user should treat them like tuples on their end. (won't access them by name)
We'd have to guarantee that for all the different execution paths we return the same number of results, using a method allows us to gently handle the cases of returning lists/tuples for instance. We can also use Python's inspect module during function registration to check if the constraint is respected and to also create the necessary number of result handles during invocation.

import ast
import inspect
from functools import wraps
from collections import defaultdict

class ParameterConsistencyChecker(ast.NodeVisitor):
    def __init__(self, function_names_to_check="multiple"):
        self.function_calls = defaultdict(list)
        self.function_names_to_check = function_names_to_check or set()
    
    def visit_Call(self, node):
        # Handle direct function calls (e.g., multiple(1, 2, 3))
        if isinstance(node.func, ast.Name):
            func_name = node.func.id
            if not self.function_names_to_check or func_name in self.function_names_to_check:
                arg_count = len(node.args) + len(node.keywords)
                self.function_calls[func_name].append(arg_count)
        
        # Handle attribute calls (e.g., obj.multiple(1, 2, 3))
        elif isinstance(node.func, ast.Attribute):
            func_name = node.func.attr
            if not self.function_names_to_check or func_name in self.function_names_to_check:
                arg_count = len(node.args) + len(node.keywords)
                self.function_calls[func_name].append(arg_count)
        
        # Continue visiting child nodes
        self.generic_visit(node)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions