You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

65 lines
1.7 KiB

"""Test for async wrapper around sync function.
This tests the issue reported in #14442 where using functools.wraps on an async
wrapper around a sync function causes FastAPI to incorrectly treat the handler
as sync, resulting in: ValueError: [TypeError("'coroutine' object is not iterable"), ...]
The issue is that Dependant.is_coroutine_callable uses inspect.unwrap() which follows
__wrapped__ back to the original sync function, instead of checking if the actual
registered handler is async.
"""
from functools import wraps
import pytest
from fastapi import Depends, FastAPI
from fastapi.testclient import TestClient
def async_wrap(func):
"""A decorator that wraps a sync function with an async handler."""
@wraps(func)
async def wrapper(*args, **kwargs):
func(*args, **kwargs)
return "OK"
return wrapper
app = FastAPI()
@app.get("/")
@async_wrap
def index():
"""A simple sync page function wrapped with async handler."""
print("Hello!")
def sync_dependency():
return "dep_value"
@app.get("/with-dependency")
@async_wrap
def with_dependency(value: str = Depends(sync_dependency)):
"""A sync function with dependency, wrapped with async handler."""
print(f"Got: {value}")
client = TestClient(app)
def test_async_wrapper_around_sync_function():
"""Test that async wrapper around sync function works correctly."""
response = client.get("/")
assert response.status_code == 200, response.text
assert response.json() == "OK"
def test_async_wrapper_with_dependency():
"""Test that async wrapper with dependency works correctly."""
response = client.get("/with-dependency")
assert response.status_code == 200, response.text
assert response.json() == "OK"