##// END OF EJS Templates
Add missing 'history_tail_reply' signal to QtKernelManager.
epatters -
Show More
@@ -1,242 +1,243
1 """ Defines a KernelManager that provides signals and slots.
1 """ Defines a KernelManager that provides signals and slots.
2 """
2 """
3
3
4 # System library imports.
4 # System library imports.
5 from IPython.external.qt import QtCore
5 from IPython.external.qt import QtCore
6
6
7 # IPython imports.
7 # IPython imports.
8 from IPython.utils.traitlets import Type
8 from IPython.utils.traitlets import Type
9 from IPython.zmq.kernelmanager import KernelManager, SubSocketChannel, \
9 from IPython.zmq.kernelmanager import KernelManager, SubSocketChannel, \
10 XReqSocketChannel, RepSocketChannel, HBSocketChannel
10 XReqSocketChannel, RepSocketChannel, HBSocketChannel
11 from util import MetaQObjectHasTraits, SuperQObject
11 from util import MetaQObjectHasTraits, SuperQObject
12
12
13
13
14 class SocketChannelQObject(SuperQObject):
14 class SocketChannelQObject(SuperQObject):
15
15
16 # Emitted when the channel is started.
16 # Emitted when the channel is started.
17 started = QtCore.Signal()
17 started = QtCore.Signal()
18
18
19 # Emitted when the channel is stopped.
19 # Emitted when the channel is stopped.
20 stopped = QtCore.Signal()
20 stopped = QtCore.Signal()
21
21
22 #---------------------------------------------------------------------------
22 #---------------------------------------------------------------------------
23 # 'ZmqSocketChannel' interface
23 # 'ZmqSocketChannel' interface
24 #---------------------------------------------------------------------------
24 #---------------------------------------------------------------------------
25
25
26 def start(self):
26 def start(self):
27 """ Reimplemented to emit signal.
27 """ Reimplemented to emit signal.
28 """
28 """
29 super(SocketChannelQObject, self).start()
29 super(SocketChannelQObject, self).start()
30 self.started.emit()
30 self.started.emit()
31
31
32 def stop(self):
32 def stop(self):
33 """ Reimplemented to emit signal.
33 """ Reimplemented to emit signal.
34 """
34 """
35 super(SocketChannelQObject, self).stop()
35 super(SocketChannelQObject, self).stop()
36 self.stopped.emit()
36 self.stopped.emit()
37
37
38
38
39 class QtXReqSocketChannel(SocketChannelQObject, XReqSocketChannel):
39 class QtXReqSocketChannel(SocketChannelQObject, XReqSocketChannel):
40
40
41 # Emitted when any message is received.
41 # Emitted when any message is received.
42 message_received = QtCore.Signal(object)
42 message_received = QtCore.Signal(object)
43
43
44 # Emitted when a reply has been received for the corresponding request
44 # Emitted when a reply has been received for the corresponding request
45 # type.
45 # type.
46 execute_reply = QtCore.Signal(object)
46 execute_reply = QtCore.Signal(object)
47 complete_reply = QtCore.Signal(object)
47 complete_reply = QtCore.Signal(object)
48 object_info_reply = QtCore.Signal(object)
48 object_info_reply = QtCore.Signal(object)
49 history_tail_reply = QtCore.Signal(object)
49
50
50 # Emitted when the first reply comes back.
51 # Emitted when the first reply comes back.
51 first_reply = QtCore.Signal()
52 first_reply = QtCore.Signal()
52
53
53 # Used by the first_reply signal logic to determine if a reply is the
54 # Used by the first_reply signal logic to determine if a reply is the
54 # first.
55 # first.
55 _handlers_called = False
56 _handlers_called = False
56
57
57 #---------------------------------------------------------------------------
58 #---------------------------------------------------------------------------
58 # 'XReqSocketChannel' interface
59 # 'XReqSocketChannel' interface
59 #---------------------------------------------------------------------------
60 #---------------------------------------------------------------------------
60
61
61 def call_handlers(self, msg):
62 def call_handlers(self, msg):
62 """ Reimplemented to emit signals instead of making callbacks.
63 """ Reimplemented to emit signals instead of making callbacks.
63 """
64 """
64 # Emit the generic signal.
65 # Emit the generic signal.
65 self.message_received.emit(msg)
66 self.message_received.emit(msg)
66
67
67 # Emit signals for specialized message types.
68 # Emit signals for specialized message types.
68 msg_type = msg['msg_type']
69 msg_type = msg['msg_type']
69 signal = getattr(self, msg_type, None)
70 signal = getattr(self, msg_type, None)
70 if signal:
71 if signal:
71 signal.emit(msg)
72 signal.emit(msg)
72
73
73 if not self._handlers_called:
74 if not self._handlers_called:
74 self.first_reply.emit()
75 self.first_reply.emit()
75 self._handlers_called = True
76 self._handlers_called = True
76
77
77 #---------------------------------------------------------------------------
78 #---------------------------------------------------------------------------
78 # 'QtXReqSocketChannel' interface
79 # 'QtXReqSocketChannel' interface
79 #---------------------------------------------------------------------------
80 #---------------------------------------------------------------------------
80
81
81 def reset_first_reply(self):
82 def reset_first_reply(self):
82 """ Reset the first_reply signal to fire again on the next reply.
83 """ Reset the first_reply signal to fire again on the next reply.
83 """
84 """
84 self._handlers_called = False
85 self._handlers_called = False
85
86
86
87
87 class QtSubSocketChannel(SocketChannelQObject, SubSocketChannel):
88 class QtSubSocketChannel(SocketChannelQObject, SubSocketChannel):
88
89
89 # Emitted when any message is received.
90 # Emitted when any message is received.
90 message_received = QtCore.Signal(object)
91 message_received = QtCore.Signal(object)
91
92
92 # Emitted when a message of type 'stream' is received.
93 # Emitted when a message of type 'stream' is received.
93 stream_received = QtCore.Signal(object)
94 stream_received = QtCore.Signal(object)
94
95
95 # Emitted when a message of type 'pyin' is received.
96 # Emitted when a message of type 'pyin' is received.
96 pyin_received = QtCore.Signal(object)
97 pyin_received = QtCore.Signal(object)
97
98
98 # Emitted when a message of type 'pyout' is received.
99 # Emitted when a message of type 'pyout' is received.
99 pyout_received = QtCore.Signal(object)
100 pyout_received = QtCore.Signal(object)
100
101
101 # Emitted when a message of type 'pyerr' is received.
102 # Emitted when a message of type 'pyerr' is received.
102 pyerr_received = QtCore.Signal(object)
103 pyerr_received = QtCore.Signal(object)
103
104
104 # Emitted when a message of type 'display_data' is received
105 # Emitted when a message of type 'display_data' is received
105 display_data_received = QtCore.Signal(object)
106 display_data_received = QtCore.Signal(object)
106
107
107 # Emitted when a crash report message is received from the kernel's
108 # Emitted when a crash report message is received from the kernel's
108 # last-resort sys.excepthook.
109 # last-resort sys.excepthook.
109 crash_received = QtCore.Signal(object)
110 crash_received = QtCore.Signal(object)
110
111
111 # Emitted when a shutdown is noticed.
112 # Emitted when a shutdown is noticed.
112 shutdown_reply_received = QtCore.Signal(object)
113 shutdown_reply_received = QtCore.Signal(object)
113
114
114 #---------------------------------------------------------------------------
115 #---------------------------------------------------------------------------
115 # 'SubSocketChannel' interface
116 # 'SubSocketChannel' interface
116 #---------------------------------------------------------------------------
117 #---------------------------------------------------------------------------
117
118
118 def call_handlers(self, msg):
119 def call_handlers(self, msg):
119 """ Reimplemented to emit signals instead of making callbacks.
120 """ Reimplemented to emit signals instead of making callbacks.
120 """
121 """
121 # Emit the generic signal.
122 # Emit the generic signal.
122 self.message_received.emit(msg)
123 self.message_received.emit(msg)
123 # Emit signals for specialized message types.
124 # Emit signals for specialized message types.
124 msg_type = msg['msg_type']
125 msg_type = msg['msg_type']
125 signal = getattr(self, msg_type + '_received', None)
126 signal = getattr(self, msg_type + '_received', None)
126 if signal:
127 if signal:
127 signal.emit(msg)
128 signal.emit(msg)
128 elif msg_type in ('stdout', 'stderr'):
129 elif msg_type in ('stdout', 'stderr'):
129 self.stream_received.emit(msg)
130 self.stream_received.emit(msg)
130
131
131 def flush(self):
132 def flush(self):
132 """ Reimplemented to ensure that signals are dispatched immediately.
133 """ Reimplemented to ensure that signals are dispatched immediately.
133 """
134 """
134 super(QtSubSocketChannel, self).flush()
135 super(QtSubSocketChannel, self).flush()
135 QtCore.QCoreApplication.instance().processEvents()
136 QtCore.QCoreApplication.instance().processEvents()
136
137
137
138
138 class QtRepSocketChannel(SocketChannelQObject, RepSocketChannel):
139 class QtRepSocketChannel(SocketChannelQObject, RepSocketChannel):
139
140
140 # Emitted when any message is received.
141 # Emitted when any message is received.
141 message_received = QtCore.Signal(object)
142 message_received = QtCore.Signal(object)
142
143
143 # Emitted when an input request is received.
144 # Emitted when an input request is received.
144 input_requested = QtCore.Signal(object)
145 input_requested = QtCore.Signal(object)
145
146
146 #---------------------------------------------------------------------------
147 #---------------------------------------------------------------------------
147 # 'RepSocketChannel' interface
148 # 'RepSocketChannel' interface
148 #---------------------------------------------------------------------------
149 #---------------------------------------------------------------------------
149
150
150 def call_handlers(self, msg):
151 def call_handlers(self, msg):
151 """ Reimplemented to emit signals instead of making callbacks.
152 """ Reimplemented to emit signals instead of making callbacks.
152 """
153 """
153 # Emit the generic signal.
154 # Emit the generic signal.
154 self.message_received.emit(msg)
155 self.message_received.emit(msg)
155
156
156 # Emit signals for specialized message types.
157 # Emit signals for specialized message types.
157 msg_type = msg['msg_type']
158 msg_type = msg['msg_type']
158 if msg_type == 'input_request':
159 if msg_type == 'input_request':
159 self.input_requested.emit(msg)
160 self.input_requested.emit(msg)
160
161
161
162
162 class QtHBSocketChannel(SocketChannelQObject, HBSocketChannel):
163 class QtHBSocketChannel(SocketChannelQObject, HBSocketChannel):
163
164
164 # Emitted when the kernel has died.
165 # Emitted when the kernel has died.
165 kernel_died = QtCore.Signal(object)
166 kernel_died = QtCore.Signal(object)
166
167
167 #---------------------------------------------------------------------------
168 #---------------------------------------------------------------------------
168 # 'HBSocketChannel' interface
169 # 'HBSocketChannel' interface
169 #---------------------------------------------------------------------------
170 #---------------------------------------------------------------------------
170
171
171 def call_handlers(self, since_last_heartbeat):
172 def call_handlers(self, since_last_heartbeat):
172 """ Reimplemented to emit signals instead of making callbacks.
173 """ Reimplemented to emit signals instead of making callbacks.
173 """
174 """
174 # Emit the generic signal.
175 # Emit the generic signal.
175 self.kernel_died.emit(since_last_heartbeat)
176 self.kernel_died.emit(since_last_heartbeat)
176
177
177
178
178 class QtKernelManager(KernelManager, SuperQObject):
179 class QtKernelManager(KernelManager, SuperQObject):
179 """ A KernelManager that provides signals and slots.
180 """ A KernelManager that provides signals and slots.
180 """
181 """
181
182
182 __metaclass__ = MetaQObjectHasTraits
183 __metaclass__ = MetaQObjectHasTraits
183
184
184 # Emitted when the kernel manager has started listening.
185 # Emitted when the kernel manager has started listening.
185 started_channels = QtCore.Signal()
186 started_channels = QtCore.Signal()
186
187
187 # Emitted when the kernel manager has stopped listening.
188 # Emitted when the kernel manager has stopped listening.
188 stopped_channels = QtCore.Signal()
189 stopped_channels = QtCore.Signal()
189
190
190 # Use Qt-specific channel classes that emit signals.
191 # Use Qt-specific channel classes that emit signals.
191 sub_channel_class = Type(QtSubSocketChannel)
192 sub_channel_class = Type(QtSubSocketChannel)
192 xreq_channel_class = Type(QtXReqSocketChannel)
193 xreq_channel_class = Type(QtXReqSocketChannel)
193 rep_channel_class = Type(QtRepSocketChannel)
194 rep_channel_class = Type(QtRepSocketChannel)
194 hb_channel_class = Type(QtHBSocketChannel)
195 hb_channel_class = Type(QtHBSocketChannel)
195
196
196 #---------------------------------------------------------------------------
197 #---------------------------------------------------------------------------
197 # 'KernelManager' interface
198 # 'KernelManager' interface
198 #---------------------------------------------------------------------------
199 #---------------------------------------------------------------------------
199
200
200 #------ Kernel process management ------------------------------------------
201 #------ Kernel process management ------------------------------------------
201
202
202 def start_kernel(self, *args, **kw):
203 def start_kernel(self, *args, **kw):
203 """ Reimplemented for proper heartbeat management.
204 """ Reimplemented for proper heartbeat management.
204 """
205 """
205 if self._xreq_channel is not None:
206 if self._xreq_channel is not None:
206 self._xreq_channel.reset_first_reply()
207 self._xreq_channel.reset_first_reply()
207 super(QtKernelManager, self).start_kernel(*args, **kw)
208 super(QtKernelManager, self).start_kernel(*args, **kw)
208
209
209 #------ Channel management -------------------------------------------------
210 #------ Channel management -------------------------------------------------
210
211
211 def start_channels(self, *args, **kw):
212 def start_channels(self, *args, **kw):
212 """ Reimplemented to emit signal.
213 """ Reimplemented to emit signal.
213 """
214 """
214 super(QtKernelManager, self).start_channels(*args, **kw)
215 super(QtKernelManager, self).start_channels(*args, **kw)
215 self.started_channels.emit()
216 self.started_channels.emit()
216
217
217 def stop_channels(self):
218 def stop_channels(self):
218 """ Reimplemented to emit signal.
219 """ Reimplemented to emit signal.
219 """
220 """
220 super(QtKernelManager, self).stop_channels()
221 super(QtKernelManager, self).stop_channels()
221 self.stopped_channels.emit()
222 self.stopped_channels.emit()
222
223
223 @property
224 @property
224 def xreq_channel(self):
225 def xreq_channel(self):
225 """ Reimplemented for proper heartbeat management.
226 """ Reimplemented for proper heartbeat management.
226 """
227 """
227 if self._xreq_channel is None:
228 if self._xreq_channel is None:
228 self._xreq_channel = super(QtKernelManager, self).xreq_channel
229 self._xreq_channel = super(QtKernelManager, self).xreq_channel
229 self._xreq_channel.first_reply.connect(self._first_reply)
230 self._xreq_channel.first_reply.connect(self._first_reply)
230 return self._xreq_channel
231 return self._xreq_channel
231
232
232 #---------------------------------------------------------------------------
233 #---------------------------------------------------------------------------
233 # Protected interface
234 # Protected interface
234 #---------------------------------------------------------------------------
235 #---------------------------------------------------------------------------
235
236
236 def _first_reply(self):
237 def _first_reply(self):
237 """ Unpauses the heartbeat channel when the first reply is received on
238 """ Unpauses the heartbeat channel when the first reply is received on
238 the execute channel. Note that this will *not* start the heartbeat
239 the execute channel. Note that this will *not* start the heartbeat
239 channel if it is not already running!
240 channel if it is not already running!
240 """
241 """
241 if self._hb_channel is not None:
242 if self._hb_channel is not None:
242 self._hb_channel.unpause()
243 self._hb_channel.unpause()
General Comments 0
You need to be logged in to leave comments. Login now