nodes_dict: DictAddAny
This commit is contained in:
@@ -5,3 +5,5 @@ Metadata-related module.
|
||||
|
||||
category: str = "String Constructor"
|
||||
category_dict: str = f"{category}/Format-Dict"
|
||||
category_old: str = f"{category}/_old"
|
||||
pack_id_suffix: str = " [String Constructor]"
|
||||
|
||||
+3
-1
@@ -2,7 +2,9 @@
|
||||
"""
|
||||
"""
|
||||
|
||||
from typing import TypeVar as _TypeVar
|
||||
import typing as _t
|
||||
from typing import Any as _A, Optional as _O, Union as _U, TypeVar as _TypeVar
|
||||
|
||||
T = _TypeVar('T')
|
||||
T2 = _TypeVar('T2')
|
||||
FormatDict = _TypeVar('FormatDict', bound=_U[_t.Dict[str, _A], _t.Mapping[str, _A]])
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
# encoding: utf-8
|
||||
"""
|
||||
"""
|
||||
|
||||
from dataclasses import fields as __dataclass_fields
|
||||
|
||||
from comfy_api.latest import io as _io
|
||||
|
||||
from .__meta import category_old as _category_old
|
||||
from .__typing import _t, T as _T
|
||||
|
||||
|
||||
_DICT = _io.Custom("DICT")
|
||||
_DICT_INPUT_OPTIONAL = _DICT.Input(
|
||||
'dict',
|
||||
optional=True,
|
||||
tooltip="An (optional) Format-Dictionary to work with."
|
||||
)
|
||||
_DICT_OUTPUT = _DICT.Output(
|
||||
'DICT',
|
||||
display_name='dict'
|
||||
)
|
||||
|
||||
_T_Input = _t.TypeVar('T_Input', bound=_io.Input)
|
||||
|
||||
|
||||
def __dataclass_fields_dict(obj) -> _t.Dict[str, _t.Any]:
|
||||
"""Return all the field values from a dataclass - as dict. No deep-copy."""
|
||||
field_names = (field.name for field in __dataclass_fields(obj))
|
||||
return {
|
||||
attr: getattr(obj, attr)
|
||||
for attr in field_names
|
||||
}
|
||||
|
||||
|
||||
def _dataclass_override(obj: _T, **overrides) -> _T:
|
||||
"""Copy a dataclass instance with optional overrides."""
|
||||
obj_dict = __dataclass_fields_dict(obj)
|
||||
obj_dict.update(overrides)
|
||||
obj_type = type(obj)
|
||||
return obj_type(**obj_dict)
|
||||
|
||||
|
||||
def _input_override(input_obj: _T_Input, **overrides) -> _T_Input:
|
||||
"""Copy an ``io.Input`` instance with optional overrides."""
|
||||
new_id = input_obj.id
|
||||
if 'id' in overrides:
|
||||
new_id = overrides.pop('id')
|
||||
|
||||
input_args = input_obj.as_dict()
|
||||
if 'id' in input_args:
|
||||
del input_args['id']
|
||||
input_args.update(overrides)
|
||||
|
||||
input_type: _t.Type[_T_Input] = type(input_obj)
|
||||
return input_type(new_id, **input_args)
|
||||
|
||||
|
||||
def _schema_old_name(schema: _io.Schema, node_id: str, **overrides):
|
||||
"""Build a deprecated schema for old node-ID."""
|
||||
schema_dict = __dataclass_fields_dict(schema)
|
||||
if 'node_id' in schema_dict:
|
||||
del schema_dict['node_id']
|
||||
name_old = schema_dict.pop('display_name')
|
||||
|
||||
schema_dict.update(dict(
|
||||
category=_category_old,
|
||||
display_name=f"{name_old} [OLD]",
|
||||
is_deprecated=True,
|
||||
is_dev_only=True,
|
||||
))
|
||||
schema_dict.update(overrides)
|
||||
return _io.Schema(node_id, **schema_dict)
|
||||
|
||||
|
||||
# noinspection PyAbstractClass
|
||||
class _BaseNode(_io.ComfyNode):
|
||||
"""Shared base class for all the nodes in pack.
|
||||
Stores schema in internal class attribute.
|
||||
"""
|
||||
_schema: _io.Schema = None
|
||||
|
||||
@classmethod
|
||||
def define_schema(cls) -> _io.Schema:
|
||||
return cls._schema
|
||||
@@ -0,0 +1,76 @@
|
||||
# encoding: utf-8
|
||||
"""Service nodes for dict preparation."""
|
||||
|
||||
from inspect import cleandoc as _cleandoc
|
||||
|
||||
from frozendict import frozendict as _frozendict
|
||||
|
||||
from comfy_api.latest import io as _io, ui as _ui
|
||||
|
||||
from .__meta import (
|
||||
category_dict as _category_dict,
|
||||
pack_id_suffix as _pack_id
|
||||
)
|
||||
from .__typing import _A, _U, _O, _t, T as _T, FormatDict as _FormatDict
|
||||
from ._dict import _new_dict_with_updated_key
|
||||
from ._io_custom import (
|
||||
_BaseNode,
|
||||
_DICT_INPUT_OPTIONAL, _DICT_OUTPUT,
|
||||
_input_override, _schema_old_name
|
||||
)
|
||||
from .docstring_formatter import format_docstring as _format_docstring
|
||||
|
||||
_dict = dict
|
||||
|
||||
# ----------------------------------------------------------
|
||||
|
||||
class DictAddAny(_BaseNode):
|
||||
"""Add/update any-type item to a Format-Dict."""
|
||||
_schema = _io.Schema(
|
||||
node_id=f'DictAddAny{_pack_id}',
|
||||
display_name='Add ANY to Dict',
|
||||
category=_category_dict,
|
||||
description=_format_docstring(_cleandoc(__doc__)),
|
||||
inputs=[
|
||||
_io.String.Input(
|
||||
'name',
|
||||
tooltip=(
|
||||
"Name (key) of the item inserted into the dict. "
|
||||
"It must comprise only of latin letters, digits and underscores + it can't start with a digit."
|
||||
),
|
||||
),
|
||||
|
||||
_DICT_INPUT_OPTIONAL,
|
||||
_io.AnyType.Input(
|
||||
'value',
|
||||
optional=True,
|
||||
tooltip="The actual any-type item to add into the dict."
|
||||
),
|
||||
],
|
||||
outputs=[_DICT_OUTPUT],
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def execute(cls,
|
||||
name: str, dict: _O[_FormatDict] = None, value: _A = None
|
||||
) -> _io.NodeOutput:
|
||||
"""Update/append an item of any type to the dict."""
|
||||
if value is None:
|
||||
if dict is None:
|
||||
dict = _frozendict()
|
||||
# No need to create another dict instance if we add nothing:
|
||||
result = dict
|
||||
else:
|
||||
result = _new_dict_with_updated_key(dict, name, value)
|
||||
return _io.NodeOutput(result)
|
||||
|
||||
|
||||
# ==========================================================
|
||||
# Deprecated nodes with old IDs (for backwards compatibility)
|
||||
|
||||
|
||||
class DictAddAnyOld1(DictAddAny):
|
||||
_schema = _schema_old_name(
|
||||
DictAddAny._schema,
|
||||
'StringConstructorDictAddAny'
|
||||
)
|
||||
Reference in New Issue
Block a user