mirror of
https://github.com/Comfy-Org/ComfyUI.git
synced 2026-08-24 18:10:27 +08:00
TypeResolver: address code review (link parsing + slot_idx guard + back-compat shim)
* Add _parse_link helper validating both node_id (str) and slot_idx (int, rejecting bool) so malformed API JSON (e.g. ['n1', '0']) degrades to AnyType instead of crashing with TypeError. * Add slot_idx type guards in resolve_output_type and is_output_list. * Extract _get_class_def_for_node helper to dedupe node/class lookup across resolve_output_type, is_output_list, get_declared_slot_io_type. * register_dynamic_input_func now detects 5-argument legacy callables via inspect.signature and silently wraps them; preserves backward compatibility for any custom node that registered its own dynamic input expansion against the pre-live_input_types signature. * Tests: malformed link (str slot idx, wrong arity), bad slot type directly to resolve_output_type, non-string class_type. Tests for the legacy 5-arg shim and the modern 6-arg passthrough, including callables with uninspectable signatures. Amp-Thread-ID: https://ampcode.com/threads/T-019e8568-f382-743d-a97f-0de3ff29d501 Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
@@ -360,6 +360,52 @@ def test_invalidate_clears_cache(fake_nodes_module, TypeResolver):
|
||||
assert r.resolve_output_type("n1", 0) == "LATENT"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Malformed input robustness
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def test_malformed_link_does_not_crash(fake_nodes_module, TypeResolver):
|
||||
"""A link with a non-int slot index must not raise; resolver returns AnyType."""
|
||||
fake_nodes_module["Src"] = _v1_node(("IMAGE",))
|
||||
fake_nodes_module["Sink"] = _v1_node(("INT",), {"required": {"x": ("*",)}})
|
||||
prompt = {
|
||||
"src": {"class_type": "Src", "inputs": {}},
|
||||
# slot index sent as a string (common API JSON mistake)
|
||||
"sink": {"class_type": "Sink", "inputs": {"x": ["src", "0"]}},
|
||||
}
|
||||
r = TypeResolver(prompt)
|
||||
# Falls back to declared slot type (still "*"), no exception.
|
||||
assert r.resolve_input_type("sink", "x") == "*"
|
||||
|
||||
|
||||
def test_malformed_link_wrong_arity_does_not_crash(fake_nodes_module, TypeResolver):
|
||||
fake_nodes_module["Src"] = _v1_node(("IMAGE",))
|
||||
fake_nodes_module["Sink"] = _v1_node(("INT",), {"required": {"x": ("*",)}})
|
||||
prompt = {
|
||||
"src": {"class_type": "Src", "inputs": {}},
|
||||
"sink": {"class_type": "Sink", "inputs": {"x": ["src"]}}, # arity 1
|
||||
}
|
||||
r = TypeResolver(prompt)
|
||||
assert r.resolve_input_type("sink", "x") == "*"
|
||||
|
||||
|
||||
def test_direct_resolve_output_type_with_bad_slot_idx_returns_any(fake_nodes_module, TypeResolver):
|
||||
fake_nodes_module["Src"] = _v1_node(("IMAGE",))
|
||||
prompt = {"src": {"class_type": "Src", "inputs": {}}}
|
||||
r = TypeResolver(prompt)
|
||||
# type-wise these should be unreachable through normal validation but the
|
||||
# resolver must still degrade gracefully.
|
||||
assert r.resolve_output_type("src", "0") == "*"
|
||||
assert r.resolve_output_type("src", True) == "*" # bool is a subclass of int
|
||||
assert r.is_output_list("src", "0") is False
|
||||
|
||||
|
||||
def test_non_string_class_type_returns_any(fake_nodes_module, TypeResolver):
|
||||
prompt = {"n1": {"class_type": 42, "inputs": {}}}
|
||||
r = TypeResolver(prompt)
|
||||
assert r.resolve_output_type("n1", 0) == "*"
|
||||
|
||||
|
||||
def test_invalidate_node_only_clears_that_node(fake_nodes_module, TypeResolver):
|
||||
fake_nodes_module["SrcA"] = _v1_node(("IMAGE",))
|
||||
fake_nodes_module["SrcB"] = _v1_node(("LATENT",))
|
||||
|
||||
Reference in New Issue
Block a user