Skip to content

Commit 81f707d

Browse files
committed
Move comm package
1 parent 7325e59 commit 81f707d

File tree

10 files changed

+62
-24
lines changed

10 files changed

+62
-24
lines changed

.github/workflows/tests.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ jobs:
131131
- name: Install Python dependencies
132132
run: |
133133
python -m pip install --upgrade pip
134-
pip install file://$PWD/python/ipywidgets#egg=ipywidgets
134+
pip install file://$PWD/python/ipywidgets#egg=ipywidgets[test]
135135
- name: Install JS dependencies
136136
run: |
137137
yarn

python/ipywidgets/ipywidgets/__init__.py

+15-7
Original file line numberDiff line numberDiff line change
@@ -21,28 +21,36 @@
2121
from ._version import __version__, __protocol_version__, __jupyter_widgets_controls_version__, __jupyter_widgets_base_version__
2222

2323
import os
24+
25+
from traitlets import link, dlink
2426
from IPython import get_ipython
27+
try:
28+
from comm import get_comm_manager
29+
except ImportError:
30+
def get_comm_manager():
31+
return get_ipython().kernel.comm_manager
32+
2533
from .widgets import *
26-
from traitlets import link, dlink
34+
2735

2836
def load_ipython_extension(ip):
2937
"""Set up Jupyter to work with widgets"""
3038
if not hasattr(ip, 'kernel'):
3139
return
32-
register_comm_target(ip.kernel)
40+
register_comm_target()
3341

3442
def register_comm_target(kernel=None):
3543
"""Register the jupyter.widget comm target"""
36-
if kernel is None:
37-
kernel = get_ipython().kernel
38-
kernel.comm_manager.register_target('jupyter.widget', Widget.handle_comm_opened)
39-
kernel.comm_manager.register_target('jupyter.widget.control', Widget.handle_control_comm_opened)
44+
comm_manager = get_comm_manager()
45+
46+
comm_manager.register_target('jupyter.widget', Widget.handle_comm_opened)
47+
comm_manager.register_target('jupyter.widget.control', Widget.handle_control_comm_opened)
4048

4149
def _handle_ipython():
4250
"""Register with the comm target at import if running in Jupyter"""
4351
ip = get_ipython()
4452
if ip is None:
4553
return
46-
load_ipython_extension(ip)
54+
register_comm_target()
4755

4856
_handle_ipython()

python/ipywidgets/ipywidgets/tests/test_embed.py

+3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99

1010
import traitlets
1111

12+
# This has a byproduct of setting up the comms
13+
import ipykernel.ipkernel
14+
1215
from ..widgets import IntSlider, IntText, Text, Widget, jslink, HBox, widget_serialization, widget as widget_module
1316
from ..embed import embed_data, embed_snippet, embed_minimal_html, dependency_state
1417

python/ipywidgets/ipywidgets/widgets/tests/test_interaction.py

-1
Original file line numberDiff line numberDiff line change
@@ -624,4 +624,3 @@ def test_state_schema():
624624
with open(os.path.join(os.path.dirname(os.path.realpath(__file__)), '../../', 'state.schema.json')) as f:
625625
schema = json.load(f)
626626
jsonschema.validate(state, schema)
627-

python/ipywidgets/ipywidgets/widgets/tests/test_widget_templates.py

-2
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,6 @@ def test_update_dynamically(self, send_state): #pylint: disable=no-self-use
220220
assert box.layout.grid_template_areas == ('"top-left top-right"\n' +
221221
'"top-left bottom-right"')
222222

223-
box.layout.comm.kernel = mock.MagicMock(spec=Kernel) #for mocking purposes
224223
send_state.reset_mock()
225224
box.bottom_left = button2
226225

@@ -235,7 +234,6 @@ def test_update_dynamically(self, send_state): #pylint: disable=no-self-use
235234
bottom_left=None, bottom_right=button4)
236235
assert box.layout.grid_template_areas == ('"top-left top-right"\n' +
237236
'"top-left bottom-right"')
238-
box.layout.comm.kernel = mock.MagicMock(spec=Kernel) #for mocking purposes
239237
send_state.reset_mock()
240238
box.merge = False
241239
assert box.layout.grid_template_areas == ('"top-left top-right"\n' +

python/ipywidgets/ipywidgets/widgets/tests/test_widget_upload.py

-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ def test_serialization_deserialization_integrity(self):
7676
from ipykernel.comm import Comm
7777
uploader = FileUpload()
7878
mock_comm = MagicMock(spec=Comm)
79-
mock_comm.kernel = 'does not matter'
8079
mock_comm.send = MagicMock()
8180
uploader.comm = mock_comm
8281
message = {'value': [FILE_UPLOAD_FRONTEND_CONTENT]}

python/ipywidgets/ipywidgets/widgets/tests/utils.py

+24-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
# Copyright (c) Jupyter Development Team.
22
# Distributed under the terms of the Modified BSD License.
33

4-
from ipykernel.comm import Comm
54
from ipywidgets import Widget
65
import ipywidgets.widgets.widget
76

8-
class DummyComm(Comm):
7+
import comm
8+
from ipykernel.comm import Comm
9+
10+
11+
class DummyComm():
912
comm_id = 'a-b-c-d'
1013
kernel = 'Truthy'
1114

@@ -16,16 +19,33 @@ def __init__(self, *args, **kwargs):
1619
def open(self, *args, **kwargs):
1720
pass
1821

22+
def on_msg(self, *args, **kwargs):
23+
pass
24+
1925
def send(self, *args, **kwargs):
2026
self.messages.append((args, kwargs))
2127

2228
def close(self, *args, **kwargs):
2329
pass
2430

31+
32+
def dummy_create_comm(**kwargs):
33+
return DummyComm()
34+
35+
36+
def dummy_get_comm_manager(**kwargs):
37+
return {}
38+
39+
2540
_widget_attrs = {}
2641
undefined = object()
2742

43+
orig_create_comm = comm.create_comm
44+
orig_get_comm_manager = comm.get_comm_manager
45+
2846
def setup_test_comm():
47+
comm.create_comm = dummy_create_comm
48+
comm.get_comm_manager = dummy_get_comm_manager
2949
Widget.comm.klass = DummyComm
3050
ipywidgets.widgets.widget.Comm = DummyComm
3151
_widget_attrs['_repr_mimebundle_'] = Widget._repr_mimebundle_
@@ -34,6 +54,8 @@ def raise_not_implemented(*args, **kwargs):
3454
Widget._repr_mimebundle_ = raise_not_implemented
3555

3656
def teardown_test_comm():
57+
comm.create_comm = orig_create_comm
58+
comm.get_comm_manager = orig_get_comm_manager
3759
Widget.comm.klass = Comm
3860
ipywidgets.widgets.widget.Comm = Comm
3961
for attr, value in _widget_attrs.items():

python/ipywidgets/ipywidgets/widgets/widget.py

+13-6
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,8 @@
1010
from contextlib import contextmanager
1111
from collections.abc import Iterable
1212
from IPython import get_ipython
13-
from ipykernel.comm import Comm
1413
from traitlets import (
15-
HasTraits, Unicode, Dict, Instance, List, Int, Set, Bytes, observe, default, Container,
14+
Any, HasTraits, Unicode, Dict, Instance, List, Int, Set, Bytes, observe, default, Container,
1615
Undefined)
1716
from json import loads as jsonloads, dumps as jsondumps
1817

@@ -480,7 +479,7 @@ def get_view_spec(self):
480479

481480
_view_count = Int(None, allow_none=True,
482481
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)
483-
comm = Instance('ipykernel.comm.Comm', allow_none=True)
482+
comm = Any(None, allow_none=True)
484483

485484
keys = List(help="The traits which are synced.")
486485

@@ -525,7 +524,15 @@ def open(self):
525524
if self._model_id is not None:
526525
args['comm_id'] = self._model_id
527526

528-
self.comm = Comm(**args)
527+
try:
528+
from comm import create_comm
529+
except ImportError:
530+
def create_comm(**kwargs):
531+
from ipykernel.comm import Comm
532+
533+
return Comm(**kwargs)
534+
535+
self.comm = create_comm(**args)
529536

530537
@observe('comm')
531538
def _comm_changed(self, change):
@@ -686,7 +693,7 @@ def notify_change(self, change):
686693
# Send the state to the frontend before the user-registered callbacks
687694
# are called.
688695
name = change['name']
689-
if self.comm is not None and self.comm.kernel is not None:
696+
if self.comm is not None:
690697
# Make sure this isn't information that the front-end just sent us.
691698
if name in self.keys and self._should_send_property(name, getattr(self, name)):
692699
# Send new state to front-end
@@ -814,7 +821,7 @@ def _repr_mimebundle_(self, **kwargs):
814821

815822
def _send(self, msg, buffers=None):
816823
"""Sends a message to the model in the front-end."""
817-
if self.comm is not None and self.comm.kernel is not None:
824+
if self.comm is not None:
818825
self.comm.send(data=msg, buffers=buffers)
819826

820827
def _repr_keys(self):

python/ipywidgets/ipywidgets/widgets/widget_output.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,9 @@ def __enter__(self):
111111
kernel = None
112112
if ip and getattr(ip, "kernel", None) is not None:
113113
kernel = ip.kernel
114-
elif self.comm is not None and self.comm.kernel is not None:
114+
elif self.comm is not None and getattr(self.comm, "kernel", None) is not None:
115115
kernel = self.comm.kernel
116-
116+
117117
if kernel:
118118
parent = None
119119
if hasattr(kernel, "get_parent"):
@@ -134,7 +134,9 @@ def __exit__(self, etype, evalue, tb):
134134
if ip:
135135
kernel = ip
136136
ip.showtraceback((etype, evalue, tb), tb_offset=0)
137-
elif self.comm is not None and self.comm.kernel is not None:
137+
elif (self.comm is not None and
138+
getattr(self.comm, "kernel", None) is not None and
139+
getattr(self.comm.kernel, "send_response", None) is not None):
138140
kernel = self.comm.kernel
139141
kernel.send_response(kernel.iopub_socket,
140142
u'error',

python/ipywidgets/setup.cfg

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ zip_safe = False
3434
packages = find:
3535

3636
install_requires =
37-
ipykernel>=4.5.1
3837
ipython>=6.1.0
3938
traitlets>=4.3.1
4039
widgetsnbextension~=4.0
@@ -43,6 +42,7 @@ install_requires =
4342
[options.extras_require]
4443
test =
4544
jsonschema
45+
ipykernel
4646
pytest>=3.6.0
4747
pytest-cov
4848
pytz

0 commit comments

Comments
 (0)