diff --git a/python/ipywidgets/ipywidgets/__init__.py b/python/ipywidgets/ipywidgets/__init__.py index 4eb69423564..04b27494c0f 100644 --- a/python/ipywidgets/ipywidgets/__init__.py +++ b/python/ipywidgets/ipywidgets/__init__.py @@ -21,28 +21,26 @@ from ._version import __version__, __protocol_version__, __jupyter_widgets_controls_version__, __jupyter_widgets_base_version__ import os -from IPython import get_ipython -from .widgets import * + from traitlets import link, dlink +from comm import get_comm_manager + +from .widgets import * + def load_ipython_extension(ip): """Set up Jupyter to work with widgets""" - if not hasattr(ip, 'kernel'): - return - register_comm_target(ip.kernel) + register_comm_target() -def register_comm_target(kernel=None): +def register_comm_target(): """Register the jupyter.widget comm target""" - 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_control_comm_opened) + comm_manager = get_comm_manager() + + comm_manager.register_target('jupyter.widget', Widget.handle_comm_opened) + comm_manager.register_target('jupyter.widget.control', Widget.handle_control_comm_opened) def _handle_ipython(): """Register with the comm target at import if running in Jupyter""" - ip = get_ipython() - if ip is None: - return - load_ipython_extension(ip) + register_comm_target() _handle_ipython() diff --git a/python/ipywidgets/ipywidgets/widgets/tests/test_widget_templates.py b/python/ipywidgets/ipywidgets/widgets/tests/test_widget_templates.py index e53683630cd..c551bcf0950 100644 --- a/python/ipywidgets/ipywidgets/widgets/tests/test_widget_templates.py +++ b/python/ipywidgets/ipywidgets/widgets/tests/test_widget_templates.py @@ -220,7 +220,6 @@ def test_update_dynamically(self, send_state): #pylint: disable=no-self-use assert box.layout.grid_template_areas == ('"top-left top-right"\n' + '"top-left bottom-right"') - box.layout.comm.kernel = mock.MagicMock(spec=Kernel) #for mocking purposes send_state.reset_mock() box.bottom_left = button2 @@ -235,7 +234,6 @@ def test_update_dynamically(self, send_state): #pylint: disable=no-self-use bottom_left=None, bottom_right=button4) assert box.layout.grid_template_areas == ('"top-left top-right"\n' + '"top-left bottom-right"') - box.layout.comm.kernel = mock.MagicMock(spec=Kernel) #for mocking purposes send_state.reset_mock() box.merge = False assert box.layout.grid_template_areas == ('"top-left top-right"\n' + diff --git a/python/ipywidgets/ipywidgets/widgets/tests/test_widget_upload.py b/python/ipywidgets/ipywidgets/widgets/tests/test_widget_upload.py index f8dc1a8ceed..9434c683c9f 100644 --- a/python/ipywidgets/ipywidgets/widgets/tests/test_widget_upload.py +++ b/python/ipywidgets/ipywidgets/widgets/tests/test_widget_upload.py @@ -76,7 +76,6 @@ def test_serialization_deserialization_integrity(self): from ipykernel.comm import Comm uploader = FileUpload() mock_comm = MagicMock(spec=Comm) - mock_comm.kernel = 'does not matter' mock_comm.send = MagicMock() uploader.comm = mock_comm message = {'value': [FILE_UPLOAD_FRONTEND_CONTENT]} diff --git a/python/ipywidgets/ipywidgets/widgets/tests/utils.py b/python/ipywidgets/ipywidgets/widgets/tests/utils.py index 7b9b8fcc298..0c1b1984d1b 100644 --- a/python/ipywidgets/ipywidgets/widgets/tests/utils.py +++ b/python/ipywidgets/ipywidgets/widgets/tests/utils.py @@ -1,11 +1,10 @@ # Copyright (c) Jupyter Development Team. # Distributed under the terms of the Modified BSD License. -from ipykernel.comm import Comm from ipywidgets import Widget import ipywidgets.widgets.widget -class DummyComm(Comm): +class DummyComm(): comm_id = 'a-b-c-d' kernel = 'Truthy' diff --git a/python/ipywidgets/ipywidgets/widgets/widget.py b/python/ipywidgets/ipywidgets/widgets/widget.py index 030fdc45ce8..0c0492171ad 100644 --- a/python/ipywidgets/ipywidgets/widgets/widget.py +++ b/python/ipywidgets/ipywidgets/widgets/widget.py @@ -10,9 +10,9 @@ from contextlib import contextmanager from collections.abc import Iterable from IPython import get_ipython -from ipykernel.comm import Comm +from comm import create_comm from traitlets import ( - HasTraits, Unicode, Dict, Instance, List, Int, Set, Bytes, observe, default, Container, + Any, HasTraits, Unicode, Dict, Instance, List, Int, Set, Bytes, observe, default, Container, Undefined) from json import loads as jsonloads, dumps as jsondumps @@ -480,7 +480,7 @@ def get_view_spec(self): _view_count = Int(None, allow_none=True, help="EXPERIMENTAL: The number of views of the model displayed in the frontend. This attribute is experimental and may change or be removed in the future. None signifies that views will not be tracked. Set this to 0 to start tracking view creation/deletion.").tag(sync=True) - comm = Instance('ipykernel.comm.Comm', allow_none=True) + comm = Any(None, allow_none=True) keys = List(help="The traits which are synced.") @@ -525,7 +525,7 @@ def open(self): if self._model_id is not None: args['comm_id'] = self._model_id - self.comm = Comm(**args) + self.comm = create_comm(**args) @observe('comm') def _comm_changed(self, change): @@ -686,11 +686,10 @@ def notify_change(self, change): # Send the state to the frontend before the user-registered callbacks # are called. name = change['name'] - if self.comm is not None and self.comm.kernel is not None: - # Make sure this isn't information that the front-end just sent us. - if name in self.keys and self._should_send_property(name, getattr(self, name)): - # Send new state to front-end - self.send_state(key=name) + # Make sure this isn't information that the front-end just sent us. + if name in self.keys and self._should_send_property(name, getattr(self, name)): + # Send new state to front-end + self.send_state(key=name) super().notify_change(change) def __repr__(self): @@ -814,7 +813,7 @@ def _repr_mimebundle_(self, **kwargs): def _send(self, msg, buffers=None): """Sends a message to the model in the front-end.""" - if self.comm is not None and self.comm.kernel is not None: + if self.comm is not None: self.comm.send(data=msg, buffers=buffers) def _repr_keys(self): diff --git a/python/ipywidgets/ipywidgets/widgets/widget_output.py b/python/ipywidgets/ipywidgets/widgets/widget_output.py index 6d1bfdae4bc..ba6098e60e5 100644 --- a/python/ipywidgets/ipywidgets/widgets/widget_output.py +++ b/python/ipywidgets/ipywidgets/widgets/widget_output.py @@ -111,9 +111,7 @@ def __enter__(self): kernel = None if ip and getattr(ip, "kernel", None) is not None: kernel = ip.kernel - elif self.comm is not None and self.comm.kernel is not None: - kernel = self.comm.kernel - + if kernel: parent = None if hasattr(kernel, "get_parent"): @@ -134,15 +132,6 @@ def __exit__(self, etype, evalue, tb): if ip: kernel = ip ip.showtraceback((etype, evalue, tb), tb_offset=0) - elif self.comm is not None and self.comm.kernel is not None: - kernel = self.comm.kernel - kernel.send_response(kernel.iopub_socket, - u'error', - { - u'traceback': ["".join(traceback.format_exception(etype, evalue, tb))], - u'evalue': repr(evalue.args), - u'ename': etype.__name__ - }) self._flush() self.__counter -= 1 if self.__counter == 0: