""" HCFS SDK Exception Classes Comprehensive exception hierarchy for error handling. """ from typing import Optional, Dict, Any class HCFSError(Exception): """Base exception for all HCFS SDK errors.""" def __init__(self, message: str, error_code: Optional[str] = None, details: Optional[Dict[str, Any]] = None): super().__init__(message) self.message = message self.error_code = error_code self.details = details or {} def __str__(self) -> str: if self.error_code: return f"[{self.error_code}] {self.message}" return self.message def to_dict(self) -> Dict[str, Any]: """Convert exception to dictionary for serialization.""" return { "type": self.__class__.__name__, "message": self.message, "error_code": self.error_code, "details": self.details } class HCFSConnectionError(HCFSError): """Raised when connection to HCFS API fails.""" def __init__(self, message: str = "Failed to connect to HCFS API", **kwargs): super().__init__(message, error_code="CONNECTION_FAILED", **kwargs) class HCFSAuthenticationError(HCFSError): """Raised when authentication fails.""" def __init__(self, message: str = "Authentication failed", **kwargs): super().__init__(message, error_code="AUTH_FAILED", **kwargs) class HCFSAuthorizationError(HCFSError): """Raised when user lacks permissions for an operation.""" def __init__(self, message: str = "Insufficient permissions", **kwargs): super().__init__(message, error_code="INSUFFICIENT_PERMISSIONS", **kwargs) class HCFSNotFoundError(HCFSError): """Raised when a requested resource is not found.""" def __init__(self, resource_type: str = "Resource", resource_id: str = "", **kwargs): message = f"{resource_type} not found" if resource_id: message += f": {resource_id}" super().__init__(message, error_code="NOT_FOUND", **kwargs) class HCFSValidationError(HCFSError): """Raised when request validation fails.""" def __init__(self, message: str = "Request validation failed", validation_errors: Optional[list] = None, **kwargs): super().__init__(message, error_code="VALIDATION_FAILED", **kwargs) self.validation_errors = validation_errors or [] def to_dict(self) -> Dict[str, Any]: result = super().to_dict() result["validation_errors"] = self.validation_errors return result class HCFSRateLimitError(HCFSError): """Raised when rate limit is exceeded.""" def __init__(self, retry_after: Optional[int] = None, **kwargs): message = "Rate limit exceeded" if retry_after: message += f". Retry after {retry_after} seconds" super().__init__(message, error_code="RATE_LIMIT_EXCEEDED", **kwargs) self.retry_after = retry_after class HCFSServerError(HCFSError): """Raised for server-side errors (5xx status codes).""" def __init__(self, message: str = "Internal server error", status_code: Optional[int] = None, **kwargs): super().__init__(message, error_code="SERVER_ERROR", **kwargs) self.status_code = status_code class HCFSTimeoutError(HCFSError): """Raised when a request times out.""" def __init__(self, operation: str = "Request", timeout_seconds: Optional[float] = None, **kwargs): message = f"{operation} timed out" if timeout_seconds: message += f" after {timeout_seconds}s" super().__init__(message, error_code="TIMEOUT", **kwargs) self.timeout_seconds = timeout_seconds class HCFSCacheError(HCFSError): """Raised for cache-related errors.""" def __init__(self, message: str = "Cache operation failed", **kwargs): super().__init__(message, error_code="CACHE_ERROR", **kwargs) class HCFSBatchError(HCFSError): """Raised for batch operation errors.""" def __init__(self, message: str = "Batch operation failed", failed_items: Optional[list] = None, **kwargs): super().__init__(message, error_code="BATCH_ERROR", **kwargs) self.failed_items = failed_items or [] def to_dict(self) -> Dict[str, Any]: result = super().to_dict() result["failed_items"] = self.failed_items return result class HCFSStreamError(HCFSError): """Raised for streaming/WebSocket errors.""" def __init__(self, message: str = "Stream operation failed", **kwargs): super().__init__(message, error_code="STREAM_ERROR", **kwargs) class HCFSSearchError(HCFSError): """Raised for search operation errors.""" def __init__(self, query: str = "", search_type: str = "", **kwargs): message = f"Search failed" if search_type: message += f" ({search_type})" if query: message += f": '{query}'" super().__init__(message, error_code="SEARCH_ERROR", **kwargs) self.query = query self.search_type = search_type def handle_api_error(response) -> None: """ Convert HTTP response errors to appropriate HCFS exceptions. Args: response: HTTP response object Raises: Appropriate HCFSError subclass based on status code """ status_code = response.status_code try: error_data = response.json() if response.content else {} except Exception: error_data = {} error_message = error_data.get("error", "Unknown error") error_details = error_data.get("error_details", []) if status_code == 400: raise HCFSValidationError(error_message, validation_errors=error_details) elif status_code == 401: raise HCFSAuthenticationError(error_message) elif status_code == 403: raise HCFSAuthorizationError(error_message) elif status_code == 404: raise HCFSNotFoundError("Resource", error_message) elif status_code == 429: retry_after = response.headers.get("Retry-After") retry_after = int(retry_after) if retry_after else None raise HCFSRateLimitError(retry_after=retry_after) elif 500 <= status_code < 600: raise HCFSServerError(error_message, status_code=status_code) else: raise HCFSError(f"HTTP {status_code}: {error_message}")