Show More
@@ -192,7 +192,7 class FrontendWidget(HistoryConsoleWidget): | |||
|
192 | 192 | xreq.execute_reply.disconnect(self._handle_execute_reply) |
|
193 | 193 | xreq.complete_reply.disconnect(self._handle_complete_reply) |
|
194 | 194 | xreq.object_info_reply.disconnect(self._handle_object_info_reply) |
|
195 |
rep. |
|
|
195 | rep.input_requested.disconnect(self._handle_req) | |
|
196 | 196 | |
|
197 | 197 | # Handle the case where the old kernel manager is still listening. |
|
198 | 198 | if self._kernel_manager.channels_running: |
@@ -215,7 +215,7 class FrontendWidget(HistoryConsoleWidget): | |||
|
215 | 215 | xreq.execute_reply.connect(self._handle_execute_reply) |
|
216 | 216 | xreq.complete_reply.connect(self._handle_complete_reply) |
|
217 | 217 | xreq.object_info_reply.connect(self._handle_object_info_reply) |
|
218 |
rep. |
|
|
218 | rep.input_requested.connect(self._handle_req) | |
|
219 | 219 | |
|
220 | 220 | # Handle the case where the kernel manager started channels before |
|
221 | 221 | # we connected. |
@@ -325,8 +325,8 class FrontendWidget(HistoryConsoleWidget): | |||
|
325 | 325 | self.kernel_manager.sub_channel.flush() |
|
326 | 326 | |
|
327 | 327 | def callback(line): |
|
328 |
self.kernel_manager.rep_channel. |
|
|
329 | self._readline(callback=callback) | |
|
328 | self.kernel_manager.rep_channel.input(line) | |
|
329 | self._readline(req['content']['prompt'], callback=callback) | |
|
330 | 330 | |
|
331 | 331 | def _handle_sub(self, omsg): |
|
332 | 332 | if self._hidden: |
@@ -98,8 +98,8 class QtRepSocketChannel(RepSocketChannel, QtCore.QObject): | |||
|
98 | 98 | # Emitted when any message is received. |
|
99 | 99 | message_received = QtCore.pyqtSignal(object) |
|
100 | 100 | |
|
101 |
# Emitted when a |
|
|
102 |
|
|
|
101 | # Emitted when an input request is received. | |
|
102 | input_requested = QtCore.pyqtSignal(object) | |
|
103 | 103 | |
|
104 | 104 | #--------------------------------------------------------------------------- |
|
105 | 105 | # 'object' interface |
@@ -123,8 +123,8 class QtRepSocketChannel(RepSocketChannel, QtCore.QObject): | |||
|
123 | 123 | |
|
124 | 124 | # Emit signals for specialized message types. |
|
125 | 125 | msg_type = msg['msg_type'] |
|
126 |
if msg_type == ' |
|
|
127 |
self. |
|
|
126 | if msg_type == 'input_request': | |
|
127 | self.input_requested.emit(msg) | |
|
128 | 128 | |
|
129 | 129 | |
|
130 | 130 | class QtKernelManager(KernelManager, QtCore.QObject): |
@@ -37,93 +37,6 from completer import KernelCompleter | |||
|
37 | 37 | # Kernel and stream classes |
|
38 | 38 | #----------------------------------------------------------------------------- |
|
39 | 39 | |
|
40 | class InStream(object): | |
|
41 | """ A file like object that reads from a 0MQ XREQ socket.""" | |
|
42 | ||
|
43 | def __init__(self, session, socket): | |
|
44 | self.session = session | |
|
45 | self.socket = socket | |
|
46 | ||
|
47 | def close(self): | |
|
48 | self.socket = None | |
|
49 | ||
|
50 | def flush(self): | |
|
51 | if self.socket is None: | |
|
52 | raise ValueError('I/O operation on closed file') | |
|
53 | ||
|
54 | def isatty(self): | |
|
55 | return False | |
|
56 | ||
|
57 | def next(self): | |
|
58 | raise IOError('Seek not supported.') | |
|
59 | ||
|
60 | def read(self, size=-1): | |
|
61 | # FIXME: Do we want another request for this? | |
|
62 | string = '\n'.join(self.readlines()) | |
|
63 | return self._truncate(string, size) | |
|
64 | ||
|
65 | def readline(self, size=-1): | |
|
66 | if self.socket is None: | |
|
67 | raise ValueError('I/O operation on closed file') | |
|
68 | else: | |
|
69 | content = dict(size=size) | |
|
70 | msg = self.session.msg('readline_request', content=content) | |
|
71 | reply = self._request(msg) | |
|
72 | line = reply['content']['line'] | |
|
73 | return self._truncate(line, size) | |
|
74 | ||
|
75 | def readlines(self, sizehint=-1): | |
|
76 | # Sizehint is ignored, as is permitted. | |
|
77 | if self.socket is None: | |
|
78 | raise ValueError('I/O operation on closed file') | |
|
79 | else: | |
|
80 | lines = [] | |
|
81 | while True: | |
|
82 | line = self.readline() | |
|
83 | if line: | |
|
84 | lines.append(line) | |
|
85 | else: | |
|
86 | break | |
|
87 | return lines | |
|
88 | ||
|
89 | def seek(self, offset, whence=None): | |
|
90 | raise IOError('Seek not supported.') | |
|
91 | ||
|
92 | def write(self, string): | |
|
93 | raise IOError('Write not supported on a read only stream.') | |
|
94 | ||
|
95 | def writelines(self, sequence): | |
|
96 | raise IOError('Write not supported on a read only stream.') | |
|
97 | ||
|
98 | def _request(self, msg): | |
|
99 | # Flush output before making the request. This ensures, for example, | |
|
100 | # that raw_input(prompt) actually gets a prompt written. | |
|
101 | sys.stderr.flush() | |
|
102 | sys.stdout.flush() | |
|
103 | ||
|
104 | self.socket.send_json(msg) | |
|
105 | while True: | |
|
106 | try: | |
|
107 | reply = self.socket.recv_json(zmq.NOBLOCK) | |
|
108 | except zmq.ZMQError, e: | |
|
109 | if e.errno == zmq.EAGAIN: | |
|
110 | pass | |
|
111 | else: | |
|
112 | raise | |
|
113 | else: | |
|
114 | break | |
|
115 | return reply | |
|
116 | ||
|
117 | def _truncate(self, string, size): | |
|
118 | if size >= 0: | |
|
119 | if isinstance(string, str): | |
|
120 | return string[:size] | |
|
121 | elif isinstance(string, unicode): | |
|
122 | encoded = string.encode('utf-8')[:size] | |
|
123 | return encoded.decode('utf-8', 'ignore') | |
|
124 | return string | |
|
125 | ||
|
126 | ||
|
127 | 40 | class OutStream(object): |
|
128 | 41 | """A file like object that publishes the stream to a 0MQ PUB socket.""" |
|
129 | 42 | |
@@ -215,10 +128,11 class DisplayHook(object): | |||
|
215 | 128 | |
|
216 | 129 | class Kernel(object): |
|
217 | 130 | |
|
218 | def __init__(self, session, reply_socket, pub_socket): | |
|
131 | def __init__(self, session, reply_socket, pub_socket, req_socket): | |
|
219 | 132 | self.session = session |
|
220 | 133 | self.reply_socket = reply_socket |
|
221 | 134 | self.pub_socket = pub_socket |
|
135 | self.req_socket = req_socket | |
|
222 | 136 | self.user_ns = {} |
|
223 | 137 | self.history = [] |
|
224 | 138 | self.compiler = CommandCompiler() |
@@ -265,7 +179,15 class Kernel(object): | |||
|
265 | 179 | |
|
266 | 180 | try: |
|
267 | 181 | comp_code = self.compiler(code, '<zmq-kernel>') |
|
182 | ||
|
183 | # Replace raw_input. Note that is not sufficient to replace | |
|
184 | # raw_input in the user namespace. | |
|
185 | raw_input = lambda prompt='': self.raw_input(prompt, ident, parent) | |
|
186 | __builtin__.raw_input = raw_input | |
|
187 | ||
|
188 | # Configure the display hook. | |
|
268 | 189 | sys.displayhook.set_parent(parent) |
|
190 | ||
|
269 | 191 | exec comp_code in self.user_ns, self.user_ns |
|
270 | 192 | except: |
|
271 | 193 | result = u'error' |
@@ -295,6 +217,26 class Kernel(object): | |||
|
295 | 217 | if reply_msg['content']['status'] == u'error': |
|
296 | 218 | self.abort_queue() |
|
297 | 219 | |
|
220 | def raw_input(self, prompt, ident, parent): | |
|
221 | # Flush output before making the request. | |
|
222 | sys.stderr.flush() | |
|
223 | sys.stdout.flush() | |
|
224 | ||
|
225 | # Send the input request. | |
|
226 | content = dict(prompt=prompt) | |
|
227 | msg = self.session.msg(u'input_request', content, parent) | |
|
228 | self.req_socket.send_json(msg) | |
|
229 | ||
|
230 | # Await a response. | |
|
231 | reply = self.req_socket.recv_json() | |
|
232 | try: | |
|
233 | value = reply['content']['value'] | |
|
234 | except: | |
|
235 | print>>sys.__stderr__, "Got bad raw_input reply: " | |
|
236 | print>>sys.__stderr__, Message(parent) | |
|
237 | value = '' | |
|
238 | return value | |
|
239 | ||
|
298 | 240 | def complete_request(self, ident, parent): |
|
299 | 241 | matches = {'matches' : self.complete(parent), |
|
300 | 242 | 'status' : 'ok'} |
@@ -345,7 +287,7 class Kernel(object): | |||
|
345 | 287 | def start(self): |
|
346 | 288 | while True: |
|
347 | 289 | ident = self.reply_socket.recv() |
|
348 |
assert self.reply_socket.rcvmore(), " |
|
|
290 | assert self.reply_socket.rcvmore(), "Missing message part." | |
|
349 | 291 | msg = self.reply_socket.recv_json() |
|
350 | 292 | omsg = Message(msg) |
|
351 | 293 | print>>sys.__stdout__ |
@@ -362,7 +304,7 class Kernel(object): | |||
|
362 | 304 | |
|
363 | 305 | class ExitPollerUnix(Thread): |
|
364 | 306 | """ A Unix-specific daemon thread that terminates the program immediately |
|
365 |
when th |
|
|
307 | when the parent process no longer exists. | |
|
366 | 308 | """ |
|
367 | 309 | |
|
368 | 310 | def __init__(self): |
@@ -452,13 +394,12 def main(): | |||
|
452 | 394 | print >>sys.__stdout__, "REQ Channel on port", req_port |
|
453 | 395 | |
|
454 | 396 | # Redirect input streams and set a display hook. |
|
455 | sys.stdin = InStream(session, req_socket) | |
|
456 | 397 | sys.stdout = OutStream(session, pub_socket, u'stdout') |
|
457 | 398 | sys.stderr = OutStream(session, pub_socket, u'stderr') |
|
458 | 399 | sys.displayhook = DisplayHook(session, pub_socket) |
|
459 | 400 | |
|
460 | 401 | # Create the kernel. |
|
461 | kernel = Kernel(session, reply_socket, pub_socket) | |
|
402 | kernel = Kernel(session, reply_socket, pub_socket, req_socket) | |
|
462 | 403 | |
|
463 | 404 | # Configure this kernel/process to die on parent termination, if necessary. |
|
464 | 405 | if namespace.parent: |
@@ -368,16 +368,10 class RepSocketChannel(ZmqSocketChannel): | |||
|
368 | 368 | """ |
|
369 | 369 | raise NotImplementedError('call_handlers must be defined in a subclass.') |
|
370 | 370 | |
|
371 |
def |
|
|
372 |
""" |
|
|
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) | |
|
371 | def input(self, string): | |
|
372 | """Send a string of raw input to the kernel.""" | |
|
373 | content = dict(value=string) | |
|
374 | msg = self.session.msg('input_reply', content) | |
|
381 | 375 | self._queue_reply(msg) |
|
382 | 376 | |
|
383 | 377 | def _handle_events(self, socket, events): |
@@ -432,13 +426,15 class KernelManager(HasTraits): | |||
|
432 | 426 | # The Session to use for communication with the kernel. |
|
433 | 427 | session = Instance(Session) |
|
434 | 428 | |
|
429 | # The kernel process with which the KernelManager is communicating. | |
|
430 | kernel = Instance(Popen) | |
|
431 | ||
|
435 | 432 | # The classes to use for the various channels. |
|
436 | 433 | xreq_channel_class = Type(XReqSocketChannel) |
|
437 | 434 | sub_channel_class = Type(SubSocketChannel) |
|
438 | 435 | rep_channel_class = Type(RepSocketChannel) |
|
439 | 436 | |
|
440 | 437 | # Protected traits. |
|
441 | _kernel = Instance(Popen) | |
|
442 | 438 | _xreq_address = Any |
|
443 | 439 | _sub_address = Any |
|
444 | 440 | _rep_address = Any |
@@ -504,9 +500,8 class KernelManager(HasTraits): | |||
|
504 | 500 | "Make sure that the '*_address' attributes are " |
|
505 | 501 | "configured properly.") |
|
506 | 502 | |
|
507 | kernel, xrep, pub, req = launch_kernel( | |
|
503 | self.kernel, xrep, pub, req = launch_kernel( | |
|
508 | 504 | xrep_port=xreq[1], pub_port=sub[1], req_port=rep[1]) |
|
509 | self._kernel = kernel | |
|
510 | 505 | self._xreq_address = (LOCALHOST, xrep) |
|
511 | 506 | self._sub_address = (LOCALHOST, pub) |
|
512 | 507 | self._rep_address = (LOCALHOST, req) |
@@ -515,31 +510,29 class KernelManager(HasTraits): | |||
|
515 | 510 | def has_kernel(self): |
|
516 | 511 | """Returns whether a kernel process has been specified for the kernel |
|
517 | 512 | manager. |
|
518 | ||
|
519 | A kernel process can be set via 'start_kernel' or 'set_kernel'. | |
|
520 | 513 | """ |
|
521 |
return self. |
|
|
514 | return self.kernel is not None | |
|
522 | 515 | |
|
523 | 516 | def kill_kernel(self): |
|
524 | 517 | """ Kill the running kernel. """ |
|
525 |
if self. |
|
|
526 |
self. |
|
|
527 |
self. |
|
|
518 | if self.kernel is not None: | |
|
519 | self.kernel.kill() | |
|
520 | self.kernel = None | |
|
528 | 521 | else: |
|
529 | 522 | raise RuntimeError("Cannot kill kernel. No kernel is running!") |
|
530 | 523 | |
|
531 | 524 | def signal_kernel(self, signum): |
|
532 | 525 | """ Sends a signal to the kernel. """ |
|
533 |
if self. |
|
|
534 |
self. |
|
|
526 | if self.kernel is not None: | |
|
527 | self.kernel.send_signal(signum) | |
|
535 | 528 | else: |
|
536 | 529 | raise RuntimeError("Cannot signal kernel. No kernel is running!") |
|
537 | 530 | |
|
538 | 531 | @property |
|
539 | 532 | def is_alive(self): |
|
540 | 533 | """Is the kernel process still running?""" |
|
541 |
if self. |
|
|
542 |
if self. |
|
|
534 | if self.kernel is not None: | |
|
535 | if self.kernel.poll() is None: | |
|
543 | 536 | return True |
|
544 | 537 | else: |
|
545 | 538 | return False |
General Comments 0
You need to be logged in to leave comments.
Login now