From 2fb8d39a94048771f528a1bf279bc6bf96314860 Mon Sep 17 00:00:00 2001 From: "Lex Darlog (DRL)" <3897975+Lex-DRL@users.noreply.github.com> Date: Mon, 21 Jul 2025 06:36:28 +0500 Subject: [PATCH] `StringConstructorDictPreview` --- CHANGELOG.md | 1 + __init__.py | 5 ++++- funcs_dict_preview.py | 47 ++++++++++++++++++++++++++++++++++++++ node_dict_preview.py | 52 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 funcs_dict_preview.py create mode 100644 node_dict_preview.py diff --git a/CHANGELOG.md b/CHANGELOG.md index f90a535..1b83b7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,3 +2,4 @@ MVP nodes: - `Format-Dict from Text` +- `Format-Dict Preview` diff --git a/__init__.py b/__init__.py index 839dda5..1a01136 100644 --- a/__init__.py +++ b/__init__.py @@ -5,12 +5,15 @@ import typing as _t from .node_dict_from_text import StringConstructorDictFromText +from .node_dict_preview import StringConstructorDictPreview NODE_CLASS_MAPPINGS: _t.Dict[str, type] = { 'StringConstructorDictFromText': StringConstructorDictFromText, + 'StringConstructorDictPreview': StringConstructorDictPreview, } NODE_DISPLAY_NAME_MAPPINGS: _t.Dict[str, str] = { - 'StringConstructorDictFromText': "Format-Dict from Text" + 'StringConstructorDictFromText': "Format-Dict from Text", + 'StringConstructorDictPreview': "Preview Format-Dict", } __all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS'] diff --git a/funcs_dict_preview.py b/funcs_dict_preview.py new file mode 100644 index 0000000..0285211 --- /dev/null +++ b/funcs_dict_preview.py @@ -0,0 +1,47 @@ +# encoding: utf-8 +""" +The actual code (MVC pattern) for `StringConstructorDictPreview` node. +""" + +import typing as _t + +from pprint import pformat as _pformat + +from .funcs_common import _show_text_on_node, _verify_input_dict + + +def _to_regular_dict_recursive_copy(input_dict: dict = None) -> dict: + """ + To simplify preview, turns frozen dicts back to regular ones. + Copies the dict in process and does so recursively, but not truly deep: if value is another dict, + it will be processed, too. But dicts within other objects (like lists) won't be found. + """ + if not input_dict: + return dict() + return { + k: (_to_regular_dict_recursive_copy(v) if isinstance(v, dict) else v) + for k, v in input_dict.items() + } + + +def _preview_single_entry(key: str, value) -> str: + if isinstance(value, str): + return f"{key}:\n{value}" + value_repr = _pformat(value) + return f"{key}:\n{value_repr}" + + +def _preview_message(input_dict: dict = None): + input_dict = _to_regular_dict_recursive_copy(_verify_input_dict(input_dict)) + parts: _t.List[str] = [ + _preview_single_entry(k, v) for k, v in input_dict.items() + ] + return '\n\n'.join(parts) + + +def preview_str_dict(input_dict: dict, unique_id: str = None): + if not unique_id: + return (input_dict, ) + status_text = _preview_message(input_dict) + _show_text_on_node(status_text, unique_id) + return (input_dict, ) diff --git a/node_dict_preview.py b/node_dict_preview.py new file mode 100644 index 0000000..64a4b17 --- /dev/null +++ b/node_dict_preview.py @@ -0,0 +1,52 @@ +# 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_dict_preview import preview_str_dict as _preview_str_dict + + +# A tiny optimization by reusing the same immutable dict: +_input_types = _deepfreeze({ + 'required': { + 'str_dict': _DataTypes.input_str_dict(tooltip="A dictionary of named substrings."), + }, + # 'optional': {}, + 'hidden': { + 'unique_id': 'UNIQUE_ID', # used for text display at the bottom of the node + }, +}) + + +class StringConstructorDictPreview: + """ + Show the contents of a Format-Dict. + """ + NODE_NAME = 'StringConstructorDictPreview' + CATEGORY = _meta.category + DESCRIPTION = _format_docstring(_cleandoc(__doc__)) + + OUTPUT_NODE = True + + FUNCTION = 'main' + RETURN_TYPES = (_DataTypes.STR_DICT, ) + RETURN_NAMES = (_DataTypes.STR_DICT.lower(), ) + # OUTPUT_TOOLTIPS = tuple() + + @classmethod + def INPUT_TYPES(cls): + return _input_types + + def main( + self, str_dict: _t.Dict[str, _t.Any], + unique_id: str = None, + ): + return _preview_str_dict(str_dict, unique_id=unique_id)