From 56ccfeaa8a5c08e6621c84f6258758b9ebf5f80f Mon Sep 17 00:00:00 2001 From: "kosinkadink1@gmail.com" Date: Wed, 9 Jul 2025 03:25:23 -0500 Subject: [PATCH] Add fingerprint_inputs support (V3's IS_CHANGED) --- comfy_api/v3/io.py | 4 +++- comfy_extras/nodes_v3_test.py | 5 +++++ execution.py | 12 ++++++++++-- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/comfy_api/v3/io.py b/comfy_api/v3/io.py index 58ce0bfc8..721e4aa75 100644 --- a/comfy_api/v3/io.py +++ b/comfy_api/v3/io.py @@ -844,7 +844,9 @@ class HiddenHolder: return None @classmethod - def from_dict(cls, d: dict): + def from_dict(cls, d: dict | None): + if d is None: + d = {} return cls( unique_id=d.get(Hidden.unique_id, None), prompt=d.get(Hidden.prompt, None), diff --git a/comfy_extras/nodes_v3_test.py b/comfy_extras/nodes_v3_test.py index a73516ae0..55f179f2a 100644 --- a/comfy_extras/nodes_v3_test.py +++ b/comfy_extras/nodes_v3_test.py @@ -1,4 +1,5 @@ import torch +import time from comfy_api.v3 import io, ui, resources import logging import folder_paths @@ -176,6 +177,10 @@ class NInputsTest(io.ComfyNodeV3): def validate_inputs(cls, nmock, nmock2): return True + @classmethod + def fingerprint_inputs(cls, nmock, nmock2): + return time.time() + @classmethod def check_lazy_status(cls, **kwargs) -> list[str]: need = [name for name in kwargs if kwargs[name] is None] diff --git a/execution.py b/execution.py index d7e46e5b2..896537980 100644 --- a/execution.py +++ b/execution.py @@ -52,7 +52,15 @@ class IsChangedCache: node = self.dynprompt.get_node(node_id) class_type = node["class_type"] class_def = nodes.NODE_CLASS_MAPPINGS[class_type] - if not hasattr(class_def, "IS_CHANGED"): + has_is_changed = False + is_changed_name = None + if issubclass(class_def, ComfyNodeV3) and getattr(class_def, "fingerprint_inputs", None) is not None: + has_is_changed = True + is_changed_name = "fingerprint_inputs" + elif hasattr(class_def, "IS_CHANGED"): + has_is_changed = True + is_changed_name = "IS_CHANGED" + if not has_is_changed: self.is_changed[node_id] = False return self.is_changed[node_id] @@ -63,7 +71,7 @@ class IsChangedCache: # Intentionally do not use cached outputs here. We only want constants in IS_CHANGED input_data_all, _, hidden_inputs = get_input_data(node["inputs"], class_def, node_id, None) try: - is_changed = _map_node_over_list(class_def, input_data_all, "IS_CHANGED") + is_changed = _map_node_over_list(class_def, input_data_all, is_changed_name) node["is_changed"] = [None if isinstance(x, ExecutionBlocker) else x for x in is_changed] except Exception as e: logging.warning("WARNING: {}".format(e))