##// END OF EJS Templates
allow metadata in Kernel-side Comm messages.
MinRK -
Show More
@@ -1,136 +1,138 b''
1 """Base class for a Comm"""
1 """Base class for a Comm"""
2
2
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Copyright (C) 2013 The IPython Development Team
4 # Copyright (C) 2013 The IPython Development Team
5 #
5 #
6 # Distributed under the terms of the BSD License. The full license is in
6 # Distributed under the terms of the BSD License. The full license is in
7 # the file COPYING, distributed as part of this software.
7 # the file COPYING, distributed as part of this software.
8 #-----------------------------------------------------------------------------
8 #-----------------------------------------------------------------------------
9
9
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11 # Imports
11 # Imports
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13
13
14 import uuid
14 import uuid
15
15
16 from IPython.config import LoggingConfigurable
16 from IPython.config import LoggingConfigurable
17 from IPython.core.getipython import get_ipython
17 from IPython.core.getipython import get_ipython
18
18
19 from IPython.utils.traitlets import Instance, Unicode, Bytes, Bool, Dict, Any
19 from IPython.utils.traitlets import Instance, Unicode, Bytes, Bool, Dict, Any
20
20
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22 # Code
22 # Code
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24
24
25 class Comm(LoggingConfigurable):
25 class Comm(LoggingConfigurable):
26
26
27 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
27 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
28 def _shell_default(self):
28 def _shell_default(self):
29 return get_ipython()
29 return get_ipython()
30
30
31 iopub_socket = Any()
31 iopub_socket = Any()
32 def _iopub_socket_default(self):
32 def _iopub_socket_default(self):
33 return self.shell.kernel.iopub_socket
33 return self.shell.kernel.iopub_socket
34 session = Instance('IPython.kernel.zmq.session.Session')
34 session = Instance('IPython.kernel.zmq.session.Session')
35 def _session_default(self):
35 def _session_default(self):
36 if self.shell is None:
36 if self.shell is None:
37 return
37 return
38 return self.shell.kernel.session
38 return self.shell.kernel.session
39
39
40 target_name = Unicode('comm')
40 target_name = Unicode('comm')
41
41
42 topic = Bytes()
42 topic = Bytes()
43 def _topic_default(self):
43 def _topic_default(self):
44 return ('comm-%s' % self.comm_id).encode('ascii')
44 return ('comm-%s' % self.comm_id).encode('ascii')
45
45
46 _open_data = Dict(help="data dict, if any, to be included in comm_open")
46 _open_data = Dict(help="data dict, if any, to be included in comm_open")
47 _close_data = Dict(help="data dict, if any, to be included in comm_close")
47 _close_data = Dict(help="data dict, if any, to be included in comm_close")
48
48
49 _msg_callback = Any()
49 _msg_callback = Any()
50 _close_callback = Any()
50 _close_callback = Any()
51
51
52 _closed = Bool(False)
52 _closed = Bool(False)
53 comm_id = Unicode()
53 comm_id = Unicode()
54 def _comm_id_default(self):
54 def _comm_id_default(self):
55 return uuid.uuid4().hex
55 return uuid.uuid4().hex
56
56
57 primary = Bool(True, help="Am I the primary or secondary Comm?")
57 primary = Bool(True, help="Am I the primary or secondary Comm?")
58
58
59 def __init__(self, data=None, **kwargs):
59 def __init__(self, data=None, **kwargs):
60 super(Comm, self).__init__(**kwargs)
60 super(Comm, self).__init__(**kwargs)
61 get_ipython().comm_manager.register_comm(self)
61 get_ipython().comm_manager.register_comm(self)
62 if self.primary:
62 if self.primary:
63 # I am primary, open my peer.
63 # I am primary, open my peer.
64 self.open(data)
64 self.open(data)
65
65
66 def _publish_msg(self, msg_type, data=None, **keys):
66 def _publish_msg(self, msg_type, data=None, metadata=None, **keys):
67 """Helper for sending a comm message on IOPub"""
67 """Helper for sending a comm message on IOPub"""
68 data = {} if data is None else data
68 data = {} if data is None else data
69 metadata = {} if metadata is None else metadata
69 self.session.send(self.iopub_socket, msg_type,
70 self.session.send(self.iopub_socket, msg_type,
70 dict(data=data, comm_id=self.comm_id, **keys),
71 dict(data=data, comm_id=self.comm_id, **keys),
72 metadata=metadata,
71 parent=self.shell.get_parent(),
73 parent=self.shell.get_parent(),
72 ident=self.topic,
74 ident=self.topic,
73 )
75 )
74
76
75 def __del__(self):
77 def __del__(self):
76 """trigger close on gc"""
78 """trigger close on gc"""
77 self.close()
79 self.close()
78
80
79 # publishing messages
81 # publishing messages
80
82
81 def open(self, data=None):
83 def open(self, data=None, metadata=None):
82 """Open the frontend-side version of this comm"""
84 """Open the frontend-side version of this comm"""
83 if data is None:
85 if data is None:
84 data = self._open_data
86 data = self._open_data
85 self._publish_msg('comm_open', data, target_name=self.target_name)
87 self._publish_msg('comm_open', data, metadata, target_name=self.target_name)
86
88
87 def close(self, data=None):
89 def close(self, data=None, metadata=None):
88 """Close the frontend-side version of this comm"""
90 """Close the frontend-side version of this comm"""
89 if self._closed:
91 if self._closed:
90 # only close once
92 # only close once
91 return
93 return
92 if data is None:
94 if data is None:
93 data = self._close_data
95 data = self._close_data
94 self._publish_msg('comm_close', data)
96 self._publish_msg('comm_close', data, metadata)
95 self._closed = True
97 self._closed = True
96
98
97 def send(self, data=None):
99 def send(self, data=None, metadata=None):
98 """Send a message to the frontend-side version of this comm"""
100 """Send a message to the frontend-side version of this comm"""
99 self._publish_msg('comm_msg', data)
101 self._publish_msg('comm_msg', data, metadata)
100
102
101 # registering callbacks
103 # registering callbacks
102
104
103 def on_close(self, callback):
105 def on_close(self, callback):
104 """Register a callback for comm_close
106 """Register a callback for comm_close
105
107
106 Will be called with the `data` of the close message.
108 Will be called with the `data` of the close message.
107
109
108 Call `on_close(None)` to disable an existing callback.
110 Call `on_close(None)` to disable an existing callback.
109 """
111 """
110 self._close_callback = callback
112 self._close_callback = callback
111
113
112 def on_msg(self, callback):
114 def on_msg(self, callback):
113 """Register a callback for comm_msg
115 """Register a callback for comm_msg
114
116
115 Will be called with the `data` of any comm_msg messages.
117 Will be called with the `data` of any comm_msg messages.
116
118
117 Call `on_msg(None)` to disable an existing callback.
119 Call `on_msg(None)` to disable an existing callback.
118 """
120 """
119 self._msg_callback = callback
121 self._msg_callback = callback
120
122
121 # handling of incoming messages
123 # handling of incoming messages
122
124
123 def handle_close(self, msg):
125 def handle_close(self, msg):
124 """Handle a comm_close message"""
126 """Handle a comm_close message"""
125 self.log.debug("handle_close[%s](%s)", self.comm_id, msg)
127 self.log.debug("handle_close[%s](%s)", self.comm_id, msg)
126 if self._close_callback:
128 if self._close_callback:
127 self._close_callback(msg)
129 self._close_callback(msg)
128
130
129 def handle_msg(self, msg):
131 def handle_msg(self, msg):
130 """Handle a comm_msg message"""
132 """Handle a comm_msg message"""
131 self.log.debug("handle_msg[%s](%s)", self.comm_id, msg)
133 self.log.debug("handle_msg[%s](%s)", self.comm_id, msg)
132 if self._msg_callback:
134 if self._msg_callback:
133 self._msg_callback(msg)
135 self._msg_callback(msg)
134
136
135
137
136 __all__ = ['Comm']
138 __all__ = ['Comm']
General Comments 0
You need to be logged in to leave comments. Login now