New nodes: - Isulion Censored Part: blur/pixelate/black bar/noise over a mask and/or a percent rectangle; accepts 2D/3D/4D masks and fails closed (blacks the item out) instead of passing an uncensored image through - Prompt Vault Save/Load: named prompt library stored in ComfyUI's user directory (outside the checkout, so updates never conflict), seeded from prompt_vault.example.json; Load re-runs when the vault changes Refactor: - SimpleSelectorNode base: ~20 selector nodes use an instance RNG instead of reseeding the global random module (same seed => same output) - Theme handlers declare DISPLAY_NAME; theme package auto-discovers modules - __init__ imports node classes directly Fixes: - net_utils: re-validate every redirect hop, unwrap IPv4-mapped IPv6, block NAT64 and all non-global addresses (SSRF) - Multiple Prompt Generator: no duplicate prompts for themes listed in two categories; 6 themes missing from every category are now reachable - Shutdown node: parameter renamed to match its "any" input (TypeError) - ConfigManager: deterministic (sorted) merge order, warns on key collisions; drop stale space_colony copy from tropical_paradise_config - Mega Prompt V3: seed honored again with randomize=disable Breaking: Civitai api_key widget removed (use CIVITAI_API_TOKEN), absolute paths refused by Load Images, Negative Prompt pools de-duplicated (shorter "strict" output), Dynamic Random theme order is now alphabetical. Tooling: pytest suite (51 tests), GitHub CI (compileall, pytest, ruff), ruff config, uv.lock. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
39 lines
1.3 KiB
Python
39 lines
1.3 KiB
Python
"""Saved-workflow compatibility guard.
|
|
|
|
Every node's ``INPUT_TYPES()`` must exactly match the v2 contract snapshot
|
|
(``tests/fixtures/node_contracts_v2.json``). The diff against the older v1
|
|
baseline (removal of the Civitai ``api_key`` widget) is intentional: secrets
|
|
must never be embedded in saved workflows, so v2 is the source of truth.
|
|
"""
|
|
|
|
from isulion_testkit import import_package, load_fixture, normalize_json
|
|
|
|
|
|
def test_input_types_match_v2_contracts_exactly():
|
|
pkg = import_package()
|
|
contracts = load_fixture("node_contracts_v2.json")
|
|
assert set(pkg.NODE_CLASS_MAPPINGS.keys()) == set(contracts.keys()), (
|
|
"node registry and node_contracts_v2.json fixture disagree on key set"
|
|
)
|
|
|
|
mismatches = {}
|
|
for name in sorted(contracts):
|
|
cls = pkg.NODE_CLASS_MAPPINGS[name]
|
|
actual = normalize_json(cls.INPUT_TYPES())
|
|
if actual != contracts[name]:
|
|
mismatches[name] = {
|
|
"actual": actual,
|
|
"expected": contracts[name],
|
|
}
|
|
|
|
assert not mismatches, (
|
|
"INPUT_TYPES drifted from node_contracts_v2.json for: "
|
|
f"{sorted(mismatches)}\n"
|
|
+ "\n".join(
|
|
f"--- {name} ---\n"
|
|
f"actual : {mismatches[name]['actual']}\n"
|
|
f"expected: {mismatches[name]['expected']}"
|
|
for name in sorted(mismatches)
|
|
)
|
|
)
|