Browse Source
Use lenient ForwardRef resolution as fallback
pull/15234/head
giria660
3 months ago
No known key found for this signature in database
GPG Key ID: 3D8290B3CD372BA4
2 changed files with
29 additions and
5 deletions
-
fastapi/dependencies/utils.py
-
tests/test_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 |
|
|
|
|
|
|
|
@ -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) |
|
|
|
|