|
|
|
|
|
|
|
import os |
|
import importlib.util |
|
import subprocess |
|
import sys |
|
import shutil |
|
import __main__ |
|
import pkgutil |
|
import re |
|
import threading |
|
import ast |
|
|
|
python = sys.executable |
|
|
|
|
|
extension_folder = os.path.dirname(os.path.realpath(__file__)) |
|
|
|
|
|
folder_web = os.path.join(os.path.dirname(os.path.realpath(__main__.__file__)), "web") |
|
folder_comfyui_web_extensions = os.path.join(folder_web, "extensions") |
|
|
|
folder__web_lib = os.path.join(folder_web, "lib") |
|
extension_dirs = [ |
|
"web_alekpet_nodes", |
|
] |
|
|
|
|
|
DEBUG = False |
|
|
|
|
|
|
|
|
|
humanReadableTextReg = re.compile("(?<=[a-z])([A-Z])|(?<=[A-Z])([A-Z][a-z]+)") |
|
module_name_cut_version = re.compile("[>=<]") |
|
|
|
installed_modules = list(m[1] for m in pkgutil.iter_modules(None)) |
|
|
|
|
|
def log(*text): |
|
if DEBUG: |
|
print("".join(map(str, text))) |
|
|
|
|
|
def information(datas): |
|
for info in datas: |
|
if DEBUG: |
|
print(info, end="") |
|
|
|
|
|
def get_classes(code): |
|
cls = [] |
|
tree = ast.parse(code) |
|
for n in ast.walk(tree): |
|
if isinstance(n, ast.ClassDef) and "Node" in n.name: |
|
cls.append(n.name) |
|
return cls |
|
|
|
|
|
def getNamesNodesInsidePyFile(nodeElement): |
|
node_folder = os.path.join(extension_folder, nodeElement) |
|
cls_name = [] |
|
for f in os.listdir(node_folder): |
|
ext = os.path.splitext(f) |
|
path_to_py = os.path.join(node_folder, f) |
|
|
|
if ( |
|
os.path.isfile(path_to_py) |
|
and not f.startswith("__") |
|
and ext[1] == ".py" |
|
and ext[0] != "__init__" |
|
): |
|
with open(path_to_py, "r") as pyf: |
|
cls_name = get_classes(pyf.read()) |
|
|
|
return cls_name |
|
|
|
def module_install(commands, cwd="."): |
|
result = subprocess.Popen( |
|
commands, |
|
cwd=cwd, |
|
stdout=subprocess.PIPE, |
|
stderr=subprocess.PIPE, |
|
text=True, |
|
bufsize=1, |
|
) |
|
out = threading.Thread(target=information, args=(result.stdout,)) |
|
err = threading.Thread(target=information, args=(result.stderr,)) |
|
out.start() |
|
err.start() |
|
out.join() |
|
err.join() |
|
|
|
return result.wait() |
|
|
|
|
|
def checkModules(nodeElement): |
|
file_requir = os.path.join(extension_folder, nodeElement, "requirements.txt") |
|
if os.path.exists(file_requir): |
|
log(" -> File 'requirements.txt' found!") |
|
module_install([sys.executable, "-m", "pip", "install", "-r", file_requir]) |
|
|
|
|
|
def addComfyUINodesToMapping(nodeElement): |
|
log(f" -> Find class execute node <{nodeElement}>, add NODE_CLASS_MAPPINGS ...") |
|
node_folder = os.path.join(extension_folder, nodeElement) |
|
for f in os.listdir(node_folder): |
|
ext = os.path.splitext(f) |
|
|
|
if ( |
|
os.path.isfile(os.path.join(node_folder, f)) |
|
and not f.startswith("__") |
|
and ext[1] == ".py" |
|
and ext[0] != "__init__" |
|
): |
|
|
|
module_without_py = f.replace(ext[1], "") |
|
|
|
spec = importlib.util.spec_from_file_location( |
|
module_without_py, os.path.join(node_folder, f) |
|
) |
|
module = importlib.util.module_from_spec(spec) |
|
spec.loader.exec_module(module) |
|
classes_names = list( |
|
filter( |
|
lambda p: callable(getattr(module, p)) and p.find("Node") != -1, |
|
dir(module), |
|
) |
|
) |
|
for class_module_name in classes_names: |
|
|
|
if ( |
|
class_module_name |
|
and class_module_name not in NODE_CLASS_MAPPINGS.keys() |
|
): |
|
log( |
|
f" [*] Class node found '{class_module_name}' add to NODE_CLASS_MAPPINGS..." |
|
) |
|
NODE_CLASS_MAPPINGS.update( |
|
{class_module_name: getattr(module, class_module_name)} |
|
) |
|
NODE_DISPLAY_NAME_MAPPINGS.update( |
|
{ |
|
class_module_name: humanReadableTextReg.sub( |
|
" \\1\\2", class_module_name |
|
) |
|
} |
|
) |
|
|
|
|
|
def checkFolderIsset(): |
|
log(f"* Check and make not isset dirs...") |
|
for d in extension_dirs: |
|
dir_ = os.path.join(extension_folder, d) |
|
if not os.path.exists(dir_): |
|
log(f"* Dir <{d}> is not found, create...") |
|
os.mkdir(dir_) |
|
log(f"* Dir <{d}> created!") |
|
|
|
|
|
def printColorInfo(text, color="\033[92m"): |
|
CLEAR = "\033[0m" |
|
print(f"{color}{text}{CLEAR}") |
|
|
|
|
|
def installNodes(): |
|
log(f"\n-------> AlekPet Node Installing [DEBUG] <-------") |
|
printColorInfo(f"### [START] ComfyUI AlekPet Nodes ###", "\033[1;35m") |
|
web_extensions_dir = os.path.join(extension_folder, extension_dirs[0]) |
|
|
|
|
|
libfiles = ["fabric.js"] |
|
for file in libfiles: |
|
filePath = os.path.join(folder__web_lib, file) |
|
if os.path.exists(filePath): |
|
os.remove(filePath) |
|
|
|
|
|
oldDirNodes = os.path.join(folder_comfyui_web_extensions, "AlekPet_Nodes") |
|
if os.path.exists(oldDirNodes): |
|
shutil.rmtree(oldDirNodes) |
|
|
|
|
|
if os.path.exists(web_extensions_dir): |
|
shutil.rmtree(web_extensions_dir) |
|
|
|
checkFolderIsset() |
|
|
|
extensions_dirs_copy = ["js", "css", "assets", "lib"] |
|
|
|
for nodeElement in os.listdir(extension_folder): |
|
if ( |
|
not nodeElement.startswith("__") |
|
and nodeElement.endswith("Node") |
|
and os.path.isdir(os.path.join(extension_folder, nodeElement)) |
|
): |
|
log(f"* Node <{nodeElement}> is found, installing...") |
|
|
|
|
|
for dir_name in extensions_dirs_copy: |
|
folder_curr = os.path.join(extension_folder, nodeElement, dir_name) |
|
if os.path.exists(folder_curr): |
|
folder_curr_dist = os.path.join( |
|
web_extensions_dir, |
|
dir_name, |
|
nodeElement.lower() if dir_name != "js" else web_extensions_dir, |
|
) |
|
shutil.copytree(folder_curr, folder_curr_dist, dirs_exist_ok=True) |
|
|
|
|
|
clsNodes = getNamesNodesInsidePyFile(nodeElement) |
|
clsNodesText = "\033[93m"+", ".join(clsNodes)+"\033[0m" if len(clsNodes) else "" |
|
printColorInfo(f"Node -> {nodeElement}: {clsNodesText} \033[92m[Loading]") |
|
|
|
checkModules(nodeElement) |
|
|
|
|
|
printColorInfo(f"### [END] ComfyUI AlekPet Nodes ###", "\033[1;35m") |
|
|
|
|
|
|
|
WEB_DIRECTORY = f"./{extension_dirs[0]}" |
|
|
|
|
|
|
|
installNodes() |
|
|
|
|
|
|
|
from .ArgosTranslateNode.argos_translate_node import ( |
|
ArgosTranslateCLIPTextEncodeNode, |
|
ArgosTranslateTextNode, |
|
) |
|
from .DeepTranslatorNode.deep_translator_node import ( |
|
DeepTranslatorCLIPTextEncodeNode, |
|
DeepTranslatorTextNode, |
|
) |
|
from .ExtrasNode.extras_node import PreviewTextNode, HexToHueNode, ColorsCorrectNode |
|
from .GoogleTranslateNode.google_translate_node import ( |
|
GoogleTranslateCLIPTextEncodeNode, |
|
GoogleTranslateTextNode, |
|
) |
|
from .PainterNode.painter_node import PainterNode |
|
from .PoseNode.pose_node import PoseNode |
|
from .IDENode.ide_node import IDENode |
|
|
|
|
|
NODE_CLASS_MAPPINGS = { |
|
"ArgosTranslateCLIPTextEncodeNode": ArgosTranslateCLIPTextEncodeNode, |
|
"ArgosTranslateTextNode": ArgosTranslateTextNode, |
|
"DeepTranslatorCLIPTextEncodeNode": DeepTranslatorCLIPTextEncodeNode, |
|
"DeepTranslatorTextNode": DeepTranslatorTextNode, |
|
"PreviewTextNode": PreviewTextNode, |
|
"HexToHueNode": HexToHueNode, |
|
"ColorsCorrectNode": ColorsCorrectNode, |
|
"GoogleTranslateCLIPTextEncodeNode": GoogleTranslateCLIPTextEncodeNode, |
|
"GoogleTranslateTextNode": GoogleTranslateTextNode, |
|
"PainterNode": PainterNode, |
|
"PoseNode": PoseNode, |
|
"IDENode": IDENode, |
|
} |
|
|
|
|
|
NODE_DISPLAY_NAME_MAPPINGS = { |
|
"ArgosTranslateCLIPTextEncodeNode": "Argos Translate CLIP Text Encode Node", |
|
"ArgosTranslateTextNode": "Argos Translate Text Node", |
|
"DeepTranslatorCLIPTextEncodeNode": "Deep Translator CLIP Text Encode Node", |
|
"DeepTranslatorTextNode": "Deep Translator Text Node", |
|
"PreviewTextNode": "Preview Text Node", |
|
"HexToHueNode": "HEX to HUE Node", |
|
"ColorsCorrectNode": "Colors Correct Node", |
|
"GoogleTranslateCLIPTextEncodeNode": "Google Translate CLIP Text Encode Node", |
|
"GoogleTranslateTextNode": "Google Translate Text Node", |
|
"PainterNode": "Painter Node", |
|
"PoseNode": "Pose Node", |
|
"IDENode": "IDE Node", |
|
} |
|
|