fastapi-errors-plus 0.4.0__py3-none-any.whl → 0.5.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.
@@ -10,5 +10,5 @@ __all__ = [
10
10
  "BaseErrorDTO", # Base implementation (optional)
11
11
  "StandardErrorDTO", # Extended implementation (optional)
12
12
  ]
13
- __version__ = "0.4.0"
13
+ __version__ = "0.5.0"
14
14
 
@@ -120,3 +120,4 @@ class StandardErrorDTO(BaseErrorDTO):
120
120
  for key, message in self.examples.items()
121
121
  }
122
122
 
123
+
@@ -1,7 +1,7 @@
1
1
  """Main Errors class for documenting errors in FastAPI endpoints."""
2
2
 
3
3
  from collections.abc import Mapping
4
- from typing import Any, Dict, Iterator, Union
4
+ from typing import Any, Dict, Iterator, Optional, Union
5
5
 
6
6
  from fastapi import status
7
7
 
@@ -29,10 +29,7 @@ class Errors(Mapping):
29
29
  @router.delete(
30
30
  "/{id}",
31
31
  responses=Errors(
32
- unauthorized_401=True, # 401 (explicit)
33
- forbidden_403=True, # 403 (explicit)
34
- validation_error_422=True, # 422 (explicit)
35
- {404: { # 404 via dict
32
+ {404: { # 404 via dict (positional first)
36
33
  "description": "Not found",
37
34
  "content": {
38
35
  "application/json": {
@@ -40,6 +37,9 @@ class Errors(Mapping):
40
37
  },
41
38
  },
42
39
  }},
40
+ unauthorized_401=True, # 401 (explicit, named after positional)
41
+ forbidden_403=True, # 403 (explicit)
42
+ # validation_error_422=True - not needed, defaults to True
43
43
  ),
44
44
  )
45
45
  def delete_item(id: int):
@@ -55,12 +55,12 @@ class Errors(Mapping):
55
55
  # Old parameters (for backward compatibility)
56
56
  unauthorized: bool = False, # 401
57
57
  forbidden: bool = False, # 403
58
- validation_error: bool = None, # 422 (None = use default True, False = disable, True = enable)
58
+ validation_error: Optional[bool] = None, # 422 (None = use default True, False = disable, True = enable)
59
59
  internal_server_error: bool = False, # 500
60
60
  # New parameters with explicit status codes (recommended)
61
61
  unauthorized_401: bool = False, # 401 (explicit)
62
62
  forbidden_403: bool = False, # 403 (explicit)
63
- validation_error_422: bool = None, # 422 (explicit, None = use default True, False = disable, True = enable)
63
+ validation_error_422: Optional[bool] = None, # 422 (explicit, None = use default True, False = disable, True = enable)
64
64
  internal_server_error_500: bool = False, # 500 (explicit)
65
65
  ) -> None:
66
66
  """Initialize Errors instance.
@@ -73,7 +73,10 @@ class Errors(Mapping):
73
73
  Deprecated: Use `unauthorized_401` instead for explicit status code.
74
74
  forbidden: Add 403 Forbidden error. Defaults to False.
75
75
  Deprecated: Use `forbidden_403` instead for explicit status code.
76
- validation_error: Add 422 Unprocessable Entity error. Defaults to True (None means True).
76
+ validation_error: Add 422 Unprocessable Entity error.
77
+ - None (default): Add 422 (True by default, FastAPI validates all parameters)
78
+ - False: Explicitly disable 422
79
+ - True: Explicitly enable 422
77
80
  FastAPI automatically validates all parameters (Path, Query, Body), so 422 is relevant
78
81
  in 95%+ of endpoints. Set to False only for endpoints without parameters.
79
82
  Deprecated: Use `validation_error_422` instead for explicit status code.
@@ -81,7 +84,10 @@ class Errors(Mapping):
81
84
  Deprecated: Use `internal_server_error_500` instead for explicit status code.
82
85
  unauthorized_401: Add 401 Unauthorized error (explicit). Defaults to False.
83
86
  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).
87
+ validation_error_422: Add 422 Unprocessable Entity error (explicit).
88
+ - None (default): Add 422 (True by default, FastAPI validates all parameters)
89
+ - False: Explicitly disable 422
90
+ - True: Explicitly enable 422
85
91
  FastAPI automatically validates all parameters (Path, Query, Body), so 422 is relevant
86
92
  in 95%+ of endpoints. Set to False only for endpoints without parameters.
87
93
  internal_server_error_500: Add 500 Internal Server Error (explicit). Defaults to False.
@@ -205,6 +211,38 @@ class Errors(Mapping):
205
211
  f"Got {type(error).__name__}"
206
212
  )
207
213
 
214
+ def _unique_key(self, examples: Dict[str, Any], base: str) -> str:
215
+ """Generate unique key for examples dict.
216
+
217
+ Args:
218
+ examples: Existing examples dict
219
+ base: Base key name
220
+
221
+ Returns:
222
+ Unique key that doesn't exist in examples
223
+
224
+ Example:
225
+ >>> errors = Errors()
226
+ >>> errors._unique_key({"default": {}}, "default")
227
+ "default_2"
228
+ >>> errors._unique_key({"default": {}, "default_2": {}}, "default")
229
+ "default_3"
230
+ """
231
+ key = base
232
+ i = 2
233
+ while key in examples:
234
+ key = f"{base}_{i}"
235
+ i += 1
236
+ return key
237
+
238
+ # Standard descriptions for priority checking
239
+ STANDARD_DESCRIPTIONS = {
240
+ status.HTTP_401_UNAUTHORIZED: "Unauthorized",
241
+ status.HTTP_403_FORBIDDEN: "Forbidden",
242
+ status.HTTP_422_UNPROCESSABLE_ENTITY: "Validation Error",
243
+ status.HTTP_500_INTERNAL_SERVER_ERROR: "Internal Server Error",
244
+ }
245
+
208
246
  def _add_standard_error(
209
247
  self,
210
248
  status_code: int,
@@ -257,7 +295,9 @@ class Errors(Mapping):
257
295
  content["examples"] = {}
258
296
 
259
297
  # Add new example with unique key (don't overwrite existing!)
260
- content["examples"][example_key] = {"value": example}
298
+ # Check if example_key already exists in examples, use unique key if needed
299
+ unique_key = self._unique_key(content["examples"], example_key)
300
+ content["examples"][unique_key] = {"value": example}
261
301
 
262
302
  # Don't overwrite description if it already exists
263
303
  # Priority: dict > DTO > standard flags
@@ -334,7 +374,8 @@ class Errors(Mapping):
334
374
  existing_json["examples"]["default"] = {"value": response_json["example"]}
335
375
  else:
336
376
  # If default exists, add with a unique key
337
- existing_json["examples"]["CustomExample"] = {"value": response_json["example"]}
377
+ unique_key = self._unique_key(existing_json["examples"], "CustomExample")
378
+ existing_json["examples"][unique_key] = {"value": response_json["example"]}
338
379
 
339
380
  def _add_error_dto(self, error_dto: ErrorDTO) -> None:
340
381
  """Add error from ErrorDTO (via Protocol).
@@ -373,6 +414,11 @@ class Errors(Mapping):
373
414
  # Merge examples for the same status code
374
415
  # Safely access content/application/json with defaults
375
416
  existing = self._responses[status_code]
417
+
418
+ # If description is standard, replace it with DTO message (priority: DTO > flags)
419
+ if existing.get("description") == self.STANDARD_DESCRIPTIONS.get(status_code):
420
+ existing["description"] = error_dto.message
421
+
376
422
  existing_content = existing.setdefault("content", {})
377
423
  content_json = existing_content.setdefault("application/json", {})
378
424
  existing_examples = content_json.get("examples", {})
@@ -48,3 +48,4 @@ class ErrorDTO(Protocol):
48
48
  ...
49
49
 
50
50
 
51
+
File without changes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-errors-plus
3
- Version: 0.4.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
@@ -375,11 +375,11 @@ Errors(
375
375
  *errors: Union[Dict[int, Dict[str, Any]], ErrorDTO],
376
376
  unauthorized: bool = False,
377
377
  forbidden: bool = False,
378
- validation_error: bool = True, # Defaults to True (FastAPI validates all parameters)
378
+ validation_error: Optional[bool] = None, # None (default) => True (FastAPI validates all parameters)
379
379
  internal_server_error: bool = False,
380
380
  unauthorized_401: bool = False,
381
381
  forbidden_403: bool = False,
382
- validation_error_422: bool = True, # Defaults to True (FastAPI validates all parameters)
382
+ validation_error_422: Optional[bool] = None, # None (default) => True (FastAPI validates all parameters)
383
383
  internal_server_error_500: bool = False,
384
384
  )
385
385
  ```
@@ -388,18 +388,25 @@ Errors(
388
388
  - `*errors`: Arbitrary errors as dict or ErrorDTO objects
389
389
  - `unauthorized_401`: Add 401 Unauthorized error (recommended, explicit). Defaults to `False`.
390
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).
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
392
395
  - `internal_server_error_500`: Add 500 Internal Server Error (recommended, explicit). Defaults to `False`.
393
396
  - `unauthorized`: Add 401 Unauthorized error (legacy, for backward compatibility). Defaults to `False`.
394
397
  - `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).
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
396
402
  - `internal_server_error`: Add 500 Internal Server Error (legacy, for backward compatibility). Defaults to `False`.
397
403
 
398
404
  **Why `validation_error=True` by default?**
399
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`.
400
406
 
401
407
  **Returns:**
402
- - Callable object that returns `Dict[int, Dict[str, Any]]` in FastAPI responses format
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(...)`
403
410
 
404
411
  #### Usage
405
412
 
@@ -0,0 +1,10 @@
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,,
@@ -21,3 +21,4 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  SOFTWARE.
22
22
 
23
23
 
24
+
@@ -1,9 +0,0 @@
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,,