"""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