Browse Source

Merge 50b9bd5d8b into 6df50d40fe

pull/13920/merge
Albin Skott 5 days ago
committed by GitHub
parent
commit
59d370458b
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 36
      fastapi/dependencies/utils.py
  2. 27
      tests/test_dependency_pep695.py

36
fastapi/dependencies/utils.py

@ -1,4 +1,6 @@
import inspect import inspect
import sys
import typing
from contextlib import AsyncExitStack, contextmanager from contextlib import AsyncExitStack, contextmanager
from copy import copy, deepcopy from copy import copy, deepcopy
from dataclasses import dataclass from dataclasses import dataclass
@ -19,6 +21,7 @@ from typing import (
) )
import anyio import anyio
import typing_extensions
from fastapi import params from fastapi import params
from fastapi._compat import ( from fastapi._compat import (
PYDANTIC_V2, PYDANTIC_V2,
@ -71,7 +74,12 @@ from starlette.datastructures import (
from starlette.requests import HTTPConnection, Request from starlette.requests import HTTPConnection, Request
from starlette.responses import Response from starlette.responses import Response
from starlette.websockets import WebSocket from starlette.websockets import WebSocket
from typing_extensions import Annotated, get_args, get_origin from typing_extensions import Annotated, TypeAliasType, TypeGuard, get_args, get_origin
try:
from types import GenericAlias
except ImportError: # pragma: no cover
GenericAlias = None # type: ignore[misc,assignment]
multipart_not_installed_error = ( multipart_not_installed_error = (
'Form data requires "python-multipart" to be installed. \n' 'Form data requires "python-multipart" to be installed. \n'
@ -356,6 +364,9 @@ def analyze_param(
depends = None depends = None
type_annotation: Any = Any type_annotation: Any = Any
use_annotation: Any = Any use_annotation: Any = Any
if _is_typealiastype(annotation):
# unpack in case py3.12 type syntax is used
annotation = annotation.__value__
if annotation is not inspect.Signature.empty: if annotation is not inspect.Signature.empty:
use_annotation = annotation use_annotation = annotation
type_annotation = annotation type_annotation = annotation
@ -999,3 +1010,26 @@ def get_body_field(
field_info=BodyFieldInfo(**BodyFieldInfo_kwargs), field_info=BodyFieldInfo(**BodyFieldInfo_kwargs),
) )
return final_field return final_field
def _is_typealiastype(tp: Any, /) -> TypeGuard[TypeAliasType]:
in_typing = hasattr(typing, "TypeAliasType")
in_typing_extensions = hasattr(typing_extensions, "TypeAliasType")
is_typealiastype = False
if in_typing and in_typing_extensions:
if getattr(typing, "TypeAliasType", None) is getattr(
typing_extensions, "TypeAliasType", None
): # pragma: no cover
is_typealiastype = isinstance(tp, typing.TypeAliasType) # type: ignore [attr-defined]
else:
is_typealiastype = isinstance(
tp,
(typing.TypeAliasType, typing_extensions.TypeAliasType), # type: ignore [attr-defined]
)
elif in_typing and not in_typing_extensions: # pragma: no cover
is_typealiastype = isinstance(tp, typing.TypeAliasType) # type: ignore [attr-defined]
elif not in_typing and in_typing_extensions:
is_typealiastype = isinstance(tp, typing_extensions.TypeAliasType)
if sys.version_info[:2] == (3, 10):
return type(tp) is not GenericAlias and is_typealiastype
return is_typealiastype

27
tests/test_dependency_pep695.py

@ -0,0 +1,27 @@
from __future__ import annotations
from fastapi import Depends, FastAPI
from fastapi.testclient import TestClient
from typing_extensions import Annotated, 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"'
Loading…
Cancel
Save