fastapi-errors-plus 0.1.0__py3-none-any.whl → 0.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fastapi_errors_plus/__init__.py +8 -2
- fastapi_errors_plus/base.py +122 -0
- fastapi_errors_plus/errors.py +39 -9
- fastapi_errors_plus/protocol.py +1 -0
- {fastapi_errors_plus-0.1.0.dist-info → fastapi_errors_plus-0.4.0.dist-info}/METADATA +166 -18
- fastapi_errors_plus-0.4.0.dist-info/RECORD +9 -0
- {fastapi_errors_plus-0.1.0.dist-info → fastapi_errors_plus-0.4.0.dist-info}/licenses/LICENSE +1 -0
- fastapi_errors_plus-0.1.0.dist-info/RECORD +0 -8
- {fastapi_errors_plus-0.1.0.dist-info → fastapi_errors_plus-0.4.0.dist-info}/WHEEL +0 -0
- {fastapi_errors_plus-0.1.0.dist-info → fastapi_errors_plus-0.4.0.dist-info}/top_level.txt +0 -0
fastapi_errors_plus/__init__.py
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
"""Universal library for documenting errors in FastAPI endpoints."""
|
|
2
2
|
|
|
3
|
+
from fastapi_errors_plus.base import BaseErrorDTO, StandardErrorDTO
|
|
3
4
|
from fastapi_errors_plus.errors import Errors
|
|
4
5
|
from fastapi_errors_plus.protocol import ErrorDTO
|
|
5
6
|
|
|
6
|
-
__all__ = [
|
|
7
|
-
|
|
7
|
+
__all__ = [
|
|
8
|
+
"Errors",
|
|
9
|
+
"ErrorDTO", # Protocol (for structural typing)
|
|
10
|
+
"BaseErrorDTO", # Base implementation (optional)
|
|
11
|
+
"StandardErrorDTO", # Extended implementation (optional)
|
|
12
|
+
]
|
|
13
|
+
__version__ = "0.4.0"
|
|
8
14
|
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"""Base implementations of ErrorDTO protocol for convenience."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from typing import Any, Dict, Optional
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass
|
|
8
|
+
class BaseErrorDTO:
|
|
9
|
+
"""Base implementation of ErrorDTO Protocol.
|
|
10
|
+
|
|
11
|
+
Projects can use this class directly or create their own implementation
|
|
12
|
+
that implements ErrorDTO Protocol through structural typing.
|
|
13
|
+
|
|
14
|
+
This class provides a simple way to create error DTOs without writing
|
|
15
|
+
boilerplate code in every project.
|
|
16
|
+
|
|
17
|
+
Example:
|
|
18
|
+
```python
|
|
19
|
+
from fastapi_errors_plus import Errors, BaseErrorDTO
|
|
20
|
+
|
|
21
|
+
notification_error = BaseErrorDTO(
|
|
22
|
+
status_code=404,
|
|
23
|
+
message="Notification not found",
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
@router.delete(
|
|
27
|
+
"/{id}",
|
|
28
|
+
responses=Errors(notification_error),
|
|
29
|
+
)
|
|
30
|
+
def delete_item(id: int):
|
|
31
|
+
pass
|
|
32
|
+
```
|
|
33
|
+
"""
|
|
34
|
+
status_code: int
|
|
35
|
+
"""HTTP status code for the error."""
|
|
36
|
+
|
|
37
|
+
message: str
|
|
38
|
+
"""Error message description."""
|
|
39
|
+
|
|
40
|
+
def to_example(self) -> Dict[str, Any]:
|
|
41
|
+
"""Generate example for OpenAPI.
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
Dict in format: {"key": {"value": {"detail": "message"}}}
|
|
45
|
+
|
|
46
|
+
Example:
|
|
47
|
+
```python
|
|
48
|
+
{
|
|
49
|
+
"Notification not found": {
|
|
50
|
+
"value": {"detail": "Notification not found"},
|
|
51
|
+
},
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
"""
|
|
55
|
+
return {
|
|
56
|
+
self.message: {
|
|
57
|
+
"value": {"detail": self.message},
|
|
58
|
+
},
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@dataclass
|
|
63
|
+
class StandardErrorDTO(BaseErrorDTO):
|
|
64
|
+
"""Extended implementation for errors with multiple examples.
|
|
65
|
+
|
|
66
|
+
Useful for standard HTTP errors (401, 403) that can have different
|
|
67
|
+
causes with different messages.
|
|
68
|
+
|
|
69
|
+
Example:
|
|
70
|
+
```python
|
|
71
|
+
from fastapi_errors_plus import Errors, StandardErrorDTO
|
|
72
|
+
|
|
73
|
+
unauthorized_error = StandardErrorDTO(
|
|
74
|
+
status_code=401,
|
|
75
|
+
message="Unauthorized",
|
|
76
|
+
examples={
|
|
77
|
+
"InvalidToken": "Ошибка декодирования токена.",
|
|
78
|
+
"SessionNotFound": "Сессия пользователя не была найдена.",
|
|
79
|
+
},
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
@router.delete(
|
|
83
|
+
"/{id}",
|
|
84
|
+
responses=Errors(unauthorized_error),
|
|
85
|
+
)
|
|
86
|
+
def delete_item(id: int):
|
|
87
|
+
pass
|
|
88
|
+
```
|
|
89
|
+
"""
|
|
90
|
+
examples: Optional[Dict[str, str]] = field(default=None)
|
|
91
|
+
"""Dictionary of examples: {"key": "message"}."""
|
|
92
|
+
|
|
93
|
+
def __post_init__(self) -> None:
|
|
94
|
+
"""Initialize examples with default value if not provided."""
|
|
95
|
+
if self.examples is None:
|
|
96
|
+
self.examples = {self.message: self.message}
|
|
97
|
+
|
|
98
|
+
def to_example(self) -> Dict[str, Any]:
|
|
99
|
+
"""Generate examples for OpenAPI with multiple examples.
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
Dict in format: {"key": {"value": {"detail": "message"}}, ...}
|
|
103
|
+
|
|
104
|
+
Example:
|
|
105
|
+
```python
|
|
106
|
+
{
|
|
107
|
+
"InvalidToken": {
|
|
108
|
+
"value": {"detail": "Ошибка декодирования токена."},
|
|
109
|
+
},
|
|
110
|
+
"SessionNotFound": {
|
|
111
|
+
"value": {"detail": "Сессия пользователя не была найдена."},
|
|
112
|
+
},
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
"""
|
|
116
|
+
return {
|
|
117
|
+
key: {
|
|
118
|
+
"value": {"detail": message},
|
|
119
|
+
}
|
|
120
|
+
for key, message in self.examples.items()
|
|
121
|
+
}
|
|
122
|
+
|
fastapi_errors_plus/errors.py
CHANGED
|
@@ -29,9 +29,9 @@ class Errors(Mapping):
|
|
|
29
29
|
@router.delete(
|
|
30
30
|
"/{id}",
|
|
31
31
|
responses=Errors(
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
unauthorized_401=True, # 401 (explicit)
|
|
33
|
+
forbidden_403=True, # 403 (explicit)
|
|
34
|
+
validation_error_422=True, # 422 (explicit)
|
|
35
35
|
{404: { # 404 via dict
|
|
36
36
|
"description": "Not found",
|
|
37
37
|
"content": {
|
|
@@ -52,10 +52,16 @@ class Errors(Mapping):
|
|
|
52
52
|
# Arbitrary errors (dict or ErrorDTO) - must come first
|
|
53
53
|
*errors: Union[Dict[int, Dict[str, Any]], ErrorDTO],
|
|
54
54
|
# Standard HTTP statuses (boolean flags)
|
|
55
|
+
# Old parameters (for backward compatibility)
|
|
55
56
|
unauthorized: bool = False, # 401
|
|
56
57
|
forbidden: bool = False, # 403
|
|
57
|
-
validation_error: bool =
|
|
58
|
+
validation_error: bool = None, # 422 (None = use default True, False = disable, True = enable)
|
|
58
59
|
internal_server_error: bool = False, # 500
|
|
60
|
+
# New parameters with explicit status codes (recommended)
|
|
61
|
+
unauthorized_401: bool = False, # 401 (explicit)
|
|
62
|
+
forbidden_403: bool = False, # 403 (explicit)
|
|
63
|
+
validation_error_422: bool = None, # 422 (explicit, None = use default True, False = disable, True = enable)
|
|
64
|
+
internal_server_error_500: bool = False, # 500 (explicit)
|
|
59
65
|
) -> None:
|
|
60
66
|
"""Initialize Errors instance.
|
|
61
67
|
|
|
@@ -64,9 +70,21 @@ class Errors(Mapping):
|
|
|
64
70
|
Dict should be in FastAPI responses format: {status_code: {...}}.
|
|
65
71
|
ErrorDTO objects must implement the ErrorDTO protocol.
|
|
66
72
|
unauthorized: Add 401 Unauthorized error. Defaults to False.
|
|
73
|
+
Deprecated: Use `unauthorized_401` instead for explicit status code.
|
|
67
74
|
forbidden: Add 403 Forbidden error. Defaults to False.
|
|
68
|
-
|
|
75
|
+
Deprecated: Use `forbidden_403` instead for explicit status code.
|
|
76
|
+
validation_error: Add 422 Unprocessable Entity error. Defaults to True (None means True).
|
|
77
|
+
FastAPI automatically validates all parameters (Path, Query, Body), so 422 is relevant
|
|
78
|
+
in 95%+ of endpoints. Set to False only for endpoints without parameters.
|
|
79
|
+
Deprecated: Use `validation_error_422` instead for explicit status code.
|
|
69
80
|
internal_server_error: Add 500 Internal Server Error. Defaults to False.
|
|
81
|
+
Deprecated: Use `internal_server_error_500` instead for explicit status code.
|
|
82
|
+
unauthorized_401: Add 401 Unauthorized error (explicit). Defaults to False.
|
|
83
|
+
forbidden_403: Add 403 Forbidden error (explicit). Defaults to False.
|
|
84
|
+
validation_error_422: Add 422 Unprocessable Entity error (explicit). Defaults to True (None means True).
|
|
85
|
+
FastAPI automatically validates all parameters (Path, Query, Body), so 422 is relevant
|
|
86
|
+
in 95%+ of endpoints. Set to False only for endpoints without parameters.
|
|
87
|
+
internal_server_error_500: Add 500 Internal Server Error (explicit). Defaults to False.
|
|
70
88
|
|
|
71
89
|
Example:
|
|
72
90
|
```python
|
|
@@ -90,25 +108,37 @@ class Errors(Mapping):
|
|
|
90
108
|
self._responses: Dict[int, Dict[str, Any]] = {}
|
|
91
109
|
|
|
92
110
|
# Add standard errors
|
|
93
|
-
|
|
111
|
+
# New parameters with explicit codes have priority, but old ones still work
|
|
112
|
+
if unauthorized_401 or unauthorized:
|
|
94
113
|
self._add_standard_error(
|
|
95
114
|
status.HTTP_401_UNAUTHORIZED,
|
|
96
115
|
"Unauthorized",
|
|
97
116
|
{"detail": "Unauthorized"},
|
|
98
117
|
)
|
|
99
|
-
if forbidden:
|
|
118
|
+
if forbidden_403 or forbidden:
|
|
100
119
|
self._add_standard_error(
|
|
101
120
|
status.HTTP_403_FORBIDDEN,
|
|
102
121
|
"Forbidden",
|
|
103
122
|
{"detail": "Forbidden"},
|
|
104
123
|
)
|
|
105
|
-
|
|
124
|
+
# For validation_error: True by default (FastAPI validates all parameters)
|
|
125
|
+
# Add 422 unless at least one parameter is explicitly False
|
|
126
|
+
# If user sets validation_error=False, they want to disable 422 (even if validation_error_422 defaults to True)
|
|
127
|
+
# If user sets validation_error_422=False, they want to disable 422 (even if validation_error defaults to True)
|
|
128
|
+
# Only if both are explicitly False, we definitely don't add
|
|
129
|
+
# If at least one is True (or None which defaults to True) and neither is explicitly False, add
|
|
130
|
+
add_422 = True # Default is True
|
|
131
|
+
if validation_error is False or validation_error_422 is False:
|
|
132
|
+
# At least one is explicitly False - don't add
|
|
133
|
+
add_422 = False
|
|
134
|
+
|
|
135
|
+
if add_422:
|
|
106
136
|
self._add_standard_error(
|
|
107
137
|
status.HTTP_422_UNPROCESSABLE_ENTITY,
|
|
108
138
|
"Validation Error",
|
|
109
139
|
{"detail": "Validation error"},
|
|
110
140
|
)
|
|
111
|
-
if internal_server_error:
|
|
141
|
+
if internal_server_error_500 or internal_server_error:
|
|
112
142
|
self._add_standard_error(
|
|
113
143
|
status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
114
144
|
"Internal Server Error",
|
fastapi_errors_plus/protocol.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fastapi-errors-plus
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Universal library for documenting errors in FastAPI endpoints
|
|
5
5
|
Author-email: Igor Selivanov <seligoroff@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -30,8 +30,8 @@ Dynamic: license-file
|
|
|
30
30
|
[](https://opensource.org/licenses/MIT)
|
|
31
31
|
[](https://www.python.org/downloads/)
|
|
32
32
|
[](https://fastapi.tiangolo.com/)
|
|
33
|
-
[](https://github.com/
|
|
33
|
+
[](https://github.com/seligoroff/fastapi-errors-plus)
|
|
34
|
+
[](https://github.com/seligoroff/fastapi-errors-plus)
|
|
35
35
|
|
|
36
36
|
Universal library for documenting errors in FastAPI endpoints.
|
|
37
37
|
|
|
@@ -56,7 +56,7 @@ pip install fastapi-errors-plus
|
|
|
56
56
|
Or install from source:
|
|
57
57
|
|
|
58
58
|
```bash
|
|
59
|
-
git clone
|
|
59
|
+
git clone git@github.com:seligoroff/fastapi-errors-plus.git
|
|
60
60
|
cd fastapi-errors-plus
|
|
61
61
|
pip install -e .
|
|
62
62
|
```
|
|
@@ -82,9 +82,9 @@ router = APIRouter()
|
|
|
82
82
|
},
|
|
83
83
|
},
|
|
84
84
|
}},
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
85
|
+
unauthorized_401=True, # 401 Unauthorized (explicit)
|
|
86
|
+
forbidden_403=True, # 403 Forbidden (explicit)
|
|
87
|
+
# validation_error_422=True - not needed, defaults to True
|
|
88
88
|
),
|
|
89
89
|
)
|
|
90
90
|
def delete_item(id: int):
|
|
@@ -99,17 +99,26 @@ def delete_item(id: int):
|
|
|
99
99
|
|
|
100
100
|
Use boolean flags for common HTTP status codes:
|
|
101
101
|
|
|
102
|
+
**Recommended (explicit status codes):**
|
|
103
|
+
- `unauthorized_401=True` → 401 Unauthorized
|
|
104
|
+
- `forbidden_403=True` → 403 Forbidden
|
|
105
|
+
- `validation_error_422=True` → 422 Unprocessable Entity (defaults to `True`)
|
|
106
|
+
- `internal_server_error_500=True` → 500 Internal Server Error
|
|
107
|
+
|
|
108
|
+
**Legacy (for backward compatibility):**
|
|
102
109
|
- `unauthorized=True` → 401 Unauthorized
|
|
103
110
|
- `forbidden=True` → 403 Forbidden
|
|
104
|
-
- `validation_error=True` → 422 Unprocessable Entity
|
|
111
|
+
- `validation_error=True` → 422 Unprocessable Entity (defaults to `True`)
|
|
105
112
|
- `internal_server_error=True` → 500 Internal Server Error
|
|
106
113
|
|
|
114
|
+
**Note:** `validation_error` and `validation_error_422` default to `True` because FastAPI automatically validates all parameters (Path, Query, Body), making 422 relevant in 95%+ of endpoints. Set to `False` only for endpoints without parameters.
|
|
115
|
+
|
|
107
116
|
```python
|
|
108
117
|
@router.get(
|
|
109
118
|
"/protected",
|
|
110
119
|
responses=Errors(
|
|
111
|
-
|
|
112
|
-
|
|
120
|
+
unauthorized_401=True, # Explicit: 401 is visible
|
|
121
|
+
forbidden_403=True, # Explicit: 403 is visible
|
|
113
122
|
),
|
|
114
123
|
)
|
|
115
124
|
def get_protected():
|
|
@@ -117,6 +126,8 @@ def get_protected():
|
|
|
117
126
|
pass
|
|
118
127
|
```
|
|
119
128
|
|
|
129
|
+
**Why explicit flags?** The new flags with status codes (`_401`, `_403`, etc.) make it immediately clear which HTTP status code corresponds to each flag, improving code readability without needing to remember the mapping.
|
|
130
|
+
|
|
120
131
|
### 2. Dict-based Errors
|
|
121
132
|
|
|
122
133
|
Use standard FastAPI `responses` dict format for custom errors:
|
|
@@ -171,7 +182,76 @@ def get_resource(id: int):
|
|
|
171
182
|
pass
|
|
172
183
|
```
|
|
173
184
|
|
|
174
|
-
### 4.
|
|
185
|
+
### 4. BaseErrorDTO and StandardErrorDTO (Recommended)
|
|
186
|
+
|
|
187
|
+
For convenience, the library provides ready-to-use implementations:
|
|
188
|
+
|
|
189
|
+
#### BaseErrorDTO
|
|
190
|
+
|
|
191
|
+
Simple implementation for errors with a single example:
|
|
192
|
+
|
|
193
|
+
```python
|
|
194
|
+
from fastapi_errors_plus import Errors, BaseErrorDTO
|
|
195
|
+
|
|
196
|
+
notification_error = BaseErrorDTO(
|
|
197
|
+
status_code=404,
|
|
198
|
+
message="Notification not found",
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
@router.delete(
|
|
202
|
+
"/{id}",
|
|
203
|
+
responses=Errors(notification_error),
|
|
204
|
+
)
|
|
205
|
+
def delete_item(id: int):
|
|
206
|
+
"""Delete an item."""
|
|
207
|
+
pass
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
#### StandardErrorDTO
|
|
211
|
+
|
|
212
|
+
Extended implementation for errors with multiple examples (useful for standard HTTP errors):
|
|
213
|
+
|
|
214
|
+
```python
|
|
215
|
+
from fastapi_errors_plus import Errors, StandardErrorDTO
|
|
216
|
+
|
|
217
|
+
unauthorized_error = StandardErrorDTO(
|
|
218
|
+
status_code=401,
|
|
219
|
+
message="Unauthorized",
|
|
220
|
+
examples={
|
|
221
|
+
"InvalidToken": "Ошибка декодирования токена.",
|
|
222
|
+
"SessionNotFound": "Сессия пользователя не была найдена.",
|
|
223
|
+
},
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
forbidden_error = StandardErrorDTO(
|
|
227
|
+
status_code=403,
|
|
228
|
+
message="Forbidden",
|
|
229
|
+
examples={
|
|
230
|
+
"AccountNotSelected": "Аккаунт не выбран.",
|
|
231
|
+
"RoleHasNoAccess": "Роль не имеет доступа.",
|
|
232
|
+
},
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
@router.delete(
|
|
236
|
+
"/{id}",
|
|
237
|
+
responses=Errors(
|
|
238
|
+
unauthorized_error,
|
|
239
|
+
forbidden_error,
|
|
240
|
+
# validation_error=True - not needed, defaults to True
|
|
241
|
+
),
|
|
242
|
+
)
|
|
243
|
+
def delete_item(id: int):
|
|
244
|
+
"""Delete an item."""
|
|
245
|
+
pass
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
**Benefits:**
|
|
249
|
+
- ✅ No need to write ErrorDTO classes from scratch
|
|
250
|
+
- ✅ Correct implementation out of the box
|
|
251
|
+
- ✅ Reusable across all endpoints
|
|
252
|
+
- ✅ Supports inheritance for custom logic
|
|
253
|
+
|
|
254
|
+
### 5. Mixed Usage
|
|
175
255
|
|
|
176
256
|
Combine flags, dict, and ErrorDTO:
|
|
177
257
|
|
|
@@ -190,6 +270,7 @@ Combine flags, dict, and ErrorDTO:
|
|
|
190
270
|
MyErrorDTO(), # ErrorDTO
|
|
191
271
|
unauthorized=True, # Flag
|
|
192
272
|
forbidden=True, # Flag
|
|
273
|
+
# validation_error=True - not needed, defaults to True
|
|
193
274
|
),
|
|
194
275
|
)
|
|
195
276
|
def create_item_mixed(id: int):
|
|
@@ -197,7 +278,7 @@ def create_item_mixed(id: int):
|
|
|
197
278
|
pass
|
|
198
279
|
```
|
|
199
280
|
|
|
200
|
-
###
|
|
281
|
+
### 6. Merging Examples
|
|
201
282
|
|
|
202
283
|
Multiple errors with the same status code are automatically merged:
|
|
203
284
|
|
|
@@ -238,6 +319,20 @@ class ErrorDTO(Protocol):
|
|
|
238
319
|
|
|
239
320
|
Any class implementing this protocol (through structural typing) can be used with `Errors()`.
|
|
240
321
|
|
|
322
|
+
### When to Use Protocol vs BaseErrorDTO
|
|
323
|
+
|
|
324
|
+
**Use Protocol (structural typing)** when:
|
|
325
|
+
- Your project already has error DTOs that implement the protocol
|
|
326
|
+
- You need maximum flexibility and custom implementations
|
|
327
|
+
- You want to keep your existing error infrastructure
|
|
328
|
+
|
|
329
|
+
**Use BaseErrorDTO/StandardErrorDTO** when:
|
|
330
|
+
- Starting a new project or adding error documentation
|
|
331
|
+
- You want a ready-to-use implementation without boilerplate
|
|
332
|
+
- You need multiple examples for standard HTTP errors (401, 403, etc.)
|
|
333
|
+
|
|
334
|
+
Both approaches work together — you can mix them in the same `Errors()` call!
|
|
335
|
+
|
|
241
336
|
## Compatibility with Existing Projects
|
|
242
337
|
|
|
243
338
|
If your project already has error DTOs (like `ApiErrorDTO`), they can work with `fastapi-errors-plus` if they implement the `ErrorDTO` protocol:
|
|
@@ -280,17 +375,28 @@ Errors(
|
|
|
280
375
|
*errors: Union[Dict[int, Dict[str, Any]], ErrorDTO],
|
|
281
376
|
unauthorized: bool = False,
|
|
282
377
|
forbidden: bool = False,
|
|
283
|
-
validation_error: bool =
|
|
378
|
+
validation_error: bool = True, # Defaults to True (FastAPI validates all parameters)
|
|
284
379
|
internal_server_error: bool = False,
|
|
380
|
+
unauthorized_401: bool = False,
|
|
381
|
+
forbidden_403: bool = False,
|
|
382
|
+
validation_error_422: bool = True, # Defaults to True (FastAPI validates all parameters)
|
|
383
|
+
internal_server_error_500: bool = False,
|
|
285
384
|
)
|
|
286
385
|
```
|
|
287
386
|
|
|
288
387
|
**Parameters:**
|
|
289
388
|
- `*errors`: Arbitrary errors as dict or ErrorDTO objects
|
|
290
|
-
- `
|
|
291
|
-
- `
|
|
292
|
-
- `
|
|
293
|
-
- `
|
|
389
|
+
- `unauthorized_401`: Add 401 Unauthorized error (recommended, explicit). Defaults to `False`.
|
|
390
|
+
- `forbidden_403`: Add 403 Forbidden error (recommended, explicit). Defaults to `False`.
|
|
391
|
+
- `validation_error_422`: Add 422 Unprocessable Entity error (recommended, explicit). Defaults to `True` (FastAPI validates all parameters).
|
|
392
|
+
- `internal_server_error_500`: Add 500 Internal Server Error (recommended, explicit). Defaults to `False`.
|
|
393
|
+
- `unauthorized`: Add 401 Unauthorized error (legacy, for backward compatibility). Defaults to `False`.
|
|
394
|
+
- `forbidden`: Add 403 Forbidden error (legacy, for backward compatibility). Defaults to `False`.
|
|
395
|
+
- `validation_error`: Add 422 Unprocessable Entity error (legacy, for backward compatibility). Defaults to `True` (FastAPI validates all parameters).
|
|
396
|
+
- `internal_server_error`: Add 500 Internal Server Error (legacy, for backward compatibility). Defaults to `False`.
|
|
397
|
+
|
|
398
|
+
**Why `validation_error=True` by default?**
|
|
399
|
+
FastAPI automatically validates all parameters (Path, Query, Body), so 422 is relevant in 95%+ of endpoints. For endpoints without parameters, explicitly set `validation_error=False` or `validation_error_422=False`.
|
|
294
400
|
|
|
295
401
|
**Returns:**
|
|
296
402
|
- Callable object that returns `Dict[int, Dict[str, Any]]` in FastAPI responses format
|
|
@@ -313,6 +419,48 @@ Protocol for error objects compatible with the library.
|
|
|
313
419
|
**Required methods:**
|
|
314
420
|
- `to_example() -> Dict[str, Any]` — Generate example for OpenAPI
|
|
315
421
|
|
|
422
|
+
### `BaseErrorDTO`
|
|
423
|
+
|
|
424
|
+
Base implementation of ErrorDTO Protocol for convenience.
|
|
425
|
+
|
|
426
|
+
**Constructor:**
|
|
427
|
+
```python
|
|
428
|
+
BaseErrorDTO(
|
|
429
|
+
status_code: int,
|
|
430
|
+
message: str,
|
|
431
|
+
)
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
**Example:**
|
|
435
|
+
```python
|
|
436
|
+
error = BaseErrorDTO(status_code=404, message="Not found")
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
### `StandardErrorDTO`
|
|
440
|
+
|
|
441
|
+
Extended implementation for errors with multiple examples.
|
|
442
|
+
|
|
443
|
+
**Constructor:**
|
|
444
|
+
```python
|
|
445
|
+
StandardErrorDTO(
|
|
446
|
+
status_code: int,
|
|
447
|
+
message: str,
|
|
448
|
+
examples: Optional[Dict[str, str]] = None,
|
|
449
|
+
)
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
**Example:**
|
|
453
|
+
```python
|
|
454
|
+
error = StandardErrorDTO(
|
|
455
|
+
status_code=401,
|
|
456
|
+
message="Unauthorized",
|
|
457
|
+
examples={
|
|
458
|
+
"InvalidToken": "Invalid token",
|
|
459
|
+
"SessionNotFound": "Session not found",
|
|
460
|
+
},
|
|
461
|
+
)
|
|
462
|
+
```
|
|
463
|
+
|
|
316
464
|
## Examples
|
|
317
465
|
|
|
318
466
|
### Example 1: Standard FastAPI Project
|
|
@@ -471,7 +619,7 @@ router = APIRouter()
|
|
|
471
619
|
responses=Errors(
|
|
472
620
|
unauthorized=True, # From authentication dependency
|
|
473
621
|
forbidden=True, # From authorization dependency
|
|
474
|
-
validation_error=True,
|
|
622
|
+
# validation_error=True - not needed, defaults to True (FastAPI validates all parameters)
|
|
475
623
|
ItemAlreadyExistsError(), # Domain error
|
|
476
624
|
),
|
|
477
625
|
)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
fastapi_errors_plus/__init__.py,sha256=0f8Avw6S8rxv_dq54spP7DsIrgcOlZ8TAMWPfd0XoRQ,454
|
|
2
|
+
fastapi_errors_plus/base.py,sha256=SpZxS_avOr1kwcuJXjR-BQbeKX8Yp3pExCujR76E8Uk,3578
|
|
3
|
+
fastapi_errors_plus/errors.py,sha256=pz7AJQoGc6vqVIA0ZA6agrq-QHxvL6wOMutR0gmB-tI,18899
|
|
4
|
+
fastapi_errors_plus/protocol.py,sha256=pFIVjMB5foltP_BINLllo6wEDdVncXeNIpOEbd2_o4o,1216
|
|
5
|
+
fastapi_errors_plus-0.4.0.dist-info/licenses/LICENSE,sha256=yQIQ4Uyt7lAeNcxDofCQTLZA7G5hkHqJc0BKHC4CDXk,1091
|
|
6
|
+
fastapi_errors_plus-0.4.0.dist-info/METADATA,sha256=WDr9qBzVqBcte5CTQpUVl8zxXxQ1OkHw0UL3PXIpwec,19186
|
|
7
|
+
fastapi_errors_plus-0.4.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
8
|
+
fastapi_errors_plus-0.4.0.dist-info/top_level.txt,sha256=vmHLF1-DQYB2quqrvdBA0g6rDtgOWQBrA1m-X_WyNk8,20
|
|
9
|
+
fastapi_errors_plus-0.4.0.dist-info/RECORD,,
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
fastapi_errors_plus/__init__.py,sha256=Dbn9fmqBoSa5yTF0d4gVvyoJ61pI3My3aZNMq8wsGGg,223
|
|
2
|
-
fastapi_errors_plus/errors.py,sha256=kvM2DeDYJ-pMREWmSslF0KgIWixERqj-Nt5oJ8IeSHc,16325
|
|
3
|
-
fastapi_errors_plus/protocol.py,sha256=mSb-nabNDz7tjbSboHOQJu6QGsUPZOivC-XztvYoHRA,1215
|
|
4
|
-
fastapi_errors_plus-0.1.0.dist-info/licenses/LICENSE,sha256=wKw57ZiHT4OAK3euOE2UxSzr3RN_AEarSxQV88xMBgA,1090
|
|
5
|
-
fastapi_errors_plus-0.1.0.dist-info/METADATA,sha256=wEThfjUfdMt4sUG6paPrTBE_gGVj5QVWbXg2oPe-26o,14039
|
|
6
|
-
fastapi_errors_plus-0.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
7
|
-
fastapi_errors_plus-0.1.0.dist-info/top_level.txt,sha256=vmHLF1-DQYB2quqrvdBA0g6rDtgOWQBrA1m-X_WyNk8,20
|
|
8
|
-
fastapi_errors_plus-0.1.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|