115 lines
4.3 KiB
Python
115 lines
4.3 KiB
Python
# ======================================================================
|
|
# Node Pack: artyclaw-comfy
|
|
# Author: artyclaw
|
|
# Version: 1.0.0
|
|
# Description: A power-user toolkit for prompt logic, IO, and RNG.
|
|
# ======================================================================
|
|
|
|
# __init__.py
|
|
# DebugTextSaver — write or append text with real newlines and a timestamp header
|
|
# Now with extra debug prints.
|
|
|
|
import os
|
|
import re
|
|
from datetime import datetime
|
|
import traceback
|
|
|
|
NODE_NAME = "DebugTextSaver"
|
|
|
|
class DebugTextSaver:
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"string": ("STRING", {"multiline": True, "default": ""}),
|
|
"output_file_path": ("STRING", {"default": "output/debug"}),
|
|
"file_name": ("STRING", {"default": "debug_log"}),
|
|
},
|
|
"optional": {
|
|
"file_extension": ("STRING", {"default": "txt"}),
|
|
"append": ("BOOLEAN", {"default": False}),
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = ("STRING",)
|
|
RETURN_NAMES = ("file_path",)
|
|
FUNCTION = "save"
|
|
CATEGORY = "text/utils"
|
|
|
|
def save(self, string, output_file_path="output/debug", file_name="debug_log",
|
|
file_extension="txt", append=False):
|
|
|
|
print("[DebugTextSaver] --- run start ---")
|
|
|
|
# Expand escape sequences: \n, \\n, \r\n → actual newlines
|
|
print(f"[DebugTextSaver] raw input string: {repr(string)}")
|
|
|
|
# Ensure we have a str
|
|
if not isinstance(string, str):
|
|
string = str(string)
|
|
|
|
def normalize_escapes(s: str) -> str:
|
|
"""
|
|
Convert only a small set of literal escape sequences to real characters:
|
|
- \\r\\n -> newline
|
|
- \\n -> newline
|
|
- \\r -> newline
|
|
- \\t -> tab
|
|
Collapse double backslashes into a single backslash so that sequences like
|
|
'\\\\N' become '\\N' (a literal backslash + 'N') and
|
|
will not be interpreted by any codec.
|
|
"""
|
|
# Convert common literal escapes to real characters
|
|
s = s.replace('\\r\\n', '\n').replace('\\n', '\n').replace('\\r', '\n').replace('\\t', '\t')
|
|
# Collapse double backslashes -> single backslash
|
|
s = s.replace('\\\\', '\\')
|
|
return s
|
|
|
|
clean_text = normalize_escapes(string)
|
|
# Normalize any remaining CR/LF to single \n
|
|
clean_text = re.sub(r'\r\n?', '\n', clean_text)
|
|
|
|
# Timestamp header
|
|
timestamp = datetime.now().strftime("[%Y-%m-%d %H:%M:%S]")
|
|
clean_text = f"{timestamp}\n{clean_text.strip()}\n"
|
|
|
|
# Build directory and filename
|
|
if not output_file_path:
|
|
output_file_path = "output/debug"
|
|
print("[DebugTextSaver] output_file_path was empty, using fallback 'output/debug'")
|
|
|
|
base_dir = os.path.abspath(output_file_path)
|
|
print(f"[DebugTextSaver] target directory (abs): {base_dir}")
|
|
os.makedirs(base_dir, exist_ok=True)
|
|
|
|
safe_name = re.sub(r"[^\w\-.]", "_", file_name.strip())
|
|
if not safe_name:
|
|
safe_name = datetime.now().strftime("debug_%Y%m%d_%H%M%S")
|
|
print(f"[DebugTextSaver] file_name was empty, generated: {safe_name}")
|
|
|
|
ext = file_extension.strip().lstrip(".") or "txt"
|
|
file_path = os.path.join(base_dir, f"{safe_name}.{ext}")
|
|
print(f"[DebugTextSaver] final file path: {file_path}")
|
|
|
|
# Choose mode
|
|
mode = "a" if append else "w"
|
|
print(f"[DebugTextSaver] open mode: {mode}")
|
|
|
|
# Write (append or overwrite)
|
|
try:
|
|
with open(file_path, mode, encoding="utf-8", newline="\n") as f:
|
|
f.write(clean_text)
|
|
print(f"[DebugTextSaver] wrote {len(clean_text)} bytes")
|
|
except Exception as e:
|
|
print("[DebugTextSaver] ERROR while writing file!")
|
|
traceback.print_exc()
|
|
# return empty path on error so you see it downstream
|
|
return ("",)
|
|
|
|
print("[DebugTextSaver] --- run end ---")
|
|
return (file_path,)
|
|
|
|
|
|
NODE_CLASS_MAPPINGS = {"DebugTextSaver": DebugTextSaver}
|
|
NODE_DISPLAY_NAME_MAPPINGS = {"DebugTextSaver": "Debug Text Saver"}
|