Skip to content

Commit

Permalink
Add models-request message on the control comm channel
Browse files Browse the repository at this point in the history
  • Loading branch information
martinRenou committed Nov 9, 2021
1 parent 16d0f57 commit d7e9b99
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 19 deletions.
2 changes: 1 addition & 1 deletion ipywidgets/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def register_comm_target(kernel=None):
if kernel is None:
kernel = get_ipython().kernel
kernel.comm_manager.register_target('jupyter.widget', Widget.handle_comm_opened)
kernel.comm_manager.register_target('jupyter.widget.control', Widget.handle_comm_opened_control)
kernel.comm_manager.register_target('jupyter.widget.control', Widget.handle_control_comm_opened)

# deprecated alias
handle_kernel = register_comm_target
Expand Down
3 changes: 2 additions & 1 deletion ipywidgets/widgets/tests/test_send_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,6 @@ def test_control():
comm = DummyComm()
Widget.close_all()
w = SimpleWidget()
Widget.handle_comm_opened_control(comm, {})
Widget.handle_control_comm_opened(comm, {})
Widget.handle_control_comm_msg({'type': 'models-request'})
assert comm.messages
44 changes: 28 additions & 16 deletions ipywidgets/widgets/widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ class Widget(LoggingHasTraits):
# Class attributes
#-------------------------------------------------------------------------
_widget_construction_callback = None
_control_comm = None

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


@staticmethod
def on_widget_constructed(callback):
"""Registers a callback to be called when a widget is constructed.
Expand All @@ -319,25 +319,37 @@ def _call_widget_constructed(widget):
Widget._widget_construction_callback(widget)

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

cls.get_manager_state()
widgets = Widget.widgets.values()
# build a single dict with the full widget state
full_state = {}
drop_defaults = False
for widget in widgets:
full_state[widget.model_id] = {
'model_name': widget._model_name,
'model_module': widget._model_module,
'model_module_version': widget._model_module_version,
'state': widget.get_state(drop_defaults=drop_defaults),
}
full_state, buffer_paths, buffers = _remove_buffers(full_state)
comm.send([full_state, buffer_paths], buffers=buffers)
cls._control_comm = comm
cls._control_comm.on_msg(cls.handle_control_comm_msg)

@classmethod
def handle_control_comm_msg(cls, msg):
# This shouldn't happen unless someone calls this method manually
if cls._control_comm is None:
raise RuntimeError('Control comm has not been properly opened')

if msg['content']['data']['type'] == 'models-request':
# Send back the full widgets state
cls.get_manager_state()
widgets = Widget.widgets.values()
full_state = {}
drop_defaults = False
for widget in widgets:
full_state[widget.model_id] = {
'model_name': widget._model_name,
'model_module': widget._model_module,
'model_module_version': widget._model_module_version,
'state': widget.get_state(drop_defaults=drop_defaults),
}
full_state, buffer_paths, buffers = _remove_buffers(full_state)
cls._control_comm.send([full_state, buffer_paths], buffers=buffers)
else:
raise RuntimeError('Control comm msg "{}" not implemented'.format(msg['content']['data']['type']))

@staticmethod
def handle_comm_opened(comm, msg):
Expand Down
4 changes: 3 additions & 1 deletion packages/schema/messages.md
Original file line number Diff line number Diff line change
Expand Up @@ -348,4 +348,6 @@ This is implemented in ipywidgets 7.7.

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

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.
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 `{"type": "models-request"}` message with a comm message containing the full state of all widget instances.

0 comments on commit d7e9b99

Please sign in to comment.