126 lines
4.5 KiB
Python
126 lines
4.5 KiB
Python
# SimpleSyrup - workflow-focused ComfyUI extensions for image generation
|
|
# Copyright (C) 2026 Artificial Sweetener and contributors
|
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
"""Contract tests for package metadata and node-local requirements."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import tomllib
|
|
from importlib import import_module
|
|
from pathlib import Path
|
|
|
|
from packaging.requirements import Requirement
|
|
|
|
REPO_ROOT = Path(__file__).resolve().parents[1]
|
|
COMFY_ROOT = REPO_ROOT.parents[1]
|
|
EXPECTED_RUNTIME_REQUIREMENTS = (
|
|
"torchlanc",
|
|
"ultralytics",
|
|
"onnxruntime",
|
|
"segment-anything",
|
|
"timm",
|
|
"addict",
|
|
"yapf",
|
|
"huggingface-hub",
|
|
"keyring",
|
|
)
|
|
|
|
|
|
def _requirements(path: Path) -> tuple[Requirement, ...]:
|
|
"""Parse non-comment requirement lines from a requirements file."""
|
|
|
|
return tuple(
|
|
Requirement(line)
|
|
for line in path.read_text(encoding="utf-8").splitlines()
|
|
if line.strip() and not line.lstrip().startswith("#")
|
|
)
|
|
|
|
|
|
def test_requirements_are_node_local_and_do_not_duplicate_comfyui() -> None:
|
|
"""Keep SimpleSyrup requirements limited to packages ComfyUI does not own."""
|
|
|
|
simple_syrup_requirements = _requirements(REPO_ROOT / "requirements.txt")
|
|
comfy_requirements = _requirements(COMFY_ROOT / "requirements.txt")
|
|
comfy_names = {requirement.name.lower() for requirement in comfy_requirements}
|
|
|
|
assert (
|
|
tuple(requirement.name.lower() for requirement in simple_syrup_requirements)
|
|
== EXPECTED_RUNTIME_REQUIREMENTS
|
|
)
|
|
assert not {
|
|
requirement.name.lower()
|
|
for requirement in simple_syrup_requirements
|
|
if requirement.name.lower() in comfy_names
|
|
}
|
|
|
|
|
|
def test_pyproject_reads_runtime_dependencies_from_requirements_txt() -> None:
|
|
"""Use requirements.txt as the only runtime dependency source."""
|
|
|
|
pyproject = tomllib.loads((REPO_ROOT / "pyproject.toml").read_text("utf-8"))
|
|
|
|
assert pyproject["project"]["dynamic"] == ["dependencies"]
|
|
assert "dependencies" not in pyproject["project"]
|
|
assert pyproject["tool"]["setuptools"]["dynamic"]["dependencies"] == {
|
|
"file": ["requirements.txt"]
|
|
}
|
|
|
|
|
|
def test_pyproject_has_registry_ready_metadata() -> None:
|
|
"""Require Comfy Registry and package metadata needed for publication."""
|
|
|
|
pyproject = tomllib.loads((REPO_ROOT / "pyproject.toml").read_text("utf-8"))
|
|
|
|
assert pyproject["build-system"]["requires"] == ["setuptools>=77"]
|
|
assert pyproject["build-system"]["build-backend"] == "setuptools.build_meta"
|
|
assert pyproject["project"]["license"] == "AGPL-3.0-or-later"
|
|
assert pyproject["project"]["license-files"] == ["LICENSE"]
|
|
assert (
|
|
pyproject["project"]["description"]
|
|
== "Workflow-focused ComfyUI extensions for image generation."
|
|
)
|
|
assert pyproject["project"]["urls"]["Repository"].endswith("/SimpleSyrup")
|
|
assert pyproject["tool"]["comfy"]["PublisherId"] == "artificialsweetener"
|
|
assert pyproject["tool"]["comfy"]["DisplayName"] == "SimpleSyrup"
|
|
assert pyproject["tool"]["setuptools"]["packages"]["find"]["include"] == [
|
|
"simple_syrup*"
|
|
]
|
|
|
|
|
|
def test_frontend_package_metadata_matches_python_package_license() -> None:
|
|
"""Keep frontend package metadata aligned with the Python package license."""
|
|
|
|
pyproject = tomllib.loads((REPO_ROOT / "pyproject.toml").read_text("utf-8"))
|
|
package = json.loads((REPO_ROOT / "package.json").read_text(encoding="utf-8"))
|
|
|
|
assert package["private"] is True
|
|
assert package["license"] == pyproject["project"]["license"]
|
|
|
|
|
|
def test_package_versions_match_release_metadata() -> None:
|
|
"""Keep release-managed version fields aligned across package metadata."""
|
|
|
|
pyproject = tomllib.loads((REPO_ROOT / "pyproject.toml").read_text("utf-8"))
|
|
package = json.loads((REPO_ROOT / "package.json").read_text(encoding="utf-8"))
|
|
package_lock = json.loads(
|
|
(REPO_ROOT / "package-lock.json").read_text(encoding="utf-8")
|
|
)
|
|
simple_syrup = import_module("simple_syrup")
|
|
|
|
expected_version = pyproject["project"]["version"]
|
|
|
|
assert package["version"] == expected_version
|
|
assert package_lock["version"] == expected_version
|
|
assert package_lock["packages"][""]["version"] == expected_version
|
|
assert simple_syrup.__version__ == expected_version
|
|
|
|
|
|
def test_frontend_dist_bundle_is_tracked_for_comfy_serving() -> None:
|
|
"""ComfyUI serves the checked-in frontend bundle from WEB_DIRECTORY."""
|
|
|
|
dist_bundle = REPO_ROOT / "web" / "dist" / "simple-syrup.js"
|
|
|
|
assert dist_bundle.is_file()
|