Replaced 'behavior' with 'optional'; unlikely there will be anything other than 'required'/'optional' in the long run

This commit is contained in:
kosinkadink1@gmail.com 2025-06-10 01:11:09 -07:00
parent 70d2bbfec0
commit 2873aaf4db
2 changed files with 35 additions and 33 deletions

View File

@ -10,6 +10,7 @@ import torch
class InputBehavior(str, Enum): class InputBehavior(str, Enum):
'''Likely deprecated; required/optional can be a bool, unlikely to be more categories that fit.'''
required = "required" required = "required"
optional = "optional" optional = "optional"
@ -68,20 +69,20 @@ class IO_V3:
def __init__(self): def __init__(self):
pass pass
def __init_subclass__(cls, io_type: IO | str, Type=Any, **kwargs): def __init_subclass__(cls, io_type: IO | str, **kwargs):
# TODO: do we need __ne__ trick for io_type? (see IO.__ne__ for details)
cls.io_type = io_type cls.io_type = io_type
cls.Type = Type
super().__init_subclass__(**kwargs) super().__init_subclass__(**kwargs)
class InputV3(IO_V3, io_type=None): class InputV3(IO_V3, io_type=None):
''' '''
Base class for a V3 Input. Base class for a V3 Input.
''' '''
def __init__(self, id: str, display_name: str=None, behavior=InputBehavior.required, tooltip: str=None, lazy: bool=None): def __init__(self, id: str, display_name: str=None, optional=False, tooltip: str=None, lazy: bool=None):
super().__init__() super().__init__()
self.id = id self.id = id
self.display_name = display_name self.display_name = display_name
self.behavior = behavior self.optional = optional
self.tooltip = tooltip self.tooltip = tooltip
self.lazy = lazy self.lazy = lazy
@ -99,10 +100,10 @@ class WidgetInputV3(InputV3, io_type=None):
''' '''
Base class for a V3 Input with widget. Base class for a V3 Input with widget.
''' '''
def __init__(self, id: str, display_name: str=None, behavior=InputBehavior.required, tooltip: str=None, lazy: bool=None, def __init__(self, id: str, display_name: str=None, optional=False, tooltip: str=None, lazy: bool=None,
default: Any=None, default: Any=None,
socketless: bool=None, widgetType: str=None): socketless: bool=None, widgetType: str=None):
super().__init__(id, display_name, behavior, tooltip, lazy) super().__init__(id, display_name, optional, tooltip, lazy)
self.default = default self.default = default
self.socketless = socketless self.socketless = socketless
self.widgetType = widgetType self.widgetType = widgetType
@ -118,14 +119,14 @@ def CustomType(io_type: IO | str) -> type[IO_V3]:
name = f"{io_type}_IO_V3" name = f"{io_type}_IO_V3"
return type(name, (IO_V3,), {}, io_type=io_type) return type(name, (IO_V3,), {}, io_type=io_type)
def CustomInput(id: str, io_type: IO | str, display_name: str=None, behavior=InputBehavior.required, tooltip: str=None, lazy: bool=None) -> InputV3: def CustomInput(id: str, io_type: IO | str, display_name: str=None, optional=False, tooltip: str=None, lazy: bool=None) -> InputV3:
''' '''
Defines input for 'io_type'. Can be used to stand in for non-core types. Defines input for 'io_type'. Can be used to stand in for non-core types.
''' '''
input_kwargs = { input_kwargs = {
"id": id, "id": id,
"display_name": display_name, "display_name": display_name,
"behavior": behavior, "optional": optional,
"tooltip": tooltip, "tooltip": tooltip,
"lazy": lazy, "lazy": lazy,
} }
@ -148,10 +149,10 @@ class BooleanInput(WidgetInputV3, io_type=IO.BOOLEAN):
Boolean input. Boolean input.
''' '''
Type = bool Type = bool
def __init__(self, id: str, display_name: str=None, behavior=InputBehavior.required, tooltip: str=None, lazy: bool=None, def __init__(self, id: str, display_name: str=None, optional=False, tooltip: str=None, lazy: bool=None,
default: bool=None, label_on: str=None, label_off: str=None, default: bool=None, label_on: str=None, label_off: str=None,
socketless: bool=None, widgetType: str=None): socketless: bool=None, widgetType: str=None):
super().__init__(id, display_name, behavior, tooltip, lazy, default, socketless, widgetType) super().__init__(id, display_name, optional, tooltip, lazy, default, socketless, widgetType)
self.label_on = label_on self.label_on = label_on
self.label_off = label_off self.label_off = label_off
self.default: bool self.default: bool
@ -167,10 +168,10 @@ class IntegerInput(WidgetInputV3, io_type=IO.INT):
Integer input. Integer input.
''' '''
Type = int Type = int
def __init__(self, id: str, display_name: str=None, behavior=InputBehavior.required, tooltip: str=None, lazy: bool=None, def __init__(self, id: str, display_name: str=None, optional=False, tooltip: str=None, lazy: bool=None,
default: int=None, min: int=None, max: int=None, step: int=None, control_after_generate: bool=None, default: int=None, min: int=None, max: int=None, step: int=None, control_after_generate: bool=None,
display_mode: NumberDisplay=None, socketless: bool=None, widgetType: str=None): display_mode: NumberDisplay=None, socketless: bool=None, widgetType: str=None):
super().__init__(id, display_name, behavior, tooltip, lazy, default, socketless, widgetType) super().__init__(id, display_name, optional, tooltip, lazy, default, socketless, widgetType)
self.min = min self.min = min
self.max = max self.max = max
self.step = step self.step = step
@ -192,10 +193,10 @@ class FloatInput(WidgetInputV3, io_type=IO.FLOAT):
Float input. Float input.
''' '''
Type = float Type = float
def __init__(self, id: str, display_name: str=None, behavior=InputBehavior.required, tooltip: str=None, lazy: bool=None, def __init__(self, id: str, display_name: str=None, optional=False, tooltip: str=None, lazy: bool=None,
default: float=None, min: float=None, max: float=None, step: float=None, round: float=None, default: float=None, min: float=None, max: float=None, step: float=None, round: float=None,
display_mode: NumberDisplay=None, socketless: bool=None, widgetType: str=None): display_mode: NumberDisplay=None, socketless: bool=None, widgetType: str=None):
super().__init__(id, display_name, behavior, tooltip, lazy, default, socketless, widgetType) super().__init__(id, display_name, optional, tooltip, lazy, default, socketless, widgetType)
self.default = default self.default = default
self.min = min self.min = min
self.max = max self.max = max
@ -218,10 +219,10 @@ class StringInput(WidgetInputV3, io_type=IO.STRING):
String input. String input.
''' '''
Type = str Type = str
def __init__(self, id: str, display_name: str=None, behavior=InputBehavior.required, tooltip: str=None, lazy: bool=None, def __init__(self, id: str, display_name: str=None, optional=False, tooltip: str=None, lazy: bool=None,
multiline=False, placeholder: str=None, default: int=None, multiline=False, placeholder: str=None, default: int=None,
socketless: bool=None, widgetType: str=None): socketless: bool=None, widgetType: str=None):
super().__init__(id, display_name, behavior, tooltip, lazy, default, socketless, widgetType) super().__init__(id, display_name, optional, tooltip, lazy, default, socketless, widgetType)
self.multiline = multiline self.multiline = multiline
self.placeholder = placeholder self.placeholder = placeholder
self.default: str self.default: str
@ -235,12 +236,12 @@ class StringInput(WidgetInputV3, io_type=IO.STRING):
class ComboInput(WidgetInputV3, io_type=IO.COMBO): class ComboInput(WidgetInputV3, io_type=IO.COMBO):
'''Combo input (dropdown).''' '''Combo input (dropdown).'''
Type = str Type = str
def __init__(self, id: str, options: list[str]=None, display_name: str=None, behavior=InputBehavior.required, tooltip: str=None, lazy: bool=None, def __init__(self, id: str, options: list[str]=None, display_name: str=None, optional=False, tooltip: str=None, lazy: bool=None,
default: str=None, control_after_generate: bool=None, default: str=None, control_after_generate: bool=None,
image_upload: bool=None, image_folder: FolderType=None, image_upload: bool=None, image_folder: FolderType=None,
remote: RemoteOptions=None, remote: RemoteOptions=None,
socketless: bool=None, widgetType: str=None): socketless: bool=None, widgetType: str=None):
super().__init__(id, display_name, behavior, tooltip, lazy, default, socketless, widgetType) super().__init__(id, display_name, optional, tooltip, lazy, default, socketless, widgetType)
self.multiselect = False self.multiselect = False
self.options = options self.options = options
self.control_after_generate = control_after_generate self.control_after_generate = control_after_generate
@ -261,10 +262,10 @@ class ComboInput(WidgetInputV3, io_type=IO.COMBO):
class MultiselectComboWidget(ComboInput, io_type=IO.COMBO): class MultiselectComboWidget(ComboInput, io_type=IO.COMBO):
'''Multiselect Combo input (dropdown for selecting potentially more than one value).''' '''Multiselect Combo input (dropdown for selecting potentially more than one value).'''
def __init__(self, id: str, options: list[str], display_name: str=None, behavior=InputBehavior.required, tooltip: str=None, lazy: bool=None, def __init__(self, id: str, options: list[str], display_name: str=None, optional=False, tooltip: str=None, lazy: bool=None,
default: list[str]=None, placeholder: str=None, chip: bool=None, control_after_generate: bool=None, default: list[str]=None, placeholder: str=None, chip: bool=None, control_after_generate: bool=None,
socketless: bool=None, widgetType: str=None): socketless: bool=None, widgetType: str=None):
super().__init__(id, options, display_name, behavior, tooltip, lazy, default, control_after_generate, socketless, widgetType) super().__init__(id, options, display_name, optional, tooltip, lazy, default, control_after_generate, socketless, widgetType)
self.multiselect = True self.multiselect = True
self.placeholder = placeholder self.placeholder = placeholder
self.chip = chip self.chip = chip
@ -282,30 +283,30 @@ class ImageInput(InputV3, io_type=IO.IMAGE):
Image input. Image input.
''' '''
Type = torch.Tensor Type = torch.Tensor
def __init__(self, id: str, display_name: str=None, behavior=InputBehavior.required, tooltip: str=None): def __init__(self, id: str, display_name: str=None, optional=False, tooltip: str=None):
super().__init__(id, display_name, behavior, tooltip) super().__init__(id, display_name, optional, tooltip)
class MaskInput(InputV3, io_type=IO.MASK): class MaskInput(InputV3, io_type=IO.MASK):
''' '''
Mask input. Mask input.
''' '''
Type = torch.Tensor Type = torch.Tensor
def __init__(self, id: str, display_name: str=None, behavior=InputBehavior.required, tooltip: str=None): def __init__(self, id: str, display_name: str=None, optional=False, tooltip: str=None):
super().__init__(id, display_name, behavior, tooltip) super().__init__(id, display_name, optional, tooltip)
class LatentInput(InputV3, io_type=IO.LATENT): class LatentInput(InputV3, io_type=IO.LATENT):
''' '''
Latent input. Latent input.
''' '''
def __init__(self, id: str, display_name: str=None, behavior=InputBehavior.required, tooltip: str=None): def __init__(self, id: str, display_name: str=None, optional=False, tooltip: str=None):
super().__init__(id, display_name, behavior, tooltip) super().__init__(id, display_name, optional, tooltip)
class MultitypedInput(InputV3, io_type="COMFY_MULTITYPED_V3"): class MultitypedInput(InputV3, io_type="COMFY_MULTITYPED_V3"):
''' '''
Input that permits more than one input type. Input that permits more than one input type.
''' '''
def __init__(self, id: str, io_types: list[type[IO_V3] | InputV3 | IO |str], display_name: str=None, behavior=InputBehavior.required, tooltip: str=None,): def __init__(self, id: str, io_types: list[type[IO_V3] | InputV3 | IO |str], display_name: str=None, optional=False, tooltip: str=None,):
super().__init__(id, display_name, behavior, tooltip) super().__init__(id, display_name, optional, tooltip)
self._io_types = io_types self._io_types = io_types
@property @property
@ -708,7 +709,8 @@ class ComfyNodeV3(ABC):
} }
if schema.inputs: if schema.inputs:
for i in schema.inputs: for i in schema.inputs:
input.setdefault(i.behavior.value, {})[i.id] = (i.get_io_type_V1(), i.as_dict_V1()) key = "optional" if i.optional else "required"
input.setdefault(key, {})[i.id] = (i.get_io_type_V1(), i.as_dict_V1())
if schema.hidden: if schema.hidden:
for hidden in schema.hidden: for hidden in schema.hidden:
input.setdefault("hidden", {})[hidden.name] = (hidden.value,) input.setdefault("hidden", {})[hidden.name] = (hidden.value,)

View File

@ -1,6 +1,6 @@
import torch import torch
from comfy_api.v3.io import ( from comfy_api.v3.io import (
ComfyNodeV3, SchemaV3, InputBehavior, NumberDisplay, ComfyNodeV3, SchemaV3, NumberDisplay,
IntegerInput, MaskInput, ImageInput, ComboInput, CustomInput, StringInput, CustomType, IntegerInput, MaskInput, ImageInput, ComboInput, CustomInput, StringInput, CustomType,
IntegerOutput, ImageOutput, MultitypedInput, InputV3, OutputV3, IntegerOutput, ImageOutput, MultitypedInput, InputV3, OutputV3,
NodeOutput, Hidden NodeOutput, Hidden
@ -29,9 +29,9 @@ class V3TestNode(ComfyNodeV3):
category="v3 nodes", category="v3 nodes",
inputs=[ inputs=[
ImageInput("image", display_name="new_image"), ImageInput("image", display_name="new_image"),
XYZInput("xyz", behavior=InputBehavior.optional), XYZInput("xyz", optional=True),
#CustomInput("xyz", "XYZ", behavior=InputBehavior.optional), #CustomInput("xyz", "XYZ", optional=True),
MaskInput("mask", behavior=InputBehavior.optional), MaskInput("mask", optional=True),
IntegerInput("some_int", display_name="new_name", min=0, max=127, default=42, IntegerInput("some_int", display_name="new_name", min=0, max=127, default=42,
tooltip="My tooltip 😎", display_mode=NumberDisplay.slider), tooltip="My tooltip 😎", display_mode=NumberDisplay.slider),
ComboInput("combo", options=["a", "b", "c"], tooltip="This is a combo input"), ComboInput("combo", options=["a", "b", "c"], tooltip="This is a combo input"),