mirror of
https://github.com/Comfy-Org/ComfyUI.git
synced 2026-09-21 05:27:57 -05:00
Declare loop boundaries in node schema (#16347)
This commit is contained in:
@@ -1607,7 +1607,7 @@ class Hidden(str, Enum):
|
||||
comfy_usage_source = "COMFY_USAGE_SOURCE"
|
||||
"""COMFY_USAGE_SOURCE identifies the client that submitted the prompt (e.g. comfyui-frontend, comfy-cli, comfyui-mcp); forwarded to API nodes' upstream requests via the Comfy-Usage-Source header."""
|
||||
execution_list = "EXECUTION_LIST"
|
||||
"""EXECUTION_LIST is the active graph scheduler."""
|
||||
"""Custom node Developers and Agents: This attribute is core-internal use only and will be removed in a near-future ComfyUI release. DO NOT USE"""
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -1767,6 +1767,8 @@ class Schema:
|
||||
Use this for nodes with interactive/operable UI regions that produce intermediate outputs
|
||||
(e.g., Image Crop, Painter) rather than final outputs (e.g., Save Image).
|
||||
"""
|
||||
loop_boundary: Literal["start", "end"] | None = None
|
||||
"""Identifies this node as the start or end of a loop for prompt validation."""
|
||||
|
||||
def validate(self):
|
||||
'''Validate the schema:
|
||||
|
||||
@@ -103,8 +103,6 @@ def _expand_loop(dynprompt, opener_id, body, close_id, values, list_items, initi
|
||||
|
||||
|
||||
class StartLoop(io.ComfyNode):
|
||||
LOOP_BOUNDARY = "start"
|
||||
|
||||
@classmethod
|
||||
def define_schema(cls):
|
||||
list_item_type = io.MatchType.Template("list_item")
|
||||
@@ -113,6 +111,7 @@ class StartLoop(io.ComfyNode):
|
||||
node_id="StartLoop",
|
||||
display_name="Start Loop",
|
||||
category="utilities/looping",
|
||||
loop_boundary="start",
|
||||
is_input_list=True,
|
||||
inputs=[
|
||||
io.DynamicCombo.Input("mode", options=[
|
||||
@@ -338,8 +337,6 @@ class LoopResult(io.ComfyNode):
|
||||
|
||||
|
||||
class EndLoop(io.ComfyNode):
|
||||
LOOP_BOUNDARY = "end"
|
||||
|
||||
@classmethod
|
||||
def define_schema(cls):
|
||||
output_type = io.MatchType.Template("output_value")
|
||||
@@ -357,6 +354,7 @@ class EndLoop(io.ComfyNode):
|
||||
node_id="EndLoop",
|
||||
display_name="End Loop",
|
||||
category="utilities/looping",
|
||||
loop_boundary="end",
|
||||
is_input_list=True,
|
||||
inputs=[
|
||||
io.MatchType.Input(
|
||||
|
||||
+2
-1
@@ -1176,7 +1176,8 @@ async def validate_prompt(prompt_id, prompt, partial_execution_list: Union[list[
|
||||
start_nodes = set()
|
||||
end_nodes = set()
|
||||
for node_id, node in prompt.items():
|
||||
boundary = getattr(nodes.NODE_CLASS_MAPPINGS[node["class_type"]], "LOOP_BOUNDARY", None)
|
||||
class_def = nodes.NODE_CLASS_MAPPINGS[node["class_type"]]
|
||||
boundary = class_def.GET_SCHEMA().loop_boundary if issubclass(class_def, _ComfyNodeInternal) else None
|
||||
if boundary == "start":
|
||||
start_nodes.add(node_id)
|
||||
elif boundary == "end":
|
||||
|
||||
@@ -8,6 +8,10 @@ from comfy_extras.nodes_loop import EndLoop, LoopIteration, LoopProgress, LoopRe
|
||||
def test_loop_schema_exposes_cache_policy_and_integrated_carry():
|
||||
inputs = StartLoop.INPUT_TYPES()
|
||||
|
||||
assert StartLoop.GET_SCHEMA().loop_boundary == "start"
|
||||
assert EndLoop.GET_SCHEMA().loop_boundary == "end"
|
||||
assert not hasattr(StartLoop, "LOOP_BOUNDARY")
|
||||
assert not hasattr(EndLoop, "LOOP_BOUNDARY")
|
||||
assert inputs["required"]["cache_iterations"][1]["default"] is False
|
||||
assert inputs["required"]["cache_iterations"][1]["advanced"] is True
|
||||
assert list(inputs["optional"]) == ["parent_iteration", "initial_iteration_value"]
|
||||
|
||||
Reference in New Issue
Block a user