From e13da8104c1314d467272ab1a1e46b84d1180002 Mon Sep 17 00:00:00 2001 From: xmarre Date: Wed, 18 Mar 2026 12:26:30 +0100 Subject: [PATCH] Fix shallow is_changed handling --- comfy_execution/caching.py | 18 ++++++++++-------- tests/execution/test_caching.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/comfy_execution/caching.py b/comfy_execution/caching.py index fecf54d1e..398036eb8 100644 --- a/comfy_execution/caching.py +++ b/comfy_execution/caching.py @@ -68,20 +68,22 @@ _FAILED_SIGNATURE = object() def _shallow_is_changed_signature(value): - """Sanitize execution-time `is_changed` values with a small fail-closed budget.""" + """Reduce execution-time `is_changed` values without deep traversal.""" value_type = type(value) if value_type in _PRIMITIVE_SIGNATURE_TYPES: return value - canonical = to_hashable(value, max_nodes=64) - if type(canonical) is Unhashable: - return canonical - if value_type is list or value_type is tuple: - container_tag = "is_changed_list" if value_type is list else "is_changed_tuple" - return (container_tag, canonical[1]) + try: + items = tuple(value) + except RuntimeError: + return Unhashable() + if all(type(item) in _PRIMITIVE_SIGNATURE_TYPES for item in items): + container_tag = "is_changed_list" if value_type is list else "is_changed_tuple" + return (container_tag, items) + return Unhashable() - return canonical + return Unhashable() def _primitive_signature_sort_key(obj): diff --git a/tests/execution/test_caching.py b/tests/execution/test_caching.py index 569bf5bd8..db6d95063 100644 --- a/tests/execution/test_caching.py +++ b/tests/execution/test_caching.py @@ -25,6 +25,34 @@ class _StubNode: return {"required": {}} +def test_shallow_is_changed_signature_keeps_primitive_only_list_shallow(): + assert caching._shallow_is_changed_signature([1, "two", None, True]) == ( + "is_changed_list", + (1, "two", None, True), + ) + + +def test_shallow_is_changed_signature_keeps_primitive_only_tuple_shallow(): + assert caching._shallow_is_changed_signature((1, "two", None, True)) == ( + "is_changed_tuple", + (1, "two", None, True), + ) + + +def test_shallow_is_changed_signature_fails_closed_for_nested_container(monkeypatch): + monkeypatch.setattr( + caching, + "to_hashable", + lambda *_args, **_kwargs: (_ for _ in ()).throw( + AssertionError("is_changed signature must not deep-canonicalize") + ), + ) + + signature = caching._shallow_is_changed_signature([1, [2, 3]]) + + assert isinstance(signature, caching.Unhashable) + + def test_get_immediate_node_signature_canonicalizes_non_link_inputs(monkeypatch): live_value = [1, {"nested": [2, 3]}] dynprompt = _StubDynPrompt(