Skip to content

Commit bb29df0

Browse files
Import ensure_async and run_sync from jupyter_core (#889)
* Import ensure_async and run_sync from jupyter_core * bump jupyter_core dep * update dep Co-authored-by: Steven Silvester <[email protected]>
1 parent 7ab6ed6 commit bb29df0

File tree

2 files changed

+4
-78
lines changed

2 files changed

+4
-78
lines changed

jupyter_client/utils.py

Lines changed: 3 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -3,84 +3,10 @@
33
- provides utility wrappers to run asynchronous functions in a blocking environment.
44
- vendor functions from ipython_genutils that should be retired at some point.
55
"""
6-
import asyncio
7-
import atexit
8-
import inspect
96
import os
10-
import threading
11-
from typing import Optional
12-
13-
14-
class _TaskRunner:
15-
"""A task runner that runs an asyncio event loop on a background thread."""
16-
17-
def __init__(self):
18-
self.__io_loop: Optional[asyncio.AbstractEventLoop] = None
19-
self.__runner_thread: Optional[threading.Thread] = None
20-
self.__lock = threading.Lock()
21-
atexit.register(self._close)
22-
23-
def _close(self):
24-
if self.__io_loop:
25-
self.__io_loop.stop()
26-
27-
def _runner(self):
28-
loop = self.__io_loop
29-
assert loop is not None
30-
try:
31-
loop.run_forever()
32-
finally:
33-
loop.close()
34-
35-
def run(self, coro):
36-
"""Synchronously run a coroutine on a background thread."""
37-
with self.__lock:
38-
name = f"{threading.current_thread().name} - runner"
39-
if self.__io_loop is None:
40-
self.__io_loop = asyncio.new_event_loop()
41-
self.__runner_thread = threading.Thread(target=self._runner, daemon=True, name=name)
42-
self.__runner_thread.start()
43-
fut = asyncio.run_coroutine_threadsafe(coro, self.__io_loop)
44-
return fut.result(None)
45-
46-
47-
_runner_map = {}
48-
_loop_map = {}
49-
50-
51-
def run_sync(coro):
52-
def wrapped(*args, **kwargs):
53-
name = threading.current_thread().name
54-
inner = coro(*args, **kwargs)
55-
try:
56-
# If a loop is currently running in this thread,
57-
# use a task runner.
58-
asyncio.get_running_loop()
59-
if name not in _runner_map:
60-
_runner_map[name] = _TaskRunner()
61-
return _runner_map[name].run(inner)
62-
except RuntimeError:
63-
pass
64-
65-
# Run the loop for this thread.
66-
if name not in _loop_map:
67-
_loop_map[name] = asyncio.new_event_loop()
68-
loop = _loop_map[name]
69-
return loop.run_until_complete(inner)
70-
71-
wrapped.__doc__ = coro.__doc__
72-
return wrapped
73-
74-
75-
async def ensure_async(obj):
76-
"""Ensure a returned object is asynchronous.L
77-
78-
NOTE: This should only be used on methods of external classes,
79-
not on a `self` method.
80-
"""
81-
if inspect.isawaitable(obj):
82-
return await obj
83-
return obj
7+
8+
from jupyter_core.utils import ensure_async # noqa: F401
9+
from jupyter_core.utils import run_sync # noqa: F401
8410

8511

8612
def _filefind(filename, path_dirs=None):

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ classifiers = [
2525
requires-python = ">=3.8"
2626
dependencies = [
2727
"importlib_metadata>=4.8.3;python_version<\"3.10\"",
28-
"jupyter_core>=4.9.2",
28+
"jupyter_core>=4.12,!=~5.0",
2929
"python-dateutil>=2.8.2",
3030
"pyzmq>=23.0",
3131
"tornado>=6.2",

0 commit comments

Comments
 (0)