Skip to content

Commit a1d651b

Browse files
authored
Merge pull request #12 from pydn/dev
Dev
2 parents 48248e0 + 9549e3f commit a1d651b

File tree

2 files changed

+78
-33
lines changed

2 files changed

+78
-33
lines changed

comfyui_to_python.py

+35-14
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,21 @@
22
import glob
33
import inspect
44
import json
5-
import logging
65
import os
76
import random
87
import sys
8+
import re
99
from typing import Dict, List, Any, Callable, Tuple
1010

1111
import black
1212

13-
from utils import import_custom_nodes, add_comfyui_directory_to_sys_path, get_value_at_index
1413

15-
sys.path.append('../')
14+
from utils import import_custom_nodes, find_path, add_comfyui_directory_to_sys_path, add_extra_model_paths, get_value_at_index
1615

16+
sys.path.append('../')
1717
from nodes import NODE_CLASS_MAPPINGS
1818

1919

20-
logging.basicConfig(level=logging.INFO)
21-
22-
2320
class FileHandler:
2421
"""Handles reading and writing files.
2522
@@ -217,7 +214,7 @@ def generate_workflow(self, load_order: List, filename: str = 'generated_code_wo
217214
continue
218215

219216
class_type, import_statement, class_code = self.get_class_info(class_type)
220-
initialized_objects[class_type] = class_type.lower().strip()
217+
initialized_objects[class_type] = self.clean_variable_name(class_type)
221218
if class_type in self.base_node_class_mappings.keys():
222219
import_statements.add(import_statement)
223220
if class_type not in self.base_node_class_mappings.keys():
@@ -234,9 +231,9 @@ def generate_workflow(self, load_order: List, filename: str = 'generated_code_wo
234231
inputs['unique_id'] = random.randint(1, 2**64)
235232

236233
# Create executed variable and generate code
237-
executed_variables[idx] = f'{class_type.lower().strip()}_{idx}'
234+
executed_variables[idx] = f'{self.clean_variable_name(class_type)}_{idx}'
238235
inputs = self.update_inputs(inputs, executed_variables)
239-
236+
240237
if is_special_function:
241238
special_functions_code.append(self.create_function_call_code(initialized_objects[class_type], class_def.FUNCTION, executed_variables[idx], is_special_function, **inputs))
242239
else:
@@ -306,11 +303,11 @@ def assemble_python_code(self, import_statements: set, speical_functions_code: L
306303
"""
307304
# Get the source code of the utils functions as a string
308305
func_strings = []
309-
for func in [add_comfyui_directory_to_sys_path, get_value_at_index]:
306+
for func in [get_value_at_index, find_path, add_comfyui_directory_to_sys_path, add_extra_model_paths]:
310307
func_strings.append(f'\n{inspect.getsource(func)}')
311308
# Define static import statements required for the script
312309
static_imports = ['import os', 'import random', 'import sys', 'from typing import Sequence, Mapping, Any, Union',
313-
'import torch'] + func_strings + ['\n\nadd_comfyui_directory_to_sys_path()']
310+
'import torch'] + func_strings + ['\n\nadd_comfyui_directory_to_sys_path()\nadd_extra_model_paths()\n']
314311
# Check if custom nodes should be included
315312
if custom_nodes:
316313
static_imports.append(f'\n{inspect.getsource(import_custom_nodes)}\n')
@@ -328,7 +325,7 @@ def assemble_python_code(self, import_statements: set, speical_functions_code: L
328325
final_code = black.format_str(final_code, mode=black.Mode())
329326

330327
return final_code
331-
328+
332329
def get_class_info(self, class_type: str) -> Tuple[str, str, str]:
333330
"""Generates and returns necessary information about class type.
334331
@@ -339,12 +336,36 @@ def get_class_info(self, class_type: str) -> Tuple[str, str, str]:
339336
Tuple[str, str, str]: Updated class type, import statement string, class initialization code.
340337
"""
341338
import_statement = class_type
339+
variable_name = self.clean_variable_name(class_type)
342340
if class_type in self.base_node_class_mappings.keys():
343-
class_code = f'{class_type.lower().strip()} = {class_type.strip()}()'
341+
class_code = f'{variable_name} = {class_type.strip()}()'
344342
else:
345-
class_code = f'{class_type.lower().strip()} = NODE_CLASS_MAPPINGS["{class_type}"]()'
343+
class_code = f'{variable_name} = NODE_CLASS_MAPPINGS["{class_type}"]()'
346344

347345
return class_type, import_statement, class_code
346+
347+
@staticmethod
348+
def clean_variable_name(class_type: str) -> str:
349+
"""
350+
Remove any characters from variable name that could cause errors running the Python script.
351+
352+
Args:
353+
class_type (str): Class type.
354+
355+
Returns:
356+
str: Cleaned variable name with no special characters or spaces
357+
"""
358+
# Convert to lowercase and replace spaces with underscores
359+
clean_name = class_type.lower().strip().replace("-", "_").replace(" ", "_")
360+
361+
# Remove characters that are not letters, numbers, or underscores
362+
clean_name = re.sub(r'[^a-z0-9_]', '', clean_name)
363+
364+
# Ensure that it doesn't start with a number
365+
if clean_name[0].isdigit():
366+
clean_name = "_" + clean_name
367+
368+
return clean_name
348369

349370
def get_function_parameters(self, func: Callable) -> List:
350371
"""Get the names of a function's parameters.

utils.py

+43-19
Original file line numberDiff line numberDiff line change
@@ -27,32 +27,56 @@ def import_custom_nodes() -> None:
2727
# Initializing custom nodes
2828
init_custom_nodes()
2929

30-
def add_comfyui_directory_to_sys_path() -> None:
30+
31+
def find_path(name: str, path: str = None) -> str:
3132
"""
32-
Recursively looks at parent folders starting from the current working directory until it finds 'ComfyUI'.
33-
Once found, the directory is added to sys.path.
33+
Recursively looks at parent folders starting from the given path until it finds the given name.
34+
Returns the path as a Path object if found, or None otherwise.
3435
"""
35-
start_path = os.getcwd() # Get the current working directory
36+
# If no path is given, use the current working directory
37+
if path is None:
38+
path = os.getcwd()
39+
40+
# Check if the current directory contains the name
41+
if name in os.listdir(path):
42+
path_name = os.path.join(path, name)
43+
print(f"{name} found: {path_name}")
44+
return path_name
45+
46+
# Get the parent directory
47+
parent_directory = os.path.dirname(path)
3648

37-
def search_directory(path: str) -> None:
38-
# Check if the current directory contains 'ComfyUI'
39-
if 'ComfyUI' in os.listdir(path):
40-
directory_path = os.path.join(path, 'ComfyUI')
41-
sys.path.append(directory_path)
42-
print(f"ComfyUI found and added to sys.path: {directory_path}")
49+
# If the parent directory is the same as the current directory, we've reached the root and stop the search
50+
if parent_directory == path:
51+
return None
4352

44-
# Get the parent directory
45-
parent_directory = os.path.dirname(path)
53+
# Recursively call the function with the parent directory
54+
return find_path(name, parent_directory)
4655

47-
# If the parent directory is the same as the current directory, we've reached the root and stop the search
48-
if parent_directory == path:
49-
return
5056

51-
# Recursively call the function with the parent directory
52-
search_directory(parent_directory)
57+
def add_comfyui_directory_to_sys_path() -> None:
58+
"""
59+
Add 'ComfyUI' to the sys.path
60+
"""
61+
comfyui_path = find_path('ComfyUI')
62+
if comfyui_path is not None and os.path.isdir(comfyui_path):
63+
sys.path.append(comfyui_path)
64+
print(f"'{comfyui_path}' added to sys.path")
5365

54-
# Start the search from the current working directory
55-
search_directory(start_path)
66+
67+
def add_extra_model_paths() -> None:
68+
"""
69+
Parse the optional extra_model_paths.yaml file and add the parsed paths to the sys.path.
70+
"""
71+
from main import load_extra_path_config
72+
73+
extra_model_paths = find_path("extra_model_paths.yaml")
74+
75+
if extra_model_paths is not None:
76+
load_extra_path_config(extra_model_paths)
77+
else:
78+
print("Could not find the extra_model_paths config file.")
79+
5680

5781

5882
def get_value_at_index(obj: Union[Sequence, Mapping], index: int) -> Any:

0 commit comments

Comments
 (0)