Merge branch 'dev': v1.0.2
This commit is contained in:
+8
-2
@@ -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
|
||||
|
||||
|
||||
@@ -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']
|
||||
|
||||
+15
-3
@@ -60,13 +60,15 @@ def _raise_from_errors_dict(
|
||||
raise KeyError(msg)
|
||||
|
||||
|
||||
def _verify_input_dict(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(input_dict: _t.Dict[str, _T] = None) -> _t.Dict[str, _T]:
|
||||
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)
|
||||
|
||||
@@ -7,7 +7,7 @@ import typing as _t
|
||||
|
||||
from frozendict import deepfreeze as _deepfreeze
|
||||
|
||||
from .funcs_common import _raise_from_errors_dict, _validate_key, _verify_input_dict
|
||||
from .funcs_common import _raise_from_errors_dict, _validate_key, _verify_input_dict_into_new
|
||||
|
||||
|
||||
def set_dict_any_type_item(
|
||||
@@ -15,7 +15,7 @@ def set_dict_any_type_item(
|
||||
# unique_id: str = None,
|
||||
) -> _t.Tuple[_t.Dict[str, _t.Any]]:
|
||||
"""Update/append an item of any type to the dict."""
|
||||
out_dict: _t.Dict[str, _t.Any] = _verify_input_dict(in_dict)
|
||||
out_dict: _t.Dict[str, _t.Any] = _verify_input_dict_into_new(in_dict)
|
||||
if value is None:
|
||||
return (_deepfreeze(in_dict), ) # No need to create another dict instance if it's already frozen
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import typing as _t
|
||||
from frozendict import deepfreeze as _deepfreeze
|
||||
|
||||
from .enums import T as _T
|
||||
from .funcs_common import _raise_from_errors_dict, _validate_key, _verify_input_dict
|
||||
from .funcs_common import _raise_from_errors_dict, _validate_key, _verify_input_dict_into_new
|
||||
|
||||
|
||||
def set_dict_string(
|
||||
@@ -16,7 +16,7 @@ def set_dict_string(
|
||||
# unique_id: str = None,
|
||||
) -> _t.Tuple[_t.Dict[str, _t.Union[_T, str]]]:
|
||||
"""Update/append a string to the dict."""
|
||||
out_dict: _t.Dict[str, _t.Union[_T, str]] = _verify_input_dict(in_dict)
|
||||
out_dict: _t.Dict[str, _t.Union[_T, str]] = _verify_input_dict_into_new(in_dict)
|
||||
errors_dict: _t.Dict[_t.Any, str] = dict()
|
||||
name = _validate_key(name, errors_dict)
|
||||
_raise_from_errors_dict(errors_dict)
|
||||
|
||||
@@ -8,7 +8,7 @@ import typing as _t
|
||||
from frozendict import frozendict as _frozendict, deepfreeze as _deepfreeze
|
||||
|
||||
from .enums import T as _T
|
||||
from .funcs_common import _show_text_on_node, _raise_from_errors_dict, _validate_key, _verify_input_dict
|
||||
from .funcs_common import _show_text_on_node, _raise_from_errors_dict, _validate_key, _verify_input_dict_into_new
|
||||
|
||||
|
||||
def _return_line_raw(line_raw: str, line_stripped:str) -> str:
|
||||
@@ -61,7 +61,7 @@ def parse_dict_from_text(
|
||||
multiline_str: str, strip_lines=True,
|
||||
show: bool = True, in_dict: _t.Dict[str, _T] = None, unique_id: str = None
|
||||
) -> _t.Tuple[_t.Dict[str, _T]]:
|
||||
out_dict: _t.Dict[str, _T] = _verify_input_dict(in_dict)
|
||||
out_dict: _t.Dict[str, _T] = _verify_input_dict_into_new(in_dict)
|
||||
|
||||
errors_dict: _t.Dict[_t.Any, str] = dict()
|
||||
new_dict: _t.Dict[str, str] = {
|
||||
|
||||
@@ -7,7 +7,7 @@ import typing as _t
|
||||
|
||||
from pprint import pformat as _pformat
|
||||
|
||||
from .funcs_common import _show_text_on_node, _verify_input_dict
|
||||
from .funcs_common import _show_text_on_node, _verify_input_dict_into_new
|
||||
|
||||
|
||||
def _to_regular_dict_recursive_copy(input_dict: dict = None) -> dict:
|
||||
@@ -32,7 +32,7 @@ def _preview_single_entry(key: str, value) -> str:
|
||||
|
||||
|
||||
def _preview_message(input_dict: dict = None):
|
||||
input_dict = _to_regular_dict_recursive_copy(_verify_input_dict(input_dict))
|
||||
input_dict = _to_regular_dict_recursive_copy(_verify_input_dict_into_new(input_dict))
|
||||
parts: _t.List[str] = [
|
||||
_preview_single_entry(k, v) for k, v in input_dict.items()
|
||||
]
|
||||
|
||||
+2
-2
@@ -7,7 +7,7 @@ import typing as _t
|
||||
|
||||
import sys as _sys
|
||||
|
||||
from .funcs_common import _show_text_on_node, _verify_input_dict
|
||||
from .funcs_common import _show_text_on_node, _verify_input_dict_into_new
|
||||
|
||||
|
||||
_RECURSION_LIMIT = max(int(_sys.getrecursionlimit()), 10) # You can externally monkey-patch it... but if it blows up, your fault 🤷🏻♂️
|
||||
@@ -45,7 +45,7 @@ def formatter(
|
||||
template: str, recursive: bool = False, format_dict: _t.Dict[str, _t.Any] = None,
|
||||
show: bool = True, unique_id: str = None
|
||||
) -> _t.Tuple[str]:
|
||||
format_dict = _verify_input_dict(format_dict)
|
||||
format_dict = _verify_input_dict_into_new(format_dict)
|
||||
if not isinstance(template, str):
|
||||
raise TypeError(f"Not a string: {template!r}")
|
||||
|
||||
|
||||
@@ -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, )
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
[project]
|
||||
name = "string-constructor"
|
||||
description = "Composing prompt variants from the same text pieces with ease:\n• Build your \"library\" (dictionary) of named text chunks (sub-strings) to use it across the entire workflow.\n• Compile these snippets into different prompts in-place - with just one string formatting node.\n• Freely update the dictionary down the line - get different prompts.\n• Reference text chunks within each other to build dependent hierarchies of less/more detailed descriptions.\n• A real life-saver for regional prompting (aka area composition)."
|
||||
version = "1.0.1"
|
||||
description = "String formatting (compiling text from pieces) made for humans:\n• Turn parts of prompt into a dictionary - to share them all across the entire workflow as a single connection.\n• Compose your prompt in-place from these snippets and regular text - with just one text field.\n• Easily update the dictionary down the line - get different prompts from the same template.\n• Reference text chunks within each other to build complex hierarchies of self-updating prompts.\n• A true time-saver for regional prompting (aka area composition)."
|
||||
version = "1.0.2"
|
||||
authors = [
|
||||
{name = "Lex Darlog"}
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user