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
--- /dev/null
+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
import importlib
+import sys
from types import ModuleType
from typing import Annotated, Any
from unittest.mock import Mock, patch
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):
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+"
)