Browse Source

Enhance response model inference in APIRoute and utils

- Introduced a new helper function `_contains_response` to check for response types in return annotations, improving the inference logic in `APIRoute`.
- Updated the `infer_response_model_from_ast` function to prevent model creation when all fields are of type `Any`, ensuring better type information and avoiding unnecessary overrides.
pull/14446/head
g7azazlo 8 months ago
parent
commit
7e36726baa
  1. 18
      fastapi/routing.py
  2. 6
      fastapi/utils.py

18
fastapi/routing.py

@ -21,6 +21,8 @@ from typing import (
Tuple, Tuple,
Type, Type,
Union, Union,
get_args,
get_origin,
) )
from annotated_doc import Doc from annotated_doc import Doc
@ -122,6 +124,18 @@ def request_response(
return app return app
def _contains_response(annotation: Any) -> bool:
if lenient_issubclass(annotation, Response):
return True
args = get_args(annotation)
for arg in args:
if _contains_response(arg):
return True
return False
# Copy of starlette.routing.websocket_session modified to include the # Copy of starlette.routing.websocket_session modified to include the
# dependencies' AsyncExitStack # dependencies' AsyncExitStack
def websocket_session( def websocket_session(
@ -549,7 +563,9 @@ class APIRoute(routing.Route):
not lenient_issubclass(response_model, BaseModel) not lenient_issubclass(response_model, BaseModel)
and not dataclasses.is_dataclass(response_model) and not dataclasses.is_dataclass(response_model)
): ):
if return_annotation is not None: if return_annotation is not None and not _contains_response(
return_annotation
):
inferred = infer_response_model_from_ast(endpoint) inferred = infer_response_model_from_ast(endpoint)
if inferred: if inferred:
response_model = inferred response_model = inferred

6
fastapi/utils.py

@ -429,6 +429,12 @@ def infer_response_model_from_ast(
if not fields: if not fields:
return None return None
# Don't create a model if all fields are Any - this provides no additional
# type information compared to Dict[str, Any] and would override explicit
# type annotations unnecessarily
if all(field_type is Any for field_type, _ in fields.values()):
return None
if PYDANTIC_V2: if PYDANTIC_V2:
from pydantic import create_model from pydantic import create_model
else: else:

Loading…
Cancel
Save