Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/build-pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ on:
- main
jobs:
build:
runs-on: ${{ matrix.os }}
runs-on: ${{ matrix.os }}
env:
PYTHONIOENCODING: "utf8"
strategy:
Expand All @@ -21,14 +21,16 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install .[dev]
- name: Run Linting
run: |
ruff check .
- name: Set PYTHONPATH
run: echo "PYTHONPATH=$(pwd)" >> $GITHUB_ENV
- name: Run Tests
run: |
pytest tests/
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Icon = ""

[tool.pytest.ini_options]
minversion = "8.0"
pythonpath = "src"
testpaths = [
"tests",
]
Expand Down
45 changes: 20 additions & 25 deletions src/basic_data_handling/dict_nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def INPUT_TYPES(cls):
"key": ("STRING", {"default": ""}),
},
"optional": {
"default_value": ("*", {}),
"default": ("*", {}),
}
}

Expand All @@ -77,8 +77,8 @@ def INPUT_TYPES(cls):
DESCRIPTION = cleandoc(__doc__ or "")
FUNCTION = "get"

def get(self, input_dict: dict, key: str, default_value=None) -> tuple[Any]:
return (input_dict.get(key, default_value),)
def get(self, input_dict: dict, key: str, default=None) -> tuple[Any]:
return (input_dict.get(key, default),)


class DictSet:
Expand Down Expand Up @@ -297,28 +297,24 @@ def INPUT_TYPES(cls):
},
"optional": {
"default_value": ("*", {}),
"has_default": (["False", "True"], {"default": "False"}),
}
}

RETURN_TYPES = ("DICT", "*", "BOOLEAN")
RETURN_NAMES = ("dict", "value", "key_found")
RETURN_TYPES = ("DICT", "*")
RETURN_NAMES = ("dict", "value")
CATEGORY = "Basic/DICT"
DESCRIPTION = cleandoc(__doc__ or "")
FUNCTION = "pop"

def pop(self, input_dict: dict, key: str, default_value=None, has_default: str = "False") -> tuple[dict, Any, bool]:
def pop(self, input_dict: dict, key: str, default_value=None) -> tuple[dict, Any]:
result = input_dict.copy()
has_default_bool = (has_default == "True")

try:
if key in result:
value = result.pop(key)
return result, value, True
elif has_default_bool:
return result, default_value, False
return result, value
else:
raise KeyError(f"Key '{key}' not found in dictionary")
return result, default_value
except Exception as e:
raise ValueError(f"Error popping key from dictionary: {str(e)}")

Expand Down Expand Up @@ -376,7 +372,7 @@ def INPUT_TYPES(cls):
}

RETURN_TYPES = ("DICT", "*")
RETURN_NAMES = ("dict", "value")
RETURN_NAMES = ("DICT", "value")
CATEGORY = "Basic/DICT"
DESCRIPTION = cleandoc(__doc__ or "")
FUNCTION = "setdefault"
Expand Down Expand Up @@ -605,7 +601,7 @@ def INPUT_TYPES(cls):
"keys": ("LIST", {}),
},
"optional": {
"default_value": ("*", {}),
"default": ("*", {}),
}
}

Expand All @@ -615,8 +611,8 @@ def INPUT_TYPES(cls):
DESCRIPTION = cleandoc(__doc__ or "")
FUNCTION = "get_multiple"

def get_multiple(self, input_dict: dict, keys: list, default_value=None) -> tuple[list]:
values = [input_dict.get(key, default_value) for key in keys]
def get_multiple(self, input_dict: dict, keys: list, default=None) -> tuple[list]:
values = [input_dict.get(key, default) for key in keys]
return (values,)


Expand Down Expand Up @@ -736,40 +732,39 @@ def INPUT_TYPES(cls):
}

RETURN_TYPES = ("DICT", "BOOLEAN")
RETURN_NAMES = ("dict", "success")
CATEGORY = "Basic/DICT"
DESCRIPTION = cleandoc(__doc__ or "")
FUNCTION = "convert"

def convert(self, input: Any) -> tuple[dict, bool]:
def convert(self, input: Any) -> tuple[dict]:
try:
if isinstance(input, dict):
return input.copy(), True
return (input.copy(),)

# Try converting from items
if hasattr(input, "items"):
return dict(input.items()), True
return (dict(input.items()),)

# Try converting from sequence of pairs
if hasattr(input, "__iter__") and not isinstance(input, str):
try:
result = dict(input)
return result, True
return (result,)
except (TypeError, ValueError):
pass

# Check for to_dict or as_dict methods
if hasattr(input, "to_dict") and callable(getattr(input, "to_dict")):
return input.to_dict(), True
return (input.to_dict(),)

if hasattr(input, "as_dict") and callable(getattr(input, "as_dict")):
return input.as_dict(), True
return (input.as_dict(),)

# Failed to convert
return {}, False
return ({},)

except Exception:
return {}, False
return ({},)


NODE_CLASS_MAPPINGS = {
Expand Down
3 changes: 0 additions & 3 deletions src/basic_data_handling/list_nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -347,9 +347,6 @@ def INPUT_TYPES(cls):
FUNCTION = "slice"

def slice(self, list: list[Any], start: int = 0, stop: int = -1, step: int = 1) -> tuple[list[Any]]:
if stop == -1:
stop = len(list)

return (list[start:stop:step],)


Expand Down
193 changes: 193 additions & 0 deletions tests/test_dict_nodes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
#import pytest
from src.basic_data_handling.dict_nodes import (
DictCreate,
DictCreateFromItems,
DictGet,
DictSet,
DictKeys,
DictValues,
DictItems,
DictContainsKey,
DictClear,
DictCopy,
DictFromKeys,
DictPop,
DictPopItem,
DictSetDefault,
DictUpdate,
DictLength,
DictMerge,
DictGetKeysValues,
DictRemove,
DictFilterByKeys,
DictExcludeKeys,
DictGetMultiple,
DictInvert,
DictCreateFromLists,
DictCompare,
AnyToDict,
)

def test_dict_create():
node = DictCreate()
assert node.create() == ({},) # Creates an empty dictionary


def test_dict_create_from_items():
node = DictCreateFromItems()
items = [("key1", "value1"), ("key2", "value2")]
assert node.create_from_items(items) == ({"key1": "value1", "key2": "value2"},)


def test_dict_get():
node = DictGet()
my_dict = {"key1": "value1", "key2": "value2"}
assert node.get(my_dict, "key1") == ("value1",)
assert node.get(my_dict, "key3", default="default_value") == ("default_value",)


def test_dict_set():
node = DictSet()
my_dict = {"key1": "value1"}
assert node.set(my_dict, "key2", "value2") == ({"key1": "value1", "key2": "value2"},)


def test_dict_keys():
node = DictKeys()
my_dict = {"key1": "value1", "key2": "value2"}
assert node.keys(my_dict) == (["key1", "key2"],)


def test_dict_values():
node = DictValues()
my_dict = {"key1": "value1", "key2": "value2"}
assert node.values(my_dict) == (["value1", "value2"],)


def test_dict_items():
node = DictItems()
my_dict = {"key1": "value1", "key2": "value2"}
assert node.items(my_dict) == ([("key1", "value1"), ("key2", "value2")],)


def test_dict_contains_key():
node = DictContainsKey()
my_dict = {"key1": "value1"}
assert node.contains_key(my_dict, "key1") == (True,)
assert node.contains_key(my_dict, "key2") == (False,)


def test_dict_clear():
node = DictClear()
my_dict = {"key1": "value1"}
assert node.clear(my_dict) == ({},)


def test_dict_copy():
node = DictCopy()
my_dict = {"key1": "value1"}
assert node.copy(my_dict) == ({"key1": "value1"},)


def test_dict_from_keys():
node = DictFromKeys()
keys = ["key1", "key2"]
assert node.from_keys(keys, value="value") == ({"key1": "value", "key2": "value"},)


def test_dict_pop():
node = DictPop()
my_dict = {"key1": "value1", "key2": "value2"}
assert node.pop(my_dict, "key1") == ({"key2": "value2"}, "value1")


def test_dict_pop_item():
node = DictPopItem()
my_dict = {"key1": "value1"}
assert node.popitem(my_dict) == ({}, "key1", "value1", True)
assert node.popitem({}) == ({}, "", None, False)


def test_dict_set_default():
node = DictSetDefault()
my_dict = {"key1": "value1"}
assert node.setdefault(my_dict, "key2", "default") == ({"key1": "value1", "key2": "default"}, "default")


def test_dict_update():
node = DictUpdate()
my_dict = {"key1": "value1"}
update_dict = {"key2": "value2"}
assert node.update(my_dict, update_dict) == ({"key1": "value1", "key2": "value2"},)


def test_dict_length():
node = DictLength()
my_dict = {"key1": "value1"}
assert node.length(my_dict) == (1,)


def test_dict_merge():
node = DictMerge()
dict1 = {"key1": "value1"}
dict2 = {"key2": "value2"}
assert node.merge(dict1, dict2) == ({"key1": "value1", "key2": "value2"},)


def test_dict_get_keys_values():
node = DictGetKeysValues()
my_dict = {"key1": "value1", "key2": "value2"}
assert node.get_keys_values(my_dict) == (["key1", "key2"], ["value1", "value2"])


def test_dict_remove():
node = DictRemove()
my_dict = {"key1": "value1"}
assert node.remove(my_dict, "key1") == ({}, True)


def test_dict_filter_by_keys():
node = DictFilterByKeys()
my_dict = {"key1": "value1", "key2": "value2"}
keys = ["key1"]
assert node.filter_by_keys(my_dict, keys) == ({"key1": "value1"},)


def test_dict_exclude_keys():
node = DictExcludeKeys()
my_dict = {"key1": "value1", "key2": "value2"}
keys = ["key1"]
assert node.exclude_keys(my_dict, keys) == ({"key2": "value2"},)


def test_dict_get_multiple():
node = DictGetMultiple()
my_dict = {"key1": "value1", "key2": "value2"}
keys = ["key1", "key3"]
assert node.get_multiple(my_dict, keys, default="default") == (["value1", "default"],)


def test_dict_invert():
node = DictInvert()
my_dict = {"key1": "value1", "key2": "value2"}
assert node.invert(my_dict) == ({"value1": "key1", "value2": "key2"}, True)


def test_dict_create_from_lists():
node = DictCreateFromLists()
keys = ["key1", "key2"]
values = ["value1", "value2"]
assert node.create_from_lists(keys, values) == ({"key1": "value1", "key2": "value2"},)


def test_dict_compare():
node = DictCompare()
dict1 = {"key1": "value1"}
dict2 = {"key1": "value1"}
assert node.compare(dict1, dict2) == (True, [], [], [])


def test_any_to_dict():
node = AnyToDict()
my_dict = {"key1": "value1"}
assert node.convert(my_dict) == ({"key1": "value1"},)
Loading
Loading