Add BOOLEAN, FLOAT, INT and data lists.
Bump to version 0.0.3
This commit is contained in:
@@ -6,10 +6,6 @@ __all__ = [
|
||||
"WEB_DIRECTORY",
|
||||
]
|
||||
|
||||
__author__ = """Basic data handling"""
|
||||
__email__ = "stablellama@tutanota.com"
|
||||
__version__ = "0.0.1"
|
||||
|
||||
from .src.basic_data_handling import NODE_CLASS_MAPPINGS
|
||||
from .src.basic_data_handling import NODE_DISPLAY_NAME_MAPPINGS
|
||||
|
||||
|
||||
+4
-6
@@ -4,18 +4,16 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "basic_data_handling"
|
||||
version = "0.0.2"
|
||||
description = """Basic Python functions for manipulating data that every programmer
|
||||
is used to. Currently supported: STRING."""
|
||||
version = "0.0.3"
|
||||
description = """Basic Python functions for manipulating data that every programmer is used to.
|
||||
Currently supported: BOOLEAN, FLOAT, INT, STRING and data lists."""
|
||||
authors = [
|
||||
{name = "Basic data handling"}
|
||||
]
|
||||
readme = "README.md"
|
||||
license = {text = "MIT license"}
|
||||
classifiers = []
|
||||
dependencies = [
|
||||
|
||||
]
|
||||
dependencies = []
|
||||
|
||||
[project.optional-dependencies]
|
||||
dev = [
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
from . import string_nodes, list_nodes, dict_nodes
|
||||
from . import boolean_nodes, dict_nodes, float_nodes, int_nodes, list_nodes, string_nodes
|
||||
|
||||
NODE_CLASS_MAPPINGS = {}
|
||||
NODE_CLASS_MAPPINGS.update(string_nodes.NODE_CLASS_MAPPINGS)
|
||||
NODE_CLASS_MAPPINGS.update(list_nodes.NODE_CLASS_MAPPINGS)
|
||||
NODE_CLASS_MAPPINGS.update(boolean_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)
|
||||
NODE_CLASS_MAPPINGS.update(list_nodes.NODE_CLASS_MAPPINGS)
|
||||
NODE_CLASS_MAPPINGS.update(string_nodes.NODE_CLASS_MAPPINGS)
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {}
|
||||
NODE_DISPLAY_NAME_MAPPINGS.update(string_nodes.NODE_DISPLAY_NAME_MAPPINGS)
|
||||
NODE_DISPLAY_NAME_MAPPINGS.update(list_nodes.NODE_DISPLAY_NAME_MAPPINGS)
|
||||
NODE_DISPLAY_NAME_MAPPINGS.update(boolean_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)
|
||||
NODE_DISPLAY_NAME_MAPPINGS.update(list_nodes.NODE_DISPLAY_NAME_MAPPINGS)
|
||||
NODE_DISPLAY_NAME_MAPPINGS.update(string_nodes.NODE_DISPLAY_NAME_MAPPINGS)
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
from inspect import cleandoc
|
||||
|
||||
class BooleanAnd:
|
||||
"""
|
||||
Returns the logical AND result of two boolean values.
|
||||
|
||||
This node takes two boolean inputs and returns their logical AND result.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input1": ("BOOLEAN", {"default": False}),
|
||||
"input2": ("BOOLEAN", {"default": False}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("BOOLEAN",)
|
||||
CATEGORY = "Basic/BOOLEAN"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "and_operation"
|
||||
|
||||
def and_operation(self, input1: bool, input2: bool) -> tuple[bool]:
|
||||
return (input1 and input2,)
|
||||
|
||||
|
||||
class BooleanOr:
|
||||
"""
|
||||
Returns the logical OR result of two boolean values.
|
||||
|
||||
This node takes two boolean inputs and returns their logical OR result.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input1": ("BOOLEAN", {"default": False}),
|
||||
"input2": ("BOOLEAN", {"default": False}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("BOOLEAN",)
|
||||
CATEGORY = "Basic/BOOLEAN"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "or_operation"
|
||||
|
||||
def or_operation(self, input1: bool, input2: bool) -> tuple[bool]:
|
||||
return (input1 or input2,)
|
||||
|
||||
|
||||
class BooleanNot:
|
||||
"""
|
||||
Returns the logical NOT result of a boolean value.
|
||||
|
||||
This node takes one boolean input and returns its logical NOT result.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input": ("BOOLEAN", {"default": False}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("BOOLEAN",)
|
||||
CATEGORY = "Basic/BOOLEAN"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "not_operation"
|
||||
|
||||
def not_operation(self, input: bool) -> tuple[bool]:
|
||||
return (not input,)
|
||||
|
||||
|
||||
class BooleanXor:
|
||||
"""
|
||||
Returns the logical XOR result of two boolean values.
|
||||
|
||||
This node takes two boolean inputs and returns their logical XOR result.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input1": ("BOOLEAN", {"default": False}),
|
||||
"input2": ("BOOLEAN", {"default": False}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("BOOLEAN",)
|
||||
CATEGORY = "Basic/BOOLEAN"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "xor_operation"
|
||||
|
||||
def xor_operation(self, input1: bool, input2: bool) -> tuple[bool]:
|
||||
return (input1 != input2,)
|
||||
|
||||
|
||||
class BooleanNand:
|
||||
"""
|
||||
Returns the logical NAND result of two boolean values.
|
||||
|
||||
This node takes two boolean inputs and returns their logical NAND result.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input1": ("BOOLEAN", {"default": False}),
|
||||
"input2": ("BOOLEAN", {"default": False}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("BOOLEAN",)
|
||||
CATEGORY = "Basic/BOOLEAN"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "nand_operation"
|
||||
|
||||
def nand_operation(self, input1: bool, input2: bool) -> tuple[bool]:
|
||||
return (not (input1 and input2),)
|
||||
|
||||
|
||||
class BooleanNor:
|
||||
"""
|
||||
Returns the logical NOR result of two boolean values.
|
||||
|
||||
This node takes two boolean inputs and returns their logical NOR result.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input1": ("BOOLEAN", {"default": False}),
|
||||
"input2": ("BOOLEAN", {"default": False}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("BOOLEAN",)
|
||||
CATEGORY = "Basic/BOOLEAN"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "nor_operation"
|
||||
|
||||
def nor_operation(self, input1: bool, input2: bool) -> tuple[bool]:
|
||||
return (not (input1 or input2),)
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"BooleanAnd": BooleanAnd,
|
||||
"BooleanOr": BooleanOr,
|
||||
"BooleanNot": BooleanNot,
|
||||
"BooleanXor": BooleanXor,
|
||||
"BooleanNand": BooleanNand,
|
||||
"BooleanNor": BooleanNor,
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"BooleanAnd": "and",
|
||||
"BooleanOr": "or",
|
||||
"BooleanNot": "not",
|
||||
"BooleanXor": "xor",
|
||||
"BooleanNand": "nand",
|
||||
"BooleanNor": "nor",
|
||||
}
|
||||
@@ -0,0 +1,274 @@
|
||||
from inspect import cleandoc
|
||||
|
||||
class FloatAdd:
|
||||
"""
|
||||
Adds two floating-point numbers.
|
||||
|
||||
This node takes two floats as input and returns their sum.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"float1": ("FLOAT", {"default": 0.0}),
|
||||
"float2": ("FLOAT", {"default": 0.0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("FLOAT",)
|
||||
CATEGORY = "Basic/FLOAT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "add"
|
||||
|
||||
def add(self, float1: float, float2: float) -> tuple[float]:
|
||||
return (float1 + float2,)
|
||||
|
||||
|
||||
class FloatSubtract:
|
||||
"""
|
||||
Subtracts one floating-point number from another.
|
||||
|
||||
This node takes two floats as input and returns the result of subtracting
|
||||
the second float from the first.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"float1": ("FLOAT", {"default": 0.0}),
|
||||
"float2": ("FLOAT", {"default": 0.0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("FLOAT",)
|
||||
CATEGORY = "Basic/FLOAT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "subtract"
|
||||
|
||||
def subtract(self, float1: float, float2: float) -> tuple[float]:
|
||||
return (float1 - float2,)
|
||||
|
||||
|
||||
class FloatMultiply:
|
||||
"""
|
||||
Multiplies two floating-point numbers.
|
||||
|
||||
This node takes two floats as input and returns their product.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"float1": ("FLOAT", {"default": 1.0}),
|
||||
"float2": ("FLOAT", {"default": 1.0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("FLOAT",)
|
||||
CATEGORY = "Basic/FLOAT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "multiply"
|
||||
|
||||
def multiply(self, float1: float, float2: float) -> tuple[float]:
|
||||
return (float1 * float2,)
|
||||
|
||||
|
||||
class FloatDivide:
|
||||
"""
|
||||
Divides one floating-point number by another.
|
||||
|
||||
This node takes two floats as input and returns the result of division.
|
||||
It raises a ValueError if the divisor is 0.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"float1": ("FLOAT", {"default": 1.0}),
|
||||
"float2": ("FLOAT", {"default": 1.0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("FLOAT",)
|
||||
CATEGORY = "Basic/FLOAT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "divide"
|
||||
|
||||
def divide(self, float1: float, float2: float) -> tuple[float]:
|
||||
if float2 == 0.0:
|
||||
raise ValueError("Cannot divide by zero.")
|
||||
return (float1 / float2,)
|
||||
|
||||
|
||||
class FloatPower:
|
||||
"""
|
||||
Raises one floating-point number to the power of another.
|
||||
|
||||
This node takes two floats as input and returns the result of raising
|
||||
the first float to the power of the second.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"base": ("FLOAT", {"default": 1.0}),
|
||||
"exponent": ("FLOAT", {"default": 1.0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("FLOAT",)
|
||||
CATEGORY = "Basic/FLOAT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "power"
|
||||
|
||||
def power(self, base: float, exponent: float) -> tuple[float]:
|
||||
return (base ** exponent,)
|
||||
|
||||
|
||||
class FloatRound:
|
||||
"""
|
||||
Rounds a floating-point number to the specified number of decimal places.
|
||||
|
||||
This node takes a float and an integer for decimal places as inputs,
|
||||
and returns the rounded result.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"float_value": ("FLOAT", {"default": 0.0}),
|
||||
"decimal_places": ("INT", {"default": 2, "min": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("FLOAT",)
|
||||
CATEGORY = "Basic/FLOAT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "round"
|
||||
|
||||
def round(self, float_value: float, decimal_places: int) -> tuple[float]:
|
||||
return (round(float_value, decimal_places),)
|
||||
|
||||
|
||||
class FloatIsInteger:
|
||||
"""
|
||||
Checks if a floating-point number is an integer.
|
||||
|
||||
This node takes a floating-point number as input and returns True if the number
|
||||
is an integer, otherwise False.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"float_value": ("FLOAT", {"default": 0.0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("BOOLEAN",)
|
||||
CATEGORY = "Basic/FLOAT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "is_integer"
|
||||
|
||||
def is_integer(self, float_value: float) -> tuple[bool]:
|
||||
return (float_value.is_integer(),)
|
||||
|
||||
|
||||
class FloatAsIntegerRatio:
|
||||
"""
|
||||
Returns the integer ratio of a floating-point number.
|
||||
|
||||
This node takes a floating-point number and returns two integers,
|
||||
which represent the ratio as numerator and denominator.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"float_value": ("FLOAT", {"default": 0.0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("INT", "INT")
|
||||
RETURN_NAMES = ("numerator", "denominator")
|
||||
CATEGORY = "Basic/FLOAT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "as_integer_ratio"
|
||||
|
||||
def as_integer_ratio(self, float_value: float) -> tuple[int, int]:
|
||||
# Decompose the float into numerator and denominator
|
||||
numerator, denominator = float_value.as_integer_ratio()
|
||||
return numerator, denominator
|
||||
|
||||
|
||||
class FloatHex:
|
||||
"""
|
||||
Converts a floating-point number to its hexadecimal representation.
|
||||
|
||||
This node takes a float as input and returns its hexadecimal string representation.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"float_value": ("FLOAT", {"default": 0.0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
CATEGORY = "Basic/FLOAT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "to_hex"
|
||||
|
||||
def to_hex(self, float_value: float) -> tuple[str]:
|
||||
return (float_value.hex(),)
|
||||
|
||||
|
||||
class FloatFromHex:
|
||||
"""
|
||||
Converts a hexadecimal string to its corresponding floating-point number.
|
||||
|
||||
This node takes a hexadecimal float string as input and returns the float.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"hex_value": ("STRING", {"default": "0x0.0p+0"}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("FLOAT",)
|
||||
CATEGORY = "Basic/FLOAT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "from_hex"
|
||||
|
||||
def from_hex(self, hex_value: str) -> tuple[float]:
|
||||
return (float.fromhex(hex_value),)
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"FloatAdd": FloatAdd,
|
||||
"FloatSubtract": FloatSubtract,
|
||||
"FloatMultiply": FloatMultiply,
|
||||
"FloatDivide": FloatDivide,
|
||||
"FloatPower": FloatPower,
|
||||
"FloatRound": FloatRound,
|
||||
"FloatIsInteger": FloatIsInteger,
|
||||
"FloatAsIntegerRatio": FloatAsIntegerRatio,
|
||||
"FloatHex": FloatHex,
|
||||
"FloatFromHex": FloatFromHex,
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"FloatAdd": "add",
|
||||
"FloatSubtract": "subtract",
|
||||
"FloatMultiply": "multiply",
|
||||
"FloatDivide": "divide",
|
||||
"FloatPower": "power",
|
||||
"FloatRound": "round",
|
||||
"FloatIsInteger": "is_integer",
|
||||
"FloatAsIntegerRatio": "as_integer_ratio",
|
||||
"FloatHex": "to_hex",
|
||||
"FloatFromHex": "from_hex",
|
||||
}
|
||||
@@ -0,0 +1,285 @@
|
||||
from inspect import cleandoc
|
||||
from typing import Literal
|
||||
|
||||
|
||||
class IntAdd:
|
||||
"""
|
||||
Adds two integers.
|
||||
|
||||
This node takes two integers as input and returns their sum.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"int1": ("INT", {"default": 0}),
|
||||
"int2": ("INT", {"default": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("INT",)
|
||||
CATEGORY = "Basic/INT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "add"
|
||||
|
||||
def add(self, int1: int, int2: int) -> tuple[int]:
|
||||
return (int1 + int2,)
|
||||
|
||||
|
||||
class IntSubtract:
|
||||
"""
|
||||
Subtracts one integer from another.
|
||||
|
||||
This node takes two integers as input and returns the result of subtracting
|
||||
the second integer from the first.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"int1": ("INT", {"default": 0}),
|
||||
"int2": ("INT", {"default": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("INT",)
|
||||
CATEGORY = "Basic/INT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "subtract"
|
||||
|
||||
def subtract(self, int1: int, int2: int) -> tuple[int]:
|
||||
return (int1 - int2,)
|
||||
|
||||
|
||||
class IntMultiply:
|
||||
"""
|
||||
Multiplies two integers.
|
||||
|
||||
This node takes two integers as input and returns their product.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"int1": ("INT", {"default": 1}),
|
||||
"int2": ("INT", {"default": 1}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("INT",)
|
||||
CATEGORY = "Basic/INT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "multiply"
|
||||
|
||||
def multiply(self, int1: int, int2: int) -> tuple[int]:
|
||||
return (int1 * int2,)
|
||||
|
||||
|
||||
class IntDivide:
|
||||
"""
|
||||
Divides one integer by another.
|
||||
|
||||
This node takes two integers as input and returns the result of integer
|
||||
division. It raises a ValueError if the divisor is 0.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"int1": ("INT", {"default": 1}),
|
||||
"int2": ("INT", {"default": 1}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("INT",)
|
||||
CATEGORY = "Basic/INT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "divide"
|
||||
|
||||
def divide(self, int1: int, int2: int) -> tuple[int]:
|
||||
if int2 == 0:
|
||||
raise ValueError("Cannot divide by zero.")
|
||||
return (int1 // int2,)
|
||||
|
||||
|
||||
class IntModulus:
|
||||
"""
|
||||
Returns the modulus of two integers.
|
||||
|
||||
This node takes two integers as input and returns the remainder when the
|
||||
first integer is divided by the second.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"int1": ("INT", {"default": 0}),
|
||||
"int2": ("INT", {"default": 1}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("INT",)
|
||||
CATEGORY = "Basic/INT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "modulus"
|
||||
|
||||
def modulus(self, int1: int, int2: int) -> tuple[int]:
|
||||
if int2 == 0:
|
||||
raise ValueError("Cannot perform modulus operation by zero.")
|
||||
return (int1 % int2,)
|
||||
|
||||
|
||||
class IntPower:
|
||||
"""
|
||||
Raises one integer to the power of another.
|
||||
|
||||
This node takes two integers as input and returns the result of raising
|
||||
the first integer to the power of the second.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"base": ("INT", {"default": 1}),
|
||||
"exponent": ("INT", {"default": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("INT",)
|
||||
CATEGORY = "Basic/INT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "power"
|
||||
|
||||
def power(self, base: int, exponent: int) -> tuple[int]:
|
||||
return (base**exponent,)
|
||||
|
||||
|
||||
class IntBitLength:
|
||||
"""
|
||||
Returns the number of bits required to represent an integer in binary.
|
||||
|
||||
This node takes an integer as input and returns the number of bits needed
|
||||
to represent it, excluding the sign and leading zeros.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"int_value": ("INT", {"default": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("INT",)
|
||||
CATEGORY = "Additional Methods/INT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "bit_length"
|
||||
|
||||
def bit_length(self, int_value: int) -> tuple[int]:
|
||||
return (int_value.bit_length(),)
|
||||
|
||||
|
||||
class IntToBytes:
|
||||
"""
|
||||
Converts an integer to its byte representation.
|
||||
|
||||
This node takes an integer, byte length, and byte order as inputs and
|
||||
returns the bytes object representation of the integer.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"int_value": ("INT", {"default": 0}),
|
||||
"length": ("INT", {"default": 4, "min": 1}),
|
||||
"byteorder": (["big", "little"], {"default": "big"}),
|
||||
"signed": (["True", "False"], {"default": "False"}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("BYTES",)
|
||||
CATEGORY = "Additional Methods/INT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "to_bytes"
|
||||
|
||||
def to_bytes(self, int_value: int, length: int, byteorder: Literal["big"|"little"], signed: Literal["True"|"False"]) -> tuple[int]:
|
||||
signed_bool = (signed == "True")
|
||||
return (int_value.to_bytes(length, byteorder=byteorder, signed=signed_bool),)
|
||||
|
||||
|
||||
class IntFromBytes:
|
||||
"""
|
||||
Converts a bytes object to an integer.
|
||||
|
||||
This class method takes bytes, byte order, and signed flag as inputs and
|
||||
returns an integer.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"bytes_value": ("BYTES", {}),
|
||||
"byteorder": (["big", "little"], {"default": "big"}),
|
||||
"signed": (["True", "False"], {"default": "False"}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("INT",)
|
||||
CATEGORY = "Additional Methods/INT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "from_bytes"
|
||||
|
||||
def from_bytes(self, bytes_value, byteorder: Literal["big"|"little"], signed: Literal["True"|"False"]) -> tuple[int]:
|
||||
signed_bool = (signed == "True")
|
||||
return (int.from_bytes(bytes_value, byteorder=byteorder, signed=signed_bool),)
|
||||
|
||||
|
||||
class IntBitCount:
|
||||
"""
|
||||
Returns the number of 1 bits in the binary representation of an integer.
|
||||
|
||||
This node takes an integer as input and returns the count of set bits.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"int_value": ("INT", {"default": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("INT",)
|
||||
CATEGORY = "Additional Methods/INT"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "bit_count"
|
||||
|
||||
def bit_count(self, int_value: int) -> tuple[int]:
|
||||
# Introduced in Python 3.10
|
||||
return (int_value.bit_count(),)
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"IntAdd": IntAdd,
|
||||
"IntSubtract": IntSubtract,
|
||||
"IntMultiply": IntMultiply,
|
||||
"IntDivide": IntDivide,
|
||||
"IntModulus": IntModulus,
|
||||
"IntPower": IntPower,
|
||||
"IntBitLength": IntBitLength,
|
||||
"IntToBytes": IntToBytes,
|
||||
"IntFromBytes": IntFromBytes,
|
||||
"IntBitCount": IntBitCount,
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"IntAdd": "add",
|
||||
"IntSubtract": "subtract",
|
||||
"IntMultiply": "multiply",
|
||||
"IntDivide": "divide",
|
||||
"IntModulus": "modulus",
|
||||
"IntPower": "power",
|
||||
"IntBitLength": "bit_length",
|
||||
"IntToBytes": "to_bytes",
|
||||
"IntFromBytes": "from_bytes",
|
||||
"IntBitCount": "bit_count",
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
from typing import Any
|
||||
|
||||
from inspect import cleandoc
|
||||
|
||||
class ListAppend:
|
||||
@@ -10,20 +12,389 @@ class ListAppend:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input_list": ("LIST",),
|
||||
"item": ("ANY",),
|
||||
"optional": {
|
||||
"list":("*",{}),
|
||||
"item":("*",{}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("LIST",)
|
||||
CATEGORY = "Basic/LIST"
|
||||
RETURN_TYPES = ("*",)
|
||||
RETURN_NAMES = ("list",)
|
||||
CATEGORY = "Basic/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 ListExtend:
|
||||
"""
|
||||
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/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 ListInsert:
|
||||
"""
|
||||
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/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 ListRemove:
|
||||
"""
|
||||
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/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 ListPop:
|
||||
"""
|
||||
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/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]
|
||||
try:
|
||||
item = result.pop(index)
|
||||
return result, item
|
||||
except IndexError:
|
||||
return result, None
|
||||
|
||||
|
||||
class ListClear:
|
||||
"""
|
||||
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.
|
||||
"""
|
||||
@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/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 ListCount:
|
||||
"""
|
||||
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/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 ListSort:
|
||||
"""
|
||||
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/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 ListReverse:
|
||||
"""
|
||||
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/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 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(),)
|
||||
|
||||
def append(self, input_list, item):
|
||||
input_list.append(item)
|
||||
return (input_list,)
|
||||
|
||||
class ListLength:
|
||||
"""
|
||||
@@ -35,24 +406,286 @@ class ListLength:
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input_list": ("LIST",),
|
||||
"list": ("*",),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("INT",)
|
||||
CATEGORY = "Basic/LIST"
|
||||
RETURN_NAMES = ("length",)
|
||||
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', [])),)
|
||||
|
||||
|
||||
class ListSlice:
|
||||
"""
|
||||
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/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 ListGetItem:
|
||||
"""
|
||||
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/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 ListSetItem:
|
||||
"""
|
||||
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/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 ListContains:
|
||||
"""
|
||||
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/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 ListCreateEmpty:
|
||||
"""
|
||||
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/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.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"list1": ("*",),
|
||||
"list2": ("*",),
|
||||
},
|
||||
"optional": {
|
||||
"list3": ("*",),
|
||||
"list4": ("*",),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("*",)
|
||||
RETURN_NAMES = ("list",)
|
||||
CATEGORY = "Basic/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,)
|
||||
|
||||
def length(self, input_list):
|
||||
return (len(input_list),)
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"ListAppend": ListAppend,
|
||||
"ListExtend": ListExtend,
|
||||
"ListInsert": ListInsert,
|
||||
"ListRemove": ListRemove,
|
||||
"ListPop": ListPop,
|
||||
"ListClear": ListClear,
|
||||
"ListIndex": ListIndex,
|
||||
"ListCount": ListCount,
|
||||
"ListSort": ListSort,
|
||||
"ListReverse": ListReverse,
|
||||
"ListCopy": ListCopy,
|
||||
"ListLength": ListLength,
|
||||
"ListSlice": ListSlice,
|
||||
"ListGetItem": ListGetItem,
|
||||
"ListSetItem": ListSetItem,
|
||||
"ListContains": ListContains,
|
||||
"ListCreateEmpty": ListCreateEmpty,
|
||||
"ListZip": ListZip,
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"ListAppend": "append",
|
||||
"ListExtend": "extend",
|
||||
"ListInsert": "insert",
|
||||
"ListRemove": "remove",
|
||||
"ListPop": "pop",
|
||||
"ListClear": "clear",
|
||||
"ListIndex": "index",
|
||||
"ListCount": "count",
|
||||
"ListSort": "sort",
|
||||
"ListReverse": "reverse",
|
||||
"ListCopy": "copy",
|
||||
"ListLength": "length",
|
||||
"ListSlice": "slice",
|
||||
"ListGetItem": "get_item",
|
||||
"ListSetItem": "set_item",
|
||||
"ListContains": "contains",
|
||||
"ListCreateEmpty": "create_empty",
|
||||
"ListZip": "zip",
|
||||
}
|
||||
|
||||
@@ -1,118 +0,0 @@
|
||||
from inspect import cleandoc
|
||||
class Example:
|
||||
"""
|
||||
A example node
|
||||
|
||||
Class methods
|
||||
-------------
|
||||
INPUT_TYPES (dict):
|
||||
Tell the main program input parameters of nodes.
|
||||
IS_CHANGED:
|
||||
optional method to control when the node is re executed.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
RETURN_TYPES (`tuple`):
|
||||
The type of each element in the output tulple.
|
||||
RETURN_NAMES (`tuple`):
|
||||
Optional: The name of each output in the output tulple.
|
||||
FUNCTION (`str`):
|
||||
The name of the entry-point method. For example, if `FUNCTION = "execute"` then it will run Example().execute()
|
||||
OUTPUT_NODE ([`bool`]):
|
||||
If this node is an output node that outputs a result/image from the graph. The SaveImage node is an example.
|
||||
The backend iterates on these output nodes and tries to execute all their parents if their parent graph is properly connected.
|
||||
Assumed to be False if not present.
|
||||
CATEGORY (`str`):
|
||||
The category the node should appear in the UI.
|
||||
execute(s) -> tuple || None:
|
||||
The entry point method. The name of this method must be the same as the value of property `FUNCTION`.
|
||||
For example, if `FUNCTION = "execute"` then this method's name must be `execute`, if `FUNCTION = "foo"` then it must be `foo`.
|
||||
"""
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
"""
|
||||
Return a dictionary which contains config for all input fields.
|
||||
Some types (string): "MODEL", "VAE", "CLIP", "CONDITIONING", "LATENT", "IMAGE", "INT", "STRING", "FLOAT".
|
||||
Input types "INT", "STRING" or "FLOAT" are special values for fields on the node.
|
||||
The type can be a list for selection.
|
||||
|
||||
Returns: `dict`:
|
||||
- Key input_fields_group (`string`): Can be either required, hidden or optional. A node class must have property `required`
|
||||
- Value input_fields (`dict`): Contains input fields config:
|
||||
* Key field_name (`string`): Name of a entry-point method's argument
|
||||
* Value field_config (`tuple`):
|
||||
+ First value is a string indicate the type of field or a list for selection.
|
||||
+ Secound value is a config for type "INT", "STRING" or "FLOAT".
|
||||
"""
|
||||
return {
|
||||
"required": {
|
||||
"image": ("Image", { "tooltip": "This is an image"}),
|
||||
"int_field": ("INT", {
|
||||
"default": 0,
|
||||
"min": 0, #Minimum value
|
||||
"max": 4096, #Maximum value
|
||||
"step": 64, #Slider's step
|
||||
"display": "number" # Cosmetic only: display as "number" or "slider"
|
||||
}),
|
||||
"float_field": ("FLOAT", {
|
||||
"default": 1.0,
|
||||
"min": 0.0,
|
||||
"max": 10.0,
|
||||
"step": 0.01,
|
||||
"round": 0.001, #The value represeting the precision to round to, will be set to the step value by default. Can be set to False to disable rounding.
|
||||
"display": "number"}),
|
||||
"print_to_screen": (["enable", "disable"],),
|
||||
"string_field": ("STRING", {
|
||||
"multiline": False, #True if you want the field to look like the one on the ClipTextEncode node
|
||||
"default": "Hello World!"
|
||||
}),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE",)
|
||||
#RETURN_NAMES = ("image_output_name",)
|
||||
DESCRIPTION = cleandoc(__doc__)
|
||||
FUNCTION = "test"
|
||||
|
||||
#OUTPUT_NODE = False
|
||||
#OUTPUT_TOOLTIPS = ("",) # Tooltips for the output node
|
||||
|
||||
CATEGORY = "Example"
|
||||
|
||||
def test(self, image, string_field, int_field, float_field, print_to_screen):
|
||||
if print_to_screen == "enable":
|
||||
print(f"""Your input contains:
|
||||
string_field aka input text: {string_field}
|
||||
int_field: {int_field}
|
||||
float_field: {float_field}
|
||||
""")
|
||||
#do some processing on the image, in this example I just invert it
|
||||
image = 1.0 - image
|
||||
return (image,)
|
||||
|
||||
"""
|
||||
The node will always be re executed if any of the inputs change but
|
||||
this method can be used to force the node to execute again even when the inputs don't change.
|
||||
You can make this node return a number or a string. This value will be compared to the one returned the last time the node was
|
||||
executed, if it is different the node will be executed again.
|
||||
This method is used in the core repo for the LoadImage node where they return the image hash as a string, if the image hash
|
||||
changes between executions the LoadImage node is executed again.
|
||||
"""
|
||||
#@classmethod
|
||||
#def IS_CHANGED(s, image, string_field, int_field, float_field, print_to_screen):
|
||||
# return ""
|
||||
|
||||
|
||||
# A dictionary that contains all nodes you want to export with their names
|
||||
# NOTE: names should be globally unique
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"Example": Example
|
||||
}
|
||||
|
||||
# A dictionary that contains the friendly/humanly readable titles for the nodes
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"Example": "Example Node"
|
||||
}
|
||||
@@ -914,10 +914,11 @@ class StringRsplit:
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("LIST",)
|
||||
RETURN_TYPES = ("STRING",)
|
||||
CATEGORY = "Basic/STRING"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "rsplit"
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
|
||||
def rsplit(self, string, sep=None, maxsplit=-1):
|
||||
if sep == "":
|
||||
@@ -1205,10 +1206,11 @@ class StringRsplit:
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("LIST",)
|
||||
RETURN_TYPES = ("STRING",)
|
||||
CATEGORY = "Basic/STRING"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "rsplit"
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
|
||||
def rsplit(self, string, sep=None, maxsplit=-1):
|
||||
if sep == "":
|
||||
@@ -1216,6 +1218,7 @@ class StringRsplit:
|
||||
return (string.rsplit(sep, maxsplit),)
|
||||
|
||||
|
||||
|
||||
class StringRstrip:
|
||||
"""
|
||||
Removes trailing characters from the string.
|
||||
@@ -1246,6 +1249,34 @@ class StringRstrip:
|
||||
return (string.rstrip(chars),)
|
||||
|
||||
|
||||
class StringJoin:
|
||||
"""
|
||||
Joins strings from a data list with a specified separator.
|
||||
|
||||
This node takes a data list of strings and concatenates them, with the specified
|
||||
separator string between each element. The separator is inserted between the strings,
|
||||
not at the beginning or end of the result.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"sep": ("STRING", {"default": " ", "defaultInput": True}),
|
||||
"strings": ("STRING", {"forceInput": True}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
CATEGORY = "Basic/STRING"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "join"
|
||||
INPUT_IS_LIST = True # The "strings" input accepts a data list
|
||||
|
||||
def join(self, sep, strings):
|
||||
separator = sep[0] # everything comes as a list, so sep is list[str]
|
||||
return (separator.join(strings),)
|
||||
|
||||
|
||||
class StringLjust:
|
||||
"""
|
||||
Left-aligns the string within a field of a given width.
|
||||
@@ -1465,10 +1496,11 @@ class StringRsplit:
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("LIST",)
|
||||
RETURN_TYPES = ("STRING",) # Changed from "LIST" to "STRING"
|
||||
CATEGORY = "Basic/STRING"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "rsplit"
|
||||
OUTPUT_IS_LIST = (True,) # This indicates that the output is a data list
|
||||
|
||||
def rsplit(self, string, sep=None, maxsplit=-1):
|
||||
if sep == "":
|
||||
@@ -1510,8 +1542,10 @@ class StringSplit:
|
||||
"""
|
||||
Splits the string at the specified separator.
|
||||
|
||||
This node returns a list of strings by splitting the input string at the specified separator.
|
||||
If maxsplit is provided, at most maxsplit splits are done.
|
||||
This node splits the input string at the specified separator and returns a
|
||||
data list containing all parts. If maxsplit is provided, at most maxsplit
|
||||
splits are done.
|
||||
|
||||
If the separator is not specified or is None, any whitespace string is a separator.
|
||||
"""
|
||||
@classmethod
|
||||
@@ -1526,15 +1560,19 @@ class StringSplit:
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("LIST",)
|
||||
RETURN_TYPES = ("STRING",)
|
||||
FUNCTION = "split"
|
||||
CATEGORY = "Basic/STRING"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "split"
|
||||
OUTPUT_IS_LIST = (True,) # This indicates that the output is a data list
|
||||
|
||||
def split(self, string, sep=None, maxsplit=-1):
|
||||
if sep == "":
|
||||
sep = None
|
||||
return (string.split(sep, maxsplit),)
|
||||
|
||||
parts = string.split(sep, maxsplit)
|
||||
# Return a data list where each item is a separate string
|
||||
return (parts,)
|
||||
|
||||
|
||||
class StringSplitlines:
|
||||
@@ -1551,17 +1589,20 @@ class StringSplitlines:
|
||||
"string": ("STRING", {"default": "", "defaultInput": True}),
|
||||
},
|
||||
"optional": {
|
||||
"keepends": ("BOOLEAN", {"default": False}),
|
||||
"keepends": (["False", "True"], {"default": "False"}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("LIST",)
|
||||
RETURN_TYPES = ("STRING",)
|
||||
CATEGORY = "Basic/STRING"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "splitlines"
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
|
||||
def splitlines(self, string, keepends=False):
|
||||
return (string.splitlines(keepends),)
|
||||
def splitlines(self, string, keepends="False"):
|
||||
keepends_bool = (keepends == "True")
|
||||
lines = string.splitlines(keepends_bool)
|
||||
return (lines,)
|
||||
|
||||
|
||||
class StringStartswith:
|
||||
@@ -1750,6 +1791,7 @@ NODE_CLASS_MAPPINGS = {
|
||||
"StringIsSpace": StringIsSpace,
|
||||
"StringIsTitle": StringIsTitle,
|
||||
"StringIsUpper": StringIsUpper,
|
||||
"StringJoin": StringJoin,
|
||||
"StringLjust": StringLjust,
|
||||
"StringLower": StringLower,
|
||||
"StringLstrip": StringLstrip,
|
||||
@@ -1795,6 +1837,7 @@ NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"StringIsSpace": "isspace",
|
||||
"StringIsTitle": "istitle",
|
||||
"StringIsUpper": "isupper",
|
||||
"StringJoin": "join",
|
||||
"StringLjust": "ljust",
|
||||
"StringLower": "lower",
|
||||
"StringLstrip": "lstrip",
|
||||
|
||||
Reference in New Issue
Block a user