+1
-1
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "basic_data_handling"
|
||||
version = "0.0.8"
|
||||
version = "0.0.9"
|
||||
description = """NOTE: Still in development! Expect breaking changes!
|
||||
Basic Python functions for manipulating data that every programmer is used to.
|
||||
Currently supported ComfyUI data types: BOOLEAN, FLOAT, INT, STRING and data lists.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from . import (boolean_nodes, casting_nodes, comparison_nodes, control_flow,
|
||||
from . import (boolean_nodes, casting_nodes, comparison_nodes, control_flow_nodes,
|
||||
data_list_nodes, dict_nodes, float_nodes, int_nodes, list_nodes,
|
||||
math_nodes, path_nodes, regex_nodes, set_nodes, string_nodes)
|
||||
|
||||
@@ -6,7 +6,7 @@ NODE_CLASS_MAPPINGS = {}
|
||||
NODE_CLASS_MAPPINGS.update(boolean_nodes.NODE_CLASS_MAPPINGS)
|
||||
NODE_CLASS_MAPPINGS.update(casting_nodes.NODE_CLASS_MAPPINGS)
|
||||
NODE_CLASS_MAPPINGS.update(comparison_nodes.NODE_CLASS_MAPPINGS)
|
||||
NODE_CLASS_MAPPINGS.update(control_flow.NODE_CLASS_MAPPINGS)
|
||||
NODE_CLASS_MAPPINGS.update(control_flow_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)
|
||||
@@ -22,7 +22,7 @@ NODE_DISPLAY_NAME_MAPPINGS = {}
|
||||
NODE_DISPLAY_NAME_MAPPINGS.update(boolean_nodes.NODE_DISPLAY_NAME_MAPPINGS)
|
||||
NODE_DISPLAY_NAME_MAPPINGS.update(casting_nodes.NODE_DISPLAY_NAME_MAPPINGS)
|
||||
NODE_DISPLAY_NAME_MAPPINGS.update(comparison_nodes.NODE_DISPLAY_NAME_MAPPINGS)
|
||||
NODE_DISPLAY_NAME_MAPPINGS.update(control_flow.NODE_DISPLAY_NAME_MAPPINGS)
|
||||
NODE_DISPLAY_NAME_MAPPINGS.update(control_flow_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)
|
||||
|
||||
@@ -51,7 +51,7 @@ class CastToInt:
|
||||
def convert_to_int(self, input: Any) -> tuple[int]:
|
||||
try:
|
||||
return (int(input),)
|
||||
except ValueError:
|
||||
except (ValueError, TypeError):
|
||||
raise ValueError(f"Cannot convert {input} to an INT.")
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ class CastToFloat:
|
||||
def convert_to_float(self, input: Any) -> tuple[float]:
|
||||
try:
|
||||
return (float(input),)
|
||||
except ValueError:
|
||||
except (ValueError, TypeError):
|
||||
raise ValueError(f"Cannot convert {input} to a FLOAT.")
|
||||
|
||||
|
||||
@@ -161,7 +161,7 @@ class CastDataListToList:
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def convert(self, **kwargs: dict[str, list]) -> tuple[list[Any]]:
|
||||
def convert(self, **kwargs: list[Any]) -> tuple[list[Any]]:
|
||||
return (kwargs.get('list', []).copy(),)
|
||||
|
||||
|
||||
@@ -218,7 +218,7 @@ class CastDataListToSet:
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def convert(self, **kwargs: dict[str, list]) -> tuple[list[Any]]:
|
||||
def convert(self, **kwargs: list[Any]) -> tuple[set[Any]]:
|
||||
return (set(kwargs.get('list', [])),)
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
from typing import Any, Dict, List, Union
|
||||
from typing import Any
|
||||
from inspect import cleandoc
|
||||
|
||||
class IfElse:
|
||||
@@ -30,7 +30,7 @@ class DataListAppend:
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def append(self, **kwargs: dict[str, list]) -> tuple[list[Any]]:
|
||||
def append(self, **kwargs: list[Any]) -> tuple[list[Any]]:
|
||||
result = kwargs.get('list', []).copy()
|
||||
item = kwargs.get('item', [])
|
||||
if len(item) > 0:
|
||||
@@ -66,7 +66,7 @@ class DataListExtend:
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def extend(self, **kwargs: dict[str, list]) -> tuple[list[Any]]:
|
||||
def extend(self, **kwargs: list[Any]) -> tuple[list[Any]]:
|
||||
return (kwargs.get('list_a', []) + kwargs.get('list_b', []),)
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ class DataListInsert:
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def insert(self, **kwargs: dict[str, list]) -> tuple[list[Any]]:
|
||||
def insert(self, **kwargs: list[Any]) -> tuple[list[Any]]:
|
||||
result = kwargs.get('list', []).copy()
|
||||
result.insert(kwargs.get('index', [0])[0], kwargs.get('item', [None])[0])
|
||||
return (result,)
|
||||
@@ -133,7 +133,7 @@ class DataListRemove:
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def remove(self, **kwargs: dict[str, list]) -> tuple[list[Any], bool]:
|
||||
def remove(self, **kwargs: list[Any]) -> tuple[list[Any], bool]:
|
||||
result = kwargs.get('list', []).copy()
|
||||
value = kwargs.get('value', [])
|
||||
try:
|
||||
@@ -172,12 +172,12 @@ class DataListPop:
|
||||
OUTPUT_IS_LIST = (True, False)
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool|str:
|
||||
if input_types[0].get("index", "INT") not in ("INT"):
|
||||
def VALIDATE_INPUTS(cls, input_types: list[dict[str, str]]) -> bool|str:
|
||||
if input_types[0].get("index", "INT") != "INT":
|
||||
return "index must be an INT type"
|
||||
return True
|
||||
|
||||
def pop(self, **kwargs: dict[str, list]) -> tuple[list[Any], Any]:
|
||||
def pop(self, **kwargs: list[Any]) -> tuple[list[Any], Any]:
|
||||
result = kwargs.get('list', []).copy()
|
||||
index = kwargs.get('index', [-1])[0]
|
||||
try:
|
||||
@@ -213,7 +213,7 @@ class DataListClear:
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def clear(self, **kwargs: dict[str, list]) -> tuple[[]]:
|
||||
def clear(self, **kwargs: list[Any]) -> tuple[list]:
|
||||
# Return a new empty list rather than modifying the input
|
||||
return ([],)
|
||||
|
||||
@@ -250,7 +250,7 @@ class DataListIndex:
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def list_index(self, **kwargs: dict[str, list]) -> tuple[int]:
|
||||
def list_index(self, **kwargs: list[Any]) -> tuple[int]:
|
||||
input_list = kwargs.get('list', [])
|
||||
value = kwargs.get('value', [None])[0]
|
||||
start = kwargs.get('start', [0])[0]
|
||||
@@ -291,7 +291,7 @@ class DataListCount:
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def count(self, **kwargs: dict[str, list]) -> tuple[int]:
|
||||
def count(self, **kwargs: list[Any]) -> tuple[int]:
|
||||
value = kwargs.get('value', [None])[0]
|
||||
return (kwargs.get('list', []).count(value),)
|
||||
|
||||
@@ -326,7 +326,7 @@ class DataListSort:
|
||||
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, **kwargs: list[Any]) -> tuple[list[Any]]:
|
||||
# Convert string to boolean
|
||||
reverse = kwargs.get('reverse', ["False"])[0] == "True"
|
||||
|
||||
@@ -360,7 +360,7 @@ class DataListReverse:
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def reverse(self, **kwargs: dict[str, list]) -> tuple[list[Any]]:
|
||||
def reverse(self, **kwargs: list[Any]) -> tuple[list[Any]]:
|
||||
result = kwargs.get('list', []).copy()
|
||||
result.reverse()
|
||||
return (result,)
|
||||
@@ -392,7 +392,7 @@ class DataListCopy:
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def copy(self, **kwargs: dict[str, list]) -> tuple[list[Any]]:
|
||||
def copy(self, **kwargs: list[Any]) -> tuple[list[Any]]:
|
||||
return (kwargs.get('list', []).copy(),)
|
||||
|
||||
|
||||
@@ -421,7 +421,7 @@ class DataListLength:
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def length(self, **kwargs: dict[str, list]) -> tuple[int]:
|
||||
def length(self, **kwargs: list[Any]) -> tuple[int]:
|
||||
return (len(kwargs.get('list', [])),)
|
||||
|
||||
|
||||
@@ -457,7 +457,7 @@ class DataListSlice:
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def slice(self, **kwargs: dict[str, list]) -> tuple[list[Any]]:
|
||||
def slice(self, **kwargs: list[Any]) -> tuple[list[Any]]:
|
||||
input_list = kwargs.get('list', [])
|
||||
start = kwargs.get('start', [0])[0]
|
||||
stop = kwargs.get('stop', [-1])[0]
|
||||
@@ -481,7 +481,7 @@ class DataListGetItem:
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input_list": ("*",),
|
||||
"list": ("*",),
|
||||
"index": ("INT", {"default": 0}),
|
||||
}
|
||||
}
|
||||
@@ -497,7 +497,7 @@ class DataListGetItem:
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def get_item(self, **kwargs: dict[str, list]) -> tuple[Any]:
|
||||
def get_item(self, **kwargs: list[Any]) -> tuple[Any]:
|
||||
index = kwargs.get('index', [0])[0]
|
||||
try:
|
||||
return (kwargs.get('list', [])[index],)
|
||||
@@ -534,7 +534,7 @@ class DataListSetItem:
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def set_item(self, **kwargs: dict[str, list]) -> tuple[Any]:
|
||||
def set_item(self, **kwargs: list[Any]) -> tuple[Any]:
|
||||
input_list = kwargs.get('list', [])
|
||||
index = kwargs.get('index', [0])[0]
|
||||
value = kwargs.get('value', [None])[0]
|
||||
@@ -557,7 +557,7 @@ class DataListContains:
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input_list": ("*",),
|
||||
"list": ("*",),
|
||||
"value": ("*",),
|
||||
}
|
||||
}
|
||||
@@ -573,7 +573,7 @@ class DataListContains:
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def contains(self, **kwargs: dict[str, list]) -> tuple[bool]:
|
||||
def contains(self, **kwargs: list[Any]) -> tuple[bool]:
|
||||
value = kwargs.get('value', [])
|
||||
if len(value) == 0:
|
||||
return (False,)
|
||||
@@ -597,7 +597,7 @@ class DataListCreateEmpty:
|
||||
FUNCTION = "create_empty"
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
|
||||
def create_empty(self) -> tuple[[]]:
|
||||
def create_empty(self) -> tuple[list]:
|
||||
return ([],)
|
||||
|
||||
|
||||
@@ -634,7 +634,7 @@ class DataListZip:
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool:
|
||||
return True
|
||||
|
||||
def zip_lists(self, **kwargs: dict[str, list]) -> tuple[list[Any]]:
|
||||
def zip_lists(self, **kwargs: list[Any]) -> tuple[list[Any]]:
|
||||
lists = [kwargs.get('list1', []), kwargs.get('list2', [])]
|
||||
|
||||
if 'list3' in kwargs:
|
||||
@@ -677,12 +677,12 @@ class DataListFilter:
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool|str:
|
||||
if input_types[0]["filter"] not in ("BOOLEAN"):
|
||||
def VALIDATE_INPUTS(cls, input_types: list[dict[str, str]]) -> bool|str:
|
||||
if input_types[0]["filter"] != "BOOLEAN":
|
||||
return "filter must be a BOOLEAN type"
|
||||
return True
|
||||
|
||||
def filter_data(self, **kwargs: dict[str, list]) -> tuple[list[Any]]:
|
||||
def filter_data(self, **kwargs: list[Any]) -> tuple[list[Any]]:
|
||||
values = kwargs.get('value', [])
|
||||
filters = kwargs.get('filter', [])
|
||||
|
||||
@@ -716,12 +716,12 @@ class DataListMin:
|
||||
INPUT_IS_LIST = True
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool|str:
|
||||
def VALIDATE_INPUTS(cls, input_types: list[dict[str, str]]) -> bool|str:
|
||||
if input_types[0]["list"] not in ("FLOAT", "INT"):
|
||||
return "list must contain FLOAT or INT types"
|
||||
return True
|
||||
|
||||
def find_min(self, **kwargs: dict[str, list]) -> tuple[Any]:
|
||||
def find_min(self, **kwargs: list[Any]) -> tuple[Any]:
|
||||
values = kwargs.get('list', [])
|
||||
if not values:
|
||||
return (None,)
|
||||
@@ -758,12 +758,12 @@ class DataListMax:
|
||||
INPUT_IS_LIST = True
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, input_types: dict[str, str]) -> bool|str:
|
||||
def VALIDATE_INPUTS(cls, input_types: list[dict[str, str]]) -> bool|str:
|
||||
if input_types[0]["list"] not in ("FLOAT", "INT"):
|
||||
return "list must contain FLOAT or INT types"
|
||||
return True
|
||||
|
||||
def find_max(self, **kwargs: dict[str, list]) -> tuple[Any]:
|
||||
def find_max(self, **kwargs: list[Any]) -> tuple[Any]:
|
||||
values = kwargs.get('list', [])
|
||||
if not values:
|
||||
return (None,)
|
||||
|
||||
@@ -353,7 +353,7 @@ class DictPopItem:
|
||||
return result, key, value, True
|
||||
else:
|
||||
return result, "", None, False
|
||||
except Exception as e:
|
||||
except:
|
||||
return result, "", None, False
|
||||
|
||||
|
||||
|
||||
@@ -201,7 +201,7 @@ class IntToBytes:
|
||||
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]:
|
||||
def to_bytes(self, int_value: int, length: int, byteorder: Literal["big", "little"], signed: Literal["True", "False"]) -> tuple[bytes]:
|
||||
signed_bool = (signed == "True")
|
||||
return (int_value.to_bytes(length, byteorder=byteorder, signed=signed_bool),)
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
from typing import Any
|
||||
from inspect import cleandoc
|
||||
import re
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ class StringCenter:
|
||||
return (string.center(width, fillchar),)
|
||||
|
||||
|
||||
class StringConcat:
|
||||
class DataStringConcat:
|
||||
"""Combines two text strings together, joining them end-to-end."""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
@@ -696,29 +696,6 @@ class StringLjust:
|
||||
return (string.ljust(width, fillchar),)
|
||||
|
||||
|
||||
class StringLower:
|
||||
"""
|
||||
Converts the string to lowercase.
|
||||
|
||||
This node returns a copy of the string with all uppercase characters converted to lowercase.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"string": ("STRING", {"default": "", "defaultInput": True}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
CATEGORY = "Basic/STRING"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "lower"
|
||||
|
||||
def lower(self, string):
|
||||
return (string.lower(),)
|
||||
|
||||
|
||||
class StringLstrip:
|
||||
"""
|
||||
Removes leading characters from the string.
|
||||
@@ -749,36 +726,6 @@ class StringLstrip:
|
||||
return (string.lstrip(chars),)
|
||||
|
||||
|
||||
class StringReplace:
|
||||
"""
|
||||
Replaces occurrences of a substring with another substring.
|
||||
|
||||
This node returns a copy of the string with all occurrences of substring
|
||||
old replaced by new. If the optional argument count is given, only the
|
||||
first count occurrences are replaced.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"string": ("STRING", {"default": "", "defaultInput": True}),
|
||||
"old": ("STRING", {"default": ""}),
|
||||
"new": ("STRING", {"default": ""}),
|
||||
},
|
||||
"optional": {
|
||||
"count": ("INT", {"default": -1, "min": -1}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
CATEGORY = "Basic/STRING"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "replace"
|
||||
|
||||
def replace(self, string, old, new, count=-1):
|
||||
return (string.replace(old, new, count),)
|
||||
|
||||
|
||||
class StringRemoveprefix:
|
||||
"""
|
||||
Removes prefix from the string if present.
|
||||
@@ -829,71 +776,6 @@ class StringRemovesuffix:
|
||||
return (string.removesuffix(suffix),)
|
||||
|
||||
|
||||
class StringRfind:
|
||||
"""
|
||||
Finds the highest index of the substring in the string.
|
||||
|
||||
This node searches for the last occurrence of the specified substring within the input string.
|
||||
Returns the highest index where the substring is found. If the substring is not found, it returns -1.
|
||||
Optional start and end parameters allow you to limit the search to a specific portion of the string.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"string": ("STRING", {"default": "", "defaultInput": True}),
|
||||
"substring": ("STRING", {"default": ""}),
|
||||
},
|
||||
"optional": {
|
||||
"start": ("INT", {"default": 0, "min": 0}),
|
||||
"end": ("INT", {"default": 0, "min": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("INT",)
|
||||
CATEGORY = "Basic/STRING"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "rfind"
|
||||
|
||||
def rfind(self, string, substring, start=0, end=0):
|
||||
# If end is 0 or negative, search to the end of the string
|
||||
if end <= 0:
|
||||
end = len(string)
|
||||
|
||||
return (string.rfind(substring, start, end),)
|
||||
|
||||
|
||||
class StringRjust:
|
||||
"""
|
||||
Right-aligns the string within a field of a given width.
|
||||
|
||||
This node returns a string right-aligned in a field of the specified width.
|
||||
If fillchar is provided, it is used as the padding character instead of a space.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"string": ("STRING", {"default": "", "defaultInput": True}),
|
||||
"width": ("INT", {"default": 10, "min": 0}),
|
||||
},
|
||||
"optional": {
|
||||
"fillchar": ("STRING", {"default": " "}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
CATEGORY = "Basic/STRING"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "rjust"
|
||||
|
||||
def rjust(self, string, width, fillchar=" "):
|
||||
# Ensure fillchar is only one character
|
||||
if len(fillchar) > 0:
|
||||
fillchar = fillchar[0]
|
||||
return (string.rjust(width, fillchar),)
|
||||
|
||||
|
||||
class StringRsplit:
|
||||
"""
|
||||
Splits the string at the specified separator from the right.
|
||||
@@ -926,68 +808,6 @@ class StringRsplit:
|
||||
return (string.rsplit(sep, maxsplit),)
|
||||
|
||||
|
||||
class StringRstrip:
|
||||
"""
|
||||
Removes trailing characters from the string.
|
||||
|
||||
This node returns a copy of the string with trailing characters removed.
|
||||
If chars is provided, it specifies the set of characters to be removed.
|
||||
If chars is not provided, whitespace characters are removed.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"string": ("STRING", {"default": "", "defaultInput": True}),
|
||||
},
|
||||
"optional": {
|
||||
"chars": ("STRING", {"default": ""}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
CATEGORY = "Basic/STRING"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "rstrip"
|
||||
|
||||
def rstrip(self, string, chars=None):
|
||||
if chars == "":
|
||||
chars = None
|
||||
return (string.rstrip(chars),)
|
||||
|
||||
|
||||
|
||||
class StringLjust:
|
||||
"""
|
||||
Left-aligns the string within a field of a given width.
|
||||
|
||||
This node returns a string left-aligned in a field of the specified width.
|
||||
If fillchar is provided, it is used as the padding character instead of a space.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"string": ("STRING", {"default": "", "defaultInput": True}),
|
||||
"width": ("INT", {"default": 10, "min": 0}),
|
||||
},
|
||||
"optional": {
|
||||
"fillchar": ("STRING", {"default": " "}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
CATEGORY = "Basic/STRING"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "ljust"
|
||||
|
||||
def ljust(self, string, width, fillchar=" "):
|
||||
# Ensure fillchar is only one character
|
||||
if len(fillchar) > 0:
|
||||
fillchar = fillchar[0]
|
||||
return (string.ljust(width, fillchar),)
|
||||
|
||||
|
||||
class StringLower:
|
||||
"""
|
||||
Converts the string to lowercase.
|
||||
@@ -1011,36 +831,6 @@ class StringLower:
|
||||
return (string.lower(),)
|
||||
|
||||
|
||||
class StringLstrip:
|
||||
"""
|
||||
Removes leading characters from the string.
|
||||
|
||||
This node returns a copy of the string with leading characters removed.
|
||||
If chars is provided, it specifies the set of characters to be removed.
|
||||
If chars is not provided, whitespace characters are removed.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"string": ("STRING", {"default": "", "defaultInput": True}),
|
||||
},
|
||||
"optional": {
|
||||
"chars": ("STRING", {"default": ""}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
CATEGORY = "Basic/STRING"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "lstrip"
|
||||
|
||||
def lstrip(self, string, chars=None):
|
||||
if chars == "":
|
||||
chars = None
|
||||
return (string.lstrip(chars),)
|
||||
|
||||
|
||||
class StringReplace:
|
||||
"""
|
||||
Replaces occurrences of a substring with another substring.
|
||||
@@ -1071,90 +861,6 @@ class StringReplace:
|
||||
return (string.replace(old, new, count),)
|
||||
|
||||
|
||||
class StringRemoveprefix:
|
||||
"""
|
||||
Removes prefix from the string if present.
|
||||
|
||||
This node returns a copy of the string with the specified prefix removed
|
||||
if the string starts with that prefix, otherwise returns the original string.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"string": ("STRING", {"default": "", "defaultInput": True}),
|
||||
"prefix": ("STRING", {"default": ""}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
CATEGORY = "Basic/STRING"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "removeprefix"
|
||||
|
||||
def removeprefix(self, string, prefix):
|
||||
return (string.removeprefix(prefix),)
|
||||
|
||||
|
||||
class StringRemovesuffix:
|
||||
"""
|
||||
Removes suffix from the string if present.
|
||||
|
||||
This node returns a copy of the string with the specified suffix removed
|
||||
if the string ends with that suffix, otherwise returns the original string.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"string": ("STRING", {"default": "", "defaultInput": True}),
|
||||
"suffix": ("STRING", {"default": ""}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
CATEGORY = "Basic/STRING"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "removesuffix"
|
||||
|
||||
def removesuffix(self, string, suffix):
|
||||
return (string.removesuffix(suffix),)
|
||||
|
||||
|
||||
class StringRfind:
|
||||
"""
|
||||
Finds the highest index of the substring in the string.
|
||||
|
||||
This node searches for the last occurrence of the specified substring within the input string.
|
||||
Returns the highest index where the substring is found. If the substring is not found, it returns -1.
|
||||
Optional start and end parameters allow you to limit the search to a specific portion of the string.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"string": ("STRING", {"default": "", "defaultInput": True}),
|
||||
"substring": ("STRING", {"default": ""}),
|
||||
},
|
||||
"optional": {
|
||||
"start": ("INT", {"default": 0, "min": 0}),
|
||||
"end": ("INT", {"default": 0, "min": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("INT",)
|
||||
CATEGORY = "Basic/STRING"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "rfind"
|
||||
|
||||
def rfind(self, string, substring, start=0, end=0):
|
||||
# If end is 0 or negative, search to the end of the string
|
||||
if end <= 0:
|
||||
end = len(string)
|
||||
|
||||
return (string.rfind(substring, start, end),)
|
||||
|
||||
|
||||
class StringRjust:
|
||||
"""
|
||||
Right-aligns the string within a field of a given width.
|
||||
@@ -1186,69 +892,6 @@ class StringRjust:
|
||||
return (string.rjust(width, fillchar),)
|
||||
|
||||
|
||||
class StringRsplit:
|
||||
"""
|
||||
Splits the string at the specified separator from the right.
|
||||
|
||||
This node returns a list of strings by splitting the input string at the specified separator,
|
||||
starting from the right. 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
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"string": ("STRING", {"default": "", "defaultInput": True}),
|
||||
},
|
||||
"optional": {
|
||||
"sep": ("STRING", {"default": ""}),
|
||||
"maxsplit": ("INT", {"default": -1, "min": -1}),
|
||||
}
|
||||
}
|
||||
|
||||
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 == "":
|
||||
sep = None
|
||||
return (string.rsplit(sep, maxsplit),)
|
||||
|
||||
|
||||
|
||||
class StringRstrip:
|
||||
"""
|
||||
Removes trailing characters from the string.
|
||||
|
||||
This node returns a copy of the string with trailing characters removed.
|
||||
If chars is provided, it specifies the set of characters to be removed.
|
||||
If chars is not provided, whitespace characters are removed.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"string": ("STRING", {"default": "", "defaultInput": True}),
|
||||
},
|
||||
"optional": {
|
||||
"chars": ("STRING", {"default": ""}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
CATEGORY = "Basic/STRING"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "rstrip"
|
||||
|
||||
def rstrip(self, string, chars=None):
|
||||
if chars == "":
|
||||
chars = None
|
||||
return (string.rstrip(chars),)
|
||||
|
||||
|
||||
class StringJoin:
|
||||
"""
|
||||
Joins strings from a data list with a specified separator.
|
||||
@@ -1277,140 +920,6 @@ class StringJoin:
|
||||
return (separator.join(strings),)
|
||||
|
||||
|
||||
class StringLjust:
|
||||
"""
|
||||
Left-aligns the string within a field of a given width.
|
||||
|
||||
This node returns a string left-aligned in a field of the specified width.
|
||||
If fillchar is provided, it is used as the padding character instead of a space.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"string": ("STRING", {"default": "", "defaultInput": True}),
|
||||
"width": ("INT", {"default": 10, "min": 0}),
|
||||
},
|
||||
"optional": {
|
||||
"fillchar": ("STRING", {"default": " "}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
CATEGORY = "Basic/STRING"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "ljust"
|
||||
|
||||
def ljust(self, string, width, fillchar=" "):
|
||||
# Ensure fillchar is only one character
|
||||
if len(fillchar) > 0:
|
||||
fillchar = fillchar[0]
|
||||
return (string.ljust(width, fillchar),)
|
||||
|
||||
|
||||
class StringLower:
|
||||
"""
|
||||
Converts the string to lowercase.
|
||||
|
||||
This node returns a copy of the string with all uppercase characters converted to lowercase.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"string": ("STRING", {"default": "", "defaultInput": True}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
CATEGORY = "Basic/STRING"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "lower"
|
||||
|
||||
def lower(self, string):
|
||||
return (string.lower(),)
|
||||
|
||||
|
||||
class StringLstrip:
|
||||
"""
|
||||
Removes leading characters from the string.
|
||||
|
||||
This node returns a copy of the string with leading characters removed.
|
||||
If chars is provided, it specifies the set of characters to be removed.
|
||||
If chars is not provided, whitespace characters are removed.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"string": ("STRING", {"default": "", "defaultInput": True}),
|
||||
},
|
||||
"optional": {
|
||||
"chars": ("STRING", {"default": ""}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
CATEGORY = "Basic/STRING"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "lstrip"
|
||||
|
||||
def lstrip(self, string, chars=None):
|
||||
if chars == "":
|
||||
chars = None
|
||||
return (string.lstrip(chars),)
|
||||
|
||||
|
||||
class StringRemoveprefix:
|
||||
"""
|
||||
Removes prefix from the string if present.
|
||||
|
||||
This node returns a copy of the string with the specified prefix removed
|
||||
if the string starts with that prefix, otherwise returns the original string.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"string": ("STRING", {"default": "", "defaultInput": True}),
|
||||
"prefix": ("STRING", {"default": ""}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
CATEGORY = "Basic/STRING"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "removeprefix"
|
||||
|
||||
def removeprefix(self, string, prefix):
|
||||
return (string.removeprefix(prefix),)
|
||||
|
||||
|
||||
class StringRemovesuffix:
|
||||
"""
|
||||
Removes suffix from the string if present.
|
||||
|
||||
This node returns a copy of the string with the specified suffix removed
|
||||
if the string ends with that suffix, otherwise returns the original string.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"string": ("STRING", {"default": "", "defaultInput": True}),
|
||||
"suffix": ("STRING", {"default": ""}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
CATEGORY = "Basic/STRING"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "removesuffix"
|
||||
|
||||
def removesuffix(self, string, suffix):
|
||||
return (string.removesuffix(suffix),)
|
||||
|
||||
|
||||
class StringRfind:
|
||||
"""
|
||||
Finds the highest index of the substring in the string.
|
||||
@@ -1445,69 +954,6 @@ class StringRfind:
|
||||
return (string.rfind(substring, start, end),)
|
||||
|
||||
|
||||
class StringRjust:
|
||||
"""
|
||||
Right-aligns the string within a field of a given width.
|
||||
|
||||
This node returns a string right-aligned in a field of the specified width.
|
||||
If fillchar is provided, it is used as the padding character instead of a space.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"string": ("STRING", {"default": "", "defaultInput": True}),
|
||||
"width": ("INT", {"default": 10, "min": 0}),
|
||||
},
|
||||
"optional": {
|
||||
"fillchar": ("STRING", {"default": " "}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
CATEGORY = "Basic/STRING"
|
||||
DESCRIPTION = cleandoc(__doc__ or "")
|
||||
FUNCTION = "rjust"
|
||||
|
||||
def rjust(self, string, width, fillchar=" "):
|
||||
# Ensure fillchar is only one character
|
||||
if len(fillchar) > 0:
|
||||
fillchar = fillchar[0]
|
||||
return (string.rjust(width, fillchar),)
|
||||
|
||||
|
||||
class StringRsplit:
|
||||
"""
|
||||
Splits the string at the specified separator from the right.
|
||||
|
||||
This node returns a list of strings by splitting the input string at the specified separator,
|
||||
starting from the right. 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
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"string": ("STRING", {"default": "", "defaultInput": True}),
|
||||
},
|
||||
"optional": {
|
||||
"sep": ("STRING", {"default": ""}),
|
||||
"maxsplit": ("INT", {"default": -1, "min": -1}),
|
||||
}
|
||||
}
|
||||
|
||||
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 == "":
|
||||
sep = None
|
||||
return (string.rsplit(sep, maxsplit),)
|
||||
|
||||
|
||||
class StringRstrip:
|
||||
"""
|
||||
Removes trailing characters from the string.
|
||||
@@ -1771,7 +1217,7 @@ NODE_CLASS_MAPPINGS = {
|
||||
"StringCapitalize": StringCapitalize,
|
||||
"StringCasefold": StringCasefold,
|
||||
"StringCenter": StringCenter,
|
||||
"StringConcat": StringConcat,
|
||||
"DataStringConcat": DataStringConcat,
|
||||
"StringCount": StringCount,
|
||||
"StringDecode": StringDecode,
|
||||
"StringEncode": StringEncode,
|
||||
@@ -1816,7 +1262,7 @@ NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"StringCapitalize": "capitalize",
|
||||
"StringCasefold": "casefold",
|
||||
"StringCenter": "center",
|
||||
"StringConcat": "concat",
|
||||
"DataStringConcat": "concat",
|
||||
"StringCount": "count",
|
||||
"StringDecode": "decode",
|
||||
"StringEncode": "encode",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import pytest
|
||||
#import pytest
|
||||
|
||||
from src.basic_data_handling.boolean_nodes import (
|
||||
BooleanAnd,
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
import pytest
|
||||
from src.basic_data_handling.casting_nodes import (CastToString, CastToInt, CastToFloat, CastToBoolean,
|
||||
CastToList, CastDataListToList, CastToSet, CastDataListToSet,
|
||||
CastToDict)
|
||||
|
||||
|
||||
def test_cast_to_string():
|
||||
node = CastToString()
|
||||
assert node.convert_to_string(123) == ("123",)
|
||||
assert node.convert_to_string(None) == ("None",)
|
||||
assert node.convert_to_string(True) == ("True",)
|
||||
assert node.convert_to_string("hello") == ("hello",)
|
||||
|
||||
|
||||
def test_cast_to_int():
|
||||
node = CastToInt()
|
||||
assert node.convert_to_int("123") == (123,)
|
||||
assert node.convert_to_int(456) == (456,)
|
||||
with pytest.raises(ValueError):
|
||||
node.convert_to_int("abc")
|
||||
with pytest.raises(ValueError):
|
||||
node.convert_to_int(None)
|
||||
|
||||
|
||||
def test_cast_to_float():
|
||||
node = CastToFloat()
|
||||
assert node.convert_to_float("123.45") == (123.45,)
|
||||
assert node.convert_to_float(67.89) == (67.89,)
|
||||
assert node.convert_to_float(123) == (123.0,)
|
||||
with pytest.raises(ValueError):
|
||||
node.convert_to_float("abc")
|
||||
with pytest.raises(ValueError):
|
||||
node.convert_to_float(None)
|
||||
|
||||
|
||||
def test_cast_to_boolean():
|
||||
node = CastToBoolean()
|
||||
assert node.convert_to_boolean(0) == (False,)
|
||||
assert node.convert_to_boolean(1) == (True,)
|
||||
assert node.convert_to_boolean("") == (False,)
|
||||
assert node.convert_to_boolean("non_empty_string") == (True,)
|
||||
|
||||
|
||||
def test_cast_to_list():
|
||||
node = CastToList()
|
||||
assert node.convert_to_list(123) == ([123],)
|
||||
assert node.convert_to_list([1, 2, 3]) == ([1, 2, 3],)
|
||||
assert node.convert_to_list("hello") == (["hello"],)
|
||||
assert node.convert_to_list(None) == ([None],)
|
||||
|
||||
|
||||
def test_cast_data_list_to_list():
|
||||
node = CastDataListToList()
|
||||
assert node.convert(list=[1, 2, 3]) == ([1, 2, 3],)
|
||||
assert node.convert(list=[]) == ([],)
|
||||
assert node.convert(list=["a", "b", "c"]) == (["a", "b", "c"],)
|
||||
|
||||
|
||||
def test_cast_to_set():
|
||||
node = CastToSet()
|
||||
assert node.convert_to_set(123) == ({123},)
|
||||
assert node.convert_to_set([1, 2, 2]) == ({1, 2},)
|
||||
assert node.convert_to_set("abc") == ({"abc"},)
|
||||
assert node.convert_to_set(None) == ({None},)
|
||||
|
||||
|
||||
def test_cast_data_list_to_set():
|
||||
node = CastDataListToSet()
|
||||
assert node.convert(list=[1, 2, 3, 3]) == ({1, 2, 3},)
|
||||
assert node.convert(list=["a", "b", "b"]) == ({"a", "b"},)
|
||||
assert node.convert(list=[]) == (set(),)
|
||||
|
||||
|
||||
def test_cast_to_dict():
|
||||
node = CastToDict()
|
||||
assert node.convert_to_dict({"key": "value"}) == ({"key": "value"},)
|
||||
assert node.convert_to_dict([("key1", "value1"), ("key2", "value2")]) == ({"key1": "value1", "key2": "value2"},)
|
||||
with pytest.raises(ValueError):
|
||||
node.convert_to_dict(123)
|
||||
with pytest.raises(ValueError):
|
||||
node.convert_to_dict("string")
|
||||
@@ -0,0 +1,115 @@
|
||||
#import pytest
|
||||
from src.basic_data_handling.comparison_nodes import (
|
||||
Equal,
|
||||
NotEqual,
|
||||
GreaterThan,
|
||||
LessThan,
|
||||
GreaterThanOrEqual,
|
||||
LessThanOrEqual,
|
||||
StringComparison,
|
||||
NumberInRange,
|
||||
IsNull,
|
||||
CompareLength,
|
||||
)
|
||||
|
||||
|
||||
def test_equal():
|
||||
node = Equal()
|
||||
assert node.compare(10, 10) == (True,)
|
||||
assert node.compare(10, 20) == (False,)
|
||||
assert node.compare("hello", "hello") == (True,)
|
||||
assert node.compare([1, 2], [1, 2]) == (True,)
|
||||
assert node.compare(None, None) == (True,)
|
||||
|
||||
|
||||
def test_not_equal():
|
||||
node = NotEqual()
|
||||
assert node.compare(10, 10) == (False,)
|
||||
assert node.compare(10, 20) == (True,)
|
||||
assert node.compare("hello", "world") == (True,)
|
||||
assert node.compare([1, 2], [1, 3]) == (True,)
|
||||
assert node.compare(None, []) == (True,)
|
||||
|
||||
|
||||
def test_greater_than():
|
||||
node = GreaterThan()
|
||||
assert node.compare(10, 5) == (True,)
|
||||
assert node.compare(5, 10) == (False,)
|
||||
assert node.compare(10, 10) == (False,)
|
||||
assert node.compare(5.6, 2.3) == (True,)
|
||||
|
||||
|
||||
def test_less_than():
|
||||
node = LessThan()
|
||||
assert node.compare(5, 10) == (True,)
|
||||
assert node.compare(10, 5) == (False,)
|
||||
assert node.compare(10, 10) == (False,)
|
||||
assert node.compare(2.3, 5.6) == (True,)
|
||||
|
||||
|
||||
def test_greater_than_or_equal():
|
||||
node = GreaterThanOrEqual()
|
||||
assert node.compare(10, 10) == (True,)
|
||||
assert node.compare(15, 10) == (True,)
|
||||
assert node.compare(5, 10) == (False,)
|
||||
assert node.compare(5.5, 5.5) == (True,)
|
||||
|
||||
|
||||
def test_less_than_or_equal():
|
||||
node = LessThanOrEqual()
|
||||
assert node.compare(10, 10) == (True,)
|
||||
assert node.compare(5, 15) == (True,)
|
||||
assert node.compare(15, 5) == (False,)
|
||||
assert node.compare(3.1, 3.1) == (True,)
|
||||
|
||||
|
||||
def test_string_comparison():
|
||||
node = StringComparison()
|
||||
|
||||
# Case-sensitive tests
|
||||
assert node.compare("hello", "hello", "==", "True") == (True,)
|
||||
assert node.compare("apple", "banana", "<", "True") == (True,)
|
||||
assert node.compare("apple", "banana", ">", "True") == (False,)
|
||||
assert node.compare("apple", "apple", "!=", "True") == (False,)
|
||||
|
||||
# Case-insensitive tests
|
||||
assert node.compare("Hello", "hello", "==", "False") == (True,)
|
||||
assert node.compare("Apple", "BANANA", "<", "False") == (True,)
|
||||
assert node.compare("Grape", "GRAPE", ">=", "False") == (True,)
|
||||
|
||||
|
||||
def test_number_in_range():
|
||||
node = NumberInRange()
|
||||
|
||||
# Inclusive range tests
|
||||
assert node.check_range(50, 0, 100) == (True,)
|
||||
assert node.check_range(0, 0, 100) == (True,)
|
||||
|
||||
# Exclusive range tests
|
||||
assert node.check_range(0, 0, 100, include_min="False") == (False,)
|
||||
assert node.check_range(100, 0, 100, include_max="False") == (False,)
|
||||
|
||||
# Out of range tests
|
||||
assert node.check_range(-1, 0, 100) == (False,)
|
||||
assert node.check_range(101, 0, 100) == (False,)
|
||||
|
||||
|
||||
def test_is_null():
|
||||
node = IsNull()
|
||||
assert node.check_null(None) == (True,)
|
||||
assert node.check_null(0) == (False,)
|
||||
assert node.check_null("") == (False,)
|
||||
assert node.check_null([]) == (False,)
|
||||
|
||||
|
||||
def test_compare_length():
|
||||
node = CompareLength()
|
||||
|
||||
# Valid comparisons
|
||||
assert node.compare_length([1, 2, 3], "==", 3) == (True, 3)
|
||||
assert node.compare_length("hello", "!=", 4) == (True, 5)
|
||||
assert node.compare_length((1, 2), ">", 1) == (True, 2)
|
||||
|
||||
# Invalid comparisons
|
||||
assert node.compare_length({"key": "value"}, "<", 1) == (False, 1)
|
||||
assert node.compare_length(123, "==", 0) == (False, -1) # Non-container input edge case
|
||||
@@ -0,0 +1,39 @@
|
||||
#import pytest
|
||||
from src.basic_data_handling.control_flow_nodes import IfElse, SwitchCase
|
||||
|
||||
|
||||
def test_if_else():
|
||||
node = IfElse()
|
||||
|
||||
# Test where condition is True
|
||||
assert node.execute(True, "Value if True", "Value if False") == ("Value if True",)
|
||||
|
||||
# Test where condition is False
|
||||
assert node.execute(False, "Value if True", "Value if False") == ("Value if False",)
|
||||
|
||||
# Test edge cases
|
||||
assert node.execute(True, 1, 2) == (1,) # Integers
|
||||
assert node.execute(False, [1, 2, 3], None) == (None,) # Complex types
|
||||
assert node.execute(True, None, "fallback") == (None,) # Fallback to True branch
|
||||
|
||||
|
||||
def test_switch_case():
|
||||
node = SwitchCase()
|
||||
|
||||
# Selector within range, valid cases
|
||||
assert node.execute(0, "Case 0", "Case 1", "Case 2", "Case 3") == ("Case 0",)
|
||||
assert node.execute(1, "Case 0", "Case 1", "Case 2", "Case 3") == ("Case 1",)
|
||||
assert node.execute(3, "Case 0", "Case 1", "Case 2", "Case 3") == ("Case 3",)
|
||||
|
||||
# Selector out of range, fallback to default case
|
||||
assert node.execute(4, "Case 0", "Case 1", "Case 2", "Case 3", default="Default") == ("Default",)
|
||||
assert node.execute(99, "Case 0", "Case 1", "Case 2", "Case 3", default="Default") == ("Default",)
|
||||
|
||||
# Selector out of range, no default provided
|
||||
assert node.execute(4, "Case 0", "Case 1", "Case 2", "Case 3") == (None,)
|
||||
|
||||
# Edge cases
|
||||
assert node.execute(0, None, "Case 1", "Case 2") == (None,) # Case with None
|
||||
assert node.execute(2, "Case 0", "Case 1", "Case 2") == ("Case 2",)
|
||||
assert node.execute(0, 123, False, "Case 2") == (123,) # Different data types
|
||||
assert node.execute(10, "Case 0", "Case 1", "Case 2", default="Fallback") == ("Fallback",)
|
||||
@@ -0,0 +1,164 @@
|
||||
import pytest
|
||||
from src.basic_data_handling.data_list_nodes import (
|
||||
DataListAppend,
|
||||
DataListExtend,
|
||||
DataListInsert,
|
||||
DataListRemove,
|
||||
DataListPop,
|
||||
DataListClear,
|
||||
DataListIndex,
|
||||
DataListCount,
|
||||
DataListSort,
|
||||
DataListReverse,
|
||||
DataListCopy,
|
||||
DataListLength,
|
||||
DataListSlice,
|
||||
DataListGetItem,
|
||||
DataListSetItem,
|
||||
DataListContains,
|
||||
DataListCreateEmpty,
|
||||
DataListZip,
|
||||
DataListFilter,
|
||||
DataListMin,
|
||||
DataListMax,
|
||||
)
|
||||
|
||||
|
||||
def test_append():
|
||||
node = DataListAppend()
|
||||
assert node.append(list=[1, 2, 3], item=[4]) == ([1, 2, 3, 4],)
|
||||
assert node.append(list=[], item=["test"]) == (["test"],)
|
||||
assert node.append(list=[1, 2, 3], item=[]) == ([1, 2, 3],)
|
||||
|
||||
|
||||
def test_extend():
|
||||
node = DataListExtend()
|
||||
assert node.extend(list_a=[1, 2], list_b=[3, 4]) == ([1, 2, 3, 4],)
|
||||
assert node.extend(list_a=[], list_b=["a", "b"]) == (["a", "b"],)
|
||||
assert node.extend(list_a=[1], list_b=[]) == ([1],)
|
||||
|
||||
|
||||
def test_insert():
|
||||
node = DataListInsert()
|
||||
assert node.insert(list=[1, 2, 4], index=[2], item=[3]) == ([1, 2, 3, 4],)
|
||||
assert node.insert(list=[], index=[0], item=["a"]) == (["a"],)
|
||||
assert node.insert(list=[1, 2], index=[5], item=[3]) == ([1, 2, 3],) # Out-of-range insert
|
||||
|
||||
|
||||
def test_remove():
|
||||
node = DataListRemove()
|
||||
assert node.remove(list=[1, 2, 3], value=[2]) == ([1, 3], True)
|
||||
assert node.remove(list=["a", "b", "a"], value=["a"]) == (["b", "a"], True)
|
||||
assert node.remove(list=[1, 2, 3], value=[5]) == ([1, 2, 3], False) # Value not found
|
||||
|
||||
|
||||
def test_pop():
|
||||
node = DataListPop()
|
||||
assert node.pop(list=[1, 2, 3], index=[1]) == ([1, 3], 2)
|
||||
assert node.pop(list=["a", "b", "c"], index=[-1]) == (["a", "b"], "c") # Negative index
|
||||
assert node.pop(list=[], index=[0]) == ([], None) # Pop from empty list
|
||||
|
||||
|
||||
def test_clear():
|
||||
node = DataListClear()
|
||||
assert node.clear(list=[1, 2, 3]) == ([],)
|
||||
assert node.clear(list=[]) == ([],)
|
||||
|
||||
|
||||
def test_index():
|
||||
node = DataListIndex()
|
||||
assert node.list_index(list=["a", "b", "c"], value=["b"]) == (1,)
|
||||
assert node.list_index(list=[1, 2, 3], value=[5]) == (-1,) # Value not found
|
||||
assert node.list_index(list=[1, 2, 1, 2], value=[1], start=[1]) == (2,)
|
||||
|
||||
|
||||
def test_count():
|
||||
node = DataListCount()
|
||||
assert node.count(list=[1, 2, 1, 2], value=[1]) == (2,)
|
||||
assert node.count(list=["a", "b", "a"], value=["a"]) == (2,)
|
||||
assert node.count(list=[], value=["x"]) == (0,)
|
||||
|
||||
|
||||
def test_sort():
|
||||
node = DataListSort()
|
||||
assert node.sort(list=[3, 2, 1]) == ([1, 2, 3],)
|
||||
assert node.sort(list=["c", "a", "b"]) == (["a", "b", "c"],)
|
||||
assert node.sort(list=[3, 1, 2], reverse=["True"]) == ([3, 2, 1],) # Reverse sort
|
||||
|
||||
|
||||
def test_reverse():
|
||||
node = DataListReverse()
|
||||
assert node.reverse(list=[1, 2, 3]) == ([3, 2, 1],)
|
||||
assert node.reverse(list=[]) == ([],)
|
||||
|
||||
|
||||
def test_copy():
|
||||
node = DataListCopy()
|
||||
assert node.copy(list=[1, 2, 3]) == ([1, 2, 3],)
|
||||
assert node.copy(list=[]) == ([],)
|
||||
|
||||
|
||||
def test_length():
|
||||
node = DataListLength()
|
||||
assert node.length(list=[1, 2, 3]) == (3,)
|
||||
assert node.length(list=[]) == (0,)
|
||||
|
||||
|
||||
def test_slice():
|
||||
node = DataListSlice()
|
||||
assert node.slice(list=[1, 2, 3, 4, 5], start=[1], stop=[4]) == ([2, 3, 4],)
|
||||
assert node.slice(list=[1, 2, 3], start=[0], stop=[2], step=[2]) == ([1],)
|
||||
assert node.slice(list=["a", "b", "c"], start=[-2], stop=[3]) == (["b", "c"],)
|
||||
|
||||
|
||||
def test_get_item():
|
||||
node = DataListGetItem()
|
||||
assert node.get_item(list=[1, 2, 3], index=[1]) == (2,)
|
||||
assert node.get_item(list=["a", "b", "c"], index=[-1]) == ("c",) # Negative index
|
||||
assert node.get_item(list=[], index=[0]) == (None,) # Out of range
|
||||
|
||||
|
||||
def test_set_item():
|
||||
node = DataListSetItem()
|
||||
assert node.set_item(list=[1, 2, 3], index=[1], value=[9]) == ([1, 9, 3],)
|
||||
assert node.set_item(list=["a", "b", "c"], index=[-1], value=["z"]) == (["a", "b", "z"],)
|
||||
with pytest.raises(IndexError):
|
||||
node.set_item(list=[], index=[0], value=["test"]) # Out of range
|
||||
|
||||
|
||||
def test_contains():
|
||||
node = DataListContains()
|
||||
assert node.contains(list=[1, 2, 3], value=[2]) == (True,)
|
||||
assert node.contains(list=["a", "b"], value=["c"]) == (False,)
|
||||
assert node.contains(list=[], value=["x"]) == (False,)
|
||||
|
||||
|
||||
def test_create_empty():
|
||||
node = DataListCreateEmpty()
|
||||
assert node.create_empty() == ([],)
|
||||
|
||||
|
||||
def test_zip():
|
||||
node = DataListZip()
|
||||
assert node.zip_lists(list1=[1, 2], list2=["a", "b"]) == ([[1, "a"], [2, "b"]],)
|
||||
assert node.zip_lists(list1=[1], list2=["a", "b"]) == ([[1, "a"]],) # Shortest list length
|
||||
|
||||
|
||||
def test_filter():
|
||||
node = DataListFilter()
|
||||
assert node.filter_data(value=[1, 2, 3], filter=[False, True, False]) == ([1, 3],)
|
||||
assert node.filter_data(value=[1, 2], filter=[True, True]) == ([],)
|
||||
|
||||
|
||||
def test_min():
|
||||
node = DataListMin()
|
||||
assert node.find_min(list=[3, 1, 2]) == (1,)
|
||||
assert node.find_min(list=[-1, -5, 0]) == (-5,)
|
||||
assert node.find_min(list=[]) == (None,)
|
||||
|
||||
|
||||
def test_max():
|
||||
node = DataListMax()
|
||||
assert node.find_max(list=[3, 1, 2]) == (3,)
|
||||
assert node.find_max(list=[-1, -5, 0]) == (0,)
|
||||
assert node.find_max(list=[]) == (None,)
|
||||
@@ -1,10 +1,10 @@
|
||||
import pytest
|
||||
#import pytest
|
||||
|
||||
from src.basic_data_handling.string_nodes import (
|
||||
StringCapitalize,
|
||||
StringCasefold,
|
||||
StringCenter,
|
||||
StringConcat,
|
||||
DataStringConcat,
|
||||
StringCount,
|
||||
StringDecode,
|
||||
StringEncode,
|
||||
@@ -72,7 +72,7 @@ def test_center():
|
||||
assert node.center("test", 10, "ab") == ("aaatestaaa",)
|
||||
|
||||
def test_concat():
|
||||
node = StringConcat()
|
||||
node = DataStringConcat()
|
||||
assert node.concat("hello ", "world") == ("hello world",)
|
||||
assert node.concat("", "") == ("",) # Empty strings
|
||||
assert node.concat("123", "456") == ("123456",) # Numbers as strings
|
||||
|
||||
Reference in New Issue
Block a user