Skip to content

Commit d7e9b99

Browse files
committed
Add models-request message on the control comm channel
1 parent 16d0f57 commit d7e9b99

File tree

4 files changed

+34
-19
lines changed

4 files changed

+34
-19
lines changed

ipywidgets/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def register_comm_target(kernel=None):
3838
if kernel is None:
3939
kernel = get_ipython().kernel
4040
kernel.comm_manager.register_target('jupyter.widget', Widget.handle_comm_opened)
41-
kernel.comm_manager.register_target('jupyter.widget.control', Widget.handle_comm_opened_control)
41+
kernel.comm_manager.register_target('jupyter.widget.control', Widget.handle_control_comm_opened)
4242

4343
# deprecated alias
4444
handle_kernel = register_comm_target

ipywidgets/widgets/tests/test_send_state.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,6 @@ def test_control():
2929
comm = DummyComm()
3030
Widget.close_all()
3131
w = SimpleWidget()
32-
Widget.handle_comm_opened_control(comm, {})
32+
Widget.handle_control_comm_opened(comm, {})
33+
Widget.handle_control_comm_msg({'type': 'models-request'})
3334
assert comm.messages

ipywidgets/widgets/widget.py

+28-16
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,7 @@ class Widget(LoggingHasTraits):
291291
# Class attributes
292292
#-------------------------------------------------------------------------
293293
_widget_construction_callback = None
294+
_control_comm = None
294295

295296
# widgets is a dictionary of all active widget objects
296297
widgets = {}
@@ -303,7 +304,6 @@ def close_all(cls):
303304
for widget in list(cls.widgets.values()):
304305
widget.close()
305306

306-
307307
@staticmethod
308308
def on_widget_constructed(callback):
309309
"""Registers a callback to be called when a widget is constructed.
@@ -319,25 +319,37 @@ def _call_widget_constructed(widget):
319319
Widget._widget_construction_callback(widget)
320320

321321
@classmethod
322-
def handle_comm_opened_control(cls, comm, msg):
322+
def handle_control_comm_opened(cls, comm, msg):
323323
version = msg.get('metadata', {}).get('version', '')
324324
if version.split('.')[0] != CONTROL_PROTOCOL_VERSION_MAJOR:
325325
raise ValueError("Incompatible widget control protocol versions: received version %r, expected version %r"%(version, __control_protocol_version__))
326326

327-
cls.get_manager_state()
328-
widgets = Widget.widgets.values()
329-
# build a single dict with the full widget state
330-
full_state = {}
331-
drop_defaults = False
332-
for widget in widgets:
333-
full_state[widget.model_id] = {
334-
'model_name': widget._model_name,
335-
'model_module': widget._model_module,
336-
'model_module_version': widget._model_module_version,
337-
'state': widget.get_state(drop_defaults=drop_defaults),
338-
}
339-
full_state, buffer_paths, buffers = _remove_buffers(full_state)
340-
comm.send([full_state, buffer_paths], buffers=buffers)
327+
cls._control_comm = comm
328+
cls._control_comm.on_msg(cls.handle_control_comm_msg)
329+
330+
@classmethod
331+
def handle_control_comm_msg(cls, msg):
332+
# This shouldn't happen unless someone calls this method manually
333+
if cls._control_comm is None:
334+
raise RuntimeError('Control comm has not been properly opened')
335+
336+
if msg['content']['data']['type'] == 'models-request':
337+
# Send back the full widgets state
338+
cls.get_manager_state()
339+
widgets = Widget.widgets.values()
340+
full_state = {}
341+
drop_defaults = False
342+
for widget in widgets:
343+
full_state[widget.model_id] = {
344+
'model_name': widget._model_name,
345+
'model_module': widget._model_module,
346+
'model_module_version': widget._model_module_version,
347+
'state': widget.get_state(drop_defaults=drop_defaults),
348+
}
349+
full_state, buffer_paths, buffers = _remove_buffers(full_state)
350+
cls._control_comm.send([full_state, buffer_paths], buffers=buffers)
351+
else:
352+
raise RuntimeError('Control comm msg "{}" not implemented'.format(msg['content']['data']['type']))
341353

342354
@staticmethod
343355
def handle_comm_opened(comm, msg):

packages/schema/messages.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -348,4 +348,6 @@ This is implemented in ipywidgets 7.7.
348348

349349
### The `jupyter.widget.control` comm target
350350

351-
A kernel-side Jupyter widgets library registers a `jupyter.widget.control` comm target that is used for fetching all widgets states through a "one shot" comm message (one for all widget instances). The kernel-side widgets library must answer to the "comm-open" message with a comm message containing the full state of all widget instances.
351+
A kernel-side Jupyter widgets library registers a `jupyter.widget.control` comm target that is used for fetching all widgets states through a "one shot" comm message (one for all widget instances).
352+
353+
The kernel-side widgets library must answer to the `{"type": "models-request"}` message with a comm message containing the full state of all widget instances.

0 commit comments

Comments
 (0)