[feature1] provide serialize context

This commit is contained in:
Ilia Merochkin 2024-06-01 17:22:12 +03:00
parent 563b355a75
commit b7df8eb110
3 changed files with 164 additions and 0 deletions

View File

@ -15,6 +15,7 @@ from typing import (
Tuple,
Type,
Union,
Optional,
)
from fastapi.exceptions import RequestErrorModel
@ -143,7 +144,9 @@ if PYDANTIC_V2:
exclude_unset: bool = False,
exclude_defaults: bool = False,
exclude_none: bool = False,
context: Optional[Dict[str, Any]] = None,
) -> Any:
kwargs = {"context": context} if PYDANTIC_VERSION >= "2.7.3" else {}
# What calls this code passes a value that already called
# self._type_adapter.validate_python(value)
return self._type_adapter.dump_python(
@ -155,6 +158,7 @@ if PYDANTIC_V2:
exclude_unset=exclude_unset,
exclude_defaults=exclude_defaults,
exclude_none=exclude_none,
**kwargs,
)
def __hash__(self) -> int:

View File

@ -1075,6 +1075,7 @@ class FastAPI(Starlette):
response_model_exclude_unset: bool = False,
response_model_exclude_defaults: bool = False,
response_model_exclude_none: bool = False,
response_model_context: Optional[Dict[str, Any]] = None,
include_in_schema: bool = True,
response_class: Union[Type[Response], DefaultPlaceholder] = Default(
JSONResponse
@ -1105,6 +1106,7 @@ class FastAPI(Starlette):
response_model_exclude_unset=response_model_exclude_unset,
response_model_exclude_defaults=response_model_exclude_defaults,
response_model_exclude_none=response_model_exclude_none,
response_model_context=response_model_context,
include_in_schema=include_in_schema,
response_class=response_class,
name=name,
@ -1133,6 +1135,7 @@ class FastAPI(Starlette):
response_model_exclude_unset: bool = False,
response_model_exclude_defaults: bool = False,
response_model_exclude_none: bool = False,
response_model_context: Optional[Dict[str, Any]] = None,
include_in_schema: bool = True,
response_class: Type[Response] = Default(JSONResponse),
name: Optional[str] = None,
@ -1162,6 +1165,7 @@ class FastAPI(Starlette):
response_model_exclude_unset=response_model_exclude_unset,
response_model_exclude_defaults=response_model_exclude_defaults,
response_model_exclude_none=response_model_exclude_none,
response_model_context=response_model_context,
include_in_schema=include_in_schema,
response_class=response_class,
name=name,
@ -1711,6 +1715,14 @@ class FastAPI(Starlette):
"""
),
] = False,
response_model_context: Annotated[
Optional[Dict[str, Any]],
Doc(
"""
Additional context to pass to Pydantic when creating the response.
"""
),
] = None,
include_in_schema: Annotated[
bool,
Doc(
@ -1822,6 +1834,7 @@ class FastAPI(Starlette):
response_model_exclude_unset=response_model_exclude_unset,
response_model_exclude_defaults=response_model_exclude_defaults,
response_model_exclude_none=response_model_exclude_none,
response_model_context=response_model_context,
include_in_schema=include_in_schema,
response_class=response_class,
name=name,
@ -2084,6 +2097,14 @@ class FastAPI(Starlette):
"""
),
] = False,
response_model_context: Annotated[
Optional[Dict[str, Any]],
Doc(
"""
Additional context to pass to Pydantic when creating the response.
"""
),
] = None,
include_in_schema: Annotated[
bool,
Doc(
@ -2200,6 +2221,7 @@ class FastAPI(Starlette):
response_model_exclude_unset=response_model_exclude_unset,
response_model_exclude_defaults=response_model_exclude_defaults,
response_model_exclude_none=response_model_exclude_none,
response_model_context=response_model_context,
include_in_schema=include_in_schema,
response_class=response_class,
name=name,
@ -2462,6 +2484,14 @@ class FastAPI(Starlette):
"""
),
] = False,
response_model_context: Annotated[
Optional[Dict[str, Any]],
Doc(
"""
Additional context to pass to Pydantic when creating the response.
"""
),
] = None,
include_in_schema: Annotated[
bool,
Doc(
@ -2578,6 +2608,7 @@ class FastAPI(Starlette):
response_model_exclude_unset=response_model_exclude_unset,
response_model_exclude_defaults=response_model_exclude_defaults,
response_model_exclude_none=response_model_exclude_none,
response_model_context=response_model_context,
include_in_schema=include_in_schema,
response_class=response_class,
name=name,
@ -2840,6 +2871,14 @@ class FastAPI(Starlette):
"""
),
] = False,
response_model_context: Annotated[
Optional[Dict[str, Any]],
Doc(
"""
Additional context to pass to Pydantic when creating the response.
"""
),
] = None,
include_in_schema: Annotated[
bool,
Doc(
@ -2951,6 +2990,7 @@ class FastAPI(Starlette):
response_model_exclude_unset=response_model_exclude_unset,
response_model_exclude_defaults=response_model_exclude_defaults,
response_model_exclude_none=response_model_exclude_none,
response_model_context=response_model_context,
include_in_schema=include_in_schema,
response_class=response_class,
name=name,
@ -3213,6 +3253,14 @@ class FastAPI(Starlette):
"""
),
] = False,
response_model_context: Annotated[
Optional[Dict[str, Any]],
Doc(
"""
Additional context to pass to Pydantic when creating the response.
"""
),
] = None,
include_in_schema: Annotated[
bool,
Doc(
@ -3324,6 +3372,7 @@ class FastAPI(Starlette):
response_model_exclude_unset=response_model_exclude_unset,
response_model_exclude_defaults=response_model_exclude_defaults,
response_model_exclude_none=response_model_exclude_none,
response_model_context=response_model_context,
include_in_schema=include_in_schema,
response_class=response_class,
name=name,
@ -3586,6 +3635,14 @@ class FastAPI(Starlette):
"""
),
] = False,
response_model_context: Annotated[
Optional[Dict[str, Any]],
Doc(
"""
Additional context to pass to Pydantic when creating the response.
"""
),
] = None,
include_in_schema: Annotated[
bool,
Doc(
@ -3698,6 +3755,7 @@ class FastAPI(Starlette):
response_model_exclude_defaults=response_model_exclude_defaults,
response_model_exclude_none=response_model_exclude_none,
include_in_schema=include_in_schema,
response_model_context=response_model_context,
response_class=response_class,
name=name,
callbacks=callbacks,
@ -3959,6 +4017,14 @@ class FastAPI(Starlette):
"""
),
] = False,
response_model_context: Annotated[
Optional[Dict[str, Any]],
Doc(
"""
Additional context to pass to Pydantic when creating the response.
"""
),
] = None,
include_in_schema: Annotated[
bool,
Doc(
@ -4075,6 +4141,7 @@ class FastAPI(Starlette):
response_model_exclude_unset=response_model_exclude_unset,
response_model_exclude_defaults=response_model_exclude_defaults,
response_model_exclude_none=response_model_exclude_none,
response_model_context=response_model_context,
include_in_schema=include_in_schema,
response_class=response_class,
name=name,
@ -4337,6 +4404,14 @@ class FastAPI(Starlette):
"""
),
] = False,
response_model_context: Annotated[
Optional[Dict[str, Any]],
Doc(
"""
Additional context to pass to Pydantic when creating the response.
"""
),
] = None,
include_in_schema: Annotated[
bool,
Doc(
@ -4448,6 +4523,7 @@ class FastAPI(Starlette):
response_model_exclude_unset=response_model_exclude_unset,
response_model_exclude_defaults=response_model_exclude_defaults,
response_model_exclude_none=response_model_exclude_none,
response_model_context=response_model_context,
include_in_schema=include_in_schema,
response_class=response_class,
name=name,

View File

@ -130,6 +130,7 @@ async def serialize_response(
exclude_defaults: bool = False,
exclude_none: bool = False,
is_coroutine: bool = True,
context: Optional[Dict[str, Any]] = None,
) -> Any:
if field:
errors = []
@ -165,6 +166,7 @@ async def serialize_response(
exclude_unset=exclude_unset,
exclude_defaults=exclude_defaults,
exclude_none=exclude_none,
context=context,
)
return jsonable_encoder(
@ -206,6 +208,7 @@ def get_request_handler(
response_model_exclude_defaults: bool = False,
response_model_exclude_none: bool = False,
dependency_overrides_provider: Optional[Any] = None,
response_model_context: Optional[Dict[str, Any]] = None,
) -> Callable[[Request], Coroutine[Any, Any, Response]]:
assert dependant.call is not None, "dependant.call must be a function"
is_coroutine = asyncio.iscoroutinefunction(dependant.call)
@ -303,6 +306,7 @@ def get_request_handler(
exclude_defaults=response_model_exclude_defaults,
exclude_none=response_model_exclude_none,
is_coroutine=is_coroutine,
context=response_model_context,
)
response = actual_response_class(content, **response_args)
if not is_body_allowed_for_status_code(response.status_code):
@ -410,6 +414,7 @@ class APIRoute(routing.Route):
response_model_exclude_unset: bool = False,
response_model_exclude_defaults: bool = False,
response_model_exclude_none: bool = False,
response_model_context: Optional[Dict[str, Any]] = None,
include_in_schema: bool = True,
response_class: Union[Type[Response], DefaultPlaceholder] = Default(
JSONResponse
@ -440,6 +445,7 @@ class APIRoute(routing.Route):
self.response_model_exclude_unset = response_model_exclude_unset
self.response_model_exclude_defaults = response_model_exclude_defaults
self.response_model_exclude_none = response_model_exclude_none
self.response_model_context = response_model_context
self.include_in_schema = include_in_schema
self.response_class = response_class
self.dependency_overrides_provider = dependency_overrides_provider
@ -532,6 +538,7 @@ class APIRoute(routing.Route):
response_model_exclude_unset=self.response_model_exclude_unset,
response_model_exclude_defaults=self.response_model_exclude_defaults,
response_model_exclude_none=self.response_model_exclude_none,
response_model_context=self.response_model_context,
dependency_overrides_provider=self.dependency_overrides_provider,
)
@ -850,6 +857,7 @@ class APIRouter(routing.Router):
response_model_exclude_unset: bool = False,
response_model_exclude_defaults: bool = False,
response_model_exclude_none: bool = False,
response_model_context: Optional[Dict[str, Any]] = None,
include_in_schema: bool = True,
response_class: Union[Type[Response], DefaultPlaceholder] = Default(
JSONResponse
@ -900,6 +908,7 @@ class APIRouter(routing.Router):
response_model_exclude_unset=response_model_exclude_unset,
response_model_exclude_defaults=response_model_exclude_defaults,
response_model_exclude_none=response_model_exclude_none,
response_model_context=response_model_context,
include_in_schema=include_in_schema and self.include_in_schema,
response_class=current_response_class,
name=name,
@ -931,6 +940,7 @@ class APIRouter(routing.Router):
response_model_exclude_unset: bool = False,
response_model_exclude_defaults: bool = False,
response_model_exclude_none: bool = False,
response_model_context: Optional[Dict[str, Any]] = None,
include_in_schema: bool = True,
response_class: Type[Response] = Default(JSONResponse),
name: Optional[str] = None,
@ -961,6 +971,7 @@ class APIRouter(routing.Router):
response_model_exclude_unset=response_model_exclude_unset,
response_model_exclude_defaults=response_model_exclude_defaults,
response_model_exclude_none=response_model_exclude_none,
response_model_context=response_model_context,
include_in_schema=include_in_schema,
response_class=response_class,
name=name,
@ -1269,6 +1280,7 @@ class APIRouter(routing.Router):
response_model_exclude_unset=route.response_model_exclude_unset,
response_model_exclude_defaults=route.response_model_exclude_defaults,
response_model_exclude_none=route.response_model_exclude_none,
response_model_context=route.response_model_context,
include_in_schema=route.include_in_schema
and self.include_in_schema
and include_in_schema,
@ -1563,6 +1575,14 @@ class APIRouter(routing.Router):
"""
),
] = False,
response_model_context: Annotated[
Optional[Dict[str, Any]],
Doc(
"""
Additional context to pass to Pydantic when creating the response.
"""
),
] = None,
include_in_schema: Annotated[
bool,
Doc(
@ -1678,6 +1698,7 @@ class APIRouter(routing.Router):
response_model_exclude_unset=response_model_exclude_unset,
response_model_exclude_defaults=response_model_exclude_defaults,
response_model_exclude_none=response_model_exclude_none,
response_model_context=response_model_context,
include_in_schema=include_in_schema,
response_class=response_class,
name=name,
@ -1940,6 +1961,14 @@ class APIRouter(routing.Router):
"""
),
] = False,
response_model_context: Annotated[
Optional[Dict[str, Any]],
Doc(
"""
Additional context to pass to Pydantic when creating the response.
"""
),
] = None,
include_in_schema: Annotated[
bool,
Doc(
@ -2060,6 +2089,7 @@ class APIRouter(routing.Router):
response_model_exclude_unset=response_model_exclude_unset,
response_model_exclude_defaults=response_model_exclude_defaults,
response_model_exclude_none=response_model_exclude_none,
response_model_context=response_model_context,
include_in_schema=include_in_schema,
response_class=response_class,
name=name,
@ -2322,6 +2352,14 @@ class APIRouter(routing.Router):
"""
),
] = False,
response_model_context: Annotated[
Optional[Dict[str, Any]],
Doc(
"""
Additional context to pass to Pydantic when creating the response.
"""
),
] = None,
include_in_schema: Annotated[
bool,
Doc(
@ -2442,6 +2480,7 @@ class APIRouter(routing.Router):
response_model_exclude_unset=response_model_exclude_unset,
response_model_exclude_defaults=response_model_exclude_defaults,
response_model_exclude_none=response_model_exclude_none,
response_model_context=response_model_context,
include_in_schema=include_in_schema,
response_class=response_class,
name=name,
@ -2704,6 +2743,14 @@ class APIRouter(routing.Router):
"""
),
] = False,
response_model_context: Annotated[
Optional[Dict[str, Any]],
Doc(
"""
Additional context to pass to Pydantic when creating the response.
"""
),
] = None,
include_in_schema: Annotated[
bool,
Doc(
@ -2819,6 +2866,7 @@ class APIRouter(routing.Router):
response_model_exclude_unset=response_model_exclude_unset,
response_model_exclude_defaults=response_model_exclude_defaults,
response_model_exclude_none=response_model_exclude_none,
response_model_context=response_model_context,
include_in_schema=include_in_schema,
response_class=response_class,
name=name,
@ -3081,6 +3129,14 @@ class APIRouter(routing.Router):
"""
),
] = False,
response_model_context: Annotated[
Optional[Dict[str, Any]],
Doc(
"""
Additional context to pass to Pydantic when creating the response.
"""
),
] = None,
include_in_schema: Annotated[
bool,
Doc(
@ -3196,6 +3252,7 @@ class APIRouter(routing.Router):
response_model_exclude_unset=response_model_exclude_unset,
response_model_exclude_defaults=response_model_exclude_defaults,
response_model_exclude_none=response_model_exclude_none,
response_model_context=response_model_context,
include_in_schema=include_in_schema,
response_class=response_class,
name=name,
@ -3458,6 +3515,14 @@ class APIRouter(routing.Router):
"""
),
] = False,
response_model_context: Annotated[
Optional[Dict[str, Any]],
Doc(
"""
Additional context to pass to Pydantic when creating the response.
"""
),
] = None,
include_in_schema: Annotated[
bool,
Doc(
@ -3578,6 +3643,7 @@ class APIRouter(routing.Router):
response_model_exclude_unset=response_model_exclude_unset,
response_model_exclude_defaults=response_model_exclude_defaults,
response_model_exclude_none=response_model_exclude_none,
response_model_context=response_model_context,
include_in_schema=include_in_schema,
response_class=response_class,
name=name,
@ -3840,6 +3906,14 @@ class APIRouter(routing.Router):
"""
),
] = False,
response_model_context: Annotated[
Optional[Dict[str, Any]],
Doc(
"""
Additional context to pass to Pydantic when creating the response.
"""
),
] = None,
include_in_schema: Annotated[
bool,
Doc(
@ -3960,6 +4034,7 @@ class APIRouter(routing.Router):
response_model_exclude_unset=response_model_exclude_unset,
response_model_exclude_defaults=response_model_exclude_defaults,
response_model_exclude_none=response_model_exclude_none,
response_model_context=response_model_context,
include_in_schema=include_in_schema,
response_class=response_class,
name=name,
@ -4222,6 +4297,14 @@ class APIRouter(routing.Router):
"""
),
] = False,
response_model_context: Annotated[
Optional[Dict[str, Any]],
Doc(
"""
Additional context to pass to Pydantic when creating the response.
"""
),
] = None,
include_in_schema: Annotated[
bool,
Doc(
@ -4342,6 +4425,7 @@ class APIRouter(routing.Router):
response_model_exclude_unset=response_model_exclude_unset,
response_model_exclude_defaults=response_model_exclude_defaults,
response_model_exclude_none=response_model_exclude_none,
response_model_context=response_model_context,
include_in_schema=include_in_schema,
response_class=response_class,
name=name,