Files
jaidaken f09734b0ee
Some checks failed
Python Linting / Run Ruff (push) Has been cancelled
Python Linting / Run Pylint (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.10, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.11, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.12, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-unix-nightly (12.1, , linux, 3.11, [self-hosted Linux], nightly) (push) Has been cancelled
Execution Tests / test (macos-latest) (push) Has been cancelled
Execution Tests / test (ubuntu-latest) (push) Has been cancelled
Execution Tests / test (windows-latest) (push) Has been cancelled
Test server launches without errors / test (push) Has been cancelled
Unit Tests / test (macos-latest) (push) Has been cancelled
Unit Tests / test (ubuntu-latest) (push) Has been cancelled
Unit Tests / test (windows-2022) (push) Has been cancelled
Add custom nodes, Civitai loras (LFS), and vast.ai setup script
Includes 30 custom nodes committed directly, 7 Civitai-exclusive
loras stored via Git LFS, and a setup script that installs all
dependencies and downloads HuggingFace-hosted models on vast.ai.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 00:56:42 +00:00

175 lines
4.9 KiB
Python

"""
Setup for the ComfyUI engine and shared test fixtures.
"""
import os
import sys
from pathlib import Path
import pytest
import asyncio
import logging
from setup_utils import SilenceLogs, execute
from hf_downloader import download_test_images
from configs import DirectoryConfig
# Because of manipulations to sys.path, non-packaged imports should be delayed to avoid import issues
#
# # Configuration
#
TEST_CHECKPOINT = "v1-5-pruned-emaonly-fp16.safetensors"
TEST_UPSCALE_MODEL = "4x-UltraSharp.pth"
SAMPLE_IMAGE_SUBDIR = "sample_images"
TEST_IMAGE_SUBDIR = "test_images"
# conftest.py is in repo_root/test/ directory
REPO_ROOT = Path(__file__).parent.parent.resolve()
COMFYUI_ROOT = REPO_ROOT.parent.parent.resolve()
# Make sure the repo root is in sys.path for imports
# Ensure submodule root is in path for test imports
if str(REPO_ROOT) not in sys.path:
sys.path.insert(0, str(REPO_ROOT))
# Ensure ComfyUI path is set up
if str(COMFYUI_ROOT) not in sys.path:
sys.path.insert(0, str(COMFYUI_ROOT))
# Session scoped fixtures
from fixtures_images import base_image
def pytest_configure(config):
"""Called before test collection begins."""
# Download test images
download_test_images(
repo_id="ssitu/ultimatesdupscale_test",
save_dir=(REPO_ROOT / "test" / "test_images").resolve(),
repo_folder="test_images",
)
from comfy.cli_args import args
# args.cpu = True # Force CPU mode for tests
# args.force_fp16 = True # Force float16 mode for tests
args.disable_all_custom_nodes = True
# Assumes the name of the custom node folder is ComfyUI_UltimateSDUpscale
args.whitelist_custom_nodes = ["ComfyUI_UltimateSDUpscale"]
#
# # Path Setup
#
def _setup_comfyui_paths():
"""Configure ComfyUI folder paths for testing."""
# Ensure modules containing a utils.py are NOT in sys.path
# The comfy directory must be removed to prevent comfy/utils.py from shadowing
# ComfyUI's utils/ package directory when we import utils.extra_config
to_remove = [
str(COMFYUI_ROOT / "comfy"),
]
for path_to_remove in to_remove:
while path_to_remove in sys.path:
sys.path.remove(path_to_remove)
# Ensure ComfyUI is in path
if str(COMFYUI_ROOT) not in sys.path:
sys.path.insert(0, str(COMFYUI_ROOT))
# Apply custom paths
# main.py will trigger a warning that torch was already imported, probably by pytest. Shouldn't be a problem as far as I know.
from main import apply_custom_paths
apply_custom_paths()
#
# # Fixtures
#
@pytest.fixture(scope="session")
def comfyui_initialized():
"""Initialize ComfyUI nodes once per test session."""
from nodes import init_extra_nodes
_setup_comfyui_paths()
async def _init():
with SilenceLogs():
await init_extra_nodes(init_api_nodes=False)
asyncio.run(_init())
yield True
@pytest.fixture(scope="session")
def node_classes(comfyui_initialized):
"""Get ComfyUI node class mappings."""
from nodes import NODE_CLASS_MAPPINGS
return NODE_CLASS_MAPPINGS
@pytest.fixture(scope="session")
def test_checkpoint():
"""Find and return a valid test checkpoint."""
import folder_paths
checkpoints = folder_paths.get_filename_list("checkpoints")
# TODO: Should probably use a hash instead of matching the filename
if TEST_CHECKPOINT not in checkpoints:
pytest.skip(f"No test checkpoint found. Please add {TEST_CHECKPOINT}")
return TEST_CHECKPOINT
@pytest.fixture(scope="session")
def loaded_checkpoint(comfyui_initialized, test_checkpoint, node_classes):
"""Load checkpoint and return (model, clip, vae) tuple."""
import torch
with torch.inference_mode():
CheckpointLoaderSimple = node_classes["CheckpointLoaderSimple"]
model, clip, vae = execute(CheckpointLoaderSimple, test_checkpoint)
return model, clip, vae
@pytest.fixture(scope="session")
def upscale_model(comfyui_initialized, node_classes):
"""Load the first available upscale model."""
import torch
import folder_paths
UpscaleModelLoader = node_classes["UpscaleModelLoader"]
upscale_models = folder_paths.get_filename_list("upscale_models")
# TODO: Should probably use a hash instead of matching the filename
if TEST_UPSCALE_MODEL not in upscale_models:
pytest.skip("No upscale models found")
model_name = upscale_models[0]
with torch.inference_mode():
(model,) = execute(UpscaleModelLoader, model_name)
return model
@pytest.fixture(scope="session")
def test_dirs():
"""Return paths to test and sample image directories."""
test_dir = REPO_ROOT / "test"
test_image_dir = test_dir / TEST_IMAGE_SUBDIR
sample_image_dir = test_dir / SAMPLE_IMAGE_SUBDIR
sample_image_dir.mkdir(exist_ok=True)
return DirectoryConfig(
test_images=test_image_dir,
sample_images=sample_image_dir,
)
@pytest.fixture(scope="session")
def seed():
"""Default seed for reproducible tests."""
return 1