diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index 79c0679365..daaf6a9904 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -18,7 +18,6 @@ from typing import ( Type, Union, cast, - get_type_hints, ) import anyio @@ -228,40 +227,27 @@ def get_typed_signature(call: Callable[..., Any]) -> inspect.Signature: unwrapped = inspect.unwrap(call) globalns = getattr(unwrapped, "__globals__", {}) - # Try to use get_type_hints first for better forward reference resolution - # This properly handles Annotated types with forward references when using - # `from __future__ import annotations` (PEP 563) - type_hints: Dict[str, Any] = {} - try: - # include_extras=True preserves Annotated metadata (like Depends) - type_hints = get_type_hints(unwrapped, globalns=globalns, include_extras=True) - except NameError: - # If get_type_hints fails due to unresolved names, try to get updated - # globalns from the module (in case classes were defined after the function) - module_name = getattr(unwrapped, "__module__", None) - if module_name: - import importlib + # Get updated globalns from the module (in case classes were defined after the function) + # This is needed for forward references when using `from __future__ import annotations` + module_name = getattr(unwrapped, "__module__", None) + if module_name: + import importlib - try: - module = importlib.import_module(module_name) - updated_globalns = vars(module) - type_hints = get_type_hints( - unwrapped, globalns=updated_globalns, include_extras=True - ) - except Exception: - pass - except Exception: - # Fall back to manual resolution if get_type_hints fails for other reasons - pass + try: + module = importlib.import_module(module_name) + # Merge module namespace with function's globalns + # Function's globalns takes precedence for imports made in the function's scope + updated_globalns = {**vars(module), **globalns} + globalns = updated_globalns + except Exception: + pass typed_params = [ inspect.Parameter( name=param.name, kind=param.kind, default=param.default, - annotation=type_hints.get(param.name) - if param.name in type_hints - else get_typed_annotation(param.annotation, globalns), + annotation=get_typed_annotation(param.annotation, globalns), ) for param in signature.parameters.values() ] diff --git a/tests/test_annotated_forward_ref.py b/tests/test_annotated_forward_ref.py index b82547197a..92005af790 100644 --- a/tests/test_annotated_forward_ref.py +++ b/tests/test_annotated_forward_ref.py @@ -2,8 +2,15 @@ from __future__ import annotations +import sys from dataclasses import dataclass -from typing import Annotated + +# Annotated is available in typing from Python 3.9+ +# For Python 3.8, we need to import from typing_extensions +if sys.version_info >= (3, 9): + from typing import Annotated +else: + from typing_extensions import Annotated from fastapi import Depends, FastAPI from fastapi.testclient import TestClient