Skip to content

Commit f6a20d0

Browse files
committed
Merge pull request #140 from minrk/fix-wait-for-ready
Fixes for starting a new kernel
2 parents fa2e1f5 + 9a05659 commit f6a20d0

File tree

4 files changed

+35
-4
lines changed

4 files changed

+35
-4
lines changed

jupyter_client/blocking/client.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,24 @@
1616
from jupyter_client.client import KernelClient
1717
from .channels import ZMQSocketChannel
1818

19+
1920
class BlockingKernelClient(KernelClient):
21+
"""A BlockingKernelClient """
22+
2023
def wait_for_ready(self, timeout=None):
24+
"""Waits for a response when a client is blocked
25+
26+
- Sets future time for timeout
27+
- Blocks on shell channel until a message is received
28+
- Exit if the kernel has died
29+
- If client times out before receiving a message from the kernel, send RuntimeError
30+
- Flush the IOPub channel
31+
"""
2132
if timeout is None:
2233
abs_timeout = float('inf')
2334
else:
2435
abs_timeout = time.time() + timeout
36+
2537
# Wait for kernel info reply on shell channel
2638
while True:
2739
try:
@@ -36,7 +48,8 @@ def wait_for_ready(self, timeout=None):
3648
if not self.is_alive():
3749
raise RuntimeError('Kernel died before replying to kernel_info')
3850

39-
if time.time() < abs_timeout:
51+
# Check if current time is ready check time plus timeout
52+
if time.time() > abs_timeout:
4053
raise RuntimeError("Kernel didn't respond in %d seconds" % timeout)
4154

4255
# Flush IOPub channel

jupyter_client/channels.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,10 @@ def __init__(self, context=None, session=None, address=None):
7272
self.address = address
7373
atexit.register(self._notice_exit)
7474

75+
# running is False until `.start()` is called
7576
self._running = False
76-
self._pause = True
77+
# don't start paused
78+
self._pause = False
7779
self.poller = zmq.Poller()
7880

7981
def _notice_exit(self):

jupyter_client/tests/signalkernel.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,11 @@ class SignalTestKernel(Kernel):
1818
implementation = 'signaltest'
1919
implementation_version = '0.0'
2020
banner = ''
21-
21+
2222
def __init__(self, **kwargs):
2323
kwargs.pop('user_ns', None)
2424
super(SignalTestKernel, self).__init__(**kwargs)
2525
self.children = []
26-
2726

2827
def do_execute(self, code, silent, store_history=True, user_expressions=None,
2928
allow_stdin=False):
@@ -51,6 +50,14 @@ def do_execute(self, code, silent, store_history=True, user_expressions=None,
5150
reply['evalue'] = code
5251
reply['traceback'] = ['no such command: %s' % code]
5352
return reply
53+
54+
def kernel_info_request(self, *args, **kwargs):
55+
"""Add delay to kernel_info_request
56+
57+
triggers slow-response code in KernelClient.wait_for_ready
58+
"""
59+
time.sleep(1)
60+
return super(SignalTestKernel, self).kernel_info_request(*args, **kwargs)
5461

5562
class SignalTestApp(IPKernelApp):
5663
kernel_class = SignalTestKernel

jupyter_client/tests/test_kernelmanager.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,3 +120,12 @@ def execute(cmd):
120120
break
121121
# verify that subprocesses were interrupted
122122
self.assertEqual(reply['user_expressions']['poll'], [-signal.SIGINT] * N)
123+
124+
def test_start_new_kernel(self):
125+
self._install_test_kernel()
126+
km, kc = start_new_kernel(kernel_name='signaltest')
127+
self.addCleanup(kc.stop_channels)
128+
self.addCleanup(km.shutdown_kernel)
129+
130+
self.assertTrue(km.is_alive())
131+
self.assertTrue(kc.is_alive())

0 commit comments

Comments
 (0)