Browse Source

fix: support unresolved forward refs in annotated dependencies

pull/15550/head
Nisar k 3 weeks ago
parent
commit
4543539546
  1. 11
      fastapi/dependencies/utils.py
  2. 60
      tests/test_stringified_annotation_dependency.py

11
fastapi/dependencies/utils.py

@ -242,10 +242,21 @@ def get_typed_signature(call: Callable[..., Any]) -> inspect.Signature:
return typed_signature
class _DictWithForwardRefs(dict[str, Any]):
def __missing__(self, key: str) -> Any:
value = ForwardRef(key)
self[key] = value
return value
def get_typed_annotation(annotation: Any, globalns: dict[str, Any]) -> Any:
if isinstance(annotation, str):
annotation_string = annotation
annotation = ForwardRef(annotation)
annotation = evaluate_forwardref(annotation, globalns, globalns)
if isinstance(annotation, ForwardRef) and "Annotated" in annotation_string:
annotationns = _DictWithForwardRefs(globalns)
annotation = eval(annotation_string, annotationns, annotationns)
if annotation is type(None):
return None
return annotation

60
tests/test_stringified_annotation_dependency.py

@ -1,5 +1,6 @@
from __future__ import annotations
from dataclasses import dataclass
from typing import TYPE_CHECKING, Annotated
import pytest
@ -27,6 +28,25 @@ async def get_client() -> AsyncGenerator[DummyClient, None]:
Client = Annotated[DummyClient, Depends(get_client)]
app_with_late_forward_ref = FastAPI()
def get_potato() -> Potato:
return Potato(color="red", size=10)
@app_with_late_forward_ref.get("/")
async def get_late_forward_ref(
potato: Annotated[Potato, Depends(get_potato)],
) -> dict[str, str]:
return {"color": potato.color}
@dataclass
class Potato:
color: str
size: int
@pytest.fixture(name="client")
def client_fixture() -> TestClient:
@ -77,3 +97,43 @@ def test_openapi_schema(client: TestClient):
},
}
)
def test_late_forward_ref_dependency():
client = TestClient(app_with_late_forward_ref)
response = client.get("/")
assert response.status_code == 200, response.text
assert response.json() == {"color": "red"}
def test_late_forward_ref_dependency_openapi():
assert app_with_late_forward_ref.openapi() == snapshot(
{
"openapi": "3.1.0",
"info": {"title": "FastAPI", "version": "0.1.0"},
"paths": {
"/": {
"get": {
"summary": "Get Late Forward Ref",
"operationId": "get_late_forward_ref__get",
"responses": {
"200": {
"description": "Successful Response",
"content": {
"application/json": {
"schema": {
"additionalProperties": {"type": "string"},
"type": "object",
"title": "Response Get Late Forward Ref Get",
}
}
},
}
},
}
}
},
}
)

Loading…
Cancel
Save