Spaces:
Sleeping
Sleeping
| """ | |
| Custom Exception Classes | |
| Provides a structured exception hierarchy for the Farm Help API. | |
| All custom exceptions derive from a single base class so that the | |
| global error handler can distinguish application-level errors from | |
| unexpected failures. | |
| """ | |
| from typing import Any, Dict, Optional | |
| class AppException(Exception): | |
| """ | |
| Base exception for all application-level errors. | |
| Attributes: | |
| status_code: HTTP status code to return. | |
| error_code: Machine-readable error identifier (e.g. "DISEASE_NOT_FOUND"). | |
| message: Human-readable error description. | |
| detail: Optional additional context. | |
| """ | |
| def __init__( | |
| self, | |
| status_code: int = 500, | |
| error_code: str = "INTERNAL_ERROR", | |
| message: str = "An unexpected error occurred.", | |
| detail: Optional[str] = None, | |
| ) -> None: | |
| self.status_code = status_code | |
| self.error_code = error_code | |
| self.message = message | |
| self.detail = detail | |
| super().__init__(message) | |
| def to_dict(self) -> Dict[str, Any]: | |
| payload: Dict[str, Any] = { | |
| "error_code": self.error_code, | |
| "message": self.message, | |
| "status_code": self.status_code, | |
| } | |
| if self.detail: | |
| payload["detail"] = self.detail | |
| return payload | |
| class NotFoundError(AppException): | |
| """Resource not found (HTTP 404).""" | |
| def __init__( | |
| self, | |
| message: str = "Requested resource not found.", | |
| detail: Optional[str] = None, | |
| error_code: str = "NOT_FOUND", | |
| ) -> None: | |
| super().__init__( | |
| status_code=404, | |
| error_code=error_code, | |
| message=message, | |
| detail=detail, | |
| ) | |
| class ValidationError(AppException): | |
| """Input validation failure (HTTP 422).""" | |
| def __init__( | |
| self, | |
| message: str = "Input validation failed.", | |
| detail: Optional[str] = None, | |
| error_code: str = "VALIDATION_ERROR", | |
| ) -> None: | |
| super().__init__( | |
| status_code=422, | |
| error_code=error_code, | |
| message=message, | |
| detail=detail, | |
| ) | |
| class ExternalAPIError(AppException): | |
| """External API call failure (HTTP 503).""" | |
| def __init__( | |
| self, | |
| message: str = "External service is temporarily unavailable.", | |
| detail: Optional[str] = None, | |
| error_code: str = "EXTERNAL_API_ERROR", | |
| ) -> None: | |
| super().__init__( | |
| status_code=503, | |
| error_code=error_code, | |
| message=message, | |
| detail=detail, | |
| ) | |
| class RateLimitError(AppException): | |
| """Rate limit exceeded (HTTP 429).""" | |
| def __init__( | |
| self, | |
| message: str = "Too many requests. Please try again later.", | |
| detail: Optional[str] = None, | |
| error_code: str = "RATE_LIMIT_EXCEEDED", | |
| ) -> None: | |
| super().__init__( | |
| status_code=429, | |
| error_code=error_code, | |
| message=message, | |
| detail=detail, | |
| ) | |
| class DatabaseError(AppException): | |
| """Database operation failure (HTTP 500).""" | |
| def __init__( | |
| self, | |
| message: str = "A database error occurred.", | |
| detail: Optional[str] = None, | |
| error_code: str = "DATABASE_ERROR", | |
| ) -> None: | |
| super().__init__( | |
| status_code=500, | |
| error_code=error_code, | |
| message=message, | |
| detail=detail, | |
| ) | |