##// END OF EJS Templates
Drop nested() function for context managers
Thomas Kluyver -
Show More
@@ -1,493 +1,488 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """terminal client to the IPython kernel
2 """terminal client to the IPython kernel
3
3
4 """
4 """
5 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
6 # Copyright (C) 2013 The IPython Development Team
6 # Copyright (C) 2013 The IPython Development Team
7 #
7 #
8 # Distributed under the terms of the BSD License. The full license is in
8 # Distributed under the terms of the BSD License. The full license is in
9 # the file COPYING, distributed as part of this software.
9 # the file COPYING, distributed as part of this software.
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11
11
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13 # Imports
13 # Imports
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15 from __future__ import print_function
15 from __future__ import print_function
16
16
17 import bdb
17 import bdb
18 import signal
18 import signal
19 import os
19 import os
20 import sys
20 import sys
21 import time
21 import time
22 import subprocess
22 import subprocess
23 from io import BytesIO
23 from io import BytesIO
24 import base64
24 import base64
25
25
26 from Queue import Empty
26 from Queue import Empty
27
27
28 try:
29 from contextlib import nested
30 except:
31 from IPython.utils.nested_context import nested
32
33 from IPython.core import page
28 from IPython.core import page
34 from IPython.utils.warn import warn, error
29 from IPython.utils.warn import warn, error
35 from IPython.utils import io
30 from IPython.utils import io
36 from IPython.utils.traitlets import List, Enum, Any, Instance, Unicode, Float
31 from IPython.utils.traitlets import List, Enum, Any, Instance, Unicode, Float
37 from IPython.utils.tempdir import NamedFileInTemporaryDirectory
32 from IPython.utils.tempdir import NamedFileInTemporaryDirectory
38
33
39 from IPython.terminal.interactiveshell import TerminalInteractiveShell
34 from IPython.terminal.interactiveshell import TerminalInteractiveShell
40 from IPython.terminal.console.completer import ZMQCompleter
35 from IPython.terminal.console.completer import ZMQCompleter
41
36
42
37
43 class ZMQTerminalInteractiveShell(TerminalInteractiveShell):
38 class ZMQTerminalInteractiveShell(TerminalInteractiveShell):
44 """A subclass of TerminalInteractiveShell that uses the 0MQ kernel"""
39 """A subclass of TerminalInteractiveShell that uses the 0MQ kernel"""
45 _executing = False
40 _executing = False
46 _execution_state = Unicode('')
41 _execution_state = Unicode('')
47 kernel_timeout = Float(60, config=True,
42 kernel_timeout = Float(60, config=True,
48 help="""Timeout for giving up on a kernel (in seconds).
43 help="""Timeout for giving up on a kernel (in seconds).
49
44
50 On first connect and restart, the console tests whether the
45 On first connect and restart, the console tests whether the
51 kernel is running and responsive by sending kernel_info_requests.
46 kernel is running and responsive by sending kernel_info_requests.
52 This sets the timeout in seconds for how long the kernel can take
47 This sets the timeout in seconds for how long the kernel can take
53 before being presumed dead.
48 before being presumed dead.
54 """
49 """
55 )
50 )
56
51
57 image_handler = Enum(('PIL', 'stream', 'tempfile', 'callable'),
52 image_handler = Enum(('PIL', 'stream', 'tempfile', 'callable'),
58 config=True, help=
53 config=True, help=
59 """
54 """
60 Handler for image type output. This is useful, for example,
55 Handler for image type output. This is useful, for example,
61 when connecting to the kernel in which pylab inline backend is
56 when connecting to the kernel in which pylab inline backend is
62 activated. There are four handlers defined. 'PIL': Use
57 activated. There are four handlers defined. 'PIL': Use
63 Python Imaging Library to popup image; 'stream': Use an
58 Python Imaging Library to popup image; 'stream': Use an
64 external program to show the image. Image will be fed into
59 external program to show the image. Image will be fed into
65 the STDIN of the program. You will need to configure
60 the STDIN of the program. You will need to configure
66 `stream_image_handler`; 'tempfile': Use an external program to
61 `stream_image_handler`; 'tempfile': Use an external program to
67 show the image. Image will be saved in a temporally file and
62 show the image. Image will be saved in a temporally file and
68 the program is called with the temporally file. You will need
63 the program is called with the temporally file. You will need
69 to configure `tempfile_image_handler`; 'callable': You can set
64 to configure `tempfile_image_handler`; 'callable': You can set
70 any Python callable which is called with the image data. You
65 any Python callable which is called with the image data. You
71 will need to configure `callable_image_handler`.
66 will need to configure `callable_image_handler`.
72 """
67 """
73 )
68 )
74
69
75 stream_image_handler = List(config=True, help=
70 stream_image_handler = List(config=True, help=
76 """
71 """
77 Command to invoke an image viewer program when you are using
72 Command to invoke an image viewer program when you are using
78 'stream' image handler. This option is a list of string where
73 'stream' image handler. This option is a list of string where
79 the first element is the command itself and reminders are the
74 the first element is the command itself and reminders are the
80 options for the command. Raw image data is given as STDIN to
75 options for the command. Raw image data is given as STDIN to
81 the program.
76 the program.
82 """
77 """
83 )
78 )
84
79
85 tempfile_image_handler = List(config=True, help=
80 tempfile_image_handler = List(config=True, help=
86 """
81 """
87 Command to invoke an image viewer program when you are using
82 Command to invoke an image viewer program when you are using
88 'tempfile' image handler. This option is a list of string
83 'tempfile' image handler. This option is a list of string
89 where the first element is the command itself and reminders
84 where the first element is the command itself and reminders
90 are the options for the command. You can use {file} and
85 are the options for the command. You can use {file} and
91 {format} in the string to represent the location of the
86 {format} in the string to represent the location of the
92 generated image file and image format.
87 generated image file and image format.
93 """
88 """
94 )
89 )
95
90
96 callable_image_handler = Any(config=True, help=
91 callable_image_handler = Any(config=True, help=
97 """
92 """
98 Callable object called via 'callable' image handler with one
93 Callable object called via 'callable' image handler with one
99 argument, `data`, which is `msg["content"]["data"]` where
94 argument, `data`, which is `msg["content"]["data"]` where
100 `msg` is the message from iopub channel. For exmaple, you can
95 `msg` is the message from iopub channel. For exmaple, you can
101 find base64 encoded PNG data as `data['image/png']`.
96 find base64 encoded PNG data as `data['image/png']`.
102 """
97 """
103 )
98 )
104
99
105 mime_preference = List(
100 mime_preference = List(
106 default_value=['image/png', 'image/jpeg', 'image/svg+xml'],
101 default_value=['image/png', 'image/jpeg', 'image/svg+xml'],
107 config=True, allow_none=False, help=
102 config=True, allow_none=False, help=
108 """
103 """
109 Preferred object representation MIME type in order. First
104 Preferred object representation MIME type in order. First
110 matched MIME type will be used.
105 matched MIME type will be used.
111 """
106 """
112 )
107 )
113
108
114 manager = Instance('IPython.kernel.KernelManager')
109 manager = Instance('IPython.kernel.KernelManager')
115 client = Instance('IPython.kernel.KernelClient')
110 client = Instance('IPython.kernel.KernelClient')
116 def _client_changed(self, name, old, new):
111 def _client_changed(self, name, old, new):
117 self.session_id = new.session.session
112 self.session_id = new.session.session
118 session_id = Unicode()
113 session_id = Unicode()
119
114
120 def init_completer(self):
115 def init_completer(self):
121 """Initialize the completion machinery.
116 """Initialize the completion machinery.
122
117
123 This creates completion machinery that can be used by client code,
118 This creates completion machinery that can be used by client code,
124 either interactively in-process (typically triggered by the readline
119 either interactively in-process (typically triggered by the readline
125 library), programatically (such as in test suites) or out-of-prcess
120 library), programatically (such as in test suites) or out-of-prcess
126 (typically over the network by remote frontends).
121 (typically over the network by remote frontends).
127 """
122 """
128 from IPython.core.completerlib import (module_completer,
123 from IPython.core.completerlib import (module_completer,
129 magic_run_completer, cd_completer)
124 magic_run_completer, cd_completer)
130
125
131 self.Completer = ZMQCompleter(self, self.client, config=self.config)
126 self.Completer = ZMQCompleter(self, self.client, config=self.config)
132
127
133
128
134 self.set_hook('complete_command', module_completer, str_key = 'import')
129 self.set_hook('complete_command', module_completer, str_key = 'import')
135 self.set_hook('complete_command', module_completer, str_key = 'from')
130 self.set_hook('complete_command', module_completer, str_key = 'from')
136 self.set_hook('complete_command', magic_run_completer, str_key = '%run')
131 self.set_hook('complete_command', magic_run_completer, str_key = '%run')
137 self.set_hook('complete_command', cd_completer, str_key = '%cd')
132 self.set_hook('complete_command', cd_completer, str_key = '%cd')
138
133
139 # Only configure readline if we truly are using readline. IPython can
134 # Only configure readline if we truly are using readline. IPython can
140 # do tab-completion over the network, in GUIs, etc, where readline
135 # do tab-completion over the network, in GUIs, etc, where readline
141 # itself may be absent
136 # itself may be absent
142 if self.has_readline:
137 if self.has_readline:
143 self.set_readline_completer()
138 self.set_readline_completer()
144
139
145 def run_cell(self, cell, store_history=True):
140 def run_cell(self, cell, store_history=True):
146 """Run a complete IPython cell.
141 """Run a complete IPython cell.
147
142
148 Parameters
143 Parameters
149 ----------
144 ----------
150 cell : str
145 cell : str
151 The code (including IPython code such as %magic functions) to run.
146 The code (including IPython code such as %magic functions) to run.
152 store_history : bool
147 store_history : bool
153 If True, the raw and translated cell will be stored in IPython's
148 If True, the raw and translated cell will be stored in IPython's
154 history. For user code calling back into IPython's machinery, this
149 history. For user code calling back into IPython's machinery, this
155 should be set to False.
150 should be set to False.
156 """
151 """
157 if (not cell) or cell.isspace():
152 if (not cell) or cell.isspace():
158 return
153 return
159
154
160 if cell.strip() == 'exit':
155 if cell.strip() == 'exit':
161 # explicitly handle 'exit' command
156 # explicitly handle 'exit' command
162 return self.ask_exit()
157 return self.ask_exit()
163
158
164 # flush stale replies, which could have been ignored, due to missed heartbeats
159 # flush stale replies, which could have been ignored, due to missed heartbeats
165 while self.client.shell_channel.msg_ready():
160 while self.client.shell_channel.msg_ready():
166 self.client.shell_channel.get_msg()
161 self.client.shell_channel.get_msg()
167 # shell_channel.execute takes 'hidden', which is the inverse of store_hist
162 # shell_channel.execute takes 'hidden', which is the inverse of store_hist
168 msg_id = self.client.shell_channel.execute(cell, not store_history)
163 msg_id = self.client.shell_channel.execute(cell, not store_history)
169
164
170 # first thing is wait for any side effects (output, stdin, etc.)
165 # first thing is wait for any side effects (output, stdin, etc.)
171 self._executing = True
166 self._executing = True
172 self._execution_state = "busy"
167 self._execution_state = "busy"
173 while self._execution_state != 'idle' and self.client.is_alive():
168 while self._execution_state != 'idle' and self.client.is_alive():
174 try:
169 try:
175 self.handle_stdin_request(msg_id, timeout=0.05)
170 self.handle_stdin_request(msg_id, timeout=0.05)
176 except Empty:
171 except Empty:
177 # display intermediate print statements, etc.
172 # display intermediate print statements, etc.
178 self.handle_iopub(msg_id)
173 self.handle_iopub(msg_id)
179 pass
174 pass
180
175
181 # after all of that is done, wait for the execute reply
176 # after all of that is done, wait for the execute reply
182 while self.client.is_alive():
177 while self.client.is_alive():
183 try:
178 try:
184 self.handle_execute_reply(msg_id, timeout=0.05)
179 self.handle_execute_reply(msg_id, timeout=0.05)
185 except Empty:
180 except Empty:
186 pass
181 pass
187 else:
182 else:
188 break
183 break
189 self._executing = False
184 self._executing = False
190
185
191 #-----------------
186 #-----------------
192 # message handlers
187 # message handlers
193 #-----------------
188 #-----------------
194
189
195 def handle_execute_reply(self, msg_id, timeout=None):
190 def handle_execute_reply(self, msg_id, timeout=None):
196 msg = self.client.shell_channel.get_msg(block=False, timeout=timeout)
191 msg = self.client.shell_channel.get_msg(block=False, timeout=timeout)
197 if msg["parent_header"].get("msg_id", None) == msg_id:
192 if msg["parent_header"].get("msg_id", None) == msg_id:
198
193
199 self.handle_iopub(msg_id)
194 self.handle_iopub(msg_id)
200
195
201 content = msg["content"]
196 content = msg["content"]
202 status = content['status']
197 status = content['status']
203
198
204 if status == 'aborted':
199 if status == 'aborted':
205 self.write('Aborted\n')
200 self.write('Aborted\n')
206 return
201 return
207 elif status == 'ok':
202 elif status == 'ok':
208 # print execution payloads as well:
203 # print execution payloads as well:
209 for item in content["payload"]:
204 for item in content["payload"]:
210 text = item.get('text', None)
205 text = item.get('text', None)
211 if text:
206 if text:
212 page.page(text)
207 page.page(text)
213
208
214 elif status == 'error':
209 elif status == 'error':
215 for frame in content["traceback"]:
210 for frame in content["traceback"]:
216 print(frame, file=io.stderr)
211 print(frame, file=io.stderr)
217
212
218 self.execution_count = int(content["execution_count"] + 1)
213 self.execution_count = int(content["execution_count"] + 1)
219
214
220
215
221 def handle_iopub(self, msg_id):
216 def handle_iopub(self, msg_id):
222 """ Method to process subscribe channel's messages
217 """ Method to process subscribe channel's messages
223
218
224 This method consumes and processes messages on the IOPub channel,
219 This method consumes and processes messages on the IOPub channel,
225 such as stdout, stderr, pyout and status.
220 such as stdout, stderr, pyout and status.
226
221
227 It only displays output that is caused by the given msg_id
222 It only displays output that is caused by the given msg_id
228 """
223 """
229 while self.client.iopub_channel.msg_ready():
224 while self.client.iopub_channel.msg_ready():
230 sub_msg = self.client.iopub_channel.get_msg()
225 sub_msg = self.client.iopub_channel.get_msg()
231 msg_type = sub_msg['header']['msg_type']
226 msg_type = sub_msg['header']['msg_type']
232 parent = sub_msg["parent_header"]
227 parent = sub_msg["parent_header"]
233 if (not parent) or msg_id == parent['msg_id']:
228 if (not parent) or msg_id == parent['msg_id']:
234 if msg_type == 'status':
229 if msg_type == 'status':
235 state = self._execution_state = sub_msg["content"]["execution_state"]
230 state = self._execution_state = sub_msg["content"]["execution_state"]
236 # idle messages mean an individual sequence is complete,
231 # idle messages mean an individual sequence is complete,
237 # so break out of consumption to allow other things to take over.
232 # so break out of consumption to allow other things to take over.
238 if state == 'idle':
233 if state == 'idle':
239 break
234 break
240
235
241 elif msg_type == 'stream':
236 elif msg_type == 'stream':
242 if sub_msg["content"]["name"] == "stdout":
237 if sub_msg["content"]["name"] == "stdout":
243 print(sub_msg["content"]["data"], file=io.stdout, end="")
238 print(sub_msg["content"]["data"], file=io.stdout, end="")
244 io.stdout.flush()
239 io.stdout.flush()
245 elif sub_msg["content"]["name"] == "stderr" :
240 elif sub_msg["content"]["name"] == "stderr" :
246 print(sub_msg["content"]["data"], file=io.stderr, end="")
241 print(sub_msg["content"]["data"], file=io.stderr, end="")
247 io.stderr.flush()
242 io.stderr.flush()
248
243
249 elif msg_type == 'pyout':
244 elif msg_type == 'pyout':
250 self.execution_count = int(sub_msg["content"]["execution_count"])
245 self.execution_count = int(sub_msg["content"]["execution_count"])
251 format_dict = sub_msg["content"]["data"]
246 format_dict = sub_msg["content"]["data"]
252 self.handle_rich_data(format_dict)
247 self.handle_rich_data(format_dict)
253 # taken from DisplayHook.__call__:
248 # taken from DisplayHook.__call__:
254 hook = self.displayhook
249 hook = self.displayhook
255 hook.start_displayhook()
250 hook.start_displayhook()
256 hook.write_output_prompt()
251 hook.write_output_prompt()
257 hook.write_format_data(format_dict)
252 hook.write_format_data(format_dict)
258 hook.log_output(format_dict)
253 hook.log_output(format_dict)
259 hook.finish_displayhook()
254 hook.finish_displayhook()
260
255
261 elif msg_type == 'display_data':
256 elif msg_type == 'display_data':
262 self.handle_rich_data(sub_msg["content"]["data"])
257 self.handle_rich_data(sub_msg["content"]["data"])
263
258
264
259
265 _imagemime = {
260 _imagemime = {
266 'image/png': 'png',
261 'image/png': 'png',
267 'image/jpeg': 'jpeg',
262 'image/jpeg': 'jpeg',
268 'image/svg+xml': 'svg',
263 'image/svg+xml': 'svg',
269 }
264 }
270
265
271 def handle_rich_data(self, data):
266 def handle_rich_data(self, data):
272 for mime in self.mime_preference:
267 for mime in self.mime_preference:
273 if mime in data and mime in self._imagemime:
268 if mime in data and mime in self._imagemime:
274 self.handle_image(data, mime)
269 self.handle_image(data, mime)
275 return
270 return
276
271
277 def handle_image(self, data, mime):
272 def handle_image(self, data, mime):
278 handler = getattr(
273 handler = getattr(
279 self, 'handle_image_{0}'.format(self.image_handler), None)
274 self, 'handle_image_{0}'.format(self.image_handler), None)
280 if handler:
275 if handler:
281 handler(data, mime)
276 handler(data, mime)
282
277
283 def handle_image_PIL(self, data, mime):
278 def handle_image_PIL(self, data, mime):
284 if mime not in ('image/png', 'image/jpeg'):
279 if mime not in ('image/png', 'image/jpeg'):
285 return
280 return
286 import PIL.Image
281 import PIL.Image
287 raw = base64.decodestring(data[mime].encode('ascii'))
282 raw = base64.decodestring(data[mime].encode('ascii'))
288 img = PIL.Image.open(BytesIO(raw))
283 img = PIL.Image.open(BytesIO(raw))
289 img.show()
284 img.show()
290
285
291 def handle_image_stream(self, data, mime):
286 def handle_image_stream(self, data, mime):
292 raw = base64.decodestring(data[mime].encode('ascii'))
287 raw = base64.decodestring(data[mime].encode('ascii'))
293 imageformat = self._imagemime[mime]
288 imageformat = self._imagemime[mime]
294 fmt = dict(format=imageformat)
289 fmt = dict(format=imageformat)
295 args = [s.format(**fmt) for s in self.stream_image_handler]
290 args = [s.format(**fmt) for s in self.stream_image_handler]
296 with open(os.devnull, 'w') as devnull:
291 with open(os.devnull, 'w') as devnull:
297 proc = subprocess.Popen(
292 proc = subprocess.Popen(
298 args, stdin=subprocess.PIPE,
293 args, stdin=subprocess.PIPE,
299 stdout=devnull, stderr=devnull)
294 stdout=devnull, stderr=devnull)
300 proc.communicate(raw)
295 proc.communicate(raw)
301
296
302 def handle_image_tempfile(self, data, mime):
297 def handle_image_tempfile(self, data, mime):
303 raw = base64.decodestring(data[mime].encode('ascii'))
298 raw = base64.decodestring(data[mime].encode('ascii'))
304 imageformat = self._imagemime[mime]
299 imageformat = self._imagemime[mime]
305 filename = 'tmp.{0}'.format(imageformat)
300 filename = 'tmp.{0}'.format(imageformat)
306 with nested(NamedFileInTemporaryDirectory(filename),
301 with NamedFileInTemporaryDirectory(filename) as f, \
307 open(os.devnull, 'w')) as (f, devnull):
302 open(os.devnull, 'w') as devnull:
308 f.write(raw)
303 f.write(raw)
309 f.flush()
304 f.flush()
310 fmt = dict(file=f.name, format=imageformat)
305 fmt = dict(file=f.name, format=imageformat)
311 args = [s.format(**fmt) for s in self.tempfile_image_handler]
306 args = [s.format(**fmt) for s in self.tempfile_image_handler]
312 subprocess.call(args, stdout=devnull, stderr=devnull)
307 subprocess.call(args, stdout=devnull, stderr=devnull)
313
308
314 def handle_image_callable(self, data, mime):
309 def handle_image_callable(self, data, mime):
315 self.callable_image_handler(data)
310 self.callable_image_handler(data)
316
311
317 def handle_stdin_request(self, msg_id, timeout=0.1):
312 def handle_stdin_request(self, msg_id, timeout=0.1):
318 """ Method to capture raw_input
313 """ Method to capture raw_input
319 """
314 """
320 msg_rep = self.client.stdin_channel.get_msg(timeout=timeout)
315 msg_rep = self.client.stdin_channel.get_msg(timeout=timeout)
321 # in case any iopub came while we were waiting:
316 # in case any iopub came while we were waiting:
322 self.handle_iopub(msg_id)
317 self.handle_iopub(msg_id)
323 if msg_id == msg_rep["parent_header"].get("msg_id"):
318 if msg_id == msg_rep["parent_header"].get("msg_id"):
324 # wrap SIGINT handler
319 # wrap SIGINT handler
325 real_handler = signal.getsignal(signal.SIGINT)
320 real_handler = signal.getsignal(signal.SIGINT)
326 def double_int(sig,frame):
321 def double_int(sig,frame):
327 # call real handler (forwards sigint to kernel),
322 # call real handler (forwards sigint to kernel),
328 # then raise local interrupt, stopping local raw_input
323 # then raise local interrupt, stopping local raw_input
329 real_handler(sig,frame)
324 real_handler(sig,frame)
330 raise KeyboardInterrupt
325 raise KeyboardInterrupt
331 signal.signal(signal.SIGINT, double_int)
326 signal.signal(signal.SIGINT, double_int)
332
327
333 try:
328 try:
334 raw_data = raw_input(msg_rep["content"]["prompt"])
329 raw_data = raw_input(msg_rep["content"]["prompt"])
335 except EOFError:
330 except EOFError:
336 # turn EOFError into EOF character
331 # turn EOFError into EOF character
337 raw_data = '\x04'
332 raw_data = '\x04'
338 except KeyboardInterrupt:
333 except KeyboardInterrupt:
339 sys.stdout.write('\n')
334 sys.stdout.write('\n')
340 return
335 return
341 finally:
336 finally:
342 # restore SIGINT handler
337 # restore SIGINT handler
343 signal.signal(signal.SIGINT, real_handler)
338 signal.signal(signal.SIGINT, real_handler)
344
339
345 # only send stdin reply if there *was not* another request
340 # only send stdin reply if there *was not* another request
346 # or execution finished while we were reading.
341 # or execution finished while we were reading.
347 if not (self.client.stdin_channel.msg_ready() or self.client.shell_channel.msg_ready()):
342 if not (self.client.stdin_channel.msg_ready() or self.client.shell_channel.msg_ready()):
348 self.client.stdin_channel.input(raw_data)
343 self.client.stdin_channel.input(raw_data)
349
344
350 def mainloop(self, display_banner=False):
345 def mainloop(self, display_banner=False):
351 while True:
346 while True:
352 try:
347 try:
353 self.interact(display_banner=display_banner)
348 self.interact(display_banner=display_banner)
354 #self.interact_with_readline()
349 #self.interact_with_readline()
355 # XXX for testing of a readline-decoupled repl loop, call
350 # XXX for testing of a readline-decoupled repl loop, call
356 # interact_with_readline above
351 # interact_with_readline above
357 break
352 break
358 except KeyboardInterrupt:
353 except KeyboardInterrupt:
359 # this should not be necessary, but KeyboardInterrupt
354 # this should not be necessary, but KeyboardInterrupt
360 # handling seems rather unpredictable...
355 # handling seems rather unpredictable...
361 self.write("\nKeyboardInterrupt in interact()\n")
356 self.write("\nKeyboardInterrupt in interact()\n")
362
357
363 def wait_for_kernel(self, timeout=None):
358 def wait_for_kernel(self, timeout=None):
364 """method to wait for a kernel to be ready"""
359 """method to wait for a kernel to be ready"""
365 tic = time.time()
360 tic = time.time()
366 self.client.hb_channel.unpause()
361 self.client.hb_channel.unpause()
367 while True:
362 while True:
368 msg_id = self.client.kernel_info()
363 msg_id = self.client.kernel_info()
369 reply = None
364 reply = None
370 while True:
365 while True:
371 try:
366 try:
372 reply = self.client.get_shell_msg(timeout=1)
367 reply = self.client.get_shell_msg(timeout=1)
373 except Empty:
368 except Empty:
374 break
369 break
375 else:
370 else:
376 if reply['parent_header'].get('msg_id') == msg_id:
371 if reply['parent_header'].get('msg_id') == msg_id:
377 return True
372 return True
378 if timeout is not None \
373 if timeout is not None \
379 and (time.time() - tic) > timeout \
374 and (time.time() - tic) > timeout \
380 and not self.client.hb_channel.is_beating():
375 and not self.client.hb_channel.is_beating():
381 # heart failed
376 # heart failed
382 return False
377 return False
383 return True
378 return True
384
379
385 def interact(self, display_banner=None):
380 def interact(self, display_banner=None):
386 """Closely emulate the interactive Python console."""
381 """Closely emulate the interactive Python console."""
387
382
388 # batch run -> do not interact
383 # batch run -> do not interact
389 if self.exit_now:
384 if self.exit_now:
390 return
385 return
391
386
392 if display_banner is None:
387 if display_banner is None:
393 display_banner = self.display_banner
388 display_banner = self.display_banner
394
389
395 if isinstance(display_banner, basestring):
390 if isinstance(display_banner, basestring):
396 self.show_banner(display_banner)
391 self.show_banner(display_banner)
397 elif display_banner:
392 elif display_banner:
398 self.show_banner()
393 self.show_banner()
399
394
400 more = False
395 more = False
401
396
402 # run a non-empty no-op, so that we don't get a prompt until
397 # run a non-empty no-op, so that we don't get a prompt until
403 # we know the kernel is ready. This keeps the connection
398 # we know the kernel is ready. This keeps the connection
404 # message above the first prompt.
399 # message above the first prompt.
405 if not self.wait_for_kernel(self.kernel_timeout):
400 if not self.wait_for_kernel(self.kernel_timeout):
406 error("Kernel did not respond\n")
401 error("Kernel did not respond\n")
407 return
402 return
408
403
409 if self.has_readline:
404 if self.has_readline:
410 self.readline_startup_hook(self.pre_readline)
405 self.readline_startup_hook(self.pre_readline)
411 hlen_b4_cell = self.readline.get_current_history_length()
406 hlen_b4_cell = self.readline.get_current_history_length()
412 else:
407 else:
413 hlen_b4_cell = 0
408 hlen_b4_cell = 0
414 # exit_now is set by a call to %Exit or %Quit, through the
409 # exit_now is set by a call to %Exit or %Quit, through the
415 # ask_exit callback.
410 # ask_exit callback.
416
411
417 while not self.exit_now:
412 while not self.exit_now:
418 if not self.client.is_alive():
413 if not self.client.is_alive():
419 # kernel died, prompt for action or exit
414 # kernel died, prompt for action or exit
420
415
421 action = "restart" if self.manager else "wait for restart"
416 action = "restart" if self.manager else "wait for restart"
422 ans = self.ask_yes_no("kernel died, %s ([y]/n)?" % action, default='y')
417 ans = self.ask_yes_no("kernel died, %s ([y]/n)?" % action, default='y')
423 if ans:
418 if ans:
424 if self.manager:
419 if self.manager:
425 self.manager.restart_kernel(True)
420 self.manager.restart_kernel(True)
426 self.wait_for_kernel(self.kernel_timeout)
421 self.wait_for_kernel(self.kernel_timeout)
427 else:
422 else:
428 self.exit_now = True
423 self.exit_now = True
429 continue
424 continue
430 try:
425 try:
431 # protect prompt block from KeyboardInterrupt
426 # protect prompt block from KeyboardInterrupt
432 # when sitting on ctrl-C
427 # when sitting on ctrl-C
433 self.hooks.pre_prompt_hook()
428 self.hooks.pre_prompt_hook()
434 if more:
429 if more:
435 try:
430 try:
436 prompt = self.prompt_manager.render('in2')
431 prompt = self.prompt_manager.render('in2')
437 except Exception:
432 except Exception:
438 self.showtraceback()
433 self.showtraceback()
439 if self.autoindent:
434 if self.autoindent:
440 self.rl_do_indent = True
435 self.rl_do_indent = True
441
436
442 else:
437 else:
443 try:
438 try:
444 prompt = self.separate_in + self.prompt_manager.render('in')
439 prompt = self.separate_in + self.prompt_manager.render('in')
445 except Exception:
440 except Exception:
446 self.showtraceback()
441 self.showtraceback()
447
442
448 line = self.raw_input(prompt)
443 line = self.raw_input(prompt)
449 if self.exit_now:
444 if self.exit_now:
450 # quick exit on sys.std[in|out] close
445 # quick exit on sys.std[in|out] close
451 break
446 break
452 if self.autoindent:
447 if self.autoindent:
453 self.rl_do_indent = False
448 self.rl_do_indent = False
454
449
455 except KeyboardInterrupt:
450 except KeyboardInterrupt:
456 #double-guard against keyboardinterrupts during kbdint handling
451 #double-guard against keyboardinterrupts during kbdint handling
457 try:
452 try:
458 self.write('\nKeyboardInterrupt\n')
453 self.write('\nKeyboardInterrupt\n')
459 source_raw = self.input_splitter.source_raw_reset()[1]
454 source_raw = self.input_splitter.source_raw_reset()[1]
460 hlen_b4_cell = self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
455 hlen_b4_cell = self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
461 more = False
456 more = False
462 except KeyboardInterrupt:
457 except KeyboardInterrupt:
463 pass
458 pass
464 except EOFError:
459 except EOFError:
465 if self.autoindent:
460 if self.autoindent:
466 self.rl_do_indent = False
461 self.rl_do_indent = False
467 if self.has_readline:
462 if self.has_readline:
468 self.readline_startup_hook(None)
463 self.readline_startup_hook(None)
469 self.write('\n')
464 self.write('\n')
470 self.exit()
465 self.exit()
471 except bdb.BdbQuit:
466 except bdb.BdbQuit:
472 warn('The Python debugger has exited with a BdbQuit exception.\n'
467 warn('The Python debugger has exited with a BdbQuit exception.\n'
473 'Because of how pdb handles the stack, it is impossible\n'
468 'Because of how pdb handles the stack, it is impossible\n'
474 'for IPython to properly format this particular exception.\n'
469 'for IPython to properly format this particular exception.\n'
475 'IPython will resume normal operation.')
470 'IPython will resume normal operation.')
476 except:
471 except:
477 # exceptions here are VERY RARE, but they can be triggered
472 # exceptions here are VERY RARE, but they can be triggered
478 # asynchronously by signal handlers, for example.
473 # asynchronously by signal handlers, for example.
479 self.showtraceback()
474 self.showtraceback()
480 else:
475 else:
481 self.input_splitter.push(line)
476 self.input_splitter.push(line)
482 more = self.input_splitter.push_accepts_more()
477 more = self.input_splitter.push_accepts_more()
483 if (self.SyntaxTB.last_syntax_error and
478 if (self.SyntaxTB.last_syntax_error and
484 self.autoedit_syntax):
479 self.autoedit_syntax):
485 self.edit_syntax_error()
480 self.edit_syntax_error()
486 if not more:
481 if not more:
487 source_raw = self.input_splitter.source_raw_reset()[1]
482 source_raw = self.input_splitter.source_raw_reset()[1]
488 hlen_b4_cell = self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
483 hlen_b4_cell = self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
489 self.run_cell(source_raw)
484 self.run_cell(source_raw)
490
485
491
486
492 # Turn off the exit flag, so the mainloop can be restarted if desired
487 # Turn off the exit flag, so the mainloop can be restarted if desired
493 self.exit_now = False
488 self.exit_now = False
@@ -1,301 +1,294 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 An embedded IPython shell.
3 An embedded IPython shell.
4
4
5 Authors:
5 Authors:
6
6
7 * Brian Granger
7 * Brian Granger
8 * Fernando Perez
8 * Fernando Perez
9
9
10 Notes
10 Notes
11 -----
11 -----
12 """
12 """
13
13
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15 # Copyright (C) 2008-2011 The IPython Development Team
15 # Copyright (C) 2008-2011 The IPython Development Team
16 #
16 #
17 # Distributed under the terms of the BSD License. The full license is in
17 # Distributed under the terms of the BSD License. The full license is in
18 # the file COPYING, distributed as part of this software.
18 # the file COPYING, distributed as part of this software.
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20
20
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22 # Imports
22 # Imports
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24
24
25 from __future__ import with_statement
25 from __future__ import with_statement
26
26
27 import sys
27 import sys
28 import warnings
28 import warnings
29
29
30 # We need to use nested to support python 2.6, once we move to >=2.7, we can
31 # use the with keyword's new builtin support for nested managers
32 try:
33 from contextlib import nested
34 except:
35 from IPython.utils.nested_context import nested
36
37 from IPython.core import ultratb, compilerop
30 from IPython.core import ultratb, compilerop
38 from IPython.core.magic import Magics, magics_class, line_magic
31 from IPython.core.magic import Magics, magics_class, line_magic
39 from IPython.terminal.interactiveshell import TerminalInteractiveShell
32 from IPython.terminal.interactiveshell import TerminalInteractiveShell
40 from IPython.terminal.ipapp import load_default_config
33 from IPython.terminal.ipapp import load_default_config
41
34
42 from IPython.utils.traitlets import Bool, CBool, Unicode
35 from IPython.utils.traitlets import Bool, CBool, Unicode
43 from IPython.utils.io import ask_yes_no
36 from IPython.utils.io import ask_yes_no
44
37
45
38
46 #-----------------------------------------------------------------------------
39 #-----------------------------------------------------------------------------
47 # Classes and functions
40 # Classes and functions
48 #-----------------------------------------------------------------------------
41 #-----------------------------------------------------------------------------
49
42
50 # This is an additional magic that is exposed in embedded shells.
43 # This is an additional magic that is exposed in embedded shells.
51 @magics_class
44 @magics_class
52 class EmbeddedMagics(Magics):
45 class EmbeddedMagics(Magics):
53
46
54 @line_magic
47 @line_magic
55 def kill_embedded(self, parameter_s=''):
48 def kill_embedded(self, parameter_s=''):
56 """%kill_embedded : deactivate for good the current embedded IPython.
49 """%kill_embedded : deactivate for good the current embedded IPython.
57
50
58 This function (after asking for confirmation) sets an internal flag so
51 This function (after asking for confirmation) sets an internal flag so
59 that an embedded IPython will never activate again. This is useful to
52 that an embedded IPython will never activate again. This is useful to
60 permanently disable a shell that is being called inside a loop: once
53 permanently disable a shell that is being called inside a loop: once
61 you've figured out what you needed from it, you may then kill it and
54 you've figured out what you needed from it, you may then kill it and
62 the program will then continue to run without the interactive shell
55 the program will then continue to run without the interactive shell
63 interfering again.
56 interfering again.
64 """
57 """
65
58
66 kill = ask_yes_no("Are you sure you want to kill this embedded instance "
59 kill = ask_yes_no("Are you sure you want to kill this embedded instance "
67 "(y/n)? [y/N] ",'n')
60 "(y/n)? [y/N] ",'n')
68 if kill:
61 if kill:
69 self.shell.embedded_active = False
62 self.shell.embedded_active = False
70 print ("This embedded IPython will not reactivate anymore "
63 print ("This embedded IPython will not reactivate anymore "
71 "once you exit.")
64 "once you exit.")
72
65
73
66
74 class InteractiveShellEmbed(TerminalInteractiveShell):
67 class InteractiveShellEmbed(TerminalInteractiveShell):
75
68
76 dummy_mode = Bool(False)
69 dummy_mode = Bool(False)
77 exit_msg = Unicode('')
70 exit_msg = Unicode('')
78 embedded = CBool(True)
71 embedded = CBool(True)
79 embedded_active = CBool(True)
72 embedded_active = CBool(True)
80 # Like the base class display_banner is not configurable, but here it
73 # Like the base class display_banner is not configurable, but here it
81 # is True by default.
74 # is True by default.
82 display_banner = CBool(True)
75 display_banner = CBool(True)
83
76
84 def __init__(self, config=None, ipython_dir=None, user_ns=None,
77 def __init__(self, config=None, ipython_dir=None, user_ns=None,
85 user_module=None, custom_exceptions=((),None),
78 user_module=None, custom_exceptions=((),None),
86 usage=None, banner1=None, banner2=None,
79 usage=None, banner1=None, banner2=None,
87 display_banner=None, exit_msg=u'', user_global_ns=None):
80 display_banner=None, exit_msg=u'', user_global_ns=None):
88
81
89 if user_global_ns is not None:
82 if user_global_ns is not None:
90 warnings.warn("user_global_ns has been replaced by user_module. The\
83 warnings.warn("user_global_ns has been replaced by user_module. The\
91 parameter will be ignored.", DeprecationWarning)
84 parameter will be ignored.", DeprecationWarning)
92
85
93 super(InteractiveShellEmbed,self).__init__(
86 super(InteractiveShellEmbed,self).__init__(
94 config=config, ipython_dir=ipython_dir, user_ns=user_ns,
87 config=config, ipython_dir=ipython_dir, user_ns=user_ns,
95 user_module=user_module, custom_exceptions=custom_exceptions,
88 user_module=user_module, custom_exceptions=custom_exceptions,
96 usage=usage, banner1=banner1, banner2=banner2,
89 usage=usage, banner1=banner1, banner2=banner2,
97 display_banner=display_banner
90 display_banner=display_banner
98 )
91 )
99
92
100 self.exit_msg = exit_msg
93 self.exit_msg = exit_msg
101
94
102 # don't use the ipython crash handler so that user exceptions aren't
95 # don't use the ipython crash handler so that user exceptions aren't
103 # trapped
96 # trapped
104 sys.excepthook = ultratb.FormattedTB(color_scheme=self.colors,
97 sys.excepthook = ultratb.FormattedTB(color_scheme=self.colors,
105 mode=self.xmode,
98 mode=self.xmode,
106 call_pdb=self.pdb)
99 call_pdb=self.pdb)
107
100
108 def init_sys_modules(self):
101 def init_sys_modules(self):
109 pass
102 pass
110
103
111 def init_magics(self):
104 def init_magics(self):
112 super(InteractiveShellEmbed, self).init_magics()
105 super(InteractiveShellEmbed, self).init_magics()
113 self.register_magics(EmbeddedMagics)
106 self.register_magics(EmbeddedMagics)
114
107
115 def __call__(self, header='', local_ns=None, module=None, dummy=None,
108 def __call__(self, header='', local_ns=None, module=None, dummy=None,
116 stack_depth=1, global_ns=None, compile_flags=None):
109 stack_depth=1, global_ns=None, compile_flags=None):
117 """Activate the interactive interpreter.
110 """Activate the interactive interpreter.
118
111
119 __call__(self,header='',local_ns=None,module=None,dummy=None) -> Start
112 __call__(self,header='',local_ns=None,module=None,dummy=None) -> Start
120 the interpreter shell with the given local and global namespaces, and
113 the interpreter shell with the given local and global namespaces, and
121 optionally print a header string at startup.
114 optionally print a header string at startup.
122
115
123 The shell can be globally activated/deactivated using the
116 The shell can be globally activated/deactivated using the
124 dummy_mode attribute. This allows you to turn off a shell used
117 dummy_mode attribute. This allows you to turn off a shell used
125 for debugging globally.
118 for debugging globally.
126
119
127 However, *each* time you call the shell you can override the current
120 However, *each* time you call the shell you can override the current
128 state of dummy_mode with the optional keyword parameter 'dummy'. For
121 state of dummy_mode with the optional keyword parameter 'dummy'. For
129 example, if you set dummy mode on with IPShell.dummy_mode = True, you
122 example, if you set dummy mode on with IPShell.dummy_mode = True, you
130 can still have a specific call work by making it as IPShell(dummy=False).
123 can still have a specific call work by making it as IPShell(dummy=False).
131 """
124 """
132
125
133 # If the user has turned it off, go away
126 # If the user has turned it off, go away
134 if not self.embedded_active:
127 if not self.embedded_active:
135 return
128 return
136
129
137 # Normal exits from interactive mode set this flag, so the shell can't
130 # Normal exits from interactive mode set this flag, so the shell can't
138 # re-enter (it checks this variable at the start of interactive mode).
131 # re-enter (it checks this variable at the start of interactive mode).
139 self.exit_now = False
132 self.exit_now = False
140
133
141 # Allow the dummy parameter to override the global __dummy_mode
134 # Allow the dummy parameter to override the global __dummy_mode
142 if dummy or (dummy != 0 and self.dummy_mode):
135 if dummy or (dummy != 0 and self.dummy_mode):
143 return
136 return
144
137
145 if self.has_readline:
138 if self.has_readline:
146 self.set_readline_completer()
139 self.set_readline_completer()
147
140
148 # self.banner is auto computed
141 # self.banner is auto computed
149 if header:
142 if header:
150 self.old_banner2 = self.banner2
143 self.old_banner2 = self.banner2
151 self.banner2 = self.banner2 + '\n' + header + '\n'
144 self.banner2 = self.banner2 + '\n' + header + '\n'
152 else:
145 else:
153 self.old_banner2 = ''
146 self.old_banner2 = ''
154
147
155 # Call the embedding code with a stack depth of 1 so it can skip over
148 # Call the embedding code with a stack depth of 1 so it can skip over
156 # our call and get the original caller's namespaces.
149 # our call and get the original caller's namespaces.
157 self.mainloop(local_ns, module, stack_depth=stack_depth,
150 self.mainloop(local_ns, module, stack_depth=stack_depth,
158 global_ns=global_ns, compile_flags=compile_flags)
151 global_ns=global_ns, compile_flags=compile_flags)
159
152
160 self.banner2 = self.old_banner2
153 self.banner2 = self.old_banner2
161
154
162 if self.exit_msg is not None:
155 if self.exit_msg is not None:
163 print self.exit_msg
156 print self.exit_msg
164
157
165 def mainloop(self, local_ns=None, module=None, stack_depth=0,
158 def mainloop(self, local_ns=None, module=None, stack_depth=0,
166 display_banner=None, global_ns=None, compile_flags=None):
159 display_banner=None, global_ns=None, compile_flags=None):
167 """Embeds IPython into a running python program.
160 """Embeds IPython into a running python program.
168
161
169 Input:
162 Input:
170
163
171 - header: An optional header message can be specified.
164 - header: An optional header message can be specified.
172
165
173 - local_ns, module: working local namespace (a dict) and module (a
166 - local_ns, module: working local namespace (a dict) and module (a
174 module or similar object). If given as None, they are automatically
167 module or similar object). If given as None, they are automatically
175 taken from the scope where the shell was called, so that
168 taken from the scope where the shell was called, so that
176 program variables become visible.
169 program variables become visible.
177
170
178 - stack_depth: specifies how many levels in the stack to go to
171 - stack_depth: specifies how many levels in the stack to go to
179 looking for namespaces (when local_ns or module is None). This
172 looking for namespaces (when local_ns or module is None). This
180 allows an intermediate caller to make sure that this function gets
173 allows an intermediate caller to make sure that this function gets
181 the namespace from the intended level in the stack. By default (0)
174 the namespace from the intended level in the stack. By default (0)
182 it will get its locals and globals from the immediate caller.
175 it will get its locals and globals from the immediate caller.
183
176
184 - compile_flags: A bit field identifying the __future__ features
177 - compile_flags: A bit field identifying the __future__ features
185 that are enabled, as passed to the builtin `compile` function. If
178 that are enabled, as passed to the builtin `compile` function. If
186 given as None, they are automatically taken from the scope where the
179 given as None, they are automatically taken from the scope where the
187 shell was called.
180 shell was called.
188
181
189 Warning: it's possible to use this in a program which is being run by
182 Warning: it's possible to use this in a program which is being run by
190 IPython itself (via %run), but some funny things will happen (a few
183 IPython itself (via %run), but some funny things will happen (a few
191 globals get overwritten). In the future this will be cleaned up, as
184 globals get overwritten). In the future this will be cleaned up, as
192 there is no fundamental reason why it can't work perfectly."""
185 there is no fundamental reason why it can't work perfectly."""
193
186
194 if (global_ns is not None) and (module is None):
187 if (global_ns is not None) and (module is None):
195 class DummyMod(object):
188 class DummyMod(object):
196 """A dummy module object for embedded IPython."""
189 """A dummy module object for embedded IPython."""
197 pass
190 pass
198 warnings.warn("global_ns is deprecated, use module instead.", DeprecationWarning)
191 warnings.warn("global_ns is deprecated, use module instead.", DeprecationWarning)
199 module = DummyMod()
192 module = DummyMod()
200 module.__dict__ = global_ns
193 module.__dict__ = global_ns
201
194
202 # Get locals and globals from caller
195 # Get locals and globals from caller
203 if ((local_ns is None or module is None or compile_flags is None)
196 if ((local_ns is None or module is None or compile_flags is None)
204 and self.default_user_namespaces):
197 and self.default_user_namespaces):
205 call_frame = sys._getframe(stack_depth).f_back
198 call_frame = sys._getframe(stack_depth).f_back
206
199
207 if local_ns is None:
200 if local_ns is None:
208 local_ns = call_frame.f_locals
201 local_ns = call_frame.f_locals
209 if module is None:
202 if module is None:
210 global_ns = call_frame.f_globals
203 global_ns = call_frame.f_globals
211 module = sys.modules[global_ns['__name__']]
204 module = sys.modules[global_ns['__name__']]
212 if compile_flags is None:
205 if compile_flags is None:
213 compile_flags = (call_frame.f_code.co_flags &
206 compile_flags = (call_frame.f_code.co_flags &
214 compilerop.PyCF_MASK)
207 compilerop.PyCF_MASK)
215
208
216 # Save original namespace and module so we can restore them after
209 # Save original namespace and module so we can restore them after
217 # embedding; otherwise the shell doesn't shut down correctly.
210 # embedding; otherwise the shell doesn't shut down correctly.
218 orig_user_module = self.user_module
211 orig_user_module = self.user_module
219 orig_user_ns = self.user_ns
212 orig_user_ns = self.user_ns
220 orig_compile_flags = self.compile.flags
213 orig_compile_flags = self.compile.flags
221
214
222 # Update namespaces and fire up interpreter
215 # Update namespaces and fire up interpreter
223
216
224 # The global one is easy, we can just throw it in
217 # The global one is easy, we can just throw it in
225 if module is not None:
218 if module is not None:
226 self.user_module = module
219 self.user_module = module
227
220
228 # But the user/local one is tricky: ipython needs it to store internal
221 # But the user/local one is tricky: ipython needs it to store internal
229 # data, but we also need the locals. We'll throw our hidden variables
222 # data, but we also need the locals. We'll throw our hidden variables
230 # like _ih and get_ipython() into the local namespace, but delete them
223 # like _ih and get_ipython() into the local namespace, but delete them
231 # later.
224 # later.
232 if local_ns is not None:
225 if local_ns is not None:
233 self.user_ns = local_ns
226 self.user_ns = local_ns
234 self.init_user_ns()
227 self.init_user_ns()
235
228
236 # Compiler flags
229 # Compiler flags
237 if compile_flags is not None:
230 if compile_flags is not None:
238 self.compile.flags = compile_flags
231 self.compile.flags = compile_flags
239
232
240 # Patch for global embedding to make sure that things don't overwrite
233 # Patch for global embedding to make sure that things don't overwrite
241 # user globals accidentally. Thanks to Richard <rxe@renre-europe.com>
234 # user globals accidentally. Thanks to Richard <rxe@renre-europe.com>
242 # FIXME. Test this a bit more carefully (the if.. is new)
235 # FIXME. Test this a bit more carefully (the if.. is new)
243 # N.B. This can't now ever be called. Not sure what it was for.
236 # N.B. This can't now ever be called. Not sure what it was for.
244 # And now, since it wasn't called in the previous version, I'm
237 # And now, since it wasn't called in the previous version, I'm
245 # commenting out these lines so they can't be called with my new changes
238 # commenting out these lines so they can't be called with my new changes
246 # --TK, 2011-12-10
239 # --TK, 2011-12-10
247 #if local_ns is None and module is None:
240 #if local_ns is None and module is None:
248 # self.user_global_ns.update(__main__.__dict__)
241 # self.user_global_ns.update(__main__.__dict__)
249
242
250 # make sure the tab-completer has the correct frame information, so it
243 # make sure the tab-completer has the correct frame information, so it
251 # actually completes using the frame's locals/globals
244 # actually completes using the frame's locals/globals
252 self.set_completer_frame()
245 self.set_completer_frame()
253
246
254 with nested(self.builtin_trap, self.display_trap):
247 with self.builtin_trap, self.display_trap:
255 self.interact(display_banner=display_banner)
248 self.interact(display_banner=display_banner)
256
249
257 # now, purge out the local namespace of IPython's hidden variables.
250 # now, purge out the local namespace of IPython's hidden variables.
258 if local_ns is not None:
251 if local_ns is not None:
259 for name in self.user_ns_hidden:
252 for name in self.user_ns_hidden:
260 local_ns.pop(name, None)
253 local_ns.pop(name, None)
261
254
262 # Restore original namespace so shell can shut down when we exit.
255 # Restore original namespace so shell can shut down when we exit.
263 self.user_module = orig_user_module
256 self.user_module = orig_user_module
264 self.user_ns = orig_user_ns
257 self.user_ns = orig_user_ns
265 self.compile.flags = orig_compile_flags
258 self.compile.flags = orig_compile_flags
266
259
267
260
268 def embed(**kwargs):
261 def embed(**kwargs):
269 """Call this to embed IPython at the current point in your program.
262 """Call this to embed IPython at the current point in your program.
270
263
271 The first invocation of this will create an :class:`InteractiveShellEmbed`
264 The first invocation of this will create an :class:`InteractiveShellEmbed`
272 instance and then call it. Consecutive calls just call the already
265 instance and then call it. Consecutive calls just call the already
273 created instance.
266 created instance.
274
267
275 If you don't want the kernel to initialize the namespace
268 If you don't want the kernel to initialize the namespace
276 from the scope of the surrounding function,
269 from the scope of the surrounding function,
277 and/or you want to load full IPython configuration,
270 and/or you want to load full IPython configuration,
278 you probably want `IPython.start_ipython()` instead.
271 you probably want `IPython.start_ipython()` instead.
279
272
280 Here is a simple example::
273 Here is a simple example::
281
274
282 from IPython import embed
275 from IPython import embed
283 a = 10
276 a = 10
284 b = 20
277 b = 20
285 embed('First time')
278 embed('First time')
286 c = 30
279 c = 30
287 d = 40
280 d = 40
288 embed
281 embed
289
282
290 Full customization can be done by passing a :class:`Config` in as the
283 Full customization can be done by passing a :class:`Config` in as the
291 config argument.
284 config argument.
292 """
285 """
293 config = kwargs.get('config')
286 config = kwargs.get('config')
294 header = kwargs.pop('header', u'')
287 header = kwargs.pop('header', u'')
295 compile_flags = kwargs.pop('compile_flags', None)
288 compile_flags = kwargs.pop('compile_flags', None)
296 if config is None:
289 if config is None:
297 config = load_default_config()
290 config = load_default_config()
298 config.InteractiveShellEmbed = config.TerminalInteractiveShell
291 config.InteractiveShellEmbed = config.TerminalInteractiveShell
299 kwargs['config'] = config
292 kwargs['config'] = config
300 shell = InteractiveShellEmbed.instance(**kwargs)
293 shell = InteractiveShellEmbed.instance(**kwargs)
301 shell(header=header, stack_depth=2, compile_flags=compile_flags)
294 shell(header=header, stack_depth=2, compile_flags=compile_flags)
@@ -1,697 +1,690 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Subclass of InteractiveShell for terminal based frontends."""
2 """Subclass of InteractiveShell for terminal based frontends."""
3
3
4 #-----------------------------------------------------------------------------
4 #-----------------------------------------------------------------------------
5 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de>
5 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de>
6 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
6 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
7 # Copyright (C) 2008-2011 The IPython Development Team
7 # Copyright (C) 2008-2011 The IPython Development Team
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 from __future__ import print_function
16 from __future__ import print_function
17
17
18 import bdb
18 import bdb
19 import os
19 import os
20 import sys
20 import sys
21
21
22 # We need to use nested to support python 2.6, once we move to >=2.7, we can
23 # use the with keyword's new builtin support for nested managers
24 try:
25 from contextlib import nested
26 except:
27 from IPython.utils.nested_context import nested
28
29 from IPython.core.error import TryNext, UsageError
22 from IPython.core.error import TryNext, UsageError
30 from IPython.core.usage import interactive_usage, default_banner
23 from IPython.core.usage import interactive_usage, default_banner
31 from IPython.core.inputsplitter import IPythonInputSplitter
24 from IPython.core.inputsplitter import IPythonInputSplitter
32 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
25 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
33 from IPython.core.magic import Magics, magics_class, line_magic
26 from IPython.core.magic import Magics, magics_class, line_magic
34 from IPython.testing.skipdoctest import skip_doctest
27 from IPython.testing.skipdoctest import skip_doctest
35 from IPython.utils.encoding import get_stream_enc
28 from IPython.utils.encoding import get_stream_enc
36 from IPython.utils import py3compat
29 from IPython.utils import py3compat
37 from IPython.utils.terminal import toggle_set_term_title, set_term_title
30 from IPython.utils.terminal import toggle_set_term_title, set_term_title
38 from IPython.utils.process import abbrev_cwd
31 from IPython.utils.process import abbrev_cwd
39 from IPython.utils.warn import warn, error
32 from IPython.utils.warn import warn, error
40 from IPython.utils.text import num_ini_spaces, SList, strip_email_quotes
33 from IPython.utils.text import num_ini_spaces, SList, strip_email_quotes
41 from IPython.utils.traitlets import Integer, CBool, Unicode
34 from IPython.utils.traitlets import Integer, CBool, Unicode
42
35
43 #-----------------------------------------------------------------------------
36 #-----------------------------------------------------------------------------
44 # Utilities
37 # Utilities
45 #-----------------------------------------------------------------------------
38 #-----------------------------------------------------------------------------
46
39
47 def get_default_editor():
40 def get_default_editor():
48 try:
41 try:
49 ed = os.environ['EDITOR']
42 ed = os.environ['EDITOR']
50 except KeyError:
43 except KeyError:
51 if os.name == 'posix':
44 if os.name == 'posix':
52 ed = 'vi' # the only one guaranteed to be there!
45 ed = 'vi' # the only one guaranteed to be there!
53 else:
46 else:
54 ed = 'notepad' # same in Windows!
47 ed = 'notepad' # same in Windows!
55 return ed
48 return ed
56
49
57
50
58 def get_pasted_lines(sentinel, l_input=py3compat.input):
51 def get_pasted_lines(sentinel, l_input=py3compat.input):
59 """ Yield pasted lines until the user enters the given sentinel value.
52 """ Yield pasted lines until the user enters the given sentinel value.
60 """
53 """
61 print("Pasting code; enter '%s' alone on the line to stop or use Ctrl-D." \
54 print("Pasting code; enter '%s' alone on the line to stop or use Ctrl-D." \
62 % sentinel)
55 % sentinel)
63 while True:
56 while True:
64 try:
57 try:
65 l = l_input(':')
58 l = l_input(':')
66 if l == sentinel:
59 if l == sentinel:
67 return
60 return
68 else:
61 else:
69 yield l
62 yield l
70 except EOFError:
63 except EOFError:
71 print('<EOF>')
64 print('<EOF>')
72 return
65 return
73
66
74
67
75 #------------------------------------------------------------------------
68 #------------------------------------------------------------------------
76 # Terminal-specific magics
69 # Terminal-specific magics
77 #------------------------------------------------------------------------
70 #------------------------------------------------------------------------
78
71
79 @magics_class
72 @magics_class
80 class TerminalMagics(Magics):
73 class TerminalMagics(Magics):
81 def __init__(self, shell):
74 def __init__(self, shell):
82 super(TerminalMagics, self).__init__(shell)
75 super(TerminalMagics, self).__init__(shell)
83 self.input_splitter = IPythonInputSplitter()
76 self.input_splitter = IPythonInputSplitter()
84
77
85 def store_or_execute(self, block, name):
78 def store_or_execute(self, block, name):
86 """ Execute a block, or store it in a variable, per the user's request.
79 """ Execute a block, or store it in a variable, per the user's request.
87 """
80 """
88 if name:
81 if name:
89 # If storing it for further editing
82 # If storing it for further editing
90 self.shell.user_ns[name] = SList(block.splitlines())
83 self.shell.user_ns[name] = SList(block.splitlines())
91 print("Block assigned to '%s'" % name)
84 print("Block assigned to '%s'" % name)
92 else:
85 else:
93 b = self.preclean_input(block)
86 b = self.preclean_input(block)
94 self.shell.user_ns['pasted_block'] = b
87 self.shell.user_ns['pasted_block'] = b
95 self.shell.using_paste_magics = True
88 self.shell.using_paste_magics = True
96 try:
89 try:
97 self.shell.run_cell(b)
90 self.shell.run_cell(b)
98 finally:
91 finally:
99 self.shell.using_paste_magics = False
92 self.shell.using_paste_magics = False
100
93
101 def preclean_input(self, block):
94 def preclean_input(self, block):
102 lines = block.splitlines()
95 lines = block.splitlines()
103 while lines and not lines[0].strip():
96 while lines and not lines[0].strip():
104 lines = lines[1:]
97 lines = lines[1:]
105 return strip_email_quotes('\n'.join(lines))
98 return strip_email_quotes('\n'.join(lines))
106
99
107 def rerun_pasted(self, name='pasted_block'):
100 def rerun_pasted(self, name='pasted_block'):
108 """ Rerun a previously pasted command.
101 """ Rerun a previously pasted command.
109 """
102 """
110 b = self.shell.user_ns.get(name)
103 b = self.shell.user_ns.get(name)
111
104
112 # Sanity checks
105 # Sanity checks
113 if b is None:
106 if b is None:
114 raise UsageError('No previous pasted block available')
107 raise UsageError('No previous pasted block available')
115 if not isinstance(b, basestring):
108 if not isinstance(b, basestring):
116 raise UsageError(
109 raise UsageError(
117 "Variable 'pasted_block' is not a string, can't execute")
110 "Variable 'pasted_block' is not a string, can't execute")
118
111
119 print("Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b)))
112 print("Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b)))
120 self.shell.run_cell(b)
113 self.shell.run_cell(b)
121
114
122 @line_magic
115 @line_magic
123 def autoindent(self, parameter_s = ''):
116 def autoindent(self, parameter_s = ''):
124 """Toggle autoindent on/off (if available)."""
117 """Toggle autoindent on/off (if available)."""
125
118
126 self.shell.set_autoindent()
119 self.shell.set_autoindent()
127 print("Automatic indentation is:",['OFF','ON'][self.shell.autoindent])
120 print("Automatic indentation is:",['OFF','ON'][self.shell.autoindent])
128
121
129 @skip_doctest
122 @skip_doctest
130 @line_magic
123 @line_magic
131 def cpaste(self, parameter_s=''):
124 def cpaste(self, parameter_s=''):
132 """Paste & execute a pre-formatted code block from clipboard.
125 """Paste & execute a pre-formatted code block from clipboard.
133
126
134 You must terminate the block with '--' (two minus-signs) or Ctrl-D
127 You must terminate the block with '--' (two minus-signs) or Ctrl-D
135 alone on the line. You can also provide your own sentinel with '%paste
128 alone on the line. You can also provide your own sentinel with '%paste
136 -s %%' ('%%' is the new sentinel for this operation)
129 -s %%' ('%%' is the new sentinel for this operation)
137
130
138 The block is dedented prior to execution to enable execution of method
131 The block is dedented prior to execution to enable execution of method
139 definitions. '>' and '+' characters at the beginning of a line are
132 definitions. '>' and '+' characters at the beginning of a line are
140 ignored, to allow pasting directly from e-mails, diff files and
133 ignored, to allow pasting directly from e-mails, diff files and
141 doctests (the '...' continuation prompt is also stripped). The
134 doctests (the '...' continuation prompt is also stripped). The
142 executed block is also assigned to variable named 'pasted_block' for
135 executed block is also assigned to variable named 'pasted_block' for
143 later editing with '%edit pasted_block'.
136 later editing with '%edit pasted_block'.
144
137
145 You can also pass a variable name as an argument, e.g. '%cpaste foo'.
138 You can also pass a variable name as an argument, e.g. '%cpaste foo'.
146 This assigns the pasted block to variable 'foo' as string, without
139 This assigns the pasted block to variable 'foo' as string, without
147 dedenting or executing it (preceding >>> and + is still stripped)
140 dedenting or executing it (preceding >>> and + is still stripped)
148
141
149 '%cpaste -r' re-executes the block previously entered by cpaste.
142 '%cpaste -r' re-executes the block previously entered by cpaste.
150
143
151 Do not be alarmed by garbled output on Windows (it's a readline bug).
144 Do not be alarmed by garbled output on Windows (it's a readline bug).
152 Just press enter and type -- (and press enter again) and the block
145 Just press enter and type -- (and press enter again) and the block
153 will be what was just pasted.
146 will be what was just pasted.
154
147
155 IPython statements (magics, shell escapes) are not supported (yet).
148 IPython statements (magics, shell escapes) are not supported (yet).
156
149
157 See also
150 See also
158 --------
151 --------
159 paste: automatically pull code from clipboard.
152 paste: automatically pull code from clipboard.
160
153
161 Examples
154 Examples
162 --------
155 --------
163 ::
156 ::
164
157
165 In [8]: %cpaste
158 In [8]: %cpaste
166 Pasting code; enter '--' alone on the line to stop.
159 Pasting code; enter '--' alone on the line to stop.
167 :>>> a = ["world!", "Hello"]
160 :>>> a = ["world!", "Hello"]
168 :>>> print " ".join(sorted(a))
161 :>>> print " ".join(sorted(a))
169 :--
162 :--
170 Hello world!
163 Hello world!
171 """
164 """
172 opts, name = self.parse_options(parameter_s, 'rs:', mode='string')
165 opts, name = self.parse_options(parameter_s, 'rs:', mode='string')
173 if 'r' in opts:
166 if 'r' in opts:
174 self.rerun_pasted()
167 self.rerun_pasted()
175 return
168 return
176
169
177 sentinel = opts.get('s', '--')
170 sentinel = opts.get('s', '--')
178 block = '\n'.join(get_pasted_lines(sentinel))
171 block = '\n'.join(get_pasted_lines(sentinel))
179 self.store_or_execute(block, name)
172 self.store_or_execute(block, name)
180
173
181 @line_magic
174 @line_magic
182 def paste(self, parameter_s=''):
175 def paste(self, parameter_s=''):
183 """Paste & execute a pre-formatted code block from clipboard.
176 """Paste & execute a pre-formatted code block from clipboard.
184
177
185 The text is pulled directly from the clipboard without user
178 The text is pulled directly from the clipboard without user
186 intervention and printed back on the screen before execution (unless
179 intervention and printed back on the screen before execution (unless
187 the -q flag is given to force quiet mode).
180 the -q flag is given to force quiet mode).
188
181
189 The block is dedented prior to execution to enable execution of method
182 The block is dedented prior to execution to enable execution of method
190 definitions. '>' and '+' characters at the beginning of a line are
183 definitions. '>' and '+' characters at the beginning of a line are
191 ignored, to allow pasting directly from e-mails, diff files and
184 ignored, to allow pasting directly from e-mails, diff files and
192 doctests (the '...' continuation prompt is also stripped). The
185 doctests (the '...' continuation prompt is also stripped). The
193 executed block is also assigned to variable named 'pasted_block' for
186 executed block is also assigned to variable named 'pasted_block' for
194 later editing with '%edit pasted_block'.
187 later editing with '%edit pasted_block'.
195
188
196 You can also pass a variable name as an argument, e.g. '%paste foo'.
189 You can also pass a variable name as an argument, e.g. '%paste foo'.
197 This assigns the pasted block to variable 'foo' as string, without
190 This assigns the pasted block to variable 'foo' as string, without
198 executing it (preceding >>> and + is still stripped).
191 executing it (preceding >>> and + is still stripped).
199
192
200 Options
193 Options
201 -------
194 -------
202
195
203 -r: re-executes the block previously entered by cpaste.
196 -r: re-executes the block previously entered by cpaste.
204
197
205 -q: quiet mode: do not echo the pasted text back to the terminal.
198 -q: quiet mode: do not echo the pasted text back to the terminal.
206
199
207 IPython statements (magics, shell escapes) are not supported (yet).
200 IPython statements (magics, shell escapes) are not supported (yet).
208
201
209 See also
202 See also
210 --------
203 --------
211 cpaste: manually paste code into terminal until you mark its end.
204 cpaste: manually paste code into terminal until you mark its end.
212 """
205 """
213 opts, name = self.parse_options(parameter_s, 'rq', mode='string')
206 opts, name = self.parse_options(parameter_s, 'rq', mode='string')
214 if 'r' in opts:
207 if 'r' in opts:
215 self.rerun_pasted()
208 self.rerun_pasted()
216 return
209 return
217 try:
210 try:
218 block = self.shell.hooks.clipboard_get()
211 block = self.shell.hooks.clipboard_get()
219 except TryNext as clipboard_exc:
212 except TryNext as clipboard_exc:
220 message = getattr(clipboard_exc, 'args')
213 message = getattr(clipboard_exc, 'args')
221 if message:
214 if message:
222 error(message[0])
215 error(message[0])
223 else:
216 else:
224 error('Could not get text from the clipboard.')
217 error('Could not get text from the clipboard.')
225 return
218 return
226
219
227 # By default, echo back to terminal unless quiet mode is requested
220 # By default, echo back to terminal unless quiet mode is requested
228 if 'q' not in opts:
221 if 'q' not in opts:
229 write = self.shell.write
222 write = self.shell.write
230 write(self.shell.pycolorize(block))
223 write(self.shell.pycolorize(block))
231 if not block.endswith('\n'):
224 if not block.endswith('\n'):
232 write('\n')
225 write('\n')
233 write("## -- End pasted text --\n")
226 write("## -- End pasted text --\n")
234
227
235 self.store_or_execute(block, name)
228 self.store_or_execute(block, name)
236
229
237 # Class-level: add a '%cls' magic only on Windows
230 # Class-level: add a '%cls' magic only on Windows
238 if sys.platform == 'win32':
231 if sys.platform == 'win32':
239 @line_magic
232 @line_magic
240 def cls(self, s):
233 def cls(self, s):
241 """Clear screen.
234 """Clear screen.
242 """
235 """
243 os.system("cls")
236 os.system("cls")
244
237
245 #-----------------------------------------------------------------------------
238 #-----------------------------------------------------------------------------
246 # Main class
239 # Main class
247 #-----------------------------------------------------------------------------
240 #-----------------------------------------------------------------------------
248
241
249 class TerminalInteractiveShell(InteractiveShell):
242 class TerminalInteractiveShell(InteractiveShell):
250
243
251 autoedit_syntax = CBool(False, config=True,
244 autoedit_syntax = CBool(False, config=True,
252 help="auto editing of files with syntax errors.")
245 help="auto editing of files with syntax errors.")
253 banner = Unicode('')
246 banner = Unicode('')
254 banner1 = Unicode(default_banner, config=True,
247 banner1 = Unicode(default_banner, config=True,
255 help="""The part of the banner to be printed before the profile"""
248 help="""The part of the banner to be printed before the profile"""
256 )
249 )
257 banner2 = Unicode('', config=True,
250 banner2 = Unicode('', config=True,
258 help="""The part of the banner to be printed after the profile"""
251 help="""The part of the banner to be printed after the profile"""
259 )
252 )
260 confirm_exit = CBool(True, config=True,
253 confirm_exit = CBool(True, config=True,
261 help="""
254 help="""
262 Set to confirm when you try to exit IPython with an EOF (Control-D
255 Set to confirm when you try to exit IPython with an EOF (Control-D
263 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
256 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
264 you can force a direct exit without any confirmation.""",
257 you can force a direct exit without any confirmation.""",
265 )
258 )
266 # This display_banner only controls whether or not self.show_banner()
259 # This display_banner only controls whether or not self.show_banner()
267 # is called when mainloop/interact are called. The default is False
260 # is called when mainloop/interact are called. The default is False
268 # because for the terminal based application, the banner behavior
261 # because for the terminal based application, the banner behavior
269 # is controlled by Global.display_banner, which IPythonApp looks at
262 # is controlled by Global.display_banner, which IPythonApp looks at
270 # to determine if *it* should call show_banner() by hand or not.
263 # to determine if *it* should call show_banner() by hand or not.
271 display_banner = CBool(False) # This isn't configurable!
264 display_banner = CBool(False) # This isn't configurable!
272 embedded = CBool(False)
265 embedded = CBool(False)
273 embedded_active = CBool(False)
266 embedded_active = CBool(False)
274 editor = Unicode(get_default_editor(), config=True,
267 editor = Unicode(get_default_editor(), config=True,
275 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
268 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
276 )
269 )
277 pager = Unicode('less', config=True,
270 pager = Unicode('less', config=True,
278 help="The shell program to be used for paging.")
271 help="The shell program to be used for paging.")
279
272
280 screen_length = Integer(0, config=True,
273 screen_length = Integer(0, config=True,
281 help=
274 help=
282 """Number of lines of your screen, used to control printing of very
275 """Number of lines of your screen, used to control printing of very
283 long strings. Strings longer than this number of lines will be sent
276 long strings. Strings longer than this number of lines will be sent
284 through a pager instead of directly printed. The default value for
277 through a pager instead of directly printed. The default value for
285 this is 0, which means IPython will auto-detect your screen size every
278 this is 0, which means IPython will auto-detect your screen size every
286 time it needs to print certain potentially long strings (this doesn't
279 time it needs to print certain potentially long strings (this doesn't
287 change the behavior of the 'print' keyword, it's only triggered
280 change the behavior of the 'print' keyword, it's only triggered
288 internally). If for some reason this isn't working well (it needs
281 internally). If for some reason this isn't working well (it needs
289 curses support), specify it yourself. Otherwise don't change the
282 curses support), specify it yourself. Otherwise don't change the
290 default.""",
283 default.""",
291 )
284 )
292 term_title = CBool(False, config=True,
285 term_title = CBool(False, config=True,
293 help="Enable auto setting the terminal title."
286 help="Enable auto setting the terminal title."
294 )
287 )
295
288
296 # This `using_paste_magics` is used to detect whether the code is being
289 # This `using_paste_magics` is used to detect whether the code is being
297 # executed via paste magics functions
290 # executed via paste magics functions
298 using_paste_magics = CBool(False)
291 using_paste_magics = CBool(False)
299
292
300 # In the terminal, GUI control is done via PyOS_InputHook
293 # In the terminal, GUI control is done via PyOS_InputHook
301 @staticmethod
294 @staticmethod
302 def enable_gui(gui=None, app=None):
295 def enable_gui(gui=None, app=None):
303 """Switch amongst GUI input hooks by name.
296 """Switch amongst GUI input hooks by name.
304 """
297 """
305 # Deferred import
298 # Deferred import
306 from IPython.lib.inputhook import enable_gui as real_enable_gui
299 from IPython.lib.inputhook import enable_gui as real_enable_gui
307 try:
300 try:
308 return real_enable_gui(gui, app)
301 return real_enable_gui(gui, app)
309 except ValueError as e:
302 except ValueError as e:
310 raise UsageError("%s" % e)
303 raise UsageError("%s" % e)
311
304
312 def __init__(self, config=None, ipython_dir=None, profile_dir=None,
305 def __init__(self, config=None, ipython_dir=None, profile_dir=None,
313 user_ns=None, user_module=None, custom_exceptions=((),None),
306 user_ns=None, user_module=None, custom_exceptions=((),None),
314 usage=None, banner1=None, banner2=None, display_banner=None,
307 usage=None, banner1=None, banner2=None, display_banner=None,
315 **kwargs):
308 **kwargs):
316
309
317 super(TerminalInteractiveShell, self).__init__(
310 super(TerminalInteractiveShell, self).__init__(
318 config=config, ipython_dir=ipython_dir, profile_dir=profile_dir, user_ns=user_ns,
311 config=config, ipython_dir=ipython_dir, profile_dir=profile_dir, user_ns=user_ns,
319 user_module=user_module, custom_exceptions=custom_exceptions,
312 user_module=user_module, custom_exceptions=custom_exceptions,
320 **kwargs
313 **kwargs
321 )
314 )
322 # use os.system instead of utils.process.system by default,
315 # use os.system instead of utils.process.system by default,
323 # because piped system doesn't make sense in the Terminal:
316 # because piped system doesn't make sense in the Terminal:
324 self.system = self.system_raw
317 self.system = self.system_raw
325
318
326 self.init_term_title()
319 self.init_term_title()
327 self.init_usage(usage)
320 self.init_usage(usage)
328 self.init_banner(banner1, banner2, display_banner)
321 self.init_banner(banner1, banner2, display_banner)
329
322
330 #-------------------------------------------------------------------------
323 #-------------------------------------------------------------------------
331 # Overrides of init stages
324 # Overrides of init stages
332 #-------------------------------------------------------------------------
325 #-------------------------------------------------------------------------
333
326
334 def init_display_formatter(self):
327 def init_display_formatter(self):
335 super(TerminalInteractiveShell, self).init_display_formatter()
328 super(TerminalInteractiveShell, self).init_display_formatter()
336 # terminal only supports plaintext
329 # terminal only supports plaintext
337 self.display_formatter.active_types = ['text/plain']
330 self.display_formatter.active_types = ['text/plain']
338
331
339 #-------------------------------------------------------------------------
332 #-------------------------------------------------------------------------
340 # Things related to the terminal
333 # Things related to the terminal
341 #-------------------------------------------------------------------------
334 #-------------------------------------------------------------------------
342
335
343 @property
336 @property
344 def usable_screen_length(self):
337 def usable_screen_length(self):
345 if self.screen_length == 0:
338 if self.screen_length == 0:
346 return 0
339 return 0
347 else:
340 else:
348 num_lines_bot = self.separate_in.count('\n')+1
341 num_lines_bot = self.separate_in.count('\n')+1
349 return self.screen_length - num_lines_bot
342 return self.screen_length - num_lines_bot
350
343
351 def init_term_title(self):
344 def init_term_title(self):
352 # Enable or disable the terminal title.
345 # Enable or disable the terminal title.
353 if self.term_title:
346 if self.term_title:
354 toggle_set_term_title(True)
347 toggle_set_term_title(True)
355 set_term_title('IPython: ' + abbrev_cwd())
348 set_term_title('IPython: ' + abbrev_cwd())
356 else:
349 else:
357 toggle_set_term_title(False)
350 toggle_set_term_title(False)
358
351
359 #-------------------------------------------------------------------------
352 #-------------------------------------------------------------------------
360 # Things related to aliases
353 # Things related to aliases
361 #-------------------------------------------------------------------------
354 #-------------------------------------------------------------------------
362
355
363 def init_alias(self):
356 def init_alias(self):
364 # The parent class defines aliases that can be safely used with any
357 # The parent class defines aliases that can be safely used with any
365 # frontend.
358 # frontend.
366 super(TerminalInteractiveShell, self).init_alias()
359 super(TerminalInteractiveShell, self).init_alias()
367
360
368 # Now define aliases that only make sense on the terminal, because they
361 # Now define aliases that only make sense on the terminal, because they
369 # need direct access to the console in a way that we can't emulate in
362 # need direct access to the console in a way that we can't emulate in
370 # GUI or web frontend
363 # GUI or web frontend
371 if os.name == 'posix':
364 if os.name == 'posix':
372 aliases = [('clear', 'clear'), ('more', 'more'), ('less', 'less'),
365 aliases = [('clear', 'clear'), ('more', 'more'), ('less', 'less'),
373 ('man', 'man')]
366 ('man', 'man')]
374 elif os.name == 'nt':
367 elif os.name == 'nt':
375 aliases = [('cls', 'cls')]
368 aliases = [('cls', 'cls')]
376
369
377
370
378 for name, cmd in aliases:
371 for name, cmd in aliases:
379 self.alias_manager.define_alias(name, cmd)
372 self.alias_manager.define_alias(name, cmd)
380
373
381 #-------------------------------------------------------------------------
374 #-------------------------------------------------------------------------
382 # Things related to the banner and usage
375 # Things related to the banner and usage
383 #-------------------------------------------------------------------------
376 #-------------------------------------------------------------------------
384
377
385 def _banner1_changed(self):
378 def _banner1_changed(self):
386 self.compute_banner()
379 self.compute_banner()
387
380
388 def _banner2_changed(self):
381 def _banner2_changed(self):
389 self.compute_banner()
382 self.compute_banner()
390
383
391 def _term_title_changed(self, name, new_value):
384 def _term_title_changed(self, name, new_value):
392 self.init_term_title()
385 self.init_term_title()
393
386
394 def init_banner(self, banner1, banner2, display_banner):
387 def init_banner(self, banner1, banner2, display_banner):
395 if banner1 is not None:
388 if banner1 is not None:
396 self.banner1 = banner1
389 self.banner1 = banner1
397 if banner2 is not None:
390 if banner2 is not None:
398 self.banner2 = banner2
391 self.banner2 = banner2
399 if display_banner is not None:
392 if display_banner is not None:
400 self.display_banner = display_banner
393 self.display_banner = display_banner
401 self.compute_banner()
394 self.compute_banner()
402
395
403 def show_banner(self, banner=None):
396 def show_banner(self, banner=None):
404 if banner is None:
397 if banner is None:
405 banner = self.banner
398 banner = self.banner
406 self.write(banner)
399 self.write(banner)
407
400
408 def compute_banner(self):
401 def compute_banner(self):
409 self.banner = self.banner1
402 self.banner = self.banner1
410 if self.profile and self.profile != 'default':
403 if self.profile and self.profile != 'default':
411 self.banner += '\nIPython profile: %s\n' % self.profile
404 self.banner += '\nIPython profile: %s\n' % self.profile
412 if self.banner2:
405 if self.banner2:
413 self.banner += '\n' + self.banner2
406 self.banner += '\n' + self.banner2
414
407
415 def init_usage(self, usage=None):
408 def init_usage(self, usage=None):
416 if usage is None:
409 if usage is None:
417 self.usage = interactive_usage
410 self.usage = interactive_usage
418 else:
411 else:
419 self.usage = usage
412 self.usage = usage
420
413
421 #-------------------------------------------------------------------------
414 #-------------------------------------------------------------------------
422 # Mainloop and code execution logic
415 # Mainloop and code execution logic
423 #-------------------------------------------------------------------------
416 #-------------------------------------------------------------------------
424
417
425 def mainloop(self, display_banner=None):
418 def mainloop(self, display_banner=None):
426 """Start the mainloop.
419 """Start the mainloop.
427
420
428 If an optional banner argument is given, it will override the
421 If an optional banner argument is given, it will override the
429 internally created default banner.
422 internally created default banner.
430 """
423 """
431
424
432 with nested(self.builtin_trap, self.display_trap):
425 with self.builtin_trap, self.display_trap:
433
426
434 while 1:
427 while 1:
435 try:
428 try:
436 self.interact(display_banner=display_banner)
429 self.interact(display_banner=display_banner)
437 #self.interact_with_readline()
430 #self.interact_with_readline()
438 # XXX for testing of a readline-decoupled repl loop, call
431 # XXX for testing of a readline-decoupled repl loop, call
439 # interact_with_readline above
432 # interact_with_readline above
440 break
433 break
441 except KeyboardInterrupt:
434 except KeyboardInterrupt:
442 # this should not be necessary, but KeyboardInterrupt
435 # this should not be necessary, but KeyboardInterrupt
443 # handling seems rather unpredictable...
436 # handling seems rather unpredictable...
444 self.write("\nKeyboardInterrupt in interact()\n")
437 self.write("\nKeyboardInterrupt in interact()\n")
445
438
446 def _replace_rlhist_multiline(self, source_raw, hlen_before_cell):
439 def _replace_rlhist_multiline(self, source_raw, hlen_before_cell):
447 """Store multiple lines as a single entry in history"""
440 """Store multiple lines as a single entry in history"""
448
441
449 # do nothing without readline or disabled multiline
442 # do nothing without readline or disabled multiline
450 if not self.has_readline or not self.multiline_history:
443 if not self.has_readline or not self.multiline_history:
451 return hlen_before_cell
444 return hlen_before_cell
452
445
453 # windows rl has no remove_history_item
446 # windows rl has no remove_history_item
454 if not hasattr(self.readline, "remove_history_item"):
447 if not hasattr(self.readline, "remove_history_item"):
455 return hlen_before_cell
448 return hlen_before_cell
456
449
457 # skip empty cells
450 # skip empty cells
458 if not source_raw.rstrip():
451 if not source_raw.rstrip():
459 return hlen_before_cell
452 return hlen_before_cell
460
453
461 # nothing changed do nothing, e.g. when rl removes consecutive dups
454 # nothing changed do nothing, e.g. when rl removes consecutive dups
462 hlen = self.readline.get_current_history_length()
455 hlen = self.readline.get_current_history_length()
463 if hlen == hlen_before_cell:
456 if hlen == hlen_before_cell:
464 return hlen_before_cell
457 return hlen_before_cell
465
458
466 for i in range(hlen - hlen_before_cell):
459 for i in range(hlen - hlen_before_cell):
467 self.readline.remove_history_item(hlen - i - 1)
460 self.readline.remove_history_item(hlen - i - 1)
468 stdin_encoding = get_stream_enc(sys.stdin, 'utf-8')
461 stdin_encoding = get_stream_enc(sys.stdin, 'utf-8')
469 self.readline.add_history(py3compat.unicode_to_str(source_raw.rstrip(),
462 self.readline.add_history(py3compat.unicode_to_str(source_raw.rstrip(),
470 stdin_encoding))
463 stdin_encoding))
471 return self.readline.get_current_history_length()
464 return self.readline.get_current_history_length()
472
465
473 def interact(self, display_banner=None):
466 def interact(self, display_banner=None):
474 """Closely emulate the interactive Python console."""
467 """Closely emulate the interactive Python console."""
475
468
476 # batch run -> do not interact
469 # batch run -> do not interact
477 if self.exit_now:
470 if self.exit_now:
478 return
471 return
479
472
480 if display_banner is None:
473 if display_banner is None:
481 display_banner = self.display_banner
474 display_banner = self.display_banner
482
475
483 if isinstance(display_banner, basestring):
476 if isinstance(display_banner, basestring):
484 self.show_banner(display_banner)
477 self.show_banner(display_banner)
485 elif display_banner:
478 elif display_banner:
486 self.show_banner()
479 self.show_banner()
487
480
488 more = False
481 more = False
489
482
490 if self.has_readline:
483 if self.has_readline:
491 self.readline_startup_hook(self.pre_readline)
484 self.readline_startup_hook(self.pre_readline)
492 hlen_b4_cell = self.readline.get_current_history_length()
485 hlen_b4_cell = self.readline.get_current_history_length()
493 else:
486 else:
494 hlen_b4_cell = 0
487 hlen_b4_cell = 0
495 # exit_now is set by a call to %Exit or %Quit, through the
488 # exit_now is set by a call to %Exit or %Quit, through the
496 # ask_exit callback.
489 # ask_exit callback.
497
490
498 while not self.exit_now:
491 while not self.exit_now:
499 self.hooks.pre_prompt_hook()
492 self.hooks.pre_prompt_hook()
500 if more:
493 if more:
501 try:
494 try:
502 prompt = self.prompt_manager.render('in2')
495 prompt = self.prompt_manager.render('in2')
503 except:
496 except:
504 self.showtraceback()
497 self.showtraceback()
505 if self.autoindent:
498 if self.autoindent:
506 self.rl_do_indent = True
499 self.rl_do_indent = True
507
500
508 else:
501 else:
509 try:
502 try:
510 prompt = self.separate_in + self.prompt_manager.render('in')
503 prompt = self.separate_in + self.prompt_manager.render('in')
511 except:
504 except:
512 self.showtraceback()
505 self.showtraceback()
513 try:
506 try:
514 line = self.raw_input(prompt)
507 line = self.raw_input(prompt)
515 if self.exit_now:
508 if self.exit_now:
516 # quick exit on sys.std[in|out] close
509 # quick exit on sys.std[in|out] close
517 break
510 break
518 if self.autoindent:
511 if self.autoindent:
519 self.rl_do_indent = False
512 self.rl_do_indent = False
520
513
521 except KeyboardInterrupt:
514 except KeyboardInterrupt:
522 #double-guard against keyboardinterrupts during kbdint handling
515 #double-guard against keyboardinterrupts during kbdint handling
523 try:
516 try:
524 self.write('\nKeyboardInterrupt\n')
517 self.write('\nKeyboardInterrupt\n')
525 source_raw = self.input_splitter.source_raw_reset()[1]
518 source_raw = self.input_splitter.source_raw_reset()[1]
526 hlen_b4_cell = \
519 hlen_b4_cell = \
527 self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
520 self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
528 more = False
521 more = False
529 except KeyboardInterrupt:
522 except KeyboardInterrupt:
530 pass
523 pass
531 except EOFError:
524 except EOFError:
532 if self.autoindent:
525 if self.autoindent:
533 self.rl_do_indent = False
526 self.rl_do_indent = False
534 if self.has_readline:
527 if self.has_readline:
535 self.readline_startup_hook(None)
528 self.readline_startup_hook(None)
536 self.write('\n')
529 self.write('\n')
537 self.exit()
530 self.exit()
538 except bdb.BdbQuit:
531 except bdb.BdbQuit:
539 warn('The Python debugger has exited with a BdbQuit exception.\n'
532 warn('The Python debugger has exited with a BdbQuit exception.\n'
540 'Because of how pdb handles the stack, it is impossible\n'
533 'Because of how pdb handles the stack, it is impossible\n'
541 'for IPython to properly format this particular exception.\n'
534 'for IPython to properly format this particular exception.\n'
542 'IPython will resume normal operation.')
535 'IPython will resume normal operation.')
543 except:
536 except:
544 # exceptions here are VERY RARE, but they can be triggered
537 # exceptions here are VERY RARE, but they can be triggered
545 # asynchronously by signal handlers, for example.
538 # asynchronously by signal handlers, for example.
546 self.showtraceback()
539 self.showtraceback()
547 else:
540 else:
548 self.input_splitter.push(line)
541 self.input_splitter.push(line)
549 more = self.input_splitter.push_accepts_more()
542 more = self.input_splitter.push_accepts_more()
550 if (self.SyntaxTB.last_syntax_error and
543 if (self.SyntaxTB.last_syntax_error and
551 self.autoedit_syntax):
544 self.autoedit_syntax):
552 self.edit_syntax_error()
545 self.edit_syntax_error()
553 if not more:
546 if not more:
554 source_raw = self.input_splitter.source_raw_reset()[1]
547 source_raw = self.input_splitter.source_raw_reset()[1]
555 self.run_cell(source_raw, store_history=True)
548 self.run_cell(source_raw, store_history=True)
556 hlen_b4_cell = \
549 hlen_b4_cell = \
557 self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
550 self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
558
551
559 # Turn off the exit flag, so the mainloop can be restarted if desired
552 # Turn off the exit flag, so the mainloop can be restarted if desired
560 self.exit_now = False
553 self.exit_now = False
561
554
562 def raw_input(self, prompt=''):
555 def raw_input(self, prompt=''):
563 """Write a prompt and read a line.
556 """Write a prompt and read a line.
564
557
565 The returned line does not include the trailing newline.
558 The returned line does not include the trailing newline.
566 When the user enters the EOF key sequence, EOFError is raised.
559 When the user enters the EOF key sequence, EOFError is raised.
567
560
568 Optional inputs:
561 Optional inputs:
569
562
570 - prompt(''): a string to be printed to prompt the user.
563 - prompt(''): a string to be printed to prompt the user.
571
564
572 - continue_prompt(False): whether this line is the first one or a
565 - continue_prompt(False): whether this line is the first one or a
573 continuation in a sequence of inputs.
566 continuation in a sequence of inputs.
574 """
567 """
575 # Code run by the user may have modified the readline completer state.
568 # Code run by the user may have modified the readline completer state.
576 # We must ensure that our completer is back in place.
569 # We must ensure that our completer is back in place.
577
570
578 if self.has_readline:
571 if self.has_readline:
579 self.set_readline_completer()
572 self.set_readline_completer()
580
573
581 # raw_input expects str, but we pass it unicode sometimes
574 # raw_input expects str, but we pass it unicode sometimes
582 prompt = py3compat.cast_bytes_py2(prompt)
575 prompt = py3compat.cast_bytes_py2(prompt)
583
576
584 try:
577 try:
585 line = py3compat.str_to_unicode(self.raw_input_original(prompt))
578 line = py3compat.str_to_unicode(self.raw_input_original(prompt))
586 except ValueError:
579 except ValueError:
587 warn("\n********\nYou or a %run:ed script called sys.stdin.close()"
580 warn("\n********\nYou or a %run:ed script called sys.stdin.close()"
588 " or sys.stdout.close()!\nExiting IPython!\n")
581 " or sys.stdout.close()!\nExiting IPython!\n")
589 self.ask_exit()
582 self.ask_exit()
590 return ""
583 return ""
591
584
592 # Try to be reasonably smart about not re-indenting pasted input more
585 # Try to be reasonably smart about not re-indenting pasted input more
593 # than necessary. We do this by trimming out the auto-indent initial
586 # than necessary. We do this by trimming out the auto-indent initial
594 # spaces, if the user's actual input started itself with whitespace.
587 # spaces, if the user's actual input started itself with whitespace.
595 if self.autoindent:
588 if self.autoindent:
596 if num_ini_spaces(line) > self.indent_current_nsp:
589 if num_ini_spaces(line) > self.indent_current_nsp:
597 line = line[self.indent_current_nsp:]
590 line = line[self.indent_current_nsp:]
598 self.indent_current_nsp = 0
591 self.indent_current_nsp = 0
599
592
600 return line
593 return line
601
594
602 #-------------------------------------------------------------------------
595 #-------------------------------------------------------------------------
603 # Methods to support auto-editing of SyntaxErrors.
596 # Methods to support auto-editing of SyntaxErrors.
604 #-------------------------------------------------------------------------
597 #-------------------------------------------------------------------------
605
598
606 def edit_syntax_error(self):
599 def edit_syntax_error(self):
607 """The bottom half of the syntax error handler called in the main loop.
600 """The bottom half of the syntax error handler called in the main loop.
608
601
609 Loop until syntax error is fixed or user cancels.
602 Loop until syntax error is fixed or user cancels.
610 """
603 """
611
604
612 while self.SyntaxTB.last_syntax_error:
605 while self.SyntaxTB.last_syntax_error:
613 # copy and clear last_syntax_error
606 # copy and clear last_syntax_error
614 err = self.SyntaxTB.clear_err_state()
607 err = self.SyntaxTB.clear_err_state()
615 if not self._should_recompile(err):
608 if not self._should_recompile(err):
616 return
609 return
617 try:
610 try:
618 # may set last_syntax_error again if a SyntaxError is raised
611 # may set last_syntax_error again if a SyntaxError is raised
619 self.safe_execfile(err.filename,self.user_ns)
612 self.safe_execfile(err.filename,self.user_ns)
620 except:
613 except:
621 self.showtraceback()
614 self.showtraceback()
622 else:
615 else:
623 try:
616 try:
624 f = open(err.filename)
617 f = open(err.filename)
625 try:
618 try:
626 # This should be inside a display_trap block and I
619 # This should be inside a display_trap block and I
627 # think it is.
620 # think it is.
628 sys.displayhook(f.read())
621 sys.displayhook(f.read())
629 finally:
622 finally:
630 f.close()
623 f.close()
631 except:
624 except:
632 self.showtraceback()
625 self.showtraceback()
633
626
634 def _should_recompile(self,e):
627 def _should_recompile(self,e):
635 """Utility routine for edit_syntax_error"""
628 """Utility routine for edit_syntax_error"""
636
629
637 if e.filename in ('<ipython console>','<input>','<string>',
630 if e.filename in ('<ipython console>','<input>','<string>',
638 '<console>','<BackgroundJob compilation>',
631 '<console>','<BackgroundJob compilation>',
639 None):
632 None):
640
633
641 return False
634 return False
642 try:
635 try:
643 if (self.autoedit_syntax and
636 if (self.autoedit_syntax and
644 not self.ask_yes_no('Return to editor to correct syntax error? '
637 not self.ask_yes_no('Return to editor to correct syntax error? '
645 '[Y/n] ','y')):
638 '[Y/n] ','y')):
646 return False
639 return False
647 except EOFError:
640 except EOFError:
648 return False
641 return False
649
642
650 def int0(x):
643 def int0(x):
651 try:
644 try:
652 return int(x)
645 return int(x)
653 except TypeError:
646 except TypeError:
654 return 0
647 return 0
655 # always pass integer line and offset values to editor hook
648 # always pass integer line and offset values to editor hook
656 try:
649 try:
657 self.hooks.fix_error_editor(e.filename,
650 self.hooks.fix_error_editor(e.filename,
658 int0(e.lineno),int0(e.offset),e.msg)
651 int0(e.lineno),int0(e.offset),e.msg)
659 except TryNext:
652 except TryNext:
660 warn('Could not open editor')
653 warn('Could not open editor')
661 return False
654 return False
662 return True
655 return True
663
656
664 #-------------------------------------------------------------------------
657 #-------------------------------------------------------------------------
665 # Things related to exiting
658 # Things related to exiting
666 #-------------------------------------------------------------------------
659 #-------------------------------------------------------------------------
667
660
668 def ask_exit(self):
661 def ask_exit(self):
669 """ Ask the shell to exit. Can be overiden and used as a callback. """
662 """ Ask the shell to exit. Can be overiden and used as a callback. """
670 self.exit_now = True
663 self.exit_now = True
671
664
672 def exit(self):
665 def exit(self):
673 """Handle interactive exit.
666 """Handle interactive exit.
674
667
675 This method calls the ask_exit callback."""
668 This method calls the ask_exit callback."""
676 if self.confirm_exit:
669 if self.confirm_exit:
677 if self.ask_yes_no('Do you really want to exit ([y]/n)?','y'):
670 if self.ask_yes_no('Do you really want to exit ([y]/n)?','y'):
678 self.ask_exit()
671 self.ask_exit()
679 else:
672 else:
680 self.ask_exit()
673 self.ask_exit()
681
674
682 #-------------------------------------------------------------------------
675 #-------------------------------------------------------------------------
683 # Things related to magics
676 # Things related to magics
684 #-------------------------------------------------------------------------
677 #-------------------------------------------------------------------------
685
678
686 def init_magics(self):
679 def init_magics(self):
687 super(TerminalInteractiveShell, self).init_magics()
680 super(TerminalInteractiveShell, self).init_magics()
688 self.register_magics(TerminalMagics)
681 self.register_magics(TerminalMagics)
689
682
690 def showindentationerror(self):
683 def showindentationerror(self):
691 super(TerminalInteractiveShell, self).showindentationerror()
684 super(TerminalInteractiveShell, self).showindentationerror()
692 if not self.using_paste_magics:
685 if not self.using_paste_magics:
693 print("If you want to paste code into IPython, try the "
686 print("If you want to paste code into IPython, try the "
694 "%paste and %cpaste magic functions.")
687 "%paste and %cpaste magic functions.")
695
688
696
689
697 InteractiveShellABC.register(TerminalInteractiveShell)
690 InteractiveShellABC.register(TerminalInteractiveShell)
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now