Browse Source

Enhance response model inference logic in APIRoute and utils

- Updated the response model inference in APIRoute to check for return annotations before inferring the model from the endpoint's source code.
- Added type ignore comments in utils for better type checking compatibility.
- Specified the type of nodes_to_visit in the infer_response_model_from_ast function for improved clarity.
pull/14446/head
g7azazlo 8 months ago
parent
commit
65a9b03c57
  1. 7
      fastapi/routing.py
  2. 8
      fastapi/utils.py

7
fastapi/routing.py

@ -549,9 +549,10 @@ 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)
): ):
inferred = infer_response_model_from_ast(endpoint) if return_annotation is not None:
if inferred: inferred = infer_response_model_from_ast(endpoint)
response_model = inferred if inferred:
response_model = inferred
self.response_model = response_model self.response_model = response_model
self.summary = summary self.summary = summary

8
fastapi/utils.py

@ -283,7 +283,7 @@ def _infer_type_from_ast(
return List[Any] return List[Any]
if first_type is not Any: if first_type is not Any:
return List[first_type] return List[first_type] # type: ignore
return List[Any] return List[Any]
if isinstance(node, ast.BinOp): if isinstance(node, ast.BinOp):
@ -316,7 +316,7 @@ def _infer_type_from_ast(
else: else:
from pydantic import create_model from pydantic import create_model
return create_model(f"Model_{context_name}", **fields) return create_model(f"Model_{context_name}", **fields) # type: ignore[call-overload]
if isinstance(node, ast.Name): if isinstance(node, ast.Name):
arg_name = node.id arg_name = node.id
@ -366,7 +366,7 @@ def infer_response_model_from_ast(
return_stmt = None return_stmt = None
nodes_to_visit = list(func_def.body) nodes_to_visit: List[ast.AST] = list(func_def.body)
while nodes_to_visit: while nodes_to_visit:
node = nodes_to_visit.pop(0) node = nodes_to_visit.pop(0)
@ -436,6 +436,6 @@ def infer_response_model_from_ast(
model_name = f"ResponseModel_{endpoint_function.__name__}" model_name = f"ResponseModel_{endpoint_function.__name__}"
try: try:
return create_model(model_name, **fields) return create_model(model_name, **fields) # type: ignore[call-overload,no-any-return]
except Exception: except Exception:
return None return None

Loading…
Cancel
Save