remove old import

This commit is contained in:
HotSwapp
2025-08-14 21:27:34 -05:00
parent bfc04a6909
commit 679ab4446a
17 changed files with 2016 additions and 557 deletions

246
app/utils/exceptions.py Normal file
View File

@@ -0,0 +1,246 @@
"""
Centralized exception handling utilities for consistent error management across the application.
"""
from typing import Dict, Any, Optional, Type, Union, Callable
from functools import wraps
import logging
from fastapi import HTTPException, status
from sqlalchemy.exc import SQLAlchemyError, IntegrityError, DataError
from pydantic import ValidationError
import traceback
logger = logging.getLogger(__name__)
class DatabaseError(Exception):
"""Custom exception for database-related errors"""
pass
class BusinessLogicError(Exception):
"""Custom exception for business logic violations"""
pass
class SecurityError(Exception):
"""Custom exception for security-related errors"""
pass
class APIError(HTTPException):
"""Enhanced HTTP exception with additional context"""
def __init__(
self,
status_code: int,
detail: str,
error_code: str = None,
context: Dict[str, Any] = None
):
super().__init__(status_code=status_code, detail=detail)
self.error_code = error_code
self.context = context or {}
def handle_database_errors(func: Callable) -> Callable:
"""
Decorator to handle common database errors with consistent responses.
"""
@wraps(func)
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except IntegrityError as e:
logger.error(f"Database integrity error in {func.__name__}: {str(e)}")
raise APIError(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Data integrity constraint violation",
error_code="INTEGRITY_ERROR",
context={"function": func.__name__}
)
except DataError as e:
logger.error(f"Database data error in {func.__name__}: {str(e)}")
raise APIError(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Invalid data format or type",
error_code="DATA_ERROR",
context={"function": func.__name__}
)
except SQLAlchemyError as e:
logger.error(f"Database error in {func.__name__}: {str(e)}")
raise APIError(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Database operation failed",
error_code="DATABASE_ERROR",
context={"function": func.__name__}
)
except Exception as e:
logger.error(f"Unexpected error in {func.__name__}: {str(e)}", exc_info=True)
raise APIError(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="An unexpected error occurred",
error_code="INTERNAL_ERROR",
context={"function": func.__name__}
)
return wrapper
def handle_validation_errors(func: Callable) -> Callable:
"""
Decorator to handle validation errors with consistent responses.
"""
@wraps(func)
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except ValidationError as e:
logger.warning(f"Validation error in {func.__name__}: {str(e)}")
raise APIError(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
detail="Validation failed",
error_code="VALIDATION_ERROR",
context={
"function": func.__name__,
"validation_errors": e.errors()
}
)
except ValueError as e:
logger.warning(f"Value error in {func.__name__}: {str(e)}")
raise APIError(
status_code=status.HTTP_400_BAD_REQUEST,
detail=str(e),
error_code="VALUE_ERROR",
context={"function": func.__name__}
)
return wrapper
def handle_security_errors(func: Callable) -> Callable:
"""
Decorator to handle security-related errors.
"""
@wraps(func)
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except SecurityError as e:
logger.warning(f"Security error in {func.__name__}: {str(e)}")
raise APIError(
status_code=status.HTTP_403_FORBIDDEN,
detail="Access denied",
error_code="SECURITY_ERROR",
context={"function": func.__name__}
)
except PermissionError as e:
logger.warning(f"Permission error in {func.__name__}: {str(e)}")
raise APIError(
status_code=status.HTTP_403_FORBIDDEN,
detail="Insufficient permissions",
error_code="PERMISSION_ERROR",
context={"function": func.__name__}
)
return wrapper
def safe_execute(
operation: Callable,
default_return: Any = None,
log_errors: bool = True,
raise_on_error: bool = False,
error_message: str = "Operation failed"
) -> Any:
"""
Safely execute an operation with optional error handling.
Args:
operation: Function to execute
default_return: Value to return if operation fails
log_errors: Whether to log errors
raise_on_error: Whether to re-raise exceptions
error_message: Custom error message for logging
Returns:
Result of operation or default_return on failure
"""
try:
return operation()
except Exception as e:
if log_errors:
logger.error(f"{error_message}: {str(e)}", exc_info=True)
if raise_on_error:
raise
return default_return
def create_error_response(
error: Exception,
status_code: int = status.HTTP_500_INTERNAL_SERVER_ERROR,
error_code: str = "INTERNAL_ERROR",
include_traceback: bool = False
) -> Dict[str, Any]:
"""
Create a standardized error response.
Args:
error: The exception that occurred
status_code: HTTP status code
error_code: Application-specific error code
include_traceback: Whether to include traceback (dev only)
Returns:
Standardized error response dictionary
"""
response = {
"error": {
"code": error_code,
"message": str(error),
"type": type(error).__name__
}
}
if include_traceback:
response["error"]["traceback"] = traceback.format_exc()
return response
class ErrorContext:
"""Context manager for handling errors in a specific scope."""
def __init__(
self,
operation_name: str,
default_return: Any = None,
log_errors: bool = True,
suppress_errors: bool = False
):
self.operation_name = operation_name
self.default_return = default_return
self.log_errors = log_errors
self.suppress_errors = suppress_errors
self.error = None
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type is not None:
self.error = exc_val
if self.log_errors:
logger.error(
f"Error in {self.operation_name}: {str(exc_val)}",
exc_info=True
)
return self.suppress_errors
return False
def get_result(self, success_value: Any = None) -> Any:
"""Get the result based on whether an error occurred."""
if self.error is not None:
return self.default_return
return success_value