Add iteration suffix stripping node
This commit is contained in:
@@ -26,6 +26,11 @@
|
||||
- Output: serialized `STRING`
|
||||
- Use it to compact or pretty-print JSON for prompts, logs, or file output.
|
||||
|
||||
- `Dumas Strip Iteration Suffix`
|
||||
- Input: `filename`
|
||||
- Output: cleaned `STRING`
|
||||
- Removes a trailing `_<digits>` iteration suffix before the file extension, for example `asset_003.png -> asset.png`.
|
||||
|
||||
- `Dumas JSON Get Value`
|
||||
- Inputs: `json_object`, `path`
|
||||
- Output: `JSON`
|
||||
@@ -160,6 +165,8 @@ decr -> use index - 1
|
||||
|
||||
`Save Image Dumas` leaves `folder` empty to use ComfyUI's output directory. `name` feeds `%input%` and `name_2` feeds `%input2%`, so a pattern like `project/%input%_%input2%_%counter%` can combine two upstream strings into the saved filename.
|
||||
|
||||
`Dumas Strip Iteration Suffix` only strips a final numeric suffix. Names like `my_asset_final.png` are left untouched, while `my_asset_012.png` becomes `my_asset.png`.
|
||||
|
||||
## Roadmap
|
||||
|
||||
This repo is intended to grow into a broader set of Dumas-branded generic utility nodes, including JSON helpers and adjacent data-manipulation tools.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from functools import lru_cache
|
||||
from itertools import islice
|
||||
import json
|
||||
import os
|
||||
|
||||
|
||||
def _clone_container(value):
|
||||
@@ -243,6 +244,21 @@ def _resolve_iteration_index(index, mode, total_items):
|
||||
return max(0, min(index, total_items - 1))
|
||||
|
||||
|
||||
def _strip_iteration_suffix(value):
|
||||
if not isinstance(value, str):
|
||||
return ""
|
||||
|
||||
root, extension = os.path.splitext(value)
|
||||
if "_" not in root:
|
||||
return value
|
||||
|
||||
prefix, suffix = root.rsplit("_", 1)
|
||||
if not suffix.isdigit():
|
||||
return value
|
||||
|
||||
return f"{prefix}{extension}"
|
||||
|
||||
|
||||
class DumasJSONStringToObjectNode:
|
||||
CATEGORY = "Dumas/JSON"
|
||||
RETURN_TYPES = ("JSON",)
|
||||
@@ -265,6 +281,23 @@ class DumasJSONStringToObjectNode:
|
||||
return (None,)
|
||||
|
||||
|
||||
class DumasStripIterationSuffixNode:
|
||||
CATEGORY = "Dumas/String"
|
||||
RETURN_TYPES = ("STRING",)
|
||||
FUNCTION = "strip_iteration_suffix"
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"filename": ("STRING", {"default": "", "multiline": False}),
|
||||
}
|
||||
}
|
||||
|
||||
def strip_iteration_suffix(self, filename):
|
||||
return (_strip_iteration_suffix(filename),)
|
||||
|
||||
|
||||
class DumasJSONObjectToStringNode:
|
||||
CATEGORY = "Dumas/JSON"
|
||||
RETURN_TYPES = ("STRING",)
|
||||
@@ -596,6 +629,7 @@ class DumasJSONUnflattenNode:
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"DumasJSONStringToObject": DumasJSONStringToObjectNode,
|
||||
"DumasStripIterationSuffix": DumasStripIterationSuffixNode,
|
||||
"DumasJSONObjectToString": DumasJSONObjectToStringNode,
|
||||
"DumasJSONGetValue": DumasJSONGetValueNode,
|
||||
"DumasJSONSetValue": DumasJSONSetValueNode,
|
||||
@@ -615,6 +649,7 @@ NODE_CLASS_MAPPINGS = {
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"DumasJSONStringToObject": "Dumas JSON String to Object",
|
||||
"DumasStripIterationSuffix": "Dumas Strip Iteration Suffix",
|
||||
"DumasJSONObjectToString": "Dumas JSON Object to String",
|
||||
"DumasJSONGetValue": "Dumas JSON Get Value",
|
||||
"DumasJSONSetValue": "Dumas JSON Set Value",
|
||||
|
||||
@@ -17,6 +17,7 @@ from dumas_json_nodes import (
|
||||
DumasJSONObjectToStringNode,
|
||||
DumasJSONStringToObjectNode,
|
||||
DumasJSONSetValueNode,
|
||||
DumasStripIterationSuffixNode,
|
||||
)
|
||||
|
||||
class DumasJSONNodeTests(unittest.TestCase):
|
||||
@@ -41,6 +42,27 @@ class DumasJSONNodeTests(unittest.TestCase):
|
||||
|
||||
self.assertEqual(result, ('{\n "a": 2,\n "b": 1\n}',))
|
||||
|
||||
def test_strip_iteration_suffix_removes_trailing_iteration_before_extension(self):
|
||||
node = DumasStripIterationSuffixNode()
|
||||
|
||||
result = node.strip_iteration_suffix("asset_build_003.png")
|
||||
|
||||
self.assertEqual(result, ("asset_build.png",))
|
||||
|
||||
def test_strip_iteration_suffix_removes_trailing_iteration_without_extension(self):
|
||||
node = DumasStripIterationSuffixNode()
|
||||
|
||||
result = node.strip_iteration_suffix("asset_build_003")
|
||||
|
||||
self.assertEqual(result, ("asset_build",))
|
||||
|
||||
def test_strip_iteration_suffix_leaves_names_without_numeric_suffix_unchanged(self):
|
||||
node = DumasStripIterationSuffixNode()
|
||||
|
||||
result = node.strip_iteration_suffix("my_asset_final.png")
|
||||
|
||||
self.assertEqual(result, ("my_asset_final.png",))
|
||||
|
||||
def test_get_value_reads_nested_paths(self):
|
||||
node = DumasJSONGetValueNode()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user