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
5 changes: 3 additions & 2 deletions __init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
"""Top-level package for basic_data_handling."""
import os, sys; sys.path.append(os.path.dirname(os.path.realpath(__file__)))

__all__ = [
"NODE_CLASS_MAPPINGS",
"NODE_DISPLAY_NAME_MAPPINGS",
"WEB_DIRECTORY",
]

from .src.basic_data_handling import NODE_CLASS_MAPPINGS
from .src.basic_data_handling import NODE_DISPLAY_NAME_MAPPINGS
from src.basic_data_handling import NODE_CLASS_MAPPINGS
from src.basic_data_handling import NODE_DISPLAY_NAME_MAPPINGS

WEB_DIRECTORY = "./web"
7 changes: 4 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "basic_data_handling"
version = "0.3.2"
version = "0.3.3"
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.
Expand Down Expand Up @@ -46,14 +46,15 @@ Icon = ""
minversion = "8.0"
pythonpath = [
"src",
"../..", # Path to parent directory containing comfy module
#"../..", # Path to parent directory containing comfy module
"."
]
testpaths = [
"tests",
]
#python_files = ["test_*.py"]
python_files = ["conftest.py", "test_boolean_nodes.py"]
#python_files = ["conftest.py", "test_boolean_nodes.py"]
python_files = ["test_boolean_nodes.py"]

[tool.mypy]
files = "."
Expand Down
32 changes: 32 additions & 0 deletions src/basic_data_handling/_dynamic_input.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
class ContainsDynamicDict(dict):
"""
A custom dictionary that dynamically returns values for keys based on a pattern.
- If a key in the passed dictionary has a value with `{"_dynamic": "number"}` in the tuple's second position,
then any other key starting with the same string and ending with a number will return that value.
- For other keys, normal dictionary lookup behavior applies.
"""

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Store prefixes associated with `_dynamic` values for efficient lookup
self._dynamic_prefixes = {
key.rstrip("0123456789"): value
for key, value in self.items()
if isinstance(value, tuple) and len(value) > 1 and value[1].get("_dynamic") == "number"
}

def __contains__(self, key):
# Check if key matches a dynamically handled prefix or exists normally
return (
any(key.startswith(prefix) and key[len(prefix):].isdigit() for prefix in self._dynamic_prefixes)
or super().__contains__(key)
)

def __getitem__(self, key):
# Dynamically return the value for keys matching a `prefix<number>` pattern
print(f'_ dynamic prefixes: {self._dynamic_prefixes}; get key: {key}')
for prefix, value in self._dynamic_prefixes.items():
if key.startswith(prefix) and key[len(prefix):].isdigit():
return value
# Fallback to normal dictionary behavior for other keys
return super().__getitem__(key)
13 changes: 12 additions & 1 deletion src/basic_data_handling/boolean_nodes.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
from inspect import cleandoc
from comfy.comfy_types.node_typing import IO, ComfyNodeABC

try:
from comfy.comfy_types.node_typing import IO, ComfyNodeABC
except:
class IO:
BOOLEAN = "BOOLEAN"
INT = "INT"
FLOAT = "FLOAT"
STRING = "STRING"
NUMBER = "FLOAT,INT"
ANY = "*"
ComfyNodeABC = object

class BooleanAnd(ComfyNodeABC):
"""
Expand Down
13 changes: 12 additions & 1 deletion src/basic_data_handling/casting_nodes.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
from typing import Any
from inspect import cleandoc
from comfy.comfy_types.node_typing import IO, ComfyNodeABC

try:
from comfy.comfy_types.node_typing import IO, ComfyNodeABC
except:
class IO:
BOOLEAN = "BOOLEAN"
INT = "INT"
FLOAT = "FLOAT"
STRING = "STRING"
NUMBER = "FLOAT,INT"
ANY = "*"
ComfyNodeABC = object

class CastToBoolean(ComfyNodeABC):
"""
Expand Down
13 changes: 12 additions & 1 deletion src/basic_data_handling/comparison_nodes.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
from typing import Any
from inspect import cleandoc
from comfy.comfy_types.node_typing import IO, ComfyNodeABC

try:
from comfy.comfy_types.node_typing import IO, ComfyNodeABC
except:
class IO:
BOOLEAN = "BOOLEAN"
INT = "INT"
FLOAT = "FLOAT"
STRING = "STRING"
NUMBER = "FLOAT,INT"
ANY = "*"
ComfyNodeABC = object

class Equal(ComfyNodeABC):
"""
Expand Down
26 changes: 20 additions & 6 deletions src/basic_data_handling/control_flow_nodes.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
from typing import Any
from inspect import cleandoc
from comfy.comfy_types.node_typing import IO, ComfyNodeABC
from comfy_execution.graph import ExecutionBlocker

try:
from comfy.comfy_types.node_typing import IO, ComfyNodeABC
from comfy_execution.graph import ExecutionBlocker
except:
class IO:
BOOLEAN = "BOOLEAN"
INT = "INT"
FLOAT = "FLOAT"
STRING = "STRING"
NUMBER = "FLOAT,INT"
ANY = "*"
ComfyNodeABC = object
ExecutionBlocker = lambda x: x

from ._dynamic_input import ContainsDynamicDict


class IfElse(ComfyNodeABC):
Expand Down Expand Up @@ -58,11 +72,11 @@ def INPUT_TYPES(cls):
"if": (IO.BOOLEAN, {"forceInput": True}),
"then": (IO.ANY, {"lazy": True}),
},
"optional": {
"optional": ContainsDynamicDict({
"elif_0": (IO.BOOLEAN, {"forceInput": True, "lazy": True, "_dynamic": "number", "_dynamicGroup": 0}),
"then_0": (IO.ANY, {"lazy": True, "_dynamic": "number", "_dynamicGroup": 0}),
"else": (IO.ANY, {"lazy": True}),
}
})
}

RETURN_TYPES = (IO.ANY,)
Expand Down Expand Up @@ -140,10 +154,10 @@ class SwitchCase(ComfyNodeABC):
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"required": ContainsDynamicDict({
"selector": (IO.INT, {"default": 0, "min": 0}),
"case_0": (IO.ANY, {"lazy": True, "_dynamic": "number"}),
},
}),
"optional": {
"default": (IO.ANY, {"lazy": True}),
}
Expand Down
35 changes: 24 additions & 11 deletions src/basic_data_handling/data_list_nodes.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
from typing import Any
from inspect import cleandoc
from comfy.comfy_types.node_typing import IO, ComfyNodeABC

try:
from comfy.comfy_types.node_typing import IO, ComfyNodeABC
except:
class IO:
BOOLEAN = "BOOLEAN"
INT = "INT"
FLOAT = "FLOAT"
STRING = "STRING"
NUMBER = "FLOAT,INT"
ANY = "*"
ComfyNodeABC = object

from ._dynamic_input import ContainsDynamicDict

INT_MAX = 2**15-1 # the computer can do more but be nice to the eyes

Expand All @@ -15,9 +28,9 @@ class DataListCreate(ComfyNodeABC):
@classmethod
def INPUT_TYPES(cls):
return {
"optional": {
"optional": ContainsDynamicDict({
"item_0": (IO.ANY, {"_dynamic": "number"}),
}
})
}

RETURN_TYPES = (IO.ANY,)
Expand All @@ -42,9 +55,9 @@ class DataListCreateFromBoolean(ComfyNodeABC):
@classmethod
def INPUT_TYPES(cls):
return {
"optional": {
"optional": ContainsDynamicDict({
"item_0": (IO.BOOLEAN, {"_dynamic": "number"}),
}
})
}

RETURN_TYPES = (IO.BOOLEAN,)
Expand All @@ -69,9 +82,9 @@ class DataListCreateFromFloat(ComfyNodeABC):
@classmethod
def INPUT_TYPES(cls):
return {
"optional": {
"optional": ContainsDynamicDict({
"item_0": (IO.FLOAT, {"_dynamic": "number"}),
}
})
}

RETURN_TYPES = (IO.FLOAT,)
Expand All @@ -96,9 +109,9 @@ class DataListCreateFromInt(ComfyNodeABC):
@classmethod
def INPUT_TYPES(cls):
return {
"optional": {
"optional": ContainsDynamicDict({
"item_0": (IO.INT, {"_dynamic": "number"}),
}
})
}

RETURN_TYPES = (IO.INT,)
Expand All @@ -123,9 +136,9 @@ class DataListCreateFromString(ComfyNodeABC):
@classmethod
def INPUT_TYPES(cls):
return {
"optional": {
"optional": ContainsDynamicDict({
"item_0": (IO.STRING, {"_dynamic": "number"}),
}
})
}

RETURN_TYPES = (IO.STRING,)
Expand Down
37 changes: 25 additions & 12 deletions src/basic_data_handling/dict_nodes.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
from typing import Any
from inspect import cleandoc
from comfy.comfy_types.node_typing import IO, ComfyNodeABC

try:
from comfy.comfy_types.node_typing import IO, ComfyNodeABC
except:
class IO:
BOOLEAN = "BOOLEAN"
INT = "INT"
FLOAT = "FLOAT"
STRING = "STRING"
NUMBER = "FLOAT,INT"
ANY = "*"
ComfyNodeABC = object

from ._dynamic_input import ContainsDynamicDict


class DictCreate(ComfyNodeABC):
Expand All @@ -13,10 +26,10 @@ class DictCreate(ComfyNodeABC):
@classmethod
def INPUT_TYPES(cls):
return {
"optional": {
"optional": ContainsDynamicDict({
"key_0": (IO.STRING, {"_dynamic": "number", "_dynamicGroup": 0}),
"value_0": (IO.ANY, {"_dynamic": "number", "_dynamicGroup": 0}),
}
})
}

RETURN_TYPES = ("DICT",)
Expand Down Expand Up @@ -45,10 +58,10 @@ class DictCreateFromBoolean(ComfyNodeABC):
@classmethod
def INPUT_TYPES(cls):
return {
"optional": {
"optional": ContainsDynamicDict({
"key_0": (IO.STRING, {"_dynamic": "number", "_dynamicGroup": 0}),
"value_0": (IO.BOOLEAN, {"_dynamic": "number", "_dynamicGroup": 0}),
}
"value_0": (IO.BOOLEAN, {"_dynamic": "number", "_dynamicGroup": 0}),
})
}

RETURN_TYPES = ("DICT",)
Expand Down Expand Up @@ -77,10 +90,10 @@ class DictCreateFromFloat(ComfyNodeABC):
@classmethod
def INPUT_TYPES(cls):
return {
"optional": {
"optional": ContainsDynamicDict({
"key_0": (IO.STRING, {"_dynamic": "number", "_dynamicGroup": 0}),
"value_0": (IO.FLOAT, {"_dynamic": "number", "_dynamicGroup": 0}),
}
})
}

RETURN_TYPES = ("DICT",)
Expand Down Expand Up @@ -109,10 +122,10 @@ class DictCreateFromInt(ComfyNodeABC):
@classmethod
def INPUT_TYPES(cls):
return {
"optional": {
"optional": ContainsDynamicDict({
"key_0": (IO.STRING, {"_dynamic": "number", "_dynamicGroup": 0}),
"value_0": (IO.INT, {"_dynamic": "number", "_dynamicGroup": 0}),
}
})
}

RETURN_TYPES = ("DICT",)
Expand Down Expand Up @@ -141,10 +154,10 @@ class DictCreateFromString(ComfyNodeABC):
@classmethod
def INPUT_TYPES(cls):
return {
"optional": {
"optional": ContainsDynamicDict({
"key_0": (IO.STRING, {"_dynamic": "number", "_dynamicGroup": 0}),
"value_0": (IO.STRING, {"_dynamic": "number", "_dynamicGroup": 0}),
}
})
}

RETURN_TYPES = ("DICT",)
Expand Down
13 changes: 12 additions & 1 deletion src/basic_data_handling/float_nodes.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
from inspect import cleandoc
from comfy.comfy_types.node_typing import IO, ComfyNodeABC

try:
from comfy.comfy_types.node_typing import IO, ComfyNodeABC
except:
class IO:
BOOLEAN = "BOOLEAN"
INT = "INT"
FLOAT = "FLOAT"
STRING = "STRING"
NUMBER = "FLOAT,INT"
ANY = "*"
ComfyNodeABC = object


class FloatCreate(ComfyNodeABC):
Expand Down
13 changes: 12 additions & 1 deletion src/basic_data_handling/int_nodes.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
from inspect import cleandoc
from typing import Literal
from comfy.comfy_types.node_typing import IO, ComfyNodeABC

try:
from comfy.comfy_types.node_typing import IO, ComfyNodeABC
except:
class IO:
BOOLEAN = "BOOLEAN"
INT = "INT"
FLOAT = "FLOAT"
STRING = "STRING"
NUMBER = "FLOAT,INT"
ANY = "*"
ComfyNodeABC = object


class IntCreate(ComfyNodeABC):
Expand Down
Loading
Loading