Browse Source

Merge 50b9bd5d8b into 6df50d40fe

pull/13920/merge
Albin Skott 4 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 sys
import typing
from contextlib import AsyncExitStack, contextmanager
from copy import copy, deepcopy
from dataclasses import dataclass
@ -19,6 +21,7 @@ from typing import (
)
import anyio
import typing_extensions
from fastapi import params
from fastapi._compat import (
PYDANTIC_V2,
@ -71,7 +74,12 @@ from starlette.datastructures import (
from starlette.requests import HTTPConnection, Request
from starlette.responses import Response
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 = (
'Form data requires "python-multipart" to be installed. \n'
@ -356,6 +364,9 @@ def analyze_param(
depends = None
type_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:
use_annotation = annotation
type_annotation = annotation
@ -999,3 +1010,26 @@ def get_body_field(
field_info=BodyFieldInfo(**BodyFieldInfo_kwargs),
)
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