##// END OF EJS Templates
raise UsageError for unsupported GUI backends...
MinRK -
Show More
@@ -1,223 +1,224 b''
1 1 # encoding: utf-8
2 2 """Event loop integration for the ZeroMQ-based kernels.
3 3 """
4 4
5 5 #-----------------------------------------------------------------------------
6 6 # Copyright (C) 2011 The IPython Development Team
7 7
8 8 # Distributed under the terms of the BSD License. The full license is in
9 9 # the file COPYING, distributed as part of this software.
10 10 #-----------------------------------------------------------------------------
11 11
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16
17 17 import sys
18 18
19 19 # System library imports.
20 20 import zmq
21 21
22 22 # Local imports.
23 23 from IPython.config.application import Application
24 24 from IPython.utils import io
25 25
26 26
27 27 #------------------------------------------------------------------------------
28 28 # Eventloops for integrating the Kernel into different GUIs
29 29 #------------------------------------------------------------------------------
30 30
31 31 def loop_qt4(kernel):
32 32 """Start a kernel with PyQt4 event loop integration."""
33 33
34 34 from IPython.external.qt_for_kernel import QtCore
35 35 from IPython.lib.guisupport import get_app_qt4, start_event_loop_qt4
36 36
37 37 kernel.app = get_app_qt4([" "])
38 38 kernel.app.setQuitOnLastWindowClosed(False)
39 39 kernel.timer = QtCore.QTimer()
40 40 kernel.timer.timeout.connect(kernel.do_one_iteration)
41 41 # Units for the timer are in milliseconds
42 42 kernel.timer.start(1000*kernel._poll_interval)
43 43 start_event_loop_qt4(kernel.app)
44 44
45 45
46 46 def loop_wx(kernel):
47 47 """Start a kernel with wx event loop support."""
48 48
49 49 import wx
50 50 from IPython.lib.guisupport import start_event_loop_wx
51 51
52 52 doi = kernel.do_one_iteration
53 53 # Wx uses milliseconds
54 54 poll_interval = int(1000*kernel._poll_interval)
55 55
56 56 # We have to put the wx.Timer in a wx.Frame for it to fire properly.
57 57 # We make the Frame hidden when we create it in the main app below.
58 58 class TimerFrame(wx.Frame):
59 59 def __init__(self, func):
60 60 wx.Frame.__init__(self, None, -1)
61 61 self.timer = wx.Timer(self)
62 62 # Units for the timer are in milliseconds
63 63 self.timer.Start(poll_interval)
64 64 self.Bind(wx.EVT_TIMER, self.on_timer)
65 65 self.func = func
66 66
67 67 def on_timer(self, event):
68 68 self.func()
69 69
70 70 # We need a custom wx.App to create our Frame subclass that has the
71 71 # wx.Timer to drive the ZMQ event loop.
72 72 class IPWxApp(wx.App):
73 73 def OnInit(self):
74 74 self.frame = TimerFrame(doi)
75 75 self.frame.Show(False)
76 76 return True
77 77
78 78 # The redirect=False here makes sure that wx doesn't replace
79 79 # sys.stdout/stderr with its own classes.
80 80 kernel.app = IPWxApp(redirect=False)
81 81
82 82 # The import of wx on Linux sets the handler for signal.SIGINT
83 83 # to 0. This is a bug in wx or gtk. We fix by just setting it
84 84 # back to the Python default.
85 85 import signal
86 86 if not callable(signal.getsignal(signal.SIGINT)):
87 87 signal.signal(signal.SIGINT, signal.default_int_handler)
88 88
89 89 start_event_loop_wx(kernel.app)
90 90
91 91
92 92 def loop_tk(kernel):
93 93 """Start a kernel with the Tk event loop."""
94 94
95 95 import Tkinter
96 96 doi = kernel.do_one_iteration
97 97 # Tk uses milliseconds
98 98 poll_interval = int(1000*kernel._poll_interval)
99 99 # For Tkinter, we create a Tk object and call its withdraw method.
100 100 class Timer(object):
101 101 def __init__(self, func):
102 102 self.app = Tkinter.Tk()
103 103 self.app.withdraw()
104 104 self.func = func
105 105
106 106 def on_timer(self):
107 107 self.func()
108 108 self.app.after(poll_interval, self.on_timer)
109 109
110 110 def start(self):
111 111 self.on_timer() # Call it once to get things going.
112 112 self.app.mainloop()
113 113
114 114 kernel.timer = Timer(doi)
115 115 kernel.timer.start()
116 116
117 117
118 118 def loop_gtk(kernel):
119 119 """Start the kernel, coordinating with the GTK event loop"""
120 120 from .gui.gtkembed import GTKEmbed
121 121
122 122 gtk_kernel = GTKEmbed(kernel)
123 123 gtk_kernel.start()
124 124
125 125
126 126 def loop_cocoa(kernel):
127 127 """Start the kernel, coordinating with the Cocoa CFRunLoop event loop
128 128 via the matplotlib MacOSX backend.
129 129 """
130 130 import matplotlib
131 131 if matplotlib.__version__ < '1.1.0':
132 132 kernel.log.warn(
133 133 "MacOSX backend in matplotlib %s doesn't have a Timer, "
134 134 "falling back on Tk for CFRunLoop integration. Note that "
135 135 "even this won't work if Tk is linked against X11 instead of "
136 136 "Cocoa (e.g. EPD). To use the MacOSX backend in the kernel, "
137 137 "you must use matplotlib >= 1.1.0, or a native libtk."
138 138 )
139 139 return loop_tk(kernel)
140 140
141 141 from matplotlib.backends.backend_macosx import TimerMac, show
142 142
143 143 # scale interval for sec->ms
144 144 poll_interval = int(1000*kernel._poll_interval)
145 145
146 146 real_excepthook = sys.excepthook
147 147 def handle_int(etype, value, tb):
148 148 """don't let KeyboardInterrupts look like crashes"""
149 149 if etype is KeyboardInterrupt:
150 150 io.raw_print("KeyboardInterrupt caught in CFRunLoop")
151 151 else:
152 152 real_excepthook(etype, value, tb)
153 153
154 154 # add doi() as a Timer to the CFRunLoop
155 155 def doi():
156 156 # restore excepthook during IPython code
157 157 sys.excepthook = real_excepthook
158 158 kernel.do_one_iteration()
159 159 # and back:
160 160 sys.excepthook = handle_int
161 161
162 162 t = TimerMac(poll_interval)
163 163 t.add_callback(doi)
164 164 t.start()
165 165
166 166 # but still need a Poller for when there are no active windows,
167 167 # during which time mainloop() returns immediately
168 168 poller = zmq.Poller()
169 169 if kernel.control_stream:
170 170 poller.register(kernel.control_stream.socket, zmq.POLLIN)
171 171 for stream in kernel.shell_streams:
172 172 poller.register(stream.socket, zmq.POLLIN)
173 173
174 174 while True:
175 175 try:
176 176 # double nested try/except, to properly catch KeyboardInterrupt
177 177 # due to pyzmq Issue #130
178 178 try:
179 179 # don't let interrupts during mainloop invoke crash_handler:
180 180 sys.excepthook = handle_int
181 181 show.mainloop()
182 182 sys.excepthook = real_excepthook
183 183 # use poller if mainloop returned (no windows)
184 184 # scale by extra factor of 10, since it's a real poll
185 185 poller.poll(10*poll_interval)
186 186 kernel.do_one_iteration()
187 187 except:
188 188 raise
189 189 except KeyboardInterrupt:
190 190 # Ctrl-C shouldn't crash the kernel
191 191 io.raw_print("KeyboardInterrupt caught in kernel")
192 192 finally:
193 193 # ensure excepthook is restored
194 194 sys.excepthook = real_excepthook
195 195
196 196 # mapping of keys to loop functions
197 197 loop_map = {
198 198 'qt' : loop_qt4,
199 199 'qt4': loop_qt4,
200 200 'inline': None,
201 201 'osx': loop_cocoa,
202 202 'wx' : loop_wx,
203 203 'tk' : loop_tk,
204 204 'gtk': loop_gtk,
205 205 None : None,
206 206 }
207 207
208 208
209 209 def enable_gui(gui, kernel=None):
210 210 """Enable integration with a given GUI"""
211 211 if gui not in loop_map:
212 raise ValueError("GUI %r not supported" % gui)
212 e = "Invalid GUI request %r, valid ones are:%s" % (gui, loop_map.keys())
213 raise ValueError(e)
213 214 if kernel is None:
214 215 if Application.initialized():
215 216 kernel = getattr(Application.instance(), 'kernel', None)
216 217 if kernel is None:
217 218 raise RuntimeError("You didn't specify a kernel,"
218 219 " and no IPython Application with a kernel appears to be running."
219 220 )
220 221 loop = loop_map[gui]
221 222 if loop and kernel.eventloop is not None and kernel.eventloop is not loop:
222 223 raise RuntimeError("Cannot activate multiple GUI eventloops")
223 224 kernel.eventloop = loop
@@ -1,597 +1,602 b''
1 1 """A ZMQ-based subclass of InteractiveShell.
2 2
3 3 This code is meant to ease the refactoring of the base InteractiveShell into
4 4 something with a cleaner architecture for 2-process use, without actually
5 5 breaking InteractiveShell itself. So we're doing something a bit ugly, where
6 6 we subclass and override what we want to fix. Once this is working well, we
7 7 can go back to the base class and refactor the code for a cleaner inheritance
8 8 implementation that doesn't rely on so much monkeypatching.
9 9
10 10 But this lets us maintain a fully working IPython as we develop the new
11 11 machinery. This should thus be thought of as scaffolding.
12 12 """
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16 from __future__ import print_function
17 17
18 18 # Stdlib
19 19 import os
20 20 import sys
21 21 import time
22 22
23 23 # System library imports
24 24 from zmq.eventloop import ioloop
25 25
26 26 # Our own
27 27 from IPython.core.interactiveshell import (
28 28 InteractiveShell, InteractiveShellABC
29 29 )
30 30 from IPython.core import page
31 31 from IPython.core.autocall import ZMQExitAutocall
32 32 from IPython.core.displaypub import DisplayPublisher
33 33 from IPython.core.error import UsageError
34 34 from IPython.core.magics import MacroToEdit, CodeMagics
35 35 from IPython.core.magic import magics_class, line_magic, Magics
36 36 from IPython.core.payloadpage import install_payload_page
37 37 from IPython.display import display, Javascript
38 38 from IPython.kernel.inprocess.socket import SocketABC
39 39 from IPython.kernel import (
40 40 get_connection_file, get_connection_info, connect_qtconsole
41 41 )
42 42 from IPython.testing.skipdoctest import skip_doctest
43 43 from IPython.utils import openpy
44 44 from IPython.utils.jsonutil import json_clean, encode_images
45 45 from IPython.utils.process import arg_split
46 46 from IPython.utils import py3compat
47 47 from IPython.utils.traitlets import Instance, Type, Dict, CBool, CBytes
48 48 from IPython.utils.warn import error
49 49 from IPython.kernel.zmq.displayhook import ZMQShellDisplayHook
50 50 from IPython.kernel.zmq.datapub import ZMQDataPublisher
51 51 from IPython.kernel.zmq.session import extract_header
52 52 from session import Session
53 53
54 54 #-----------------------------------------------------------------------------
55 55 # Functions and classes
56 56 #-----------------------------------------------------------------------------
57 57
58 58 class ZMQDisplayPublisher(DisplayPublisher):
59 59 """A display publisher that publishes data using a ZeroMQ PUB socket."""
60 60
61 61 session = Instance(Session)
62 62 pub_socket = Instance(SocketABC)
63 63 parent_header = Dict({})
64 64 topic = CBytes(b'displaypub')
65 65
66 66 def set_parent(self, parent):
67 67 """Set the parent for outbound messages."""
68 68 self.parent_header = extract_header(parent)
69 69
70 70 def _flush_streams(self):
71 71 """flush IO Streams prior to display"""
72 72 sys.stdout.flush()
73 73 sys.stderr.flush()
74 74
75 75 def publish(self, source, data, metadata=None):
76 76 self._flush_streams()
77 77 if metadata is None:
78 78 metadata = {}
79 79 self._validate_data(source, data, metadata)
80 80 content = {}
81 81 content['source'] = source
82 82 content['data'] = encode_images(data)
83 83 content['metadata'] = metadata
84 84 self.session.send(
85 85 self.pub_socket, u'display_data', json_clean(content),
86 86 parent=self.parent_header, ident=self.topic,
87 87 )
88 88
89 89 def clear_output(self, stdout=True, stderr=True, other=True):
90 90 content = dict(stdout=stdout, stderr=stderr, other=other)
91 91
92 92 if stdout:
93 93 print('\r', file=sys.stdout, end='')
94 94 if stderr:
95 95 print('\r', file=sys.stderr, end='')
96 96
97 97 self._flush_streams()
98 98
99 99 self.session.send(
100 100 self.pub_socket, u'clear_output', content,
101 101 parent=self.parent_header, ident=self.topic,
102 102 )
103 103
104 104 @magics_class
105 105 class KernelMagics(Magics):
106 106 #------------------------------------------------------------------------
107 107 # Magic overrides
108 108 #------------------------------------------------------------------------
109 109 # Once the base class stops inheriting from magic, this code needs to be
110 110 # moved into a separate machinery as well. For now, at least isolate here
111 111 # the magics which this class needs to implement differently from the base
112 112 # class, or that are unique to it.
113 113
114 114 @line_magic
115 115 def doctest_mode(self, parameter_s=''):
116 116 """Toggle doctest mode on and off.
117 117
118 118 This mode is intended to make IPython behave as much as possible like a
119 119 plain Python shell, from the perspective of how its prompts, exceptions
120 120 and output look. This makes it easy to copy and paste parts of a
121 121 session into doctests. It does so by:
122 122
123 123 - Changing the prompts to the classic ``>>>`` ones.
124 124 - Changing the exception reporting mode to 'Plain'.
125 125 - Disabling pretty-printing of output.
126 126
127 127 Note that IPython also supports the pasting of code snippets that have
128 128 leading '>>>' and '...' prompts in them. This means that you can paste
129 129 doctests from files or docstrings (even if they have leading
130 130 whitespace), and the code will execute correctly. You can then use
131 131 '%history -t' to see the translated history; this will give you the
132 132 input after removal of all the leading prompts and whitespace, which
133 133 can be pasted back into an editor.
134 134
135 135 With these features, you can switch into this mode easily whenever you
136 136 need to do testing and changes to doctests, without having to leave
137 137 your existing IPython session.
138 138 """
139 139
140 140 from IPython.utils.ipstruct import Struct
141 141
142 142 # Shorthands
143 143 shell = self.shell
144 144 disp_formatter = self.shell.display_formatter
145 145 ptformatter = disp_formatter.formatters['text/plain']
146 146 # dstore is a data store kept in the instance metadata bag to track any
147 147 # changes we make, so we can undo them later.
148 148 dstore = shell.meta.setdefault('doctest_mode', Struct())
149 149 save_dstore = dstore.setdefault
150 150
151 151 # save a few values we'll need to recover later
152 152 mode = save_dstore('mode', False)
153 153 save_dstore('rc_pprint', ptformatter.pprint)
154 154 save_dstore('rc_active_types',disp_formatter.active_types)
155 155 save_dstore('xmode', shell.InteractiveTB.mode)
156 156
157 157 if mode == False:
158 158 # turn on
159 159 ptformatter.pprint = False
160 160 disp_formatter.active_types = ['text/plain']
161 161 shell.magic('xmode Plain')
162 162 else:
163 163 # turn off
164 164 ptformatter.pprint = dstore.rc_pprint
165 165 disp_formatter.active_types = dstore.rc_active_types
166 166 shell.magic("xmode " + dstore.xmode)
167 167
168 168 # Store new mode and inform on console
169 169 dstore.mode = bool(1-int(mode))
170 170 mode_label = ['OFF','ON'][dstore.mode]
171 171 print('Doctest mode is:', mode_label)
172 172
173 173 # Send the payload back so that clients can modify their prompt display
174 174 payload = dict(
175 175 source='IPython.kernel.zmq.zmqshell.ZMQInteractiveShell.doctest_mode',
176 176 mode=dstore.mode)
177 177 shell.payload_manager.write_payload(payload)
178 178
179 179
180 180 _find_edit_target = CodeMagics._find_edit_target
181 181
182 182 @skip_doctest
183 183 @line_magic
184 184 def edit(self, parameter_s='', last_call=['','']):
185 185 """Bring up an editor and execute the resulting code.
186 186
187 187 Usage:
188 188 %edit [options] [args]
189 189
190 190 %edit runs an external text editor. You will need to set the command for
191 191 this editor via the ``TerminalInteractiveShell.editor`` option in your
192 192 configuration file before it will work.
193 193
194 194 This command allows you to conveniently edit multi-line code right in
195 195 your IPython session.
196 196
197 197 If called without arguments, %edit opens up an empty editor with a
198 198 temporary file and will execute the contents of this file when you
199 199 close it (don't forget to save it!).
200 200
201 201
202 202 Options:
203 203
204 204 -n <number>: open the editor at a specified line number. By default,
205 205 the IPython editor hook uses the unix syntax 'editor +N filename', but
206 206 you can configure this by providing your own modified hook if your
207 207 favorite editor supports line-number specifications with a different
208 208 syntax.
209 209
210 210 -p: this will call the editor with the same data as the previous time
211 211 it was used, regardless of how long ago (in your current session) it
212 212 was.
213 213
214 214 -r: use 'raw' input. This option only applies to input taken from the
215 215 user's history. By default, the 'processed' history is used, so that
216 216 magics are loaded in their transformed version to valid Python. If
217 217 this option is given, the raw input as typed as the command line is
218 218 used instead. When you exit the editor, it will be executed by
219 219 IPython's own processor.
220 220
221 221 -x: do not execute the edited code immediately upon exit. This is
222 222 mainly useful if you are editing programs which need to be called with
223 223 command line arguments, which you can then do using %run.
224 224
225 225
226 226 Arguments:
227 227
228 228 If arguments are given, the following possibilites exist:
229 229
230 230 - The arguments are numbers or pairs of colon-separated numbers (like
231 231 1 4:8 9). These are interpreted as lines of previous input to be
232 232 loaded into the editor. The syntax is the same of the %macro command.
233 233
234 234 - If the argument doesn't start with a number, it is evaluated as a
235 235 variable and its contents loaded into the editor. You can thus edit
236 236 any string which contains python code (including the result of
237 237 previous edits).
238 238
239 239 - If the argument is the name of an object (other than a string),
240 240 IPython will try to locate the file where it was defined and open the
241 241 editor at the point where it is defined. You can use `%edit function`
242 242 to load an editor exactly at the point where 'function' is defined,
243 243 edit it and have the file be executed automatically.
244 244
245 245 If the object is a macro (see %macro for details), this opens up your
246 246 specified editor with a temporary file containing the macro's data.
247 247 Upon exit, the macro is reloaded with the contents of the file.
248 248
249 249 Note: opening at an exact line is only supported under Unix, and some
250 250 editors (like kedit and gedit up to Gnome 2.8) do not understand the
251 251 '+NUMBER' parameter necessary for this feature. Good editors like
252 252 (X)Emacs, vi, jed, pico and joe all do.
253 253
254 254 - If the argument is not found as a variable, IPython will look for a
255 255 file with that name (adding .py if necessary) and load it into the
256 256 editor. It will execute its contents with execfile() when you exit,
257 257 loading any code in the file into your interactive namespace.
258 258
259 259 After executing your code, %edit will return as output the code you
260 260 typed in the editor (except when it was an existing file). This way
261 261 you can reload the code in further invocations of %edit as a variable,
262 262 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
263 263 the output.
264 264
265 265 Note that %edit is also available through the alias %ed.
266 266
267 267 This is an example of creating a simple function inside the editor and
268 268 then modifying it. First, start up the editor:
269 269
270 270 In [1]: ed
271 271 Editing... done. Executing edited code...
272 272 Out[1]: 'def foo():n print "foo() was defined in an editing session"n'
273 273
274 274 We can then call the function foo():
275 275
276 276 In [2]: foo()
277 277 foo() was defined in an editing session
278 278
279 279 Now we edit foo. IPython automatically loads the editor with the
280 280 (temporary) file where foo() was previously defined:
281 281
282 282 In [3]: ed foo
283 283 Editing... done. Executing edited code...
284 284
285 285 And if we call foo() again we get the modified version:
286 286
287 287 In [4]: foo()
288 288 foo() has now been changed!
289 289
290 290 Here is an example of how to edit a code snippet successive
291 291 times. First we call the editor:
292 292
293 293 In [5]: ed
294 294 Editing... done. Executing edited code...
295 295 hello
296 296 Out[5]: "print 'hello'n"
297 297
298 298 Now we call it again with the previous output (stored in _):
299 299
300 300 In [6]: ed _
301 301 Editing... done. Executing edited code...
302 302 hello world
303 303 Out[6]: "print 'hello world'n"
304 304
305 305 Now we call it with the output #8 (stored in _8, also as Out[8]):
306 306
307 307 In [7]: ed _8
308 308 Editing... done. Executing edited code...
309 309 hello again
310 310 Out[7]: "print 'hello again'n"
311 311 """
312 312
313 313 opts,args = self.parse_options(parameter_s,'prn:')
314 314
315 315 try:
316 316 filename, lineno, _ = CodeMagics._find_edit_target(self.shell, args, opts, last_call)
317 317 except MacroToEdit as e:
318 318 # TODO: Implement macro editing over 2 processes.
319 319 print("Macro editing not yet implemented in 2-process model.")
320 320 return
321 321
322 322 # Make sure we send to the client an absolute path, in case the working
323 323 # directory of client and kernel don't match
324 324 filename = os.path.abspath(filename)
325 325
326 326 payload = {
327 327 'source' : 'IPython.kernel.zmq.zmqshell.ZMQInteractiveShell.edit_magic',
328 328 'filename' : filename,
329 329 'line_number' : lineno
330 330 }
331 331 self.shell.payload_manager.write_payload(payload)
332 332
333 333 # A few magics that are adapted to the specifics of using pexpect and a
334 334 # remote terminal
335 335
336 336 @line_magic
337 337 def clear(self, arg_s):
338 338 """Clear the terminal."""
339 339 if os.name == 'posix':
340 340 self.shell.system("clear")
341 341 else:
342 342 self.shell.system("cls")
343 343
344 344 if os.name == 'nt':
345 345 # This is the usual name in windows
346 346 cls = line_magic('cls')(clear)
347 347
348 348 # Terminal pagers won't work over pexpect, but we do have our own pager
349 349
350 350 @line_magic
351 351 def less(self, arg_s):
352 352 """Show a file through the pager.
353 353
354 354 Files ending in .py are syntax-highlighted."""
355 355 if not arg_s:
356 356 raise UsageError('Missing filename.')
357 357
358 358 cont = open(arg_s).read()
359 359 if arg_s.endswith('.py'):
360 360 cont = self.shell.pycolorize(openpy.read_py_file(arg_s, skip_encoding_cookie=False))
361 361 else:
362 362 cont = open(arg_s).read()
363 363 page.page(cont)
364 364
365 365 more = line_magic('more')(less)
366 366
367 367 # Man calls a pager, so we also need to redefine it
368 368 if os.name == 'posix':
369 369 @line_magic
370 370 def man(self, arg_s):
371 371 """Find the man page for the given command and display in pager."""
372 372 page.page(self.shell.getoutput('man %s | col -b' % arg_s,
373 373 split=False))
374 374
375 375 @line_magic
376 376 def connect_info(self, arg_s):
377 377 """Print information for connecting other clients to this kernel
378 378
379 379 It will print the contents of this session's connection file, as well as
380 380 shortcuts for local clients.
381 381
382 382 In the simplest case, when called from the most recently launched kernel,
383 383 secondary clients can be connected, simply with:
384 384
385 385 $> ipython <app> --existing
386 386
387 387 """
388 388
389 389 from IPython.core.application import BaseIPythonApplication as BaseIPApp
390 390
391 391 if BaseIPApp.initialized():
392 392 app = BaseIPApp.instance()
393 393 security_dir = app.profile_dir.security_dir
394 394 profile = app.profile
395 395 else:
396 396 profile = 'default'
397 397 security_dir = ''
398 398
399 399 try:
400 400 connection_file = get_connection_file()
401 401 info = get_connection_info(unpack=False)
402 402 except Exception as e:
403 403 error("Could not get connection info: %r" % e)
404 404 return
405 405
406 406 # add profile flag for non-default profile
407 407 profile_flag = "--profile %s" % profile if profile != 'default' else ""
408 408
409 409 # if it's in the security dir, truncate to basename
410 410 if security_dir == os.path.dirname(connection_file):
411 411 connection_file = os.path.basename(connection_file)
412 412
413 413
414 414 print (info + '\n')
415 415 print ("Paste the above JSON into a file, and connect with:\n"
416 416 " $> ipython <app> --existing <file>\n"
417 417 "or, if you are local, you can connect with just:\n"
418 418 " $> ipython <app> --existing {0} {1}\n"
419 419 "or even just:\n"
420 420 " $> ipython <app> --existing {1}\n"
421 421 "if this is the most recent IPython session you have started.".format(
422 422 connection_file, profile_flag
423 423 )
424 424 )
425 425
426 426 @line_magic
427 427 def qtconsole(self, arg_s):
428 428 """Open a qtconsole connected to this kernel.
429 429
430 430 Useful for connecting a qtconsole to running notebooks, for better
431 431 debugging.
432 432 """
433 433
434 434 # %qtconsole should imply bind_kernel for engines:
435 435 try:
436 436 from IPython.parallel import bind_kernel
437 437 except ImportError:
438 438 # technically possible, because parallel has higher pyzmq min-version
439 439 pass
440 440 else:
441 441 bind_kernel()
442 442
443 443 try:
444 444 p = connect_qtconsole(argv=arg_split(arg_s, os.name=='posix'))
445 445 except Exception as e:
446 446 error("Could not start qtconsole: %r" % e)
447 447 return
448 448
449 449 @line_magic
450 450 def autosave(self, arg_s):
451 451 """Set the autosave interval in the notebook (in seconds).
452 452
453 453 The default value is 120, or two minutes.
454 454 ``%autosave 0`` will disable autosave.
455 455
456 456 This magic only has an effect when called from the notebook interface.
457 457 It has no effect when called in a startup file.
458 458 """
459 459
460 460 try:
461 461 interval = int(arg_s)
462 462 except ValueError:
463 463 raise UsageError("%%autosave requires an integer, got %r" % arg_s)
464 464
465 465 # javascript wants milliseconds
466 466 milliseconds = 1000 * interval
467 467 display(Javascript("IPython.notebook.set_autosave_interval(%i)" % milliseconds),
468 468 include=['application/javascript']
469 469 )
470 470 if interval:
471 471 print("Autosaving every %i seconds" % interval)
472 472 else:
473 473 print("Autosave disabled")
474 474
475 475
476 476 class ZMQInteractiveShell(InteractiveShell):
477 477 """A subclass of InteractiveShell for ZMQ."""
478 478
479 479 displayhook_class = Type(ZMQShellDisplayHook)
480 480 display_pub_class = Type(ZMQDisplayPublisher)
481 481 data_pub_class = Type(ZMQDataPublisher)
482 482
483 483 # Override the traitlet in the parent class, because there's no point using
484 484 # readline for the kernel. Can be removed when the readline code is moved
485 485 # to the terminal frontend.
486 486 colors_force = CBool(True)
487 487 readline_use = CBool(False)
488 488 # autoindent has no meaning in a zmqshell, and attempting to enable it
489 489 # will print a warning in the absence of readline.
490 490 autoindent = CBool(False)
491 491
492 492 exiter = Instance(ZMQExitAutocall)
493 493 def _exiter_default(self):
494 494 return ZMQExitAutocall(self)
495 495
496 496 def _exit_now_changed(self, name, old, new):
497 497 """stop eventloop when exit_now fires"""
498 498 if new:
499 499 loop = ioloop.IOLoop.instance()
500 500 loop.add_timeout(time.time()+0.1, loop.stop)
501 501
502 502 keepkernel_on_exit = None
503 503
504 504 # Over ZeroMQ, GUI control isn't done with PyOS_InputHook as there is no
505 505 # interactive input being read; we provide event loop support in ipkernel
506 from .eventloops import enable_gui
507 enable_gui = staticmethod(enable_gui)
506 @staticmethod
507 def enable_gui(gui):
508 from .eventloops import enable_gui as real_enable_gui
509 try:
510 real_enable_gui(gui)
511 except ValueError as e:
512 raise UsageError("%s" % e)
508 513
509 514 def init_environment(self):
510 515 """Configure the user's environment.
511 516
512 517 """
513 518 env = os.environ
514 519 # These two ensure 'ls' produces nice coloring on BSD-derived systems
515 520 env['TERM'] = 'xterm-color'
516 521 env['CLICOLOR'] = '1'
517 522 # Since normal pagers don't work at all (over pexpect we don't have
518 523 # single-key control of the subprocess), try to disable paging in
519 524 # subprocesses as much as possible.
520 525 env['PAGER'] = 'cat'
521 526 env['GIT_PAGER'] = 'cat'
522 527
523 528 # And install the payload version of page.
524 529 install_payload_page()
525 530
526 531 def auto_rewrite_input(self, cmd):
527 532 """Called to show the auto-rewritten input for autocall and friends.
528 533
529 534 FIXME: this payload is currently not correctly processed by the
530 535 frontend.
531 536 """
532 537 new = self.prompt_manager.render('rewrite') + cmd
533 538 payload = dict(
534 539 source='IPython.kernel.zmq.zmqshell.ZMQInteractiveShell.auto_rewrite_input',
535 540 transformed_input=new,
536 541 )
537 542 self.payload_manager.write_payload(payload)
538 543
539 544 def ask_exit(self):
540 545 """Engage the exit actions."""
541 546 self.exit_now = True
542 547 payload = dict(
543 548 source='IPython.kernel.zmq.zmqshell.ZMQInteractiveShell.ask_exit',
544 549 exit=True,
545 550 keepkernel=self.keepkernel_on_exit,
546 551 )
547 552 self.payload_manager.write_payload(payload)
548 553
549 554 def _showtraceback(self, etype, evalue, stb):
550 555
551 556 exc_content = {
552 557 u'traceback' : stb,
553 558 u'ename' : unicode(etype.__name__),
554 559 u'evalue' : py3compat.safe_unicode(evalue),
555 560 }
556 561
557 562 dh = self.displayhook
558 563 # Send exception info over pub socket for other clients than the caller
559 564 # to pick up
560 565 topic = None
561 566 if dh.topic:
562 567 topic = dh.topic.replace(b'pyout', b'pyerr')
563 568
564 569 exc_msg = dh.session.send(dh.pub_socket, u'pyerr', json_clean(exc_content), dh.parent_header, ident=topic)
565 570
566 571 # FIXME - Hack: store exception info in shell object. Right now, the
567 572 # caller is reading this info after the fact, we need to fix this logic
568 573 # to remove this hack. Even uglier, we need to store the error status
569 574 # here, because in the main loop, the logic that sets it is being
570 575 # skipped because runlines swallows the exceptions.
571 576 exc_content[u'status'] = u'error'
572 577 self._reply_content = exc_content
573 578 # /FIXME
574 579
575 580 return exc_content
576 581
577 582 def set_next_input(self, text):
578 583 """Send the specified text to the frontend to be presented at the next
579 584 input cell."""
580 585 payload = dict(
581 586 source='IPython.kernel.zmq.zmqshell.ZMQInteractiveShell.set_next_input',
582 587 text=text
583 588 )
584 589 self.payload_manager.write_payload(payload)
585 590
586 591 #-------------------------------------------------------------------------
587 592 # Things related to magics
588 593 #-------------------------------------------------------------------------
589 594
590 595 def init_magics(self):
591 596 super(ZMQInteractiveShell, self).init_magics()
592 597 self.register_magics(KernelMagics)
593 598 self.magics_manager.register_alias('ed', 'edit')
594 599
595 600
596 601
597 602 InteractiveShellABC.register(ZMQInteractiveShell)
@@ -1,694 +1,697 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Subclass of InteractiveShell for terminal based frontends."""
3 3
4 4 #-----------------------------------------------------------------------------
5 5 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de>
6 6 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
7 7 # Copyright (C) 2008-2011 The IPython Development Team
8 8 #
9 9 # Distributed under the terms of the BSD License. The full license is in
10 10 # the file COPYING, distributed as part of this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16 from __future__ import print_function
17 17
18 18 import bdb
19 19 import os
20 20 import sys
21 21
22 22 # We need to use nested to support python 2.6, once we move to >=2.7, we can
23 23 # use the with keyword's new builtin support for nested managers
24 24 try:
25 25 from contextlib import nested
26 26 except:
27 27 from IPython.utils.nested_context import nested
28 28
29 29 from IPython.core.error import TryNext, UsageError
30 30 from IPython.core.usage import interactive_usage, default_banner
31 31 from IPython.core.inputsplitter import IPythonInputSplitter
32 32 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
33 33 from IPython.core.magic import Magics, magics_class, line_magic
34 34 from IPython.testing.skipdoctest import skip_doctest
35 35 from IPython.utils.encoding import get_stream_enc
36 36 from IPython.utils import py3compat
37 37 from IPython.utils.terminal import toggle_set_term_title, set_term_title
38 38 from IPython.utils.process import abbrev_cwd
39 39 from IPython.utils.warn import warn, error
40 40 from IPython.utils.text import num_ini_spaces, SList, strip_email_quotes
41 41 from IPython.utils.traitlets import Integer, CBool, Unicode
42 42
43 43 #-----------------------------------------------------------------------------
44 44 # Utilities
45 45 #-----------------------------------------------------------------------------
46 46
47 47 def get_default_editor():
48 48 try:
49 49 ed = os.environ['EDITOR']
50 50 except KeyError:
51 51 if os.name == 'posix':
52 52 ed = 'vi' # the only one guaranteed to be there!
53 53 else:
54 54 ed = 'notepad' # same in Windows!
55 55 return ed
56 56
57 57
58 58 def get_pasted_lines(sentinel, l_input=py3compat.input):
59 59 """ Yield pasted lines until the user enters the given sentinel value.
60 60 """
61 61 print("Pasting code; enter '%s' alone on the line to stop or use Ctrl-D." \
62 62 % sentinel)
63 63 while True:
64 64 try:
65 65 l = l_input(':')
66 66 if l == sentinel:
67 67 return
68 68 else:
69 69 yield l
70 70 except EOFError:
71 71 print('<EOF>')
72 72 return
73 73
74 74
75 75 #------------------------------------------------------------------------
76 76 # Terminal-specific magics
77 77 #------------------------------------------------------------------------
78 78
79 79 @magics_class
80 80 class TerminalMagics(Magics):
81 81 def __init__(self, shell):
82 82 super(TerminalMagics, self).__init__(shell)
83 83 self.input_splitter = IPythonInputSplitter()
84 84
85 85 def store_or_execute(self, block, name):
86 86 """ Execute a block, or store it in a variable, per the user's request.
87 87 """
88 88 if name:
89 89 # If storing it for further editing
90 90 self.shell.user_ns[name] = SList(block.splitlines())
91 91 print("Block assigned to '%s'" % name)
92 92 else:
93 93 b = self.preclean_input(block)
94 94 self.shell.user_ns['pasted_block'] = b
95 95 self.shell.using_paste_magics = True
96 96 try:
97 97 self.shell.run_cell(b)
98 98 finally:
99 99 self.shell.using_paste_magics = False
100 100
101 101 def preclean_input(self, block):
102 102 lines = block.splitlines()
103 103 while lines and not lines[0].strip():
104 104 lines = lines[1:]
105 105 return strip_email_quotes('\n'.join(lines))
106 106
107 107 def rerun_pasted(self, name='pasted_block'):
108 108 """ Rerun a previously pasted command.
109 109 """
110 110 b = self.shell.user_ns.get(name)
111 111
112 112 # Sanity checks
113 113 if b is None:
114 114 raise UsageError('No previous pasted block available')
115 115 if not isinstance(b, basestring):
116 116 raise UsageError(
117 117 "Variable 'pasted_block' is not a string, can't execute")
118 118
119 119 print("Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b)))
120 120 self.shell.run_cell(b)
121 121
122 122 @line_magic
123 123 def autoindent(self, parameter_s = ''):
124 124 """Toggle autoindent on/off (if available)."""
125 125
126 126 self.shell.set_autoindent()
127 127 print("Automatic indentation is:",['OFF','ON'][self.shell.autoindent])
128 128
129 129 @skip_doctest
130 130 @line_magic
131 131 def cpaste(self, parameter_s=''):
132 132 """Paste & execute a pre-formatted code block from clipboard.
133 133
134 134 You must terminate the block with '--' (two minus-signs) or Ctrl-D
135 135 alone on the line. You can also provide your own sentinel with '%paste
136 136 -s %%' ('%%' is the new sentinel for this operation)
137 137
138 138 The block is dedented prior to execution to enable execution of method
139 139 definitions. '>' and '+' characters at the beginning of a line are
140 140 ignored, to allow pasting directly from e-mails, diff files and
141 141 doctests (the '...' continuation prompt is also stripped). The
142 142 executed block is also assigned to variable named 'pasted_block' for
143 143 later editing with '%edit pasted_block'.
144 144
145 145 You can also pass a variable name as an argument, e.g. '%cpaste foo'.
146 146 This assigns the pasted block to variable 'foo' as string, without
147 147 dedenting or executing it (preceding >>> and + is still stripped)
148 148
149 149 '%cpaste -r' re-executes the block previously entered by cpaste.
150 150
151 151 Do not be alarmed by garbled output on Windows (it's a readline bug).
152 152 Just press enter and type -- (and press enter again) and the block
153 153 will be what was just pasted.
154 154
155 155 IPython statements (magics, shell escapes) are not supported (yet).
156 156
157 157 See also
158 158 --------
159 159 paste: automatically pull code from clipboard.
160 160
161 161 Examples
162 162 --------
163 163 ::
164 164
165 165 In [8]: %cpaste
166 166 Pasting code; enter '--' alone on the line to stop.
167 167 :>>> a = ["world!", "Hello"]
168 168 :>>> print " ".join(sorted(a))
169 169 :--
170 170 Hello world!
171 171 """
172 172 opts, name = self.parse_options(parameter_s, 'rs:', mode='string')
173 173 if 'r' in opts:
174 174 self.rerun_pasted()
175 175 return
176 176
177 177 sentinel = opts.get('s', '--')
178 178 block = '\n'.join(get_pasted_lines(sentinel))
179 179 self.store_or_execute(block, name)
180 180
181 181 @line_magic
182 182 def paste(self, parameter_s=''):
183 183 """Paste & execute a pre-formatted code block from clipboard.
184 184
185 185 The text is pulled directly from the clipboard without user
186 186 intervention and printed back on the screen before execution (unless
187 187 the -q flag is given to force quiet mode).
188 188
189 189 The block is dedented prior to execution to enable execution of method
190 190 definitions. '>' and '+' characters at the beginning of a line are
191 191 ignored, to allow pasting directly from e-mails, diff files and
192 192 doctests (the '...' continuation prompt is also stripped). The
193 193 executed block is also assigned to variable named 'pasted_block' for
194 194 later editing with '%edit pasted_block'.
195 195
196 196 You can also pass a variable name as an argument, e.g. '%paste foo'.
197 197 This assigns the pasted block to variable 'foo' as string, without
198 198 executing it (preceding >>> and + is still stripped).
199 199
200 200 Options
201 201 -------
202 202
203 203 -r: re-executes the block previously entered by cpaste.
204 204
205 205 -q: quiet mode: do not echo the pasted text back to the terminal.
206 206
207 207 IPython statements (magics, shell escapes) are not supported (yet).
208 208
209 209 See also
210 210 --------
211 211 cpaste: manually paste code into terminal until you mark its end.
212 212 """
213 213 opts, name = self.parse_options(parameter_s, 'rq', mode='string')
214 214 if 'r' in opts:
215 215 self.rerun_pasted()
216 216 return
217 217 try:
218 218 block = self.shell.hooks.clipboard_get()
219 219 except TryNext as clipboard_exc:
220 220 message = getattr(clipboard_exc, 'args')
221 221 if message:
222 222 error(message[0])
223 223 else:
224 224 error('Could not get text from the clipboard.')
225 225 return
226 226
227 227 # By default, echo back to terminal unless quiet mode is requested
228 228 if 'q' not in opts:
229 229 write = self.shell.write
230 230 write(self.shell.pycolorize(block))
231 231 if not block.endswith('\n'):
232 232 write('\n')
233 233 write("## -- End pasted text --\n")
234 234
235 235 self.store_or_execute(block, name)
236 236
237 237 # Class-level: add a '%cls' magic only on Windows
238 238 if sys.platform == 'win32':
239 239 @line_magic
240 240 def cls(self, s):
241 241 """Clear screen.
242 242 """
243 243 os.system("cls")
244 244
245 245 #-----------------------------------------------------------------------------
246 246 # Main class
247 247 #-----------------------------------------------------------------------------
248 248
249 249 class TerminalInteractiveShell(InteractiveShell):
250 250
251 251 autoedit_syntax = CBool(False, config=True,
252 252 help="auto editing of files with syntax errors.")
253 253 banner = Unicode('')
254 254 banner1 = Unicode(default_banner, config=True,
255 255 help="""The part of the banner to be printed before the profile"""
256 256 )
257 257 banner2 = Unicode('', config=True,
258 258 help="""The part of the banner to be printed after the profile"""
259 259 )
260 260 confirm_exit = CBool(True, config=True,
261 261 help="""
262 262 Set to confirm when you try to exit IPython with an EOF (Control-D
263 263 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
264 264 you can force a direct exit without any confirmation.""",
265 265 )
266 266 # This display_banner only controls whether or not self.show_banner()
267 267 # is called when mainloop/interact are called. The default is False
268 268 # because for the terminal based application, the banner behavior
269 269 # is controlled by Global.display_banner, which IPythonApp looks at
270 270 # to determine if *it* should call show_banner() by hand or not.
271 271 display_banner = CBool(False) # This isn't configurable!
272 272 embedded = CBool(False)
273 273 embedded_active = CBool(False)
274 274 editor = Unicode(get_default_editor(), config=True,
275 275 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
276 276 )
277 277 pager = Unicode('less', config=True,
278 278 help="The shell program to be used for paging.")
279 279
280 280 screen_length = Integer(0, config=True,
281 281 help=
282 282 """Number of lines of your screen, used to control printing of very
283 283 long strings. Strings longer than this number of lines will be sent
284 284 through a pager instead of directly printed. The default value for
285 285 this is 0, which means IPython will auto-detect your screen size every
286 286 time it needs to print certain potentially long strings (this doesn't
287 287 change the behavior of the 'print' keyword, it's only triggered
288 288 internally). If for some reason this isn't working well (it needs
289 289 curses support), specify it yourself. Otherwise don't change the
290 290 default.""",
291 291 )
292 292 term_title = CBool(False, config=True,
293 293 help="Enable auto setting the terminal title."
294 294 )
295 295
296 296 # This `using_paste_magics` is used to detect whether the code is being
297 297 # executed via paste magics functions
298 298 using_paste_magics = CBool(False)
299 299
300 300 # In the terminal, GUI control is done via PyOS_InputHook
301 301 @staticmethod
302 302 def enable_gui(gui=None, app=None):
303 303 """Switch amongst GUI input hooks by name.
304 304 """
305 305 # Deferred import
306 306 from IPython.lib.inputhook import enable_gui as real_enable_gui
307 try:
307 308 return real_enable_gui(gui, app)
309 except ValueError as e:
310 raise UsageError("%s" % e)
308 311
309 312 def __init__(self, config=None, ipython_dir=None, profile_dir=None,
310 313 user_ns=None, user_module=None, custom_exceptions=((),None),
311 314 usage=None, banner1=None, banner2=None, display_banner=None,
312 315 **kwargs):
313 316
314 317 super(TerminalInteractiveShell, self).__init__(
315 318 config=config, ipython_dir=ipython_dir, profile_dir=profile_dir, user_ns=user_ns,
316 319 user_module=user_module, custom_exceptions=custom_exceptions,
317 320 **kwargs
318 321 )
319 322 # use os.system instead of utils.process.system by default,
320 323 # because piped system doesn't make sense in the Terminal:
321 324 self.system = self.system_raw
322 325
323 326 self.init_term_title()
324 327 self.init_usage(usage)
325 328 self.init_banner(banner1, banner2, display_banner)
326 329
327 330 #-------------------------------------------------------------------------
328 331 # Overrides of init stages
329 332 #-------------------------------------------------------------------------
330 333
331 334 def init_display_formatter(self):
332 335 super(TerminalInteractiveShell, self).init_display_formatter()
333 336 # terminal only supports plaintext
334 337 self.display_formatter.active_types = ['text/plain']
335 338
336 339 #-------------------------------------------------------------------------
337 340 # Things related to the terminal
338 341 #-------------------------------------------------------------------------
339 342
340 343 @property
341 344 def usable_screen_length(self):
342 345 if self.screen_length == 0:
343 346 return 0
344 347 else:
345 348 num_lines_bot = self.separate_in.count('\n')+1
346 349 return self.screen_length - num_lines_bot
347 350
348 351 def init_term_title(self):
349 352 # Enable or disable the terminal title.
350 353 if self.term_title:
351 354 toggle_set_term_title(True)
352 355 set_term_title('IPython: ' + abbrev_cwd())
353 356 else:
354 357 toggle_set_term_title(False)
355 358
356 359 #-------------------------------------------------------------------------
357 360 # Things related to aliases
358 361 #-------------------------------------------------------------------------
359 362
360 363 def init_alias(self):
361 364 # The parent class defines aliases that can be safely used with any
362 365 # frontend.
363 366 super(TerminalInteractiveShell, self).init_alias()
364 367
365 368 # Now define aliases that only make sense on the terminal, because they
366 369 # need direct access to the console in a way that we can't emulate in
367 370 # GUI or web frontend
368 371 if os.name == 'posix':
369 372 aliases = [('clear', 'clear'), ('more', 'more'), ('less', 'less'),
370 373 ('man', 'man')]
371 374 elif os.name == 'nt':
372 375 aliases = [('cls', 'cls')]
373 376
374 377
375 378 for name, cmd in aliases:
376 379 self.alias_manager.define_alias(name, cmd)
377 380
378 381 #-------------------------------------------------------------------------
379 382 # Things related to the banner and usage
380 383 #-------------------------------------------------------------------------
381 384
382 385 def _banner1_changed(self):
383 386 self.compute_banner()
384 387
385 388 def _banner2_changed(self):
386 389 self.compute_banner()
387 390
388 391 def _term_title_changed(self, name, new_value):
389 392 self.init_term_title()
390 393
391 394 def init_banner(self, banner1, banner2, display_banner):
392 395 if banner1 is not None:
393 396 self.banner1 = banner1
394 397 if banner2 is not None:
395 398 self.banner2 = banner2
396 399 if display_banner is not None:
397 400 self.display_banner = display_banner
398 401 self.compute_banner()
399 402
400 403 def show_banner(self, banner=None):
401 404 if banner is None:
402 405 banner = self.banner
403 406 self.write(banner)
404 407
405 408 def compute_banner(self):
406 409 self.banner = self.banner1
407 410 if self.profile and self.profile != 'default':
408 411 self.banner += '\nIPython profile: %s\n' % self.profile
409 412 if self.banner2:
410 413 self.banner += '\n' + self.banner2
411 414
412 415 def init_usage(self, usage=None):
413 416 if usage is None:
414 417 self.usage = interactive_usage
415 418 else:
416 419 self.usage = usage
417 420
418 421 #-------------------------------------------------------------------------
419 422 # Mainloop and code execution logic
420 423 #-------------------------------------------------------------------------
421 424
422 425 def mainloop(self, display_banner=None):
423 426 """Start the mainloop.
424 427
425 428 If an optional banner argument is given, it will override the
426 429 internally created default banner.
427 430 """
428 431
429 432 with nested(self.builtin_trap, self.display_trap):
430 433
431 434 while 1:
432 435 try:
433 436 self.interact(display_banner=display_banner)
434 437 #self.interact_with_readline()
435 438 # XXX for testing of a readline-decoupled repl loop, call
436 439 # interact_with_readline above
437 440 break
438 441 except KeyboardInterrupt:
439 442 # this should not be necessary, but KeyboardInterrupt
440 443 # handling seems rather unpredictable...
441 444 self.write("\nKeyboardInterrupt in interact()\n")
442 445
443 446 def _replace_rlhist_multiline(self, source_raw, hlen_before_cell):
444 447 """Store multiple lines as a single entry in history"""
445 448
446 449 # do nothing without readline or disabled multiline
447 450 if not self.has_readline or not self.multiline_history:
448 451 return hlen_before_cell
449 452
450 453 # windows rl has no remove_history_item
451 454 if not hasattr(self.readline, "remove_history_item"):
452 455 return hlen_before_cell
453 456
454 457 # skip empty cells
455 458 if not source_raw.rstrip():
456 459 return hlen_before_cell
457 460
458 461 # nothing changed do nothing, e.g. when rl removes consecutive dups
459 462 hlen = self.readline.get_current_history_length()
460 463 if hlen == hlen_before_cell:
461 464 return hlen_before_cell
462 465
463 466 for i in range(hlen - hlen_before_cell):
464 467 self.readline.remove_history_item(hlen - i - 1)
465 468 stdin_encoding = get_stream_enc(sys.stdin, 'utf-8')
466 469 self.readline.add_history(py3compat.unicode_to_str(source_raw.rstrip(),
467 470 stdin_encoding))
468 471 return self.readline.get_current_history_length()
469 472
470 473 def interact(self, display_banner=None):
471 474 """Closely emulate the interactive Python console."""
472 475
473 476 # batch run -> do not interact
474 477 if self.exit_now:
475 478 return
476 479
477 480 if display_banner is None:
478 481 display_banner = self.display_banner
479 482
480 483 if isinstance(display_banner, basestring):
481 484 self.show_banner(display_banner)
482 485 elif display_banner:
483 486 self.show_banner()
484 487
485 488 more = False
486 489
487 490 if self.has_readline:
488 491 self.readline_startup_hook(self.pre_readline)
489 492 hlen_b4_cell = self.readline.get_current_history_length()
490 493 else:
491 494 hlen_b4_cell = 0
492 495 # exit_now is set by a call to %Exit or %Quit, through the
493 496 # ask_exit callback.
494 497
495 498 while not self.exit_now:
496 499 self.hooks.pre_prompt_hook()
497 500 if more:
498 501 try:
499 502 prompt = self.prompt_manager.render('in2')
500 503 except:
501 504 self.showtraceback()
502 505 if self.autoindent:
503 506 self.rl_do_indent = True
504 507
505 508 else:
506 509 try:
507 510 prompt = self.separate_in + self.prompt_manager.render('in')
508 511 except:
509 512 self.showtraceback()
510 513 try:
511 514 line = self.raw_input(prompt)
512 515 if self.exit_now:
513 516 # quick exit on sys.std[in|out] close
514 517 break
515 518 if self.autoindent:
516 519 self.rl_do_indent = False
517 520
518 521 except KeyboardInterrupt:
519 522 #double-guard against keyboardinterrupts during kbdint handling
520 523 try:
521 524 self.write('\nKeyboardInterrupt\n')
522 525 source_raw = self.input_splitter.source_raw_reset()[1]
523 526 hlen_b4_cell = \
524 527 self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
525 528 more = False
526 529 except KeyboardInterrupt:
527 530 pass
528 531 except EOFError:
529 532 if self.autoindent:
530 533 self.rl_do_indent = False
531 534 if self.has_readline:
532 535 self.readline_startup_hook(None)
533 536 self.write('\n')
534 537 self.exit()
535 538 except bdb.BdbQuit:
536 539 warn('The Python debugger has exited with a BdbQuit exception.\n'
537 540 'Because of how pdb handles the stack, it is impossible\n'
538 541 'for IPython to properly format this particular exception.\n'
539 542 'IPython will resume normal operation.')
540 543 except:
541 544 # exceptions here are VERY RARE, but they can be triggered
542 545 # asynchronously by signal handlers, for example.
543 546 self.showtraceback()
544 547 else:
545 548 self.input_splitter.push(line)
546 549 more = self.input_splitter.push_accepts_more()
547 550 if (self.SyntaxTB.last_syntax_error and
548 551 self.autoedit_syntax):
549 552 self.edit_syntax_error()
550 553 if not more:
551 554 source_raw = self.input_splitter.source_raw_reset()[1]
552 555 self.run_cell(source_raw, store_history=True)
553 556 hlen_b4_cell = \
554 557 self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
555 558
556 559 # Turn off the exit flag, so the mainloop can be restarted if desired
557 560 self.exit_now = False
558 561
559 562 def raw_input(self, prompt=''):
560 563 """Write a prompt and read a line.
561 564
562 565 The returned line does not include the trailing newline.
563 566 When the user enters the EOF key sequence, EOFError is raised.
564 567
565 568 Optional inputs:
566 569
567 570 - prompt(''): a string to be printed to prompt the user.
568 571
569 572 - continue_prompt(False): whether this line is the first one or a
570 573 continuation in a sequence of inputs.
571 574 """
572 575 # Code run by the user may have modified the readline completer state.
573 576 # We must ensure that our completer is back in place.
574 577
575 578 if self.has_readline:
576 579 self.set_readline_completer()
577 580
578 581 # raw_input expects str, but we pass it unicode sometimes
579 582 prompt = py3compat.cast_bytes_py2(prompt)
580 583
581 584 try:
582 585 line = py3compat.str_to_unicode(self.raw_input_original(prompt))
583 586 except ValueError:
584 587 warn("\n********\nYou or a %run:ed script called sys.stdin.close()"
585 588 " or sys.stdout.close()!\nExiting IPython!\n")
586 589 self.ask_exit()
587 590 return ""
588 591
589 592 # Try to be reasonably smart about not re-indenting pasted input more
590 593 # than necessary. We do this by trimming out the auto-indent initial
591 594 # spaces, if the user's actual input started itself with whitespace.
592 595 if self.autoindent:
593 596 if num_ini_spaces(line) > self.indent_current_nsp:
594 597 line = line[self.indent_current_nsp:]
595 598 self.indent_current_nsp = 0
596 599
597 600 return line
598 601
599 602 #-------------------------------------------------------------------------
600 603 # Methods to support auto-editing of SyntaxErrors.
601 604 #-------------------------------------------------------------------------
602 605
603 606 def edit_syntax_error(self):
604 607 """The bottom half of the syntax error handler called in the main loop.
605 608
606 609 Loop until syntax error is fixed or user cancels.
607 610 """
608 611
609 612 while self.SyntaxTB.last_syntax_error:
610 613 # copy and clear last_syntax_error
611 614 err = self.SyntaxTB.clear_err_state()
612 615 if not self._should_recompile(err):
613 616 return
614 617 try:
615 618 # may set last_syntax_error again if a SyntaxError is raised
616 619 self.safe_execfile(err.filename,self.user_ns)
617 620 except:
618 621 self.showtraceback()
619 622 else:
620 623 try:
621 624 f = open(err.filename)
622 625 try:
623 626 # This should be inside a display_trap block and I
624 627 # think it is.
625 628 sys.displayhook(f.read())
626 629 finally:
627 630 f.close()
628 631 except:
629 632 self.showtraceback()
630 633
631 634 def _should_recompile(self,e):
632 635 """Utility routine for edit_syntax_error"""
633 636
634 637 if e.filename in ('<ipython console>','<input>','<string>',
635 638 '<console>','<BackgroundJob compilation>',
636 639 None):
637 640
638 641 return False
639 642 try:
640 643 if (self.autoedit_syntax and
641 644 not self.ask_yes_no('Return to editor to correct syntax error? '
642 645 '[Y/n] ','y')):
643 646 return False
644 647 except EOFError:
645 648 return False
646 649
647 650 def int0(x):
648 651 try:
649 652 return int(x)
650 653 except TypeError:
651 654 return 0
652 655 # always pass integer line and offset values to editor hook
653 656 try:
654 657 self.hooks.fix_error_editor(e.filename,
655 658 int0(e.lineno),int0(e.offset),e.msg)
656 659 except TryNext:
657 660 warn('Could not open editor')
658 661 return False
659 662 return True
660 663
661 664 #-------------------------------------------------------------------------
662 665 # Things related to exiting
663 666 #-------------------------------------------------------------------------
664 667
665 668 def ask_exit(self):
666 669 """ Ask the shell to exit. Can be overiden and used as a callback. """
667 670 self.exit_now = True
668 671
669 672 def exit(self):
670 673 """Handle interactive exit.
671 674
672 675 This method calls the ask_exit callback."""
673 676 if self.confirm_exit:
674 677 if self.ask_yes_no('Do you really want to exit ([y]/n)?','y'):
675 678 self.ask_exit()
676 679 else:
677 680 self.ask_exit()
678 681
679 682 #-------------------------------------------------------------------------
680 683 # Things related to magics
681 684 #-------------------------------------------------------------------------
682 685
683 686 def init_magics(self):
684 687 super(TerminalInteractiveShell, self).init_magics()
685 688 self.register_magics(TerminalMagics)
686 689
687 690 def showindentationerror(self):
688 691 super(TerminalInteractiveShell, self).showindentationerror()
689 692 if not self.using_paste_magics:
690 693 print("If you want to paste code into IPython, try the "
691 694 "%paste and %cpaste magic functions.")
692 695
693 696
694 697 InteractiveShellABC.register(TerminalInteractiveShell)
General Comments 0
You need to be logged in to leave comments. Login now