##// END OF EJS Templates
__builtin__.exit and quit are now hidden - exit magic is now the only exit command
Erik Tollerud -
Show More
@@ -1,120 +1,127 b''
1 1 """
2 2 A context manager for managing things injected into :mod:`__builtin__`.
3 3
4 4 Authors:
5 5
6 6 * Brian Granger
7 7 * Fernando Perez
8 8 """
9 9 #-----------------------------------------------------------------------------
10 10 # Copyright (C) 2010 The IPython Development Team.
11 11 #
12 12 # Distributed under the terms of the BSD License.
13 13 #
14 14 # Complete license in the file COPYING.txt, distributed with this software.
15 15 #-----------------------------------------------------------------------------
16 16
17 17 #-----------------------------------------------------------------------------
18 18 # Imports
19 19 #-----------------------------------------------------------------------------
20 20
21 21 import __builtin__
22 22
23 23 from IPython.config.configurable import Configurable
24 24 from IPython.core.quitter import Quitter
25 25
26 26 from IPython.utils.traitlets import Instance
27 27
28 28 #-----------------------------------------------------------------------------
29 29 # Classes and functions
30 30 #-----------------------------------------------------------------------------
31 31
32 32 class __BuiltinUndefined(object): pass
33 33 BuiltinUndefined = __BuiltinUndefined()
34 34
35 class __HideBuiltin(object): pass
36 HideBuiltin = __HideBuiltin()
37
35 38
36 39 class BuiltinTrap(Configurable):
37 40
38 41 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
39 42
40 43 def __init__(self, shell=None):
41 44 super(BuiltinTrap, self).__init__(shell=shell, config=None)
42 45 self._orig_builtins = {}
43 46 # We define this to track if a single BuiltinTrap is nested.
44 47 # Only turn off the trap when the outermost call to __exit__ is made.
45 48 self._nested_level = 0
46 49 self.shell = shell
47 # builtins we always add
48 self.auto_builtins = {'exit': Quitter(self.shell, 'exit'),
49 'quit': Quitter(self.shell, 'quit'),
50 # builtins we always add - if set to HideBuiltin, they will just
51 # be removed instead of being replaced by something else
52 self.auto_builtins = {'exit': HideBuiltin,
53 'quit': HideBuiltin,
50 54 'get_ipython': self.shell.get_ipython,
51 55 }
52 56 # Recursive reload function
53 57 try:
54 58 from IPython.lib import deepreload
55 59 if self.shell.deep_reload:
56 60 self.auto_builtins['reload'] = deepreload.reload
57 61 else:
58 62 self.auto_builtins['dreload']= deepreload.reload
59 63 except ImportError:
60 64 pass
61 65
62 66 def __enter__(self):
63 67 if self._nested_level == 0:
64 68 self.activate()
65 69 self._nested_level += 1
66 70 # I return self, so callers can use add_builtin in a with clause.
67 71 return self
68 72
69 73 def __exit__(self, type, value, traceback):
70 74 if self._nested_level == 1:
71 75 self.deactivate()
72 76 self._nested_level -= 1
73 77 # Returning False will cause exceptions to propagate
74 78 return False
75 79
76 80 def add_builtin(self, key, value):
77 81 """Add a builtin and save the original."""
78 82 bdict = __builtin__.__dict__
79 83 orig = bdict.get(key, BuiltinUndefined)
80 84 self._orig_builtins[key] = orig
81 bdict[key] = value
85 if value is HideBuiltin:
86 del bdict[key]
87 else:
88 bdict[key] = value
82 89
83 90 def remove_builtin(self, key):
84 91 """Remove an added builtin and re-set the original."""
85 92 try:
86 93 orig = self._orig_builtins.pop(key)
87 94 except KeyError:
88 95 pass
89 96 else:
90 97 if orig is BuiltinUndefined:
91 98 del __builtin__.__dict__[key]
92 99 else:
93 100 __builtin__.__dict__[key] = orig
94 101
95 102 def activate(self):
96 103 """Store ipython references in the __builtin__ namespace."""
97 104
98 105 add_builtin = self.add_builtin
99 106 for name, func in self.auto_builtins.iteritems():
100 107 add_builtin(name, func)
101 108
102 109 # Keep in the builtins a flag for when IPython is active. We set it
103 110 # with setdefault so that multiple nested IPythons don't clobber one
104 111 # another.
105 112 __builtin__.__dict__.setdefault('__IPYTHON__active', 0)
106 113
107 114 def deactivate(self):
108 115 """Remove any builtins which might have been added by add_builtins, or
109 116 restore overwritten ones to their previous values."""
110 117 # Note: must iterate over a static keys() list because we'll be
111 118 # mutating the dict itself
112 119 remove_builtin = self.remove_builtin
113 120 for key in self._orig_builtins.keys():
114 121 remove_builtin(key)
115 122 self._orig_builtins.clear()
116 123 self._builtins_added = False
117 124 try:
118 125 del __builtin__.__dict__['__IPYTHON__active']
119 126 except KeyError:
120 127 pass
@@ -1,266 +1,270 b''
1 1 """ A minimal application using the Qt console-style IPython frontend.
2 2 """
3 3
4 4 #-----------------------------------------------------------------------------
5 5 # Imports
6 6 #-----------------------------------------------------------------------------
7 7
8 8 # Systemm library imports
9 9 from PyQt4 import QtGui
10 10 from pygments.styles import get_all_styles
11 11 # Local imports
12 12 from IPython.external.argparse import ArgumentParser
13 13 from IPython.frontend.qt.console.frontend_widget import FrontendWidget
14 14 from IPython.frontend.qt.console.ipython_widget import IPythonWidget
15 15 from IPython.frontend.qt.console.rich_ipython_widget import RichIPythonWidget
16 16 from IPython.frontend.qt.console import styles
17 17 from IPython.frontend.qt.kernelmanager import QtKernelManager
18 18
19 19 #-----------------------------------------------------------------------------
20 20 # Network Constants
21 21 #-----------------------------------------------------------------------------
22 22
23 23 from IPython.utils.localinterfaces import LOCALHOST, LOCAL_IPS
24 24
25 25 #-----------------------------------------------------------------------------
26 26 # Classes
27 27 #-----------------------------------------------------------------------------
28 28
29 29 class MainWindow(QtGui.QMainWindow):
30 30
31 31 #---------------------------------------------------------------------------
32 32 # 'object' interface
33 33 #---------------------------------------------------------------------------
34 34
35 35 def __init__(self, app, frontend, existing=False, may_close=True):
36 36 """ Create a MainWindow for the specified FrontendWidget.
37 37
38 38 The app is passed as an argument to allow for different
39 39 closing behavior depending on whether we are the Kernel's parent.
40 40
41 41 If existing is True, then this Console does not own the Kernel.
42 42
43 43 If may_close is True, then this Console is permitted to close the kernel
44 44 """
45 45 super(MainWindow, self).__init__()
46 46 self._app = app
47 47 self._frontend = frontend
48 48 self._existing = existing
49 49 if existing:
50 50 self._may_close = may_close
51 51 else:
52 52 self._may_close = True
53 53 self._frontend.exit_requested.connect(self.close)
54 54 self.setCentralWidget(frontend)
55 55
56 56 #---------------------------------------------------------------------------
57 57 # QWidget interface
58 58 #---------------------------------------------------------------------------
59 59
60 60 def closeEvent(self, event):
61 """ Reimplemented to prompt the user and close the kernel cleanly.
61 """ Reimplemented to prompt the user and close the kernel cleanly, or
62 close without prompt only if the exit magic is used.
62 63 """
63 keepkernel = self._frontend._keep_kernel_on_exit
64 keepkernel = None #Use the prompt by default
65 if hasattr(self._frontend,'_keep_kernel_on_exit'): #set by exit magic
66 keepkernel = self._frontend._keep_kernel_on_exit
67
64 68 kernel_manager = self._frontend.kernel_manager
65 69
66 if keepkernel is None:
70 if keepkernel is None: #show prompt
67 71 if kernel_manager and kernel_manager.channels_running:
68 72 title = self.window().windowTitle()
69 73 cancel = QtGui.QMessageBox.Cancel
70 74 okay = QtGui.QMessageBox.Ok
71 75 if self._may_close:
72 76 msg = "You are closing this Console window."
73 77 info = "Would you like to quit the Kernel and all attached Consoles as well?"
74 78 justthis = QtGui.QPushButton("&No, just this Console", self)
75 79 justthis.setShortcut('N')
76 80 closeall = QtGui.QPushButton("&Yes, quit everything", self)
77 81 closeall.setShortcut('Y')
78 82 box = QtGui.QMessageBox(QtGui.QMessageBox.Question, title, msg)
79 83 box.setInformativeText(info)
80 84 box.addButton(cancel)
81 85 box.addButton(justthis, QtGui.QMessageBox.NoRole)
82 86 box.addButton(closeall, QtGui.QMessageBox.YesRole)
83 87 box.setDefaultButton(closeall)
84 88 box.setEscapeButton(cancel)
85 89 reply = box.exec_()
86 90 if reply == 1: # close All
87 91 kernel_manager.shutdown_kernel()
88 92 #kernel_manager.stop_channels()
89 93 event.accept()
90 94 elif reply == 0: # close Console
91 95 if not self._existing:
92 96 # Have kernel: don't quit, just close the window
93 97 self._app.setQuitOnLastWindowClosed(False)
94 98 self.deleteLater()
95 99 event.accept()
96 100 else:
97 101 event.ignore()
98 102 else:
99 103 reply = QtGui.QMessageBox.question(self, title,
100 104 "Are you sure you want to close this Console?"+
101 105 "\nThe Kernel and other Consoles will remain active.",
102 106 okay|cancel,
103 107 defaultButton=okay
104 108 )
105 109 if reply == okay:
106 110 event.accept()
107 111 else:
108 112 event.ignore()
109 elif keepkernel: #close console but leave kernel running
113 elif keepkernel: #close console but leave kernel running (no prompt)
110 114 if kernel_manager and kernel_manager.channels_running:
111 115 if not self._existing:
112 116 # I have the kernel: don't quit, just close the window
113 117 self._app.setQuitOnLastWindowClosed(False)
114 118 event.accept()
115 else: #close console and kernel
119 else: #close console and kernel (no prompt)
116 120 if kernel_manager and kernel_manager.channels_running:
117 121 kernel_manager.shutdown_kernel()
118 122 event.accept()
119 123
120 124 #-----------------------------------------------------------------------------
121 125 # Main entry point
122 126 #-----------------------------------------------------------------------------
123 127
124 128 def main():
125 129 """ Entry point for application.
126 130 """
127 131 # Parse command line arguments.
128 132 parser = ArgumentParser()
129 133 kgroup = parser.add_argument_group('kernel options')
130 134 kgroup.add_argument('-e', '--existing', action='store_true',
131 135 help='connect to an existing kernel')
132 136 kgroup.add_argument('--ip', type=str, default=LOCALHOST,
133 137 help=\
134 138 "set the kernel\'s IP address [default localhost].\
135 139 If the IP address is something other than localhost, then \
136 140 Consoles on other machines will be able to connect\
137 141 to the Kernel, so be careful!")
138 142 kgroup.add_argument('--xreq', type=int, metavar='PORT', default=0,
139 143 help='set the XREQ channel port [default random]')
140 144 kgroup.add_argument('--sub', type=int, metavar='PORT', default=0,
141 145 help='set the SUB channel port [default random]')
142 146 kgroup.add_argument('--rep', type=int, metavar='PORT', default=0,
143 147 help='set the REP channel port [default random]')
144 148 kgroup.add_argument('--hb', type=int, metavar='PORT', default=0,
145 149 help='set the heartbeat port [default random]')
146 150
147 151 egroup = kgroup.add_mutually_exclusive_group()
148 152 egroup.add_argument('--pure', action='store_true', help = \
149 153 'use a pure Python kernel instead of an IPython kernel')
150 154 egroup.add_argument('--pylab', type=str, metavar='GUI', nargs='?',
151 155 const='auto', help = \
152 156 "Pre-load matplotlib and numpy for interactive use. If GUI is not \
153 157 given, the GUI backend is matplotlib's, otherwise use one of: \
154 158 ['tk', 'gtk', 'qt', 'wx', 'inline'].")
155 159
156 160 wgroup = parser.add_argument_group('widget options')
157 161 wgroup.add_argument('--paging', type=str, default='inside',
158 162 choices = ['inside', 'hsplit', 'vsplit', 'none'],
159 163 help='set the paging style [default inside]')
160 164 wgroup.add_argument('--rich', action='store_true',
161 165 help='enable rich text support')
162 166 wgroup.add_argument('--gui-completion', action='store_true',
163 167 help='use a GUI widget for tab completion')
164 168 wgroup.add_argument('--style', type=str,
165 169 choices = list(get_all_styles()),
166 170 help='specify a pygments style for by name.')
167 171 wgroup.add_argument('--stylesheet', type=str,
168 172 help="path to a custom CSS stylesheet.")
169 173 wgroup.add_argument('--colors', type=str,
170 174 help="Set the color scheme (LightBG,Linux,NoColor). This is guessed\
171 175 based on the pygments style if not set.")
172 176
173 177 args = parser.parse_args()
174 178
175 179 # parse the colors arg down to current known labels
176 180 if args.colors:
177 181 colors=args.colors.lower()
178 182 if colors in ('lightbg', 'light'):
179 183 colors='lightbg'
180 184 elif colors in ('dark', 'linux'):
181 185 colors='linux'
182 186 else:
183 187 colors='nocolor'
184 188 elif args.style:
185 189 if args.style=='bw':
186 190 colors='nocolor'
187 191 elif styles.dark_style(args.style):
188 192 colors='linux'
189 193 else:
190 194 colors='lightbg'
191 195 else:
192 196 colors=None
193 197
194 198 # Don't let Qt or ZMQ swallow KeyboardInterupts.
195 199 import signal
196 200 signal.signal(signal.SIGINT, signal.SIG_DFL)
197 201
198 202 # Create a KernelManager and start a kernel.
199 203 kernel_manager = QtKernelManager(xreq_address=(args.ip, args.xreq),
200 204 sub_address=(args.ip, args.sub),
201 205 rep_address=(args.ip, args.rep),
202 206 hb_address=(args.ip, args.hb))
203 207 if not args.existing:
204 208 # if not args.ip in LOCAL_IPS+ALL_ALIAS:
205 209 # raise ValueError("Must bind a local ip, such as: %s"%LOCAL_IPS)
206 210
207 211 kwargs = dict(ip=args.ip)
208 212 if args.pure:
209 213 kwargs['ipython']=False
210 214 else:
211 215 kwargs['colors']=colors
212 216 if args.pylab:
213 217 kwargs['pylab']=args.pylab
214 218
215 219 kernel_manager.start_kernel(**kwargs)
216 220 kernel_manager.start_channels()
217 221
218 222 local_kernel = (not args.existing) or args.ip in LOCAL_IPS
219 223 # Create the widget.
220 224 app = QtGui.QApplication([])
221 225 if args.pure:
222 226 kind = 'rich' if args.rich else 'plain'
223 227 widget = FrontendWidget(kind=kind, paging=args.paging, local_kernel=local_kernel)
224 228 elif args.rich or args.pylab:
225 229 widget = RichIPythonWidget(paging=args.paging, local_kernel=local_kernel)
226 230 else:
227 231 widget = IPythonWidget(paging=args.paging, local_kernel=local_kernel)
228 232 widget.gui_completion = args.gui_completion
229 233 widget.kernel_manager = kernel_manager
230 234
231 235 # configure the style:
232 236 if not args.pure: # only IPythonWidget supports styles
233 237 if args.style:
234 238 widget.syntax_style = args.style
235 239 widget.style_sheet = styles.sheet_from_template(args.style, colors)
236 240 widget._syntax_style_changed()
237 241 widget._style_sheet_changed()
238 242 elif colors:
239 243 # use a default style
240 244 widget.set_default_style(colors=colors)
241 245 else:
242 246 # this is redundant for now, but allows the widget's
243 247 # defaults to change
244 248 widget.set_default_style()
245 249
246 250 if args.stylesheet:
247 251 # we got an expicit stylesheet
248 252 if os.path.isfile(args.stylesheet):
249 253 with open(args.stylesheet) as f:
250 254 sheet = f.read()
251 255 widget.style_sheet = sheet
252 256 widget._style_sheet_changed()
253 257 else:
254 258 raise IOError("Stylesheet %r not found."%args.stylesheet)
255 259
256 260 # Create the main window.
257 261 window = MainWindow(app, widget, args.existing, may_close=local_kernel)
258 262 window.setWindowTitle('Python' if args.pure else 'IPython')
259 263 window.show()
260 264
261 265 # Start the application main loop.
262 266 app.exec_()
263 267
264 268
265 269 if __name__ == '__main__':
266 270 main()
@@ -1,580 +1,580 b''
1 1 """A ZMQ-based subclass of InteractiveShell.
2 2
3 3 This code is meant to ease the refactoring of the base InteractiveShell into
4 4 something with a cleaner architecture for 2-process use, without actually
5 5 breaking InteractiveShell itself. So we're doing something a bit ugly, where
6 6 we subclass and override what we want to fix. Once this is working well, we
7 7 can go back to the base class and refactor the code for a cleaner inheritance
8 8 implementation that doesn't rely on so much monkeypatching.
9 9
10 10 But this lets us maintain a fully working IPython as we develop the new
11 11 machinery. This should thus be thought of as scaffolding.
12 12 """
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16 from __future__ import print_function
17 17
18 18 # Stdlib
19 19 import inspect
20 20 import os
21 21 import re
22 22
23 23 # Our own
24 24 from IPython.core.interactiveshell import (
25 25 InteractiveShell, InteractiveShellABC
26 26 )
27 27 from IPython.core import page
28 28 from IPython.core.displayhook import DisplayHook
29 29 from IPython.core.macro import Macro
30 30 from IPython.core.payloadpage import install_payload_page
31 31 from IPython.utils import io
32 32 from IPython.utils.path import get_py_filename
33 33 from IPython.utils.text import StringTypes
34 34 from IPython.utils.traitlets import Instance, Type, Dict
35 35 from IPython.utils.warn import warn
36 36 from IPython.zmq.session import extract_header
37 37 from session import Session
38 38
39 39 #-----------------------------------------------------------------------------
40 40 # Globals and side-effects
41 41 #-----------------------------------------------------------------------------
42 42
43 43 # Install the payload version of page.
44 44 install_payload_page()
45 45
46 46 #-----------------------------------------------------------------------------
47 47 # Functions and classes
48 48 #-----------------------------------------------------------------------------
49 49
50 50 class ZMQDisplayHook(DisplayHook):
51 51
52 52 session = Instance(Session)
53 53 pub_socket = Instance('zmq.Socket')
54 54 parent_header = Dict({})
55 55
56 56 def set_parent(self, parent):
57 57 """Set the parent for outbound messages."""
58 58 self.parent_header = extract_header(parent)
59 59
60 60 def start_displayhook(self):
61 61 self.msg = self.session.msg(u'pyout', {}, parent=self.parent_header)
62 62
63 63 def write_output_prompt(self):
64 64 """Write the output prompt."""
65 65 if self.do_full_cache:
66 66 self.msg['content']['execution_count'] = self.prompt_count
67 67
68 68 def write_result_repr(self, result_repr):
69 69 self.msg['content']['data'] = result_repr
70 70
71 71 def finish_displayhook(self):
72 72 """Finish up all displayhook activities."""
73 73 self.pub_socket.send_json(self.msg)
74 74 self.msg = None
75 75
76 76
77 77 class ZMQInteractiveShell(InteractiveShell):
78 78 """A subclass of InteractiveShell for ZMQ."""
79 79
80 80 displayhook_class = Type(ZMQDisplayHook)
81 keepkernel = None
81 keepkernel_on_exit = None
82 82
83 83 def init_environment(self):
84 84 """Configure the user's environment.
85 85
86 86 """
87 87 env = os.environ
88 88 # These two ensure 'ls' produces nice coloring on BSD-derived systems
89 89 env['TERM'] = 'xterm-color'
90 90 env['CLICOLOR'] = '1'
91 91 # Since normal pagers don't work at all (over pexpect we don't have
92 92 # single-key control of the subprocess), try to disable paging in
93 93 # subprocesses as much as possible.
94 94 env['PAGER'] = 'cat'
95 95 env['GIT_PAGER'] = 'cat'
96 96
97 97 def auto_rewrite_input(self, cmd):
98 98 """Called to show the auto-rewritten input for autocall and friends.
99 99
100 100 FIXME: this payload is currently not correctly processed by the
101 101 frontend.
102 102 """
103 103 new = self.displayhook.prompt1.auto_rewrite() + cmd
104 104 payload = dict(
105 105 source='IPython.zmq.zmqshell.ZMQInteractiveShell.auto_rewrite_input',
106 106 transformed_input=new,
107 107 )
108 108 self.payload_manager.write_payload(payload)
109 109
110 110 def ask_exit(self):
111 111 """Engage the exit actions."""
112 112 payload = dict(
113 113 source='IPython.zmq.zmqshell.ZMQInteractiveShell.ask_exit',
114 114 exit=True,
115 keepkernel=self.keepkernel,
115 keepkernel=self.keepkernel_on_exit,
116 116 )
117 117 self.payload_manager.write_payload(payload)
118 118
119 119 def _showtraceback(self, etype, evalue, stb):
120 120
121 121 exc_content = {
122 122 u'traceback' : stb,
123 123 u'ename' : unicode(etype.__name__),
124 124 u'evalue' : unicode(evalue)
125 125 }
126 126
127 127 dh = self.displayhook
128 128 exc_msg = dh.session.msg(u'pyerr', exc_content, dh.parent_header)
129 129 # Send exception info over pub socket for other clients than the caller
130 130 # to pick up
131 131 dh.pub_socket.send_json(exc_msg)
132 132
133 133 # FIXME - Hack: store exception info in shell object. Right now, the
134 134 # caller is reading this info after the fact, we need to fix this logic
135 135 # to remove this hack. Even uglier, we need to store the error status
136 136 # here, because in the main loop, the logic that sets it is being
137 137 # skipped because runlines swallows the exceptions.
138 138 exc_content[u'status'] = u'error'
139 139 self._reply_content = exc_content
140 140 # /FIXME
141 141
142 142 return exc_content
143 143
144 144 #------------------------------------------------------------------------
145 145 # Magic overrides
146 146 #------------------------------------------------------------------------
147 147 # Once the base class stops inheriting from magic, this code needs to be
148 148 # moved into a separate machinery as well. For now, at least isolate here
149 149 # the magics which this class needs to implement differently from the base
150 150 # class, or that are unique to it.
151 151
152 152 def magic_doctest_mode(self,parameter_s=''):
153 153 """Toggle doctest mode on and off.
154 154
155 155 This mode is intended to make IPython behave as much as possible like a
156 156 plain Python shell, from the perspective of how its prompts, exceptions
157 157 and output look. This makes it easy to copy and paste parts of a
158 158 session into doctests. It does so by:
159 159
160 160 - Changing the prompts to the classic ``>>>`` ones.
161 161 - Changing the exception reporting mode to 'Plain'.
162 162 - Disabling pretty-printing of output.
163 163
164 164 Note that IPython also supports the pasting of code snippets that have
165 165 leading '>>>' and '...' prompts in them. This means that you can paste
166 166 doctests from files or docstrings (even if they have leading
167 167 whitespace), and the code will execute correctly. You can then use
168 168 '%history -t' to see the translated history; this will give you the
169 169 input after removal of all the leading prompts and whitespace, which
170 170 can be pasted back into an editor.
171 171
172 172 With these features, you can switch into this mode easily whenever you
173 173 need to do testing and changes to doctests, without having to leave
174 174 your existing IPython session.
175 175 """
176 176
177 177 from IPython.utils.ipstruct import Struct
178 178
179 179 # Shorthands
180 180 shell = self.shell
181 181 # dstore is a data store kept in the instance metadata bag to track any
182 182 # changes we make, so we can undo them later.
183 183 dstore = shell.meta.setdefault('doctest_mode', Struct())
184 184 save_dstore = dstore.setdefault
185 185
186 186 # save a few values we'll need to recover later
187 187 mode = save_dstore('mode', False)
188 188 save_dstore('rc_pprint', shell.pprint)
189 189 save_dstore('xmode', shell.InteractiveTB.mode)
190 190
191 191 if mode == False:
192 192 # turn on
193 193 shell.pprint = False
194 194 shell.magic_xmode('Plain')
195 195 else:
196 196 # turn off
197 197 shell.pprint = dstore.rc_pprint
198 198 shell.magic_xmode(dstore.xmode)
199 199
200 200 # Store new mode and inform on console
201 201 dstore.mode = bool(1-int(mode))
202 202 mode_label = ['OFF','ON'][dstore.mode]
203 203 print('Doctest mode is:', mode_label)
204 204
205 205 # Send the payload back so that clients can modify their prompt display
206 206 payload = dict(
207 207 source='IPython.zmq.zmqshell.ZMQInteractiveShell.magic_doctest_mode',
208 208 mode=dstore.mode)
209 209 self.payload_manager.write_payload(payload)
210 210
211 211 def magic_edit(self,parameter_s='',last_call=['','']):
212 212 """Bring up an editor and execute the resulting code.
213 213
214 214 Usage:
215 215 %edit [options] [args]
216 216
217 217 %edit runs IPython's editor hook. The default version of this hook is
218 218 set to call the __IPYTHON__.rc.editor command. This is read from your
219 219 environment variable $EDITOR. If this isn't found, it will default to
220 220 vi under Linux/Unix and to notepad under Windows. See the end of this
221 221 docstring for how to change the editor hook.
222 222
223 223 You can also set the value of this editor via the command line option
224 224 '-editor' or in your ipythonrc file. This is useful if you wish to use
225 225 specifically for IPython an editor different from your typical default
226 226 (and for Windows users who typically don't set environment variables).
227 227
228 228 This command allows you to conveniently edit multi-line code right in
229 229 your IPython session.
230 230
231 231 If called without arguments, %edit opens up an empty editor with a
232 232 temporary file and will execute the contents of this file when you
233 233 close it (don't forget to save it!).
234 234
235 235
236 236 Options:
237 237
238 238 -n <number>: open the editor at a specified line number. By default,
239 239 the IPython editor hook uses the unix syntax 'editor +N filename', but
240 240 you can configure this by providing your own modified hook if your
241 241 favorite editor supports line-number specifications with a different
242 242 syntax.
243 243
244 244 -p: this will call the editor with the same data as the previous time
245 245 it was used, regardless of how long ago (in your current session) it
246 246 was.
247 247
248 248 -r: use 'raw' input. This option only applies to input taken from the
249 249 user's history. By default, the 'processed' history is used, so that
250 250 magics are loaded in their transformed version to valid Python. If
251 251 this option is given, the raw input as typed as the command line is
252 252 used instead. When you exit the editor, it will be executed by
253 253 IPython's own processor.
254 254
255 255 -x: do not execute the edited code immediately upon exit. This is
256 256 mainly useful if you are editing programs which need to be called with
257 257 command line arguments, which you can then do using %run.
258 258
259 259
260 260 Arguments:
261 261
262 262 If arguments are given, the following possibilites exist:
263 263
264 264 - The arguments are numbers or pairs of colon-separated numbers (like
265 265 1 4:8 9). These are interpreted as lines of previous input to be
266 266 loaded into the editor. The syntax is the same of the %macro command.
267 267
268 268 - If the argument doesn't start with a number, it is evaluated as a
269 269 variable and its contents loaded into the editor. You can thus edit
270 270 any string which contains python code (including the result of
271 271 previous edits).
272 272
273 273 - If the argument is the name of an object (other than a string),
274 274 IPython will try to locate the file where it was defined and open the
275 275 editor at the point where it is defined. You can use `%edit function`
276 276 to load an editor exactly at the point where 'function' is defined,
277 277 edit it and have the file be executed automatically.
278 278
279 279 If the object is a macro (see %macro for details), this opens up your
280 280 specified editor with a temporary file containing the macro's data.
281 281 Upon exit, the macro is reloaded with the contents of the file.
282 282
283 283 Note: opening at an exact line is only supported under Unix, and some
284 284 editors (like kedit and gedit up to Gnome 2.8) do not understand the
285 285 '+NUMBER' parameter necessary for this feature. Good editors like
286 286 (X)Emacs, vi, jed, pico and joe all do.
287 287
288 288 - If the argument is not found as a variable, IPython will look for a
289 289 file with that name (adding .py if necessary) and load it into the
290 290 editor. It will execute its contents with execfile() when you exit,
291 291 loading any code in the file into your interactive namespace.
292 292
293 293 After executing your code, %edit will return as output the code you
294 294 typed in the editor (except when it was an existing file). This way
295 295 you can reload the code in further invocations of %edit as a variable,
296 296 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
297 297 the output.
298 298
299 299 Note that %edit is also available through the alias %ed.
300 300
301 301 This is an example of creating a simple function inside the editor and
302 302 then modifying it. First, start up the editor:
303 303
304 304 In [1]: ed
305 305 Editing... done. Executing edited code...
306 306 Out[1]: 'def foo():n print "foo() was defined in an editing session"n'
307 307
308 308 We can then call the function foo():
309 309
310 310 In [2]: foo()
311 311 foo() was defined in an editing session
312 312
313 313 Now we edit foo. IPython automatically loads the editor with the
314 314 (temporary) file where foo() was previously defined:
315 315
316 316 In [3]: ed foo
317 317 Editing... done. Executing edited code...
318 318
319 319 And if we call foo() again we get the modified version:
320 320
321 321 In [4]: foo()
322 322 foo() has now been changed!
323 323
324 324 Here is an example of how to edit a code snippet successive
325 325 times. First we call the editor:
326 326
327 327 In [5]: ed
328 328 Editing... done. Executing edited code...
329 329 hello
330 330 Out[5]: "print 'hello'n"
331 331
332 332 Now we call it again with the previous output (stored in _):
333 333
334 334 In [6]: ed _
335 335 Editing... done. Executing edited code...
336 336 hello world
337 337 Out[6]: "print 'hello world'n"
338 338
339 339 Now we call it with the output #8 (stored in _8, also as Out[8]):
340 340
341 341 In [7]: ed _8
342 342 Editing... done. Executing edited code...
343 343 hello again
344 344 Out[7]: "print 'hello again'n"
345 345
346 346
347 347 Changing the default editor hook:
348 348
349 349 If you wish to write your own editor hook, you can put it in a
350 350 configuration file which you load at startup time. The default hook
351 351 is defined in the IPython.core.hooks module, and you can use that as a
352 352 starting example for further modifications. That file also has
353 353 general instructions on how to set a new hook for use once you've
354 354 defined it."""
355 355
356 356 # FIXME: This function has become a convoluted mess. It needs a
357 357 # ground-up rewrite with clean, simple logic.
358 358
359 359 def make_filename(arg):
360 360 "Make a filename from the given args"
361 361 try:
362 362 filename = get_py_filename(arg)
363 363 except IOError:
364 364 if args.endswith('.py'):
365 365 filename = arg
366 366 else:
367 367 filename = None
368 368 return filename
369 369
370 370 # custom exceptions
371 371 class DataIsObject(Exception): pass
372 372
373 373 opts,args = self.parse_options(parameter_s,'prn:')
374 374 # Set a few locals from the options for convenience:
375 375 opts_p = opts.has_key('p')
376 376 opts_r = opts.has_key('r')
377 377
378 378 # Default line number value
379 379 lineno = opts.get('n',None)
380 380 if lineno is not None:
381 381 try:
382 382 lineno = int(lineno)
383 383 except:
384 384 warn("The -n argument must be an integer.")
385 385 return
386 386
387 387 if opts_p:
388 388 args = '_%s' % last_call[0]
389 389 if not self.shell.user_ns.has_key(args):
390 390 args = last_call[1]
391 391
392 392 # use last_call to remember the state of the previous call, but don't
393 393 # let it be clobbered by successive '-p' calls.
394 394 try:
395 395 last_call[0] = self.shell.displayhook.prompt_count
396 396 if not opts_p:
397 397 last_call[1] = parameter_s
398 398 except:
399 399 pass
400 400
401 401 # by default this is done with temp files, except when the given
402 402 # arg is a filename
403 403 use_temp = 1
404 404
405 405 if re.match(r'\d',args):
406 406 # Mode where user specifies ranges of lines, like in %macro.
407 407 # This means that you can't edit files whose names begin with
408 408 # numbers this way. Tough.
409 409 ranges = args.split()
410 410 data = ''.join(self.extract_input_slices(ranges,opts_r))
411 411 elif args.endswith('.py'):
412 412 filename = make_filename(args)
413 413 data = ''
414 414 use_temp = 0
415 415 elif args:
416 416 try:
417 417 # Load the parameter given as a variable. If not a string,
418 418 # process it as an object instead (below)
419 419
420 420 #print '*** args',args,'type',type(args) # dbg
421 421 data = eval(args,self.shell.user_ns)
422 422 if not type(data) in StringTypes:
423 423 raise DataIsObject
424 424
425 425 except (NameError,SyntaxError):
426 426 # given argument is not a variable, try as a filename
427 427 filename = make_filename(args)
428 428 if filename is None:
429 429 warn("Argument given (%s) can't be found as a variable "
430 430 "or as a filename." % args)
431 431 return
432 432
433 433 data = ''
434 434 use_temp = 0
435 435 except DataIsObject:
436 436
437 437 # macros have a special edit function
438 438 if isinstance(data,Macro):
439 439 self._edit_macro(args,data)
440 440 return
441 441
442 442 # For objects, try to edit the file where they are defined
443 443 try:
444 444 filename = inspect.getabsfile(data)
445 445 if 'fakemodule' in filename.lower() and inspect.isclass(data):
446 446 # class created by %edit? Try to find source
447 447 # by looking for method definitions instead, the
448 448 # __module__ in those classes is FakeModule.
449 449 attrs = [getattr(data, aname) for aname in dir(data)]
450 450 for attr in attrs:
451 451 if not inspect.ismethod(attr):
452 452 continue
453 453 filename = inspect.getabsfile(attr)
454 454 if filename and 'fakemodule' not in filename.lower():
455 455 # change the attribute to be the edit target instead
456 456 data = attr
457 457 break
458 458
459 459 datafile = 1
460 460 except TypeError:
461 461 filename = make_filename(args)
462 462 datafile = 1
463 463 warn('Could not find file where `%s` is defined.\n'
464 464 'Opening a file named `%s`' % (args,filename))
465 465 # Now, make sure we can actually read the source (if it was in
466 466 # a temp file it's gone by now).
467 467 if datafile:
468 468 try:
469 469 if lineno is None:
470 470 lineno = inspect.getsourcelines(data)[1]
471 471 except IOError:
472 472 filename = make_filename(args)
473 473 if filename is None:
474 474 warn('The file `%s` where `%s` was defined cannot '
475 475 'be read.' % (filename,data))
476 476 return
477 477 use_temp = 0
478 478 else:
479 479 data = ''
480 480
481 481 if use_temp:
482 482 filename = self.shell.mktempfile(data)
483 483 print('IPython will make a temporary file named:', filename)
484 484
485 485 # Make sure we send to the client an absolute path, in case the working
486 486 # directory of client and kernel don't match
487 487 filename = os.path.abspath(filename)
488 488
489 489 payload = {
490 490 'source' : 'IPython.zmq.zmqshell.ZMQInteractiveShell.edit_magic',
491 491 'filename' : filename,
492 492 'line_number' : lineno
493 493 }
494 494 self.payload_manager.write_payload(payload)
495 495
496 496 def magic_gui(self, *args, **kwargs):
497 497 raise NotImplementedError(
498 498 'GUI support must be enabled in command line options.')
499 499
500 500 def magic_pylab(self, *args, **kwargs):
501 501 raise NotImplementedError(
502 502 'pylab support must be enabled in command line options.')
503 503
504 504 # A few magics that are adapted to the specifics of using pexpect and a
505 505 # remote terminal
506 506
507 507 def magic_clear(self, arg_s):
508 508 """Clear the terminal."""
509 509 if os.name == 'posix':
510 510 self.shell.system("clear")
511 511 else:
512 512 self.shell.system("cls")
513 513
514 514 if os.name == 'nt':
515 515 # This is the usual name in windows
516 516 magic_cls = magic_clear
517 517
518 518 # Terminal pagers won't work over pexpect, but we do have our own pager
519 519
520 520 def magic_less(self, arg_s):
521 521 """Show a file through the pager.
522 522
523 523 Files ending in .py are syntax-highlighted."""
524 524 cont = open(arg_s).read()
525 525 if arg_s.endswith('.py'):
526 526 cont = self.shell.pycolorize(cont)
527 527 page.page(cont)
528 528
529 529 magic_more = magic_less
530 530
531 531 # Man calls a pager, so we also need to redefine it
532 532 if os.name == 'posix':
533 533 def magic_man(self, arg_s):
534 534 """Find the man page for the given command and display in pager."""
535 535 page.page(self.shell.getoutput('man %s | col -b' % arg_s,
536 536 split=False))
537 537
538 538 # FIXME: this is specific to the GUI, so we should let the gui app load
539 539 # magics at startup that are only for the gui. Once the gui app has proper
540 540 # profile and configuration management, we can have it initialize a kernel
541 541 # with a special config file that provides these.
542 542 def magic_guiref(self, arg_s):
543 543 """Show a basic reference about the GUI console."""
544 544 from IPython.core.usage import gui_reference
545 545 page.page(gui_reference, auto_html=True)
546 546
547 547 def magic_loadpy(self, arg_s):
548 548 """Load a .py python script into the GUI console.
549 549
550 550 This magic command can either take a local filename or a url::
551 551
552 552 %loadpy myscript.py
553 553 %loadpy http://www.example.com/myscript.py
554 554 """
555 555 if not arg_s.endswith('.py'):
556 556 raise ValueError('%%load only works with .py files: %s' % arg_s)
557 557 if arg_s.startswith('http'):
558 558 import urllib2
559 559 response = urllib2.urlopen(arg_s)
560 560 content = response.read()
561 561 else:
562 562 content = open(arg_s).read()
563 563 payload = dict(
564 564 source='IPython.zmq.zmqshell.ZMQInteractiveShell.magic_loadpy',
565 565 text=content
566 566 )
567 567 self.payload_manager.write_payload(payload)
568 568
569 569 def magic_Exit(self, parameter_s=''):
570 570 """Exit IPython. If the -k option is provided, the kernel will be left
571 571 running. Otherwise, it will shutdown without prompting.
572 572 """
573 573 opts,args = self.parse_options(parameter_s,'k')
574 self.shell.keepkernel = opts.has_key('k')
574 self.shell.keepkernel_on_exit = opts.has_key('k')
575 575 self.shell.ask_exit()
576 576
577 577 # Add aliases as magics so all common forms work: exit, quit, Exit, Quit.
578 578 magic_exit = magic_quit = magic_Quit = magic_Exit
579 579
580 580 InteractiveShellABC.register(ZMQInteractiveShell)
General Comments 0
You need to be logged in to leave comments. Login now