Spaces:
Building
Building
""" | |
Custom Exception Classes for Flare Platform | |
""" | |
from typing import Optional, Dict, Any | |
from datetime import datetime | |
class FlareException(Exception): | |
"""Base exception for Flare""" | |
def __init__(self, message: str, details: Optional[Dict[str, Any]] = None): | |
self.message = message | |
self.details = details or {} | |
self.timestamp = datetime.utcnow() | |
super().__init__(self.message) | |
def to_dict(self) -> Dict[str, Any]: | |
"""Convert exception to dictionary""" | |
return { | |
"error": self.__class__.__name__, | |
"message": self.message, | |
"details": self.details, | |
"timestamp": self.timestamp.isoformat() | |
} | |
def to_http_detail(self) -> Dict[str, Any]: | |
"""Convert to HTTP response detail""" | |
return { | |
"detail": self.message, | |
"error_type": self.__class__.__name__.lower().replace('error', ''), | |
**self.details | |
} | |
class RaceConditionError(FlareException): | |
"""Raised when a race condition is detected during concurrent updates""" | |
def __init__( | |
self, | |
message: str, | |
current_user: Optional[str] = None, | |
last_update_user: Optional[str] = None, | |
last_update_date: Optional[str] = None, | |
entity_type: Optional[str] = None, | |
entity_id: Optional[Any] = None | |
): | |
details = { | |
"current_user": current_user, | |
"last_update_user": last_update_user, | |
"last_update_date": last_update_date, | |
"entity_type": entity_type, | |
"entity_id": entity_id, | |
"action": "Please reload the data and try again" | |
} | |
super().__init__(message, details) | |
self.current_user = current_user | |
self.last_update_user = last_update_user | |
self.last_update_date = last_update_date | |
def to_http_detail(self) -> Dict[str, Any]: | |
"""Convert to HTTPException detail format with proper serialization""" | |
return { | |
"message": self.message, | |
"last_update_user": self.last_update_user, | |
"last_update_date": self.last_update_date.isoformat() if isinstance(self.last_update_date, datetime) else self.last_update_date, | |
"type": "race_condition" | |
} | |
class ConfigurationError(FlareException): | |
"""Raised when there's a configuration issue""" | |
def __init__(self, message: str, config_key: Optional[str] = None): | |
details = {"config_key": config_key} if config_key else {} | |
super().__init__(message, details) | |
class ValidationError(FlareException): | |
"""Raised when validation fails""" | |
def __init__(self, message: str, field: Optional[str] = None, value: Any = None): | |
details = {} | |
if field: | |
details["field"] = field | |
if value is not None: | |
details["value"] = str(value) | |
super().__init__(message, details) | |
class AuthenticationError(FlareException): | |
"""Raised when authentication fails""" | |
def __init__(self, message: str = "Authentication failed"): | |
super().__init__(message) | |
class AuthorizationError(FlareException): | |
"""Raised when authorization fails""" | |
def __init__(self, message: str = "Insufficient permissions", required_permission: Optional[str] = None): | |
details = {"required_permission": required_permission} if required_permission else {} | |
super().__init__(message, details) | |
class SessionError(FlareException): | |
"""Raised when there's a session-related error""" | |
def __init__(self, message: str, session_id: Optional[str] = None): | |
details = {"session_id": session_id} if session_id else {} | |
super().__init__(message, details) | |
class ProviderError(FlareException): | |
"""Raised when a provider (LLM, TTS, STT) fails""" | |
def __init__(self, message: str, provider_type: str, provider_name: str, original_error: Optional[str] = None): | |
details = { | |
"provider_type": provider_type, | |
"provider_name": provider_name, | |
"original_error": original_error | |
} | |
super().__init__(message, details) | |
class APICallError(FlareException): | |
"""Raised when an external API call fails""" | |
def __init__( | |
self, | |
message: str, | |
api_name: str, | |
status_code: Optional[int] = None, | |
response_body: Optional[str] = None | |
): | |
details = { | |
"api_name": api_name, | |
"status_code": status_code, | |
"response_body": response_body | |
} | |
super().__init__(message, details) | |
class WebSocketError(FlareException): | |
"""Raised when WebSocket operations fail""" | |
def __init__(self, message: str, session_id: Optional[str] = None, state: Optional[str] = None): | |
details = { | |
"session_id": session_id, | |
"state": state | |
} | |
super().__init__(message, details) | |
class ResourceNotFoundError(FlareException): | |
"""Raised when a requested resource is not found""" | |
def __init__(self, resource_type: str, resource_id: Any): | |
message = f"{resource_type} not found: {resource_id}" | |
details = { | |
"resource_type": resource_type, | |
"resource_id": str(resource_id) | |
} | |
super().__init__(message, details) | |
class DuplicateResourceError(FlareException): | |
"""Raised when attempting to create a duplicate resource""" | |
def __init__(self, resource_type: str, identifier: str): | |
message = f"{resource_type} already exists: {identifier}" | |
details = { | |
"resource_type": resource_type, | |
"identifier": identifier | |
} | |
super().__init__(message, details) | |
# Error response formatters | |
def format_error_response(error: Exception, request_id: Optional[str] = None) -> Dict[str, Any]: | |
"""Format any exception into a standardized error response""" | |
if isinstance(error, FlareException): | |
response = error.to_dict() | |
else: | |
# Generic error | |
response = { | |
"error": error.__class__.__name__, | |
"message": str(error), | |
"details": {}, | |
"timestamp": datetime.utcnow().isoformat() | |
} | |
if request_id: | |
response["request_id"] = request_id | |
return response | |
def get_http_status_code(error: Exception) -> int: | |
"""Get appropriate HTTP status code for an exception""" | |
status_map = { | |
ValidationError: 422, | |
AuthenticationError: 401, | |
AuthorizationError: 403, | |
ResourceNotFoundError: 404, | |
DuplicateResourceError: 409, | |
RaceConditionError: 409, | |
ConfigurationError: 500, | |
ProviderError: 503, | |
APICallError: 502, | |
WebSocketError: 500, | |
SessionError: 400 | |
} | |
for error_class, status_code in status_map.items(): | |
if isinstance(error, error_class): | |
return status_code | |
# Default to 500 for unknown errors | |
return 500 | |