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