File size: 3,485 Bytes
b64de39
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""
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,
        )