diff options
Diffstat (limited to 'ATRI/syncer.py')
-rw-r--r-- | ATRI/syncer.py | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/ATRI/syncer.py b/ATRI/syncer.py new file mode 100644 index 0000000..b4c59b1 --- /dev/null +++ b/ATRI/syncer.py @@ -0,0 +1,47 @@ +import sys +import asyncio +import inspect +import types +from functools import singledispatch, wraps + +from typing import Any, Callable, Generator + + +PY37 = sys.version_info >= (3, 7) + + +def _is_awaitable(co: Generator[Any, None, Any]) -> bool: + if PY37: + return inspect.isawaitable(co) + else: + return (isinstance(co, types.GeneratorType) or + isinstance(co, asyncio.Future)) + + +@singledispatch +def sync(co: Any) -> Any: + raise TypeError(f'Called with unsupported argument: {co}') + + [email protected](asyncio.Future) [email protected](types.GeneratorType) +def sync_co(co: Generator[Any, None, Any]) -> Any: + if not _is_awaitable(co): + raise TypeError(f'Called with unsupported argument: {co}') + return asyncio.get_event_loop().run_until_complete(co) + + [email protected](types.FunctionType) [email protected](types.MethodType) # type: ignore +def sync_fu(f: Callable[..., Any]) -> Callable[..., Any]: + if not asyncio.iscoroutinefunction(f): + raise TypeError(f'Called with unsupported argument: {f}') + + @wraps(f) + def run(*args, **kwargs) -> Any: + return asyncio.get_event_loop().run_until_complete(f(*args, **kwargs)) + return run + + +if PY37: + sync.register(types.CoroutineType)(sync_co) |