Your Name
feat: UI improvements and error suppression - Enhanced dashboard and market pages with improved header buttons, logo, and currency symbol display - Stopped animated ticker - Removed pie chart legends - Added error suppressor for external service errors (SSE, Permissions-Policy warnings) - Improved header button prominence and icon appearance - Enhanced logo with glow effects and better design - Fixed currency symbol visibility in market tables
8b7b267
| """ | |
| Utils package - Consolidated utility functions | |
| Provides logging setup and other utility functions for the application | |
| """ | |
| # Import logger functions first (most critical) | |
| try: | |
| from .logger import setup_logger | |
| except ImportError as e: | |
| print(f"ERROR: Failed to import setup_logger from .logger: {e}") | |
| import logging | |
| def setup_logger(name: str, level: str = "INFO") -> logging.Logger: | |
| """Fallback setup_logger if import fails""" | |
| logger = logging.getLogger(name) | |
| if not logger.handlers: | |
| handler = logging.StreamHandler() | |
| handler.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')) | |
| logger.addHandler(handler) | |
| logger.setLevel(getattr(logging, level.upper())) | |
| return logger | |
| # Create setup_logging as an alias for setup_logger for backward compatibility | |
| # This MUST be defined before any other imports that might use it | |
| def setup_logging(): | |
| """ | |
| Setup logging for the application | |
| This is a compatibility wrapper around setup_logger | |
| Returns: | |
| logging.Logger: Configured logger instance | |
| """ | |
| return setup_logger("crypto_aggregator", level="INFO") | |
| # Import utility functions from the standalone utils.py module | |
| # We need to access it via a different path since we're inside the utils package | |
| import sys | |
| import os | |
| # Add parent directory to path to import standalone utils module | |
| parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | |
| if parent_dir not in sys.path: | |
| sys.path.insert(0, parent_dir) | |
| # Import from standalone utils.py with a different name to avoid circular imports | |
| try: | |
| # Try importing specific functions from the standalone utils file | |
| import importlib.util | |
| utils_path = os.path.join(parent_dir, 'utils.py') | |
| spec = importlib.util.spec_from_file_location("utils_standalone", utils_path) | |
| if spec and spec.loader: | |
| utils_standalone = importlib.util.module_from_spec(spec) | |
| spec.loader.exec_module(utils_standalone) | |
| # Expose the functions | |
| format_number = utils_standalone.format_number | |
| calculate_moving_average = utils_standalone.calculate_moving_average | |
| calculate_rsi = utils_standalone.calculate_rsi | |
| extract_coins_from_text = utils_standalone.extract_coins_from_text | |
| export_to_csv = utils_standalone.export_to_csv | |
| validate_price_data = utils_standalone.validate_price_data | |
| is_data_stale = utils_standalone.is_data_stale | |
| cache_with_ttl = utils_standalone.cache_with_ttl | |
| safe_float = utils_standalone.safe_float | |
| safe_int = utils_standalone.safe_int | |
| truncate_string = utils_standalone.truncate_string | |
| percentage_change = utils_standalone.percentage_change | |
| except Exception as e: | |
| print(f"Warning: Could not import from standalone utils.py: {e}") | |
| # Provide dummy implementations to prevent errors | |
| def format_number(num, decimals=2): | |
| return str(num) | |
| def calculate_moving_average(prices, period): | |
| return None | |
| def calculate_rsi(prices, period=14): | |
| return None | |
| def extract_coins_from_text(text): | |
| return [] | |
| def export_to_csv(data, filename): | |
| return False | |
| def validate_price_data(price_data): | |
| return True | |
| def is_data_stale(timestamp_str, max_age_minutes=30): | |
| return False | |
| def cache_with_ttl(ttl_seconds=300): | |
| def decorator(func): | |
| return func | |
| return decorator | |
| def safe_float(value, default=0.0): | |
| return default | |
| def safe_int(value, default=0): | |
| return default | |
| def truncate_string(text, max_length=100, suffix="..."): | |
| return text | |
| def percentage_change(old_value, new_value): | |
| return None | |
| __all__ = [ | |
| 'setup_logging', | |
| 'setup_logger', | |
| 'format_number', | |
| 'calculate_moving_average', | |
| 'calculate_rsi', | |
| 'extract_coins_from_text', | |
| 'export_to_csv', | |
| 'validate_price_data', | |
| 'is_data_stale', | |
| 'cache_with_ttl', | |
| 'safe_float', | |
| 'safe_int', | |
| 'truncate_string', | |
| 'percentage_change', | |
| ] | |