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