Version 0.4.1

Add all, any, enumerate and sum nodes for LIST, SET and data list
This commit is contained in:
StableLlama
2025-06-09 15:08:56 +02:00
parent 622f471bfa
commit e4d59c24a7
8 changed files with 657 additions and 19 deletions
+120
View File
@@ -153,6 +153,56 @@ class DataListCreateFromString(ComfyNodeABC):
return (values[:-1],)
class DataListAll(ComfyNodeABC):
"""
Check if all elements in the data list are true.
Returns true if all elements are true (or if the list is empty).
"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"list": (IO.ANY, {}),
}
}
RETURN_TYPES = (IO.BOOLEAN,)
RETURN_NAMES = ("result",)
CATEGORY = "Basic/Data List"
DESCRIPTION = cleandoc(__doc__ or "")
FUNCTION = "check_all"
INPUT_IS_LIST = True
def check_all(self, **kwargs: list[Any]) -> tuple[bool]:
return (all(kwargs.get('list', [])),)
class DataListAny(ComfyNodeABC):
"""
Check if any element in the data list is true.
Returns true if at least one element is true. Returns false if the list is empty.
"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"list": (IO.ANY, {}),
}
}
RETURN_TYPES = (IO.BOOLEAN,)
RETURN_NAMES = ("result",)
CATEGORY = "Basic/Data List"
DESCRIPTION = cleandoc(__doc__ or "")
FUNCTION = "check_any"
INPUT_IS_LIST = True
def check_any(self, **kwargs: list[Any]) -> tuple[bool]:
return (any(kwargs.get('list', [])),)
class DataListAppend(ComfyNodeABC):
"""
Adds an item to the end of a list.
@@ -243,6 +293,37 @@ class DataListCount(ComfyNodeABC):
return (kwargs.get('list', []).count(value),)
class DataListEnumerate(ComfyNodeABC):
"""
Enumerate a data list, returning a list of [index, value] pairs.
Optionally, specify a starting value for the index.
"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"list": (IO.ANY, {}),
},
"optional": {
"start": (IO.INT, {"default": 0}),
}
}
RETURN_TYPES = (IO.ANY,)
RETURN_NAMES = ("list",)
CATEGORY = "Basic/Data List"
DESCRIPTION = cleandoc(__doc__ or "")
FUNCTION = "enumerate_list"
INPUT_IS_LIST = True
OUTPUT_IS_LIST = (True,)
def enumerate_list(self, **kwargs: list[Any]) -> tuple[list]:
input_list = kwargs.get('list', [])
start = kwargs.get('start', [0])[0]
return ([list(item) for item in enumerate(input_list, start=start)],)
class DataListExtend(ComfyNodeABC):
"""
Extends a list by appending elements from another list.
@@ -876,6 +957,37 @@ class DataListSort(ComfyNodeABC):
return (result,)
class DataListSum(ComfyNodeABC):
"""
Sum all elements of the data list.
Returns 0 for an empty list.
"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"list": (IO.NUMBER, {}),
},
"optional": {
"start": (IO.INT, {"default": 0}),
}
}
RETURN_TYPES = (IO.INT, IO.FLOAT,)
RETURN_NAMES = ("int_sum", "float_sum",)
CATEGORY = "Basic/Data List"
DESCRIPTION = cleandoc(__doc__ or "")
FUNCTION = "sum_list"
INPUT_IS_LIST = True
def sum_list(self, **kwargs: list[Any]) -> tuple[int, float]:
input_list = kwargs.get('list', [])
start = kwargs.get('start', [0])[0]
result = sum(input_list, start)
return int(result), float(result)
class DataListZip(ComfyNodeABC):
"""
Combines multiple lists element-wise.
@@ -975,9 +1087,12 @@ NODE_CLASS_MAPPINGS = {
"Basic data handling: DataListCreateFromFloat": DataListCreateFromFloat,
"Basic data handling: DataListCreateFromInt": DataListCreateFromInt,
"Basic data handling: DataListCreateFromString": DataListCreateFromString,
"Basic data handling: DataListAll": DataListAll,
"Basic data handling: DataListAny": DataListAny,
"Basic data handling: DataListAppend": DataListAppend,
"Basic data handling: DataListContains": DataListContains,
"Basic data handling: DataListCount": DataListCount,
"Basic data handling: DataListEnumerate": DataListEnumerate,
"Basic data handling: DataListExtend": DataListExtend,
"Basic data handling: DataListFilter": DataListFilter,
"Basic data handling: DataListFilterSelect": DataListFilterSelect,
@@ -997,6 +1112,7 @@ NODE_CLASS_MAPPINGS = {
"Basic data handling: DataListSetItem": DataListSetItem,
"Basic data handling: DataListSlice": DataListSlice,
"Basic data handling: DataListSort": DataListSort,
"Basic data handling: DataListSum": DataListSum,
"Basic data handling: DataListZip": DataListZip,
"Basic data handling: DataListToList": DataListToList,
"Basic data handling: DataListToSet": DataListToSet,
@@ -1008,9 +1124,12 @@ NODE_DISPLAY_NAME_MAPPINGS = {
"Basic data handling: DataListCreateFromFloat": "create Data List from FLOATs",
"Basic data handling: DataListCreateFromInt": "create Data List from INTs",
"Basic data handling: DataListCreateFromString": "create Data List from STRINGs",
"Basic data handling: DataListAll": "all",
"Basic data handling: DataListAny": "any",
"Basic data handling: DataListAppend": "append",
"Basic data handling: DataListContains": "contains",
"Basic data handling: DataListCount": "count",
"Basic data handling: DataListEnumerate": "enumerate",
"Basic data handling: DataListExtend": "extend",
"Basic data handling: DataListFilter": "filter",
"Basic data handling: DataListFilterSelect": "filter select",
@@ -1030,6 +1149,7 @@ NODE_DISPLAY_NAME_MAPPINGS = {
"Basic data handling: DataListSetItem": "set item",
"Basic data handling: DataListSlice": "slice",
"Basic data handling: DataListSort": "sort",
"Basic data handling: DataListSum": "sum",
"Basic data handling: DataListZip": "zip",
"Basic data handling: DataListToList": "convert to LIST",
"Basic data handling: DataListToSet": "convert to SET",
+108 -2
View File
@@ -143,6 +143,52 @@ class ListCreateFromString(ComfyNodeABC):
return (values,)
class ListAll:
"""
Check if all elements in the list are true.
Returns true if all elements are true (or if the list is empty).
"""
@classmethod
def INPUT_TYPES(cls) -> dict:
return {
"required": {
"list": ("LIST",),
}
}
RETURN_TYPES = ("BOOLEAN",)
CATEGORY = "Basic/LIST"
DESCRIPTION = cleandoc(__doc__ or "")
FUNCTION = "check_all"
def check_all(self, list: list[Any]) -> tuple[bool]:
return (all(list),)
class ListAny:
"""
Check if any element in the list is true.
Returns true if at least one element is true. Returns false if the list is empty.
"""
@classmethod
def INPUT_TYPES(cls) -> dict:
return {
"required": {
"list": ("LIST",),
}
}
RETURN_TYPES = ("BOOLEAN",)
CATEGORY = "Basic/LIST"
DESCRIPTION = cleandoc(__doc__ or "")
FUNCTION = "check_any"
def check_any(self, list: list[Any]) -> tuple[bool]:
return (any(list),)
class ListAppend(ComfyNodeABC):
"""
Adds an item to the end of a LIST.
@@ -222,6 +268,32 @@ class ListCount(ComfyNodeABC):
return (list.count(value),)
class ListEnumerate:
"""
Enumerate a list, returning a list of [index, value] pairs.
Optionally, specify a starting value for the index.
"""
@classmethod
def INPUT_TYPES(cls) -> dict:
return {
"required": {
"list": ("LIST",),
},
"optional": {
"start": ("INT", {"default": 0}),
}
}
RETURN_TYPES = ("LIST",)
CATEGORY = "Basic/LIST"
DESCRIPTION = cleandoc(__doc__ or "")
FUNCTION = "enumerate_list"
def enumerate_list(self, list: list[Any], start: int = 0) -> tuple[list]:
return ([__builtins__['list'](enumerate(list, start=start))],)
class ListExtend(ComfyNodeABC):
"""
Extends a LIST by appending elements from another LIST.
@@ -665,7 +737,6 @@ class ListSetItem(ComfyNodeABC):
except IndexError:
raise IndexError(f"Index {index} out of range for LIST of length {len(list)}")
class ListSlice(ComfyNodeABC):
"""
Creates a slice of a LIST.
@@ -695,7 +766,6 @@ class ListSlice(ComfyNodeABC):
step: int = 1) -> tuple[list[Any]]:
return (list[start:stop:step],)
class ListSort(ComfyNodeABC):
"""
Sorts the items in a LIST.
@@ -732,6 +802,33 @@ class ListSort(ComfyNodeABC):
return (list.copy(),)
class ListSum:
"""
Sum all elements of the list.
Returns 0 for an empty list.
"""
@classmethod
def INPUT_TYPES(cls) -> dict:
return {
"required": {
"list": ("LIST",),
},
"optional": {
"start": ("INT", {"default": 0}),
}
}
RETURN_TYPES = ("INT", "FLOAT",)
CATEGORY = "Basic/LIST"
DESCRIPTION = cleandoc(__doc__ or "")
FUNCTION = "sum_list"
def sum_list(self, list: list[Any], start: int = 0) -> tuple[int, float]:
result = sum(list, start)
return result, float(result)
class ListToDataList(ComfyNodeABC):
"""
Converts a LIST object into a ComfyUI data list.
@@ -757,6 +854,7 @@ class ListToDataList(ComfyNodeABC):
def convert(self, list) -> tuple[list[Any]]:
return (list,)
class ListToSet(ComfyNodeABC):
"""
Converts a LIST into a SET.
@@ -787,9 +885,12 @@ NODE_CLASS_MAPPINGS = {
"Basic data handling: ListCreateFromFloat": ListCreateFromFloat,
"Basic data handling: ListCreateFromInt": ListCreateFromInt,
"Basic data handling: ListCreateFromString": ListCreateFromString,
"Basic data handling: ListAll": ListAll,
"Basic data handling: ListAny": ListAny,
"Basic data handling: ListAppend": ListAppend,
"Basic data handling: ListContains": ListContains,
"Basic data handling: ListCount": ListCount,
"Basic data handling: ListEnumerate": ListEnumerate,
"Basic data handling: ListExtend": ListExtend,
"Basic data handling: ListFirst": ListFirst,
"Basic data handling: ListGetItem": ListGetItem,
@@ -807,6 +908,7 @@ NODE_CLASS_MAPPINGS = {
"Basic data handling: ListSetItem": ListSetItem,
"Basic data handling: ListSlice": ListSlice,
"Basic data handling: ListSort": ListSort,
"Basic data handling: ListSum": ListSum,
"Basic data handling: ListToDataList": ListToDataList,
"Basic data handling: ListToSet": ListToSet,
}
@@ -817,9 +919,12 @@ NODE_DISPLAY_NAME_MAPPINGS = {
"Basic data handling: ListCreateFromFloat": "create LIST from FLOATs",
"Basic data handling: ListCreateFromInt": "create LIST from INTs",
"Basic data handling: ListCreateFromString": "create LIST from STRINGs",
"Basic data handling: ListAll": "all",
"Basic data handling: ListAny": "any",
"Basic data handling: ListAppend": "append",
"Basic data handling: ListContains": "contains",
"Basic data handling: ListCount": "count",
"Basic data handling: ListEnumerate": "enumerate",
"Basic data handling: ListExtend": "extend",
"Basic data handling: ListFirst": "first",
"Basic data handling: ListGetItem": "get item",
@@ -837,6 +942,7 @@ NODE_DISPLAY_NAME_MAPPINGS = {
"Basic data handling: ListSetItem": "set item",
"Basic data handling: ListSlice": "slice",
"Basic data handling: ListSort": "sort",
"Basic data handling: ListSum": "sum",
"Basic data handling: ListToDataList": "convert to Data List",
"Basic data handling: ListToSet": "convert to SET",
}
+122
View File
@@ -168,6 +168,56 @@ class SetAdd(ComfyNodeABC):
return (result,)
class SetAll(ComfyNodeABC):
"""
Checks if all elements in the SET are true.
This node takes a SET as input and returns True if all elements in the SET
evaluate to True (or if the SET is empty), and False otherwise.
"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"set": ("SET", {}),
}
}
RETURN_TYPES = (IO.BOOLEAN,)
RETURN_NAMES = ("all_true",)
CATEGORY = "Basic/SET"
DESCRIPTION = cleandoc(__doc__ or "")
FUNCTION = "check_all"
def check_all(self, set: set[Any]) -> tuple[bool]:
return (all(set),)
class SetAny(ComfyNodeABC):
"""
Checks if any element in the SET is true.
This node takes a SET as input and returns True if at least one element
in the SET evaluates to True, and False otherwise (including if the SET is empty).
"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"set": ("SET", {}),
}
}
RETURN_TYPES = (IO.BOOLEAN,)
RETURN_NAMES = ("any_true",)
CATEGORY = "Basic/SET"
DESCRIPTION = cleandoc(__doc__ or "")
FUNCTION = "check_any"
def check_any(self, set: set[Any]) -> tuple[bool]:
return (any(set),)
class SetContains(ComfyNodeABC):
"""
Checks if a SET contains a specified value.
@@ -248,6 +298,37 @@ class SetDiscard(ComfyNodeABC):
return (result,)
class SetEnumerate(ComfyNodeABC):
"""
Enumerates elements in a SET.
This node takes a SET as input and returns a LIST of tuples where each tuple
contains an index and a value from the SET. The start parameter specifies the
initial index value (default is 0).
Note: Since SETs are unordered, the enumeration order is arbitrary but consistent
within a single operation.
"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"set": ("SET", {}),
},
"optional": {
"start": ("INT", {"default": 0}),
}
}
RETURN_TYPES = ("LIST",)
CATEGORY = "Basic/SET"
DESCRIPTION = cleandoc(__doc__ or "")
FUNCTION = "enumerate_set"
def enumerate_set(self, set: set[Any], start: int = 0) -> tuple[list]:
return (list(enumerate(set, start=start)),)
class SetIntersection(ComfyNodeABC):
"""
Returns the intersection of two or more SETs.
@@ -481,6 +562,39 @@ class SetRemove(ComfyNodeABC):
return result, False
class SetSum(ComfyNodeABC):
"""
Calculates the sum of all elements in a SET.
This node takes a SET as input and returns the sum of all its elements.
The optional start parameter specifies the initial value (default is 0).
Note: This operation requires all elements to be numeric or otherwise
compatible with addition. If the SET contains mixed or incompatible types,
it may raise an error.
"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"set": ("SET", {}),
},
"optional": {
"start": ("INT", {"default": 0}),
}
}
RETURN_TYPES = ("INT", "FLOAT",)
RETURN_NAMES = ("sum_int", "sum_float",)
CATEGORY = "Basic/SET"
DESCRIPTION = cleandoc(__doc__ or "")
FUNCTION = "sum_set"
def sum_set(self, set: set[Any], start: int = 0) -> tuple[int, float]:
result = sum(set, start)
return result, float(result)
class SetSymmetricDifference(ComfyNodeABC):
"""
Returns the symmetric difference between two SETs.
@@ -604,9 +718,12 @@ NODE_CLASS_MAPPINGS = {
"Basic data handling: SetCreateFromInt": SetCreateFromInt,
"Basic data handling: SetCreateFromString": SetCreateFromString,
"Basic data handling: SetAdd": SetAdd,
"Basic data handling: SetAll": SetAll,
"Basic data handling: SetAny": SetAny,
"Basic data handling: SetContains": SetContains,
"Basic data handling: SetDifference": SetDifference,
"Basic data handling: SetDiscard": SetDiscard,
"Basic data handling: SetEnumerate": SetEnumerate,
"Basic data handling: SetIntersection": SetIntersection,
"Basic data handling: SetIsDisjoint": SetIsDisjoint,
"Basic data handling: SetIsSubset": SetIsSubset,
@@ -615,6 +732,7 @@ NODE_CLASS_MAPPINGS = {
"Basic data handling: SetPop": SetPop,
"Basic data handling: SetPopRandom": SetPopRandom,
"Basic data handling: SetRemove": SetRemove,
"Basic data handling: SetSum": SetSum,
"Basic data handling: SetSymmetricDifference": SetSymmetricDifference,
"Basic data handling: SetUnion": SetUnion,
"Basic data handling: SetToDataList": SetToDataList,
@@ -628,9 +746,12 @@ NODE_DISPLAY_NAME_MAPPINGS = {
"Basic data handling: SetCreateFromInt": "create SET from INTs",
"Basic data handling: SetCreateFromString": "create SET from STRINGs",
"Basic data handling: SetAdd": "add",
"Basic data handling: SetAll": "all",
"Basic data handling: SetAny": "any",
"Basic data handling: SetContains": "contains",
"Basic data handling: SetDifference": "difference",
"Basic data handling: SetDiscard": "discard",
"Basic data handling: SetEnumerate": "enumerate",
"Basic data handling: SetIntersection": "intersection",
"Basic data handling: SetIsDisjoint": "is disjoint",
"Basic data handling: SetIsSubset": "is subset",
@@ -639,6 +760,7 @@ NODE_DISPLAY_NAME_MAPPINGS = {
"Basic data handling: SetPop": "pop",
"Basic data handling: SetPopRandom": "pop random",
"Basic data handling: SetRemove": "remove",
"Basic data handling: SetSum": "sum",
"Basic data handling: SetSymmetricDifference": "symmetric difference",
"Basic data handling: SetUnion": "union",
"Basic data handling: SetToDataList": "convert to Data List",