Skip to content

Commit

Permalink
Merge pull request #6540 from takluyver/comms-mgr-needs-no-shell
Browse files Browse the repository at this point in the history
Make comm manager (mostly) independent of InteractiveShell
  • Loading branch information
jdfreder committed Oct 12, 2014
2 parents 0ae5cd3 + 2bd78ac commit ddc0593
Show file tree
Hide file tree
Showing 8 changed files with 51 additions and 52 deletions.
9 changes: 0 additions & 9 deletions IPython/core/interactiveshell.py
Expand Up @@ -523,7 +523,6 @@ def __init__(self, ipython_dir=None, profile_dir=None,
self.init_pdb()
self.init_extension_manager()
self.init_payload()
self.init_comms()
self.hooks.late_startup_hook()
self.events.trigger('shell_initialized', self)
atexit.register(self.atexit_operations)
Expand Down Expand Up @@ -2418,14 +2417,6 @@ def init_payload(self):
self.payload_manager = PayloadManager(parent=self)
self.configurables.append(self.payload_manager)

#-------------------------------------------------------------------------
# Things related to widgets
#-------------------------------------------------------------------------

def init_comms(self):
# not implemented in the base class
pass

#-------------------------------------------------------------------------
# Things related to the prefilter
#-------------------------------------------------------------------------
Expand Down
3 changes: 3 additions & 0 deletions IPython/html/widgets/tests/test_interaction.py
Expand Up @@ -22,6 +22,9 @@
class DummyComm(Comm):
comm_id = 'a-b-c-d'

def open(self, *args, **kwargs):
pass

def send(self, *args, **kwargs):
pass

Expand Down
57 changes: 31 additions & 26 deletions IPython/kernel/comm/comm.py
Expand Up @@ -6,26 +6,29 @@
import uuid

from IPython.config import LoggingConfigurable
from IPython.core.getipython import get_ipython
from IPython.kernel.zmq.kernelbase import Kernel

from IPython.utils.jsonutil import json_clean
from IPython.utils.traitlets import Instance, Unicode, Bytes, Bool, Dict, Any


class Comm(LoggingConfigurable):

shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
def _shell_default(self):
return get_ipython()
# If this is instantiated by a non-IPython kernel, shell will be None
shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
allow_none=True)
kernel = Instance('IPython.kernel.zmq.kernelbase.Kernel')
def _kernel_default(self):
if Kernel.initialized():
return Kernel.instance()

iopub_socket = Any()
def _iopub_socket_default(self):
return self.shell.kernel.iopub_socket
return self.kernel.iopub_socket
session = Instance('IPython.kernel.zmq.session.Session')
def _session_default(self):
if self.shell is None or not hasattr(self.shell, 'kernel'):
return
return self.shell.kernel.session
if self.kernel is not None:
return self.kernel.session

target_name = Unicode('comm')

Expand Down Expand Up @@ -56,16 +59,15 @@ def __init__(self, target_name='', data=None, **kwargs):

def _publish_msg(self, msg_type, data=None, metadata=None, **keys):
"""Helper for sending a comm message on IOPub"""
if self.session is not None:
data = {} if data is None else data
metadata = {} if metadata is None else metadata
content = json_clean(dict(data=data, comm_id=self.comm_id, **keys))
self.session.send(self.iopub_socket, msg_type,
content,
metadata=json_clean(metadata),
parent=self.shell.get_parent(),
ident=self.topic,
)
data = {} if data is None else data
metadata = {} if metadata is None else metadata
content = json_clean(dict(data=data, comm_id=self.comm_id, **keys))
self.session.send(self.iopub_socket, msg_type,
content,
metadata=json_clean(metadata),
parent=self.kernel._parent_header,
ident=self.topic,
)

def __del__(self):
"""trigger close on gc"""
Expand All @@ -77,10 +79,13 @@ def open(self, data=None, metadata=None):
"""Open the frontend-side version of this comm"""
if data is None:
data = self._open_data
comm_manager = getattr(self.kernel, 'comm_manager', None)
if comm_manager is None:
raise RuntimeError("Comms cannot be opened without a kernel "
"and a comm_manager attached to that kernel.")

comm_manager.register_comm(self)
self._closed = False
ip = get_ipython()
if hasattr(ip, 'comm_manager'):
ip.comm_manager.register_comm(self)
self._publish_msg('comm_open', data, metadata, target_name=self.target_name)

def close(self, data=None, metadata=None):
Expand All @@ -91,9 +96,7 @@ def close(self, data=None, metadata=None):
if data is None:
data = self._close_data
self._publish_msg('comm_close', data, metadata)
ip = get_ipython()
if hasattr(ip, 'comm_manager'):
ip.comm_manager.unregister_comm(self)
self.kernel.comm_manager.unregister_comm(self)
self._closed = True

def send(self, data=None, metadata=None):
Expand Down Expand Up @@ -132,9 +135,11 @@ def handle_msg(self, msg):
"""Handle a comm_msg message"""
self.log.debug("handle_msg[%s](%s)", self.comm_id, msg)
if self._msg_callback:
self.shell.events.trigger('pre_execute')
if self.shell:
self.shell.events.trigger('pre_execute')
self._msg_callback(msg)
self.shell.events.trigger('post_execute')
if self.shell:
self.shell.events.trigger('post_execute')


__all__ = ['Comm']
16 changes: 9 additions & 7 deletions IPython/kernel/comm/manager.py
Expand Up @@ -28,17 +28,17 @@ def lazy_keys(dikt):
class CommManager(LoggingConfigurable):
"""Manager for Comms in the Kernel"""

shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
def _shell_default(self):
return get_ipython()
# If this is instantiated by a non-IPython kernel, shell will be None
shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
allow_none=True)
kernel = Instance('IPython.kernel.zmq.kernelbase.Kernel')

iopub_socket = Any()
def _iopub_socket_default(self):
return self.shell.kernel.iopub_socket
return self.kernel.iopub_socket
session = Instance('IPython.kernel.zmq.session.Session')
def _session_default(self):
if self.shell is None:
return
return self.shell.kernel.session
return self.kernel.session

comms = Dict()
targets = Dict()
Expand Down Expand Up @@ -68,6 +68,7 @@ def register_comm(self, comm):
"""Register a new comm"""
comm_id = comm.comm_id
comm.shell = self.shell
comm.kernel = self.kernel
comm.iopub_socket = self.iopub_socket
self.comms[comm_id] = comm
return comm_id
Expand Down Expand Up @@ -102,6 +103,7 @@ def comm_open(self, stream, ident, msg):
f = self.targets.get(target_name, None)
comm = Comm(comm_id=comm_id,
shell=self.shell,
kernel=self.kernel,
iopub_socket=self.iopub_socket,
primary=False,
)
Expand Down
7 changes: 5 additions & 2 deletions IPython/kernel/zmq/ipkernel.py
Expand Up @@ -10,6 +10,7 @@
from IPython.utils.traitlets import Instance, Type, Any
from IPython.utils.decorators import undoc

from ..comm import CommManager
from .kernelbase import Kernel as KernelBase
from .serialize import serialize_object, unpack_apply_message
from .zmqshell import ZMQInteractiveShell
Expand Down Expand Up @@ -55,10 +56,12 @@ def __init__(self, **kwargs):
# TMP - hack while developing
self.shell._reply_content = None

self.comm_manager = CommManager(shell=self.shell, parent=self,
kernel=self)
self.shell.configurables.append(self.comm_manager)
comm_msg_types = [ 'comm_open', 'comm_msg', 'comm_close' ]
comm_manager = self.shell.comm_manager
for msg_type in comm_msg_types:
self.shell_handlers[msg_type] = getattr(comm_manager, msg_type)
self.shell_handlers[msg_type] = getattr(self.comm_manager, msg_type)

# Kernel info fields
implementation = 'ipython'
Expand Down
2 changes: 1 addition & 1 deletion IPython/kernel/zmq/kernelapp.py
Expand Up @@ -302,7 +302,7 @@ def init_kernel(self):
shell_stream = ZMQStream(self.shell_socket)
control_stream = ZMQStream(self.control_socket)

kernel_factory = self.kernel_class
kernel_factory = self.kernel_class.instance

kernel = kernel_factory(parent=self, session=self.session,
shell_streams=[shell_stream, control_stream],
Expand Down
4 changes: 2 additions & 2 deletions IPython/kernel/zmq/kernelbase.py
Expand Up @@ -19,7 +19,7 @@
from zmq.eventloop import ioloop
from zmq.eventloop.zmqstream import ZMQStream

from IPython.config.configurable import Configurable
from IPython.config.configurable import SingletonConfigurable
from IPython.core.error import StdinNotImplementedError
from IPython.core import release
from IPython.utils import py3compat
Expand All @@ -32,7 +32,7 @@
from .session import Session


class Kernel(Configurable):
class Kernel(SingletonConfigurable):

#---------------------------------------------------------------------------
# Kernel interface
Expand Down
5 changes: 0 additions & 5 deletions IPython/kernel/zmq/zmqshell.py
Expand Up @@ -49,7 +49,6 @@
from IPython.kernel.zmq.displayhook import ZMQShellDisplayHook
from IPython.kernel.zmq.datapub import ZMQDataPublisher
from IPython.kernel.zmq.session import extract_header
from IPython.kernel.comm import CommManager
from .session import Session

#-----------------------------------------------------------------------------
Expand Down Expand Up @@ -563,10 +562,6 @@ def init_magics(self):
super(ZMQInteractiveShell, self).init_magics()
self.register_magics(KernelMagics)
self.magics_manager.register_alias('ed', 'edit')

def init_comms(self):
self.comm_manager = CommManager(shell=self, parent=self)
self.configurables.append(self.comm_manager)


InteractiveShellABC.register(ZMQInteractiveShell)

0 comments on commit ddc0593

Please sign in to comment.