Browse Source

Merge 63998b27ed into 460f8d2cc8

pull/15411/merge
armorbreak001 15 hours ago
committed by GitHub
parent
commit
ec64b90ff0
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 35
      fastapi/dependencies/utils.py

35
fastapi/dependencies/utils.py

@ -302,6 +302,8 @@ def get_dependant(
own_oauth_scopes=own_oauth_scopes,
parent_oauth_scopes=parent_oauth_scopes,
)
unwrapped_call = inspect.unwrap(call)
globalns = getattr(unwrapped_call, "__globals__", {})
current_scopes = (parent_oauth_scopes or []) + (own_oauth_scopes or [])
path_param_names = get_path_param_names(path)
endpoint_signature = get_typed_signature(call)
@ -313,6 +315,7 @@ def get_dependant(
annotation=param.annotation,
value=param.default,
is_path_param=is_path_param,
globalns=globalns,
)
if param_details.depends is not None:
assert param_details.depends.dependency
@ -396,6 +399,7 @@ def analyze_param(
annotation: Any,
value: Any,
is_path_param: bool,
globalns: dict[str, Any] | None = None,
) -> ParamDetails:
field_info = None
depends = None
@ -407,10 +411,39 @@ def analyze_param(
if annotation is not inspect.Signature.empty:
use_annotation = annotation
type_annotation = annotation
# When ``from __future__ import annotations`` is active, the annotation
# may still be a ForwardRef (e.g. ``Annotated[Potato, Depends(...)]``
# where *Potato* hasn't been defined yet). The lenient evaluator leaves
# it as a ForwardRef because it cannot resolve *Potato*, but we still
# need to unpack the Annotated wrapper so that FastAPI-specific markers
# (Depends / Field / Body) are discovered. We use ``eval`` with a
# dict that turns undefined names into ForwardRef objects, which gives
# us the same partial-evaluation behaviour that the normal code-path
# expects.
if isinstance(use_annotation, ForwardRef):
if globalns is not None:
try:
_safe_ns: dict[str, Any] = dict(globalns)
_missing = ForwardRef # noqa: F811
class _SafeDict(dict):
def __missing__(self, key): # type: ignore[override]
return _missing(key)
use_annotation = eval(
use_annotation.__forward_arg__, {"__builtins__": {}}, _SafeDict(_safe_ns)
)
if use_annotation is not inspect.Signature.empty:
type_annotation = use_annotation
except Exception:
pass
# Extract Annotated info
if get_origin(use_annotation) is Annotated:
annotated_args = get_args(annotation)
annotated_args = get_args(use_annotation)
type_annotation = annotated_args[0]
# Resolve forward references in the inner type (e.g. when using
# ``from __future__ import annotations`` with Annotated[..., Depends()])
if isinstance(type_annotation, (str, ForwardRef)):
if globalns is not None:
type_annotation = get_typed_annotation(type_annotation, globalns)
fastapi_annotations = [
arg
for arg in annotated_args[1:]

Loading…
Cancel
Save