Show More
@@ -179,10 +179,12 class FrontendWidget(HistoryConsoleWidget): | |||||
179 | # Disconnect the old kernel manager's channels. |
|
179 | # Disconnect the old kernel manager's channels. | |
180 | sub = self._kernel_manager.sub_channel |
|
180 | sub = self._kernel_manager.sub_channel | |
181 | xreq = self._kernel_manager.xreq_channel |
|
181 | xreq = self._kernel_manager.xreq_channel | |
|
182 | rep = self._kernel_manager.rep_channel | |||
182 | sub.message_received.disconnect(self._handle_sub) |
|
183 | sub.message_received.disconnect(self._handle_sub) | |
183 | xreq.execute_reply.disconnect(self._handle_execute_reply) |
|
184 | xreq.execute_reply.disconnect(self._handle_execute_reply) | |
184 | xreq.complete_reply.disconnect(self._handle_complete_reply) |
|
185 | xreq.complete_reply.disconnect(self._handle_complete_reply) | |
185 | xreq.object_info_reply.disconnect(self._handle_object_info_reply) |
|
186 | xreq.object_info_reply.disconnect(self._handle_object_info_reply) | |
|
187 | rep.readline_requested.disconnect(self._handle_req) | |||
186 |
|
188 | |||
187 | # Handle the case where the old kernel manager is still listening. |
|
189 | # Handle the case where the old kernel manager is still listening. | |
188 | if self._kernel_manager.channels_running: |
|
190 | if self._kernel_manager.channels_running: | |
@@ -200,10 +202,12 class FrontendWidget(HistoryConsoleWidget): | |||||
200 | # Connect the new kernel manager's channels. |
|
202 | # Connect the new kernel manager's channels. | |
201 | sub = kernel_manager.sub_channel |
|
203 | sub = kernel_manager.sub_channel | |
202 | xreq = kernel_manager.xreq_channel |
|
204 | xreq = kernel_manager.xreq_channel | |
|
205 | rep = kernel_manager.rep_channel | |||
203 | sub.message_received.connect(self._handle_sub) |
|
206 | sub.message_received.connect(self._handle_sub) | |
204 | xreq.execute_reply.connect(self._handle_execute_reply) |
|
207 | xreq.execute_reply.connect(self._handle_execute_reply) | |
205 | xreq.complete_reply.connect(self._handle_complete_reply) |
|
208 | xreq.complete_reply.connect(self._handle_complete_reply) | |
206 | xreq.object_info_reply.connect(self._handle_object_info_reply) |
|
209 | xreq.object_info_reply.connect(self._handle_object_info_reply) | |
|
210 | rep.readline_requested.connect(self._handle_req) | |||
207 |
|
211 | |||
208 | # Handle the case where the kernel manager started channels before |
|
212 | # Handle the case where the kernel manager started channels before | |
209 | # we connected. |
|
213 | # we connected. | |
@@ -292,10 +296,9 class FrontendWidget(HistoryConsoleWidget): | |||||
292 | if position == self.textCursor().position(): |
|
296 | if position == self.textCursor().position(): | |
293 | self._call_tip() |
|
297 | self._call_tip() | |
294 |
|
298 | |||
295 | def _handle_req(self): |
|
299 | def _handle_req(self, req): | |
296 | def callback(line): |
|
300 | def callback(line): | |
297 | print repr(line) |
|
301 | self.kernel_manager.rep_channel.readline(line) | |
298 | self._show_prompt() |
|
|||
299 | self._readline(callback=callback) |
|
302 | self._readline(callback=callback) | |
300 |
|
303 | |||
301 | def _handle_sub(self, omsg): |
|
304 | def _handle_sub(self, omsg): |
@@ -95,6 +95,12 class QtXReqSocketChannel(XReqSocketChannel, QtCore.QObject): | |||||
95 |
|
95 | |||
96 | class QtRepSocketChannel(RepSocketChannel, QtCore.QObject): |
|
96 | class QtRepSocketChannel(RepSocketChannel, QtCore.QObject): | |
97 |
|
97 | |||
|
98 | # Emitted when any message is received. | |||
|
99 | message_received = QtCore.pyqtSignal(object) | |||
|
100 | ||||
|
101 | # Emitted when a readline request is received. | |||
|
102 | readline_requested = QtCore.pyqtSignal(object) | |||
|
103 | ||||
98 | #--------------------------------------------------------------------------- |
|
104 | #--------------------------------------------------------------------------- | |
99 | # 'object' interface |
|
105 | # 'object' interface | |
100 | #--------------------------------------------------------------------------- |
|
106 | #--------------------------------------------------------------------------- | |
@@ -105,6 +111,21 class QtRepSocketChannel(RepSocketChannel, QtCore.QObject): | |||||
105 | QtCore.QObject.__init__(self) |
|
111 | QtCore.QObject.__init__(self) | |
106 | RepSocketChannel.__init__(self, *args, **kw) |
|
112 | RepSocketChannel.__init__(self, *args, **kw) | |
107 |
|
113 | |||
|
114 | #--------------------------------------------------------------------------- | |||
|
115 | # 'RepSocketChannel' interface | |||
|
116 | #--------------------------------------------------------------------------- | |||
|
117 | ||||
|
118 | def call_handlers(self, msg): | |||
|
119 | """ Reimplemented to emit signals instead of making callbacks. | |||
|
120 | """ | |||
|
121 | # Emit the generic signal. | |||
|
122 | self.message_received.emit(msg) | |||
|
123 | ||||
|
124 | # Emit signals for specialized message types. | |||
|
125 | msg_type = msg['msg_type'] | |||
|
126 | if msg_type == 'readline_request': | |||
|
127 | self.readline_requested.emit(msg) | |||
|
128 | ||||
108 |
|
129 | |||
109 | class QtKernelManager(KernelManager, QtCore.QObject): |
|
130 | class QtKernelManager(KernelManager, QtCore.QObject): | |
110 | """ A KernelManager that provides signals and slots. |
|
131 | """ A KernelManager that provides signals and slots. |
@@ -55,9 +55,10 class InStream(object): | |||||
55 | if self.socket is None: |
|
55 | if self.socket is None: | |
56 | raise ValueError(u'I/O operation on closed file') |
|
56 | raise ValueError(u'I/O operation on closed file') | |
57 | else: |
|
57 | else: | |
58 |
content = |
|
58 | content = dict(size=size) | |
59 |
msg = self.session.msg( |
|
59 | msg = self.session.msg('readline_request', content=content) | |
60 |
re |
|
60 | reply = self._request(msg) | |
|
61 | return reply['content']['line'] | |||
61 |
|
62 | |||
62 | def readlines(self, size=-1): |
|
63 | def readlines(self, size=-1): | |
63 | raise NotImplementedError |
|
64 | raise NotImplementedError | |
@@ -83,7 +84,7 class InStream(object): | |||||
83 | raise |
|
84 | raise | |
84 | else: |
|
85 | else: | |
85 | break |
|
86 | break | |
86 |
return reply |
|
87 | return reply | |
87 |
|
88 | |||
88 |
|
89 | |||
89 | class OutStream(object): |
|
90 | class OutStream(object): |
@@ -199,7 +199,6 class XReqSocketChannel(ZmqSocketChannel): | |||||
199 | Returns |
|
199 | Returns | |
200 | ------- |
|
200 | ------- | |
201 | The msg_id of the message sent. |
|
201 | The msg_id of the message sent. | |
202 |
|
||||
203 | """ |
|
202 | """ | |
204 | content = dict(text=text, line=line) |
|
203 | content = dict(text=text, line=line) | |
205 | msg = self.session.msg('complete_request', content) |
|
204 | msg = self.session.msg('complete_request', content) | |
@@ -338,24 +337,84 class SubSocketChannel(ZmqSocketChannel): | |||||
338 | class RepSocketChannel(ZmqSocketChannel): |
|
337 | class RepSocketChannel(ZmqSocketChannel): | |
339 | """A reply channel to handle raw_input requests that the kernel makes.""" |
|
338 | """A reply channel to handle raw_input requests that the kernel makes.""" | |
340 |
|
339 | |||
|
340 | msg_queue = None | |||
|
341 | ||||
|
342 | def __init__(self, context, session, address): | |||
|
343 | self.msg_queue = Queue() | |||
|
344 | super(RepSocketChannel, self).__init__(context, session, address) | |||
|
345 | ||||
341 | def run(self): |
|
346 | def run(self): | |
342 | """The thread's main activity. Call start() instead.""" |
|
347 | """The thread's main activity. Call start() instead.""" | |
|
348 | self.socket = self.context.socket(zmq.XREQ) | |||
|
349 | self.socket.setsockopt(zmq.IDENTITY, self.session.session) | |||
|
350 | self.socket.connect('tcp://%s:%i' % self.address) | |||
343 | self.ioloop = ioloop.IOLoop() |
|
351 | self.ioloop = ioloop.IOLoop() | |
|
352 | self.iostate = POLLERR|POLLIN | |||
|
353 | self.ioloop.add_handler(self.socket, self._handle_events, | |||
|
354 | self.iostate) | |||
344 | self.ioloop.start() |
|
355 | self.ioloop.start() | |
345 |
|
356 | |||
346 | def stop(self): |
|
357 | def stop(self): | |
347 | self.ioloop.stop() |
|
358 | self.ioloop.stop() | |
348 | super(RepSocketChannel, self).stop() |
|
359 | super(RepSocketChannel, self).stop() | |
349 |
|
360 | |||
350 | def on_raw_input(self): |
|
361 | def call_handlers(self, msg): | |
351 | pass |
|
362 | """This method is called in the ioloop thread when a message arrives. | |
|
363 | ||||
|
364 | Subclasses should override this method to handle incoming messages. | |||
|
365 | It is important to remember that this method is called in the thread | |||
|
366 | so that some logic must be done to ensure that the application leve | |||
|
367 | handlers are called in the application thread. | |||
|
368 | """ | |||
|
369 | raise NotImplementedError('call_handlers must be defined in a subclass.') | |||
|
370 | ||||
|
371 | def readline(self, line): | |||
|
372 | """A send a line of raw input to the kernel. | |||
|
373 | ||||
|
374 | Parameters | |||
|
375 | ---------- | |||
|
376 | line : str | |||
|
377 | The line of the input. | |||
|
378 | """ | |||
|
379 | content = dict(line=line) | |||
|
380 | msg = self.session.msg('readline_reply', content) | |||
|
381 | self._queue_reply(msg) | |||
|
382 | ||||
|
383 | def _handle_events(self, socket, events): | |||
|
384 | if events & POLLERR: | |||
|
385 | self._handle_err() | |||
|
386 | if events & POLLOUT: | |||
|
387 | self._handle_send() | |||
|
388 | if events & POLLIN: | |||
|
389 | self._handle_recv() | |||
|
390 | ||||
|
391 | def _handle_recv(self): | |||
|
392 | msg = self.socket.recv_json() | |||
|
393 | self.call_handlers(msg) | |||
|
394 | ||||
|
395 | def _handle_send(self): | |||
|
396 | try: | |||
|
397 | msg = self.msg_queue.get(False) | |||
|
398 | except Empty: | |||
|
399 | pass | |||
|
400 | else: | |||
|
401 | self.socket.send_json(msg) | |||
|
402 | if self.msg_queue.empty(): | |||
|
403 | self.drop_io_state(POLLOUT) | |||
|
404 | ||||
|
405 | def _handle_err(self): | |||
|
406 | # We don't want to let this go silently, so eventually we should log. | |||
|
407 | raise zmq.ZMQError() | |||
|
408 | ||||
|
409 | def _queue_reply(self, msg): | |||
|
410 | self.msg_queue.put(msg) | |||
|
411 | self.add_io_state(POLLOUT) | |||
352 |
|
412 | |||
353 |
|
413 | |||
354 | #----------------------------------------------------------------------------- |
|
414 | #----------------------------------------------------------------------------- | |
355 | # Main kernel manager class |
|
415 | # Main kernel manager class | |
356 | #----------------------------------------------------------------------------- |
|
416 | #----------------------------------------------------------------------------- | |
357 |
|
417 | |||
358 |
|
||||
359 | class KernelManager(HasTraits): |
|
418 | class KernelManager(HasTraits): | |
360 | """ Manages a kernel for a frontend. |
|
419 | """ Manages a kernel for a frontend. | |
361 |
|
420 |
General Comments 0
You need to be logged in to leave comments.
Login now