You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ORPA-pyOpenRPA/Resources/LPy64-3105/lib/python3.10/site-packages/nbclient/util.py

114 lines
3.2 KiB

"""General utility methods"""
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.
import asyncio
import inspect
import sys
from typing import Any, Awaitable, Callable, Optional, TypeVar, Union
def check_ipython() -> None:
# original from vaex/asyncio.py
IPython = sys.modules.get('IPython')
if IPython:
version_str = IPython.__version__
# We get rid of any trailing ".dev"
version_str = version_str.replace(".dev", "")
IPython_version = tuple(map(int, version_str.split('.')))
if IPython_version < (7, 0, 0):
raise RuntimeError(
f'You are using IPython {IPython.__version__} '
'while we require 7.0.0+, please update IPython'
)
def check_patch_tornado() -> None:
"""If tornado is imported, add the patched asyncio.Future to its tuple of acceptable Futures"""
# original from vaex/asyncio.py
if 'tornado' in sys.modules:
import tornado.concurrent
if asyncio.Future not in tornado.concurrent.FUTURES:
tornado.concurrent.FUTURES = tornado.concurrent.FUTURES + ( # type: ignore
asyncio.Future,
)
def just_run(coro: Awaitable) -> Any:
"""Make the coroutine run, even if there is an event loop running (using nest_asyncio)"""
try:
loop = asyncio.get_running_loop()
except RuntimeError:
loop = None
if loop is None:
had_running_loop = False
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
else:
had_running_loop = True
if had_running_loop:
# if there is a running loop, we patch using nest_asyncio
# to have reentrant event loops
check_ipython()
import nest_asyncio
nest_asyncio.apply()
check_patch_tornado()
return loop.run_until_complete(coro)
T = TypeVar("T")
def run_sync(coro: Callable[..., Awaitable[T]]) -> Callable[..., T]:
"""Runs a coroutine and blocks until it has executed.
An event loop is created if no one already exists. If an event loop is
already running, this event loop execution is nested into the already
running one if `nest_asyncio` is set to True.
Parameters
----------
coro : coroutine
The coroutine to be executed.
Returns
-------
result :
Whatever the coroutine returns.
"""
def wrapped(*args, **kwargs):
return just_run(coro(*args, **kwargs))
wrapped.__doc__ = coro.__doc__
return wrapped
async def ensure_async(obj: Union[Awaitable, Any]) -> Any:
"""Convert a non-awaitable object to a coroutine if needed,
and await it if it was not already awaited.
"""
if inspect.isawaitable(obj):
try:
result = await obj
except RuntimeError as e:
if str(e) == 'cannot reuse already awaited coroutine':
# obj is already the coroutine's result
return obj
raise
return result
# obj doesn't need to be awaited
return obj
async def run_hook(hook: Optional[Callable], **kwargs: Any) -> None:
if hook is None:
return
res = hook(**kwargs)
if inspect.isawaitable(res):
await res