Add iteration suffix stripping node

This commit is contained in:
2026-08-05 11:08:10 +00:00
parent 52d006cade
commit 5b9886cd1c
3 changed files with 64 additions and 0 deletions
+7
View File
@@ -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.
+35
View File
@@ -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",
+22
View File
@@ -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()