Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 2ca678c

Browse filesBrowse files
committed
FIX: destroy figs in python when destroyed in js
- only actually closes the figure (in the mpl sense) if all of the managers active comms are dead - closes figure when all visible copies are removed from dom - eliminates many of the [IPKernelApp] ERROR | No such comm: XXXX errors closes #4841
1 parent 72c82e8 commit 2ca678c
Copy full SHA for 2ca678c

File tree

Expand file treeCollapse file tree

2 files changed

+38
-7
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+38
-7
lines changed

‎lib/matplotlib/backends/backend_nbagg.py

Copy file name to clipboardExpand all lines: lib/matplotlib/backends/backend_nbagg.py
+24-5Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -160,16 +160,22 @@ def _create_comm(self):
160160

161161
def destroy(self):
162162
self._send_event('close')
163-
for comm in self.web_sockets.copy():
163+
# need to copy comms as callbacks will modify this list
164+
for comm in list(self.web_sockets):
164165
comm.on_close()
166+
self.clearup_closed()
165167

166168
def clearup_closed(self):
167169
"""Clear up any closed Comms."""
168170
self.web_sockets = set([socket for socket in self.web_sockets
169171
if socket.is_open()])
170172

171173
if len(self.web_sockets) == 0:
172-
self.manager.canvas.close_event()
174+
self.canvas.close_event()
175+
176+
def remove_comm(self, comm_id):
177+
self.web_sockets = set([socket for socket in self.web_sockets
178+
if not socket.comm.comm_id == comm_id])
173179

174180

175181
class TimerTornado(TimerBase):
@@ -267,15 +273,27 @@ def __init__(self, manager):
267273
self.comm.on_msg(self.on_message)
268274

269275
manager = self.manager
270-
self.comm.on_close(lambda close_message: manager.clearup_closed())
276+
self._ext_close = False
277+
278+
def _on_close(close_message):
279+
self._ext_close = True
280+
manager.remove_comm(close_message['content']['comm_id'])
281+
manager.clearup_closed()
282+
283+
self.comm.on_close(_on_close)
271284

272285
def is_open(self):
273-
return not self.comm._closed
286+
return not (self._ext_close or self.comm._closed)
274287

275288
def on_close(self):
276289
# When the socket is closed, deregister the websocket with
277290
# the FigureManager.
278-
self.comm.close()
291+
if self.is_open():
292+
try:
293+
self.comm.close()
294+
except KeyError:
295+
# apparently already cleaned it up?
296+
pass
279297

280298
def send_json(self, content):
281299
self.comm.send({'data': json.dumps(content)})
@@ -298,6 +316,7 @@ def on_message(self, message):
298316
message = json.loads(message['content']['data'])
299317
if message['type'] == 'closing':
300318
self.on_close()
319+
self.manager.clearup_closed()
301320
elif message['type'] == 'supports_binary':
302321
self.supports_binary = message['value']
303322
else:

‎lib/matplotlib/backends/web_backend/nbagg_mpl.js

Copy file name to clipboardExpand all lines: lib/matplotlib/backends/web_backend/nbagg_mpl.js
+14-2Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,21 @@ mpl.mpl_figure_comm = function(comm, msg) {
5555
};
5656

5757
mpl.figure.prototype.handle_close = function(fig, msg) {
58+
fig.root.unbind('remove')
59+
5860
// Update the output cell to use the data from the current canvas.
5961
fig.push_to_output();
6062
var dataURL = fig.canvas.toDataURL();
6163
// Re-enable the keyboard manager in IPython - without this line, in FF,
6264
// the notebook keyboard shortcuts fail.
6365
IPython.keyboard_manager.enable()
6466
$(fig.parent_element).html('<img src="' + dataURL + '">');
65-
fig.send_message('closing', {});
66-
fig.ws.close()
67+
fig.close_ws(fig, msg);
68+
}
69+
70+
mpl.figure.prototype.close_ws = function(fig, msg){
71+
fig.send_message('closing', msg);
72+
// fig.ws.close()
6773
}
6874

6975
mpl.figure.prototype.push_to_output = function(remove_interactive) {
@@ -126,6 +132,12 @@ mpl.figure.prototype._init_toolbar = function() {
126132
titlebar.prepend(buttongrp);
127133
}
128134

135+
mpl.figure.prototype._root_extra_style = function(el){
136+
var fig = this
137+
el.on("remove", function(){
138+
fig.close_ws(fig, {});
139+
});
140+
}
129141

130142
mpl.figure.prototype._canvas_extra_style = function(el){
131143
// this is important to make the div 'focusable

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.