##// END OF EJS Templates
Redirect unused pipes to devnull
Takafumi Arakaki -
Show More
@@ -1,461 +1,462 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Frontend of ipython working with python-zmq
2 """Frontend of ipython working with python-zmq
3
3
4 Ipython's frontend, is a ipython interface that send request to kernel and proccess the kernel's outputs.
4 Ipython's frontend, is a ipython interface that send request to kernel and proccess the kernel's outputs.
5
5
6 For more details, see the ipython-zmq design
6 For more details, see the ipython-zmq design
7 """
7 """
8 #-----------------------------------------------------------------------------
8 #-----------------------------------------------------------------------------
9 # Copyright (C) 2011 The IPython Development Team
9 # Copyright (C) 2011 The IPython Development Team
10 #
10 #
11 # Distributed under the terms of the BSD License. The full license is in
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
12 # the file COPYING, distributed as part of this software.
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 # Imports
16 # Imports
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18 from __future__ import print_function
18 from __future__ import print_function
19
19
20 import bdb
20 import bdb
21 import signal
21 import signal
22 import os
22 import sys
23 import sys
23 import time
24 import time
24 import tempfile
25 import tempfile
25 import subprocess
26 import subprocess
26 from io import BytesIO
27 from io import BytesIO
27 import base64
28 import base64
28
29
29 from Queue import Empty
30 from Queue import Empty
30
31
31 from IPython.core.alias import AliasManager, AliasError
32 from IPython.core.alias import AliasManager, AliasError
32 from IPython.core import page
33 from IPython.core import page
33 from IPython.utils.warn import warn, error, fatal
34 from IPython.utils.warn import warn, error, fatal
34 from IPython.utils import io
35 from IPython.utils import io
35 from IPython.utils.traitlets import List, Enum, Any
36 from IPython.utils.traitlets import List, Enum, Any
36
37
37 from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell
38 from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell
38 from IPython.frontend.terminal.console.completer import ZMQCompleter
39 from IPython.frontend.terminal.console.completer import ZMQCompleter
39
40
40
41
41 class ZMQTerminalInteractiveShell(TerminalInteractiveShell):
42 class ZMQTerminalInteractiveShell(TerminalInteractiveShell):
42 """A subclass of TerminalInteractiveShell that uses the 0MQ kernel"""
43 """A subclass of TerminalInteractiveShell that uses the 0MQ kernel"""
43 _executing = False
44 _executing = False
44
45
45 image_handler = Enum(('PIL', 'stream', 'tempfile', 'callable'),
46 image_handler = Enum(('PIL', 'stream', 'tempfile', 'callable'),
46 config=True, help=
47 config=True, help=
47 """
48 """
48 Handler for image type output. This is useful, for example,
49 Handler for image type output. This is useful, for example,
49 when connecting to the kernel in which pylab inline backend is
50 when connecting to the kernel in which pylab inline backend is
50 activated. There are four handlers defined. 'PIL': Use
51 activated. There are four handlers defined. 'PIL': Use
51 Python Imaging Library to popup image; 'stream': Use an
52 Python Imaging Library to popup image; 'stream': Use an
52 external program to show the image. Image will be fed into
53 external program to show the image. Image will be fed into
53 the STDIN of the program. You will need to configure
54 the STDIN of the program. You will need to configure
54 `stream_image_handler`; 'tempfile': Use an external program to
55 `stream_image_handler`; 'tempfile': Use an external program to
55 show the image. Image will be saved in a temporally file and
56 show the image. Image will be saved in a temporally file and
56 the program is called with the temporally file. You will need
57 the program is called with the temporally file. You will need
57 to configure `tempfile_image_handler`; 'callable': You can set
58 to configure `tempfile_image_handler`; 'callable': You can set
58 any Python callable which is called with the image data. You
59 any Python callable which is called with the image data. You
59 will need to configure `callable_image_handler`.
60 will need to configure `callable_image_handler`.
60 """
61 """
61 )
62 )
62
63
63 stream_image_handler = List(config=True, help=
64 stream_image_handler = List(config=True, help=
64 """
65 """
65 Command to invoke an image viewer program when you are using
66 Command to invoke an image viewer program when you are using
66 'stream' image handler. This option is a list of string where
67 'stream' image handler. This option is a list of string where
67 the first element is the command itself and reminders are the
68 the first element is the command itself and reminders are the
68 options for the command. Raw image data is given as STDIN to
69 options for the command. Raw image data is given as STDIN to
69 the program.
70 the program.
70 """
71 """
71 )
72 )
72
73
73 tempfile_image_handler = List(config=True, help=
74 tempfile_image_handler = List(config=True, help=
74 """
75 """
75 Command to invoke an image viewer program when you are using
76 Command to invoke an image viewer program when you are using
76 'tempfile' image handler. This option is a list of string
77 'tempfile' image handler. This option is a list of string
77 where the first element is the command itself and reminders
78 where the first element is the command itself and reminders
78 are the options for the command. You can use {file} and
79 are the options for the command. You can use {file} and
79 {format} in the string to represent the location of the
80 {format} in the string to represent the location of the
80 generated image file and image format.
81 generated image file and image format.
81 """
82 """
82 )
83 )
83
84
84 callable_image_handler = Any(config=True, help=
85 callable_image_handler = Any(config=True, help=
85 """
86 """
86 Callable object called via 'callable' image handler with one
87 Callable object called via 'callable' image handler with one
87 argument, `data`, which is `msg["content"]["data"]` where
88 argument, `data`, which is `msg["content"]["data"]` where
88 `msg` is the message from iopub channel. For exmaple, you can
89 `msg` is the message from iopub channel. For exmaple, you can
89 find base64 encoded PNG data as `data['image/png']`. You can
90 find base64 encoded PNG data as `data['image/png']`. You can
90 use {format} in the string to represent the image format.
91 use {format} in the string to represent the image format.
91 """
92 """
92 )
93 )
93
94
94 mime_preference = List(
95 mime_preference = List(
95 default_value=['image/png', 'image/jpeg', 'image/svg+xml'],
96 default_value=['image/png', 'image/jpeg', 'image/svg+xml'],
96 config=True, allow_none=False, help=
97 config=True, allow_none=False, help=
97 """
98 """
98 Preferred object representation MIME type in order. First
99 Preferred object representation MIME type in order. First
99 matched MIME type will be used.
100 matched MIME type will be used.
100 """
101 """
101 )
102 )
102
103
103 def __init__(self, *args, **kwargs):
104 def __init__(self, *args, **kwargs):
104 self.km = kwargs.pop('kernel_manager')
105 self.km = kwargs.pop('kernel_manager')
105 self.session_id = self.km.session.session
106 self.session_id = self.km.session.session
106 super(ZMQTerminalInteractiveShell, self).__init__(*args, **kwargs)
107 super(ZMQTerminalInteractiveShell, self).__init__(*args, **kwargs)
107
108
108 def init_completer(self):
109 def init_completer(self):
109 """Initialize the completion machinery.
110 """Initialize the completion machinery.
110
111
111 This creates completion machinery that can be used by client code,
112 This creates completion machinery that can be used by client code,
112 either interactively in-process (typically triggered by the readline
113 either interactively in-process (typically triggered by the readline
113 library), programatically (such as in test suites) or out-of-prcess
114 library), programatically (such as in test suites) or out-of-prcess
114 (typically over the network by remote frontends).
115 (typically over the network by remote frontends).
115 """
116 """
116 from IPython.core.completerlib import (module_completer,
117 from IPython.core.completerlib import (module_completer,
117 magic_run_completer, cd_completer)
118 magic_run_completer, cd_completer)
118
119
119 self.Completer = ZMQCompleter(self, self.km)
120 self.Completer = ZMQCompleter(self, self.km)
120
121
121
122
122 self.set_hook('complete_command', module_completer, str_key = 'import')
123 self.set_hook('complete_command', module_completer, str_key = 'import')
123 self.set_hook('complete_command', module_completer, str_key = 'from')
124 self.set_hook('complete_command', module_completer, str_key = 'from')
124 self.set_hook('complete_command', magic_run_completer, str_key = '%run')
125 self.set_hook('complete_command', magic_run_completer, str_key = '%run')
125 self.set_hook('complete_command', cd_completer, str_key = '%cd')
126 self.set_hook('complete_command', cd_completer, str_key = '%cd')
126
127
127 # Only configure readline if we truly are using readline. IPython can
128 # Only configure readline if we truly are using readline. IPython can
128 # do tab-completion over the network, in GUIs, etc, where readline
129 # do tab-completion over the network, in GUIs, etc, where readline
129 # itself may be absent
130 # itself may be absent
130 if self.has_readline:
131 if self.has_readline:
131 self.set_readline_completer()
132 self.set_readline_completer()
132
133
133 def run_cell(self, cell, store_history=True):
134 def run_cell(self, cell, store_history=True):
134 """Run a complete IPython cell.
135 """Run a complete IPython cell.
135
136
136 Parameters
137 Parameters
137 ----------
138 ----------
138 cell : str
139 cell : str
139 The code (including IPython code such as %magic functions) to run.
140 The code (including IPython code such as %magic functions) to run.
140 store_history : bool
141 store_history : bool
141 If True, the raw and translated cell will be stored in IPython's
142 If True, the raw and translated cell will be stored in IPython's
142 history. For user code calling back into IPython's machinery, this
143 history. For user code calling back into IPython's machinery, this
143 should be set to False.
144 should be set to False.
144 """
145 """
145 if (not cell) or cell.isspace():
146 if (not cell) or cell.isspace():
146 return
147 return
147
148
148 if cell.strip() == 'exit':
149 if cell.strip() == 'exit':
149 # explicitly handle 'exit' command
150 # explicitly handle 'exit' command
150 return self.ask_exit()
151 return self.ask_exit()
151
152
152 self._executing = True
153 self._executing = True
153 # flush stale replies, which could have been ignored, due to missed heartbeats
154 # flush stale replies, which could have been ignored, due to missed heartbeats
154 while self.km.shell_channel.msg_ready():
155 while self.km.shell_channel.msg_ready():
155 self.km.shell_channel.get_msg()
156 self.km.shell_channel.get_msg()
156 # shell_channel.execute takes 'hidden', which is the inverse of store_hist
157 # shell_channel.execute takes 'hidden', which is the inverse of store_hist
157 msg_id = self.km.shell_channel.execute(cell, not store_history)
158 msg_id = self.km.shell_channel.execute(cell, not store_history)
158 while not self.km.shell_channel.msg_ready() and self.km.is_alive:
159 while not self.km.shell_channel.msg_ready() and self.km.is_alive:
159 try:
160 try:
160 self.handle_stdin_request(timeout=0.05)
161 self.handle_stdin_request(timeout=0.05)
161 except Empty:
162 except Empty:
162 # display intermediate print statements, etc.
163 # display intermediate print statements, etc.
163 self.handle_iopub()
164 self.handle_iopub()
164 pass
165 pass
165 if self.km.shell_channel.msg_ready():
166 if self.km.shell_channel.msg_ready():
166 self.handle_execute_reply(msg_id)
167 self.handle_execute_reply(msg_id)
167 self._executing = False
168 self._executing = False
168
169
169 #-----------------
170 #-----------------
170 # message handlers
171 # message handlers
171 #-----------------
172 #-----------------
172
173
173 def handle_execute_reply(self, msg_id):
174 def handle_execute_reply(self, msg_id):
174 msg = self.km.shell_channel.get_msg()
175 msg = self.km.shell_channel.get_msg()
175 if msg["parent_header"].get("msg_id", None) == msg_id:
176 if msg["parent_header"].get("msg_id", None) == msg_id:
176
177
177 self.handle_iopub()
178 self.handle_iopub()
178
179
179 content = msg["content"]
180 content = msg["content"]
180 status = content['status']
181 status = content['status']
181
182
182 if status == 'aborted':
183 if status == 'aborted':
183 self.write('Aborted\n')
184 self.write('Aborted\n')
184 return
185 return
185 elif status == 'ok':
186 elif status == 'ok':
186 # print execution payloads as well:
187 # print execution payloads as well:
187 for item in content["payload"]:
188 for item in content["payload"]:
188 text = item.get('text', None)
189 text = item.get('text', None)
189 if text:
190 if text:
190 page.page(text)
191 page.page(text)
191
192
192 elif status == 'error':
193 elif status == 'error':
193 for frame in content["traceback"]:
194 for frame in content["traceback"]:
194 print(frame, file=io.stderr)
195 print(frame, file=io.stderr)
195
196
196 self.execution_count = int(content["execution_count"] + 1)
197 self.execution_count = int(content["execution_count"] + 1)
197
198
198
199
199 def handle_iopub(self):
200 def handle_iopub(self):
200 """ Method to procces subscribe channel's messages
201 """ Method to procces subscribe channel's messages
201
202
202 This method reads a message and processes the content in different
203 This method reads a message and processes the content in different
203 outputs like stdout, stderr, pyout and status
204 outputs like stdout, stderr, pyout and status
204
205
205 Arguments:
206 Arguments:
206 sub_msg: message receive from kernel in the sub socket channel
207 sub_msg: message receive from kernel in the sub socket channel
207 capture by kernel manager.
208 capture by kernel manager.
208 """
209 """
209 while self.km.sub_channel.msg_ready():
210 while self.km.sub_channel.msg_ready():
210 sub_msg = self.km.sub_channel.get_msg()
211 sub_msg = self.km.sub_channel.get_msg()
211 msg_type = sub_msg['header']['msg_type']
212 msg_type = sub_msg['header']['msg_type']
212 parent = sub_msg["parent_header"]
213 parent = sub_msg["parent_header"]
213 if (not parent) or self.session_id == parent['session']:
214 if (not parent) or self.session_id == parent['session']:
214 if msg_type == 'status' :
215 if msg_type == 'status' :
215 if sub_msg["content"]["execution_state"] == "busy" :
216 if sub_msg["content"]["execution_state"] == "busy" :
216 pass
217 pass
217
218
218 elif msg_type == 'stream' :
219 elif msg_type == 'stream' :
219 if sub_msg["content"]["name"] == "stdout":
220 if sub_msg["content"]["name"] == "stdout":
220 print(sub_msg["content"]["data"], file=io.stdout, end="")
221 print(sub_msg["content"]["data"], file=io.stdout, end="")
221 io.stdout.flush()
222 io.stdout.flush()
222 elif sub_msg["content"]["name"] == "stderr" :
223 elif sub_msg["content"]["name"] == "stderr" :
223 print(sub_msg["content"]["data"], file=io.stderr, end="")
224 print(sub_msg["content"]["data"], file=io.stderr, end="")
224 io.stderr.flush()
225 io.stderr.flush()
225
226
226 elif msg_type == 'pyout':
227 elif msg_type == 'pyout':
227 self.execution_count = int(sub_msg["content"]["execution_count"])
228 self.execution_count = int(sub_msg["content"]["execution_count"])
228 format_dict = sub_msg["content"]["data"]
229 format_dict = sub_msg["content"]["data"]
229 self.handle_rich_data(format_dict)
230 self.handle_rich_data(format_dict)
230 # taken from DisplayHook.__call__:
231 # taken from DisplayHook.__call__:
231 hook = self.displayhook
232 hook = self.displayhook
232 hook.start_displayhook()
233 hook.start_displayhook()
233 hook.write_output_prompt()
234 hook.write_output_prompt()
234 hook.write_format_data(format_dict)
235 hook.write_format_data(format_dict)
235 hook.log_output(format_dict)
236 hook.log_output(format_dict)
236 hook.finish_displayhook()
237 hook.finish_displayhook()
237
238
238 elif msg_type == 'display_data':
239 elif msg_type == 'display_data':
239 self.handle_rich_data(sub_msg["content"]["data"])
240 self.handle_rich_data(sub_msg["content"]["data"])
240
241
241 _imagemime = {
242 _imagemime = {
242 'image/png': 'png',
243 'image/png': 'png',
243 'image/jpeg': 'jpeg',
244 'image/jpeg': 'jpeg',
244 'image/svg+xml': 'svg',
245 'image/svg+xml': 'svg',
245 }
246 }
246
247
247 def handle_rich_data(self, data):
248 def handle_rich_data(self, data):
248 for mime in self.mime_preference:
249 for mime in self.mime_preference:
249 if mime in data and mime in self._imagemime:
250 if mime in data and mime in self._imagemime:
250 self.handle_image(data, mime)
251 self.handle_image(data, mime)
251 return
252 return
252
253
253 def handle_image(self, data, mime):
254 def handle_image(self, data, mime):
254 handler = getattr(
255 handler = getattr(
255 self, 'handle_image_{0}'.format(self.image_handler), None)
256 self, 'handle_image_{0}'.format(self.image_handler), None)
256 if handler:
257 if handler:
257 handler(data, mime)
258 handler(data, mime)
258
259
259 def handle_image_PIL(self, data, mime):
260 def handle_image_PIL(self, data, mime):
260 if mime not in ('image/png', 'image/jpeg'):
261 if mime not in ('image/png', 'image/jpeg'):
261 return
262 return
262 import PIL
263 import PIL
263 raw = base64.decodestring(data[mime])
264 raw = base64.decodestring(data[mime])
264 img = PIL.Image.open(BytesIO(raw))
265 img = PIL.Image.open(BytesIO(raw))
265 img.show()
266 img.show()
266
267
267 def handle_image_stream(self, data, mime):
268 def handle_image_stream(self, data, mime):
268 raw = base64.decodestring(data[mime])
269 raw = base64.decodestring(data[mime])
269 imageformat = self._imagemime[mime]
270 imageformat = self._imagemime[mime]
270 fmt = dict(format=imageformat)
271 fmt = dict(format=imageformat)
271 args = [s.format(**fmt) for s in self.stream_image_handler]
272 args = [s.format(**fmt) for s in self.stream_image_handler]
272 proc = subprocess.Popen(
273 with open(os.devnull, 'w') as devnull:
273 args, stdin=subprocess.PIPE,
274 proc = subprocess.Popen(
274 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
275 args, stdin=subprocess.PIPE,
275 proc.communicate(raw)
276 stdout=devnull, stderr=devnull)
277 proc.communicate(raw)
276
278
277 def handle_image_tempfile(self, data, mime):
279 def handle_image_tempfile(self, data, mime):
278 raw = base64.decodestring(data[mime])
280 raw = base64.decodestring(data[mime])
279 imageformat = self._imagemime[mime]
281 imageformat = self._imagemime[mime]
280 ext = '.{0}'.format(imageformat)
282 ext = '.{0}'.format(imageformat)
281 with tempfile.NamedTemporaryFile(suffix=ext) as f:
283 with tempfile.NamedTemporaryFile(suffix=ext) as f, \
284 open(os.devnull, 'w') as devnull:
282 f.write(raw)
285 f.write(raw)
283 f.flush()
286 f.flush()
284 fmt = dict(file=f.name, format=imageformat)
287 fmt = dict(file=f.name, format=imageformat)
285 args = [s.format(**fmt) for s in self.tempfile_image_handler]
288 args = [s.format(**fmt) for s in self.tempfile_image_handler]
286 subprocess.Popen(
289 subprocess.call(args, stdout=devnull, stderr=devnull)
287 args, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
288 ).communicate()
289
290
290 def handle_image_callable(self, data, mime):
291 def handle_image_callable(self, data, mime):
291 self.callable_image_handler(data)
292 self.callable_image_handler(data)
292
293
293 def handle_stdin_request(self, timeout=0.1):
294 def handle_stdin_request(self, timeout=0.1):
294 """ Method to capture raw_input
295 """ Method to capture raw_input
295 """
296 """
296 msg_rep = self.km.stdin_channel.get_msg(timeout=timeout)
297 msg_rep = self.km.stdin_channel.get_msg(timeout=timeout)
297 # in case any iopub came while we were waiting:
298 # in case any iopub came while we were waiting:
298 self.handle_iopub()
299 self.handle_iopub()
299 if self.session_id == msg_rep["parent_header"].get("session"):
300 if self.session_id == msg_rep["parent_header"].get("session"):
300 # wrap SIGINT handler
301 # wrap SIGINT handler
301 real_handler = signal.getsignal(signal.SIGINT)
302 real_handler = signal.getsignal(signal.SIGINT)
302 def double_int(sig,frame):
303 def double_int(sig,frame):
303 # call real handler (forwards sigint to kernel),
304 # call real handler (forwards sigint to kernel),
304 # then raise local interrupt, stopping local raw_input
305 # then raise local interrupt, stopping local raw_input
305 real_handler(sig,frame)
306 real_handler(sig,frame)
306 raise KeyboardInterrupt
307 raise KeyboardInterrupt
307 signal.signal(signal.SIGINT, double_int)
308 signal.signal(signal.SIGINT, double_int)
308
309
309 try:
310 try:
310 raw_data = raw_input(msg_rep["content"]["prompt"])
311 raw_data = raw_input(msg_rep["content"]["prompt"])
311 except EOFError:
312 except EOFError:
312 # turn EOFError into EOF character
313 # turn EOFError into EOF character
313 raw_data = '\x04'
314 raw_data = '\x04'
314 except KeyboardInterrupt:
315 except KeyboardInterrupt:
315 sys.stdout.write('\n')
316 sys.stdout.write('\n')
316 return
317 return
317 finally:
318 finally:
318 # restore SIGINT handler
319 # restore SIGINT handler
319 signal.signal(signal.SIGINT, real_handler)
320 signal.signal(signal.SIGINT, real_handler)
320
321
321 # only send stdin reply if there *was not* another request
322 # only send stdin reply if there *was not* another request
322 # or execution finished while we were reading.
323 # or execution finished while we were reading.
323 if not (self.km.stdin_channel.msg_ready() or self.km.shell_channel.msg_ready()):
324 if not (self.km.stdin_channel.msg_ready() or self.km.shell_channel.msg_ready()):
324 self.km.stdin_channel.input(raw_data)
325 self.km.stdin_channel.input(raw_data)
325
326
326 def mainloop(self, display_banner=False):
327 def mainloop(self, display_banner=False):
327 while True:
328 while True:
328 try:
329 try:
329 self.interact(display_banner=display_banner)
330 self.interact(display_banner=display_banner)
330 #self.interact_with_readline()
331 #self.interact_with_readline()
331 # XXX for testing of a readline-decoupled repl loop, call
332 # XXX for testing of a readline-decoupled repl loop, call
332 # interact_with_readline above
333 # interact_with_readline above
333 break
334 break
334 except KeyboardInterrupt:
335 except KeyboardInterrupt:
335 # this should not be necessary, but KeyboardInterrupt
336 # this should not be necessary, but KeyboardInterrupt
336 # handling seems rather unpredictable...
337 # handling seems rather unpredictable...
337 self.write("\nKeyboardInterrupt in interact()\n")
338 self.write("\nKeyboardInterrupt in interact()\n")
338
339
339 def wait_for_kernel(self, timeout=None):
340 def wait_for_kernel(self, timeout=None):
340 """method to wait for a kernel to be ready"""
341 """method to wait for a kernel to be ready"""
341 tic = time.time()
342 tic = time.time()
342 self.km.hb_channel.unpause()
343 self.km.hb_channel.unpause()
343 while True:
344 while True:
344 self.run_cell('1', False)
345 self.run_cell('1', False)
345 if self.km.hb_channel.is_beating():
346 if self.km.hb_channel.is_beating():
346 # heart failure was not the reason this returned
347 # heart failure was not the reason this returned
347 break
348 break
348 else:
349 else:
349 # heart failed
350 # heart failed
350 if timeout is not None and (time.time() - tic) > timeout:
351 if timeout is not None and (time.time() - tic) > timeout:
351 return False
352 return False
352 return True
353 return True
353
354
354 def interact(self, display_banner=None):
355 def interact(self, display_banner=None):
355 """Closely emulate the interactive Python console."""
356 """Closely emulate the interactive Python console."""
356
357
357 # batch run -> do not interact
358 # batch run -> do not interact
358 if self.exit_now:
359 if self.exit_now:
359 return
360 return
360
361
361 if display_banner is None:
362 if display_banner is None:
362 display_banner = self.display_banner
363 display_banner = self.display_banner
363
364
364 if isinstance(display_banner, basestring):
365 if isinstance(display_banner, basestring):
365 self.show_banner(display_banner)
366 self.show_banner(display_banner)
366 elif display_banner:
367 elif display_banner:
367 self.show_banner()
368 self.show_banner()
368
369
369 more = False
370 more = False
370
371
371 # run a non-empty no-op, so that we don't get a prompt until
372 # run a non-empty no-op, so that we don't get a prompt until
372 # we know the kernel is ready. This keeps the connection
373 # we know the kernel is ready. This keeps the connection
373 # message above the first prompt.
374 # message above the first prompt.
374 if not self.wait_for_kernel(3):
375 if not self.wait_for_kernel(3):
375 error("Kernel did not respond\n")
376 error("Kernel did not respond\n")
376 return
377 return
377
378
378 if self.has_readline:
379 if self.has_readline:
379 self.readline_startup_hook(self.pre_readline)
380 self.readline_startup_hook(self.pre_readline)
380 hlen_b4_cell = self.readline.get_current_history_length()
381 hlen_b4_cell = self.readline.get_current_history_length()
381 else:
382 else:
382 hlen_b4_cell = 0
383 hlen_b4_cell = 0
383 # exit_now is set by a call to %Exit or %Quit, through the
384 # exit_now is set by a call to %Exit or %Quit, through the
384 # ask_exit callback.
385 # ask_exit callback.
385
386
386 while not self.exit_now:
387 while not self.exit_now:
387 if not self.km.is_alive:
388 if not self.km.is_alive:
388 # kernel died, prompt for action or exit
389 # kernel died, prompt for action or exit
389 action = "restart" if self.km.has_kernel else "wait for restart"
390 action = "restart" if self.km.has_kernel else "wait for restart"
390 ans = self.ask_yes_no("kernel died, %s ([y]/n)?" % action, default='y')
391 ans = self.ask_yes_no("kernel died, %s ([y]/n)?" % action, default='y')
391 if ans:
392 if ans:
392 if self.km.has_kernel:
393 if self.km.has_kernel:
393 self.km.restart_kernel(True)
394 self.km.restart_kernel(True)
394 self.wait_for_kernel(3)
395 self.wait_for_kernel(3)
395 else:
396 else:
396 self.exit_now = True
397 self.exit_now = True
397 continue
398 continue
398 try:
399 try:
399 # protect prompt block from KeyboardInterrupt
400 # protect prompt block from KeyboardInterrupt
400 # when sitting on ctrl-C
401 # when sitting on ctrl-C
401 self.hooks.pre_prompt_hook()
402 self.hooks.pre_prompt_hook()
402 if more:
403 if more:
403 try:
404 try:
404 prompt = self.prompt_manager.render('in2')
405 prompt = self.prompt_manager.render('in2')
405 except Exception:
406 except Exception:
406 self.showtraceback()
407 self.showtraceback()
407 if self.autoindent:
408 if self.autoindent:
408 self.rl_do_indent = True
409 self.rl_do_indent = True
409
410
410 else:
411 else:
411 try:
412 try:
412 prompt = self.separate_in + self.prompt_manager.render('in')
413 prompt = self.separate_in + self.prompt_manager.render('in')
413 except Exception:
414 except Exception:
414 self.showtraceback()
415 self.showtraceback()
415
416
416 line = self.raw_input(prompt)
417 line = self.raw_input(prompt)
417 if self.exit_now:
418 if self.exit_now:
418 # quick exit on sys.std[in|out] close
419 # quick exit on sys.std[in|out] close
419 break
420 break
420 if self.autoindent:
421 if self.autoindent:
421 self.rl_do_indent = False
422 self.rl_do_indent = False
422
423
423 except KeyboardInterrupt:
424 except KeyboardInterrupt:
424 #double-guard against keyboardinterrupts during kbdint handling
425 #double-guard against keyboardinterrupts during kbdint handling
425 try:
426 try:
426 self.write('\nKeyboardInterrupt\n')
427 self.write('\nKeyboardInterrupt\n')
427 source_raw = self.input_splitter.source_raw_reset()[1]
428 source_raw = self.input_splitter.source_raw_reset()[1]
428 hlen_b4_cell = self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
429 hlen_b4_cell = self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
429 more = False
430 more = False
430 except KeyboardInterrupt:
431 except KeyboardInterrupt:
431 pass
432 pass
432 except EOFError:
433 except EOFError:
433 if self.autoindent:
434 if self.autoindent:
434 self.rl_do_indent = False
435 self.rl_do_indent = False
435 if self.has_readline:
436 if self.has_readline:
436 self.readline_startup_hook(None)
437 self.readline_startup_hook(None)
437 self.write('\n')
438 self.write('\n')
438 self.exit()
439 self.exit()
439 except bdb.BdbQuit:
440 except bdb.BdbQuit:
440 warn('The Python debugger has exited with a BdbQuit exception.\n'
441 warn('The Python debugger has exited with a BdbQuit exception.\n'
441 'Because of how pdb handles the stack, it is impossible\n'
442 'Because of how pdb handles the stack, it is impossible\n'
442 'for IPython to properly format this particular exception.\n'
443 'for IPython to properly format this particular exception.\n'
443 'IPython will resume normal operation.')
444 'IPython will resume normal operation.')
444 except:
445 except:
445 # exceptions here are VERY RARE, but they can be triggered
446 # exceptions here are VERY RARE, but they can be triggered
446 # asynchronously by signal handlers, for example.
447 # asynchronously by signal handlers, for example.
447 self.showtraceback()
448 self.showtraceback()
448 else:
449 else:
449 self.input_splitter.push(line)
450 self.input_splitter.push(line)
450 more = self.input_splitter.push_accepts_more()
451 more = self.input_splitter.push_accepts_more()
451 if (self.SyntaxTB.last_syntax_error and
452 if (self.SyntaxTB.last_syntax_error and
452 self.autoedit_syntax):
453 self.autoedit_syntax):
453 self.edit_syntax_error()
454 self.edit_syntax_error()
454 if not more:
455 if not more:
455 source_raw = self.input_splitter.source_raw_reset()[1]
456 source_raw = self.input_splitter.source_raw_reset()[1]
456 hlen_b4_cell = self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
457 hlen_b4_cell = self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
457 self.run_cell(source_raw)
458 self.run_cell(source_raw)
458
459
459
460
460 # Turn off the exit flag, so the mainloop can be restarted if desired
461 # Turn off the exit flag, so the mainloop can be restarted if desired
461 self.exit_now = False
462 self.exit_now = False
General Comments 0
You need to be logged in to leave comments. Login now