🐛 Fix TYPE_CHECKING annotations for Python 3.14 (PEP 649) (#14789)

This commit is contained in:
Mickaël Guérin 2026-02-04 14:49:44 +01:00 committed by GitHub
parent c944add5a9
commit 09f5941f0e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 46 additions and 5 deletions

View File

@ -204,7 +204,12 @@ 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
signature = inspect.signature(call)
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)
return signature

View File

@ -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

View File

@ -1,4 +1,5 @@
import importlib
import sys
from types import ModuleType
from typing import Annotated, Any
from unittest.mock import Mock, patch
@ -12,8 +13,13 @@ from fastapi.testclient import TestClient
name="module",
params=[
"tutorial008_py39",
# Fails with `NameError: name 'DepA' is not defined`
pytest.param("tutorial008_an_py39", marks=pytest.mark.xfail),
pytest.param(
"tutorial008_an_py39",
marks=pytest.mark.xfail(
sys.version_info < (3, 14),
reason="Fails with `NameError: name 'DepA' is not defined`",
),
),
],
)
def get_module(request: pytest.FixtureRequest):

View File

@ -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+"
)