diff --git a/IPython/html/static/services/kernels/js/comm.js b/IPython/html/static/services/kernels/js/comm.js
index 4cb24a6..04307cf 100644
--- a/IPython/html/static/services/kernels/js/comm.js
+++ b/IPython/html/static/services/kernels/js/comm.js
@@ -56,9 +56,9 @@ define([
return comm.comm_id;
};
- CommManager.prototype.unregister_comm = function (comm_id) {
+ CommManager.prototype.unregister_comm = function (comm) {
// Remove a comm from the mapping
- delete this.comms[comm_id];
+ delete this.comms[comm.comm_id];
};
// comm message handlers
@@ -88,7 +88,7 @@ define([
if (comm === undefined) {
return;
}
- delete this.comms[content.comm_id];
+ this.unregister_comm(comm);
try {
comm.handle_close(msg);
} catch (e) {
diff --git a/IPython/html/widgets/widget.py b/IPython/html/widgets/widget.py
index 345a4c7..745e7d6 100644
--- a/IPython/html/widgets/widget.py
+++ b/IPython/html/widgets/widget.py
@@ -141,7 +141,6 @@ class Widget(LoggingConfigurable):
# Create a comm.
self._comm = Comm(target_name=self._model_name)
self._comm.on_msg(self._handle_msg)
- self._comm.on_close(self._close)
Widget.widgets[self.model_id] = self
# first update
@@ -158,21 +157,18 @@ class Widget(LoggingConfigurable):
#-------------------------------------------------------------------------
# Methods
#-------------------------------------------------------------------------
- def _close(self):
- """Private close - cleanup objects, registry entries"""
- del Widget.widgets[self.model_id]
- self._comm = None
def close(self):
"""Close method.
- Closes the widget which closes the underlying comm.
+ Closes the underlying comm.
When the comm is closed, all of the widget views are automatically
removed from the front-end."""
+ del Widget.widgets[self.model_id]
if self._comm is not None:
self._comm.close()
- self._close()
-
+ self._comm = None
+
def send_state(self, key=None):
"""Sends the widget state, or a piece of it, to the front-end.
diff --git a/IPython/kernel/comm/comm.py b/IPython/kernel/comm/comm.py
index d9c37af..502210b 100644
--- a/IPython/kernel/comm/comm.py
+++ b/IPython/kernel/comm/comm.py
@@ -50,7 +50,6 @@ class Comm(LoggingConfigurable):
if target_name:
kwargs['target_name'] = target_name
super(Comm, self).__init__(**kwargs)
- get_ipython().comm_manager.register_comm(self)
if self.primary:
# I am primary, open my peer.
self.open(data)
@@ -77,6 +76,8 @@ class Comm(LoggingConfigurable):
"""Open the frontend-side version of this comm"""
if data is None:
data = self._open_data
+ self._closed = False
+ get_ipython().comm_manager.register_comm(self)
self._publish_msg('comm_open', data, metadata, target_name=self.target_name)
def close(self, data=None, metadata=None):
@@ -87,6 +88,7 @@ class Comm(LoggingConfigurable):
if data is None:
data = self._close_data
self._publish_msg('comm_close', data, metadata)
+ get_ipython().comm_manager.unregister_comm(self)
self._closed = True
def send(self, data=None, metadata=None):
diff --git a/IPython/kernel/comm/manager.py b/IPython/kernel/comm/manager.py
index fdc7ba6..b1c2332 100644
--- a/IPython/kernel/comm/manager.py
+++ b/IPython/kernel/comm/manager.py
@@ -72,11 +72,10 @@ class CommManager(LoggingConfigurable):
self.comms[comm_id] = comm
return comm_id
- def unregister_comm(self, comm_id):
+ def unregister_comm(self, comm):
"""Unregister a comm, and close its counterpart"""
# unlike get_comm, this should raise a KeyError
- comm = self.comms.pop(comm_id)
- comm.close()
+ comm = self.comms.pop(comm.comm_id)
def get_comm(self, comm_id):
"""Get a comm with a particular id
@@ -110,13 +109,11 @@ class CommManager(LoggingConfigurable):
self.log.error("No such comm target registered: %s", target_name)
comm.close()
return
- self.register_comm(comm)
try:
f(comm, msg)
except Exception:
self.log.error("Exception opening comm with target: %s", target_name, exc_info=True)
comm.close()
- self.unregister_comm(comm_id)
def comm_msg(self, stream, ident, msg):
"""Handler for comm_msg messages"""