Skip to content

Commit 0b4788d

Browse files
committed
Bugfixes for args, updated the README
1 parent 793854d commit 0b4788d

File tree

4 files changed

+41
-13
lines changed

4 files changed

+41
-13
lines changed

README.md

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Let me know of any major issues by submitting an Issue.
33
I plan to do some fresh install testing when I have time.
44

5-
## ComfyUI-to-Python-Extension (SaveAsScript version)
5+
## ComfyUI-SaveAsScript
66

77
This is a fork maintained by Anthony Maranto of the original [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.
88

@@ -38,15 +38,36 @@ options:
3838
Overwrite the output file if it exists
3939
```
4040
41-
### Other Changes
41+
### Arguments
42+
43+
It is now possible to pass command-line arguments to a generated script file. Any time a **required** input variable for *any* node in your the ComfyUI workflow is left unfilled, SaveAsScript will automatically convert that node into an argument.
4244
43-
I also fixed what seemed to be a minor bug with exporting certain Crystools nodes, possibly due to their unusual name.
45+
For instance, if you have a simple default workflow, but have converted the text widget of the positive prompt into an input and left it unfilled like so:
4446
45-
### Improvement TODO
47+
![An altered version of the default ComfyUI workflow](images/default_altered.png)
48+
49+
Then the unfilled required variable will be available as an argument:
50+
```bash
51+
usage: default-workflow.py [-h] text1
52+
53+
A converted ComfyUI workflow. Required inputs listed below. Values passed should be in JSON
54+
55+
positional arguments:
56+
text1 Argument 0, input `text` for node "CLIP Text Encode (Prompt)" id 6 (autogenerated)
57+
58+
options:
59+
-h, --help show this help message and exit
60+
```
61+
62+
Arguments are new. **If you have any suggestions on how to improve them or on how to effectively specify defaults in the workflow and override in the command-line**, feel free to suggest that in an Issue.
63+
64+
### Other Changes
4665
47-
Disable export of invalid nodes (ones for which required args are not satisfied) and log a warning to the console.
66+
#### Bugfixes
67+
- Windows paths are now properly escaped.
68+
- I also fixed what seemed to be a minor bug with exporting certain Crystools nodes, possibly due to their unusual name.
4869
49-
## Description of ComfyUI-to-Python-Extension (usage altered)
70+
## Old Description of ComfyUI-to-Python-Extension (usage altered)
5071
5172
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.
5273

comfyui_to_python.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import black
1212

1313

14-
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
14+
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, parse_arg
1515

1616
add_comfyui_directory_to_sys_path()
1717
from nodes import NODE_CLASS_MAPPINGS
@@ -202,7 +202,7 @@ def generate_workflow(self, load_order: List, queue_size: int = 10) -> str:
202202
arg_inputs.append((input_var, f"Argument {i}, input `{input}` for node \\\"{data['_meta'].get('title', class_type)}\\\" id {idx}"))
203203
print("WARNING: Missing required input", input, "for", class_type)
204204
print("That will be CLI arg " + str(len(arg_inputs)))
205-
missing.append((input_var, len(arg_inputs)))
205+
missing.append((input, input_var, len(arg_inputs)))
206206

207207
class_def = self.node_class_mappings[class_type]()
208208

@@ -225,8 +225,8 @@ def generate_workflow(self, load_order: List, queue_size: int = 10) -> str:
225225

226226
# Remove any keyword arguments from **inputs if they are not in class_def_params
227227
inputs = {key: value for key, value in inputs.items() if key in class_def_params}
228-
for input, arg in missing:
229-
inputs[input] = {"variable_name": f"argv." + input}
228+
for input, input_var, arg in missing:
229+
inputs[input] = {"variable_name": f"parse_arg(args." + input_var + ")"}
230230
# Deal with hidden variables
231231
if 'unique_id' in class_def_params:
232232
inputs['unique_id'] = random.randint(1, 2**64)
@@ -303,18 +303,18 @@ def assemble_python_code(self, import_statements: set, speical_functions_code: L
303303
"""
304304
# Get the source code of the utils functions as a string
305305
func_strings = []
306-
for func in [get_value_at_index, find_path, add_comfyui_directory_to_sys_path, add_extra_model_paths, import_custom_nodes]:
306+
for func in [get_value_at_index, find_path, add_comfyui_directory_to_sys_path, add_extra_model_paths, import_custom_nodes, parse_arg]:
307307
func_strings.append(f'\n{inspect.getsource(func)}')
308308

309309
argparse_code = ""
310310
if arg_inputs:
311-
argparse_code = f'argv = sys.argv[:]\n\nparser = argparse.ArgumentParser(description="A converted ComfyUI workflow. Required inputs listed below. Values passed should be in JSON")\n'
311+
argparse_code = f'\nparser = argparse.ArgumentParser(description="A converted ComfyUI workflow. Required inputs listed below. Values passed should be in JSON")\n'
312312
for i, (input_name, arg_desc) in enumerate(arg_inputs):
313313
argparse_code += f'parser.add_argument("{input_name}", help="{arg_desc} (autogenerated)")\n'
314314
argparse_code += 'args = parser.parse_args()\nsys.argv = [sys.argv[0]]\n'
315315

316316
# Define static import statements required for the script
317-
static_imports = ['import os', 'import random', 'import sys', 'import argparse', 'from typing import Sequence, Mapping, Any, Union',
317+
static_imports = ['import os', 'import random', 'import sys', 'import json', 'import argparse', 'from typing import Sequence, Mapping, Any, Union',
318318
'import torch'] + func_strings + [argparse_code]
319319
# Check if custom nodes should be included
320320
if custom_nodes:

comfyui_to_python_utils.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,3 +101,10 @@ def get_value_at_index(obj: Union[Sequence, Mapping], index: int) -> Any:
101101
return obj[index]
102102
except KeyError:
103103
return obj['result'][index]
104+
105+
def parse_arg(s: str):
106+
""" Parses a JSON string, returning it unchanged if the parsing fails. """
107+
try:
108+
return json.loads(s)
109+
except json.JSONDecodeError:
110+
return s

images/default_altered.png

151 KB
Loading

0 commit comments

Comments
 (0)