From 1ff1e0c9617e431aee61e3caff569c7a5b7dbafb Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 19 Dec 2024 01:18:46 +0100 Subject: [PATCH] Changes: cleanup responses --- esmerald/responses/base.py | 39 ++++++++++++++------------------- esmerald/responses/encoders.py | 40 ++++++++++++++++------------------ esmerald/responses/json.py | 21 +----------------- pyproject.toml | 2 +- 4 files changed, 37 insertions(+), 65 deletions(-) diff --git a/esmerald/responses/base.py b/esmerald/responses/base.py index 042d2c28..2e962a81 100644 --- a/esmerald/responses/base.py +++ b/esmerald/responses/base.py @@ -14,6 +14,7 @@ from lilya import status from lilya.responses import ( + RESPONSE_TRANSFORM_KWARGS, Error as Error, FileResponse as FileResponse, # noqa HTMLResponse as HTMLResponse, # noqa @@ -27,7 +28,7 @@ from orjson import OPT_OMIT_MICROSECONDS, OPT_SERIALIZE_NUMPY, dumps, loads from typing_extensions import Annotated, Doc -from esmerald.encoders import LILYA_ENCODER_TYPES, Encoder, json_encoder +from esmerald.encoders import Encoder, json_encoder from esmerald.enums import MediaType from esmerald.exceptions import ImproperlyConfigured @@ -193,19 +194,7 @@ def transform( ), ) - def make_response(self, content: Any) -> Union[bytes, str]: - # here we need lilyas encoders not only esmerald encoders - # in case no extra encoders are defined use the default by passing None - encoders = ( - ( - ( - *self.encoders, - *LILYA_ENCODER_TYPES.get(), - ) - ) - if self.encoders - else None - ) + def make_response(self, content: Any) -> bytes: try: if ( content is None @@ -219,17 +208,21 @@ def make_response(self, content: Any) -> Union[bytes, str]: return b"" # switch to a special mode for MediaType.JSON if self.media_type == MediaType.JSON: - return cast( - bytes, - json_encoder( - content, - json_encode_fn=partial( - dumps, option=OPT_SERIALIZE_NUMPY | OPT_OMIT_MICROSECONDS - ), - post_transform_fn=None, - with_encoders=encoders, + transform_kwargs = RESPONSE_TRANSFORM_KWARGS.get() + if transform_kwargs: + transform_kwargs = transform_kwargs.copy() + else: + transform_kwargs = {} + transform_kwargs.setdefault( + "json_encode_fn", + partial( + dumps, + option=OPT_SERIALIZE_NUMPY | OPT_OMIT_MICROSECONDS, ), ) + # less strict + transform_kwargs.setdefault("post_transform_fn", None) + return cast(bytes, json_encoder(content, **transform_kwargs)) return super().make_response(content) except (AttributeError, ValueError, TypeError) as e: # pragma: no cover raise ImproperlyConfigured("Unable to serialize response content") from e diff --git a/esmerald/responses/encoders.py b/esmerald/responses/encoders.py index 011ae03d..1bfbd03c 100644 --- a/esmerald/responses/encoders.py +++ b/esmerald/responses/encoders.py @@ -1,7 +1,8 @@ from functools import partial -from typing import Any, cast +from typing import Any, NoReturn, cast import orjson +from lilya.responses import RESPONSE_TRANSFORM_KWARGS from esmerald.encoders import LILYA_ENCODER_TYPES, json_encoder from esmerald.responses.json import BaseJSONResponse @@ -20,28 +21,25 @@ class ORJSONResponse(BaseJSONResponse): """ def make_response(self, content: Any) -> bytes: - # here we need lilyas encoders not only esmerald encoders - encoders = ( - ( - ( - *self.encoders, - *LILYA_ENCODER_TYPES.get(), - ) - ) - if self.encoders - else None - ) - return cast( - bytes, - json_encoder( - content, - json_encode_fn=partial( - orjson.dumps, option=orjson.OPT_SERIALIZE_NUMPY | orjson.OPT_OMIT_MICROSECONDS - ), - post_transform_fn=None, - with_encoders=encoders, + new_params = RESPONSE_TRANSFORM_KWARGS.get() + if new_params: + new_params = new_params.copy() + else: + new_params = {} + new_params.setdefault( + "json_encode_fn", + partial( + orjson.dumps, + option=orjson.OPT_SERIALIZE_NUMPY | orjson.OPT_OMIT_MICROSECONDS, ), ) + # TODO: cleanup after new lilya release, just use with_transform_kwargs + new_params["post_transform_fn"] = None + if content is NoReturn: + return b"" + if self.encoders: + new_params["with_encoders"] = (*self.encoders, *LILYA_ENCODER_TYPES.get()) + return cast(bytes, json_encoder(content, **new_params)) class UJSONResponse(BaseJSONResponse): diff --git a/esmerald/responses/json.py b/esmerald/responses/json.py index 2b7a7df0..0eb661f0 100644 --- a/esmerald/responses/json.py +++ b/esmerald/responses/json.py @@ -1,22 +1,3 @@ -from typing import Any, Dict, cast - -from lilya.responses import JSONResponse - -from esmerald.encoders import json_encoder - - -class BaseJSONResponse(JSONResponse): - """ - Making sure it parses all the values from pydantic into dictionary. - """ - - @staticmethod - def transform(value: Any) -> Dict[str, Any]: # pragma: no cover - """ - Makes sure that every value is checked and if it's a pydantic model then parses into - a dict(). - """ - return cast(Dict[str, Any], json_encoder(value)) - +from lilya.responses import JSONResponse as BaseJSONResponse __all__ = ["BaseJSONResponse"] diff --git a/pyproject.toml b/pyproject.toml index b1a61876..66859a4c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,7 +41,7 @@ dependencies = [ "email-validator >=2.2.0,<3.0.0", "itsdangerous>=2.1.2,<3.0.0", "jinja2>=3.1.2,<4.0.0", - "lilya>=0.11.6", + "lilya>=0.11.7", "loguru>=0.7.0,<0.8.0", "pydantic>=2.10,<3.0.0", "pydantic-settings>=2.0.0,<3.0.0",