extra libs installation dir

This commit is contained in:
Ahmed 2026-02-23 05:31:48 +02:00
parent 0ef2235588
commit 607d73a7d8
3 changed files with 154 additions and 15 deletions

View File

@ -192,6 +192,8 @@ if comfy_path is None:
if comfy_base_path is None:
comfy_base_path = comfy_path
manager_util.ensure_comfy_libs_path(os.path.join(comfy_base_path, 'custom_nodes'))
channel_list_template_path = os.path.join(manager_util.comfyui_manager_path, 'channels.list.template')
git_script_path = os.path.join(manager_util.comfyui_manager_path, "git_helper.py")
@ -939,9 +941,10 @@ class UnifiedManager:
if package_name and not package_name.startswith('#') and package_name not in self.processed_install:
self.processed_install.add(package_name)
clean_package_name = package_name.split('#')[0].strip()
install_cmd = manager_util.make_pip_cmd(["install", clean_package_name])
install_cmd = manager_util.make_pip_install_cmd(clean_package_name, get_default_custom_nodes_path())
if clean_package_name != "" and not clean_package_name.startswith('#'):
res = res and try_install_script(url, repo_path, install_cmd, instant_execution=instant_execution)
if install_cmd is not None:
res = res and try_install_script(url, repo_path, install_cmd, instant_execution=instant_execution)
pip_fixer.fix_broken()
@ -1993,14 +1996,11 @@ def execute_install_script(url, repo_path, lazy_mode=False, instant_execution=Fa
package_name = remap_pip_package(line.strip())
if package_name and not package_name.startswith('#'):
if '--index-url' in package_name:
s = package_name.split('--index-url')
install_cmd = manager_util.make_pip_cmd(["install", s[0].strip(), '--index-url', s[1].strip()])
else:
install_cmd = manager_util.make_pip_cmd(["install", package_name])
install_cmd = manager_util.make_pip_install_cmd(package_name, get_default_custom_nodes_path())
if package_name.strip() != "" and not package_name.startswith('#'):
try_install_script(url, repo_path, install_cmd, instant_execution=instant_execution)
if install_cmd is not None:
try_install_script(url, repo_path, install_cmd, instant_execution=instant_execution)
pip_fixer.fix_broken()
if os.path.exists(install_script_path):

View File

@ -16,6 +16,8 @@ import logging
import platform
import shlex
from functools import lru_cache
from pathlib import Path
from importlib import metadata
cache_lock = threading.Lock()
@ -25,6 +27,7 @@ cache_dir = os.path.join(comfyui_manager_path, '.cache') # This path is also up
use_uv = False
bypass_ssl = False
libs_map = None
def add_python_path_to_env():
if platform.system() != "Windows":
@ -35,6 +38,81 @@ def add_python_path_to_env():
os.environ['PATH'] = os.path.dirname(sys.executable)+sep+os.environ['PATH']
def normalize_package_name(name: str) -> str:
return name.lower().replace('-', '_').strip()
def is_comfy_libs_enabled() -> bool:
value = os.environ.get("COMFY_LIBS", "")
return value.lower() == "true"
def get_comfy_libs_path(custom_nodes_base_path: str = None) -> str:
if custom_nodes_base_path:
base_dir = os.path.dirname(os.path.abspath(custom_nodes_base_path))
return os.path.join(base_dir, "libs")
comfy_base_path = os.environ.get('COMFYUI_FOLDERS_BASE_PATH') or os.environ.get('COMFYUI_PATH')
if comfy_base_path:
return os.path.join(os.path.abspath(comfy_base_path), "libs")
try:
import folder_paths
custom_nodes_path = folder_paths.get_folder_paths("custom_nodes")[0]
return os.path.join(os.path.dirname(os.path.abspath(custom_nodes_path)), "libs")
except Exception:
# fallback: .../ComfyUI/custom_nodes/ComfyUI-Manager/glob -> .../ComfyUI/libs
return os.path.abspath(os.path.join(comfyui_manager_path, "..", "..", "libs"))
def ensure_comfy_libs_path(custom_nodes_base_path: str = None) -> str | None:
if not is_comfy_libs_enabled():
return None
libs_path = get_comfy_libs_path(custom_nodes_base_path)
os.makedirs(libs_path, exist_ok=True)
if libs_path not in sys.path:
sys.path.insert(0, libs_path)
py_path = os.environ.get("PYTHONPATH", "")
py_parts = py_path.split(os.pathsep) if py_path else []
if libs_path not in py_parts:
os.environ["PYTHONPATH"] = libs_path if not py_path else libs_path + os.pathsep + py_path
return libs_path
def get_comfy_libs_packages(renew=False, custom_nodes_base_path: str = None):
global libs_map
if not is_comfy_libs_enabled():
return {}
if renew or libs_map is None:
libs_map = {}
libs_path = ensure_comfy_libs_path(custom_nodes_base_path)
if libs_path is None:
return {}
try:
for dist in metadata.distributions(path=[libs_path]):
name = dist.metadata.get("Name")
version = dist.version
if name and version:
libs_map[normalize_package_name(name)] = version
except Exception:
# fallback: best-effort from dist-info folder names
try:
for item in Path(libs_path).glob("*.dist-info"):
name = item.name.split("-")[0]
libs_map[normalize_package_name(name)] = "0"
except Exception:
pass
return libs_map
@lru_cache(maxsize=2)
def get_pip_cmd(force_uv=False):
"""
@ -94,6 +172,62 @@ def make_pip_cmd(cmd):
return base_cmd + cmd
def get_install_target_for_package(requirement: str, custom_nodes_base_path: str = None):
"""
Return a custom libs target path when COMFY_LIBS is enabled and package does not exist
in either site-packages or libs.
"""
if not is_comfy_libs_enabled():
return None
try:
parsed = parse_requirement_line(requirement)
pkg_name = normalize_package_name(parsed['package']) if parsed is not None else None
except Exception:
pkg_name = None
if pkg_name is None:
# Fallback for non-StrictVersion requirement specs.
match = re.match(r'^([A-Za-z0-9_.+-]+)', requirement)
if match is None:
return None
pkg_name = normalize_package_name(match.group(1))
installed = get_installed_packages().get(pkg_name)
if installed is not None:
return None
libs_packages = get_comfy_libs_packages(custom_nodes_base_path=custom_nodes_base_path)
if pkg_name in libs_packages:
return None
return ensure_comfy_libs_path(custom_nodes_base_path)
def make_pip_install_cmd(requirement: str, custom_nodes_base_path: str = None):
"""
Build a pip install command from a requirement expression.
Applies --target <libs> when COMFY_LIBS=True and the package is not installed.
"""
requirement = requirement.split('#')[0].strip()
if requirement == "" or requirement.startswith("#"):
return None
install_args = ["install"]
target = get_install_target_for_package(requirement, custom_nodes_base_path=custom_nodes_base_path)
if target is not None:
install_args += ["--target", target]
if '--index-url' in requirement:
s = requirement.split('--index-url', 1)
package = s[0].strip()
index_url = s[1].strip()
install_args += [package, '--index-url', index_url]
else:
install_args += [requirement]
return make_pip_cmd(install_args)
# DON'T USE StrictVersion - cannot handle pre_release version
# try:
# from distutils.version import StrictVersion
@ -305,12 +439,19 @@ def get_installed_packages(renew=False):
logging.error("[ComfyUI-Manager] Failed to retrieve the information of installed pip packages.")
return {}
if is_comfy_libs_enabled():
for name, ver in get_comfy_libs_packages(renew=renew).items():
if name not in pip_map:
pip_map[name] = ver
return pip_map
def clear_pip_cache():
global pip_map
global libs_map
pip_map = None
libs_map = None
def parse_requirement_line(line):
@ -630,4 +771,4 @@ def restore_pip_snapshot(pips, options):
if res != 0:
failed.append(x)
print(f"Installation failed for pip packages: {failed}")
print(f"Installation failed for pip packages: {failed}")

View File

@ -85,6 +85,7 @@ cm_global.register_api('cm.is_import_failed_extension', is_import_failed_extensi
comfyui_manager_path = os.path.abspath(os.path.dirname(__file__))
custom_nodes_base_path = folder_paths.get_folder_paths('custom_nodes')[0]
manager_util.ensure_comfy_libs_path(custom_nodes_base_path)
# Check for System User API availability (PR #10966)
_has_system_user_api = hasattr(folder_paths, 'get_system_user_directory')
@ -642,13 +643,10 @@ def execute_lazy_install_script(repo_path, executable):
package_name = remap_pip_package(line.strip())
package_name = package_name.split('#')[0].strip()
if package_name and not is_installed(package_name):
if '--index-url' in package_name:
s = package_name.split('--index-url')
install_cmd = manager_util.make_pip_cmd(["install", s[0].strip(), '--index-url', s[1].strip()])
else:
install_cmd = manager_util.make_pip_cmd(["install", package_name])
install_cmd = manager_util.make_pip_install_cmd(package_name, custom_nodes_base_path)
process_wrap(install_cmd, repo_path)
if install_cmd is not None:
process_wrap(install_cmd, repo_path)
if os.path.exists(install_script_path) and f'{repo_path}/install.py' not in processed_install:
processed_install.add(f'{repo_path}/install.py')