##// END OF EJS Templates
Don't register comm with comm_manager if comm_manager is undefined
U-Jon-PC\Jon -
Show More
@@ -1,135 +1,139 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 if self.primary:
53 if self.primary:
54 # I am primary, open my peer.
54 # I am primary, open my peer.
55 self.open(data)
55 self.open(data)
56
56
57 def _publish_msg(self, msg_type, data=None, metadata=None, **keys):
57 def _publish_msg(self, msg_type, data=None, metadata=None, **keys):
58 """Helper for sending a comm message on IOPub"""
58 """Helper for sending a comm message on IOPub"""
59 data = {} if data is None else data
59 data = {} if data is None else data
60 metadata = {} if metadata is None else metadata
60 metadata = {} if metadata is None else metadata
61 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))
62 self.session.send(self.iopub_socket, msg_type,
62 self.session.send(self.iopub_socket, msg_type,
63 content,
63 content,
64 metadata=json_clean(metadata),
64 metadata=json_clean(metadata),
65 parent=self.shell.get_parent(),
65 parent=self.shell.get_parent(),
66 ident=self.topic,
66 ident=self.topic,
67 )
67 )
68
68
69 def __del__(self):
69 def __del__(self):
70 """trigger close on gc"""
70 """trigger close on gc"""
71 self.close()
71 self.close()
72
72
73 # publishing messages
73 # publishing messages
74
74
75 def open(self, data=None, metadata=None):
75 def open(self, data=None, metadata=None):
76 """Open the frontend-side version of this comm"""
76 """Open the frontend-side version of this comm"""
77 if data is None:
77 if data is None:
78 data = self._open_data
78 data = self._open_data
79 self._closed = False
79 self._closed = False
80 get_ipython().comm_manager.register_comm(self)
80 ip = get_ipython()
81 if hasattr(ip, 'comm_manager'):
82 ip.comm_manager.register_comm(self)
81 self._publish_msg('comm_open', data, metadata, target_name=self.target_name)
83 self._publish_msg('comm_open', data, metadata, target_name=self.target_name)
82
84
83 def close(self, data=None, metadata=None):
85 def close(self, data=None, metadata=None):
84 """Close the frontend-side version of this comm"""
86 """Close the frontend-side version of this comm"""
85 if self._closed:
87 if self._closed:
86 # only close once
88 # only close once
87 return
89 return
88 if data is None:
90 if data is None:
89 data = self._close_data
91 data = self._close_data
90 self._publish_msg('comm_close', data, metadata)
92 self._publish_msg('comm_close', data, metadata)
91 get_ipython().comm_manager.unregister_comm(self)
93 ip = get_ipython()
94 if hasattr(ip, 'comm_manager'):
95 ip.comm_manager.unregister_comm(self)
92 self._closed = True
96 self._closed = True
93
97
94 def send(self, data=None, metadata=None):
98 def send(self, data=None, metadata=None):
95 """Send a message to the frontend-side version of this comm"""
99 """Send a message to the frontend-side version of this comm"""
96 self._publish_msg('comm_msg', data, metadata)
100 self._publish_msg('comm_msg', data, metadata)
97
101
98 # registering callbacks
102 # registering callbacks
99
103
100 def on_close(self, callback):
104 def on_close(self, callback):
101 """Register a callback for comm_close
105 """Register a callback for comm_close
102
106
103 Will be called with the `data` of the close message.
107 Will be called with the `data` of the close message.
104
108
105 Call `on_close(None)` to disable an existing callback.
109 Call `on_close(None)` to disable an existing callback.
106 """
110 """
107 self._close_callback = callback
111 self._close_callback = callback
108
112
109 def on_msg(self, callback):
113 def on_msg(self, callback):
110 """Register a callback for comm_msg
114 """Register a callback for comm_msg
111
115
112 Will be called with the `data` of any comm_msg messages.
116 Will be called with the `data` of any comm_msg messages.
113
117
114 Call `on_msg(None)` to disable an existing callback.
118 Call `on_msg(None)` to disable an existing callback.
115 """
119 """
116 self._msg_callback = callback
120 self._msg_callback = callback
117
121
118 # handling of incoming messages
122 # handling of incoming messages
119
123
120 def handle_close(self, msg):
124 def handle_close(self, msg):
121 """Handle a comm_close message"""
125 """Handle a comm_close message"""
122 self.log.debug("handle_close[%s](%s)", self.comm_id, msg)
126 self.log.debug("handle_close[%s](%s)", self.comm_id, msg)
123 if self._close_callback:
127 if self._close_callback:
124 self._close_callback(msg)
128 self._close_callback(msg)
125
129
126 def handle_msg(self, msg):
130 def handle_msg(self, msg):
127 """Handle a comm_msg message"""
131 """Handle a comm_msg message"""
128 self.log.debug("handle_msg[%s](%s)", self.comm_id, msg)
132 self.log.debug("handle_msg[%s](%s)", self.comm_id, msg)
129 if self._msg_callback:
133 if self._msg_callback:
130 self.shell.events.trigger('pre_execute')
134 self.shell.events.trigger('pre_execute')
131 self._msg_callback(msg)
135 self._msg_callback(msg)
132 self.shell.events.trigger('post_execute')
136 self.shell.events.trigger('post_execute')
133
137
134
138
135 __all__ = ['Comm']
139 __all__ = ['Comm']
General Comments 0
You need to be logged in to leave comments. Login now