back to Index
Searching for documentation...
http://ipython.org/ipython-doc/2/index.html ->
http://ipython.org/ipython-doc/2/development/index.html ->
http://ipython.org/ipython-doc/2/development/messaging.html -->
http://ipython.org/ipython-doc/2/development/messaging.html#comm-messages
Comm messages are one-way communications to update comm state, used for synchronizing widget state, or simply requesting actions of a comm’s counterpart.
In [2]:
ls
In [5]:
cp /projects/0a592ce8-7730-49b4-baed-e8ce6f939851/ipython/ . -r
In [9]:
!grep -r 'comm_msg' .
In [13]:
!grep -r 'monitor.send(' .
In [18]:
import IPython.utils.traitlets
from IPython.utils.traitlets import link, CFloat, Float, HasTraits, Unicode, Long
In [19]:
class Employee(HasTraits):
name = Unicode()
age = Long()
In [27]:
dilbert = Employee(name="dilbert", age=35)
In [28]:
dilbert.age
Out[28]:
In [29]:
doug = Employee(name="doug", age=21)
In [30]:
link((dilbert, 'age'), (doug, 'age'))
Out[30]:
In [31]:
doug.age
Out[31]:
In [32]:
dilbert.age=22
In [33]:
doug.age
Out[33]:
In [34]:
doug.age=60
In [35]:
dilbert.age
Out[35]:
Next: see how the widgets interface with javascript
In [38]:
from IPython.html import widgets # Widget definitions
from IPython.display import display # Used to display widgets in the notebook
from IPython.utils.traitlets import Unicode # Used to declare attributes of our widget
from IPython.display import HTML, Javascript
from IPython.html.widgets.widget_bool import _BoolWidget
from IPython.html.widgets.widget_float import _FloatWidget
from IPython.utils.traitlets import CInt, CFloat, Unicode
from IPython.html.widgets.widget import DOMWidget
class BattleCruiserView(DOMWidget):
_view_name = Unicode('BattleCruiserView', sync=True)
value = CFloat(0.0, help="Float value", sync=True)
axis_id = CInt(0, help='axis_id', sync=True)
x = CFloat(0.0, help="Position (x) of the battlecruiser", sync=True)
y = CFloat(0.0, help="Position (y) of the battlecruiser", sync=True)
theta = CFloat(0.0, help="Orientation (degrees) of the battlecruiser", sync=True)
mouse_x = CFloat(0.0, help="Position (x) of the cursor", sync=True)
mouse_y = CFloat(0.0, help="Position (y) of the cursor", sync=True)
description = Unicode('', help="Description of the float (label).", sync=True)
DomWidget extends Widget extends LoggingConfigurable extends Configurable extends HasTraits
class DOMWidget(Widget):
The Widget class appears to contain the callbacks!
In [41]:
!grep -r 'class LoggingConfigurable' .
In [43]:
slider=widgets.FloatSliderWidget()
In [44]:
slider
In [46]:
slider.value
Out[46]:
In [48]:
import time
for i in range (5):
print(slider.value)
time.sleep(1)
Slider doesn't update.
Widget: receiving state
class Widget(LoggingConfigurable):
def _handle_receive_state(self, sync_data):
"""Called when a state is received from the front-end."""
for name in self.keys:
if name in sync_data:
value = self._unpack_widgets(sync_data[name])
with self._lock_property(name, value):
setattr(self, name, value)
Widget: general callback
class Widget(LoggingConfigurable):
# Event handlers
@_show_traceback
def _handle_msg(self, msg):
"""Called when a msg is received from the front-end"""
data = msg['content']['data']
method = data['method']
if not method in ['backbone', 'custom']:
self.log.error('Unknown front-end to back-end widget msg with method "%s"' % method)
# Handle backbone sync methods CREATE, PATCH, and UPDATE all in one.
if method == 'backbone' and 'sync_data' in data:
sync_data = data['sync_data']
self._handle_receive_state(sync_data) # handles all methods
# Handle a custom msg from the front-end
elif method == 'custom':
if 'content' in data:
self._handle_custom_msg(data['content'])
Widget: Registering callbacks
class Widget(LoggingConfigurable):
@property
def comm(self):
"""Gets the Comm associated with this widget.
If a Comm doesn't exist yet, a Comm will be created automagically."""
if self._comm is None:
# Create a comm.
self._comm = Comm(target_name=self._model_name)
self._comm.on_msg(self._handle_msg)
self._comm.on_close(self._close)
Widget.widgets[self.model_id] = self
# first update
self.send_state()
return self._comm
Comm: handling comm message
class Comm(LoggingConfigurable):
def handle_msg(self, msg):
"""Handle a comm_msg message"""
self.log.debug("handle_msg[%s](%s)", self.comm_id, msg)
if self._msg_callback:
self.shell.events.trigger('pre_execute')
self._msg_callback(msg)
self.shell.events.trigger('post_execute')
Comm: sending messages
class Comm(LoggingConfigurable):
def _publish_msg(self, msg_type, data=None, metadata=None, **keys):
"""Helper for sending a comm message on IOPub"""
data = {} if data is None else data
metadata = {} if metadata is None else metadata
content = json_clean(dict(data=data, comm_id=self.comm_id, **keys))
self.session.send(self.iopub_socket, msg_type,
content,
metadata=json_clean(metadata),
parent=self.shell.get_parent(),
ident=self.topic,
)
def send(self, data=None, metadata=None):
"""Send a message to the frontend-side version of this comm"""
self._publish_msg('comm_msg', data, metadata)
Who registers this callback? Who calls this?
In [50]:
!grep -r 'handle_msg' .
What are: the
shell
io_pub
session
initialized:
class Comm(LoggingConfigurable):
shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
def _shell_default(self):
return get_ipython()
iopub_socket = Any()
def _iopub_socket_default(self):
return self.shell.kernel.iopub_socket
session = Instance('IPython.kernel.zmq.session.Session')
def _session_default(self):
if self.shell is None:
return
return self.shell.kernel.session
What are:
Any
Instance
get_ipython
InteractiveShellABC:
class InteractiveShellABC(with_metaclass(abc.ABCMeta, object)):
"""An abstract base class for InteractiveShell."""
InteractiveShellABC.register(InteractiveShell)
class InteractiveShell(SingletonConfigurable):
"""An enhanced, interactive shell for Python."""
IPython.kernel.zmq.session.Session:
class Session(Configurable):
"""Object for handling serialization and sending of messages.
The Session object handles building messages and sending them
with ZMQ sockets or ZMQStream objects. Objects can communicate with each
other over the network via Session objects, and only need to work with the
dict-based IPython message spec. The Session will handle
serialization/deserialization, security, and metadata.
Sessions support configurable serialiization via packer/unpacker traits,
and signing with HMAC digests via the key/keyfile traits.
"""
Comm hasa IPython.core.interactiveshell.InteractiveShellABC
In [ ]: