""" Error handling utilities """ from typing import Optional, Dict, Any import traceback from utils.logger import logger class ProcessingError(Exception): """Base exception for processing errors""" pass class DataValidationError(ProcessingError): """Raised when data validation fails""" pass class DatabaseError(ProcessingError): """Raised when database operations fail""" pass def handle_processing_error( error: Exception, context: Optional[Dict[str, Any]] = None, raise_error: bool = True ) -> Optional[Dict[str, Any]]: """ Handle processing errors with logging and optional error response Args: error: The exception that occurred context: Additional context about where the error occurred raise_error: Whether to re-raise the error Returns: Error response dict if not raising, None otherwise """ error_info = { 'error_type': type(error).__name__, 'error_message': str(error), 'context': context or {} } # Log the error logger.error( f"Processing error: {error_info['error_type']} - {error_info['error_message']}", extra={'context': context, 'traceback': traceback.format_exc()} ) if raise_error: raise error return error_info def validate_dataframe(df, required_columns: list, operation: str = "operation"): """Validate DataFrame has required columns""" if df is None or df.empty: raise DataValidationError(f"DataFrame is empty for {operation}") missing_columns = [col for col in required_columns if col not in df.columns] if missing_columns: raise DataValidationError( f"Missing required columns for {operation}: {missing_columns}" ) def safe_divide(numerator, denominator, default=0.0): """Safely divide two numbers, returning default if denominator is zero or None""" if denominator is None or denominator == 0: return default try: return numerator / denominator except (TypeError, ZeroDivisionError): return default