"""Unified logging utility for automatic file and function name tracking.""" import sys import inspect from pathlib import Path _DEBUG_ENABLED = False def set_debug(enabled: bool) -> None: """Enable or disable debug logging.""" global _DEBUG_ENABLED _DEBUG_ENABLED = enabled def debug(*args, **kwargs) -> None: """Print debug message if debug logging is enabled. Automatically prepends [filename.function_name] to all output. """ if not _DEBUG_ENABLED: return # Set default to stderr for debug messages if 'file' not in kwargs: kwargs['file'] = sys.stderr # Prepend DEBUG label args = ("DEBUG:", *args) # Use the same logic as log() log(*args, **kwargs) def log(*args, **kwargs) -> None: """Print with automatic file.function prefix. Automatically prepends [filename.function_name] to all output. Defaults to stdout if not specified. Example: log("Upload started") # Output: [add_file.run] Upload started """ # Get the calling frame frame = inspect.currentframe() if frame is None: print(*args, **kwargs) return caller_frame = frame.f_back if caller_frame is None: print(*args, **kwargs) return try: # Get file name without extension file_name = Path(caller_frame.f_code.co_filename).stem # Get function name func_name = caller_frame.f_code.co_name # Set default to stdout if not specified if 'file' not in kwargs: kwargs['file'] = sys.stdout # Build prefix prefix = f"[{file_name}.{func_name}]" # Print with prefix print(prefix, *args, **kwargs) finally: del frame del caller_frame