From 70b3ef3644c46930e3360079a24138a9a20f3de0 Mon Sep 17 00:00:00 2001 From: "Lex Darlog (DRL)" <3897975+Lex-DRL@users.noreply.github.com> Date: Fri, 25 Jul 2025 04:14:42 +0500 Subject: [PATCH] `StringConstructorValidateKeys` --- CHANGELOG.md | 10 +++++-- __init__.py | 3 +++ funcs_common.py | 18 ++++++++++--- node_validate_keys.py | 61 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 87 insertions(+), 5 deletions(-) create mode 100644 node_validate_keys.py diff --git a/CHANGELOG.md b/CHANGELOG.md index f13a8ae..47de817 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,13 @@ ## `TODO` -- Multi-item nodes. -- Bulk `Search & Replace` within **keys** in dictionary. +The pack has already started to sip into dictionary-editing domain. Only the validator and the actual formatting node needs to stay. The rest need to go to their own repo. + +- ~~Multi-item nodes.~~ +- ~~Bulk `Search & Replace` within **keys** in dictionary.~~ + +# v1.0.2 + +- New node: `Validate Format-Dict` # v1.0.1 diff --git a/__init__.py b/__init__.py index 4c613d2..0779f7d 100644 --- a/__init__.py +++ b/__init__.py @@ -9,6 +9,7 @@ from .node_dict_add_string import StringConstructorDictAddString from .node_dict_from_text import StringConstructorDictFromText from .node_dict_preview import StringConstructorDictPreview from .node_formatter import StringConstructorFormatter +from .node_validate_keys import StringConstructorValidateKeys NODE_CLASS_MAPPINGS: _t.Dict[str, type] = { 'StringConstructorDictAddAny': StringConstructorDictAddAny, @@ -16,6 +17,7 @@ NODE_CLASS_MAPPINGS: _t.Dict[str, type] = { 'StringConstructorDictFromText': StringConstructorDictFromText, 'StringConstructorDictPreview': StringConstructorDictPreview, 'StringConstructorFormatter': StringConstructorFormatter, + 'StringConstructorValidateKeys': StringConstructorValidateKeys, } NODE_DISPLAY_NAME_MAPPINGS: _t.Dict[str, str] = { 'StringConstructorDictAddAny': "Add ANY to Format-Dict (Advanced)", @@ -23,6 +25,7 @@ NODE_DISPLAY_NAME_MAPPINGS: _t.Dict[str, str] = { 'StringConstructorDictFromText': "Format-Dict from Text", 'StringConstructorDictPreview': "Preview Format-Dict", 'StringConstructorFormatter': "String Formatter", + 'StringConstructorValidateKeys': "Validate Format-Dict", } __all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS'] diff --git a/funcs_common.py b/funcs_common.py index 4e71b7b..0ffd27b 100644 --- a/funcs_common.py +++ b/funcs_common.py @@ -60,13 +60,15 @@ def _raise_from_errors_dict( raise KeyError(msg) -def _verify_input_dict_into_new(input_dict: _t.Dict[str, _T] = None) -> _t.Dict[str, _T]: +def _verify_input_dict(input_dict: _t.Dict[str, _T] = None, error_if_none=False): """ Verify input dict to have only valid keys. Raises errors if invalid ones found. - Always returns a new dict instance (shallow copy if non-empty dict passed). """ if input_dict is None: - return dict() + if error_if_none: + raise TypeError("No input-dict") + return + if not isinstance(input_dict, dict): raise TypeError(f"Input-dict isn't a dict. Got: {input_dict!r}") @@ -78,4 +80,14 @@ def _verify_input_dict_into_new(input_dict: _t.Dict[str, _T] = None) -> _t.Dict[ errors_dict, "Invalid input-dict:\n{}", "Invalid keys (string names) in input-dict:\n{}" ) + + +def _verify_input_dict_into_new(input_dict: _t.Dict[str, _T] = None) -> _t.Dict[str, _T]: + """ + Verify input dict to have only valid keys. Raises errors if invalid ones found. + Always returns a new dict instance (shallow copy if non-empty dict passed). + """ + if input_dict is None: + return dict() + _verify_input_dict(input_dict) return dict(input_dict) diff --git a/node_validate_keys.py b/node_validate_keys.py new file mode 100644 index 0000000..5ab0b58 --- /dev/null +++ b/node_validate_keys.py @@ -0,0 +1,61 @@ +# encoding: utf-8 +""" +""" + +import typing as _t + +from inspect import cleandoc as _cleandoc + +from frozendict import deepfreeze as _deepfreeze + +from . import _meta +from .docstring_formatter import format_docstring as _format_docstring +from .enums import DataTypes as _DataTypes +from .funcs_common import _verify_input_dict, _show_text_on_node, _T + + +_input_types = _deepfreeze({ + 'required': { + 'dict': _DataTypes.input_dict(), + }, + # 'optional': {}, + # 'hidden': { + # 'unique_id': 'UNIQUE_ID', # used for text display at the bottom of the node + # }, +}) + + +class StringConstructorValidateKeys: + """ + Verify the dict to have string-formatting-compatible keys. No need to add it before "String Formatter" node, + but it might be handy to verify the dict right after it's created. + """ + NODE_NAME = 'StringConstructorValidateKeys' + CATEGORY = _meta.category + DESCRIPTION = _format_docstring(_cleandoc(__doc__)) + + OUTPUT_NODE = True + + FUNCTION = 'main' + RETURN_TYPES = (_DataTypes.DICT, ) + RETURN_NAMES = (_DataTypes.DICT.lower(), ) + # OUTPUT_TOOLTIPS = tuple() + + @classmethod + def INPUT_TYPES(cls): + return _input_types + + @staticmethod + def main( + dict: _t.Dict[str, _T], + # unique_id: str = None, + ) -> _t.Tuple[_t.Dict[str, _T]]: + # try: + # _verify_input_dict(dict, error_if_none=True) + # except Exception: + # _show_text_on_node('❌', unique_id) + # raise + # return (Null, ) + # _show_text_on_node('✅', unique_id) + _verify_input_dict(dict, error_if_none=True) + return (dict, )