conkernelclient 0.0.7__tar.gz → 0.0.9__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {conkernelclient-0.0.7/conkernelclient.egg-info → conkernelclient-0.0.9}/PKG-INFO +1 -1
- conkernelclient-0.0.9/conkernelclient/__init__.py +2 -0
- {conkernelclient-0.0.7 → conkernelclient-0.0.9}/conkernelclient/_modidx.py +4 -0
- {conkernelclient-0.0.7 → conkernelclient-0.0.9}/conkernelclient/core.py +35 -12
- {conkernelclient-0.0.7 → conkernelclient-0.0.9/conkernelclient.egg-info}/PKG-INFO +1 -1
- {conkernelclient-0.0.7 → conkernelclient-0.0.9}/pyproject.toml +2 -0
- conkernelclient-0.0.7/conkernelclient/__init__.py +0 -2
- {conkernelclient-0.0.7 → conkernelclient-0.0.9}/LICENSE +0 -0
- {conkernelclient-0.0.7 → conkernelclient-0.0.9}/MANIFEST.in +0 -0
- {conkernelclient-0.0.7 → conkernelclient-0.0.9}/README.md +0 -0
- {conkernelclient-0.0.7 → conkernelclient-0.0.9}/conkernelclient.egg-info/SOURCES.txt +0 -0
- {conkernelclient-0.0.7 → conkernelclient-0.0.9}/conkernelclient.egg-info/dependency_links.txt +0 -0
- {conkernelclient-0.0.7 → conkernelclient-0.0.9}/conkernelclient.egg-info/entry_points.txt +0 -0
- {conkernelclient-0.0.7 → conkernelclient-0.0.9}/conkernelclient.egg-info/requires.txt +0 -0
- {conkernelclient-0.0.7 → conkernelclient-0.0.9}/conkernelclient.egg-info/top_level.txt +0 -0
- {conkernelclient-0.0.7 → conkernelclient-0.0.9}/setup.cfg +0 -0
|
@@ -8,6 +8,10 @@ d = { 'settings': { 'branch': 'main',
|
|
|
8
8
|
'syms': { 'conkernelclient.core': { 'conkernelclient.core.ConKernelClient': ('core.html#conkernelclient', 'conkernelclient/core.py'),
|
|
9
9
|
'conkernelclient.core.ConKernelClient._async_recv_reply': ( 'core.html#conkernelclient._async_recv_reply',
|
|
10
10
|
'conkernelclient/core.py'),
|
|
11
|
+
'conkernelclient.core.ConKernelClient._check_alive': ( 'core.html#conkernelclient._check_alive',
|
|
12
|
+
'conkernelclient/core.py'),
|
|
13
|
+
'conkernelclient.core.ConKernelClient._fail_pending': ( 'core.html#conkernelclient._fail_pending',
|
|
14
|
+
'conkernelclient/core.py'),
|
|
11
15
|
'conkernelclient.core.ConKernelClient.execute': ( 'core.html#conkernelclient.execute',
|
|
12
16
|
'conkernelclient/core.py'),
|
|
13
17
|
'conkernelclient.core.ConKernelClient.start_channels': ( 'core.html#conkernelclient.start_channels',
|
|
@@ -15,7 +15,10 @@ from zmq.error import ZMQError
|
|
|
15
15
|
from jupyter_client.kernelspec import KernelSpec
|
|
16
16
|
from jupyter_client import AsyncKernelManager
|
|
17
17
|
from traitlets import Type
|
|
18
|
-
import asyncio, zmq.asyncio, time
|
|
18
|
+
import asyncio, zmq.asyncio, time, logging
|
|
19
|
+
|
|
20
|
+
# %% ../nbs/00_core.ipynb #737a0fc1
|
|
21
|
+
_log = logging.getLogger(__name__)
|
|
19
22
|
|
|
20
23
|
# %% ../nbs/00_core.ipynb #374b75d0
|
|
21
24
|
if not hasattr(Session, '_orig_send'): Session._orig_send = Session.send
|
|
@@ -36,6 +39,17 @@ Session.send = _send
|
|
|
36
39
|
|
|
37
40
|
# %% ../nbs/00_core.ipynb #d6a5fa6a
|
|
38
41
|
class ConKernelClient(AsyncKernelClient):
|
|
42
|
+
def _fail_pending(self, exc:Exception, skip=None):
|
|
43
|
+
for k,(q,_) in list(getattr(self, '_pending', {}).items()):
|
|
44
|
+
if k != skip:
|
|
45
|
+
try: q.put_nowait(exc)
|
|
46
|
+
except asyncio.QueueFull: pass
|
|
47
|
+
|
|
48
|
+
def _check_alive(self):
|
|
49
|
+
if not self.channels_running: raise RuntimeError("Channels not running")
|
|
50
|
+
tk = getattr(self, '_shell_reader_task', None)
|
|
51
|
+
return tk is not None and not tk.done()
|
|
52
|
+
|
|
39
53
|
async def start_channels(self, shell:bool=True, iopub:bool=True, stdin:bool=True, hb:bool=True, control:bool=True):
|
|
40
54
|
"Start channels, wait for ready, and launch background shell-reply reader"
|
|
41
55
|
super().start_channels(shell=shell, iopub=iopub, stdin=stdin, hb=hb, control=control)
|
|
@@ -47,12 +61,20 @@ class ConKernelClient(AsyncKernelClient):
|
|
|
47
61
|
while True:
|
|
48
62
|
try: reply = await self.get_shell_msg(timeout=None)
|
|
49
63
|
except Exception as e:
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
else: logging.warning(f"_reader died with no pending: {e}")
|
|
64
|
+
self._fail_pending(e)
|
|
65
|
+
_log.warning(f"_reader died, pending={list(self._pending)}: {e}")
|
|
53
66
|
break
|
|
54
|
-
|
|
55
|
-
|
|
67
|
+
mid = reply["parent_header"].get("msg_id")
|
|
68
|
+
pend = self._pending.get(mid)
|
|
69
|
+
if pend:
|
|
70
|
+
q, soe = pend
|
|
71
|
+
try: q.put_nowait(reply)
|
|
72
|
+
except asyncio.QueueFull: pass
|
|
73
|
+
else: _log.warning(f"Orphan reply for {reply['parent_header'].get('msg_id')}, pending={list(self._pending)}")
|
|
74
|
+
cts = reply.get("content", {})
|
|
75
|
+
if cts.get("status") in ("error", "aborted") and pend and soe:
|
|
76
|
+
exc = RuntimeError(f"Kernel error aborted: {cts.get('ename')}: {cts.get('evalue')}")
|
|
77
|
+
self._fail_pending(exc, skip=mid)
|
|
56
78
|
self._shell_reader_task = asyncio.create_task(_reader())
|
|
57
79
|
await _ready.wait()
|
|
58
80
|
await asyncio.sleep(0.2)
|
|
@@ -60,6 +82,7 @@ class ConKernelClient(AsyncKernelClient):
|
|
|
60
82
|
|
|
61
83
|
def stop_channels(self):
|
|
62
84
|
"Stop channels and cancel the background shell-reply reader task"
|
|
85
|
+
self._fail_pending(RuntimeError("Shell channels stopped before reply"))
|
|
63
86
|
super().stop_channels()
|
|
64
87
|
if (tk := getattr(self, '_shell_reader_task', None)):
|
|
65
88
|
tk.cancel()
|
|
@@ -68,26 +91,26 @@ class ConKernelClient(AsyncKernelClient):
|
|
|
68
91
|
|
|
69
92
|
async def _async_recv_reply(self, msg_id, timeout=None, channel="shell"):
|
|
70
93
|
if channel == "control": return await self._async_get_control_msg(timeout=timeout)
|
|
71
|
-
q = self._pending[msg_id]
|
|
94
|
+
q, _ = self._pending[msg_id]
|
|
72
95
|
try:
|
|
73
96
|
res = await asyncio.wait_for(q.get(), timeout)
|
|
74
97
|
if isinstance(res, Exception): raise res
|
|
75
98
|
return res
|
|
76
|
-
except asyncio.TimeoutError as e: raise TimeoutError("Timeout waiting for reply") from e
|
|
77
99
|
finally: self._pending.pop(msg_id, None)
|
|
78
100
|
|
|
79
101
|
def execute(self, code, user_expressions=None, allow_stdin=None, reply=False, subsh_id=None,
|
|
80
|
-
cts_typ='code', timeout=60, msg_id=None, **kw):
|
|
102
|
+
cts_typ='code', timeout=60, msg_id=None, stop_on_error=True, **kw):
|
|
81
103
|
"Send an execute request, returning a coroutine for the reply if `reply`, else the msg_id"
|
|
104
|
+
if not self._check_alive(): return asyncio.sleep(0) if reply else None
|
|
82
105
|
if user_expressions is None: user_expressions = {}
|
|
83
106
|
if allow_stdin is None: allow_stdin = self.allow_stdin
|
|
84
|
-
content = dict(user_expressions=user_expressions, allow_stdin=allow_stdin, subsh_id=subsh_id, **kw)
|
|
107
|
+
content = dict(user_expressions=user_expressions, allow_stdin=allow_stdin, subsh_id=subsh_id, stop_on_error=stop_on_error, **kw)
|
|
85
108
|
content[cts_typ] = code
|
|
86
109
|
msg = self.session.msg("execute_request", content)
|
|
87
110
|
if msg_id is not None: msg["header"]["msg_id"] = msg_id
|
|
88
111
|
if subsh_id is not None: msg["header"]["subshell_id"] = subsh_id
|
|
89
112
|
msg_id = msg["header"]["msg_id"]
|
|
90
|
-
if reply: self._pending[msg_id] = asyncio.Queue(maxsize=1)
|
|
113
|
+
if reply: self._pending[msg_id] = (asyncio.Queue(maxsize=1), stop_on_error)
|
|
91
114
|
self.shell_channel.send(msg)
|
|
92
115
|
if not reply: return msg_id
|
|
93
116
|
return self._async_recv_reply(msg_id, timeout=timeout)
|
|
@@ -95,7 +118,7 @@ class ConKernelClient(AsyncKernelClient):
|
|
|
95
118
|
async def stdin_send(self, msg:dict):
|
|
96
119
|
"Send on `stdin_channel` then ping event loop"
|
|
97
120
|
self.stdin_channel.send(msg)
|
|
98
|
-
await asyncio.sleep(0)
|
|
121
|
+
await asyncio.sleep(0.01)
|
|
99
122
|
|
|
100
123
|
# %% ../nbs/00_core.ipynb #b828c222
|
|
101
124
|
class ConKernelManager(AsyncKernelManager): client_class,client_factory = ConKernelClient,Type(ConKernelClient)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{conkernelclient-0.0.7 → conkernelclient-0.0.9}/conkernelclient.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|