From: Albin Skott Date: Thu, 5 Feb 2026 18:34:34 +0000 (+0100) Subject: ✨ Add support for PEP695 `TypeAliasType` (#13920) X-Git-Tag: 0.128.2~10 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=97145588f5442aa7c3830173813d5d1a2c893521;p=thirdparty%2Ffastapi%2Ffastapi.git ✨ Add support for PEP695 `TypeAliasType` (#13920) Co-authored-by: lokidev Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Yurii Motov Co-authored-by: Sebastián Ramírez --- diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index 3037b233b9..e5ac51d53c 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -66,6 +66,7 @@ from starlette.requests import HTTPConnection, Request from starlette.responses import Response from starlette.websockets import WebSocket from typing_extensions import Literal, get_args, get_origin +from typing_inspection.typing_objects import is_typealiastype multipart_not_installed_error = ( 'Form data requires "python-multipart" to be installed. \n' @@ -370,6 +371,9 @@ def analyze_param( depends = None type_annotation: Any = Any use_annotation: Any = Any + if is_typealiastype(annotation): + # unpack in case PEP 695 type syntax is used + annotation = annotation.__value__ if annotation is not inspect.Signature.empty: use_annotation = annotation type_annotation = annotation diff --git a/pyproject.toml b/pyproject.toml index 0f6bf1e4ac..e62baa5f85 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,6 +46,7 @@ dependencies = [ "starlette>=0.40.0,<0.51.0", "pydantic>=2.7.0", "typing-extensions>=4.8.0", + "typing-inspection>=0.4.2", "annotated-doc>=0.0.2", ] diff --git a/tests/test_dependency_pep695.py b/tests/test_dependency_pep695.py new file mode 100644 index 0000000000..ef5636638e --- /dev/null +++ b/tests/test_dependency_pep695.py @@ -0,0 +1,27 @@ +from typing import Annotated + +from fastapi import Depends, FastAPI +from fastapi.testclient import TestClient +from typing_extensions import TypeAliasType + + +async def some_value() -> int: + return 123 + + +DependedValue = TypeAliasType( + "DependedValue", Annotated[int, Depends(some_value)], type_params=() +) + + +def test_pep695_type_dependencies(): + app = FastAPI() + + @app.get("/") + async def get_with_dep(value: DependedValue) -> str: # noqa + return f"value: {value}" + + client = TestClient(app) + response = client.get("/") + assert response.status_code == 200 + assert response.text == '"value: 123"' diff --git a/uv.lock b/uv.lock index 931a27021b..db5d2e9b1a 100644 --- a/uv.lock +++ b/uv.lock @@ -1021,6 +1021,7 @@ dependencies = [ { name = "starlette", version = "0.49.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "starlette", version = "0.50.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "typing-extensions" }, + { name = "typing-inspection" }, ] [package.optional-dependencies] @@ -1202,6 +1203,7 @@ requires-dist = [ { name = "pyyaml", marker = "extra == 'all'", specifier = ">=5.3.1" }, { name = "starlette", specifier = ">=0.40.0,<0.51.0" }, { name = "typing-extensions", specifier = ">=4.8.0" }, + { name = "typing-inspection", specifier = ">=0.4.2" }, { name = "ujson", marker = "extra == 'all'", specifier = ">=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0" }, { name = "uvicorn", extras = ["standard"], marker = "extra == 'all'", specifier = ">=0.12.0" }, { name = "uvicorn", extras = ["standard"], marker = "extra == 'standard'", specifier = ">=0.12.0" },