mirror of https://github.com/tiangolo/fastapi.git
✨ Add support for wrapped functions (e.g. `@functools.wraps()`) used with forward references (#5077)
Co-authored-by: Yurii Karabas <1998uriyyo@gmail.com> Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
This commit is contained in:
parent
930b27e5fa
commit
1c1e584abd
|
|
@ -192,7 +192,8 @@ def get_flat_params(dependant: Dependant) -> List[ModelField]:
|
|||
|
||||
def get_typed_signature(call: Callable[..., Any]) -> inspect.Signature:
|
||||
signature = inspect.signature(call)
|
||||
globalns = getattr(call, "__globals__", {})
|
||||
unwrapped = inspect.unwrap(call)
|
||||
globalns = getattr(unwrapped, "__globals__", {})
|
||||
typed_params = [
|
||||
inspect.Parameter(
|
||||
name=param.name,
|
||||
|
|
@ -217,12 +218,13 @@ def get_typed_annotation(annotation: Any, globalns: Dict[str, Any]) -> Any:
|
|||
|
||||
def get_typed_return_annotation(call: Callable[..., Any]) -> Any:
|
||||
signature = inspect.signature(call)
|
||||
unwrapped = inspect.unwrap(call)
|
||||
annotation = signature.return_annotation
|
||||
|
||||
if annotation is inspect.Signature.empty:
|
||||
return None
|
||||
|
||||
globalns = getattr(call, "__globals__", {})
|
||||
globalns = getattr(unwrapped, "__globals__", {})
|
||||
return get_typed_annotation(annotation, globalns)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
from pydantic import BaseModel
|
||||
|
||||
|
||||
def forwardref_method(input: "ForwardRefModel") -> "ForwardRefModel":
|
||||
return ForwardRefModel(x=input.x + 1)
|
||||
|
||||
|
||||
class ForwardRefModel(BaseModel):
|
||||
x: int = 0
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
import functools
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from .forward_reference_type import forwardref_method
|
||||
|
||||
|
||||
def passthrough(f):
|
||||
@functools.wraps(f)
|
||||
def method(*args, **kwargs):
|
||||
return f(*args, **kwargs)
|
||||
|
||||
return method
|
||||
|
||||
|
||||
def test_wrapped_method_type_inference():
|
||||
"""
|
||||
Regression test ensuring that when a method imported from another module
|
||||
is decorated with something that sets the __wrapped__ attribute (functools.wraps),
|
||||
then the types are still processed correctly, including dereferencing of forward
|
||||
references.
|
||||
"""
|
||||
app = FastAPI()
|
||||
client = TestClient(app)
|
||||
app.post("/endpoint")(passthrough(forwardref_method))
|
||||
app.post("/endpoint2")(passthrough(passthrough(forwardref_method)))
|
||||
with client:
|
||||
response = client.post("/endpoint", json={"input": {"x": 0}})
|
||||
response2 = client.post("/endpoint2", json={"input": {"x": 0}})
|
||||
assert response.json() == response2.json() == {"x": 1}
|
||||
Loading…
Reference in New Issue