Browse Source

Fix support for unevaluated stringified annotations (Python 3.14)

PR #14485 fixed support for if TYPE_CHECKING, non-evaluated stringified
annotations, when using `from __future__ import annotations`.

This change adds the same support when using deferred evaluation of
annotations introduced in Python 3.14
pull/14789/head
Mickael Guerin 6 months ago
committed by Mickaël Guérin
parent
commit
5567c7d129
  1. 5
      fastapi/dependencies/utils.py
  2. 30
      tests/test_stringified_annotation_dependency_py314.py
  3. 4
      tests/utils.py

5
fastapi/dependencies/utils.py

@ -204,6 +204,11 @@ def _get_signature(call: Callable[..., Any]) -> inspect.Signature:
except NameError:
# Handle type annotations with if TYPE_CHECKING, not used by FastAPI
# e.g. dependency return types
if sys.version_info >= (3, 14):
from annotationlib import Format
signature = inspect.signature(call, annotation_format=Format.FORWARDREF)
else:
signature = inspect.signature(call)
else:
signature = inspect.signature(call)

30
tests/test_stringified_annotation_dependency_py314.py

@ -0,0 +1,30 @@
from typing import TYPE_CHECKING, Annotated
from fastapi import Depends, FastAPI
from fastapi.testclient import TestClient
from .utils import needs_py314
if TYPE_CHECKING: # pragma: no cover
class DummyUser: ...
@needs_py314
def test_stringified_annotation():
# python3.14: Use forward reference without "from __future__ import annotations"
async def get_current_user() -> DummyUser | None:
return None
app = FastAPI()
client = TestClient(app)
@app.get("/")
async def get(
current_user: Annotated[DummyUser | None, Depends(get_current_user)],
) -> str:
return "hello world"
response = client.get("/")
assert response.status_code == 200

4
tests/utils.py

@ -6,8 +6,8 @@ needs_py39 = pytest.mark.skipif(sys.version_info < (3, 9), reason="requires pyth
needs_py310 = pytest.mark.skipif(
sys.version_info < (3, 10), reason="requires python3.10+"
)
needs_py_lt_314 = pytest.mark.skipif(
sys.version_info >= (3, 14), reason="requires python3.13-"
needs_py314 = pytest.mark.skipif(
sys.version_info < (3, 14), reason="requires python3.14+"
)

Loading…
Cancel
Save