|
7 | 7 | import warnings
|
8 | 8 | from collections import defaultdict
|
9 | 9 | from datetime import timedelta
|
10 |
| -from inspect import isasyncgen, isgenerator |
| 10 | +from inspect import isasyncgen, iscoroutinefunction as _inspect_iscoroutinefunction, isgenerator |
11 | 11 | from types import TracebackType
|
12 | 12 | from typing import (
|
13 | 13 | Any,
|
|
127 | 127 | except ImportError:
|
128 | 128 | from typing_extensions import ParamSpec # type: ignore
|
129 | 129 |
|
| 130 | +# Python 3.14 deprecated asyncio.iscoroutinefunction, but suggested |
| 131 | +# inspect.iscoroutinefunction does not work correctly in some Python |
| 132 | +# versions before 3.12. |
| 133 | +# See https://github.com/python/cpython/issues/122858#issuecomment-2466239748 |
| 134 | +if sys.version_info >= (3, 12): |
| 135 | + iscoroutinefunction = _inspect_iscoroutinefunction |
| 136 | +else: |
| 137 | + iscoroutinefunction = asyncio.iscoroutinefunction |
| 138 | + |
130 | 139 | AppOrBlueprintKey = Optional[str] # The App key is None, whereas blueprints are named
|
131 | 140 | T_after_serving = TypeVar("T_after_serving", bound=AfterServingCallable)
|
132 | 141 | T_after_websocket = TypeVar("T_after_websocket", bound=AfterWebsocketCallable)
|
@@ -1130,7 +1139,7 @@ def ensure_async(
|
1130 | 1139 | run. Before Quart 0.11 this did not run the synchronous code
|
1131 | 1140 | in an executor.
|
1132 | 1141 | """
|
1133 |
| - if asyncio.iscoroutinefunction(func): |
| 1142 | + if iscoroutinefunction(func): |
1134 | 1143 | return func
|
1135 | 1144 | else:
|
1136 | 1145 | return self.sync_to_async(cast(Callable[P, T], func))
|
|
0 commit comments