Files
olivv-cs-ComfyUI-FunPack/modules/sampling/tests/test_patching.py
T
Claude 3adebb731f Rename FunPack to FunUI (5.0.3 Classy Chopper): /fun endpoint, wink logo, load-time migration of old names
Old project/workflow names and browser settings migrate on load; /funpack redirects to /fun.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016acRss69eH1235eRdFTZHY
2026-10-25 13:11:03 +00:00

94 lines
3.2 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, "funui.x"))
assert len(patcher.model_options["sampler_pre_cfg_function"]) == 1
assert patching.strip(patcher, "funui.") == 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, "funui.") == 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, "funui.") == 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, "funui.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 FunUILoadModifiers
values = {"sharpen": {"enabled": True, "amount": 0.4, "radius": 5}}
once = FunUILoadModifiers.execute(patcher, settings=values).result[0]
twice = FunUILoadModifiers.execute(once, settings=values).result[0]
thrice = FunUILoadModifiers.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.funui_dropped = patching.Dropped()
assert patching.clone(m).funui_dropped is m.funui_dropped
assert not hasattr(patching.clone(P()), "funui_dropped")
def test_a_stock_clone_between_the_nodes_keeps_the_fault_record(patcher):
from core import patching
record = patching.Dropped()
patcher.model_options["funui_dropped"] = record
assert patcher.clone().model_options["funui_dropped"] is record