summaryrefslogtreecommitdiff
path: root/ATRI/syncer.py
diff options
context:
space:
mode:
[Update]
Diffstat (limited to 'ATRI/syncer.py')
-rw-r--r--ATRI/syncer.py47
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}')
+
+
+@sync.register(asyncio.Future)
+@sync.register(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)
+
+
+@sync.register(types.FunctionType)
+@sync.register(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)