mirror of https://github.com/tiangolo/fastapi.git
🐛 Fix `inspect.getcoroutinefunction()` can break testing with `unittest.mock.patch()` (#14022)
This commit is contained in:
parent
73841b9976
commit
c831cdbde2
|
|
@ -1,4 +1,5 @@
|
||||||
import inspect
|
import inspect
|
||||||
|
import sys
|
||||||
from contextlib import AsyncExitStack, contextmanager
|
from contextlib import AsyncExitStack, contextmanager
|
||||||
from copy import copy, deepcopy
|
from copy import copy, deepcopy
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
|
@ -73,6 +74,11 @@ from starlette.responses import Response
|
||||||
from starlette.websockets import WebSocket
|
from starlette.websockets import WebSocket
|
||||||
from typing_extensions import Annotated, get_args, get_origin
|
from typing_extensions import Annotated, get_args, get_origin
|
||||||
|
|
||||||
|
if sys.version_info >= (3, 13): # pragma: no cover
|
||||||
|
from inspect import iscoroutinefunction
|
||||||
|
else: # pragma: no cover
|
||||||
|
from asyncio import iscoroutinefunction
|
||||||
|
|
||||||
multipart_not_installed_error = (
|
multipart_not_installed_error = (
|
||||||
'Form data requires "python-multipart" to be installed. \n'
|
'Form data requires "python-multipart" to be installed. \n'
|
||||||
'You can install "python-multipart" with: \n\n'
|
'You can install "python-multipart" with: \n\n'
|
||||||
|
|
@ -529,11 +535,11 @@ def add_param_to_fields(*, field: ModelField, dependant: Dependant) -> None:
|
||||||
|
|
||||||
def is_coroutine_callable(call: Callable[..., Any]) -> bool:
|
def is_coroutine_callable(call: Callable[..., Any]) -> bool:
|
||||||
if inspect.isroutine(call):
|
if inspect.isroutine(call):
|
||||||
return inspect.iscoroutinefunction(call)
|
return iscoroutinefunction(call)
|
||||||
if inspect.isclass(call):
|
if inspect.isclass(call):
|
||||||
return False
|
return False
|
||||||
dunder_call = getattr(call, "__call__", None) # noqa: B004
|
dunder_call = getattr(call, "__call__", None) # noqa: B004
|
||||||
return inspect.iscoroutinefunction(dunder_call)
|
return iscoroutinefunction(dunder_call)
|
||||||
|
|
||||||
|
|
||||||
def is_async_gen_callable(call: Callable[..., Any]) -> bool:
|
def is_async_gen_callable(call: Callable[..., Any]) -> bool:
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import asyncio
|
|
||||||
import dataclasses
|
import dataclasses
|
||||||
import email.message
|
import email.message
|
||||||
import inspect
|
import inspect
|
||||||
import json
|
import json
|
||||||
|
import sys
|
||||||
from contextlib import AsyncExitStack, asynccontextmanager
|
from contextlib import AsyncExitStack, asynccontextmanager
|
||||||
from enum import Enum, IntEnum
|
from enum import Enum, IntEnum
|
||||||
from typing import (
|
from typing import (
|
||||||
|
|
@ -76,6 +76,11 @@ from starlette.types import AppType, ASGIApp, Lifespan, Scope
|
||||||
from starlette.websockets import WebSocket
|
from starlette.websockets import WebSocket
|
||||||
from typing_extensions import Annotated, Doc, deprecated
|
from typing_extensions import Annotated, Doc, deprecated
|
||||||
|
|
||||||
|
if sys.version_info >= (3, 13): # pragma: no cover
|
||||||
|
from inspect import iscoroutinefunction
|
||||||
|
else: # pragma: no cover
|
||||||
|
from asyncio import iscoroutinefunction
|
||||||
|
|
||||||
|
|
||||||
def _prepare_response_content(
|
def _prepare_response_content(
|
||||||
res: Any,
|
res: Any,
|
||||||
|
|
@ -232,7 +237,7 @@ def get_request_handler(
|
||||||
embed_body_fields: bool = False,
|
embed_body_fields: bool = False,
|
||||||
) -> Callable[[Request], Coroutine[Any, Any, Response]]:
|
) -> Callable[[Request], Coroutine[Any, Any, Response]]:
|
||||||
assert dependant.call is not None, "dependant.call must be a function"
|
assert dependant.call is not None, "dependant.call must be a function"
|
||||||
is_coroutine = asyncio.iscoroutinefunction(dependant.call)
|
is_coroutine = iscoroutinefunction(dependant.call)
|
||||||
is_body_form = body_field and isinstance(body_field.field_info, params.Form)
|
is_body_form = body_field and isinstance(body_field.field_info, params.Form)
|
||||||
if isinstance(response_class, DefaultPlaceholder):
|
if isinstance(response_class, DefaultPlaceholder):
|
||||||
actual_response_class: Type[Response] = response_class.value
|
actual_response_class: Type[Response] = response_class.value
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue