From 9aaee0bc8c68ac6ddd3e20a7283c9c3008d8d933 Mon Sep 17 00:00:00 2001 From: atmaranto <35581227+atmaranto@users.noreply.github.com> Date: Thu, 7 Mar 2024 03:45:37 -0600 Subject: [PATCH] Initial SaveAsScript changes --- LICENSE | 1 + README.md | 37 +++++++- __init__.py | 42 +++++++++ comfyui_to_python.py | 117 ++++++++++++++----------- utils.py => comfyui_to_python_utils.py | 0 images/save_as_script.png | Bin 0 -> 58889 bytes install.py | 20 +++++ js/save-as-script.js | 52 +++++++++++ 8 files changed, 218 insertions(+), 51 deletions(-) create mode 100644 __init__.py rename utils.py => comfyui_to_python_utils.py (100%) create mode 100644 images/save_as_script.png create mode 100644 install.py create mode 100644 js/save-as-script.js diff --git a/LICENSE b/LICENSE index a8907c1..6cecb61 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,6 @@ The MIT License (MIT) +Copyright (c) 2024 Anthony Maranto Copyright (c) 2023 Peyton DeNiro Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/README.md b/README.md index aa3adc3..3e7ddce 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,39 @@ -## ComfyUI-to-Python-Extension +## ComfyUI-to-Python-Extension (SaveAsScript version) + +This is a fork of the [ComfyUI-To-Python-Extension](https://github.com/pydn/ComfyUI-to-Python-Extension) by Peyton DeNiro. It provides a more robust command-line interface and the ability to export your current workflow as a script directly from the ComfyUI web interface. + +### Usage (Web) + +Upon installation, there will be a button labeled "Save as Script" on the interface, pictured below: + +![A button that exports the current script on the ComfyUI](images/save_as_script.png) + +Click that button and enter your preferred name for the downloaded script (no ".py" is appeneded automatically), and your file will be downloaded. + +Note that if you use the script this way, you do **not** need to enable developer mode. You *will* if you use the CLI (to get the API JSON). + +### Usage (CLI) + +Navigating to the extension directory, you can also use the basic CLI included in the script to save your script without changing the Python file. + +```bash +usage: comfyui_to_python.py [-h] [--queue-size QUEUE_SIZE] [--yes] workflow output + +Converts a ComfyUI-style workflow.json file to a Python file. Must have been exported with API calls + +positional arguments: + workflow The workflow.json file to convert + output The output file (defaults to [input file].py) + +options: + -h, --help show this help message and exit + --queue-size QUEUE_SIZE, -q QUEUE_SIZE + The queue size per run + --yes, --overwrite, -y + Overwrite the output file if it exists +``` + +## Original Description The `ComfyUI-to-Python-Extension` is a powerful tool that translates [ComfyUI](https://github.com/comfyanonymous/ComfyUI) workflows into executable Python code. Designed to bridge the gap between ComfyUI's visual interface and Python's programming environment, this script facilitates the seamless transition from design to code execution. Whether you're a data scientist, a software developer, or an AI enthusiast, this tool streamlines the process of implementing ComfyUI workflows in Python. diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..ca899b4 --- /dev/null +++ b/__init__.py @@ -0,0 +1,42 @@ +import sys +import os + +from io import StringIO +import json + +import traceback + +from aiohttp import web + +ext_dir = os.path.dirname(__file__) +sys.path.append(ext_dir) + +# Prevent reimporting of custom nodes +os.environ["RUNNING_IN_COMFYUI"] = "TRUE" + +from comfyui_to_python import ComfyUItoPython + +sys.path.append(os.path.dirname(os.path.dirname(ext_dir))) + +import server + +WEB_DIRECTORY = "js" +NODE_CLASS_MAPPINGS = {} + +@server.PromptServer.instance.routes.post("/saveasscript") +async def save_as_script(request): + try: + data = await request.json() + name = data['name'] + workflow = data['workflow'] + + sio = StringIO() + ComfyUItoPython(workflow=workflow, output_file=sio) + + sio.seek(0) + data = sio.read() + + return web.Response(text=data, status=200) + except Exception as e: + traceback.print_exc() + return web.Response(text=str(e), status=500) diff --git a/comfyui_to_python.py b/comfyui_to_python.py index 33e6e53..47ae90e 100644 --- a/comfyui_to_python.py +++ b/comfyui_to_python.py @@ -6,25 +6,26 @@ import os import random import sys import re -from typing import Dict, List, Any, Callable, Tuple +from typing import Dict, List, Any, Callable, Tuple, TextIO import black -from utils import import_custom_nodes, find_path, add_comfyui_directory_to_sys_path, add_extra_model_paths, get_value_at_index +from comfyui_to_python_utils import import_custom_nodes, find_path, add_comfyui_directory_to_sys_path, add_extra_model_paths, get_value_at_index -sys.path.append('../') +add_comfyui_directory_to_sys_path() from nodes import NODE_CLASS_MAPPINGS +import nodes class FileHandler: """Handles reading and writing files. - This class provides methods to read JSON data from an input file and write code to an output file. + This class provides methods to read JSON data from an input file and write code to an output file (either file-like objects or string paths). """ @staticmethod - def read_json_file(file_path: str) -> dict: + def read_json_file(file_path: str | TextIO) -> dict: """ Reads a JSON file and returns its contents as a dictionary. @@ -39,33 +40,13 @@ class FileHandler: ValueError: If the file is not a valid JSON. """ - try: - with open(file_path, 'r') as file: - data = json.load(file) - return data - - except FileNotFoundError: - # Get the directory from the file_path - directory = os.path.dirname(file_path) - - # If the directory is an empty string (which means file is in the current directory), - # get the current working directory - if not directory: - directory = os.getcwd() - - # Find all JSON files in the directory - json_files = glob.glob(f"{directory}/*.json") - - # Format the list of JSON files as a string - json_files_str = "\n".join(json_files) - - raise FileNotFoundError(f"\n\nFile not found: {file_path}. JSON files in the directory:\n{json_files_str}") - - except json.JSONDecodeError: - raise ValueError(f"Invalid JSON format in file: {file_path}") + if hasattr(file_path, "read"): return json.load(file_path) + with open(file_path, 'r') as file: + data = json.load(file) + return data @staticmethod - def write_code_to_file(file_path: str, code: str) -> None: + def write_code_to_file(file_path: str | TextIO, code: str) -> None: """Write the specified code to a Python file. Args: @@ -75,16 +56,19 @@ class FileHandler: Returns: None """ - # Extract directory from the filename - directory = os.path.dirname(file_path) + if isinstance(file_path, str): + # Extract directory from the filename + directory = os.path.dirname(file_path) - # If the directory does not exist, create it - if directory and not os.path.exists(directory): - os.makedirs(directory) + # If the directory does not exist, create it + if directory and not os.path.exists(directory): + os.makedirs(directory) - # Save the code to a .py file - with open(file_path, 'w') as file: - file.write(code) + # Save the code to a .py file + with open(file_path, 'w') as file: + file.write(code) + else: + file_path.write(code) class LoadOrderDeterminer: @@ -181,6 +165,13 @@ class CodeGenerator: """ self.node_class_mappings = node_class_mappings self.base_node_class_mappings = base_node_class_mappings + + def can_be_imported(self, import_name: str): + if import_name in self.base_node_class_mappings.keys(): + if getattr(nodes, import_name, None) is not None: + return True + + return False def generate_workflow(self, load_order: List, filename: str = 'generated_code_workflow.py', queue_size: int = 10) -> str: """Generate the execution code based on the load order. @@ -212,10 +203,10 @@ class CodeGenerator: # No need to use preview image nodes since we are executing the script in a terminal if class_type == 'PreviewImage': continue - + class_type, import_statement, class_code = self.get_class_info(class_type) initialized_objects[class_type] = self.clean_variable_name(class_type) - if class_type in self.base_node_class_mappings.keys(): + if self.can_be_imported(class_type): import_statements.add(import_statement) if class_type not in self.base_node_class_mappings.keys(): custom_nodes = True @@ -337,7 +328,7 @@ class CodeGenerator: """ import_statement = class_type variable_name = self.clean_variable_name(class_type) - if class_type in self.base_node_class_mappings.keys(): + if self.can_be_imported(class_type): class_code = f'{variable_name} = {class_type.strip()}()' else: class_code = f'{variable_name} = NODE_CLASS_MAPPINGS["{class_type}"]()' @@ -408,19 +399,27 @@ class ComfyUItoPython: base_node_class_mappings (Dict): Base mappings of node classes. """ - def __init__(self, input_file: str, output_file: str, queue_size: int = 10, node_class_mappings: Dict = NODE_CLASS_MAPPINGS): + def __init__(self, workflow: str = "", input_file: str = "", output_file: (str | TextIO) = "", queue_size: int = 10, node_class_mappings: Dict = NODE_CLASS_MAPPINGS): """Initialize the ComfyUItoPython class with the given parameters. Args: + workflow (str): The input_file (str): Path to the input JSON file. output_file (str): Path to the output Python file. queue_size (int): The number of times a workflow will be executed by the script. Defaults to 10. node_class_mappings (Dict): Mappings of node classes. Defaults to NODE_CLASS_MAPPINGS. """ + if input_file and workflow: + raise ValueError("Can't provide both input_file and workflow") + elif not input_file and not workflow: + raise ValueError("Needs input_file or workflow") + + self.workflow = workflow self.input_file = input_file self.output_file = output_file self.queue_size = queue_size self.node_class_mappings = node_class_mappings + self.base_node_class_mappings = copy.deepcopy(self.node_class_mappings) self.execute() @@ -430,11 +429,15 @@ class ComfyUItoPython: Returns: None """ - # Step 1: Import all custom nodes - import_custom_nodes() + #if self.should_init_custom_nodes: + # Step 1: Import all custom nodes (already done for us) + #import_custom_nodes() # Step 2: Read JSON data from the input file - data = FileHandler.read_json_file(self.input_file) + if self.input_file: + data = FileHandler.read_json_file(self.input_file) + else: + data = json.loads(self.workflow) # Step 3: Determine the load order load_order_determiner = LoadOrderDeterminer(data, self.node_class_mappings) @@ -451,10 +454,24 @@ class ComfyUItoPython: if __name__ == '__main__': - # Update class parameters here - input_file = 'workflow_api.json' - output_file = 'workflow_api.py' - queue_size = 10 + import argparse + + ap = argparse.ArgumentParser(description="Converts a ComfyUI-style workflow.json file to a Python file. Must have been exported with API calls") + + ap.add_argument("workflow", help="The workflow.json file to convert") + ap.add_argument("output", default=None, help="The output file (defaults to [input file].py)") + ap.add_argument("--queue-size", "-q", default=1, type=int, help="The queue size per run") + ap.add_argument("--yes", "--overwrite", "-y", action="store_true", help="Overwrite the output file if it exists") + + args = ap.parse_args() + + + output_file = args.output_file if args.output_file else args.input_file + ".py" + if os.path.isfile(output_file): + if not args.yes: + if input("Are you sure you want to overwrite " + output_file + "?\nY/n").strip().lower() not in ("y", "yes"): + print("Exiting.") + sys.exit(1) # Convert ComfyUI workflow to Python - ComfyUItoPython(input_file=input_file, output_file=output_file, queue_size=queue_size) + ComfyUItoPython(input_file=args.input_file, output_file=output_file, queue_size=args.queue_size) diff --git a/utils.py b/comfyui_to_python_utils.py similarity index 100% rename from utils.py rename to comfyui_to_python_utils.py diff --git a/images/save_as_script.png b/images/save_as_script.png new file mode 100644 index 0000000000000000000000000000000000000000..3b8dc75a8ddaf6688683ff3fd831004c0d90c432 GIT binary patch literal 58889 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%0A?lHY3&BFt`S@jPe!^*Ao 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 M)aDZ5g4=`t0w3a<8UO$Q literal 0 HcmV?d00001 diff --git a/install.py b/install.py new file mode 100644 index 0000000..8d6ba79 --- /dev/null +++ b/install.py @@ -0,0 +1,20 @@ +import os +import sys + +from subprocess import Popen, check_output, PIPE + +requirements = open(os.path.join(os.path.dirname(__file__), "requirements.txt")).read().split("\n") + +installed_packages = check_output( + [sys.executable, "-m", "pip", "list"], + universal_newlines=True +).split("\n") + +installed_packages = set([package.split(" ")[0].lower() for package in installed_packages if package.strip()]) + +for requirement in requirements: + if requirement.lower() not in installed_packages: + print(f"Installing requirements...") + Popen([sys.executable, "-m", "pip", "install", "-r", "requirements.txt"], stdout=PIPE, stderr=PIPE, cwd=os.path.dirname(__file__)).communicate() + print(f"Installed.") + break diff --git a/js/save-as-script.js b/js/save-as-script.js new file mode 100644 index 0000000..60432a6 --- /dev/null +++ b/js/save-as-script.js @@ -0,0 +1,52 @@ +import { app } from "../../scripts/app.js"; +import { api } from "../../scripts/api.js"; +import { $el } from "../../scripts/ui.js"; + +app.registerExtension({ + name: "Comfy.SaveAsScript", + init() { + $el("style", { + parent: document.head, + }); + }, + async setup() { + const menu = document.querySelector(".comfy-menu"); + const separator = document.createElement("hr"); + + separator.style.margin = "20px 0"; + separator.style.width = "100%"; + menu.append(separator); + + const saveButton = document.createElement("button"); + saveButton.textContent = "Save as Script"; + saveButton.onclick = () => { + const filename = prompt("Save script as:"); + if(filename === undefined || filename === null || filename === "") { + return + } + + app.graphToPrompt().then(async (p) => { + const json = JSON.stringify({name: filename, workflow: JSON.stringify(p.output, null, 2)}, null, 2); // convert the data to a JSON string + var response = await api.fetchApi(`/saveasscript`, { method: "POST", body: json }); + if(response.status == 200) { + const blob = new Blob([await response.text()], {type: "application/json"}); + const url = URL.createObjectURL(blob); + const a = $el("a", { + href: url, + download: filename, + style: {display: "none"}, + parent: document.body, + }); + a.click(); + setTimeout(function () { + a.remove(); + window.URL.revokeObjectURL(url); + }, 0); + } + }); + } + menu.append(saveButton); + + console.log("SaveAsScript loaded"); + } +});