Source code for async_wrapper.convert.main
from __future__ import annotations
from inspect import iscoroutinefunction
from typing import TYPE_CHECKING, Any, overload
from typing_extensions import ParamSpec, TypeVar
from async_wrapper.convert._async import Async, sync_to_async
from async_wrapper.convert._sync import async_to_sync
from async_wrapper.convert._sync.main import Sync
if TYPE_CHECKING:
from collections.abc import Awaitable, Callable, Coroutine
_T = TypeVar("_T", infer_variance=True)
_P = ParamSpec("_P")
__all__ = ["toggle_func", "async_to_sync", "sync_to_async"]
@overload
def toggle_func(
func: Callable[_P, Coroutine[Any, Any, _T]],
) -> Callable[_P, _T]: ... # pragma: no cover
@overload
def toggle_func(
func: Callable[_P, _T],
) -> Callable[_P, Awaitable[_T]]: ... # pragma: no cover
# TODO: Coroutine -> Awaitable
[docs]
def toggle_func(
func: Callable[_P, _T] | Callable[_P, Coroutine[Any, Any, _T]],
) -> Callable[_P, _T] | Callable[_P, Awaitable[_T]]:
"""
Convert between synchronous and asynchronous functions.
Args:
func: A function that can be either synchronous or asynchronous.
Returns:
A function that matches the desired synchronicity,
either synchronous or asynchronous.
"""
if isinstance(func, (Async, Sync)):
return func._func # noqa: SLF001
if iscoroutinefunction(func):
return async_to_sync(func)
return sync_to_async(func) # pyright: ignore[reportReturnType]