crypticorn 2.5.0rc4__py3-none-any.whl → 2.5.0rc5__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.
- crypticorn/common/exceptions.py +19 -16
- {crypticorn-2.5.0rc4.dist-info → crypticorn-2.5.0rc5.dist-info}/METADATA +1 -1
- {crypticorn-2.5.0rc4.dist-info → crypticorn-2.5.0rc5.dist-info}/RECORD +6 -6
- {crypticorn-2.5.0rc4.dist-info → crypticorn-2.5.0rc5.dist-info}/WHEEL +0 -0
- {crypticorn-2.5.0rc4.dist-info → crypticorn-2.5.0rc5.dist-info}/entry_points.txt +0 -0
- {crypticorn-2.5.0rc4.dist-info → crypticorn-2.5.0rc5.dist-info}/top_level.txt +0 -0
crypticorn/common/exceptions.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
from enum import Enum
|
2
|
-
from typing import Optional, Dict, Type
|
2
|
+
from typing import Optional, Dict, Type, Any
|
3
3
|
from pydantic import BaseModel, Field
|
4
4
|
from fastapi import HTTPException as FastAPIHTTPException, Request, FastAPI
|
5
5
|
from fastapi.exceptions import RequestValidationError, ResponseValidationError
|
@@ -7,27 +7,30 @@ from fastapi.openapi.utils import get_openapi
|
|
7
7
|
from fastapi.responses import JSONResponse
|
8
8
|
from crypticorn.common import ApiError, ApiErrorIdentifier, ApiErrorType, ApiErrorLevel
|
9
9
|
|
10
|
-
class
|
10
|
+
class ExceptionDetail(BaseModel):
|
11
11
|
'''This is the detail of the exception. It is used to enrich the exception with additional information by unwrapping the ApiError into its components.'''
|
12
12
|
message: Optional[str] = Field(None, description="An additional error message")
|
13
13
|
code: ApiErrorIdentifier = Field(..., description="The unique error code")
|
14
14
|
type: ApiErrorType = Field(..., description="The type of error")
|
15
15
|
level: ApiErrorLevel = Field(..., description="The level of the error")
|
16
16
|
status_code: int = Field(..., description="The HTTP status code")
|
17
|
+
details: Any = Field(None, description="Additional details about the error")
|
17
18
|
|
18
19
|
|
19
|
-
class
|
20
|
+
class ExceptionContent(BaseModel):
|
20
21
|
'''This is the detail of the exception. Pass an ApiError to the constructor and an optional human readable message.'''
|
21
22
|
error: ApiError = Field(..., description="The unique error code")
|
22
23
|
message: Optional[str] = Field(None, description="An additional error message")
|
23
|
-
|
24
|
-
|
25
|
-
|
24
|
+
details: Any = Field(None, description="Additional details about the error")
|
25
|
+
|
26
|
+
def enrich(self) -> ExceptionDetail:
|
27
|
+
return ExceptionDetail(
|
26
28
|
message=self.message,
|
27
29
|
code=self.error.identifier,
|
28
30
|
type=self.error.type,
|
29
31
|
level=self.error.level,
|
30
32
|
status_code=self.error.status_code,
|
33
|
+
details=self.details,
|
31
34
|
)
|
32
35
|
|
33
36
|
class HTTPException(FastAPIHTTPException):
|
@@ -38,11 +41,11 @@ class HTTPException(FastAPIHTTPException):
|
|
38
41
|
|
39
42
|
def __init__(
|
40
43
|
self,
|
41
|
-
|
44
|
+
content: ExceptionContent,
|
42
45
|
headers: Optional[Dict[str, str]] = None,
|
43
46
|
):
|
44
|
-
assert isinstance(
|
45
|
-
body =
|
47
|
+
assert isinstance(content, ExceptionContent)
|
48
|
+
body = content.enrich()
|
46
49
|
super().__init__(
|
47
50
|
status_code=body.status_code,
|
48
51
|
detail=body.model_dump(mode="json"),
|
@@ -51,18 +54,18 @@ class HTTPException(FastAPIHTTPException):
|
|
51
54
|
|
52
55
|
async def general_handler(request: Request, exc: Exception):
|
53
56
|
'''This is the default exception handler for all exceptions.'''
|
54
|
-
body =
|
55
|
-
return JSONResponse(status_code=body.error.status_code, content=HTTPException(
|
57
|
+
body = ExceptionContent(message=str(exc), error=ApiError.UNKNOWN_ERROR)
|
58
|
+
return JSONResponse(status_code=body.error.status_code, content=HTTPException(content=body).detail)
|
56
59
|
|
57
60
|
async def request_validation_handler(request: Request, exc: RequestValidationError):
|
58
61
|
'''This is the exception handler for all request validation errors.'''
|
59
|
-
body =
|
60
|
-
return JSONResponse(status_code=body.error.status_code, content=HTTPException(
|
62
|
+
body = ExceptionContent(message=str(exc), error=ApiError.INVALID_DATA_REQUEST)
|
63
|
+
return JSONResponse(status_code=body.error.status_code, content=HTTPException(content=body).detail)
|
61
64
|
|
62
65
|
async def response_validation_handler(request: Request, exc: ResponseValidationError):
|
63
66
|
'''This is the exception handler for all response validation errors.'''
|
64
|
-
body =
|
65
|
-
return JSONResponse(status_code=body.error.status_code, content=HTTPException(
|
67
|
+
body = ExceptionContent(message=str(exc), error=ApiError.INVALID_DATA_RESPONSE)
|
68
|
+
return JSONResponse(status_code=body.error.status_code, content=HTTPException(content=body).detail)
|
66
69
|
|
67
70
|
async def http_handler(request: Request, exc: HTTPException):
|
68
71
|
'''This is the exception handler for HTTPExceptions. It unwraps the HTTPException and returns the detail in a flat JSON response.'''
|
@@ -76,5 +79,5 @@ def register_exception_handlers(app: FastAPI):
|
|
76
79
|
app.add_exception_handler(ResponseValidationError, response_validation_handler)
|
77
80
|
|
78
81
|
exception_response = {
|
79
|
-
"default": {"model":
|
82
|
+
"default": {"model": ExceptionDetail, "description": "Error response"}
|
80
83
|
}
|
@@ -63,7 +63,7 @@ crypticorn/common/__init__.py,sha256=ZR6znFCEMAJH-FuSMga0KaTpAXj3tl9Xz_4Xi820l9w
|
|
63
63
|
crypticorn/common/auth.py,sha256=q5DwgoIzveGWXCHpGl4xMPEABsjufptTqsR92MsOi6M,7618
|
64
64
|
crypticorn/common/enums.py,sha256=6cCwQZVdXUoN33WA8kSf4LeSZyExZcWO2ahSsgGddCs,1243
|
65
65
|
crypticorn/common/errors.py,sha256=sRlcNe84sJxU2ujikhjSG7eJ9GdOqOo5uv7duYDATBo,20645
|
66
|
-
crypticorn/common/exceptions.py,sha256=
|
66
|
+
crypticorn/common/exceptions.py,sha256=JbL5K9aE1kQkZpq6J6WDfMS3dh7ImmgUPcFMNfJ_Puc,4484
|
67
67
|
crypticorn/common/pydantic.py,sha256=pmnGYCIrLv59wZkDbvPyK9NJmgPJWW74LXTdIWSjOkY,1063
|
68
68
|
crypticorn/common/scopes.py,sha256=MgH9sGodJfPjEqVtFsaczNmwEaGL2wuGzeTpga_ehXs,2407
|
69
69
|
crypticorn/common/sorter.py,sha256=keRRp4u7KJk3nS2A8tMdSF8Hbc1jcsre8KdTVuetfGc,1278
|
@@ -283,8 +283,8 @@ crypticorn/trade/client/models/tpsl.py,sha256=LlqzHaSA-HgQp1k4PhRckmxWNhgVZU6NgB
|
|
283
283
|
crypticorn/trade/client/models/trading_action_type.py,sha256=oLVDp94VeC9kjYbgZN7dHn2t07YGGUrAkNr2PE435eM,827
|
284
284
|
crypticorn/trade/client/models/validation_error.py,sha256=x4rR325juK4EJiFJ8l5IKp2werY8y6PWbLx_WJMxbbA,3208
|
285
285
|
crypticorn/trade/client/models/validation_error_loc_inner.py,sha256=ZB2NbHkxhjDZ2-qK1HyvzTUnabeCdxeTjbSAHNmWq5A,5111
|
286
|
-
crypticorn-2.5.
|
287
|
-
crypticorn-2.5.
|
288
|
-
crypticorn-2.5.
|
289
|
-
crypticorn-2.5.
|
290
|
-
crypticorn-2.5.
|
286
|
+
crypticorn-2.5.0rc5.dist-info/METADATA,sha256=6Fa3y26orE2mUsmRabsklJ-vi6tPfJHLVRrmsjQ25zw,6210
|
287
|
+
crypticorn-2.5.0rc5.dist-info/WHEEL,sha256=SmOxYU7pzNKBqASvQJ7DjX3XGUF92lrGhMb3R6_iiqI,91
|
288
|
+
crypticorn-2.5.0rc5.dist-info/entry_points.txt,sha256=d_xHsGvUTebPveVUK0SrpDFQ5ZRSjlI7lNCc11sn2PM,59
|
289
|
+
crypticorn-2.5.0rc5.dist-info/top_level.txt,sha256=EP3NY216qIBYfmvGl0L2Zc9ItP0DjGSkiYqd9xJwGcM,11
|
290
|
+
crypticorn-2.5.0rc5.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|