Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
94 lines
3.3 KiB
Python
94 lines
3.3 KiB
Python
"""Tag and strip, for BOTH shapes of hook ComfyUI offers.
|
|
|
|
Keyed wrappers can be removed by name. The function lists on model_options
|
|
cannot: `set_model_sampler_pre_cfg_function` appends an anonymous callable and
|
|
records nothing about who added it. That second shape is how the accumulation bug
|
|
came back a third time -- a model run through the loader twice carried two copies
|
|
and applied the effect at double strength while reporting once.
|
|
"""
|
|
|
|
import pytest
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def _needs_comfy(comfyui):
|
|
"""Imports comfy."""
|
|
|
|
|
|
def test_a_tagged_pre_cfg_hook_is_removed(patcher):
|
|
from core import patching
|
|
|
|
def hook(args):
|
|
return args["conds_out"]
|
|
|
|
patcher.set_model_sampler_pre_cfg_function(patching.tag(hook, "funpack.x"))
|
|
assert len(patcher.model_options["sampler_pre_cfg_function"]) == 1
|
|
|
|
assert patching.strip(patcher, "funpack.") == 1
|
|
assert patcher.model_options["sampler_pre_cfg_function"] == []
|
|
|
|
|
|
def test_an_untagged_hook_is_left_alone(patcher):
|
|
"""Someone else's hook is not ours to remove, and removing it would be a
|
|
worse fault than the one being fixed."""
|
|
from core import patching
|
|
|
|
def theirs(args):
|
|
return args["conds_out"]
|
|
|
|
patcher.set_model_sampler_pre_cfg_function(theirs)
|
|
assert patching.strip(patcher, "funpack.") == 0
|
|
assert patcher.model_options["sampler_pre_cfg_function"] == [theirs]
|
|
|
|
|
|
def test_a_differently_namespaced_hook_is_left_alone(patcher):
|
|
from core import patching
|
|
|
|
def other(args):
|
|
return args["conds_out"]
|
|
|
|
patcher.set_model_sampler_pre_cfg_function(patching.tag(other, "otherpack.y"))
|
|
assert patching.strip(patcher, "funpack.") == 0
|
|
|
|
|
|
def test_something_that_cannot_be_tagged_is_refused_rather_than_installed():
|
|
"""An untaggable hook could never be removed, so installing it would build
|
|
in the accumulation this exists to prevent."""
|
|
from core import patching
|
|
with pytest.raises(TypeError, match="could never be removed"):
|
|
patching.tag(len, "funpack.x")
|
|
|
|
|
|
def test_chaining_the_loader_does_not_stack_a_pre_cfg_modifier(patcher):
|
|
"""The end-to-end version, through the real node."""
|
|
from modules.sampling.modifiers.nodes import FunPackLoadModifiers
|
|
|
|
values = {"sharpen": {"enabled": True, "amount": 0.4, "radius": 5}}
|
|
once = FunPackLoadModifiers.execute(patcher, settings=values).result[0]
|
|
twice = FunPackLoadModifiers.execute(once, settings=values).result[0]
|
|
thrice = FunPackLoadModifiers.execute(twice, settings=values).result[0]
|
|
|
|
def count(model):
|
|
return len(model.model_options.get("sampler_pre_cfg_function", []))
|
|
|
|
assert count(once) == count(twice) == count(thrice) == 1
|
|
assert count(patcher) == 0, "the shared model was modified"
|
|
|
|
|
|
def test_clone_keeps_the_fault_record_the_sampler_will_clear():
|
|
from core import patching
|
|
class P:
|
|
def clone(self):
|
|
return P()
|
|
m = P()
|
|
m.funpack_dropped = patching.Dropped()
|
|
assert patching.clone(m).funpack_dropped is m.funpack_dropped
|
|
assert not hasattr(patching.clone(P()), "funpack_dropped")
|
|
|
|
|
|
def test_a_stock_clone_between_the_nodes_keeps_the_fault_record(patcher):
|
|
from core import patching
|
|
record = patching.Dropped()
|
|
patcher.model_options["funpack_dropped"] = record
|
|
assert patcher.clone().model_options["funpack_dropped"] is record
|