Browse Source

Fix forward references inside Annotated dependencies (fixes #13056)

pull/14703/head
AnshMNSoni 6 months ago
parent
commit
62d3a23f09
  1. 12
      fastapi/dependencies/utils.py
  2. 28
      tests/test_annotated_forwardref.py

12
fastapi/dependencies/utils.py

@ -5,6 +5,7 @@ from collections.abc import Coroutine, Mapping, Sequence
from contextlib import AsyncExitStack, contextmanager from contextlib import AsyncExitStack, contextmanager
from copy import copy, deepcopy from copy import copy, deepcopy
from dataclasses import dataclass from dataclasses import dataclass
from typing import get_type_hints
from typing import ( from typing import (
Annotated, Annotated,
Any, Any,
@ -270,8 +271,19 @@ def get_dependant(
current_scopes = (parent_oauth_scopes or []) + (own_oauth_scopes or []) current_scopes = (parent_oauth_scopes or []) + (own_oauth_scopes or [])
path_param_names = get_path_param_names(path) path_param_names = get_path_param_names(path)
endpoint_signature = get_typed_signature(call) endpoint_signature = get_typed_signature(call)
# Resolve forward references inside Annotated (fix for issue #13056)
try:
type_hints = get_type_hints(call, include_extras=True)
except Exception:
type_hints = {}
signature_params = endpoint_signature.parameters signature_params = endpoint_signature.parameters
for param_name, param in signature_params.items(): for param_name, param in signature_params.items():
# Inject fully resolved Annotated types (including forward refs)
if param_name in type_hints:
param = param.replace(annotation=type_hints[param_name])
is_path_param = param_name in path_param_names is_path_param = param_name in path_param_names
param_details = analyze_param( param_details = analyze_param(
param_name=param_name, param_name=param_name,

28
tests/test_annotated_forwardref.py

@ -0,0 +1,28 @@
from __future__ import annotations
from dataclasses import dataclass
from typing import Annotated
from fastapi import Depends, FastAPI
from fastapi.testclient import TestClient
def test_annotated_forwardref_dependency():
app = FastAPI()
def get_item() -> Item:
return Item(name="apple")
@app.get("/")
def read(item: Annotated[Item, Depends(get_item)]):
return {"name": item.name}
@dataclass
class Item:
name: str
client = TestClient(app)
response = client.get("/")
assert response.status_code == 200
assert response.json() == {"name": "apple"}
Loading…
Cancel
Save