From 0702e32875e0952d479ba9fbdc7d2c44b5c8f950 Mon Sep 17 00:00:00 2001 From: Min RK Date: Wed, 14 Apr 2021 11:26:42 +0200 Subject: [PATCH 1/2] make deprecated shell_streams writable shell_streams is deprecated, but keep it working with deprecation warnings instead of breaking it and handle debugpy_stream being undefined, since allow_none is True --- ipykernel/ipkernel.py | 5 ++++- ipykernel/kernelbase.py | 38 +++++++++++++++++++++++++++++++++----- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/ipykernel/ipkernel.py b/ipykernel/ipkernel.py index f9125b992..38cef9f92 100644 --- a/ipykernel/ipkernel.py +++ b/ipykernel/ipkernel.py @@ -162,7 +162,10 @@ def banner(self): def start(self): self.shell.exit_now = False - self.debugpy_stream.on_recv(self.dispatch_debugpy, copy=False) + if self.debugpy_stream is None: + self.log.warning("debugpy_stream undefined, debugging will not be enabled") + else: + self.debugpy_stream.on_recv(self.dispatch_debugpy, copy=False) super(IPythonKernel, self).start() def set_parent(self, ident, parent, channel='shell'): diff --git a/ipykernel/kernelbase.py b/ipykernel/kernelbase.py index bbd7a2a20..21552e758 100644 --- a/ipykernel/kernelbase.py +++ b/ipykernel/kernelbase.py @@ -59,13 +59,41 @@ def _update_eventloop(self, change): profile_dir = Instance('IPython.core.profiledir.ProfileDir', allow_none=True) shell_stream = Instance(ZMQStream, allow_none=True) - @property - def shell_streams(self): + shell_streams = List( + help="""Deprecated shell_streams alias. Use shell_stream + + .. versionchanged:: 6.0 + shell_streams is deprecated. Use shell_stream. + """ + ) + + @default("shell_streams") + def _shell_streams_default(self): warnings.warn( - 'Property shell_streams is deprecated in favor of shell_stream', - DeprecationWarning + "Kernel.shell_streams is deprecated in ipykernel 6.0. Use Kernel.shell_stream", + DeprecationWarning, + stacklevel=2, ) - return [self.shell_stream] + if self.shell_stream is not None: + return [self.shell_stream] + else: + return [] + + @observe("shell_streams") + def _shell_streams_changed(self, change): + warnings.warn( + "Kernel.shell_streams is deprecated in ipykernel 6.0. Use Kernel.shell_stream", + DeprecationWarning, + stacklevel=2, + ) + if len(change.new) > 1: + warnings.warn( + "Kernel only supports one shell stream. Additional streams will be ignored.", + RuntimeWarning, + stacklevel=2, + ) + if change.new: + self.shell_stream = change.new[0] control_stream = Instance(ZMQStream, allow_none=True) From a19816f8373e9e977cfd1d9d4833f874c930ad7c Mon Sep 17 00:00:00 2001 From: Min RK Date: Wed, 14 Apr 2021 11:38:24 +0200 Subject: [PATCH 2/2] ensure control messages are handled without optional control_thread and start handling them in `.start()` instead of `__init__` --- ipykernel/kernelbase.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ipykernel/kernelbase.py b/ipykernel/kernelbase.py index 21552e758..91a26df18 100644 --- a/ipykernel/kernelbase.py +++ b/ipykernel/kernelbase.py @@ -205,8 +205,6 @@ def __init__(self, **kwargs): self.control_handlers[msg_type] = getattr(self, msg_type) self.control_queue = Queue() - if 'control_thread' in kwargs: - kwargs['control_thread'].io_loop.add_callback(self.poll_control_queue) @gen.coroutine def dispatch_control(self, msg): @@ -452,6 +450,13 @@ def start(self): self.control_stream.on_recv(self.dispatch_control, copy=False) + if self.control_thread: + control_loop = self.control_thread.io_loop + else: + control_loop = self.io_loop + + control_loop.add_callback(self.poll_control_queue) + self.shell_stream.on_recv( partial( self.schedule_dispatch,