mirror of https://github.com/tiangolo/fastapi.git
Fix CI failures: Python 3.8 compatibility and Pydantic v1 tests
- Fix Python 3.8 compatibility by importing Annotated from typing_extensions when running on Python < 3.9 - Simplify get_typed_signature to not use get_type_hints which was causing issues with Pydantic v1 parameter detection (Header, Cookie, Query, etc.) - Instead, expand globalns with module namespace to help resolve forward references while keeping the original annotation resolution logic intact 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
80370ab52f
commit
c171f468d8
|
|
@ -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()
|
||||
]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue