Files
82dfce256f feat: new tests for nunchaku comfyui from lmxyy & ttio2tech, tested and verified on comfyui 0.3.63 upstream and 0.3.60 LTS (#641) (#650)
* bump requires-python

* model patcher now implements everything it needs for comfyui

* index

* Support LTS and Vanilla ComfyUI

* Fix version string when installed as package (not material)

* style: make linter happy

* update init.py

* Update nunchaku index

* Bump dependencies, include config and workflows when installed using pip/uv

* Update installation instructions to include ComfyUI LTS

* Update requirements for nunchaku>=1.0.1

* Fix torch210 key

* Fix pep 508 spec

* Improve tests (still more to go)

* Fix comfyui_controlnet_aux flaws

* Update tests (all should pass)

* Organize the tests in this runner

* Update contribution guide

* Install uv

* Dependencies now resolve with correct conflicts with uv's most stringent resolution

* Mediapipe hasn't been built for 3.13 yet, so we can't use it here

* Remove controlnet-aux dep

* make linter happy

* make the linter happy

* optimize the loading

* update installation

* update

* update contribution guide

* update qwenimage

* need to figure out why the toml parsing doesn't owk

* update

* update

* update

* style: make linter happy

* update

* add pulid requirement

* update docs

* update

* update

* update

* update

* update

* organize the pyproject.toml

* update

* update

* update

* passing all tests

* update

* update

* update

* update

* update

* remove a useless class

* update

* update

* fix a typo

---------

Co-authored-by: doctorpangloss <@hiddenswitch.com>
Co-authored-by: doctorpangloss <2229300+doctorpangloss@users.noreply.github.com>
2025-10-14 00:46:20 -04:00

147 lines
4.7 KiB
Python
Executable File

#!/usr/bin/env python3
"""
Script to clone custom nodes from test_data/custom_nodes.yaml,
checkout to specified commits, and install dependencies.
"""
import subprocess
import sys
from pathlib import Path
import yaml
def run_command(cmd, cwd=None, check=True):
"""Run a shell command and return the result."""
print(f"Running: {' '.join(cmd)}")
result = subprocess.run(cmd, cwd=cwd, capture_output=True, text=True, check=check)
if result.stdout:
print(result.stdout)
if result.stderr:
print(result.stderr, file=sys.stderr)
return result
def clone_and_setup_node(node_info, custom_nodes_dir, dependencies_dir):
"""Clone a node repository, checkout to specified commit, and install dependencies."""
name = node_info["name"]
url = node_info["url"]
branch = node_info.get("branch", "main")
node_path = custom_nodes_dir / name
print(f"\n{'='*60}")
print(f"Setting up: {name}")
print(f"{'='*60}")
# Clone repository if it doesn't exist
if not node_path.exists():
print(f"Cloning {name} from {url}...")
try:
run_command(["git", "clone", url, str(node_path)])
except subprocess.CalledProcessError as e:
print(f"Error cloning {name}: {e}", file=sys.stderr)
return False
else:
print(f"{name} already exists at {node_path}")
# Checkout to specified commit/branch
print(f"Checking out to {branch}...")
try:
run_command(["git", "fetch", "--all"], cwd=node_path)
run_command(["git", "checkout", branch], cwd=node_path)
except subprocess.CalledProcessError as e:
print(f"Error checking out {branch} for {name}: {e}", file=sys.stderr)
return False
# Install dependencies
print(f"Installing dependencies for {name}...")
# Check if custom dependency file exists in test_data/dependencies
custom_deps_file = dependencies_dir / f"{name}.txt"
if custom_deps_file.exists():
print(f"Using custom dependencies from {custom_deps_file}")
try:
run_command(["uv", "pip", "install", "-r", str(custom_deps_file)])
except subprocess.CalledProcessError as e:
print(f"Error installing dependencies from {custom_deps_file}: {e}", file=sys.stderr)
return False
else:
# Fall back to requirements.txt in the repository
requirements_file = node_path / "requirements.txt"
if requirements_file.exists():
print(f"Using requirements.txt from repository: {requirements_file}")
try:
run_command(["uv", "pip", "install", "-r", str(requirements_file)])
except subprocess.CalledProcessError as e:
print(f"Error installing dependencies from {requirements_file}: {e}", file=sys.stderr)
return False
else:
print(f"No requirements.txt found for {name}, skipping dependency installation")
print(f"✓ Successfully set up {name}")
return True
def main():
# Get project root directory (parent of scripts/)
script_dir = Path(__file__).parent
project_root = script_dir.parent
# Define paths
custom_nodes_yaml = project_root / "test_data" / "custom_nodes.yaml"
dependencies_dir = project_root / "test_data" / "dependencies"
custom_nodes_dir = Path("custom_nodes")
# Verify required files exist
if not custom_nodes_yaml.exists():
print(f"Error: {custom_nodes_yaml} not found!", file=sys.stderr)
sys.exit(1)
# Create custom_nodes directory if it doesn't exist
custom_nodes_dir.mkdir(exist_ok=True)
# Load custom nodes configuration
print(f"Loading configuration from {custom_nodes_yaml}...")
with open(custom_nodes_yaml, "r") as f:
config = yaml.safe_load(f)
nodes = config.get("nodes", [])
if not nodes:
print("No nodes found in configuration")
sys.exit(0)
print(f"Found {len(nodes)} node(s) to set up")
# Process each node
success_count = 0
failed_nodes = []
for node_info in nodes:
success = clone_and_setup_node(node_info, custom_nodes_dir, dependencies_dir)
if success:
success_count += 1
else:
failed_nodes.append(node_info["name"])
# Print summary
print(f"\n{'='*60}")
print("SUMMARY")
print(f"{'='*60}")
print(f"Total nodes: {len(nodes)}")
print(f"Successfully set up: {success_count}")
print(f"Failed: {len(failed_nodes)}")
if failed_nodes:
print("\nFailed nodes:")
for name in failed_nodes:
print(f" - {name}")
sys.exit(1)
else:
print("\n✓ All nodes set up successfully!")
if __name__ == "__main__":
main()