Files
ausboss 7a1f89ab15 Skip a second install of the pack instead of stopping ComfyUI
Manager installs the pack in custom_nodes/ausboss-nodes and a git clone
lands in custom_nodes/ComfyUI-AusBoss. With both folders present, both
copies registered GET /ausboss/pack_modules and ComfyUI stopped at
startup: "Added route will never be executed, method HEAD is already
registered".

The first copy to load claims a marker in sys.modules. A later copy
loads no node modules, registers no routes, serves no js folder, and
prints which folder it skipped.
2026-11-09 15:21:25 -06:00

151 lines
4.7 KiB
Python

"""ComfyUI-AusBoss entry point.
Every node lives in its own file under nodes/ and exports its own
NODE_CLASS_MAPPINGS / NODE_DISPLAY_NAME_MAPPINGS. This file merges them
and hands the result to ComfyUI. To register a new node, add its module
name to NODE_MODULES below — nothing else to wire up.
A module that fails to import is skipped with a console warning instead
of taking the whole pack down, so one broken node never hides the rest.
Only one copy of the pack loads. People install it from ComfyUI-Manager
(custom_nodes/ausboss-nodes) and from GitHub (custom_nodes/ComfyUI-AusBoss),
and two copies used to register the same server routes, which stopped
ComfyUI at startup. A second copy now loads nothing and says which folder
to delete.
"""
import importlib
import os
import sys
import tomllib
import traceback
import types
_HERE = os.path.dirname(os.path.abspath(__file__))
_FIRST_COPY = sys.modules.setdefault(
"_ausboss_nodes_first_copy", types.SimpleNamespace(folder=_HERE)
)
_IS_SECOND_COPY = _FIRST_COPY.folder != _HERE
# One entry per file in nodes/, kept alphabetical. The order has no
# functional effect.
NODE_MODULES = [
"node_align_image",
"node_batch_utils",
"node_callout",
"node_color_match",
"node_compare",
"node_frame_interpolate",
"node_free_memory",
"node_h3_prompt_writer",
"node_image_crop_rotate_pad",
"node_image_folder",
"node_image_resize",
"node_image_size",
"node_inpaint_crop_stitch",
"node_krea2_encode",
"node_krea2_model_patch",
"node_lama_inpaint",
"node_layout_boxes",
"node_literals",
"node_load_image_pad",
"node_load_audio",
"node_load_video",
"node_lora_loader",
"node_mask_by_name",
"node_mask_by_touch",
"node_math",
"node_realign_to_source",
"node_refine_mask",
"node_resolution",
"node_run_timer",
"node_save_image",
"node_save_video",
"node_seed",
"node_select_frame",
"node_show_text",
"node_step_preview",
"node_tiled_upscale",
"node_video_crop_rotate_pad",
"node_video_crop_rotate_pad_clip",
"node_workflow_note",
"node_workflow_switches",
]
NODE_CLASS_MAPPINGS = {}
NODE_DISPLAY_NAME_MAPPINGS = {}
_failed_modules = []
for _module_name in NODE_MODULES:
if _IS_SECOND_COPY:
break
try:
_module = importlib.import_module(f".nodes.{_module_name}", __name__)
NODE_CLASS_MAPPINGS.update(getattr(_module, "NODE_CLASS_MAPPINGS", {}))
NODE_DISPLAY_NAME_MAPPINGS.update(
getattr(_module, "NODE_DISPLAY_NAME_MAPPINGS", {})
)
except Exception:
_failed_modules.append(_module_name)
traceback.print_exc()
# Folder ComfyUI serves to the browser; every .js file in it is loaded as a
# frontend extension. Shared modules use .mjs so they are import-only.
WEB_DIRECTORY = None if _IS_SECOND_COPY else "./js"
__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS", "WEB_DIRECTORY"]
def _read_version(folder=None):
"""Version straight from pyproject.toml so it is never duplicated."""
try:
pyproject = os.path.join(folder or os.path.dirname(__file__), "pyproject.toml")
with open(pyproject, "rb") as f:
version = tomllib.load(f).get("project", {}).get("version")
return version if isinstance(version, str) and version.strip() else "unknown"
except Exception:
return "unknown"
def _print_banner():
# ASCII only in here: ComfyUI on Windows often runs with a cp1252
# console, and a UnicodeEncodeError at import time kills the whole pack.
teal = "\033[38;2;0;180;170m"
grey = "\033[0;37m"
red = "\033[0;31m"
reset = "\033[0m"
bar = f"{teal}{'-' * 70}{reset}"
print(bar)
if _IS_SECOND_COPY:
def where(folder):
text = f"{os.path.basename(folder)} (v{_read_version(folder)})"
return text.encode("ascii", "replace").decode("ascii")
print(f" {red}AusBoss is installed twice, so this copy is not loaded.{reset}")
print(f" In use: custom_nodes/{where(_FIRST_COPY.folder)}")
print(f" Skipped: custom_nodes/{where(_HERE)}")
print(" Delete one of the two folders and restart ComfyUI.")
print(bar)
return
print(
f" {teal}AusBoss{reset} v{_read_version()} | "
f"{len(NODE_CLASS_MAPPINGS)} nodes loaded"
)
if _failed_modules:
print(f" {red}Failed to load: {', '.join(_failed_modules)}{reset}")
print(f" {grey}https://github.com/ausboss/ComfyUI-AusBoss{reset}")
print(bar)
try:
if not _IS_SECOND_COPY:
from .nodes._frontend_cache import register_frontend_cache_guard
register_frontend_cache_guard()
except Exception:
traceback.print_exc()
_print_banner()