11from __future__import annotations
22
3- import sys
43import asyncio
54import functools
6- import contextvars
7- from typing import Any ,TypeVar ,Callable ,Awaitable
5+ from typing import TypeVar ,Callable ,Awaitable
86from typing_extensions import ParamSpec
97
108import anyio
1513T_ParamSpec = ParamSpec ("T_ParamSpec" )
1614
1715
18- if sys .version_info >= (3 ,9 ):
19- _asyncio_to_thread = asyncio .to_thread
20- else :
21- # backport of https://docs.python.org/3/library/asyncio-task.html#asyncio.to_thread
22- # for Python 3.8 support
23- async def _asyncio_to_thread (
24- func :Callable [T_ParamSpec ,T_Retval ],/ ,* args :T_ParamSpec .args ,** kwargs :T_ParamSpec .kwargs
25- )-> Any :
26- """Asynchronously run function *func* in a separate thread.
27-
28- Any *args and **kwargs supplied for this function are directly passed
29- to *func*. Also, the current :class:`contextvars.Context` is propagated,
30- allowing context variables from the main thread to be accessed in the
31- separate thread.
32-
33- Returns a coroutine that can be awaited to get the eventual result of *func*.
34- """
35- loop = asyncio .events .get_running_loop ()
36- ctx = contextvars .copy_context ()
37- func_call = functools .partial (ctx .run ,func ,* args ,** kwargs )
38- return await loop .run_in_executor (None ,func_call )
39-
40-
4116async def to_thread (
4217func :Callable [T_ParamSpec ,T_Retval ],/ ,* args :T_ParamSpec .args ,** kwargs :T_ParamSpec .kwargs
4318)-> T_Retval :
4419if sniffio .current_async_library ()== "asyncio" :
45- return await _asyncio_to_thread (func ,* args ,** kwargs )
20+ return await asyncio . to_thread (func ,* args ,** kwargs )
4621
4722return await anyio .to_thread .run_sync (
4823functools .partial (func ,* args ,** kwargs ),
@@ -53,10 +28,7 @@ async def to_thread(
5328def asyncify (function :Callable [T_ParamSpec ,T_Retval ])-> Callable [T_ParamSpec ,Awaitable [T_Retval ]]:
5429"""
5530 Take a blocking function and create an async one that receives the same
56- positional and keyword arguments. For python version 3.9 and above, it uses
57- asyncio.to_thread to run the function in a separate thread. For python version
58- 3.8, it uses locally defined copy of the asyncio.to_thread function which was
59- introduced in python 3.9.
31+ positional and keyword arguments.
6032
6133 Usage:
6234