fastapi-errors-plus 0.5.0__py3-none-any.whl → 0.6.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 +1 -1
- fastapi_errors_plus/base.py +1 -0
- fastapi_errors_plus/protocol.py +1 -0
- {fastapi_errors_plus-0.5.0.dist-info → fastapi_errors_plus-0.6.0.dist-info}/METADATA +72 -5
- fastapi_errors_plus-0.6.0.dist-info/RECORD +10 -0
- {fastapi_errors_plus-0.5.0.dist-info → fastapi_errors_plus-0.6.0.dist-info}/licenses/LICENSE +1 -0
- fastapi_errors_plus-0.5.0.dist-info/RECORD +0 -10
- {fastapi_errors_plus-0.5.0.dist-info → fastapi_errors_plus-0.6.0.dist-info}/WHEEL +0 -0
- {fastapi_errors_plus-0.5.0.dist-info → fastapi_errors_plus-0.6.0.dist-info}/top_level.txt +0 -0
fastapi_errors_plus/__init__.py
CHANGED
fastapi_errors_plus/base.py
CHANGED
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.6.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
|
|
@@ -246,10 +246,10 @@ def delete_item(id: int):
|
|
|
246
246
|
```
|
|
247
247
|
|
|
248
248
|
**Benefits:**
|
|
249
|
-
-
|
|
250
|
-
-
|
|
251
|
-
-
|
|
252
|
-
-
|
|
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
253
|
|
|
254
254
|
### 5. Mixed Usage
|
|
255
255
|
|
|
@@ -319,6 +319,8 @@ class ErrorDTO(Protocol):
|
|
|
319
319
|
|
|
320
320
|
Any class implementing this protocol (through structural typing) can be used with `Errors()`.
|
|
321
321
|
|
|
322
|
+
**Best Practice:** For maximum clarity, consider making your domain exceptions implement the ErrorDTO protocol directly. See [Best Practice: Connecting Exceptions and ErrorDTO](#best-practice-connecting-exceptions-and-errordto) for details.
|
|
323
|
+
|
|
322
324
|
### When to Use Protocol vs BaseErrorDTO
|
|
323
325
|
|
|
324
326
|
**Use Protocol (structural typing)** when:
|
|
@@ -333,6 +335,71 @@ Any class implementing this protocol (through structural typing) can be used wit
|
|
|
333
335
|
|
|
334
336
|
Both approaches work together — you can mix them in the same `Errors()` call!
|
|
335
337
|
|
|
338
|
+
## Best Practice: Connecting Exceptions and ErrorDTO
|
|
339
|
+
|
|
340
|
+
### Problem
|
|
341
|
+
|
|
342
|
+
It's not always clear which exception corresponds to which ErrorDTO:
|
|
343
|
+
|
|
344
|
+
```python
|
|
345
|
+
# Not clear which exception this documents
|
|
346
|
+
responses=Errors(notification_not_found_error)
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### Solution: Domain Exception as ErrorDTO
|
|
350
|
+
|
|
351
|
+
**Recommended approach** — make your exceptions implement ErrorDTO protocol:
|
|
352
|
+
|
|
353
|
+
```python
|
|
354
|
+
# domain/exceptions.py
|
|
355
|
+
from typing import Dict, Any
|
|
356
|
+
|
|
357
|
+
class DomainException(Exception):
|
|
358
|
+
"""Base exception implementing ErrorDTO protocol."""
|
|
359
|
+
status_code: int
|
|
360
|
+
message: str
|
|
361
|
+
|
|
362
|
+
def to_example(self) -> Dict[str, Any]:
|
|
363
|
+
return {self.message: {"value": {"detail": self.message}}}
|
|
364
|
+
|
|
365
|
+
@classmethod
|
|
366
|
+
def for_openapi(cls):
|
|
367
|
+
"""Returns instance for OpenAPI documentation."""
|
|
368
|
+
return cls()
|
|
369
|
+
|
|
370
|
+
class NotificationNotFoundError(DomainException):
|
|
371
|
+
status_code = 404
|
|
372
|
+
message = "Notification not found"
|
|
373
|
+
|
|
374
|
+
def __init__(self, notification_id: str = ""):
|
|
375
|
+
self.notification_id = notification_id
|
|
376
|
+
super().__init__(self.message)
|
|
377
|
+
|
|
378
|
+
@classmethod
|
|
379
|
+
def for_openapi(cls):
|
|
380
|
+
return cls(notification_id="example_id")
|
|
381
|
+
|
|
382
|
+
# In endpoint
|
|
383
|
+
@router.delete(
|
|
384
|
+
"/{notificationId}",
|
|
385
|
+
responses=Errors(
|
|
386
|
+
NotificationNotFoundError.for_openapi(), # Clear connection!
|
|
387
|
+
),
|
|
388
|
+
)
|
|
389
|
+
async def delete_notification(notification_id: str):
|
|
390
|
+
if not notification:
|
|
391
|
+
raise NotificationNotFoundError(notification_id) # Same exception!
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
**Benefits:**
|
|
395
|
+
- Exception and ErrorDTO are one class
|
|
396
|
+
- Clear connection visible in endpoint
|
|
397
|
+
- No duplication
|
|
398
|
+
- Type-safe
|
|
399
|
+
- Works with any project architecture
|
|
400
|
+
|
|
401
|
+
See [examples/domain_exceptions.py](examples/domain_exceptions.py) for complete example.
|
|
402
|
+
|
|
336
403
|
## Compatibility with Existing Projects
|
|
337
404
|
|
|
338
405
|
If your project already has error DTOs (like `ApiErrorDTO`), they can work with `fastapi-errors-plus` if they implement the `ErrorDTO` protocol:
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
fastapi_errors_plus/__init__.py,sha256=6xx4sQHjvhEHcxsenhJMZlR2RrH-FnahEPVoRvAjakI,454
|
|
2
|
+
fastapi_errors_plus/base.py,sha256=iTQ6WFxc5fLoY0Omi8aPNua7wBqQj20Z5ZPOOJhTIow,3580
|
|
3
|
+
fastapi_errors_plus/errors.py,sha256=7ikmrSphWOH_nnxLC0HPQ0RPiuR1u8olw3bxGxdLv50,20868
|
|
4
|
+
fastapi_errors_plus/protocol.py,sha256=466lfnVKWa1jjD0iWy3r_FIXFIqTuATJOT9sqXxbKZE,1218
|
|
5
|
+
fastapi_errors_plus/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
+
fastapi_errors_plus-0.6.0.dist-info/licenses/LICENSE,sha256=W_dONuuw-DA1UPcP9NPnQbhCbtMkLjhUr3Ne96398VU,1093
|
|
7
|
+
fastapi_errors_plus-0.6.0.dist-info/METADATA,sha256=03r27kEKm4G10pYJ77aBQecEQOq_8hTlndEuYYWpzo4,21455
|
|
8
|
+
fastapi_errors_plus-0.6.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
9
|
+
fastapi_errors_plus-0.6.0.dist-info/top_level.txt,sha256=vmHLF1-DQYB2quqrvdBA0g6rDtgOWQBrA1m-X_WyNk8,20
|
|
10
|
+
fastapi_errors_plus-0.6.0.dist-info/RECORD,,
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
fastapi_errors_plus/__init__.py,sha256=uc5QIsWWvHQWAOA2Ri94hIWBAiT_QhmL4YOnUCMVqA8,454
|
|
2
|
-
fastapi_errors_plus/base.py,sha256=9158lfwZ5pPbgFJqmL1V6bFEivxr1UpwCwR4cL87ZVo,3579
|
|
3
|
-
fastapi_errors_plus/errors.py,sha256=7ikmrSphWOH_nnxLC0HPQ0RPiuR1u8olw3bxGxdLv50,20868
|
|
4
|
-
fastapi_errors_plus/protocol.py,sha256=krTYPOWTxbz_I4w2ESzGHgE6trONa1wDMQgErMs1nLc,1217
|
|
5
|
-
fastapi_errors_plus/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
-
fastapi_errors_plus-0.5.0.dist-info/licenses/LICENSE,sha256=Ilkf6MRaeVru1agPGtmMlsxEY-4DEUIo1_3PGkTdzm0,1092
|
|
7
|
-
fastapi_errors_plus-0.5.0.dist-info/METADATA,sha256=sRjs9kYXl3d69iwWAVAmgFH96tKTaSSgHANr3_iPbeo,19511
|
|
8
|
-
fastapi_errors_plus-0.5.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
9
|
-
fastapi_errors_plus-0.5.0.dist-info/top_level.txt,sha256=vmHLF1-DQYB2quqrvdBA0g6rDtgOWQBrA1m-X_WyNk8,20
|
|
10
|
-
fastapi_errors_plus-0.5.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|