def _update_steps(function_name, caller_line, args=None, template_name=None): """ Step of Argo Yaml contains name, related template and parameters. thus, we insert these information into couler.step. """ function_id = pyfunc.invocation_name(function_name, caller_line) # Update `steps` only if needed if _update_steps_lock: step_template = OrderedDict() if _run_concurrent_lock: _id = pyfunc.invocation_name(template_name, caller_line) step_template["name"] = _id else: step_template["name"] = function_id if template_name is None: step_template["template"] = function_name else: step_template["template"] = template_name if _when_prefix is not None: step_template["when"] = _when_prefix if args is not None: parameters = [] for i in range(len(args)): value = args[i] if "couler" in value: tmp = args[i].split(".") if len(tmp) < 3: raise ValueError( "wrong container return representation") # To avoid duplicate map function # value = ".".join(map(str, tmp[2:])) value = tmp[2] for item in tmp[3:]: value = value + "." + item value = '"{{steps.%s}}"' % value if _run_concurrent_lock: parameters.append({ "name": pyfunc.input_parameter(template_name, i), "value": value, }) else: parameters.append({ "name": pyfunc.input_parameter(function_name, i), "value": value, }) step_template["arguments"] = {"parameters": parameters} if _condition_id is not None: function_id = _condition_id if _while_lock: if function_id in _while_steps: _while_steps.get(function_id).append(step_template) else: _while_steps[function_id] = [step_template] else: if function_id in _steps: _steps.get(function_id).append(step_template) else: _steps[function_id] = [step_template]
def exec_while(condition, inner_while): """ Generate the Argo recursive logic. For example https://github.com/argoproj/argo/blob/master/examples/README.md#recursion """ # _while_lock means 'exec_while' operation begins to work # _while_steps stores logic steps inside the recursion logic global _while_lock, _while_steps _while_lock = True # Enforce inner function of the while-loop to run if isinstance(inner_while, types.FunctionType): branch = inner_while() if branch is None: raise SyntaxError("require function return value") else: raise TypeError("condition to run would be a function") branch_dict = _extract_step_return(branch) recursive_name = "exec-while-" + branch_dict["name"] recursive_id = "exec-while-" + branch_dict["id"] if recursive_name not in _templates: template = OrderedDict({"name": recursive_name}) else: raise SyntaxError("Recursive function can not be called twice ") # Generates leaving point for recursive step_out_name = "%s-%s" % (recursive_name, "exit") pre = condition["pre"] pre_dict = _extract_step_return(pre) condition_suffix = condition["condition"] # Generates the recursive go to step when_prefix = "{{steps.%s.%s}} %s %s" % ( branch_dict["id"], branch_dict["output"], condition_suffix, pre_dict["value"], ) step_out_template = OrderedDict({ "name": step_out_name, "template": recursive_name, "when": when_prefix, }) step_out_id = pyfunc.invocation_name(step_out_name, recursive_id) _while_steps[step_out_id] = [step_out_template] # Adds steps inside the recursive logic to recursive template template["steps"] = list(_while_steps.values()) # Adds this recursive logic to the _templates _templates[recursive_name] = template # Add recursive logic to global _steps recursive_out_template = OrderedDict({ "name": recursive_id, "template": recursive_name }) if recursive_id in _steps: _steps.get(recursive_id).append(recursive_out_template) else: _steps[recursive_id] = [recursive_out_template] _while_lock = False _while_steps = OrderedDict() return _templates