Spaces:
Building
Building
File size: 7,161 Bytes
1e4a027 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
"""
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
|