fastapi-errors-plus 0.1.1__tar.gz → 0.5.0__tar.gz
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-0.1.1 → fastapi_errors_plus-0.5.0}/LICENSE +2 -0
- {fastapi_errors_plus-0.1.1 → fastapi_errors_plus-0.5.0}/PKG-INFO +172 -17
- {fastapi_errors_plus-0.1.1 → fastapi_errors_plus-0.5.0}/README.md +171 -16
- fastapi_errors_plus-0.5.0/fastapi_errors_plus/__init__.py +14 -0
- fastapi_errors_plus-0.5.0/fastapi_errors_plus/base.py +123 -0
- {fastapi_errors_plus-0.1.1 → fastapi_errors_plus-0.5.0}/fastapi_errors_plus/errors.py +89 -13
- {fastapi_errors_plus-0.1.1 → fastapi_errors_plus-0.5.0}/fastapi_errors_plus/protocol.py +2 -0
- fastapi_errors_plus-0.5.0/fastapi_errors_plus/py.typed +0 -0
- {fastapi_errors_plus-0.1.1 → fastapi_errors_plus-0.5.0}/fastapi_errors_plus.egg-info/PKG-INFO +172 -17
- {fastapi_errors_plus-0.1.1 → fastapi_errors_plus-0.5.0}/fastapi_errors_plus.egg-info/SOURCES.txt +3 -0
- {fastapi_errors_plus-0.1.1 → fastapi_errors_plus-0.5.0}/pyproject.toml +1 -1
- {fastapi_errors_plus-0.1.1 → fastapi_errors_plus-0.5.0}/tests/test_app.py +68 -2
- fastapi_errors_plus-0.5.0/tests/test_base.py +305 -0
- {fastapi_errors_plus-0.1.1 → fastapi_errors_plus-0.5.0}/tests/test_errors.py +261 -6
- {fastapi_errors_plus-0.1.1 → fastapi_errors_plus-0.5.0}/tests/test_integration.py +114 -1
- fastapi_errors_plus-0.1.1/fastapi_errors_plus/__init__.py +0 -8
- {fastapi_errors_plus-0.1.1 → fastapi_errors_plus-0.5.0}/fastapi_errors_plus.egg-info/dependency_links.txt +0 -0
- {fastapi_errors_plus-0.1.1 → fastapi_errors_plus-0.5.0}/fastapi_errors_plus.egg-info/requires.txt +0 -0
- {fastapi_errors_plus-0.1.1 → fastapi_errors_plus-0.5.0}/fastapi_errors_plus.egg-info/top_level.txt +0 -0
- {fastapi_errors_plus-0.1.1 → fastapi_errors_plus-0.5.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fastapi-errors-plus
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.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,7 +30,7 @@ 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/seligoroff/fastapi-errors-plus)
|
|
34
34
|
[](https://github.com/seligoroff/fastapi-errors-plus)
|
|
35
35
|
|
|
36
36
|
Universal library for documenting errors in FastAPI endpoints.
|
|
@@ -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,20 +375,38 @@ 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: Optional[bool] = None, # None (default) => 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: Optional[bool] = None, # None (default) => 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).
|
|
392
|
+
- `None` (default): Add 422 (True by default, FastAPI validates all parameters)
|
|
393
|
+
- `False`: Explicitly disable 422
|
|
394
|
+
- `True`: Explicitly enable 422
|
|
395
|
+
- `internal_server_error_500`: Add 500 Internal Server Error (recommended, explicit). Defaults to `False`.
|
|
396
|
+
- `unauthorized`: Add 401 Unauthorized error (legacy, for backward compatibility). Defaults to `False`.
|
|
397
|
+
- `forbidden`: Add 403 Forbidden error (legacy, for backward compatibility). Defaults to `False`.
|
|
398
|
+
- `validation_error`: Add 422 Unprocessable Entity error (legacy, for backward compatibility).
|
|
399
|
+
- `None` (default): Add 422 (True by default, FastAPI validates all parameters)
|
|
400
|
+
- `False`: Explicitly disable 422
|
|
401
|
+
- `True`: Explicitly enable 422
|
|
402
|
+
- `internal_server_error`: Add 500 Internal Server Error (legacy, for backward compatibility). Defaults to `False`.
|
|
403
|
+
|
|
404
|
+
**Why `validation_error=True` by default?**
|
|
405
|
+
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
406
|
|
|
295
407
|
**Returns:**
|
|
296
|
-
-
|
|
408
|
+
- Mapping object (dict-like) that implements `Dict[int, Dict[str, Any]]` for FastAPI responses
|
|
409
|
+
- Can be used directly in `responses` parameter without calling: `responses=Errors(...)`
|
|
297
410
|
|
|
298
411
|
#### Usage
|
|
299
412
|
|
|
@@ -313,6 +426,48 @@ Protocol for error objects compatible with the library.
|
|
|
313
426
|
**Required methods:**
|
|
314
427
|
- `to_example() -> Dict[str, Any]` — Generate example for OpenAPI
|
|
315
428
|
|
|
429
|
+
### `BaseErrorDTO`
|
|
430
|
+
|
|
431
|
+
Base implementation of ErrorDTO Protocol for convenience.
|
|
432
|
+
|
|
433
|
+
**Constructor:**
|
|
434
|
+
```python
|
|
435
|
+
BaseErrorDTO(
|
|
436
|
+
status_code: int,
|
|
437
|
+
message: str,
|
|
438
|
+
)
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
**Example:**
|
|
442
|
+
```python
|
|
443
|
+
error = BaseErrorDTO(status_code=404, message="Not found")
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
### `StandardErrorDTO`
|
|
447
|
+
|
|
448
|
+
Extended implementation for errors with multiple examples.
|
|
449
|
+
|
|
450
|
+
**Constructor:**
|
|
451
|
+
```python
|
|
452
|
+
StandardErrorDTO(
|
|
453
|
+
status_code: int,
|
|
454
|
+
message: str,
|
|
455
|
+
examples: Optional[Dict[str, str]] = None,
|
|
456
|
+
)
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
**Example:**
|
|
460
|
+
```python
|
|
461
|
+
error = StandardErrorDTO(
|
|
462
|
+
status_code=401,
|
|
463
|
+
message="Unauthorized",
|
|
464
|
+
examples={
|
|
465
|
+
"InvalidToken": "Invalid token",
|
|
466
|
+
"SessionNotFound": "Session not found",
|
|
467
|
+
},
|
|
468
|
+
)
|
|
469
|
+
```
|
|
470
|
+
|
|
316
471
|
## Examples
|
|
317
472
|
|
|
318
473
|
### Example 1: Standard FastAPI Project
|
|
@@ -471,7 +626,7 @@ router = APIRouter()
|
|
|
471
626
|
responses=Errors(
|
|
472
627
|
unauthorized=True, # From authentication dependency
|
|
473
628
|
forbidden=True, # From authorization dependency
|
|
474
|
-
validation_error=True,
|
|
629
|
+
# validation_error=True - not needed, defaults to True (FastAPI validates all parameters)
|
|
475
630
|
ItemAlreadyExistsError(), # Domain error
|
|
476
631
|
),
|
|
477
632
|
)
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
[](https://opensource.org/licenses/MIT)
|
|
5
5
|
[](https://www.python.org/downloads/)
|
|
6
6
|
[](https://fastapi.tiangolo.com/)
|
|
7
|
-
[](https://github.com/seligoroff/fastapi-errors-plus)
|
|
8
8
|
[](https://github.com/seligoroff/fastapi-errors-plus)
|
|
9
9
|
|
|
10
10
|
Universal library for documenting errors in FastAPI endpoints.
|
|
@@ -56,9 +56,9 @@ router = APIRouter()
|
|
|
56
56
|
},
|
|
57
57
|
},
|
|
58
58
|
}},
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
unauthorized_401=True, # 401 Unauthorized (explicit)
|
|
60
|
+
forbidden_403=True, # 403 Forbidden (explicit)
|
|
61
|
+
# validation_error_422=True - not needed, defaults to True
|
|
62
62
|
),
|
|
63
63
|
)
|
|
64
64
|
def delete_item(id: int):
|
|
@@ -73,17 +73,26 @@ def delete_item(id: int):
|
|
|
73
73
|
|
|
74
74
|
Use boolean flags for common HTTP status codes:
|
|
75
75
|
|
|
76
|
+
**Recommended (explicit status codes):**
|
|
77
|
+
- `unauthorized_401=True` → 401 Unauthorized
|
|
78
|
+
- `forbidden_403=True` → 403 Forbidden
|
|
79
|
+
- `validation_error_422=True` → 422 Unprocessable Entity (defaults to `True`)
|
|
80
|
+
- `internal_server_error_500=True` → 500 Internal Server Error
|
|
81
|
+
|
|
82
|
+
**Legacy (for backward compatibility):**
|
|
76
83
|
- `unauthorized=True` → 401 Unauthorized
|
|
77
84
|
- `forbidden=True` → 403 Forbidden
|
|
78
|
-
- `validation_error=True` → 422 Unprocessable Entity
|
|
85
|
+
- `validation_error=True` → 422 Unprocessable Entity (defaults to `True`)
|
|
79
86
|
- `internal_server_error=True` → 500 Internal Server Error
|
|
80
87
|
|
|
88
|
+
**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.
|
|
89
|
+
|
|
81
90
|
```python
|
|
82
91
|
@router.get(
|
|
83
92
|
"/protected",
|
|
84
93
|
responses=Errors(
|
|
85
|
-
|
|
86
|
-
|
|
94
|
+
unauthorized_401=True, # Explicit: 401 is visible
|
|
95
|
+
forbidden_403=True, # Explicit: 403 is visible
|
|
87
96
|
),
|
|
88
97
|
)
|
|
89
98
|
def get_protected():
|
|
@@ -91,6 +100,8 @@ def get_protected():
|
|
|
91
100
|
pass
|
|
92
101
|
```
|
|
93
102
|
|
|
103
|
+
**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.
|
|
104
|
+
|
|
94
105
|
### 2. Dict-based Errors
|
|
95
106
|
|
|
96
107
|
Use standard FastAPI `responses` dict format for custom errors:
|
|
@@ -145,7 +156,76 @@ def get_resource(id: int):
|
|
|
145
156
|
pass
|
|
146
157
|
```
|
|
147
158
|
|
|
148
|
-
### 4.
|
|
159
|
+
### 4. BaseErrorDTO and StandardErrorDTO (Recommended)
|
|
160
|
+
|
|
161
|
+
For convenience, the library provides ready-to-use implementations:
|
|
162
|
+
|
|
163
|
+
#### BaseErrorDTO
|
|
164
|
+
|
|
165
|
+
Simple implementation for errors with a single example:
|
|
166
|
+
|
|
167
|
+
```python
|
|
168
|
+
from fastapi_errors_plus import Errors, BaseErrorDTO
|
|
169
|
+
|
|
170
|
+
notification_error = BaseErrorDTO(
|
|
171
|
+
status_code=404,
|
|
172
|
+
message="Notification not found",
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
@router.delete(
|
|
176
|
+
"/{id}",
|
|
177
|
+
responses=Errors(notification_error),
|
|
178
|
+
)
|
|
179
|
+
def delete_item(id: int):
|
|
180
|
+
"""Delete an item."""
|
|
181
|
+
pass
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
#### StandardErrorDTO
|
|
185
|
+
|
|
186
|
+
Extended implementation for errors with multiple examples (useful for standard HTTP errors):
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
from fastapi_errors_plus import Errors, StandardErrorDTO
|
|
190
|
+
|
|
191
|
+
unauthorized_error = StandardErrorDTO(
|
|
192
|
+
status_code=401,
|
|
193
|
+
message="Unauthorized",
|
|
194
|
+
examples={
|
|
195
|
+
"InvalidToken": "Ошибка декодирования токена.",
|
|
196
|
+
"SessionNotFound": "Сессия пользователя не была найдена.",
|
|
197
|
+
},
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
forbidden_error = StandardErrorDTO(
|
|
201
|
+
status_code=403,
|
|
202
|
+
message="Forbidden",
|
|
203
|
+
examples={
|
|
204
|
+
"AccountNotSelected": "Аккаунт не выбран.",
|
|
205
|
+
"RoleHasNoAccess": "Роль не имеет доступа.",
|
|
206
|
+
},
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
@router.delete(
|
|
210
|
+
"/{id}",
|
|
211
|
+
responses=Errors(
|
|
212
|
+
unauthorized_error,
|
|
213
|
+
forbidden_error,
|
|
214
|
+
# validation_error=True - not needed, defaults to True
|
|
215
|
+
),
|
|
216
|
+
)
|
|
217
|
+
def delete_item(id: int):
|
|
218
|
+
"""Delete an item."""
|
|
219
|
+
pass
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
**Benefits:**
|
|
223
|
+
- ✅ No need to write ErrorDTO classes from scratch
|
|
224
|
+
- ✅ Correct implementation out of the box
|
|
225
|
+
- ✅ Reusable across all endpoints
|
|
226
|
+
- ✅ Supports inheritance for custom logic
|
|
227
|
+
|
|
228
|
+
### 5. Mixed Usage
|
|
149
229
|
|
|
150
230
|
Combine flags, dict, and ErrorDTO:
|
|
151
231
|
|
|
@@ -164,6 +244,7 @@ Combine flags, dict, and ErrorDTO:
|
|
|
164
244
|
MyErrorDTO(), # ErrorDTO
|
|
165
245
|
unauthorized=True, # Flag
|
|
166
246
|
forbidden=True, # Flag
|
|
247
|
+
# validation_error=True - not needed, defaults to True
|
|
167
248
|
),
|
|
168
249
|
)
|
|
169
250
|
def create_item_mixed(id: int):
|
|
@@ -171,7 +252,7 @@ def create_item_mixed(id: int):
|
|
|
171
252
|
pass
|
|
172
253
|
```
|
|
173
254
|
|
|
174
|
-
###
|
|
255
|
+
### 6. Merging Examples
|
|
175
256
|
|
|
176
257
|
Multiple errors with the same status code are automatically merged:
|
|
177
258
|
|
|
@@ -212,6 +293,20 @@ class ErrorDTO(Protocol):
|
|
|
212
293
|
|
|
213
294
|
Any class implementing this protocol (through structural typing) can be used with `Errors()`.
|
|
214
295
|
|
|
296
|
+
### When to Use Protocol vs BaseErrorDTO
|
|
297
|
+
|
|
298
|
+
**Use Protocol (structural typing)** when:
|
|
299
|
+
- Your project already has error DTOs that implement the protocol
|
|
300
|
+
- You need maximum flexibility and custom implementations
|
|
301
|
+
- You want to keep your existing error infrastructure
|
|
302
|
+
|
|
303
|
+
**Use BaseErrorDTO/StandardErrorDTO** when:
|
|
304
|
+
- Starting a new project or adding error documentation
|
|
305
|
+
- You want a ready-to-use implementation without boilerplate
|
|
306
|
+
- You need multiple examples for standard HTTP errors (401, 403, etc.)
|
|
307
|
+
|
|
308
|
+
Both approaches work together — you can mix them in the same `Errors()` call!
|
|
309
|
+
|
|
215
310
|
## Compatibility with Existing Projects
|
|
216
311
|
|
|
217
312
|
If your project already has error DTOs (like `ApiErrorDTO`), they can work with `fastapi-errors-plus` if they implement the `ErrorDTO` protocol:
|
|
@@ -254,20 +349,38 @@ Errors(
|
|
|
254
349
|
*errors: Union[Dict[int, Dict[str, Any]], ErrorDTO],
|
|
255
350
|
unauthorized: bool = False,
|
|
256
351
|
forbidden: bool = False,
|
|
257
|
-
validation_error: bool =
|
|
352
|
+
validation_error: Optional[bool] = None, # None (default) => True (FastAPI validates all parameters)
|
|
258
353
|
internal_server_error: bool = False,
|
|
354
|
+
unauthorized_401: bool = False,
|
|
355
|
+
forbidden_403: bool = False,
|
|
356
|
+
validation_error_422: Optional[bool] = None, # None (default) => True (FastAPI validates all parameters)
|
|
357
|
+
internal_server_error_500: bool = False,
|
|
259
358
|
)
|
|
260
359
|
```
|
|
261
360
|
|
|
262
361
|
**Parameters:**
|
|
263
362
|
- `*errors`: Arbitrary errors as dict or ErrorDTO objects
|
|
264
|
-
- `
|
|
265
|
-
- `
|
|
266
|
-
- `
|
|
267
|
-
- `
|
|
363
|
+
- `unauthorized_401`: Add 401 Unauthorized error (recommended, explicit). Defaults to `False`.
|
|
364
|
+
- `forbidden_403`: Add 403 Forbidden error (recommended, explicit). Defaults to `False`.
|
|
365
|
+
- `validation_error_422`: Add 422 Unprocessable Entity error (recommended, explicit).
|
|
366
|
+
- `None` (default): Add 422 (True by default, FastAPI validates all parameters)
|
|
367
|
+
- `False`: Explicitly disable 422
|
|
368
|
+
- `True`: Explicitly enable 422
|
|
369
|
+
- `internal_server_error_500`: Add 500 Internal Server Error (recommended, explicit). Defaults to `False`.
|
|
370
|
+
- `unauthorized`: Add 401 Unauthorized error (legacy, for backward compatibility). Defaults to `False`.
|
|
371
|
+
- `forbidden`: Add 403 Forbidden error (legacy, for backward compatibility). Defaults to `False`.
|
|
372
|
+
- `validation_error`: Add 422 Unprocessable Entity error (legacy, for backward compatibility).
|
|
373
|
+
- `None` (default): Add 422 (True by default, FastAPI validates all parameters)
|
|
374
|
+
- `False`: Explicitly disable 422
|
|
375
|
+
- `True`: Explicitly enable 422
|
|
376
|
+
- `internal_server_error`: Add 500 Internal Server Error (legacy, for backward compatibility). Defaults to `False`.
|
|
377
|
+
|
|
378
|
+
**Why `validation_error=True` by default?**
|
|
379
|
+
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`.
|
|
268
380
|
|
|
269
381
|
**Returns:**
|
|
270
|
-
-
|
|
382
|
+
- Mapping object (dict-like) that implements `Dict[int, Dict[str, Any]]` for FastAPI responses
|
|
383
|
+
- Can be used directly in `responses` parameter without calling: `responses=Errors(...)`
|
|
271
384
|
|
|
272
385
|
#### Usage
|
|
273
386
|
|
|
@@ -287,6 +400,48 @@ Protocol for error objects compatible with the library.
|
|
|
287
400
|
**Required methods:**
|
|
288
401
|
- `to_example() -> Dict[str, Any]` — Generate example for OpenAPI
|
|
289
402
|
|
|
403
|
+
### `BaseErrorDTO`
|
|
404
|
+
|
|
405
|
+
Base implementation of ErrorDTO Protocol for convenience.
|
|
406
|
+
|
|
407
|
+
**Constructor:**
|
|
408
|
+
```python
|
|
409
|
+
BaseErrorDTO(
|
|
410
|
+
status_code: int,
|
|
411
|
+
message: str,
|
|
412
|
+
)
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
**Example:**
|
|
416
|
+
```python
|
|
417
|
+
error = BaseErrorDTO(status_code=404, message="Not found")
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
### `StandardErrorDTO`
|
|
421
|
+
|
|
422
|
+
Extended implementation for errors with multiple examples.
|
|
423
|
+
|
|
424
|
+
**Constructor:**
|
|
425
|
+
```python
|
|
426
|
+
StandardErrorDTO(
|
|
427
|
+
status_code: int,
|
|
428
|
+
message: str,
|
|
429
|
+
examples: Optional[Dict[str, str]] = None,
|
|
430
|
+
)
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
**Example:**
|
|
434
|
+
```python
|
|
435
|
+
error = StandardErrorDTO(
|
|
436
|
+
status_code=401,
|
|
437
|
+
message="Unauthorized",
|
|
438
|
+
examples={
|
|
439
|
+
"InvalidToken": "Invalid token",
|
|
440
|
+
"SessionNotFound": "Session not found",
|
|
441
|
+
},
|
|
442
|
+
)
|
|
443
|
+
```
|
|
444
|
+
|
|
290
445
|
## Examples
|
|
291
446
|
|
|
292
447
|
### Example 1: Standard FastAPI Project
|
|
@@ -445,7 +600,7 @@ router = APIRouter()
|
|
|
445
600
|
responses=Errors(
|
|
446
601
|
unauthorized=True, # From authentication dependency
|
|
447
602
|
forbidden=True, # From authorization dependency
|
|
448
|
-
validation_error=True,
|
|
603
|
+
# validation_error=True - not needed, defaults to True (FastAPI validates all parameters)
|
|
449
604
|
ItemAlreadyExistsError(), # Domain error
|
|
450
605
|
),
|
|
451
606
|
)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""Universal library for documenting errors in FastAPI endpoints."""
|
|
2
|
+
|
|
3
|
+
from fastapi_errors_plus.base import BaseErrorDTO, StandardErrorDTO
|
|
4
|
+
from fastapi_errors_plus.errors import Errors
|
|
5
|
+
from fastapi_errors_plus.protocol import ErrorDTO
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
"Errors",
|
|
9
|
+
"ErrorDTO", # Protocol (for structural typing)
|
|
10
|
+
"BaseErrorDTO", # Base implementation (optional)
|
|
11
|
+
"StandardErrorDTO", # Extended implementation (optional)
|
|
12
|
+
]
|
|
13
|
+
__version__ = "0.5.0"
|
|
14
|
+
|