""" 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")