diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index 6162aa5efc..bc6cd85ac8 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -245,19 +245,23 @@ def get_typed_signature(call: Callable[..., Any]) -> inspect.Signature: class _LenientTypeResolutionDict(dict[str, Any]): def __missing__(self, key: str) -> Any: - value = vars(builtins).get(key, ForwardRef(key)) - self[key] = value - return value + return vars(builtins).get(key, ForwardRef(key)) def get_typed_annotation(annotation: Any, globalns: dict[str, Any]) -> Any: if isinstance(annotation, str): annotation = ForwardRef(annotation) if isinstance(annotation, ForwardRef): - lenient_globalns = _LenientTypeResolutionDict(globalns) annotation = evaluate_forwardref( # ty: ignore[deprecated] - annotation, lenient_globalns, lenient_globalns + annotation, globalns, globalns ) + if isinstance(annotation, ForwardRef): + try: + annotation = eval( # noqa: S307 + annotation.__forward_arg__, _LenientTypeResolutionDict(globalns) + ) + except Exception: + pass if annotation is type(None): return None return annotation diff --git a/tests/test_dependencies_utils.py b/tests/test_dependencies_utils.py index 9257d1c9ee..896042102e 100644 --- a/tests/test_dependencies_utils.py +++ b/tests/test_dependencies_utils.py @@ -1,3 +1,6 @@ +from typing import Annotated, ForwardRef, get_args, get_origin + +from fastapi import Depends, params from fastapi.dependencies.utils import get_typed_annotation @@ -6,3 +9,20 @@ def test_get_typed_annotation(): annotation = "None" typed_annotation = get_typed_annotation(annotation, globals()) assert typed_annotation is None + + +def test_get_typed_annotation_falls_back_to_lenient_forwardref_resolution(): + def dependency() -> None: + return None + + annotation = "Annotated[Potato, Depends(dependency)]" + typed_annotation = get_typed_annotation( + annotation, + {"Annotated": Annotated, "Depends": Depends, "dependency": dependency}, + ) + + assert get_origin(typed_annotation) is Annotated + type_annotation, depends = get_args(typed_annotation) + assert isinstance(type_annotation, ForwardRef) + assert type_annotation.__forward_arg__ == "Potato" + assert isinstance(depends, params.Depends)