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