##// END OF EJS Templates
enable %gui/%pylab magics in the Kernel...
MinRK -
Show More
@@ -1,322 +1,322 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Pylab (matplotlib) support utilities.
2 """Pylab (matplotlib) support utilities.
3
3
4 Authors
4 Authors
5 -------
5 -------
6
6
7 * Fernando Perez.
7 * Fernando Perez.
8 * Brian Granger
8 * Brian Granger
9 """
9 """
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Copyright (C) 2009 The IPython Development Team
12 # Copyright (C) 2009 The IPython Development Team
13 #
13 #
14 # Distributed under the terms of the BSD License. The full license is in
14 # Distributed under the terms of the BSD License. The full license is in
15 # the file COPYING, distributed as part of this software.
15 # the file COPYING, distributed as part of this software.
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17
17
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19 # Imports
19 # Imports
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21
21
22 from io import BytesIO
22 from io import BytesIO
23
23
24 from IPython.utils.decorators import flag_calls
24 from IPython.utils.decorators import flag_calls
25
25
26 # If user specifies a GUI, that dictates the backend, otherwise we read the
26 # If user specifies a GUI, that dictates the backend, otherwise we read the
27 # user's mpl default from the mpl rc structure
27 # user's mpl default from the mpl rc structure
28 backends = {'tk': 'TkAgg',
28 backends = {'tk': 'TkAgg',
29 'gtk': 'GTKAgg',
29 'gtk': 'GTKAgg',
30 'wx': 'WXAgg',
30 'wx': 'WXAgg',
31 'qt': 'Qt4Agg', # qt3 not supported
31 'qt': 'Qt4Agg', # qt3 not supported
32 'qt4': 'Qt4Agg',
32 'qt4': 'Qt4Agg',
33 'osx': 'MacOSX',
33 'osx': 'MacOSX',
34 'inline' : 'module://IPython.zmq.pylab.backend_inline'}
34 'inline' : 'module://IPython.zmq.pylab.backend_inline'}
35
35
36 # We also need a reverse backends2guis mapping that will properly choose which
36 # We also need a reverse backends2guis mapping that will properly choose which
37 # GUI support to activate based on the desired matplotlib backend. For the
37 # GUI support to activate based on the desired matplotlib backend. For the
38 # most part it's just a reverse of the above dict, but we also need to add a
38 # most part it's just a reverse of the above dict, but we also need to add a
39 # few others that map to the same GUI manually:
39 # few others that map to the same GUI manually:
40 backend2gui = dict(zip(backends.values(), backends.keys()))
40 backend2gui = dict(zip(backends.values(), backends.keys()))
41 # In the reverse mapping, there are a few extra valid matplotlib backends that
41 # In the reverse mapping, there are a few extra valid matplotlib backends that
42 # map to the same GUI support
42 # map to the same GUI support
43 backend2gui['GTK'] = backend2gui['GTKCairo'] = 'gtk'
43 backend2gui['GTK'] = backend2gui['GTKCairo'] = 'gtk'
44 backend2gui['WX'] = 'wx'
44 backend2gui['WX'] = 'wx'
45 backend2gui['CocoaAgg'] = 'osx'
45 backend2gui['CocoaAgg'] = 'osx'
46
46
47 #-----------------------------------------------------------------------------
47 #-----------------------------------------------------------------------------
48 # Matplotlib utilities
48 # Matplotlib utilities
49 #-----------------------------------------------------------------------------
49 #-----------------------------------------------------------------------------
50
50
51
51
52 def getfigs(*fig_nums):
52 def getfigs(*fig_nums):
53 """Get a list of matplotlib figures by figure numbers.
53 """Get a list of matplotlib figures by figure numbers.
54
54
55 If no arguments are given, all available figures are returned. If the
55 If no arguments are given, all available figures are returned. If the
56 argument list contains references to invalid figures, a warning is printed
56 argument list contains references to invalid figures, a warning is printed
57 but the function continues pasting further figures.
57 but the function continues pasting further figures.
58
58
59 Parameters
59 Parameters
60 ----------
60 ----------
61 figs : tuple
61 figs : tuple
62 A tuple of ints giving the figure numbers of the figures to return.
62 A tuple of ints giving the figure numbers of the figures to return.
63 """
63 """
64 from matplotlib._pylab_helpers import Gcf
64 from matplotlib._pylab_helpers import Gcf
65 if not fig_nums:
65 if not fig_nums:
66 fig_managers = Gcf.get_all_fig_managers()
66 fig_managers = Gcf.get_all_fig_managers()
67 return [fm.canvas.figure for fm in fig_managers]
67 return [fm.canvas.figure for fm in fig_managers]
68 else:
68 else:
69 figs = []
69 figs = []
70 for num in fig_nums:
70 for num in fig_nums:
71 f = Gcf.figs.get(num)
71 f = Gcf.figs.get(num)
72 if f is None:
72 if f is None:
73 print('Warning: figure %s not available.' % num)
73 print('Warning: figure %s not available.' % num)
74 else:
74 else:
75 figs.append(f.canvas.figure)
75 figs.append(f.canvas.figure)
76 return figs
76 return figs
77
77
78
78
79 def figsize(sizex, sizey):
79 def figsize(sizex, sizey):
80 """Set the default figure size to be [sizex, sizey].
80 """Set the default figure size to be [sizex, sizey].
81
81
82 This is just an easy to remember, convenience wrapper that sets::
82 This is just an easy to remember, convenience wrapper that sets::
83
83
84 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
84 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
85 """
85 """
86 import matplotlib
86 import matplotlib
87 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
87 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
88
88
89
89
90 def print_figure(fig, fmt='png'):
90 def print_figure(fig, fmt='png'):
91 """Convert a figure to svg or png for inline display."""
91 """Convert a figure to svg or png for inline display."""
92 # When there's an empty figure, we shouldn't return anything, otherwise we
92 # When there's an empty figure, we shouldn't return anything, otherwise we
93 # get big blank areas in the qt console.
93 # get big blank areas in the qt console.
94 if not fig.axes:
94 if not fig.axes:
95 return
95 return
96
96
97 fc = fig.get_facecolor()
97 fc = fig.get_facecolor()
98 ec = fig.get_edgecolor()
98 ec = fig.get_edgecolor()
99 fig.set_facecolor('white')
99 fig.set_facecolor('white')
100 fig.set_edgecolor('white')
100 fig.set_edgecolor('white')
101 try:
101 try:
102 bytes_io = BytesIO()
102 bytes_io = BytesIO()
103 # use 72 dpi to match QTConsole's dpi
103 # use 72 dpi to match QTConsole's dpi
104 fig.canvas.print_figure(bytes_io, format=fmt, dpi=72,
104 fig.canvas.print_figure(bytes_io, format=fmt, dpi=72,
105 bbox_inches='tight')
105 bbox_inches='tight')
106 data = bytes_io.getvalue()
106 data = bytes_io.getvalue()
107 finally:
107 finally:
108 fig.set_facecolor(fc)
108 fig.set_facecolor(fc)
109 fig.set_edgecolor(ec)
109 fig.set_edgecolor(ec)
110 return data
110 return data
111
111
112
112
113 # We need a little factory function here to create the closure where
113 # We need a little factory function here to create the closure where
114 # safe_execfile can live.
114 # safe_execfile can live.
115 def mpl_runner(safe_execfile):
115 def mpl_runner(safe_execfile):
116 """Factory to return a matplotlib-enabled runner for %run.
116 """Factory to return a matplotlib-enabled runner for %run.
117
117
118 Parameters
118 Parameters
119 ----------
119 ----------
120 safe_execfile : function
120 safe_execfile : function
121 This must be a function with the same interface as the
121 This must be a function with the same interface as the
122 :meth:`safe_execfile` method of IPython.
122 :meth:`safe_execfile` method of IPython.
123
123
124 Returns
124 Returns
125 -------
125 -------
126 A function suitable for use as the ``runner`` argument of the %run magic
126 A function suitable for use as the ``runner`` argument of the %run magic
127 function.
127 function.
128 """
128 """
129
129
130 def mpl_execfile(fname,*where,**kw):
130 def mpl_execfile(fname,*where,**kw):
131 """matplotlib-aware wrapper around safe_execfile.
131 """matplotlib-aware wrapper around safe_execfile.
132
132
133 Its interface is identical to that of the :func:`execfile` builtin.
133 Its interface is identical to that of the :func:`execfile` builtin.
134
134
135 This is ultimately a call to execfile(), but wrapped in safeties to
135 This is ultimately a call to execfile(), but wrapped in safeties to
136 properly handle interactive rendering."""
136 properly handle interactive rendering."""
137
137
138 import matplotlib
138 import matplotlib
139 import matplotlib.pylab as pylab
139 import matplotlib.pylab as pylab
140
140
141 #print '*** Matplotlib runner ***' # dbg
141 #print '*** Matplotlib runner ***' # dbg
142 # turn off rendering until end of script
142 # turn off rendering until end of script
143 is_interactive = matplotlib.rcParams['interactive']
143 is_interactive = matplotlib.rcParams['interactive']
144 matplotlib.interactive(False)
144 matplotlib.interactive(False)
145 safe_execfile(fname,*where,**kw)
145 safe_execfile(fname,*where,**kw)
146 matplotlib.interactive(is_interactive)
146 matplotlib.interactive(is_interactive)
147 # make rendering call now, if the user tried to do it
147 # make rendering call now, if the user tried to do it
148 if pylab.draw_if_interactive.called:
148 if pylab.draw_if_interactive.called:
149 pylab.draw()
149 pylab.draw()
150 pylab.draw_if_interactive.called = False
150 pylab.draw_if_interactive.called = False
151
151
152 return mpl_execfile
152 return mpl_execfile
153
153
154
154
155 def select_figure_format(shell, fmt):
155 def select_figure_format(shell, fmt):
156 """Select figure format for inline backend, either 'png' or 'svg'.
156 """Select figure format for inline backend, either 'png' or 'svg'.
157
157
158 Using this method ensures only one figure format is active at a time.
158 Using this method ensures only one figure format is active at a time.
159 """
159 """
160 from matplotlib.figure import Figure
160 from matplotlib.figure import Figure
161 from IPython.zmq.pylab import backend_inline
161 from IPython.zmq.pylab import backend_inline
162
162
163 svg_formatter = shell.display_formatter.formatters['image/svg+xml']
163 svg_formatter = shell.display_formatter.formatters['image/svg+xml']
164 png_formatter = shell.display_formatter.formatters['image/png']
164 png_formatter = shell.display_formatter.formatters['image/png']
165
165
166 if fmt=='png':
166 if fmt=='png':
167 svg_formatter.type_printers.pop(Figure, None)
167 svg_formatter.type_printers.pop(Figure, None)
168 png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png'))
168 png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png'))
169 elif fmt=='svg':
169 elif fmt=='svg':
170 png_formatter.type_printers.pop(Figure, None)
170 png_formatter.type_printers.pop(Figure, None)
171 svg_formatter.for_type(Figure, lambda fig: print_figure(fig, 'svg'))
171 svg_formatter.for_type(Figure, lambda fig: print_figure(fig, 'svg'))
172 else:
172 else:
173 raise ValueError("supported formats are: 'png', 'svg', not %r"%fmt)
173 raise ValueError("supported formats are: 'png', 'svg', not %r"%fmt)
174
174
175 # set the format to be used in the backend()
175 # set the format to be used in the backend()
176 backend_inline._figure_format = fmt
176 backend_inline._figure_format = fmt
177
177
178 #-----------------------------------------------------------------------------
178 #-----------------------------------------------------------------------------
179 # Code for initializing matplotlib and importing pylab
179 # Code for initializing matplotlib and importing pylab
180 #-----------------------------------------------------------------------------
180 #-----------------------------------------------------------------------------
181
181
182
182
183 def find_gui_and_backend(gui=None):
183 def find_gui_and_backend(gui=None):
184 """Given a gui string return the gui and mpl backend.
184 """Given a gui string return the gui and mpl backend.
185
185
186 Parameters
186 Parameters
187 ----------
187 ----------
188 gui : str
188 gui : str
189 Can be one of ('tk','gtk','wx','qt','qt4','inline').
189 Can be one of ('tk','gtk','wx','qt','qt4','inline').
190
190
191 Returns
191 Returns
192 -------
192 -------
193 A tuple of (gui, backend) where backend is one of ('TkAgg','GTKAgg',
193 A tuple of (gui, backend) where backend is one of ('TkAgg','GTKAgg',
194 'WXAgg','Qt4Agg','module://IPython.zmq.pylab.backend_inline').
194 'WXAgg','Qt4Agg','module://IPython.zmq.pylab.backend_inline').
195 """
195 """
196
196
197 import matplotlib
197 import matplotlib
198
198
199 if gui:
199 if gui:
200 # select backend based on requested gui
200 # select backend based on requested gui
201 backend = backends[gui]
201 backend = backends[gui]
202 else:
202 else:
203 backend = matplotlib.rcParams['backend']
203 backend = matplotlib.rcParams['backend']
204 # In this case, we need to find what the appropriate gui selection call
204 # In this case, we need to find what the appropriate gui selection call
205 # should be for IPython, so we can activate inputhook accordingly
205 # should be for IPython, so we can activate inputhook accordingly
206 gui = backend2gui.get(backend, None)
206 gui = backend2gui.get(backend, None)
207 return gui, backend
207 return gui, backend
208
208
209
209
210 def activate_matplotlib(backend):
210 def activate_matplotlib(backend):
211 """Activate the given backend and set interactive to True."""
211 """Activate the given backend and set interactive to True."""
212
212
213 import matplotlib
213 import matplotlib
214 if backend.startswith('module://'):
214 if backend.startswith('module://'):
215 # Work around bug in matplotlib: matplotlib.use converts the
215 # Work around bug in matplotlib: matplotlib.use converts the
216 # backend_id to lowercase even if a module name is specified!
216 # backend_id to lowercase even if a module name is specified!
217 matplotlib.rcParams['backend'] = backend
217 matplotlib.rcParams['backend'] = backend
218 else:
218 else:
219 matplotlib.use(backend)
219 matplotlib.use(backend)
220 matplotlib.interactive(True)
220 matplotlib.interactive(True)
221
221
222 # This must be imported last in the matplotlib series, after
222 # This must be imported last in the matplotlib series, after
223 # backend/interactivity choices have been made
223 # backend/interactivity choices have been made
224 import matplotlib.pylab as pylab
224 import matplotlib.pylab as pylab
225
225
226 # XXX For now leave this commented out, but depending on discussions with
226 # XXX For now leave this commented out, but depending on discussions with
227 # mpl-dev, we may be able to allow interactive switching...
227 # mpl-dev, we may be able to allow interactive switching...
228 #import matplotlib.pyplot
228 #import matplotlib.pyplot
229 #matplotlib.pyplot.switch_backend(backend)
229 #matplotlib.pyplot.switch_backend(backend)
230
230
231 pylab.show._needmain = False
231 pylab.show._needmain = False
232 # We need to detect at runtime whether show() is called by the user.
232 # We need to detect at runtime whether show() is called by the user.
233 # For this, we wrap it into a decorator which adds a 'called' flag.
233 # For this, we wrap it into a decorator which adds a 'called' flag.
234 pylab.draw_if_interactive = flag_calls(pylab.draw_if_interactive)
234 pylab.draw_if_interactive = flag_calls(pylab.draw_if_interactive)
235
235
236 def import_pylab(user_ns, backend, import_all=True, shell=None):
236 def import_pylab(user_ns, backend, import_all=True, shell=None):
237 """Import the standard pylab symbols into user_ns."""
237 """Import the standard pylab symbols into user_ns."""
238
238
239 # Import numpy as np/pyplot as plt are conventions we're trying to
239 # Import numpy as np/pyplot as plt are conventions we're trying to
240 # somewhat standardize on. Making them available to users by default
240 # somewhat standardize on. Making them available to users by default
241 # will greatly help this.
241 # will greatly help this.
242 s = ("import numpy\n"
242 s = ("import numpy\n"
243 "import matplotlib\n"
243 "import matplotlib\n"
244 "from matplotlib import pylab, mlab, pyplot\n"
244 "from matplotlib import pylab, mlab, pyplot\n"
245 "np = numpy\n"
245 "np = numpy\n"
246 "plt = pyplot\n"
246 "plt = pyplot\n"
247 )
247 )
248 exec s in user_ns
248 exec s in user_ns
249
249
250 if shell is not None:
250 if shell is not None:
251 exec s in shell.user_ns_hidden
251 exec s in shell.user_ns_hidden
252 # If using our svg payload backend, register the post-execution
252 # If using our svg payload backend, register the post-execution
253 # function that will pick up the results for display. This can only be
253 # function that will pick up the results for display. This can only be
254 # done with access to the real shell object.
254 # done with access to the real shell object.
255 #
255 #
256 from IPython.zmq.pylab.backend_inline import InlineBackendConfig
256 from IPython.zmq.pylab.backend_inline import InlineBackendConfig
257
257
258 cfg = InlineBackendConfig.instance(config=shell.config)
258 cfg = InlineBackendConfig.instance(config=shell.config)
259 cfg.shell = shell
259 cfg.shell = shell
260
260
261 if backend == backends['inline']:
261 if backend == backends['inline']:
262 from IPython.zmq.pylab.backend_inline import flush_figures
262 from IPython.zmq.pylab.backend_inline import flush_figures
263 from matplotlib import pyplot
263 from matplotlib import pyplot
264 shell.register_post_execute(flush_figures)
264 shell.register_post_execute(flush_figures)
265 # load inline_rc
265 # load inline_rc
266 pyplot.rcParams.update(cfg.rc)
266 pyplot.rcParams.update(cfg.rc)
267
267
268 # Add 'figsize' to pyplot and to the user's namespace
268 # Add 'figsize' to pyplot and to the user's namespace
269 user_ns['figsize'] = pyplot.figsize = figsize
269 user_ns['figsize'] = pyplot.figsize = figsize
270 shell.user_ns_hidden['figsize'] = figsize
270 shell.user_ns_hidden['figsize'] = figsize
271
271
272 # Setup the default figure format
272 # Setup the default figure format
273 fmt = cfg.figure_format
273 fmt = cfg.figure_format
274 select_figure_format(shell, fmt)
274 select_figure_format(shell, fmt)
275
275
276 # The old pastefig function has been replaced by display
276 # The old pastefig function has been replaced by display
277 from IPython.core.display import display
277 from IPython.core.display import display
278 # Add display and display_png to the user's namespace
278 # Add display and display_png to the user's namespace
279 user_ns['display'] = display
279 user_ns['display'] = display
280 shell.user_ns_hidden['display'] = display
280 shell.user_ns_hidden['display'] = display
281 user_ns['getfigs'] = getfigs
281 user_ns['getfigs'] = getfigs
282 shell.user_ns_hidden['getfigs'] = getfigs
282 shell.user_ns_hidden['getfigs'] = getfigs
283
283
284 if import_all:
284 if import_all:
285 s = ("from matplotlib.pylab import *\n"
285 s = ("from matplotlib.pylab import *\n"
286 "from numpy import *\n")
286 "from numpy import *\n")
287 exec s in user_ns
287 exec s in user_ns
288 if shell is not None:
288 if shell is not None:
289 exec s in shell.user_ns_hidden
289 exec s in shell.user_ns_hidden
290
290
291
291
292 def pylab_activate(user_ns, gui=None, import_all=True):
292 def pylab_activate(user_ns, gui=None, import_all=True, shell=None):
293 """Activate pylab mode in the user's namespace.
293 """Activate pylab mode in the user's namespace.
294
294
295 Loads and initializes numpy, matplotlib and friends for interactive use.
295 Loads and initializes numpy, matplotlib and friends for interactive use.
296
296
297 Parameters
297 Parameters
298 ----------
298 ----------
299 user_ns : dict
299 user_ns : dict
300 Namespace where the imports will occur.
300 Namespace where the imports will occur.
301
301
302 gui : optional, string
302 gui : optional, string
303 A valid gui name following the conventions of the %gui magic.
303 A valid gui name following the conventions of the %gui magic.
304
304
305 import_all : optional, boolean
305 import_all : optional, boolean
306 If true, an 'import *' is done from numpy and pylab.
306 If true, an 'import *' is done from numpy and pylab.
307
307
308 Returns
308 Returns
309 -------
309 -------
310 The actual gui used (if not given as input, it was obtained from matplotlib
310 The actual gui used (if not given as input, it was obtained from matplotlib
311 itself, and will be needed next to configure IPython's gui integration.
311 itself, and will be needed next to configure IPython's gui integration.
312 """
312 """
313 gui, backend = find_gui_and_backend(gui)
313 gui, backend = find_gui_and_backend(gui)
314 activate_matplotlib(backend)
314 activate_matplotlib(backend)
315 import_pylab(user_ns, backend, import_all)
315 import_pylab(user_ns, backend, import_all, shell)
316
316
317 print """
317 print """
318 Welcome to pylab, a matplotlib-based Python environment [backend: %s].
318 Welcome to pylab, a matplotlib-based Python environment [backend: %s].
319 For more information, type 'help(pylab)'.""" % backend
319 For more information, type 'help(pylab)'.""" % backend
320
320
321 return gui
321 return gui
322
322
@@ -1,782 +1,790 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 """A simple interactive kernel that talks to a frontend over 0MQ.
2 """A simple interactive kernel that talks to a frontend over 0MQ.
3
3
4 Things to do:
4 Things to do:
5
5
6 * Implement `set_parent` logic. Right before doing exec, the Kernel should
6 * Implement `set_parent` logic. Right before doing exec, the Kernel should
7 call set_parent on all the PUB objects with the message about to be executed.
7 call set_parent on all the PUB objects with the message about to be executed.
8 * Implement random port and security key logic.
8 * Implement random port and security key logic.
9 * Implement control messages.
9 * Implement control messages.
10 * Implement event loop and poll version.
10 * Implement event loop and poll version.
11 """
11 """
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 from __future__ import print_function
16 from __future__ import print_function
17
17
18 # Standard library imports.
18 # Standard library imports.
19 import __builtin__
19 import __builtin__
20 import atexit
20 import atexit
21 import sys
21 import sys
22 import time
22 import time
23 import traceback
23 import traceback
24 import logging
24 import logging
25
25 # System library imports.
26 # System library imports.
26 import zmq
27 import zmq
27
28
28 # Local imports.
29 # Local imports.
29 from IPython.config.configurable import Configurable
30 from IPython.config.configurable import Configurable
30 from IPython.config.application import boolean_flag
31 from IPython.config.application import boolean_flag
31 from IPython.core.application import ProfileDir
32 from IPython.core.application import ProfileDir
32 from IPython.core.error import StdinNotImplementedError
33 from IPython.core.error import StdinNotImplementedError
33 from IPython.core.shellapp import (
34 from IPython.core.shellapp import (
34 InteractiveShellApp, shell_flags, shell_aliases
35 InteractiveShellApp, shell_flags, shell_aliases
35 )
36 )
36 from IPython.utils import io
37 from IPython.utils import io
37 from IPython.utils import py3compat
38 from IPython.utils import py3compat
38 from IPython.utils.jsonutil import json_clean
39 from IPython.utils.jsonutil import json_clean
39 from IPython.lib import pylabtools
40 from IPython.lib import pylabtools
40 from IPython.utils.traitlets import (
41 from IPython.utils.traitlets import (
41 List, Instance, Float, Dict, Bool, Int, Unicode, CaselessStrEnum
42 Any, List, Instance, Float, Dict, Bool, Int, Unicode, CaselessStrEnum
42 )
43 )
43
44
44 from entry_point import base_launch_kernel
45 from entry_point import base_launch_kernel
45 from kernelapp import KernelApp, kernel_flags, kernel_aliases
46 from kernelapp import KernelApp, kernel_flags, kernel_aliases
46 from iostream import OutStream
47 from iostream import OutStream
47 from session import Session, Message
48 from session import Session, Message
48 from zmqshell import ZMQInteractiveShell
49 from zmqshell import ZMQInteractiveShell
49
50
50
51
51 #-----------------------------------------------------------------------------
52 #-----------------------------------------------------------------------------
52 # Main kernel class
53 # Main kernel class
53 #-----------------------------------------------------------------------------
54 #-----------------------------------------------------------------------------
54
55
55 class Kernel(Configurable):
56 class Kernel(Configurable):
56
57
57 #---------------------------------------------------------------------------
58 #---------------------------------------------------------------------------
58 # Kernel interface
59 # Kernel interface
59 #---------------------------------------------------------------------------
60 #---------------------------------------------------------------------------
60
61
62 # attribute to override with a GUI
63 eventloop = Any(None)
64
61 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
65 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
62 session = Instance(Session)
66 session = Instance(Session)
63 shell_socket = Instance('zmq.Socket')
67 shell_socket = Instance('zmq.Socket')
64 iopub_socket = Instance('zmq.Socket')
68 iopub_socket = Instance('zmq.Socket')
65 stdin_socket = Instance('zmq.Socket')
69 stdin_socket = Instance('zmq.Socket')
66 log = Instance(logging.Logger)
70 log = Instance(logging.Logger)
67
71
68 # Private interface
72 # Private interface
69
73
70 # Time to sleep after flushing the stdout/err buffers in each execute
74 # Time to sleep after flushing the stdout/err buffers in each execute
71 # cycle. While this introduces a hard limit on the minimal latency of the
75 # cycle. While this introduces a hard limit on the minimal latency of the
72 # execute cycle, it helps prevent output synchronization problems for
76 # execute cycle, it helps prevent output synchronization problems for
73 # clients.
77 # clients.
74 # Units are in seconds. The minimum zmq latency on local host is probably
78 # Units are in seconds. The minimum zmq latency on local host is probably
75 # ~150 microseconds, set this to 500us for now. We may need to increase it
79 # ~150 microseconds, set this to 500us for now. We may need to increase it
76 # a little if it's not enough after more interactive testing.
80 # a little if it's not enough after more interactive testing.
77 _execute_sleep = Float(0.0005, config=True)
81 _execute_sleep = Float(0.0005, config=True)
78
82
79 # Frequency of the kernel's event loop.
83 # Frequency of the kernel's event loop.
80 # Units are in seconds, kernel subclasses for GUI toolkits may need to
84 # Units are in seconds, kernel subclasses for GUI toolkits may need to
81 # adapt to milliseconds.
85 # adapt to milliseconds.
82 _poll_interval = Float(0.05, config=True)
86 _poll_interval = Float(0.05, config=True)
83
87
84 # If the shutdown was requested over the network, we leave here the
88 # If the shutdown was requested over the network, we leave here the
85 # necessary reply message so it can be sent by our registered atexit
89 # necessary reply message so it can be sent by our registered atexit
86 # handler. This ensures that the reply is only sent to clients truly at
90 # handler. This ensures that the reply is only sent to clients truly at
87 # the end of our shutdown process (which happens after the underlying
91 # the end of our shutdown process (which happens after the underlying
88 # IPython shell's own shutdown).
92 # IPython shell's own shutdown).
89 _shutdown_message = None
93 _shutdown_message = None
90
94
91 # This is a dict of port number that the kernel is listening on. It is set
95 # This is a dict of port number that the kernel is listening on. It is set
92 # by record_ports and used by connect_request.
96 # by record_ports and used by connect_request.
93 _recorded_ports = Dict()
97 _recorded_ports = Dict()
94
98
95
99
96
100
97 def __init__(self, **kwargs):
101 def __init__(self, **kwargs):
98 super(Kernel, self).__init__(**kwargs)
102 super(Kernel, self).__init__(**kwargs)
99
103
100 # Before we even start up the shell, register *first* our exit handlers
104 # Before we even start up the shell, register *first* our exit handlers
101 # so they come before the shell's
105 # so they come before the shell's
102 atexit.register(self._at_shutdown)
106 atexit.register(self._at_shutdown)
103
107
104 # Initialize the InteractiveShell subclass
108 # Initialize the InteractiveShell subclass
105 self.shell = ZMQInteractiveShell.instance(config=self.config)
109 self.shell = ZMQInteractiveShell.instance(config=self.config)
106 self.shell.displayhook.session = self.session
110 self.shell.displayhook.session = self.session
107 self.shell.displayhook.pub_socket = self.iopub_socket
111 self.shell.displayhook.pub_socket = self.iopub_socket
108 self.shell.display_pub.session = self.session
112 self.shell.display_pub.session = self.session
109 self.shell.display_pub.pub_socket = self.iopub_socket
113 self.shell.display_pub.pub_socket = self.iopub_socket
110
114
111 # TMP - hack while developing
115 # TMP - hack while developing
112 self.shell._reply_content = None
116 self.shell._reply_content = None
113
117
114 # Build dict of handlers for message types
118 # Build dict of handlers for message types
115 msg_types = [ 'execute_request', 'complete_request',
119 msg_types = [ 'execute_request', 'complete_request',
116 'object_info_request', 'history_request',
120 'object_info_request', 'history_request',
117 'connect_request', 'shutdown_request']
121 'connect_request', 'shutdown_request']
118 self.handlers = {}
122 self.handlers = {}
119 for msg_type in msg_types:
123 for msg_type in msg_types:
120 self.handlers[msg_type] = getattr(self, msg_type)
124 self.handlers[msg_type] = getattr(self, msg_type)
121
125
122 def do_one_iteration(self):
126 def do_one_iteration(self):
123 """Do one iteration of the kernel's evaluation loop.
127 """Do one iteration of the kernel's evaluation loop.
124 """
128 """
125 try:
129 try:
126 ident,msg = self.session.recv(self.shell_socket, zmq.NOBLOCK)
130 ident,msg = self.session.recv(self.shell_socket, zmq.NOBLOCK)
127 except Exception:
131 except Exception:
128 self.log.warn("Invalid Message:", exc_info=True)
132 self.log.warn("Invalid Message:", exc_info=True)
129 return
133 return
130 if msg is None:
134 if msg is None:
131 return
135 return
132
136
133 msg_type = msg['header']['msg_type']
137 msg_type = msg['header']['msg_type']
134
138
135 # This assert will raise in versions of zeromq 2.0.7 and lesser.
139 # This assert will raise in versions of zeromq 2.0.7 and lesser.
136 # We now require 2.0.8 or above, so we can uncomment for safety.
140 # We now require 2.0.8 or above, so we can uncomment for safety.
137 # print(ident,msg, file=sys.__stdout__)
141 # print(ident,msg, file=sys.__stdout__)
138 assert ident is not None, "Missing message part."
142 assert ident is not None, "Missing message part."
139
143
140 # Print some info about this message and leave a '--->' marker, so it's
144 # Print some info about this message and leave a '--->' marker, so it's
141 # easier to trace visually the message chain when debugging. Each
145 # easier to trace visually the message chain when debugging. Each
142 # handler prints its message at the end.
146 # handler prints its message at the end.
143 self.log.debug('\n*** MESSAGE TYPE:'+str(msg_type)+'***')
147 self.log.debug('\n*** MESSAGE TYPE:'+str(msg_type)+'***')
144 self.log.debug(' Content: '+str(msg['content'])+'\n --->\n ')
148 self.log.debug(' Content: '+str(msg['content'])+'\n --->\n ')
145
149
146 # Find and call actual handler for message
150 # Find and call actual handler for message
147 handler = self.handlers.get(msg_type, None)
151 handler = self.handlers.get(msg_type, None)
148 if handler is None:
152 if handler is None:
149 self.log.error("UNKNOWN MESSAGE TYPE:" +str(msg))
153 self.log.error("UNKNOWN MESSAGE TYPE:" +str(msg))
150 else:
154 else:
151 handler(ident, msg)
155 handler(ident, msg)
152
156
153 # Check whether we should exit, in case the incoming message set the
157 # Check whether we should exit, in case the incoming message set the
154 # exit flag on
158 # exit flag on
155 if self.shell.exit_now:
159 if self.shell.exit_now:
156 self.log.debug('\nExiting IPython kernel...')
160 self.log.debug('\nExiting IPython kernel...')
157 # We do a normal, clean exit, which allows any actions registered
161 # We do a normal, clean exit, which allows any actions registered
158 # via atexit (such as history saving) to take place.
162 # via atexit (such as history saving) to take place.
159 sys.exit(0)
163 sys.exit(0)
160
164
161
165
162 def start(self):
166 def start(self):
163 """ Start the kernel main loop.
167 """ Start the kernel main loop.
164 """
168 """
165 poller = zmq.Poller()
169 poller = zmq.Poller()
166 poller.register(self.shell_socket, zmq.POLLIN)
170 poller.register(self.shell_socket, zmq.POLLIN)
167 while True:
171 # loop while self.eventloop has not been overridden
172 while self.eventloop is None:
168 try:
173 try:
169 # scale by extra factor of 10, because there is no
174 # scale by extra factor of 10, because there is no
170 # reason for this to be anything less than ~ 0.1s
175 # reason for this to be anything less than ~ 0.1s
171 # since it is a real poller and will respond
176 # since it is a real poller and will respond
172 # to events immediately
177 # to events immediately
173
178
174 # double nested try/except, to properly catch KeyboardInterrupt
179 # double nested try/except, to properly catch KeyboardInterrupt
175 # due to pyzmq Issue #130
180 # due to pyzmq Issue #130
176 try:
181 try:
177 poller.poll(10*1000*self._poll_interval)
182 poller.poll(10*1000*self._poll_interval)
178 self.do_one_iteration()
183 self.do_one_iteration()
179 except:
184 except:
180 raise
185 raise
181 except KeyboardInterrupt:
186 except KeyboardInterrupt:
182 # Ctrl-C shouldn't crash the kernel
187 # Ctrl-C shouldn't crash the kernel
183 io.raw_print("KeyboardInterrupt caught in kernel")
188 io.raw_print("KeyboardInterrupt caught in kernel")
189 if self.eventloop is not None:
190 try:
191 self.eventloop(self)
192 except KeyboardInterrupt:
193 # Ctrl-C shouldn't crash the kernel
194 io.raw_print("KeyboardInterrupt caught in kernel")
195
184
196
185 def record_ports(self, ports):
197 def record_ports(self, ports):
186 """Record the ports that this kernel is using.
198 """Record the ports that this kernel is using.
187
199
188 The creator of the Kernel instance must call this methods if they
200 The creator of the Kernel instance must call this methods if they
189 want the :meth:`connect_request` method to return the port numbers.
201 want the :meth:`connect_request` method to return the port numbers.
190 """
202 """
191 self._recorded_ports = ports
203 self._recorded_ports = ports
192
204
193 #---------------------------------------------------------------------------
205 #---------------------------------------------------------------------------
194 # Kernel request handlers
206 # Kernel request handlers
195 #---------------------------------------------------------------------------
207 #---------------------------------------------------------------------------
196
208
197 def _publish_pyin(self, code, parent):
209 def _publish_pyin(self, code, parent):
198 """Publish the code request on the pyin stream."""
210 """Publish the code request on the pyin stream."""
199
211
200 pyin_msg = self.session.send(self.iopub_socket, u'pyin',{u'code':code}, parent=parent)
212 pyin_msg = self.session.send(self.iopub_socket, u'pyin',{u'code':code}, parent=parent)
201
213
202 def execute_request(self, ident, parent):
214 def execute_request(self, ident, parent):
203
215
204 status_msg = self.session.send(self.iopub_socket,
216 status_msg = self.session.send(self.iopub_socket,
205 u'status',
217 u'status',
206 {u'execution_state':u'busy'},
218 {u'execution_state':u'busy'},
207 parent=parent
219 parent=parent
208 )
220 )
209
221
210 try:
222 try:
211 content = parent[u'content']
223 content = parent[u'content']
212 code = content[u'code']
224 code = content[u'code']
213 silent = content[u'silent']
225 silent = content[u'silent']
214 except:
226 except:
215 self.log.error("Got bad msg: ")
227 self.log.error("Got bad msg: ")
216 self.log.error(str(Message(parent)))
228 self.log.error(str(Message(parent)))
217 return
229 return
218
230
219 shell = self.shell # we'll need this a lot here
231 shell = self.shell # we'll need this a lot here
220
232
221 # Replace raw_input. Note that is not sufficient to replace
233 # Replace raw_input. Note that is not sufficient to replace
222 # raw_input in the user namespace.
234 # raw_input in the user namespace.
223 if content.get('allow_stdin', False):
235 if content.get('allow_stdin', False):
224 raw_input = lambda prompt='': self._raw_input(prompt, ident, parent)
236 raw_input = lambda prompt='': self._raw_input(prompt, ident, parent)
225 else:
237 else:
226 raw_input = lambda prompt='' : self._no_raw_input()
238 raw_input = lambda prompt='' : self._no_raw_input()
227
239
228 if py3compat.PY3:
240 if py3compat.PY3:
229 __builtin__.input = raw_input
241 __builtin__.input = raw_input
230 else:
242 else:
231 __builtin__.raw_input = raw_input
243 __builtin__.raw_input = raw_input
232
244
233 # Set the parent message of the display hook and out streams.
245 # Set the parent message of the display hook and out streams.
234 shell.displayhook.set_parent(parent)
246 shell.displayhook.set_parent(parent)
235 shell.display_pub.set_parent(parent)
247 shell.display_pub.set_parent(parent)
236 sys.stdout.set_parent(parent)
248 sys.stdout.set_parent(parent)
237 sys.stderr.set_parent(parent)
249 sys.stderr.set_parent(parent)
238
250
239 # Re-broadcast our input for the benefit of listening clients, and
251 # Re-broadcast our input for the benefit of listening clients, and
240 # start computing output
252 # start computing output
241 if not silent:
253 if not silent:
242 self._publish_pyin(code, parent)
254 self._publish_pyin(code, parent)
243
255
244 reply_content = {}
256 reply_content = {}
245 try:
257 try:
246 if silent:
258 if silent:
247 # run_code uses 'exec' mode, so no displayhook will fire, and it
259 # run_code uses 'exec' mode, so no displayhook will fire, and it
248 # doesn't call logging or history manipulations. Print
260 # doesn't call logging or history manipulations. Print
249 # statements in that code will obviously still execute.
261 # statements in that code will obviously still execute.
250 shell.run_code(code)
262 shell.run_code(code)
251 else:
263 else:
252 # FIXME: the shell calls the exception handler itself.
264 # FIXME: the shell calls the exception handler itself.
253 shell.run_cell(code, store_history=True)
265 shell.run_cell(code, store_history=True)
254 except:
266 except:
255 status = u'error'
267 status = u'error'
256 # FIXME: this code right now isn't being used yet by default,
268 # FIXME: this code right now isn't being used yet by default,
257 # because the run_cell() call above directly fires off exception
269 # because the run_cell() call above directly fires off exception
258 # reporting. This code, therefore, is only active in the scenario
270 # reporting. This code, therefore, is only active in the scenario
259 # where runlines itself has an unhandled exception. We need to
271 # where runlines itself has an unhandled exception. We need to
260 # uniformize this, for all exception construction to come from a
272 # uniformize this, for all exception construction to come from a
261 # single location in the codbase.
273 # single location in the codbase.
262 etype, evalue, tb = sys.exc_info()
274 etype, evalue, tb = sys.exc_info()
263 tb_list = traceback.format_exception(etype, evalue, tb)
275 tb_list = traceback.format_exception(etype, evalue, tb)
264 reply_content.update(shell._showtraceback(etype, evalue, tb_list))
276 reply_content.update(shell._showtraceback(etype, evalue, tb_list))
265 else:
277 else:
266 status = u'ok'
278 status = u'ok'
267
279
268 reply_content[u'status'] = status
280 reply_content[u'status'] = status
269
281
270 # Return the execution counter so clients can display prompts
282 # Return the execution counter so clients can display prompts
271 reply_content['execution_count'] = shell.execution_count -1
283 reply_content['execution_count'] = shell.execution_count -1
272
284
273 # FIXME - fish exception info out of shell, possibly left there by
285 # FIXME - fish exception info out of shell, possibly left there by
274 # runlines. We'll need to clean up this logic later.
286 # runlines. We'll need to clean up this logic later.
275 if shell._reply_content is not None:
287 if shell._reply_content is not None:
276 reply_content.update(shell._reply_content)
288 reply_content.update(shell._reply_content)
277 # reset after use
289 # reset after use
278 shell._reply_content = None
290 shell._reply_content = None
279
291
280 # At this point, we can tell whether the main code execution succeeded
292 # At this point, we can tell whether the main code execution succeeded
281 # or not. If it did, we proceed to evaluate user_variables/expressions
293 # or not. If it did, we proceed to evaluate user_variables/expressions
282 if reply_content['status'] == 'ok':
294 if reply_content['status'] == 'ok':
283 reply_content[u'user_variables'] = \
295 reply_content[u'user_variables'] = \
284 shell.user_variables(content[u'user_variables'])
296 shell.user_variables(content[u'user_variables'])
285 reply_content[u'user_expressions'] = \
297 reply_content[u'user_expressions'] = \
286 shell.user_expressions(content[u'user_expressions'])
298 shell.user_expressions(content[u'user_expressions'])
287 else:
299 else:
288 # If there was an error, don't even try to compute variables or
300 # If there was an error, don't even try to compute variables or
289 # expressions
301 # expressions
290 reply_content[u'user_variables'] = {}
302 reply_content[u'user_variables'] = {}
291 reply_content[u'user_expressions'] = {}
303 reply_content[u'user_expressions'] = {}
292
304
293 # Payloads should be retrieved regardless of outcome, so we can both
305 # Payloads should be retrieved regardless of outcome, so we can both
294 # recover partial output (that could have been generated early in a
306 # recover partial output (that could have been generated early in a
295 # block, before an error) and clear the payload system always.
307 # block, before an error) and clear the payload system always.
296 reply_content[u'payload'] = shell.payload_manager.read_payload()
308 reply_content[u'payload'] = shell.payload_manager.read_payload()
297 # Be agressive about clearing the payload because we don't want
309 # Be agressive about clearing the payload because we don't want
298 # it to sit in memory until the next execute_request comes in.
310 # it to sit in memory until the next execute_request comes in.
299 shell.payload_manager.clear_payload()
311 shell.payload_manager.clear_payload()
300
312
301 # Flush output before sending the reply.
313 # Flush output before sending the reply.
302 sys.stdout.flush()
314 sys.stdout.flush()
303 sys.stderr.flush()
315 sys.stderr.flush()
304 # FIXME: on rare occasions, the flush doesn't seem to make it to the
316 # FIXME: on rare occasions, the flush doesn't seem to make it to the
305 # clients... This seems to mitigate the problem, but we definitely need
317 # clients... This seems to mitigate the problem, but we definitely need
306 # to better understand what's going on.
318 # to better understand what's going on.
307 if self._execute_sleep:
319 if self._execute_sleep:
308 time.sleep(self._execute_sleep)
320 time.sleep(self._execute_sleep)
309
321
310 # Send the reply.
322 # Send the reply.
311 reply_content = json_clean(reply_content)
323 reply_content = json_clean(reply_content)
312 reply_msg = self.session.send(self.shell_socket, u'execute_reply',
324 reply_msg = self.session.send(self.shell_socket, u'execute_reply',
313 reply_content, parent, ident=ident)
325 reply_content, parent, ident=ident)
314 self.log.debug(str(reply_msg))
326 self.log.debug(str(reply_msg))
315
327
316 if reply_msg['content']['status'] == u'error':
328 if reply_msg['content']['status'] == u'error':
317 self._abort_queue()
329 self._abort_queue()
318
330
319 status_msg = self.session.send(self.iopub_socket,
331 status_msg = self.session.send(self.iopub_socket,
320 u'status',
332 u'status',
321 {u'execution_state':u'idle'},
333 {u'execution_state':u'idle'},
322 parent=parent
334 parent=parent
323 )
335 )
324
336
325 def complete_request(self, ident, parent):
337 def complete_request(self, ident, parent):
326 txt, matches = self._complete(parent)
338 txt, matches = self._complete(parent)
327 matches = {'matches' : matches,
339 matches = {'matches' : matches,
328 'matched_text' : txt,
340 'matched_text' : txt,
329 'status' : 'ok'}
341 'status' : 'ok'}
330 matches = json_clean(matches)
342 matches = json_clean(matches)
331 completion_msg = self.session.send(self.shell_socket, 'complete_reply',
343 completion_msg = self.session.send(self.shell_socket, 'complete_reply',
332 matches, parent, ident)
344 matches, parent, ident)
333 self.log.debug(str(completion_msg))
345 self.log.debug(str(completion_msg))
334
346
335 def object_info_request(self, ident, parent):
347 def object_info_request(self, ident, parent):
336 object_info = self.shell.object_inspect(parent['content']['oname'])
348 object_info = self.shell.object_inspect(parent['content']['oname'])
337 # Before we send this object over, we scrub it for JSON usage
349 # Before we send this object over, we scrub it for JSON usage
338 oinfo = json_clean(object_info)
350 oinfo = json_clean(object_info)
339 msg = self.session.send(self.shell_socket, 'object_info_reply',
351 msg = self.session.send(self.shell_socket, 'object_info_reply',
340 oinfo, parent, ident)
352 oinfo, parent, ident)
341 self.log.debug(msg)
353 self.log.debug(msg)
342
354
343 def history_request(self, ident, parent):
355 def history_request(self, ident, parent):
344 # We need to pull these out, as passing **kwargs doesn't work with
356 # We need to pull these out, as passing **kwargs doesn't work with
345 # unicode keys before Python 2.6.5.
357 # unicode keys before Python 2.6.5.
346 hist_access_type = parent['content']['hist_access_type']
358 hist_access_type = parent['content']['hist_access_type']
347 raw = parent['content']['raw']
359 raw = parent['content']['raw']
348 output = parent['content']['output']
360 output = parent['content']['output']
349 if hist_access_type == 'tail':
361 if hist_access_type == 'tail':
350 n = parent['content']['n']
362 n = parent['content']['n']
351 hist = self.shell.history_manager.get_tail(n, raw=raw, output=output,
363 hist = self.shell.history_manager.get_tail(n, raw=raw, output=output,
352 include_latest=True)
364 include_latest=True)
353
365
354 elif hist_access_type == 'range':
366 elif hist_access_type == 'range':
355 session = parent['content']['session']
367 session = parent['content']['session']
356 start = parent['content']['start']
368 start = parent['content']['start']
357 stop = parent['content']['stop']
369 stop = parent['content']['stop']
358 hist = self.shell.history_manager.get_range(session, start, stop,
370 hist = self.shell.history_manager.get_range(session, start, stop,
359 raw=raw, output=output)
371 raw=raw, output=output)
360
372
361 elif hist_access_type == 'search':
373 elif hist_access_type == 'search':
362 pattern = parent['content']['pattern']
374 pattern = parent['content']['pattern']
363 hist = self.shell.history_manager.search(pattern, raw=raw, output=output)
375 hist = self.shell.history_manager.search(pattern, raw=raw, output=output)
364
376
365 else:
377 else:
366 hist = []
378 hist = []
367 content = {'history' : list(hist)}
379 content = {'history' : list(hist)}
368 content = json_clean(content)
380 content = json_clean(content)
369 msg = self.session.send(self.shell_socket, 'history_reply',
381 msg = self.session.send(self.shell_socket, 'history_reply',
370 content, parent, ident)
382 content, parent, ident)
371 self.log.debug(str(msg))
383 self.log.debug(str(msg))
372
384
373 def connect_request(self, ident, parent):
385 def connect_request(self, ident, parent):
374 if self._recorded_ports is not None:
386 if self._recorded_ports is not None:
375 content = self._recorded_ports.copy()
387 content = self._recorded_ports.copy()
376 else:
388 else:
377 content = {}
389 content = {}
378 msg = self.session.send(self.shell_socket, 'connect_reply',
390 msg = self.session.send(self.shell_socket, 'connect_reply',
379 content, parent, ident)
391 content, parent, ident)
380 self.log.debug(msg)
392 self.log.debug(msg)
381
393
382 def shutdown_request(self, ident, parent):
394 def shutdown_request(self, ident, parent):
383 self.shell.exit_now = True
395 self.shell.exit_now = True
384 self._shutdown_message = self.session.msg(u'shutdown_reply', parent['content'], parent)
396 self._shutdown_message = self.session.msg(u'shutdown_reply', parent['content'], parent)
385 sys.exit(0)
397 sys.exit(0)
386
398
387 #---------------------------------------------------------------------------
399 #---------------------------------------------------------------------------
388 # Protected interface
400 # Protected interface
389 #---------------------------------------------------------------------------
401 #---------------------------------------------------------------------------
390
402
391 def _abort_queue(self):
403 def _abort_queue(self):
392 while True:
404 while True:
393 try:
405 try:
394 ident,msg = self.session.recv(self.shell_socket, zmq.NOBLOCK)
406 ident,msg = self.session.recv(self.shell_socket, zmq.NOBLOCK)
395 except Exception:
407 except Exception:
396 self.log.warn("Invalid Message:", exc_info=True)
408 self.log.warn("Invalid Message:", exc_info=True)
397 continue
409 continue
398 if msg is None:
410 if msg is None:
399 break
411 break
400 else:
412 else:
401 assert ident is not None, \
413 assert ident is not None, \
402 "Unexpected missing message part."
414 "Unexpected missing message part."
403
415
404 self.log.debug("Aborting:\n"+str(Message(msg)))
416 self.log.debug("Aborting:\n"+str(Message(msg)))
405 msg_type = msg['header']['msg_type']
417 msg_type = msg['header']['msg_type']
406 reply_type = msg_type.split('_')[0] + '_reply'
418 reply_type = msg_type.split('_')[0] + '_reply'
407 reply_msg = self.session.send(self.shell_socket, reply_type,
419 reply_msg = self.session.send(self.shell_socket, reply_type,
408 {'status' : 'aborted'}, msg, ident=ident)
420 {'status' : 'aborted'}, msg, ident=ident)
409 self.log.debug(reply_msg)
421 self.log.debug(reply_msg)
410 # We need to wait a bit for requests to come in. This can probably
422 # We need to wait a bit for requests to come in. This can probably
411 # be set shorter for true asynchronous clients.
423 # be set shorter for true asynchronous clients.
412 time.sleep(0.1)
424 time.sleep(0.1)
413
425
414 def _no_raw_input(self):
426 def _no_raw_input(self):
415 """Raise StdinNotImplentedError if active frontend doesn't support stdin."""
427 """Raise StdinNotImplentedError if active frontend doesn't support stdin."""
416 raise StdinNotImplementedError("raw_input was called, but this frontend does not support stdin.")
428 raise StdinNotImplementedError("raw_input was called, but this frontend does not support stdin.")
417
429
418 def _raw_input(self, prompt, ident, parent):
430 def _raw_input(self, prompt, ident, parent):
419 # Flush output before making the request.
431 # Flush output before making the request.
420 sys.stderr.flush()
432 sys.stderr.flush()
421 sys.stdout.flush()
433 sys.stdout.flush()
422
434
423 # Send the input request.
435 # Send the input request.
424 content = json_clean(dict(prompt=prompt))
436 content = json_clean(dict(prompt=prompt))
425 msg = self.session.send(self.stdin_socket, u'input_request', content, parent, ident=ident)
437 msg = self.session.send(self.stdin_socket, u'input_request', content, parent, ident=ident)
426
438
427 # Await a response.
439 # Await a response.
428 while True:
440 while True:
429 try:
441 try:
430 ident, reply = self.session.recv(self.stdin_socket, 0)
442 ident, reply = self.session.recv(self.stdin_socket, 0)
431 except Exception:
443 except Exception:
432 self.log.warn("Invalid Message:", exc_info=True)
444 self.log.warn("Invalid Message:", exc_info=True)
433 else:
445 else:
434 break
446 break
435 try:
447 try:
436 value = reply['content']['value']
448 value = reply['content']['value']
437 except:
449 except:
438 self.log.error("Got bad raw_input reply: ")
450 self.log.error("Got bad raw_input reply: ")
439 self.log.error(str(Message(parent)))
451 self.log.error(str(Message(parent)))
440 value = ''
452 value = ''
441 return value
453 return value
442
454
443 def _complete(self, msg):
455 def _complete(self, msg):
444 c = msg['content']
456 c = msg['content']
445 try:
457 try:
446 cpos = int(c['cursor_pos'])
458 cpos = int(c['cursor_pos'])
447 except:
459 except:
448 # If we don't get something that we can convert to an integer, at
460 # If we don't get something that we can convert to an integer, at
449 # least attempt the completion guessing the cursor is at the end of
461 # least attempt the completion guessing the cursor is at the end of
450 # the text, if there's any, and otherwise of the line
462 # the text, if there's any, and otherwise of the line
451 cpos = len(c['text'])
463 cpos = len(c['text'])
452 if cpos==0:
464 if cpos==0:
453 cpos = len(c['line'])
465 cpos = len(c['line'])
454 return self.shell.complete(c['text'], c['line'], cpos)
466 return self.shell.complete(c['text'], c['line'], cpos)
455
467
456 def _object_info(self, context):
468 def _object_info(self, context):
457 symbol, leftover = self._symbol_from_context(context)
469 symbol, leftover = self._symbol_from_context(context)
458 if symbol is not None and not leftover:
470 if symbol is not None and not leftover:
459 doc = getattr(symbol, '__doc__', '')
471 doc = getattr(symbol, '__doc__', '')
460 else:
472 else:
461 doc = ''
473 doc = ''
462 object_info = dict(docstring = doc)
474 object_info = dict(docstring = doc)
463 return object_info
475 return object_info
464
476
465 def _symbol_from_context(self, context):
477 def _symbol_from_context(self, context):
466 if not context:
478 if not context:
467 return None, context
479 return None, context
468
480
469 base_symbol_string = context[0]
481 base_symbol_string = context[0]
470 symbol = self.shell.user_ns.get(base_symbol_string, None)
482 symbol = self.shell.user_ns.get(base_symbol_string, None)
471 if symbol is None:
483 if symbol is None:
472 symbol = __builtin__.__dict__.get(base_symbol_string, None)
484 symbol = __builtin__.__dict__.get(base_symbol_string, None)
473 if symbol is None:
485 if symbol is None:
474 return None, context
486 return None, context
475
487
476 context = context[1:]
488 context = context[1:]
477 for i, name in enumerate(context):
489 for i, name in enumerate(context):
478 new_symbol = getattr(symbol, name, None)
490 new_symbol = getattr(symbol, name, None)
479 if new_symbol is None:
491 if new_symbol is None:
480 return symbol, context[i:]
492 return symbol, context[i:]
481 else:
493 else:
482 symbol = new_symbol
494 symbol = new_symbol
483
495
484 return symbol, []
496 return symbol, []
485
497
486 def _at_shutdown(self):
498 def _at_shutdown(self):
487 """Actions taken at shutdown by the kernel, called by python's atexit.
499 """Actions taken at shutdown by the kernel, called by python's atexit.
488 """
500 """
489 # io.rprint("Kernel at_shutdown") # dbg
501 # io.rprint("Kernel at_shutdown") # dbg
490 if self._shutdown_message is not None:
502 if self._shutdown_message is not None:
491 self.session.send(self.shell_socket, self._shutdown_message)
503 self.session.send(self.shell_socket, self._shutdown_message)
492 self.session.send(self.iopub_socket, self._shutdown_message)
504 self.session.send(self.iopub_socket, self._shutdown_message)
493 self.log.debug(str(self._shutdown_message))
505 self.log.debug(str(self._shutdown_message))
494 # A very short sleep to give zmq time to flush its message buffers
506 # A very short sleep to give zmq time to flush its message buffers
495 # before Python truly shuts down.
507 # before Python truly shuts down.
496 time.sleep(0.01)
508 time.sleep(0.01)
497
509
498
510
499 class QtKernel(Kernel):
511 #------------------------------------------------------------------------------
500 """A Kernel subclass with Qt support."""
512 # Eventloops for integrating the Kernel into different GUIs
513 #------------------------------------------------------------------------------
501
514
502 def start(self):
503 """Start a kernel with QtPy4 event loop integration."""
504
515
505 from IPython.external.qt_for_kernel import QtCore
516 def loop_qt4(kernel):
506 from IPython.lib.guisupport import get_app_qt4, start_event_loop_qt4
517 """Start a kernel with PyQt4 event loop integration."""
507
518
508 self.app = get_app_qt4([" "])
519 from IPython.external.qt_for_kernel import QtCore
509 self.app.setQuitOnLastWindowClosed(False)
520 from IPython.lib.guisupport import get_app_qt4, start_event_loop_qt4
510 self.timer = QtCore.QTimer()
511 self.timer.timeout.connect(self.do_one_iteration)
512 # Units for the timer are in milliseconds
513 self.timer.start(1000*self._poll_interval)
514 start_event_loop_qt4(self.app)
515
521
522 kernel.app = get_app_qt4([" "])
523 kernel.app.setQuitOnLastWindowClosed(False)
524 kernel.timer = QtCore.QTimer()
525 kernel.timer.timeout.connect(kernel.do_one_iteration)
526 # Units for the timer are in milliseconds
527 kernel.timer.start(1000*kernel._poll_interval)
528 start_event_loop_qt4(kernel.app)
516
529
517 class WxKernel(Kernel):
518 """A Kernel subclass with Wx support."""
519
530
520 def start(self):
531 def loop_wx(kernel):
521 """Start a kernel with wx event loop support."""
532 """Start a kernel with wx event loop support."""
522
523 import wx
524 from IPython.lib.guisupport import start_event_loop_wx
525
526 doi = self.do_one_iteration
527 # Wx uses milliseconds
528 poll_interval = int(1000*self._poll_interval)
529
530 # We have to put the wx.Timer in a wx.Frame for it to fire properly.
531 # We make the Frame hidden when we create it in the main app below.
532 class TimerFrame(wx.Frame):
533 def __init__(self, func):
534 wx.Frame.__init__(self, None, -1)
535 self.timer = wx.Timer(self)
536 # Units for the timer are in milliseconds
537 self.timer.Start(poll_interval)
538 self.Bind(wx.EVT_TIMER, self.on_timer)
539 self.func = func
540
541 def on_timer(self, event):
542 self.func()
543
544 # We need a custom wx.App to create our Frame subclass that has the
545 # wx.Timer to drive the ZMQ event loop.
546 class IPWxApp(wx.App):
547 def OnInit(self):
548 self.frame = TimerFrame(doi)
549 self.frame.Show(False)
550 return True
551
552 # The redirect=False here makes sure that wx doesn't replace
553 # sys.stdout/stderr with its own classes.
554 self.app = IPWxApp(redirect=False)
555 start_event_loop_wx(self.app)
556
557
558 class TkKernel(Kernel):
559 """A Kernel subclass with Tk support."""
560
533
561 def start(self):
534 import wx
562 """Start a Tk enabled event loop."""
535 from IPython.lib.guisupport import start_event_loop_wx
563
536
564 import Tkinter
537 doi = kernel.do_one_iteration
565 doi = self.do_one_iteration
538 # Wx uses milliseconds
566 # Tk uses milliseconds
539 poll_interval = int(1000*kernel._poll_interval)
567 poll_interval = int(1000*self._poll_interval)
568 # For Tkinter, we create a Tk object and call its withdraw method.
569 class Timer(object):
570 def __init__(self, func):
571 self.app = Tkinter.Tk()
572 self.app.withdraw()
573 self.func = func
574
540
575 def on_timer(self):
541 # We have to put the wx.Timer in a wx.Frame for it to fire properly.
576 self.func()
542 # We make the Frame hidden when we create it in the main app below.
577 self.app.after(poll_interval, self.on_timer)
543 class TimerFrame(wx.Frame):
544 def __init__(self, func):
545 wx.Frame.__init__(self, None, -1)
546 self.timer = wx.Timer(self)
547 # Units for the timer are in milliseconds
548 self.timer.Start(poll_interval)
549 self.Bind(wx.EVT_TIMER, self.on_timer)
550 self.func = func
578
551
579 def start(self):
552 def on_timer(self, event):
580 self.on_timer() # Call it once to get things going.
553 self.func()
581 self.app.mainloop()
582
554
583 self.timer = Timer(doi)
555 # We need a custom wx.App to create our Frame subclass that has the
584 self.timer.start()
556 # wx.Timer to drive the ZMQ event loop.
557 class IPWxApp(wx.App):
558 def OnInit(self):
559 self.frame = TimerFrame(doi)
560 self.frame.Show(False)
561 return True
585
562
563 # The redirect=False here makes sure that wx doesn't replace
564 # sys.stdout/stderr with its own classes.
565 kernel.app = IPWxApp(redirect=False)
566 start_event_loop_wx(kernel.app)
586
567
587 class GTKKernel(Kernel):
588 """A Kernel subclass with GTK support."""
589
568
590 def start(self):
569 def loop_tk(kernel):
591 """Start the kernel, coordinating with the GTK event loop"""
570 """Start a kernel with the Tk event loop."""
592 from .gui.gtkembed import GTKEmbed
571
572 import Tkinter
573 doi = kernel.do_one_iteration
574 # Tk uses milliseconds
575 poll_interval = int(1000*kernel._poll_interval)
576 # For Tkinter, we create a Tk object and call its withdraw method.
577 class Timer(object):
578 def __init__(self, func):
579 self.app = Tkinter.Tk()
580 self.app.withdraw()
581 self.func = func
593
582
594 gtk_kernel = GTKEmbed(self)
583 def on_timer(self):
595 gtk_kernel.start()
584 self.func()
585 self.app.after(poll_interval, self.on_timer)
596
586
587 def start(self):
588 self.on_timer() # Call it once to get things going.
589 self.app.mainloop()
597
590
598 class OSXKernel(TkKernel):
591 kernel.timer = Timer(doi)
599 """A Kernel subclass with Cocoa support via the matplotlib OSX backend."""
592 kernel.timer.start()
593
594
595 def loop_gtk(kernel):
596 """Start the kernel, coordinating with the GTK event loop"""
597 from .gui.gtkembed import GTKEmbed
598
599 gtk_kernel = GTKEmbed(kernel)
600 gtk_kernel.start()
601
602
603 def loop_cocoa(kernel):
604 """Start the kernel, coordinating with the Cocoa CFRunLoop event loop
605 via the matplotlib MacOSX backend.
606 """
607 import matplotlib
608 if matplotlib.__version__ < '1.1.0':
609 kernel.log.warn(
610 "MacOSX backend in matplotlib %s doesn't have a Timer, "
611 "falling back on Tk for CFRunLoop integration. Note that "
612 "even this won't work if Tk is linked against X11 instead of "
613 "Cocoa (e.g. EPD). To use the MacOSX backend in the kernel, "
614 "you must use matplotlib >= 1.1.0, or a native libtk."
615 )
616 return loop_tk(kernel)
600
617
601 def start(self):
618 from matplotlib.backends.backend_macosx import TimerMac, show
602 """Start the kernel, coordinating with the Cocoa CFRunLoop event loop
619
603 via the matplotlib MacOSX backend.
620 # scale interval for sec->ms
604 """
621 poll_interval = int(1000*kernel._poll_interval)
605 import matplotlib
622
606 if matplotlib.__version__ < '1.1.0':
623 real_excepthook = sys.excepthook
607 self.log.warn(
624 def handle_int(etype, value, tb):
608 "MacOSX backend in matplotlib %s doesn't have a Timer, "
625 """don't let KeyboardInterrupts look like crashes"""
609 "falling back on Tk for CFRunLoop integration. Note that "
626 if etype is KeyboardInterrupt:
610 "even this won't work if Tk is linked against X11 instead of "
627 io.raw_print("KeyboardInterrupt caught in CFRunLoop")
611 "Cocoa (e.g. EPD). To use the MacOSX backend in the kernel, "
628 else:
612 "you must use matplotlib >= 1.1.0, or a native libtk."
629 real_excepthook(etype, value, tb)
613 )
630
614 return TkKernel.start(self)
631 # add doi() as a Timer to the CFRunLoop
615
632 def doi():
616 from matplotlib.backends.backend_macosx import TimerMac, show
633 # restore excepthook during IPython code
617
634 sys.excepthook = real_excepthook
618 # scale interval for sec->ms
635 kernel.do_one_iteration()
619 poll_interval = int(1000*self._poll_interval)
636 # and back:
620
637 sys.excepthook = handle_int
621 real_excepthook = sys.excepthook
638
622 def handle_int(etype, value, tb):
639 t = TimerMac(poll_interval)
623 """don't let KeyboardInterrupts look like crashes"""
640 t.add_callback(doi)
624 if etype is KeyboardInterrupt:
641 t.start()
625 io.raw_print("KeyboardInterrupt caught in CFRunLoop")
642
626 else:
643 # but still need a Poller for when there are no active windows,
627 real_excepthook(etype, value, tb)
644 # during which time mainloop() returns immediately
628
645 poller = zmq.Poller()
629 # add doi() as a Timer to the CFRunLoop
646 poller.register(kernel.shell_socket, zmq.POLLIN)
630 def doi():
647
631 # restore excepthook during IPython code
648 while True:
632 sys.excepthook = real_excepthook
649 try:
633 self.do_one_iteration()
650 # double nested try/except, to properly catch KeyboardInterrupt
634 # and back:
651 # due to pyzmq Issue #130
635 sys.excepthook = handle_int
636
637 t = TimerMac(poll_interval)
638 t.add_callback(doi)
639 t.start()
640
641 # but still need a Poller for when there are no active windows,
642 # during which time mainloop() returns immediately
643 poller = zmq.Poller()
644 poller.register(self.shell_socket, zmq.POLLIN)
645
646 while True:
647 try:
652 try:
648 # double nested try/except, to properly catch KeyboardInterrupt
653 # don't let interrupts during mainloop invoke crash_handler:
649 # due to pyzmq Issue #130
654 sys.excepthook = handle_int
650 try:
655 show.mainloop()
651 # don't let interrupts during mainloop invoke crash_handler:
652 sys.excepthook = handle_int
653 show.mainloop()
654 sys.excepthook = real_excepthook
655 # use poller if mainloop returned (no windows)
656 # scale by extra factor of 10, since it's a real poll
657 poller.poll(10*poll_interval)
658 self.do_one_iteration()
659 except:
660 raise
661 except KeyboardInterrupt:
662 # Ctrl-C shouldn't crash the kernel
663 io.raw_print("KeyboardInterrupt caught in kernel")
664 finally:
665 # ensure excepthook is restored
666 sys.excepthook = real_excepthook
656 sys.excepthook = real_excepthook
657 # use poller if mainloop returned (no windows)
658 # scale by extra factor of 10, since it's a real poll
659 poller.poll(10*poll_interval)
660 kernel.do_one_iteration()
661 except:
662 raise
663 except KeyboardInterrupt:
664 # Ctrl-C shouldn't crash the kernel
665 io.raw_print("KeyboardInterrupt caught in kernel")
666 finally:
667 # ensure excepthook is restored
668 sys.excepthook = real_excepthook
669
670 # mapping of keys to loop functions
671 loop_map = {
672 'qt' : loop_qt4,
673 'qt4': loop_qt4,
674 'inline': None,
675 'osx': loop_cocoa,
676 'wx' : loop_wx,
677 'tk' : loop_tk,
678 'gtk': loop_gtk,
679 }
680
681 def enable_gui(gui, kernel=None):
682 """Enable integration with a give GUI"""
683 if kernel is None:
684 kernel = IPKernelApp.instance().kernel
685 if gui not in loop_map:
686 raise ValueError("GUI %r not supported" % gui)
687 loop = loop_map[gui]
688 if kernel.eventloop is not None and kernel.eventloop is not loop:
689 raise RuntimeError("Cannot activate multiple GUI eventloops")
690 kernel.eventloop = loop
667
691
668
692
669 #-----------------------------------------------------------------------------
693 #-----------------------------------------------------------------------------
670 # Aliases and Flags for the IPKernelApp
694 # Aliases and Flags for the IPKernelApp
671 #-----------------------------------------------------------------------------
695 #-----------------------------------------------------------------------------
672
696
673 flags = dict(kernel_flags)
697 flags = dict(kernel_flags)
674 flags.update(shell_flags)
698 flags.update(shell_flags)
675
699
676 addflag = lambda *args: flags.update(boolean_flag(*args))
700 addflag = lambda *args: flags.update(boolean_flag(*args))
677
701
678 flags['pylab'] = (
702 flags['pylab'] = (
679 {'IPKernelApp' : {'pylab' : 'auto'}},
703 {'IPKernelApp' : {'pylab' : 'auto'}},
680 """Pre-load matplotlib and numpy for interactive use with
704 """Pre-load matplotlib and numpy for interactive use with
681 the default matplotlib backend."""
705 the default matplotlib backend."""
682 )
706 )
683
707
684 aliases = dict(kernel_aliases)
708 aliases = dict(kernel_aliases)
685 aliases.update(shell_aliases)
709 aliases.update(shell_aliases)
686
710
687 # it's possible we don't want short aliases for *all* of these:
711 # it's possible we don't want short aliases for *all* of these:
688 aliases.update(dict(
712 aliases.update(dict(
689 pylab='IPKernelApp.pylab',
713 pylab='IPKernelApp.pylab',
690 ))
714 ))
691
715
692 #-----------------------------------------------------------------------------
716 #-----------------------------------------------------------------------------
693 # The IPKernelApp class
717 # The IPKernelApp class
694 #-----------------------------------------------------------------------------
718 #-----------------------------------------------------------------------------
695
719
696 class IPKernelApp(KernelApp, InteractiveShellApp):
720 class IPKernelApp(KernelApp, InteractiveShellApp):
697 name = 'ipkernel'
721 name = 'ipkernel'
698
722
699 aliases = Dict(aliases)
723 aliases = Dict(aliases)
700 flags = Dict(flags)
724 flags = Dict(flags)
701 classes = [Kernel, ZMQInteractiveShell, ProfileDir, Session]
725 classes = [Kernel, ZMQInteractiveShell, ProfileDir, Session]
702 # configurables
726 # configurables
703 pylab = CaselessStrEnum(['tk', 'qt', 'wx', 'gtk', 'osx', 'inline', 'auto'],
727 pylab = CaselessStrEnum(['tk', 'qt', 'wx', 'gtk', 'osx', 'inline', 'auto'],
704 config=True,
728 config=True,
705 help="""Pre-load matplotlib and numpy for interactive use,
729 help="""Pre-load matplotlib and numpy for interactive use,
706 selecting a particular matplotlib backend and loop integration.
730 selecting a particular matplotlib backend and loop integration.
707 """
731 """
708 )
732 )
709 def initialize(self, argv=None):
733 def initialize(self, argv=None):
710 super(IPKernelApp, self).initialize(argv)
734 super(IPKernelApp, self).initialize(argv)
711 self.init_shell()
735 self.init_shell()
712 self.init_extensions()
736 self.init_extensions()
713 self.init_code()
737 self.init_code()
714
738
715 def init_kernel(self):
739 def init_kernel(self):
716 kernel_factory = Kernel
740 kernel_factory = Kernel
717
741
718 kernel_map = {
719 'qt' : QtKernel,
720 'qt4': QtKernel,
721 'inline': Kernel,
722 'osx': OSXKernel,
723 'wx' : WxKernel,
724 'tk' : TkKernel,
725 'gtk': GTKKernel,
726 }
727
728 if self.pylab:
742 if self.pylab:
729 key = None if self.pylab == 'auto' else self.pylab
743 key = None if self.pylab == 'auto' else self.pylab
730 gui, backend = pylabtools.find_gui_and_backend(key)
744 gui, backend = pylabtools.find_gui_and_backend(key)
731 kernel_factory = kernel_map.get(gui)
732 if kernel_factory is None:
733 raise ValueError('GUI is not supported: %r' % gui)
734 pylabtools.activate_matplotlib(backend)
735
745
736 kernel = kernel_factory(config=self.config, session=self.session,
746 kernel = kernel_factory(config=self.config, session=self.session,
737 shell_socket=self.shell_socket,
747 shell_socket=self.shell_socket,
738 iopub_socket=self.iopub_socket,
748 iopub_socket=self.iopub_socket,
739 stdin_socket=self.stdin_socket,
749 stdin_socket=self.stdin_socket,
740 log=self.log
750 log=self.log,
741 )
751 )
742 self.kernel = kernel
752 self.kernel = kernel
743 kernel.record_ports(self.ports)
753 kernel.record_ports(self.ports)
744
754
745 if self.pylab:
755 if self.pylab:
746 import_all = self.pylab_import_all
756 kernel.shell.enable_pylab(gui, import_all=self.pylab_import_all)
747 pylabtools.import_pylab(kernel.shell.user_ns, backend, import_all,
748 shell=kernel.shell)
749
757
750 def init_shell(self):
758 def init_shell(self):
751 self.shell = self.kernel.shell
759 self.shell = self.kernel.shell
752
760
753
761
754 #-----------------------------------------------------------------------------
762 #-----------------------------------------------------------------------------
755 # Kernel main and launch functions
763 # Kernel main and launch functions
756 #-----------------------------------------------------------------------------
764 #-----------------------------------------------------------------------------
757
765
758 def launch_kernel(*args, **kwargs):
766 def launch_kernel(*args, **kwargs):
759 """Launches a localhost IPython kernel, binding to the specified ports.
767 """Launches a localhost IPython kernel, binding to the specified ports.
760
768
761 This function simply calls entry_point.base_launch_kernel with the right first
769 This function simply calls entry_point.base_launch_kernel with the right first
762 command to start an ipkernel. See base_launch_kernel for arguments.
770 command to start an ipkernel. See base_launch_kernel for arguments.
763
771
764 Returns
772 Returns
765 -------
773 -------
766 A tuple of form:
774 A tuple of form:
767 (kernel_process, shell_port, iopub_port, stdin_port, hb_port)
775 (kernel_process, shell_port, iopub_port, stdin_port, hb_port)
768 where kernel_process is a Popen object and the ports are integers.
776 where kernel_process is a Popen object and the ports are integers.
769 """
777 """
770 return base_launch_kernel('from IPython.zmq.ipkernel import main; main()',
778 return base_launch_kernel('from IPython.zmq.ipkernel import main; main()',
771 *args, **kwargs)
779 *args, **kwargs)
772
780
773
781
774 def main():
782 def main():
775 """Run an IPKernel as an application"""
783 """Run an IPKernel as an application"""
776 app = IPKernelApp.instance()
784 app = IPKernelApp.instance()
777 app.initialize()
785 app.initialize()
778 app.start()
786 app.start()
779
787
780
788
781 if __name__ == '__main__':
789 if __name__ == '__main__':
782 main()
790 main()
@@ -1,495 +1,548 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 sys
21 import sys
22 from subprocess import Popen, PIPE
22 from subprocess import Popen, PIPE
23
23
24 # Our own
24 # Our own
25 from IPython.core.interactiveshell import (
25 from IPython.core.interactiveshell import (
26 InteractiveShell, InteractiveShellABC
26 InteractiveShell, InteractiveShellABC
27 )
27 )
28 from IPython.core import page
28 from IPython.core import page
29 from IPython.core.autocall import ZMQExitAutocall
29 from IPython.core.autocall import ZMQExitAutocall
30 from IPython.core.displaypub import DisplayPublisher
30 from IPython.core.displaypub import DisplayPublisher
31 from IPython.core.macro import Macro
31 from IPython.core.macro import Macro
32 from IPython.core.magic import MacroToEdit
32 from IPython.core.magic import MacroToEdit
33 from IPython.core.payloadpage import install_payload_page
33 from IPython.core.payloadpage import install_payload_page
34 from IPython.lib import pylabtools
34 from IPython.lib.kernel import (
35 from IPython.lib.kernel import (
35 get_connection_file, get_connection_info, connect_qtconsole
36 get_connection_file, get_connection_info, connect_qtconsole
36 )
37 )
37 from IPython.utils import io
38 from IPython.utils import io
38 from IPython.utils.jsonutil import json_clean
39 from IPython.utils.jsonutil import json_clean
39 from IPython.utils.path import get_py_filename
40 from IPython.utils.path import get_py_filename
40 from IPython.utils.process import arg_split
41 from IPython.utils.process import arg_split
41 from IPython.utils.traitlets import Instance, Type, Dict, CBool
42 from IPython.utils.traitlets import Instance, Type, Dict, CBool
42 from IPython.utils.warn import warn, error
43 from IPython.utils.warn import warn, error
43 from IPython.zmq.displayhook import ZMQShellDisplayHook, _encode_binary
44 from IPython.zmq.displayhook import ZMQShellDisplayHook, _encode_binary
44 from IPython.zmq.session import extract_header
45 from IPython.zmq.session import extract_header
45 from session import Session
46 from session import Session
46
47
47 #-----------------------------------------------------------------------------
48 #-----------------------------------------------------------------------------
48 # Globals and side-effects
49 # Globals and side-effects
49 #-----------------------------------------------------------------------------
50 #-----------------------------------------------------------------------------
50
51
51 # Install the payload version of page.
52 # Install the payload version of page.
52 install_payload_page()
53 install_payload_page()
53
54
54 #-----------------------------------------------------------------------------
55 #-----------------------------------------------------------------------------
55 # Functions and classes
56 # Functions and classes
56 #-----------------------------------------------------------------------------
57 #-----------------------------------------------------------------------------
57
58
58 class ZMQDisplayPublisher(DisplayPublisher):
59 class ZMQDisplayPublisher(DisplayPublisher):
59 """A display publisher that publishes data using a ZeroMQ PUB socket."""
60 """A display publisher that publishes data using a ZeroMQ PUB socket."""
60
61
61 session = Instance(Session)
62 session = Instance(Session)
62 pub_socket = Instance('zmq.Socket')
63 pub_socket = Instance('zmq.Socket')
63 parent_header = Dict({})
64 parent_header = Dict({})
64
65
65 def set_parent(self, parent):
66 def set_parent(self, parent):
66 """Set the parent for outbound messages."""
67 """Set the parent for outbound messages."""
67 self.parent_header = extract_header(parent)
68 self.parent_header = extract_header(parent)
68
69
69 def publish(self, source, data, metadata=None):
70 def publish(self, source, data, metadata=None):
70 if metadata is None:
71 if metadata is None:
71 metadata = {}
72 metadata = {}
72 self._validate_data(source, data, metadata)
73 self._validate_data(source, data, metadata)
73 content = {}
74 content = {}
74 content['source'] = source
75 content['source'] = source
75 _encode_binary(data)
76 _encode_binary(data)
76 content['data'] = data
77 content['data'] = data
77 content['metadata'] = metadata
78 content['metadata'] = metadata
78 self.session.send(
79 self.session.send(
79 self.pub_socket, u'display_data', json_clean(content),
80 self.pub_socket, u'display_data', json_clean(content),
80 parent=self.parent_header
81 parent=self.parent_header
81 )
82 )
82
83
83 def clear_output(self, stdout=True, stderr=True, other=True):
84 def clear_output(self, stdout=True, stderr=True, other=True):
84 content = dict(stdout=stdout, stderr=stderr, other=other)
85 content = dict(stdout=stdout, stderr=stderr, other=other)
85 self.session.send(
86 self.session.send(
86 self.pub_socket, u'clear_output', content,
87 self.pub_socket, u'clear_output', content,
87 parent=self.parent_header
88 parent=self.parent_header
88 )
89 )
89
90
90 class ZMQInteractiveShell(InteractiveShell):
91 class ZMQInteractiveShell(InteractiveShell):
91 """A subclass of InteractiveShell for ZMQ."""
92 """A subclass of InteractiveShell for ZMQ."""
92
93
93 displayhook_class = Type(ZMQShellDisplayHook)
94 displayhook_class = Type(ZMQShellDisplayHook)
94 display_pub_class = Type(ZMQDisplayPublisher)
95 display_pub_class = Type(ZMQDisplayPublisher)
95
96
96 # Override the traitlet in the parent class, because there's no point using
97 # Override the traitlet in the parent class, because there's no point using
97 # readline for the kernel. Can be removed when the readline code is moved
98 # readline for the kernel. Can be removed when the readline code is moved
98 # to the terminal frontend.
99 # to the terminal frontend.
99 colors_force = CBool(True)
100 colors_force = CBool(True)
100 readline_use = CBool(False)
101 readline_use = CBool(False)
101 # autoindent has no meaning in a zmqshell, and attempting to enable it
102 # autoindent has no meaning in a zmqshell, and attempting to enable it
102 # will print a warning in the absence of readline.
103 # will print a warning in the absence of readline.
103 autoindent = CBool(False)
104 autoindent = CBool(False)
104
105
105 exiter = Instance(ZMQExitAutocall)
106 exiter = Instance(ZMQExitAutocall)
106 def _exiter_default(self):
107 def _exiter_default(self):
107 return ZMQExitAutocall(self)
108 return ZMQExitAutocall(self)
108
109
109 keepkernel_on_exit = None
110 keepkernel_on_exit = None
110
111
111 def init_environment(self):
112 def init_environment(self):
112 """Configure the user's environment.
113 """Configure the user's environment.
113
114
114 """
115 """
115 env = os.environ
116 env = os.environ
116 # These two ensure 'ls' produces nice coloring on BSD-derived systems
117 # These two ensure 'ls' produces nice coloring on BSD-derived systems
117 env['TERM'] = 'xterm-color'
118 env['TERM'] = 'xterm-color'
118 env['CLICOLOR'] = '1'
119 env['CLICOLOR'] = '1'
119 # Since normal pagers don't work at all (over pexpect we don't have
120 # Since normal pagers don't work at all (over pexpect we don't have
120 # single-key control of the subprocess), try to disable paging in
121 # single-key control of the subprocess), try to disable paging in
121 # subprocesses as much as possible.
122 # subprocesses as much as possible.
122 env['PAGER'] = 'cat'
123 env['PAGER'] = 'cat'
123 env['GIT_PAGER'] = 'cat'
124 env['GIT_PAGER'] = 'cat'
124
125
125 def auto_rewrite_input(self, cmd):
126 def auto_rewrite_input(self, cmd):
126 """Called to show the auto-rewritten input for autocall and friends.
127 """Called to show the auto-rewritten input for autocall and friends.
127
128
128 FIXME: this payload is currently not correctly processed by the
129 FIXME: this payload is currently not correctly processed by the
129 frontend.
130 frontend.
130 """
131 """
131 new = self.displayhook.prompt1.auto_rewrite() + cmd
132 new = self.displayhook.prompt1.auto_rewrite() + cmd
132 payload = dict(
133 payload = dict(
133 source='IPython.zmq.zmqshell.ZMQInteractiveShell.auto_rewrite_input',
134 source='IPython.zmq.zmqshell.ZMQInteractiveShell.auto_rewrite_input',
134 transformed_input=new,
135 transformed_input=new,
135 )
136 )
136 self.payload_manager.write_payload(payload)
137 self.payload_manager.write_payload(payload)
137
138
138 def ask_exit(self):
139 def ask_exit(self):
139 """Engage the exit actions."""
140 """Engage the exit actions."""
140 payload = dict(
141 payload = dict(
141 source='IPython.zmq.zmqshell.ZMQInteractiveShell.ask_exit',
142 source='IPython.zmq.zmqshell.ZMQInteractiveShell.ask_exit',
142 exit=True,
143 exit=True,
143 keepkernel=self.keepkernel_on_exit,
144 keepkernel=self.keepkernel_on_exit,
144 )
145 )
145 self.payload_manager.write_payload(payload)
146 self.payload_manager.write_payload(payload)
146
147
147 def _showtraceback(self, etype, evalue, stb):
148 def _showtraceback(self, etype, evalue, stb):
148
149
149 exc_content = {
150 exc_content = {
150 u'traceback' : stb,
151 u'traceback' : stb,
151 u'ename' : unicode(etype.__name__),
152 u'ename' : unicode(etype.__name__),
152 u'evalue' : unicode(evalue)
153 u'evalue' : unicode(evalue)
153 }
154 }
154
155
155 dh = self.displayhook
156 dh = self.displayhook
156 # Send exception info over pub socket for other clients than the caller
157 # Send exception info over pub socket for other clients than the caller
157 # to pick up
158 # to pick up
158 exc_msg = dh.session.send(dh.pub_socket, u'pyerr', json_clean(exc_content), dh.parent_header)
159 exc_msg = dh.session.send(dh.pub_socket, u'pyerr', json_clean(exc_content), dh.parent_header)
159
160
160 # FIXME - Hack: store exception info in shell object. Right now, the
161 # FIXME - Hack: store exception info in shell object. Right now, the
161 # caller is reading this info after the fact, we need to fix this logic
162 # caller is reading this info after the fact, we need to fix this logic
162 # to remove this hack. Even uglier, we need to store the error status
163 # to remove this hack. Even uglier, we need to store the error status
163 # here, because in the main loop, the logic that sets it is being
164 # here, because in the main loop, the logic that sets it is being
164 # skipped because runlines swallows the exceptions.
165 # skipped because runlines swallows the exceptions.
165 exc_content[u'status'] = u'error'
166 exc_content[u'status'] = u'error'
166 self._reply_content = exc_content
167 self._reply_content = exc_content
167 # /FIXME
168 # /FIXME
168
169
169 return exc_content
170 return exc_content
170
171
171 #------------------------------------------------------------------------
172 #------------------------------------------------------------------------
172 # Magic overrides
173 # Magic overrides
173 #------------------------------------------------------------------------
174 #------------------------------------------------------------------------
174 # Once the base class stops inheriting from magic, this code needs to be
175 # Once the base class stops inheriting from magic, this code needs to be
175 # moved into a separate machinery as well. For now, at least isolate here
176 # moved into a separate machinery as well. For now, at least isolate here
176 # the magics which this class needs to implement differently from the base
177 # the magics which this class needs to implement differently from the base
177 # class, or that are unique to it.
178 # class, or that are unique to it.
178
179
179 def magic_doctest_mode(self,parameter_s=''):
180 def magic_doctest_mode(self,parameter_s=''):
180 """Toggle doctest mode on and off.
181 """Toggle doctest mode on and off.
181
182
182 This mode is intended to make IPython behave as much as possible like a
183 This mode is intended to make IPython behave as much as possible like a
183 plain Python shell, from the perspective of how its prompts, exceptions
184 plain Python shell, from the perspective of how its prompts, exceptions
184 and output look. This makes it easy to copy and paste parts of a
185 and output look. This makes it easy to copy and paste parts of a
185 session into doctests. It does so by:
186 session into doctests. It does so by:
186
187
187 - Changing the prompts to the classic ``>>>`` ones.
188 - Changing the prompts to the classic ``>>>`` ones.
188 - Changing the exception reporting mode to 'Plain'.
189 - Changing the exception reporting mode to 'Plain'.
189 - Disabling pretty-printing of output.
190 - Disabling pretty-printing of output.
190
191
191 Note that IPython also supports the pasting of code snippets that have
192 Note that IPython also supports the pasting of code snippets that have
192 leading '>>>' and '...' prompts in them. This means that you can paste
193 leading '>>>' and '...' prompts in them. This means that you can paste
193 doctests from files or docstrings (even if they have leading
194 doctests from files or docstrings (even if they have leading
194 whitespace), and the code will execute correctly. You can then use
195 whitespace), and the code will execute correctly. You can then use
195 '%history -t' to see the translated history; this will give you the
196 '%history -t' to see the translated history; this will give you the
196 input after removal of all the leading prompts and whitespace, which
197 input after removal of all the leading prompts and whitespace, which
197 can be pasted back into an editor.
198 can be pasted back into an editor.
198
199
199 With these features, you can switch into this mode easily whenever you
200 With these features, you can switch into this mode easily whenever you
200 need to do testing and changes to doctests, without having to leave
201 need to do testing and changes to doctests, without having to leave
201 your existing IPython session.
202 your existing IPython session.
202 """
203 """
203
204
204 from IPython.utils.ipstruct import Struct
205 from IPython.utils.ipstruct import Struct
205
206
206 # Shorthands
207 # Shorthands
207 shell = self.shell
208 shell = self.shell
208 disp_formatter = self.shell.display_formatter
209 disp_formatter = self.shell.display_formatter
209 ptformatter = disp_formatter.formatters['text/plain']
210 ptformatter = disp_formatter.formatters['text/plain']
210 # dstore is a data store kept in the instance metadata bag to track any
211 # dstore is a data store kept in the instance metadata bag to track any
211 # changes we make, so we can undo them later.
212 # changes we make, so we can undo them later.
212 dstore = shell.meta.setdefault('doctest_mode', Struct())
213 dstore = shell.meta.setdefault('doctest_mode', Struct())
213 save_dstore = dstore.setdefault
214 save_dstore = dstore.setdefault
214
215
215 # save a few values we'll need to recover later
216 # save a few values we'll need to recover later
216 mode = save_dstore('mode', False)
217 mode = save_dstore('mode', False)
217 save_dstore('rc_pprint', ptformatter.pprint)
218 save_dstore('rc_pprint', ptformatter.pprint)
218 save_dstore('rc_plain_text_only',disp_formatter.plain_text_only)
219 save_dstore('rc_plain_text_only',disp_formatter.plain_text_only)
219 save_dstore('xmode', shell.InteractiveTB.mode)
220 save_dstore('xmode', shell.InteractiveTB.mode)
220
221
221 if mode == False:
222 if mode == False:
222 # turn on
223 # turn on
223 ptformatter.pprint = False
224 ptformatter.pprint = False
224 disp_formatter.plain_text_only = True
225 disp_formatter.plain_text_only = True
225 shell.magic_xmode('Plain')
226 shell.magic_xmode('Plain')
226 else:
227 else:
227 # turn off
228 # turn off
228 ptformatter.pprint = dstore.rc_pprint
229 ptformatter.pprint = dstore.rc_pprint
229 disp_formatter.plain_text_only = dstore.rc_plain_text_only
230 disp_formatter.plain_text_only = dstore.rc_plain_text_only
230 shell.magic_xmode(dstore.xmode)
231 shell.magic_xmode(dstore.xmode)
231
232
232 # Store new mode and inform on console
233 # Store new mode and inform on console
233 dstore.mode = bool(1-int(mode))
234 dstore.mode = bool(1-int(mode))
234 mode_label = ['OFF','ON'][dstore.mode]
235 mode_label = ['OFF','ON'][dstore.mode]
235 print('Doctest mode is:', mode_label)
236 print('Doctest mode is:', mode_label)
236
237
237 # Send the payload back so that clients can modify their prompt display
238 # Send the payload back so that clients can modify their prompt display
238 payload = dict(
239 payload = dict(
239 source='IPython.zmq.zmqshell.ZMQInteractiveShell.magic_doctest_mode',
240 source='IPython.zmq.zmqshell.ZMQInteractiveShell.magic_doctest_mode',
240 mode=dstore.mode)
241 mode=dstore.mode)
241 self.payload_manager.write_payload(payload)
242 self.payload_manager.write_payload(payload)
242
243
243 def magic_edit(self,parameter_s='',last_call=['','']):
244 def magic_edit(self,parameter_s='',last_call=['','']):
244 """Bring up an editor and execute the resulting code.
245 """Bring up an editor and execute the resulting code.
245
246
246 Usage:
247 Usage:
247 %edit [options] [args]
248 %edit [options] [args]
248
249
249 %edit runs an external text editor. You will need to set the command for
250 %edit runs an external text editor. You will need to set the command for
250 this editor via the ``TerminalInteractiveShell.editor`` option in your
251 this editor via the ``TerminalInteractiveShell.editor`` option in your
251 configuration file before it will work.
252 configuration file before it will work.
252
253
253 This command allows you to conveniently edit multi-line code right in
254 This command allows you to conveniently edit multi-line code right in
254 your IPython session.
255 your IPython session.
255
256
256 If called without arguments, %edit opens up an empty editor with a
257 If called without arguments, %edit opens up an empty editor with a
257 temporary file and will execute the contents of this file when you
258 temporary file and will execute the contents of this file when you
258 close it (don't forget to save it!).
259 close it (don't forget to save it!).
259
260
260
261
261 Options:
262 Options:
262
263
263 -n <number>: open the editor at a specified line number. By default,
264 -n <number>: open the editor at a specified line number. By default,
264 the IPython editor hook uses the unix syntax 'editor +N filename', but
265 the IPython editor hook uses the unix syntax 'editor +N filename', but
265 you can configure this by providing your own modified hook if your
266 you can configure this by providing your own modified hook if your
266 favorite editor supports line-number specifications with a different
267 favorite editor supports line-number specifications with a different
267 syntax.
268 syntax.
268
269
269 -p: this will call the editor with the same data as the previous time
270 -p: this will call the editor with the same data as the previous time
270 it was used, regardless of how long ago (in your current session) it
271 it was used, regardless of how long ago (in your current session) it
271 was.
272 was.
272
273
273 -r: use 'raw' input. This option only applies to input taken from the
274 -r: use 'raw' input. This option only applies to input taken from the
274 user's history. By default, the 'processed' history is used, so that
275 user's history. By default, the 'processed' history is used, so that
275 magics are loaded in their transformed version to valid Python. If
276 magics are loaded in their transformed version to valid Python. If
276 this option is given, the raw input as typed as the command line is
277 this option is given, the raw input as typed as the command line is
277 used instead. When you exit the editor, it will be executed by
278 used instead. When you exit the editor, it will be executed by
278 IPython's own processor.
279 IPython's own processor.
279
280
280 -x: do not execute the edited code immediately upon exit. This is
281 -x: do not execute the edited code immediately upon exit. This is
281 mainly useful if you are editing programs which need to be called with
282 mainly useful if you are editing programs which need to be called with
282 command line arguments, which you can then do using %run.
283 command line arguments, which you can then do using %run.
283
284
284
285
285 Arguments:
286 Arguments:
286
287
287 If arguments are given, the following possibilites exist:
288 If arguments are given, the following possibilites exist:
288
289
289 - The arguments are numbers or pairs of colon-separated numbers (like
290 - The arguments are numbers or pairs of colon-separated numbers (like
290 1 4:8 9). These are interpreted as lines of previous input to be
291 1 4:8 9). These are interpreted as lines of previous input to be
291 loaded into the editor. The syntax is the same of the %macro command.
292 loaded into the editor. The syntax is the same of the %macro command.
292
293
293 - If the argument doesn't start with a number, it is evaluated as a
294 - If the argument doesn't start with a number, it is evaluated as a
294 variable and its contents loaded into the editor. You can thus edit
295 variable and its contents loaded into the editor. You can thus edit
295 any string which contains python code (including the result of
296 any string which contains python code (including the result of
296 previous edits).
297 previous edits).
297
298
298 - If the argument is the name of an object (other than a string),
299 - If the argument is the name of an object (other than a string),
299 IPython will try to locate the file where it was defined and open the
300 IPython will try to locate the file where it was defined and open the
300 editor at the point where it is defined. You can use `%edit function`
301 editor at the point where it is defined. You can use `%edit function`
301 to load an editor exactly at the point where 'function' is defined,
302 to load an editor exactly at the point where 'function' is defined,
302 edit it and have the file be executed automatically.
303 edit it and have the file be executed automatically.
303
304
304 If the object is a macro (see %macro for details), this opens up your
305 If the object is a macro (see %macro for details), this opens up your
305 specified editor with a temporary file containing the macro's data.
306 specified editor with a temporary file containing the macro's data.
306 Upon exit, the macro is reloaded with the contents of the file.
307 Upon exit, the macro is reloaded with the contents of the file.
307
308
308 Note: opening at an exact line is only supported under Unix, and some
309 Note: opening at an exact line is only supported under Unix, and some
309 editors (like kedit and gedit up to Gnome 2.8) do not understand the
310 editors (like kedit and gedit up to Gnome 2.8) do not understand the
310 '+NUMBER' parameter necessary for this feature. Good editors like
311 '+NUMBER' parameter necessary for this feature. Good editors like
311 (X)Emacs, vi, jed, pico and joe all do.
312 (X)Emacs, vi, jed, pico and joe all do.
312
313
313 - If the argument is not found as a variable, IPython will look for a
314 - If the argument is not found as a variable, IPython will look for a
314 file with that name (adding .py if necessary) and load it into the
315 file with that name (adding .py if necessary) and load it into the
315 editor. It will execute its contents with execfile() when you exit,
316 editor. It will execute its contents with execfile() when you exit,
316 loading any code in the file into your interactive namespace.
317 loading any code in the file into your interactive namespace.
317
318
318 After executing your code, %edit will return as output the code you
319 After executing your code, %edit will return as output the code you
319 typed in the editor (except when it was an existing file). This way
320 typed in the editor (except when it was an existing file). This way
320 you can reload the code in further invocations of %edit as a variable,
321 you can reload the code in further invocations of %edit as a variable,
321 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
322 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
322 the output.
323 the output.
323
324
324 Note that %edit is also available through the alias %ed.
325 Note that %edit is also available through the alias %ed.
325
326
326 This is an example of creating a simple function inside the editor and
327 This is an example of creating a simple function inside the editor and
327 then modifying it. First, start up the editor:
328 then modifying it. First, start up the editor:
328
329
329 In [1]: ed
330 In [1]: ed
330 Editing... done. Executing edited code...
331 Editing... done. Executing edited code...
331 Out[1]: 'def foo():n print "foo() was defined in an editing session"n'
332 Out[1]: 'def foo():n print "foo() was defined in an editing session"n'
332
333
333 We can then call the function foo():
334 We can then call the function foo():
334
335
335 In [2]: foo()
336 In [2]: foo()
336 foo() was defined in an editing session
337 foo() was defined in an editing session
337
338
338 Now we edit foo. IPython automatically loads the editor with the
339 Now we edit foo. IPython automatically loads the editor with the
339 (temporary) file where foo() was previously defined:
340 (temporary) file where foo() was previously defined:
340
341
341 In [3]: ed foo
342 In [3]: ed foo
342 Editing... done. Executing edited code...
343 Editing... done. Executing edited code...
343
344
344 And if we call foo() again we get the modified version:
345 And if we call foo() again we get the modified version:
345
346
346 In [4]: foo()
347 In [4]: foo()
347 foo() has now been changed!
348 foo() has now been changed!
348
349
349 Here is an example of how to edit a code snippet successive
350 Here is an example of how to edit a code snippet successive
350 times. First we call the editor:
351 times. First we call the editor:
351
352
352 In [5]: ed
353 In [5]: ed
353 Editing... done. Executing edited code...
354 Editing... done. Executing edited code...
354 hello
355 hello
355 Out[5]: "print 'hello'n"
356 Out[5]: "print 'hello'n"
356
357
357 Now we call it again with the previous output (stored in _):
358 Now we call it again with the previous output (stored in _):
358
359
359 In [6]: ed _
360 In [6]: ed _
360 Editing... done. Executing edited code...
361 Editing... done. Executing edited code...
361 hello world
362 hello world
362 Out[6]: "print 'hello world'n"
363 Out[6]: "print 'hello world'n"
363
364
364 Now we call it with the output #8 (stored in _8, also as Out[8]):
365 Now we call it with the output #8 (stored in _8, also as Out[8]):
365
366
366 In [7]: ed _8
367 In [7]: ed _8
367 Editing... done. Executing edited code...
368 Editing... done. Executing edited code...
368 hello again
369 hello again
369 Out[7]: "print 'hello again'n"
370 Out[7]: "print 'hello again'n"
370 """
371 """
371
372
372 opts,args = self.parse_options(parameter_s,'prn:')
373 opts,args = self.parse_options(parameter_s,'prn:')
373
374
374 try:
375 try:
375 filename, lineno, _ = self._find_edit_target(args, opts, last_call)
376 filename, lineno, _ = self._find_edit_target(args, opts, last_call)
376 except MacroToEdit as e:
377 except MacroToEdit as e:
377 # TODO: Implement macro editing over 2 processes.
378 # TODO: Implement macro editing over 2 processes.
378 print("Macro editing not yet implemented in 2-process model.")
379 print("Macro editing not yet implemented in 2-process model.")
379 return
380 return
380
381
381 # Make sure we send to the client an absolute path, in case the working
382 # Make sure we send to the client an absolute path, in case the working
382 # directory of client and kernel don't match
383 # directory of client and kernel don't match
383 filename = os.path.abspath(filename)
384 filename = os.path.abspath(filename)
384
385
385 payload = {
386 payload = {
386 'source' : 'IPython.zmq.zmqshell.ZMQInteractiveShell.edit_magic',
387 'source' : 'IPython.zmq.zmqshell.ZMQInteractiveShell.edit_magic',
387 'filename' : filename,
388 'filename' : filename,
388 'line_number' : lineno
389 'line_number' : lineno
389 }
390 }
390 self.payload_manager.write_payload(payload)
391 self.payload_manager.write_payload(payload)
391
392
392 def magic_gui(self, *args, **kwargs):
393 def magic_gui(self, parameter_s=''):
393 raise NotImplementedError(
394 """Enable or disable IPython GUI event loop integration.
394 'Kernel GUI support is not implemented yet, except for --pylab.')
395
396 %gui [GUINAME]
397
398 This magic replaces IPython's threaded shells that were activated
399 using the (pylab/wthread/etc.) command line flags. GUI toolkits
400 can now be enabled at runtime and keyboard
401 interrupts should work without any problems. The following toolkits
402 are supported: wxPython, PyQt4, PyGTK, Cocoa, and Tk::
403
404 %gui wx # enable wxPython event loop integration
405 %gui qt4|qt # enable PyQt4 event loop integration
406 %gui gtk # enable PyGTK event loop integration
407 %gui OSX # enable Cocoa event loop integration (requires matplotlib 1.1)
408 %gui tk # enable Tk event loop integration
409
410 WARNING: after any of these has been called you can simply create
411 an application object, but DO NOT start the event loop yourself, as
412 we have already handled that.
413 """
414 from IPython.zmq.ipkernel import enable_gui
415 opts, arg = self.parse_options(parameter_s, '')
416 if arg=='': arg = None
417 return enable_gui(arg)
418
419 def enable_pylab(self, gui=None, import_all=True):
420 """Activate pylab support at runtime.
421
422 This turns on support for matplotlib, preloads into the interactive
423 namespace all of numpy and pylab, and configures IPython to correcdtly
424 interact with the GUI event loop. The GUI backend to be used can be
425 optionally selected with the optional :param:`gui` argument.
426
427 Parameters
428 ----------
429 gui : optional, string [default: inline]
430
431 If given, dictates the choice of matplotlib GUI backend to use
432 (should be one of IPython's supported backends, 'inline', 'qt', 'osx',
433 'tk', or 'gtk'), otherwise we use the default chosen by matplotlib
434 (as dictated by the matplotlib build-time options plus the user's
435 matplotlibrc configuration file).
436 """
437 from IPython.zmq.ipkernel import enable_gui
438 # We want to prevent the loading of pylab to pollute the user's
439 # namespace as shown by the %who* magics, so we execute the activation
440 # code in an empty namespace, and we update *both* user_ns and
441 # user_ns_hidden with this information.
442 ns = {}
443 # override default to inline, from auto-detect
444 gui = pylabtools.pylab_activate(ns, gui or 'inline', import_all, self)
445 self.user_ns.update(ns)
446 self.user_ns_hidden.update(ns)
447 # Now we must activate the gui pylab wants to use, and fix %run to take
448 # plot updates into account
449 enable_gui(gui)
450 self.magic_run = self._pylab_magic_run
395
451
396 def magic_pylab(self, *args, **kwargs):
397 raise NotImplementedError(
398 'pylab support must be enabled in command line options.')
399
452
400 # A few magics that are adapted to the specifics of using pexpect and a
453 # A few magics that are adapted to the specifics of using pexpect and a
401 # remote terminal
454 # remote terminal
402
455
403 def magic_clear(self, arg_s):
456 def magic_clear(self, arg_s):
404 """Clear the terminal."""
457 """Clear the terminal."""
405 if os.name == 'posix':
458 if os.name == 'posix':
406 self.shell.system("clear")
459 self.shell.system("clear")
407 else:
460 else:
408 self.shell.system("cls")
461 self.shell.system("cls")
409
462
410 if os.name == 'nt':
463 if os.name == 'nt':
411 # This is the usual name in windows
464 # This is the usual name in windows
412 magic_cls = magic_clear
465 magic_cls = magic_clear
413
466
414 # Terminal pagers won't work over pexpect, but we do have our own pager
467 # Terminal pagers won't work over pexpect, but we do have our own pager
415
468
416 def magic_less(self, arg_s):
469 def magic_less(self, arg_s):
417 """Show a file through the pager.
470 """Show a file through the pager.
418
471
419 Files ending in .py are syntax-highlighted."""
472 Files ending in .py are syntax-highlighted."""
420 cont = open(arg_s).read()
473 cont = open(arg_s).read()
421 if arg_s.endswith('.py'):
474 if arg_s.endswith('.py'):
422 cont = self.shell.pycolorize(cont)
475 cont = self.shell.pycolorize(cont)
423 page.page(cont)
476 page.page(cont)
424
477
425 magic_more = magic_less
478 magic_more = magic_less
426
479
427 # Man calls a pager, so we also need to redefine it
480 # Man calls a pager, so we also need to redefine it
428 if os.name == 'posix':
481 if os.name == 'posix':
429 def magic_man(self, arg_s):
482 def magic_man(self, arg_s):
430 """Find the man page for the given command and display in pager."""
483 """Find the man page for the given command and display in pager."""
431 page.page(self.shell.getoutput('man %s | col -b' % arg_s,
484 page.page(self.shell.getoutput('man %s | col -b' % arg_s,
432 split=False))
485 split=False))
433
486
434 # FIXME: this is specific to the GUI, so we should let the gui app load
487 # FIXME: this is specific to the GUI, so we should let the gui app load
435 # magics at startup that are only for the gui. Once the gui app has proper
488 # magics at startup that are only for the gui. Once the gui app has proper
436 # profile and configuration management, we can have it initialize a kernel
489 # profile and configuration management, we can have it initialize a kernel
437 # with a special config file that provides these.
490 # with a special config file that provides these.
438 def magic_guiref(self, arg_s):
491 def magic_guiref(self, arg_s):
439 """Show a basic reference about the GUI console."""
492 """Show a basic reference about the GUI console."""
440 from IPython.core.usage import gui_reference
493 from IPython.core.usage import gui_reference
441 page.page(gui_reference, auto_html=True)
494 page.page(gui_reference, auto_html=True)
442
495
443 def magic_connect_info(self, arg_s):
496 def magic_connect_info(self, arg_s):
444 """Print information for connecting other clients to this kernel
497 """Print information for connecting other clients to this kernel
445
498
446 It will print the contents of this session's connection file, as well as
499 It will print the contents of this session's connection file, as well as
447 shortcuts for local clients.
500 shortcuts for local clients.
448
501
449 In the simplest case, when called from the most recently launched kernel,
502 In the simplest case, when called from the most recently launched kernel,
450 secondary clients can be connected, simply with:
503 secondary clients can be connected, simply with:
451
504
452 $> ipython <app> --existing
505 $> ipython <app> --existing
453
506
454 """
507 """
455 try:
508 try:
456 connection_file = get_connection_file()
509 connection_file = get_connection_file()
457 info = get_connection_info(unpack=False)
510 info = get_connection_info(unpack=False)
458 except Exception as e:
511 except Exception as e:
459 error("Could not get connection info: %r" % e)
512 error("Could not get connection info: %r" % e)
460 return
513 return
461
514
462 print (info + '\n')
515 print (info + '\n')
463 print ("Paste the above JSON into a file, and connect with:\n"
516 print ("Paste the above JSON into a file, and connect with:\n"
464 " $> ipython <app> --existing <file>\n"
517 " $> ipython <app> --existing <file>\n"
465 "or, if you are local, you can connect with just:\n"
518 "or, if you are local, you can connect with just:\n"
466 " $> ipython <app> --existing %s\n"
519 " $> ipython <app> --existing %s\n"
467 "or even just:\n"
520 "or even just:\n"
468 " $> ipython <app> --existing\n"
521 " $> ipython <app> --existing\n"
469 "if this is the most recent IPython session you have started."
522 "if this is the most recent IPython session you have started."
470 % os.path.basename(connection_file)
523 % os.path.basename(connection_file)
471 )
524 )
472
525
473 def magic_qtconsole(self, arg_s):
526 def magic_qtconsole(self, arg_s):
474 """Open a qtconsole connected to this kernel.
527 """Open a qtconsole connected to this kernel.
475
528
476 Useful for connecting a qtconsole to running notebooks, for better
529 Useful for connecting a qtconsole to running notebooks, for better
477 debugging.
530 debugging.
478 """
531 """
479 try:
532 try:
480 p = connect_qtconsole(argv=arg_split(arg_s, os.name=='posix'))
533 p = connect_qtconsole(argv=arg_split(arg_s, os.name=='posix'))
481 except Exception as e:
534 except Exception as e:
482 error("Could not start qtconsole: %r" % e)
535 error("Could not start qtconsole: %r" % e)
483 return
536 return
484
537
485
538
486 def set_next_input(self, text):
539 def set_next_input(self, text):
487 """Send the specified text to the frontend to be presented at the next
540 """Send the specified text to the frontend to be presented at the next
488 input cell."""
541 input cell."""
489 payload = dict(
542 payload = dict(
490 source='IPython.zmq.zmqshell.ZMQInteractiveShell.set_next_input',
543 source='IPython.zmq.zmqshell.ZMQInteractiveShell.set_next_input',
491 text=text
544 text=text
492 )
545 )
493 self.payload_manager.write_payload(payload)
546 self.payload_manager.write_payload(payload)
494
547
495 InteractiveShellABC.register(ZMQInteractiveShell)
548 InteractiveShellABC.register(ZMQInteractiveShell)
General Comments 0
You need to be logged in to leave comments. Login now