import logging import sys from typing import Dict, Any, List, Optional logger = logging.getLogger(__name__) class LogFormatter: """Utility class for consistent log formatting across the application""" @staticmethod def section(title: str) -> str: """Create a section header""" return f"\n{'='*20} {title.upper()} {'='*20}" @staticmethod def subsection(title: str) -> str: """Create a subsection header""" return f"\n{'ā”€'*20} {title} {'ā”€'*20}" @staticmethod def tree(items: Dict[str, Any], title: str = None) -> List[str]: """Create a tree view of dictionary data""" lines = [] if title: lines.append(f"šŸ“Š {title}:") # Get the maximum length for alignment max_key_length = max(len(str(k)) for k in items.keys()) # Format each item for i, (key, value) in enumerate(items.items()): prefix = "ā””ā”€ā”€" if i == len(items) - 1 else "ā”œā”€ā”€" if isinstance(value, (int, float)): value = f"{value:,}" # Add thousand separators lines.append(f"{prefix} {str(key):<{max_key_length}}: {value}") return lines @staticmethod def stats(stats: Dict[str, int], title: str = None) -> List[str]: """Format statistics with icons""" lines = [] if title: lines.append(f"šŸ“Š {title}:") # Get the maximum length for alignment max_key_length = max(len(str(k)) for k in stats.keys()) # Format each stat with an appropriate icon icons = { "total": "šŸ“Œ", "success": "āœ…", "error": "āŒ", "pending": "ā³", "processing": "āš™ļø", "finished": "āœØ", "evaluating": "šŸ”„", "downloads": "ā¬‡ļø", "files": "šŸ“", "cached": "šŸ’¾", "size": "šŸ“", "time": "ā±ļø", "rate": "šŸš€" } # Format each item for i, (key, value) in enumerate(stats.items()): prefix = "ā””ā”€ā”€" if i == len(stats) - 1 else "ā”œā”€ā”€" icon = icons.get(key.lower().split('_')[0], "ā€¢") if isinstance(value, (int, float)): value = f"{value:,}" # Add thousand separators lines.append(f"{prefix} {icon} {str(key):<{max_key_length}}: {value}") return lines @staticmethod def progress_bar(current: int, total: int, width: int = 20) -> str: """Create a progress bar""" percentage = (current * 100) // total filled = "ā–ˆ" * (percentage * width // 100) empty = "ā–‘" * (width - len(filled)) return f"{filled}{empty} {percentage:3d}%" @staticmethod def error(message: str, error: Optional[Exception] = None) -> str: """Format error message""" error_msg = f"\nāŒ Error: {message}" if error: error_msg += f"\n ā””ā”€ā”€ Details: {str(error)}" return error_msg @staticmethod def success(message: str) -> str: """Format success message""" return f"āœ… {message}" @staticmethod def warning(message: str) -> str: """Format warning message""" return f"āš ļø {message}" @staticmethod def info(message: str) -> str: """Format info message""" return f"ā„¹ļø {message}"