From 2ceeec39de89f22bf63c911728fadeaddc2d3e41 Mon Sep 17 00:00:00 2001 From: Tony M <> Date: Thu, 11 Sep 2025 05:58:35 -0500 Subject: [PATCH] Update for new ComfyUI --- comfyui_to_python.py | 25 ++++++++++++++----------- comfyui_to_python_utils.py | 18 ++++++++++++------ 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/comfyui_to_python.py b/comfyui_to_python.py index 94c370e..8169ff0 100644 --- a/comfyui_to_python.py +++ b/comfyui_to_python.py @@ -203,6 +203,7 @@ class CodeGenerator: initialized_objects = {} custom_nodes = False + # Loop over each dictionary in the load order list for idx, data, is_special_function in load_order: # Generate class definition and inputs from the data @@ -211,11 +212,10 @@ class CodeGenerator: input_types = self.node_class_mappings[class_type].INPUT_TYPES() missing = [] for i, input in enumerate(input_types.get("required", {}).keys()): - if input not in inputs: + if isinstance(inputs.get(input, []), (int, str, float, bool)): input_var = f"{input}{len(arg_inputs)+1}" - arg_inputs.append((input_var, f"Argument {i}, input `{input}` for node \\\"{data.get('_meta', {}).get('title', class_type)}\\\" id {idx}")) - print("WARNING: Missing required input", input, "for", class_type) - print("That will be CLI arg " + str(len(arg_inputs))) + arg_inputs.append((input_var, f"Argument {i}, input `{input}` for node \\\"{data.get('_meta', {}).get('title', class_type)}\\\" id {idx}", inputs.get(input, []))) + print(f"CLI arg {input} for type {class_type} " + str(len(arg_inputs))) missing.append((input, input_var, len(arg_inputs))) class_def = self.node_class_mappings[class_type]() @@ -255,7 +255,7 @@ class CodeGenerator: inputs = self.update_inputs(inputs, executed_variables) if class_type == 'SaveImage': - save_code = self.create_function_call_code(initialized_objects[class_type], class_def.FUNCTION, executed_variables[idx], is_special_function, **inputs).strip() + save_code = self.create_function_call_code(initialized_objects[class_type], class_def.FUNCTION, executed_variables[idx], is_special_function, inputs).strip() return_code = ['if __name__ != "__main__":', '\treturn dict(' + ', '.join(self.format_arg(key, value) for key, value in inputs.items()) + ')', 'else:', '\t' + save_code] if is_special_function: @@ -264,16 +264,16 @@ class CodeGenerator: code.extend(return_code) ### This should presumably NEVER occur for a valid workflow else: if is_special_function: - special_functions_code.append(self.create_function_call_code(initialized_objects[class_type], class_def.FUNCTION, executed_variables[idx], is_special_function, **inputs)) + special_functions_code.append(self.create_function_call_code(initialized_objects[class_type], class_def.FUNCTION, executed_variables[idx], is_special_function, inputs)) else: - code.append(self.create_function_call_code(initialized_objects[class_type], class_def.FUNCTION, executed_variables[idx], is_special_function, **inputs)) + code.append(self.create_function_call_code(initialized_objects[class_type], class_def.FUNCTION, executed_variables[idx], is_special_function, inputs)) # Generate final code by combining imports and code, and wrap them in a main function final_code = self.assemble_python_code(import_statements, special_functions_code, arg_inputs, code, queue_size, custom_nodes, include_prompt_data) return final_code - def create_function_call_code(self, obj_name: str, func: str, variable_name: str, is_special_function: bool, **kwargs) -> str: + def create_function_call_code(self, obj_name: str, func: str, variable_name: str, is_special_function: bool, kwargs) -> str: """Generate Python code for a function call. Args: @@ -331,8 +331,11 @@ class CodeGenerator: func_strings.append(f'\n{inspect.getsource(func)}') argparse_code = [f'parser = argparse.ArgumentParser(description="A converted ComfyUI workflow. Required inputs listed below. Values passed should be valid JSON (assumes string if not valid JSON).")'] - for i, (input_name, arg_desc) in enumerate(arg_inputs): - argparse_code.append(f'parser.add_argument("{input_name}", help="{arg_desc} (autogenerated)")\n') + for i, (input_name, arg_desc, default) in enumerate(arg_inputs): + extra = "" + if default is not None: + extra = f"default={repr(default)}, " + argparse_code.append(f'parser.add_argument("--{input_name}", {extra}help="{arg_desc} (autogenerated)")\n') argparse_code.append(f'parser.add_argument("--queue-size", "-q", type=int, default={queue_size}, help="How many times the workflow will be executed (default: {queue_size})")\n') argparse_code.append('parser.add_argument("--comfyui-directory", "-c", default=None, help="Where to look for ComfyUI (default: current directory)")\n') argparse_code.append(f'parser.add_argument("--output", "-o", default=None, help="The location to save the output image. Either a file path, a directory, or - for stdout (default: the ComfyUI output directory)")\n') @@ -376,7 +379,7 @@ def main(*func_args, **func_kwargs): args = parser.parse_args() else: defaults = dict((arg, parser.get_default(arg)) for arg in ['queue_size', 'comfyui_directory', 'output', 'disable_metadata']) - ordered_args = dict(zip({[input_name for input_name, _ in arg_inputs]}, func_args)) + ordered_args = dict(zip({[input_name for input_name, _, _ in arg_inputs]}, func_args)) all_args = dict() all_args.update(defaults) diff --git a/comfyui_to_python_utils.py b/comfyui_to_python_utils.py index 6e5e33b..c63e368 100644 --- a/comfyui_to_python_utils.py +++ b/comfyui_to_python_utils.py @@ -21,12 +21,15 @@ def import_custom_nodes() -> None: loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) - # Creating an instance of PromptServer with the loop - server_instance = server.PromptServer(loop) - execution.PromptQueue(server_instance) + async def inner(): + # Creating an instance of PromptServer with the loop + server_instance = server.PromptServer(loop) + execution.PromptQueue(server_instance) - # Initializing custom nodes - init_extra_nodes(init_custom_nodes=True) + # Initializing custom nodes + await init_extra_nodes(init_custom_nodes=True) + + loop.run_until_complete(inner()) def find_path(name: str, path: str = None) -> str: @@ -77,8 +80,11 @@ def add_extra_model_paths() -> None: """ Parse the optional extra_model_paths.yaml file and add the parsed paths to the sys.path. """ + from comfy.options import enable_args_parsing + enable_args_parsing() from utils.extra_config import load_extra_path_config + extra_model_paths = find_path("extra_model_paths.yaml") if extra_model_paths is not None: @@ -111,7 +117,7 @@ def get_value_at_index(obj: Union[Sequence, Mapping], index: int) -> Any: except KeyError: return obj['result'][index] -def parse_arg(s: Any): +def parse_arg(s: Any, default: Any = None) -> Any: """ Parses a JSON string, returning it unchanged if the parsing fails. """ if __name__ == "__main__" or not isinstance(s, str): return s