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