Version 0.0.5
Add Python list and dict as LIST and DICT custom data type
This commit is contained in:
@@ -22,13 +22,30 @@ These nodes are very lightweight and require no additional dependencies.
|
||||
- Case conversion: lower, upper, swapcase, title, capitalize
|
||||
- Validation: isalnum, isalpha, isdigit, isnumeric, etc.
|
||||
|
||||
- **LIST**: List manipulation nodes
|
||||
- Creation: create, create_empty
|
||||
- **LIST**: Python list manipulation nodes (as a single variable)
|
||||
- Conversion: convert to data list
|
||||
- Creation: any to LIST
|
||||
- Modification: append, extend, insert, remove, pop, clear, set_item
|
||||
- Access: get_item, slice, index, contains
|
||||
- Information: length, count
|
||||
- Operations: sort, reverse, copy, join, zip, flatten
|
||||
- Unpacking: unpack
|
||||
- Operations: sort, reverse
|
||||
|
||||
- **data list**: ComfyUI list manipulation nodes (for processing individual items)
|
||||
- Conversion: convert to LIST
|
||||
- Creation: create_empty
|
||||
- Modification: append, extend, insert, remove, pop, clear, set_item
|
||||
- Access: get_item, slice, index, contains
|
||||
- Information: length, count
|
||||
- Operations: sort, reverse, copy, zip
|
||||
|
||||
- **DICT**: Dictionary manipulation nodes
|
||||
- Creation: create, from_items, from_lists, fromkeys, any_to_DICT
|
||||
- Access: get, get_multiple, keys, values, items
|
||||
- Modification: set, update, setdefault, merge
|
||||
- Removal: pop, popitem, remove, clear
|
||||
- Information: length, contains_key
|
||||
- Operations: copy, filter_by_keys, exclude_keys, invert, compare
|
||||
- Conversion: get_keys_values
|
||||
|
||||
- **INT**: Integer operation nodes
|
||||
- Basic operations: add, subtract, multiply, divide, modulus, power
|
||||
@@ -41,6 +58,48 @@ These nodes are very lightweight and require no additional dependencies.
|
||||
- **BOOLEAN**: Boolean logic nodes
|
||||
- Logic operations: and, or, not, xor, nand, nor
|
||||
|
||||
## Understanding LIST vs. data list
|
||||
|
||||
ComfyUI has two different list data types that serve different purposes:
|
||||
|
||||
### 1. LIST datatype
|
||||
- A Python list represented as a **single variable** in the workflow
|
||||
- Treated as a self-contained object that can be passed between nodes
|
||||
- Cannot directly connect to nodes that expect individual items
|
||||
- Best for:
|
||||
- Working with collections of data as a single unit
|
||||
- Storing intermediate results that need to be processed as a whole
|
||||
- Passing collections between different parts of your workflow
|
||||
- Complex data storage that shouldn't be split apart
|
||||
|
||||
### 2. data list
|
||||
- A native ComfyUI list where **items are processed individually**
|
||||
- Acts like a standard array/list in most programming contexts
|
||||
- Items can be accessed individually by compatible nodes
|
||||
- Supports built-in ComfyUI iteration over each item
|
||||
- Best for:
|
||||
- Working directly with multiple items in parallel
|
||||
- Batch processing scenarios
|
||||
- When you need to apply the same operation to multiple inputs
|
||||
- When your operation needs to work with individual items separately
|
||||
|
||||
### Converting between types
|
||||
- Use `convert to data list` node to transform a LIST into a ComfyUI data list
|
||||
- Use `convert to LIST` node to transform a ComfyUI data list into a LIST object
|
||||
|
||||
### When to use which type
|
||||
- Use **LIST** when you need to:
|
||||
- Keep items grouped together as a single entity
|
||||
- Perform operations on the entire collection (sorting, reversing, etc.)
|
||||
- Pass a collection between workflow sections
|
||||
- Prevent automatic iteration over items
|
||||
|
||||
- Use **data list** when you need to:
|
||||
- Process each item individually through ComfyUI nodes
|
||||
- Allow nodes to iterate through your items automatically
|
||||
- Connect to nodes that expect individual inputs
|
||||
- Perform batch processing operations
|
||||
|
||||
## Tests
|
||||
|
||||
This repo contains unit tests written in Pytest in the `tests/` directory. It is recommended to unit test your custom node.
|
||||
|
||||
+3
-2
@@ -4,9 +4,10 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "basic_data_handling"
|
||||
version = "0.0.4"
|
||||
version = "0.0.5"
|
||||
description = """Basic Python functions for manipulating data that every programmer is used to.
|
||||
Currently supported: BOOLEAN, FLOAT, INT, STRING and data lists."""
|
||||
Currently supported ComfyUI data types: BOOLEAN, FLOAT, INT, STRING and data lists.
|
||||
Additionally supported Python data types as custom data types: DICT, LIST."""
|
||||
authors = [
|
||||
{name = "Basic data handling"}
|
||||
]
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
from . import boolean_nodes, dict_nodes, float_nodes, int_nodes, list_nodes, string_nodes
|
||||
from . import boolean_nodes, data_list_nodes, dict_nodes, float_nodes, int_nodes, list_nodes, string_nodes
|
||||
|
||||
NODE_CLASS_MAPPINGS = {}
|
||||
NODE_CLASS_MAPPINGS.update(boolean_nodes.NODE_CLASS_MAPPINGS)
|
||||
NODE_CLASS_MAPPINGS.update(data_list_nodes.NODE_CLASS_MAPPINGS)
|
||||
NODE_CLASS_MAPPINGS.update(dict_nodes.NODE_CLASS_MAPPINGS)
|
||||
NODE_CLASS_MAPPINGS.update(float_nodes.NODE_CLASS_MAPPINGS)
|
||||
NODE_CLASS_MAPPINGS.update(int_nodes.NODE_CLASS_MAPPINGS)
|
||||
@@ -10,6 +11,7 @@ NODE_CLASS_MAPPINGS.update(string_nodes.NODE_CLASS_MAPPINGS)
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {}
|
||||
NODE_DISPLAY_NAME_MAPPINGS.update(boolean_nodes.NODE_DISPLAY_NAME_MAPPINGS)
|
||||
NODE_DISPLAY_NAME_MAPPINGS.update(data_list_nodes.NODE_DISPLAY_NAME_MAPPINGS)
|
||||
NODE_DISPLAY_NAME_MAPPINGS.update(dict_nodes.NODE_DISPLAY_NAME_MAPPINGS)
|
||||
NODE_DISPLAY_NAME_MAPPINGS.update(float_nodes.NODE_DISPLAY_NAME_MAPPINGS)
|
||||
NODE_DISPLAY_NAME_MAPPINGS.update(int_nodes.NODE_DISPLAY_NAME_MAPPINGS)
|
||||
|
||||
@@ -0,0 +1,722 @@
|
||||
from typing import Any
|
||||
|
||||
from inspect import cleandoc
|
||||
|
||||
class DataListConvertToList:
|
||||
"""
|
||||
Converts a ComfyUI data list into a LIST object.
|
||||
|
||||
This node takes a data list input (which is typically a list of items with the same type)
|
||||
and converts it to a LIST object (a Python list as a single variable).
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"list": ("*", {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("LIST",)
|
||||
CATEGORY = "Basic/data list"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "convert"
|
||||
INPUT_IS_LIST = True
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def convert(self, **kwargs: dict[str, list]) -> tuple[list[Any]]:
|
||||
return (kwargs.get('list', []).copy(),)
|
||||
|
||||
|
||||
class DataListAppend:
|
||||
"""
|
||||
Adds an item to the end of a list.
|
||||
|
||||
This node takes a list and any item as inputs, then returns the modified
|
||||
list with the new item appended.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"optional": {
|
||||
"list":("*",{}),
|
||||
"item":("*",{}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("*",)
|
||||
RETURN_NAMES = ("list",)
|
||||
CATEGORY = "Basic/data list"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "append"
|
||||
INPUT_IS_LIST = True
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def append(self, **kwargs: dict[str, list]) -> tuple[list[Any]]:
|
||||
result = kwargs.get('list', []).copy()
|
||||
item = kwargs.get('item', [])
|
||||
if len(item) > 0:
|
||||
result.append(item[0])
|
||||
return (result,)
|
||||
|
||||
|
||||
class DataListExtend:
|
||||
"""
|
||||
Extends a list by appending elements from another list.
|
||||
|
||||
This node takes two lists as input and returns a new list that contains
|
||||
all elements from both lists.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"optional": {
|
||||
"list_a": ("*",{}),
|
||||
"list_b": ("*",{}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("*",)
|
||||
RETURN_NAMES = ("list",)
|
||||
CATEGORY = "Basic/data list"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "extend"
|
||||
INPUT_IS_LIST = True
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def extend(self, **kwargs: dict[str, list]) -> tuple[list[Any]]:
|
||||
return (kwargs.get('list_a', []) + kwargs.get('list_b', []),)
|
||||
|
||||
|
||||
class DataListInsert:
|
||||
"""
|
||||
Inserts an item at a specified position in a list.
|
||||
|
||||
This node takes a list, an index, and any item as inputs, then returns a new
|
||||
list with the item inserted at the specified index.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"list": ("*",),
|
||||
"index": ("INT", {"default": 0}),
|
||||
"item": ("*",),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("*",)
|
||||
RETURN_NAMES = ("list",)
|
||||
CATEGORY = "Basic/data list"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "insert"
|
||||
INPUT_IS_LIST = True
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def insert(self, **kwargs: dict[str, list]) -> tuple[list[Any]]:
|
||||
result = kwargs.get('list', []).copy()
|
||||
result.insert(kwargs.get('index', [0])[0], kwargs.get('item', [None])[0])
|
||||
return (result,)
|
||||
|
||||
|
||||
class DataListRemove:
|
||||
"""
|
||||
Removes the first occurrence of a specified value from a list.
|
||||
|
||||
This node takes a list and a value as inputs, then returns a new list with
|
||||
the first occurrence of the value removed. Raises a ValueError if the value is not present.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"list": ("*",),
|
||||
"value": ("*",),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("*", "BOOLEAN",)
|
||||
RETURN_NAMES = ("list", "success",)
|
||||
CATEGORY = "Basic/data list"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "remove"
|
||||
INPUT_IS_LIST = True
|
||||
OUTPUT_IS_LIST = (True, False,)
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def remove(self, **kwargs: dict[str, list]) -> tuple[list[Any], bool]:
|
||||
result = kwargs.get('list', []).copy()
|
||||
value = kwargs.get('value', [])
|
||||
try:
|
||||
result.remove(value[0])
|
||||
return result, True
|
||||
except ValueError:
|
||||
return result, False
|
||||
|
||||
|
||||
class DataListPop:
|
||||
"""
|
||||
Removes and returns an item at a specified position in a list.
|
||||
|
||||
This node takes a list and an index as inputs, then returns both the new list
|
||||
with the item removed and the removed item. If no index is specified,
|
||||
removes and returns the last item.
|
||||
When the list is empty, the item is None.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"list": ("*",),
|
||||
},
|
||||
"optional": {
|
||||
"index": ("INT", {"default": -1}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("*", "*")
|
||||
RETURN_NAMES = ("list", "item")
|
||||
CATEGORY = "Basic/data list"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "pop"
|
||||
INPUT_IS_LIST = True
|
||||
OUTPUT_IS_LIST = (True, False)
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool|str:
|
||||
if input_types["index"] not in ("INT"):
|
||||
return "index must be an INT type"
|
||||
return True
|
||||
|
||||
def pop(self, **kwargs: dict[str, list]) -> tuple[list[Any], Any]:
|
||||
result = kwargs.get('list', []).copy()
|
||||
index = kwargs.get('index', [-1])[0]
|
||||
try:
|
||||
item = result.pop(index)
|
||||
return result, item
|
||||
except IndexError:
|
||||
return result, None
|
||||
|
||||
|
||||
class DataListClear:
|
||||
"""
|
||||
Removes all items from a list.
|
||||
|
||||
This node takes a list as input and returns a new empty list.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"optional": {
|
||||
"list": ("*",),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("*",)
|
||||
RETURN_NAMES = ("list",)
|
||||
CATEGORY = "Basic/data list"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "clear"
|
||||
INPUT_IS_LIST = True
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def clear(self, **kwargs: dict[str, list]) -> tuple[[]]:
|
||||
# Return a new empty list rather than modifying the input
|
||||
return ([],)
|
||||
|
||||
|
||||
class DataListIndex:
|
||||
"""
|
||||
Returns the index of the first occurrence of a value in a list.
|
||||
|
||||
This node takes a list and a value as inputs, then returns the index of the first
|
||||
occurrence of the value. Optional start and end parameters limit the search to a slice
|
||||
of the list. Returns -1 if the value is not present.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"list": ("*",),
|
||||
"value": ("*",),
|
||||
},
|
||||
"optional": {
|
||||
"start": ("INT", {"default": 0}),
|
||||
"end": ("INT", {"default": -1}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("INT",)
|
||||
RETURN_NAMES = ("index",)
|
||||
CATEGORY = "Basic/data list"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "list_index"
|
||||
INPUT_IS_LIST = True
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def list_index(self, **kwargs: dict[str, list]) -> tuple[int]:
|
||||
input_list = kwargs.get('list', [])
|
||||
value = kwargs.get('value', [None])[0]
|
||||
start = kwargs.get('start', [0])[0]
|
||||
end = kwargs.get('end', [-1])[0]
|
||||
if end == -1:
|
||||
end = len(input_list)
|
||||
|
||||
try:
|
||||
return (input_list.index(value, start, end),)
|
||||
except ValueError:
|
||||
return (-1,)
|
||||
|
||||
|
||||
class DataListCount:
|
||||
"""
|
||||
Counts the number of occurrences of a value in a list.
|
||||
|
||||
This node takes a list and a value as inputs, then returns the number of times
|
||||
the value appears in the list.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"list": ("*",),
|
||||
"value": ("*",),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("INT",)
|
||||
RETURN_NAMES = ("count",)
|
||||
CATEGORY = "Basic/data list"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "count"
|
||||
INPUT_IS_LIST = True
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def count(self, **kwargs: dict[str, list]) -> tuple[int]:
|
||||
value = kwargs.get('value', [None])[0]
|
||||
return (kwargs.get('list', []).count(value),)
|
||||
|
||||
|
||||
class DataListSort:
|
||||
"""
|
||||
Sorts the items in a list.
|
||||
|
||||
This node takes a list as input and returns a new sorted list.
|
||||
Options include sorting in reverse order and using a key function.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"list": ("*",),
|
||||
},
|
||||
"optional": {
|
||||
"reverse": (["False", "True"], {"default": "False"}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("*",)
|
||||
RETURN_NAMES = ("list",)
|
||||
CATEGORY = "Basic/data list"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "sort"
|
||||
INPUT_IS_LIST = True
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def sort(self, **kwargs: dict[str, list]) -> tuple[list[Any]]:
|
||||
# Convert string to boolean
|
||||
reverse = kwargs.get('reverse', ["False"])[0] == "True"
|
||||
|
||||
result = sorted(kwargs.get('list', []), reverse=reverse)
|
||||
return (result,)
|
||||
|
||||
|
||||
class DataListReverse:
|
||||
"""
|
||||
Reverses the order of items in a list.
|
||||
|
||||
This node takes a list as input and returns a new list with the items in reversed order.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"list": ("*",),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("*",)
|
||||
RETURN_NAMES = ("list",)
|
||||
CATEGORY = "Basic/data list"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "reverse"
|
||||
INPUT_IS_LIST = True
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def reverse(self, **kwargs: dict[str, list]) -> tuple[list[Any]]:
|
||||
result = kwargs.get('list', []).copy()
|
||||
result.reverse()
|
||||
return (result,)
|
||||
|
||||
|
||||
class DataListCopy:
|
||||
"""
|
||||
Creates a shallow copy of a list.
|
||||
|
||||
This node takes a list as input and returns a new list that is a shallow copy of the original.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"list": ("*",),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("*",)
|
||||
RETURN_NAMES = ("list",)
|
||||
CATEGORY = "Basic/data list"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "copy"
|
||||
INPUT_IS_LIST = True
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def copy(self, **kwargs: dict[str, list]) -> tuple[list[Any]]:
|
||||
return (kwargs.get('list', []).copy(),)
|
||||
|
||||
|
||||
class DataListLength:
|
||||
"""
|
||||
Counts the number of items in a list.
|
||||
|
||||
This node takes a list as input and returns its length as an integer.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"list": ("*",),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("INT",)
|
||||
RETURN_NAMES = ("length",)
|
||||
CATEGORY = "Basic/data list"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "length"
|
||||
INPUT_IS_LIST = True
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def length(self, **kwargs: dict[str, list]) -> tuple[int]:
|
||||
return (len(kwargs.get('list', [])),)
|
||||
|
||||
|
||||
class DataListSlice:
|
||||
"""
|
||||
Creates a slice of a list.
|
||||
|
||||
This node takes a list and start/stop/step parameters, and returns a new list
|
||||
containing the specified slice of the original list.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"list": ("*",),
|
||||
},
|
||||
"optional": {
|
||||
"start": ("INT", {"default": 0}),
|
||||
"stop": ("INT", {"default": -1}),
|
||||
"step": ("INT", {"default": 1}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("*",)
|
||||
RETURN_NAMES = ("list",)
|
||||
CATEGORY = "Basic/data list"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "slice"
|
||||
INPUT_IS_LIST = True
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def slice(self, **kwargs: dict[str, list]) -> tuple[list[Any]]:
|
||||
input_list = kwargs.get('list', [])
|
||||
start = kwargs.get('start', [0])[0]
|
||||
stop = kwargs.get('stop', [-1])[0]
|
||||
step = kwargs.get('step', [1])[0]
|
||||
|
||||
if stop == -1:
|
||||
stop = len(input_list)
|
||||
|
||||
return (input_list[start:stop:step],)
|
||||
|
||||
|
||||
class DataListGetItem:
|
||||
"""
|
||||
Retrieves an item at a specified position in a list.
|
||||
|
||||
This node takes a list and an index as inputs, then returns the item at the specified index.
|
||||
Negative indices count from the end of the list.
|
||||
Out of range indices return None.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input_list": ("*",),
|
||||
"index": ("INT", {"default": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("*",)
|
||||
RETURN_NAMES = ("item",)
|
||||
CATEGORY = "Basic/data list"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "get_item"
|
||||
INPUT_IS_LIST = True
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def get_item(self, **kwargs: dict[str, list]) -> tuple[Any]:
|
||||
index = kwargs.get('index', [0])[0]
|
||||
try:
|
||||
return (kwargs.get('list', [])[index],)
|
||||
except IndexError:
|
||||
return (None,)
|
||||
|
||||
|
||||
class DataListSetItem:
|
||||
"""
|
||||
Sets an item at a specified position in a list.
|
||||
|
||||
This node takes a list, an index, and a value, then returns a new list with
|
||||
the item at the specified index replaced by the value.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"list": ("*",),
|
||||
"index": ("INT", {"default": 0}),
|
||||
"value": ("*",),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("*",)
|
||||
RETURN_NAMES = ("list",)
|
||||
CATEGORY = "Basic/data list"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "set_item"
|
||||
INPUT_IS_LIST = True
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def set_item(self, **kwargs: dict[str, list]) -> tuple[Any]:
|
||||
input_list = kwargs.get('list', [])
|
||||
index = kwargs.get('index', [0])[0]
|
||||
value = kwargs.get('value', [None])[0]
|
||||
try:
|
||||
result = input_list.copy()
|
||||
result[index] = value
|
||||
return (result,)
|
||||
except IndexError:
|
||||
raise IndexError(f"Index {index} out of range for list of length {len(input_list)}")
|
||||
|
||||
|
||||
class DataListContains:
|
||||
"""
|
||||
Checks if a list contains a specified value.
|
||||
|
||||
This node takes a list and a value as inputs, then returns True if the value
|
||||
is present in the list, and False otherwise.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input_list": ("*",),
|
||||
"value": ("*",),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("BOOLEAN",)
|
||||
RETURN_NAMES = ("contains",)
|
||||
CATEGORY = "Basic/data list"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "contains"
|
||||
INPUT_IS_LIST = True
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def contains(self, **kwargs: dict[str, list]) -> tuple[bool]:
|
||||
value = kwargs.get('value', [])
|
||||
if len(value) == 0:
|
||||
return (False,)
|
||||
return (value[0] in kwargs.get('list', []),)
|
||||
|
||||
|
||||
class DataListCreateEmpty:
|
||||
"""
|
||||
Creates a new empty list.
|
||||
|
||||
This node creates and returns an empty list.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {"required": {}}
|
||||
|
||||
RETURN_TYPES = ("*",)
|
||||
RETURN_NAMES = ("list",)
|
||||
CATEGORY = "Basic/data list"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "create_empty"
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
|
||||
def create_empty(self) -> tuple[[]]:
|
||||
return ([],)
|
||||
|
||||
|
||||
class DataListZip:
|
||||
"""
|
||||
Combines multiple lists element-wise.
|
||||
|
||||
This node takes multiple data lists as input and returns a new data list
|
||||
where each item is a list containing the corresponding elements from the input lists.
|
||||
The length of the output list will be equal to the length of the shortest input list.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"list1": ("*",),
|
||||
"list2": ("*",),
|
||||
},
|
||||
"optional": {
|
||||
"list3": ("*",),
|
||||
"list4": ("*",),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("*",)
|
||||
RETURN_NAMES = ("list",)
|
||||
CATEGORY = "Basic/data list"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "zip_lists"
|
||||
INPUT_IS_LIST = True
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def zip_lists(self, **kwargs: dict[str, list]) -> tuple[list[Any]]:
|
||||
lists = [kwargs.get('list1', []), kwargs.get('list2', [])]
|
||||
|
||||
if 'list3' in kwargs:
|
||||
lists.append(kwargs['list3'])
|
||||
|
||||
if 'list4' in kwargs:
|
||||
lists.append(kwargs['list4'])
|
||||
|
||||
# Zip the lists together and convert each tuple to a list
|
||||
result = [list(item) for item in zip(*lists)]
|
||||
return (result,)
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"DataListConvertToList": DataListConvertToList,
|
||||
"DataListAppend": DataListAppend,
|
||||
"DataListExtend": DataListExtend,
|
||||
"DataListInsert": DataListInsert,
|
||||
"DataListRemove": DataListRemove,
|
||||
"DataListPop": DataListPop,
|
||||
"DataListClear": DataListClear,
|
||||
"DataListIndex": DataListIndex,
|
||||
"DataListCount": DataListCount,
|
||||
"DataListSort": DataListSort,
|
||||
"DataListReverse": DataListReverse,
|
||||
"DataListCopy": DataListCopy,
|
||||
"DataListLength": DataListLength,
|
||||
"DataListSlice": DataListSlice,
|
||||
"DataListGetItem": DataListGetItem,
|
||||
"DataListSetItem": DataListSetItem,
|
||||
"DataListContains": DataListContains,
|
||||
"DataListCreateEmpty": DataListCreateEmpty,
|
||||
"DataListZip": DataListZip,
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"DataListConvertToList": "convert to LIST",
|
||||
"DataListAppend": "append",
|
||||
"DataListExtend": "extend",
|
||||
"DataListInsert": "insert",
|
||||
"DataListRemove": "remove",
|
||||
"DataListPop": "pop",
|
||||
"DataListClear": "clear",
|
||||
"DataListIndex": "index",
|
||||
"DataListCount": "count",
|
||||
"DataListSort": "sort",
|
||||
"DataListReverse": "reverse",
|
||||
"DataListCopy": "copy",
|
||||
"DataListLength": "length",
|
||||
"DataListSlice": "slice",
|
||||
"DataListGetItem": "get_item",
|
||||
"DataListSetItem": "set_item",
|
||||
"DataListContains": "contains",
|
||||
"DataListCreateEmpty": "create_empty",
|
||||
"DataListZip": "zip",
|
||||
}
|
||||
@@ -1,27 +1,85 @@
|
||||
from typing import Any
|
||||
from inspect import cleandoc
|
||||
|
||||
class DictGet:
|
||||
class DictCreate:
|
||||
"""
|
||||
Retrieves a value from a dictionary using the specified key.
|
||||
Creates a new empty dictionary.
|
||||
|
||||
If the key is not found, the node will return None.
|
||||
This node creates and returns a new empty dictionary object.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {"required": {}}
|
||||
|
||||
RETURN_TYPES = ("DICT",)
|
||||
CATEGORY = "Basic/DICT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "create"
|
||||
|
||||
def create(self) -> tuple[dict]:
|
||||
return ({},)
|
||||
|
||||
|
||||
class DictCreateFromItems:
|
||||
"""
|
||||
Creates a dictionary from a list of key-value pairs.
|
||||
|
||||
This node takes a list of key-value pairs (tuples) and builds a dictionary from them.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input_dict": ("DICT",),
|
||||
"key": ("STRING", {"default": ""}),
|
||||
"items": ("LIST", {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("ANY",)
|
||||
RETURN_TYPES = ("DICT",)
|
||||
CATEGORY = "Basic/DICT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "create_from_items"
|
||||
|
||||
def create_from_items(self, items: list) -> tuple[dict]:
|
||||
try:
|
||||
# Check if items are valid (key-value pairs)
|
||||
for item in items:
|
||||
if not isinstance(item, tuple) or len(item) != 2:
|
||||
raise ValueError("Each item must be a (key, value) pair")
|
||||
|
||||
return (dict(items),)
|
||||
except Exception as e:
|
||||
raise ValueError(f"Error creating dictionary from items: {str(e)}")
|
||||
|
||||
|
||||
class DictGet:
|
||||
"""
|
||||
Retrieves a value from a dictionary using the specified key.
|
||||
|
||||
This node gets the value for the specified key from a dictionary.
|
||||
If the key is not found and a default value is provided, that default is returned.
|
||||
Otherwise, it returns None.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input_dict": ("DICT", {}),
|
||||
"key": ("STRING", {"default": ""}),
|
||||
},
|
||||
"optional": {
|
||||
"default_value": ("*", {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("*",)
|
||||
RETURN_NAMES = ("value",)
|
||||
CATEGORY = "Basic/DICT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "get"
|
||||
|
||||
def get(self, input_dict, key):
|
||||
return (input_dict.get(key, None),)
|
||||
def get(self, input_dict: dict, key: str, default_value=None) -> tuple[Any]:
|
||||
return (input_dict.get(key, default_value),)
|
||||
|
||||
|
||||
class DictSet:
|
||||
"""
|
||||
@@ -34,9 +92,9 @@ class DictSet:
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input_dict": ("DICT",),
|
||||
"input_dict": ("DICT", {}),
|
||||
"key": ("STRING", {"default": ""}),
|
||||
"value": ("ANY",),
|
||||
"value": ("*", {}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,16 +103,729 @@ class DictSet:
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "set"
|
||||
|
||||
def set(self, input_dict, key, value):
|
||||
input_dict[key] = value
|
||||
return (input_dict,)
|
||||
def set(self, input_dict: dict, key: str, value: Any) -> tuple[dict]:
|
||||
result = input_dict.copy()
|
||||
result[key] = value
|
||||
return (result,)
|
||||
|
||||
|
||||
class DictKeys:
|
||||
"""
|
||||
Returns all keys in a dictionary.
|
||||
|
||||
This node takes a dictionary and returns a list containing all of its keys.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input_dict": ("DICT", {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("LIST",)
|
||||
CATEGORY = "Basic/DICT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "keys"
|
||||
|
||||
def keys(self, input_dict: dict) -> tuple[list]:
|
||||
return (list(input_dict.keys()),)
|
||||
|
||||
|
||||
class DictValues:
|
||||
"""
|
||||
Returns all values in a dictionary.
|
||||
|
||||
This node takes a dictionary and returns a list containing all of its values.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input_dict": ("DICT", {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("LIST",)
|
||||
CATEGORY = "Basic/DICT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "values"
|
||||
|
||||
def values(self, input_dict: dict) -> tuple[list]:
|
||||
return (list(input_dict.values()),)
|
||||
|
||||
|
||||
class DictItems:
|
||||
"""
|
||||
Returns all key-value pairs in a dictionary.
|
||||
|
||||
This node takes a dictionary and returns a list of tuples, where each tuple
|
||||
contains a key-value pair from the dictionary.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input_dict": ("DICT", {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("LIST",)
|
||||
CATEGORY = "Basic/DICT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "items"
|
||||
|
||||
def items(self, input_dict: dict) -> tuple[list]:
|
||||
return (list(input_dict.items()),)
|
||||
|
||||
|
||||
class DictContainsKey:
|
||||
"""
|
||||
Checks if a key exists in a dictionary.
|
||||
|
||||
This node takes a dictionary and a key as inputs, then returns True if the key
|
||||
exists in the dictionary, and False otherwise.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input_dict": ("DICT", {}),
|
||||
"key": ("STRING", {"default": ""}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("BOOLEAN",)
|
||||
CATEGORY = "Basic/DICT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "contains_key"
|
||||
|
||||
def contains_key(self, input_dict: dict, key: str) -> tuple[bool]:
|
||||
return (key in input_dict,)
|
||||
|
||||
|
||||
class DictClear:
|
||||
"""
|
||||
Removes all items from a dictionary.
|
||||
|
||||
This node takes a dictionary as input and returns a new empty dictionary.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input_dict": ("DICT", {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("DICT",)
|
||||
CATEGORY = "Basic/DICT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "clear"
|
||||
|
||||
def clear(self, input_dict: dict) -> tuple[dict]:
|
||||
return ({},)
|
||||
|
||||
|
||||
class DictCopy:
|
||||
"""
|
||||
Creates a shallow copy of a dictionary.
|
||||
|
||||
This node takes a dictionary as input and returns a new dictionary that is
|
||||
a shallow copy of the original.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input_dict": ("DICT", {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("DICT",)
|
||||
CATEGORY = "Basic/DICT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "copy"
|
||||
|
||||
def copy(self, input_dict: dict) -> tuple[dict]:
|
||||
return (input_dict.copy(),)
|
||||
|
||||
|
||||
class DictFromKeys:
|
||||
"""
|
||||
Creates a dictionary from a list of keys and a default value.
|
||||
|
||||
This node takes a list of keys and an optional value, then creates a new
|
||||
dictionary where each key is associated with the value. If no value is
|
||||
provided, None is used.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"keys": ("LIST", {}),
|
||||
},
|
||||
"optional": {
|
||||
"value": ("*", {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("DICT",)
|
||||
CATEGORY = "Basic/DICT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "from_keys"
|
||||
|
||||
def from_keys(self, keys: list, value=None) -> tuple[dict]:
|
||||
return (dict.fromkeys(keys, value),)
|
||||
|
||||
|
||||
class DictPop:
|
||||
"""
|
||||
Removes and returns a key-value pair from a dictionary.
|
||||
|
||||
This node takes a dictionary and a key as inputs, removes the specified key
|
||||
from the dictionary, and returns both the modified dictionary and the value
|
||||
associated with the key. If the key is not found and a default value is provided,
|
||||
that default is returned. Otherwise, an error is raised.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input_dict": ("DICT", {}),
|
||||
"key": ("STRING", {"default": ""}),
|
||||
},
|
||||
"optional": {
|
||||
"default_value": ("*", {}),
|
||||
"has_default": (["False", "True"], {"default": "False"}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("DICT", "*", "BOOLEAN")
|
||||
RETURN_NAMES = ("dict", "value", "key_found")
|
||||
CATEGORY = "Basic/DICT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "pop"
|
||||
|
||||
def pop(self, input_dict: dict, key: str, default_value=None, has_default: str = "False") -> tuple[dict, Any, bool]:
|
||||
result = input_dict.copy()
|
||||
has_default_bool = (has_default == "True")
|
||||
|
||||
try:
|
||||
if key in result:
|
||||
value = result.pop(key)
|
||||
return result, value, True
|
||||
elif has_default_bool:
|
||||
return result, default_value, False
|
||||
else:
|
||||
raise KeyError(f"Key '{key}' not found in dictionary")
|
||||
except Exception as e:
|
||||
raise ValueError(f"Error popping key from dictionary: {str(e)}")
|
||||
|
||||
|
||||
class DictPopItem:
|
||||
"""
|
||||
Removes and returns an arbitrary key-value pair from a dictionary.
|
||||
|
||||
This node takes a dictionary as input, removes an arbitrary key-value pair,
|
||||
and returns the modified dictionary along with the removed key and value.
|
||||
If the dictionary is empty, returns an error.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input_dict": ("DICT", {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("DICT", "STRING", "*", "BOOLEAN")
|
||||
RETURN_NAMES = ("dict", "key", "value", "success")
|
||||
CATEGORY = "Basic/DICT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "popitem"
|
||||
|
||||
def popitem(self, input_dict: dict) -> tuple[dict, str, Any, bool]:
|
||||
result = input_dict.copy()
|
||||
try:
|
||||
if result:
|
||||
key, value = result.popitem()
|
||||
return result, key, value, True
|
||||
else:
|
||||
return result, "", None, False
|
||||
except Exception as e:
|
||||
return result, "", None, False
|
||||
|
||||
|
||||
class DictSetDefault:
|
||||
"""
|
||||
Returns the value for a key, setting a default if the key doesn't exist.
|
||||
|
||||
This node takes a dictionary, a key, and a default value. If the key exists
|
||||
in the dictionary, the corresponding value is returned. If the key doesn't
|
||||
exist, the default value is inserted for the key and returned.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input_dict": ("DICT", {}),
|
||||
"key": ("STRING", {"default": ""}),
|
||||
"default_value": ("*", {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("DICT", "*")
|
||||
RETURN_NAMES = ("dict", "value")
|
||||
CATEGORY = "Basic/DICT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "setdefault"
|
||||
|
||||
def setdefault(self, input_dict: dict, key: str, default_value=None) -> tuple[dict, Any]:
|
||||
result = input_dict.copy()
|
||||
value = result.setdefault(key, default_value)
|
||||
return result, value
|
||||
|
||||
|
||||
class DictUpdate:
|
||||
"""
|
||||
Updates a dictionary with key-value pairs from another dictionary.
|
||||
|
||||
This node takes two dictionaries as inputs and returns a new dictionary that
|
||||
contains all key-value pairs from both dictionaries. If there are duplicate
|
||||
keys, the values from the second dictionary take precedence.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"dict1": ("DICT", {}),
|
||||
"dict2": ("DICT", {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("DICT",)
|
||||
CATEGORY = "Basic/DICT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "update"
|
||||
|
||||
def update(self, dict1: dict, dict2: dict) -> tuple[dict]:
|
||||
result = dict1.copy()
|
||||
result.update(dict2)
|
||||
return (result,)
|
||||
|
||||
|
||||
class DictLength:
|
||||
"""
|
||||
Returns the number of key-value pairs in a dictionary.
|
||||
|
||||
This node takes a dictionary as input and returns its length (number of items).
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input_dict": ("DICT", {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("INT",)
|
||||
RETURN_NAMES = ("length",)
|
||||
CATEGORY = "Basic/DICT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "length"
|
||||
|
||||
def length(self, input_dict: dict) -> tuple[int]:
|
||||
return (len(input_dict),)
|
||||
|
||||
|
||||
class DictMerge:
|
||||
"""
|
||||
Merges multiple dictionaries into a single dictionary.
|
||||
|
||||
This node takes multiple dictionaries as input and combines them into a single
|
||||
dictionary. If there are duplicate keys, values from later dictionaries take precedence.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"dict1": ("DICT", {}),
|
||||
},
|
||||
"optional": {
|
||||
"dict2": ("DICT", {}),
|
||||
"dict3": ("DICT", {}),
|
||||
"dict4": ("DICT", {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("DICT",)
|
||||
CATEGORY = "Basic/DICT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "merge"
|
||||
|
||||
def merge(self, dict1: dict, dict2=None, dict3=None, dict4=None) -> tuple[dict]:
|
||||
result = dict1.copy()
|
||||
|
||||
if dict2 is not None:
|
||||
result.update(dict2)
|
||||
|
||||
if dict3 is not None:
|
||||
result.update(dict3)
|
||||
|
||||
if dict4 is not None:
|
||||
result.update(dict4)
|
||||
|
||||
return (result,)
|
||||
|
||||
|
||||
class DictGetKeysValues:
|
||||
"""
|
||||
Returns keys and values as separate lists.
|
||||
|
||||
This node takes a dictionary and returns two lists: one containing
|
||||
all keys and another containing all corresponding values.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input_dict": ("DICT", {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("LIST", "LIST")
|
||||
RETURN_NAMES = ("keys", "values")
|
||||
CATEGORY = "Basic/DICT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "get_keys_values"
|
||||
|
||||
def get_keys_values(self, input_dict: dict) -> tuple[list, list]:
|
||||
keys = list(input_dict.keys())
|
||||
values = list(input_dict.values())
|
||||
return keys, values
|
||||
|
||||
|
||||
class DictRemove:
|
||||
"""
|
||||
Removes a key-value pair from a dictionary.
|
||||
|
||||
This node takes a dictionary and a key as inputs, then returns a new
|
||||
dictionary with the specified key removed. If the key doesn't exist,
|
||||
the dictionary remains unchanged.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input_dict": ("DICT", {}),
|
||||
"key": ("STRING", {"default": ""}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("DICT", "BOOLEAN")
|
||||
RETURN_NAMES = ("dict", "key_removed")
|
||||
CATEGORY = "Basic/DICT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "remove"
|
||||
|
||||
def remove(self, input_dict: dict, key: str) -> tuple[dict, bool]:
|
||||
result = input_dict.copy()
|
||||
if key in result:
|
||||
del result[key]
|
||||
return result, True
|
||||
return result, False
|
||||
|
||||
|
||||
class AnyToDict:
|
||||
"""
|
||||
Converts compatible data structures to a dictionary.
|
||||
|
||||
This node attempts to convert an input value to a dictionary. Compatible
|
||||
inputs include sequences of key-value pairs, mapping objects, and objects
|
||||
with a to_dict() or as_dict() method.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input": ("*", {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("DICT", "BOOLEAN")
|
||||
RETURN_NAMES = ("dict", "success")
|
||||
CATEGORY = "Basic/DICT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "convert"
|
||||
|
||||
def convert(self, input: Any) -> tuple[dict, bool]:
|
||||
try:
|
||||
if isinstance(input, dict):
|
||||
return input.copy(), True
|
||||
|
||||
# Try converting from items
|
||||
if hasattr(input, "items"):
|
||||
return dict(input.items()), True
|
||||
|
||||
# Try converting from sequence of pairs
|
||||
if hasattr(input, "__iter__") and not isinstance(input, str):
|
||||
try:
|
||||
result = dict(input)
|
||||
return result, True
|
||||
except (TypeError, ValueError):
|
||||
pass
|
||||
|
||||
# Check for to_dict or as_dict methods
|
||||
if hasattr(input, "to_dict") and callable(getattr(input, "to_dict")):
|
||||
return input.to_dict(), True
|
||||
|
||||
if hasattr(input, "as_dict") and callable(getattr(input, "as_dict")):
|
||||
return input.as_dict(), True
|
||||
|
||||
# Failed to convert
|
||||
return {}, False
|
||||
|
||||
except Exception:
|
||||
return {}, False
|
||||
|
||||
|
||||
class DictFilterByKeys:
|
||||
"""
|
||||
Creates a new dictionary with only the specified keys.
|
||||
|
||||
This node takes a dictionary and a list of keys, then returns a new dictionary
|
||||
containing only the key-value pairs for the keys that exist in the original dictionary.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input_dict": ("DICT", {}),
|
||||
"keys": ("LIST", {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("DICT",)
|
||||
CATEGORY = "Basic/DICT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "filter_by_keys"
|
||||
|
||||
def filter_by_keys(self, input_dict: dict, keys: list) -> tuple[dict]:
|
||||
result = {k: input_dict[k] for k in keys if k in input_dict}
|
||||
return (result,)
|
||||
|
||||
|
||||
class DictExcludeKeys:
|
||||
"""
|
||||
Creates a new dictionary excluding the specified keys.
|
||||
|
||||
This node takes a dictionary and a list of keys, then returns a new dictionary
|
||||
containing all key-value pairs except those with keys in the provided list.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input_dict": ("DICT", {}),
|
||||
"keys_to_exclude": ("LIST", {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("DICT",)
|
||||
CATEGORY = "Basic/DICT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "exclude_keys"
|
||||
|
||||
def exclude_keys(self, input_dict: dict, keys_to_exclude: list) -> tuple[dict]:
|
||||
result = {k: v for k, v in input_dict.items() if k not in keys_to_exclude}
|
||||
return (result,)
|
||||
|
||||
|
||||
class DictGetMultiple:
|
||||
"""
|
||||
Retrieves multiple values from a dictionary using a list of keys.
|
||||
|
||||
This node takes a dictionary and a list of keys, then returns a list
|
||||
containing the corresponding values. If a key is not found, the default
|
||||
value is used for that position.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input_dict": ("DICT", {}),
|
||||
"keys": ("LIST", {}),
|
||||
},
|
||||
"optional": {
|
||||
"default_value": ("*", {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("LIST",)
|
||||
RETURN_NAMES = ("values",)
|
||||
CATEGORY = "Basic/DICT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "get_multiple"
|
||||
|
||||
def get_multiple(self, input_dict: dict, keys: list, default_value=None) -> tuple[list]:
|
||||
values = [input_dict.get(key, default_value) for key in keys]
|
||||
return (values,)
|
||||
|
||||
|
||||
class DictInvert:
|
||||
"""
|
||||
Creates a new dictionary with keys and values swapped.
|
||||
|
||||
This node takes a dictionary as input and returns a new dictionary where
|
||||
the keys become values and values become keys. Note that values must be
|
||||
hashable to be used as keys in the new dictionary.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input_dict": ("DICT", {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("DICT", "BOOLEAN")
|
||||
RETURN_NAMES = ("inverted_dict", "success")
|
||||
CATEGORY = "Basic/DICT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "invert"
|
||||
|
||||
def invert(self, input_dict: dict) -> tuple[dict, bool]:
|
||||
try:
|
||||
inverted = {v: k for k, v in input_dict.items()}
|
||||
return inverted, True
|
||||
except Exception:
|
||||
# Return original dictionary if inversion fails (e.g., unhashable values)
|
||||
return input_dict, False
|
||||
|
||||
|
||||
class DictCreateFromLists:
|
||||
"""
|
||||
Creates a dictionary from separate lists of keys and values.
|
||||
|
||||
This node takes a list of keys and a list of values, then creates a dictionary
|
||||
by pairing corresponding elements from each list. If the lists are of different
|
||||
lengths, only pairs up to the length of the shorter list are used.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"keys": ("LIST", {}),
|
||||
"values": ("LIST", {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("DICT",)
|
||||
CATEGORY = "Basic/DICT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "create_from_lists"
|
||||
|
||||
def create_from_lists(self, keys: list, values: list) -> tuple[dict]:
|
||||
# Pair keys with values up to the length of the shorter list
|
||||
result = dict(zip(keys, values))
|
||||
return (result,)
|
||||
|
||||
|
||||
class DictCompare:
|
||||
"""
|
||||
Compares two dictionaries and reports differences.
|
||||
|
||||
This node takes two dictionaries and compares them, returning information about
|
||||
their equality, any keys that exist in only one dictionary, and any keys with
|
||||
different values.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"dict1": ("DICT", {}),
|
||||
"dict2": ("DICT", {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("BOOLEAN", "LIST", "LIST", "LIST")
|
||||
RETURN_NAMES = ("are_equal", "only_in_dict1", "only_in_dict2", "different_values")
|
||||
CATEGORY = "Basic/DICT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "compare"
|
||||
|
||||
def compare(self, dict1: dict, dict2: dict) -> tuple[bool, list, list, list]:
|
||||
are_equal = (dict1 == dict2)
|
||||
|
||||
keys1 = set(dict1.keys())
|
||||
keys2 = set(dict2.keys())
|
||||
|
||||
only_in_dict1 = list(keys1 - keys2)
|
||||
only_in_dict2 = list(keys2 - keys1)
|
||||
|
||||
different_values = []
|
||||
for key in keys1 & keys2:
|
||||
if dict1[key] != dict2[key]:
|
||||
different_values.append(key)
|
||||
|
||||
return are_equal, only_in_dict1, only_in_dict2, different_values
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"DictCreate": DictCreate,
|
||||
"DictCreateFromItems": DictCreateFromItems,
|
||||
"DictGet": DictGet,
|
||||
"DictSet": DictSet,
|
||||
"DictKeys": DictKeys,
|
||||
"DictValues": DictValues,
|
||||
"DictItems": DictItems,
|
||||
"DictContainsKey": DictContainsKey,
|
||||
"DictClear": DictClear,
|
||||
"DictCopy": DictCopy,
|
||||
"DictFromKeys": DictFromKeys,
|
||||
"DictPop": DictPop,
|
||||
"DictPopItem": DictPopItem,
|
||||
"DictSetDefault": DictSetDefault,
|
||||
"DictUpdate": DictUpdate,
|
||||
"DictLength": DictLength,
|
||||
"DictMerge": DictMerge,
|
||||
"DictGetKeysValues": DictGetKeysValues,
|
||||
"DictRemove": DictRemove,
|
||||
"AnyToDict": AnyToDict,
|
||||
"DictFilterByKeys": DictFilterByKeys,
|
||||
"DictExcludeKeys": DictExcludeKeys,
|
||||
"DictGetMultiple": DictGetMultiple,
|
||||
"DictInvert": DictInvert,
|
||||
"DictCreateFromLists": DictCreateFromLists,
|
||||
"DictCompare": DictCompare,
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"DictCreate": "create",
|
||||
"DictCreateFromItems": "from_items",
|
||||
"DictGet": "get",
|
||||
"DictSet": "set",
|
||||
"DictKeys": "keys",
|
||||
"DictValues": "values",
|
||||
"DictItems": "items",
|
||||
"DictContainsKey": "contains_key",
|
||||
"DictClear": "clear",
|
||||
"DictCopy": "copy",
|
||||
"DictFromKeys": "fromkeys",
|
||||
"DictPop": "pop",
|
||||
"DictPopItem": "popitem",
|
||||
"DictSetDefault": "setdefault",
|
||||
"DictUpdate": "update",
|
||||
"DictLength": "length",
|
||||
"DictMerge": "merge",
|
||||
"DictGetKeysValues": "get_keys_values",
|
||||
"DictRemove": "remove",
|
||||
"AnyToDict": "any_to_DICT",
|
||||
"DictFilterByKeys": "filter_by_keys",
|
||||
"DictExcludeKeys": "exclude_keys",
|
||||
"DictGetMultiple": "get_multiple",
|
||||
"DictInvert": "invert",
|
||||
"DictCreateFromLists": "from_lists",
|
||||
"DictCompare": "compare",
|
||||
}
|
||||
|
||||
@@ -1,143 +1,141 @@
|
||||
from typing import Any
|
||||
|
||||
from inspect import cleandoc
|
||||
|
||||
class ListAppend:
|
||||
class ListConvertToDataList:
|
||||
"""
|
||||
Adds an item to the end of a list.
|
||||
Converts a LIST object into a ComfyUI data list.
|
||||
|
||||
This node takes a list and any item as inputs, then returns the modified
|
||||
list with the new item appended.
|
||||
This node takes a LIST object (Python list as a single variable) and
|
||||
converts it to a ComfyUI data list, allowing its items to be processed
|
||||
individually by nodes that accept data lists.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"optional": {
|
||||
"list":("*",{}),
|
||||
"item":("*",{}),
|
||||
"required": {
|
||||
"list": ("LIST", {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("*",)
|
||||
RETURN_NAMES = ("list",)
|
||||
CATEGORY = "Basic/list"
|
||||
CATEGORY = "Basic/LIST"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "append"
|
||||
INPUT_IS_LIST = True
|
||||
FUNCTION = "convert"
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
def convert(self, list) -> tuple[list[Any]]:
|
||||
return (list,)
|
||||
|
||||
def append(self, **kwargs: dict[str, list]) -> tuple[list[Any]]:
|
||||
result = kwargs.get('list', []).copy()
|
||||
item = kwargs.get('item', [])
|
||||
if len(item) > 0:
|
||||
result.append(item[0])
|
||||
|
||||
class ListAppend:
|
||||
"""
|
||||
Adds an item to the end of a LIST.
|
||||
|
||||
This node takes a LIST and any item as inputs, then returns a new LIST
|
||||
with the item appended to the end.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"list": ("LIST", {}),
|
||||
"item": ("*", {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("LIST",)
|
||||
CATEGORY = "Basic/LIST"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "append"
|
||||
|
||||
def append(self, list: list[Any], item: Any) -> tuple[list[Any]]:
|
||||
result = list.copy()
|
||||
result.append(item)
|
||||
return (result,)
|
||||
|
||||
|
||||
class ListExtend:
|
||||
"""
|
||||
Extends a list by appending elements from another list.
|
||||
Extends a LIST by appending elements from another LIST.
|
||||
|
||||
This node takes two lists as input and returns a new list that contains
|
||||
This node takes two LIST objects as input and returns a new LIST that contains
|
||||
all elements from both lists.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"optional": {
|
||||
"list_a": ("*",{}),
|
||||
"list_b": ("*",{}),
|
||||
"required": {
|
||||
"list1": ("LIST", {}),
|
||||
"list2": ("LIST", {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("*",)
|
||||
RETURN_NAMES = ("list",)
|
||||
CATEGORY = "Basic/list"
|
||||
RETURN_TYPES = ("LIST",)
|
||||
CATEGORY = "Basic/LIST"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "extend"
|
||||
INPUT_IS_LIST = True
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def extend(self, **kwargs: dict[str, list]) -> tuple[list[Any]]:
|
||||
return (kwargs.get('list_a', []) + kwargs.get('list_b', []),)
|
||||
def extend(self, list1: list[Any], list2: list[Any]) -> tuple[list[Any]]:
|
||||
result = list1.copy()
|
||||
result.extend(list2)
|
||||
return (result,)
|
||||
|
||||
|
||||
class ListInsert:
|
||||
"""
|
||||
Inserts an item at a specified position in a list.
|
||||
Inserts an item at a specified position in a LIST.
|
||||
|
||||
This node takes a list, an index, and any item as inputs, then returns a new
|
||||
list with the item inserted at the specified index.
|
||||
This node takes a LIST, an index, and any item as inputs, then returns a new
|
||||
LIST with the item inserted at the specified index.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"list": ("*",),
|
||||
"list": ("LIST", {}),
|
||||
"index": ("INT", {"default": 0}),
|
||||
"item": ("*",),
|
||||
"item": ("*", {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("*",)
|
||||
RETURN_NAMES = ("list",)
|
||||
CATEGORY = "Basic/list"
|
||||
RETURN_TYPES = ("LIST",)
|
||||
CATEGORY = "Basic/LIST"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "insert"
|
||||
INPUT_IS_LIST = True
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def insert(self, **kwargs: dict[str, list]) -> tuple[list[Any]]:
|
||||
result = kwargs.get('list', []).copy()
|
||||
result.insert(kwargs.get('index', [0])[0], kwargs.get('item', [None])[0])
|
||||
def insert(self, list: list[Any], index: int, item: Any) -> tuple[list[Any]]:
|
||||
result = list.copy()
|
||||
result.insert(index, item)
|
||||
return (result,)
|
||||
|
||||
|
||||
class ListRemove:
|
||||
"""
|
||||
Removes the first occurrence of a specified value from a list.
|
||||
Removes the first occurrence of a specified value from a LIST.
|
||||
|
||||
This node takes a list and a value as inputs, then returns a new list with
|
||||
the first occurrence of the value removed. Raises a ValueError if the value is not present.
|
||||
This node takes a LIST and a value as inputs, then returns a new LIST with
|
||||
the first occurrence of the value removed and a success indicator. If the value
|
||||
is not present, the original LIST is returned with success set to False.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"list": ("*",),
|
||||
"value": ("*",),
|
||||
"list": ("LIST", {}),
|
||||
"value": ("*", {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("*", "BOOLEAN",)
|
||||
RETURN_NAMES = ("list", "success",)
|
||||
CATEGORY = "Basic/list"
|
||||
RETURN_TYPES = ("LIST", "BOOLEAN")
|
||||
RETURN_NAMES = ("list", "success")
|
||||
CATEGORY = "Basic/LIST"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "remove"
|
||||
INPUT_IS_LIST = True
|
||||
OUTPUT_IS_LIST = (True, False,)
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def remove(self, **kwargs: dict[str, list]) -> tuple[list[Any], bool]:
|
||||
result = kwargs.get('list', []).copy()
|
||||
value = kwargs.get('value', [])
|
||||
def remove(self, list: list[Any], value: Any) -> tuple[list[Any], bool]:
|
||||
result = list.copy()
|
||||
try:
|
||||
result.remove(value[0])
|
||||
result.remove(value)
|
||||
return result, True
|
||||
except ValueError:
|
||||
return result, False
|
||||
@@ -145,41 +143,32 @@ class ListRemove:
|
||||
|
||||
class ListPop:
|
||||
"""
|
||||
Removes and returns an item at a specified position in a list.
|
||||
Removes and returns an item at a specified position in a LIST.
|
||||
|
||||
This node takes a list and an index as inputs, then returns both the new list
|
||||
This node takes a LIST and an index as inputs, then returns both the new LIST
|
||||
with the item removed and the removed item. If no index is specified,
|
||||
removes and returns the last item.
|
||||
When the list is empty, the item is None.
|
||||
When the LIST is empty, the item is None.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"list": ("*",),
|
||||
"list": ("LIST", {}),
|
||||
},
|
||||
"optional": {
|
||||
"index": ("INT", {"default": -1}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("*", "*")
|
||||
RETURN_TYPES = ("LIST", "*")
|
||||
RETURN_NAMES = ("list", "item")
|
||||
CATEGORY = "Basic/list"
|
||||
CATEGORY = "Basic/LIST"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "pop"
|
||||
INPUT_IS_LIST = True
|
||||
OUTPUT_IS_LIST = (True, False)
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
if input_types["index"] not in ("INT"):
|
||||
return "index must be an INT type"
|
||||
return True
|
||||
|
||||
def pop(self, **kwargs: dict[str, list]) -> tuple[list[Any], Any]:
|
||||
result = kwargs.get('list', []).copy()
|
||||
index = kwargs.get('index', [-1])[0]
|
||||
def pop(self, list: list[Any], index: int = -1) -> tuple[list[Any], Any]:
|
||||
result = list.copy()
|
||||
try:
|
||||
item = result.pop(index)
|
||||
return result, item
|
||||
@@ -189,49 +178,41 @@ class ListPop:
|
||||
|
||||
class ListClear:
|
||||
"""
|
||||
Removes all items from a list.
|
||||
Removes all items from a LIST.
|
||||
|
||||
This node takes a list as input and returns a new empty list.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"optional": {
|
||||
"list": ("*",),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("*",)
|
||||
RETURN_NAMES = ("list",)
|
||||
CATEGORY = "Basic/list"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "clear"
|
||||
INPUT_IS_LIST = True
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def clear(self, **kwargs: dict[str, list]) -> tuple[[]]:
|
||||
# Return a new empty list rather than modifying the input
|
||||
return ([],)
|
||||
|
||||
|
||||
class ListIndex:
|
||||
"""
|
||||
Returns the index of the first occurrence of a value in a list.
|
||||
|
||||
This node takes a list and a value as inputs, then returns the index of the first
|
||||
occurrence of the value. Optional start and end parameters limit the search to a slice
|
||||
of the list. Returns -1 if the value is not present.
|
||||
This node takes a LIST as input and returns a new empty LIST.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"list": ("*",),
|
||||
"value": ("*",),
|
||||
"list": ("LIST", {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("LIST",)
|
||||
CATEGORY = "Basic/LIST"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "clear"
|
||||
|
||||
def clear(self, list: list[Any]) -> tuple[list[Any]]:
|
||||
return ([],)
|
||||
|
||||
|
||||
class ListIndex:
|
||||
"""
|
||||
Returns the index of the first occurrence of a value in a LIST.
|
||||
|
||||
This node takes a LIST and a value as inputs, then returns the index of the first
|
||||
occurrence of the value. Optional start and end parameters limit the search to a slice
|
||||
of the LIST. Returns -1 if the value is not present.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"list": ("LIST", {}),
|
||||
"value": ("*", {}),
|
||||
},
|
||||
"optional": {
|
||||
"start": ("INT", {"default": 0}),
|
||||
@@ -241,202 +222,143 @@ class ListIndex:
|
||||
|
||||
RETURN_TYPES = ("INT",)
|
||||
RETURN_NAMES = ("index",)
|
||||
CATEGORY = "Basic/list"
|
||||
CATEGORY = "Basic/LIST"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "list_index"
|
||||
INPUT_IS_LIST = True
|
||||
FUNCTION = "index"
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def list_index(self, **kwargs: dict[str, list]) -> tuple[int]:
|
||||
input_list = kwargs.get('list', [])
|
||||
value = kwargs.get('value', [None])[0]
|
||||
start = kwargs.get('start', [0])[0]
|
||||
end = kwargs.get('end', [-1])[0]
|
||||
def index(self, list: list[Any], value: Any, start: int = 0, end: int = -1) -> tuple[int]:
|
||||
if end == -1:
|
||||
end = len(input_list)
|
||||
end = len(list)
|
||||
|
||||
try:
|
||||
return (input_list.index(value, start, end),)
|
||||
return (list.index(value, start, end),)
|
||||
except ValueError:
|
||||
return (-1,)
|
||||
|
||||
|
||||
class ListCount:
|
||||
"""
|
||||
Counts the number of occurrences of a value in a list.
|
||||
Counts the number of occurrences of a value in a LIST.
|
||||
|
||||
This node takes a list and a value as inputs, then returns the number of times
|
||||
the value appears in the list.
|
||||
This node takes a LIST and a value as inputs, then returns the number of times
|
||||
the value appears in the LIST.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"list": ("*",),
|
||||
"value": ("*",),
|
||||
"list": ("LIST", {}),
|
||||
"value": ("*", {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("INT",)
|
||||
RETURN_NAMES = ("count",)
|
||||
CATEGORY = "Basic/list"
|
||||
CATEGORY = "Basic/LIST"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "count"
|
||||
INPUT_IS_LIST = True
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def count(self, **kwargs: dict[str, list]) -> tuple[int]:
|
||||
value = kwargs.get('value', [None])[0]
|
||||
return (kwargs.get('list', []).count(value),)
|
||||
def count(self, list: list[Any], value: Any) -> tuple[int]:
|
||||
return (list.count(value),)
|
||||
|
||||
|
||||
class ListSort:
|
||||
"""
|
||||
Sorts the items in a list.
|
||||
Sorts the items in a LIST.
|
||||
|
||||
This node takes a list as input and returns a new sorted list.
|
||||
Options include sorting in reverse order and using a key function.
|
||||
This node takes a LIST as input and returns a new sorted LIST.
|
||||
Option includes sorting in reverse order.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"list": ("*",),
|
||||
"list": ("LIST", {}),
|
||||
},
|
||||
"optional": {
|
||||
"reverse": (["False", "True"], {"default": "False"}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("*",)
|
||||
RETURN_NAMES = ("list",)
|
||||
CATEGORY = "Basic/list"
|
||||
RETURN_TYPES = ("LIST",)
|
||||
CATEGORY = "Basic/LIST"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "sort"
|
||||
INPUT_IS_LIST = True
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def sort(self, **kwargs: dict[str, list]) -> tuple[list[Any]]:
|
||||
def sort(self, list: list[Any], reverse: str = "False") -> tuple[list[Any]]:
|
||||
# Convert string to boolean
|
||||
reverse = kwargs.get('reverse', ["False"])[0] == "True"
|
||||
reverse_bool = (reverse == "True")
|
||||
|
||||
result = sorted(kwargs.get('list', []), reverse=reverse)
|
||||
return (result,)
|
||||
# Use sorted to create a new sorted list
|
||||
try:
|
||||
result = sorted(list, reverse=reverse_bool)
|
||||
return (result,)
|
||||
except TypeError:
|
||||
# If list contains mixed types that can't be compared, return original list
|
||||
return (list.copy(),)
|
||||
|
||||
|
||||
class ListReverse:
|
||||
"""
|
||||
Reverses the order of items in a list.
|
||||
Reverses the order of items in a LIST.
|
||||
|
||||
This node takes a list as input and returns a new list with the items in reversed order.
|
||||
This node takes a LIST as input and returns a new LIST with the items in reversed order.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"list": ("*",),
|
||||
"list": ("LIST", {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("*",)
|
||||
RETURN_NAMES = ("list",)
|
||||
CATEGORY = "Basic/list"
|
||||
RETURN_TYPES = ("LIST",)
|
||||
CATEGORY = "Basic/LIST"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "reverse"
|
||||
INPUT_IS_LIST = True
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def reverse(self, **kwargs: dict[str, list]) -> tuple[list[Any]]:
|
||||
result = kwargs.get('list', []).copy()
|
||||
def reverse(self, list: list[Any]) -> tuple[list[Any]]:
|
||||
result = list.copy()
|
||||
result.reverse()
|
||||
return (result,)
|
||||
|
||||
|
||||
class ListCopy:
|
||||
"""
|
||||
Creates a shallow copy of a list.
|
||||
|
||||
This node takes a list as input and returns a new list that is a shallow copy of the original.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"list": ("*",),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("*",)
|
||||
RETURN_NAMES = ("list",)
|
||||
CATEGORY = "Basic/list"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "copy"
|
||||
INPUT_IS_LIST = True
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def copy(self, **kwargs: dict[str, list]) -> tuple[list[Any]]:
|
||||
return (kwargs.get('list', []).copy(),)
|
||||
|
||||
|
||||
class ListLength:
|
||||
"""
|
||||
Counts the number of items in a list.
|
||||
Returns the number of items in a LIST.
|
||||
|
||||
This node takes a list as input and returns its length as an integer.
|
||||
This node takes a LIST as input and returns its length as an integer.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"list": ("*",),
|
||||
"list": ("LIST", {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("INT",)
|
||||
RETURN_NAMES = ("length",)
|
||||
CATEGORY = "Basic/list"
|
||||
CATEGORY = "Basic/LIST"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "length"
|
||||
INPUT_IS_LIST = True
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def length(self, **kwargs: dict[str, list]) -> tuple[int]:
|
||||
return (len(kwargs.get('list', [])),)
|
||||
def length(self, list: list[Any]) -> tuple[int]:
|
||||
return (len(list),)
|
||||
|
||||
|
||||
class ListSlice:
|
||||
"""
|
||||
Creates a slice of a list.
|
||||
Creates a slice of a LIST.
|
||||
|
||||
This node takes a list and start/stop/step parameters, and returns a new list
|
||||
containing the specified slice of the original list.
|
||||
This node takes a LIST and start/stop/step parameters, and returns a new LIST
|
||||
containing the specified slice of the original LIST.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"list": ("*",),
|
||||
"list": ("LIST", {}),
|
||||
},
|
||||
"optional": {
|
||||
"start": ("INT", {"default": 0}),
|
||||
@@ -445,210 +367,132 @@ class ListSlice:
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("*",)
|
||||
RETURN_NAMES = ("list",)
|
||||
CATEGORY = "Basic/list"
|
||||
RETURN_TYPES = ("LIST",)
|
||||
CATEGORY = "Basic/LIST"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "slice"
|
||||
INPUT_IS_LIST = True
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def slice(self, **kwargs: dict[str, list]) -> tuple[list[Any]]:
|
||||
input_list = kwargs.get('list', [])
|
||||
start = kwargs.get('start', [0])[0]
|
||||
stop = kwargs.get('stop', [-1])[0]
|
||||
step = kwargs.get('step', [1])[0]
|
||||
|
||||
def slice(self, list: list[Any], start: int = 0, stop: int = -1, step: int = 1) -> tuple[list[Any]]:
|
||||
if stop == -1:
|
||||
stop = len(input_list)
|
||||
stop = len(list)
|
||||
|
||||
return (input_list[start:stop:step],)
|
||||
return (list[start:stop:step],)
|
||||
|
||||
|
||||
class ListGetItem:
|
||||
"""
|
||||
Retrieves an item at a specified position in a list.
|
||||
Retrieves an item at a specified position in a LIST.
|
||||
|
||||
This node takes a list and an index as inputs, then returns the item at the specified index.
|
||||
Negative indices count from the end of the list.
|
||||
This node takes a LIST and an index as inputs, then returns the item at the specified index.
|
||||
Negative indices count from the end of the LIST.
|
||||
Out of range indices return None.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input_list": ("*",),
|
||||
"list": ("LIST", {}),
|
||||
"index": ("INT", {"default": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("*",)
|
||||
RETURN_NAMES = ("item",)
|
||||
CATEGORY = "Basic/list"
|
||||
CATEGORY = "Basic/LIST"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "get_item"
|
||||
INPUT_IS_LIST = True
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def get_item(self, **kwargs: dict[str, list]) -> tuple[Any]:
|
||||
index = kwargs.get('index', [0])[0]
|
||||
def get_item(self, list: list[Any], index: int) -> tuple[Any]:
|
||||
try:
|
||||
return (kwargs.get('list', [])[index],)
|
||||
return (list[index],)
|
||||
except IndexError:
|
||||
return (None,)
|
||||
|
||||
|
||||
class ListSetItem:
|
||||
"""
|
||||
Sets an item at a specified position in a list.
|
||||
Sets an item at a specified position in a LIST.
|
||||
|
||||
This node takes a list, an index, and a value, then returns a new list with
|
||||
This node takes a LIST, an index, and a value, then returns a new LIST with
|
||||
the item at the specified index replaced by the value.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"list": ("*",),
|
||||
"list": ("LIST", {}),
|
||||
"index": ("INT", {"default": 0}),
|
||||
"value": ("*",),
|
||||
"value": ("*", {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("*",)
|
||||
RETURN_NAMES = ("list",)
|
||||
CATEGORY = "Basic/list"
|
||||
RETURN_TYPES = ("LIST",)
|
||||
CATEGORY = "Basic/LIST"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "set_item"
|
||||
INPUT_IS_LIST = True
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def set_item(self, **kwargs: dict[str, list]) -> tuple[Any]:
|
||||
input_list = kwargs.get('list', [])
|
||||
index = kwargs.get('index', [0])[0]
|
||||
value = kwargs.get('value', [None])[0]
|
||||
def set_item(self, list: list[Any], index: int, value: Any) -> tuple[list[Any]]:
|
||||
result = list.copy()
|
||||
try:
|
||||
result = input_list.copy()
|
||||
result[index] = value
|
||||
return (result,)
|
||||
except IndexError:
|
||||
raise IndexError(f"Index {index} out of range for list of length {len(input_list)}")
|
||||
raise IndexError(f"Index {index} out of range for LIST of length {len(list)}")
|
||||
|
||||
|
||||
class ListContains:
|
||||
"""
|
||||
Checks if a list contains a specified value.
|
||||
Checks if a LIST contains a specified value.
|
||||
|
||||
This node takes a list and a value as inputs, then returns True if the value
|
||||
is present in the list, and False otherwise.
|
||||
This node takes a LIST and a value as inputs, then returns True if the value
|
||||
is present in the LIST, and False otherwise.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input_list": ("*",),
|
||||
"value": ("*",),
|
||||
"list": ("LIST", {}),
|
||||
"value": ("*", {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("BOOLEAN",)
|
||||
RETURN_NAMES = ("contains",)
|
||||
CATEGORY = "Basic/list"
|
||||
CATEGORY = "Basic/LIST"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "contains"
|
||||
INPUT_IS_LIST = True
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def contains(self, **kwargs: dict[str, list]) -> tuple[bool]:
|
||||
value = kwargs.get('value', [])
|
||||
if len(value) == 0:
|
||||
return (False,)
|
||||
return (value[0] in kwargs.get('list', []),)
|
||||
def contains(self, list: list[Any], value: Any) -> tuple[bool]:
|
||||
return (value in list,)
|
||||
|
||||
|
||||
class ListCreateEmpty:
|
||||
class AnyToList:
|
||||
"""
|
||||
Creates a new empty list.
|
||||
Converts any input datatype into a LIST.
|
||||
|
||||
This node creates and returns an empty list.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {"required": {}}
|
||||
|
||||
RETURN_TYPES = ("*",)
|
||||
RETURN_NAMES = ("list",)
|
||||
CATEGORY = "Basic/list"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "create_empty"
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
|
||||
def create_empty(self) -> tuple[[]]:
|
||||
return ([],)
|
||||
|
||||
|
||||
class ListZip:
|
||||
"""
|
||||
Combines multiple lists element-wise.
|
||||
|
||||
This node takes multiple data lists as input and returns a new data list
|
||||
where each item is a list containing the corresponding elements from the input lists.
|
||||
The length of the output list will be equal to the length of the shortest input list.
|
||||
This node takes any input value and wraps it in a LIST object,
|
||||
allowing it to be processed by nodes that expect LIST inputs.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"list1": ("*",),
|
||||
"list2": ("*",),
|
||||
},
|
||||
"optional": {
|
||||
"list3": ("*",),
|
||||
"list4": ("*",),
|
||||
"input": ("*", {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("*",)
|
||||
RETURN_NAMES = ("list",)
|
||||
CATEGORY = "Basic/list"
|
||||
RETURN_TYPES = ("LIST",)
|
||||
CATEGORY = "Basic/LIST"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "zip_lists"
|
||||
INPUT_IS_LIST = True
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
FUNCTION = "convert"
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def zip_lists(self, **kwargs: dict[str, list]) -> tuple[list[Any]]:
|
||||
lists = [kwargs.get('list1', []), kwargs.get('list2', [])]
|
||||
|
||||
if 'list3' in kwargs:
|
||||
lists.append(kwargs['list3'])
|
||||
|
||||
if 'list4' in kwargs:
|
||||
lists.append(kwargs['list4'])
|
||||
|
||||
# Zip the lists together and convert each tuple to a list
|
||||
result = [list(item) for item in zip(*lists)]
|
||||
return (result,)
|
||||
def convert(self, input: Any) -> tuple[list[Any]]:
|
||||
# Create a new list containing the input value
|
||||
return ([input],)
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"ListConvertToDataList": ListConvertToDataList,
|
||||
"ListAppend": ListAppend,
|
||||
"ListExtend": ListExtend,
|
||||
"ListInsert": ListInsert,
|
||||
@@ -659,17 +503,16 @@ NODE_CLASS_MAPPINGS = {
|
||||
"ListCount": ListCount,
|
||||
"ListSort": ListSort,
|
||||
"ListReverse": ListReverse,
|
||||
"ListCopy": ListCopy,
|
||||
"ListLength": ListLength,
|
||||
"ListSlice": ListSlice,
|
||||
"ListGetItem": ListGetItem,
|
||||
"ListSetItem": ListSetItem,
|
||||
"ListContains": ListContains,
|
||||
"ListCreateEmpty": ListCreateEmpty,
|
||||
"ListZip": ListZip,
|
||||
"AnyToList": AnyToList,
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"ListConvertToDataList": "convert to data list",
|
||||
"ListAppend": "append",
|
||||
"ListExtend": "extend",
|
||||
"ListInsert": "insert",
|
||||
@@ -680,12 +523,10 @@ NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"ListCount": "count",
|
||||
"ListSort": "sort",
|
||||
"ListReverse": "reverse",
|
||||
"ListCopy": "copy",
|
||||
"ListLength": "length",
|
||||
"ListSlice": "slice",
|
||||
"ListGetItem": "get_item",
|
||||
"ListSetItem": "set_item",
|
||||
"ListGetItem": "get item",
|
||||
"ListSetItem": "set item",
|
||||
"ListContains": "contains",
|
||||
"ListCreateEmpty": "create_empty",
|
||||
"ListZip": "zip",
|
||||
"AnyToList": "any to LIST",
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user