mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-21 21:22:11 -03:00
- Add _get_gguf_path() to dynamically derive ComfyUI-GGUF path from current file location - Remove Strategy 2 and 3, keeping only Strategy 1 (sys.modules path-based lookup) - Remove hard-coded absolute paths - Streamline logging output - Code cleanup: reduced from 235 to 154 lines
162 lines
5.5 KiB
Python
162 lines
5.5 KiB
Python
"""
|
|
Helper module to safely import ComfyUI-GGUF modules.
|
|
|
|
This module provides a robust way to import ComfyUI-GGUF functionality
|
|
regardless of how ComfyUI loaded it.
|
|
"""
|
|
|
|
import sys
|
|
import os
|
|
import importlib.util
|
|
import logging
|
|
from typing import Optional, Tuple, Any
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def _get_gguf_path() -> str:
|
|
"""Get the path to ComfyUI-GGUF based on this file's location.
|
|
|
|
Since ComfyUI-Lora-Manager and ComfyUI-GGUF are both in custom_nodes/,
|
|
we can derive the GGUF path from our own location.
|
|
"""
|
|
# This file is at: custom_nodes/ComfyUI-Lora-Manager/py/nodes/gguf_import_helper.py
|
|
# ComfyUI-GGUF is at: custom_nodes/ComfyUI-GGUF
|
|
current_file = os.path.abspath(__file__)
|
|
# Go up 4 levels: nodes -> py -> ComfyUI-Lora-Manager -> custom_nodes
|
|
custom_nodes_dir = os.path.dirname(
|
|
os.path.dirname(os.path.dirname(os.path.dirname(current_file)))
|
|
)
|
|
return os.path.join(custom_nodes_dir, "ComfyUI-GGUF")
|
|
|
|
|
|
def _find_gguf_module() -> Optional[Any]:
|
|
"""Find ComfyUI-GGUF module in sys.modules.
|
|
|
|
ComfyUI registers modules using the full path with dots replaced by _x_.
|
|
"""
|
|
gguf_path = _get_gguf_path()
|
|
sys_module_name = gguf_path.replace(".", "_x_")
|
|
|
|
logger.debug(f"[GGUF Import] Looking for module '{sys_module_name}' in sys.modules")
|
|
if sys_module_name in sys.modules:
|
|
logger.info(f"[GGUF Import] Found module: '{sys_module_name}'")
|
|
return sys.modules[sys_module_name]
|
|
|
|
logger.debug(f"[GGUF Import] Module not found: '{sys_module_name}'")
|
|
return None
|
|
|
|
|
|
def _load_gguf_modules_directly() -> Optional[Any]:
|
|
"""Load ComfyUI-GGUF modules directly from file paths."""
|
|
gguf_path = _get_gguf_path()
|
|
|
|
logger.info(f"[GGUF Import] Direct Load: Attempting to load from '{gguf_path}'")
|
|
|
|
if not os.path.exists(gguf_path):
|
|
logger.warning(f"[GGUF Import] Path does not exist: {gguf_path}")
|
|
return None
|
|
|
|
try:
|
|
namespace = "ComfyUI_GGUF_Dynamic"
|
|
init_path = os.path.join(gguf_path, "__init__.py")
|
|
|
|
if not os.path.exists(init_path):
|
|
logger.warning(f"[GGUF Import] __init__.py not found at '{init_path}'")
|
|
return None
|
|
|
|
logger.debug(f"[GGUF Import] Loading from '{init_path}'")
|
|
spec = importlib.util.spec_from_file_location(namespace, init_path)
|
|
if not spec or not spec.loader:
|
|
logger.error(f"[GGUF Import] Failed to create spec for '{init_path}'")
|
|
return None
|
|
|
|
package = importlib.util.module_from_spec(spec)
|
|
package.__path__ = [gguf_path]
|
|
sys.modules[namespace] = package
|
|
spec.loader.exec_module(package)
|
|
logger.debug(f"[GGUF Import] Loaded main package '{namespace}'")
|
|
|
|
# Load submodules
|
|
loaded = []
|
|
for submod_name in ["loader", "ops", "nodes"]:
|
|
submod_path = os.path.join(gguf_path, f"{submod_name}.py")
|
|
if os.path.exists(submod_path):
|
|
submod_spec = importlib.util.spec_from_file_location(
|
|
f"{namespace}.{submod_name}", submod_path
|
|
)
|
|
if submod_spec and submod_spec.loader:
|
|
submod = importlib.util.module_from_spec(submod_spec)
|
|
submod.__package__ = namespace
|
|
sys.modules[f"{namespace}.{submod_name}"] = submod
|
|
submod_spec.loader.exec_module(submod)
|
|
setattr(package, submod_name, submod)
|
|
loaded.append(submod_name)
|
|
logger.debug(f"[GGUF Import] Loaded submodule '{submod_name}'")
|
|
|
|
logger.info(f"[GGUF Import] Direct Load success: {loaded}")
|
|
return package
|
|
|
|
except Exception as e:
|
|
logger.error(f"[GGUF Import] Direct Load failed: {e}", exc_info=True)
|
|
return None
|
|
|
|
|
|
def get_gguf_modules() -> Tuple[Any, Any, Any]:
|
|
"""Get ComfyUI-GGUF modules (loader, ops, nodes).
|
|
|
|
Returns:
|
|
Tuple of (loader_module, ops_module, nodes_module)
|
|
|
|
Raises:
|
|
RuntimeError: If ComfyUI-GGUF cannot be found or loaded.
|
|
"""
|
|
logger.debug("[GGUF Import] Starting module search...")
|
|
|
|
# Try to find already loaded module first
|
|
gguf_module = _find_gguf_module()
|
|
|
|
if gguf_module is None:
|
|
logger.info("[GGUF Import] Not found in sys.modules, trying direct load...")
|
|
gguf_module = _load_gguf_modules_directly()
|
|
|
|
if gguf_module is None:
|
|
raise RuntimeError(
|
|
"ComfyUI-GGUF is not installed. "
|
|
"Please install from https://github.com/city96/ComfyUI-GGUF"
|
|
)
|
|
|
|
# Extract submodules
|
|
loader = getattr(gguf_module, "loader", None)
|
|
ops = getattr(gguf_module, "ops", None)
|
|
nodes = getattr(gguf_module, "nodes", None)
|
|
|
|
if loader is None or ops is None or nodes is None:
|
|
missing = [
|
|
name
|
|
for name, mod in [("loader", loader), ("ops", ops), ("nodes", nodes)]
|
|
if mod is None
|
|
]
|
|
raise RuntimeError(f"ComfyUI-GGUF missing submodules: {missing}")
|
|
|
|
logger.debug("[GGUF Import] All modules loaded successfully")
|
|
return loader, ops, nodes
|
|
|
|
|
|
def get_gguf_sd_loader():
|
|
"""Get the gguf_sd_loader function from ComfyUI-GGUF."""
|
|
loader, _, _ = get_gguf_modules()
|
|
return getattr(loader, "gguf_sd_loader")
|
|
|
|
|
|
def get_ggml_ops():
|
|
"""Get the GGMLOps class from ComfyUI-GGUF."""
|
|
_, ops, _ = get_gguf_modules()
|
|
return getattr(ops, "GGMLOps")
|
|
|
|
|
|
def get_gguf_model_patcher():
|
|
"""Get the GGUFModelPatcher class from ComfyUI-GGUF."""
|
|
_, _, nodes = get_gguf_modules()
|
|
return getattr(nodes, "GGUFModelPatcher")
|