Reduce the diff, simplify `init_attributes`, fix `create_cloned_field` comment

This commit is contained in:
Yurii Motov 2025-10-02 14:09:16 +02:00
parent 3d6472e375
commit 61bc1184d5
1 changed files with 39 additions and 40 deletions

View File

@ -596,29 +596,6 @@ class APIRoute(routing.Route):
if not defer_init:
self.init_attributes()
def get_route_handler(self) -> Callable[[Request], Coroutine[Any, Any, Response]]:
return get_request_handler(
dependant=self.dependant,
body_field=self.body_field,
status_code=self.status_code,
response_class=self.response_class,
response_field=self.secure_cloned_response_field,
response_model_include=self.response_model_include,
response_model_exclude=self.response_model_exclude,
response_model_by_alias=self.response_model_by_alias,
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,
dependency_overrides_provider=self.dependency_overrides_provider,
embed_body_fields=self._embed_body_fields,
)
def matches(self, scope: Scope) -> Tuple[Match, Scope]:
match, child_scope = super().matches(scope)
if match != Match.NONE:
child_scope["route"] = self
return match, child_scope
@cached_property
def response_field(self) -> Optional[ModelField]:
if not self.response_model:
@ -630,16 +607,16 @@ class APIRoute(routing.Route):
mode="serialization",
)
# Create a clone of the field, so that a Pydantic submodel is not returned
# as is just because it's an instance of a subclass of a more limited class
# e.g. UserInDB (containing hashed_password) could be a subclass of User
# that doesn't have the hashed_password. But because it's a subclass, it
# would pass the validation and be returned as is.
# By being a new field, no inheritance will be passed as is. A new model
# will always be created.
# TODO: remove when deprecating Pydantic v1
@cached_property
def secure_cloned_response_field(self) -> Optional[ModelField]:
# Create a clone of the field, so that a Pydantic submodel is not returned
# as is just because it's an instance of a subclass of a more limited class
# e.g. UserInDB (containing hashed_password) could be a subclass of User
# that doesn't have the hashed_password. But because it's a subclass, it
# would pass the validation and be returned as is.
# By being a new field, no inheritance will be passed as is. A new model
# will always be created.
# TODO: remove when deprecating Pydantic v1
return create_cloned_field(self.response_field) if self.response_field else None
@cached_property
@ -652,7 +629,6 @@ class APIRoute(routing.Route):
assert is_body_allowed_for_status_code(additional_status_code), (
f"Status code {additional_status_code} must not have a response body"
)
response_name = f"Response_{additional_status_code}_{self.unique_id}"
response_field = create_model_field(
name=response_name, type_=model, mode="serialization"
@ -691,14 +667,37 @@ class APIRoute(routing.Route):
return request_response(self.get_route_handler())
def init_attributes(self) -> None:
self.app = self.app
self.dependant = self.dependant
self.response_field = self.response_field
self.response_fields = self.response_fields
self.secure_cloned_response_field = self.secure_cloned_response_field
self.body_field = self.body_field
self._flat_dependant = self._flat_dependant
self._embed_body_fields = self._embed_body_fields
_ = self.app
_ = self.dependant
_ = self.response_field
_ = self.response_fields
_ = self.secure_cloned_response_field
_ = self.body_field
_ = self._flat_dependant
_ = self._embed_body_fields
def get_route_handler(self) -> Callable[[Request], Coroutine[Any, Any, Response]]:
return get_request_handler(
dependant=self.dependant,
body_field=self.body_field,
status_code=self.status_code,
response_class=self.response_class,
response_field=self.secure_cloned_response_field,
response_model_include=self.response_model_include,
response_model_exclude=self.response_model_exclude,
response_model_by_alias=self.response_model_by_alias,
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,
dependency_overrides_provider=self.dependency_overrides_provider,
embed_body_fields=self._embed_body_fields,
)
def matches(self, scope: Scope) -> Tuple[Match, Scope]:
match, child_scope = super().matches(scope)
if match != Match.NONE:
child_scope["route"] = self
return match, child_scope
class APIRouter(routing.Router):