Files
S4MUEL-404-ComfyUI-PromptsO/py/anyToString.py
T
2025-11-19 17:20:53 +08:00

285 lines
9.8 KiB
Python

"""
S4 Custom Any To String Node
Author: S4MUEL
GitHub: https://github.com/S4MUEL-404/ComfyUI-PromptsO
Convert any input type to string with advanced formatting options.
"""
import re
from ..s4_logger import S4APILogger, log_processing_step
class S4AnyToString:
"""
Convert any input type to string with formatting and cleaning options.
"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {},
"optional": {
"string_input": (
"STRING",
{
"forceInput": True,
"tooltip": "String input to convert"
}
),
"int_input": (
"INT",
{
"forceInput": True,
"tooltip": "Integer input to convert"
}
),
"float_input": (
"FLOAT",
{
"forceInput": True,
"tooltip": "Float input to convert"
}
),
"remove_whitespace": (
["None", "All", "Leading/Trailing", "Extra Spaces"],
{
"default": "None",
"tooltip": "Remove whitespace from output"
}
),
"remove_special_chars": (
"BOOLEAN",
{
"default": False,
"tooltip": "Remove special characters (keep only alphanumeric and spaces)"
}
),
"lowercase": (
"BOOLEAN",
{
"default": False,
"tooltip": "Convert output to lowercase"
}
),
"uppercase": (
"BOOLEAN",
{
"default": False,
"tooltip": "Convert output to uppercase"
}
),
"prefix": (
"STRING",
{
"default": "",
"multiline": False,
"tooltip": "Text to add at the beginning"
}
),
"suffix": (
"STRING",
{
"default": "",
"multiline": False,
"tooltip": "Text to add at the end"
}
),
"expression": (
"STRING",
{
"default": "",
"multiline": True,
"tooltip": "Python expression to evaluate (use 'value' as the input variable)"
}
),
}
}
RETURN_TYPES = ("STRING",)
RETURN_NAMES = ("text",)
FUNCTION = "convert_to_string"
CATEGORY = "💀PromptsO"
DESCRIPTION = "Convert any input type to string with advanced formatting and cleaning options."
def convert_any_to_string(self, input_value) -> str:
"""Convert any type to string representation"""
if input_value is None:
return ""
# Handle different types
if isinstance(input_value, str):
return input_value
elif isinstance(input_value, (int, float, bool)):
return str(input_value)
elif isinstance(input_value, (list, tuple)):
# Convert list/tuple to comma-separated string
return ", ".join(str(item) for item in input_value)
elif isinstance(input_value, dict):
# Convert dict to key=value pairs
return ", ".join(f"{k}={v}" for k, v in input_value.items())
elif hasattr(input_value, '__str__'):
return str(input_value)
else:
# Fallback for any other type
return repr(input_value)
def apply_whitespace_removal(self, text: str, mode: str) -> str:
"""Apply whitespace removal based on mode"""
if mode == "None":
return text
elif mode == "All":
return re.sub(r'\s+', '', text)
elif mode == "Leading/Trailing":
return text.strip()
elif mode == "Extra Spaces":
# Replace multiple spaces with single space
text = re.sub(r' +', ' ', text)
# Replace multiple newlines with single newline
text = re.sub(r'\n+', '\n', text)
return text.strip()
return text
def apply_special_char_removal(self, text: str) -> str:
"""Remove special characters, keep only alphanumeric and spaces"""
return re.sub(r'[^a-zA-Z0-9\s]', '', text)
def apply_expression(self, text: str, expression: str) -> str:
"""Apply Python expression to the text"""
if not expression or not expression.strip():
return text
try:
# Create a safe evaluation context
safe_globals = {
'__builtins__': {},
'len': len,
'str': str,
'int': int,
'float': float,
'bool': bool,
'list': list,
'dict': dict,
'tuple': tuple,
'max': max,
'min': min,
'sum': sum,
'abs': abs,
'round': round,
}
# Make the value available as 'value' in the expression
local_vars = {'value': text}
# Evaluate the expression
result = eval(expression.strip(), safe_globals, local_vars)
# Convert result back to string
return str(result)
except Exception as e:
error_msg = f"Expression evaluation error: {str(e)}"
S4APILogger.error("AnyToString", error_msg)
raise ValueError(error_msg)
def convert_to_string(
self,
string_input=None,
int_input=None,
float_input=None,
remove_whitespace="None",
remove_special_chars=False,
lowercase=False,
uppercase=False,
prefix="",
suffix="",
expression="",
):
"""Convert input to string with formatting options"""
log_processing_step("AnyToString", "Starting conversion")
# Determine which input is provided
input_value = None
input_type = "unknown"
if string_input is not None:
input_value = string_input
input_type = "STRING"
elif int_input is not None:
input_value = int_input
input_type = "INT"
elif float_input is not None:
input_value = float_input
input_type = "FLOAT"
# Handle empty input
if input_value is None:
S4APILogger.warning("AnyToString", "No input provided, returning empty string")
return ("",)
S4APILogger.debug("AnyToString", f"Input type: {input_type}")
# Convert to string
result = self.convert_any_to_string(input_value)
original_length = len(result)
S4APILogger.debug("AnyToString", f"Initial conversion: {original_length} chars")
# Apply expression first if provided
if expression and expression.strip():
try:
result = self.apply_expression(result, expression)
S4APILogger.debug("AnyToString", f"Expression applied: '{expression[:50]}...'")
except ValueError:
# Error already logged, re-raise
raise
# Apply case transformations
if lowercase and uppercase:
S4APILogger.warning("AnyToString", "Both lowercase and uppercase enabled, applying lowercase only")
result = result.lower()
elif lowercase:
result = result.lower()
S4APILogger.debug("AnyToString", "Applied lowercase transformation")
elif uppercase:
result = result.upper()
S4APILogger.debug("AnyToString", "Applied uppercase transformation")
# Remove special characters
if remove_special_chars:
before_length = len(result)
result = self.apply_special_char_removal(result)
removed_count = before_length - len(result)
if removed_count > 0:
S4APILogger.debug("AnyToString", f"Removed {removed_count} special characters")
# Apply whitespace removal
if remove_whitespace != "None":
before_length = len(result)
result = self.apply_whitespace_removal(result, remove_whitespace)
removed_count = before_length - len(result)
if removed_count > 0:
S4APILogger.debug("AnyToString", f"Whitespace mode '{remove_whitespace}': removed {removed_count} chars")
# Add prefix and suffix
if prefix:
result = prefix + result
S4APILogger.debug("AnyToString", f"Added prefix: '{prefix}'")
if suffix:
result = result + suffix
S4APILogger.debug("AnyToString", f"Added suffix: '{suffix}'")
# Log results
result_info = f"Type: {input_type}, Length: {original_length} → {len(result)} chars"
preview = result[:100] + "..." if len(result) > 100 else result
result_info += f", Preview: {preview}"
S4APILogger.success("AnyToString", f"Conversion completed - {result_info}")
return (result,)
@classmethod
def IS_CHANGED(cls, **kwargs):
return float("NaN")