Create ComfyTypeI that only has as an input, improved hints on Boolean, Int, and Combos

This commit is contained in:
kosinkadink1@gmail.com 2025-07-14 01:03:21 -05:00
parent 8f7e27352e
commit 139025f0fd

View File

@ -98,11 +98,9 @@ class NumberDisplay(str, Enum):
slider = "slider" slider = "slider"
class ComfyType: class ComfyType(ABC):
Type = Any Type = Any
io_type: str = None io_type: str = None
Input: type[InputV3] = None
Output: type[OutputV3] = None
# NOTE: this is a workaround to make the decorator return the correct type # NOTE: this is a workaround to make the decorator return the correct type
T = TypeVar("T", bound=type) T = TypeVar("T", bound=type)
@ -119,7 +117,9 @@ def comfytype(io_type: str, **kwargs):
if isinstance(cls, ComfyType) or issubclass(cls, ComfyType): if isinstance(cls, ComfyType) or issubclass(cls, ComfyType):
# clone Input and Output classes to avoid modifying the original class # clone Input and Output classes to avoid modifying the original class
new_cls = cls new_cls = cls
if hasattr(new_cls, "Input"):
new_cls.Input = copy_class(new_cls.Input) new_cls.Input = copy_class(new_cls.Input)
if hasattr(new_cls, "Output"):
new_cls.Output = copy_class(new_cls.Output) new_cls.Output = copy_class(new_cls.Output)
else: else:
# copy class attributes except for special ones that shouldn't be in type() # copy class attributes except for special ones that shouldn't be in type()
@ -128,9 +128,9 @@ def comfytype(io_type: str, **kwargs):
if k not in ('__dict__', '__weakref__', '__module__', '__doc__') if k not in ('__dict__', '__weakref__', '__module__', '__doc__')
} }
# new class # new class
new_cls: ComfyType = type( new_cls: ComfyTypeIO = type(
cls.__name__, cls.__name__,
(cls, ComfyType), (cls, ComfyTypeIO),
cls_dict cls_dict
) )
# metadata preservation # metadata preservation
@ -139,14 +139,14 @@ def comfytype(io_type: str, **kwargs):
# assign ComfyType attributes, if needed # assign ComfyType attributes, if needed
# NOTE: do we need __ne__ trick for io_type? (see node_typing.IO.__ne__ for details) # NOTE: do we need __ne__ trick for io_type? (see node_typing.IO.__ne__ for details)
new_cls.io_type = io_type new_cls.io_type = io_type
if new_cls.Input is not None: if hasattr(new_cls, "Input") and new_cls.Input is not None:
new_cls.Input.Parent = new_cls new_cls.Input.Parent = new_cls
if new_cls.Output is not None: if hasattr(new_cls, "Output") and new_cls.Output is not None:
new_cls.Output.Parent = new_cls new_cls.Output.Parent = new_cls
return new_cls return new_cls
return decorator return decorator
def Custom(io_type: str) -> type[ComfyType]: def Custom(io_type: str) -> type[ComfyTypeIO]:
'''Create a ComfyType for a custom io_type.''' '''Create a ComfyType for a custom io_type.'''
@comfytype(io_type=io_type) @comfytype(io_type=io_type)
class CustomComfyType(ComfyTypeIO): class CustomComfyType(ComfyTypeIO):
@ -227,10 +227,13 @@ class OutputV3(IO_V3):
self.is_output_list = is_output_list self.is_output_list = is_output_list
class ComfyTypeIO(ComfyType): class ComfyTypeI(ComfyType):
'''ComfyType subclass that has default Input and Output classes; useful for basic Inputs and Outputs.''' '''ComfyType subclass that only has a default Input class - intended for types that only have Inputs.'''
class Input(InputV3): class Input(InputV3):
... ...
class ComfyTypeIO(ComfyTypeI):
'''ComfyType subclass that has default Input and Output classes; useful for types with both Inputs and Outputs.'''
class Output(OutputV3): class Output(OutputV3):
... ...
@ -297,7 +300,7 @@ class NodeStateLocal(NodeState):
@comfytype(io_type="BOOLEAN") @comfytype(io_type="BOOLEAN")
class Boolean: class Boolean(ComfyTypeIO):
Type = bool Type = bool
class Input(WidgetInputV3): class Input(WidgetInputV3):
@ -316,11 +319,8 @@ class Boolean:
"label_off": self.label_off, "label_off": self.label_off,
}) })
class Output(OutputV3):
...
@comfytype(io_type="INT") @comfytype(io_type="INT")
class Int: class Int(ComfyTypeIO):
Type = int Type = int
class Input(WidgetInputV3): class Input(WidgetInputV3):
@ -345,9 +345,6 @@ class Int:
"display": self.display_mode, "display": self.display_mode,
}) })
class Output(OutputV3):
...
@comfytype(io_type="FLOAT") @comfytype(io_type="FLOAT")
class Float(ComfyTypeIO): class Float(ComfyTypeIO):
Type = float Type = float
@ -395,7 +392,7 @@ class String(ComfyTypeIO):
}) })
@comfytype(io_type="COMBO") @comfytype(io_type="COMBO")
class Combo(ComfyType): class Combo(ComfyTypeI):
Type = str Type = str
class Input(WidgetInputV3): class Input(WidgetInputV3):
"""Combo input (dropdown).""" """Combo input (dropdown)."""
@ -426,7 +423,7 @@ class Combo(ComfyType):
@comfytype(io_type="COMBO") @comfytype(io_type="COMBO")
class MultiCombo(ComfyType): class MultiCombo(ComfyTypeI):
'''Multiselect Combo input (dropdown for selecting potentially more than one value).''' '''Multiselect Combo input (dropdown for selecting potentially more than one value).'''
# TODO: something is wrong with the serialization, frontend does not recognize it as multiselect # TODO: something is wrong with the serialization, frontend does not recognize it as multiselect
Type = list[str] Type = list[str]