Show More
The requested changes are too big and content was truncated. Show full diff
@@ -1,566 +1,566 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
1 | # -*- coding: utf-8 -*- | |
2 | """ |
|
2 | """ | |
3 | Pdb debugger class. |
|
3 | Pdb debugger class. | |
4 |
|
4 | |||
5 | Modified from the standard pdb.Pdb class to avoid including readline, so that |
|
5 | Modified from the standard pdb.Pdb class to avoid including readline, so that | |
6 | the command line completion of other programs which include this isn't |
|
6 | the command line completion of other programs which include this isn't | |
7 | damaged. |
|
7 | damaged. | |
8 |
|
8 | |||
9 | In the future, this class will be expanded with improvements over the standard |
|
9 | In the future, this class will be expanded with improvements over the standard | |
10 | pdb. |
|
10 | pdb. | |
11 |
|
11 | |||
12 | The code in this file is mainly lifted out of cmd.py in Python 2.2, with minor |
|
12 | The code in this file is mainly lifted out of cmd.py in Python 2.2, with minor | |
13 | changes. Licensing should therefore be under the standard Python terms. For |
|
13 | changes. Licensing should therefore be under the standard Python terms. For | |
14 | details on the PSF (Python Software Foundation) standard license, see: |
|
14 | details on the PSF (Python Software Foundation) standard license, see: | |
15 |
|
15 | |||
16 | http://www.python.org/2.2.3/license.html""" |
|
16 | http://www.python.org/2.2.3/license.html""" | |
17 |
|
17 | |||
18 | #***************************************************************************** |
|
18 | #***************************************************************************** | |
19 | # |
|
19 | # | |
20 | # This file is licensed under the PSF license. |
|
20 | # This file is licensed under the PSF license. | |
21 | # |
|
21 | # | |
22 | # Copyright (C) 2001 Python Software Foundation, www.python.org |
|
22 | # Copyright (C) 2001 Python Software Foundation, www.python.org | |
23 | # Copyright (C) 2005-2006 Fernando Perez. <fperez@colorado.edu> |
|
23 | # Copyright (C) 2005-2006 Fernando Perez. <fperez@colorado.edu> | |
24 | # |
|
24 | # | |
25 | # |
|
25 | # | |
26 | #***************************************************************************** |
|
26 | #***************************************************************************** | |
27 | from __future__ import print_function |
|
27 | from __future__ import print_function | |
28 |
|
28 | |||
29 | import bdb |
|
29 | import bdb | |
30 | import functools |
|
30 | import functools | |
31 | import linecache |
|
31 | import linecache | |
32 | import sys |
|
32 | import sys | |
33 |
|
33 | |||
34 | from IPython.utils import PyColorize, ulinecache |
|
34 | from IPython.utils import PyColorize, ulinecache | |
35 | from IPython.core import ipapi |
|
35 | from IPython.core import ipapi | |
36 | from IPython.utils import coloransi, io, openpy, py3compat |
|
36 | from IPython.utils import coloransi, io, openpy, py3compat | |
37 | from IPython.core.excolors import exception_colors |
|
37 | from IPython.core.excolors import exception_colors | |
38 |
|
38 | |||
39 | # See if we can use pydb. |
|
39 | # See if we can use pydb. | |
40 | has_pydb = False |
|
40 | has_pydb = False | |
41 | prompt = 'ipdb> ' |
|
41 | prompt = 'ipdb> ' | |
42 | #We have to check this directly from sys.argv, config struct not yet available |
|
42 | #We have to check this directly from sys.argv, config struct not yet available | |
43 | if '--pydb' in sys.argv: |
|
43 | if '--pydb' in sys.argv: | |
44 | try: |
|
44 | try: | |
45 | import pydb |
|
45 | import pydb | |
46 | if hasattr(pydb.pydb, "runl") and pydb.version>'1.17': |
|
46 | if hasattr(pydb.pydb, "runl") and pydb.version>'1.17': | |
47 | # Version 1.17 is broken, and that's what ships with Ubuntu Edgy, so we |
|
47 | # Version 1.17 is broken, and that's what ships with Ubuntu Edgy, so we | |
48 | # better protect against it. |
|
48 | # better protect against it. | |
49 | has_pydb = True |
|
49 | has_pydb = True | |
50 | except ImportError: |
|
50 | except ImportError: | |
51 | print("Pydb (http://bashdb.sourceforge.net/pydb/) does not seem to be available") |
|
51 | print("Pydb (http://bashdb.sourceforge.net/pydb/) does not seem to be available") | |
52 |
|
52 | |||
53 | if has_pydb: |
|
53 | if has_pydb: | |
54 | from pydb import Pdb as OldPdb |
|
54 | from pydb import Pdb as OldPdb | |
55 | #print "Using pydb for %run -d and post-mortem" #dbg |
|
55 | #print "Using pydb for %run -d and post-mortem" #dbg | |
56 | prompt = 'ipydb> ' |
|
56 | prompt = 'ipydb> ' | |
57 | else: |
|
57 | else: | |
58 | from pdb import Pdb as OldPdb |
|
58 | from pdb import Pdb as OldPdb | |
59 |
|
59 | |||
60 | # Allow the set_trace code to operate outside of an ipython instance, even if |
|
60 | # Allow the set_trace code to operate outside of an ipython instance, even if | |
61 | # it does so with some limitations. The rest of this support is implemented in |
|
61 | # it does so with some limitations. The rest of this support is implemented in | |
62 | # the Tracer constructor. |
|
62 | # the Tracer constructor. | |
63 | def BdbQuit_excepthook(et, ev, tb, excepthook=None): |
|
63 | def BdbQuit_excepthook(et, ev, tb, excepthook=None): | |
64 | """Exception hook which handles `BdbQuit` exceptions. |
|
64 | """Exception hook which handles `BdbQuit` exceptions. | |
65 |
|
65 | |||
66 | All other exceptions are processed using the `excepthook` |
|
66 | All other exceptions are processed using the `excepthook` | |
67 | parameter. |
|
67 | parameter. | |
68 | """ |
|
68 | """ | |
69 | if et==bdb.BdbQuit: |
|
69 | if et==bdb.BdbQuit: | |
70 | print('Exiting Debugger.') |
|
70 | print('Exiting Debugger.') | |
71 | elif excepthook is not None: |
|
71 | elif excepthook is not None: | |
72 | excepthook(et, ev, tb) |
|
72 | excepthook(et, ev, tb) | |
73 | else: |
|
73 | else: | |
74 | # Backwards compatibility. Raise deprecation warning? |
|
74 | # Backwards compatibility. Raise deprecation warning? | |
75 | BdbQuit_excepthook.excepthook_ori(et,ev,tb) |
|
75 | BdbQuit_excepthook.excepthook_ori(et,ev,tb) | |
76 |
|
76 | |||
77 | def BdbQuit_IPython_excepthook(self,et,ev,tb,tb_offset=None): |
|
77 | def BdbQuit_IPython_excepthook(self,et,ev,tb,tb_offset=None): | |
78 | print('Exiting Debugger.') |
|
78 | print('Exiting Debugger.') | |
79 |
|
79 | |||
80 |
|
80 | |||
81 | class Tracer(object): |
|
81 | class Tracer(object): | |
82 | """Class for local debugging, similar to pdb.set_trace. |
|
82 | """Class for local debugging, similar to pdb.set_trace. | |
83 |
|
83 | |||
84 | Instances of this class, when called, behave like pdb.set_trace, but |
|
84 | Instances of this class, when called, behave like pdb.set_trace, but | |
85 | providing IPython's enhanced capabilities. |
|
85 | providing IPython's enhanced capabilities. | |
86 |
|
86 | |||
87 | This is implemented as a class which must be initialized in your own code |
|
87 | This is implemented as a class which must be initialized in your own code | |
88 | and not as a standalone function because we need to detect at runtime |
|
88 | and not as a standalone function because we need to detect at runtime | |
89 | whether IPython is already active or not. That detection is done in the |
|
89 | whether IPython is already active or not. That detection is done in the | |
90 | constructor, ensuring that this code plays nicely with a running IPython, |
|
90 | constructor, ensuring that this code plays nicely with a running IPython, | |
91 | while functioning acceptably (though with limitations) if outside of it. |
|
91 | while functioning acceptably (though with limitations) if outside of it. | |
92 | """ |
|
92 | """ | |
93 |
|
93 | |||
94 | def __init__(self,colors=None): |
|
94 | def __init__(self,colors=None): | |
95 | """Create a local debugger instance. |
|
95 | """Create a local debugger instance. | |
96 |
|
96 | |||
97 | :Parameters: |
|
97 | :Parameters: | |
98 |
|
98 | |||
99 | - `colors` (None): a string containing the name of the color scheme to |
|
99 | - `colors` (None): a string containing the name of the color scheme to | |
100 | use, it must be one of IPython's valid color schemes. If not given, the |
|
100 | use, it must be one of IPython's valid color schemes. If not given, the | |
101 | function will default to the current IPython scheme when running inside |
|
101 | function will default to the current IPython scheme when running inside | |
102 | IPython, and to 'NoColor' otherwise. |
|
102 | IPython, and to 'NoColor' otherwise. | |
103 |
|
103 | |||
104 | Usage example: |
|
104 | Usage example: | |
105 |
|
105 | |||
106 | from IPython.core.debugger import Tracer; debug_here = Tracer() |
|
106 | from IPython.core.debugger import Tracer; debug_here = Tracer() | |
107 |
|
107 | |||
108 | ... later in your code |
|
108 | ... later in your code | |
109 | debug_here() # -> will open up the debugger at that point. |
|
109 | debug_here() # -> will open up the debugger at that point. | |
110 |
|
110 | |||
111 | Once the debugger activates, you can use all of its regular commands to |
|
111 | Once the debugger activates, you can use all of its regular commands to | |
112 | step through code, set breakpoints, etc. See the pdb documentation |
|
112 | step through code, set breakpoints, etc. See the pdb documentation | |
113 | from the Python standard library for usage details. |
|
113 | from the Python standard library for usage details. | |
114 | """ |
|
114 | """ | |
115 |
|
115 | |||
116 | try: |
|
116 | try: | |
117 | ip = get_ipython() |
|
117 | ip = get_ipython() | |
118 | except NameError: |
|
118 | except NameError: | |
119 | # Outside of ipython, we set our own exception hook manually |
|
119 | # Outside of ipython, we set our own exception hook manually | |
120 | sys.excepthook = functools.partial(BdbQuit_excepthook, |
|
120 | sys.excepthook = functools.partial(BdbQuit_excepthook, | |
121 | excepthook=sys.excepthook) |
|
121 | excepthook=sys.excepthook) | |
122 | def_colors = 'NoColor' |
|
122 | def_colors = 'NoColor' | |
123 | try: |
|
123 | try: | |
124 | # Limited tab completion support |
|
124 | # Limited tab completion support | |
125 | import readline |
|
125 | import readline | |
126 | readline.parse_and_bind('tab: complete') |
|
126 | readline.parse_and_bind('tab: complete') | |
127 | except ImportError: |
|
127 | except ImportError: | |
128 | pass |
|
128 | pass | |
129 | else: |
|
129 | else: | |
130 | # In ipython, we use its custom exception handler mechanism |
|
130 | # In ipython, we use its custom exception handler mechanism | |
131 | def_colors = ip.colors |
|
131 | def_colors = ip.colors | |
132 | ip.set_custom_exc((bdb.BdbQuit,), BdbQuit_IPython_excepthook) |
|
132 | ip.set_custom_exc((bdb.BdbQuit,), BdbQuit_IPython_excepthook) | |
133 |
|
133 | |||
134 | if colors is None: |
|
134 | if colors is None: | |
135 | colors = def_colors |
|
135 | colors = def_colors | |
136 |
|
136 | |||
137 | # The stdlib debugger internally uses a modified repr from the `repr` |
|
137 | # The stdlib debugger internally uses a modified repr from the `repr` | |
138 | # module, that limits the length of printed strings to a hardcoded |
|
138 | # module, that limits the length of printed strings to a hardcoded | |
139 | # limit of 30 characters. That much trimming is too aggressive, let's |
|
139 | # limit of 30 characters. That much trimming is too aggressive, let's | |
140 | # at least raise that limit to 80 chars, which should be enough for |
|
140 | # at least raise that limit to 80 chars, which should be enough for | |
141 | # most interactive uses. |
|
141 | # most interactive uses. | |
142 | try: |
|
142 | try: | |
143 | from repr import aRepr |
|
143 | from repr import aRepr | |
144 | aRepr.maxstring = 80 |
|
144 | aRepr.maxstring = 80 | |
145 | except: |
|
145 | except: | |
146 | # This is only a user-facing convenience, so any error we encounter |
|
146 | # This is only a user-facing convenience, so any error we encounter | |
147 | # here can be warned about but can be otherwise ignored. These |
|
147 | # here can be warned about but can be otherwise ignored. These | |
148 | # printouts will tell us about problems if this API changes |
|
148 | # printouts will tell us about problems if this API changes | |
149 | import traceback |
|
149 | import traceback | |
150 | traceback.print_exc() |
|
150 | traceback.print_exc() | |
151 |
|
151 | |||
152 | self.debugger = Pdb(colors) |
|
152 | self.debugger = Pdb(colors) | |
153 |
|
153 | |||
154 | def __call__(self): |
|
154 | def __call__(self): | |
155 | """Starts an interactive debugger at the point where called. |
|
155 | """Starts an interactive debugger at the point where called. | |
156 |
|
156 | |||
157 | This is similar to the pdb.set_trace() function from the std lib, but |
|
157 | This is similar to the pdb.set_trace() function from the std lib, but | |
158 | using IPython's enhanced debugger.""" |
|
158 | using IPython's enhanced debugger.""" | |
159 |
|
159 | |||
160 | self.debugger.set_trace(sys._getframe().f_back) |
|
160 | self.debugger.set_trace(sys._getframe().f_back) | |
161 |
|
161 | |||
162 |
|
162 | |||
163 | def decorate_fn_with_doc(new_fn, old_fn, additional_text=""): |
|
163 | def decorate_fn_with_doc(new_fn, old_fn, additional_text=""): | |
164 | """Make new_fn have old_fn's doc string. This is particularly useful |
|
164 | """Make new_fn have old_fn's doc string. This is particularly useful | |
165 | for the do_... commands that hook into the help system. |
|
165 | for the ``do_...`` commands that hook into the help system. | |
166 | Adapted from from a comp.lang.python posting |
|
166 | Adapted from from a comp.lang.python posting | |
167 | by Duncan Booth.""" |
|
167 | by Duncan Booth.""" | |
168 | def wrapper(*args, **kw): |
|
168 | def wrapper(*args, **kw): | |
169 | return new_fn(*args, **kw) |
|
169 | return new_fn(*args, **kw) | |
170 | if old_fn.__doc__: |
|
170 | if old_fn.__doc__: | |
171 | wrapper.__doc__ = old_fn.__doc__ + additional_text |
|
171 | wrapper.__doc__ = old_fn.__doc__ + additional_text | |
172 | return wrapper |
|
172 | return wrapper | |
173 |
|
173 | |||
174 |
|
174 | |||
175 | def _file_lines(fname): |
|
175 | def _file_lines(fname): | |
176 | """Return the contents of a named file as a list of lines. |
|
176 | """Return the contents of a named file as a list of lines. | |
177 |
|
177 | |||
178 | This function never raises an IOError exception: if the file can't be |
|
178 | This function never raises an IOError exception: if the file can't be | |
179 | read, it simply returns an empty list.""" |
|
179 | read, it simply returns an empty list.""" | |
180 |
|
180 | |||
181 | try: |
|
181 | try: | |
182 | outfile = open(fname) |
|
182 | outfile = open(fname) | |
183 | except IOError: |
|
183 | except IOError: | |
184 | return [] |
|
184 | return [] | |
185 | else: |
|
185 | else: | |
186 | out = outfile.readlines() |
|
186 | out = outfile.readlines() | |
187 | outfile.close() |
|
187 | outfile.close() | |
188 | return out |
|
188 | return out | |
189 |
|
189 | |||
190 |
|
190 | |||
191 | class Pdb(OldPdb): |
|
191 | class Pdb(OldPdb): | |
192 | """Modified Pdb class, does not load readline.""" |
|
192 | """Modified Pdb class, does not load readline.""" | |
193 |
|
193 | |||
194 | def __init__(self,color_scheme='NoColor',completekey=None, |
|
194 | def __init__(self,color_scheme='NoColor',completekey=None, | |
195 | stdin=None, stdout=None): |
|
195 | stdin=None, stdout=None): | |
196 |
|
196 | |||
197 | # Parent constructor: |
|
197 | # Parent constructor: | |
198 | if has_pydb and completekey is None: |
|
198 | if has_pydb and completekey is None: | |
199 | OldPdb.__init__(self,stdin=stdin,stdout=io.stdout) |
|
199 | OldPdb.__init__(self,stdin=stdin,stdout=io.stdout) | |
200 | else: |
|
200 | else: | |
201 | OldPdb.__init__(self,completekey,stdin,stdout) |
|
201 | OldPdb.__init__(self,completekey,stdin,stdout) | |
202 |
|
202 | |||
203 | self.prompt = prompt # The default prompt is '(Pdb)' |
|
203 | self.prompt = prompt # The default prompt is '(Pdb)' | |
204 |
|
204 | |||
205 | # IPython changes... |
|
205 | # IPython changes... | |
206 | self.is_pydb = has_pydb |
|
206 | self.is_pydb = has_pydb | |
207 |
|
207 | |||
208 | self.shell = ipapi.get() |
|
208 | self.shell = ipapi.get() | |
209 |
|
209 | |||
210 | if self.is_pydb: |
|
210 | if self.is_pydb: | |
211 |
|
211 | |||
212 | # interactiveshell.py's ipalias seems to want pdb's checkline |
|
212 | # interactiveshell.py's ipalias seems to want pdb's checkline | |
213 | # which located in pydb.fn |
|
213 | # which located in pydb.fn | |
214 | import pydb.fns |
|
214 | import pydb.fns | |
215 | self.checkline = lambda filename, lineno: \ |
|
215 | self.checkline = lambda filename, lineno: \ | |
216 | pydb.fns.checkline(self, filename, lineno) |
|
216 | pydb.fns.checkline(self, filename, lineno) | |
217 |
|
217 | |||
218 | self.curframe = None |
|
218 | self.curframe = None | |
219 | self.do_restart = self.new_do_restart |
|
219 | self.do_restart = self.new_do_restart | |
220 |
|
220 | |||
221 | self.old_all_completions = self.shell.Completer.all_completions |
|
221 | self.old_all_completions = self.shell.Completer.all_completions | |
222 | self.shell.Completer.all_completions=self.all_completions |
|
222 | self.shell.Completer.all_completions=self.all_completions | |
223 |
|
223 | |||
224 | self.do_list = decorate_fn_with_doc(self.list_command_pydb, |
|
224 | self.do_list = decorate_fn_with_doc(self.list_command_pydb, | |
225 | OldPdb.do_list) |
|
225 | OldPdb.do_list) | |
226 | self.do_l = self.do_list |
|
226 | self.do_l = self.do_list | |
227 | self.do_frame = decorate_fn_with_doc(self.new_do_frame, |
|
227 | self.do_frame = decorate_fn_with_doc(self.new_do_frame, | |
228 | OldPdb.do_frame) |
|
228 | OldPdb.do_frame) | |
229 |
|
229 | |||
230 | self.aliases = {} |
|
230 | self.aliases = {} | |
231 |
|
231 | |||
232 | # Create color table: we copy the default one from the traceback |
|
232 | # Create color table: we copy the default one from the traceback | |
233 | # module and add a few attributes needed for debugging |
|
233 | # module and add a few attributes needed for debugging | |
234 | self.color_scheme_table = exception_colors() |
|
234 | self.color_scheme_table = exception_colors() | |
235 |
|
235 | |||
236 | # shorthands |
|
236 | # shorthands | |
237 | C = coloransi.TermColors |
|
237 | C = coloransi.TermColors | |
238 | cst = self.color_scheme_table |
|
238 | cst = self.color_scheme_table | |
239 |
|
239 | |||
240 | cst['NoColor'].colors.breakpoint_enabled = C.NoColor |
|
240 | cst['NoColor'].colors.breakpoint_enabled = C.NoColor | |
241 | cst['NoColor'].colors.breakpoint_disabled = C.NoColor |
|
241 | cst['NoColor'].colors.breakpoint_disabled = C.NoColor | |
242 |
|
242 | |||
243 | cst['Linux'].colors.breakpoint_enabled = C.LightRed |
|
243 | cst['Linux'].colors.breakpoint_enabled = C.LightRed | |
244 | cst['Linux'].colors.breakpoint_disabled = C.Red |
|
244 | cst['Linux'].colors.breakpoint_disabled = C.Red | |
245 |
|
245 | |||
246 | cst['LightBG'].colors.breakpoint_enabled = C.LightRed |
|
246 | cst['LightBG'].colors.breakpoint_enabled = C.LightRed | |
247 | cst['LightBG'].colors.breakpoint_disabled = C.Red |
|
247 | cst['LightBG'].colors.breakpoint_disabled = C.Red | |
248 |
|
248 | |||
249 | self.set_colors(color_scheme) |
|
249 | self.set_colors(color_scheme) | |
250 |
|
250 | |||
251 | # Add a python parser so we can syntax highlight source while |
|
251 | # Add a python parser so we can syntax highlight source while | |
252 | # debugging. |
|
252 | # debugging. | |
253 | self.parser = PyColorize.Parser() |
|
253 | self.parser = PyColorize.Parser() | |
254 |
|
254 | |||
255 | def set_colors(self, scheme): |
|
255 | def set_colors(self, scheme): | |
256 | """Shorthand access to the color table scheme selector method.""" |
|
256 | """Shorthand access to the color table scheme selector method.""" | |
257 | self.color_scheme_table.set_active_scheme(scheme) |
|
257 | self.color_scheme_table.set_active_scheme(scheme) | |
258 |
|
258 | |||
259 | def interaction(self, frame, traceback): |
|
259 | def interaction(self, frame, traceback): | |
260 | self.shell.set_completer_frame(frame) |
|
260 | self.shell.set_completer_frame(frame) | |
261 | OldPdb.interaction(self, frame, traceback) |
|
261 | OldPdb.interaction(self, frame, traceback) | |
262 |
|
262 | |||
263 | def new_do_up(self, arg): |
|
263 | def new_do_up(self, arg): | |
264 | OldPdb.do_up(self, arg) |
|
264 | OldPdb.do_up(self, arg) | |
265 | self.shell.set_completer_frame(self.curframe) |
|
265 | self.shell.set_completer_frame(self.curframe) | |
266 | do_u = do_up = decorate_fn_with_doc(new_do_up, OldPdb.do_up) |
|
266 | do_u = do_up = decorate_fn_with_doc(new_do_up, OldPdb.do_up) | |
267 |
|
267 | |||
268 | def new_do_down(self, arg): |
|
268 | def new_do_down(self, arg): | |
269 | OldPdb.do_down(self, arg) |
|
269 | OldPdb.do_down(self, arg) | |
270 | self.shell.set_completer_frame(self.curframe) |
|
270 | self.shell.set_completer_frame(self.curframe) | |
271 |
|
271 | |||
272 | do_d = do_down = decorate_fn_with_doc(new_do_down, OldPdb.do_down) |
|
272 | do_d = do_down = decorate_fn_with_doc(new_do_down, OldPdb.do_down) | |
273 |
|
273 | |||
274 | def new_do_frame(self, arg): |
|
274 | def new_do_frame(self, arg): | |
275 | OldPdb.do_frame(self, arg) |
|
275 | OldPdb.do_frame(self, arg) | |
276 | self.shell.set_completer_frame(self.curframe) |
|
276 | self.shell.set_completer_frame(self.curframe) | |
277 |
|
277 | |||
278 | def new_do_quit(self, arg): |
|
278 | def new_do_quit(self, arg): | |
279 |
|
279 | |||
280 | if hasattr(self, 'old_all_completions'): |
|
280 | if hasattr(self, 'old_all_completions'): | |
281 | self.shell.Completer.all_completions=self.old_all_completions |
|
281 | self.shell.Completer.all_completions=self.old_all_completions | |
282 |
|
282 | |||
283 |
|
283 | |||
284 | return OldPdb.do_quit(self, arg) |
|
284 | return OldPdb.do_quit(self, arg) | |
285 |
|
285 | |||
286 | do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit) |
|
286 | do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit) | |
287 |
|
287 | |||
288 | def new_do_restart(self, arg): |
|
288 | def new_do_restart(self, arg): | |
289 | """Restart command. In the context of ipython this is exactly the same |
|
289 | """Restart command. In the context of ipython this is exactly the same | |
290 | thing as 'quit'.""" |
|
290 | thing as 'quit'.""" | |
291 | self.msg("Restart doesn't make sense here. Using 'quit' instead.") |
|
291 | self.msg("Restart doesn't make sense here. Using 'quit' instead.") | |
292 | return self.do_quit(arg) |
|
292 | return self.do_quit(arg) | |
293 |
|
293 | |||
294 | def postloop(self): |
|
294 | def postloop(self): | |
295 | self.shell.set_completer_frame(None) |
|
295 | self.shell.set_completer_frame(None) | |
296 |
|
296 | |||
297 | def print_stack_trace(self): |
|
297 | def print_stack_trace(self): | |
298 | try: |
|
298 | try: | |
299 | for frame_lineno in self.stack: |
|
299 | for frame_lineno in self.stack: | |
300 | self.print_stack_entry(frame_lineno, context = 5) |
|
300 | self.print_stack_entry(frame_lineno, context = 5) | |
301 | except KeyboardInterrupt: |
|
301 | except KeyboardInterrupt: | |
302 | pass |
|
302 | pass | |
303 |
|
303 | |||
304 | def print_stack_entry(self,frame_lineno,prompt_prefix='\n-> ', |
|
304 | def print_stack_entry(self,frame_lineno,prompt_prefix='\n-> ', | |
305 | context = 3): |
|
305 | context = 3): | |
306 | #frame, lineno = frame_lineno |
|
306 | #frame, lineno = frame_lineno | |
307 | print(self.format_stack_entry(frame_lineno, '', context), file=io.stdout) |
|
307 | print(self.format_stack_entry(frame_lineno, '', context), file=io.stdout) | |
308 |
|
308 | |||
309 | # vds: >> |
|
309 | # vds: >> | |
310 | frame, lineno = frame_lineno |
|
310 | frame, lineno = frame_lineno | |
311 | filename = frame.f_code.co_filename |
|
311 | filename = frame.f_code.co_filename | |
312 | self.shell.hooks.synchronize_with_editor(filename, lineno, 0) |
|
312 | self.shell.hooks.synchronize_with_editor(filename, lineno, 0) | |
313 | # vds: << |
|
313 | # vds: << | |
314 |
|
314 | |||
315 | def format_stack_entry(self, frame_lineno, lprefix=': ', context = 3): |
|
315 | def format_stack_entry(self, frame_lineno, lprefix=': ', context = 3): | |
316 | import repr |
|
316 | import repr | |
317 |
|
317 | |||
318 | ret = [] |
|
318 | ret = [] | |
319 |
|
319 | |||
320 | Colors = self.color_scheme_table.active_colors |
|
320 | Colors = self.color_scheme_table.active_colors | |
321 | ColorsNormal = Colors.Normal |
|
321 | ColorsNormal = Colors.Normal | |
322 | tpl_link = u'%s%%s%s' % (Colors.filenameEm, ColorsNormal) |
|
322 | tpl_link = u'%s%%s%s' % (Colors.filenameEm, ColorsNormal) | |
323 | tpl_call = u'%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal) |
|
323 | tpl_call = u'%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal) | |
324 | tpl_line = u'%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal) |
|
324 | tpl_line = u'%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal) | |
325 | tpl_line_em = u'%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, |
|
325 | tpl_line_em = u'%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, | |
326 | ColorsNormal) |
|
326 | ColorsNormal) | |
327 |
|
327 | |||
328 | frame, lineno = frame_lineno |
|
328 | frame, lineno = frame_lineno | |
329 |
|
329 | |||
330 | return_value = '' |
|
330 | return_value = '' | |
331 | if '__return__' in frame.f_locals: |
|
331 | if '__return__' in frame.f_locals: | |
332 | rv = frame.f_locals['__return__'] |
|
332 | rv = frame.f_locals['__return__'] | |
333 | #return_value += '->' |
|
333 | #return_value += '->' | |
334 | return_value += repr.repr(rv) + '\n' |
|
334 | return_value += repr.repr(rv) + '\n' | |
335 | ret.append(return_value) |
|
335 | ret.append(return_value) | |
336 |
|
336 | |||
337 | #s = filename + '(' + `lineno` + ')' |
|
337 | #s = filename + '(' + `lineno` + ')' | |
338 | filename = self.canonic(frame.f_code.co_filename) |
|
338 | filename = self.canonic(frame.f_code.co_filename) | |
339 | link = tpl_link % py3compat.cast_unicode(filename) |
|
339 | link = tpl_link % py3compat.cast_unicode(filename) | |
340 |
|
340 | |||
341 | if frame.f_code.co_name: |
|
341 | if frame.f_code.co_name: | |
342 | func = frame.f_code.co_name |
|
342 | func = frame.f_code.co_name | |
343 | else: |
|
343 | else: | |
344 | func = "<lambda>" |
|
344 | func = "<lambda>" | |
345 |
|
345 | |||
346 | call = '' |
|
346 | call = '' | |
347 | if func != '?': |
|
347 | if func != '?': | |
348 | if '__args__' in frame.f_locals: |
|
348 | if '__args__' in frame.f_locals: | |
349 | args = repr.repr(frame.f_locals['__args__']) |
|
349 | args = repr.repr(frame.f_locals['__args__']) | |
350 | else: |
|
350 | else: | |
351 | args = '()' |
|
351 | args = '()' | |
352 | call = tpl_call % (func, args) |
|
352 | call = tpl_call % (func, args) | |
353 |
|
353 | |||
354 | # The level info should be generated in the same format pdb uses, to |
|
354 | # The level info should be generated in the same format pdb uses, to | |
355 | # avoid breaking the pdbtrack functionality of python-mode in *emacs. |
|
355 | # avoid breaking the pdbtrack functionality of python-mode in *emacs. | |
356 | if frame is self.curframe: |
|
356 | if frame is self.curframe: | |
357 | ret.append('> ') |
|
357 | ret.append('> ') | |
358 | else: |
|
358 | else: | |
359 | ret.append(' ') |
|
359 | ret.append(' ') | |
360 | ret.append(u'%s(%s)%s\n' % (link,lineno,call)) |
|
360 | ret.append(u'%s(%s)%s\n' % (link,lineno,call)) | |
361 |
|
361 | |||
362 | start = lineno - 1 - context//2 |
|
362 | start = lineno - 1 - context//2 | |
363 | lines = ulinecache.getlines(filename) |
|
363 | lines = ulinecache.getlines(filename) | |
364 | start = min(start, len(lines) - context) |
|
364 | start = min(start, len(lines) - context) | |
365 | start = max(start, 0) |
|
365 | start = max(start, 0) | |
366 | lines = lines[start : start + context] |
|
366 | lines = lines[start : start + context] | |
367 |
|
367 | |||
368 | for i,line in enumerate(lines): |
|
368 | for i,line in enumerate(lines): | |
369 | show_arrow = (start + 1 + i == lineno) |
|
369 | show_arrow = (start + 1 + i == lineno) | |
370 | linetpl = (frame is self.curframe or show_arrow) \ |
|
370 | linetpl = (frame is self.curframe or show_arrow) \ | |
371 | and tpl_line_em \ |
|
371 | and tpl_line_em \ | |
372 | or tpl_line |
|
372 | or tpl_line | |
373 | ret.append(self.__format_line(linetpl, filename, |
|
373 | ret.append(self.__format_line(linetpl, filename, | |
374 | start + 1 + i, line, |
|
374 | start + 1 + i, line, | |
375 | arrow = show_arrow) ) |
|
375 | arrow = show_arrow) ) | |
376 | return ''.join(ret) |
|
376 | return ''.join(ret) | |
377 |
|
377 | |||
378 | def __format_line(self, tpl_line, filename, lineno, line, arrow = False): |
|
378 | def __format_line(self, tpl_line, filename, lineno, line, arrow = False): | |
379 | bp_mark = "" |
|
379 | bp_mark = "" | |
380 | bp_mark_color = "" |
|
380 | bp_mark_color = "" | |
381 |
|
381 | |||
382 | scheme = self.color_scheme_table.active_scheme_name |
|
382 | scheme = self.color_scheme_table.active_scheme_name | |
383 | new_line, err = self.parser.format2(line, 'str', scheme) |
|
383 | new_line, err = self.parser.format2(line, 'str', scheme) | |
384 | if not err: line = new_line |
|
384 | if not err: line = new_line | |
385 |
|
385 | |||
386 | bp = None |
|
386 | bp = None | |
387 | if lineno in self.get_file_breaks(filename): |
|
387 | if lineno in self.get_file_breaks(filename): | |
388 | bps = self.get_breaks(filename, lineno) |
|
388 | bps = self.get_breaks(filename, lineno) | |
389 | bp = bps[-1] |
|
389 | bp = bps[-1] | |
390 |
|
390 | |||
391 | if bp: |
|
391 | if bp: | |
392 | Colors = self.color_scheme_table.active_colors |
|
392 | Colors = self.color_scheme_table.active_colors | |
393 | bp_mark = str(bp.number) |
|
393 | bp_mark = str(bp.number) | |
394 | bp_mark_color = Colors.breakpoint_enabled |
|
394 | bp_mark_color = Colors.breakpoint_enabled | |
395 | if not bp.enabled: |
|
395 | if not bp.enabled: | |
396 | bp_mark_color = Colors.breakpoint_disabled |
|
396 | bp_mark_color = Colors.breakpoint_disabled | |
397 |
|
397 | |||
398 | numbers_width = 7 |
|
398 | numbers_width = 7 | |
399 | if arrow: |
|
399 | if arrow: | |
400 | # This is the line with the error |
|
400 | # This is the line with the error | |
401 | pad = numbers_width - len(str(lineno)) - len(bp_mark) |
|
401 | pad = numbers_width - len(str(lineno)) - len(bp_mark) | |
402 | if pad >= 3: |
|
402 | if pad >= 3: | |
403 | marker = '-'*(pad-3) + '-> ' |
|
403 | marker = '-'*(pad-3) + '-> ' | |
404 | elif pad == 2: |
|
404 | elif pad == 2: | |
405 | marker = '> ' |
|
405 | marker = '> ' | |
406 | elif pad == 1: |
|
406 | elif pad == 1: | |
407 | marker = '>' |
|
407 | marker = '>' | |
408 | else: |
|
408 | else: | |
409 | marker = '' |
|
409 | marker = '' | |
410 | num = '%s%s' % (marker, str(lineno)) |
|
410 | num = '%s%s' % (marker, str(lineno)) | |
411 | line = tpl_line % (bp_mark_color + bp_mark, num, line) |
|
411 | line = tpl_line % (bp_mark_color + bp_mark, num, line) | |
412 | else: |
|
412 | else: | |
413 | num = '%*s' % (numbers_width - len(bp_mark), str(lineno)) |
|
413 | num = '%*s' % (numbers_width - len(bp_mark), str(lineno)) | |
414 | line = tpl_line % (bp_mark_color + bp_mark, num, line) |
|
414 | line = tpl_line % (bp_mark_color + bp_mark, num, line) | |
415 |
|
415 | |||
416 | return line |
|
416 | return line | |
417 |
|
417 | |||
418 | def list_command_pydb(self, arg): |
|
418 | def list_command_pydb(self, arg): | |
419 | """List command to use if we have a newer pydb installed""" |
|
419 | """List command to use if we have a newer pydb installed""" | |
420 | filename, first, last = OldPdb.parse_list_cmd(self, arg) |
|
420 | filename, first, last = OldPdb.parse_list_cmd(self, arg) | |
421 | if filename is not None: |
|
421 | if filename is not None: | |
422 | self.print_list_lines(filename, first, last) |
|
422 | self.print_list_lines(filename, first, last) | |
423 |
|
423 | |||
424 | def print_list_lines(self, filename, first, last): |
|
424 | def print_list_lines(self, filename, first, last): | |
425 | """The printing (as opposed to the parsing part of a 'list' |
|
425 | """The printing (as opposed to the parsing part of a 'list' | |
426 | command.""" |
|
426 | command.""" | |
427 | try: |
|
427 | try: | |
428 | Colors = self.color_scheme_table.active_colors |
|
428 | Colors = self.color_scheme_table.active_colors | |
429 | ColorsNormal = Colors.Normal |
|
429 | ColorsNormal = Colors.Normal | |
430 | tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal) |
|
430 | tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal) | |
431 | tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal) |
|
431 | tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal) | |
432 | src = [] |
|
432 | src = [] | |
433 | if filename == "<string>" and hasattr(self, "_exec_filename"): |
|
433 | if filename == "<string>" and hasattr(self, "_exec_filename"): | |
434 | filename = self._exec_filename |
|
434 | filename = self._exec_filename | |
435 |
|
435 | |||
436 | for lineno in range(first, last+1): |
|
436 | for lineno in range(first, last+1): | |
437 | line = ulinecache.getline(filename, lineno) |
|
437 | line = ulinecache.getline(filename, lineno) | |
438 | if not line: |
|
438 | if not line: | |
439 | break |
|
439 | break | |
440 |
|
440 | |||
441 | if lineno == self.curframe.f_lineno: |
|
441 | if lineno == self.curframe.f_lineno: | |
442 | line = self.__format_line(tpl_line_em, filename, lineno, line, arrow = True) |
|
442 | line = self.__format_line(tpl_line_em, filename, lineno, line, arrow = True) | |
443 | else: |
|
443 | else: | |
444 | line = self.__format_line(tpl_line, filename, lineno, line, arrow = False) |
|
444 | line = self.__format_line(tpl_line, filename, lineno, line, arrow = False) | |
445 |
|
445 | |||
446 | src.append(line) |
|
446 | src.append(line) | |
447 | self.lineno = lineno |
|
447 | self.lineno = lineno | |
448 |
|
448 | |||
449 | print(''.join(src), file=io.stdout) |
|
449 | print(''.join(src), file=io.stdout) | |
450 |
|
450 | |||
451 | except KeyboardInterrupt: |
|
451 | except KeyboardInterrupt: | |
452 | pass |
|
452 | pass | |
453 |
|
453 | |||
454 | def do_list(self, arg): |
|
454 | def do_list(self, arg): | |
455 | self.lastcmd = 'list' |
|
455 | self.lastcmd = 'list' | |
456 | last = None |
|
456 | last = None | |
457 | if arg: |
|
457 | if arg: | |
458 | try: |
|
458 | try: | |
459 | x = eval(arg, {}, {}) |
|
459 | x = eval(arg, {}, {}) | |
460 | if type(x) == type(()): |
|
460 | if type(x) == type(()): | |
461 | first, last = x |
|
461 | first, last = x | |
462 | first = int(first) |
|
462 | first = int(first) | |
463 | last = int(last) |
|
463 | last = int(last) | |
464 | if last < first: |
|
464 | if last < first: | |
465 | # Assume it's a count |
|
465 | # Assume it's a count | |
466 | last = first + last |
|
466 | last = first + last | |
467 | else: |
|
467 | else: | |
468 | first = max(1, int(x) - 5) |
|
468 | first = max(1, int(x) - 5) | |
469 | except: |
|
469 | except: | |
470 | print('*** Error in argument:', repr(arg)) |
|
470 | print('*** Error in argument:', repr(arg)) | |
471 | return |
|
471 | return | |
472 | elif self.lineno is None: |
|
472 | elif self.lineno is None: | |
473 | first = max(1, self.curframe.f_lineno - 5) |
|
473 | first = max(1, self.curframe.f_lineno - 5) | |
474 | else: |
|
474 | else: | |
475 | first = self.lineno + 1 |
|
475 | first = self.lineno + 1 | |
476 | if last is None: |
|
476 | if last is None: | |
477 | last = first + 10 |
|
477 | last = first + 10 | |
478 | self.print_list_lines(self.curframe.f_code.co_filename, first, last) |
|
478 | self.print_list_lines(self.curframe.f_code.co_filename, first, last) | |
479 |
|
479 | |||
480 | # vds: >> |
|
480 | # vds: >> | |
481 | lineno = first |
|
481 | lineno = first | |
482 | filename = self.curframe.f_code.co_filename |
|
482 | filename = self.curframe.f_code.co_filename | |
483 | self.shell.hooks.synchronize_with_editor(filename, lineno, 0) |
|
483 | self.shell.hooks.synchronize_with_editor(filename, lineno, 0) | |
484 | # vds: << |
|
484 | # vds: << | |
485 |
|
485 | |||
486 | do_l = do_list |
|
486 | do_l = do_list | |
487 |
|
487 | |||
488 | def do_pdef(self, arg): |
|
488 | def do_pdef(self, arg): | |
489 | """Print the call signature for any callable object. |
|
489 | """Print the call signature for any callable object. | |
490 |
|
490 | |||
491 | The debugger interface to %pdef""" |
|
491 | The debugger interface to %pdef""" | |
492 | namespaces = [('Locals', self.curframe.f_locals), |
|
492 | namespaces = [('Locals', self.curframe.f_locals), | |
493 | ('Globals', self.curframe.f_globals)] |
|
493 | ('Globals', self.curframe.f_globals)] | |
494 | self.shell.find_line_magic('pdef')(arg, namespaces=namespaces) |
|
494 | self.shell.find_line_magic('pdef')(arg, namespaces=namespaces) | |
495 |
|
495 | |||
496 | def do_pdoc(self, arg): |
|
496 | def do_pdoc(self, arg): | |
497 | """Print the docstring for an object. |
|
497 | """Print the docstring for an object. | |
498 |
|
498 | |||
499 | The debugger interface to %pdoc.""" |
|
499 | The debugger interface to %pdoc.""" | |
500 | namespaces = [('Locals', self.curframe.f_locals), |
|
500 | namespaces = [('Locals', self.curframe.f_locals), | |
501 | ('Globals', self.curframe.f_globals)] |
|
501 | ('Globals', self.curframe.f_globals)] | |
502 | self.shell.find_line_magic('pdoc')(arg, namespaces=namespaces) |
|
502 | self.shell.find_line_magic('pdoc')(arg, namespaces=namespaces) | |
503 |
|
503 | |||
504 | def do_pfile(self, arg): |
|
504 | def do_pfile(self, arg): | |
505 | """Print (or run through pager) the file where an object is defined. |
|
505 | """Print (or run through pager) the file where an object is defined. | |
506 |
|
506 | |||
507 | The debugger interface to %pfile. |
|
507 | The debugger interface to %pfile. | |
508 | """ |
|
508 | """ | |
509 | namespaces = [('Locals', self.curframe.f_locals), |
|
509 | namespaces = [('Locals', self.curframe.f_locals), | |
510 | ('Globals', self.curframe.f_globals)] |
|
510 | ('Globals', self.curframe.f_globals)] | |
511 | self.shell.find_line_magic('pfile')(arg, namespaces=namespaces) |
|
511 | self.shell.find_line_magic('pfile')(arg, namespaces=namespaces) | |
512 |
|
512 | |||
513 | def do_pinfo(self, arg): |
|
513 | def do_pinfo(self, arg): | |
514 | """Provide detailed information about an object. |
|
514 | """Provide detailed information about an object. | |
515 |
|
515 | |||
516 | The debugger interface to %pinfo, i.e., obj?.""" |
|
516 | The debugger interface to %pinfo, i.e., obj?.""" | |
517 | namespaces = [('Locals', self.curframe.f_locals), |
|
517 | namespaces = [('Locals', self.curframe.f_locals), | |
518 | ('Globals', self.curframe.f_globals)] |
|
518 | ('Globals', self.curframe.f_globals)] | |
519 | self.shell.find_line_magic('pinfo')(arg, namespaces=namespaces) |
|
519 | self.shell.find_line_magic('pinfo')(arg, namespaces=namespaces) | |
520 |
|
520 | |||
521 | def do_pinfo2(self, arg): |
|
521 | def do_pinfo2(self, arg): | |
522 | """Provide extra detailed information about an object. |
|
522 | """Provide extra detailed information about an object. | |
523 |
|
523 | |||
524 | The debugger interface to %pinfo2, i.e., obj??.""" |
|
524 | The debugger interface to %pinfo2, i.e., obj??.""" | |
525 | namespaces = [('Locals', self.curframe.f_locals), |
|
525 | namespaces = [('Locals', self.curframe.f_locals), | |
526 | ('Globals', self.curframe.f_globals)] |
|
526 | ('Globals', self.curframe.f_globals)] | |
527 | self.shell.find_line_magic('pinfo2')(arg, namespaces=namespaces) |
|
527 | self.shell.find_line_magic('pinfo2')(arg, namespaces=namespaces) | |
528 |
|
528 | |||
529 | def do_psource(self, arg): |
|
529 | def do_psource(self, arg): | |
530 | """Print (or run through pager) the source code for an object.""" |
|
530 | """Print (or run through pager) the source code for an object.""" | |
531 | namespaces = [('Locals', self.curframe.f_locals), |
|
531 | namespaces = [('Locals', self.curframe.f_locals), | |
532 | ('Globals', self.curframe.f_globals)] |
|
532 | ('Globals', self.curframe.f_globals)] | |
533 | self.shell.find_line_magic('psource')(arg, namespaces=namespaces) |
|
533 | self.shell.find_line_magic('psource')(arg, namespaces=namespaces) | |
534 |
|
534 | |||
535 | def checkline(self, filename, lineno): |
|
535 | def checkline(self, filename, lineno): | |
536 | """Check whether specified line seems to be executable. |
|
536 | """Check whether specified line seems to be executable. | |
537 |
|
537 | |||
538 | Return `lineno` if it is, 0 if not (e.g. a docstring, comment, blank |
|
538 | Return `lineno` if it is, 0 if not (e.g. a docstring, comment, blank | |
539 | line or EOF). Warning: testing is not comprehensive. |
|
539 | line or EOF). Warning: testing is not comprehensive. | |
540 | """ |
|
540 | """ | |
541 | ####################################################################### |
|
541 | ####################################################################### | |
542 | # XXX Hack! Use python-2.5 compatible code for this call, because with |
|
542 | # XXX Hack! Use python-2.5 compatible code for this call, because with | |
543 | # all of our changes, we've drifted from the pdb api in 2.6. For now, |
|
543 | # all of our changes, we've drifted from the pdb api in 2.6. For now, | |
544 | # changing: |
|
544 | # changing: | |
545 | # |
|
545 | # | |
546 | #line = linecache.getline(filename, lineno, self.curframe.f_globals) |
|
546 | #line = linecache.getline(filename, lineno, self.curframe.f_globals) | |
547 | # to: |
|
547 | # to: | |
548 | # |
|
548 | # | |
549 | line = linecache.getline(filename, lineno) |
|
549 | line = linecache.getline(filename, lineno) | |
550 | # |
|
550 | # | |
551 | # does the trick. But in reality, we need to fix this by reconciling |
|
551 | # does the trick. But in reality, we need to fix this by reconciling | |
552 | # our updates with the new Pdb APIs in Python 2.6. |
|
552 | # our updates with the new Pdb APIs in Python 2.6. | |
553 | # |
|
553 | # | |
554 | # End hack. The rest of this method is copied verbatim from 2.6 pdb.py |
|
554 | # End hack. The rest of this method is copied verbatim from 2.6 pdb.py | |
555 | ####################################################################### |
|
555 | ####################################################################### | |
556 |
|
556 | |||
557 | if not line: |
|
557 | if not line: | |
558 | print('End of file', file=self.stdout) |
|
558 | print('End of file', file=self.stdout) | |
559 | return 0 |
|
559 | return 0 | |
560 | line = line.strip() |
|
560 | line = line.strip() | |
561 | # Don't allow setting breakpoint at a blank line |
|
561 | # Don't allow setting breakpoint at a blank line | |
562 | if (not line or (line[0] == '#') or |
|
562 | if (not line or (line[0] == '#') or | |
563 | (line[:3] == '"""') or line[:3] == "'''"): |
|
563 | (line[:3] == '"""') or line[:3] == "'''"): | |
564 | print('*** Blank or comment', file=self.stdout) |
|
564 | print('*** Blank or comment', file=self.stdout) | |
565 | return 0 |
|
565 | return 0 | |
566 | return lineno |
|
566 | return lineno |
@@ -1,230 +1,224 b'' | |||||
1 |
""" |
|
1 | """Hooks for IPython. | |
2 |
|
2 | |||
3 | In Python, it is possible to overwrite any method of any object if you really |
|
3 | In Python, it is possible to overwrite any method of any object if you really | |
4 |
want to. But IPython exposes a few 'hooks', methods which are |
|
4 | want to. But IPython exposes a few 'hooks', methods which are *designed* to | |
5 | be overwritten by users for customization purposes. This module defines the |
|
5 | be overwritten by users for customization purposes. This module defines the | |
6 | default versions of all such hooks, which get used by IPython if not |
|
6 | default versions of all such hooks, which get used by IPython if not | |
7 | overridden by the user. |
|
7 | overridden by the user. | |
8 |
|
8 | |||
9 |
|
|
9 | Hooks are simple functions, but they should be declared with ``self`` as their | |
10 | first argument, because when activated they are registered into IPython as |
|
10 | first argument, because when activated they are registered into IPython as | |
11 |
instance methods. |
|
11 | instance methods. The self argument will be the IPython running instance | |
12 | itself, so hooks have full access to the entire IPython object. |
|
12 | itself, so hooks have full access to the entire IPython object. | |
13 |
|
13 | |||
14 |
If you wish to define a new hook and activate it, you |
|
14 | If you wish to define a new hook and activate it, you can make an :doc:`extension | |
15 | necessary code into a python file which can be either imported or execfile()'d |
|
15 | </config/extensions/index>` or a :ref:`startup script <startup_files>`. For | |
16 | from within your profile's ipython_config.py configuration. |
|
16 | example, you could use a startup file like this:: | |
17 |
|
17 | |||
18 | For example, suppose that you have a module called 'myiphooks' in your |
|
18 | import os | |
19 | PYTHONPATH, which contains the following definition: |
|
|||
20 |
|
19 | |||
21 | import os |
|
20 | def calljed(self,filename, linenum): | |
22 | from IPython.core import ipapi |
|
21 | "My editor hook calls the jed editor directly." | |
23 | ip = ipapi.get() |
|
22 | print "Calling my own editor, jed ..." | |
24 |
|
23 | if os.system('jed +%d %s' % (linenum,filename)) != 0: | ||
25 | def calljed(self,filename, linenum): |
|
24 | raise TryNext() | |
26 | "My editor hook calls the jed editor directly." |
|
|||
27 | print "Calling my own editor, jed ..." |
|
|||
28 | if os.system('jed +%d %s' % (linenum,filename)) != 0: |
|
|||
29 | raise TryNext() |
|
|||
30 |
|
25 | |||
31 | ip.set_hook('editor', calljed) |
|
26 | def load_ipython_extension(ip): | |
|
27 | ip.set_hook('editor', calljed) | |||
32 |
|
28 | |||
33 | You can then enable the functionality by doing 'import myiphooks' |
|
|||
34 | somewhere in your configuration files or ipython command line. |
|
|||
35 | """ |
|
29 | """ | |
36 |
|
30 | |||
37 | #***************************************************************************** |
|
31 | #***************************************************************************** | |
38 | # Copyright (C) 2005 Fernando Perez. <fperez@colorado.edu> |
|
32 | # Copyright (C) 2005 Fernando Perez. <fperez@colorado.edu> | |
39 | # |
|
33 | # | |
40 | # Distributed under the terms of the BSD License. The full license is in |
|
34 | # Distributed under the terms of the BSD License. The full license is in | |
41 | # the file COPYING, distributed as part of this software. |
|
35 | # the file COPYING, distributed as part of this software. | |
42 | #***************************************************************************** |
|
36 | #***************************************************************************** | |
43 |
|
37 | |||
44 | import os |
|
38 | import os | |
45 | import subprocess |
|
39 | import subprocess | |
46 | import sys |
|
40 | import sys | |
47 |
|
41 | |||
48 | from IPython.core.error import TryNext |
|
42 | from IPython.core.error import TryNext | |
49 |
|
43 | |||
50 | # List here all the default hooks. For now it's just the editor functions |
|
44 | # List here all the default hooks. For now it's just the editor functions | |
51 | # but over time we'll move here all the public API for user-accessible things. |
|
45 | # but over time we'll move here all the public API for user-accessible things. | |
52 |
|
46 | |||
53 | __all__ = ['editor', 'fix_error_editor', 'synchronize_with_editor', |
|
47 | __all__ = ['editor', 'fix_error_editor', 'synchronize_with_editor', | |
54 | 'input_prefilter', 'shutdown_hook', 'late_startup_hook', |
|
48 | 'input_prefilter', 'shutdown_hook', 'late_startup_hook', | |
55 | 'show_in_pager','pre_prompt_hook', |
|
49 | 'show_in_pager','pre_prompt_hook', | |
56 | 'pre_run_code_hook', 'clipboard_get'] |
|
50 | 'pre_run_code_hook', 'clipboard_get'] | |
57 |
|
51 | |||
58 | def editor(self, filename, linenum=None, wait=True): |
|
52 | def editor(self, filename, linenum=None, wait=True): | |
59 | """Open the default editor at the given filename and linenumber. |
|
53 | """Open the default editor at the given filename and linenumber. | |
60 |
|
54 | |||
61 | This is IPython's default editor hook, you can use it as an example to |
|
55 | This is IPython's default editor hook, you can use it as an example to | |
62 | write your own modified one. To set your own editor function as the |
|
56 | write your own modified one. To set your own editor function as the | |
63 | new editor hook, call ip.set_hook('editor',yourfunc).""" |
|
57 | new editor hook, call ip.set_hook('editor',yourfunc).""" | |
64 |
|
58 | |||
65 | # IPython configures a default editor at startup by reading $EDITOR from |
|
59 | # IPython configures a default editor at startup by reading $EDITOR from | |
66 | # the environment, and falling back on vi (unix) or notepad (win32). |
|
60 | # the environment, and falling back on vi (unix) or notepad (win32). | |
67 | editor = self.editor |
|
61 | editor = self.editor | |
68 |
|
62 | |||
69 | # marker for at which line to open the file (for existing objects) |
|
63 | # marker for at which line to open the file (for existing objects) | |
70 | if linenum is None or editor=='notepad': |
|
64 | if linenum is None or editor=='notepad': | |
71 | linemark = '' |
|
65 | linemark = '' | |
72 | else: |
|
66 | else: | |
73 | linemark = '+%d' % int(linenum) |
|
67 | linemark = '+%d' % int(linenum) | |
74 |
|
68 | |||
75 | # Enclose in quotes if necessary and legal |
|
69 | # Enclose in quotes if necessary and legal | |
76 | if ' ' in editor and os.path.isfile(editor) and editor[0] != '"': |
|
70 | if ' ' in editor and os.path.isfile(editor) and editor[0] != '"': | |
77 | editor = '"%s"' % editor |
|
71 | editor = '"%s"' % editor | |
78 |
|
72 | |||
79 | # Call the actual editor |
|
73 | # Call the actual editor | |
80 | proc = subprocess.Popen('%s %s %s' % (editor, linemark, filename), |
|
74 | proc = subprocess.Popen('%s %s %s' % (editor, linemark, filename), | |
81 | shell=True) |
|
75 | shell=True) | |
82 | if wait and proc.wait() != 0: |
|
76 | if wait and proc.wait() != 0: | |
83 | raise TryNext() |
|
77 | raise TryNext() | |
84 |
|
78 | |||
85 | import tempfile |
|
79 | import tempfile | |
86 | def fix_error_editor(self,filename,linenum,column,msg): |
|
80 | def fix_error_editor(self,filename,linenum,column,msg): | |
87 | """Open the editor at the given filename, linenumber, column and |
|
81 | """Open the editor at the given filename, linenumber, column and | |
88 | show an error message. This is used for correcting syntax errors. |
|
82 | show an error message. This is used for correcting syntax errors. | |
89 | The current implementation only has special support for the VIM editor, |
|
83 | The current implementation only has special support for the VIM editor, | |
90 | and falls back on the 'editor' hook if VIM is not used. |
|
84 | and falls back on the 'editor' hook if VIM is not used. | |
91 |
|
85 | |||
92 | Call ip.set_hook('fix_error_editor',youfunc) to use your own function, |
|
86 | Call ip.set_hook('fix_error_editor',youfunc) to use your own function, | |
93 | """ |
|
87 | """ | |
94 | def vim_quickfix_file(): |
|
88 | def vim_quickfix_file(): | |
95 | t = tempfile.NamedTemporaryFile() |
|
89 | t = tempfile.NamedTemporaryFile() | |
96 | t.write('%s:%d:%d:%s\n' % (filename,linenum,column,msg)) |
|
90 | t.write('%s:%d:%d:%s\n' % (filename,linenum,column,msg)) | |
97 | t.flush() |
|
91 | t.flush() | |
98 | return t |
|
92 | return t | |
99 | if os.path.basename(self.editor) != 'vim': |
|
93 | if os.path.basename(self.editor) != 'vim': | |
100 | self.hooks.editor(filename,linenum) |
|
94 | self.hooks.editor(filename,linenum) | |
101 | return |
|
95 | return | |
102 | t = vim_quickfix_file() |
|
96 | t = vim_quickfix_file() | |
103 | try: |
|
97 | try: | |
104 | if os.system('vim --cmd "set errorformat=%f:%l:%c:%m" -q ' + t.name): |
|
98 | if os.system('vim --cmd "set errorformat=%f:%l:%c:%m" -q ' + t.name): | |
105 | raise TryNext() |
|
99 | raise TryNext() | |
106 | finally: |
|
100 | finally: | |
107 | t.close() |
|
101 | t.close() | |
108 |
|
102 | |||
109 |
|
103 | |||
110 | def synchronize_with_editor(self, filename, linenum, column): |
|
104 | def synchronize_with_editor(self, filename, linenum, column): | |
111 | pass |
|
105 | pass | |
112 |
|
106 | |||
113 |
|
107 | |||
114 | class CommandChainDispatcher: |
|
108 | class CommandChainDispatcher: | |
115 | """ Dispatch calls to a chain of commands until some func can handle it |
|
109 | """ Dispatch calls to a chain of commands until some func can handle it | |
116 |
|
110 | |||
117 | Usage: instantiate, execute "add" to add commands (with optional |
|
111 | Usage: instantiate, execute "add" to add commands (with optional | |
118 | priority), execute normally via f() calling mechanism. |
|
112 | priority), execute normally via f() calling mechanism. | |
119 |
|
113 | |||
120 | """ |
|
114 | """ | |
121 | def __init__(self,commands=None): |
|
115 | def __init__(self,commands=None): | |
122 | if commands is None: |
|
116 | if commands is None: | |
123 | self.chain = [] |
|
117 | self.chain = [] | |
124 | else: |
|
118 | else: | |
125 | self.chain = commands |
|
119 | self.chain = commands | |
126 |
|
120 | |||
127 |
|
121 | |||
128 | def __call__(self,*args, **kw): |
|
122 | def __call__(self,*args, **kw): | |
129 | """ Command chain is called just like normal func. |
|
123 | """ Command chain is called just like normal func. | |
130 |
|
124 | |||
131 | This will call all funcs in chain with the same args as were given to |
|
125 | This will call all funcs in chain with the same args as were given to | |
132 | this function, and return the result of first func that didn't raise |
|
126 | this function, and return the result of first func that didn't raise | |
133 | TryNext""" |
|
127 | TryNext""" | |
134 | last_exc = TryNext() |
|
128 | last_exc = TryNext() | |
135 | for prio,cmd in self.chain: |
|
129 | for prio,cmd in self.chain: | |
136 | #print "prio",prio,"cmd",cmd #dbg |
|
130 | #print "prio",prio,"cmd",cmd #dbg | |
137 | try: |
|
131 | try: | |
138 | return cmd(*args, **kw) |
|
132 | return cmd(*args, **kw) | |
139 | except TryNext as exc: |
|
133 | except TryNext as exc: | |
140 | last_exc = exc |
|
134 | last_exc = exc | |
141 | # if no function will accept it, raise TryNext up to the caller |
|
135 | # if no function will accept it, raise TryNext up to the caller | |
142 | raise last_exc |
|
136 | raise last_exc | |
143 |
|
137 | |||
144 | def __str__(self): |
|
138 | def __str__(self): | |
145 | return str(self.chain) |
|
139 | return str(self.chain) | |
146 |
|
140 | |||
147 | def add(self, func, priority=0): |
|
141 | def add(self, func, priority=0): | |
148 | """ Add a func to the cmd chain with given priority """ |
|
142 | """ Add a func to the cmd chain with given priority """ | |
149 | self.chain.append((priority, func)) |
|
143 | self.chain.append((priority, func)) | |
150 | self.chain.sort(key=lambda x: x[0]) |
|
144 | self.chain.sort(key=lambda x: x[0]) | |
151 |
|
145 | |||
152 | def __iter__(self): |
|
146 | def __iter__(self): | |
153 | """ Return all objects in chain. |
|
147 | """ Return all objects in chain. | |
154 |
|
148 | |||
155 | Handy if the objects are not callable. |
|
149 | Handy if the objects are not callable. | |
156 | """ |
|
150 | """ | |
157 | return iter(self.chain) |
|
151 | return iter(self.chain) | |
158 |
|
152 | |||
159 |
|
153 | |||
160 | def input_prefilter(self,line): |
|
154 | def input_prefilter(self,line): | |
161 | """ Default input prefilter |
|
155 | """ Default input prefilter | |
162 |
|
156 | |||
163 | This returns the line as unchanged, so that the interpreter |
|
157 | This returns the line as unchanged, so that the interpreter | |
164 | knows that nothing was done and proceeds with "classic" prefiltering |
|
158 | knows that nothing was done and proceeds with "classic" prefiltering | |
165 | (%magics, !shell commands etc.). |
|
159 | (%magics, !shell commands etc.). | |
166 |
|
160 | |||
167 | Note that leading whitespace is not passed to this hook. Prefilter |
|
161 | Note that leading whitespace is not passed to this hook. Prefilter | |
168 | can't alter indentation. |
|
162 | can't alter indentation. | |
169 |
|
163 | |||
170 | """ |
|
164 | """ | |
171 | #print "attempt to rewrite",line #dbg |
|
165 | #print "attempt to rewrite",line #dbg | |
172 | return line |
|
166 | return line | |
173 |
|
167 | |||
174 |
|
168 | |||
175 | def shutdown_hook(self): |
|
169 | def shutdown_hook(self): | |
176 | """ default shutdown hook |
|
170 | """ default shutdown hook | |
177 |
|
171 | |||
178 | Typically, shotdown hooks should raise TryNext so all shutdown ops are done |
|
172 | Typically, shotdown hooks should raise TryNext so all shutdown ops are done | |
179 | """ |
|
173 | """ | |
180 |
|
174 | |||
181 | #print "default shutdown hook ok" # dbg |
|
175 | #print "default shutdown hook ok" # dbg | |
182 | return |
|
176 | return | |
183 |
|
177 | |||
184 |
|
178 | |||
185 | def late_startup_hook(self): |
|
179 | def late_startup_hook(self): | |
186 | """ Executed after ipython has been constructed and configured |
|
180 | """ Executed after ipython has been constructed and configured | |
187 |
|
181 | |||
188 | """ |
|
182 | """ | |
189 | #print "default startup hook ok" # dbg |
|
183 | #print "default startup hook ok" # dbg | |
190 |
|
184 | |||
191 |
|
185 | |||
192 | def show_in_pager(self,s): |
|
186 | def show_in_pager(self,s): | |
193 | """ Run a string through pager """ |
|
187 | """ Run a string through pager """ | |
194 | # raising TryNext here will use the default paging functionality |
|
188 | # raising TryNext here will use the default paging functionality | |
195 | raise TryNext |
|
189 | raise TryNext | |
196 |
|
190 | |||
197 |
|
191 | |||
198 | def pre_prompt_hook(self): |
|
192 | def pre_prompt_hook(self): | |
199 | """ Run before displaying the next prompt |
|
193 | """ Run before displaying the next prompt | |
200 |
|
194 | |||
201 | Use this e.g. to display output from asynchronous operations (in order |
|
195 | Use this e.g. to display output from asynchronous operations (in order | |
202 | to not mess up text entry) |
|
196 | to not mess up text entry) | |
203 | """ |
|
197 | """ | |
204 |
|
198 | |||
205 | return None |
|
199 | return None | |
206 |
|
200 | |||
207 |
|
201 | |||
208 | def pre_run_code_hook(self): |
|
202 | def pre_run_code_hook(self): | |
209 | """ Executed before running the (prefiltered) code in IPython """ |
|
203 | """ Executed before running the (prefiltered) code in IPython """ | |
210 | return None |
|
204 | return None | |
211 |
|
205 | |||
212 |
|
206 | |||
213 | def clipboard_get(self): |
|
207 | def clipboard_get(self): | |
214 | """ Get text from the clipboard. |
|
208 | """ Get text from the clipboard. | |
215 | """ |
|
209 | """ | |
216 | from IPython.lib.clipboard import ( |
|
210 | from IPython.lib.clipboard import ( | |
217 | osx_clipboard_get, tkinter_clipboard_get, |
|
211 | osx_clipboard_get, tkinter_clipboard_get, | |
218 | win32_clipboard_get |
|
212 | win32_clipboard_get | |
219 | ) |
|
213 | ) | |
220 | if sys.platform == 'win32': |
|
214 | if sys.platform == 'win32': | |
221 | chain = [win32_clipboard_get, tkinter_clipboard_get] |
|
215 | chain = [win32_clipboard_get, tkinter_clipboard_get] | |
222 | elif sys.platform == 'darwin': |
|
216 | elif sys.platform == 'darwin': | |
223 | chain = [osx_clipboard_get, tkinter_clipboard_get] |
|
217 | chain = [osx_clipboard_get, tkinter_clipboard_get] | |
224 | else: |
|
218 | else: | |
225 | chain = [tkinter_clipboard_get] |
|
219 | chain = [tkinter_clipboard_get] | |
226 | dispatcher = CommandChainDispatcher() |
|
220 | dispatcher = CommandChainDispatcher() | |
227 | for func in chain: |
|
221 | for func in chain: | |
228 | dispatcher.add(func) |
|
222 | dispatcher.add(func) | |
229 | text = dispatcher() |
|
223 | text = dispatcher() | |
230 | return text |
|
224 | return text |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
@@ -1,312 +1,319 b'' | |||||
1 | """Implementation of magic functions related to History. |
|
1 | """Implementation of magic functions related to History. | |
2 | """ |
|
2 | """ | |
3 | #----------------------------------------------------------------------------- |
|
3 | #----------------------------------------------------------------------------- | |
4 | # Copyright (c) 2012, IPython Development Team. |
|
4 | # Copyright (c) 2012, IPython Development Team. | |
5 | # |
|
5 | # | |
6 | # Distributed under the terms of the Modified BSD License. |
|
6 | # Distributed under the terms of the Modified BSD License. | |
7 | # |
|
7 | # | |
8 | # The full license is in the file COPYING.txt, distributed with this software. |
|
8 | # The full license is in the file COPYING.txt, distributed with this software. | |
9 | #----------------------------------------------------------------------------- |
|
9 | #----------------------------------------------------------------------------- | |
10 |
|
10 | |||
11 | #----------------------------------------------------------------------------- |
|
11 | #----------------------------------------------------------------------------- | |
12 | # Imports |
|
12 | # Imports | |
13 | #----------------------------------------------------------------------------- |
|
13 | #----------------------------------------------------------------------------- | |
14 | from __future__ import print_function |
|
14 | from __future__ import print_function | |
15 |
|
15 | |||
16 | # Stdlib |
|
16 | # Stdlib | |
17 | import os |
|
17 | import os | |
18 | from io import open as io_open |
|
18 | from io import open as io_open | |
19 | from IPython.external.argparse import Action |
|
19 | from IPython.external.argparse import Action | |
20 |
|
20 | |||
21 | # Our own packages |
|
21 | # Our own packages | |
22 | from IPython.core.error import StdinNotImplementedError |
|
22 | from IPython.core.error import StdinNotImplementedError | |
23 | from IPython.core.magic import Magics, magics_class, line_magic |
|
23 | from IPython.core.magic import Magics, magics_class, line_magic | |
24 | from IPython.core.magic_arguments import (argument, magic_arguments, |
|
24 | from IPython.core.magic_arguments import (argument, magic_arguments, | |
25 | parse_argstring) |
|
25 | parse_argstring) | |
26 | from IPython.testing.skipdoctest import skip_doctest |
|
26 | from IPython.testing.skipdoctest import skip_doctest | |
27 | from IPython.utils import io |
|
27 | from IPython.utils import io | |
28 |
|
28 | |||
29 | #----------------------------------------------------------------------------- |
|
29 | #----------------------------------------------------------------------------- | |
30 | # Magics class implementation |
|
30 | # Magics class implementation | |
31 | #----------------------------------------------------------------------------- |
|
31 | #----------------------------------------------------------------------------- | |
32 |
|
32 | |||
33 |
|
33 | |||
34 | _unspecified = object() |
|
34 | _unspecified = object() | |
35 |
|
35 | |||
36 |
|
36 | |||
37 | @magics_class |
|
37 | @magics_class | |
38 | class HistoryMagics(Magics): |
|
38 | class HistoryMagics(Magics): | |
39 |
|
39 | |||
40 | @magic_arguments() |
|
40 | @magic_arguments() | |
41 | @argument( |
|
41 | @argument( | |
42 | '-n', dest='print_nums', action='store_true', default=False, |
|
42 | '-n', dest='print_nums', action='store_true', default=False, | |
43 | help=""" |
|
43 | help=""" | |
44 | print line numbers for each input. |
|
44 | print line numbers for each input. | |
45 | This feature is only available if numbered prompts are in use. |
|
45 | This feature is only available if numbered prompts are in use. | |
46 | """) |
|
46 | """) | |
47 | @argument( |
|
47 | @argument( | |
48 | '-o', dest='get_output', action='store_true', default=False, |
|
48 | '-o', dest='get_output', action='store_true', default=False, | |
49 | help="also print outputs for each input.") |
|
49 | help="also print outputs for each input.") | |
50 | @argument( |
|
50 | @argument( | |
51 | '-p', dest='pyprompts', action='store_true', default=False, |
|
51 | '-p', dest='pyprompts', action='store_true', default=False, | |
52 | help=""" |
|
52 | help=""" | |
53 | print classic '>>>' python prompts before each input. |
|
53 | print classic '>>>' python prompts before each input. | |
54 | This is useful for making documentation, and in conjunction |
|
54 | This is useful for making documentation, and in conjunction | |
55 | with -o, for producing doctest-ready output. |
|
55 | with -o, for producing doctest-ready output. | |
56 | """) |
|
56 | """) | |
57 | @argument( |
|
57 | @argument( | |
58 | '-t', dest='raw', action='store_false', default=True, |
|
58 | '-t', dest='raw', action='store_false', default=True, | |
59 | help=""" |
|
59 | help=""" | |
60 | print the 'translated' history, as IPython understands it. |
|
60 | print the 'translated' history, as IPython understands it. | |
61 | IPython filters your input and converts it all into valid Python |
|
61 | IPython filters your input and converts it all into valid Python | |
62 | source before executing it (things like magics or aliases are turned |
|
62 | source before executing it (things like magics or aliases are turned | |
63 | into function calls, for example). With this option, you'll see the |
|
63 | into function calls, for example). With this option, you'll see the | |
64 | native history instead of the user-entered version: '%%cd /' will be |
|
64 | native history instead of the user-entered version: '%%cd /' will be | |
65 | seen as 'get_ipython().magic("%%cd /")' instead of '%%cd /'. |
|
65 | seen as 'get_ipython().magic("%%cd /")' instead of '%%cd /'. | |
66 | """) |
|
66 | """) | |
67 | @argument( |
|
67 | @argument( | |
68 | '-f', dest='filename', |
|
68 | '-f', dest='filename', | |
69 | help=""" |
|
69 | help=""" | |
70 | FILENAME: instead of printing the output to the screen, redirect |
|
70 | FILENAME: instead of printing the output to the screen, redirect | |
71 | it to the given file. The file is always overwritten, though *when |
|
71 | it to the given file. The file is always overwritten, though *when | |
72 | it can*, IPython asks for confirmation first. In particular, running |
|
72 | it can*, IPython asks for confirmation first. In particular, running | |
73 | the command 'history -f FILENAME' from the IPython Notebook |
|
73 | the command 'history -f FILENAME' from the IPython Notebook | |
74 | interface will replace FILENAME even if it already exists *without* |
|
74 | interface will replace FILENAME even if it already exists *without* | |
75 | confirmation. |
|
75 | confirmation. | |
76 | """) |
|
76 | """) | |
77 | @argument( |
|
77 | @argument( | |
78 | '-g', dest='pattern', nargs='*', default=None, |
|
78 | '-g', dest='pattern', nargs='*', default=None, | |
79 | help=""" |
|
79 | help=""" | |
80 | treat the arg as a glob pattern to search for in (full) history. |
|
80 | treat the arg as a glob pattern to search for in (full) history. | |
81 | This includes the saved history (almost all commands ever written). |
|
81 | This includes the saved history (almost all commands ever written). | |
82 | The pattern may contain '?' to match one unknown character and '*' |
|
82 | The pattern may contain '?' to match one unknown character and '*' | |
83 | to match any number of unknown characters. Use '%%hist -g' to show |
|
83 | to match any number of unknown characters. Use '%%hist -g' to show | |
84 | full saved history (may be very long). |
|
84 | full saved history (may be very long). | |
85 | """) |
|
85 | """) | |
86 | @argument( |
|
86 | @argument( | |
87 | '-l', dest='limit', type=int, nargs='?', default=_unspecified, |
|
87 | '-l', dest='limit', type=int, nargs='?', default=_unspecified, | |
88 | help=""" |
|
88 | help=""" | |
89 | get the last n lines from all sessions. Specify n as a single |
|
89 | get the last n lines from all sessions. Specify n as a single | |
90 | arg, or the default is the last 10 lines. |
|
90 | arg, or the default is the last 10 lines. | |
91 | """) |
|
91 | """) | |
92 | @argument( |
|
92 | @argument( | |
93 | '-u', dest='unique', action='store_true', |
|
93 | '-u', dest='unique', action='store_true', | |
94 | help=""" |
|
94 | help=""" | |
95 | when searching history using `-g`, show only unique history. |
|
95 | when searching history using `-g`, show only unique history. | |
96 | """) |
|
96 | """) | |
97 | @argument('range', nargs='*') |
|
97 | @argument('range', nargs='*') | |
98 | @skip_doctest |
|
98 | @skip_doctest | |
99 | @line_magic |
|
99 | @line_magic | |
100 | def history(self, parameter_s = ''): |
|
100 | def history(self, parameter_s = ''): | |
101 | """Print input history (_i<n> variables), with most recent last. |
|
101 | """Print input history (_i<n> variables), with most recent last. | |
102 |
|
102 | |||
103 | By default, input history is printed without line numbers so it can be |
|
103 | By default, input history is printed without line numbers so it can be | |
104 | directly pasted into an editor. Use -n to show them. |
|
104 | directly pasted into an editor. Use -n to show them. | |
105 |
|
105 | |||
106 | By default, all input history from the current session is displayed. |
|
106 | By default, all input history from the current session is displayed. | |
107 | Ranges of history can be indicated using the syntax: |
|
107 | Ranges of history can be indicated using the syntax: | |
108 | 4 : Line 4, current session |
|
108 | ||
109 | 4-6 : Lines 4-6, current session |
|
109 | ``4`` | |
110 |
|
|
110 | Line 4, current session | |
111 | ~2/7 : Line 7, session 2 before current |
|
111 | ``4-6`` | |
112 | ~8/1-~6/5 : From the first line of 8 sessions ago, to the fifth line |
|
112 | Lines 4-6, current session | |
113 | of 6 sessions ago. |
|
113 | ``243/1-5`` | |
|
114 | Lines 1-5, session 243 | |||
|
115 | ``~2/7`` | |||
|
116 | Line 7, session 2 before current | |||
|
117 | ``~8/1-~6/5`` | |||
|
118 | From the first line of 8 sessions ago, to the fifth line of 6 | |||
|
119 | sessions ago. | |||
|
120 | ||||
114 | Multiple ranges can be entered, separated by spaces |
|
121 | Multiple ranges can be entered, separated by spaces | |
115 |
|
122 | |||
116 | The same syntax is used by %macro, %save, %edit, %rerun |
|
123 | The same syntax is used by %macro, %save, %edit, %rerun | |
117 |
|
124 | |||
118 | Examples |
|
125 | Examples | |
119 | -------- |
|
126 | -------- | |
120 | :: |
|
127 | :: | |
121 |
|
128 | |||
122 | In [6]: %history -n 4-6 |
|
129 | In [6]: %history -n 4-6 | |
123 | 4:a = 12 |
|
130 | 4:a = 12 | |
124 | 5:print a**2 |
|
131 | 5:print a**2 | |
125 | 6:%history -n 4-6 |
|
132 | 6:%history -n 4-6 | |
126 |
|
133 | |||
127 | """ |
|
134 | """ | |
128 |
|
135 | |||
129 | args = parse_argstring(self.history, parameter_s) |
|
136 | args = parse_argstring(self.history, parameter_s) | |
130 |
|
137 | |||
131 | # For brevity |
|
138 | # For brevity | |
132 | history_manager = self.shell.history_manager |
|
139 | history_manager = self.shell.history_manager | |
133 |
|
140 | |||
134 | def _format_lineno(session, line): |
|
141 | def _format_lineno(session, line): | |
135 | """Helper function to format line numbers properly.""" |
|
142 | """Helper function to format line numbers properly.""" | |
136 | if session in (0, history_manager.session_number): |
|
143 | if session in (0, history_manager.session_number): | |
137 | return str(line) |
|
144 | return str(line) | |
138 | return "%s/%s" % (session, line) |
|
145 | return "%s/%s" % (session, line) | |
139 |
|
146 | |||
140 | # Check if output to specific file was requested. |
|
147 | # Check if output to specific file was requested. | |
141 | outfname = args.filename |
|
148 | outfname = args.filename | |
142 | if not outfname: |
|
149 | if not outfname: | |
143 | outfile = io.stdout # default |
|
150 | outfile = io.stdout # default | |
144 | # We don't want to close stdout at the end! |
|
151 | # We don't want to close stdout at the end! | |
145 | close_at_end = False |
|
152 | close_at_end = False | |
146 | else: |
|
153 | else: | |
147 | if os.path.exists(outfname): |
|
154 | if os.path.exists(outfname): | |
148 | try: |
|
155 | try: | |
149 | ans = io.ask_yes_no("File %r exists. Overwrite?" % outfname) |
|
156 | ans = io.ask_yes_no("File %r exists. Overwrite?" % outfname) | |
150 | except StdinNotImplementedError: |
|
157 | except StdinNotImplementedError: | |
151 | ans = True |
|
158 | ans = True | |
152 | if not ans: |
|
159 | if not ans: | |
153 | print('Aborting.') |
|
160 | print('Aborting.') | |
154 | return |
|
161 | return | |
155 | print("Overwriting file.") |
|
162 | print("Overwriting file.") | |
156 | outfile = io_open(outfname, 'w', encoding='utf-8') |
|
163 | outfile = io_open(outfname, 'w', encoding='utf-8') | |
157 | close_at_end = True |
|
164 | close_at_end = True | |
158 |
|
165 | |||
159 | print_nums = args.print_nums |
|
166 | print_nums = args.print_nums | |
160 | get_output = args.get_output |
|
167 | get_output = args.get_output | |
161 | pyprompts = args.pyprompts |
|
168 | pyprompts = args.pyprompts | |
162 | raw = args.raw |
|
169 | raw = args.raw | |
163 |
|
170 | |||
164 | pattern = None |
|
171 | pattern = None | |
165 | limit = None if args.limit is _unspecified else args.limit |
|
172 | limit = None if args.limit is _unspecified else args.limit | |
166 |
|
173 | |||
167 | if args.pattern is not None: |
|
174 | if args.pattern is not None: | |
168 | if args.pattern: |
|
175 | if args.pattern: | |
169 | pattern = "*" + " ".join(args.pattern) + "*" |
|
176 | pattern = "*" + " ".join(args.pattern) + "*" | |
170 | else: |
|
177 | else: | |
171 | pattern = "*" |
|
178 | pattern = "*" | |
172 | hist = history_manager.search(pattern, raw=raw, output=get_output, |
|
179 | hist = history_manager.search(pattern, raw=raw, output=get_output, | |
173 | n=limit, unique=args.unique) |
|
180 | n=limit, unique=args.unique) | |
174 | print_nums = True |
|
181 | print_nums = True | |
175 | elif args.limit is not _unspecified: |
|
182 | elif args.limit is not _unspecified: | |
176 | n = 10 if limit is None else limit |
|
183 | n = 10 if limit is None else limit | |
177 | hist = history_manager.get_tail(n, raw=raw, output=get_output) |
|
184 | hist = history_manager.get_tail(n, raw=raw, output=get_output) | |
178 | else: |
|
185 | else: | |
179 | if args.range: # Get history by ranges |
|
186 | if args.range: # Get history by ranges | |
180 | hist = history_manager.get_range_by_str(" ".join(args.range), |
|
187 | hist = history_manager.get_range_by_str(" ".join(args.range), | |
181 | raw, get_output) |
|
188 | raw, get_output) | |
182 | else: # Just get history for the current session |
|
189 | else: # Just get history for the current session | |
183 | hist = history_manager.get_range(raw=raw, output=get_output) |
|
190 | hist = history_manager.get_range(raw=raw, output=get_output) | |
184 |
|
191 | |||
185 | # We could be displaying the entire history, so let's not try to pull |
|
192 | # We could be displaying the entire history, so let's not try to pull | |
186 | # it into a list in memory. Anything that needs more space will just |
|
193 | # it into a list in memory. Anything that needs more space will just | |
187 | # misalign. |
|
194 | # misalign. | |
188 | width = 4 |
|
195 | width = 4 | |
189 |
|
196 | |||
190 | for session, lineno, inline in hist: |
|
197 | for session, lineno, inline in hist: | |
191 | # Print user history with tabs expanded to 4 spaces. The GUI |
|
198 | # Print user history with tabs expanded to 4 spaces. The GUI | |
192 | # clients use hard tabs for easier usability in auto-indented code, |
|
199 | # clients use hard tabs for easier usability in auto-indented code, | |
193 | # but we want to produce PEP-8 compliant history for safe pasting |
|
200 | # but we want to produce PEP-8 compliant history for safe pasting | |
194 | # into an editor. |
|
201 | # into an editor. | |
195 | if get_output: |
|
202 | if get_output: | |
196 | inline, output = inline |
|
203 | inline, output = inline | |
197 | inline = inline.expandtabs(4).rstrip() |
|
204 | inline = inline.expandtabs(4).rstrip() | |
198 |
|
205 | |||
199 | multiline = "\n" in inline |
|
206 | multiline = "\n" in inline | |
200 | line_sep = '\n' if multiline else ' ' |
|
207 | line_sep = '\n' if multiline else ' ' | |
201 | if print_nums: |
|
208 | if print_nums: | |
202 | print(u'%s:%s' % (_format_lineno(session, lineno).rjust(width), |
|
209 | print(u'%s:%s' % (_format_lineno(session, lineno).rjust(width), | |
203 | line_sep), file=outfile, end=u'') |
|
210 | line_sep), file=outfile, end=u'') | |
204 | if pyprompts: |
|
211 | if pyprompts: | |
205 | print(u">>> ", end=u"", file=outfile) |
|
212 | print(u">>> ", end=u"", file=outfile) | |
206 | if multiline: |
|
213 | if multiline: | |
207 | inline = "\n... ".join(inline.splitlines()) + "\n..." |
|
214 | inline = "\n... ".join(inline.splitlines()) + "\n..." | |
208 | print(inline, file=outfile) |
|
215 | print(inline, file=outfile) | |
209 | if get_output and output: |
|
216 | if get_output and output: | |
210 | print(output, file=outfile) |
|
217 | print(output, file=outfile) | |
211 |
|
218 | |||
212 | if close_at_end: |
|
219 | if close_at_end: | |
213 | outfile.close() |
|
220 | outfile.close() | |
214 |
|
221 | |||
215 | @line_magic |
|
222 | @line_magic | |
216 | def recall(self, arg): |
|
223 | def recall(self, arg): | |
217 | r"""Repeat a command, or get command to input line for editing. |
|
224 | r"""Repeat a command, or get command to input line for editing. | |
218 |
|
225 | |||
219 | %recall and %rep are equivalent. |
|
226 | %recall and %rep are equivalent. | |
220 |
|
227 | |||
221 | - %recall (no arguments): |
|
228 | - %recall (no arguments): | |
222 |
|
229 | |||
223 | Place a string version of last computation result (stored in the |
|
230 | Place a string version of last computation result (stored in the | |
224 | special '_' variable) to the next input prompt. Allows you to create |
|
231 | special '_' variable) to the next input prompt. Allows you to create | |
225 | elaborate command lines without using copy-paste:: |
|
232 | elaborate command lines without using copy-paste:: | |
226 |
|
233 | |||
227 | In[1]: l = ["hei", "vaan"] |
|
234 | In[1]: l = ["hei", "vaan"] | |
228 | In[2]: "".join(l) |
|
235 | In[2]: "".join(l) | |
229 | Out[2]: heivaan |
|
236 | Out[2]: heivaan | |
230 | In[3]: %recall |
|
237 | In[3]: %recall | |
231 | In[4]: heivaan_ <== cursor blinking |
|
238 | In[4]: heivaan_ <== cursor blinking | |
232 |
|
239 | |||
233 | %recall 45 |
|
240 | %recall 45 | |
234 |
|
241 | |||
235 | Place history line 45 on the next input prompt. Use %hist to find |
|
242 | Place history line 45 on the next input prompt. Use %hist to find | |
236 | out the number. |
|
243 | out the number. | |
237 |
|
244 | |||
238 | %recall 1-4 |
|
245 | %recall 1-4 | |
239 |
|
246 | |||
240 | Combine the specified lines into one cell, and place it on the next |
|
247 | Combine the specified lines into one cell, and place it on the next | |
241 | input prompt. See %history for the slice syntax. |
|
248 | input prompt. See %history for the slice syntax. | |
242 |
|
249 | |||
243 | %recall foo+bar |
|
250 | %recall foo+bar | |
244 |
|
251 | |||
245 | If foo+bar can be evaluated in the user namespace, the result is |
|
252 | If foo+bar can be evaluated in the user namespace, the result is | |
246 | placed at the next input prompt. Otherwise, the history is searched |
|
253 | placed at the next input prompt. Otherwise, the history is searched | |
247 | for lines which contain that substring, and the most recent one is |
|
254 | for lines which contain that substring, and the most recent one is | |
248 | placed at the next input prompt. |
|
255 | placed at the next input prompt. | |
249 | """ |
|
256 | """ | |
250 | if not arg: # Last output |
|
257 | if not arg: # Last output | |
251 | self.shell.set_next_input(str(self.shell.user_ns["_"])) |
|
258 | self.shell.set_next_input(str(self.shell.user_ns["_"])) | |
252 | return |
|
259 | return | |
253 | # Get history range |
|
260 | # Get history range | |
254 | histlines = self.shell.history_manager.get_range_by_str(arg) |
|
261 | histlines = self.shell.history_manager.get_range_by_str(arg) | |
255 | cmd = "\n".join(x[2] for x in histlines) |
|
262 | cmd = "\n".join(x[2] for x in histlines) | |
256 | if cmd: |
|
263 | if cmd: | |
257 | self.shell.set_next_input(cmd.rstrip()) |
|
264 | self.shell.set_next_input(cmd.rstrip()) | |
258 | return |
|
265 | return | |
259 |
|
266 | |||
260 | try: # Variable in user namespace |
|
267 | try: # Variable in user namespace | |
261 | cmd = str(eval(arg, self.shell.user_ns)) |
|
268 | cmd = str(eval(arg, self.shell.user_ns)) | |
262 | except Exception: # Search for term in history |
|
269 | except Exception: # Search for term in history | |
263 | histlines = self.shell.history_manager.search("*"+arg+"*") |
|
270 | histlines = self.shell.history_manager.search("*"+arg+"*") | |
264 | for h in reversed([x[2] for x in histlines]): |
|
271 | for h in reversed([x[2] for x in histlines]): | |
265 | if 'recall' in h or 'rep' in h: |
|
272 | if 'recall' in h or 'rep' in h: | |
266 | continue |
|
273 | continue | |
267 | self.shell.set_next_input(h.rstrip()) |
|
274 | self.shell.set_next_input(h.rstrip()) | |
268 | return |
|
275 | return | |
269 | else: |
|
276 | else: | |
270 | self.shell.set_next_input(cmd.rstrip()) |
|
277 | self.shell.set_next_input(cmd.rstrip()) | |
271 | print("Couldn't evaluate or find in history:", arg) |
|
278 | print("Couldn't evaluate or find in history:", arg) | |
272 |
|
279 | |||
273 | @line_magic |
|
280 | @line_magic | |
274 | def rerun(self, parameter_s=''): |
|
281 | def rerun(self, parameter_s=''): | |
275 | """Re-run previous input |
|
282 | """Re-run previous input | |
276 |
|
283 | |||
277 | By default, you can specify ranges of input history to be repeated |
|
284 | By default, you can specify ranges of input history to be repeated | |
278 | (as with %history). With no arguments, it will repeat the last line. |
|
285 | (as with %history). With no arguments, it will repeat the last line. | |
279 |
|
286 | |||
280 | Options: |
|
287 | Options: | |
281 |
|
288 | |||
282 | -l <n> : Repeat the last n lines of input, not including the |
|
289 | -l <n> : Repeat the last n lines of input, not including the | |
283 | current command. |
|
290 | current command. | |
284 |
|
291 | |||
285 | -g foo : Repeat the most recent line which contains foo |
|
292 | -g foo : Repeat the most recent line which contains foo | |
286 | """ |
|
293 | """ | |
287 | opts, args = self.parse_options(parameter_s, 'l:g:', mode='string') |
|
294 | opts, args = self.parse_options(parameter_s, 'l:g:', mode='string') | |
288 | if "l" in opts: # Last n lines |
|
295 | if "l" in opts: # Last n lines | |
289 | n = int(opts['l']) |
|
296 | n = int(opts['l']) | |
290 | hist = self.shell.history_manager.get_tail(n) |
|
297 | hist = self.shell.history_manager.get_tail(n) | |
291 | elif "g" in opts: # Search |
|
298 | elif "g" in opts: # Search | |
292 | p = "*"+opts['g']+"*" |
|
299 | p = "*"+opts['g']+"*" | |
293 | hist = list(self.shell.history_manager.search(p)) |
|
300 | hist = list(self.shell.history_manager.search(p)) | |
294 | for l in reversed(hist): |
|
301 | for l in reversed(hist): | |
295 | if "rerun" not in l[2]: |
|
302 | if "rerun" not in l[2]: | |
296 | hist = [l] # The last match which isn't a %rerun |
|
303 | hist = [l] # The last match which isn't a %rerun | |
297 | break |
|
304 | break | |
298 | else: |
|
305 | else: | |
299 | hist = [] # No matches except %rerun |
|
306 | hist = [] # No matches except %rerun | |
300 | elif args: # Specify history ranges |
|
307 | elif args: # Specify history ranges | |
301 | hist = self.shell.history_manager.get_range_by_str(args) |
|
308 | hist = self.shell.history_manager.get_range_by_str(args) | |
302 | else: # Last line |
|
309 | else: # Last line | |
303 | hist = self.shell.history_manager.get_tail(1) |
|
310 | hist = self.shell.history_manager.get_tail(1) | |
304 | hist = [x[2] for x in hist] |
|
311 | hist = [x[2] for x in hist] | |
305 | if not hist: |
|
312 | if not hist: | |
306 | print("No lines in history match specification") |
|
313 | print("No lines in history match specification") | |
307 | return |
|
314 | return | |
308 | histlines = "\n".join(hist) |
|
315 | histlines = "\n".join(hist) | |
309 | print("=== Executing: ===") |
|
316 | print("=== Executing: ===") | |
310 | print(histlines) |
|
317 | print(histlines) | |
311 | print("=== Output: ===") |
|
318 | print("=== Output: ===") | |
312 | self.shell.run_cell("\n".join(hist), store_history=False) |
|
319 | self.shell.run_cell("\n".join(hist), store_history=False) |
@@ -1,96 +1,96 b'' | |||||
1 | # encoding: utf-8 |
|
1 | # encoding: utf-8 | |
2 | """ |
|
2 | """ | |
3 | A payload based version of page. |
|
3 | A payload based version of page. | |
4 |
|
4 | |||
5 | Authors: |
|
5 | Authors: | |
6 |
|
6 | |||
7 | * Brian Granger |
|
7 | * Brian Granger | |
8 | * Fernando Perez |
|
8 | * Fernando Perez | |
9 | """ |
|
9 | """ | |
10 |
|
10 | |||
11 | #----------------------------------------------------------------------------- |
|
11 | #----------------------------------------------------------------------------- | |
12 | # Copyright (C) 2008-2011 The IPython Development Team |
|
12 | # Copyright (C) 2008-2011 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 | # Third-party |
|
22 | # Third-party | |
23 | try: |
|
23 | try: | |
24 | from docutils.core import publish_string |
|
24 | from docutils.core import publish_string | |
25 | except ImportError: |
|
25 | except ImportError: | |
26 | # html paging won't be available, but we don't raise any errors. It's a |
|
26 | # html paging won't be available, but we don't raise any errors. It's a | |
27 | # purely optional feature. |
|
27 | # purely optional feature. | |
28 | pass |
|
28 | pass | |
29 |
|
29 | |||
30 | # Our own |
|
30 | # Our own | |
31 | from IPython.core.interactiveshell import InteractiveShell |
|
31 | from IPython.core.interactiveshell import InteractiveShell | |
32 |
|
32 | |||
33 | #----------------------------------------------------------------------------- |
|
33 | #----------------------------------------------------------------------------- | |
34 | # Classes and functions |
|
34 | # Classes and functions | |
35 | #----------------------------------------------------------------------------- |
|
35 | #----------------------------------------------------------------------------- | |
36 |
|
36 | |||
37 | def page(strng, start=0, screen_lines=0, pager_cmd=None, |
|
37 | def page(strng, start=0, screen_lines=0, pager_cmd=None, | |
38 | html=None, auto_html=False): |
|
38 | html=None, auto_html=False): | |
39 | """Print a string, piping through a pager. |
|
39 | """Print a string, piping through a pager. | |
40 |
|
40 | |||
41 | This version ignores the screen_lines and pager_cmd arguments and uses |
|
41 | This version ignores the screen_lines and pager_cmd arguments and uses | |
42 | IPython's payload system instead. |
|
42 | IPython's payload system instead. | |
43 |
|
43 | |||
44 | Parameters |
|
44 | Parameters | |
45 | ---------- |
|
45 | ---------- | |
46 | strng : str |
|
46 | strng : str | |
47 | Text to page. |
|
47 | Text to page. | |
48 |
|
48 | |||
49 | start : int |
|
49 | start : int | |
50 | Starting line at which to place the display. |
|
50 | Starting line at which to place the display. | |
51 |
|
51 | |||
52 | html : str, optional |
|
52 | html : str, optional | |
53 | If given, an html string to send as well. |
|
53 | If given, an html string to send as well. | |
54 |
|
54 | |||
55 | auto_html : bool, optional |
|
55 | auto_html : bool, optional | |
56 | If true, the input string is assumed to be valid reStructuredText and is |
|
56 | If true, the input string is assumed to be valid reStructuredText and is | |
57 | converted to HTML with docutils. Note that if docutils is not found, |
|
57 | converted to HTML with docutils. Note that if docutils is not found, | |
58 | this option is silently ignored. |
|
58 | this option is silently ignored. | |
59 |
|
59 | |||
60 | Note |
|
60 | Notes | |
61 | ---- |
|
61 | ----- | |
62 |
|
62 | |||
63 | Only one of the ``html`` and ``auto_html`` options can be given, not |
|
63 | Only one of the ``html`` and ``auto_html`` options can be given, not | |
64 | both. |
|
64 | both. | |
65 | """ |
|
65 | """ | |
66 |
|
66 | |||
67 | # Some routines may auto-compute start offsets incorrectly and pass a |
|
67 | # Some routines may auto-compute start offsets incorrectly and pass a | |
68 | # negative value. Offset to 0 for robustness. |
|
68 | # negative value. Offset to 0 for robustness. | |
69 | start = max(0, start) |
|
69 | start = max(0, start) | |
70 | shell = InteractiveShell.instance() |
|
70 | shell = InteractiveShell.instance() | |
71 |
|
71 | |||
72 | if auto_html: |
|
72 | if auto_html: | |
73 | try: |
|
73 | try: | |
74 | # These defaults ensure user configuration variables for docutils |
|
74 | # These defaults ensure user configuration variables for docutils | |
75 | # are not loaded, only our config is used here. |
|
75 | # are not loaded, only our config is used here. | |
76 | defaults = {'file_insertion_enabled': 0, |
|
76 | defaults = {'file_insertion_enabled': 0, | |
77 | 'raw_enabled': 0, |
|
77 | 'raw_enabled': 0, | |
78 | '_disable_config': 1} |
|
78 | '_disable_config': 1} | |
79 | html = publish_string(strng, writer_name='html', |
|
79 | html = publish_string(strng, writer_name='html', | |
80 | settings_overrides=defaults) |
|
80 | settings_overrides=defaults) | |
81 | except: |
|
81 | except: | |
82 | pass |
|
82 | pass | |
83 |
|
83 | |||
84 | payload = dict( |
|
84 | payload = dict( | |
85 | source='IPython.zmq.page.page', |
|
85 | source='IPython.zmq.page.page', | |
86 | text=strng, |
|
86 | text=strng, | |
87 | html=html, |
|
87 | html=html, | |
88 | start_line_number=start |
|
88 | start_line_number=start | |
89 | ) |
|
89 | ) | |
90 | shell.payload_manager.write_payload(payload) |
|
90 | shell.payload_manager.write_payload(payload) | |
91 |
|
91 | |||
92 |
|
92 | |||
93 | def install_payload_page(): |
|
93 | def install_payload_page(): | |
94 | """Install this version of page as IPython.core.page.page.""" |
|
94 | """Install this version of page as IPython.core.page.page.""" | |
95 | from IPython.core import page as corepage |
|
95 | from IPython.core import page as corepage | |
96 | corepage.page = page |
|
96 | corepage.page = page |
@@ -1,1247 +1,1247 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
1 | # -*- coding: utf-8 -*- | |
2 | """ |
|
2 | """ | |
3 | ultratb.py -- Spice up your tracebacks! |
|
3 | ultratb.py -- Spice up your tracebacks! | |
4 |
|
4 | |||
5 | * ColorTB |
|
5 | * ColorTB | |
6 | I've always found it a bit hard to visually parse tracebacks in Python. The |
|
6 | I've always found it a bit hard to visually parse tracebacks in Python. The | |
7 | ColorTB class is a solution to that problem. It colors the different parts of a |
|
7 | ColorTB class is a solution to that problem. It colors the different parts of a | |
8 | traceback in a manner similar to what you would expect from a syntax-highlighting |
|
8 | traceback in a manner similar to what you would expect from a syntax-highlighting | |
9 | text editor. |
|
9 | text editor. | |
10 |
|
10 | |||
11 | Installation instructions for ColorTB: |
|
11 | Installation instructions for ColorTB: | |
12 | import sys,ultratb |
|
12 | import sys,ultratb | |
13 | sys.excepthook = ultratb.ColorTB() |
|
13 | sys.excepthook = ultratb.ColorTB() | |
14 |
|
14 | |||
15 | * VerboseTB |
|
15 | * VerboseTB | |
16 | I've also included a port of Ka-Ping Yee's "cgitb.py" that produces all kinds |
|
16 | I've also included a port of Ka-Ping Yee's "cgitb.py" that produces all kinds | |
17 | of useful info when a traceback occurs. Ping originally had it spit out HTML |
|
17 | of useful info when a traceback occurs. Ping originally had it spit out HTML | |
18 | and intended it for CGI programmers, but why should they have all the fun? I |
|
18 | and intended it for CGI programmers, but why should they have all the fun? I | |
19 | altered it to spit out colored text to the terminal. It's a bit overwhelming, |
|
19 | altered it to spit out colored text to the terminal. It's a bit overwhelming, | |
20 | but kind of neat, and maybe useful for long-running programs that you believe |
|
20 | but kind of neat, and maybe useful for long-running programs that you believe | |
21 | are bug-free. If a crash *does* occur in that type of program you want details. |
|
21 | are bug-free. If a crash *does* occur in that type of program you want details. | |
22 | Give it a shot--you'll love it or you'll hate it. |
|
22 | Give it a shot--you'll love it or you'll hate it. | |
23 |
|
23 | |||
24 | Note: |
|
24 | Note: | |
25 |
|
25 | |||
26 | The Verbose mode prints the variables currently visible where the exception |
|
26 | The Verbose mode prints the variables currently visible where the exception | |
27 | happened (shortening their strings if too long). This can potentially be |
|
27 | happened (shortening their strings if too long). This can potentially be | |
28 | very slow, if you happen to have a huge data structure whose string |
|
28 | very slow, if you happen to have a huge data structure whose string | |
29 | representation is complex to compute. Your computer may appear to freeze for |
|
29 | representation is complex to compute. Your computer may appear to freeze for | |
30 | a while with cpu usage at 100%. If this occurs, you can cancel the traceback |
|
30 | a while with cpu usage at 100%. If this occurs, you can cancel the traceback | |
31 | with Ctrl-C (maybe hitting it more than once). |
|
31 | with Ctrl-C (maybe hitting it more than once). | |
32 |
|
32 | |||
33 | If you encounter this kind of situation often, you may want to use the |
|
33 | If you encounter this kind of situation often, you may want to use the | |
34 | Verbose_novars mode instead of the regular Verbose, which avoids formatting |
|
34 | Verbose_novars mode instead of the regular Verbose, which avoids formatting | |
35 | variables (but otherwise includes the information and context given by |
|
35 | variables (but otherwise includes the information and context given by | |
36 | Verbose). |
|
36 | Verbose). | |
37 |
|
37 | |||
38 |
|
38 | |||
39 | Installation instructions for ColorTB: |
|
39 | Installation instructions for ColorTB: | |
40 | import sys,ultratb |
|
40 | import sys,ultratb | |
41 | sys.excepthook = ultratb.VerboseTB() |
|
41 | sys.excepthook = ultratb.VerboseTB() | |
42 |
|
42 | |||
43 | Note: Much of the code in this module was lifted verbatim from the standard |
|
43 | Note: Much of the code in this module was lifted verbatim from the standard | |
44 | library module 'traceback.py' and Ka-Ping Yee's 'cgitb.py'. |
|
44 | library module 'traceback.py' and Ka-Ping Yee's 'cgitb.py'. | |
45 |
|
45 | |||
46 | * Color schemes |
|
46 | * Color schemes | |
47 | The colors are defined in the class TBTools through the use of the |
|
47 | The colors are defined in the class TBTools through the use of the | |
48 | ColorSchemeTable class. Currently the following exist: |
|
48 | ColorSchemeTable class. Currently the following exist: | |
49 |
|
49 | |||
50 | - NoColor: allows all of this module to be used in any terminal (the color |
|
50 | - NoColor: allows all of this module to be used in any terminal (the color | |
51 | escapes are just dummy blank strings). |
|
51 | escapes are just dummy blank strings). | |
52 |
|
52 | |||
53 | - Linux: is meant to look good in a terminal like the Linux console (black |
|
53 | - Linux: is meant to look good in a terminal like the Linux console (black | |
54 | or very dark background). |
|
54 | or very dark background). | |
55 |
|
55 | |||
56 | - LightBG: similar to Linux but swaps dark/light colors to be more readable |
|
56 | - LightBG: similar to Linux but swaps dark/light colors to be more readable | |
57 | in light background terminals. |
|
57 | in light background terminals. | |
58 |
|
58 | |||
59 | You can implement other color schemes easily, the syntax is fairly |
|
59 | You can implement other color schemes easily, the syntax is fairly | |
60 | self-explanatory. Please send back new schemes you develop to the author for |
|
60 | self-explanatory. Please send back new schemes you develop to the author for | |
61 | possible inclusion in future releases. |
|
61 | possible inclusion in future releases. | |
62 |
|
62 | |||
63 | Inheritance diagram: |
|
63 | Inheritance diagram: | |
64 |
|
64 | |||
65 | .. inheritance-diagram:: IPython.core.ultratb |
|
65 | .. inheritance-diagram:: IPython.core.ultratb | |
66 | :parts: 3 |
|
66 | :parts: 3 | |
67 | """ |
|
67 | """ | |
68 |
|
68 | |||
69 | #***************************************************************************** |
|
69 | #***************************************************************************** | |
70 | # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu> |
|
70 | # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu> | |
71 | # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu> |
|
71 | # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu> | |
72 | # |
|
72 | # | |
73 | # Distributed under the terms of the BSD License. The full license is in |
|
73 | # Distributed under the terms of the BSD License. The full license is in | |
74 | # the file COPYING, distributed as part of this software. |
|
74 | # the file COPYING, distributed as part of this software. | |
75 | #***************************************************************************** |
|
75 | #***************************************************************************** | |
76 |
|
76 | |||
77 | from __future__ import unicode_literals |
|
77 | from __future__ import unicode_literals | |
78 |
|
78 | |||
79 | import inspect |
|
79 | import inspect | |
80 | import keyword |
|
80 | import keyword | |
81 | import linecache |
|
81 | import linecache | |
82 | import os |
|
82 | import os | |
83 | import pydoc |
|
83 | import pydoc | |
84 | import re |
|
84 | import re | |
85 | import sys |
|
85 | import sys | |
86 | import time |
|
86 | import time | |
87 | import tokenize |
|
87 | import tokenize | |
88 | import traceback |
|
88 | import traceback | |
89 | import types |
|
89 | import types | |
90 |
|
90 | |||
91 | try: # Python 2 |
|
91 | try: # Python 2 | |
92 | generate_tokens = tokenize.generate_tokens |
|
92 | generate_tokens = tokenize.generate_tokens | |
93 | except AttributeError: # Python 3 |
|
93 | except AttributeError: # Python 3 | |
94 | generate_tokens = tokenize.tokenize |
|
94 | generate_tokens = tokenize.tokenize | |
95 |
|
95 | |||
96 | # For purposes of monkeypatching inspect to fix a bug in it. |
|
96 | # For purposes of monkeypatching inspect to fix a bug in it. | |
97 | from inspect import getsourcefile, getfile, getmodule,\ |
|
97 | from inspect import getsourcefile, getfile, getmodule,\ | |
98 | ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode |
|
98 | ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode | |
99 |
|
99 | |||
100 | # IPython's own modules |
|
100 | # IPython's own modules | |
101 | # Modified pdb which doesn't damage IPython's readline handling |
|
101 | # Modified pdb which doesn't damage IPython's readline handling | |
102 | from IPython.core import debugger, ipapi |
|
102 | from IPython.core import debugger, ipapi | |
103 | from IPython.core.display_trap import DisplayTrap |
|
103 | from IPython.core.display_trap import DisplayTrap | |
104 | from IPython.core.excolors import exception_colors |
|
104 | from IPython.core.excolors import exception_colors | |
105 | from IPython.utils import PyColorize |
|
105 | from IPython.utils import PyColorize | |
106 | from IPython.utils import io |
|
106 | from IPython.utils import io | |
107 | from IPython.utils import path as util_path |
|
107 | from IPython.utils import path as util_path | |
108 | from IPython.utils import py3compat |
|
108 | from IPython.utils import py3compat | |
109 | from IPython.utils import pyfile |
|
109 | from IPython.utils import pyfile | |
110 | from IPython.utils import ulinecache |
|
110 | from IPython.utils import ulinecache | |
111 | from IPython.utils.data import uniq_stable |
|
111 | from IPython.utils.data import uniq_stable | |
112 | from IPython.utils.openpy import read_py_file |
|
112 | from IPython.utils.openpy import read_py_file | |
113 | from IPython.utils.warn import info, error |
|
113 | from IPython.utils.warn import info, error | |
114 |
|
114 | |||
115 | # Globals |
|
115 | # Globals | |
116 | # amount of space to put line numbers before verbose tracebacks |
|
116 | # amount of space to put line numbers before verbose tracebacks | |
117 | INDENT_SIZE = 8 |
|
117 | INDENT_SIZE = 8 | |
118 |
|
118 | |||
119 | # Default color scheme. This is used, for example, by the traceback |
|
119 | # Default color scheme. This is used, for example, by the traceback | |
120 | # formatter. When running in an actual IPython instance, the user's rc.colors |
|
120 | # formatter. When running in an actual IPython instance, the user's rc.colors | |
121 | # value is used, but havinga module global makes this functionality available |
|
121 | # value is used, but havinga module global makes this functionality available | |
122 | # to users of ultratb who are NOT running inside ipython. |
|
122 | # to users of ultratb who are NOT running inside ipython. | |
123 | DEFAULT_SCHEME = 'NoColor' |
|
123 | DEFAULT_SCHEME = 'NoColor' | |
124 |
|
124 | |||
125 | #--------------------------------------------------------------------------- |
|
125 | #--------------------------------------------------------------------------- | |
126 | # Code begins |
|
126 | # Code begins | |
127 |
|
127 | |||
128 | # Utility functions |
|
128 | # Utility functions | |
129 | def inspect_error(): |
|
129 | def inspect_error(): | |
130 | """Print a message about internal inspect errors. |
|
130 | """Print a message about internal inspect errors. | |
131 |
|
131 | |||
132 | These are unfortunately quite common.""" |
|
132 | These are unfortunately quite common.""" | |
133 |
|
133 | |||
134 | error('Internal Python error in the inspect module.\n' |
|
134 | error('Internal Python error in the inspect module.\n' | |
135 | 'Below is the traceback from this internal error.\n') |
|
135 | 'Below is the traceback from this internal error.\n') | |
136 |
|
136 | |||
137 | # This function is a monkeypatch we apply to the Python inspect module. We have |
|
137 | # This function is a monkeypatch we apply to the Python inspect module. We have | |
138 | # now found when it's needed (see discussion on issue gh-1456), and we have a |
|
138 | # now found when it's needed (see discussion on issue gh-1456), and we have a | |
139 | # test case (IPython.core.tests.test_ultratb.ChangedPyFileTest) that fails if |
|
139 | # test case (IPython.core.tests.test_ultratb.ChangedPyFileTest) that fails if | |
140 | # the monkeypatch is not applied. TK, Aug 2012. |
|
140 | # the monkeypatch is not applied. TK, Aug 2012. | |
141 | def findsource(object): |
|
141 | def findsource(object): | |
142 | """Return the entire source file and starting line number for an object. |
|
142 | """Return the entire source file and starting line number for an object. | |
143 |
|
143 | |||
144 | The argument may be a module, class, method, function, traceback, frame, |
|
144 | The argument may be a module, class, method, function, traceback, frame, | |
145 | or code object. The source code is returned as a list of all the lines |
|
145 | or code object. The source code is returned as a list of all the lines | |
146 | in the file and the line number indexes a line in that list. An IOError |
|
146 | in the file and the line number indexes a line in that list. An IOError | |
147 | is raised if the source code cannot be retrieved. |
|
147 | is raised if the source code cannot be retrieved. | |
148 |
|
148 | |||
149 | FIXED version with which we monkeypatch the stdlib to work around a bug.""" |
|
149 | FIXED version with which we monkeypatch the stdlib to work around a bug.""" | |
150 |
|
150 | |||
151 | file = getsourcefile(object) or getfile(object) |
|
151 | file = getsourcefile(object) or getfile(object) | |
152 | # If the object is a frame, then trying to get the globals dict from its |
|
152 | # If the object is a frame, then trying to get the globals dict from its | |
153 | # module won't work. Instead, the frame object itself has the globals |
|
153 | # module won't work. Instead, the frame object itself has the globals | |
154 | # dictionary. |
|
154 | # dictionary. | |
155 | globals_dict = None |
|
155 | globals_dict = None | |
156 | if inspect.isframe(object): |
|
156 | if inspect.isframe(object): | |
157 | # XXX: can this ever be false? |
|
157 | # XXX: can this ever be false? | |
158 | globals_dict = object.f_globals |
|
158 | globals_dict = object.f_globals | |
159 | else: |
|
159 | else: | |
160 | module = getmodule(object, file) |
|
160 | module = getmodule(object, file) | |
161 | if module: |
|
161 | if module: | |
162 | globals_dict = module.__dict__ |
|
162 | globals_dict = module.__dict__ | |
163 | lines = linecache.getlines(file, globals_dict) |
|
163 | lines = linecache.getlines(file, globals_dict) | |
164 | if not lines: |
|
164 | if not lines: | |
165 | raise IOError('could not get source code') |
|
165 | raise IOError('could not get source code') | |
166 |
|
166 | |||
167 | if ismodule(object): |
|
167 | if ismodule(object): | |
168 | return lines, 0 |
|
168 | return lines, 0 | |
169 |
|
169 | |||
170 | if isclass(object): |
|
170 | if isclass(object): | |
171 | name = object.__name__ |
|
171 | name = object.__name__ | |
172 | pat = re.compile(r'^(\s*)class\s*' + name + r'\b') |
|
172 | pat = re.compile(r'^(\s*)class\s*' + name + r'\b') | |
173 | # make some effort to find the best matching class definition: |
|
173 | # make some effort to find the best matching class definition: | |
174 | # use the one with the least indentation, which is the one |
|
174 | # use the one with the least indentation, which is the one | |
175 | # that's most probably not inside a function definition. |
|
175 | # that's most probably not inside a function definition. | |
176 | candidates = [] |
|
176 | candidates = [] | |
177 | for i in range(len(lines)): |
|
177 | for i in range(len(lines)): | |
178 | match = pat.match(lines[i]) |
|
178 | match = pat.match(lines[i]) | |
179 | if match: |
|
179 | if match: | |
180 | # if it's at toplevel, it's already the best one |
|
180 | # if it's at toplevel, it's already the best one | |
181 | if lines[i][0] == 'c': |
|
181 | if lines[i][0] == 'c': | |
182 | return lines, i |
|
182 | return lines, i | |
183 | # else add whitespace to candidate list |
|
183 | # else add whitespace to candidate list | |
184 | candidates.append((match.group(1), i)) |
|
184 | candidates.append((match.group(1), i)) | |
185 | if candidates: |
|
185 | if candidates: | |
186 | # this will sort by whitespace, and by line number, |
|
186 | # this will sort by whitespace, and by line number, | |
187 | # less whitespace first |
|
187 | # less whitespace first | |
188 | candidates.sort() |
|
188 | candidates.sort() | |
189 | return lines, candidates[0][1] |
|
189 | return lines, candidates[0][1] | |
190 | else: |
|
190 | else: | |
191 | raise IOError('could not find class definition') |
|
191 | raise IOError('could not find class definition') | |
192 |
|
192 | |||
193 | if ismethod(object): |
|
193 | if ismethod(object): | |
194 | object = object.im_func |
|
194 | object = object.im_func | |
195 | if isfunction(object): |
|
195 | if isfunction(object): | |
196 | object = object.func_code |
|
196 | object = object.func_code | |
197 | if istraceback(object): |
|
197 | if istraceback(object): | |
198 | object = object.tb_frame |
|
198 | object = object.tb_frame | |
199 | if isframe(object): |
|
199 | if isframe(object): | |
200 | object = object.f_code |
|
200 | object = object.f_code | |
201 | if iscode(object): |
|
201 | if iscode(object): | |
202 | if not hasattr(object, 'co_firstlineno'): |
|
202 | if not hasattr(object, 'co_firstlineno'): | |
203 | raise IOError('could not find function definition') |
|
203 | raise IOError('could not find function definition') | |
204 | pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)') |
|
204 | pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)') | |
205 | pmatch = pat.match |
|
205 | pmatch = pat.match | |
206 | # fperez - fix: sometimes, co_firstlineno can give a number larger than |
|
206 | # fperez - fix: sometimes, co_firstlineno can give a number larger than | |
207 | # the length of lines, which causes an error. Safeguard against that. |
|
207 | # the length of lines, which causes an error. Safeguard against that. | |
208 | lnum = min(object.co_firstlineno,len(lines))-1 |
|
208 | lnum = min(object.co_firstlineno,len(lines))-1 | |
209 | while lnum > 0: |
|
209 | while lnum > 0: | |
210 | if pmatch(lines[lnum]): break |
|
210 | if pmatch(lines[lnum]): break | |
211 | lnum -= 1 |
|
211 | lnum -= 1 | |
212 |
|
212 | |||
213 | return lines, lnum |
|
213 | return lines, lnum | |
214 | raise IOError('could not find code object') |
|
214 | raise IOError('could not find code object') | |
215 |
|
215 | |||
216 | # Monkeypatch inspect to apply our bugfix. This code only works with Python >= 2.5 |
|
216 | # Monkeypatch inspect to apply our bugfix. This code only works with Python >= 2.5 | |
217 | inspect.findsource = findsource |
|
217 | inspect.findsource = findsource | |
218 |
|
218 | |||
219 | def fix_frame_records_filenames(records): |
|
219 | def fix_frame_records_filenames(records): | |
220 | """Try to fix the filenames in each record from inspect.getinnerframes(). |
|
220 | """Try to fix the filenames in each record from inspect.getinnerframes(). | |
221 |
|
221 | |||
222 | Particularly, modules loaded from within zip files have useless filenames |
|
222 | Particularly, modules loaded from within zip files have useless filenames | |
223 | attached to their code object, and inspect.getinnerframes() just uses it. |
|
223 | attached to their code object, and inspect.getinnerframes() just uses it. | |
224 | """ |
|
224 | """ | |
225 | fixed_records = [] |
|
225 | fixed_records = [] | |
226 | for frame, filename, line_no, func_name, lines, index in records: |
|
226 | for frame, filename, line_no, func_name, lines, index in records: | |
227 | # Look inside the frame's globals dictionary for __file__, which should |
|
227 | # Look inside the frame's globals dictionary for __file__, which should | |
228 | # be better. |
|
228 | # be better. | |
229 | better_fn = frame.f_globals.get('__file__', None) |
|
229 | better_fn = frame.f_globals.get('__file__', None) | |
230 | if isinstance(better_fn, str): |
|
230 | if isinstance(better_fn, str): | |
231 | # Check the type just in case someone did something weird with |
|
231 | # Check the type just in case someone did something weird with | |
232 | # __file__. It might also be None if the error occurred during |
|
232 | # __file__. It might also be None if the error occurred during | |
233 | # import. |
|
233 | # import. | |
234 | filename = better_fn |
|
234 | filename = better_fn | |
235 | fixed_records.append((frame, filename, line_no, func_name, lines, index)) |
|
235 | fixed_records.append((frame, filename, line_no, func_name, lines, index)) | |
236 | return fixed_records |
|
236 | return fixed_records | |
237 |
|
237 | |||
238 |
|
238 | |||
239 | def _fixed_getinnerframes(etb, context=1,tb_offset=0): |
|
239 | def _fixed_getinnerframes(etb, context=1,tb_offset=0): | |
240 | LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5 |
|
240 | LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5 | |
241 |
|
241 | |||
242 | records = fix_frame_records_filenames(inspect.getinnerframes(etb, context)) |
|
242 | records = fix_frame_records_filenames(inspect.getinnerframes(etb, context)) | |
243 |
|
243 | |||
244 | # If the error is at the console, don't build any context, since it would |
|
244 | # If the error is at the console, don't build any context, since it would | |
245 | # otherwise produce 5 blank lines printed out (there is no file at the |
|
245 | # otherwise produce 5 blank lines printed out (there is no file at the | |
246 | # console) |
|
246 | # console) | |
247 | rec_check = records[tb_offset:] |
|
247 | rec_check = records[tb_offset:] | |
248 | try: |
|
248 | try: | |
249 | rname = rec_check[0][1] |
|
249 | rname = rec_check[0][1] | |
250 | if rname == '<ipython console>' or rname.endswith('<string>'): |
|
250 | if rname == '<ipython console>' or rname.endswith('<string>'): | |
251 | return rec_check |
|
251 | return rec_check | |
252 | except IndexError: |
|
252 | except IndexError: | |
253 | pass |
|
253 | pass | |
254 |
|
254 | |||
255 | aux = traceback.extract_tb(etb) |
|
255 | aux = traceback.extract_tb(etb) | |
256 | assert len(records) == len(aux) |
|
256 | assert len(records) == len(aux) | |
257 | for i, (file, lnum, _, _) in zip(range(len(records)), aux): |
|
257 | for i, (file, lnum, _, _) in zip(range(len(records)), aux): | |
258 | maybeStart = lnum-1 - context//2 |
|
258 | maybeStart = lnum-1 - context//2 | |
259 | start = max(maybeStart, 0) |
|
259 | start = max(maybeStart, 0) | |
260 | end = start + context |
|
260 | end = start + context | |
261 | lines = ulinecache.getlines(file)[start:end] |
|
261 | lines = ulinecache.getlines(file)[start:end] | |
262 | buf = list(records[i]) |
|
262 | buf = list(records[i]) | |
263 | buf[LNUM_POS] = lnum |
|
263 | buf[LNUM_POS] = lnum | |
264 | buf[INDEX_POS] = lnum - 1 - start |
|
264 | buf[INDEX_POS] = lnum - 1 - start | |
265 | buf[LINES_POS] = lines |
|
265 | buf[LINES_POS] = lines | |
266 | records[i] = tuple(buf) |
|
266 | records[i] = tuple(buf) | |
267 | return records[tb_offset:] |
|
267 | return records[tb_offset:] | |
268 |
|
268 | |||
269 | # Helper function -- largely belongs to VerboseTB, but we need the same |
|
269 | # Helper function -- largely belongs to VerboseTB, but we need the same | |
270 | # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they |
|
270 | # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they | |
271 | # can be recognized properly by ipython.el's py-traceback-line-re |
|
271 | # can be recognized properly by ipython.el's py-traceback-line-re | |
272 | # (SyntaxErrors have to be treated specially because they have no traceback) |
|
272 | # (SyntaxErrors have to be treated specially because they have no traceback) | |
273 |
|
273 | |||
274 | _parser = PyColorize.Parser() |
|
274 | _parser = PyColorize.Parser() | |
275 |
|
275 | |||
276 | def _format_traceback_lines(lnum, index, lines, Colors, lvals=None,scheme=None): |
|
276 | def _format_traceback_lines(lnum, index, lines, Colors, lvals=None,scheme=None): | |
277 | numbers_width = INDENT_SIZE - 1 |
|
277 | numbers_width = INDENT_SIZE - 1 | |
278 | res = [] |
|
278 | res = [] | |
279 | i = lnum - index |
|
279 | i = lnum - index | |
280 |
|
280 | |||
281 | # This lets us get fully syntax-highlighted tracebacks. |
|
281 | # This lets us get fully syntax-highlighted tracebacks. | |
282 | if scheme is None: |
|
282 | if scheme is None: | |
283 | ipinst = ipapi.get() |
|
283 | ipinst = ipapi.get() | |
284 | if ipinst is not None: |
|
284 | if ipinst is not None: | |
285 | scheme = ipinst.colors |
|
285 | scheme = ipinst.colors | |
286 | else: |
|
286 | else: | |
287 | scheme = DEFAULT_SCHEME |
|
287 | scheme = DEFAULT_SCHEME | |
288 |
|
288 | |||
289 | _line_format = _parser.format2 |
|
289 | _line_format = _parser.format2 | |
290 |
|
290 | |||
291 | for line in lines: |
|
291 | for line in lines: | |
292 | line = py3compat.cast_unicode(line) |
|
292 | line = py3compat.cast_unicode(line) | |
293 |
|
293 | |||
294 | new_line, err = _line_format(line, 'str', scheme) |
|
294 | new_line, err = _line_format(line, 'str', scheme) | |
295 | if not err: line = new_line |
|
295 | if not err: line = new_line | |
296 |
|
296 | |||
297 | if i == lnum: |
|
297 | if i == lnum: | |
298 | # This is the line with the error |
|
298 | # This is the line with the error | |
299 | pad = numbers_width - len(str(i)) |
|
299 | pad = numbers_width - len(str(i)) | |
300 | if pad >= 3: |
|
300 | if pad >= 3: | |
301 | marker = '-'*(pad-3) + '-> ' |
|
301 | marker = '-'*(pad-3) + '-> ' | |
302 | elif pad == 2: |
|
302 | elif pad == 2: | |
303 | marker = '> ' |
|
303 | marker = '> ' | |
304 | elif pad == 1: |
|
304 | elif pad == 1: | |
305 | marker = '>' |
|
305 | marker = '>' | |
306 | else: |
|
306 | else: | |
307 | marker = '' |
|
307 | marker = '' | |
308 | num = marker + str(i) |
|
308 | num = marker + str(i) | |
309 | line = '%s%s%s %s%s' %(Colors.linenoEm, num, |
|
309 | line = '%s%s%s %s%s' %(Colors.linenoEm, num, | |
310 | Colors.line, line, Colors.Normal) |
|
310 | Colors.line, line, Colors.Normal) | |
311 | else: |
|
311 | else: | |
312 | num = '%*s' % (numbers_width,i) |
|
312 | num = '%*s' % (numbers_width,i) | |
313 | line = '%s%s%s %s' %(Colors.lineno, num, |
|
313 | line = '%s%s%s %s' %(Colors.lineno, num, | |
314 | Colors.Normal, line) |
|
314 | Colors.Normal, line) | |
315 |
|
315 | |||
316 | res.append(line) |
|
316 | res.append(line) | |
317 | if lvals and i == lnum: |
|
317 | if lvals and i == lnum: | |
318 | res.append(lvals + '\n') |
|
318 | res.append(lvals + '\n') | |
319 | i = i + 1 |
|
319 | i = i + 1 | |
320 | return res |
|
320 | return res | |
321 |
|
321 | |||
322 |
|
322 | |||
323 | #--------------------------------------------------------------------------- |
|
323 | #--------------------------------------------------------------------------- | |
324 | # Module classes |
|
324 | # Module classes | |
325 | class TBTools(object): |
|
325 | class TBTools(object): | |
326 | """Basic tools used by all traceback printer classes.""" |
|
326 | """Basic tools used by all traceback printer classes.""" | |
327 |
|
327 | |||
328 | # Number of frames to skip when reporting tracebacks |
|
328 | # Number of frames to skip when reporting tracebacks | |
329 | tb_offset = 0 |
|
329 | tb_offset = 0 | |
330 |
|
330 | |||
331 | def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None): |
|
331 | def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None): | |
332 | # Whether to call the interactive pdb debugger after printing |
|
332 | # Whether to call the interactive pdb debugger after printing | |
333 | # tracebacks or not |
|
333 | # tracebacks or not | |
334 | self.call_pdb = call_pdb |
|
334 | self.call_pdb = call_pdb | |
335 |
|
335 | |||
336 | # Output stream to write to. Note that we store the original value in |
|
336 | # Output stream to write to. Note that we store the original value in | |
337 | # a private attribute and then make the public ostream a property, so |
|
337 | # a private attribute and then make the public ostream a property, so | |
338 | # that we can delay accessing io.stdout until runtime. The way |
|
338 | # that we can delay accessing io.stdout until runtime. The way | |
339 | # things are written now, the io.stdout object is dynamically managed |
|
339 | # things are written now, the io.stdout object is dynamically managed | |
340 | # so a reference to it should NEVER be stored statically. This |
|
340 | # so a reference to it should NEVER be stored statically. This | |
341 | # property approach confines this detail to a single location, and all |
|
341 | # property approach confines this detail to a single location, and all | |
342 | # subclasses can simply access self.ostream for writing. |
|
342 | # subclasses can simply access self.ostream for writing. | |
343 | self._ostream = ostream |
|
343 | self._ostream = ostream | |
344 |
|
344 | |||
345 | # Create color table |
|
345 | # Create color table | |
346 | self.color_scheme_table = exception_colors() |
|
346 | self.color_scheme_table = exception_colors() | |
347 |
|
347 | |||
348 | self.set_colors(color_scheme) |
|
348 | self.set_colors(color_scheme) | |
349 | self.old_scheme = color_scheme # save initial value for toggles |
|
349 | self.old_scheme = color_scheme # save initial value for toggles | |
350 |
|
350 | |||
351 | if call_pdb: |
|
351 | if call_pdb: | |
352 | self.pdb = debugger.Pdb(self.color_scheme_table.active_scheme_name) |
|
352 | self.pdb = debugger.Pdb(self.color_scheme_table.active_scheme_name) | |
353 | else: |
|
353 | else: | |
354 | self.pdb = None |
|
354 | self.pdb = None | |
355 |
|
355 | |||
356 | def _get_ostream(self): |
|
356 | def _get_ostream(self): | |
357 | """Output stream that exceptions are written to. |
|
357 | """Output stream that exceptions are written to. | |
358 |
|
358 | |||
359 | Valid values are: |
|
359 | Valid values are: | |
360 |
|
360 | |||
361 | - None: the default, which means that IPython will dynamically resolve |
|
361 | - None: the default, which means that IPython will dynamically resolve | |
362 | to io.stdout. This ensures compatibility with most tools, including |
|
362 | to io.stdout. This ensures compatibility with most tools, including | |
363 | Windows (where plain stdout doesn't recognize ANSI escapes). |
|
363 | Windows (where plain stdout doesn't recognize ANSI escapes). | |
364 |
|
364 | |||
365 | - Any object with 'write' and 'flush' attributes. |
|
365 | - Any object with 'write' and 'flush' attributes. | |
366 | """ |
|
366 | """ | |
367 | return io.stdout if self._ostream is None else self._ostream |
|
367 | return io.stdout if self._ostream is None else self._ostream | |
368 |
|
368 | |||
369 | def _set_ostream(self, val): |
|
369 | def _set_ostream(self, val): | |
370 | assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush')) |
|
370 | assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush')) | |
371 | self._ostream = val |
|
371 | self._ostream = val | |
372 |
|
372 | |||
373 | ostream = property(_get_ostream, _set_ostream) |
|
373 | ostream = property(_get_ostream, _set_ostream) | |
374 |
|
374 | |||
375 | def set_colors(self,*args,**kw): |
|
375 | def set_colors(self,*args,**kw): | |
376 | """Shorthand access to the color table scheme selector method.""" |
|
376 | """Shorthand access to the color table scheme selector method.""" | |
377 |
|
377 | |||
378 | # Set own color table |
|
378 | # Set own color table | |
379 | self.color_scheme_table.set_active_scheme(*args,**kw) |
|
379 | self.color_scheme_table.set_active_scheme(*args,**kw) | |
380 | # for convenience, set Colors to the active scheme |
|
380 | # for convenience, set Colors to the active scheme | |
381 | self.Colors = self.color_scheme_table.active_colors |
|
381 | self.Colors = self.color_scheme_table.active_colors | |
382 | # Also set colors of debugger |
|
382 | # Also set colors of debugger | |
383 | if hasattr(self,'pdb') and self.pdb is not None: |
|
383 | if hasattr(self,'pdb') and self.pdb is not None: | |
384 | self.pdb.set_colors(*args,**kw) |
|
384 | self.pdb.set_colors(*args,**kw) | |
385 |
|
385 | |||
386 | def color_toggle(self): |
|
386 | def color_toggle(self): | |
387 | """Toggle between the currently active color scheme and NoColor.""" |
|
387 | """Toggle between the currently active color scheme and NoColor.""" | |
388 |
|
388 | |||
389 | if self.color_scheme_table.active_scheme_name == 'NoColor': |
|
389 | if self.color_scheme_table.active_scheme_name == 'NoColor': | |
390 | self.color_scheme_table.set_active_scheme(self.old_scheme) |
|
390 | self.color_scheme_table.set_active_scheme(self.old_scheme) | |
391 | self.Colors = self.color_scheme_table.active_colors |
|
391 | self.Colors = self.color_scheme_table.active_colors | |
392 | else: |
|
392 | else: | |
393 | self.old_scheme = self.color_scheme_table.active_scheme_name |
|
393 | self.old_scheme = self.color_scheme_table.active_scheme_name | |
394 | self.color_scheme_table.set_active_scheme('NoColor') |
|
394 | self.color_scheme_table.set_active_scheme('NoColor') | |
395 | self.Colors = self.color_scheme_table.active_colors |
|
395 | self.Colors = self.color_scheme_table.active_colors | |
396 |
|
396 | |||
397 | def stb2text(self, stb): |
|
397 | def stb2text(self, stb): | |
398 | """Convert a structured traceback (a list) to a string.""" |
|
398 | """Convert a structured traceback (a list) to a string.""" | |
399 | return '\n'.join(stb) |
|
399 | return '\n'.join(stb) | |
400 |
|
400 | |||
401 | def text(self, etype, value, tb, tb_offset=None, context=5): |
|
401 | def text(self, etype, value, tb, tb_offset=None, context=5): | |
402 | """Return formatted traceback. |
|
402 | """Return formatted traceback. | |
403 |
|
403 | |||
404 | Subclasses may override this if they add extra arguments. |
|
404 | Subclasses may override this if they add extra arguments. | |
405 | """ |
|
405 | """ | |
406 | tb_list = self.structured_traceback(etype, value, tb, |
|
406 | tb_list = self.structured_traceback(etype, value, tb, | |
407 | tb_offset, context) |
|
407 | tb_offset, context) | |
408 | return self.stb2text(tb_list) |
|
408 | return self.stb2text(tb_list) | |
409 |
|
409 | |||
410 | def structured_traceback(self, etype, evalue, tb, tb_offset=None, |
|
410 | def structured_traceback(self, etype, evalue, tb, tb_offset=None, | |
411 | context=5, mode=None): |
|
411 | context=5, mode=None): | |
412 | """Return a list of traceback frames. |
|
412 | """Return a list of traceback frames. | |
413 |
|
413 | |||
414 | Must be implemented by each class. |
|
414 | Must be implemented by each class. | |
415 | """ |
|
415 | """ | |
416 | raise NotImplementedError() |
|
416 | raise NotImplementedError() | |
417 |
|
417 | |||
418 |
|
418 | |||
419 | #--------------------------------------------------------------------------- |
|
419 | #--------------------------------------------------------------------------- | |
420 | class ListTB(TBTools): |
|
420 | class ListTB(TBTools): | |
421 | """Print traceback information from a traceback list, with optional color. |
|
421 | """Print traceback information from a traceback list, with optional color. | |
422 |
|
422 | |||
423 |
Calling |
|
423 | Calling requires 3 arguments: (etype, evalue, elist) | |
424 | (etype, evalue, elist) |
|
424 | as would be obtained by:: | |
425 | as would be obtained by: |
|
425 | ||
426 | etype, evalue, tb = sys.exc_info() |
|
426 | etype, evalue, tb = sys.exc_info() | |
427 | if tb: |
|
427 | if tb: | |
428 | elist = traceback.extract_tb(tb) |
|
428 | elist = traceback.extract_tb(tb) | |
429 | else: |
|
429 | else: | |
430 | elist = None |
|
430 | elist = None | |
431 |
|
431 | |||
432 | It can thus be used by programs which need to process the traceback before |
|
432 | It can thus be used by programs which need to process the traceback before | |
433 | printing (such as console replacements based on the code module from the |
|
433 | printing (such as console replacements based on the code module from the | |
434 | standard library). |
|
434 | standard library). | |
435 |
|
435 | |||
436 | Because they are meant to be called without a full traceback (only a |
|
436 | Because they are meant to be called without a full traceback (only a | |
437 | list), instances of this class can't call the interactive pdb debugger.""" |
|
437 | list), instances of this class can't call the interactive pdb debugger.""" | |
438 |
|
438 | |||
439 | def __init__(self,color_scheme = 'NoColor', call_pdb=False, ostream=None): |
|
439 | def __init__(self,color_scheme = 'NoColor', call_pdb=False, ostream=None): | |
440 | TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb, |
|
440 | TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb, | |
441 | ostream=ostream) |
|
441 | ostream=ostream) | |
442 |
|
442 | |||
443 | def __call__(self, etype, value, elist): |
|
443 | def __call__(self, etype, value, elist): | |
444 | self.ostream.flush() |
|
444 | self.ostream.flush() | |
445 | self.ostream.write(self.text(etype, value, elist)) |
|
445 | self.ostream.write(self.text(etype, value, elist)) | |
446 | self.ostream.write('\n') |
|
446 | self.ostream.write('\n') | |
447 |
|
447 | |||
448 | def structured_traceback(self, etype, value, elist, tb_offset=None, |
|
448 | def structured_traceback(self, etype, value, elist, tb_offset=None, | |
449 | context=5): |
|
449 | context=5): | |
450 | """Return a color formatted string with the traceback info. |
|
450 | """Return a color formatted string with the traceback info. | |
451 |
|
451 | |||
452 | Parameters |
|
452 | Parameters | |
453 | ---------- |
|
453 | ---------- | |
454 | etype : exception type |
|
454 | etype : exception type | |
455 | Type of the exception raised. |
|
455 | Type of the exception raised. | |
456 |
|
456 | |||
457 | value : object |
|
457 | value : object | |
458 | Data stored in the exception |
|
458 | Data stored in the exception | |
459 |
|
459 | |||
460 | elist : list |
|
460 | elist : list | |
461 | List of frames, see class docstring for details. |
|
461 | List of frames, see class docstring for details. | |
462 |
|
462 | |||
463 | tb_offset : int, optional |
|
463 | tb_offset : int, optional | |
464 | Number of frames in the traceback to skip. If not given, the |
|
464 | Number of frames in the traceback to skip. If not given, the | |
465 | instance value is used (set in constructor). |
|
465 | instance value is used (set in constructor). | |
466 |
|
466 | |||
467 | context : int, optional |
|
467 | context : int, optional | |
468 | Number of lines of context information to print. |
|
468 | Number of lines of context information to print. | |
469 |
|
469 | |||
470 | Returns |
|
470 | Returns | |
471 | ------- |
|
471 | ------- | |
472 | String with formatted exception. |
|
472 | String with formatted exception. | |
473 | """ |
|
473 | """ | |
474 | tb_offset = self.tb_offset if tb_offset is None else tb_offset |
|
474 | tb_offset = self.tb_offset if tb_offset is None else tb_offset | |
475 | Colors = self.Colors |
|
475 | Colors = self.Colors | |
476 | out_list = [] |
|
476 | out_list = [] | |
477 | if elist: |
|
477 | if elist: | |
478 |
|
478 | |||
479 | if tb_offset and len(elist) > tb_offset: |
|
479 | if tb_offset and len(elist) > tb_offset: | |
480 | elist = elist[tb_offset:] |
|
480 | elist = elist[tb_offset:] | |
481 |
|
481 | |||
482 | out_list.append('Traceback %s(most recent call last)%s:' % |
|
482 | out_list.append('Traceback %s(most recent call last)%s:' % | |
483 | (Colors.normalEm, Colors.Normal) + '\n') |
|
483 | (Colors.normalEm, Colors.Normal) + '\n') | |
484 | out_list.extend(self._format_list(elist)) |
|
484 | out_list.extend(self._format_list(elist)) | |
485 | # The exception info should be a single entry in the list. |
|
485 | # The exception info should be a single entry in the list. | |
486 | lines = ''.join(self._format_exception_only(etype, value)) |
|
486 | lines = ''.join(self._format_exception_only(etype, value)) | |
487 | out_list.append(lines) |
|
487 | out_list.append(lines) | |
488 |
|
488 | |||
489 | # Note: this code originally read: |
|
489 | # Note: this code originally read: | |
490 |
|
490 | |||
491 | ## for line in lines[:-1]: |
|
491 | ## for line in lines[:-1]: | |
492 | ## out_list.append(" "+line) |
|
492 | ## out_list.append(" "+line) | |
493 | ## out_list.append(lines[-1]) |
|
493 | ## out_list.append(lines[-1]) | |
494 |
|
494 | |||
495 | # This means it was indenting everything but the last line by a little |
|
495 | # This means it was indenting everything but the last line by a little | |
496 | # bit. I've disabled this for now, but if we see ugliness somewhre we |
|
496 | # bit. I've disabled this for now, but if we see ugliness somewhre we | |
497 | # can restore it. |
|
497 | # can restore it. | |
498 |
|
498 | |||
499 | return out_list |
|
499 | return out_list | |
500 |
|
500 | |||
501 | def _format_list(self, extracted_list): |
|
501 | def _format_list(self, extracted_list): | |
502 | """Format a list of traceback entry tuples for printing. |
|
502 | """Format a list of traceback entry tuples for printing. | |
503 |
|
503 | |||
504 | Given a list of tuples as returned by extract_tb() or |
|
504 | Given a list of tuples as returned by extract_tb() or | |
505 | extract_stack(), return a list of strings ready for printing. |
|
505 | extract_stack(), return a list of strings ready for printing. | |
506 | Each string in the resulting list corresponds to the item with the |
|
506 | Each string in the resulting list corresponds to the item with the | |
507 | same index in the argument list. Each string ends in a newline; |
|
507 | same index in the argument list. Each string ends in a newline; | |
508 | the strings may contain internal newlines as well, for those items |
|
508 | the strings may contain internal newlines as well, for those items | |
509 | whose source text line is not None. |
|
509 | whose source text line is not None. | |
510 |
|
510 | |||
511 | Lifted almost verbatim from traceback.py |
|
511 | Lifted almost verbatim from traceback.py | |
512 | """ |
|
512 | """ | |
513 |
|
513 | |||
514 | Colors = self.Colors |
|
514 | Colors = self.Colors | |
515 | list = [] |
|
515 | list = [] | |
516 | for filename, lineno, name, line in extracted_list[:-1]: |
|
516 | for filename, lineno, name, line in extracted_list[:-1]: | |
517 | item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \ |
|
517 | item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \ | |
518 | (Colors.filename, filename, Colors.Normal, |
|
518 | (Colors.filename, filename, Colors.Normal, | |
519 | Colors.lineno, lineno, Colors.Normal, |
|
519 | Colors.lineno, lineno, Colors.Normal, | |
520 | Colors.name, name, Colors.Normal) |
|
520 | Colors.name, name, Colors.Normal) | |
521 | if line: |
|
521 | if line: | |
522 | item += ' %s\n' % line.strip() |
|
522 | item += ' %s\n' % line.strip() | |
523 | list.append(item) |
|
523 | list.append(item) | |
524 | # Emphasize the last entry |
|
524 | # Emphasize the last entry | |
525 | filename, lineno, name, line = extracted_list[-1] |
|
525 | filename, lineno, name, line = extracted_list[-1] | |
526 | item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \ |
|
526 | item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \ | |
527 | (Colors.normalEm, |
|
527 | (Colors.normalEm, | |
528 | Colors.filenameEm, filename, Colors.normalEm, |
|
528 | Colors.filenameEm, filename, Colors.normalEm, | |
529 | Colors.linenoEm, lineno, Colors.normalEm, |
|
529 | Colors.linenoEm, lineno, Colors.normalEm, | |
530 | Colors.nameEm, name, Colors.normalEm, |
|
530 | Colors.nameEm, name, Colors.normalEm, | |
531 | Colors.Normal) |
|
531 | Colors.Normal) | |
532 | if line: |
|
532 | if line: | |
533 | item += '%s %s%s\n' % (Colors.line, line.strip(), |
|
533 | item += '%s %s%s\n' % (Colors.line, line.strip(), | |
534 | Colors.Normal) |
|
534 | Colors.Normal) | |
535 | list.append(item) |
|
535 | list.append(item) | |
536 | #from pprint import pformat; print 'LISTTB', pformat(list) # dbg |
|
536 | #from pprint import pformat; print 'LISTTB', pformat(list) # dbg | |
537 | return list |
|
537 | return list | |
538 |
|
538 | |||
539 | def _format_exception_only(self, etype, value): |
|
539 | def _format_exception_only(self, etype, value): | |
540 | """Format the exception part of a traceback. |
|
540 | """Format the exception part of a traceback. | |
541 |
|
541 | |||
542 | The arguments are the exception type and value such as given by |
|
542 | The arguments are the exception type and value such as given by | |
543 | sys.exc_info()[:2]. The return value is a list of strings, each ending |
|
543 | sys.exc_info()[:2]. The return value is a list of strings, each ending | |
544 | in a newline. Normally, the list contains a single string; however, |
|
544 | in a newline. Normally, the list contains a single string; however, | |
545 | for SyntaxError exceptions, it contains several lines that (when |
|
545 | for SyntaxError exceptions, it contains several lines that (when | |
546 | printed) display detailed information about where the syntax error |
|
546 | printed) display detailed information about where the syntax error | |
547 | occurred. The message indicating which exception occurred is the |
|
547 | occurred. The message indicating which exception occurred is the | |
548 | always last string in the list. |
|
548 | always last string in the list. | |
549 |
|
549 | |||
550 | Also lifted nearly verbatim from traceback.py |
|
550 | Also lifted nearly verbatim from traceback.py | |
551 | """ |
|
551 | """ | |
552 | have_filedata = False |
|
552 | have_filedata = False | |
553 | Colors = self.Colors |
|
553 | Colors = self.Colors | |
554 | list = [] |
|
554 | list = [] | |
555 | stype = Colors.excName + etype.__name__ + Colors.Normal |
|
555 | stype = Colors.excName + etype.__name__ + Colors.Normal | |
556 | if value is None: |
|
556 | if value is None: | |
557 | # Not sure if this can still happen in Python 2.6 and above |
|
557 | # Not sure if this can still happen in Python 2.6 and above | |
558 | list.append( py3compat.cast_unicode(stype) + '\n') |
|
558 | list.append( py3compat.cast_unicode(stype) + '\n') | |
559 | else: |
|
559 | else: | |
560 | if issubclass(etype, SyntaxError): |
|
560 | if issubclass(etype, SyntaxError): | |
561 | have_filedata = True |
|
561 | have_filedata = True | |
562 | #print 'filename is',filename # dbg |
|
562 | #print 'filename is',filename # dbg | |
563 | if not value.filename: value.filename = "<string>" |
|
563 | if not value.filename: value.filename = "<string>" | |
564 | if value.lineno: |
|
564 | if value.lineno: | |
565 | lineno = value.lineno |
|
565 | lineno = value.lineno | |
566 | textline = ulinecache.getline(value.filename, value.lineno) |
|
566 | textline = ulinecache.getline(value.filename, value.lineno) | |
567 | else: |
|
567 | else: | |
568 | lineno = 'unknown' |
|
568 | lineno = 'unknown' | |
569 | textline = '' |
|
569 | textline = '' | |
570 | list.append('%s File %s"%s"%s, line %s%s%s\n' % \ |
|
570 | list.append('%s File %s"%s"%s, line %s%s%s\n' % \ | |
571 | (Colors.normalEm, |
|
571 | (Colors.normalEm, | |
572 | Colors.filenameEm, py3compat.cast_unicode(value.filename), Colors.normalEm, |
|
572 | Colors.filenameEm, py3compat.cast_unicode(value.filename), Colors.normalEm, | |
573 | Colors.linenoEm, lineno, Colors.Normal )) |
|
573 | Colors.linenoEm, lineno, Colors.Normal )) | |
574 | if textline == '': |
|
574 | if textline == '': | |
575 | textline = py3compat.cast_unicode(value.text, "utf-8") |
|
575 | textline = py3compat.cast_unicode(value.text, "utf-8") | |
576 |
|
576 | |||
577 | if textline is not None: |
|
577 | if textline is not None: | |
578 | i = 0 |
|
578 | i = 0 | |
579 | while i < len(textline) and textline[i].isspace(): |
|
579 | while i < len(textline) and textline[i].isspace(): | |
580 | i += 1 |
|
580 | i += 1 | |
581 | list.append('%s %s%s\n' % (Colors.line, |
|
581 | list.append('%s %s%s\n' % (Colors.line, | |
582 | textline.strip(), |
|
582 | textline.strip(), | |
583 | Colors.Normal)) |
|
583 | Colors.Normal)) | |
584 | if value.offset is not None: |
|
584 | if value.offset is not None: | |
585 | s = ' ' |
|
585 | s = ' ' | |
586 | for c in textline[i:value.offset-1]: |
|
586 | for c in textline[i:value.offset-1]: | |
587 | if c.isspace(): |
|
587 | if c.isspace(): | |
588 | s += c |
|
588 | s += c | |
589 | else: |
|
589 | else: | |
590 | s += ' ' |
|
590 | s += ' ' | |
591 | list.append('%s%s^%s\n' % (Colors.caret, s, |
|
591 | list.append('%s%s^%s\n' % (Colors.caret, s, | |
592 | Colors.Normal) ) |
|
592 | Colors.Normal) ) | |
593 |
|
593 | |||
594 | try: |
|
594 | try: | |
595 | s = value.msg |
|
595 | s = value.msg | |
596 | except Exception: |
|
596 | except Exception: | |
597 | s = self._some_str(value) |
|
597 | s = self._some_str(value) | |
598 | if s: |
|
598 | if s: | |
599 | list.append('%s%s:%s %s\n' % (str(stype), Colors.excName, |
|
599 | list.append('%s%s:%s %s\n' % (str(stype), Colors.excName, | |
600 | Colors.Normal, s)) |
|
600 | Colors.Normal, s)) | |
601 | else: |
|
601 | else: | |
602 | list.append('%s\n' % str(stype)) |
|
602 | list.append('%s\n' % str(stype)) | |
603 |
|
603 | |||
604 | # sync with user hooks |
|
604 | # sync with user hooks | |
605 | if have_filedata: |
|
605 | if have_filedata: | |
606 | ipinst = ipapi.get() |
|
606 | ipinst = ipapi.get() | |
607 | if ipinst is not None: |
|
607 | if ipinst is not None: | |
608 | ipinst.hooks.synchronize_with_editor(value.filename, value.lineno, 0) |
|
608 | ipinst.hooks.synchronize_with_editor(value.filename, value.lineno, 0) | |
609 |
|
609 | |||
610 | return list |
|
610 | return list | |
611 |
|
611 | |||
612 | def get_exception_only(self, etype, value): |
|
612 | def get_exception_only(self, etype, value): | |
613 | """Only print the exception type and message, without a traceback. |
|
613 | """Only print the exception type and message, without a traceback. | |
614 |
|
614 | |||
615 | Parameters |
|
615 | Parameters | |
616 | ---------- |
|
616 | ---------- | |
617 | etype : exception type |
|
617 | etype : exception type | |
618 | value : exception value |
|
618 | value : exception value | |
619 | """ |
|
619 | """ | |
620 | return ListTB.structured_traceback(self, etype, value, []) |
|
620 | return ListTB.structured_traceback(self, etype, value, []) | |
621 |
|
621 | |||
622 |
|
622 | |||
623 | def show_exception_only(self, etype, evalue): |
|
623 | def show_exception_only(self, etype, evalue): | |
624 | """Only print the exception type and message, without a traceback. |
|
624 | """Only print the exception type and message, without a traceback. | |
625 |
|
625 | |||
626 | Parameters |
|
626 | Parameters | |
627 | ---------- |
|
627 | ---------- | |
628 | etype : exception type |
|
628 | etype : exception type | |
629 | value : exception value |
|
629 | value : exception value | |
630 | """ |
|
630 | """ | |
631 | # This method needs to use __call__ from *this* class, not the one from |
|
631 | # This method needs to use __call__ from *this* class, not the one from | |
632 | # a subclass whose signature or behavior may be different |
|
632 | # a subclass whose signature or behavior may be different | |
633 | ostream = self.ostream |
|
633 | ostream = self.ostream | |
634 | ostream.flush() |
|
634 | ostream.flush() | |
635 | ostream.write('\n'.join(self.get_exception_only(etype, evalue))) |
|
635 | ostream.write('\n'.join(self.get_exception_only(etype, evalue))) | |
636 | ostream.flush() |
|
636 | ostream.flush() | |
637 |
|
637 | |||
638 | def _some_str(self, value): |
|
638 | def _some_str(self, value): | |
639 | # Lifted from traceback.py |
|
639 | # Lifted from traceback.py | |
640 | try: |
|
640 | try: | |
641 | return str(value) |
|
641 | return str(value) | |
642 | except: |
|
642 | except: | |
643 | return '<unprintable %s object>' % type(value).__name__ |
|
643 | return '<unprintable %s object>' % type(value).__name__ | |
644 |
|
644 | |||
645 | #---------------------------------------------------------------------------- |
|
645 | #---------------------------------------------------------------------------- | |
646 | class VerboseTB(TBTools): |
|
646 | class VerboseTB(TBTools): | |
647 | """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead |
|
647 | """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead | |
648 | of HTML. Requires inspect and pydoc. Crazy, man. |
|
648 | of HTML. Requires inspect and pydoc. Crazy, man. | |
649 |
|
649 | |||
650 | Modified version which optionally strips the topmost entries from the |
|
650 | Modified version which optionally strips the topmost entries from the | |
651 | traceback, to be used with alternate interpreters (because their own code |
|
651 | traceback, to be used with alternate interpreters (because their own code | |
652 | would appear in the traceback).""" |
|
652 | would appear in the traceback).""" | |
653 |
|
653 | |||
654 | def __init__(self,color_scheme = 'Linux', call_pdb=False, ostream=None, |
|
654 | def __init__(self,color_scheme = 'Linux', call_pdb=False, ostream=None, | |
655 | tb_offset=0, long_header=False, include_vars=True, |
|
655 | tb_offset=0, long_header=False, include_vars=True, | |
656 | check_cache=None): |
|
656 | check_cache=None): | |
657 | """Specify traceback offset, headers and color scheme. |
|
657 | """Specify traceback offset, headers and color scheme. | |
658 |
|
658 | |||
659 | Define how many frames to drop from the tracebacks. Calling it with |
|
659 | Define how many frames to drop from the tracebacks. Calling it with | |
660 | tb_offset=1 allows use of this handler in interpreters which will have |
|
660 | tb_offset=1 allows use of this handler in interpreters which will have | |
661 | their own code at the top of the traceback (VerboseTB will first |
|
661 | their own code at the top of the traceback (VerboseTB will first | |
662 | remove that frame before printing the traceback info).""" |
|
662 | remove that frame before printing the traceback info).""" | |
663 | TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb, |
|
663 | TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb, | |
664 | ostream=ostream) |
|
664 | ostream=ostream) | |
665 | self.tb_offset = tb_offset |
|
665 | self.tb_offset = tb_offset | |
666 | self.long_header = long_header |
|
666 | self.long_header = long_header | |
667 | self.include_vars = include_vars |
|
667 | self.include_vars = include_vars | |
668 | # By default we use linecache.checkcache, but the user can provide a |
|
668 | # By default we use linecache.checkcache, but the user can provide a | |
669 | # different check_cache implementation. This is used by the IPython |
|
669 | # different check_cache implementation. This is used by the IPython | |
670 | # kernel to provide tracebacks for interactive code that is cached, |
|
670 | # kernel to provide tracebacks for interactive code that is cached, | |
671 | # by a compiler instance that flushes the linecache but preserves its |
|
671 | # by a compiler instance that flushes the linecache but preserves its | |
672 | # own code cache. |
|
672 | # own code cache. | |
673 | if check_cache is None: |
|
673 | if check_cache is None: | |
674 | check_cache = linecache.checkcache |
|
674 | check_cache = linecache.checkcache | |
675 | self.check_cache = check_cache |
|
675 | self.check_cache = check_cache | |
676 |
|
676 | |||
677 | def structured_traceback(self, etype, evalue, etb, tb_offset=None, |
|
677 | def structured_traceback(self, etype, evalue, etb, tb_offset=None, | |
678 | context=5): |
|
678 | context=5): | |
679 | """Return a nice text document describing the traceback.""" |
|
679 | """Return a nice text document describing the traceback.""" | |
680 |
|
680 | |||
681 | tb_offset = self.tb_offset if tb_offset is None else tb_offset |
|
681 | tb_offset = self.tb_offset if tb_offset is None else tb_offset | |
682 |
|
682 | |||
683 | # some locals |
|
683 | # some locals | |
684 | try: |
|
684 | try: | |
685 | etype = etype.__name__ |
|
685 | etype = etype.__name__ | |
686 | except AttributeError: |
|
686 | except AttributeError: | |
687 | pass |
|
687 | pass | |
688 | Colors = self.Colors # just a shorthand + quicker name lookup |
|
688 | Colors = self.Colors # just a shorthand + quicker name lookup | |
689 | ColorsNormal = Colors.Normal # used a lot |
|
689 | ColorsNormal = Colors.Normal # used a lot | |
690 | col_scheme = self.color_scheme_table.active_scheme_name |
|
690 | col_scheme = self.color_scheme_table.active_scheme_name | |
691 | indent = ' '*INDENT_SIZE |
|
691 | indent = ' '*INDENT_SIZE | |
692 | em_normal = '%s\n%s%s' % (Colors.valEm, indent,ColorsNormal) |
|
692 | em_normal = '%s\n%s%s' % (Colors.valEm, indent,ColorsNormal) | |
693 | undefined = '%sundefined%s' % (Colors.em, ColorsNormal) |
|
693 | undefined = '%sundefined%s' % (Colors.em, ColorsNormal) | |
694 | exc = '%s%s%s' % (Colors.excName,etype,ColorsNormal) |
|
694 | exc = '%s%s%s' % (Colors.excName,etype,ColorsNormal) | |
695 |
|
695 | |||
696 | # some internal-use functions |
|
696 | # some internal-use functions | |
697 | def text_repr(value): |
|
697 | def text_repr(value): | |
698 | """Hopefully pretty robust repr equivalent.""" |
|
698 | """Hopefully pretty robust repr equivalent.""" | |
699 | # this is pretty horrible but should always return *something* |
|
699 | # this is pretty horrible but should always return *something* | |
700 | try: |
|
700 | try: | |
701 | return pydoc.text.repr(value) |
|
701 | return pydoc.text.repr(value) | |
702 | except KeyboardInterrupt: |
|
702 | except KeyboardInterrupt: | |
703 | raise |
|
703 | raise | |
704 | except: |
|
704 | except: | |
705 | try: |
|
705 | try: | |
706 | return repr(value) |
|
706 | return repr(value) | |
707 | except KeyboardInterrupt: |
|
707 | except KeyboardInterrupt: | |
708 | raise |
|
708 | raise | |
709 | except: |
|
709 | except: | |
710 | try: |
|
710 | try: | |
711 | # all still in an except block so we catch |
|
711 | # all still in an except block so we catch | |
712 | # getattr raising |
|
712 | # getattr raising | |
713 | name = getattr(value, '__name__', None) |
|
713 | name = getattr(value, '__name__', None) | |
714 | if name: |
|
714 | if name: | |
715 | # ick, recursion |
|
715 | # ick, recursion | |
716 | return text_repr(name) |
|
716 | return text_repr(name) | |
717 | klass = getattr(value, '__class__', None) |
|
717 | klass = getattr(value, '__class__', None) | |
718 | if klass: |
|
718 | if klass: | |
719 | return '%s instance' % text_repr(klass) |
|
719 | return '%s instance' % text_repr(klass) | |
720 | except KeyboardInterrupt: |
|
720 | except KeyboardInterrupt: | |
721 | raise |
|
721 | raise | |
722 | except: |
|
722 | except: | |
723 | return 'UNRECOVERABLE REPR FAILURE' |
|
723 | return 'UNRECOVERABLE REPR FAILURE' | |
724 | def eqrepr(value, repr=text_repr): return '=%s' % repr(value) |
|
724 | def eqrepr(value, repr=text_repr): return '=%s' % repr(value) | |
725 | def nullrepr(value, repr=text_repr): return '' |
|
725 | def nullrepr(value, repr=text_repr): return '' | |
726 |
|
726 | |||
727 | # meat of the code begins |
|
727 | # meat of the code begins | |
728 | try: |
|
728 | try: | |
729 | etype = etype.__name__ |
|
729 | etype = etype.__name__ | |
730 | except AttributeError: |
|
730 | except AttributeError: | |
731 | pass |
|
731 | pass | |
732 |
|
732 | |||
733 | if self.long_header: |
|
733 | if self.long_header: | |
734 | # Header with the exception type, python version, and date |
|
734 | # Header with the exception type, python version, and date | |
735 | pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable |
|
735 | pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable | |
736 | date = time.ctime(time.time()) |
|
736 | date = time.ctime(time.time()) | |
737 |
|
737 | |||
738 | head = '%s%s%s\n%s%s%s\n%s' % (Colors.topline, '-'*75, ColorsNormal, |
|
738 | head = '%s%s%s\n%s%s%s\n%s' % (Colors.topline, '-'*75, ColorsNormal, | |
739 | exc, ' '*(75-len(str(etype))-len(pyver)), |
|
739 | exc, ' '*(75-len(str(etype))-len(pyver)), | |
740 | pyver, date.rjust(75) ) |
|
740 | pyver, date.rjust(75) ) | |
741 | head += "\nA problem occured executing Python code. Here is the sequence of function"\ |
|
741 | head += "\nA problem occured executing Python code. Here is the sequence of function"\ | |
742 | "\ncalls leading up to the error, with the most recent (innermost) call last." |
|
742 | "\ncalls leading up to the error, with the most recent (innermost) call last." | |
743 | else: |
|
743 | else: | |
744 | # Simplified header |
|
744 | # Simplified header | |
745 | head = '%s%s%s\n%s%s' % (Colors.topline, '-'*75, ColorsNormal,exc, |
|
745 | head = '%s%s%s\n%s%s' % (Colors.topline, '-'*75, ColorsNormal,exc, | |
746 | 'Traceback (most recent call last)'.\ |
|
746 | 'Traceback (most recent call last)'.\ | |
747 | rjust(75 - len(str(etype)) ) ) |
|
747 | rjust(75 - len(str(etype)) ) ) | |
748 | frames = [] |
|
748 | frames = [] | |
749 | # Flush cache before calling inspect. This helps alleviate some of the |
|
749 | # Flush cache before calling inspect. This helps alleviate some of the | |
750 | # problems with python 2.3's inspect.py. |
|
750 | # problems with python 2.3's inspect.py. | |
751 | ##self.check_cache() |
|
751 | ##self.check_cache() | |
752 | # Drop topmost frames if requested |
|
752 | # Drop topmost frames if requested | |
753 | try: |
|
753 | try: | |
754 | # Try the default getinnerframes and Alex's: Alex's fixes some |
|
754 | # Try the default getinnerframes and Alex's: Alex's fixes some | |
755 | # problems, but it generates empty tracebacks for console errors |
|
755 | # problems, but it generates empty tracebacks for console errors | |
756 | # (5 blanks lines) where none should be returned. |
|
756 | # (5 blanks lines) where none should be returned. | |
757 | #records = inspect.getinnerframes(etb, context)[tb_offset:] |
|
757 | #records = inspect.getinnerframes(etb, context)[tb_offset:] | |
758 | #print 'python records:', records # dbg |
|
758 | #print 'python records:', records # dbg | |
759 | records = _fixed_getinnerframes(etb, context, tb_offset) |
|
759 | records = _fixed_getinnerframes(etb, context, tb_offset) | |
760 | #print 'alex records:', records # dbg |
|
760 | #print 'alex records:', records # dbg | |
761 | except: |
|
761 | except: | |
762 |
|
762 | |||
763 | # FIXME: I've been getting many crash reports from python 2.3 |
|
763 | # FIXME: I've been getting many crash reports from python 2.3 | |
764 | # users, traceable to inspect.py. If I can find a small test-case |
|
764 | # users, traceable to inspect.py. If I can find a small test-case | |
765 | # to reproduce this, I should either write a better workaround or |
|
765 | # to reproduce this, I should either write a better workaround or | |
766 | # file a bug report against inspect (if that's the real problem). |
|
766 | # file a bug report against inspect (if that's the real problem). | |
767 | # So far, I haven't been able to find an isolated example to |
|
767 | # So far, I haven't been able to find an isolated example to | |
768 | # reproduce the problem. |
|
768 | # reproduce the problem. | |
769 | inspect_error() |
|
769 | inspect_error() | |
770 | traceback.print_exc(file=self.ostream) |
|
770 | traceback.print_exc(file=self.ostream) | |
771 | info('\nUnfortunately, your original traceback can not be constructed.\n') |
|
771 | info('\nUnfortunately, your original traceback can not be constructed.\n') | |
772 | return '' |
|
772 | return '' | |
773 |
|
773 | |||
774 | # build some color string templates outside these nested loops |
|
774 | # build some color string templates outside these nested loops | |
775 | tpl_link = '%s%%s%s' % (Colors.filenameEm,ColorsNormal) |
|
775 | tpl_link = '%s%%s%s' % (Colors.filenameEm,ColorsNormal) | |
776 | tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm, |
|
776 | tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm, | |
777 | ColorsNormal) |
|
777 | ColorsNormal) | |
778 | tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \ |
|
778 | tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \ | |
779 | (Colors.vName, Colors.valEm, ColorsNormal) |
|
779 | (Colors.vName, Colors.valEm, ColorsNormal) | |
780 | tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal) |
|
780 | tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal) | |
781 | tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal, |
|
781 | tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal, | |
782 | Colors.vName, ColorsNormal) |
|
782 | Colors.vName, ColorsNormal) | |
783 | tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal) |
|
783 | tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal) | |
784 | tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal) |
|
784 | tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal) | |
785 | tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm,Colors.line, |
|
785 | tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm,Colors.line, | |
786 | ColorsNormal) |
|
786 | ColorsNormal) | |
787 |
|
787 | |||
788 | # now, loop over all records printing context and info |
|
788 | # now, loop over all records printing context and info | |
789 | abspath = os.path.abspath |
|
789 | abspath = os.path.abspath | |
790 | for frame, file, lnum, func, lines, index in records: |
|
790 | for frame, file, lnum, func, lines, index in records: | |
791 | #print '*** record:',file,lnum,func,lines,index # dbg |
|
791 | #print '*** record:',file,lnum,func,lines,index # dbg | |
792 | if not file: |
|
792 | if not file: | |
793 | file = '?' |
|
793 | file = '?' | |
794 | elif not(file.startswith(str("<")) and file.endswith(str(">"))): |
|
794 | elif not(file.startswith(str("<")) and file.endswith(str(">"))): | |
795 | # Guess that filenames like <string> aren't real filenames, so |
|
795 | # Guess that filenames like <string> aren't real filenames, so | |
796 | # don't call abspath on them. |
|
796 | # don't call abspath on them. | |
797 | try: |
|
797 | try: | |
798 | file = abspath(file) |
|
798 | file = abspath(file) | |
799 | except OSError: |
|
799 | except OSError: | |
800 | # Not sure if this can still happen: abspath now works with |
|
800 | # Not sure if this can still happen: abspath now works with | |
801 | # file names like <string> |
|
801 | # file names like <string> | |
802 | pass |
|
802 | pass | |
803 | file = py3compat.cast_unicode(file, util_path.fs_encoding) |
|
803 | file = py3compat.cast_unicode(file, util_path.fs_encoding) | |
804 | link = tpl_link % file |
|
804 | link = tpl_link % file | |
805 | args, varargs, varkw, locals = inspect.getargvalues(frame) |
|
805 | args, varargs, varkw, locals = inspect.getargvalues(frame) | |
806 |
|
806 | |||
807 | if func == '?': |
|
807 | if func == '?': | |
808 | call = '' |
|
808 | call = '' | |
809 | else: |
|
809 | else: | |
810 | # Decide whether to include variable details or not |
|
810 | # Decide whether to include variable details or not | |
811 | var_repr = self.include_vars and eqrepr or nullrepr |
|
811 | var_repr = self.include_vars and eqrepr or nullrepr | |
812 | try: |
|
812 | try: | |
813 | call = tpl_call % (func,inspect.formatargvalues(args, |
|
813 | call = tpl_call % (func,inspect.formatargvalues(args, | |
814 | varargs, varkw, |
|
814 | varargs, varkw, | |
815 | locals,formatvalue=var_repr)) |
|
815 | locals,formatvalue=var_repr)) | |
816 | except KeyError: |
|
816 | except KeyError: | |
817 | # This happens in situations like errors inside generator |
|
817 | # This happens in situations like errors inside generator | |
818 | # expressions, where local variables are listed in the |
|
818 | # expressions, where local variables are listed in the | |
819 | # line, but can't be extracted from the frame. I'm not |
|
819 | # line, but can't be extracted from the frame. I'm not | |
820 | # 100% sure this isn't actually a bug in inspect itself, |
|
820 | # 100% sure this isn't actually a bug in inspect itself, | |
821 | # but since there's no info for us to compute with, the |
|
821 | # but since there's no info for us to compute with, the | |
822 | # best we can do is report the failure and move on. Here |
|
822 | # best we can do is report the failure and move on. Here | |
823 | # we must *not* call any traceback construction again, |
|
823 | # we must *not* call any traceback construction again, | |
824 | # because that would mess up use of %debug later on. So we |
|
824 | # because that would mess up use of %debug later on. So we | |
825 | # simply report the failure and move on. The only |
|
825 | # simply report the failure and move on. The only | |
826 | # limitation will be that this frame won't have locals |
|
826 | # limitation will be that this frame won't have locals | |
827 | # listed in the call signature. Quite subtle problem... |
|
827 | # listed in the call signature. Quite subtle problem... | |
828 | # I can't think of a good way to validate this in a unit |
|
828 | # I can't think of a good way to validate this in a unit | |
829 | # test, but running a script consisting of: |
|
829 | # test, but running a script consisting of: | |
830 | # dict( (k,v.strip()) for (k,v) in range(10) ) |
|
830 | # dict( (k,v.strip()) for (k,v) in range(10) ) | |
831 | # will illustrate the error, if this exception catch is |
|
831 | # will illustrate the error, if this exception catch is | |
832 | # disabled. |
|
832 | # disabled. | |
833 | call = tpl_call_fail % func |
|
833 | call = tpl_call_fail % func | |
834 |
|
834 | |||
835 | # Don't attempt to tokenize binary files. |
|
835 | # Don't attempt to tokenize binary files. | |
836 | if file.endswith(('.so', '.pyd', '.dll')): |
|
836 | if file.endswith(('.so', '.pyd', '.dll')): | |
837 | frames.append('%s %s\n' % (link,call)) |
|
837 | frames.append('%s %s\n' % (link,call)) | |
838 | continue |
|
838 | continue | |
839 | elif file.endswith(('.pyc','.pyo')): |
|
839 | elif file.endswith(('.pyc','.pyo')): | |
840 | # Look up the corresponding source file. |
|
840 | # Look up the corresponding source file. | |
841 | file = pyfile.source_from_cache(file) |
|
841 | file = pyfile.source_from_cache(file) | |
842 |
|
842 | |||
843 | def linereader(file=file, lnum=[lnum], getline=ulinecache.getline): |
|
843 | def linereader(file=file, lnum=[lnum], getline=ulinecache.getline): | |
844 | line = getline(file, lnum[0]) |
|
844 | line = getline(file, lnum[0]) | |
845 | lnum[0] += 1 |
|
845 | lnum[0] += 1 | |
846 | return line |
|
846 | return line | |
847 |
|
847 | |||
848 | # Build the list of names on this line of code where the exception |
|
848 | # Build the list of names on this line of code where the exception | |
849 | # occurred. |
|
849 | # occurred. | |
850 | try: |
|
850 | try: | |
851 | names = [] |
|
851 | names = [] | |
852 | name_cont = False |
|
852 | name_cont = False | |
853 |
|
853 | |||
854 | for token_type, token, start, end, line in generate_tokens(linereader): |
|
854 | for token_type, token, start, end, line in generate_tokens(linereader): | |
855 | # build composite names |
|
855 | # build composite names | |
856 | if token_type == tokenize.NAME and token not in keyword.kwlist: |
|
856 | if token_type == tokenize.NAME and token not in keyword.kwlist: | |
857 | if name_cont: |
|
857 | if name_cont: | |
858 | # Continuation of a dotted name |
|
858 | # Continuation of a dotted name | |
859 | try: |
|
859 | try: | |
860 | names[-1].append(token) |
|
860 | names[-1].append(token) | |
861 | except IndexError: |
|
861 | except IndexError: | |
862 | names.append([token]) |
|
862 | names.append([token]) | |
863 | name_cont = False |
|
863 | name_cont = False | |
864 | else: |
|
864 | else: | |
865 | # Regular new names. We append everything, the caller |
|
865 | # Regular new names. We append everything, the caller | |
866 | # will be responsible for pruning the list later. It's |
|
866 | # will be responsible for pruning the list later. It's | |
867 | # very tricky to try to prune as we go, b/c composite |
|
867 | # very tricky to try to prune as we go, b/c composite | |
868 | # names can fool us. The pruning at the end is easy |
|
868 | # names can fool us. The pruning at the end is easy | |
869 | # to do (or the caller can print a list with repeated |
|
869 | # to do (or the caller can print a list with repeated | |
870 | # names if so desired. |
|
870 | # names if so desired. | |
871 | names.append([token]) |
|
871 | names.append([token]) | |
872 | elif token == '.': |
|
872 | elif token == '.': | |
873 | name_cont = True |
|
873 | name_cont = True | |
874 | elif token_type == tokenize.NEWLINE: |
|
874 | elif token_type == tokenize.NEWLINE: | |
875 | break |
|
875 | break | |
876 |
|
876 | |||
877 | except (IndexError, UnicodeDecodeError): |
|
877 | except (IndexError, UnicodeDecodeError): | |
878 | # signals exit of tokenizer |
|
878 | # signals exit of tokenizer | |
879 | pass |
|
879 | pass | |
880 | except tokenize.TokenError as msg: |
|
880 | except tokenize.TokenError as msg: | |
881 | _m = ("An unexpected error occurred while tokenizing input\n" |
|
881 | _m = ("An unexpected error occurred while tokenizing input\n" | |
882 | "The following traceback may be corrupted or invalid\n" |
|
882 | "The following traceback may be corrupted or invalid\n" | |
883 | "The error message is: %s\n" % msg) |
|
883 | "The error message is: %s\n" % msg) | |
884 | error(_m) |
|
884 | error(_m) | |
885 |
|
885 | |||
886 | # Join composite names (e.g. "dict.fromkeys") |
|
886 | # Join composite names (e.g. "dict.fromkeys") | |
887 | names = ['.'.join(n) for n in names] |
|
887 | names = ['.'.join(n) for n in names] | |
888 | # prune names list of duplicates, but keep the right order |
|
888 | # prune names list of duplicates, but keep the right order | |
889 | unique_names = uniq_stable(names) |
|
889 | unique_names = uniq_stable(names) | |
890 |
|
890 | |||
891 | # Start loop over vars |
|
891 | # Start loop over vars | |
892 | lvals = [] |
|
892 | lvals = [] | |
893 | if self.include_vars: |
|
893 | if self.include_vars: | |
894 | for name_full in unique_names: |
|
894 | for name_full in unique_names: | |
895 | name_base = name_full.split('.',1)[0] |
|
895 | name_base = name_full.split('.',1)[0] | |
896 | if name_base in frame.f_code.co_varnames: |
|
896 | if name_base in frame.f_code.co_varnames: | |
897 | if name_base in locals: |
|
897 | if name_base in locals: | |
898 | try: |
|
898 | try: | |
899 | value = repr(eval(name_full,locals)) |
|
899 | value = repr(eval(name_full,locals)) | |
900 | except: |
|
900 | except: | |
901 | value = undefined |
|
901 | value = undefined | |
902 | else: |
|
902 | else: | |
903 | value = undefined |
|
903 | value = undefined | |
904 | name = tpl_local_var % name_full |
|
904 | name = tpl_local_var % name_full | |
905 | else: |
|
905 | else: | |
906 | if name_base in frame.f_globals: |
|
906 | if name_base in frame.f_globals: | |
907 | try: |
|
907 | try: | |
908 | value = repr(eval(name_full,frame.f_globals)) |
|
908 | value = repr(eval(name_full,frame.f_globals)) | |
909 | except: |
|
909 | except: | |
910 | value = undefined |
|
910 | value = undefined | |
911 | else: |
|
911 | else: | |
912 | value = undefined |
|
912 | value = undefined | |
913 | name = tpl_global_var % name_full |
|
913 | name = tpl_global_var % name_full | |
914 | lvals.append(tpl_name_val % (name,value)) |
|
914 | lvals.append(tpl_name_val % (name,value)) | |
915 | if lvals: |
|
915 | if lvals: | |
916 | lvals = '%s%s' % (indent,em_normal.join(lvals)) |
|
916 | lvals = '%s%s' % (indent,em_normal.join(lvals)) | |
917 | else: |
|
917 | else: | |
918 | lvals = '' |
|
918 | lvals = '' | |
919 |
|
919 | |||
920 | level = '%s %s\n' % (link,call) |
|
920 | level = '%s %s\n' % (link,call) | |
921 |
|
921 | |||
922 | if index is None: |
|
922 | if index is None: | |
923 | frames.append(level) |
|
923 | frames.append(level) | |
924 | else: |
|
924 | else: | |
925 | frames.append('%s%s' % (level,''.join( |
|
925 | frames.append('%s%s' % (level,''.join( | |
926 | _format_traceback_lines(lnum,index,lines,Colors,lvals, |
|
926 | _format_traceback_lines(lnum,index,lines,Colors,lvals, | |
927 | col_scheme)))) |
|
927 | col_scheme)))) | |
928 |
|
928 | |||
929 | # Get (safely) a string form of the exception info |
|
929 | # Get (safely) a string form of the exception info | |
930 | try: |
|
930 | try: | |
931 | etype_str,evalue_str = map(str,(etype,evalue)) |
|
931 | etype_str,evalue_str = map(str,(etype,evalue)) | |
932 | except: |
|
932 | except: | |
933 | # User exception is improperly defined. |
|
933 | # User exception is improperly defined. | |
934 | etype,evalue = str,sys.exc_info()[:2] |
|
934 | etype,evalue = str,sys.exc_info()[:2] | |
935 | etype_str,evalue_str = map(str,(etype,evalue)) |
|
935 | etype_str,evalue_str = map(str,(etype,evalue)) | |
936 | # ... and format it |
|
936 | # ... and format it | |
937 | exception = ['%s%s%s: %s' % (Colors.excName, etype_str, |
|
937 | exception = ['%s%s%s: %s' % (Colors.excName, etype_str, | |
938 | ColorsNormal, py3compat.cast_unicode(evalue_str))] |
|
938 | ColorsNormal, py3compat.cast_unicode(evalue_str))] | |
939 | if (not py3compat.PY3) and type(evalue) is types.InstanceType: |
|
939 | if (not py3compat.PY3) and type(evalue) is types.InstanceType: | |
940 | try: |
|
940 | try: | |
941 | names = [w for w in dir(evalue) if isinstance(w, basestring)] |
|
941 | names = [w for w in dir(evalue) if isinstance(w, basestring)] | |
942 | except: |
|
942 | except: | |
943 | # Every now and then, an object with funny inernals blows up |
|
943 | # Every now and then, an object with funny inernals blows up | |
944 | # when dir() is called on it. We do the best we can to report |
|
944 | # when dir() is called on it. We do the best we can to report | |
945 | # the problem and continue |
|
945 | # the problem and continue | |
946 | _m = '%sException reporting error (object with broken dir())%s:' |
|
946 | _m = '%sException reporting error (object with broken dir())%s:' | |
947 | exception.append(_m % (Colors.excName,ColorsNormal)) |
|
947 | exception.append(_m % (Colors.excName,ColorsNormal)) | |
948 | etype_str,evalue_str = map(str,sys.exc_info()[:2]) |
|
948 | etype_str,evalue_str = map(str,sys.exc_info()[:2]) | |
949 | exception.append('%s%s%s: %s' % (Colors.excName,etype_str, |
|
949 | exception.append('%s%s%s: %s' % (Colors.excName,etype_str, | |
950 | ColorsNormal, py3compat.cast_unicode(evalue_str))) |
|
950 | ColorsNormal, py3compat.cast_unicode(evalue_str))) | |
951 | names = [] |
|
951 | names = [] | |
952 | for name in names: |
|
952 | for name in names: | |
953 | value = text_repr(getattr(evalue, name)) |
|
953 | value = text_repr(getattr(evalue, name)) | |
954 | exception.append('\n%s%s = %s' % (indent, name, value)) |
|
954 | exception.append('\n%s%s = %s' % (indent, name, value)) | |
955 |
|
955 | |||
956 | # vds: >> |
|
956 | # vds: >> | |
957 | if records: |
|
957 | if records: | |
958 | filepath, lnum = records[-1][1:3] |
|
958 | filepath, lnum = records[-1][1:3] | |
959 | #print "file:", str(file), "linenb", str(lnum) # dbg |
|
959 | #print "file:", str(file), "linenb", str(lnum) # dbg | |
960 | filepath = os.path.abspath(filepath) |
|
960 | filepath = os.path.abspath(filepath) | |
961 | ipinst = ipapi.get() |
|
961 | ipinst = ipapi.get() | |
962 | if ipinst is not None: |
|
962 | if ipinst is not None: | |
963 | ipinst.hooks.synchronize_with_editor(filepath, lnum, 0) |
|
963 | ipinst.hooks.synchronize_with_editor(filepath, lnum, 0) | |
964 | # vds: << |
|
964 | # vds: << | |
965 |
|
965 | |||
966 | # return all our info assembled as a single string |
|
966 | # return all our info assembled as a single string | |
967 | # return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) ) |
|
967 | # return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) ) | |
968 | return [head] + frames + [''.join(exception[0])] |
|
968 | return [head] + frames + [''.join(exception[0])] | |
969 |
|
969 | |||
970 | def debugger(self,force=False): |
|
970 | def debugger(self,force=False): | |
971 | """Call up the pdb debugger if desired, always clean up the tb |
|
971 | """Call up the pdb debugger if desired, always clean up the tb | |
972 | reference. |
|
972 | reference. | |
973 |
|
973 | |||
974 | Keywords: |
|
974 | Keywords: | |
975 |
|
975 | |||
976 | - force(False): by default, this routine checks the instance call_pdb |
|
976 | - force(False): by default, this routine checks the instance call_pdb | |
977 | flag and does not actually invoke the debugger if the flag is false. |
|
977 | flag and does not actually invoke the debugger if the flag is false. | |
978 | The 'force' option forces the debugger to activate even if the flag |
|
978 | The 'force' option forces the debugger to activate even if the flag | |
979 | is false. |
|
979 | is false. | |
980 |
|
980 | |||
981 | If the call_pdb flag is set, the pdb interactive debugger is |
|
981 | If the call_pdb flag is set, the pdb interactive debugger is | |
982 | invoked. In all cases, the self.tb reference to the current traceback |
|
982 | invoked. In all cases, the self.tb reference to the current traceback | |
983 | is deleted to prevent lingering references which hamper memory |
|
983 | is deleted to prevent lingering references which hamper memory | |
984 | management. |
|
984 | management. | |
985 |
|
985 | |||
986 | Note that each call to pdb() does an 'import readline', so if your app |
|
986 | Note that each call to pdb() does an 'import readline', so if your app | |
987 | requires a special setup for the readline completers, you'll have to |
|
987 | requires a special setup for the readline completers, you'll have to | |
988 | fix that by hand after invoking the exception handler.""" |
|
988 | fix that by hand after invoking the exception handler.""" | |
989 |
|
989 | |||
990 | if force or self.call_pdb: |
|
990 | if force or self.call_pdb: | |
991 | if self.pdb is None: |
|
991 | if self.pdb is None: | |
992 | self.pdb = debugger.Pdb( |
|
992 | self.pdb = debugger.Pdb( | |
993 | self.color_scheme_table.active_scheme_name) |
|
993 | self.color_scheme_table.active_scheme_name) | |
994 | # the system displayhook may have changed, restore the original |
|
994 | # the system displayhook may have changed, restore the original | |
995 | # for pdb |
|
995 | # for pdb | |
996 | display_trap = DisplayTrap(hook=sys.__displayhook__) |
|
996 | display_trap = DisplayTrap(hook=sys.__displayhook__) | |
997 | with display_trap: |
|
997 | with display_trap: | |
998 | self.pdb.reset() |
|
998 | self.pdb.reset() | |
999 | # Find the right frame so we don't pop up inside ipython itself |
|
999 | # Find the right frame so we don't pop up inside ipython itself | |
1000 | if hasattr(self,'tb') and self.tb is not None: |
|
1000 | if hasattr(self,'tb') and self.tb is not None: | |
1001 | etb = self.tb |
|
1001 | etb = self.tb | |
1002 | else: |
|
1002 | else: | |
1003 | etb = self.tb = sys.last_traceback |
|
1003 | etb = self.tb = sys.last_traceback | |
1004 | while self.tb is not None and self.tb.tb_next is not None: |
|
1004 | while self.tb is not None and self.tb.tb_next is not None: | |
1005 | self.tb = self.tb.tb_next |
|
1005 | self.tb = self.tb.tb_next | |
1006 | if etb and etb.tb_next: |
|
1006 | if etb and etb.tb_next: | |
1007 | etb = etb.tb_next |
|
1007 | etb = etb.tb_next | |
1008 | self.pdb.botframe = etb.tb_frame |
|
1008 | self.pdb.botframe = etb.tb_frame | |
1009 | self.pdb.interaction(self.tb.tb_frame, self.tb) |
|
1009 | self.pdb.interaction(self.tb.tb_frame, self.tb) | |
1010 |
|
1010 | |||
1011 | if hasattr(self,'tb'): |
|
1011 | if hasattr(self,'tb'): | |
1012 | del self.tb |
|
1012 | del self.tb | |
1013 |
|
1013 | |||
1014 | def handler(self, info=None): |
|
1014 | def handler(self, info=None): | |
1015 | (etype, evalue, etb) = info or sys.exc_info() |
|
1015 | (etype, evalue, etb) = info or sys.exc_info() | |
1016 | self.tb = etb |
|
1016 | self.tb = etb | |
1017 | ostream = self.ostream |
|
1017 | ostream = self.ostream | |
1018 | ostream.flush() |
|
1018 | ostream.flush() | |
1019 | ostream.write(self.text(etype, evalue, etb)) |
|
1019 | ostream.write(self.text(etype, evalue, etb)) | |
1020 | ostream.write('\n') |
|
1020 | ostream.write('\n') | |
1021 | ostream.flush() |
|
1021 | ostream.flush() | |
1022 |
|
1022 | |||
1023 | # Changed so an instance can just be called as VerboseTB_inst() and print |
|
1023 | # Changed so an instance can just be called as VerboseTB_inst() and print | |
1024 | # out the right info on its own. |
|
1024 | # out the right info on its own. | |
1025 | def __call__(self, etype=None, evalue=None, etb=None): |
|
1025 | def __call__(self, etype=None, evalue=None, etb=None): | |
1026 | """This hook can replace sys.excepthook (for Python 2.1 or higher).""" |
|
1026 | """This hook can replace sys.excepthook (for Python 2.1 or higher).""" | |
1027 | if etb is None: |
|
1027 | if etb is None: | |
1028 | self.handler() |
|
1028 | self.handler() | |
1029 | else: |
|
1029 | else: | |
1030 | self.handler((etype, evalue, etb)) |
|
1030 | self.handler((etype, evalue, etb)) | |
1031 | try: |
|
1031 | try: | |
1032 | self.debugger() |
|
1032 | self.debugger() | |
1033 | except KeyboardInterrupt: |
|
1033 | except KeyboardInterrupt: | |
1034 | print "\nKeyboardInterrupt" |
|
1034 | print "\nKeyboardInterrupt" | |
1035 |
|
1035 | |||
1036 | #---------------------------------------------------------------------------- |
|
1036 | #---------------------------------------------------------------------------- | |
1037 | class FormattedTB(VerboseTB, ListTB): |
|
1037 | class FormattedTB(VerboseTB, ListTB): | |
1038 | """Subclass ListTB but allow calling with a traceback. |
|
1038 | """Subclass ListTB but allow calling with a traceback. | |
1039 |
|
1039 | |||
1040 | It can thus be used as a sys.excepthook for Python > 2.1. |
|
1040 | It can thus be used as a sys.excepthook for Python > 2.1. | |
1041 |
|
1041 | |||
1042 | Also adds 'Context' and 'Verbose' modes, not available in ListTB. |
|
1042 | Also adds 'Context' and 'Verbose' modes, not available in ListTB. | |
1043 |
|
1043 | |||
1044 | Allows a tb_offset to be specified. This is useful for situations where |
|
1044 | Allows a tb_offset to be specified. This is useful for situations where | |
1045 | one needs to remove a number of topmost frames from the traceback (such as |
|
1045 | one needs to remove a number of topmost frames from the traceback (such as | |
1046 | occurs with python programs that themselves execute other python code, |
|
1046 | occurs with python programs that themselves execute other python code, | |
1047 | like Python shells). """ |
|
1047 | like Python shells). """ | |
1048 |
|
1048 | |||
1049 | def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False, |
|
1049 | def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False, | |
1050 | ostream=None, |
|
1050 | ostream=None, | |
1051 | tb_offset=0, long_header=False, include_vars=False, |
|
1051 | tb_offset=0, long_header=False, include_vars=False, | |
1052 | check_cache=None): |
|
1052 | check_cache=None): | |
1053 |
|
1053 | |||
1054 | # NEVER change the order of this list. Put new modes at the end: |
|
1054 | # NEVER change the order of this list. Put new modes at the end: | |
1055 | self.valid_modes = ['Plain','Context','Verbose'] |
|
1055 | self.valid_modes = ['Plain','Context','Verbose'] | |
1056 | self.verbose_modes = self.valid_modes[1:3] |
|
1056 | self.verbose_modes = self.valid_modes[1:3] | |
1057 |
|
1057 | |||
1058 | VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb, |
|
1058 | VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb, | |
1059 | ostream=ostream, tb_offset=tb_offset, |
|
1059 | ostream=ostream, tb_offset=tb_offset, | |
1060 | long_header=long_header, include_vars=include_vars, |
|
1060 | long_header=long_header, include_vars=include_vars, | |
1061 | check_cache=check_cache) |
|
1061 | check_cache=check_cache) | |
1062 |
|
1062 | |||
1063 | # Different types of tracebacks are joined with different separators to |
|
1063 | # Different types of tracebacks are joined with different separators to | |
1064 | # form a single string. They are taken from this dict |
|
1064 | # form a single string. They are taken from this dict | |
1065 | self._join_chars = dict(Plain='', Context='\n', Verbose='\n') |
|
1065 | self._join_chars = dict(Plain='', Context='\n', Verbose='\n') | |
1066 | # set_mode also sets the tb_join_char attribute |
|
1066 | # set_mode also sets the tb_join_char attribute | |
1067 | self.set_mode(mode) |
|
1067 | self.set_mode(mode) | |
1068 |
|
1068 | |||
1069 | def _extract_tb(self,tb): |
|
1069 | def _extract_tb(self,tb): | |
1070 | if tb: |
|
1070 | if tb: | |
1071 | return traceback.extract_tb(tb) |
|
1071 | return traceback.extract_tb(tb) | |
1072 | else: |
|
1072 | else: | |
1073 | return None |
|
1073 | return None | |
1074 |
|
1074 | |||
1075 | def structured_traceback(self, etype, value, tb, tb_offset=None, context=5): |
|
1075 | def structured_traceback(self, etype, value, tb, tb_offset=None, context=5): | |
1076 | tb_offset = self.tb_offset if tb_offset is None else tb_offset |
|
1076 | tb_offset = self.tb_offset if tb_offset is None else tb_offset | |
1077 | mode = self.mode |
|
1077 | mode = self.mode | |
1078 | if mode in self.verbose_modes: |
|
1078 | if mode in self.verbose_modes: | |
1079 | # Verbose modes need a full traceback |
|
1079 | # Verbose modes need a full traceback | |
1080 | return VerboseTB.structured_traceback( |
|
1080 | return VerboseTB.structured_traceback( | |
1081 | self, etype, value, tb, tb_offset, context |
|
1081 | self, etype, value, tb, tb_offset, context | |
1082 | ) |
|
1082 | ) | |
1083 | else: |
|
1083 | else: | |
1084 | # We must check the source cache because otherwise we can print |
|
1084 | # We must check the source cache because otherwise we can print | |
1085 | # out-of-date source code. |
|
1085 | # out-of-date source code. | |
1086 | self.check_cache() |
|
1086 | self.check_cache() | |
1087 | # Now we can extract and format the exception |
|
1087 | # Now we can extract and format the exception | |
1088 | elist = self._extract_tb(tb) |
|
1088 | elist = self._extract_tb(tb) | |
1089 | return ListTB.structured_traceback( |
|
1089 | return ListTB.structured_traceback( | |
1090 | self, etype, value, elist, tb_offset, context |
|
1090 | self, etype, value, elist, tb_offset, context | |
1091 | ) |
|
1091 | ) | |
1092 |
|
1092 | |||
1093 | def stb2text(self, stb): |
|
1093 | def stb2text(self, stb): | |
1094 | """Convert a structured traceback (a list) to a string.""" |
|
1094 | """Convert a structured traceback (a list) to a string.""" | |
1095 | return self.tb_join_char.join(stb) |
|
1095 | return self.tb_join_char.join(stb) | |
1096 |
|
1096 | |||
1097 |
|
1097 | |||
1098 | def set_mode(self,mode=None): |
|
1098 | def set_mode(self,mode=None): | |
1099 | """Switch to the desired mode. |
|
1099 | """Switch to the desired mode. | |
1100 |
|
1100 | |||
1101 | If mode is not specified, cycles through the available modes.""" |
|
1101 | If mode is not specified, cycles through the available modes.""" | |
1102 |
|
1102 | |||
1103 | if not mode: |
|
1103 | if not mode: | |
1104 | new_idx = ( self.valid_modes.index(self.mode) + 1 ) % \ |
|
1104 | new_idx = ( self.valid_modes.index(self.mode) + 1 ) % \ | |
1105 | len(self.valid_modes) |
|
1105 | len(self.valid_modes) | |
1106 | self.mode = self.valid_modes[new_idx] |
|
1106 | self.mode = self.valid_modes[new_idx] | |
1107 | elif mode not in self.valid_modes: |
|
1107 | elif mode not in self.valid_modes: | |
1108 | raise ValueError('Unrecognized mode in FormattedTB: <'+mode+'>\n' |
|
1108 | raise ValueError('Unrecognized mode in FormattedTB: <'+mode+'>\n' | |
1109 | 'Valid modes: '+str(self.valid_modes)) |
|
1109 | 'Valid modes: '+str(self.valid_modes)) | |
1110 | else: |
|
1110 | else: | |
1111 | self.mode = mode |
|
1111 | self.mode = mode | |
1112 | # include variable details only in 'Verbose' mode |
|
1112 | # include variable details only in 'Verbose' mode | |
1113 | self.include_vars = (self.mode == self.valid_modes[2]) |
|
1113 | self.include_vars = (self.mode == self.valid_modes[2]) | |
1114 | # Set the join character for generating text tracebacks |
|
1114 | # Set the join character for generating text tracebacks | |
1115 | self.tb_join_char = self._join_chars[self.mode] |
|
1115 | self.tb_join_char = self._join_chars[self.mode] | |
1116 |
|
1116 | |||
1117 | # some convenient shorcuts |
|
1117 | # some convenient shorcuts | |
1118 | def plain(self): |
|
1118 | def plain(self): | |
1119 | self.set_mode(self.valid_modes[0]) |
|
1119 | self.set_mode(self.valid_modes[0]) | |
1120 |
|
1120 | |||
1121 | def context(self): |
|
1121 | def context(self): | |
1122 | self.set_mode(self.valid_modes[1]) |
|
1122 | self.set_mode(self.valid_modes[1]) | |
1123 |
|
1123 | |||
1124 | def verbose(self): |
|
1124 | def verbose(self): | |
1125 | self.set_mode(self.valid_modes[2]) |
|
1125 | self.set_mode(self.valid_modes[2]) | |
1126 |
|
1126 | |||
1127 | #---------------------------------------------------------------------------- |
|
1127 | #---------------------------------------------------------------------------- | |
1128 | class AutoFormattedTB(FormattedTB): |
|
1128 | class AutoFormattedTB(FormattedTB): | |
1129 | """A traceback printer which can be called on the fly. |
|
1129 | """A traceback printer which can be called on the fly. | |
1130 |
|
1130 | |||
1131 | It will find out about exceptions by itself. |
|
1131 | It will find out about exceptions by itself. | |
1132 |
|
1132 | |||
1133 | A brief example: |
|
1133 | A brief example:: | |
1134 |
|
1134 | |||
1135 | AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux') |
|
1135 | AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux') | |
1136 | try: |
|
1136 | try: | |
1137 | ... |
|
1137 | ... | |
1138 | except: |
|
1138 | except: | |
1139 | AutoTB() # or AutoTB(out=logfile) where logfile is an open file object |
|
1139 | AutoTB() # or AutoTB(out=logfile) where logfile is an open file object | |
1140 | """ |
|
1140 | """ | |
1141 |
|
1141 | |||
1142 | def __call__(self,etype=None,evalue=None,etb=None, |
|
1142 | def __call__(self,etype=None,evalue=None,etb=None, | |
1143 | out=None,tb_offset=None): |
|
1143 | out=None,tb_offset=None): | |
1144 | """Print out a formatted exception traceback. |
|
1144 | """Print out a formatted exception traceback. | |
1145 |
|
1145 | |||
1146 | Optional arguments: |
|
1146 | Optional arguments: | |
1147 | - out: an open file-like object to direct output to. |
|
1147 | - out: an open file-like object to direct output to. | |
1148 |
|
1148 | |||
1149 | - tb_offset: the number of frames to skip over in the stack, on a |
|
1149 | - tb_offset: the number of frames to skip over in the stack, on a | |
1150 | per-call basis (this overrides temporarily the instance's tb_offset |
|
1150 | per-call basis (this overrides temporarily the instance's tb_offset | |
1151 | given at initialization time. """ |
|
1151 | given at initialization time. """ | |
1152 |
|
1152 | |||
1153 |
|
1153 | |||
1154 | if out is None: |
|
1154 | if out is None: | |
1155 | out = self.ostream |
|
1155 | out = self.ostream | |
1156 | out.flush() |
|
1156 | out.flush() | |
1157 | out.write(self.text(etype, evalue, etb, tb_offset)) |
|
1157 | out.write(self.text(etype, evalue, etb, tb_offset)) | |
1158 | out.write('\n') |
|
1158 | out.write('\n') | |
1159 | out.flush() |
|
1159 | out.flush() | |
1160 | # FIXME: we should remove the auto pdb behavior from here and leave |
|
1160 | # FIXME: we should remove the auto pdb behavior from here and leave | |
1161 | # that to the clients. |
|
1161 | # that to the clients. | |
1162 | try: |
|
1162 | try: | |
1163 | self.debugger() |
|
1163 | self.debugger() | |
1164 | except KeyboardInterrupt: |
|
1164 | except KeyboardInterrupt: | |
1165 | print "\nKeyboardInterrupt" |
|
1165 | print "\nKeyboardInterrupt" | |
1166 |
|
1166 | |||
1167 | def structured_traceback(self, etype=None, value=None, tb=None, |
|
1167 | def structured_traceback(self, etype=None, value=None, tb=None, | |
1168 | tb_offset=None, context=5): |
|
1168 | tb_offset=None, context=5): | |
1169 | if etype is None: |
|
1169 | if etype is None: | |
1170 | etype,value,tb = sys.exc_info() |
|
1170 | etype,value,tb = sys.exc_info() | |
1171 | self.tb = tb |
|
1171 | self.tb = tb | |
1172 | return FormattedTB.structured_traceback( |
|
1172 | return FormattedTB.structured_traceback( | |
1173 | self, etype, value, tb, tb_offset, context) |
|
1173 | self, etype, value, tb, tb_offset, context) | |
1174 |
|
1174 | |||
1175 | #--------------------------------------------------------------------------- |
|
1175 | #--------------------------------------------------------------------------- | |
1176 |
|
1176 | |||
1177 | # A simple class to preserve Nathan's original functionality. |
|
1177 | # A simple class to preserve Nathan's original functionality. | |
1178 | class ColorTB(FormattedTB): |
|
1178 | class ColorTB(FormattedTB): | |
1179 | """Shorthand to initialize a FormattedTB in Linux colors mode.""" |
|
1179 | """Shorthand to initialize a FormattedTB in Linux colors mode.""" | |
1180 | def __init__(self,color_scheme='Linux',call_pdb=0): |
|
1180 | def __init__(self,color_scheme='Linux',call_pdb=0): | |
1181 | FormattedTB.__init__(self,color_scheme=color_scheme, |
|
1181 | FormattedTB.__init__(self,color_scheme=color_scheme, | |
1182 | call_pdb=call_pdb) |
|
1182 | call_pdb=call_pdb) | |
1183 |
|
1183 | |||
1184 |
|
1184 | |||
1185 | class SyntaxTB(ListTB): |
|
1185 | class SyntaxTB(ListTB): | |
1186 | """Extension which holds some state: the last exception value""" |
|
1186 | """Extension which holds some state: the last exception value""" | |
1187 |
|
1187 | |||
1188 | def __init__(self,color_scheme = 'NoColor'): |
|
1188 | def __init__(self,color_scheme = 'NoColor'): | |
1189 | ListTB.__init__(self,color_scheme) |
|
1189 | ListTB.__init__(self,color_scheme) | |
1190 | self.last_syntax_error = None |
|
1190 | self.last_syntax_error = None | |
1191 |
|
1191 | |||
1192 | def __call__(self, etype, value, elist): |
|
1192 | def __call__(self, etype, value, elist): | |
1193 | self.last_syntax_error = value |
|
1193 | self.last_syntax_error = value | |
1194 | ListTB.__call__(self,etype,value,elist) |
|
1194 | ListTB.__call__(self,etype,value,elist) | |
1195 |
|
1195 | |||
1196 | def clear_err_state(self): |
|
1196 | def clear_err_state(self): | |
1197 | """Return the current error state and clear it""" |
|
1197 | """Return the current error state and clear it""" | |
1198 | e = self.last_syntax_error |
|
1198 | e = self.last_syntax_error | |
1199 | self.last_syntax_error = None |
|
1199 | self.last_syntax_error = None | |
1200 | return e |
|
1200 | return e | |
1201 |
|
1201 | |||
1202 | def stb2text(self, stb): |
|
1202 | def stb2text(self, stb): | |
1203 | """Convert a structured traceback (a list) to a string.""" |
|
1203 | """Convert a structured traceback (a list) to a string.""" | |
1204 | return ''.join(stb) |
|
1204 | return ''.join(stb) | |
1205 |
|
1205 | |||
1206 |
|
1206 | |||
1207 | #---------------------------------------------------------------------------- |
|
1207 | #---------------------------------------------------------------------------- | |
1208 | # module testing (minimal) |
|
1208 | # module testing (minimal) | |
1209 | if __name__ == "__main__": |
|
1209 | if __name__ == "__main__": | |
1210 | def spam(c, d_e): |
|
1210 | def spam(c, d_e): | |
1211 | (d, e) = d_e |
|
1211 | (d, e) = d_e | |
1212 | x = c + d |
|
1212 | x = c + d | |
1213 | y = c * d |
|
1213 | y = c * d | |
1214 | foo(x, y) |
|
1214 | foo(x, y) | |
1215 |
|
1215 | |||
1216 | def foo(a, b, bar=1): |
|
1216 | def foo(a, b, bar=1): | |
1217 | eggs(a, b + bar) |
|
1217 | eggs(a, b + bar) | |
1218 |
|
1218 | |||
1219 | def eggs(f, g, z=globals()): |
|
1219 | def eggs(f, g, z=globals()): | |
1220 | h = f + g |
|
1220 | h = f + g | |
1221 | i = f - g |
|
1221 | i = f - g | |
1222 | return h / i |
|
1222 | return h / i | |
1223 |
|
1223 | |||
1224 | print '' |
|
1224 | print '' | |
1225 | print '*** Before ***' |
|
1225 | print '*** Before ***' | |
1226 | try: |
|
1226 | try: | |
1227 | print spam(1, (2, 3)) |
|
1227 | print spam(1, (2, 3)) | |
1228 | except: |
|
1228 | except: | |
1229 | traceback.print_exc() |
|
1229 | traceback.print_exc() | |
1230 | print '' |
|
1230 | print '' | |
1231 |
|
1231 | |||
1232 | handler = ColorTB() |
|
1232 | handler = ColorTB() | |
1233 | print '*** ColorTB ***' |
|
1233 | print '*** ColorTB ***' | |
1234 | try: |
|
1234 | try: | |
1235 | print spam(1, (2, 3)) |
|
1235 | print spam(1, (2, 3)) | |
1236 | except: |
|
1236 | except: | |
1237 | handler(*sys.exc_info()) |
|
1237 | handler(*sys.exc_info()) | |
1238 | print '' |
|
1238 | print '' | |
1239 |
|
1239 | |||
1240 | handler = VerboseTB() |
|
1240 | handler = VerboseTB() | |
1241 | print '*** VerboseTB ***' |
|
1241 | print '*** VerboseTB ***' | |
1242 | try: |
|
1242 | try: | |
1243 | print spam(1, (2, 3)) |
|
1243 | print spam(1, (2, 3)) | |
1244 | except: |
|
1244 | except: | |
1245 | handler(*sys.exc_info()) |
|
1245 | handler(*sys.exc_info()) | |
1246 | print '' |
|
1246 | print '' | |
1247 |
|
1247 |
@@ -1,287 +1,291 b'' | |||||
1 | """Various display related classes. |
|
1 | """Various display related classes. | |
2 |
|
2 | |||
3 | Authors : MinRK, gregcaporaso, dannystaple |
|
3 | Authors : MinRK, gregcaporaso, dannystaple | |
4 | """ |
|
4 | """ | |
5 | import urllib |
|
5 | import urllib | |
6 |
|
6 | |||
7 | from os.path import exists, isfile, splitext, abspath, join, isdir |
|
7 | from os.path import exists, isfile, splitext, abspath, join, isdir | |
8 | from os import walk |
|
8 | from os import walk | |
9 |
|
9 | |||
10 |
|
10 | |||
11 | class YouTubeVideo(object): |
|
11 | class YouTubeVideo(object): | |
12 | """Class for embedding a YouTube Video in an IPython session, based on its video id. |
|
12 | """Class for embedding a YouTube Video in an IPython session, based on its video id. | |
13 |
|
13 | |||
14 | e.g. to embed the video on this page: |
|
14 | e.g. to embed the video on this page: | |
15 |
|
15 | |||
16 | http://www.youtube.com/watch?v=foo |
|
16 | http://www.youtube.com/watch?v=foo | |
17 |
|
17 | |||
18 | you would do: |
|
18 | you would do: | |
19 |
|
19 | |||
20 | vid = YouTubeVideo("foo") |
|
20 | vid = YouTubeVideo("foo") | |
21 | display(vid) |
|
21 | display(vid) | |
22 |
|
22 | |||
23 | To start from 30 seconds: |
|
23 | To start from 30 seconds: | |
24 |
|
24 | |||
25 | vid = YouTubeVideo("abc", start=30) |
|
25 | vid = YouTubeVideo("abc", start=30) | |
26 | display(vid) |
|
26 | display(vid) | |
27 |
|
27 | |||
28 | To calculate seconds from time as hours, minutes, seconds use: |
|
28 | To calculate seconds from time as hours, minutes, seconds use: | |
29 | start=int(timedelta(hours=1, minutes=46, seconds=40).total_seconds()) |
|
29 | start=int(timedelta(hours=1, minutes=46, seconds=40).total_seconds()) | |
30 |
|
30 | |||
31 | Other parameters can be provided as documented at |
|
31 | Other parameters can be provided as documented at | |
32 | https://developers.google.com/youtube/player_parameters#parameter-subheader |
|
32 | https://developers.google.com/youtube/player_parameters#parameter-subheader | |
33 | """ |
|
33 | """ | |
34 |
|
34 | |||
35 | def __init__(self, id, width=400, height=300, **kwargs): |
|
35 | def __init__(self, id, width=400, height=300, **kwargs): | |
36 | self.id = id |
|
36 | self.id = id | |
37 | self.width = width |
|
37 | self.width = width | |
38 | self.height = height |
|
38 | self.height = height | |
39 | self.params = kwargs |
|
39 | self.params = kwargs | |
40 |
|
40 | |||
41 | def _repr_html_(self): |
|
41 | def _repr_html_(self): | |
42 | """return YouTube embed iframe for this video id""" |
|
42 | """return YouTube embed iframe for this video id""" | |
43 | if self.params: |
|
43 | if self.params: | |
44 | params = "?" + urllib.urlencode(self.params) |
|
44 | params = "?" + urllib.urlencode(self.params) | |
45 | else: |
|
45 | else: | |
46 | params = "" |
|
46 | params = "" | |
47 | return """ |
|
47 | return """ | |
48 | <iframe |
|
48 | <iframe | |
49 | width="%i" |
|
49 | width="%i" | |
50 | height="%i" |
|
50 | height="%i" | |
51 | src="http://www.youtube.com/embed/%s%s" |
|
51 | src="http://www.youtube.com/embed/%s%s" | |
52 | frameborder="0" |
|
52 | frameborder="0" | |
53 | allowfullscreen |
|
53 | allowfullscreen | |
54 | ></iframe> |
|
54 | ></iframe> | |
55 | """ % (self.width, self.height, self.id, params) |
|
55 | """ % (self.width, self.height, self.id, params) | |
56 |
|
56 | |||
57 | class FileLink(object): |
|
57 | class FileLink(object): | |
58 | """Class for embedding a local file link in an IPython session, based on path |
|
58 | """Class for embedding a local file link in an IPython session, based on path | |
59 |
|
59 | |||
60 | e.g. to embed a link that was generated in the IPython notebook as my/data.txt |
|
60 | e.g. to embed a link that was generated in the IPython notebook as my/data.txt | |
61 |
|
61 | |||
62 | you would do: |
|
62 | you would do:: | |
63 |
|
63 | |||
64 | local_file = FileLink("my/data.txt") |
|
64 | local_file = FileLink("my/data.txt") | |
65 | display(local_file) |
|
65 | display(local_file) | |
66 |
|
66 | |||
67 | or in the HTML notebook, just |
|
67 | or in the HTML notebook, just:: | |
68 |
|
68 | |||
69 | FileLink("my/data.txt") |
|
69 | FileLink("my/data.txt") | |
70 | """ |
|
70 | """ | |
71 |
|
71 | |||
72 | html_link_str = "<a href='%s' target='_blank'>%s</a>" |
|
72 | html_link_str = "<a href='%s' target='_blank'>%s</a>" | |
73 |
|
73 | |||
74 | def __init__(self, |
|
74 | def __init__(self, | |
75 | path, |
|
75 | path, | |
76 | url_prefix='files/', |
|
76 | url_prefix='files/', | |
77 | result_html_prefix='', |
|
77 | result_html_prefix='', | |
78 | result_html_suffix='<br>'): |
|
78 | result_html_suffix='<br>'): | |
79 | """ |
|
79 | """ | |
80 | path : path to the file or directory that should be formatted |
|
80 | Parameters | |
81 | directory_prefix : prefix to be prepended to all files to form a |
|
81 | ---------- | |
82 | working link [default: 'files'] |
|
82 | path : str | |
83 | result_html_prefix : text to append to beginning to link |
|
83 | path to the file or directory that should be formatted | |
84 | [default: none] |
|
84 | directory_prefix : str | |
85 | result_html_suffix : text to append at the end of link |
|
85 | prefix to be prepended to all files to form a working link [default: | |
86 |
|
|
86 | 'files'] | |
|
87 | result_html_prefix : str | |||
|
88 | text to append to beginning to link [default: none] | |||
|
89 | result_html_suffix : str | |||
|
90 | text to append at the end of link [default: '<br>'] | |||
87 | """ |
|
91 | """ | |
88 | if isdir(path): |
|
92 | if isdir(path): | |
89 | raise ValueError,\ |
|
93 | raise ValueError,\ | |
90 | ("Cannot display a directory using FileLink. " |
|
94 | ("Cannot display a directory using FileLink. " | |
91 | "Use FileLinks to display '%s'." % path) |
|
95 | "Use FileLinks to display '%s'." % path) | |
92 | self.path = path |
|
96 | self.path = path | |
93 | self.url_prefix = url_prefix |
|
97 | self.url_prefix = url_prefix | |
94 | self.result_html_prefix = result_html_prefix |
|
98 | self.result_html_prefix = result_html_prefix | |
95 | self.result_html_suffix = result_html_suffix |
|
99 | self.result_html_suffix = result_html_suffix | |
96 |
|
100 | |||
97 | def _format_path(self): |
|
101 | def _format_path(self): | |
98 | fp = ''.join([self.url_prefix,self.path]) |
|
102 | fp = ''.join([self.url_prefix,self.path]) | |
99 | return ''.join([self.result_html_prefix, |
|
103 | return ''.join([self.result_html_prefix, | |
100 | self.html_link_str % (fp, self.path), |
|
104 | self.html_link_str % (fp, self.path), | |
101 | self.result_html_suffix]) |
|
105 | self.result_html_suffix]) | |
102 |
|
106 | |||
103 | def _repr_html_(self): |
|
107 | def _repr_html_(self): | |
104 | """return html link to file |
|
108 | """return html link to file | |
105 | """ |
|
109 | """ | |
106 | if not exists(self.path): |
|
110 | if not exists(self.path): | |
107 | return ("Path (<tt>%s</tt>) doesn't exist. " |
|
111 | return ("Path (<tt>%s</tt>) doesn't exist. " | |
108 | "It may still be in the process of " |
|
112 | "It may still be in the process of " | |
109 | "being generated, or you may have the " |
|
113 | "being generated, or you may have the " | |
110 | "incorrect path." % self.path) |
|
114 | "incorrect path." % self.path) | |
111 |
|
115 | |||
112 | return self._format_path() |
|
116 | return self._format_path() | |
113 |
|
117 | |||
114 | def __repr__(self): |
|
118 | def __repr__(self): | |
115 | """return absolute path to file |
|
119 | """return absolute path to file | |
116 | """ |
|
120 | """ | |
117 | return abspath(self.path) |
|
121 | return abspath(self.path) | |
118 |
|
122 | |||
119 | class FileLinks(FileLink): |
|
123 | class FileLinks(FileLink): | |
120 | """Class for embedding local file links in an IPython session, based on path |
|
124 | """Class for embedding local file links in an IPython session, based on path | |
121 |
|
125 | |||
122 | e.g. to embed links to files that were generated in the IPython notebook under my/data |
|
126 | e.g. to embed links to files that were generated in the IPython notebook under my/data | |
123 |
|
127 | |||
124 | you would do: |
|
128 | you would do: | |
125 |
|
129 | |||
126 | local_files = FileLinks("my/data") |
|
130 | local_files = FileLinks("my/data") | |
127 | display(local_files) |
|
131 | display(local_files) | |
128 |
|
132 | |||
129 | or in the HTML notebook, just |
|
133 | or in the HTML notebook, just | |
130 |
|
134 | |||
131 | FileLinks("my/data") |
|
135 | FileLinks("my/data") | |
132 |
|
136 | |||
133 | """ |
|
137 | """ | |
134 | def __init__(self, |
|
138 | def __init__(self, | |
135 | path, |
|
139 | path, | |
136 | url_prefix='files/', |
|
140 | url_prefix='files/', | |
137 | included_suffixes=None, |
|
141 | included_suffixes=None, | |
138 | result_html_prefix='', |
|
142 | result_html_prefix='', | |
139 | result_html_suffix='<br>', |
|
143 | result_html_suffix='<br>', | |
140 | notebook_display_formatter=None, |
|
144 | notebook_display_formatter=None, | |
141 | terminal_display_formatter=None): |
|
145 | terminal_display_formatter=None): | |
142 | """ |
|
146 | """ | |
143 | included_suffixes : list of filename suffixes to include when |
|
147 | included_suffixes : list of filename suffixes to include when | |
144 | formatting output [default: include all files] |
|
148 | formatting output [default: include all files] | |
145 |
|
149 | |||
146 | See the FileLink (baseclass of LocalDirectory) docstring for |
|
150 | See the FileLink (baseclass of LocalDirectory) docstring for | |
147 | information on additional parameters. |
|
151 | information on additional parameters. | |
148 |
|
152 | |||
149 | notebook_display_formatter : func used to format links for display |
|
153 | notebook_display_formatter : func used to format links for display | |
150 | in the notebook. See discussion of formatter function below. |
|
154 | in the notebook. See discussion of formatter function below. | |
151 |
|
155 | |||
152 | terminal_display_formatter : func used to format links for display |
|
156 | terminal_display_formatter : func used to format links for display | |
153 | in the terminal. See discussion of formatter function below. |
|
157 | in the terminal. See discussion of formatter function below. | |
154 |
|
158 | |||
155 |
|
159 | |||
156 | Passing custom formatter functions |
|
160 | Passing custom formatter functions | |
157 | ---------------------------------- |
|
161 | ---------------------------------- | |
158 | Formatter functions must be of the form: |
|
162 | Formatter functions must be of the form: | |
159 | f(dirname, fnames, included_suffixes) |
|
163 | f(dirname, fnames, included_suffixes) | |
160 | dirname : the name of a directory (a string), |
|
164 | dirname : the name of a directory (a string), | |
161 | fnames : a list of the files in that directory |
|
165 | fnames : a list of the files in that directory | |
162 | included_suffixes : a list of the file suffixes that should be |
|
166 | included_suffixes : a list of the file suffixes that should be | |
163 | included in the output (passing None means |
|
167 | included in the output (passing None means | |
164 | to include all suffixes in the output in |
|
168 | to include all suffixes in the output in | |
165 | the built-in formatters) |
|
169 | the built-in formatters) | |
166 |
|
170 | |||
167 | returns a list of lines that should will be print in the |
|
171 | returns a list of lines that should will be print in the | |
168 | notebook (if passing notebook_display_formatter) or the terminal |
|
172 | notebook (if passing notebook_display_formatter) or the terminal | |
169 | (if passing terminal_display_formatter). This function is iterated |
|
173 | (if passing terminal_display_formatter). This function is iterated | |
170 | over for each directory in self.path. Default formatters are in |
|
174 | over for each directory in self.path. Default formatters are in | |
171 | place, can be passed here to support alternative formatting. |
|
175 | place, can be passed here to support alternative formatting. | |
172 |
|
176 | |||
173 | """ |
|
177 | """ | |
174 | if isfile(path): |
|
178 | if isfile(path): | |
175 | raise ValueError,\ |
|
179 | raise ValueError,\ | |
176 | ("Cannot display a file using FileLinks. " |
|
180 | ("Cannot display a file using FileLinks. " | |
177 | "Use FileLink to display '%s'." % path) |
|
181 | "Use FileLink to display '%s'." % path) | |
178 | self.included_suffixes = included_suffixes |
|
182 | self.included_suffixes = included_suffixes | |
179 | # remove trailing slashs for more consistent output formatting |
|
183 | # remove trailing slashs for more consistent output formatting | |
180 | path = path.rstrip('/') |
|
184 | path = path.rstrip('/') | |
181 |
|
185 | |||
182 | self.path = path |
|
186 | self.path = path | |
183 | self.url_prefix = url_prefix |
|
187 | self.url_prefix = url_prefix | |
184 | self.result_html_prefix = result_html_prefix |
|
188 | self.result_html_prefix = result_html_prefix | |
185 | self.result_html_suffix = result_html_suffix |
|
189 | self.result_html_suffix = result_html_suffix | |
186 |
|
190 | |||
187 | self.notebook_display_formatter = \ |
|
191 | self.notebook_display_formatter = \ | |
188 | notebook_display_formatter or self._get_notebook_display_formatter() |
|
192 | notebook_display_formatter or self._get_notebook_display_formatter() | |
189 | self.terminal_display_formatter = \ |
|
193 | self.terminal_display_formatter = \ | |
190 | terminal_display_formatter or self._get_terminal_display_formatter() |
|
194 | terminal_display_formatter or self._get_terminal_display_formatter() | |
191 |
|
195 | |||
192 | def _get_display_formatter(self, |
|
196 | def _get_display_formatter(self, | |
193 | dirname_output_format, |
|
197 | dirname_output_format, | |
194 | fname_output_format, |
|
198 | fname_output_format, | |
195 | fp_format): |
|
199 | fp_format): | |
196 | """ generate built-in formatter function |
|
200 | """ generate built-in formatter function | |
197 |
|
201 | |||
198 | this is used to define both the notebook and terminal built-in |
|
202 | this is used to define both the notebook and terminal built-in | |
199 | formatters as they only differ by some wrapper text for each entry |
|
203 | formatters as they only differ by some wrapper text for each entry | |
200 |
|
204 | |||
201 | dirname_output_format: string to use for formatting directory |
|
205 | dirname_output_format: string to use for formatting directory | |
202 | names, dirname will be substituted for a single "%s" which |
|
206 | names, dirname will be substituted for a single "%s" which | |
203 | must appear in this string |
|
207 | must appear in this string | |
204 | fname_output_format: string to use for formatting file names, |
|
208 | fname_output_format: string to use for formatting file names, | |
205 | if a single "%s" appears in the string, fname will be substituted |
|
209 | if a single "%s" appears in the string, fname will be substituted | |
206 | if two "%s" appear in the string, the path to fname will be |
|
210 | if two "%s" appear in the string, the path to fname will be | |
207 | substituted for the first and fname will be substituted for the |
|
211 | substituted for the first and fname will be substituted for the | |
208 | second |
|
212 | second | |
209 | fp_format: string to use for formatting filepaths, must contain |
|
213 | fp_format: string to use for formatting filepaths, must contain | |
210 | exactly two "%s" and the dirname will be subsituted for the first |
|
214 | exactly two "%s" and the dirname will be subsituted for the first | |
211 | and fname will be substituted for the second |
|
215 | and fname will be substituted for the second | |
212 | """ |
|
216 | """ | |
213 | def f(dirname, fnames, included_suffixes=None): |
|
217 | def f(dirname, fnames, included_suffixes=None): | |
214 | result = [] |
|
218 | result = [] | |
215 | # begin by figuring out which filenames, if any, |
|
219 | # begin by figuring out which filenames, if any, | |
216 | # are going to be displayed |
|
220 | # are going to be displayed | |
217 | display_fnames = [] |
|
221 | display_fnames = [] | |
218 | for fname in fnames: |
|
222 | for fname in fnames: | |
219 | if (isfile(join(dirname,fname)) and |
|
223 | if (isfile(join(dirname,fname)) and | |
220 | (included_suffixes == None or |
|
224 | (included_suffixes == None or | |
221 | splitext(fname)[1] in included_suffixes)): |
|
225 | splitext(fname)[1] in included_suffixes)): | |
222 | display_fnames.append(fname) |
|
226 | display_fnames.append(fname) | |
223 |
|
227 | |||
224 | if len(display_fnames) == 0: |
|
228 | if len(display_fnames) == 0: | |
225 | # if there are no filenames to display, don't print anything |
|
229 | # if there are no filenames to display, don't print anything | |
226 | # (not even the directory name) |
|
230 | # (not even the directory name) | |
227 | pass |
|
231 | pass | |
228 | else: |
|
232 | else: | |
229 | # otherwise print the formatted directory name followed by |
|
233 | # otherwise print the formatted directory name followed by | |
230 | # the formatted filenames |
|
234 | # the formatted filenames | |
231 | dirname_output_line = dirname_output_format % dirname |
|
235 | dirname_output_line = dirname_output_format % dirname | |
232 | result.append(dirname_output_line) |
|
236 | result.append(dirname_output_line) | |
233 | for fname in display_fnames: |
|
237 | for fname in display_fnames: | |
234 | fp = fp_format % (dirname,fname) |
|
238 | fp = fp_format % (dirname,fname) | |
235 | try: |
|
239 | try: | |
236 | # output can include both a filepath and a filename... |
|
240 | # output can include both a filepath and a filename... | |
237 | fname_output_line = fname_output_format % (fp, fname) |
|
241 | fname_output_line = fname_output_format % (fp, fname) | |
238 | except TypeError: |
|
242 | except TypeError: | |
239 | # ... or just a single filepath |
|
243 | # ... or just a single filepath | |
240 | fname_output_line = fname_output_format % fname |
|
244 | fname_output_line = fname_output_format % fname | |
241 | result.append(fname_output_line) |
|
245 | result.append(fname_output_line) | |
242 | return result |
|
246 | return result | |
243 | return f |
|
247 | return f | |
244 |
|
248 | |||
245 | def _get_notebook_display_formatter(self, |
|
249 | def _get_notebook_display_formatter(self, | |
246 | spacer=" "): |
|
250 | spacer=" "): | |
247 | """ generate function to use for notebook formatting |
|
251 | """ generate function to use for notebook formatting | |
248 | """ |
|
252 | """ | |
249 | dirname_output_format = \ |
|
253 | dirname_output_format = \ | |
250 | self.result_html_prefix + "%s/" + self.result_html_suffix |
|
254 | self.result_html_prefix + "%s/" + self.result_html_suffix | |
251 | fname_output_format = \ |
|
255 | fname_output_format = \ | |
252 | self.result_html_prefix + spacer + self.html_link_str + self.result_html_suffix |
|
256 | self.result_html_prefix + spacer + self.html_link_str + self.result_html_suffix | |
253 | fp_format = self.url_prefix + '%s/%s' |
|
257 | fp_format = self.url_prefix + '%s/%s' | |
254 |
|
258 | |||
255 | return self._get_display_formatter(dirname_output_format, |
|
259 | return self._get_display_formatter(dirname_output_format, | |
256 | fname_output_format, |
|
260 | fname_output_format, | |
257 | fp_format) |
|
261 | fp_format) | |
258 |
|
262 | |||
259 | def _get_terminal_display_formatter(self, |
|
263 | def _get_terminal_display_formatter(self, | |
260 | spacer=" "): |
|
264 | spacer=" "): | |
261 | """ generate function to use for terminal formatting |
|
265 | """ generate function to use for terminal formatting | |
262 | """ |
|
266 | """ | |
263 | dirname_output_format = "%s/" |
|
267 | dirname_output_format = "%s/" | |
264 | fname_output_format = spacer + "%s" |
|
268 | fname_output_format = spacer + "%s" | |
265 | fp_format = '%s/%s' |
|
269 | fp_format = '%s/%s' | |
266 |
|
270 | |||
267 | return self._get_display_formatter(dirname_output_format, |
|
271 | return self._get_display_formatter(dirname_output_format, | |
268 | fname_output_format, |
|
272 | fname_output_format, | |
269 | fp_format) |
|
273 | fp_format) | |
270 |
|
274 | |||
271 | def _format_path(self): |
|
275 | def _format_path(self): | |
272 | result_lines = [] |
|
276 | result_lines = [] | |
273 | walked_dir = list(walk(self.path)) |
|
277 | walked_dir = list(walk(self.path)) | |
274 | walked_dir.sort() |
|
278 | walked_dir.sort() | |
275 | for dirname, subdirs, fnames in walked_dir: |
|
279 | for dirname, subdirs, fnames in walked_dir: | |
276 | result_lines += self.notebook_display_formatter(dirname, fnames, self.included_suffixes) |
|
280 | result_lines += self.notebook_display_formatter(dirname, fnames, self.included_suffixes) | |
277 | return '\n'.join(result_lines) |
|
281 | return '\n'.join(result_lines) | |
278 |
|
282 | |||
279 | def __repr__(self): |
|
283 | def __repr__(self): | |
280 | """return newline-separated absolute paths |
|
284 | """return newline-separated absolute paths | |
281 | """ |
|
285 | """ | |
282 | result_lines = [] |
|
286 | result_lines = [] | |
283 | walked_dir = list(walk(self.path)) |
|
287 | walked_dir = list(walk(self.path)) | |
284 | walked_dir.sort() |
|
288 | walked_dir.sort() | |
285 | for dirname, subdirs, fnames in walked_dir: |
|
289 | for dirname, subdirs, fnames in walked_dir: | |
286 | result_lines += self.terminal_display_formatter(dirname, fnames, self.included_suffixes) |
|
290 | result_lines += self.terminal_display_formatter(dirname, fnames, self.included_suffixes) | |
287 | return '\n'.join(result_lines) |
|
291 | return '\n'.join(result_lines) |
@@ -1,529 +1,529 b'' | |||||
1 | # coding: utf-8 |
|
1 | # coding: utf-8 | |
2 | """ |
|
2 | """ | |
3 | Inputhook management for GUI event loop integration. |
|
3 | Inputhook management for GUI event loop integration. | |
4 | """ |
|
4 | """ | |
5 |
|
5 | |||
6 | #----------------------------------------------------------------------------- |
|
6 | #----------------------------------------------------------------------------- | |
7 | # Copyright (C) 2008-2011 The IPython Development Team |
|
7 | # Copyright (C) 2008-2011 The IPython Development Team | |
8 | # |
|
8 | # | |
9 | # Distributed under the terms of the BSD License. The full license is in |
|
9 | # Distributed under the terms of the BSD License. The full license is in | |
10 | # the file COPYING, distributed as part of this software. |
|
10 | # the file COPYING, distributed as part of this software. | |
11 | #----------------------------------------------------------------------------- |
|
11 | #----------------------------------------------------------------------------- | |
12 |
|
12 | |||
13 | #----------------------------------------------------------------------------- |
|
13 | #----------------------------------------------------------------------------- | |
14 | # Imports |
|
14 | # Imports | |
15 | #----------------------------------------------------------------------------- |
|
15 | #----------------------------------------------------------------------------- | |
16 |
|
16 | |||
17 | try: |
|
17 | try: | |
18 | import ctypes |
|
18 | import ctypes | |
19 | except ImportError: |
|
19 | except ImportError: | |
20 | ctypes = None |
|
20 | ctypes = None | |
21 | import os |
|
21 | import os | |
22 | import sys |
|
22 | import sys | |
23 | from distutils.version import LooseVersion as V |
|
23 | from distutils.version import LooseVersion as V | |
24 |
|
24 | |||
25 | from IPython.utils.warn import warn |
|
25 | from IPython.utils.warn import warn | |
26 |
|
26 | |||
27 | #----------------------------------------------------------------------------- |
|
27 | #----------------------------------------------------------------------------- | |
28 | # Constants |
|
28 | # Constants | |
29 | #----------------------------------------------------------------------------- |
|
29 | #----------------------------------------------------------------------------- | |
30 |
|
30 | |||
31 | # Constants for identifying the GUI toolkits. |
|
31 | # Constants for identifying the GUI toolkits. | |
32 | GUI_WX = 'wx' |
|
32 | GUI_WX = 'wx' | |
33 | GUI_QT = 'qt' |
|
33 | GUI_QT = 'qt' | |
34 | GUI_QT4 = 'qt4' |
|
34 | GUI_QT4 = 'qt4' | |
35 | GUI_GTK = 'gtk' |
|
35 | GUI_GTK = 'gtk' | |
36 | GUI_TK = 'tk' |
|
36 | GUI_TK = 'tk' | |
37 | GUI_OSX = 'osx' |
|
37 | GUI_OSX = 'osx' | |
38 | GUI_GLUT = 'glut' |
|
38 | GUI_GLUT = 'glut' | |
39 | GUI_PYGLET = 'pyglet' |
|
39 | GUI_PYGLET = 'pyglet' | |
40 | GUI_GTK3 = 'gtk3' |
|
40 | GUI_GTK3 = 'gtk3' | |
41 | GUI_NONE = 'none' # i.e. disable |
|
41 | GUI_NONE = 'none' # i.e. disable | |
42 |
|
42 | |||
43 | #----------------------------------------------------------------------------- |
|
43 | #----------------------------------------------------------------------------- | |
44 | # Utilities |
|
44 | # Utilities | |
45 | #----------------------------------------------------------------------------- |
|
45 | #----------------------------------------------------------------------------- | |
46 |
|
46 | |||
47 | def _stdin_ready_posix(): |
|
47 | def _stdin_ready_posix(): | |
48 | """Return True if there's something to read on stdin (posix version).""" |
|
48 | """Return True if there's something to read on stdin (posix version).""" | |
49 | infds, outfds, erfds = select.select([sys.stdin],[],[],0) |
|
49 | infds, outfds, erfds = select.select([sys.stdin],[],[],0) | |
50 | return bool(infds) |
|
50 | return bool(infds) | |
51 |
|
51 | |||
52 | def _stdin_ready_nt(): |
|
52 | def _stdin_ready_nt(): | |
53 | """Return True if there's something to read on stdin (nt version).""" |
|
53 | """Return True if there's something to read on stdin (nt version).""" | |
54 | return msvcrt.kbhit() |
|
54 | return msvcrt.kbhit() | |
55 |
|
55 | |||
56 | def _stdin_ready_other(): |
|
56 | def _stdin_ready_other(): | |
57 | """Return True, assuming there's something to read on stdin.""" |
|
57 | """Return True, assuming there's something to read on stdin.""" | |
58 | return True # |
|
58 | return True # | |
59 |
|
59 | |||
60 |
|
60 | |||
61 | def _ignore_CTRL_C_posix(): |
|
61 | def _ignore_CTRL_C_posix(): | |
62 | """Ignore CTRL+C (SIGINT).""" |
|
62 | """Ignore CTRL+C (SIGINT).""" | |
63 | signal.signal(signal.SIGINT, signal.SIG_IGN) |
|
63 | signal.signal(signal.SIGINT, signal.SIG_IGN) | |
64 |
|
64 | |||
65 | def _allow_CTRL_C_posix(): |
|
65 | def _allow_CTRL_C_posix(): | |
66 | """Take CTRL+C into account (SIGINT).""" |
|
66 | """Take CTRL+C into account (SIGINT).""" | |
67 | signal.signal(signal.SIGINT, signal.default_int_handler) |
|
67 | signal.signal(signal.SIGINT, signal.default_int_handler) | |
68 |
|
68 | |||
69 | def _ignore_CTRL_C_other(): |
|
69 | def _ignore_CTRL_C_other(): | |
70 | """Ignore CTRL+C (not implemented).""" |
|
70 | """Ignore CTRL+C (not implemented).""" | |
71 | pass |
|
71 | pass | |
72 |
|
72 | |||
73 | def _allow_CTRL_C_other(): |
|
73 | def _allow_CTRL_C_other(): | |
74 | """Take CTRL+C into account (not implemented).""" |
|
74 | """Take CTRL+C into account (not implemented).""" | |
75 | pass |
|
75 | pass | |
76 |
|
76 | |||
77 | if os.name == 'posix': |
|
77 | if os.name == 'posix': | |
78 | import select |
|
78 | import select | |
79 | import signal |
|
79 | import signal | |
80 | stdin_ready = _stdin_ready_posix |
|
80 | stdin_ready = _stdin_ready_posix | |
81 | ignore_CTRL_C = _ignore_CTRL_C_posix |
|
81 | ignore_CTRL_C = _ignore_CTRL_C_posix | |
82 | allow_CTRL_C = _allow_CTRL_C_posix |
|
82 | allow_CTRL_C = _allow_CTRL_C_posix | |
83 | elif os.name == 'nt': |
|
83 | elif os.name == 'nt': | |
84 | import msvcrt |
|
84 | import msvcrt | |
85 | stdin_ready = _stdin_ready_nt |
|
85 | stdin_ready = _stdin_ready_nt | |
86 | ignore_CTRL_C = _ignore_CTRL_C_other |
|
86 | ignore_CTRL_C = _ignore_CTRL_C_other | |
87 | allow_CTRL_C = _allow_CTRL_C_other |
|
87 | allow_CTRL_C = _allow_CTRL_C_other | |
88 | else: |
|
88 | else: | |
89 | stdin_ready = _stdin_ready_other |
|
89 | stdin_ready = _stdin_ready_other | |
90 | ignore_CTRL_C = _ignore_CTRL_C_other |
|
90 | ignore_CTRL_C = _ignore_CTRL_C_other | |
91 | allow_CTRL_C = _allow_CTRL_C_other |
|
91 | allow_CTRL_C = _allow_CTRL_C_other | |
92 |
|
92 | |||
93 |
|
93 | |||
94 | #----------------------------------------------------------------------------- |
|
94 | #----------------------------------------------------------------------------- | |
95 | # Main InputHookManager class |
|
95 | # Main InputHookManager class | |
96 | #----------------------------------------------------------------------------- |
|
96 | #----------------------------------------------------------------------------- | |
97 |
|
97 | |||
98 |
|
98 | |||
99 | class InputHookManager(object): |
|
99 | class InputHookManager(object): | |
100 | """Manage PyOS_InputHook for different GUI toolkits. |
|
100 | """Manage PyOS_InputHook for different GUI toolkits. | |
101 |
|
101 | |||
102 | This class installs various hooks under ``PyOSInputHook`` to handle |
|
102 | This class installs various hooks under ``PyOSInputHook`` to handle | |
103 | GUI event loop integration. |
|
103 | GUI event loop integration. | |
104 | """ |
|
104 | """ | |
105 |
|
105 | |||
106 | def __init__(self): |
|
106 | def __init__(self): | |
107 | if ctypes is None: |
|
107 | if ctypes is None: | |
108 | warn("IPython GUI event loop requires ctypes, %gui will not be available") |
|
108 | warn("IPython GUI event loop requires ctypes, %gui will not be available") | |
109 | return |
|
109 | return | |
110 | self.PYFUNC = ctypes.PYFUNCTYPE(ctypes.c_int) |
|
110 | self.PYFUNC = ctypes.PYFUNCTYPE(ctypes.c_int) | |
111 | self._apps = {} |
|
111 | self._apps = {} | |
112 | self._reset() |
|
112 | self._reset() | |
113 |
|
113 | |||
114 | def _reset(self): |
|
114 | def _reset(self): | |
115 | self._callback_pyfunctype = None |
|
115 | self._callback_pyfunctype = None | |
116 | self._callback = None |
|
116 | self._callback = None | |
117 | self._installed = False |
|
117 | self._installed = False | |
118 | self._current_gui = None |
|
118 | self._current_gui = None | |
119 |
|
119 | |||
120 | def get_pyos_inputhook(self): |
|
120 | def get_pyos_inputhook(self): | |
121 | """Return the current PyOS_InputHook as a ctypes.c_void_p.""" |
|
121 | """Return the current PyOS_InputHook as a ctypes.c_void_p.""" | |
122 | return ctypes.c_void_p.in_dll(ctypes.pythonapi,"PyOS_InputHook") |
|
122 | return ctypes.c_void_p.in_dll(ctypes.pythonapi,"PyOS_InputHook") | |
123 |
|
123 | |||
124 | def get_pyos_inputhook_as_func(self): |
|
124 | def get_pyos_inputhook_as_func(self): | |
125 | """Return the current PyOS_InputHook as a ctypes.PYFUNCYPE.""" |
|
125 | """Return the current PyOS_InputHook as a ctypes.PYFUNCYPE.""" | |
126 | return self.PYFUNC.in_dll(ctypes.pythonapi,"PyOS_InputHook") |
|
126 | return self.PYFUNC.in_dll(ctypes.pythonapi,"PyOS_InputHook") | |
127 |
|
127 | |||
128 | def set_inputhook(self, callback): |
|
128 | def set_inputhook(self, callback): | |
129 | """Set PyOS_InputHook to callback and return the previous one.""" |
|
129 | """Set PyOS_InputHook to callback and return the previous one.""" | |
130 | # On platforms with 'readline' support, it's all too likely to |
|
130 | # On platforms with 'readline' support, it's all too likely to | |
131 | # have a KeyboardInterrupt signal delivered *even before* an |
|
131 | # have a KeyboardInterrupt signal delivered *even before* an | |
132 | # initial ``try:`` clause in the callback can be executed, so |
|
132 | # initial ``try:`` clause in the callback can be executed, so | |
133 | # we need to disable CTRL+C in this situation. |
|
133 | # we need to disable CTRL+C in this situation. | |
134 | ignore_CTRL_C() |
|
134 | ignore_CTRL_C() | |
135 | self._callback = callback |
|
135 | self._callback = callback | |
136 | self._callback_pyfunctype = self.PYFUNC(callback) |
|
136 | self._callback_pyfunctype = self.PYFUNC(callback) | |
137 | pyos_inputhook_ptr = self.get_pyos_inputhook() |
|
137 | pyos_inputhook_ptr = self.get_pyos_inputhook() | |
138 | original = self.get_pyos_inputhook_as_func() |
|
138 | original = self.get_pyos_inputhook_as_func() | |
139 | pyos_inputhook_ptr.value = \ |
|
139 | pyos_inputhook_ptr.value = \ | |
140 | ctypes.cast(self._callback_pyfunctype, ctypes.c_void_p).value |
|
140 | ctypes.cast(self._callback_pyfunctype, ctypes.c_void_p).value | |
141 | self._installed = True |
|
141 | self._installed = True | |
142 | return original |
|
142 | return original | |
143 |
|
143 | |||
144 | def clear_inputhook(self, app=None): |
|
144 | def clear_inputhook(self, app=None): | |
145 | """Set PyOS_InputHook to NULL and return the previous one. |
|
145 | """Set PyOS_InputHook to NULL and return the previous one. | |
146 |
|
146 | |||
147 | Parameters |
|
147 | Parameters | |
148 | ---------- |
|
148 | ---------- | |
149 | app : optional, ignored |
|
149 | app : optional, ignored | |
150 | This parameter is allowed only so that clear_inputhook() can be |
|
150 | This parameter is allowed only so that clear_inputhook() can be | |
151 | called with a similar interface as all the ``enable_*`` methods. But |
|
151 | called with a similar interface as all the ``enable_*`` methods. But | |
152 | the actual value of the parameter is ignored. This uniform interface |
|
152 | the actual value of the parameter is ignored. This uniform interface | |
153 | makes it easier to have user-level entry points in the main IPython |
|
153 | makes it easier to have user-level entry points in the main IPython | |
154 | app like :meth:`enable_gui`.""" |
|
154 | app like :meth:`enable_gui`.""" | |
155 | pyos_inputhook_ptr = self.get_pyos_inputhook() |
|
155 | pyos_inputhook_ptr = self.get_pyos_inputhook() | |
156 | original = self.get_pyos_inputhook_as_func() |
|
156 | original = self.get_pyos_inputhook_as_func() | |
157 | pyos_inputhook_ptr.value = ctypes.c_void_p(None).value |
|
157 | pyos_inputhook_ptr.value = ctypes.c_void_p(None).value | |
158 | allow_CTRL_C() |
|
158 | allow_CTRL_C() | |
159 | self._reset() |
|
159 | self._reset() | |
160 | return original |
|
160 | return original | |
161 |
|
161 | |||
162 | def clear_app_refs(self, gui=None): |
|
162 | def clear_app_refs(self, gui=None): | |
163 | """Clear IPython's internal reference to an application instance. |
|
163 | """Clear IPython's internal reference to an application instance. | |
164 |
|
164 | |||
165 | Whenever we create an app for a user on qt4 or wx, we hold a |
|
165 | Whenever we create an app for a user on qt4 or wx, we hold a | |
166 | reference to the app. This is needed because in some cases bad things |
|
166 | reference to the app. This is needed because in some cases bad things | |
167 | can happen if a user doesn't hold a reference themselves. This |
|
167 | can happen if a user doesn't hold a reference themselves. This | |
168 | method is provided to clear the references we are holding. |
|
168 | method is provided to clear the references we are holding. | |
169 |
|
169 | |||
170 | Parameters |
|
170 | Parameters | |
171 | ---------- |
|
171 | ---------- | |
172 | gui : None or str |
|
172 | gui : None or str | |
173 | If None, clear all app references. If ('wx', 'qt4') clear |
|
173 | If None, clear all app references. If ('wx', 'qt4') clear | |
174 | the app for that toolkit. References are not held for gtk or tk |
|
174 | the app for that toolkit. References are not held for gtk or tk | |
175 | as those toolkits don't have the notion of an app. |
|
175 | as those toolkits don't have the notion of an app. | |
176 | """ |
|
176 | """ | |
177 | if gui is None: |
|
177 | if gui is None: | |
178 | self._apps = {} |
|
178 | self._apps = {} | |
179 | elif gui in self._apps: |
|
179 | elif gui in self._apps: | |
180 | del self._apps[gui] |
|
180 | del self._apps[gui] | |
181 |
|
181 | |||
182 | def enable_wx(self, app=None): |
|
182 | def enable_wx(self, app=None): | |
183 | """Enable event loop integration with wxPython. |
|
183 | """Enable event loop integration with wxPython. | |
184 |
|
184 | |||
185 | Parameters |
|
185 | Parameters | |
186 | ---------- |
|
186 | ---------- | |
187 | app : WX Application, optional. |
|
187 | app : WX Application, optional. | |
188 | Running application to use. If not given, we probe WX for an |
|
188 | Running application to use. If not given, we probe WX for an | |
189 | existing application object, and create a new one if none is found. |
|
189 | existing application object, and create a new one if none is found. | |
190 |
|
190 | |||
191 | Notes |
|
191 | Notes | |
192 | ----- |
|
192 | ----- | |
193 | This methods sets the ``PyOS_InputHook`` for wxPython, which allows |
|
193 | This methods sets the ``PyOS_InputHook`` for wxPython, which allows | |
194 | the wxPython to integrate with terminal based applications like |
|
194 | the wxPython to integrate with terminal based applications like | |
195 | IPython. |
|
195 | IPython. | |
196 |
|
196 | |||
197 | If ``app`` is not given we probe for an existing one, and return it if |
|
197 | If ``app`` is not given we probe for an existing one, and return it if | |
198 | found. If no existing app is found, we create an :class:`wx.App` as |
|
198 | found. If no existing app is found, we create an :class:`wx.App` as | |
199 | follows:: |
|
199 | follows:: | |
200 |
|
200 | |||
201 | import wx |
|
201 | import wx | |
202 | app = wx.App(redirect=False, clearSigInt=False) |
|
202 | app = wx.App(redirect=False, clearSigInt=False) | |
203 | """ |
|
203 | """ | |
204 | import wx |
|
204 | import wx | |
205 |
|
205 | |||
206 | wx_version = V(wx.__version__).version |
|
206 | wx_version = V(wx.__version__).version | |
207 |
|
207 | |||
208 | if wx_version < [2, 8]: |
|
208 | if wx_version < [2, 8]: | |
209 | raise ValueError("requires wxPython >= 2.8, but you have %s" % wx.__version__) |
|
209 | raise ValueError("requires wxPython >= 2.8, but you have %s" % wx.__version__) | |
210 |
|
210 | |||
211 | from IPython.lib.inputhookwx import inputhook_wx |
|
211 | from IPython.lib.inputhookwx import inputhook_wx | |
212 | self.set_inputhook(inputhook_wx) |
|
212 | self.set_inputhook(inputhook_wx) | |
213 | self._current_gui = GUI_WX |
|
213 | self._current_gui = GUI_WX | |
214 | import wx |
|
214 | import wx | |
215 | if app is None: |
|
215 | if app is None: | |
216 | app = wx.GetApp() |
|
216 | app = wx.GetApp() | |
217 | if app is None: |
|
217 | if app is None: | |
218 | app = wx.App(redirect=False, clearSigInt=False) |
|
218 | app = wx.App(redirect=False, clearSigInt=False) | |
219 | app._in_event_loop = True |
|
219 | app._in_event_loop = True | |
220 | self._apps[GUI_WX] = app |
|
220 | self._apps[GUI_WX] = app | |
221 | return app |
|
221 | return app | |
222 |
|
222 | |||
223 | def disable_wx(self): |
|
223 | def disable_wx(self): | |
224 | """Disable event loop integration with wxPython. |
|
224 | """Disable event loop integration with wxPython. | |
225 |
|
225 | |||
226 | This merely sets PyOS_InputHook to NULL. |
|
226 | This merely sets PyOS_InputHook to NULL. | |
227 | """ |
|
227 | """ | |
228 | if GUI_WX in self._apps: |
|
228 | if GUI_WX in self._apps: | |
229 | self._apps[GUI_WX]._in_event_loop = False |
|
229 | self._apps[GUI_WX]._in_event_loop = False | |
230 | self.clear_inputhook() |
|
230 | self.clear_inputhook() | |
231 |
|
231 | |||
232 | def enable_qt4(self, app=None): |
|
232 | def enable_qt4(self, app=None): | |
233 | """Enable event loop integration with PyQt4. |
|
233 | """Enable event loop integration with PyQt4. | |
234 |
|
234 | |||
235 | Parameters |
|
235 | Parameters | |
236 | ---------- |
|
236 | ---------- | |
237 | app : Qt Application, optional. |
|
237 | app : Qt Application, optional. | |
238 | Running application to use. If not given, we probe Qt for an |
|
238 | Running application to use. If not given, we probe Qt for an | |
239 | existing application object, and create a new one if none is found. |
|
239 | existing application object, and create a new one if none is found. | |
240 |
|
240 | |||
241 | Notes |
|
241 | Notes | |
242 | ----- |
|
242 | ----- | |
243 | This methods sets the PyOS_InputHook for PyQt4, which allows |
|
243 | This methods sets the PyOS_InputHook for PyQt4, which allows | |
244 | the PyQt4 to integrate with terminal based applications like |
|
244 | the PyQt4 to integrate with terminal based applications like | |
245 | IPython. |
|
245 | IPython. | |
246 |
|
246 | |||
247 | If ``app`` is not given we probe for an existing one, and return it if |
|
247 | If ``app`` is not given we probe for an existing one, and return it if | |
248 | found. If no existing app is found, we create an :class:`QApplication` |
|
248 | found. If no existing app is found, we create an :class:`QApplication` | |
249 | as follows:: |
|
249 | as follows:: | |
250 |
|
250 | |||
251 | from PyQt4 import QtCore |
|
251 | from PyQt4 import QtCore | |
252 | app = QtGui.QApplication(sys.argv) |
|
252 | app = QtGui.QApplication(sys.argv) | |
253 | """ |
|
253 | """ | |
254 | from IPython.lib.inputhookqt4 import create_inputhook_qt4 |
|
254 | from IPython.lib.inputhookqt4 import create_inputhook_qt4 | |
255 | app, inputhook_qt4 = create_inputhook_qt4(self, app) |
|
255 | app, inputhook_qt4 = create_inputhook_qt4(self, app) | |
256 | self.set_inputhook(inputhook_qt4) |
|
256 | self.set_inputhook(inputhook_qt4) | |
257 |
|
257 | |||
258 | self._current_gui = GUI_QT4 |
|
258 | self._current_gui = GUI_QT4 | |
259 | app._in_event_loop = True |
|
259 | app._in_event_loop = True | |
260 | self._apps[GUI_QT4] = app |
|
260 | self._apps[GUI_QT4] = app | |
261 | return app |
|
261 | return app | |
262 |
|
262 | |||
263 | def disable_qt4(self): |
|
263 | def disable_qt4(self): | |
264 | """Disable event loop integration with PyQt4. |
|
264 | """Disable event loop integration with PyQt4. | |
265 |
|
265 | |||
266 | This merely sets PyOS_InputHook to NULL. |
|
266 | This merely sets PyOS_InputHook to NULL. | |
267 | """ |
|
267 | """ | |
268 | if GUI_QT4 in self._apps: |
|
268 | if GUI_QT4 in self._apps: | |
269 | self._apps[GUI_QT4]._in_event_loop = False |
|
269 | self._apps[GUI_QT4]._in_event_loop = False | |
270 | self.clear_inputhook() |
|
270 | self.clear_inputhook() | |
271 |
|
271 | |||
272 | def enable_gtk(self, app=None): |
|
272 | def enable_gtk(self, app=None): | |
273 | """Enable event loop integration with PyGTK. |
|
273 | """Enable event loop integration with PyGTK. | |
274 |
|
274 | |||
275 | Parameters |
|
275 | Parameters | |
276 | ---------- |
|
276 | ---------- | |
277 | app : ignored |
|
277 | app : ignored | |
278 | Ignored, it's only a placeholder to keep the call signature of all |
|
278 | Ignored, it's only a placeholder to keep the call signature of all | |
279 | gui activation methods consistent, which simplifies the logic of |
|
279 | gui activation methods consistent, which simplifies the logic of | |
280 | supporting magics. |
|
280 | supporting magics. | |
281 |
|
281 | |||
282 | Notes |
|
282 | Notes | |
283 | ----- |
|
283 | ----- | |
284 | This methods sets the PyOS_InputHook for PyGTK, which allows |
|
284 | This methods sets the PyOS_InputHook for PyGTK, which allows | |
285 | the PyGTK to integrate with terminal based applications like |
|
285 | the PyGTK to integrate with terminal based applications like | |
286 | IPython. |
|
286 | IPython. | |
287 | """ |
|
287 | """ | |
288 | import gtk |
|
288 | import gtk | |
289 | try: |
|
289 | try: | |
290 | gtk.set_interactive(True) |
|
290 | gtk.set_interactive(True) | |
291 | self._current_gui = GUI_GTK |
|
291 | self._current_gui = GUI_GTK | |
292 | except AttributeError: |
|
292 | except AttributeError: | |
293 | # For older versions of gtk, use our own ctypes version |
|
293 | # For older versions of gtk, use our own ctypes version | |
294 | from IPython.lib.inputhookgtk import inputhook_gtk |
|
294 | from IPython.lib.inputhookgtk import inputhook_gtk | |
295 | self.set_inputhook(inputhook_gtk) |
|
295 | self.set_inputhook(inputhook_gtk) | |
296 | self._current_gui = GUI_GTK |
|
296 | self._current_gui = GUI_GTK | |
297 |
|
297 | |||
298 | def disable_gtk(self): |
|
298 | def disable_gtk(self): | |
299 | """Disable event loop integration with PyGTK. |
|
299 | """Disable event loop integration with PyGTK. | |
300 |
|
300 | |||
301 | This merely sets PyOS_InputHook to NULL. |
|
301 | This merely sets PyOS_InputHook to NULL. | |
302 | """ |
|
302 | """ | |
303 | self.clear_inputhook() |
|
303 | self.clear_inputhook() | |
304 |
|
304 | |||
305 | def enable_tk(self, app=None): |
|
305 | def enable_tk(self, app=None): | |
306 | """Enable event loop integration with Tk. |
|
306 | """Enable event loop integration with Tk. | |
307 |
|
307 | |||
308 | Parameters |
|
308 | Parameters | |
309 | ---------- |
|
309 | ---------- | |
310 | app : toplevel :class:`Tkinter.Tk` widget, optional. |
|
310 | app : toplevel :class:`Tkinter.Tk` widget, optional. | |
311 | Running toplevel widget to use. If not given, we probe Tk for an |
|
311 | Running toplevel widget to use. If not given, we probe Tk for an | |
312 | existing one, and create a new one if none is found. |
|
312 | existing one, and create a new one if none is found. | |
313 |
|
313 | |||
314 | Notes |
|
314 | Notes | |
315 | ----- |
|
315 | ----- | |
316 | If you have already created a :class:`Tkinter.Tk` object, the only |
|
316 | If you have already created a :class:`Tkinter.Tk` object, the only | |
317 | thing done by this method is to register with the |
|
317 | thing done by this method is to register with the | |
318 | :class:`InputHookManager`, since creating that object automatically |
|
318 | :class:`InputHookManager`, since creating that object automatically | |
319 | sets ``PyOS_InputHook``. |
|
319 | sets ``PyOS_InputHook``. | |
320 | """ |
|
320 | """ | |
321 | self._current_gui = GUI_TK |
|
321 | self._current_gui = GUI_TK | |
322 | if app is None: |
|
322 | if app is None: | |
323 | import Tkinter |
|
323 | import Tkinter | |
324 | app = Tkinter.Tk() |
|
324 | app = Tkinter.Tk() | |
325 | app.withdraw() |
|
325 | app.withdraw() | |
326 | self._apps[GUI_TK] = app |
|
326 | self._apps[GUI_TK] = app | |
327 | return app |
|
327 | return app | |
328 |
|
328 | |||
329 | def disable_tk(self): |
|
329 | def disable_tk(self): | |
330 | """Disable event loop integration with Tkinter. |
|
330 | """Disable event loop integration with Tkinter. | |
331 |
|
331 | |||
332 | This merely sets PyOS_InputHook to NULL. |
|
332 | This merely sets PyOS_InputHook to NULL. | |
333 | """ |
|
333 | """ | |
334 | self.clear_inputhook() |
|
334 | self.clear_inputhook() | |
335 |
|
335 | |||
336 |
|
336 | |||
337 | def enable_glut(self, app=None): |
|
337 | def enable_glut(self, app=None): | |
338 | """ Enable event loop integration with GLUT. |
|
338 | """ Enable event loop integration with GLUT. | |
339 |
|
339 | |||
340 | Parameters |
|
340 | Parameters | |
341 | ---------- |
|
341 | ---------- | |
342 |
|
342 | |||
343 | app : ignored |
|
343 | app : ignored | |
344 | Ignored, it's only a placeholder to keep the call signature of all |
|
344 | Ignored, it's only a placeholder to keep the call signature of all | |
345 | gui activation methods consistent, which simplifies the logic of |
|
345 | gui activation methods consistent, which simplifies the logic of | |
346 | supporting magics. |
|
346 | supporting magics. | |
347 |
|
347 | |||
348 | Notes |
|
348 | Notes | |
349 | ----- |
|
349 | ----- | |
350 |
|
350 | |||
351 | This methods sets the PyOS_InputHook for GLUT, which allows the GLUT to |
|
351 | This methods sets the PyOS_InputHook for GLUT, which allows the GLUT to | |
352 | integrate with terminal based applications like IPython. Due to GLUT |
|
352 | integrate with terminal based applications like IPython. Due to GLUT | |
353 | limitations, it is currently not possible to start the event loop |
|
353 | limitations, it is currently not possible to start the event loop | |
354 | without first creating a window. You should thus not create another |
|
354 | without first creating a window. You should thus not create another | |
355 | window but use instead the created one. See 'gui-glut.py' in the |
|
355 | window but use instead the created one. See 'gui-glut.py' in the | |
356 | docs/examples/lib directory. |
|
356 | docs/examples/lib directory. | |
357 |
|
357 | |||
358 | The default screen mode is set to: |
|
358 | The default screen mode is set to: | |
359 | glut.GLUT_DOUBLE | glut.GLUT_RGBA | glut.GLUT_DEPTH |
|
359 | glut.GLUT_DOUBLE | glut.GLUT_RGBA | glut.GLUT_DEPTH | |
360 | """ |
|
360 | """ | |
361 |
|
361 | |||
362 | import OpenGL.GLUT as glut |
|
362 | import OpenGL.GLUT as glut | |
363 | from IPython.lib.inputhookglut import glut_display_mode, \ |
|
363 | from IPython.lib.inputhookglut import glut_display_mode, \ | |
364 | glut_close, glut_display, \ |
|
364 | glut_close, glut_display, \ | |
365 | glut_idle, inputhook_glut |
|
365 | glut_idle, inputhook_glut | |
366 |
|
366 | |||
367 | if GUI_GLUT not in self._apps: |
|
367 | if GUI_GLUT not in self._apps: | |
368 | glut.glutInit( sys.argv ) |
|
368 | glut.glutInit( sys.argv ) | |
369 | glut.glutInitDisplayMode( glut_display_mode ) |
|
369 | glut.glutInitDisplayMode( glut_display_mode ) | |
370 | # This is specific to freeglut |
|
370 | # This is specific to freeglut | |
371 | if bool(glut.glutSetOption): |
|
371 | if bool(glut.glutSetOption): | |
372 | glut.glutSetOption( glut.GLUT_ACTION_ON_WINDOW_CLOSE, |
|
372 | glut.glutSetOption( glut.GLUT_ACTION_ON_WINDOW_CLOSE, | |
373 | glut.GLUT_ACTION_GLUTMAINLOOP_RETURNS ) |
|
373 | glut.GLUT_ACTION_GLUTMAINLOOP_RETURNS ) | |
374 | glut.glutCreateWindow( sys.argv[0] ) |
|
374 | glut.glutCreateWindow( sys.argv[0] ) | |
375 | glut.glutReshapeWindow( 1, 1 ) |
|
375 | glut.glutReshapeWindow( 1, 1 ) | |
376 | glut.glutHideWindow( ) |
|
376 | glut.glutHideWindow( ) | |
377 | glut.glutWMCloseFunc( glut_close ) |
|
377 | glut.glutWMCloseFunc( glut_close ) | |
378 | glut.glutDisplayFunc( glut_display ) |
|
378 | glut.glutDisplayFunc( glut_display ) | |
379 | glut.glutIdleFunc( glut_idle ) |
|
379 | glut.glutIdleFunc( glut_idle ) | |
380 | else: |
|
380 | else: | |
381 | glut.glutWMCloseFunc( glut_close ) |
|
381 | glut.glutWMCloseFunc( glut_close ) | |
382 | glut.glutDisplayFunc( glut_display ) |
|
382 | glut.glutDisplayFunc( glut_display ) | |
383 | glut.glutIdleFunc( glut_idle) |
|
383 | glut.glutIdleFunc( glut_idle) | |
384 | self.set_inputhook( inputhook_glut ) |
|
384 | self.set_inputhook( inputhook_glut ) | |
385 | self._current_gui = GUI_GLUT |
|
385 | self._current_gui = GUI_GLUT | |
386 | self._apps[GUI_GLUT] = True |
|
386 | self._apps[GUI_GLUT] = True | |
387 |
|
387 | |||
388 |
|
388 | |||
389 | def disable_glut(self): |
|
389 | def disable_glut(self): | |
390 | """Disable event loop integration with glut. |
|
390 | """Disable event loop integration with glut. | |
391 |
|
391 | |||
392 | This sets PyOS_InputHook to NULL and set the display function to a |
|
392 | This sets PyOS_InputHook to NULL and set the display function to a | |
393 | dummy one and set the timer to a dummy timer that will be triggered |
|
393 | dummy one and set the timer to a dummy timer that will be triggered | |
394 | very far in the future. |
|
394 | very far in the future. | |
395 | """ |
|
395 | """ | |
396 | import OpenGL.GLUT as glut |
|
396 | import OpenGL.GLUT as glut | |
397 | from glut_support import glutMainLoopEvent |
|
397 | from glut_support import glutMainLoopEvent | |
398 |
|
398 | |||
399 | glut.glutHideWindow() # This is an event to be processed below |
|
399 | glut.glutHideWindow() # This is an event to be processed below | |
400 | glutMainLoopEvent() |
|
400 | glutMainLoopEvent() | |
401 | self.clear_inputhook() |
|
401 | self.clear_inputhook() | |
402 |
|
402 | |||
403 | def enable_pyglet(self, app=None): |
|
403 | def enable_pyglet(self, app=None): | |
404 | """Enable event loop integration with pyglet. |
|
404 | """Enable event loop integration with pyglet. | |
405 |
|
405 | |||
406 | Parameters |
|
406 | Parameters | |
407 | ---------- |
|
407 | ---------- | |
408 | app : ignored |
|
408 | app : ignored | |
409 | Ignored, it's only a placeholder to keep the call signature of all |
|
409 | Ignored, it's only a placeholder to keep the call signature of all | |
410 | gui activation methods consistent, which simplifies the logic of |
|
410 | gui activation methods consistent, which simplifies the logic of | |
411 | supporting magics. |
|
411 | supporting magics. | |
412 |
|
412 | |||
413 | Notes |
|
413 | Notes | |
414 | ----- |
|
414 | ----- | |
415 | This methods sets the ``PyOS_InputHook`` for pyglet, which allows |
|
415 | This methods sets the ``PyOS_InputHook`` for pyglet, which allows | |
416 | pyglet to integrate with terminal based applications like |
|
416 | pyglet to integrate with terminal based applications like | |
417 | IPython. |
|
417 | IPython. | |
418 |
|
418 | |||
419 | """ |
|
419 | """ | |
420 | import pyglet |
|
420 | import pyglet | |
421 | from IPython.lib.inputhookpyglet import inputhook_pyglet |
|
421 | from IPython.lib.inputhookpyglet import inputhook_pyglet | |
422 | self.set_inputhook(inputhook_pyglet) |
|
422 | self.set_inputhook(inputhook_pyglet) | |
423 | self._current_gui = GUI_PYGLET |
|
423 | self._current_gui = GUI_PYGLET | |
424 | return app |
|
424 | return app | |
425 |
|
425 | |||
426 | def disable_pyglet(self): |
|
426 | def disable_pyglet(self): | |
427 | """Disable event loop integration with pyglet. |
|
427 | """Disable event loop integration with pyglet. | |
428 |
|
428 | |||
429 | This merely sets PyOS_InputHook to NULL. |
|
429 | This merely sets PyOS_InputHook to NULL. | |
430 | """ |
|
430 | """ | |
431 | self.clear_inputhook() |
|
431 | self.clear_inputhook() | |
432 |
|
432 | |||
433 | def enable_gtk3(self, app=None): |
|
433 | def enable_gtk3(self, app=None): | |
434 | """Enable event loop integration with Gtk3 (gir bindings). |
|
434 | """Enable event loop integration with Gtk3 (gir bindings). | |
435 |
|
435 | |||
436 | Parameters |
|
436 | Parameters | |
437 | ---------- |
|
437 | ---------- | |
438 | app : ignored |
|
438 | app : ignored | |
439 | Ignored, it's only a placeholder to keep the call signature of all |
|
439 | Ignored, it's only a placeholder to keep the call signature of all | |
440 | gui activation methods consistent, which simplifies the logic of |
|
440 | gui activation methods consistent, which simplifies the logic of | |
441 | supporting magics. |
|
441 | supporting magics. | |
442 |
|
442 | |||
443 | Notes |
|
443 | Notes | |
444 | ----- |
|
444 | ----- | |
445 | This methods sets the PyOS_InputHook for Gtk3, which allows |
|
445 | This methods sets the PyOS_InputHook for Gtk3, which allows | |
446 | the Gtk3 to integrate with terminal based applications like |
|
446 | the Gtk3 to integrate with terminal based applications like | |
447 | IPython. |
|
447 | IPython. | |
448 | """ |
|
448 | """ | |
449 | from IPython.lib.inputhookgtk3 import inputhook_gtk3 |
|
449 | from IPython.lib.inputhookgtk3 import inputhook_gtk3 | |
450 | self.set_inputhook(inputhook_gtk3) |
|
450 | self.set_inputhook(inputhook_gtk3) | |
451 | self._current_gui = GUI_GTK |
|
451 | self._current_gui = GUI_GTK | |
452 |
|
452 | |||
453 | def disable_gtk3(self): |
|
453 | def disable_gtk3(self): | |
454 | """Disable event loop integration with PyGTK. |
|
454 | """Disable event loop integration with PyGTK. | |
455 |
|
455 | |||
456 | This merely sets PyOS_InputHook to NULL. |
|
456 | This merely sets PyOS_InputHook to NULL. | |
457 | """ |
|
457 | """ | |
458 | self.clear_inputhook() |
|
458 | self.clear_inputhook() | |
459 |
|
459 | |||
460 | def current_gui(self): |
|
460 | def current_gui(self): | |
461 | """Return a string indicating the currently active GUI or None.""" |
|
461 | """Return a string indicating the currently active GUI or None.""" | |
462 | return self._current_gui |
|
462 | return self._current_gui | |
463 |
|
463 | |||
464 | inputhook_manager = InputHookManager() |
|
464 | inputhook_manager = InputHookManager() | |
465 |
|
465 | |||
466 | enable_wx = inputhook_manager.enable_wx |
|
466 | enable_wx = inputhook_manager.enable_wx | |
467 | disable_wx = inputhook_manager.disable_wx |
|
467 | disable_wx = inputhook_manager.disable_wx | |
468 | enable_qt4 = inputhook_manager.enable_qt4 |
|
468 | enable_qt4 = inputhook_manager.enable_qt4 | |
469 | disable_qt4 = inputhook_manager.disable_qt4 |
|
469 | disable_qt4 = inputhook_manager.disable_qt4 | |
470 | enable_gtk = inputhook_manager.enable_gtk |
|
470 | enable_gtk = inputhook_manager.enable_gtk | |
471 | disable_gtk = inputhook_manager.disable_gtk |
|
471 | disable_gtk = inputhook_manager.disable_gtk | |
472 | enable_tk = inputhook_manager.enable_tk |
|
472 | enable_tk = inputhook_manager.enable_tk | |
473 | disable_tk = inputhook_manager.disable_tk |
|
473 | disable_tk = inputhook_manager.disable_tk | |
474 | enable_glut = inputhook_manager.enable_glut |
|
474 | enable_glut = inputhook_manager.enable_glut | |
475 | disable_glut = inputhook_manager.disable_glut |
|
475 | disable_glut = inputhook_manager.disable_glut | |
476 | enable_pyglet = inputhook_manager.enable_pyglet |
|
476 | enable_pyglet = inputhook_manager.enable_pyglet | |
477 | disable_pyglet = inputhook_manager.disable_pyglet |
|
477 | disable_pyglet = inputhook_manager.disable_pyglet | |
478 | enable_gtk3 = inputhook_manager.enable_gtk3 |
|
478 | enable_gtk3 = inputhook_manager.enable_gtk3 | |
479 | disable_gtk3 = inputhook_manager.disable_gtk3 |
|
479 | disable_gtk3 = inputhook_manager.disable_gtk3 | |
480 | clear_inputhook = inputhook_manager.clear_inputhook |
|
480 | clear_inputhook = inputhook_manager.clear_inputhook | |
481 | set_inputhook = inputhook_manager.set_inputhook |
|
481 | set_inputhook = inputhook_manager.set_inputhook | |
482 | current_gui = inputhook_manager.current_gui |
|
482 | current_gui = inputhook_manager.current_gui | |
483 | clear_app_refs = inputhook_manager.clear_app_refs |
|
483 | clear_app_refs = inputhook_manager.clear_app_refs | |
484 |
|
484 | |||
485 |
|
485 | |||
486 | # Convenience function to switch amongst them |
|
486 | # Convenience function to switch amongst them | |
487 | def enable_gui(gui=None, app=None): |
|
487 | def enable_gui(gui=None, app=None): | |
488 | """Switch amongst GUI input hooks by name. |
|
488 | """Switch amongst GUI input hooks by name. | |
489 |
|
489 | |||
490 | This is just a utility wrapper around the methods of the InputHookManager |
|
490 | This is just a utility wrapper around the methods of the InputHookManager | |
491 | object. |
|
491 | object. | |
492 |
|
492 | |||
493 | Parameters |
|
493 | Parameters | |
494 | ---------- |
|
494 | ---------- | |
495 | gui : optional, string or None |
|
495 | gui : optional, string or None | |
496 | If None (or 'none'), clears input hook, otherwise it must be one |
|
496 | If None (or 'none'), clears input hook, otherwise it must be one | |
497 | of the recognized GUI names (see ``GUI_*`` constants in module). |
|
497 | of the recognized GUI names (see ``GUI_*`` constants in module). | |
498 |
|
498 | |||
499 | app : optional, existing application object. |
|
499 | app : optional, existing application object. | |
500 | For toolkits that have the concept of a global app, you can supply an |
|
500 | For toolkits that have the concept of a global app, you can supply an | |
501 | existing one. If not given, the toolkit will be probed for one, and if |
|
501 | existing one. If not given, the toolkit will be probed for one, and if | |
502 | none is found, a new one will be created. Note that GTK does not have |
|
502 | none is found, a new one will be created. Note that GTK does not have | |
503 |
this concept, and passing an app if `gui |
|
503 | this concept, and passing an app if ``gui=="GTK"`` will raise an error. | |
504 |
|
504 | |||
505 | Returns |
|
505 | Returns | |
506 | ------- |
|
506 | ------- | |
507 | The output of the underlying gui switch routine, typically the actual |
|
507 | The output of the underlying gui switch routine, typically the actual | |
508 | PyOS_InputHook wrapper object or the GUI toolkit app created, if there was |
|
508 | PyOS_InputHook wrapper object or the GUI toolkit app created, if there was | |
509 | one. |
|
509 | one. | |
510 | """ |
|
510 | """ | |
511 | guis = {None: clear_inputhook, |
|
511 | guis = {None: clear_inputhook, | |
512 | GUI_NONE: clear_inputhook, |
|
512 | GUI_NONE: clear_inputhook, | |
513 | GUI_OSX: lambda app=False: None, |
|
513 | GUI_OSX: lambda app=False: None, | |
514 | GUI_TK: enable_tk, |
|
514 | GUI_TK: enable_tk, | |
515 | GUI_GTK: enable_gtk, |
|
515 | GUI_GTK: enable_gtk, | |
516 | GUI_WX: enable_wx, |
|
516 | GUI_WX: enable_wx, | |
517 | GUI_QT: enable_qt4, # qt3 not supported |
|
517 | GUI_QT: enable_qt4, # qt3 not supported | |
518 | GUI_QT4: enable_qt4, |
|
518 | GUI_QT4: enable_qt4, | |
519 | GUI_GLUT: enable_glut, |
|
519 | GUI_GLUT: enable_glut, | |
520 | GUI_PYGLET: enable_pyglet, |
|
520 | GUI_PYGLET: enable_pyglet, | |
521 | GUI_GTK3: enable_gtk3, |
|
521 | GUI_GTK3: enable_gtk3, | |
522 | } |
|
522 | } | |
523 | try: |
|
523 | try: | |
524 | gui_hook = guis[gui] |
|
524 | gui_hook = guis[gui] | |
525 | except KeyError: |
|
525 | except KeyError: | |
526 | e = "Invalid GUI request %r, valid ones are:%s" % (gui, guis.keys()) |
|
526 | e = "Invalid GUI request %r, valid ones are:%s" % (gui, guis.keys()) | |
527 | raise ValueError(e) |
|
527 | raise ValueError(e) | |
528 | return gui_hook(app) |
|
528 | return gui_hook(app) | |
529 |
|
529 |
@@ -1,358 +1,358 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
1 | # -*- coding: utf-8 -*- | |
2 | """Decorators for labeling test objects. |
|
2 | """Decorators for labeling test objects. | |
3 |
|
3 | |||
4 | Decorators that merely return a modified version of the original function |
|
4 | Decorators that merely return a modified version of the original function | |
5 | object are straightforward. Decorators that return a new function object need |
|
5 | object are straightforward. Decorators that return a new function object need | |
6 | to use nose.tools.make_decorator(original_function)(decorator) in returning the |
|
6 | to use nose.tools.make_decorator(original_function)(decorator) in returning the | |
7 | decorator, in order to preserve metadata such as function name, setup and |
|
7 | decorator, in order to preserve metadata such as function name, setup and | |
8 | teardown functions and so on - see nose.tools for more information. |
|
8 | teardown functions and so on - see nose.tools for more information. | |
9 |
|
9 | |||
10 | This module provides a set of useful decorators meant to be ready to use in |
|
10 | This module provides a set of useful decorators meant to be ready to use in | |
11 | your own tests. See the bottom of the file for the ready-made ones, and if you |
|
11 | your own tests. See the bottom of the file for the ready-made ones, and if you | |
12 | find yourself writing a new one that may be of generic use, add it here. |
|
12 | find yourself writing a new one that may be of generic use, add it here. | |
13 |
|
13 | |||
14 | Included decorators: |
|
14 | Included decorators: | |
15 |
|
15 | |||
16 |
|
16 | |||
17 | Lightweight testing that remains unittest-compatible. |
|
17 | Lightweight testing that remains unittest-compatible. | |
18 |
|
18 | |||
19 | - @parametric, for parametric test support that is vastly easier to use than |
|
19 | - @parametric, for parametric test support that is vastly easier to use than | |
20 | nose's for debugging. With ours, if a test fails, the stack under inspection |
|
20 | nose's for debugging. With ours, if a test fails, the stack under inspection | |
21 | is that of the test and not that of the test framework. |
|
21 | is that of the test and not that of the test framework. | |
22 |
|
22 | |||
23 | - An @as_unittest decorator can be used to tag any normal parameter-less |
|
23 | - An @as_unittest decorator can be used to tag any normal parameter-less | |
24 | function as a unittest TestCase. Then, both nose and normal unittest will |
|
24 | function as a unittest TestCase. Then, both nose and normal unittest will | |
25 | recognize it as such. This will make it easier to migrate away from Nose if |
|
25 | recognize it as such. This will make it easier to migrate away from Nose if | |
26 | we ever need/want to while maintaining very lightweight tests. |
|
26 | we ever need/want to while maintaining very lightweight tests. | |
27 |
|
27 | |||
28 | NOTE: This file contains IPython-specific decorators. Using the machinery in |
|
28 | NOTE: This file contains IPython-specific decorators. Using the machinery in | |
29 | IPython.external.decorators, we import either numpy.testing.decorators if numpy is |
|
29 | IPython.external.decorators, we import either numpy.testing.decorators if numpy is | |
30 | available, OR use equivalent code in IPython.external._decorators, which |
|
30 | available, OR use equivalent code in IPython.external._decorators, which | |
31 | we've copied verbatim from numpy. |
|
31 | we've copied verbatim from numpy. | |
32 |
|
32 | |||
33 | Authors |
|
33 | Authors | |
34 | ------- |
|
34 | ------- | |
35 |
|
35 | |||
36 | - Fernando Perez <Fernando.Perez@berkeley.edu> |
|
36 | - Fernando Perez <Fernando.Perez@berkeley.edu> | |
37 | """ |
|
37 | """ | |
38 |
|
38 | |||
39 | #----------------------------------------------------------------------------- |
|
39 | #----------------------------------------------------------------------------- | |
40 | # Copyright (C) 2009-2011 The IPython Development Team |
|
40 | # Copyright (C) 2009-2011 The IPython Development Team | |
41 | # |
|
41 | # | |
42 | # Distributed under the terms of the BSD License. The full license is in |
|
42 | # Distributed under the terms of the BSD License. The full license is in | |
43 | # the file COPYING, distributed as part of this software. |
|
43 | # the file COPYING, distributed as part of this software. | |
44 | #----------------------------------------------------------------------------- |
|
44 | #----------------------------------------------------------------------------- | |
45 |
|
45 | |||
46 | #----------------------------------------------------------------------------- |
|
46 | #----------------------------------------------------------------------------- | |
47 | # Imports |
|
47 | # Imports | |
48 | #----------------------------------------------------------------------------- |
|
48 | #----------------------------------------------------------------------------- | |
49 |
|
49 | |||
50 | # Stdlib imports |
|
50 | # Stdlib imports | |
51 | import inspect |
|
51 | import inspect | |
52 | import sys |
|
52 | import sys | |
53 | import tempfile |
|
53 | import tempfile | |
54 | import unittest |
|
54 | import unittest | |
55 |
|
55 | |||
56 | # Third-party imports |
|
56 | # Third-party imports | |
57 |
|
57 | |||
58 | # This is Michele Simionato's decorator module, kept verbatim. |
|
58 | # This is Michele Simionato's decorator module, kept verbatim. | |
59 | from IPython.external.decorator import decorator |
|
59 | from IPython.external.decorator import decorator | |
60 |
|
60 | |||
61 | # We already have python3-compliant code for parametric tests |
|
61 | # We already have python3-compliant code for parametric tests | |
62 | if sys.version[0]=='2': |
|
62 | if sys.version[0]=='2': | |
63 | from _paramtestpy2 import parametric, ParametricTestCase |
|
63 | from _paramtestpy2 import parametric, ParametricTestCase | |
64 | else: |
|
64 | else: | |
65 | from _paramtestpy3 import parametric, ParametricTestCase |
|
65 | from _paramtestpy3 import parametric, ParametricTestCase | |
66 |
|
66 | |||
67 | # Expose the unittest-driven decorators |
|
67 | # Expose the unittest-driven decorators | |
68 | from ipunittest import ipdoctest, ipdocstring |
|
68 | from ipunittest import ipdoctest, ipdocstring | |
69 |
|
69 | |||
70 | # Grab the numpy-specific decorators which we keep in a file that we |
|
70 | # Grab the numpy-specific decorators which we keep in a file that we | |
71 | # occasionally update from upstream: decorators.py is a copy of |
|
71 | # occasionally update from upstream: decorators.py is a copy of | |
72 | # numpy.testing.decorators, we expose all of it here. |
|
72 | # numpy.testing.decorators, we expose all of it here. | |
73 | from IPython.external.decorators import * |
|
73 | from IPython.external.decorators import * | |
74 |
|
74 | |||
75 | # For onlyif_cmd_exists decorator |
|
75 | # For onlyif_cmd_exists decorator | |
76 | from IPython.utils.process import is_cmd_found |
|
76 | from IPython.utils.process import is_cmd_found | |
77 |
|
77 | |||
78 | #----------------------------------------------------------------------------- |
|
78 | #----------------------------------------------------------------------------- | |
79 | # Classes and functions |
|
79 | # Classes and functions | |
80 | #----------------------------------------------------------------------------- |
|
80 | #----------------------------------------------------------------------------- | |
81 |
|
81 | |||
82 | # Simple example of the basic idea |
|
82 | # Simple example of the basic idea | |
83 | def as_unittest(func): |
|
83 | def as_unittest(func): | |
84 | """Decorator to make a simple function into a normal test via unittest.""" |
|
84 | """Decorator to make a simple function into a normal test via unittest.""" | |
85 | class Tester(unittest.TestCase): |
|
85 | class Tester(unittest.TestCase): | |
86 | def test(self): |
|
86 | def test(self): | |
87 | func() |
|
87 | func() | |
88 |
|
88 | |||
89 | Tester.__name__ = func.__name__ |
|
89 | Tester.__name__ = func.__name__ | |
90 |
|
90 | |||
91 | return Tester |
|
91 | return Tester | |
92 |
|
92 | |||
93 | # Utility functions |
|
93 | # Utility functions | |
94 |
|
94 | |||
95 | def apply_wrapper(wrapper,func): |
|
95 | def apply_wrapper(wrapper,func): | |
96 | """Apply a wrapper to a function for decoration. |
|
96 | """Apply a wrapper to a function for decoration. | |
97 |
|
97 | |||
98 | This mixes Michele Simionato's decorator tool with nose's make_decorator, |
|
98 | This mixes Michele Simionato's decorator tool with nose's make_decorator, | |
99 | to apply a wrapper in a decorator so that all nose attributes, as well as |
|
99 | to apply a wrapper in a decorator so that all nose attributes, as well as | |
100 | function signature and other properties, survive the decoration cleanly. |
|
100 | function signature and other properties, survive the decoration cleanly. | |
101 | This will ensure that wrapped functions can still be well introspected via |
|
101 | This will ensure that wrapped functions can still be well introspected via | |
102 | IPython, for example. |
|
102 | IPython, for example. | |
103 | """ |
|
103 | """ | |
104 | import nose.tools |
|
104 | import nose.tools | |
105 |
|
105 | |||
106 | return decorator(wrapper,nose.tools.make_decorator(func)(wrapper)) |
|
106 | return decorator(wrapper,nose.tools.make_decorator(func)(wrapper)) | |
107 |
|
107 | |||
108 |
|
108 | |||
109 | def make_label_dec(label,ds=None): |
|
109 | def make_label_dec(label,ds=None): | |
110 | """Factory function to create a decorator that applies one or more labels. |
|
110 | """Factory function to create a decorator that applies one or more labels. | |
111 |
|
111 | |||
112 | Parameters |
|
112 | Parameters | |
113 | ---------- |
|
113 | ---------- | |
114 | label : string or sequence |
|
114 | label : string or sequence | |
115 | One or more labels that will be applied by the decorator to the functions |
|
115 | One or more labels that will be applied by the decorator to the functions | |
116 | it decorates. Labels are attributes of the decorated function with their |
|
116 | it decorates. Labels are attributes of the decorated function with their | |
117 | value set to True. |
|
117 | value set to True. | |
118 |
|
118 | |||
119 | ds : string |
|
119 | ds : string | |
120 | An optional docstring for the resulting decorator. If not given, a |
|
120 | An optional docstring for the resulting decorator. If not given, a | |
121 | default docstring is auto-generated. |
|
121 | default docstring is auto-generated. | |
122 |
|
122 | |||
123 | Returns |
|
123 | Returns | |
124 | ------- |
|
124 | ------- | |
125 | A decorator. |
|
125 | A decorator. | |
126 |
|
126 | |||
127 | Examples |
|
127 | Examples | |
128 | -------- |
|
128 | -------- | |
129 |
|
129 | |||
130 | A simple labeling decorator: |
|
130 | A simple labeling decorator: | |
131 | >>> slow = make_label_dec('slow') |
|
131 | >>> slow = make_label_dec('slow') | |
132 | >>> print slow.__doc__ |
|
132 | >>> print slow.__doc__ | |
133 | Labels a test as 'slow'. |
|
133 | Labels a test as 'slow'. | |
134 |
|
134 | |||
135 | And one that uses multiple labels and a custom docstring: |
|
135 | And one that uses multiple labels and a custom docstring: | |
136 | >>> rare = make_label_dec(['slow','hard'], |
|
136 | >>> rare = make_label_dec(['slow','hard'], | |
137 | ... "Mix labels 'slow' and 'hard' for rare tests.") |
|
137 | ... "Mix labels 'slow' and 'hard' for rare tests.") | |
138 | >>> print rare.__doc__ |
|
138 | >>> print rare.__doc__ | |
139 | Mix labels 'slow' and 'hard' for rare tests. |
|
139 | Mix labels 'slow' and 'hard' for rare tests. | |
140 |
|
140 | |||
141 | Now, let's test using this one: |
|
141 | Now, let's test using this one: | |
142 | >>> @rare |
|
142 | >>> @rare | |
143 | ... def f(): pass |
|
143 | ... def f(): pass | |
144 | ... |
|
144 | ... | |
145 | >>> |
|
145 | >>> | |
146 | >>> f.slow |
|
146 | >>> f.slow | |
147 | True |
|
147 | True | |
148 | >>> f.hard |
|
148 | >>> f.hard | |
149 | True |
|
149 | True | |
150 | """ |
|
150 | """ | |
151 |
|
151 | |||
152 | if isinstance(label,basestring): |
|
152 | if isinstance(label,basestring): | |
153 | labels = [label] |
|
153 | labels = [label] | |
154 | else: |
|
154 | else: | |
155 | labels = label |
|
155 | labels = label | |
156 |
|
156 | |||
157 | # Validate that the given label(s) are OK for use in setattr() by doing a |
|
157 | # Validate that the given label(s) are OK for use in setattr() by doing a | |
158 | # dry run on a dummy function. |
|
158 | # dry run on a dummy function. | |
159 | tmp = lambda : None |
|
159 | tmp = lambda : None | |
160 | for label in labels: |
|
160 | for label in labels: | |
161 | setattr(tmp,label,True) |
|
161 | setattr(tmp,label,True) | |
162 |
|
162 | |||
163 | # This is the actual decorator we'll return |
|
163 | # This is the actual decorator we'll return | |
164 | def decor(f): |
|
164 | def decor(f): | |
165 | for label in labels: |
|
165 | for label in labels: | |
166 | setattr(f,label,True) |
|
166 | setattr(f,label,True) | |
167 | return f |
|
167 | return f | |
168 |
|
168 | |||
169 | # Apply the user's docstring, or autogenerate a basic one |
|
169 | # Apply the user's docstring, or autogenerate a basic one | |
170 | if ds is None: |
|
170 | if ds is None: | |
171 | ds = "Labels a test as %r." % label |
|
171 | ds = "Labels a test as %r." % label | |
172 | decor.__doc__ = ds |
|
172 | decor.__doc__ = ds | |
173 |
|
173 | |||
174 | return decor |
|
174 | return decor | |
175 |
|
175 | |||
176 |
|
176 | |||
177 | # Inspired by numpy's skipif, but uses the full apply_wrapper utility to |
|
177 | # Inspired by numpy's skipif, but uses the full apply_wrapper utility to | |
178 | # preserve function metadata better and allows the skip condition to be a |
|
178 | # preserve function metadata better and allows the skip condition to be a | |
179 | # callable. |
|
179 | # callable. | |
180 | def skipif(skip_condition, msg=None): |
|
180 | def skipif(skip_condition, msg=None): | |
181 | ''' Make function raise SkipTest exception if skip_condition is true |
|
181 | ''' Make function raise SkipTest exception if skip_condition is true | |
182 |
|
182 | |||
183 | Parameters |
|
183 | Parameters | |
184 | ---------- |
|
184 | ---------- | |
185 | skip_condition : bool or callable. |
|
185 | skip_condition : bool or callable. | |
186 | Flag to determine whether to skip test. If the condition is a |
|
186 | Flag to determine whether to skip test. If the condition is a | |
187 | callable, it is used at runtime to dynamically make the decision. This |
|
187 | callable, it is used at runtime to dynamically make the decision. This | |
188 | is useful for tests that may require costly imports, to delay the cost |
|
188 | is useful for tests that may require costly imports, to delay the cost | |
189 | until the test suite is actually executed. |
|
189 | until the test suite is actually executed. | |
190 | msg : string |
|
190 | msg : string | |
191 | Message to give on raising a SkipTest exception |
|
191 | Message to give on raising a SkipTest exception | |
192 |
|
192 | |||
193 | Returns |
|
193 | Returns | |
194 | ------- |
|
194 | ------- | |
195 | decorator : function |
|
195 | decorator : function | |
196 | Decorator, which, when applied to a function, causes SkipTest |
|
196 | Decorator, which, when applied to a function, causes SkipTest | |
197 | to be raised when the skip_condition was True, and the function |
|
197 | to be raised when the skip_condition was True, and the function | |
198 | to be called normally otherwise. |
|
198 | to be called normally otherwise. | |
199 |
|
199 | |||
200 | Notes |
|
200 | Notes | |
201 | ----- |
|
201 | ----- | |
202 | You will see from the code that we had to further decorate the |
|
202 | You will see from the code that we had to further decorate the | |
203 | decorator with the nose.tools.make_decorator function in order to |
|
203 | decorator with the nose.tools.make_decorator function in order to | |
204 | transmit function name, and various other metadata. |
|
204 | transmit function name, and various other metadata. | |
205 | ''' |
|
205 | ''' | |
206 |
|
206 | |||
207 | def skip_decorator(f): |
|
207 | def skip_decorator(f): | |
208 | # Local import to avoid a hard nose dependency and only incur the |
|
208 | # Local import to avoid a hard nose dependency and only incur the | |
209 | # import time overhead at actual test-time. |
|
209 | # import time overhead at actual test-time. | |
210 | import nose |
|
210 | import nose | |
211 |
|
211 | |||
212 | # Allow for both boolean or callable skip conditions. |
|
212 | # Allow for both boolean or callable skip conditions. | |
213 | if callable(skip_condition): |
|
213 | if callable(skip_condition): | |
214 | skip_val = skip_condition |
|
214 | skip_val = skip_condition | |
215 | else: |
|
215 | else: | |
216 | skip_val = lambda : skip_condition |
|
216 | skip_val = lambda : skip_condition | |
217 |
|
217 | |||
218 | def get_msg(func,msg=None): |
|
218 | def get_msg(func,msg=None): | |
219 | """Skip message with information about function being skipped.""" |
|
219 | """Skip message with information about function being skipped.""" | |
220 | if msg is None: out = 'Test skipped due to test condition.' |
|
220 | if msg is None: out = 'Test skipped due to test condition.' | |
221 | else: out = msg |
|
221 | else: out = msg | |
222 | return "Skipping test: %s. %s" % (func.__name__,out) |
|
222 | return "Skipping test: %s. %s" % (func.__name__,out) | |
223 |
|
223 | |||
224 | # We need to define *two* skippers because Python doesn't allow both |
|
224 | # We need to define *two* skippers because Python doesn't allow both | |
225 | # return with value and yield inside the same function. |
|
225 | # return with value and yield inside the same function. | |
226 | def skipper_func(*args, **kwargs): |
|
226 | def skipper_func(*args, **kwargs): | |
227 | """Skipper for normal test functions.""" |
|
227 | """Skipper for normal test functions.""" | |
228 | if skip_val(): |
|
228 | if skip_val(): | |
229 | raise nose.SkipTest(get_msg(f,msg)) |
|
229 | raise nose.SkipTest(get_msg(f,msg)) | |
230 | else: |
|
230 | else: | |
231 | return f(*args, **kwargs) |
|
231 | return f(*args, **kwargs) | |
232 |
|
232 | |||
233 | def skipper_gen(*args, **kwargs): |
|
233 | def skipper_gen(*args, **kwargs): | |
234 | """Skipper for test generators.""" |
|
234 | """Skipper for test generators.""" | |
235 | if skip_val(): |
|
235 | if skip_val(): | |
236 | raise nose.SkipTest(get_msg(f,msg)) |
|
236 | raise nose.SkipTest(get_msg(f,msg)) | |
237 | else: |
|
237 | else: | |
238 | for x in f(*args, **kwargs): |
|
238 | for x in f(*args, **kwargs): | |
239 | yield x |
|
239 | yield x | |
240 |
|
240 | |||
241 | # Choose the right skipper to use when building the actual generator. |
|
241 | # Choose the right skipper to use when building the actual generator. | |
242 | if nose.util.isgenerator(f): |
|
242 | if nose.util.isgenerator(f): | |
243 | skipper = skipper_gen |
|
243 | skipper = skipper_gen | |
244 | else: |
|
244 | else: | |
245 | skipper = skipper_func |
|
245 | skipper = skipper_func | |
246 |
|
246 | |||
247 | return nose.tools.make_decorator(f)(skipper) |
|
247 | return nose.tools.make_decorator(f)(skipper) | |
248 |
|
248 | |||
249 | return skip_decorator |
|
249 | return skip_decorator | |
250 |
|
250 | |||
251 | # A version with the condition set to true, common case just to attach a message |
|
251 | # A version with the condition set to true, common case just to attach a message | |
252 | # to a skip decorator |
|
252 | # to a skip decorator | |
253 | def skip(msg=None): |
|
253 | def skip(msg=None): | |
254 | """Decorator factory - mark a test function for skipping from test suite. |
|
254 | """Decorator factory - mark a test function for skipping from test suite. | |
255 |
|
255 | |||
256 | Parameters |
|
256 | Parameters | |
257 | ---------- |
|
257 | ---------- | |
258 | msg : string |
|
258 | msg : string | |
259 | Optional message to be added. |
|
259 | Optional message to be added. | |
260 |
|
260 | |||
261 | Returns |
|
261 | Returns | |
262 | ------- |
|
262 | ------- | |
263 | decorator : function |
|
263 | decorator : function | |
264 | Decorator, which, when applied to a function, causes SkipTest |
|
264 | Decorator, which, when applied to a function, causes SkipTest | |
265 | to be raised, with the optional message added. |
|
265 | to be raised, with the optional message added. | |
266 | """ |
|
266 | """ | |
267 |
|
267 | |||
268 | return skipif(True,msg) |
|
268 | return skipif(True,msg) | |
269 |
|
269 | |||
270 |
|
270 | |||
271 | def onlyif(condition, msg): |
|
271 | def onlyif(condition, msg): | |
272 | """The reverse from skipif, see skipif for details.""" |
|
272 | """The reverse from skipif, see skipif for details.""" | |
273 |
|
273 | |||
274 | if callable(condition): |
|
274 | if callable(condition): | |
275 | skip_condition = lambda : not condition() |
|
275 | skip_condition = lambda : not condition() | |
276 | else: |
|
276 | else: | |
277 | skip_condition = lambda : not condition |
|
277 | skip_condition = lambda : not condition | |
278 |
|
278 | |||
279 | return skipif(skip_condition, msg) |
|
279 | return skipif(skip_condition, msg) | |
280 |
|
280 | |||
281 | #----------------------------------------------------------------------------- |
|
281 | #----------------------------------------------------------------------------- | |
282 | # Utility functions for decorators |
|
282 | # Utility functions for decorators | |
283 | def module_not_available(module): |
|
283 | def module_not_available(module): | |
284 | """Can module be imported? Returns true if module does NOT import. |
|
284 | """Can module be imported? Returns true if module does NOT import. | |
285 |
|
285 | |||
286 | This is used to make a decorator to skip tests that require module to be |
|
286 | This is used to make a decorator to skip tests that require module to be | |
287 | available, but delay the 'import numpy' to test execution time. |
|
287 | available, but delay the 'import numpy' to test execution time. | |
288 | """ |
|
288 | """ | |
289 | try: |
|
289 | try: | |
290 | mod = __import__(module) |
|
290 | mod = __import__(module) | |
291 | mod_not_avail = False |
|
291 | mod_not_avail = False | |
292 | except ImportError: |
|
292 | except ImportError: | |
293 | mod_not_avail = True |
|
293 | mod_not_avail = True | |
294 |
|
294 | |||
295 | return mod_not_avail |
|
295 | return mod_not_avail | |
296 |
|
296 | |||
297 | #----------------------------------------------------------------------------- |
|
297 | #----------------------------------------------------------------------------- | |
298 | # Decorators for public use |
|
298 | # Decorators for public use | |
299 |
|
299 | |||
300 | # Decorators to skip certain tests on specific platforms. |
|
300 | # Decorators to skip certain tests on specific platforms. | |
301 | skip_win32 = skipif(sys.platform == 'win32', |
|
301 | skip_win32 = skipif(sys.platform == 'win32', | |
302 | "This test does not run under Windows") |
|
302 | "This test does not run under Windows") | |
303 | skip_linux = skipif(sys.platform.startswith('linux'), |
|
303 | skip_linux = skipif(sys.platform.startswith('linux'), | |
304 | "This test does not run under Linux") |
|
304 | "This test does not run under Linux") | |
305 | skip_osx = skipif(sys.platform == 'darwin',"This test does not run under OS X") |
|
305 | skip_osx = skipif(sys.platform == 'darwin',"This test does not run under OS X") | |
306 |
|
306 | |||
307 |
|
307 | |||
308 | # Decorators to skip tests if not on specific platforms. |
|
308 | # Decorators to skip tests if not on specific platforms. | |
309 | skip_if_not_win32 = skipif(sys.platform != 'win32', |
|
309 | skip_if_not_win32 = skipif(sys.platform != 'win32', | |
310 | "This test only runs under Windows") |
|
310 | "This test only runs under Windows") | |
311 | skip_if_not_linux = skipif(not sys.platform.startswith('linux'), |
|
311 | skip_if_not_linux = skipif(not sys.platform.startswith('linux'), | |
312 | "This test only runs under Linux") |
|
312 | "This test only runs under Linux") | |
313 | skip_if_not_osx = skipif(sys.platform != 'darwin', |
|
313 | skip_if_not_osx = skipif(sys.platform != 'darwin', | |
314 | "This test only runs under OSX") |
|
314 | "This test only runs under OSX") | |
315 |
|
315 | |||
316 | # Other skip decorators |
|
316 | # Other skip decorators | |
317 |
|
317 | |||
318 | # generic skip without module |
|
318 | # generic skip without module | |
319 | skip_without = lambda mod: skipif(module_not_available(mod), "This test requires %s" % mod) |
|
319 | skip_without = lambda mod: skipif(module_not_available(mod), "This test requires %s" % mod) | |
320 |
|
320 | |||
321 | skipif_not_numpy = skip_without('numpy') |
|
321 | skipif_not_numpy = skip_without('numpy') | |
322 |
|
322 | |||
323 | skipif_not_matplotlib = skip_without('matplotlib') |
|
323 | skipif_not_matplotlib = skip_without('matplotlib') | |
324 |
|
324 | |||
325 | skipif_not_sympy = skip_without('sympy') |
|
325 | skipif_not_sympy = skip_without('sympy') | |
326 |
|
326 | |||
327 | skip_known_failure = knownfailureif(True,'This test is known to fail') |
|
327 | skip_known_failure = knownfailureif(True,'This test is known to fail') | |
328 |
|
328 | |||
329 | known_failure_py3 = knownfailureif(sys.version_info[0] >= 3, |
|
329 | known_failure_py3 = knownfailureif(sys.version_info[0] >= 3, | |
330 | 'This test is known to fail on Python 3.') |
|
330 | 'This test is known to fail on Python 3.') | |
331 |
|
331 | |||
332 | # A null 'decorator', useful to make more readable code that needs to pick |
|
332 | # A null 'decorator', useful to make more readable code that needs to pick | |
333 | # between different decorators based on OS or other conditions |
|
333 | # between different decorators based on OS or other conditions | |
334 | null_deco = lambda f: f |
|
334 | null_deco = lambda f: f | |
335 |
|
335 | |||
336 | # Some tests only run where we can use unicode paths. Note that we can't just |
|
336 | # Some tests only run where we can use unicode paths. Note that we can't just | |
337 | # check os.path.supports_unicode_filenames, which is always False on Linux. |
|
337 | # check os.path.supports_unicode_filenames, which is always False on Linux. | |
338 | try: |
|
338 | try: | |
339 | f = tempfile.NamedTemporaryFile(prefix=u"tmpβ¬") |
|
339 | f = tempfile.NamedTemporaryFile(prefix=u"tmpβ¬") | |
340 | except UnicodeEncodeError: |
|
340 | except UnicodeEncodeError: | |
341 | unicode_paths = False |
|
341 | unicode_paths = False | |
342 | else: |
|
342 | else: | |
343 | unicode_paths = True |
|
343 | unicode_paths = True | |
344 | f.close() |
|
344 | f.close() | |
345 |
|
345 | |||
346 | onlyif_unicode_paths = onlyif(unicode_paths, ("This test is only applicable " |
|
346 | onlyif_unicode_paths = onlyif(unicode_paths, ("This test is only applicable " | |
347 | "where we can use unicode in filenames.")) |
|
347 | "where we can use unicode in filenames.")) | |
348 |
|
348 | |||
349 |
|
349 | |||
350 | def onlyif_cmds_exist(*commands): |
|
350 | def onlyif_cmds_exist(*commands): | |
351 | """ |
|
351 | """ | |
352 | Decorator to skip test when at least one of `commands` is not found. |
|
352 | Decorator to skip test when at least one of `commands` is not found. | |
353 | """ |
|
353 | """ | |
354 | for cmd in commands: |
|
354 | for cmd in commands: | |
355 | if not is_cmd_found(cmd): |
|
355 | if not is_cmd_found(cmd): | |
356 | return skip("This test runs only if command '{0}' " |
|
356 | return skip("This test runs only if command '{0}' " | |
357 | "is installed".format(cmd)) |
|
357 | "is installed".format(cmd)) | |
358 | return null_deco |
|
358 | return null_deco |
@@ -1,391 +1,392 b'' | |||||
1 | """Generic testing tools. |
|
1 | """Generic testing tools. | |
2 |
|
2 | |||
3 | Authors |
|
3 | Authors | |
4 | ------- |
|
4 | ------- | |
5 | - Fernando Perez <Fernando.Perez@berkeley.edu> |
|
5 | - Fernando Perez <Fernando.Perez@berkeley.edu> | |
6 | """ |
|
6 | """ | |
7 |
|
7 | |||
8 | from __future__ import absolute_import |
|
8 | from __future__ import absolute_import | |
9 |
|
9 | |||
10 | #----------------------------------------------------------------------------- |
|
10 | #----------------------------------------------------------------------------- | |
11 | # Copyright (C) 2009-2011 The IPython Development Team |
|
11 | # Copyright (C) 2009-2011 The IPython Development Team | |
12 | # |
|
12 | # | |
13 | # Distributed under the terms of the BSD License. The full license is in |
|
13 | # Distributed under the terms of the BSD License. The full license is in | |
14 | # the file COPYING, distributed as part of this software. |
|
14 | # the file COPYING, distributed as part of this software. | |
15 | #----------------------------------------------------------------------------- |
|
15 | #----------------------------------------------------------------------------- | |
16 |
|
16 | |||
17 | #----------------------------------------------------------------------------- |
|
17 | #----------------------------------------------------------------------------- | |
18 | # Imports |
|
18 | # Imports | |
19 | #----------------------------------------------------------------------------- |
|
19 | #----------------------------------------------------------------------------- | |
20 |
|
20 | |||
21 | import os |
|
21 | import os | |
22 | import re |
|
22 | import re | |
23 | import sys |
|
23 | import sys | |
24 | import tempfile |
|
24 | import tempfile | |
25 |
|
25 | |||
26 | from contextlib import contextmanager |
|
26 | from contextlib import contextmanager | |
27 | from io import StringIO |
|
27 | from io import StringIO | |
28 |
|
28 | |||
29 | try: |
|
29 | try: | |
30 | # These tools are used by parts of the runtime, so we make the nose |
|
30 | # These tools are used by parts of the runtime, so we make the nose | |
31 | # dependency optional at this point. Nose is a hard dependency to run the |
|
31 | # dependency optional at this point. Nose is a hard dependency to run the | |
32 | # test suite, but NOT to use ipython itself. |
|
32 | # test suite, but NOT to use ipython itself. | |
33 | import nose.tools as nt |
|
33 | import nose.tools as nt | |
34 | has_nose = True |
|
34 | has_nose = True | |
35 | except ImportError: |
|
35 | except ImportError: | |
36 | has_nose = False |
|
36 | has_nose = False | |
37 |
|
37 | |||
38 | from IPython.config.loader import Config |
|
38 | from IPython.config.loader import Config | |
39 | from IPython.utils.process import find_cmd, getoutputerror |
|
39 | from IPython.utils.process import find_cmd, getoutputerror | |
40 | from IPython.utils.text import list_strings |
|
40 | from IPython.utils.text import list_strings | |
41 | from IPython.utils.io import temp_pyfile, Tee |
|
41 | from IPython.utils.io import temp_pyfile, Tee | |
42 | from IPython.utils import py3compat |
|
42 | from IPython.utils import py3compat | |
43 | from IPython.utils.encoding import DEFAULT_ENCODING |
|
43 | from IPython.utils.encoding import DEFAULT_ENCODING | |
44 |
|
44 | |||
45 | from . import decorators as dec |
|
45 | from . import decorators as dec | |
46 | from . import skipdoctest |
|
46 | from . import skipdoctest | |
47 |
|
47 | |||
48 | #----------------------------------------------------------------------------- |
|
48 | #----------------------------------------------------------------------------- | |
49 | # Functions and classes |
|
49 | # Functions and classes | |
50 | #----------------------------------------------------------------------------- |
|
50 | #----------------------------------------------------------------------------- | |
51 |
|
51 | |||
52 | # The docstring for full_path doctests differently on win32 (different path |
|
52 | # The docstring for full_path doctests differently on win32 (different path | |
53 | # separator) so just skip the doctest there. The example remains informative. |
|
53 | # separator) so just skip the doctest there. The example remains informative. | |
54 | doctest_deco = skipdoctest.skip_doctest if sys.platform == 'win32' else dec.null_deco |
|
54 | doctest_deco = skipdoctest.skip_doctest if sys.platform == 'win32' else dec.null_deco | |
55 |
|
55 | |||
56 | @doctest_deco |
|
56 | @doctest_deco | |
57 | def full_path(startPath,files): |
|
57 | def full_path(startPath,files): | |
58 | """Make full paths for all the listed files, based on startPath. |
|
58 | """Make full paths for all the listed files, based on startPath. | |
59 |
|
59 | |||
60 | Only the base part of startPath is kept, since this routine is typically |
|
60 | Only the base part of startPath is kept, since this routine is typically | |
61 | used with a script's __file__ variable as startPath. The base of startPath |
|
61 | used with a script's __file__ variable as startPath. The base of startPath | |
62 | is then prepended to all the listed files, forming the output list. |
|
62 | is then prepended to all the listed files, forming the output list. | |
63 |
|
63 | |||
64 | Parameters |
|
64 | Parameters | |
65 | ---------- |
|
65 | ---------- | |
66 | startPath : string |
|
66 | startPath : string | |
67 | Initial path to use as the base for the results. This path is split |
|
67 | Initial path to use as the base for the results. This path is split | |
68 | using os.path.split() and only its first component is kept. |
|
68 | using os.path.split() and only its first component is kept. | |
69 |
|
69 | |||
70 | files : string or list |
|
70 | files : string or list | |
71 | One or more files. |
|
71 | One or more files. | |
72 |
|
72 | |||
73 | Examples |
|
73 | Examples | |
74 | -------- |
|
74 | -------- | |
75 |
|
75 | |||
76 | >>> full_path('/foo/bar.py',['a.txt','b.txt']) |
|
76 | >>> full_path('/foo/bar.py',['a.txt','b.txt']) | |
77 | ['/foo/a.txt', '/foo/b.txt'] |
|
77 | ['/foo/a.txt', '/foo/b.txt'] | |
78 |
|
78 | |||
79 | >>> full_path('/foo',['a.txt','b.txt']) |
|
79 | >>> full_path('/foo',['a.txt','b.txt']) | |
80 | ['/a.txt', '/b.txt'] |
|
80 | ['/a.txt', '/b.txt'] | |
81 |
|
81 | |||
82 | If a single file is given, the output is still a list: |
|
82 | If a single file is given, the output is still a list: | |
83 | >>> full_path('/foo','a.txt') |
|
83 | >>> full_path('/foo','a.txt') | |
84 | ['/a.txt'] |
|
84 | ['/a.txt'] | |
85 | """ |
|
85 | """ | |
86 |
|
86 | |||
87 | files = list_strings(files) |
|
87 | files = list_strings(files) | |
88 | base = os.path.split(startPath)[0] |
|
88 | base = os.path.split(startPath)[0] | |
89 | return [ os.path.join(base,f) for f in files ] |
|
89 | return [ os.path.join(base,f) for f in files ] | |
90 |
|
90 | |||
91 |
|
91 | |||
92 | def parse_test_output(txt): |
|
92 | def parse_test_output(txt): | |
93 | """Parse the output of a test run and return errors, failures. |
|
93 | """Parse the output of a test run and return errors, failures. | |
94 |
|
94 | |||
95 | Parameters |
|
95 | Parameters | |
96 | ---------- |
|
96 | ---------- | |
97 | txt : str |
|
97 | txt : str | |
98 | Text output of a test run, assumed to contain a line of one of the |
|
98 | Text output of a test run, assumed to contain a line of one of the | |
99 | following forms:: |
|
99 | following forms:: | |
|
100 | ||||
100 | 'FAILED (errors=1)' |
|
101 | 'FAILED (errors=1)' | |
101 | 'FAILED (failures=1)' |
|
102 | 'FAILED (failures=1)' | |
102 | 'FAILED (errors=1, failures=1)' |
|
103 | 'FAILED (errors=1, failures=1)' | |
103 |
|
104 | |||
104 | Returns |
|
105 | Returns | |
105 | ------- |
|
106 | ------- | |
106 | nerr, nfail: number of errors and failures. |
|
107 | nerr, nfail: number of errors and failures. | |
107 | """ |
|
108 | """ | |
108 |
|
109 | |||
109 | err_m = re.search(r'^FAILED \(errors=(\d+)\)', txt, re.MULTILINE) |
|
110 | err_m = re.search(r'^FAILED \(errors=(\d+)\)', txt, re.MULTILINE) | |
110 | if err_m: |
|
111 | if err_m: | |
111 | nerr = int(err_m.group(1)) |
|
112 | nerr = int(err_m.group(1)) | |
112 | nfail = 0 |
|
113 | nfail = 0 | |
113 | return nerr, nfail |
|
114 | return nerr, nfail | |
114 |
|
115 | |||
115 | fail_m = re.search(r'^FAILED \(failures=(\d+)\)', txt, re.MULTILINE) |
|
116 | fail_m = re.search(r'^FAILED \(failures=(\d+)\)', txt, re.MULTILINE) | |
116 | if fail_m: |
|
117 | if fail_m: | |
117 | nerr = 0 |
|
118 | nerr = 0 | |
118 | nfail = int(fail_m.group(1)) |
|
119 | nfail = int(fail_m.group(1)) | |
119 | return nerr, nfail |
|
120 | return nerr, nfail | |
120 |
|
121 | |||
121 | both_m = re.search(r'^FAILED \(errors=(\d+), failures=(\d+)\)', txt, |
|
122 | both_m = re.search(r'^FAILED \(errors=(\d+), failures=(\d+)\)', txt, | |
122 | re.MULTILINE) |
|
123 | re.MULTILINE) | |
123 | if both_m: |
|
124 | if both_m: | |
124 | nerr = int(both_m.group(1)) |
|
125 | nerr = int(both_m.group(1)) | |
125 | nfail = int(both_m.group(2)) |
|
126 | nfail = int(both_m.group(2)) | |
126 | return nerr, nfail |
|
127 | return nerr, nfail | |
127 |
|
128 | |||
128 | # If the input didn't match any of these forms, assume no error/failures |
|
129 | # If the input didn't match any of these forms, assume no error/failures | |
129 | return 0, 0 |
|
130 | return 0, 0 | |
130 |
|
131 | |||
131 |
|
132 | |||
132 | # So nose doesn't think this is a test |
|
133 | # So nose doesn't think this is a test | |
133 | parse_test_output.__test__ = False |
|
134 | parse_test_output.__test__ = False | |
134 |
|
135 | |||
135 |
|
136 | |||
136 | def default_argv(): |
|
137 | def default_argv(): | |
137 | """Return a valid default argv for creating testing instances of ipython""" |
|
138 | """Return a valid default argv for creating testing instances of ipython""" | |
138 |
|
139 | |||
139 | return ['--quick', # so no config file is loaded |
|
140 | return ['--quick', # so no config file is loaded | |
140 | # Other defaults to minimize side effects on stdout |
|
141 | # Other defaults to minimize side effects on stdout | |
141 | '--colors=NoColor', '--no-term-title','--no-banner', |
|
142 | '--colors=NoColor', '--no-term-title','--no-banner', | |
142 | '--autocall=0'] |
|
143 | '--autocall=0'] | |
143 |
|
144 | |||
144 |
|
145 | |||
145 | def default_config(): |
|
146 | def default_config(): | |
146 | """Return a config object with good defaults for testing.""" |
|
147 | """Return a config object with good defaults for testing.""" | |
147 | config = Config() |
|
148 | config = Config() | |
148 | config.TerminalInteractiveShell.colors = 'NoColor' |
|
149 | config.TerminalInteractiveShell.colors = 'NoColor' | |
149 | config.TerminalTerminalInteractiveShell.term_title = False, |
|
150 | config.TerminalTerminalInteractiveShell.term_title = False, | |
150 | config.TerminalInteractiveShell.autocall = 0 |
|
151 | config.TerminalInteractiveShell.autocall = 0 | |
151 | config.HistoryManager.hist_file = tempfile.mktemp(u'test_hist.sqlite') |
|
152 | config.HistoryManager.hist_file = tempfile.mktemp(u'test_hist.sqlite') | |
152 | config.HistoryManager.db_cache_size = 10000 |
|
153 | config.HistoryManager.db_cache_size = 10000 | |
153 | return config |
|
154 | return config | |
154 |
|
155 | |||
155 |
|
156 | |||
156 | def ipexec(fname, options=None): |
|
157 | def ipexec(fname, options=None): | |
157 | """Utility to call 'ipython filename'. |
|
158 | """Utility to call 'ipython filename'. | |
158 |
|
159 | |||
159 | Starts IPython witha minimal and safe configuration to make startup as fast |
|
160 | Starts IPython witha minimal and safe configuration to make startup as fast | |
160 | as possible. |
|
161 | as possible. | |
161 |
|
162 | |||
162 | Note that this starts IPython in a subprocess! |
|
163 | Note that this starts IPython in a subprocess! | |
163 |
|
164 | |||
164 | Parameters |
|
165 | Parameters | |
165 | ---------- |
|
166 | ---------- | |
166 | fname : str |
|
167 | fname : str | |
167 | Name of file to be executed (should have .py or .ipy extension). |
|
168 | Name of file to be executed (should have .py or .ipy extension). | |
168 |
|
169 | |||
169 | options : optional, list |
|
170 | options : optional, list | |
170 | Extra command-line flags to be passed to IPython. |
|
171 | Extra command-line flags to be passed to IPython. | |
171 |
|
172 | |||
172 | Returns |
|
173 | Returns | |
173 | ------- |
|
174 | ------- | |
174 | (stdout, stderr) of ipython subprocess. |
|
175 | (stdout, stderr) of ipython subprocess. | |
175 | """ |
|
176 | """ | |
176 | if options is None: options = [] |
|
177 | if options is None: options = [] | |
177 |
|
178 | |||
178 | # For these subprocess calls, eliminate all prompt printing so we only see |
|
179 | # For these subprocess calls, eliminate all prompt printing so we only see | |
179 | # output from script execution |
|
180 | # output from script execution | |
180 | prompt_opts = [ '--PromptManager.in_template=""', |
|
181 | prompt_opts = [ '--PromptManager.in_template=""', | |
181 | '--PromptManager.in2_template=""', |
|
182 | '--PromptManager.in2_template=""', | |
182 | '--PromptManager.out_template=""' |
|
183 | '--PromptManager.out_template=""' | |
183 | ] |
|
184 | ] | |
184 | cmdargs = ' '.join(default_argv() + prompt_opts + options) |
|
185 | cmdargs = ' '.join(default_argv() + prompt_opts + options) | |
185 |
|
186 | |||
186 | _ip = get_ipython() |
|
187 | _ip = get_ipython() | |
187 | test_dir = os.path.dirname(__file__) |
|
188 | test_dir = os.path.dirname(__file__) | |
188 |
|
189 | |||
189 | ipython_cmd = find_cmd('ipython3' if py3compat.PY3 else 'ipython') |
|
190 | ipython_cmd = find_cmd('ipython3' if py3compat.PY3 else 'ipython') | |
190 | # Absolute path for filename |
|
191 | # Absolute path for filename | |
191 | full_fname = os.path.join(test_dir, fname) |
|
192 | full_fname = os.path.join(test_dir, fname) | |
192 | full_cmd = '%s %s %s' % (ipython_cmd, cmdargs, full_fname) |
|
193 | full_cmd = '%s %s %s' % (ipython_cmd, cmdargs, full_fname) | |
193 | #print >> sys.stderr, 'FULL CMD:', full_cmd # dbg |
|
194 | #print >> sys.stderr, 'FULL CMD:', full_cmd # dbg | |
194 | out, err = getoutputerror(full_cmd) |
|
195 | out, err = getoutputerror(full_cmd) | |
195 | # `import readline` causes 'ESC[?1034h' to be output sometimes, |
|
196 | # `import readline` causes 'ESC[?1034h' to be output sometimes, | |
196 | # so strip that out before doing comparisons |
|
197 | # so strip that out before doing comparisons | |
197 | if out: |
|
198 | if out: | |
198 | out = re.sub(r'\x1b\[[^h]+h', '', out) |
|
199 | out = re.sub(r'\x1b\[[^h]+h', '', out) | |
199 | return out, err |
|
200 | return out, err | |
200 |
|
201 | |||
201 |
|
202 | |||
202 | def ipexec_validate(fname, expected_out, expected_err='', |
|
203 | def ipexec_validate(fname, expected_out, expected_err='', | |
203 | options=None): |
|
204 | options=None): | |
204 | """Utility to call 'ipython filename' and validate output/error. |
|
205 | """Utility to call 'ipython filename' and validate output/error. | |
205 |
|
206 | |||
206 | This function raises an AssertionError if the validation fails. |
|
207 | This function raises an AssertionError if the validation fails. | |
207 |
|
208 | |||
208 | Note that this starts IPython in a subprocess! |
|
209 | Note that this starts IPython in a subprocess! | |
209 |
|
210 | |||
210 | Parameters |
|
211 | Parameters | |
211 | ---------- |
|
212 | ---------- | |
212 | fname : str |
|
213 | fname : str | |
213 | Name of the file to be executed (should have .py or .ipy extension). |
|
214 | Name of the file to be executed (should have .py or .ipy extension). | |
214 |
|
215 | |||
215 | expected_out : str |
|
216 | expected_out : str | |
216 | Expected stdout of the process. |
|
217 | Expected stdout of the process. | |
217 |
|
218 | |||
218 | expected_err : optional, str |
|
219 | expected_err : optional, str | |
219 | Expected stderr of the process. |
|
220 | Expected stderr of the process. | |
220 |
|
221 | |||
221 | options : optional, list |
|
222 | options : optional, list | |
222 | Extra command-line flags to be passed to IPython. |
|
223 | Extra command-line flags to be passed to IPython. | |
223 |
|
224 | |||
224 | Returns |
|
225 | Returns | |
225 | ------- |
|
226 | ------- | |
226 | None |
|
227 | None | |
227 | """ |
|
228 | """ | |
228 |
|
229 | |||
229 | import nose.tools as nt |
|
230 | import nose.tools as nt | |
230 |
|
231 | |||
231 | out, err = ipexec(fname, options) |
|
232 | out, err = ipexec(fname, options) | |
232 | #print 'OUT', out # dbg |
|
233 | #print 'OUT', out # dbg | |
233 | #print 'ERR', err # dbg |
|
234 | #print 'ERR', err # dbg | |
234 | # If there are any errors, we must check those befor stdout, as they may be |
|
235 | # If there are any errors, we must check those befor stdout, as they may be | |
235 | # more informative than simply having an empty stdout. |
|
236 | # more informative than simply having an empty stdout. | |
236 | if err: |
|
237 | if err: | |
237 | if expected_err: |
|
238 | if expected_err: | |
238 | nt.assert_equal("\n".join(err.strip().splitlines()), "\n".join(expected_err.strip().splitlines())) |
|
239 | nt.assert_equal("\n".join(err.strip().splitlines()), "\n".join(expected_err.strip().splitlines())) | |
239 | else: |
|
240 | else: | |
240 | raise ValueError('Running file %r produced error: %r' % |
|
241 | raise ValueError('Running file %r produced error: %r' % | |
241 | (fname, err)) |
|
242 | (fname, err)) | |
242 | # If no errors or output on stderr was expected, match stdout |
|
243 | # If no errors or output on stderr was expected, match stdout | |
243 | nt.assert_equal("\n".join(out.strip().splitlines()), "\n".join(expected_out.strip().splitlines())) |
|
244 | nt.assert_equal("\n".join(out.strip().splitlines()), "\n".join(expected_out.strip().splitlines())) | |
244 |
|
245 | |||
245 |
|
246 | |||
246 | class TempFileMixin(object): |
|
247 | class TempFileMixin(object): | |
247 | """Utility class to create temporary Python/IPython files. |
|
248 | """Utility class to create temporary Python/IPython files. | |
248 |
|
249 | |||
249 | Meant as a mixin class for test cases.""" |
|
250 | Meant as a mixin class for test cases.""" | |
250 |
|
251 | |||
251 | def mktmp(self, src, ext='.py'): |
|
252 | def mktmp(self, src, ext='.py'): | |
252 | """Make a valid python temp file.""" |
|
253 | """Make a valid python temp file.""" | |
253 | fname, f = temp_pyfile(src, ext) |
|
254 | fname, f = temp_pyfile(src, ext) | |
254 | self.tmpfile = f |
|
255 | self.tmpfile = f | |
255 | self.fname = fname |
|
256 | self.fname = fname | |
256 |
|
257 | |||
257 | def tearDown(self): |
|
258 | def tearDown(self): | |
258 | if hasattr(self, 'tmpfile'): |
|
259 | if hasattr(self, 'tmpfile'): | |
259 | # If the tmpfile wasn't made because of skipped tests, like in |
|
260 | # If the tmpfile wasn't made because of skipped tests, like in | |
260 | # win32, there's nothing to cleanup. |
|
261 | # win32, there's nothing to cleanup. | |
261 | self.tmpfile.close() |
|
262 | self.tmpfile.close() | |
262 | try: |
|
263 | try: | |
263 | os.unlink(self.fname) |
|
264 | os.unlink(self.fname) | |
264 | except: |
|
265 | except: | |
265 | # On Windows, even though we close the file, we still can't |
|
266 | # On Windows, even though we close the file, we still can't | |
266 | # delete it. I have no clue why |
|
267 | # delete it. I have no clue why | |
267 | pass |
|
268 | pass | |
268 |
|
269 | |||
269 | pair_fail_msg = ("Testing {0}\n\n" |
|
270 | pair_fail_msg = ("Testing {0}\n\n" | |
270 | "In:\n" |
|
271 | "In:\n" | |
271 | " {1!r}\n" |
|
272 | " {1!r}\n" | |
272 | "Expected:\n" |
|
273 | "Expected:\n" | |
273 | " {2!r}\n" |
|
274 | " {2!r}\n" | |
274 | "Got:\n" |
|
275 | "Got:\n" | |
275 | " {3!r}\n") |
|
276 | " {3!r}\n") | |
276 | def check_pairs(func, pairs): |
|
277 | def check_pairs(func, pairs): | |
277 | """Utility function for the common case of checking a function with a |
|
278 | """Utility function for the common case of checking a function with a | |
278 | sequence of input/output pairs. |
|
279 | sequence of input/output pairs. | |
279 |
|
280 | |||
280 | Parameters |
|
281 | Parameters | |
281 | ---------- |
|
282 | ---------- | |
282 | func : callable |
|
283 | func : callable | |
283 | The function to be tested. Should accept a single argument. |
|
284 | The function to be tested. Should accept a single argument. | |
284 | pairs : iterable |
|
285 | pairs : iterable | |
285 | A list of (input, expected_output) tuples. |
|
286 | A list of (input, expected_output) tuples. | |
286 |
|
287 | |||
287 | Returns |
|
288 | Returns | |
288 | ------- |
|
289 | ------- | |
289 | None. Raises an AssertionError if any output does not match the expected |
|
290 | None. Raises an AssertionError if any output does not match the expected | |
290 | value. |
|
291 | value. | |
291 | """ |
|
292 | """ | |
292 | name = getattr(func, "func_name", getattr(func, "__name__", "<unknown>")) |
|
293 | name = getattr(func, "func_name", getattr(func, "__name__", "<unknown>")) | |
293 | for inp, expected in pairs: |
|
294 | for inp, expected in pairs: | |
294 | out = func(inp) |
|
295 | out = func(inp) | |
295 | assert out == expected, pair_fail_msg.format(name, inp, expected, out) |
|
296 | assert out == expected, pair_fail_msg.format(name, inp, expected, out) | |
296 |
|
297 | |||
297 |
|
298 | |||
298 | if py3compat.PY3: |
|
299 | if py3compat.PY3: | |
299 | MyStringIO = StringIO |
|
300 | MyStringIO = StringIO | |
300 | else: |
|
301 | else: | |
301 | # In Python 2, stdout/stderr can have either bytes or unicode written to them, |
|
302 | # In Python 2, stdout/stderr can have either bytes or unicode written to them, | |
302 | # so we need a class that can handle both. |
|
303 | # so we need a class that can handle both. | |
303 | class MyStringIO(StringIO): |
|
304 | class MyStringIO(StringIO): | |
304 | def write(self, s): |
|
305 | def write(self, s): | |
305 | s = py3compat.cast_unicode(s, encoding=DEFAULT_ENCODING) |
|
306 | s = py3compat.cast_unicode(s, encoding=DEFAULT_ENCODING) | |
306 | super(MyStringIO, self).write(s) |
|
307 | super(MyStringIO, self).write(s) | |
307 |
|
308 | |||
308 | notprinted_msg = """Did not find {0!r} in printed output (on {1}): |
|
309 | notprinted_msg = """Did not find {0!r} in printed output (on {1}): | |
309 | ------- |
|
310 | ------- | |
310 | {2!s} |
|
311 | {2!s} | |
311 | ------- |
|
312 | ------- | |
312 | """ |
|
313 | """ | |
313 |
|
314 | |||
314 | class AssertPrints(object): |
|
315 | class AssertPrints(object): | |
315 | """Context manager for testing that code prints certain text. |
|
316 | """Context manager for testing that code prints certain text. | |
316 |
|
317 | |||
317 | Examples |
|
318 | Examples | |
318 | -------- |
|
319 | -------- | |
319 | >>> with AssertPrints("abc", suppress=False): |
|
320 | >>> with AssertPrints("abc", suppress=False): | |
320 | ... print "abcd" |
|
321 | ... print "abcd" | |
321 | ... print "def" |
|
322 | ... print "def" | |
322 | ... |
|
323 | ... | |
323 | abcd |
|
324 | abcd | |
324 | def |
|
325 | def | |
325 | """ |
|
326 | """ | |
326 | def __init__(self, s, channel='stdout', suppress=True): |
|
327 | def __init__(self, s, channel='stdout', suppress=True): | |
327 | self.s = s |
|
328 | self.s = s | |
328 | self.channel = channel |
|
329 | self.channel = channel | |
329 | self.suppress = suppress |
|
330 | self.suppress = suppress | |
330 |
|
331 | |||
331 | def __enter__(self): |
|
332 | def __enter__(self): | |
332 | self.orig_stream = getattr(sys, self.channel) |
|
333 | self.orig_stream = getattr(sys, self.channel) | |
333 | self.buffer = MyStringIO() |
|
334 | self.buffer = MyStringIO() | |
334 | self.tee = Tee(self.buffer, channel=self.channel) |
|
335 | self.tee = Tee(self.buffer, channel=self.channel) | |
335 | setattr(sys, self.channel, self.buffer if self.suppress else self.tee) |
|
336 | setattr(sys, self.channel, self.buffer if self.suppress else self.tee) | |
336 |
|
337 | |||
337 | def __exit__(self, etype, value, traceback): |
|
338 | def __exit__(self, etype, value, traceback): | |
338 | self.tee.flush() |
|
339 | self.tee.flush() | |
339 | setattr(sys, self.channel, self.orig_stream) |
|
340 | setattr(sys, self.channel, self.orig_stream) | |
340 | printed = self.buffer.getvalue() |
|
341 | printed = self.buffer.getvalue() | |
341 | assert self.s in printed, notprinted_msg.format(self.s, self.channel, printed) |
|
342 | assert self.s in printed, notprinted_msg.format(self.s, self.channel, printed) | |
342 | return False |
|
343 | return False | |
343 |
|
344 | |||
344 | printed_msg = """Found {0!r} in printed output (on {1}): |
|
345 | printed_msg = """Found {0!r} in printed output (on {1}): | |
345 | ------- |
|
346 | ------- | |
346 | {2!s} |
|
347 | {2!s} | |
347 | ------- |
|
348 | ------- | |
348 | """ |
|
349 | """ | |
349 |
|
350 | |||
350 | class AssertNotPrints(AssertPrints): |
|
351 | class AssertNotPrints(AssertPrints): | |
351 | """Context manager for checking that certain output *isn't* produced. |
|
352 | """Context manager for checking that certain output *isn't* produced. | |
352 |
|
353 | |||
353 | Counterpart of AssertPrints""" |
|
354 | Counterpart of AssertPrints""" | |
354 | def __exit__(self, etype, value, traceback): |
|
355 | def __exit__(self, etype, value, traceback): | |
355 | self.tee.flush() |
|
356 | self.tee.flush() | |
356 | setattr(sys, self.channel, self.orig_stream) |
|
357 | setattr(sys, self.channel, self.orig_stream) | |
357 | printed = self.buffer.getvalue() |
|
358 | printed = self.buffer.getvalue() | |
358 | assert self.s not in printed, printed_msg.format(self.s, self.channel, printed) |
|
359 | assert self.s not in printed, printed_msg.format(self.s, self.channel, printed) | |
359 | return False |
|
360 | return False | |
360 |
|
361 | |||
361 | @contextmanager |
|
362 | @contextmanager | |
362 | def mute_warn(): |
|
363 | def mute_warn(): | |
363 | from IPython.utils import warn |
|
364 | from IPython.utils import warn | |
364 | save_warn = warn.warn |
|
365 | save_warn = warn.warn | |
365 | warn.warn = lambda *a, **kw: None |
|
366 | warn.warn = lambda *a, **kw: None | |
366 | try: |
|
367 | try: | |
367 | yield |
|
368 | yield | |
368 | finally: |
|
369 | finally: | |
369 | warn.warn = save_warn |
|
370 | warn.warn = save_warn | |
370 |
|
371 | |||
371 | @contextmanager |
|
372 | @contextmanager | |
372 | def make_tempfile(name): |
|
373 | def make_tempfile(name): | |
373 | """ Create an empty, named, temporary file for the duration of the context. |
|
374 | """ Create an empty, named, temporary file for the duration of the context. | |
374 | """ |
|
375 | """ | |
375 | f = open(name, 'w') |
|
376 | f = open(name, 'w') | |
376 | f.close() |
|
377 | f.close() | |
377 | try: |
|
378 | try: | |
378 | yield |
|
379 | yield | |
379 | finally: |
|
380 | finally: | |
380 | os.unlink(name) |
|
381 | os.unlink(name) | |
381 |
|
382 | |||
382 |
|
383 | |||
383 | @contextmanager |
|
384 | @contextmanager | |
384 | def monkeypatch(obj, name, attr): |
|
385 | def monkeypatch(obj, name, attr): | |
385 | """ |
|
386 | """ | |
386 | Context manager to replace attribute named `name` in `obj` with `attr`. |
|
387 | Context manager to replace attribute named `name` in `obj` with `attr`. | |
387 | """ |
|
388 | """ | |
388 | orig = getattr(obj, name) |
|
389 | orig = getattr(obj, name) | |
389 | setattr(obj, name, attr) |
|
390 | setattr(obj, name, attr) | |
390 | yield |
|
391 | yield | |
391 | setattr(obj, name, orig) |
|
392 | setattr(obj, name, orig) |
@@ -1,56 +1,56 b'' | |||||
1 | # coding: utf-8 |
|
1 | # coding: utf-8 | |
2 | """ |
|
2 | """ | |
3 | Utilities for dealing with text encodings |
|
3 | Utilities for dealing with text encodings | |
4 | """ |
|
4 | """ | |
5 |
|
5 | |||
6 | #----------------------------------------------------------------------------- |
|
6 | #----------------------------------------------------------------------------- | |
7 | # Copyright (C) 2008-2012 The IPython Development Team |
|
7 | # Copyright (C) 2008-2012 The IPython Development Team | |
8 | # |
|
8 | # | |
9 | # Distributed under the terms of the BSD License. The full license is in |
|
9 | # Distributed under the terms of the BSD License. The full license is in | |
10 | # the file COPYING, distributed as part of this software. |
|
10 | # the file COPYING, distributed as part of this software. | |
11 | #----------------------------------------------------------------------------- |
|
11 | #----------------------------------------------------------------------------- | |
12 |
|
12 | |||
13 | #----------------------------------------------------------------------------- |
|
13 | #----------------------------------------------------------------------------- | |
14 | # Imports |
|
14 | # Imports | |
15 | #----------------------------------------------------------------------------- |
|
15 | #----------------------------------------------------------------------------- | |
16 | import sys |
|
16 | import sys | |
17 | import locale |
|
17 | import locale | |
18 |
|
18 | |||
19 | # to deal with the possibility of sys.std* not being a stream at all |
|
19 | # to deal with the possibility of sys.std* not being a stream at all | |
20 | def get_stream_enc(stream, default=None): |
|
20 | def get_stream_enc(stream, default=None): | |
21 | """Return the given stream's encoding or a default. |
|
21 | """Return the given stream's encoding or a default. | |
22 |
|
22 | |||
23 | There are cases where sys.std* might not actually be a stream, so |
|
23 | There are cases where ``sys.std*`` might not actually be a stream, so | |
24 | check for the encoding attribute prior to returning it, and return |
|
24 | check for the encoding attribute prior to returning it, and return | |
25 |
a default if it doesn't exist or evaluates as False. `default |
|
25 | a default if it doesn't exist or evaluates as False. ``default`` | |
26 | is None if not provided. |
|
26 | is None if not provided. | |
27 | """ |
|
27 | """ | |
28 | if not hasattr(stream, 'encoding') or not stream.encoding: |
|
28 | if not hasattr(stream, 'encoding') or not stream.encoding: | |
29 | return default |
|
29 | return default | |
30 | else: |
|
30 | else: | |
31 | return stream.encoding |
|
31 | return stream.encoding | |
32 |
|
32 | |||
33 | # Less conservative replacement for sys.getdefaultencoding, that will try |
|
33 | # Less conservative replacement for sys.getdefaultencoding, that will try | |
34 | # to match the environment. |
|
34 | # to match the environment. | |
35 | # Defined here as central function, so if we find better choices, we |
|
35 | # Defined here as central function, so if we find better choices, we | |
36 | # won't need to make changes all over IPython. |
|
36 | # won't need to make changes all over IPython. | |
37 | def getdefaultencoding(): |
|
37 | def getdefaultencoding(): | |
38 | """Return IPython's guess for the default encoding for bytes as text. |
|
38 | """Return IPython's guess for the default encoding for bytes as text. | |
39 |
|
39 | |||
40 | Asks for stdin.encoding first, to match the calling Terminal, but that |
|
40 | Asks for stdin.encoding first, to match the calling Terminal, but that | |
41 | is often None for subprocesses. Fall back on locale.getpreferredencoding() |
|
41 | is often None for subprocesses. Fall back on locale.getpreferredencoding() | |
42 | which should be a sensible platform default (that respects LANG environment), |
|
42 | which should be a sensible platform default (that respects LANG environment), | |
43 | and finally to sys.getdefaultencoding() which is the most conservative option, |
|
43 | and finally to sys.getdefaultencoding() which is the most conservative option, | |
44 | and usually ASCII. |
|
44 | and usually ASCII. | |
45 | """ |
|
45 | """ | |
46 | enc = get_stream_enc(sys.stdin) |
|
46 | enc = get_stream_enc(sys.stdin) | |
47 | if not enc or enc=='ascii': |
|
47 | if not enc or enc=='ascii': | |
48 | try: |
|
48 | try: | |
49 | # There are reports of getpreferredencoding raising errors |
|
49 | # There are reports of getpreferredencoding raising errors | |
50 | # in some cases, which may well be fixed, but let's be conservative here. |
|
50 | # in some cases, which may well be fixed, but let's be conservative here. | |
51 | enc = locale.getpreferredencoding() |
|
51 | enc = locale.getpreferredencoding() | |
52 | except Exception: |
|
52 | except Exception: | |
53 | pass |
|
53 | pass | |
54 | return enc or sys.getdefaultencoding() |
|
54 | return enc or sys.getdefaultencoding() | |
55 |
|
55 | |||
56 | DEFAULT_ENCODING = getdefaultencoding() |
|
56 | DEFAULT_ENCODING = getdefaultencoding() |
@@ -1,50 +1,50 b'' | |||||
1 | """Backwards compatibility - we use contextlib.nested to support Python 2.6, |
|
1 | """Backwards compatibility - we use contextlib.nested to support Python 2.6, | |
2 | but it's removed in Python 3.2.""" |
|
2 | but it's removed in Python 3.2.""" | |
3 |
|
3 | |||
4 | # TODO : Remove this once we drop support for Python 2.6, and use |
|
4 | # TODO : Remove this once we drop support for Python 2.6, and use | |
5 | # "with a, b:" instead. |
|
5 | # "with a, b:" instead. | |
6 |
|
6 | |||
7 | import sys |
|
7 | import sys | |
8 |
|
8 | |||
9 | from contextlib import contextmanager |
|
9 | from contextlib import contextmanager | |
10 |
|
10 | |||
11 | @contextmanager |
|
11 | @contextmanager | |
12 | def nested(*managers): |
|
12 | def nested(*managers): | |
13 | """Combine multiple context managers into a single nested context manager. |
|
13 | """Combine multiple context managers into a single nested context manager. | |
14 |
|
14 | |||
15 | This function has been deprecated in favour of the multiple manager form |
|
15 | This function has been deprecated in favour of the multiple manager form | |
16 | of the with statement. |
|
16 | of the with statement. | |
17 |
|
17 | |||
18 | The one advantage of this function over the multiple manager form of the |
|
18 | The one advantage of this function over the multiple manager form of the | |
19 | with statement is that argument unpacking allows it to be |
|
19 | with statement is that argument unpacking allows it to be | |
20 | used with a variable number of context managers as follows: |
|
20 | used with a variable number of context managers as follows:: | |
21 |
|
21 | |||
22 | with nested(*managers): |
|
22 | with nested(*managers): | |
23 | do_something() |
|
23 | do_something() | |
24 |
|
24 | |||
25 | """ |
|
25 | """ | |
26 | exits = [] |
|
26 | exits = [] | |
27 | vars = [] |
|
27 | vars = [] | |
28 | exc = (None, None, None) |
|
28 | exc = (None, None, None) | |
29 | try: |
|
29 | try: | |
30 | for mgr in managers: |
|
30 | for mgr in managers: | |
31 | exit = mgr.__exit__ |
|
31 | exit = mgr.__exit__ | |
32 | enter = mgr.__enter__ |
|
32 | enter = mgr.__enter__ | |
33 | vars.append(enter()) |
|
33 | vars.append(enter()) | |
34 | exits.append(exit) |
|
34 | exits.append(exit) | |
35 | yield vars |
|
35 | yield vars | |
36 | except: |
|
36 | except: | |
37 | exc = sys.exc_info() |
|
37 | exc = sys.exc_info() | |
38 | finally: |
|
38 | finally: | |
39 | while exits: |
|
39 | while exits: | |
40 | exit = exits.pop() |
|
40 | exit = exits.pop() | |
41 | try: |
|
41 | try: | |
42 | if exit(*exc): |
|
42 | if exit(*exc): | |
43 | exc = (None, None, None) |
|
43 | exc = (None, None, None) | |
44 | except: |
|
44 | except: | |
45 | exc = sys.exc_info() |
|
45 | exc = sys.exc_info() | |
46 | if exc != (None, None, None): |
|
46 | if exc != (None, None, None): | |
47 | # Don't rely on sys.exc_info() still containing |
|
47 | # Don't rely on sys.exc_info() still containing | |
48 | # the right information. Another exception may |
|
48 | # the right information. Another exception may | |
49 | # have been raised and caught by an exit method |
|
49 | # have been raised and caught by an exit method | |
50 | raise exc[0], exc[1], exc[2] |
|
50 | raise exc[0], exc[1], exc[2] |
@@ -1,142 +1,142 b'' | |||||
1 | # encoding: utf-8 |
|
1 | # encoding: utf-8 | |
2 | """ |
|
2 | """ | |
3 | The IPython Core Notification Center. |
|
3 | The IPython Core Notification Center. | |
4 |
|
4 | |||
5 | See docs/source/development/notification_blueprint.txt for an overview of the |
|
5 | See docs/source/development/notification_blueprint.txt for an overview of the | |
6 | notification module. |
|
6 | notification module. | |
7 |
|
7 | |||
8 | Authors: |
|
8 | Authors: | |
9 |
|
9 | |||
10 | * Barry Wark |
|
10 | * Barry Wark | |
11 | * Brian Granger |
|
11 | * Brian Granger | |
12 | """ |
|
12 | """ | |
13 |
|
13 | |||
14 | #----------------------------------------------------------------------------- |
|
14 | #----------------------------------------------------------------------------- | |
15 | # Copyright (C) 2008-2011 The IPython Development Team |
|
15 | # Copyright (C) 2008-2011 The IPython Development Team | |
16 | # |
|
16 | # | |
17 | # Distributed under the terms of the BSD License. The full license is in |
|
17 | # Distributed under the terms of the BSD License. The full license is in | |
18 | # the file COPYING, distributed as part of this software. |
|
18 | # the file COPYING, distributed as part of this software. | |
19 | #----------------------------------------------------------------------------- |
|
19 | #----------------------------------------------------------------------------- | |
20 |
|
20 | |||
21 | #----------------------------------------------------------------------------- |
|
21 | #----------------------------------------------------------------------------- | |
22 | # Code |
|
22 | # Code | |
23 | #----------------------------------------------------------------------------- |
|
23 | #----------------------------------------------------------------------------- | |
24 |
|
24 | |||
25 |
|
25 | |||
26 | class NotificationError(Exception): |
|
26 | class NotificationError(Exception): | |
27 | pass |
|
27 | pass | |
28 |
|
28 | |||
29 |
|
29 | |||
30 | class NotificationCenter(object): |
|
30 | class NotificationCenter(object): | |
31 | """Synchronous notification center. |
|
31 | """Synchronous notification center. | |
32 |
|
32 | |||
33 | Examples |
|
33 | Examples | |
34 | -------- |
|
34 | -------- | |
35 | Here is a simple example of how to use this:: |
|
35 | Here is a simple example of how to use this:: | |
36 |
|
36 | |||
37 | import IPython.util.notification as notification |
|
37 | import IPython.util.notification as notification | |
38 | def callback(ntype, theSender, args={}): |
|
38 | def callback(ntype, theSender, args={}): | |
39 | print ntype,theSender,args |
|
39 | print ntype,theSender,args | |
40 |
|
40 | |||
41 | notification.sharedCenter.add_observer(callback, 'NOTIFICATION_TYPE', None) |
|
41 | notification.sharedCenter.add_observer(callback, 'NOTIFICATION_TYPE', None) | |
42 | notification.sharedCenter.post_notification('NOTIFICATION_TYPE', object()) # doctest:+ELLIPSIS |
|
42 | notification.sharedCenter.post_notification('NOTIFICATION_TYPE', object()) # doctest:+ELLIPSIS | |
43 | NOTIFICATION_TYPE ... |
|
43 | NOTIFICATION_TYPE ... | |
44 | """ |
|
44 | """ | |
45 | def __init__(self): |
|
45 | def __init__(self): | |
46 | super(NotificationCenter, self).__init__() |
|
46 | super(NotificationCenter, self).__init__() | |
47 | self._init_observers() |
|
47 | self._init_observers() | |
48 |
|
48 | |||
49 | def _init_observers(self): |
|
49 | def _init_observers(self): | |
50 | """Initialize observer storage""" |
|
50 | """Initialize observer storage""" | |
51 |
|
51 | |||
52 | self.registered_types = set() #set of types that are observed |
|
52 | self.registered_types = set() #set of types that are observed | |
53 | self.registered_senders = set() #set of senders that are observed |
|
53 | self.registered_senders = set() #set of senders that are observed | |
54 | self.observers = {} #map (type,sender) => callback (callable) |
|
54 | self.observers = {} #map (type,sender) => callback (callable) | |
55 |
|
55 | |||
56 | def post_notification(self, ntype, sender, *args, **kwargs): |
|
56 | def post_notification(self, ntype, sender, *args, **kwargs): | |
57 | """Post notification to all registered observers. |
|
57 | """Post notification to all registered observers. | |
58 |
|
58 | |||
59 | The registered callback will be called as:: |
|
59 | The registered callback will be called as:: | |
60 |
|
60 | |||
61 | callback(ntype, sender, *args, **kwargs) |
|
61 | callback(ntype, sender, *args, **kwargs) | |
62 |
|
62 | |||
63 | Parameters |
|
63 | Parameters | |
64 | ---------- |
|
64 | ---------- | |
65 | ntype : hashable |
|
65 | ntype : hashable | |
66 | The notification type. |
|
66 | The notification type. | |
67 | sender : hashable |
|
67 | sender : hashable | |
68 | The object sending the notification. |
|
68 | The object sending the notification. | |
69 | *args : tuple |
|
69 | *args : tuple | |
70 | The positional arguments to be passed to the callback. |
|
70 | The positional arguments to be passed to the callback. | |
71 | **kwargs : dict |
|
71 | **kwargs : dict | |
72 | The keyword argument to be passed to the callback. |
|
72 | The keyword argument to be passed to the callback. | |
73 |
|
73 | |||
74 | Notes |
|
74 | Notes | |
75 | ----- |
|
75 | ----- | |
76 | * If no registered observers, performance is O(1). |
|
76 | * If no registered observers, performance is O(1). | |
77 | * Notificaiton order is undefined. |
|
77 | * Notificaiton order is undefined. | |
78 | * Notifications are posted synchronously. |
|
78 | * Notifications are posted synchronously. | |
79 | """ |
|
79 | """ | |
80 |
|
80 | |||
81 | if(ntype==None or sender==None): |
|
81 | if(ntype==None or sender==None): | |
82 | raise NotificationError( |
|
82 | raise NotificationError( | |
83 | "Notification type and sender are required.") |
|
83 | "Notification type and sender are required.") | |
84 |
|
84 | |||
85 | # If there are no registered observers for the type/sender pair |
|
85 | # If there are no registered observers for the type/sender pair | |
86 | if((ntype not in self.registered_types and |
|
86 | if((ntype not in self.registered_types and | |
87 | None not in self.registered_types) or |
|
87 | None not in self.registered_types) or | |
88 | (sender not in self.registered_senders and |
|
88 | (sender not in self.registered_senders and | |
89 | None not in self.registered_senders)): |
|
89 | None not in self.registered_senders)): | |
90 | return |
|
90 | return | |
91 |
|
91 | |||
92 | for o in self._observers_for_notification(ntype, sender): |
|
92 | for o in self._observers_for_notification(ntype, sender): | |
93 | o(ntype, sender, *args, **kwargs) |
|
93 | o(ntype, sender, *args, **kwargs) | |
94 |
|
94 | |||
95 | def _observers_for_notification(self, ntype, sender): |
|
95 | def _observers_for_notification(self, ntype, sender): | |
96 | """Find all registered observers that should recieve notification""" |
|
96 | """Find all registered observers that should recieve notification""" | |
97 |
|
97 | |||
98 | keys = ( |
|
98 | keys = ( | |
99 | (ntype,sender), |
|
99 | (ntype,sender), | |
100 | (ntype, None), |
|
100 | (ntype, None), | |
101 | (None, sender), |
|
101 | (None, sender), | |
102 | (None,None) |
|
102 | (None,None) | |
103 | ) |
|
103 | ) | |
104 |
|
104 | |||
105 | obs = set() |
|
105 | obs = set() | |
106 | for k in keys: |
|
106 | for k in keys: | |
107 | obs.update(self.observers.get(k, set())) |
|
107 | obs.update(self.observers.get(k, set())) | |
108 |
|
108 | |||
109 | return obs |
|
109 | return obs | |
110 |
|
110 | |||
111 | def add_observer(self, callback, ntype, sender): |
|
111 | def add_observer(self, callback, ntype, sender): | |
112 | """Add an observer callback to this notification center. |
|
112 | """Add an observer callback to this notification center. | |
113 |
|
113 | |||
114 | The given callback will be called upon posting of notifications of |
|
114 | The given callback will be called upon posting of notifications of | |
115 | the given type/sender and will receive any additional arguments passed |
|
115 | the given type/sender and will receive any additional arguments passed | |
116 | to post_notification. |
|
116 | to post_notification. | |
117 |
|
117 | |||
118 | Parameters |
|
118 | Parameters | |
119 | ---------- |
|
119 | ---------- | |
120 | callback : callable |
|
120 | callback : callable | |
121 | The callable that will be called by :meth:`post_notification` |
|
121 | The callable that will be called by :meth:`post_notification` | |
122 | as ``callback(ntype, sender, *args, **kwargs) |
|
122 | as ``callback(ntype, sender, *args, **kwargs)`` | |
123 | ntype : hashable |
|
123 | ntype : hashable | |
124 | The notification type. If None, all notifications from sender |
|
124 | The notification type. If None, all notifications from sender | |
125 | will be posted. |
|
125 | will be posted. | |
126 | sender : hashable |
|
126 | sender : hashable | |
127 | The notification sender. If None, all notifications of ntype |
|
127 | The notification sender. If None, all notifications of ntype | |
128 | will be posted. |
|
128 | will be posted. | |
129 | """ |
|
129 | """ | |
130 | assert(callback != None) |
|
130 | assert(callback != None) | |
131 | self.registered_types.add(ntype) |
|
131 | self.registered_types.add(ntype) | |
132 | self.registered_senders.add(sender) |
|
132 | self.registered_senders.add(sender) | |
133 | self.observers.setdefault((ntype,sender), set()).add(callback) |
|
133 | self.observers.setdefault((ntype,sender), set()).add(callback) | |
134 |
|
134 | |||
135 | def remove_all_observers(self): |
|
135 | def remove_all_observers(self): | |
136 | """Removes all observers from this notification center""" |
|
136 | """Removes all observers from this notification center""" | |
137 |
|
137 | |||
138 | self._init_observers() |
|
138 | self._init_observers() | |
139 |
|
139 | |||
140 |
|
140 | |||
141 |
|
141 | |||
142 | shared_center = NotificationCenter() |
|
142 | shared_center = NotificationCenter() |
@@ -1,850 +1,850 b'' | |||||
1 | # encoding: utf-8 |
|
1 | # encoding: utf-8 | |
2 | """ |
|
2 | """ | |
3 | Utilities for working with strings and text. |
|
3 | Utilities for working with strings and text. | |
4 |
|
4 | |||
5 | Inheritance diagram: |
|
5 | Inheritance diagram: | |
6 |
|
6 | |||
7 | .. inheritance-diagram:: IPython.utils.text |
|
7 | .. inheritance-diagram:: IPython.utils.text | |
8 | :parts: 3 |
|
8 | :parts: 3 | |
9 | """ |
|
9 | """ | |
10 |
|
10 | |||
11 | #----------------------------------------------------------------------------- |
|
11 | #----------------------------------------------------------------------------- | |
12 | # Copyright (C) 2008-2011 The IPython Development Team |
|
12 | # Copyright (C) 2008-2011 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 | import __main__ |
|
22 | import __main__ | |
23 |
|
23 | |||
24 | import os |
|
24 | import os | |
25 | import re |
|
25 | import re | |
26 | import shutil |
|
26 | import shutil | |
27 | import sys |
|
27 | import sys | |
28 | import textwrap |
|
28 | import textwrap | |
29 | from string import Formatter |
|
29 | from string import Formatter | |
30 |
|
30 | |||
31 | from IPython.external.path import path |
|
31 | from IPython.external.path import path | |
32 | from IPython.testing.skipdoctest import skip_doctest_py3, skip_doctest |
|
32 | from IPython.testing.skipdoctest import skip_doctest_py3, skip_doctest | |
33 | from IPython.utils import py3compat |
|
33 | from IPython.utils import py3compat | |
34 | from IPython.utils.io import nlprint |
|
34 | from IPython.utils.io import nlprint | |
35 | from IPython.utils.data import flatten |
|
35 | from IPython.utils.data import flatten | |
36 |
|
36 | |||
37 | #----------------------------------------------------------------------------- |
|
37 | #----------------------------------------------------------------------------- | |
38 | # Code |
|
38 | # Code | |
39 | #----------------------------------------------------------------------------- |
|
39 | #----------------------------------------------------------------------------- | |
40 |
|
40 | |||
41 | def unquote_ends(istr): |
|
41 | def unquote_ends(istr): | |
42 | """Remove a single pair of quotes from the endpoints of a string.""" |
|
42 | """Remove a single pair of quotes from the endpoints of a string.""" | |
43 |
|
43 | |||
44 | if not istr: |
|
44 | if not istr: | |
45 | return istr |
|
45 | return istr | |
46 | if (istr[0]=="'" and istr[-1]=="'") or \ |
|
46 | if (istr[0]=="'" and istr[-1]=="'") or \ | |
47 | (istr[0]=='"' and istr[-1]=='"'): |
|
47 | (istr[0]=='"' and istr[-1]=='"'): | |
48 | return istr[1:-1] |
|
48 | return istr[1:-1] | |
49 | else: |
|
49 | else: | |
50 | return istr |
|
50 | return istr | |
51 |
|
51 | |||
52 |
|
52 | |||
53 | class LSString(str): |
|
53 | class LSString(str): | |
54 | """String derivative with a special access attributes. |
|
54 | """String derivative with a special access attributes. | |
55 |
|
55 | |||
56 | These are normal strings, but with the special attributes: |
|
56 | These are normal strings, but with the special attributes: | |
57 |
|
57 | |||
58 | .l (or .list) : value as list (split on newlines). |
|
58 | .l (or .list) : value as list (split on newlines). | |
59 | .n (or .nlstr): original value (the string itself). |
|
59 | .n (or .nlstr): original value (the string itself). | |
60 | .s (or .spstr): value as whitespace-separated string. |
|
60 | .s (or .spstr): value as whitespace-separated string. | |
61 | .p (or .paths): list of path objects |
|
61 | .p (or .paths): list of path objects | |
62 |
|
62 | |||
63 | Any values which require transformations are computed only once and |
|
63 | Any values which require transformations are computed only once and | |
64 | cached. |
|
64 | cached. | |
65 |
|
65 | |||
66 | Such strings are very useful to efficiently interact with the shell, which |
|
66 | Such strings are very useful to efficiently interact with the shell, which | |
67 | typically only understands whitespace-separated options for commands.""" |
|
67 | typically only understands whitespace-separated options for commands.""" | |
68 |
|
68 | |||
69 | def get_list(self): |
|
69 | def get_list(self): | |
70 | try: |
|
70 | try: | |
71 | return self.__list |
|
71 | return self.__list | |
72 | except AttributeError: |
|
72 | except AttributeError: | |
73 | self.__list = self.split('\n') |
|
73 | self.__list = self.split('\n') | |
74 | return self.__list |
|
74 | return self.__list | |
75 |
|
75 | |||
76 | l = list = property(get_list) |
|
76 | l = list = property(get_list) | |
77 |
|
77 | |||
78 | def get_spstr(self): |
|
78 | def get_spstr(self): | |
79 | try: |
|
79 | try: | |
80 | return self.__spstr |
|
80 | return self.__spstr | |
81 | except AttributeError: |
|
81 | except AttributeError: | |
82 | self.__spstr = self.replace('\n',' ') |
|
82 | self.__spstr = self.replace('\n',' ') | |
83 | return self.__spstr |
|
83 | return self.__spstr | |
84 |
|
84 | |||
85 | s = spstr = property(get_spstr) |
|
85 | s = spstr = property(get_spstr) | |
86 |
|
86 | |||
87 | def get_nlstr(self): |
|
87 | def get_nlstr(self): | |
88 | return self |
|
88 | return self | |
89 |
|
89 | |||
90 | n = nlstr = property(get_nlstr) |
|
90 | n = nlstr = property(get_nlstr) | |
91 |
|
91 | |||
92 | def get_paths(self): |
|
92 | def get_paths(self): | |
93 | try: |
|
93 | try: | |
94 | return self.__paths |
|
94 | return self.__paths | |
95 | except AttributeError: |
|
95 | except AttributeError: | |
96 | self.__paths = [path(p) for p in self.split('\n') if os.path.exists(p)] |
|
96 | self.__paths = [path(p) for p in self.split('\n') if os.path.exists(p)] | |
97 | return self.__paths |
|
97 | return self.__paths | |
98 |
|
98 | |||
99 | p = paths = property(get_paths) |
|
99 | p = paths = property(get_paths) | |
100 |
|
100 | |||
101 | # FIXME: We need to reimplement type specific displayhook and then add this |
|
101 | # FIXME: We need to reimplement type specific displayhook and then add this | |
102 | # back as a custom printer. This should also be moved outside utils into the |
|
102 | # back as a custom printer. This should also be moved outside utils into the | |
103 | # core. |
|
103 | # core. | |
104 |
|
104 | |||
105 | # def print_lsstring(arg): |
|
105 | # def print_lsstring(arg): | |
106 | # """ Prettier (non-repr-like) and more informative printer for LSString """ |
|
106 | # """ Prettier (non-repr-like) and more informative printer for LSString """ | |
107 | # print "LSString (.p, .n, .l, .s available). Value:" |
|
107 | # print "LSString (.p, .n, .l, .s available). Value:" | |
108 | # print arg |
|
108 | # print arg | |
109 | # |
|
109 | # | |
110 | # |
|
110 | # | |
111 | # print_lsstring = result_display.when_type(LSString)(print_lsstring) |
|
111 | # print_lsstring = result_display.when_type(LSString)(print_lsstring) | |
112 |
|
112 | |||
113 |
|
113 | |||
114 | class SList(list): |
|
114 | class SList(list): | |
115 | """List derivative with a special access attributes. |
|
115 | """List derivative with a special access attributes. | |
116 |
|
116 | |||
117 | These are normal lists, but with the special attributes: |
|
117 | These are normal lists, but with the special attributes: | |
118 |
|
118 | |||
119 | .l (or .list) : value as list (the list itself). |
|
119 | .l (or .list) : value as list (the list itself). | |
120 | .n (or .nlstr): value as a string, joined on newlines. |
|
120 | .n (or .nlstr): value as a string, joined on newlines. | |
121 | .s (or .spstr): value as a string, joined on spaces. |
|
121 | .s (or .spstr): value as a string, joined on spaces. | |
122 | .p (or .paths): list of path objects |
|
122 | .p (or .paths): list of path objects | |
123 |
|
123 | |||
124 | Any values which require transformations are computed only once and |
|
124 | Any values which require transformations are computed only once and | |
125 | cached.""" |
|
125 | cached.""" | |
126 |
|
126 | |||
127 | def get_list(self): |
|
127 | def get_list(self): | |
128 | return self |
|
128 | return self | |
129 |
|
129 | |||
130 | l = list = property(get_list) |
|
130 | l = list = property(get_list) | |
131 |
|
131 | |||
132 | def get_spstr(self): |
|
132 | def get_spstr(self): | |
133 | try: |
|
133 | try: | |
134 | return self.__spstr |
|
134 | return self.__spstr | |
135 | except AttributeError: |
|
135 | except AttributeError: | |
136 | self.__spstr = ' '.join(self) |
|
136 | self.__spstr = ' '.join(self) | |
137 | return self.__spstr |
|
137 | return self.__spstr | |
138 |
|
138 | |||
139 | s = spstr = property(get_spstr) |
|
139 | s = spstr = property(get_spstr) | |
140 |
|
140 | |||
141 | def get_nlstr(self): |
|
141 | def get_nlstr(self): | |
142 | try: |
|
142 | try: | |
143 | return self.__nlstr |
|
143 | return self.__nlstr | |
144 | except AttributeError: |
|
144 | except AttributeError: | |
145 | self.__nlstr = '\n'.join(self) |
|
145 | self.__nlstr = '\n'.join(self) | |
146 | return self.__nlstr |
|
146 | return self.__nlstr | |
147 |
|
147 | |||
148 | n = nlstr = property(get_nlstr) |
|
148 | n = nlstr = property(get_nlstr) | |
149 |
|
149 | |||
150 | def get_paths(self): |
|
150 | def get_paths(self): | |
151 | try: |
|
151 | try: | |
152 | return self.__paths |
|
152 | return self.__paths | |
153 | except AttributeError: |
|
153 | except AttributeError: | |
154 | self.__paths = [path(p) for p in self if os.path.exists(p)] |
|
154 | self.__paths = [path(p) for p in self if os.path.exists(p)] | |
155 | return self.__paths |
|
155 | return self.__paths | |
156 |
|
156 | |||
157 | p = paths = property(get_paths) |
|
157 | p = paths = property(get_paths) | |
158 |
|
158 | |||
159 | def grep(self, pattern, prune = False, field = None): |
|
159 | def grep(self, pattern, prune = False, field = None): | |
160 | """ Return all strings matching 'pattern' (a regex or callable) |
|
160 | """ Return all strings matching 'pattern' (a regex or callable) | |
161 |
|
161 | |||
162 | This is case-insensitive. If prune is true, return all items |
|
162 | This is case-insensitive. If prune is true, return all items | |
163 | NOT matching the pattern. |
|
163 | NOT matching the pattern. | |
164 |
|
164 | |||
165 | If field is specified, the match must occur in the specified |
|
165 | If field is specified, the match must occur in the specified | |
166 | whitespace-separated field. |
|
166 | whitespace-separated field. | |
167 |
|
167 | |||
168 | Examples:: |
|
168 | Examples:: | |
169 |
|
169 | |||
170 | a.grep( lambda x: x.startswith('C') ) |
|
170 | a.grep( lambda x: x.startswith('C') ) | |
171 | a.grep('Cha.*log', prune=1) |
|
171 | a.grep('Cha.*log', prune=1) | |
172 | a.grep('chm', field=-1) |
|
172 | a.grep('chm', field=-1) | |
173 | """ |
|
173 | """ | |
174 |
|
174 | |||
175 | def match_target(s): |
|
175 | def match_target(s): | |
176 | if field is None: |
|
176 | if field is None: | |
177 | return s |
|
177 | return s | |
178 | parts = s.split() |
|
178 | parts = s.split() | |
179 | try: |
|
179 | try: | |
180 | tgt = parts[field] |
|
180 | tgt = parts[field] | |
181 | return tgt |
|
181 | return tgt | |
182 | except IndexError: |
|
182 | except IndexError: | |
183 | return "" |
|
183 | return "" | |
184 |
|
184 | |||
185 | if isinstance(pattern, basestring): |
|
185 | if isinstance(pattern, basestring): | |
186 | pred = lambda x : re.search(pattern, x, re.IGNORECASE) |
|
186 | pred = lambda x : re.search(pattern, x, re.IGNORECASE) | |
187 | else: |
|
187 | else: | |
188 | pred = pattern |
|
188 | pred = pattern | |
189 | if not prune: |
|
189 | if not prune: | |
190 | return SList([el for el in self if pred(match_target(el))]) |
|
190 | return SList([el for el in self if pred(match_target(el))]) | |
191 | else: |
|
191 | else: | |
192 | return SList([el for el in self if not pred(match_target(el))]) |
|
192 | return SList([el for el in self if not pred(match_target(el))]) | |
193 |
|
193 | |||
194 | def fields(self, *fields): |
|
194 | def fields(self, *fields): | |
195 | """ Collect whitespace-separated fields from string list |
|
195 | """ Collect whitespace-separated fields from string list | |
196 |
|
196 | |||
197 | Allows quick awk-like usage of string lists. |
|
197 | Allows quick awk-like usage of string lists. | |
198 |
|
198 | |||
199 | Example data (in var a, created by 'a = !ls -l'):: |
|
199 | Example data (in var a, created by 'a = !ls -l'):: | |
200 | -rwxrwxrwx 1 ville None 18 Dec 14 2006 ChangeLog |
|
200 | -rwxrwxrwx 1 ville None 18 Dec 14 2006 ChangeLog | |
201 | drwxrwxrwx+ 6 ville None 0 Oct 24 18:05 IPython |
|
201 | drwxrwxrwx+ 6 ville None 0 Oct 24 18:05 IPython | |
202 |
|
202 | |||
203 | a.fields(0) is ['-rwxrwxrwx', 'drwxrwxrwx+'] |
|
203 | a.fields(0) is ['-rwxrwxrwx', 'drwxrwxrwx+'] | |
204 | a.fields(1,0) is ['1 -rwxrwxrwx', '6 drwxrwxrwx+'] |
|
204 | a.fields(1,0) is ['1 -rwxrwxrwx', '6 drwxrwxrwx+'] | |
205 | (note the joining by space). |
|
205 | (note the joining by space). | |
206 | a.fields(-1) is ['ChangeLog', 'IPython'] |
|
206 | a.fields(-1) is ['ChangeLog', 'IPython'] | |
207 |
|
207 | |||
208 | IndexErrors are ignored. |
|
208 | IndexErrors are ignored. | |
209 |
|
209 | |||
210 | Without args, fields() just split()'s the strings. |
|
210 | Without args, fields() just split()'s the strings. | |
211 | """ |
|
211 | """ | |
212 | if len(fields) == 0: |
|
212 | if len(fields) == 0: | |
213 | return [el.split() for el in self] |
|
213 | return [el.split() for el in self] | |
214 |
|
214 | |||
215 | res = SList() |
|
215 | res = SList() | |
216 | for el in [f.split() for f in self]: |
|
216 | for el in [f.split() for f in self]: | |
217 | lineparts = [] |
|
217 | lineparts = [] | |
218 |
|
218 | |||
219 | for fd in fields: |
|
219 | for fd in fields: | |
220 | try: |
|
220 | try: | |
221 | lineparts.append(el[fd]) |
|
221 | lineparts.append(el[fd]) | |
222 | except IndexError: |
|
222 | except IndexError: | |
223 | pass |
|
223 | pass | |
224 | if lineparts: |
|
224 | if lineparts: | |
225 | res.append(" ".join(lineparts)) |
|
225 | res.append(" ".join(lineparts)) | |
226 |
|
226 | |||
227 | return res |
|
227 | return res | |
228 |
|
228 | |||
229 | def sort(self,field= None, nums = False): |
|
229 | def sort(self,field= None, nums = False): | |
230 | """ sort by specified fields (see fields()) |
|
230 | """ sort by specified fields (see fields()) | |
231 |
|
231 | |||
232 | Example:: |
|
232 | Example:: | |
233 | a.sort(1, nums = True) |
|
233 | a.sort(1, nums = True) | |
234 |
|
234 | |||
235 | Sorts a by second field, in numerical order (so that 21 > 3) |
|
235 | Sorts a by second field, in numerical order (so that 21 > 3) | |
236 |
|
236 | |||
237 | """ |
|
237 | """ | |
238 |
|
238 | |||
239 | #decorate, sort, undecorate |
|
239 | #decorate, sort, undecorate | |
240 | if field is not None: |
|
240 | if field is not None: | |
241 | dsu = [[SList([line]).fields(field), line] for line in self] |
|
241 | dsu = [[SList([line]).fields(field), line] for line in self] | |
242 | else: |
|
242 | else: | |
243 | dsu = [[line, line] for line in self] |
|
243 | dsu = [[line, line] for line in self] | |
244 | if nums: |
|
244 | if nums: | |
245 | for i in range(len(dsu)): |
|
245 | for i in range(len(dsu)): | |
246 | numstr = "".join([ch for ch in dsu[i][0] if ch.isdigit()]) |
|
246 | numstr = "".join([ch for ch in dsu[i][0] if ch.isdigit()]) | |
247 | try: |
|
247 | try: | |
248 | n = int(numstr) |
|
248 | n = int(numstr) | |
249 | except ValueError: |
|
249 | except ValueError: | |
250 | n = 0; |
|
250 | n = 0; | |
251 | dsu[i][0] = n |
|
251 | dsu[i][0] = n | |
252 |
|
252 | |||
253 |
|
253 | |||
254 | dsu.sort() |
|
254 | dsu.sort() | |
255 | return SList([t[1] for t in dsu]) |
|
255 | return SList([t[1] for t in dsu]) | |
256 |
|
256 | |||
257 |
|
257 | |||
258 | # FIXME: We need to reimplement type specific displayhook and then add this |
|
258 | # FIXME: We need to reimplement type specific displayhook and then add this | |
259 | # back as a custom printer. This should also be moved outside utils into the |
|
259 | # back as a custom printer. This should also be moved outside utils into the | |
260 | # core. |
|
260 | # core. | |
261 |
|
261 | |||
262 | # def print_slist(arg): |
|
262 | # def print_slist(arg): | |
263 | # """ Prettier (non-repr-like) and more informative printer for SList """ |
|
263 | # """ Prettier (non-repr-like) and more informative printer for SList """ | |
264 | # print "SList (.p, .n, .l, .s, .grep(), .fields(), sort() available):" |
|
264 | # print "SList (.p, .n, .l, .s, .grep(), .fields(), sort() available):" | |
265 | # if hasattr(arg, 'hideonce') and arg.hideonce: |
|
265 | # if hasattr(arg, 'hideonce') and arg.hideonce: | |
266 | # arg.hideonce = False |
|
266 | # arg.hideonce = False | |
267 | # return |
|
267 | # return | |
268 | # |
|
268 | # | |
269 | # nlprint(arg) |
|
269 | # nlprint(arg) | |
270 | # |
|
270 | # | |
271 | # print_slist = result_display.when_type(SList)(print_slist) |
|
271 | # print_slist = result_display.when_type(SList)(print_slist) | |
272 |
|
272 | |||
273 |
|
273 | |||
274 | def esc_quotes(strng): |
|
274 | def esc_quotes(strng): | |
275 | """Return the input string with single and double quotes escaped out""" |
|
275 | """Return the input string with single and double quotes escaped out""" | |
276 |
|
276 | |||
277 | return strng.replace('"','\\"').replace("'","\\'") |
|
277 | return strng.replace('"','\\"').replace("'","\\'") | |
278 |
|
278 | |||
279 |
|
279 | |||
280 | def qw(words,flat=0,sep=None,maxsplit=-1): |
|
280 | def qw(words,flat=0,sep=None,maxsplit=-1): | |
281 | """Similar to Perl's qw() operator, but with some more options. |
|
281 | """Similar to Perl's qw() operator, but with some more options. | |
282 |
|
282 | |||
283 | qw(words,flat=0,sep=' ',maxsplit=-1) -> words.split(sep,maxsplit) |
|
283 | qw(words,flat=0,sep=' ',maxsplit=-1) -> words.split(sep,maxsplit) | |
284 |
|
284 | |||
285 | words can also be a list itself, and with flat=1, the output will be |
|
285 | words can also be a list itself, and with flat=1, the output will be | |
286 | recursively flattened. |
|
286 | recursively flattened. | |
287 |
|
287 | |||
288 | Examples: |
|
288 | Examples: | |
289 |
|
289 | |||
290 | >>> qw('1 2') |
|
290 | >>> qw('1 2') | |
291 | ['1', '2'] |
|
291 | ['1', '2'] | |
292 |
|
292 | |||
293 | >>> qw(['a b','1 2',['m n','p q']]) |
|
293 | >>> qw(['a b','1 2',['m n','p q']]) | |
294 | [['a', 'b'], ['1', '2'], [['m', 'n'], ['p', 'q']]] |
|
294 | [['a', 'b'], ['1', '2'], [['m', 'n'], ['p', 'q']]] | |
295 |
|
295 | |||
296 | >>> qw(['a b','1 2',['m n','p q']],flat=1) |
|
296 | >>> qw(['a b','1 2',['m n','p q']],flat=1) | |
297 | ['a', 'b', '1', '2', 'm', 'n', 'p', 'q'] |
|
297 | ['a', 'b', '1', '2', 'm', 'n', 'p', 'q'] | |
298 | """ |
|
298 | """ | |
299 |
|
299 | |||
300 | if isinstance(words, basestring): |
|
300 | if isinstance(words, basestring): | |
301 | return [word.strip() for word in words.split(sep,maxsplit) |
|
301 | return [word.strip() for word in words.split(sep,maxsplit) | |
302 | if word and not word.isspace() ] |
|
302 | if word and not word.isspace() ] | |
303 | if flat: |
|
303 | if flat: | |
304 | return flatten(map(qw,words,[1]*len(words))) |
|
304 | return flatten(map(qw,words,[1]*len(words))) | |
305 | return map(qw,words) |
|
305 | return map(qw,words) | |
306 |
|
306 | |||
307 |
|
307 | |||
308 | def qwflat(words,sep=None,maxsplit=-1): |
|
308 | def qwflat(words,sep=None,maxsplit=-1): | |
309 | """Calls qw(words) in flat mode. It's just a convenient shorthand.""" |
|
309 | """Calls qw(words) in flat mode. It's just a convenient shorthand.""" | |
310 | return qw(words,1,sep,maxsplit) |
|
310 | return qw(words,1,sep,maxsplit) | |
311 |
|
311 | |||
312 |
|
312 | |||
313 | def qw_lol(indata): |
|
313 | def qw_lol(indata): | |
314 | """qw_lol('a b') -> [['a','b']], |
|
314 | """qw_lol('a b') -> [['a','b']], | |
315 | otherwise it's just a call to qw(). |
|
315 | otherwise it's just a call to qw(). | |
316 |
|
316 | |||
317 | We need this to make sure the modules_some keys *always* end up as a |
|
317 | We need this to make sure the modules_some keys *always* end up as a | |
318 | list of lists.""" |
|
318 | list of lists.""" | |
319 |
|
319 | |||
320 | if isinstance(indata, basestring): |
|
320 | if isinstance(indata, basestring): | |
321 | return [qw(indata)] |
|
321 | return [qw(indata)] | |
322 | else: |
|
322 | else: | |
323 | return qw(indata) |
|
323 | return qw(indata) | |
324 |
|
324 | |||
325 |
|
325 | |||
326 | def grep(pat,list,case=1): |
|
326 | def grep(pat,list,case=1): | |
327 | """Simple minded grep-like function. |
|
327 | """Simple minded grep-like function. | |
328 | grep(pat,list) returns occurrences of pat in list, None on failure. |
|
328 | grep(pat,list) returns occurrences of pat in list, None on failure. | |
329 |
|
329 | |||
330 | It only does simple string matching, with no support for regexps. Use the |
|
330 | It only does simple string matching, with no support for regexps. Use the | |
331 | option case=0 for case-insensitive matching.""" |
|
331 | option case=0 for case-insensitive matching.""" | |
332 |
|
332 | |||
333 | # This is pretty crude. At least it should implement copying only references |
|
333 | # This is pretty crude. At least it should implement copying only references | |
334 | # to the original data in case it's big. Now it copies the data for output. |
|
334 | # to the original data in case it's big. Now it copies the data for output. | |
335 | out=[] |
|
335 | out=[] | |
336 | if case: |
|
336 | if case: | |
337 | for term in list: |
|
337 | for term in list: | |
338 | if term.find(pat)>-1: out.append(term) |
|
338 | if term.find(pat)>-1: out.append(term) | |
339 | else: |
|
339 | else: | |
340 | lpat=pat.lower() |
|
340 | lpat=pat.lower() | |
341 | for term in list: |
|
341 | for term in list: | |
342 | if term.lower().find(lpat)>-1: out.append(term) |
|
342 | if term.lower().find(lpat)>-1: out.append(term) | |
343 |
|
343 | |||
344 | if len(out): return out |
|
344 | if len(out): return out | |
345 | else: return None |
|
345 | else: return None | |
346 |
|
346 | |||
347 |
|
347 | |||
348 | def dgrep(pat,*opts): |
|
348 | def dgrep(pat,*opts): | |
349 | """Return grep() on dir()+dir(__builtins__). |
|
349 | """Return grep() on dir()+dir(__builtins__). | |
350 |
|
350 | |||
351 | A very common use of grep() when working interactively.""" |
|
351 | A very common use of grep() when working interactively.""" | |
352 |
|
352 | |||
353 | return grep(pat,dir(__main__)+dir(__main__.__builtins__),*opts) |
|
353 | return grep(pat,dir(__main__)+dir(__main__.__builtins__),*opts) | |
354 |
|
354 | |||
355 |
|
355 | |||
356 | def idgrep(pat): |
|
356 | def idgrep(pat): | |
357 | """Case-insensitive dgrep()""" |
|
357 | """Case-insensitive dgrep()""" | |
358 |
|
358 | |||
359 | return dgrep(pat,0) |
|
359 | return dgrep(pat,0) | |
360 |
|
360 | |||
361 |
|
361 | |||
362 | def igrep(pat,list): |
|
362 | def igrep(pat,list): | |
363 | """Synonym for case-insensitive grep.""" |
|
363 | """Synonym for case-insensitive grep.""" | |
364 |
|
364 | |||
365 | return grep(pat,list,case=0) |
|
365 | return grep(pat,list,case=0) | |
366 |
|
366 | |||
367 |
|
367 | |||
368 | def indent(instr,nspaces=4, ntabs=0, flatten=False): |
|
368 | def indent(instr,nspaces=4, ntabs=0, flatten=False): | |
369 | """Indent a string a given number of spaces or tabstops. |
|
369 | """Indent a string a given number of spaces or tabstops. | |
370 |
|
370 | |||
371 | indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces. |
|
371 | indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces. | |
372 |
|
372 | |||
373 | Parameters |
|
373 | Parameters | |
374 | ---------- |
|
374 | ---------- | |
375 |
|
375 | |||
376 | instr : basestring |
|
376 | instr : basestring | |
377 | The string to be indented. |
|
377 | The string to be indented. | |
378 | nspaces : int (default: 4) |
|
378 | nspaces : int (default: 4) | |
379 | The number of spaces to be indented. |
|
379 | The number of spaces to be indented. | |
380 | ntabs : int (default: 0) |
|
380 | ntabs : int (default: 0) | |
381 | The number of tabs to be indented. |
|
381 | The number of tabs to be indented. | |
382 | flatten : bool (default: False) |
|
382 | flatten : bool (default: False) | |
383 | Whether to scrub existing indentation. If True, all lines will be |
|
383 | Whether to scrub existing indentation. If True, all lines will be | |
384 | aligned to the same indentation. If False, existing indentation will |
|
384 | aligned to the same indentation. If False, existing indentation will | |
385 | be strictly increased. |
|
385 | be strictly increased. | |
386 |
|
386 | |||
387 | Returns |
|
387 | Returns | |
388 | ------- |
|
388 | ------- | |
389 |
|
389 | |||
390 | str|unicode : string indented by ntabs and nspaces. |
|
390 | str|unicode : string indented by ntabs and nspaces. | |
391 |
|
391 | |||
392 | """ |
|
392 | """ | |
393 | if instr is None: |
|
393 | if instr is None: | |
394 | return |
|
394 | return | |
395 | ind = '\t'*ntabs+' '*nspaces |
|
395 | ind = '\t'*ntabs+' '*nspaces | |
396 | if flatten: |
|
396 | if flatten: | |
397 | pat = re.compile(r'^\s*', re.MULTILINE) |
|
397 | pat = re.compile(r'^\s*', re.MULTILINE) | |
398 | else: |
|
398 | else: | |
399 | pat = re.compile(r'^', re.MULTILINE) |
|
399 | pat = re.compile(r'^', re.MULTILINE) | |
400 | outstr = re.sub(pat, ind, instr) |
|
400 | outstr = re.sub(pat, ind, instr) | |
401 | if outstr.endswith(os.linesep+ind): |
|
401 | if outstr.endswith(os.linesep+ind): | |
402 | return outstr[:-len(ind)] |
|
402 | return outstr[:-len(ind)] | |
403 | else: |
|
403 | else: | |
404 | return outstr |
|
404 | return outstr | |
405 |
|
405 | |||
406 | def native_line_ends(filename,backup=1): |
|
406 | def native_line_ends(filename,backup=1): | |
407 | """Convert (in-place) a file to line-ends native to the current OS. |
|
407 | """Convert (in-place) a file to line-ends native to the current OS. | |
408 |
|
408 | |||
409 | If the optional backup argument is given as false, no backup of the |
|
409 | If the optional backup argument is given as false, no backup of the | |
410 | original file is left. """ |
|
410 | original file is left. """ | |
411 |
|
411 | |||
412 | backup_suffixes = {'posix':'~','dos':'.bak','nt':'.bak','mac':'.bak'} |
|
412 | backup_suffixes = {'posix':'~','dos':'.bak','nt':'.bak','mac':'.bak'} | |
413 |
|
413 | |||
414 | bak_filename = filename + backup_suffixes[os.name] |
|
414 | bak_filename = filename + backup_suffixes[os.name] | |
415 |
|
415 | |||
416 | original = open(filename).read() |
|
416 | original = open(filename).read() | |
417 | shutil.copy2(filename,bak_filename) |
|
417 | shutil.copy2(filename,bak_filename) | |
418 | try: |
|
418 | try: | |
419 | new = open(filename,'wb') |
|
419 | new = open(filename,'wb') | |
420 | new.write(os.linesep.join(original.splitlines())) |
|
420 | new.write(os.linesep.join(original.splitlines())) | |
421 | new.write(os.linesep) # ALWAYS put an eol at the end of the file |
|
421 | new.write(os.linesep) # ALWAYS put an eol at the end of the file | |
422 | new.close() |
|
422 | new.close() | |
423 | except: |
|
423 | except: | |
424 | os.rename(bak_filename,filename) |
|
424 | os.rename(bak_filename,filename) | |
425 | if not backup: |
|
425 | if not backup: | |
426 | try: |
|
426 | try: | |
427 | os.remove(bak_filename) |
|
427 | os.remove(bak_filename) | |
428 | except: |
|
428 | except: | |
429 | pass |
|
429 | pass | |
430 |
|
430 | |||
431 |
|
431 | |||
432 | def list_strings(arg): |
|
432 | def list_strings(arg): | |
433 | """Always return a list of strings, given a string or list of strings |
|
433 | """Always return a list of strings, given a string or list of strings | |
434 | as input. |
|
434 | as input. | |
435 |
|
435 | |||
436 | :Examples: |
|
436 | :Examples: | |
437 |
|
437 | |||
438 | In [7]: list_strings('A single string') |
|
438 | In [7]: list_strings('A single string') | |
439 | Out[7]: ['A single string'] |
|
439 | Out[7]: ['A single string'] | |
440 |
|
440 | |||
441 | In [8]: list_strings(['A single string in a list']) |
|
441 | In [8]: list_strings(['A single string in a list']) | |
442 | Out[8]: ['A single string in a list'] |
|
442 | Out[8]: ['A single string in a list'] | |
443 |
|
443 | |||
444 | In [9]: list_strings(['A','list','of','strings']) |
|
444 | In [9]: list_strings(['A','list','of','strings']) | |
445 | Out[9]: ['A', 'list', 'of', 'strings'] |
|
445 | Out[9]: ['A', 'list', 'of', 'strings'] | |
446 | """ |
|
446 | """ | |
447 |
|
447 | |||
448 | if isinstance(arg,basestring): return [arg] |
|
448 | if isinstance(arg,basestring): return [arg] | |
449 | else: return arg |
|
449 | else: return arg | |
450 |
|
450 | |||
451 |
|
451 | |||
452 | def marquee(txt='',width=78,mark='*'): |
|
452 | def marquee(txt='',width=78,mark='*'): | |
453 | """Return the input string centered in a 'marquee'. |
|
453 | """Return the input string centered in a 'marquee'. | |
454 |
|
454 | |||
455 | :Examples: |
|
455 | :Examples: | |
456 |
|
456 | |||
457 | In [16]: marquee('A test',40) |
|
457 | In [16]: marquee('A test',40) | |
458 | Out[16]: '**************** A test ****************' |
|
458 | Out[16]: '**************** A test ****************' | |
459 |
|
459 | |||
460 | In [17]: marquee('A test',40,'-') |
|
460 | In [17]: marquee('A test',40,'-') | |
461 | Out[17]: '---------------- A test ----------------' |
|
461 | Out[17]: '---------------- A test ----------------' | |
462 |
|
462 | |||
463 | In [18]: marquee('A test',40,' ') |
|
463 | In [18]: marquee('A test',40,' ') | |
464 | Out[18]: ' A test ' |
|
464 | Out[18]: ' A test ' | |
465 |
|
465 | |||
466 | """ |
|
466 | """ | |
467 | if not txt: |
|
467 | if not txt: | |
468 | return (mark*width)[:width] |
|
468 | return (mark*width)[:width] | |
469 | nmark = (width-len(txt)-2)//len(mark)//2 |
|
469 | nmark = (width-len(txt)-2)//len(mark)//2 | |
470 | if nmark < 0: nmark =0 |
|
470 | if nmark < 0: nmark =0 | |
471 | marks = mark*nmark |
|
471 | marks = mark*nmark | |
472 | return '%s %s %s' % (marks,txt,marks) |
|
472 | return '%s %s %s' % (marks,txt,marks) | |
473 |
|
473 | |||
474 |
|
474 | |||
475 | ini_spaces_re = re.compile(r'^(\s+)') |
|
475 | ini_spaces_re = re.compile(r'^(\s+)') | |
476 |
|
476 | |||
477 | def num_ini_spaces(strng): |
|
477 | def num_ini_spaces(strng): | |
478 | """Return the number of initial spaces in a string""" |
|
478 | """Return the number of initial spaces in a string""" | |
479 |
|
479 | |||
480 | ini_spaces = ini_spaces_re.match(strng) |
|
480 | ini_spaces = ini_spaces_re.match(strng) | |
481 | if ini_spaces: |
|
481 | if ini_spaces: | |
482 | return ini_spaces.end() |
|
482 | return ini_spaces.end() | |
483 | else: |
|
483 | else: | |
484 | return 0 |
|
484 | return 0 | |
485 |
|
485 | |||
486 |
|
486 | |||
487 | def format_screen(strng): |
|
487 | def format_screen(strng): | |
488 | """Format a string for screen printing. |
|
488 | """Format a string for screen printing. | |
489 |
|
489 | |||
490 | This removes some latex-type format codes.""" |
|
490 | This removes some latex-type format codes.""" | |
491 | # Paragraph continue |
|
491 | # Paragraph continue | |
492 | par_re = re.compile(r'\\$',re.MULTILINE) |
|
492 | par_re = re.compile(r'\\$',re.MULTILINE) | |
493 | strng = par_re.sub('',strng) |
|
493 | strng = par_re.sub('',strng) | |
494 | return strng |
|
494 | return strng | |
495 |
|
495 | |||
496 |
|
496 | |||
497 | def dedent(text): |
|
497 | def dedent(text): | |
498 | """Equivalent of textwrap.dedent that ignores unindented first line. |
|
498 | """Equivalent of textwrap.dedent that ignores unindented first line. | |
499 |
|
499 | |||
500 | This means it will still dedent strings like: |
|
500 | This means it will still dedent strings like: | |
501 | '''foo |
|
501 | '''foo | |
502 | is a bar |
|
502 | is a bar | |
503 | ''' |
|
503 | ''' | |
504 |
|
504 | |||
505 | For use in wrap_paragraphs. |
|
505 | For use in wrap_paragraphs. | |
506 | """ |
|
506 | """ | |
507 |
|
507 | |||
508 | if text.startswith('\n'): |
|
508 | if text.startswith('\n'): | |
509 | # text starts with blank line, don't ignore the first line |
|
509 | # text starts with blank line, don't ignore the first line | |
510 | return textwrap.dedent(text) |
|
510 | return textwrap.dedent(text) | |
511 |
|
511 | |||
512 | # split first line |
|
512 | # split first line | |
513 | splits = text.split('\n',1) |
|
513 | splits = text.split('\n',1) | |
514 | if len(splits) == 1: |
|
514 | if len(splits) == 1: | |
515 | # only one line |
|
515 | # only one line | |
516 | return textwrap.dedent(text) |
|
516 | return textwrap.dedent(text) | |
517 |
|
517 | |||
518 | first, rest = splits |
|
518 | first, rest = splits | |
519 | # dedent everything but the first line |
|
519 | # dedent everything but the first line | |
520 | rest = textwrap.dedent(rest) |
|
520 | rest = textwrap.dedent(rest) | |
521 | return '\n'.join([first, rest]) |
|
521 | return '\n'.join([first, rest]) | |
522 |
|
522 | |||
523 |
|
523 | |||
524 | def wrap_paragraphs(text, ncols=80): |
|
524 | def wrap_paragraphs(text, ncols=80): | |
525 | """Wrap multiple paragraphs to fit a specified width. |
|
525 | """Wrap multiple paragraphs to fit a specified width. | |
526 |
|
526 | |||
527 | This is equivalent to textwrap.wrap, but with support for multiple |
|
527 | This is equivalent to textwrap.wrap, but with support for multiple | |
528 | paragraphs, as separated by empty lines. |
|
528 | paragraphs, as separated by empty lines. | |
529 |
|
529 | |||
530 | Returns |
|
530 | Returns | |
531 | ------- |
|
531 | ------- | |
532 |
|
532 | |||
533 | list of complete paragraphs, wrapped to fill `ncols` columns. |
|
533 | list of complete paragraphs, wrapped to fill `ncols` columns. | |
534 | """ |
|
534 | """ | |
535 | paragraph_re = re.compile(r'\n(\s*\n)+', re.MULTILINE) |
|
535 | paragraph_re = re.compile(r'\n(\s*\n)+', re.MULTILINE) | |
536 | text = dedent(text).strip() |
|
536 | text = dedent(text).strip() | |
537 | paragraphs = paragraph_re.split(text)[::2] # every other entry is space |
|
537 | paragraphs = paragraph_re.split(text)[::2] # every other entry is space | |
538 | out_ps = [] |
|
538 | out_ps = [] | |
539 | indent_re = re.compile(r'\n\s+', re.MULTILINE) |
|
539 | indent_re = re.compile(r'\n\s+', re.MULTILINE) | |
540 | for p in paragraphs: |
|
540 | for p in paragraphs: | |
541 | # presume indentation that survives dedent is meaningful formatting, |
|
541 | # presume indentation that survives dedent is meaningful formatting, | |
542 | # so don't fill unless text is flush. |
|
542 | # so don't fill unless text is flush. | |
543 | if indent_re.search(p) is None: |
|
543 | if indent_re.search(p) is None: | |
544 | # wrap paragraph |
|
544 | # wrap paragraph | |
545 | p = textwrap.fill(p, ncols) |
|
545 | p = textwrap.fill(p, ncols) | |
546 | out_ps.append(p) |
|
546 | out_ps.append(p) | |
547 | return out_ps |
|
547 | return out_ps | |
548 |
|
548 | |||
549 |
|
549 | |||
550 | def long_substr(data): |
|
550 | def long_substr(data): | |
551 | """Return the longest common substring in a list of strings. |
|
551 | """Return the longest common substring in a list of strings. | |
552 |
|
552 | |||
553 | Credit: http://stackoverflow.com/questions/2892931/longest-common-substring-from-more-than-two-strings-python |
|
553 | Credit: http://stackoverflow.com/questions/2892931/longest-common-substring-from-more-than-two-strings-python | |
554 | """ |
|
554 | """ | |
555 | substr = '' |
|
555 | substr = '' | |
556 | if len(data) > 1 and len(data[0]) > 0: |
|
556 | if len(data) > 1 and len(data[0]) > 0: | |
557 | for i in range(len(data[0])): |
|
557 | for i in range(len(data[0])): | |
558 | for j in range(len(data[0])-i+1): |
|
558 | for j in range(len(data[0])-i+1): | |
559 | if j > len(substr) and all(data[0][i:i+j] in x for x in data): |
|
559 | if j > len(substr) and all(data[0][i:i+j] in x for x in data): | |
560 | substr = data[0][i:i+j] |
|
560 | substr = data[0][i:i+j] | |
561 | elif len(data) == 1: |
|
561 | elif len(data) == 1: | |
562 | substr = data[0] |
|
562 | substr = data[0] | |
563 | return substr |
|
563 | return substr | |
564 |
|
564 | |||
565 |
|
565 | |||
566 | def strip_email_quotes(text): |
|
566 | def strip_email_quotes(text): | |
567 | """Strip leading email quotation characters ('>'). |
|
567 | """Strip leading email quotation characters ('>'). | |
568 |
|
568 | |||
569 | Removes any combination of leading '>' interspersed with whitespace that |
|
569 | Removes any combination of leading '>' interspersed with whitespace that | |
570 | appears *identically* in all lines of the input text. |
|
570 | appears *identically* in all lines of the input text. | |
571 |
|
571 | |||
572 | Parameters |
|
572 | Parameters | |
573 | ---------- |
|
573 | ---------- | |
574 | text : str |
|
574 | text : str | |
575 |
|
575 | |||
576 | Examples |
|
576 | Examples | |
577 | -------- |
|
577 | -------- | |
578 |
|
578 | |||
579 | Simple uses:: |
|
579 | Simple uses:: | |
580 |
|
580 | |||
581 | In [2]: strip_email_quotes('> > text') |
|
581 | In [2]: strip_email_quotes('> > text') | |
582 | Out[2]: 'text' |
|
582 | Out[2]: 'text' | |
583 |
|
583 | |||
584 | In [3]: strip_email_quotes('> > text\\n> > more') |
|
584 | In [3]: strip_email_quotes('> > text\\n> > more') | |
585 | Out[3]: 'text\\nmore' |
|
585 | Out[3]: 'text\\nmore' | |
586 |
|
586 | |||
587 | Note how only the common prefix that appears in all lines is stripped:: |
|
587 | Note how only the common prefix that appears in all lines is stripped:: | |
588 |
|
588 | |||
589 | In [4]: strip_email_quotes('> > text\\n> > more\\n> more...') |
|
589 | In [4]: strip_email_quotes('> > text\\n> > more\\n> more...') | |
590 | Out[4]: '> text\\n> more\\nmore...' |
|
590 | Out[4]: '> text\\n> more\\nmore...' | |
591 |
|
591 | |||
592 | So if any line has no quote marks ('>') , then none are stripped from any |
|
592 | So if any line has no quote marks ('>') , then none are stripped from any | |
593 | of them :: |
|
593 | of them :: | |
594 |
|
594 | |||
595 | In [5]: strip_email_quotes('> > text\\n> > more\\nlast different') |
|
595 | In [5]: strip_email_quotes('> > text\\n> > more\\nlast different') | |
596 | Out[5]: '> > text\\n> > more\\nlast different' |
|
596 | Out[5]: '> > text\\n> > more\\nlast different' | |
597 | """ |
|
597 | """ | |
598 | lines = text.splitlines() |
|
598 | lines = text.splitlines() | |
599 | matches = set() |
|
599 | matches = set() | |
600 | for line in lines: |
|
600 | for line in lines: | |
601 | prefix = re.match(r'^(\s*>[ >]*)', line) |
|
601 | prefix = re.match(r'^(\s*>[ >]*)', line) | |
602 | if prefix: |
|
602 | if prefix: | |
603 | matches.add(prefix.group(1)) |
|
603 | matches.add(prefix.group(1)) | |
604 | else: |
|
604 | else: | |
605 | break |
|
605 | break | |
606 | else: |
|
606 | else: | |
607 | prefix = long_substr(list(matches)) |
|
607 | prefix = long_substr(list(matches)) | |
608 | if prefix: |
|
608 | if prefix: | |
609 | strip = len(prefix) |
|
609 | strip = len(prefix) | |
610 | text = '\n'.join([ ln[strip:] for ln in lines]) |
|
610 | text = '\n'.join([ ln[strip:] for ln in lines]) | |
611 | return text |
|
611 | return text | |
612 |
|
612 | |||
613 |
|
613 | |||
614 | class EvalFormatter(Formatter): |
|
614 | class EvalFormatter(Formatter): | |
615 | """A String Formatter that allows evaluation of simple expressions. |
|
615 | """A String Formatter that allows evaluation of simple expressions. | |
616 |
|
616 | |||
617 | Note that this version interprets a : as specifying a format string (as per |
|
617 | Note that this version interprets a : as specifying a format string (as per | |
618 | standard string formatting), so if slicing is required, you must explicitly |
|
618 | standard string formatting), so if slicing is required, you must explicitly | |
619 | create a slice. |
|
619 | create a slice. | |
620 |
|
620 | |||
621 | This is to be used in templating cases, such as the parallel batch |
|
621 | This is to be used in templating cases, such as the parallel batch | |
622 | script templates, where simple arithmetic on arguments is useful. |
|
622 | script templates, where simple arithmetic on arguments is useful. | |
623 |
|
623 | |||
624 | Examples |
|
624 | Examples | |
625 | -------- |
|
625 | -------- | |
626 |
|
626 | |||
627 | In [1]: f = EvalFormatter() |
|
627 | In [1]: f = EvalFormatter() | |
628 | In [2]: f.format('{n//4}', n=8) |
|
628 | In [2]: f.format('{n//4}', n=8) | |
629 | Out [2]: '2' |
|
629 | Out [2]: '2' | |
630 |
|
630 | |||
631 | In [3]: f.format("{greeting[slice(2,4)]}", greeting="Hello") |
|
631 | In [3]: f.format("{greeting[slice(2,4)]}", greeting="Hello") | |
632 | Out [3]: 'll' |
|
632 | Out [3]: 'll' | |
633 | """ |
|
633 | """ | |
634 | def get_field(self, name, args, kwargs): |
|
634 | def get_field(self, name, args, kwargs): | |
635 | v = eval(name, kwargs) |
|
635 | v = eval(name, kwargs) | |
636 | return v, name |
|
636 | return v, name | |
637 |
|
637 | |||
638 |
|
638 | |||
639 | @skip_doctest_py3 |
|
639 | @skip_doctest_py3 | |
640 | class FullEvalFormatter(Formatter): |
|
640 | class FullEvalFormatter(Formatter): | |
641 | """A String Formatter that allows evaluation of simple expressions. |
|
641 | """A String Formatter that allows evaluation of simple expressions. | |
642 |
|
642 | |||
643 | Any time a format key is not found in the kwargs, |
|
643 | Any time a format key is not found in the kwargs, | |
644 | it will be tried as an expression in the kwargs namespace. |
|
644 | it will be tried as an expression in the kwargs namespace. | |
645 |
|
645 | |||
646 | Note that this version allows slicing using [1:2], so you cannot specify |
|
646 | Note that this version allows slicing using [1:2], so you cannot specify | |
647 | a format string. Use :class:`EvalFormatter` to permit format strings. |
|
647 | a format string. Use :class:`EvalFormatter` to permit format strings. | |
648 |
|
648 | |||
649 | Examples |
|
649 | Examples | |
650 | -------- |
|
650 | -------- | |
651 |
|
651 | |||
652 | In [1]: f = FullEvalFormatter() |
|
652 | In [1]: f = FullEvalFormatter() | |
653 | In [2]: f.format('{n//4}', n=8) |
|
653 | In [2]: f.format('{n//4}', n=8) | |
654 | Out[2]: u'2' |
|
654 | Out[2]: u'2' | |
655 |
|
655 | |||
656 | In [3]: f.format('{list(range(5))[2:4]}') |
|
656 | In [3]: f.format('{list(range(5))[2:4]}') | |
657 | Out[3]: u'[2, 3]' |
|
657 | Out[3]: u'[2, 3]' | |
658 |
|
658 | |||
659 | In [4]: f.format('{3*2}') |
|
659 | In [4]: f.format('{3*2}') | |
660 | Out[4]: u'6' |
|
660 | Out[4]: u'6' | |
661 | """ |
|
661 | """ | |
662 | # copied from Formatter._vformat with minor changes to allow eval |
|
662 | # copied from Formatter._vformat with minor changes to allow eval | |
663 | # and replace the format_spec code with slicing |
|
663 | # and replace the format_spec code with slicing | |
664 | def _vformat(self, format_string, args, kwargs, used_args, recursion_depth): |
|
664 | def _vformat(self, format_string, args, kwargs, used_args, recursion_depth): | |
665 | if recursion_depth < 0: |
|
665 | if recursion_depth < 0: | |
666 | raise ValueError('Max string recursion exceeded') |
|
666 | raise ValueError('Max string recursion exceeded') | |
667 | result = [] |
|
667 | result = [] | |
668 | for literal_text, field_name, format_spec, conversion in \ |
|
668 | for literal_text, field_name, format_spec, conversion in \ | |
669 | self.parse(format_string): |
|
669 | self.parse(format_string): | |
670 |
|
670 | |||
671 | # output the literal text |
|
671 | # output the literal text | |
672 | if literal_text: |
|
672 | if literal_text: | |
673 | result.append(literal_text) |
|
673 | result.append(literal_text) | |
674 |
|
674 | |||
675 | # if there's a field, output it |
|
675 | # if there's a field, output it | |
676 | if field_name is not None: |
|
676 | if field_name is not None: | |
677 | # this is some markup, find the object and do |
|
677 | # this is some markup, find the object and do | |
678 | # the formatting |
|
678 | # the formatting | |
679 |
|
679 | |||
680 | if format_spec: |
|
680 | if format_spec: | |
681 | # override format spec, to allow slicing: |
|
681 | # override format spec, to allow slicing: | |
682 | field_name = ':'.join([field_name, format_spec]) |
|
682 | field_name = ':'.join([field_name, format_spec]) | |
683 |
|
683 | |||
684 | # eval the contents of the field for the object |
|
684 | # eval the contents of the field for the object | |
685 | # to be formatted |
|
685 | # to be formatted | |
686 | obj = eval(field_name, kwargs) |
|
686 | obj = eval(field_name, kwargs) | |
687 |
|
687 | |||
688 | # do any conversion on the resulting object |
|
688 | # do any conversion on the resulting object | |
689 | obj = self.convert_field(obj, conversion) |
|
689 | obj = self.convert_field(obj, conversion) | |
690 |
|
690 | |||
691 | # format the object and append to the result |
|
691 | # format the object and append to the result | |
692 | result.append(self.format_field(obj, '')) |
|
692 | result.append(self.format_field(obj, '')) | |
693 |
|
693 | |||
694 | return u''.join(py3compat.cast_unicode(s) for s in result) |
|
694 | return u''.join(py3compat.cast_unicode(s) for s in result) | |
695 |
|
695 | |||
696 |
|
696 | |||
697 | @skip_doctest_py3 |
|
697 | @skip_doctest_py3 | |
698 | class DollarFormatter(FullEvalFormatter): |
|
698 | class DollarFormatter(FullEvalFormatter): | |
699 | """Formatter allowing Itpl style $foo replacement, for names and attribute |
|
699 | """Formatter allowing Itpl style $foo replacement, for names and attribute | |
700 | access only. Standard {foo} replacement also works, and allows full |
|
700 | access only. Standard {foo} replacement also works, and allows full | |
701 | evaluation of its arguments. |
|
701 | evaluation of its arguments. | |
702 |
|
702 | |||
703 | Examples |
|
703 | Examples | |
704 | -------- |
|
704 | -------- | |
705 | In [1]: f = DollarFormatter() |
|
705 | In [1]: f = DollarFormatter() | |
706 | In [2]: f.format('{n//4}', n=8) |
|
706 | In [2]: f.format('{n//4}', n=8) | |
707 | Out[2]: u'2' |
|
707 | Out[2]: u'2' | |
708 |
|
708 | |||
709 | In [3]: f.format('23 * 76 is $result', result=23*76) |
|
709 | In [3]: f.format('23 * 76 is $result', result=23*76) | |
710 | Out[3]: u'23 * 76 is 1748' |
|
710 | Out[3]: u'23 * 76 is 1748' | |
711 |
|
711 | |||
712 | In [4]: f.format('$a or {b}', a=1, b=2) |
|
712 | In [4]: f.format('$a or {b}', a=1, b=2) | |
713 | Out[4]: u'1 or 2' |
|
713 | Out[4]: u'1 or 2' | |
714 | """ |
|
714 | """ | |
715 | _dollar_pattern = re.compile("(.*?)\$(\$?[\w\.]+)") |
|
715 | _dollar_pattern = re.compile("(.*?)\$(\$?[\w\.]+)") | |
716 | def parse(self, fmt_string): |
|
716 | def parse(self, fmt_string): | |
717 | for literal_txt, field_name, format_spec, conversion \ |
|
717 | for literal_txt, field_name, format_spec, conversion \ | |
718 | in Formatter.parse(self, fmt_string): |
|
718 | in Formatter.parse(self, fmt_string): | |
719 |
|
719 | |||
720 | # Find $foo patterns in the literal text. |
|
720 | # Find $foo patterns in the literal text. | |
721 | continue_from = 0 |
|
721 | continue_from = 0 | |
722 | txt = "" |
|
722 | txt = "" | |
723 | for m in self._dollar_pattern.finditer(literal_txt): |
|
723 | for m in self._dollar_pattern.finditer(literal_txt): | |
724 | new_txt, new_field = m.group(1,2) |
|
724 | new_txt, new_field = m.group(1,2) | |
725 | # $$foo --> $foo |
|
725 | # $$foo --> $foo | |
726 | if new_field.startswith("$"): |
|
726 | if new_field.startswith("$"): | |
727 | txt += new_txt + new_field |
|
727 | txt += new_txt + new_field | |
728 | else: |
|
728 | else: | |
729 | yield (txt + new_txt, new_field, "", None) |
|
729 | yield (txt + new_txt, new_field, "", None) | |
730 | txt = "" |
|
730 | txt = "" | |
731 | continue_from = m.end() |
|
731 | continue_from = m.end() | |
732 |
|
732 | |||
733 | # Re-yield the {foo} style pattern |
|
733 | # Re-yield the {foo} style pattern | |
734 | yield (txt + literal_txt[continue_from:], field_name, format_spec, conversion) |
|
734 | yield (txt + literal_txt[continue_from:], field_name, format_spec, conversion) | |
735 |
|
735 | |||
736 | #----------------------------------------------------------------------------- |
|
736 | #----------------------------------------------------------------------------- | |
737 | # Utils to columnize a list of string |
|
737 | # Utils to columnize a list of string | |
738 | #----------------------------------------------------------------------------- |
|
738 | #----------------------------------------------------------------------------- | |
739 |
|
739 | |||
740 | def _chunks(l, n): |
|
740 | def _chunks(l, n): | |
741 | """Yield successive n-sized chunks from l.""" |
|
741 | """Yield successive n-sized chunks from l.""" | |
742 | for i in xrange(0, len(l), n): |
|
742 | for i in xrange(0, len(l), n): | |
743 | yield l[i:i+n] |
|
743 | yield l[i:i+n] | |
744 |
|
744 | |||
745 |
|
745 | |||
746 | def _find_optimal(rlist , separator_size=2 , displaywidth=80): |
|
746 | def _find_optimal(rlist , separator_size=2 , displaywidth=80): | |
747 | """Calculate optimal info to columnize a list of string""" |
|
747 | """Calculate optimal info to columnize a list of string""" | |
748 | for nrow in range(1, len(rlist)+1) : |
|
748 | for nrow in range(1, len(rlist)+1) : | |
749 | chk = map(max,_chunks(rlist, nrow)) |
|
749 | chk = map(max,_chunks(rlist, nrow)) | |
750 | sumlength = sum(chk) |
|
750 | sumlength = sum(chk) | |
751 | ncols = len(chk) |
|
751 | ncols = len(chk) | |
752 | if sumlength+separator_size*(ncols-1) <= displaywidth : |
|
752 | if sumlength+separator_size*(ncols-1) <= displaywidth : | |
753 | break; |
|
753 | break; | |
754 | return {'columns_numbers' : ncols, |
|
754 | return {'columns_numbers' : ncols, | |
755 | 'optimal_separator_width':(displaywidth - sumlength)/(ncols-1) if (ncols -1) else 0, |
|
755 | 'optimal_separator_width':(displaywidth - sumlength)/(ncols-1) if (ncols -1) else 0, | |
756 | 'rows_numbers' : nrow, |
|
756 | 'rows_numbers' : nrow, | |
757 | 'columns_width' : chk |
|
757 | 'columns_width' : chk | |
758 | } |
|
758 | } | |
759 |
|
759 | |||
760 |
|
760 | |||
761 | def _get_or_default(mylist, i, default=None): |
|
761 | def _get_or_default(mylist, i, default=None): | |
762 | """return list item number, or default if don't exist""" |
|
762 | """return list item number, or default if don't exist""" | |
763 | if i >= len(mylist): |
|
763 | if i >= len(mylist): | |
764 | return default |
|
764 | return default | |
765 | else : |
|
765 | else : | |
766 | return mylist[i] |
|
766 | return mylist[i] | |
767 |
|
767 | |||
768 |
|
768 | |||
769 | @skip_doctest |
|
769 | @skip_doctest | |
770 | def compute_item_matrix(items, empty=None, *args, **kwargs) : |
|
770 | def compute_item_matrix(items, empty=None, *args, **kwargs) : | |
771 | """Returns a nested list, and info to columnize items |
|
771 | """Returns a nested list, and info to columnize items | |
772 |
|
772 | |||
773 |
Parameters |
|
773 | Parameters | |
774 |
---------- |
|
774 | ---------- | |
775 |
|
775 | |||
776 | items : |
|
776 | items : | |
777 | list of strings to columize |
|
777 | list of strings to columize | |
778 | empty : (default None) |
|
778 | empty : (default None) | |
779 | default value to fill list if needed |
|
779 | default value to fill list if needed | |
780 | separator_size : int (default=2) |
|
780 | separator_size : int (default=2) | |
781 | How much caracters will be used as a separation between each columns. |
|
781 | How much caracters will be used as a separation between each columns. | |
782 | displaywidth : int (default=80) |
|
782 | displaywidth : int (default=80) | |
783 | The width of the area onto wich the columns should enter |
|
783 | The width of the area onto wich the columns should enter | |
784 |
|
784 | |||
785 |
Returns |
|
785 | Returns | |
786 |
------- |
|
786 | ------- | |
787 |
|
787 | |||
788 | Returns a tuple of (strings_matrix, dict_info) |
|
788 | Returns a tuple of (strings_matrix, dict_info) | |
789 |
|
789 | |||
790 | strings_matrix : |
|
790 | strings_matrix : | |
791 |
|
791 | |||
792 | nested list of string, the outer most list contains as many list as |
|
792 | nested list of string, the outer most list contains as many list as | |
793 | rows, the innermost lists have each as many element as colums. If the |
|
793 | rows, the innermost lists have each as many element as colums. If the | |
794 | total number of elements in `items` does not equal the product of |
|
794 | total number of elements in `items` does not equal the product of | |
795 | rows*columns, the last element of some lists are filled with `None`. |
|
795 | rows*columns, the last element of some lists are filled with `None`. | |
796 |
|
796 | |||
797 | dict_info : |
|
797 | dict_info : | |
798 | some info to make columnize easier: |
|
798 | some info to make columnize easier: | |
799 |
|
799 | |||
800 | columns_numbers : number of columns |
|
800 | columns_numbers : number of columns | |
801 | rows_numbers : number of rows |
|
801 | rows_numbers : number of rows | |
802 | columns_width : list of with of each columns |
|
802 | columns_width : list of with of each columns | |
803 | optimal_separator_width : best separator width between columns |
|
803 | optimal_separator_width : best separator width between columns | |
804 |
|
804 | |||
805 |
Ex |
|
805 | Examples | |
806 |
-------- |
|
806 | -------- | |
807 |
|
807 | |||
808 | In [1]: l = ['aaa','b','cc','d','eeeee','f','g','h','i','j','k','l'] |
|
808 | In [1]: l = ['aaa','b','cc','d','eeeee','f','g','h','i','j','k','l'] | |
809 | ...: compute_item_matrix(l,displaywidth=12) |
|
809 | ...: compute_item_matrix(l,displaywidth=12) | |
810 | Out[1]: |
|
810 | Out[1]: | |
811 | ([['aaa', 'f', 'k'], |
|
811 | ([['aaa', 'f', 'k'], | |
812 | ['b', 'g', 'l'], |
|
812 | ['b', 'g', 'l'], | |
813 | ['cc', 'h', None], |
|
813 | ['cc', 'h', None], | |
814 | ['d', 'i', None], |
|
814 | ['d', 'i', None], | |
815 | ['eeeee', 'j', None]], |
|
815 | ['eeeee', 'j', None]], | |
816 | {'columns_numbers': 3, |
|
816 | {'columns_numbers': 3, | |
817 | 'columns_width': [5, 1, 1], |
|
817 | 'columns_width': [5, 1, 1], | |
818 | 'optimal_separator_width': 2, |
|
818 | 'optimal_separator_width': 2, | |
819 | 'rows_numbers': 5}) |
|
819 | 'rows_numbers': 5}) | |
820 |
|
820 | |||
821 | """ |
|
821 | """ | |
822 | info = _find_optimal(map(len, items), *args, **kwargs) |
|
822 | info = _find_optimal(map(len, items), *args, **kwargs) | |
823 | nrow, ncol = info['rows_numbers'], info['columns_numbers'] |
|
823 | nrow, ncol = info['rows_numbers'], info['columns_numbers'] | |
824 | return ([[ _get_or_default(items, c*nrow+i, default=empty) for c in range(ncol) ] for i in range(nrow) ], info) |
|
824 | return ([[ _get_or_default(items, c*nrow+i, default=empty) for c in range(ncol) ] for i in range(nrow) ], info) | |
825 |
|
825 | |||
826 |
|
826 | |||
827 | def columnize(items, separator=' ', displaywidth=80): |
|
827 | def columnize(items, separator=' ', displaywidth=80): | |
828 | """ Transform a list of strings into a single string with columns. |
|
828 | """ Transform a list of strings into a single string with columns. | |
829 |
|
829 | |||
830 | Parameters |
|
830 | Parameters | |
831 | ---------- |
|
831 | ---------- | |
832 | items : sequence of strings |
|
832 | items : sequence of strings | |
833 | The strings to process. |
|
833 | The strings to process. | |
834 |
|
834 | |||
835 | separator : str, optional [default is two spaces] |
|
835 | separator : str, optional [default is two spaces] | |
836 | The string that separates columns. |
|
836 | The string that separates columns. | |
837 |
|
837 | |||
838 | displaywidth : int, optional [default is 80] |
|
838 | displaywidth : int, optional [default is 80] | |
839 | Width of the display in number of characters. |
|
839 | Width of the display in number of characters. | |
840 |
|
840 | |||
841 | Returns |
|
841 | Returns | |
842 | ------- |
|
842 | ------- | |
843 | The formatted string. |
|
843 | The formatted string. | |
844 | """ |
|
844 | """ | |
845 | if not items : |
|
845 | if not items : | |
846 | return '\n' |
|
846 | return '\n' | |
847 | matrix, info = compute_item_matrix(items, separator_size=len(separator), displaywidth=displaywidth) |
|
847 | matrix, info = compute_item_matrix(items, separator_size=len(separator), displaywidth=displaywidth) | |
848 | fmatrix = [filter(None, x) for x in matrix] |
|
848 | fmatrix = [filter(None, x) for x in matrix] | |
849 | sjoin = lambda x : separator.join([ y.ljust(w, ' ') for y, w in zip(x, info['columns_width'])]) |
|
849 | sjoin = lambda x : separator.join([ y.ljust(w, ' ') for y, w in zip(x, info['columns_width'])]) | |
850 | return '\n'.join(map(sjoin, fmatrix))+'\n' |
|
850 | return '\n'.join(map(sjoin, fmatrix))+'\n' |
@@ -1,63 +1,65 b'' | |||||
1 | #!/usr/bin/env python |
|
1 | #!/usr/bin/env python | |
2 | """Script to auto-generate our API docs. |
|
2 | """Script to auto-generate our API docs. | |
3 | """ |
|
3 | """ | |
4 | # stdlib imports |
|
4 | # stdlib imports | |
5 | import os |
|
5 | import os | |
6 | import sys |
|
6 | import sys | |
7 |
|
7 | |||
8 | # local imports |
|
8 | # local imports | |
9 | sys.path.append(os.path.abspath('sphinxext')) |
|
9 | sys.path.append(os.path.abspath('sphinxext')) | |
10 | from apigen import ApiDocWriter |
|
10 | from apigen import ApiDocWriter | |
11 |
|
11 | |||
12 | #***************************************************************************** |
|
12 | #***************************************************************************** | |
13 | if __name__ == '__main__': |
|
13 | if __name__ == '__main__': | |
14 | pjoin = os.path.join |
|
14 | pjoin = os.path.join | |
15 | package = 'IPython' |
|
15 | package = 'IPython' | |
16 | outdir = pjoin('source','api','generated') |
|
16 | outdir = pjoin('source','api','generated') | |
17 | docwriter = ApiDocWriter(package,rst_extension='.txt') |
|
17 | docwriter = ApiDocWriter(package,rst_extension='.txt') | |
18 | # You have to escape the . here because . is a special char for regexps. |
|
18 | # You have to escape the . here because . is a special char for regexps. | |
19 | # You must do make clean if you change this! |
|
19 | # You must do make clean if you change this! | |
20 | docwriter.package_skip_patterns += [r'\.fixes$', |
|
20 | docwriter.package_skip_patterns += [r'\.fixes$', | |
21 | r'\.external$', |
|
21 | r'\.external$', | |
22 | r'\.extensions', |
|
22 | r'\.extensions', | |
23 | r'\.kernel\.config', |
|
23 | r'\.kernel\.config', | |
24 | r'\.attic', |
|
24 | r'\.attic', | |
25 | r'\.quarantine', |
|
25 | r'\.quarantine', | |
26 | r'\.deathrow', |
|
26 | r'\.deathrow', | |
27 | r'\.config\.default', |
|
27 | r'\.config\.default', | |
28 | r'\.config\.profile', |
|
28 | r'\.config\.profile', | |
29 | r'\.frontend', |
|
29 | r'\.frontend', | |
30 | r'\.gui', |
|
30 | r'\.gui', | |
31 | r'\.kernel', |
|
31 | r'\.kernel', | |
32 | # For now, the zmq code has |
|
32 | # For now, the zmq code has | |
33 | # unconditional top-level code so it's |
|
33 | # unconditional top-level code so it's | |
34 | # not import safe. This needs fixing |
|
34 | # not import safe. This needs fixing | |
35 | r'\.zmq', |
|
35 | r'\.zmq', | |
36 | ] |
|
36 | ] | |
37 |
|
37 | |||
38 | docwriter.module_skip_patterns += [ r'\.core\.fakemodule', |
|
38 | docwriter.module_skip_patterns += [ r'\.core\.fakemodule', | |
39 | r'\.testing\.iptest', |
|
39 | r'\.testing\.iptest', | |
40 | # Keeping these disabled is OK |
|
40 | # Keeping these disabled is OK | |
41 | r'\.parallel\.controller\.mongodb', |
|
41 | r'\.parallel\.controller\.mongodb', | |
42 | r'\.lib\.inputhookwx', |
|
42 | r'\.lib\.inputhookwx', | |
43 | r'\.lib\.inputhookgtk', |
|
43 | r'\.lib\.inputhookgtk', | |
44 | r'\.cocoa', |
|
44 | r'\.cocoa', | |
45 | r'\.ipdoctest', |
|
45 | r'\.ipdoctest', | |
46 | r'\.Gnuplot', |
|
46 | r'\.Gnuplot', | |
47 | r'\.frontend\.process\.winprocess', |
|
47 | r'\.frontend\.process\.winprocess', | |
48 | r'\.Shell', |
|
48 | r'\.Shell', | |
49 | ] |
|
49 | ] | |
50 |
|
50 | |||
51 | # If we don't have pexpect, we can't load irunner, so skip any code that |
|
51 | # If we don't have pexpect, we can't load irunner, so skip any code that | |
52 | # depends on it |
|
52 | # depends on it | |
53 | try: |
|
53 | try: | |
54 | import pexpect |
|
54 | import pexpect | |
55 | except ImportError: |
|
55 | except ImportError: | |
56 | docwriter.module_skip_patterns += [r'\.lib\.irunner', |
|
56 | docwriter.module_skip_patterns += [r'\.lib\.irunner', | |
57 | r'\.testing\.mkdoctests'] |
|
57 | r'\.testing\.mkdoctests'] | |
58 | # Now, generate the outputs |
|
58 | # Now, generate the outputs | |
59 | docwriter.write_api_docs(outdir) |
|
59 | docwriter.write_api_docs(outdir) | |
60 | docwriter.write_index(outdir, 'gen', |
|
60 | # Write index with .rst extension - we can include it, but Sphinx won't try | |
|
61 | # to compile it | |||
|
62 | docwriter.write_index(outdir, 'gen.rst', | |||
61 | relative_to = pjoin('source','api') |
|
63 | relative_to = pjoin('source','api') | |
62 | ) |
|
64 | ) | |
63 | print '%d files written' % len(docwriter.written_modules) |
|
65 | print '%d files written' % len(docwriter.written_modules) |
@@ -1,12 +1,12 b'' | |||||
1 | .. _api-index: |
|
1 | .. _api-index: | |
2 |
|
2 | |||
3 | ################### |
|
3 | ################### | |
4 | The IPython API |
|
4 | The IPython API | |
5 | ################### |
|
5 | ################### | |
6 |
|
6 | |||
7 | .. htmlonly:: |
|
7 | .. htmlonly:: | |
8 |
|
8 | |||
9 | :Release: |version| |
|
9 | :Release: |version| | |
10 | :Date: |today| |
|
10 | :Date: |today| | |
11 |
|
11 | |||
12 |
.. include:: generated/gen. |
|
12 | .. include:: generated/gen.rst |
@@ -1,8 +1,8 b'' | |||||
1 | .. _extensions_storemagic: |
|
1 | .. _extensions_storemagic: | |
2 |
|
2 | |||
3 | ========== |
|
3 | ========== | |
4 | storemagic |
|
4 | storemagic | |
5 | ========== |
|
5 | ========== | |
6 |
|
6 | |||
7 | .. automodule:: IPython.extensions.storemagic |
|
7 | .. automodule:: IPython.extensions.storemagic | |
8 |
:members: |
|
8 | :members: store |
@@ -1,552 +1,554 b'' | |||||
1 | .. _config_overview: |
|
1 | .. _config_overview: | |
2 |
|
2 | |||
3 | ============================================ |
|
3 | ============================================ | |
4 | Overview of the IPython configuration system |
|
4 | Overview of the IPython configuration system | |
5 | ============================================ |
|
5 | ============================================ | |
6 |
|
6 | |||
7 | This section describes the IPython configuration system. Starting with version |
|
7 | This section describes the IPython configuration system. Starting with version | |
8 | 0.11, IPython has a completely new configuration system that is quite |
|
8 | 0.11, IPython has a completely new configuration system that is quite | |
9 | different from the older :file:`ipythonrc` or :file:`ipy_user_conf.py` |
|
9 | different from the older :file:`ipythonrc` or :file:`ipy_user_conf.py` | |
10 | approaches. The new configuration system was designed from scratch to address |
|
10 | approaches. The new configuration system was designed from scratch to address | |
11 | the particular configuration needs of IPython. While there are many |
|
11 | the particular configuration needs of IPython. While there are many | |
12 | other excellent configuration systems out there, we found that none of them |
|
12 | other excellent configuration systems out there, we found that none of them | |
13 | met our requirements. |
|
13 | met our requirements. | |
14 |
|
14 | |||
15 | .. warning:: |
|
15 | .. warning:: | |
16 |
|
16 | |||
17 | If you are upgrading to version 0.11 of IPython, you will need to migrate |
|
17 | If you are upgrading to version 0.11 of IPython, you will need to migrate | |
18 | your old :file:`ipythonrc` or :file:`ipy_user_conf.py` configuration files |
|
18 | your old :file:`ipythonrc` or :file:`ipy_user_conf.py` configuration files | |
19 | to the new system. You may want to read the section on |
|
19 | to the new system. You may want to read the section on | |
20 | :ref:`configuring IPython <configuring_ipython>`. There are also some ideas |
|
20 | :ref:`configuring IPython <configuring_ipython>`. There are also some ideas | |
21 | `on the IPython wiki <http://wiki.ipython.org/Cookbook/Moving_config_to_IPython_0.11>`_ |
|
21 | `on the IPython wiki <http://wiki.ipython.org/Cookbook/Moving_config_to_IPython_0.11>`_ | |
22 | about this. |
|
22 | about this. | |
23 |
|
23 | |||
24 | The discussion that follows is focused on teaching users how to configure |
|
24 | The discussion that follows is focused on teaching users how to configure | |
25 | IPython to their liking. Developers who want to know more about how they |
|
25 | IPython to their liking. Developers who want to know more about how they | |
26 | can enable their objects to take advantage of the configuration system |
|
26 | can enable their objects to take advantage of the configuration system | |
27 | should consult our :ref:`developer guide <developer_guide>` |
|
27 | should consult our :ref:`developer guide <developer_guide>` | |
28 |
|
28 | |||
29 | The main concepts |
|
29 | The main concepts | |
30 | ================= |
|
30 | ================= | |
31 |
|
31 | |||
32 | There are a number of abstractions that the IPython configuration system uses. |
|
32 | There are a number of abstractions that the IPython configuration system uses. | |
33 | Each of these abstractions is represented by a Python class. |
|
33 | Each of these abstractions is represented by a Python class. | |
34 |
|
34 | |||
35 | Configuration object: :class:`~IPython.config.loader.Config` |
|
35 | Configuration object: :class:`~IPython.config.loader.Config` | |
36 | A configuration object is a simple dictionary-like class that holds |
|
36 | A configuration object is a simple dictionary-like class that holds | |
37 | configuration attributes and sub-configuration objects. These classes |
|
37 | configuration attributes and sub-configuration objects. These classes | |
38 | support dotted attribute style access (``Foo.bar``) in addition to the |
|
38 | support dotted attribute style access (``Foo.bar``) in addition to the | |
39 | regular dictionary style access (``Foo['bar']``). Configuration objects |
|
39 | regular dictionary style access (``Foo['bar']``). Configuration objects | |
40 | are smart. They know how to merge themselves with other configuration |
|
40 | are smart. They know how to merge themselves with other configuration | |
41 | objects and they automatically create sub-configuration objects. |
|
41 | objects and they automatically create sub-configuration objects. | |
42 |
|
42 | |||
43 | Application: :class:`~IPython.config.application.Application` |
|
43 | Application: :class:`~IPython.config.application.Application` | |
44 | An application is a process that does a specific job. The most obvious |
|
44 | An application is a process that does a specific job. The most obvious | |
45 | application is the :command:`ipython` command line program. Each |
|
45 | application is the :command:`ipython` command line program. Each | |
46 | application reads *one or more* configuration files and a single set of |
|
46 | application reads *one or more* configuration files and a single set of | |
47 | command line options |
|
47 | command line options | |
48 | and then produces a master configuration object for the application. This |
|
48 | and then produces a master configuration object for the application. This | |
49 | configuration object is then passed to the configurable objects that the |
|
49 | configuration object is then passed to the configurable objects that the | |
50 | application creates. These configurable objects implement the actual logic |
|
50 | application creates. These configurable objects implement the actual logic | |
51 | of the application and know how to configure themselves given the |
|
51 | of the application and know how to configure themselves given the | |
52 | configuration object. |
|
52 | configuration object. | |
53 |
|
53 | |||
54 | Applications always have a `log` attribute that is a configured Logger. |
|
54 | Applications always have a `log` attribute that is a configured Logger. | |
55 | This allows centralized logging configuration per-application. |
|
55 | This allows centralized logging configuration per-application. | |
56 |
|
56 | |||
57 | Configurable: :class:`~IPython.config.configurable.Configurable` |
|
57 | Configurable: :class:`~IPython.config.configurable.Configurable` | |
58 | A configurable is a regular Python class that serves as a base class for |
|
58 | A configurable is a regular Python class that serves as a base class for | |
59 | all main classes in an application. The |
|
59 | all main classes in an application. The | |
60 | :class:`~IPython.config.configurable.Configurable` base class is |
|
60 | :class:`~IPython.config.configurable.Configurable` base class is | |
61 | lightweight and only does one things. |
|
61 | lightweight and only does one things. | |
62 |
|
62 | |||
63 | This :class:`~IPython.config.configurable.Configurable` is a subclass |
|
63 | This :class:`~IPython.config.configurable.Configurable` is a subclass | |
64 | of :class:`~IPython.utils.traitlets.HasTraits` that knows how to configure |
|
64 | of :class:`~IPython.utils.traitlets.HasTraits` that knows how to configure | |
65 | itself. Class level traits with the metadata ``config=True`` become |
|
65 | itself. Class level traits with the metadata ``config=True`` become | |
66 | values that can be configured from the command line and configuration |
|
66 | values that can be configured from the command line and configuration | |
67 | files. |
|
67 | files. | |
68 |
|
68 | |||
69 | Developers create :class:`~IPython.config.configurable.Configurable` |
|
69 | Developers create :class:`~IPython.config.configurable.Configurable` | |
70 | subclasses that implement all of the logic in the application. Each of |
|
70 | subclasses that implement all of the logic in the application. Each of | |
71 | these subclasses has its own configuration information that controls how |
|
71 | these subclasses has its own configuration information that controls how | |
72 | instances are created. |
|
72 | instances are created. | |
73 |
|
73 | |||
74 | Singletons: :class:`~IPython.config.configurable.SingletonConfigurable` |
|
74 | Singletons: :class:`~IPython.config.configurable.SingletonConfigurable` | |
75 | Any object for which there is a single canonical instance. These are |
|
75 | Any object for which there is a single canonical instance. These are | |
76 | just like Configurables, except they have a class method |
|
76 | just like Configurables, except they have a class method | |
77 | :meth:`~IPython.config.configurable.SingletonConfigurable.instance`, |
|
77 | :meth:`~IPython.config.configurable.SingletonConfigurable.instance`, | |
78 | that returns the current active instance (or creates one if it |
|
78 | that returns the current active instance (or creates one if it | |
79 | does not exist). Examples of singletons include |
|
79 | does not exist). Examples of singletons include | |
80 | :class:`~IPython.config.application.Application`s and |
|
80 | :class:`~IPython.config.application.Application`s and | |
81 | :class:`~IPython.core.interactiveshell.InteractiveShell`. This lets |
|
81 | :class:`~IPython.core.interactiveshell.InteractiveShell`. This lets | |
82 | objects easily connect to the current running Application without passing |
|
82 | objects easily connect to the current running Application without passing | |
83 | objects around everywhere. For instance, to get the current running |
|
83 | objects around everywhere. For instance, to get the current running | |
84 | Application instance, simply do: ``app = Application.instance()``. |
|
84 | Application instance, simply do: ``app = Application.instance()``. | |
85 |
|
85 | |||
86 |
|
86 | |||
87 | .. note:: |
|
87 | .. note:: | |
88 |
|
88 | |||
89 | Singletons are not strictly enforced - you can have many instances |
|
89 | Singletons are not strictly enforced - you can have many instances | |
90 | of a given singleton class, but the :meth:`instance` method will always |
|
90 | of a given singleton class, but the :meth:`instance` method will always | |
91 | return the same one. |
|
91 | return the same one. | |
92 |
|
92 | |||
93 | Having described these main concepts, we can now state the main idea in our |
|
93 | Having described these main concepts, we can now state the main idea in our | |
94 | configuration system: *"configuration" allows the default values of class |
|
94 | configuration system: *"configuration" allows the default values of class | |
95 | attributes to be controlled on a class by class basis*. Thus all instances of |
|
95 | attributes to be controlled on a class by class basis*. Thus all instances of | |
96 | a given class are configured in the same way. Furthermore, if two instances |
|
96 | a given class are configured in the same way. Furthermore, if two instances | |
97 | need to be configured differently, they need to be instances of two different |
|
97 | need to be configured differently, they need to be instances of two different | |
98 | classes. While this model may seem a bit restrictive, we have found that it |
|
98 | classes. While this model may seem a bit restrictive, we have found that it | |
99 | expresses most things that need to be configured extremely well. However, it |
|
99 | expresses most things that need to be configured extremely well. However, it | |
100 | is possible to create two instances of the same class that have different |
|
100 | is possible to create two instances of the same class that have different | |
101 | trait values. This is done by overriding the configuration. |
|
101 | trait values. This is done by overriding the configuration. | |
102 |
|
102 | |||
103 | Now, we show what our configuration objects and files look like. |
|
103 | Now, we show what our configuration objects and files look like. | |
104 |
|
104 | |||
105 | Configuration objects and files |
|
105 | Configuration objects and files | |
106 | =============================== |
|
106 | =============================== | |
107 |
|
107 | |||
108 | A configuration file is simply a pure Python file that sets the attributes |
|
108 | A configuration file is simply a pure Python file that sets the attributes | |
109 | of a global, pre-created configuration object. This configuration object is a |
|
109 | of a global, pre-created configuration object. This configuration object is a | |
110 | :class:`~IPython.config.loader.Config` instance. While in a configuration |
|
110 | :class:`~IPython.config.loader.Config` instance. While in a configuration | |
111 | file, to get a reference to this object, simply call the :func:`get_config` |
|
111 | file, to get a reference to this object, simply call the :func:`get_config` | |
112 | function. We inject this function into the global namespace that the |
|
112 | function. We inject this function into the global namespace that the | |
113 | configuration file is executed in. |
|
113 | configuration file is executed in. | |
114 |
|
114 | |||
115 | Here is an example of a super simple configuration file that does nothing:: |
|
115 | Here is an example of a super simple configuration file that does nothing:: | |
116 |
|
116 | |||
117 | c = get_config() |
|
117 | c = get_config() | |
118 |
|
118 | |||
119 | Once you get a reference to the configuration object, you simply set |
|
119 | Once you get a reference to the configuration object, you simply set | |
120 | attributes on it. All you have to know is: |
|
120 | attributes on it. All you have to know is: | |
121 |
|
121 | |||
122 | * The name of each attribute. |
|
122 | * The name of each attribute. | |
123 | * The type of each attribute. |
|
123 | * The type of each attribute. | |
124 |
|
124 | |||
125 | The answers to these two questions are provided by the various |
|
125 | The answers to these two questions are provided by the various | |
126 | :class:`~IPython.config.configurable.Configurable` subclasses that an |
|
126 | :class:`~IPython.config.configurable.Configurable` subclasses that an | |
127 | application uses. Let's look at how this would work for a simple configurable |
|
127 | application uses. Let's look at how this would work for a simple configurable | |
128 | subclass:: |
|
128 | subclass:: | |
129 |
|
129 | |||
130 | # Sample configurable: |
|
130 | # Sample configurable: | |
131 | from IPython.config.configurable import Configurable |
|
131 | from IPython.config.configurable import Configurable | |
132 | from IPython.utils.traitlets import Int, Float, Unicode, Bool |
|
132 | from IPython.utils.traitlets import Int, Float, Unicode, Bool | |
133 |
|
133 | |||
134 | class MyClass(Configurable): |
|
134 | class MyClass(Configurable): | |
135 | name = Unicode(u'defaultname', config=True) |
|
135 | name = Unicode(u'defaultname', config=True) | |
136 | ranking = Int(0, config=True) |
|
136 | ranking = Int(0, config=True) | |
137 | value = Float(99.0) |
|
137 | value = Float(99.0) | |
138 | # The rest of the class implementation would go here.. |
|
138 | # The rest of the class implementation would go here.. | |
139 |
|
139 | |||
140 | In this example, we see that :class:`MyClass` has three attributes, two |
|
140 | In this example, we see that :class:`MyClass` has three attributes, two | |
141 | of whom (``name``, ``ranking``) can be configured. All of the attributes |
|
141 | of whom (``name``, ``ranking``) can be configured. All of the attributes | |
142 | are given types and default values. If a :class:`MyClass` is instantiated, |
|
142 | are given types and default values. If a :class:`MyClass` is instantiated, | |
143 | but not configured, these default values will be used. But let's see how |
|
143 | but not configured, these default values will be used. But let's see how | |
144 | to configure this class in a configuration file:: |
|
144 | to configure this class in a configuration file:: | |
145 |
|
145 | |||
146 | # Sample config file |
|
146 | # Sample config file | |
147 | c = get_config() |
|
147 | c = get_config() | |
148 |
|
148 | |||
149 | c.MyClass.name = 'coolname' |
|
149 | c.MyClass.name = 'coolname' | |
150 | c.MyClass.ranking = 10 |
|
150 | c.MyClass.ranking = 10 | |
151 |
|
151 | |||
152 | After this configuration file is loaded, the values set in it will override |
|
152 | After this configuration file is loaded, the values set in it will override | |
153 | the class defaults anytime a :class:`MyClass` is created. Furthermore, |
|
153 | the class defaults anytime a :class:`MyClass` is created. Furthermore, | |
154 | these attributes will be type checked and validated anytime they are set. |
|
154 | these attributes will be type checked and validated anytime they are set. | |
155 | This type checking is handled by the :mod:`IPython.utils.traitlets` module, |
|
155 | This type checking is handled by the :mod:`IPython.utils.traitlets` module, | |
156 | which provides the :class:`Unicode`, :class:`Int` and :class:`Float` types. |
|
156 | which provides the :class:`Unicode`, :class:`Int` and :class:`Float` types. | |
157 | In addition to these traitlets, the :mod:`IPython.utils.traitlets` provides |
|
157 | In addition to these traitlets, the :mod:`IPython.utils.traitlets` provides | |
158 | traitlets for a number of other types. |
|
158 | traitlets for a number of other types. | |
159 |
|
159 | |||
160 | .. note:: |
|
160 | .. note:: | |
161 |
|
161 | |||
162 | Underneath the hood, the :class:`Configurable` base class is a subclass of |
|
162 | Underneath the hood, the :class:`Configurable` base class is a subclass of | |
163 | :class:`IPython.utils.traitlets.HasTraits`. The |
|
163 | :class:`IPython.utils.traitlets.HasTraits`. The | |
164 | :mod:`IPython.utils.traitlets` module is a lightweight version of |
|
164 | :mod:`IPython.utils.traitlets` module is a lightweight version of | |
165 | :mod:`enthought.traits`. Our implementation is a pure Python subset |
|
165 | :mod:`enthought.traits`. Our implementation is a pure Python subset | |
166 | (mostly API compatible) of :mod:`enthought.traits` that does not have any |
|
166 | (mostly API compatible) of :mod:`enthought.traits` that does not have any | |
167 | of the automatic GUI generation capabilities. Our plan is to achieve 100% |
|
167 | of the automatic GUI generation capabilities. Our plan is to achieve 100% | |
168 | API compatibility to enable the actual :mod:`enthought.traits` to |
|
168 | API compatibility to enable the actual :mod:`enthought.traits` to | |
169 | eventually be used instead. Currently, we cannot use |
|
169 | eventually be used instead. Currently, we cannot use | |
170 | :mod:`enthought.traits` as we are committed to the core of IPython being |
|
170 | :mod:`enthought.traits` as we are committed to the core of IPython being | |
171 | pure Python. |
|
171 | pure Python. | |
172 |
|
172 | |||
173 | It should be very clear at this point what the naming convention is for |
|
173 | It should be very clear at this point what the naming convention is for | |
174 | configuration attributes:: |
|
174 | configuration attributes:: | |
175 |
|
175 | |||
176 | c.ClassName.attribute_name = attribute_value |
|
176 | c.ClassName.attribute_name = attribute_value | |
177 |
|
177 | |||
178 | Here, ``ClassName`` is the name of the class whose configuration attribute you |
|
178 | Here, ``ClassName`` is the name of the class whose configuration attribute you | |
179 | want to set, ``attribute_name`` is the name of the attribute you want to set |
|
179 | want to set, ``attribute_name`` is the name of the attribute you want to set | |
180 | and ``attribute_value`` the the value you want it to have. The ``ClassName`` |
|
180 | and ``attribute_value`` the the value you want it to have. The ``ClassName`` | |
181 | attribute of ``c`` is not the actual class, but instead is another |
|
181 | attribute of ``c`` is not the actual class, but instead is another | |
182 | :class:`~IPython.config.loader.Config` instance. |
|
182 | :class:`~IPython.config.loader.Config` instance. | |
183 |
|
183 | |||
184 | .. note:: |
|
184 | .. note:: | |
185 |
|
185 | |||
186 | The careful reader may wonder how the ``ClassName`` (``MyClass`` in |
|
186 | The careful reader may wonder how the ``ClassName`` (``MyClass`` in | |
187 | the above example) attribute of the configuration object ``c`` gets |
|
187 | the above example) attribute of the configuration object ``c`` gets | |
188 | created. These attributes are created on the fly by the |
|
188 | created. These attributes are created on the fly by the | |
189 | :class:`~IPython.config.loader.Config` instance, using a simple naming |
|
189 | :class:`~IPython.config.loader.Config` instance, using a simple naming | |
190 | convention. Any attribute of a :class:`~IPython.config.loader.Config` |
|
190 | convention. Any attribute of a :class:`~IPython.config.loader.Config` | |
191 | instance whose name begins with an uppercase character is assumed to be a |
|
191 | instance whose name begins with an uppercase character is assumed to be a | |
192 | sub-configuration and a new empty :class:`~IPython.config.loader.Config` |
|
192 | sub-configuration and a new empty :class:`~IPython.config.loader.Config` | |
193 | instance is dynamically created for that attribute. This allows deeply |
|
193 | instance is dynamically created for that attribute. This allows deeply | |
194 | hierarchical information created easily (``c.Foo.Bar.value``) on the fly. |
|
194 | hierarchical information created easily (``c.Foo.Bar.value``) on the fly. | |
195 |
|
195 | |||
196 | Configuration files inheritance |
|
196 | Configuration files inheritance | |
197 | =============================== |
|
197 | =============================== | |
198 |
|
198 | |||
199 | Let's say you want to have different configuration files for various purposes. |
|
199 | Let's say you want to have different configuration files for various purposes. | |
200 | Our configuration system makes it easy for one configuration file to inherit |
|
200 | Our configuration system makes it easy for one configuration file to inherit | |
201 | the information in another configuration file. The :func:`load_subconfig` |
|
201 | the information in another configuration file. The :func:`load_subconfig` | |
202 | command can be used in a configuration file for this purpose. Here is a simple |
|
202 | command can be used in a configuration file for this purpose. Here is a simple | |
203 | example that loads all of the values from the file :file:`base_config.py`:: |
|
203 | example that loads all of the values from the file :file:`base_config.py`:: | |
204 |
|
204 | |||
205 | # base_config.py |
|
205 | # base_config.py | |
206 | c = get_config() |
|
206 | c = get_config() | |
207 | c.MyClass.name = 'coolname' |
|
207 | c.MyClass.name = 'coolname' | |
208 | c.MyClass.ranking = 100 |
|
208 | c.MyClass.ranking = 100 | |
209 |
|
209 | |||
210 | into the configuration file :file:`main_config.py`:: |
|
210 | into the configuration file :file:`main_config.py`:: | |
211 |
|
211 | |||
212 | # main_config.py |
|
212 | # main_config.py | |
213 | c = get_config() |
|
213 | c = get_config() | |
214 |
|
214 | |||
215 | # Load everything from base_config.py |
|
215 | # Load everything from base_config.py | |
216 | load_subconfig('base_config.py') |
|
216 | load_subconfig('base_config.py') | |
217 |
|
217 | |||
218 | # Now override one of the values |
|
218 | # Now override one of the values | |
219 | c.MyClass.name = 'bettername' |
|
219 | c.MyClass.name = 'bettername' | |
220 |
|
220 | |||
221 | In a situation like this the :func:`load_subconfig` makes sure that the |
|
221 | In a situation like this the :func:`load_subconfig` makes sure that the | |
222 | search path for sub-configuration files is inherited from that of the parent. |
|
222 | search path for sub-configuration files is inherited from that of the parent. | |
223 | Thus, you can typically put the two in the same directory and everything will |
|
223 | Thus, you can typically put the two in the same directory and everything will | |
224 | just work. |
|
224 | just work. | |
225 |
|
225 | |||
226 | You can also load configuration files by profile, for instance: |
|
226 | You can also load configuration files by profile, for instance: | |
227 |
|
227 | |||
228 | .. sourcecode:: python |
|
228 | .. sourcecode:: python | |
229 |
|
229 | |||
230 | load_subconfig('ipython_config.py', profile='default') |
|
230 | load_subconfig('ipython_config.py', profile='default') | |
231 |
|
231 | |||
232 | to inherit your default configuration as a starting point. |
|
232 | to inherit your default configuration as a starting point. | |
233 |
|
233 | |||
234 |
|
234 | |||
235 | Class based configuration inheritance |
|
235 | Class based configuration inheritance | |
236 | ===================================== |
|
236 | ===================================== | |
237 |
|
237 | |||
238 | There is another aspect of configuration where inheritance comes into play. |
|
238 | There is another aspect of configuration where inheritance comes into play. | |
239 | Sometimes, your classes will have an inheritance hierarchy that you want |
|
239 | Sometimes, your classes will have an inheritance hierarchy that you want | |
240 | to be reflected in the configuration system. Here is a simple example:: |
|
240 | to be reflected in the configuration system. Here is a simple example:: | |
241 |
|
241 | |||
242 | from IPython.config.configurable import Configurable |
|
242 | from IPython.config.configurable import Configurable | |
243 | from IPython.utils.traitlets import Int, Float, Unicode, Bool |
|
243 | from IPython.utils.traitlets import Int, Float, Unicode, Bool | |
244 |
|
244 | |||
245 | class Foo(Configurable): |
|
245 | class Foo(Configurable): | |
246 | name = Unicode(u'fooname', config=True) |
|
246 | name = Unicode(u'fooname', config=True) | |
247 | value = Float(100.0, config=True) |
|
247 | value = Float(100.0, config=True) | |
248 |
|
248 | |||
249 | class Bar(Foo): |
|
249 | class Bar(Foo): | |
250 | name = Unicode(u'barname', config=True) |
|
250 | name = Unicode(u'barname', config=True) | |
251 | othervalue = Int(0, config=True) |
|
251 | othervalue = Int(0, config=True) | |
252 |
|
252 | |||
253 | Now, we can create a configuration file to configure instances of :class:`Foo` |
|
253 | Now, we can create a configuration file to configure instances of :class:`Foo` | |
254 | and :class:`Bar`:: |
|
254 | and :class:`Bar`:: | |
255 |
|
255 | |||
256 | # config file |
|
256 | # config file | |
257 | c = get_config() |
|
257 | c = get_config() | |
258 |
|
258 | |||
259 | c.Foo.name = u'bestname' |
|
259 | c.Foo.name = u'bestname' | |
260 | c.Bar.othervalue = 10 |
|
260 | c.Bar.othervalue = 10 | |
261 |
|
261 | |||
262 | This class hierarchy and configuration file accomplishes the following: |
|
262 | This class hierarchy and configuration file accomplishes the following: | |
263 |
|
263 | |||
264 | * The default value for :attr:`Foo.name` and :attr:`Bar.name` will be |
|
264 | * The default value for :attr:`Foo.name` and :attr:`Bar.name` will be | |
265 | 'bestname'. Because :class:`Bar` is a :class:`Foo` subclass it also |
|
265 | 'bestname'. Because :class:`Bar` is a :class:`Foo` subclass it also | |
266 | picks up the configuration information for :class:`Foo`. |
|
266 | picks up the configuration information for :class:`Foo`. | |
267 | * The default value for :attr:`Foo.value` and :attr:`Bar.value` will be |
|
267 | * The default value for :attr:`Foo.value` and :attr:`Bar.value` will be | |
268 | ``100.0``, which is the value specified as the class default. |
|
268 | ``100.0``, which is the value specified as the class default. | |
269 | * The default value for :attr:`Bar.othervalue` will be 10 as set in the |
|
269 | * The default value for :attr:`Bar.othervalue` will be 10 as set in the | |
270 | configuration file. Because :class:`Foo` is the parent of :class:`Bar` |
|
270 | configuration file. Because :class:`Foo` is the parent of :class:`Bar` | |
271 | it doesn't know anything about the :attr:`othervalue` attribute. |
|
271 | it doesn't know anything about the :attr:`othervalue` attribute. | |
272 |
|
272 | |||
273 |
|
273 | |||
274 | .. _ipython_dir: |
|
274 | .. _ipython_dir: | |
275 |
|
275 | |||
276 | Configuration file location |
|
276 | Configuration file location | |
277 | =========================== |
|
277 | =========================== | |
278 |
|
278 | |||
279 | So where should you put your configuration files? IPython uses "profiles" for |
|
279 | So where should you put your configuration files? IPython uses "profiles" for | |
280 | configuration, and by default, all profiles will be stored in the so called |
|
280 | configuration, and by default, all profiles will be stored in the so called | |
281 | "IPython directory". The location of this directory is determined by the |
|
281 | "IPython directory". The location of this directory is determined by the | |
282 | following algorithm: |
|
282 | following algorithm: | |
283 |
|
283 | |||
284 | * If the ``ipython-dir`` command line flag is given, its value is used. |
|
284 | * If the ``ipython-dir`` command line flag is given, its value is used. | |
285 |
|
285 | |||
286 | * If not, the value returned by :func:`IPython.utils.path.get_ipython_dir` |
|
286 | * If not, the value returned by :func:`IPython.utils.path.get_ipython_dir` | |
287 | is used. This function will first look at the :envvar:`IPYTHONDIR` |
|
287 | is used. This function will first look at the :envvar:`IPYTHONDIR` | |
288 | environment variable and then default to a platform-specific default. |
|
288 | environment variable and then default to a platform-specific default. | |
289 | Historical support for the :envvar:`IPYTHON_DIR` environment variable will |
|
289 | Historical support for the :envvar:`IPYTHON_DIR` environment variable will | |
290 | be removed in a future release. |
|
290 | be removed in a future release. | |
291 |
|
291 | |||
292 | On posix systems (Linux, Unix, etc.), IPython respects the ``$XDG_CONFIG_HOME`` |
|
292 | On posix systems (Linux, Unix, etc.), IPython respects the ``$XDG_CONFIG_HOME`` | |
293 | part of the `XDG Base Directory`_ specification. If ``$XDG_CONFIG_HOME`` is |
|
293 | part of the `XDG Base Directory`_ specification. If ``$XDG_CONFIG_HOME`` is | |
294 | defined and exists ( ``XDG_CONFIG_HOME`` has a default interpretation of |
|
294 | defined and exists ( ``XDG_CONFIG_HOME`` has a default interpretation of | |
295 | :file:`$HOME/.config`), then IPython's config directory will be located in |
|
295 | :file:`$HOME/.config`), then IPython's config directory will be located in | |
296 | :file:`$XDG_CONFIG_HOME/ipython`. If users still have an IPython directory |
|
296 | :file:`$XDG_CONFIG_HOME/ipython`. If users still have an IPython directory | |
297 | in :file:`$HOME/.ipython`, then that will be used. in preference to the |
|
297 | in :file:`$HOME/.ipython`, then that will be used. in preference to the | |
298 | system default. |
|
298 | system default. | |
299 |
|
299 | |||
300 | For most users, the default value will simply be something like |
|
300 | For most users, the default value will simply be something like | |
301 | :file:`$HOME/.config/ipython` on Linux, or :file:`$HOME/.ipython` |
|
301 | :file:`$HOME/.config/ipython` on Linux, or :file:`$HOME/.ipython` | |
302 | elsewhere. |
|
302 | elsewhere. | |
303 |
|
303 | |||
304 | Once the location of the IPython directory has been determined, you need to know |
|
304 | Once the location of the IPython directory has been determined, you need to know | |
305 | which profile you are using. For users with a single configuration, this will |
|
305 | which profile you are using. For users with a single configuration, this will | |
306 | simply be 'default', and will be located in |
|
306 | simply be 'default', and will be located in | |
307 | :file:`<IPYTHONDIR>/profile_default`. |
|
307 | :file:`<IPYTHONDIR>/profile_default`. | |
308 |
|
308 | |||
309 | The next thing you need to know is what to call your configuration file. The |
|
309 | The next thing you need to know is what to call your configuration file. The | |
310 | basic idea is that each application has its own default configuration filename. |
|
310 | basic idea is that each application has its own default configuration filename. | |
311 | The default named used by the :command:`ipython` command line program is |
|
311 | The default named used by the :command:`ipython` command line program is | |
312 | :file:`ipython_config.py`, and *all* IPython applications will use this file. |
|
312 | :file:`ipython_config.py`, and *all* IPython applications will use this file. | |
313 | Other applications, such as the parallel :command:`ipcluster` scripts or the |
|
313 | Other applications, such as the parallel :command:`ipcluster` scripts or the | |
314 | QtConsole will load their own config files *after* :file:`ipython_config.py`. To |
|
314 | QtConsole will load their own config files *after* :file:`ipython_config.py`. To | |
315 | load a particular configuration file instead of the default, the name can be |
|
315 | load a particular configuration file instead of the default, the name can be | |
316 | overridden by the ``config_file`` command line flag. |
|
316 | overridden by the ``config_file`` command line flag. | |
317 |
|
317 | |||
318 | To generate the default configuration files, do:: |
|
318 | To generate the default configuration files, do:: | |
319 |
|
319 | |||
320 | $> ipython profile create |
|
320 | $> ipython profile create | |
321 |
|
321 | |||
322 | and you will have a default :file:`ipython_config.py` in your IPython directory |
|
322 | and you will have a default :file:`ipython_config.py` in your IPython directory | |
323 | under :file:`profile_default`. If you want the default config files for the |
|
323 | under :file:`profile_default`. If you want the default config files for the | |
324 | :mod:`IPython.parallel` applications, add ``--parallel`` to the end of the |
|
324 | :mod:`IPython.parallel` applications, add ``--parallel`` to the end of the | |
325 | command-line args. |
|
325 | command-line args. | |
326 |
|
326 | |||
327 |
|
327 | |||
328 | Locating these files |
|
328 | Locating these files | |
329 | -------------------- |
|
329 | -------------------- | |
330 |
|
330 | |||
331 | From the command-line, you can quickly locate the IPYTHONDIR or a specific |
|
331 | From the command-line, you can quickly locate the IPYTHONDIR or a specific | |
332 | profile with: |
|
332 | profile with: | |
333 |
|
333 | |||
334 | .. sourcecode:: bash |
|
334 | .. sourcecode:: bash | |
335 |
|
335 | |||
336 | $> ipython locate |
|
336 | $> ipython locate | |
337 | /home/you/.ipython |
|
337 | /home/you/.ipython | |
338 |
|
338 | |||
339 | $> ipython locate profile foo |
|
339 | $> ipython locate profile foo | |
340 | /home/you/.ipython/profile_foo |
|
340 | /home/you/.ipython/profile_foo | |
341 |
|
341 | |||
342 | These map to the utility functions: :func:`IPython.utils.path.get_ipython_dir` |
|
342 | These map to the utility functions: :func:`IPython.utils.path.get_ipython_dir` | |
343 | and :func:`IPython.utils.path.locate_profile` respectively. |
|
343 | and :func:`IPython.utils.path.locate_profile` respectively. | |
344 |
|
344 | |||
345 |
|
345 | |||
346 | .. _Profiles: |
|
346 | .. _Profiles: | |
347 |
|
347 | |||
348 | Profiles |
|
348 | Profiles | |
349 | ======== |
|
349 | ======== | |
350 |
|
350 | |||
351 | A profile is a directory containing configuration and runtime files, such as |
|
351 | A profile is a directory containing configuration and runtime files, such as | |
352 | logs, connection info for the parallel apps, and your IPython command history. |
|
352 | logs, connection info for the parallel apps, and your IPython command history. | |
353 |
|
353 | |||
354 | The idea is that users often want to maintain a set of configuration files for |
|
354 | The idea is that users often want to maintain a set of configuration files for | |
355 | different purposes: one for doing numerical computing with NumPy and SciPy and |
|
355 | different purposes: one for doing numerical computing with NumPy and SciPy and | |
356 | another for doing symbolic computing with SymPy. Profiles make it easy to keep a |
|
356 | another for doing symbolic computing with SymPy. Profiles make it easy to keep a | |
357 | separate configuration files, logs, and histories for each of these purposes. |
|
357 | separate configuration files, logs, and histories for each of these purposes. | |
358 |
|
358 | |||
359 | Let's start by showing how a profile is used: |
|
359 | Let's start by showing how a profile is used: | |
360 |
|
360 | |||
361 | .. code-block:: bash |
|
361 | .. code-block:: bash | |
362 |
|
362 | |||
363 | $ ipython --profile=sympy |
|
363 | $ ipython --profile=sympy | |
364 |
|
364 | |||
365 | This tells the :command:`ipython` command line program to get its configuration |
|
365 | This tells the :command:`ipython` command line program to get its configuration | |
366 | from the "sympy" profile. The file names for various profiles do not change. The |
|
366 | from the "sympy" profile. The file names for various profiles do not change. The | |
367 | only difference is that profiles are named in a special way. In the case above, |
|
367 | only difference is that profiles are named in a special way. In the case above, | |
368 | the "sympy" profile means looking for :file:`ipython_config.py` in :file:`<IPYTHONDIR>/profile_sympy`. |
|
368 | the "sympy" profile means looking for :file:`ipython_config.py` in :file:`<IPYTHONDIR>/profile_sympy`. | |
369 |
|
369 | |||
370 | The general pattern is this: simply create a new profile with: |
|
370 | The general pattern is this: simply create a new profile with: | |
371 |
|
371 | |||
372 | .. code-block:: bash |
|
372 | .. code-block:: bash | |
373 |
|
373 | |||
374 | ipython profile create <name> |
|
374 | ipython profile create <name> | |
375 |
|
375 | |||
376 | which adds a directory called ``profile_<name>`` to your IPython directory. Then |
|
376 | which adds a directory called ``profile_<name>`` to your IPython directory. Then | |
377 | you can load this profile by adding ``--profile=<name>`` to your command line |
|
377 | you can load this profile by adding ``--profile=<name>`` to your command line | |
378 | options. Profiles are supported by all IPython applications. |
|
378 | options. Profiles are supported by all IPython applications. | |
379 |
|
379 | |||
380 | IPython ships with some sample profiles in :file:`IPython/config/profile`. If |
|
380 | IPython ships with some sample profiles in :file:`IPython/config/profile`. If | |
381 | you create profiles with the name of one of our shipped profiles, these config |
|
381 | you create profiles with the name of one of our shipped profiles, these config | |
382 | files will be copied over instead of starting with the automatically generated |
|
382 | files will be copied over instead of starting with the automatically generated | |
383 | config files. |
|
383 | config files. | |
384 |
|
384 | |||
385 | Security Files |
|
385 | Security Files | |
386 | -------------- |
|
386 | -------------- | |
387 |
|
387 | |||
388 | If you are using the notebook, qtconsole, or parallel code, IPython stores |
|
388 | If you are using the notebook, qtconsole, or parallel code, IPython stores | |
389 | connection information in small JSON files in the active profile's security |
|
389 | connection information in small JSON files in the active profile's security | |
390 | directory. This directory is made private, so only you can see the files inside. If |
|
390 | directory. This directory is made private, so only you can see the files inside. If | |
391 | you need to move connection files around to other computers, this is where they will |
|
391 | you need to move connection files around to other computers, this is where they will | |
392 | be. If you want your code to be able to open security files by name, we have a |
|
392 | be. If you want your code to be able to open security files by name, we have a | |
393 | convenience function :func:`IPython.utils.path.get_security_file`, which will return |
|
393 | convenience function :func:`IPython.utils.path.get_security_file`, which will return | |
394 | the absolute path to a security file from its filename and [optionally] profile |
|
394 | the absolute path to a security file from its filename and [optionally] profile | |
395 | name. |
|
395 | name. | |
396 |
|
396 | |||
|
397 | .. _startup_files: | |||
|
398 | ||||
397 | Startup Files |
|
399 | Startup Files | |
398 | ------------- |
|
400 | ------------- | |
399 |
|
401 | |||
400 | If you want some code to be run at the beginning of every IPython session with a |
|
402 | If you want some code to be run at the beginning of every IPython session with a | |
401 | particular profile, the easiest way is to add Python (.py) or IPython (.ipy) scripts |
|
403 | particular profile, the easiest way is to add Python (.py) or IPython (.ipy) scripts | |
402 | to your :file:`<profile>/startup` directory. Files in this directory will always be |
|
404 | to your :file:`<profile>/startup` directory. Files in this directory will always be | |
403 | executed as soon as the IPython shell is constructed, and before any other code or |
|
405 | executed as soon as the IPython shell is constructed, and before any other code or | |
404 | scripts you have specified. If you have multiple files in the startup directory, |
|
406 | scripts you have specified. If you have multiple files in the startup directory, | |
405 | they will be run in lexicographical order, so you can control the ordering by adding |
|
407 | they will be run in lexicographical order, so you can control the ordering by adding | |
406 | a '00-' prefix. |
|
408 | a '00-' prefix. | |
407 |
|
409 | |||
408 | .. note:: |
|
410 | .. note:: | |
409 |
|
411 | |||
410 | Automatic startup files are new in IPython 0.12. Use the |
|
412 | Automatic startup files are new in IPython 0.12. Use the | |
411 | InteractiveShellApp.exec_files configurable for similar behavior in 0.11. |
|
413 | InteractiveShellApp.exec_files configurable for similar behavior in 0.11. | |
412 |
|
414 | |||
413 |
|
415 | |||
414 | .. _commandline: |
|
416 | .. _commandline: | |
415 |
|
417 | |||
416 | Command-line arguments |
|
418 | Command-line arguments | |
417 | ====================== |
|
419 | ====================== | |
418 |
|
420 | |||
419 | IPython exposes *all* configurable options on the command-line. The command-line |
|
421 | IPython exposes *all* configurable options on the command-line. The command-line | |
420 | arguments are generated from the Configurable traits of the classes associated |
|
422 | arguments are generated from the Configurable traits of the classes associated | |
421 | with a given Application. Configuring IPython from the command-line may look |
|
423 | with a given Application. Configuring IPython from the command-line may look | |
422 | very similar to an IPython config file |
|
424 | very similar to an IPython config file | |
423 |
|
425 | |||
424 | IPython applications use a parser called |
|
426 | IPython applications use a parser called | |
425 | :class:`~IPython.config.loader.KeyValueLoader` to load values into a Config |
|
427 | :class:`~IPython.config.loader.KeyValueLoader` to load values into a Config | |
426 | object. Values are assigned in much the same way as in a config file: |
|
428 | object. Values are assigned in much the same way as in a config file: | |
427 |
|
429 | |||
428 | .. code-block:: bash |
|
430 | .. code-block:: bash | |
429 |
|
431 | |||
430 | $> ipython --InteractiveShell.use_readline=False --BaseIPythonApplication.profile='myprofile' |
|
432 | $> ipython --InteractiveShell.use_readline=False --BaseIPythonApplication.profile='myprofile' | |
431 |
|
433 | |||
432 | Is the same as adding: |
|
434 | Is the same as adding: | |
433 |
|
435 | |||
434 | .. sourcecode:: python |
|
436 | .. sourcecode:: python | |
435 |
|
437 | |||
436 | c.InteractiveShell.use_readline=False |
|
438 | c.InteractiveShell.use_readline=False | |
437 | c.BaseIPythonApplication.profile='myprofile' |
|
439 | c.BaseIPythonApplication.profile='myprofile' | |
438 |
|
440 | |||
439 | to your config file. Key/Value arguments *always* take a value, separated by '=' |
|
441 | to your config file. Key/Value arguments *always* take a value, separated by '=' | |
440 | and no spaces. |
|
442 | and no spaces. | |
441 |
|
443 | |||
442 | Common Arguments |
|
444 | Common Arguments | |
443 | **************** |
|
445 | ---------------- | |
444 |
|
446 | |||
445 | Since the strictness and verbosity of the KVLoader above are not ideal for everyday |
|
447 | Since the strictness and verbosity of the KVLoader above are not ideal for everyday | |
446 | use, common arguments can be specified as flags_ or aliases_. |
|
448 | use, common arguments can be specified as flags_ or aliases_. | |
447 |
|
449 | |||
448 | Flags and Aliases are handled by :mod:`argparse` instead, allowing for more flexible |
|
450 | Flags and Aliases are handled by :mod:`argparse` instead, allowing for more flexible | |
449 | parsing. In general, flags and aliases are prefixed by ``--``, except for those |
|
451 | parsing. In general, flags and aliases are prefixed by ``--``, except for those | |
450 | that are single characters, in which case they can be specified with a single ``-``, e.g.: |
|
452 | that are single characters, in which case they can be specified with a single ``-``, e.g.: | |
451 |
|
453 | |||
452 | .. code-block:: bash |
|
454 | .. code-block:: bash | |
453 |
|
455 | |||
454 | $> ipython -i -c "import numpy; x=numpy.linspace(0,1)" --profile testing --colors=lightbg |
|
456 | $> ipython -i -c "import numpy; x=numpy.linspace(0,1)" --profile testing --colors=lightbg | |
455 |
|
457 | |||
456 | Aliases |
|
458 | Aliases | |
457 | ------- |
|
459 | ******* | |
458 |
|
460 | |||
459 | For convenience, applications have a mapping of commonly used traits, so you don't have |
|
461 | For convenience, applications have a mapping of commonly used traits, so you don't have | |
460 | to specify the whole class name: |
|
462 | to specify the whole class name: | |
461 |
|
463 | |||
462 | .. code-block:: bash |
|
464 | .. code-block:: bash | |
463 |
|
465 | |||
464 | $> ipython --profile myprofile |
|
466 | $> ipython --profile myprofile | |
465 | # and |
|
467 | # and | |
466 | $> ipython --profile='myprofile' |
|
468 | $> ipython --profile='myprofile' | |
467 | # are equivalent to |
|
469 | # are equivalent to | |
468 | $> ipython --BaseIPythonApplication.profile='myprofile' |
|
470 | $> ipython --BaseIPythonApplication.profile='myprofile' | |
469 |
|
471 | |||
470 | Flags |
|
472 | Flags | |
471 | ----- |
|
473 | ***** | |
472 |
|
474 | |||
473 | Applications can also be passed **flags**. Flags are options that take no |
|
475 | Applications can also be passed **flags**. Flags are options that take no | |
474 | arguments. They are simply wrappers for |
|
476 | arguments. They are simply wrappers for | |
475 | setting one or more configurables with predefined values, often True/False. |
|
477 | setting one or more configurables with predefined values, often True/False. | |
476 |
|
478 | |||
477 | For instance: |
|
479 | For instance: | |
478 |
|
480 | |||
479 | .. code-block:: bash |
|
481 | .. code-block:: bash | |
480 |
|
482 | |||
481 | $> ipcontroller --debug |
|
483 | $> ipcontroller --debug | |
482 | # is equivalent to |
|
484 | # is equivalent to | |
483 | $> ipcontroller --Application.log_level=DEBUG |
|
485 | $> ipcontroller --Application.log_level=DEBUG | |
484 | # and |
|
486 | # and | |
485 | $> ipython --pylab |
|
487 | $> ipython --pylab | |
486 | # is equivalent to |
|
488 | # is equivalent to | |
487 | $> ipython --pylab=auto |
|
489 | $> ipython --pylab=auto | |
488 | # or |
|
490 | # or | |
489 | $> ipython --no-banner |
|
491 | $> ipython --no-banner | |
490 | # is equivalent to |
|
492 | # is equivalent to | |
491 | $> ipython --TerminalIPythonApp.display_banner=False |
|
493 | $> ipython --TerminalIPythonApp.display_banner=False | |
492 |
|
494 | |||
493 | Subcommands |
|
495 | Subcommands | |
494 | *********** |
|
496 | ----------- | |
495 |
|
497 | |||
496 |
|
498 | |||
497 | Some IPython applications have **subcommands**. Subcommands are modeled after |
|
499 | Some IPython applications have **subcommands**. Subcommands are modeled after | |
498 | :command:`git`, and are called with the form :command:`command subcommand |
|
500 | :command:`git`, and are called with the form :command:`command subcommand | |
499 | [...args]`. Currently, the QtConsole is a subcommand of terminal IPython: |
|
501 | [...args]`. Currently, the QtConsole is a subcommand of terminal IPython: | |
500 |
|
502 | |||
501 | .. code-block:: bash |
|
503 | .. code-block:: bash | |
502 |
|
504 | |||
503 | $> ipython qtconsole --profile=myprofile |
|
505 | $> ipython qtconsole --profile=myprofile | |
504 |
|
506 | |||
505 | and :command:`ipcluster` is simply a wrapper for its various subcommands (start, |
|
507 | and :command:`ipcluster` is simply a wrapper for its various subcommands (start, | |
506 | stop, engines). |
|
508 | stop, engines). | |
507 |
|
509 | |||
508 | .. code-block:: bash |
|
510 | .. code-block:: bash | |
509 |
|
511 | |||
510 | $> ipcluster start --profile=myprofile --n=4 |
|
512 | $> ipcluster start --profile=myprofile --n=4 | |
511 |
|
513 | |||
512 |
|
514 | |||
513 | To see a list of the available aliases, flags, and subcommands for an IPython application, simply pass ``-h`` or ``--help``. And to see the full list of configurable options (*very* long), pass ``--help-all``. |
|
515 | To see a list of the available aliases, flags, and subcommands for an IPython application, simply pass ``-h`` or ``--help``. And to see the full list of configurable options (*very* long), pass ``--help-all``. | |
514 |
|
516 | |||
515 |
|
517 | |||
516 | Design requirements |
|
518 | Design requirements | |
517 | =================== |
|
519 | =================== | |
518 |
|
520 | |||
519 | Here are the main requirements we wanted our configuration system to have: |
|
521 | Here are the main requirements we wanted our configuration system to have: | |
520 |
|
522 | |||
521 | * Support for hierarchical configuration information. |
|
523 | * Support for hierarchical configuration information. | |
522 |
|
524 | |||
523 | * Full integration with command line option parsers. Often, you want to read |
|
525 | * Full integration with command line option parsers. Often, you want to read | |
524 | a configuration file, but then override some of the values with command line |
|
526 | a configuration file, but then override some of the values with command line | |
525 | options. Our configuration system automates this process and allows each |
|
527 | options. Our configuration system automates this process and allows each | |
526 | command line option to be linked to a particular attribute in the |
|
528 | command line option to be linked to a particular attribute in the | |
527 | configuration hierarchy that it will override. |
|
529 | configuration hierarchy that it will override. | |
528 |
|
530 | |||
529 | * Configuration files that are themselves valid Python code. This accomplishes |
|
531 | * Configuration files that are themselves valid Python code. This accomplishes | |
530 | many things. First, it becomes possible to put logic in your configuration |
|
532 | many things. First, it becomes possible to put logic in your configuration | |
531 | files that sets attributes based on your operating system, network setup, |
|
533 | files that sets attributes based on your operating system, network setup, | |
532 | Python version, etc. Second, Python has a super simple syntax for accessing |
|
534 | Python version, etc. Second, Python has a super simple syntax for accessing | |
533 | hierarchical data structures, namely regular attribute access |
|
535 | hierarchical data structures, namely regular attribute access | |
534 | (``Foo.Bar.Bam.name``). Third, using Python makes it easy for users to |
|
536 | (``Foo.Bar.Bam.name``). Third, using Python makes it easy for users to | |
535 | import configuration attributes from one configuration file to another. |
|
537 | import configuration attributes from one configuration file to another. | |
536 | Fourth, even though Python is dynamically typed, it does have types that can |
|
538 | Fourth, even though Python is dynamically typed, it does have types that can | |
537 | be checked at runtime. Thus, a ``1`` in a config file is the integer '1', |
|
539 | be checked at runtime. Thus, a ``1`` in a config file is the integer '1', | |
538 | while a ``'1'`` is a string. |
|
540 | while a ``'1'`` is a string. | |
539 |
|
541 | |||
540 | * A fully automated method for getting the configuration information to the |
|
542 | * A fully automated method for getting the configuration information to the | |
541 | classes that need it at runtime. Writing code that walks a configuration |
|
543 | classes that need it at runtime. Writing code that walks a configuration | |
542 | hierarchy to extract a particular attribute is painful. When you have |
|
544 | hierarchy to extract a particular attribute is painful. When you have | |
543 | complex configuration information with hundreds of attributes, this makes |
|
545 | complex configuration information with hundreds of attributes, this makes | |
544 | you want to cry. |
|
546 | you want to cry. | |
545 |
|
547 | |||
546 | * Type checking and validation that doesn't require the entire configuration |
|
548 | * Type checking and validation that doesn't require the entire configuration | |
547 | hierarchy to be specified statically before runtime. Python is a very |
|
549 | hierarchy to be specified statically before runtime. Python is a very | |
548 | dynamic language and you don't always know everything that needs to be |
|
550 | dynamic language and you don't always know everything that needs to be | |
549 | configured when a program starts. |
|
551 | configured when a program starts. | |
550 |
|
552 | |||
551 |
|
553 | |||
552 | .. _`XDG Base Directory`: http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html |
|
554 | .. _`XDG Base Directory`: http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html |
@@ -1,1150 +1,1150 b'' | |||||
1 | ================= |
|
1 | ================= | |
2 | IPython reference |
|
2 | IPython reference | |
3 | ================= |
|
3 | ================= | |
4 |
|
4 | |||
5 | .. _command_line_options: |
|
5 | .. _command_line_options: | |
6 |
|
6 | |||
7 | Command-line usage |
|
7 | Command-line usage | |
8 | ================== |
|
8 | ================== | |
9 |
|
9 | |||
10 | You start IPython with the command:: |
|
10 | You start IPython with the command:: | |
11 |
|
11 | |||
12 | $ ipython [options] files |
|
12 | $ ipython [options] files | |
13 |
|
13 | |||
14 | .. note:: |
|
14 | .. note:: | |
15 |
|
15 | |||
16 | For IPython on Python 3, use ``ipython3`` in place of ``ipython``. |
|
16 | For IPython on Python 3, use ``ipython3`` in place of ``ipython``. | |
17 |
|
17 | |||
18 | If invoked with no options, it executes all the files listed in sequence |
|
18 | If invoked with no options, it executes all the files listed in sequence | |
19 | and drops you into the interpreter while still acknowledging any options |
|
19 | and drops you into the interpreter while still acknowledging any options | |
20 | you may have set in your ipython_config.py. This behavior is different from |
|
20 | you may have set in your ipython_config.py. This behavior is different from | |
21 | standard Python, which when called as python -i will only execute one |
|
21 | standard Python, which when called as python -i will only execute one | |
22 | file and ignore your configuration setup. |
|
22 | file and ignore your configuration setup. | |
23 |
|
23 | |||
24 | Please note that some of the configuration options are not available at |
|
24 | Please note that some of the configuration options are not available at | |
25 | the command line, simply because they are not practical here. Look into |
|
25 | the command line, simply because they are not practical here. Look into | |
26 | your configuration files for details on those. There are separate configuration |
|
26 | your configuration files for details on those. There are separate configuration | |
27 | files for each profile, and the files look like "ipython_config.py" or |
|
27 | files for each profile, and the files look like "ipython_config.py" or | |
28 | "ipython_config_<frontendname>.py". Profile directories look like |
|
28 | "ipython_config_<frontendname>.py". Profile directories look like | |
29 | "profile_profilename" and are typically installed in the IPYTHONDIR directory. |
|
29 | "profile_profilename" and are typically installed in the IPYTHONDIR directory. | |
30 | For Linux users, this will be $HOME/.config/ipython, and for other users it |
|
30 | For Linux users, this will be $HOME/.config/ipython, and for other users it | |
31 | will be $HOME/.ipython. For Windows users, $HOME resolves to C:\\Documents and |
|
31 | will be $HOME/.ipython. For Windows users, $HOME resolves to C:\\Documents and | |
32 | Settings\\YourUserName in most instances. |
|
32 | Settings\\YourUserName in most instances. | |
33 |
|
33 | |||
34 |
|
34 | |||
35 | Eventloop integration |
|
35 | Eventloop integration | |
36 | --------------------- |
|
36 | --------------------- | |
37 |
|
37 | |||
38 | Previously IPython had command line options for controlling GUI event loop |
|
38 | Previously IPython had command line options for controlling GUI event loop | |
39 | integration (-gthread, -qthread, -q4thread, -wthread, -pylab). As of IPython |
|
39 | integration (-gthread, -qthread, -q4thread, -wthread, -pylab). As of IPython | |
40 | version 0.11, these have been removed. Please see the new ``%gui`` |
|
40 | version 0.11, these have been removed. Please see the new ``%gui`` | |
41 | magic command or :ref:`this section <gui_support>` for details on the new |
|
41 | magic command or :ref:`this section <gui_support>` for details on the new | |
42 | interface, or specify the gui at the commandline:: |
|
42 | interface, or specify the gui at the commandline:: | |
43 |
|
43 | |||
44 | $ ipython --gui=qt |
|
44 | $ ipython --gui=qt | |
45 |
|
45 | |||
46 |
|
46 | |||
47 | Command-line Options |
|
47 | Command-line Options | |
48 | -------------------- |
|
48 | -------------------- | |
49 |
|
49 | |||
50 | To see the options IPython accepts, use ``ipython --help`` (and you probably |
|
50 | To see the options IPython accepts, use ``ipython --help`` (and you probably | |
51 | should run the output through a pager such as ``ipython --help | less`` for |
|
51 | should run the output through a pager such as ``ipython --help | less`` for | |
52 | more convenient reading). This shows all the options that have a single-word |
|
52 | more convenient reading). This shows all the options that have a single-word | |
53 | alias to control them, but IPython lets you configure all of its objects from |
|
53 | alias to control them, but IPython lets you configure all of its objects from | |
54 | the command-line by passing the full class name and a corresponding value; type |
|
54 | the command-line by passing the full class name and a corresponding value; type | |
55 | ``ipython --help-all`` to see this full list. For example:: |
|
55 | ``ipython --help-all`` to see this full list. For example:: | |
56 |
|
56 | |||
57 | ipython --pylab qt |
|
57 | ipython --pylab qt | |
58 |
|
58 | |||
59 | is equivalent to:: |
|
59 | is equivalent to:: | |
60 |
|
60 | |||
61 | ipython --TerminalIPythonApp.pylab='qt' |
|
61 | ipython --TerminalIPythonApp.pylab='qt' | |
62 |
|
62 | |||
63 | Note that in the second form, you *must* use the equal sign, as the expression |
|
63 | Note that in the second form, you *must* use the equal sign, as the expression | |
64 | is evaluated as an actual Python assignment. While in the above example the |
|
64 | is evaluated as an actual Python assignment. While in the above example the | |
65 | short form is more convenient, only the most common options have a short form, |
|
65 | short form is more convenient, only the most common options have a short form, | |
66 | while any configurable variable in IPython can be set at the command-line by |
|
66 | while any configurable variable in IPython can be set at the command-line by | |
67 | using the long form. This long form is the same syntax used in the |
|
67 | using the long form. This long form is the same syntax used in the | |
68 | configuration files, if you want to set these options permanently. |
|
68 | configuration files, if you want to set these options permanently. | |
69 |
|
69 | |||
70 |
|
70 | |||
71 | Interactive use |
|
71 | Interactive use | |
72 | =============== |
|
72 | =============== | |
73 |
|
73 | |||
74 | IPython is meant to work as a drop-in replacement for the standard interactive |
|
74 | IPython is meant to work as a drop-in replacement for the standard interactive | |
75 | interpreter. As such, any code which is valid python should execute normally |
|
75 | interpreter. As such, any code which is valid python should execute normally | |
76 | under IPython (cases where this is not true should be reported as bugs). It |
|
76 | under IPython (cases where this is not true should be reported as bugs). It | |
77 | does, however, offer many features which are not available at a standard python |
|
77 | does, however, offer many features which are not available at a standard python | |
78 | prompt. What follows is a list of these. |
|
78 | prompt. What follows is a list of these. | |
79 |
|
79 | |||
80 |
|
80 | |||
81 | Caution for Windows users |
|
81 | Caution for Windows users | |
82 | ------------------------- |
|
82 | ------------------------- | |
83 |
|
83 | |||
84 | Windows, unfortunately, uses the '\\' character as a path separator. This is a |
|
84 | Windows, unfortunately, uses the '\\' character as a path separator. This is a | |
85 | terrible choice, because '\\' also represents the escape character in most |
|
85 | terrible choice, because '\\' also represents the escape character in most | |
86 | modern programming languages, including Python. For this reason, using '/' |
|
86 | modern programming languages, including Python. For this reason, using '/' | |
87 | character is recommended if you have problems with ``\``. However, in Windows |
|
87 | character is recommended if you have problems with ``\``. However, in Windows | |
88 | commands '/' flags options, so you can not use it for the root directory. This |
|
88 | commands '/' flags options, so you can not use it for the root directory. This | |
89 | means that paths beginning at the root must be typed in a contrived manner |
|
89 | means that paths beginning at the root must be typed in a contrived manner | |
90 | like: ``%copy \opt/foo/bar.txt \tmp`` |
|
90 | like: ``%copy \opt/foo/bar.txt \tmp`` | |
91 |
|
91 | |||
92 | .. _magic: |
|
92 | .. _magic: | |
93 |
|
93 | |||
94 | Magic command system |
|
94 | Magic command system | |
95 | -------------------- |
|
95 | -------------------- | |
96 |
|
96 | |||
97 | IPython will treat any line whose first character is a % as a special |
|
97 | IPython will treat any line whose first character is a % as a special | |
98 | call to a 'magic' function. These allow you to control the behavior of |
|
98 | call to a 'magic' function. These allow you to control the behavior of | |
99 | IPython itself, plus a lot of system-type features. They are all |
|
99 | IPython itself, plus a lot of system-type features. They are all | |
100 | prefixed with a % character, but parameters are given without |
|
100 | prefixed with a % character, but parameters are given without | |
101 | parentheses or quotes. |
|
101 | parentheses or quotes. | |
102 |
|
102 | |||
103 | Lines that begin with ``%%`` signal a *cell magic*: they take as arguments not |
|
103 | Lines that begin with ``%%`` signal a *cell magic*: they take as arguments not | |
104 | only the rest of the current line, but all lines below them as well, in the |
|
104 | only the rest of the current line, but all lines below them as well, in the | |
105 | current execution block. Cell magics can in fact make arbitrary modifications |
|
105 | current execution block. Cell magics can in fact make arbitrary modifications | |
106 | to the input they receive, which need not even be valid Python code at all. |
|
106 | to the input they receive, which need not even be valid Python code at all. | |
107 | They receive the whole block as a single string. |
|
107 | They receive the whole block as a single string. | |
108 |
|
108 | |||
109 | As a line magic example, the ``%cd`` magic works just like the OS command of |
|
109 | As a line magic example, the ``%cd`` magic works just like the OS command of | |
110 | the same name:: |
|
110 | the same name:: | |
111 |
|
111 | |||
112 | In [8]: %cd |
|
112 | In [8]: %cd | |
113 | /home/fperez |
|
113 | /home/fperez | |
114 |
|
114 | |||
115 | The following uses the builtin ``timeit`` in cell mode:: |
|
115 | The following uses the builtin ``timeit`` in cell mode:: | |
116 |
|
116 | |||
117 | In [10]: %%timeit x = range(10000) |
|
117 | In [10]: %%timeit x = range(10000) | |
118 | ...: min(x) |
|
118 | ...: min(x) | |
119 | ...: max(x) |
|
119 | ...: max(x) | |
120 | ...: |
|
120 | ...: | |
121 | 1000 loops, best of 3: 438 us per loop |
|
121 | 1000 loops, best of 3: 438 us per loop | |
122 |
|
122 | |||
123 | In this case, ``x = range(10000)`` is called as the line argument, and the |
|
123 | In this case, ``x = range(10000)`` is called as the line argument, and the | |
124 | block with ``min(x)`` and ``max(x)`` is called as the cell body. The |
|
124 | block with ``min(x)`` and ``max(x)`` is called as the cell body. The | |
125 | ``timeit`` magic receives both. |
|
125 | ``timeit`` magic receives both. | |
126 |
|
126 | |||
127 | If you have 'automagic' enabled (as it by default), you don't need to type in |
|
127 | If you have 'automagic' enabled (as it by default), you don't need to type in | |
128 | the single ``%`` explicitly for line magics; IPython will scan its internal |
|
128 | the single ``%`` explicitly for line magics; IPython will scan its internal | |
129 | list of magic functions and call one if it exists. With automagic on you can |
|
129 | list of magic functions and call one if it exists. With automagic on you can | |
130 | then just type ``cd mydir`` to go to directory 'mydir':: |
|
130 | then just type ``cd mydir`` to go to directory 'mydir':: | |
131 |
|
131 | |||
132 | In [9]: cd mydir |
|
132 | In [9]: cd mydir | |
133 | /home/fperez/mydir |
|
133 | /home/fperez/mydir | |
134 |
|
134 | |||
135 | Note that cell magics *always* require an explicit ``%%`` prefix, automagic |
|
135 | Note that cell magics *always* require an explicit ``%%`` prefix, automagic | |
136 | calling only works for line magics. |
|
136 | calling only works for line magics. | |
137 |
|
137 | |||
138 | The automagic system has the lowest possible precedence in name searches, so |
|
138 | The automagic system has the lowest possible precedence in name searches, so | |
139 | defining an identifier with the same name as an existing magic function will |
|
139 | defining an identifier with the same name as an existing magic function will | |
140 | shadow it for automagic use. You can still access the shadowed magic function |
|
140 | shadow it for automagic use. You can still access the shadowed magic function | |
141 | by explicitly using the ``%`` character at the beginning of the line. |
|
141 | by explicitly using the ``%`` character at the beginning of the line. | |
142 |
|
142 | |||
143 | An example (with automagic on) should clarify all this: |
|
143 | An example (with automagic on) should clarify all this: | |
144 |
|
144 | |||
145 | .. sourcecode:: ipython |
|
145 | .. sourcecode:: ipython | |
146 |
|
146 | |||
147 | In [1]: cd ipython # %cd is called by automagic |
|
147 | In [1]: cd ipython # %cd is called by automagic | |
148 | /home/fperez/ipython |
|
148 | /home/fperez/ipython | |
149 |
|
149 | |||
150 | In [2]: cd=1 # now cd is just a variable |
|
150 | In [2]: cd=1 # now cd is just a variable | |
151 |
|
151 | |||
152 | In [3]: cd .. # and doesn't work as a function anymore |
|
152 | In [3]: cd .. # and doesn't work as a function anymore | |
153 | File "<ipython-input-3-9fedb3aff56c>", line 1 |
|
153 | File "<ipython-input-3-9fedb3aff56c>", line 1 | |
154 | cd .. |
|
154 | cd .. | |
155 | ^ |
|
155 | ^ | |
156 | SyntaxError: invalid syntax |
|
156 | SyntaxError: invalid syntax | |
157 |
|
157 | |||
158 |
|
158 | |||
159 | In [4]: %cd .. # but %cd always works |
|
159 | In [4]: %cd .. # but %cd always works | |
160 | /home/fperez |
|
160 | /home/fperez | |
161 |
|
161 | |||
162 | In [5]: del cd # if you remove the cd variable, automagic works again |
|
162 | In [5]: del cd # if you remove the cd variable, automagic works again | |
163 |
|
163 | |||
164 | In [6]: cd ipython |
|
164 | In [6]: cd ipython | |
165 |
|
165 | |||
166 | /home/fperez/ipython |
|
166 | /home/fperez/ipython | |
167 |
|
167 | |||
168 | Defining your own magics |
|
168 | Defining your own magics | |
169 | ~~~~~~~~~~~~~~~~~~~~~~~~ |
|
169 | ++++++++++++++++++++++++ | |
170 |
|
170 | |||
171 | There are two main ways to define your own magic functions: from standalone |
|
171 | There are two main ways to define your own magic functions: from standalone | |
172 | functions and by inheriting from a base class provided by IPython: |
|
172 | functions and by inheriting from a base class provided by IPython: | |
173 | :class:`IPython.core.magic.Magics`. Below we show code you can place in a file |
|
173 | :class:`IPython.core.magic.Magics`. Below we show code you can place in a file | |
174 | that you load from your configuration, such as any file in the ``startup`` |
|
174 | that you load from your configuration, such as any file in the ``startup`` | |
175 | subdirectory of your default IPython profile. |
|
175 | subdirectory of your default IPython profile. | |
176 |
|
176 | |||
177 | First, let us see the simplest case. The following shows how to create a line |
|
177 | First, let us see the simplest case. The following shows how to create a line | |
178 | magic, a cell one and one that works in both modes, using just plain functions: |
|
178 | magic, a cell one and one that works in both modes, using just plain functions: | |
179 |
|
179 | |||
180 | .. sourcecode:: python |
|
180 | .. sourcecode:: python | |
181 |
|
181 | |||
182 | from IPython.core.magic import (register_line_magic, register_cell_magic, |
|
182 | from IPython.core.magic import (register_line_magic, register_cell_magic, | |
183 | register_line_cell_magic) |
|
183 | register_line_cell_magic) | |
184 |
|
184 | |||
185 | @register_line_magic |
|
185 | @register_line_magic | |
186 | def lmagic(line): |
|
186 | def lmagic(line): | |
187 | "my line magic" |
|
187 | "my line magic" | |
188 | return line |
|
188 | return line | |
189 |
|
189 | |||
190 | @register_cell_magic |
|
190 | @register_cell_magic | |
191 | def cmagic(line, cell): |
|
191 | def cmagic(line, cell): | |
192 | "my cell magic" |
|
192 | "my cell magic" | |
193 | return line, cell |
|
193 | return line, cell | |
194 |
|
194 | |||
195 | @register_line_cell_magic |
|
195 | @register_line_cell_magic | |
196 | def lcmagic(line, cell=None): |
|
196 | def lcmagic(line, cell=None): | |
197 | "Magic that works both as %lcmagic and as %%lcmagic" |
|
197 | "Magic that works both as %lcmagic and as %%lcmagic" | |
198 | if cell is None: |
|
198 | if cell is None: | |
199 | print "Called as line magic" |
|
199 | print "Called as line magic" | |
200 | return line |
|
200 | return line | |
201 | else: |
|
201 | else: | |
202 | print "Called as cell magic" |
|
202 | print "Called as cell magic" | |
203 | return line, cell |
|
203 | return line, cell | |
204 |
|
204 | |||
205 | # We delete these to avoid name conflicts for automagic to work |
|
205 | # We delete these to avoid name conflicts for automagic to work | |
206 | del lmagic, lcmagic |
|
206 | del lmagic, lcmagic | |
207 |
|
207 | |||
208 |
|
208 | |||
209 | You can also create magics of all three kinds by inheriting from the |
|
209 | You can also create magics of all three kinds by inheriting from the | |
210 | :class:`IPython.core.magic.Magics` class. This lets you create magics that can |
|
210 | :class:`IPython.core.magic.Magics` class. This lets you create magics that can | |
211 | potentially hold state in between calls, and that have full access to the main |
|
211 | potentially hold state in between calls, and that have full access to the main | |
212 | IPython object: |
|
212 | IPython object: | |
213 |
|
213 | |||
214 | .. sourcecode:: python |
|
214 | .. sourcecode:: python | |
215 |
|
215 | |||
216 | # This code can be put in any Python module, it does not require IPython |
|
216 | # This code can be put in any Python module, it does not require IPython | |
217 | # itself to be running already. It only creates the magics subclass but |
|
217 | # itself to be running already. It only creates the magics subclass but | |
218 | # doesn't instantiate it yet. |
|
218 | # doesn't instantiate it yet. | |
219 | from IPython.core.magic import (Magics, magics_class, line_magic, |
|
219 | from IPython.core.magic import (Magics, magics_class, line_magic, | |
220 | cell_magic, line_cell_magic) |
|
220 | cell_magic, line_cell_magic) | |
221 |
|
221 | |||
222 | # The class MUST call this class decorator at creation time |
|
222 | # The class MUST call this class decorator at creation time | |
223 | @magics_class |
|
223 | @magics_class | |
224 | class MyMagics(Magics): |
|
224 | class MyMagics(Magics): | |
225 |
|
225 | |||
226 | @line_magic |
|
226 | @line_magic | |
227 | def lmagic(self, line): |
|
227 | def lmagic(self, line): | |
228 | "my line magic" |
|
228 | "my line magic" | |
229 | print "Full access to the main IPython object:", self.shell |
|
229 | print "Full access to the main IPython object:", self.shell | |
230 | print "Variables in the user namespace:", self.shell.user_ns.keys() |
|
230 | print "Variables in the user namespace:", self.shell.user_ns.keys() | |
231 | return line |
|
231 | return line | |
232 |
|
232 | |||
233 | @cell_magic |
|
233 | @cell_magic | |
234 | def cmagic(self, line, cell): |
|
234 | def cmagic(self, line, cell): | |
235 | "my cell magic" |
|
235 | "my cell magic" | |
236 | return line, cell |
|
236 | return line, cell | |
237 |
|
237 | |||
238 | @line_cell_magic |
|
238 | @line_cell_magic | |
239 | def lcmagic(self, line, cell=None): |
|
239 | def lcmagic(self, line, cell=None): | |
240 | "Magic that works both as %lcmagic and as %%lcmagic" |
|
240 | "Magic that works both as %lcmagic and as %%lcmagic" | |
241 | if cell is None: |
|
241 | if cell is None: | |
242 | print "Called as line magic" |
|
242 | print "Called as line magic" | |
243 | return line |
|
243 | return line | |
244 | else: |
|
244 | else: | |
245 | print "Called as cell magic" |
|
245 | print "Called as cell magic" | |
246 | return line, cell |
|
246 | return line, cell | |
247 |
|
247 | |||
248 |
|
248 | |||
249 | # In order to actually use these magics, you must register them with a |
|
249 | # In order to actually use these magics, you must register them with a | |
250 | # running IPython. This code must be placed in a file that is loaded once |
|
250 | # running IPython. This code must be placed in a file that is loaded once | |
251 | # IPython is up and running: |
|
251 | # IPython is up and running: | |
252 | ip = get_ipython() |
|
252 | ip = get_ipython() | |
253 | # You can register the class itself without instantiating it. IPython will |
|
253 | # You can register the class itself without instantiating it. IPython will | |
254 | # call the default constructor on it. |
|
254 | # call the default constructor on it. | |
255 | ip.register_magics(MyMagics) |
|
255 | ip.register_magics(MyMagics) | |
256 |
|
256 | |||
257 | If you want to create a class with a different constructor that holds |
|
257 | If you want to create a class with a different constructor that holds | |
258 | additional state, then you should always call the parent constructor and |
|
258 | additional state, then you should always call the parent constructor and | |
259 | instantiate the class yourself before registration: |
|
259 | instantiate the class yourself before registration: | |
260 |
|
260 | |||
261 | .. sourcecode:: python |
|
261 | .. sourcecode:: python | |
262 |
|
262 | |||
263 | @magics_class |
|
263 | @magics_class | |
264 | class StatefulMagics(Magics): |
|
264 | class StatefulMagics(Magics): | |
265 | "Magics that hold additional state" |
|
265 | "Magics that hold additional state" | |
266 |
|
266 | |||
267 | def __init__(self, shell, data): |
|
267 | def __init__(self, shell, data): | |
268 | # You must call the parent constructor |
|
268 | # You must call the parent constructor | |
269 | super(StatefulMagics, self).__init__(shell) |
|
269 | super(StatefulMagics, self).__init__(shell) | |
270 | self.data = data |
|
270 | self.data = data | |
271 |
|
271 | |||
272 | # etc... |
|
272 | # etc... | |
273 |
|
273 | |||
274 | # This class must then be registered with a manually created instance, |
|
274 | # This class must then be registered with a manually created instance, | |
275 | # since its constructor has different arguments from the default: |
|
275 | # since its constructor has different arguments from the default: | |
276 | ip = get_ipython() |
|
276 | ip = get_ipython() | |
277 | magics = StatefulMagics(ip, some_data) |
|
277 | magics = StatefulMagics(ip, some_data) | |
278 | ip.register_magics(magics) |
|
278 | ip.register_magics(magics) | |
279 |
|
279 | |||
280 |
|
280 | |||
281 | In earlier versions, IPython had an API for the creation of line magics (cell |
|
281 | In earlier versions, IPython had an API for the creation of line magics (cell | |
282 | magics did not exist at the time) that required you to create functions with a |
|
282 | magics did not exist at the time) that required you to create functions with a | |
283 | method-looking signature and to manually pass both the function and the name. |
|
283 | method-looking signature and to manually pass both the function and the name. | |
284 | While this API is no longer recommended, it remains indefinitely supported for |
|
284 | While this API is no longer recommended, it remains indefinitely supported for | |
285 | backwards compatibility purposes. With the old API, you'd create a magic as |
|
285 | backwards compatibility purposes. With the old API, you'd create a magic as | |
286 | follows: |
|
286 | follows: | |
287 |
|
287 | |||
288 | .. sourcecode:: python |
|
288 | .. sourcecode:: python | |
289 |
|
289 | |||
290 | def func(self, line): |
|
290 | def func(self, line): | |
291 | print "Line magic called with line:", line |
|
291 | print "Line magic called with line:", line | |
292 | print "IPython object:", self.shell |
|
292 | print "IPython object:", self.shell | |
293 |
|
293 | |||
294 | ip = get_ipython() |
|
294 | ip = get_ipython() | |
295 | # Declare this function as the magic %mycommand |
|
295 | # Declare this function as the magic %mycommand | |
296 | ip.define_magic('mycommand', func) |
|
296 | ip.define_magic('mycommand', func) | |
297 |
|
297 | |||
298 | Type ``%magic`` for more information, including a list of all available magic |
|
298 | Type ``%magic`` for more information, including a list of all available magic | |
299 | functions at any time and their docstrings. You can also type |
|
299 | functions at any time and their docstrings. You can also type | |
300 | ``%magic_function_name?`` (see :ref:`below <dynamic_object_info>` for |
|
300 | ``%magic_function_name?`` (see :ref:`below <dynamic_object_info>` for | |
301 | information on the '?' system) to get information about any particular magic |
|
301 | information on the '?' system) to get information about any particular magic | |
302 | function you are interested in. |
|
302 | function you are interested in. | |
303 |
|
303 | |||
304 | The API documentation for the :mod:`IPython.core.magic` module contains the full |
|
304 | The API documentation for the :mod:`IPython.core.magic` module contains the full | |
305 | docstrings of all currently available magic commands. |
|
305 | docstrings of all currently available magic commands. | |
306 |
|
306 | |||
307 |
|
307 | |||
308 | Access to the standard Python help |
|
308 | Access to the standard Python help | |
309 | ---------------------------------- |
|
309 | ---------------------------------- | |
310 |
|
310 | |||
311 | Simply type ``help()`` to access Python's standard help system. You can |
|
311 | Simply type ``help()`` to access Python's standard help system. You can | |
312 | also type ``help(object)`` for information about a given object, or |
|
312 | also type ``help(object)`` for information about a given object, or | |
313 | ``help('keyword')`` for information on a keyword. You may need to configure your |
|
313 | ``help('keyword')`` for information on a keyword. You may need to configure your | |
314 | PYTHONDOCS environment variable for this feature to work correctly. |
|
314 | PYTHONDOCS environment variable for this feature to work correctly. | |
315 |
|
315 | |||
316 | .. _dynamic_object_info: |
|
316 | .. _dynamic_object_info: | |
317 |
|
317 | |||
318 | Dynamic object information |
|
318 | Dynamic object information | |
319 | -------------------------- |
|
319 | -------------------------- | |
320 |
|
320 | |||
321 | Typing ``?word`` or ``word?`` prints detailed information about an object. If |
|
321 | Typing ``?word`` or ``word?`` prints detailed information about an object. If | |
322 | certain strings in the object are too long (e.g. function signatures) they get |
|
322 | certain strings in the object are too long (e.g. function signatures) they get | |
323 | snipped in the center for brevity. This system gives access variable types and |
|
323 | snipped in the center for brevity. This system gives access variable types and | |
324 | values, docstrings, function prototypes and other useful information. |
|
324 | values, docstrings, function prototypes and other useful information. | |
325 |
|
325 | |||
326 | If the information will not fit in the terminal, it is displayed in a pager |
|
326 | If the information will not fit in the terminal, it is displayed in a pager | |
327 | (``less`` if available, otherwise a basic internal pager). |
|
327 | (``less`` if available, otherwise a basic internal pager). | |
328 |
|
328 | |||
329 | Typing ``??word`` or ``word??`` gives access to the full information, including |
|
329 | Typing ``??word`` or ``word??`` gives access to the full information, including | |
330 | the source code where possible. Long strings are not snipped. |
|
330 | the source code where possible. Long strings are not snipped. | |
331 |
|
331 | |||
332 | The following magic functions are particularly useful for gathering |
|
332 | The following magic functions are particularly useful for gathering | |
333 | information about your working environment. You can get more details by |
|
333 | information about your working environment. You can get more details by | |
334 | typing ``%magic`` or querying them individually (``%function_name?``); |
|
334 | typing ``%magic`` or querying them individually (``%function_name?``); | |
335 | this is just a summary: |
|
335 | this is just a summary: | |
336 |
|
336 | |||
337 | * **%pdoc <object>**: Print (or run through a pager if too long) the |
|
337 | * **%pdoc <object>**: Print (or run through a pager if too long) the | |
338 | docstring for an object. If the given object is a class, it will |
|
338 | docstring for an object. If the given object is a class, it will | |
339 | print both the class and the constructor docstrings. |
|
339 | print both the class and the constructor docstrings. | |
340 | * **%pdef <object>**: Print the call signature for any callable |
|
340 | * **%pdef <object>**: Print the call signature for any callable | |
341 | object. If the object is a class, print the constructor information. |
|
341 | object. If the object is a class, print the constructor information. | |
342 | * **%psource <object>**: Print (or run through a pager if too long) |
|
342 | * **%psource <object>**: Print (or run through a pager if too long) | |
343 | the source code for an object. |
|
343 | the source code for an object. | |
344 | * **%pfile <object>**: Show the entire source file where an object was |
|
344 | * **%pfile <object>**: Show the entire source file where an object was | |
345 | defined via a pager, opening it at the line where the object |
|
345 | defined via a pager, opening it at the line where the object | |
346 | definition begins. |
|
346 | definition begins. | |
347 | * **%who/%whos**: These functions give information about identifiers |
|
347 | * **%who/%whos**: These functions give information about identifiers | |
348 | you have defined interactively (not things you loaded or defined |
|
348 | you have defined interactively (not things you loaded or defined | |
349 | in your configuration files). %who just prints a list of |
|
349 | in your configuration files). %who just prints a list of | |
350 | identifiers and %whos prints a table with some basic details about |
|
350 | identifiers and %whos prints a table with some basic details about | |
351 | each identifier. |
|
351 | each identifier. | |
352 |
|
352 | |||
353 | Note that the dynamic object information functions (?/??, ``%pdoc``, |
|
353 | Note that the dynamic object information functions (?/??, ``%pdoc``, | |
354 | ``%pfile``, ``%pdef``, ``%psource``) work on object attributes, as well as |
|
354 | ``%pfile``, ``%pdef``, ``%psource``) work on object attributes, as well as | |
355 | directly on variables. For example, after doing ``import os``, you can use |
|
355 | directly on variables. For example, after doing ``import os``, you can use | |
356 | ``os.path.abspath??``. |
|
356 | ``os.path.abspath??``. | |
357 |
|
357 | |||
358 | .. _readline: |
|
358 | .. _readline: | |
359 |
|
359 | |||
360 | Readline-based features |
|
360 | Readline-based features | |
361 | ----------------------- |
|
361 | ----------------------- | |
362 |
|
362 | |||
363 | These features require the GNU readline library, so they won't work if your |
|
363 | These features require the GNU readline library, so they won't work if your | |
364 | Python installation lacks readline support. We will first describe the default |
|
364 | Python installation lacks readline support. We will first describe the default | |
365 | behavior IPython uses, and then how to change it to suit your preferences. |
|
365 | behavior IPython uses, and then how to change it to suit your preferences. | |
366 |
|
366 | |||
367 |
|
367 | |||
368 | Command line completion |
|
368 | Command line completion | |
369 | +++++++++++++++++++++++ |
|
369 | +++++++++++++++++++++++ | |
370 |
|
370 | |||
371 | At any time, hitting TAB will complete any available python commands or |
|
371 | At any time, hitting TAB will complete any available python commands or | |
372 | variable names, and show you a list of the possible completions if |
|
372 | variable names, and show you a list of the possible completions if | |
373 | there's no unambiguous one. It will also complete filenames in the |
|
373 | there's no unambiguous one. It will also complete filenames in the | |
374 | current directory if no python names match what you've typed so far. |
|
374 | current directory if no python names match what you've typed so far. | |
375 |
|
375 | |||
376 |
|
376 | |||
377 | Search command history |
|
377 | Search command history | |
378 | ++++++++++++++++++++++ |
|
378 | ++++++++++++++++++++++ | |
379 |
|
379 | |||
380 | IPython provides two ways for searching through previous input and thus |
|
380 | IPython provides two ways for searching through previous input and thus | |
381 | reduce the need for repetitive typing: |
|
381 | reduce the need for repetitive typing: | |
382 |
|
382 | |||
383 | 1. Start typing, and then use Ctrl-p (previous,up) and Ctrl-n |
|
383 | 1. Start typing, and then use Ctrl-p (previous,up) and Ctrl-n | |
384 | (next,down) to search through only the history items that match |
|
384 | (next,down) to search through only the history items that match | |
385 | what you've typed so far. If you use Ctrl-p/Ctrl-n at a blank |
|
385 | what you've typed so far. If you use Ctrl-p/Ctrl-n at a blank | |
386 | prompt, they just behave like normal arrow keys. |
|
386 | prompt, they just behave like normal arrow keys. | |
387 | 2. Hit Ctrl-r: opens a search prompt. Begin typing and the system |
|
387 | 2. Hit Ctrl-r: opens a search prompt. Begin typing and the system | |
388 | searches your history for lines that contain what you've typed so |
|
388 | searches your history for lines that contain what you've typed so | |
389 | far, completing as much as it can. |
|
389 | far, completing as much as it can. | |
390 |
|
390 | |||
391 |
|
391 | |||
392 | Persistent command history across sessions |
|
392 | Persistent command history across sessions | |
393 | ++++++++++++++++++++++++++++++++++++++++++ |
|
393 | ++++++++++++++++++++++++++++++++++++++++++ | |
394 |
|
394 | |||
395 | IPython will save your input history when it leaves and reload it next |
|
395 | IPython will save your input history when it leaves and reload it next | |
396 | time you restart it. By default, the history file is named |
|
396 | time you restart it. By default, the history file is named | |
397 | $IPYTHONDIR/profile_<name>/history.sqlite. This allows you to keep |
|
397 | $IPYTHONDIR/profile_<name>/history.sqlite. This allows you to keep | |
398 | separate histories related to various tasks: commands related to |
|
398 | separate histories related to various tasks: commands related to | |
399 | numerical work will not be clobbered by a system shell history, for |
|
399 | numerical work will not be clobbered by a system shell history, for | |
400 | example. |
|
400 | example. | |
401 |
|
401 | |||
402 |
|
402 | |||
403 | Autoindent |
|
403 | Autoindent | |
404 | ++++++++++ |
|
404 | ++++++++++ | |
405 |
|
405 | |||
406 | IPython can recognize lines ending in ':' and indent the next line, |
|
406 | IPython can recognize lines ending in ':' and indent the next line, | |
407 | while also un-indenting automatically after 'raise' or 'return'. |
|
407 | while also un-indenting automatically after 'raise' or 'return'. | |
408 |
|
408 | |||
409 | This feature uses the readline library, so it will honor your |
|
409 | This feature uses the readline library, so it will honor your | |
410 | :file:`~/.inputrc` configuration (or whatever file your INPUTRC variable points |
|
410 | :file:`~/.inputrc` configuration (or whatever file your INPUTRC variable points | |
411 | to). Adding the following lines to your :file:`.inputrc` file can make |
|
411 | to). Adding the following lines to your :file:`.inputrc` file can make | |
412 | indenting/unindenting more convenient (M-i indents, M-u unindents):: |
|
412 | indenting/unindenting more convenient (M-i indents, M-u unindents):: | |
413 |
|
413 | |||
414 | $if Python |
|
414 | $if Python | |
415 | "\M-i": " " |
|
415 | "\M-i": " " | |
416 | "\M-u": "\d\d\d\d" |
|
416 | "\M-u": "\d\d\d\d" | |
417 | $endif |
|
417 | $endif | |
418 |
|
418 | |||
419 | Note that there are 4 spaces between the quote marks after "M-i" above. |
|
419 | Note that there are 4 spaces between the quote marks after "M-i" above. | |
420 |
|
420 | |||
421 | .. warning:: |
|
421 | .. warning:: | |
422 |
|
422 | |||
423 | Setting the above indents will cause problems with unicode text entry in |
|
423 | Setting the above indents will cause problems with unicode text entry in | |
424 | the terminal. |
|
424 | the terminal. | |
425 |
|
425 | |||
426 | .. warning:: |
|
426 | .. warning:: | |
427 |
|
427 | |||
428 | Autoindent is ON by default, but it can cause problems with the pasting of |
|
428 | Autoindent is ON by default, but it can cause problems with the pasting of | |
429 | multi-line indented code (the pasted code gets re-indented on each line). A |
|
429 | multi-line indented code (the pasted code gets re-indented on each line). A | |
430 | magic function %autoindent allows you to toggle it on/off at runtime. You |
|
430 | magic function %autoindent allows you to toggle it on/off at runtime. You | |
431 | can also disable it permanently on in your :file:`ipython_config.py` file |
|
431 | can also disable it permanently on in your :file:`ipython_config.py` file | |
432 | (set TerminalInteractiveShell.autoindent=False). |
|
432 | (set TerminalInteractiveShell.autoindent=False). | |
433 |
|
433 | |||
434 | If you want to paste multiple lines in the terminal, it is recommended that |
|
434 | If you want to paste multiple lines in the terminal, it is recommended that | |
435 | you use ``%paste``. |
|
435 | you use ``%paste``. | |
436 |
|
436 | |||
437 |
|
437 | |||
438 | Customizing readline behavior |
|
438 | Customizing readline behavior | |
439 | +++++++++++++++++++++++++++++ |
|
439 | +++++++++++++++++++++++++++++ | |
440 |
|
440 | |||
441 | All these features are based on the GNU readline library, which has an |
|
441 | All these features are based on the GNU readline library, which has an | |
442 | extremely customizable interface. Normally, readline is configured via a |
|
442 | extremely customizable interface. Normally, readline is configured via a | |
443 | file which defines the behavior of the library; the details of the |
|
443 | file which defines the behavior of the library; the details of the | |
444 | syntax for this can be found in the readline documentation available |
|
444 | syntax for this can be found in the readline documentation available | |
445 | with your system or on the Internet. IPython doesn't read this file (if |
|
445 | with your system or on the Internet. IPython doesn't read this file (if | |
446 | it exists) directly, but it does support passing to readline valid |
|
446 | it exists) directly, but it does support passing to readline valid | |
447 | options via a simple interface. In brief, you can customize readline by |
|
447 | options via a simple interface. In brief, you can customize readline by | |
448 | setting the following options in your configuration file (note |
|
448 | setting the following options in your configuration file (note | |
449 | that these options can not be specified at the command line): |
|
449 | that these options can not be specified at the command line): | |
450 |
|
450 | |||
451 | * **readline_parse_and_bind**: this holds a list of strings to be executed |
|
451 | * **readline_parse_and_bind**: this holds a list of strings to be executed | |
452 | via a readline.parse_and_bind() command. The syntax for valid commands |
|
452 | via a readline.parse_and_bind() command. The syntax for valid commands | |
453 | of this kind can be found by reading the documentation for the GNU |
|
453 | of this kind can be found by reading the documentation for the GNU | |
454 | readline library, as these commands are of the kind which readline |
|
454 | readline library, as these commands are of the kind which readline | |
455 | accepts in its configuration file. |
|
455 | accepts in its configuration file. | |
456 | * **readline_remove_delims**: a string of characters to be removed |
|
456 | * **readline_remove_delims**: a string of characters to be removed | |
457 | from the default word-delimiters list used by readline, so that |
|
457 | from the default word-delimiters list used by readline, so that | |
458 | completions may be performed on strings which contain them. Do not |
|
458 | completions may be performed on strings which contain them. Do not | |
459 | change the default value unless you know what you're doing. |
|
459 | change the default value unless you know what you're doing. | |
460 |
|
460 | |||
461 | You will find the default values in your configuration file. |
|
461 | You will find the default values in your configuration file. | |
462 |
|
462 | |||
463 |
|
463 | |||
464 | Session logging and restoring |
|
464 | Session logging and restoring | |
465 | ----------------------------- |
|
465 | ----------------------------- | |
466 |
|
466 | |||
467 | You can log all input from a session either by starting IPython with the |
|
467 | You can log all input from a session either by starting IPython with the | |
468 | command line switch ``--logfile=foo.py`` (see :ref:`here <command_line_options>`) |
|
468 | command line switch ``--logfile=foo.py`` (see :ref:`here <command_line_options>`) | |
469 | or by activating the logging at any moment with the magic function %logstart. |
|
469 | or by activating the logging at any moment with the magic function %logstart. | |
470 |
|
470 | |||
471 | Log files can later be reloaded by running them as scripts and IPython |
|
471 | Log files can later be reloaded by running them as scripts and IPython | |
472 | will attempt to 'replay' the log by executing all the lines in it, thus |
|
472 | will attempt to 'replay' the log by executing all the lines in it, thus | |
473 | restoring the state of a previous session. This feature is not quite |
|
473 | restoring the state of a previous session. This feature is not quite | |
474 | perfect, but can still be useful in many cases. |
|
474 | perfect, but can still be useful in many cases. | |
475 |
|
475 | |||
476 | The log files can also be used as a way to have a permanent record of |
|
476 | The log files can also be used as a way to have a permanent record of | |
477 | any code you wrote while experimenting. Log files are regular text files |
|
477 | any code you wrote while experimenting. Log files are regular text files | |
478 | which you can later open in your favorite text editor to extract code or |
|
478 | which you can later open in your favorite text editor to extract code or | |
479 | to 'clean them up' before using them to replay a session. |
|
479 | to 'clean them up' before using them to replay a session. | |
480 |
|
480 | |||
481 | The `%logstart` function for activating logging in mid-session is used as |
|
481 | The `%logstart` function for activating logging in mid-session is used as | |
482 | follows:: |
|
482 | follows:: | |
483 |
|
483 | |||
484 | %logstart [log_name [log_mode]] |
|
484 | %logstart [log_name [log_mode]] | |
485 |
|
485 | |||
486 | If no name is given, it defaults to a file named 'ipython_log.py' in your |
|
486 | If no name is given, it defaults to a file named 'ipython_log.py' in your | |
487 | current working directory, in 'rotate' mode (see below). |
|
487 | current working directory, in 'rotate' mode (see below). | |
488 |
|
488 | |||
489 | '%logstart name' saves to file 'name' in 'backup' mode. It saves your |
|
489 | '%logstart name' saves to file 'name' in 'backup' mode. It saves your | |
490 | history up to that point and then continues logging. |
|
490 | history up to that point and then continues logging. | |
491 |
|
491 | |||
492 | %logstart takes a second optional parameter: logging mode. This can be |
|
492 | %logstart takes a second optional parameter: logging mode. This can be | |
493 | one of (note that the modes are given unquoted): |
|
493 | one of (note that the modes are given unquoted): | |
494 |
|
494 | |||
495 | * [over:] overwrite existing log_name. |
|
495 | * [over:] overwrite existing log_name. | |
496 | * [backup:] rename (if exists) to log_name~ and start log_name. |
|
496 | * [backup:] rename (if exists) to log_name~ and start log_name. | |
497 | * [append:] well, that says it. |
|
497 | * [append:] well, that says it. | |
498 | * [rotate:] create rotating logs log_name.1~, log_name.2~, etc. |
|
498 | * [rotate:] create rotating logs log_name.1~, log_name.2~, etc. | |
499 |
|
499 | |||
500 | The %logoff and %logon functions allow you to temporarily stop and |
|
500 | The %logoff and %logon functions allow you to temporarily stop and | |
501 | resume logging to a file which had previously been started with |
|
501 | resume logging to a file which had previously been started with | |
502 | %logstart. They will fail (with an explanation) if you try to use them |
|
502 | %logstart. They will fail (with an explanation) if you try to use them | |
503 | before logging has been started. |
|
503 | before logging has been started. | |
504 |
|
504 | |||
505 | .. _system_shell_access: |
|
505 | .. _system_shell_access: | |
506 |
|
506 | |||
507 | System shell access |
|
507 | System shell access | |
508 | ------------------- |
|
508 | ------------------- | |
509 |
|
509 | |||
510 | Any input line beginning with a ! character is passed verbatim (minus |
|
510 | Any input line beginning with a ! character is passed verbatim (minus | |
511 | the !, of course) to the underlying operating system. For example, |
|
511 | the !, of course) to the underlying operating system. For example, | |
512 | typing ``!ls`` will run 'ls' in the current directory. |
|
512 | typing ``!ls`` will run 'ls' in the current directory. | |
513 |
|
513 | |||
514 | Manual capture of command output |
|
514 | Manual capture of command output | |
515 | -------------------------------- |
|
515 | -------------------------------- | |
516 |
|
516 | |||
517 | You can assign the result of a system command to a Python variable with the |
|
517 | You can assign the result of a system command to a Python variable with the | |
518 | syntax ``myfiles = !ls``. This gets machine readable output from stdout |
|
518 | syntax ``myfiles = !ls``. This gets machine readable output from stdout | |
519 | (e.g. without colours), and splits on newlines. To explicitly get this sort of |
|
519 | (e.g. without colours), and splits on newlines. To explicitly get this sort of | |
520 | output without assigning to a variable, use two exclamation marks (``!!ls``) or |
|
520 | output without assigning to a variable, use two exclamation marks (``!!ls``) or | |
521 | the ``%sx`` magic command. |
|
521 | the ``%sx`` magic command. | |
522 |
|
522 | |||
523 | The captured list has some convenience features. ``myfiles.n`` or ``myfiles.s`` |
|
523 | The captured list has some convenience features. ``myfiles.n`` or ``myfiles.s`` | |
524 | returns a string delimited by newlines or spaces, respectively. ``myfiles.p`` |
|
524 | returns a string delimited by newlines or spaces, respectively. ``myfiles.p`` | |
525 | produces `path objects <http://pypi.python.org/pypi/path.py>`_ from the list items. |
|
525 | produces `path objects <http://pypi.python.org/pypi/path.py>`_ from the list items. | |
526 | See :ref:`string_lists` for details. |
|
526 | See :ref:`string_lists` for details. | |
527 |
|
527 | |||
528 | IPython also allows you to expand the value of python variables when |
|
528 | IPython also allows you to expand the value of python variables when | |
529 | making system calls. Wrap variables or expressions in {braces}:: |
|
529 | making system calls. Wrap variables or expressions in {braces}:: | |
530 |
|
530 | |||
531 | In [1]: pyvar = 'Hello world' |
|
531 | In [1]: pyvar = 'Hello world' | |
532 | In [2]: !echo "A python variable: {pyvar}" |
|
532 | In [2]: !echo "A python variable: {pyvar}" | |
533 | A python variable: Hello world |
|
533 | A python variable: Hello world | |
534 | In [3]: import math |
|
534 | In [3]: import math | |
535 | In [4]: x = 8 |
|
535 | In [4]: x = 8 | |
536 | In [5]: !echo {math.factorial(x)} |
|
536 | In [5]: !echo {math.factorial(x)} | |
537 | 40320 |
|
537 | 40320 | |
538 |
|
538 | |||
539 | For simple cases, you can alternatively prepend $ to a variable name:: |
|
539 | For simple cases, you can alternatively prepend $ to a variable name:: | |
540 |
|
540 | |||
541 | In [6]: !echo $sys.argv |
|
541 | In [6]: !echo $sys.argv | |
542 | [/home/fperez/usr/bin/ipython] |
|
542 | [/home/fperez/usr/bin/ipython] | |
543 | In [7]: !echo "A system variable: $$HOME" # Use $$ for literal $ |
|
543 | In [7]: !echo "A system variable: $$HOME" # Use $$ for literal $ | |
544 | A system variable: /home/fperez |
|
544 | A system variable: /home/fperez | |
545 |
|
545 | |||
546 | System command aliases |
|
546 | System command aliases | |
547 | ---------------------- |
|
547 | ---------------------- | |
548 |
|
548 | |||
549 | The %alias magic function allows you to define magic functions which are in fact |
|
549 | The %alias magic function allows you to define magic functions which are in fact | |
550 | system shell commands. These aliases can have parameters. |
|
550 | system shell commands. These aliases can have parameters. | |
551 |
|
551 | |||
552 | ``%alias alias_name cmd`` defines 'alias_name' as an alias for 'cmd' |
|
552 | ``%alias alias_name cmd`` defines 'alias_name' as an alias for 'cmd' | |
553 |
|
553 | |||
554 | Then, typing ``alias_name params`` will execute the system command 'cmd |
|
554 | Then, typing ``alias_name params`` will execute the system command 'cmd | |
555 | params' (from your underlying operating system). |
|
555 | params' (from your underlying operating system). | |
556 |
|
556 | |||
557 | You can also define aliases with parameters using %s specifiers (one per |
|
557 | You can also define aliases with parameters using %s specifiers (one per | |
558 | parameter). The following example defines the parts function as an |
|
558 | parameter). The following example defines the parts function as an | |
559 | alias to the command 'echo first %s second %s' where each %s will be |
|
559 | alias to the command 'echo first %s second %s' where each %s will be | |
560 | replaced by a positional parameter to the call to %parts:: |
|
560 | replaced by a positional parameter to the call to %parts:: | |
561 |
|
561 | |||
562 | In [1]: %alias parts echo first %s second %s |
|
562 | In [1]: %alias parts echo first %s second %s | |
563 | In [2]: parts A B |
|
563 | In [2]: parts A B | |
564 | first A second B |
|
564 | first A second B | |
565 | In [3]: parts A |
|
565 | In [3]: parts A | |
566 | ERROR: Alias <parts> requires 2 arguments, 1 given. |
|
566 | ERROR: Alias <parts> requires 2 arguments, 1 given. | |
567 |
|
567 | |||
568 | If called with no parameters, %alias prints the table of currently |
|
568 | If called with no parameters, %alias prints the table of currently | |
569 | defined aliases. |
|
569 | defined aliases. | |
570 |
|
570 | |||
571 | The %rehashx magic allows you to load your entire $PATH as |
|
571 | The %rehashx magic allows you to load your entire $PATH as | |
572 | ipython aliases. See its docstring for further details. |
|
572 | ipython aliases. See its docstring for further details. | |
573 |
|
573 | |||
574 |
|
574 | |||
575 | .. _dreload: |
|
575 | .. _dreload: | |
576 |
|
576 | |||
577 | Recursive reload |
|
577 | Recursive reload | |
578 | ---------------- |
|
578 | ---------------- | |
579 |
|
579 | |||
580 | The :mod:`IPython.lib.deepreload` module allows you to recursively reload a |
|
580 | The :mod:`IPython.lib.deepreload` module allows you to recursively reload a | |
581 | module: changes made to any of its dependencies will be reloaded without |
|
581 | module: changes made to any of its dependencies will be reloaded without | |
582 | having to exit. To start using it, do:: |
|
582 | having to exit. To start using it, do:: | |
583 |
|
583 | |||
584 | from IPython.lib.deepreload import reload as dreload |
|
584 | from IPython.lib.deepreload import reload as dreload | |
585 |
|
585 | |||
586 |
|
586 | |||
587 | Verbose and colored exception traceback printouts |
|
587 | Verbose and colored exception traceback printouts | |
588 | ------------------------------------------------- |
|
588 | ------------------------------------------------- | |
589 |
|
589 | |||
590 | IPython provides the option to see very detailed exception tracebacks, |
|
590 | IPython provides the option to see very detailed exception tracebacks, | |
591 | which can be especially useful when debugging large programs. You can |
|
591 | which can be especially useful when debugging large programs. You can | |
592 | run any Python file with the %run function to benefit from these |
|
592 | run any Python file with the %run function to benefit from these | |
593 | detailed tracebacks. Furthermore, both normal and verbose tracebacks can |
|
593 | detailed tracebacks. Furthermore, both normal and verbose tracebacks can | |
594 | be colored (if your terminal supports it) which makes them much easier |
|
594 | be colored (if your terminal supports it) which makes them much easier | |
595 | to parse visually. |
|
595 | to parse visually. | |
596 |
|
596 | |||
597 | See the magic xmode and colors functions for details (just type %magic). |
|
597 | See the magic xmode and colors functions for details (just type %magic). | |
598 |
|
598 | |||
599 | These features are basically a terminal version of Ka-Ping Yee's cgitb |
|
599 | These features are basically a terminal version of Ka-Ping Yee's cgitb | |
600 | module, now part of the standard Python library. |
|
600 | module, now part of the standard Python library. | |
601 |
|
601 | |||
602 |
|
602 | |||
603 | .. _input_caching: |
|
603 | .. _input_caching: | |
604 |
|
604 | |||
605 | Input caching system |
|
605 | Input caching system | |
606 | -------------------- |
|
606 | -------------------- | |
607 |
|
607 | |||
608 | IPython offers numbered prompts (In/Out) with input and output caching |
|
608 | IPython offers numbered prompts (In/Out) with input and output caching | |
609 | (also referred to as 'input history'). All input is saved and can be |
|
609 | (also referred to as 'input history'). All input is saved and can be | |
610 | retrieved as variables (besides the usual arrow key recall), in |
|
610 | retrieved as variables (besides the usual arrow key recall), in | |
611 | addition to the %rep magic command that brings a history entry |
|
611 | addition to the %rep magic command that brings a history entry | |
612 | up for editing on the next command line. |
|
612 | up for editing on the next command line. | |
613 |
|
613 | |||
614 | The following GLOBAL variables always exist (so don't overwrite them!): |
|
614 | The following GLOBAL variables always exist (so don't overwrite them!): | |
615 |
|
615 | |||
616 | * _i, _ii, _iii: store previous, next previous and next-next previous inputs. |
|
616 | * _i, _ii, _iii: store previous, next previous and next-next previous inputs. | |
617 | * In, _ih : a list of all inputs; _ih[n] is the input from line n. If you |
|
617 | * In, _ih : a list of all inputs; _ih[n] is the input from line n. If you | |
618 | overwrite In with a variable of your own, you can remake the assignment to the |
|
618 | overwrite In with a variable of your own, you can remake the assignment to the | |
619 | internal list with a simple ``In=_ih``. |
|
619 | internal list with a simple ``In=_ih``. | |
620 |
|
620 | |||
621 | Additionally, global variables named _i<n> are dynamically created (<n> |
|
621 | Additionally, global variables named _i<n> are dynamically created (<n> | |
622 | being the prompt counter), so ``_i<n> == _ih[<n>] == In[<n>]``. |
|
622 | being the prompt counter), so ``_i<n> == _ih[<n>] == In[<n>]``. | |
623 |
|
623 | |||
624 | For example, what you typed at prompt 14 is available as _i14, _ih[14] |
|
624 | For example, what you typed at prompt 14 is available as _i14, _ih[14] | |
625 | and In[14]. |
|
625 | and In[14]. | |
626 |
|
626 | |||
627 | This allows you to easily cut and paste multi line interactive prompts |
|
627 | This allows you to easily cut and paste multi line interactive prompts | |
628 | by printing them out: they print like a clean string, without prompt |
|
628 | by printing them out: they print like a clean string, without prompt | |
629 | characters. You can also manipulate them like regular variables (they |
|
629 | characters. You can also manipulate them like regular variables (they | |
630 | are strings), modify or exec them (typing ``exec _i9`` will re-execute the |
|
630 | are strings), modify or exec them (typing ``exec _i9`` will re-execute the | |
631 | contents of input prompt 9. |
|
631 | contents of input prompt 9. | |
632 |
|
632 | |||
633 | You can also re-execute multiple lines of input easily by using the |
|
633 | You can also re-execute multiple lines of input easily by using the | |
634 | magic %rerun or %macro functions. The macro system also allows you to re-execute |
|
634 | magic %rerun or %macro functions. The macro system also allows you to re-execute | |
635 | previous lines which include magic function calls (which require special |
|
635 | previous lines which include magic function calls (which require special | |
636 | processing). Type %macro? for more details on the macro system. |
|
636 | processing). Type %macro? for more details on the macro system. | |
637 |
|
637 | |||
638 | A history function %hist allows you to see any part of your input |
|
638 | A history function %hist allows you to see any part of your input | |
639 | history by printing a range of the _i variables. |
|
639 | history by printing a range of the _i variables. | |
640 |
|
640 | |||
641 | You can also search ('grep') through your history by typing |
|
641 | You can also search ('grep') through your history by typing | |
642 | ``%hist -g somestring``. This is handy for searching for URLs, IP addresses, |
|
642 | ``%hist -g somestring``. This is handy for searching for URLs, IP addresses, | |
643 | etc. You can bring history entries listed by '%hist -g' up for editing |
|
643 | etc. You can bring history entries listed by '%hist -g' up for editing | |
644 | with the %recall command, or run them immediately with %rerun. |
|
644 | with the %recall command, or run them immediately with %rerun. | |
645 |
|
645 | |||
646 | .. _output_caching: |
|
646 | .. _output_caching: | |
647 |
|
647 | |||
648 | Output caching system |
|
648 | Output caching system | |
649 | --------------------- |
|
649 | --------------------- | |
650 |
|
650 | |||
651 | For output that is returned from actions, a system similar to the input |
|
651 | For output that is returned from actions, a system similar to the input | |
652 | cache exists but using _ instead of _i. Only actions that produce a |
|
652 | cache exists but using _ instead of _i. Only actions that produce a | |
653 | result (NOT assignments, for example) are cached. If you are familiar |
|
653 | result (NOT assignments, for example) are cached. If you are familiar | |
654 | with Mathematica, IPython's _ variables behave exactly like |
|
654 | with Mathematica, IPython's _ variables behave exactly like | |
655 | Mathematica's % variables. |
|
655 | Mathematica's % variables. | |
656 |
|
656 | |||
657 | The following GLOBAL variables always exist (so don't overwrite them!): |
|
657 | The following GLOBAL variables always exist (so don't overwrite them!): | |
658 |
|
658 | |||
659 | * [_] (a single underscore) : stores previous output, like Python's |
|
659 | * [_] (a single underscore) : stores previous output, like Python's | |
660 | default interpreter. |
|
660 | default interpreter. | |
661 | * [__] (two underscores): next previous. |
|
661 | * [__] (two underscores): next previous. | |
662 | * [___] (three underscores): next-next previous. |
|
662 | * [___] (three underscores): next-next previous. | |
663 |
|
663 | |||
664 | Additionally, global variables named _<n> are dynamically created (<n> |
|
664 | Additionally, global variables named _<n> are dynamically created (<n> | |
665 | being the prompt counter), such that the result of output <n> is always |
|
665 | being the prompt counter), such that the result of output <n> is always | |
666 | available as _<n> (don't use the angle brackets, just the number, e.g. |
|
666 | available as _<n> (don't use the angle brackets, just the number, e.g. | |
667 | _21). |
|
667 | _21). | |
668 |
|
668 | |||
669 | These variables are also stored in a global dictionary (not a |
|
669 | These variables are also stored in a global dictionary (not a | |
670 | list, since it only has entries for lines which returned a result) |
|
670 | list, since it only has entries for lines which returned a result) | |
671 | available under the names _oh and Out (similar to _ih and In). So the |
|
671 | available under the names _oh and Out (similar to _ih and In). So the | |
672 | output from line 12 can be obtained as _12, Out[12] or _oh[12]. If you |
|
672 | output from line 12 can be obtained as _12, Out[12] or _oh[12]. If you | |
673 | accidentally overwrite the Out variable you can recover it by typing |
|
673 | accidentally overwrite the Out variable you can recover it by typing | |
674 | 'Out=_oh' at the prompt. |
|
674 | 'Out=_oh' at the prompt. | |
675 |
|
675 | |||
676 | This system obviously can potentially put heavy memory demands on your |
|
676 | This system obviously can potentially put heavy memory demands on your | |
677 | system, since it prevents Python's garbage collector from removing any |
|
677 | system, since it prevents Python's garbage collector from removing any | |
678 | previously computed results. You can control how many results are kept |
|
678 | previously computed results. You can control how many results are kept | |
679 | in memory with the option (at the command line or in your configuration |
|
679 | in memory with the option (at the command line or in your configuration | |
680 | file) cache_size. If you set it to 0, the whole system is completely |
|
680 | file) cache_size. If you set it to 0, the whole system is completely | |
681 | disabled and the prompts revert to the classic '>>>' of normal Python. |
|
681 | disabled and the prompts revert to the classic '>>>' of normal Python. | |
682 |
|
682 | |||
683 |
|
683 | |||
684 | Directory history |
|
684 | Directory history | |
685 | ----------------- |
|
685 | ----------------- | |
686 |
|
686 | |||
687 | Your history of visited directories is kept in the global list _dh, and |
|
687 | Your history of visited directories is kept in the global list _dh, and | |
688 | the magic %cd command can be used to go to any entry in that list. The |
|
688 | the magic %cd command can be used to go to any entry in that list. The | |
689 | %dhist command allows you to view this history. Do ``cd -<TAB>`` to |
|
689 | %dhist command allows you to view this history. Do ``cd -<TAB>`` to | |
690 | conveniently view the directory history. |
|
690 | conveniently view the directory history. | |
691 |
|
691 | |||
692 |
|
692 | |||
693 | Automatic parentheses and quotes |
|
693 | Automatic parentheses and quotes | |
694 | -------------------------------- |
|
694 | -------------------------------- | |
695 |
|
695 | |||
696 | These features were adapted from Nathan Gray's LazyPython. They are |
|
696 | These features were adapted from Nathan Gray's LazyPython. They are | |
697 | meant to allow less typing for common situations. |
|
697 | meant to allow less typing for common situations. | |
698 |
|
698 | |||
699 |
|
699 | |||
700 | Automatic parentheses |
|
700 | Automatic parentheses | |
701 | +++++++++++++++++++++ |
|
701 | +++++++++++++++++++++ | |
702 |
|
702 | |||
703 | Callable objects (i.e. functions, methods, etc) can be invoked like this |
|
703 | Callable objects (i.e. functions, methods, etc) can be invoked like this | |
704 | (notice the commas between the arguments):: |
|
704 | (notice the commas between the arguments):: | |
705 |
|
705 | |||
706 | In [1]: callable_ob arg1, arg2, arg3 |
|
706 | In [1]: callable_ob arg1, arg2, arg3 | |
707 | ------> callable_ob(arg1, arg2, arg3) |
|
707 | ------> callable_ob(arg1, arg2, arg3) | |
708 |
|
708 | |||
709 | You can force automatic parentheses by using '/' as the first character |
|
709 | You can force automatic parentheses by using '/' as the first character | |
710 | of a line. For example:: |
|
710 | of a line. For example:: | |
711 |
|
711 | |||
712 | In [2]: /globals # becomes 'globals()' |
|
712 | In [2]: /globals # becomes 'globals()' | |
713 |
|
713 | |||
714 | Note that the '/' MUST be the first character on the line! This won't work:: |
|
714 | Note that the '/' MUST be the first character on the line! This won't work:: | |
715 |
|
715 | |||
716 | In [3]: print /globals # syntax error |
|
716 | In [3]: print /globals # syntax error | |
717 |
|
717 | |||
718 | In most cases the automatic algorithm should work, so you should rarely |
|
718 | In most cases the automatic algorithm should work, so you should rarely | |
719 | need to explicitly invoke /. One notable exception is if you are trying |
|
719 | need to explicitly invoke /. One notable exception is if you are trying | |
720 | to call a function with a list of tuples as arguments (the parenthesis |
|
720 | to call a function with a list of tuples as arguments (the parenthesis | |
721 | will confuse IPython):: |
|
721 | will confuse IPython):: | |
722 |
|
722 | |||
723 | In [4]: zip (1,2,3),(4,5,6) # won't work |
|
723 | In [4]: zip (1,2,3),(4,5,6) # won't work | |
724 |
|
724 | |||
725 | but this will work:: |
|
725 | but this will work:: | |
726 |
|
726 | |||
727 | In [5]: /zip (1,2,3),(4,5,6) |
|
727 | In [5]: /zip (1,2,3),(4,5,6) | |
728 | ------> zip ((1,2,3),(4,5,6)) |
|
728 | ------> zip ((1,2,3),(4,5,6)) | |
729 | Out[5]: [(1, 4), (2, 5), (3, 6)] |
|
729 | Out[5]: [(1, 4), (2, 5), (3, 6)] | |
730 |
|
730 | |||
731 | IPython tells you that it has altered your command line by displaying |
|
731 | IPython tells you that it has altered your command line by displaying | |
732 | the new command line preceded by ->. e.g.:: |
|
732 | the new command line preceded by ->. e.g.:: | |
733 |
|
733 | |||
734 | In [6]: callable list |
|
734 | In [6]: callable list | |
735 | ------> callable(list) |
|
735 | ------> callable(list) | |
736 |
|
736 | |||
737 |
|
737 | |||
738 | Automatic quoting |
|
738 | Automatic quoting | |
739 | +++++++++++++++++ |
|
739 | +++++++++++++++++ | |
740 |
|
740 | |||
741 | You can force automatic quoting of a function's arguments by using ',' |
|
741 | You can force automatic quoting of a function's arguments by using ',' | |
742 | or ';' as the first character of a line. For example:: |
|
742 | or ';' as the first character of a line. For example:: | |
743 |
|
743 | |||
744 | In [1]: ,my_function /home/me # becomes my_function("/home/me") |
|
744 | In [1]: ,my_function /home/me # becomes my_function("/home/me") | |
745 |
|
745 | |||
746 | If you use ';' the whole argument is quoted as a single string, while ',' splits |
|
746 | If you use ';' the whole argument is quoted as a single string, while ',' splits | |
747 | on whitespace:: |
|
747 | on whitespace:: | |
748 |
|
748 | |||
749 | In [2]: ,my_function a b c # becomes my_function("a","b","c") |
|
749 | In [2]: ,my_function a b c # becomes my_function("a","b","c") | |
750 |
|
750 | |||
751 | In [3]: ;my_function a b c # becomes my_function("a b c") |
|
751 | In [3]: ;my_function a b c # becomes my_function("a b c") | |
752 |
|
752 | |||
753 | Note that the ',' or ';' MUST be the first character on the line! This |
|
753 | Note that the ',' or ';' MUST be the first character on the line! This | |
754 | won't work:: |
|
754 | won't work:: | |
755 |
|
755 | |||
756 | In [4]: x = ,my_function /home/me # syntax error |
|
756 | In [4]: x = ,my_function /home/me # syntax error | |
757 |
|
757 | |||
758 | IPython as your default Python environment |
|
758 | IPython as your default Python environment | |
759 | ========================================== |
|
759 | ========================================== | |
760 |
|
760 | |||
761 | Python honors the environment variable PYTHONSTARTUP and will execute at |
|
761 | Python honors the environment variable PYTHONSTARTUP and will execute at | |
762 | startup the file referenced by this variable. If you put the following code at |
|
762 | startup the file referenced by this variable. If you put the following code at | |
763 | the end of that file, then IPython will be your working environment anytime you |
|
763 | the end of that file, then IPython will be your working environment anytime you | |
764 | start Python:: |
|
764 | start Python:: | |
765 |
|
765 | |||
766 | from IPython.frontend.terminal.ipapp import launch_new_instance |
|
766 | from IPython.frontend.terminal.ipapp import launch_new_instance | |
767 | launch_new_instance() |
|
767 | launch_new_instance() | |
768 | raise SystemExit |
|
768 | raise SystemExit | |
769 |
|
769 | |||
770 | The ``raise SystemExit`` is needed to exit Python when |
|
770 | The ``raise SystemExit`` is needed to exit Python when | |
771 | it finishes, otherwise you'll be back at the normal Python '>>>' |
|
771 | it finishes, otherwise you'll be back at the normal Python '>>>' | |
772 | prompt. |
|
772 | prompt. | |
773 |
|
773 | |||
774 | This is probably useful to developers who manage multiple Python |
|
774 | This is probably useful to developers who manage multiple Python | |
775 | versions and don't want to have correspondingly multiple IPython |
|
775 | versions and don't want to have correspondingly multiple IPython | |
776 | versions. Note that in this mode, there is no way to pass IPython any |
|
776 | versions. Note that in this mode, there is no way to pass IPython any | |
777 | command-line options, as those are trapped first by Python itself. |
|
777 | command-line options, as those are trapped first by Python itself. | |
778 |
|
778 | |||
779 | .. _Embedding: |
|
779 | .. _Embedding: | |
780 |
|
780 | |||
781 | Embedding IPython |
|
781 | Embedding IPython | |
782 | ================= |
|
782 | ================= | |
783 |
|
783 | |||
784 | It is possible to start an IPython instance inside your own Python |
|
784 | It is possible to start an IPython instance inside your own Python | |
785 | programs. This allows you to evaluate dynamically the state of your |
|
785 | programs. This allows you to evaluate dynamically the state of your | |
786 | code, operate with your variables, analyze them, etc. Note however that |
|
786 | code, operate with your variables, analyze them, etc. Note however that | |
787 | any changes you make to values while in the shell do not propagate back |
|
787 | any changes you make to values while in the shell do not propagate back | |
788 | to the running code, so it is safe to modify your values because you |
|
788 | to the running code, so it is safe to modify your values because you | |
789 | won't break your code in bizarre ways by doing so. |
|
789 | won't break your code in bizarre ways by doing so. | |
790 |
|
790 | |||
791 | .. note:: |
|
791 | .. note:: | |
792 |
|
792 | |||
793 | At present, trying to embed IPython from inside IPython causes problems. Run |
|
793 | At present, trying to embed IPython from inside IPython causes problems. Run | |
794 | the code samples below outside IPython. |
|
794 | the code samples below outside IPython. | |
795 |
|
795 | |||
796 | This feature allows you to easily have a fully functional python |
|
796 | This feature allows you to easily have a fully functional python | |
797 | environment for doing object introspection anywhere in your code with a |
|
797 | environment for doing object introspection anywhere in your code with a | |
798 | simple function call. In some cases a simple print statement is enough, |
|
798 | simple function call. In some cases a simple print statement is enough, | |
799 | but if you need to do more detailed analysis of a code fragment this |
|
799 | but if you need to do more detailed analysis of a code fragment this | |
800 | feature can be very valuable. |
|
800 | feature can be very valuable. | |
801 |
|
801 | |||
802 | It can also be useful in scientific computing situations where it is |
|
802 | It can also be useful in scientific computing situations where it is | |
803 | common to need to do some automatic, computationally intensive part and |
|
803 | common to need to do some automatic, computationally intensive part and | |
804 | then stop to look at data, plots, etc. |
|
804 | then stop to look at data, plots, etc. | |
805 | Opening an IPython instance will give you full access to your data and |
|
805 | Opening an IPython instance will give you full access to your data and | |
806 | functions, and you can resume program execution once you are done with |
|
806 | functions, and you can resume program execution once you are done with | |
807 | the interactive part (perhaps to stop again later, as many times as |
|
807 | the interactive part (perhaps to stop again later, as many times as | |
808 | needed). |
|
808 | needed). | |
809 |
|
809 | |||
810 | The following code snippet is the bare minimum you need to include in |
|
810 | The following code snippet is the bare minimum you need to include in | |
811 | your Python programs for this to work (detailed examples follow later):: |
|
811 | your Python programs for this to work (detailed examples follow later):: | |
812 |
|
812 | |||
813 | from IPython import embed |
|
813 | from IPython import embed | |
814 |
|
814 | |||
815 | embed() # this call anywhere in your program will start IPython |
|
815 | embed() # this call anywhere in your program will start IPython | |
816 |
|
816 | |||
817 | .. note:: |
|
817 | .. note:: | |
818 |
|
818 | |||
819 | As of 0.13, you can embed an IPython *kernel*, for use with qtconsole, |
|
819 | As of 0.13, you can embed an IPython *kernel*, for use with qtconsole, | |
820 | etc. via ``IPython.embed_kernel()`` instead of ``IPython.embed()``. |
|
820 | etc. via ``IPython.embed_kernel()`` instead of ``IPython.embed()``. | |
821 | It should function just the same as regular embed, but you connect |
|
821 | It should function just the same as regular embed, but you connect | |
822 | an external frontend rather than IPython starting up in the local |
|
822 | an external frontend rather than IPython starting up in the local | |
823 | terminal. |
|
823 | terminal. | |
824 |
|
824 | |||
825 | You can run embedded instances even in code which is itself being run at |
|
825 | You can run embedded instances even in code which is itself being run at | |
826 | the IPython interactive prompt with '%run <filename>'. Since it's easy |
|
826 | the IPython interactive prompt with '%run <filename>'. Since it's easy | |
827 | to get lost as to where you are (in your top-level IPython or in your |
|
827 | to get lost as to where you are (in your top-level IPython or in your | |
828 | embedded one), it's a good idea in such cases to set the in/out prompts |
|
828 | embedded one), it's a good idea in such cases to set the in/out prompts | |
829 | to something different for the embedded instances. The code examples |
|
829 | to something different for the embedded instances. The code examples | |
830 | below illustrate this. |
|
830 | below illustrate this. | |
831 |
|
831 | |||
832 | You can also have multiple IPython instances in your program and open |
|
832 | You can also have multiple IPython instances in your program and open | |
833 | them separately, for example with different options for data |
|
833 | them separately, for example with different options for data | |
834 | presentation. If you close and open the same instance multiple times, |
|
834 | presentation. If you close and open the same instance multiple times, | |
835 | its prompt counters simply continue from each execution to the next. |
|
835 | its prompt counters simply continue from each execution to the next. | |
836 |
|
836 | |||
837 | Please look at the docstrings in the :mod:`~IPython.frontend.terminal.embed` |
|
837 | Please look at the docstrings in the :mod:`~IPython.frontend.terminal.embed` | |
838 | module for more details on the use of this system. |
|
838 | module for more details on the use of this system. | |
839 |
|
839 | |||
840 | The following sample file illustrating how to use the embedding |
|
840 | The following sample file illustrating how to use the embedding | |
841 | functionality is provided in the examples directory as example-embed.py. |
|
841 | functionality is provided in the examples directory as example-embed.py. | |
842 | It should be fairly self-explanatory: |
|
842 | It should be fairly self-explanatory: | |
843 |
|
843 | |||
844 | .. literalinclude:: ../../../examples/core/example-embed.py |
|
844 | .. literalinclude:: ../../../examples/core/example-embed.py | |
845 | :language: python |
|
845 | :language: python | |
846 |
|
846 | |||
847 | Once you understand how the system functions, you can use the following |
|
847 | Once you understand how the system functions, you can use the following | |
848 | code fragments in your programs which are ready for cut and paste: |
|
848 | code fragments in your programs which are ready for cut and paste: | |
849 |
|
849 | |||
850 | .. literalinclude:: ../../../examples/core/example-embed-short.py |
|
850 | .. literalinclude:: ../../../examples/core/example-embed-short.py | |
851 | :language: python |
|
851 | :language: python | |
852 |
|
852 | |||
853 | Using the Python debugger (pdb) |
|
853 | Using the Python debugger (pdb) | |
854 | =============================== |
|
854 | =============================== | |
855 |
|
855 | |||
856 | Running entire programs via pdb |
|
856 | Running entire programs via pdb | |
857 | ------------------------------- |
|
857 | ------------------------------- | |
858 |
|
858 | |||
859 | pdb, the Python debugger, is a powerful interactive debugger which |
|
859 | pdb, the Python debugger, is a powerful interactive debugger which | |
860 | allows you to step through code, set breakpoints, watch variables, |
|
860 | allows you to step through code, set breakpoints, watch variables, | |
861 | etc. IPython makes it very easy to start any script under the control |
|
861 | etc. IPython makes it very easy to start any script under the control | |
862 | of pdb, regardless of whether you have wrapped it into a 'main()' |
|
862 | of pdb, regardless of whether you have wrapped it into a 'main()' | |
863 | function or not. For this, simply type '%run -d myscript' at an |
|
863 | function or not. For this, simply type '%run -d myscript' at an | |
864 | IPython prompt. See the %run command's documentation (via '%run?' or |
|
864 | IPython prompt. See the %run command's documentation (via '%run?' or | |
865 | in Sec. magic_ for more details, including how to control where pdb |
|
865 | in Sec. magic_ for more details, including how to control where pdb | |
866 | will stop execution first. |
|
866 | will stop execution first. | |
867 |
|
867 | |||
868 | For more information on the use of the pdb debugger, read the included |
|
868 | For more information on the use of the pdb debugger, read the included | |
869 | pdb.doc file (part of the standard Python distribution). On a stock |
|
869 | pdb.doc file (part of the standard Python distribution). On a stock | |
870 | Linux system it is located at /usr/lib/python2.3/pdb.doc, but the |
|
870 | Linux system it is located at /usr/lib/python2.3/pdb.doc, but the | |
871 | easiest way to read it is by using the help() function of the pdb module |
|
871 | easiest way to read it is by using the help() function of the pdb module | |
872 | as follows (in an IPython prompt):: |
|
872 | as follows (in an IPython prompt):: | |
873 |
|
873 | |||
874 | In [1]: import pdb |
|
874 | In [1]: import pdb | |
875 | In [2]: pdb.help() |
|
875 | In [2]: pdb.help() | |
876 |
|
876 | |||
877 | This will load the pdb.doc document in a file viewer for you automatically. |
|
877 | This will load the pdb.doc document in a file viewer for you automatically. | |
878 |
|
878 | |||
879 |
|
879 | |||
880 | Automatic invocation of pdb on exceptions |
|
880 | Automatic invocation of pdb on exceptions | |
881 | ----------------------------------------- |
|
881 | ----------------------------------------- | |
882 |
|
882 | |||
883 | IPython, if started with the ``--pdb`` option (or if the option is set in |
|
883 | IPython, if started with the ``--pdb`` option (or if the option is set in | |
884 | your config file) can call the Python pdb debugger every time your code |
|
884 | your config file) can call the Python pdb debugger every time your code | |
885 | triggers an uncaught exception. This feature |
|
885 | triggers an uncaught exception. This feature | |
886 | can also be toggled at any time with the %pdb magic command. This can be |
|
886 | can also be toggled at any time with the %pdb magic command. This can be | |
887 | extremely useful in order to find the origin of subtle bugs, because pdb |
|
887 | extremely useful in order to find the origin of subtle bugs, because pdb | |
888 | opens up at the point in your code which triggered the exception, and |
|
888 | opens up at the point in your code which triggered the exception, and | |
889 | while your program is at this point 'dead', all the data is still |
|
889 | while your program is at this point 'dead', all the data is still | |
890 | available and you can walk up and down the stack frame and understand |
|
890 | available and you can walk up and down the stack frame and understand | |
891 | the origin of the problem. |
|
891 | the origin of the problem. | |
892 |
|
892 | |||
893 | Furthermore, you can use these debugging facilities both with the |
|
893 | Furthermore, you can use these debugging facilities both with the | |
894 | embedded IPython mode and without IPython at all. For an embedded shell |
|
894 | embedded IPython mode and without IPython at all. For an embedded shell | |
895 | (see sec. Embedding_), simply call the constructor with |
|
895 | (see sec. Embedding_), simply call the constructor with | |
896 | ``--pdb`` in the argument string and pdb will automatically be called if an |
|
896 | ``--pdb`` in the argument string and pdb will automatically be called if an | |
897 | uncaught exception is triggered by your code. |
|
897 | uncaught exception is triggered by your code. | |
898 |
|
898 | |||
899 | For stand-alone use of the feature in your programs which do not use |
|
899 | For stand-alone use of the feature in your programs which do not use | |
900 | IPython at all, put the following lines toward the top of your 'main' |
|
900 | IPython at all, put the following lines toward the top of your 'main' | |
901 | routine:: |
|
901 | routine:: | |
902 |
|
902 | |||
903 | import sys |
|
903 | import sys | |
904 | from IPython.core import ultratb |
|
904 | from IPython.core import ultratb | |
905 | sys.excepthook = ultratb.FormattedTB(mode='Verbose', |
|
905 | sys.excepthook = ultratb.FormattedTB(mode='Verbose', | |
906 | color_scheme='Linux', call_pdb=1) |
|
906 | color_scheme='Linux', call_pdb=1) | |
907 |
|
907 | |||
908 | The mode keyword can be either 'Verbose' or 'Plain', giving either very |
|
908 | The mode keyword can be either 'Verbose' or 'Plain', giving either very | |
909 | detailed or normal tracebacks respectively. The color_scheme keyword can |
|
909 | detailed or normal tracebacks respectively. The color_scheme keyword can | |
910 | be one of 'NoColor', 'Linux' (default) or 'LightBG'. These are the same |
|
910 | be one of 'NoColor', 'Linux' (default) or 'LightBG'. These are the same | |
911 | options which can be set in IPython with ``--colors`` and ``--xmode``. |
|
911 | options which can be set in IPython with ``--colors`` and ``--xmode``. | |
912 |
|
912 | |||
913 | This will give any of your programs detailed, colored tracebacks with |
|
913 | This will give any of your programs detailed, colored tracebacks with | |
914 | automatic invocation of pdb. |
|
914 | automatic invocation of pdb. | |
915 |
|
915 | |||
916 |
|
916 | |||
917 | Extensions for syntax processing |
|
917 | Extensions for syntax processing | |
918 | ================================ |
|
918 | ================================ | |
919 |
|
919 | |||
920 | This isn't for the faint of heart, because the potential for breaking |
|
920 | This isn't for the faint of heart, because the potential for breaking | |
921 | things is quite high. But it can be a very powerful and useful feature. |
|
921 | things is quite high. But it can be a very powerful and useful feature. | |
922 | In a nutshell, you can redefine the way IPython processes the user input |
|
922 | In a nutshell, you can redefine the way IPython processes the user input | |
923 | line to accept new, special extensions to the syntax without needing to |
|
923 | line to accept new, special extensions to the syntax without needing to | |
924 | change any of IPython's own code. |
|
924 | change any of IPython's own code. | |
925 |
|
925 | |||
926 | In the IPython/extensions directory you will find some examples |
|
926 | In the IPython/extensions directory you will find some examples | |
927 | supplied, which we will briefly describe now. These can be used 'as is' |
|
927 | supplied, which we will briefly describe now. These can be used 'as is' | |
928 | (and both provide very useful functionality), or you can use them as a |
|
928 | (and both provide very useful functionality), or you can use them as a | |
929 | starting point for writing your own extensions. |
|
929 | starting point for writing your own extensions. | |
930 |
|
930 | |||
931 | .. _pasting_with_prompts: |
|
931 | .. _pasting_with_prompts: | |
932 |
|
932 | |||
933 | Pasting of code starting with Python or IPython prompts |
|
933 | Pasting of code starting with Python or IPython prompts | |
934 | ------------------------------------------------------- |
|
934 | ------------------------------------------------------- | |
935 |
|
935 | |||
936 |
IPython is smart enough to filter |
|
936 | IPython is smart enough to filter out input prompts, be they plain Python ones | |
937 |
(``>>>`` and ``...``) or IPython ones (``In [N]:`` and `` |
|
937 | (``>>>`` and ``...``) or IPython ones (``In [N]:`` and ``...:``). You can | |
938 | therefore copy and paste from existing interactive sessions without worry. |
|
938 | therefore copy and paste from existing interactive sessions without worry. | |
939 |
|
939 | |||
940 | The following is a 'screenshot' of how things work, copying an example from the |
|
940 | The following is a 'screenshot' of how things work, copying an example from the | |
941 | standard Python tutorial:: |
|
941 | standard Python tutorial:: | |
942 |
|
942 | |||
943 | In [1]: >>> # Fibonacci series: |
|
943 | In [1]: >>> # Fibonacci series: | |
944 |
|
944 | |||
945 | In [2]: ... # the sum of two elements defines the next |
|
945 | In [2]: ... # the sum of two elements defines the next | |
946 |
|
946 | |||
947 | In [3]: ... a, b = 0, 1 |
|
947 | In [3]: ... a, b = 0, 1 | |
948 |
|
948 | |||
949 | In [4]: >>> while b < 10: |
|
949 | In [4]: >>> while b < 10: | |
950 | ...: ... print b |
|
950 | ...: ... print b | |
951 | ...: ... a, b = b, a+b |
|
951 | ...: ... a, b = b, a+b | |
952 | ...: |
|
952 | ...: | |
953 | 1 |
|
953 | 1 | |
954 | 1 |
|
954 | 1 | |
955 | 2 |
|
955 | 2 | |
956 | 3 |
|
956 | 3 | |
957 | 5 |
|
957 | 5 | |
958 | 8 |
|
958 | 8 | |
959 |
|
959 | |||
960 | And pasting from IPython sessions works equally well:: |
|
960 | And pasting from IPython sessions works equally well:: | |
961 |
|
961 | |||
962 | In [1]: In [5]: def f(x): |
|
962 | In [1]: In [5]: def f(x): | |
963 | ...: ...: "A simple function" |
|
963 | ...: ...: "A simple function" | |
964 | ...: ...: return x**2 |
|
964 | ...: ...: return x**2 | |
965 | ...: ...: |
|
965 | ...: ...: | |
966 |
|
966 | |||
967 | In [2]: f(3) |
|
967 | In [2]: f(3) | |
968 | Out[2]: 9 |
|
968 | Out[2]: 9 | |
969 |
|
969 | |||
970 | .. _gui_support: |
|
970 | .. _gui_support: | |
971 |
|
971 | |||
972 | GUI event loop support |
|
972 | GUI event loop support | |
973 | ====================== |
|
973 | ====================== | |
974 |
|
974 | |||
975 | .. versionadded:: 0.11 |
|
975 | .. versionadded:: 0.11 | |
976 | The ``%gui`` magic and :mod:`IPython.lib.inputhook`. |
|
976 | The ``%gui`` magic and :mod:`IPython.lib.inputhook`. | |
977 |
|
977 | |||
978 | IPython has excellent support for working interactively with Graphical User |
|
978 | IPython has excellent support for working interactively with Graphical User | |
979 | Interface (GUI) toolkits, such as wxPython, PyQt4/PySide, PyGTK and Tk. This is |
|
979 | Interface (GUI) toolkits, such as wxPython, PyQt4/PySide, PyGTK and Tk. This is | |
980 | implemented using Python's builtin ``PyOSInputHook`` hook. This implementation |
|
980 | implemented using Python's builtin ``PyOSInputHook`` hook. This implementation | |
981 | is extremely robust compared to our previous thread-based version. The |
|
981 | is extremely robust compared to our previous thread-based version. The | |
982 | advantages of this are: |
|
982 | advantages of this are: | |
983 |
|
983 | |||
984 | * GUIs can be enabled and disabled dynamically at runtime. |
|
984 | * GUIs can be enabled and disabled dynamically at runtime. | |
985 | * The active GUI can be switched dynamically at runtime. |
|
985 | * The active GUI can be switched dynamically at runtime. | |
986 | * In some cases, multiple GUIs can run simultaneously with no problems. |
|
986 | * In some cases, multiple GUIs can run simultaneously with no problems. | |
987 | * There is a developer API in :mod:`IPython.lib.inputhook` for customizing |
|
987 | * There is a developer API in :mod:`IPython.lib.inputhook` for customizing | |
988 | all of these things. |
|
988 | all of these things. | |
989 |
|
989 | |||
990 | For users, enabling GUI event loop integration is simple. You simple use the |
|
990 | For users, enabling GUI event loop integration is simple. You simple use the | |
991 | ``%gui`` magic as follows:: |
|
991 | ``%gui`` magic as follows:: | |
992 |
|
992 | |||
993 | %gui [GUINAME] |
|
993 | %gui [GUINAME] | |
994 |
|
994 | |||
995 | With no arguments, ``%gui`` removes all GUI support. Valid ``GUINAME`` |
|
995 | With no arguments, ``%gui`` removes all GUI support. Valid ``GUINAME`` | |
996 | arguments are ``wx``, ``qt``, ``gtk`` and ``tk``. |
|
996 | arguments are ``wx``, ``qt``, ``gtk`` and ``tk``. | |
997 |
|
997 | |||
998 | Thus, to use wxPython interactively and create a running :class:`wx.App` |
|
998 | Thus, to use wxPython interactively and create a running :class:`wx.App` | |
999 | object, do:: |
|
999 | object, do:: | |
1000 |
|
1000 | |||
1001 | %gui wx |
|
1001 | %gui wx | |
1002 |
|
1002 | |||
1003 | For information on IPython's Matplotlib integration (and the ``pylab`` mode) |
|
1003 | For information on IPython's Matplotlib integration (and the ``pylab`` mode) | |
1004 | see :ref:`this section <matplotlib_support>`. |
|
1004 | see :ref:`this section <matplotlib_support>`. | |
1005 |
|
1005 | |||
1006 | For developers that want to use IPython's GUI event loop integration in the |
|
1006 | For developers that want to use IPython's GUI event loop integration in the | |
1007 | form of a library, these capabilities are exposed in library form in the |
|
1007 | form of a library, these capabilities are exposed in library form in the | |
1008 | :mod:`IPython.lib.inputhook` and :mod:`IPython.lib.guisupport` modules. |
|
1008 | :mod:`IPython.lib.inputhook` and :mod:`IPython.lib.guisupport` modules. | |
1009 | Interested developers should see the module docstrings for more information, |
|
1009 | Interested developers should see the module docstrings for more information, | |
1010 | but there are a few points that should be mentioned here. |
|
1010 | but there are a few points that should be mentioned here. | |
1011 |
|
1011 | |||
1012 | First, the ``PyOSInputHook`` approach only works in command line settings |
|
1012 | First, the ``PyOSInputHook`` approach only works in command line settings | |
1013 | where readline is activated. The integration with various eventloops |
|
1013 | where readline is activated. The integration with various eventloops | |
1014 | is handled somewhat differently (and more simply) when using the standalone |
|
1014 | is handled somewhat differently (and more simply) when using the standalone | |
1015 | kernel, as in the qtconsole and notebook. |
|
1015 | kernel, as in the qtconsole and notebook. | |
1016 |
|
1016 | |||
1017 | Second, when using the ``PyOSInputHook`` approach, a GUI application should |
|
1017 | Second, when using the ``PyOSInputHook`` approach, a GUI application should | |
1018 | *not* start its event loop. Instead all of this is handled by the |
|
1018 | *not* start its event loop. Instead all of this is handled by the | |
1019 | ``PyOSInputHook``. This means that applications that are meant to be used both |
|
1019 | ``PyOSInputHook``. This means that applications that are meant to be used both | |
1020 | in IPython and as standalone apps need to have special code to detects how the |
|
1020 | in IPython and as standalone apps need to have special code to detects how the | |
1021 | application is being run. We highly recommend using IPython's support for this. |
|
1021 | application is being run. We highly recommend using IPython's support for this. | |
1022 | Since the details vary slightly between toolkits, we point you to the various |
|
1022 | Since the details vary slightly between toolkits, we point you to the various | |
1023 | examples in our source directory :file:`docs/examples/lib` that demonstrate |
|
1023 | examples in our source directory :file:`docs/examples/lib` that demonstrate | |
1024 | these capabilities. |
|
1024 | these capabilities. | |
1025 |
|
1025 | |||
1026 | Third, unlike previous versions of IPython, we no longer "hijack" (replace |
|
1026 | Third, unlike previous versions of IPython, we no longer "hijack" (replace | |
1027 | them with no-ops) the event loops. This is done to allow applications that |
|
1027 | them with no-ops) the event loops. This is done to allow applications that | |
1028 | actually need to run the real event loops to do so. This is often needed to |
|
1028 | actually need to run the real event loops to do so. This is often needed to | |
1029 | process pending events at critical points. |
|
1029 | process pending events at critical points. | |
1030 |
|
1030 | |||
1031 | Finally, we also have a number of examples in our source directory |
|
1031 | Finally, we also have a number of examples in our source directory | |
1032 | :file:`docs/examples/lib` that demonstrate these capabilities. |
|
1032 | :file:`docs/examples/lib` that demonstrate these capabilities. | |
1033 |
|
1033 | |||
1034 | PyQt and PySide |
|
1034 | PyQt and PySide | |
1035 | --------------- |
|
1035 | --------------- | |
1036 |
|
1036 | |||
1037 | .. attempt at explanation of the complete mess that is Qt support |
|
1037 | .. attempt at explanation of the complete mess that is Qt support | |
1038 |
|
1038 | |||
1039 | When you use ``--gui=qt`` or ``--pylab=qt``, IPython can work with either |
|
1039 | When you use ``--gui=qt`` or ``--pylab=qt``, IPython can work with either | |
1040 | PyQt4 or PySide. There are three options for configuration here, because |
|
1040 | PyQt4 or PySide. There are three options for configuration here, because | |
1041 | PyQt4 has two APIs for QString and QVariant - v1, which is the default on |
|
1041 | PyQt4 has two APIs for QString and QVariant - v1, which is the default on | |
1042 | Python 2, and the more natural v2, which is the only API supported by PySide. |
|
1042 | Python 2, and the more natural v2, which is the only API supported by PySide. | |
1043 | v2 is also the default for PyQt4 on Python 3. IPython's code for the QtConsole |
|
1043 | v2 is also the default for PyQt4 on Python 3. IPython's code for the QtConsole | |
1044 | uses v2, but you can still use any interface in your code, since the |
|
1044 | uses v2, but you can still use any interface in your code, since the | |
1045 | Qt frontend is in a different process. |
|
1045 | Qt frontend is in a different process. | |
1046 |
|
1046 | |||
1047 | The default will be to import PyQt4 without configuration of the APIs, thus |
|
1047 | The default will be to import PyQt4 without configuration of the APIs, thus | |
1048 | matching what most applications would expect. It will fall back of PySide if |
|
1048 | matching what most applications would expect. It will fall back of PySide if | |
1049 | PyQt4 is unavailable. |
|
1049 | PyQt4 is unavailable. | |
1050 |
|
1050 | |||
1051 | If specified, IPython will respect the environment variable ``QT_API`` used |
|
1051 | If specified, IPython will respect the environment variable ``QT_API`` used | |
1052 | by ETS. ETS 4.0 also works with both PyQt4 and PySide, but it requires |
|
1052 | by ETS. ETS 4.0 also works with both PyQt4 and PySide, but it requires | |
1053 | PyQt4 to use its v2 API. So if ``QT_API=pyside`` PySide will be used, |
|
1053 | PyQt4 to use its v2 API. So if ``QT_API=pyside`` PySide will be used, | |
1054 | and if ``QT_API=pyqt`` then PyQt4 will be used *with the v2 API* for |
|
1054 | and if ``QT_API=pyqt`` then PyQt4 will be used *with the v2 API* for | |
1055 | QString and QVariant, so ETS codes like MayaVi will also work with IPython. |
|
1055 | QString and QVariant, so ETS codes like MayaVi will also work with IPython. | |
1056 |
|
1056 | |||
1057 | If you launch IPython in pylab mode with ``ipython --pylab=qt``, then IPython |
|
1057 | If you launch IPython in pylab mode with ``ipython --pylab=qt``, then IPython | |
1058 | will ask matplotlib which Qt library to use (only if QT_API is *not set*), via |
|
1058 | will ask matplotlib which Qt library to use (only if QT_API is *not set*), via | |
1059 | the 'backend.qt4' rcParam. If matplotlib is version 1.0.1 or older, then |
|
1059 | the 'backend.qt4' rcParam. If matplotlib is version 1.0.1 or older, then | |
1060 | IPython will always use PyQt4 without setting the v2 APIs, since neither v2 |
|
1060 | IPython will always use PyQt4 without setting the v2 APIs, since neither v2 | |
1061 | PyQt nor PySide work. |
|
1061 | PyQt nor PySide work. | |
1062 |
|
1062 | |||
1063 | .. warning:: |
|
1063 | .. warning:: | |
1064 |
|
1064 | |||
1065 | Note that this means for ETS 4 to work with PyQt4, ``QT_API`` *must* be set |
|
1065 | Note that this means for ETS 4 to work with PyQt4, ``QT_API`` *must* be set | |
1066 | to work with IPython's qt integration, because otherwise PyQt4 will be |
|
1066 | to work with IPython's qt integration, because otherwise PyQt4 will be | |
1067 | loaded in an incompatible mode. |
|
1067 | loaded in an incompatible mode. | |
1068 |
|
1068 | |||
1069 | It also means that you must *not* have ``QT_API`` set if you want to |
|
1069 | It also means that you must *not* have ``QT_API`` set if you want to | |
1070 | use ``--gui=qt`` with code that requires PyQt4 API v1. |
|
1070 | use ``--gui=qt`` with code that requires PyQt4 API v1. | |
1071 |
|
1071 | |||
1072 |
|
1072 | |||
1073 | .. _matplotlib_support: |
|
1073 | .. _matplotlib_support: | |
1074 |
|
1074 | |||
1075 | Plotting with matplotlib |
|
1075 | Plotting with matplotlib | |
1076 | ======================== |
|
1076 | ======================== | |
1077 |
|
1077 | |||
1078 | `Matplotlib`_ provides high quality 2D and 3D plotting for Python. Matplotlib |
|
1078 | `Matplotlib`_ provides high quality 2D and 3D plotting for Python. Matplotlib | |
1079 | can produce plots on screen using a variety of GUI toolkits, including Tk, |
|
1079 | can produce plots on screen using a variety of GUI toolkits, including Tk, | |
1080 | PyGTK, PyQt4 and wxPython. It also provides a number of commands useful for |
|
1080 | PyGTK, PyQt4 and wxPython. It also provides a number of commands useful for | |
1081 | scientific computing, all with a syntax compatible with that of the popular |
|
1081 | scientific computing, all with a syntax compatible with that of the popular | |
1082 | Matlab program. |
|
1082 | Matlab program. | |
1083 |
|
1083 | |||
1084 | To start IPython with matplotlib support, use the ``--pylab`` switch. If no |
|
1084 | To start IPython with matplotlib support, use the ``--pylab`` switch. If no | |
1085 | arguments are given, IPython will automatically detect your choice of |
|
1085 | arguments are given, IPython will automatically detect your choice of | |
1086 | matplotlib backend. You can also request a specific backend with ``--pylab |
|
1086 | matplotlib backend. You can also request a specific backend with ``--pylab | |
1087 | backend``, where ``backend`` must be one of: 'tk', 'qt', 'wx', 'gtk', 'osx'. |
|
1087 | backend``, where ``backend`` must be one of: 'tk', 'qt', 'wx', 'gtk', 'osx'. | |
1088 | In the web notebook and Qt console, 'inline' is also a valid backend value, |
|
1088 | In the web notebook and Qt console, 'inline' is also a valid backend value, | |
1089 | which produces static figures inlined inside the application window instead of |
|
1089 | which produces static figures inlined inside the application window instead of | |
1090 | matplotlib's interactive figures that live in separate windows. |
|
1090 | matplotlib's interactive figures that live in separate windows. | |
1091 |
|
1091 | |||
1092 | .. _Matplotlib: http://matplotlib.sourceforge.net |
|
1092 | .. _Matplotlib: http://matplotlib.sourceforge.net | |
1093 |
|
1093 | |||
1094 | .. _interactive_demos: |
|
1094 | .. _interactive_demos: | |
1095 |
|
1095 | |||
1096 | Interactive demos with IPython |
|
1096 | Interactive demos with IPython | |
1097 | ============================== |
|
1097 | ============================== | |
1098 |
|
1098 | |||
1099 | IPython ships with a basic system for running scripts interactively in |
|
1099 | IPython ships with a basic system for running scripts interactively in | |
1100 | sections, useful when presenting code to audiences. A few tags embedded |
|
1100 | sections, useful when presenting code to audiences. A few tags embedded | |
1101 | in comments (so that the script remains valid Python code) divide a file |
|
1101 | in comments (so that the script remains valid Python code) divide a file | |
1102 | into separate blocks, and the demo can be run one block at a time, with |
|
1102 | into separate blocks, and the demo can be run one block at a time, with | |
1103 | IPython printing (with syntax highlighting) the block before executing |
|
1103 | IPython printing (with syntax highlighting) the block before executing | |
1104 | it, and returning to the interactive prompt after each block. The |
|
1104 | it, and returning to the interactive prompt after each block. The | |
1105 | interactive namespace is updated after each block is run with the |
|
1105 | interactive namespace is updated after each block is run with the | |
1106 | contents of the demo's namespace. |
|
1106 | contents of the demo's namespace. | |
1107 |
|
1107 | |||
1108 | This allows you to show a piece of code, run it and then execute |
|
1108 | This allows you to show a piece of code, run it and then execute | |
1109 | interactively commands based on the variables just created. Once you |
|
1109 | interactively commands based on the variables just created. Once you | |
1110 | want to continue, you simply execute the next block of the demo. The |
|
1110 | want to continue, you simply execute the next block of the demo. The | |
1111 | following listing shows the markup necessary for dividing a script into |
|
1111 | following listing shows the markup necessary for dividing a script into | |
1112 | sections for execution as a demo: |
|
1112 | sections for execution as a demo: | |
1113 |
|
1113 | |||
1114 | .. literalinclude:: ../../../examples/lib/example-demo.py |
|
1114 | .. literalinclude:: ../../../examples/lib/example-demo.py | |
1115 | :language: python |
|
1115 | :language: python | |
1116 |
|
1116 | |||
1117 | In order to run a file as a demo, you must first make a Demo object out |
|
1117 | In order to run a file as a demo, you must first make a Demo object out | |
1118 | of it. If the file is named myscript.py, the following code will make a |
|
1118 | of it. If the file is named myscript.py, the following code will make a | |
1119 | demo:: |
|
1119 | demo:: | |
1120 |
|
1120 | |||
1121 | from IPython.lib.demo import Demo |
|
1121 | from IPython.lib.demo import Demo | |
1122 |
|
1122 | |||
1123 | mydemo = Demo('myscript.py') |
|
1123 | mydemo = Demo('myscript.py') | |
1124 |
|
1124 | |||
1125 | This creates the mydemo object, whose blocks you run one at a time by |
|
1125 | This creates the mydemo object, whose blocks you run one at a time by | |
1126 | simply calling the object with no arguments. If you have autocall active |
|
1126 | simply calling the object with no arguments. If you have autocall active | |
1127 | in IPython (the default), all you need to do is type:: |
|
1127 | in IPython (the default), all you need to do is type:: | |
1128 |
|
1128 | |||
1129 | mydemo |
|
1129 | mydemo | |
1130 |
|
1130 | |||
1131 | and IPython will call it, executing each block. Demo objects can be |
|
1131 | and IPython will call it, executing each block. Demo objects can be | |
1132 | restarted, you can move forward or back skipping blocks, re-execute the |
|
1132 | restarted, you can move forward or back skipping blocks, re-execute the | |
1133 | last block, etc. Simply use the Tab key on a demo object to see its |
|
1133 | last block, etc. Simply use the Tab key on a demo object to see its | |
1134 | methods, and call '?' on them to see their docstrings for more usage |
|
1134 | methods, and call '?' on them to see their docstrings for more usage | |
1135 | details. In addition, the demo module itself contains a comprehensive |
|
1135 | details. In addition, the demo module itself contains a comprehensive | |
1136 | docstring, which you can access via:: |
|
1136 | docstring, which you can access via:: | |
1137 |
|
1137 | |||
1138 | from IPython.lib import demo |
|
1138 | from IPython.lib import demo | |
1139 |
|
1139 | |||
1140 | demo? |
|
1140 | demo? | |
1141 |
|
1141 | |||
1142 | Limitations: It is important to note that these demos are limited to |
|
1142 | Limitations: It is important to note that these demos are limited to | |
1143 | fairly simple uses. In particular, you cannot break up sections within |
|
1143 | fairly simple uses. In particular, you cannot break up sections within | |
1144 | indented code (loops, if statements, function definitions, etc.) |
|
1144 | indented code (loops, if statements, function definitions, etc.) | |
1145 | Supporting something like this would basically require tracking the |
|
1145 | Supporting something like this would basically require tracking the | |
1146 | internal execution state of the Python interpreter, so only top-level |
|
1146 | internal execution state of the Python interpreter, so only top-level | |
1147 | divisions are allowed. If you want to be able to open an IPython |
|
1147 | divisions are allowed. If you want to be able to open an IPython | |
1148 | instance at an arbitrary point in a program, you can use IPython's |
|
1148 | instance at an arbitrary point in a program, you can use IPython's | |
1149 | embedding facilities, see :func:`IPython.embed` for details. |
|
1149 | embedding facilities, see :func:`IPython.embed` for details. | |
1150 |
|
1150 |
@@ -1,765 +1,765 b'' | |||||
1 | ============= |
|
1 | ============= | |
2 | 0.11 Series |
|
2 | 0.11 Series | |
3 | ============= |
|
3 | ============= | |
4 |
|
4 | |||
5 | Release 0.11 |
|
5 | Release 0.11 | |
6 | ============ |
|
6 | ============ | |
7 |
|
7 | |||
8 | IPython 0.11 is a *major* overhaul of IPython, two years in the making. Most |
|
8 | IPython 0.11 is a *major* overhaul of IPython, two years in the making. Most | |
9 | of the code base has been rewritten or at least reorganized, breaking backward |
|
9 | of the code base has been rewritten or at least reorganized, breaking backward | |
10 | compatibility with several APIs in previous versions. It is the first major |
|
10 | compatibility with several APIs in previous versions. It is the first major | |
11 | release in two years, and probably the most significant change to IPython since |
|
11 | release in two years, and probably the most significant change to IPython since | |
12 | its inception. We plan to have a relatively quick succession of releases, as |
|
12 | its inception. We plan to have a relatively quick succession of releases, as | |
13 | people discover new bugs and regressions. Once we iron out any significant |
|
13 | people discover new bugs and regressions. Once we iron out any significant | |
14 | bugs in this process and settle down the new APIs, this series will become |
|
14 | bugs in this process and settle down the new APIs, this series will become | |
15 | IPython 1.0. We encourage feedback now on the core APIs, which we hope to |
|
15 | IPython 1.0. We encourage feedback now on the core APIs, which we hope to | |
16 | maintain stable during the 1.0 series. |
|
16 | maintain stable during the 1.0 series. | |
17 |
|
17 | |||
18 | Since the internal APIs have changed so much, projects using IPython as a |
|
18 | Since the internal APIs have changed so much, projects using IPython as a | |
19 | library (as opposed to end-users of the application) are the most likely to |
|
19 | library (as opposed to end-users of the application) are the most likely to | |
20 | encounter regressions or changes that break their existing use patterns. We |
|
20 | encounter regressions or changes that break their existing use patterns. We | |
21 | will make every effort to provide updated versions of the APIs to facilitate |
|
21 | will make every effort to provide updated versions of the APIs to facilitate | |
22 | the transition, and we encourage you to contact us on the `development mailing |
|
22 | the transition, and we encourage you to contact us on the `development mailing | |
23 | list`__ with questions and feedback. |
|
23 | list`__ with questions and feedback. | |
24 |
|
24 | |||
25 | .. __: http://mail.scipy.org/mailman/listinfo/ipython-dev |
|
25 | .. __: http://mail.scipy.org/mailman/listinfo/ipython-dev | |
26 |
|
26 | |||
27 | Chris Fonnesbeck recently wrote an `excellent post`__ that highlights some of |
|
27 | Chris Fonnesbeck recently wrote an `excellent post`__ that highlights some of | |
28 | our major new features, with examples and screenshots. We encourage you to |
|
28 | our major new features, with examples and screenshots. We encourage you to | |
29 | read it as it provides an illustrated, high-level overview complementing the |
|
29 | read it as it provides an illustrated, high-level overview complementing the | |
30 | detailed feature breakdown in this document. |
|
30 | detailed feature breakdown in this document. | |
31 |
|
31 | |||
32 | .. __: http://fonnesbeck.calepin.co/innovations-in-ipython.html |
|
32 | .. __: http://fonnesbeck.calepin.co/innovations-in-ipython.html | |
33 |
|
33 | |||
34 | A quick summary of the major changes (see below for details): |
|
34 | A quick summary of the major changes (see below for details): | |
35 |
|
35 | |||
36 | * **Standalone Qt console**: a new rich console has been added to IPython, |
|
36 | * **Standalone Qt console**: a new rich console has been added to IPython, | |
37 | started with `ipython qtconsole`. In this application we have tried to |
|
37 | started with `ipython qtconsole`. In this application we have tried to | |
38 | retain the feel of a terminal for fast and efficient workflows, while adding |
|
38 | retain the feel of a terminal for fast and efficient workflows, while adding | |
39 | many features that a line-oriented terminal simply can not support, such as |
|
39 | many features that a line-oriented terminal simply can not support, such as | |
40 | inline figures, full multiline editing with syntax highlighting, graphical |
|
40 | inline figures, full multiline editing with syntax highlighting, graphical | |
41 | tooltips for function calls and much more. This development was sponsored by |
|
41 | tooltips for function calls and much more. This development was sponsored by | |
42 | `Enthought Inc.`__. See :ref:`below <qtconsole_011>` for details. |
|
42 | `Enthought Inc.`__. See :ref:`below <qtconsole_011>` for details. | |
43 |
|
43 | |||
44 | .. __: http://enthought.com |
|
44 | .. __: http://enthought.com | |
45 |
|
45 | |||
46 | * **High-level parallel computing with ZeroMQ**. Using the same architecture |
|
46 | * **High-level parallel computing with ZeroMQ**. Using the same architecture | |
47 | that our Qt console is based on, we have completely rewritten our high-level |
|
47 | that our Qt console is based on, we have completely rewritten our high-level | |
48 | parallel computing machinery that in prior versions used the Twisted |
|
48 | parallel computing machinery that in prior versions used the Twisted | |
49 | networking framework. While this change will require users to update their |
|
49 | networking framework. While this change will require users to update their | |
50 | codes, the improvements in performance, memory control and internal |
|
50 | codes, the improvements in performance, memory control and internal | |
51 | consistency across our codebase convinced us it was a price worth paying. We |
|
51 | consistency across our codebase convinced us it was a price worth paying. We | |
52 | have tried to explain how to best proceed with this update, and will be happy |
|
52 | have tried to explain how to best proceed with this update, and will be happy | |
53 | to answer questions that may arise. A full tutorial describing these |
|
53 | to answer questions that may arise. A full tutorial describing these | |
54 | features `was presented at SciPy'11`__, more details :ref:`below |
|
54 | features `was presented at SciPy'11`__, more details :ref:`below | |
55 | <parallel_011>`. |
|
55 | <parallel_011>`. | |
56 |
|
56 | |||
57 | .. __: http://minrk.github.com/scipy-tutorial-2011 |
|
57 | .. __: http://minrk.github.com/scipy-tutorial-2011 | |
58 |
|
58 | |||
59 | * **New model for GUI/plotting support in the terminal**. Now instead of the |
|
59 | * **New model for GUI/plotting support in the terminal**. Now instead of the | |
60 | various `-Xthread` flags we had before, GUI support is provided without the |
|
60 | various `-Xthread` flags we had before, GUI support is provided without the | |
61 | use of any threads, by directly integrating GUI event loops with Python's |
|
61 | use of any threads, by directly integrating GUI event loops with Python's | |
62 | `PyOS_InputHook` API. A new command-line flag `--gui` controls GUI support, |
|
62 | `PyOS_InputHook` API. A new command-line flag `--gui` controls GUI support, | |
63 | and it can also be enabled after IPython startup via the new `%gui` magic. |
|
63 | and it can also be enabled after IPython startup via the new `%gui` magic. | |
64 | This requires some changes if you want to execute GUI-using scripts inside |
|
64 | This requires some changes if you want to execute GUI-using scripts inside | |
65 | IPython, see :ref:`the GUI support section <gui_support>` for more details. |
|
65 | IPython, see :ref:`the GUI support section <gui_support>` for more details. | |
66 |
|
66 | |||
67 | * **A two-process architecture.** The Qt console is the first use of a new |
|
67 | * **A two-process architecture.** The Qt console is the first use of a new | |
68 | model that splits IPython between a kernel process where code is executed and |
|
68 | model that splits IPython between a kernel process where code is executed and | |
69 | a client that handles user interaction. We plan on also providing terminal |
|
69 | a client that handles user interaction. We plan on also providing terminal | |
70 | and web-browser based clients using this infrastructure in future releases. |
|
70 | and web-browser based clients using this infrastructure in future releases. | |
71 | This model allows multiple clients to interact with an IPython process |
|
71 | This model allows multiple clients to interact with an IPython process | |
72 | through a :ref:`well-documented messaging protocol <messaging>` using the |
|
72 | through a :ref:`well-documented messaging protocol <messaging>` using the | |
73 | ZeroMQ networking library. |
|
73 | ZeroMQ networking library. | |
74 |
|
74 | |||
75 | * **Refactoring.** the entire codebase has been refactored, in order to make it |
|
75 | * **Refactoring.** the entire codebase has been refactored, in order to make it | |
76 | more modular and easier to contribute to. IPython has traditionally been a |
|
76 | more modular and easier to contribute to. IPython has traditionally been a | |
77 | hard project to participate because the old codebase was very monolithic. We |
|
77 | hard project to participate because the old codebase was very monolithic. We | |
78 | hope this (ongoing) restructuring will make it easier for new developers to |
|
78 | hope this (ongoing) restructuring will make it easier for new developers to | |
79 | join us. |
|
79 | join us. | |
80 |
|
80 | |||
81 | * **Vim integration**. Vim can be configured to seamlessly control an IPython |
|
81 | * **Vim integration**. Vim can be configured to seamlessly control an IPython | |
82 | kernel, see the files in :file:`docs/examples/vim` for the full details. |
|
82 | kernel, see the files in :file:`docs/examples/vim` for the full details. | |
83 | This work was done by Paul Ivanov, who prepared a nice `video |
|
83 | This work was done by Paul Ivanov, who prepared a nice `video | |
84 | demonstration`__ of the features it provides. |
|
84 | demonstration`__ of the features it provides. | |
85 |
|
85 | |||
86 | .. __: http://pirsquared.org/blog/2011/07/28/vim-ipython/ |
|
86 | .. __: http://pirsquared.org/blog/2011/07/28/vim-ipython/ | |
87 |
|
87 | |||
88 | * **Integration into Microsoft Visual Studio**. Thanks to the work of the |
|
88 | * **Integration into Microsoft Visual Studio**. Thanks to the work of the | |
89 | Microsoft `Python Tools for Visual Studio`__ team, this version of IPython |
|
89 | Microsoft `Python Tools for Visual Studio`__ team, this version of IPython | |
90 | has been integrated into Microsoft Visual Studio's Python tools open source |
|
90 | has been integrated into Microsoft Visual Studio's Python tools open source | |
91 | plug-in. `Details below`_ |
|
91 | plug-in. `Details below`_ | |
92 |
|
92 | |||
93 | .. __: http://pytools.codeplex.com |
|
93 | .. __: http://pytools.codeplex.com | |
94 | .. _details below: ms_visual_studio_011_ |
|
94 | .. _details below: ms_visual_studio_011_ | |
95 |
|
95 | |||
96 | * **Improved unicode support**. We closed many bugs related to unicode input. |
|
96 | * **Improved unicode support**. We closed many bugs related to unicode input. | |
97 |
|
97 | |||
98 | * **Python 3**. IPython now runs on Python 3.x. See :ref:`python3_011` for |
|
98 | * **Python 3**. IPython now runs on Python 3.x. See :ref:`python3_011` for | |
99 | details. |
|
99 | details. | |
100 |
|
100 | |||
101 | * **New profile model**. Profiles are now directories that contain all relevant |
|
101 | * **New profile model**. Profiles are now directories that contain all relevant | |
102 | infromation for that session, and thus better isolate IPython use-cases. |
|
102 | infromation for that session, and thus better isolate IPython use-cases. | |
103 |
|
103 | |||
104 | * **SQLite storage for history**. All history is now stored in a SQLite |
|
104 | * **SQLite storage for history**. All history is now stored in a SQLite | |
105 | database, providing support for multiple simultaneous sessions that won't |
|
105 | database, providing support for multiple simultaneous sessions that won't | |
106 | clobber each other as well as the ability to perform queries on all stored |
|
106 | clobber each other as well as the ability to perform queries on all stored | |
107 | data. |
|
107 | data. | |
108 |
|
108 | |||
109 | * **New configuration system**. All parts of IPython are now configured via a |
|
109 | * **New configuration system**. All parts of IPython are now configured via a | |
110 | mechanism inspired by the Enthought Traits library. Any configurable element |
|
110 | mechanism inspired by the Enthought Traits library. Any configurable element | |
111 | can have its attributes set either via files that now use real Python syntax |
|
111 | can have its attributes set either via files that now use real Python syntax | |
112 | or from the command-line. |
|
112 | or from the command-line. | |
113 |
|
113 | |||
114 | * **Pasting of code with prompts**. IPython now intelligently strips out input |
|
114 | * **Pasting of code with prompts**. IPython now intelligently strips out input | |
115 | prompts , be they plain Python ones (``>>>`` and ``...``) or IPython ones |
|
115 | prompts , be they plain Python ones (``>>>`` and ``...``) or IPython ones | |
116 |
(``In [N]:`` and `` |
|
116 | (``In [N]:`` and ``...:``). More details :ref:`here <pasting_with_prompts>`. | |
117 |
|
117 | |||
118 |
|
118 | |||
119 | Authors and support |
|
119 | Authors and support | |
120 | ------------------- |
|
120 | ------------------- | |
121 |
|
121 | |||
122 | Over 60 separate authors have contributed to this release, see :ref:`below |
|
122 | Over 60 separate authors have contributed to this release, see :ref:`below | |
123 | <credits_011>` for a full list. In particular, we want to highlight the |
|
123 | <credits_011>` for a full list. In particular, we want to highlight the | |
124 | extremely active participation of two new core team members: Evan Patterson |
|
124 | extremely active participation of two new core team members: Evan Patterson | |
125 | implemented the Qt console, and Thomas Kluyver started with our Python 3 port |
|
125 | implemented the Qt console, and Thomas Kluyver started with our Python 3 port | |
126 | and by now has made major contributions to just about every area of IPython. |
|
126 | and by now has made major contributions to just about every area of IPython. | |
127 |
|
127 | |||
128 | We are also grateful for the support we have received during this development |
|
128 | We are also grateful for the support we have received during this development | |
129 | cycle from several institutions: |
|
129 | cycle from several institutions: | |
130 |
|
130 | |||
131 | - `Enthought Inc`__ funded the development of our new Qt console, an effort that |
|
131 | - `Enthought Inc`__ funded the development of our new Qt console, an effort that | |
132 | required developing major pieces of underlying infrastructure, which now |
|
132 | required developing major pieces of underlying infrastructure, which now | |
133 | power not only the Qt console but also our new parallel machinery. We'd like |
|
133 | power not only the Qt console but also our new parallel machinery. We'd like | |
134 | to thank Eric Jones and Travis Oliphant for their support, as well as Ilan |
|
134 | to thank Eric Jones and Travis Oliphant for their support, as well as Ilan | |
135 | Schnell for his tireless work integrating and testing IPython in the |
|
135 | Schnell for his tireless work integrating and testing IPython in the | |
136 | `Enthought Python Distribution`_. |
|
136 | `Enthought Python Distribution`_. | |
137 |
|
137 | |||
138 | .. __: http://enthought.com |
|
138 | .. __: http://enthought.com | |
139 | .. _Enthought Python Distribution: http://www.enthought.com/products/epd.php |
|
139 | .. _Enthought Python Distribution: http://www.enthought.com/products/epd.php | |
140 |
|
140 | |||
141 | - Nipy/NIH: funding via the `NiPy project`__ (NIH grant 5R01MH081909-02) helped |
|
141 | - Nipy/NIH: funding via the `NiPy project`__ (NIH grant 5R01MH081909-02) helped | |
142 | us jumpstart the development of this series by restructuring the entire |
|
142 | us jumpstart the development of this series by restructuring the entire | |
143 | codebase two years ago in a way that would make modular development and |
|
143 | codebase two years ago in a way that would make modular development and | |
144 | testing more approachable. Without this initial groundwork, all the new |
|
144 | testing more approachable. Without this initial groundwork, all the new | |
145 | features we have added would have been impossible to develop. |
|
145 | features we have added would have been impossible to develop. | |
146 |
|
146 | |||
147 | .. __: http://nipy.org |
|
147 | .. __: http://nipy.org | |
148 |
|
148 | |||
149 | - Sage/NSF: funding via the grant `Sage: Unifying Mathematical Software for |
|
149 | - Sage/NSF: funding via the grant `Sage: Unifying Mathematical Software for | |
150 | Scientists, Engineers, and Mathematicians`__ (NSF grant DMS-1015114) |
|
150 | Scientists, Engineers, and Mathematicians`__ (NSF grant DMS-1015114) | |
151 | supported a meeting in spring 2011 of several of the core IPython developers |
|
151 | supported a meeting in spring 2011 of several of the core IPython developers | |
152 | where major progress was made integrating the last key pieces leading to this |
|
152 | where major progress was made integrating the last key pieces leading to this | |
153 | release. |
|
153 | release. | |
154 |
|
154 | |||
155 | .. __: http://modular.math.washington.edu/grants/compmath09 |
|
155 | .. __: http://modular.math.washington.edu/grants/compmath09 | |
156 |
|
156 | |||
157 | - Microsoft's team working on `Python Tools for Visual Studio`__ developed the |
|
157 | - Microsoft's team working on `Python Tools for Visual Studio`__ developed the | |
158 | integraton of IPython into the Python plugin for Visual Studio 2010. |
|
158 | integraton of IPython into the Python plugin for Visual Studio 2010. | |
159 |
|
159 | |||
160 | .. __: http://pytools.codeplex.com |
|
160 | .. __: http://pytools.codeplex.com | |
161 |
|
161 | |||
162 | - Google Summer of Code: in 2010, we had two students developing prototypes of |
|
162 | - Google Summer of Code: in 2010, we had two students developing prototypes of | |
163 | the new machinery that is now maturing in this release: `Omar Zapata`_ and |
|
163 | the new machinery that is now maturing in this release: `Omar Zapata`_ and | |
164 | `Gerardo GutiΓ©rrez`_. |
|
164 | `Gerardo GutiΓ©rrez`_. | |
165 |
|
165 | |||
166 | .. _Omar Zapata: http://ipythonzmq.blogspot.com/2010/08/ipython-zmq-status.html |
|
166 | .. _Omar Zapata: http://ipythonzmq.blogspot.com/2010/08/ipython-zmq-status.html | |
167 | .. _Gerardo GutiΓ©rrez: http://ipythonqt.blogspot.com/2010/04/ipython-qt-interface-gsoc-2010-proposal.html> |
|
167 | .. _Gerardo GutiΓ©rrez: http://ipythonqt.blogspot.com/2010/04/ipython-qt-interface-gsoc-2010-proposal.html> | |
168 |
|
168 | |||
169 |
|
169 | |||
170 | Development summary: moving to Git and Github |
|
170 | Development summary: moving to Git and Github | |
171 | --------------------------------------------- |
|
171 | --------------------------------------------- | |
172 |
|
172 | |||
173 | In April 2010, after `one breakage too many with bzr`__, we decided to move our |
|
173 | In April 2010, after `one breakage too many with bzr`__, we decided to move our | |
174 | entire development process to Git and Github.com. This has proven to be one of |
|
174 | entire development process to Git and Github.com. This has proven to be one of | |
175 | the best decisions in the project's history, as the combination of git and |
|
175 | the best decisions in the project's history, as the combination of git and | |
176 | github have made us far, far more productive than we could be with our previous |
|
176 | github have made us far, far more productive than we could be with our previous | |
177 | tools. We first converted our bzr repo to a git one without losing history, |
|
177 | tools. We first converted our bzr repo to a git one without losing history, | |
178 | and a few weeks later ported all open Launchpad bugs to github issues with |
|
178 | and a few weeks later ported all open Launchpad bugs to github issues with | |
179 | their comments mostly intact (modulo some formatting changes). This ensured a |
|
179 | their comments mostly intact (modulo some formatting changes). This ensured a | |
180 | smooth transition where no development history or submitted bugs were lost. |
|
180 | smooth transition where no development history or submitted bugs were lost. | |
181 | Feel free to use our little Launchpad to Github issues `porting script`_ if you |
|
181 | Feel free to use our little Launchpad to Github issues `porting script`_ if you | |
182 | need to make a similar transition. |
|
182 | need to make a similar transition. | |
183 |
|
183 | |||
184 | .. __: http://mail.scipy.org/pipermail/ipython-dev/2010-April/005944.html |
|
184 | .. __: http://mail.scipy.org/pipermail/ipython-dev/2010-April/005944.html | |
185 | .. _porting script: https://gist.github.com/835577 |
|
185 | .. _porting script: https://gist.github.com/835577 | |
186 |
|
186 | |||
187 | These simple statistics show how much work has been done on the new release, by |
|
187 | These simple statistics show how much work has been done on the new release, by | |
188 | comparing the current code to the last point it had in common with the 0.10 |
|
188 | comparing the current code to the last point it had in common with the 0.10 | |
189 | series. A huge diff and ~2200 commits make up this cycle:: |
|
189 | series. A huge diff and ~2200 commits make up this cycle:: | |
190 |
|
190 | |||
191 | git diff $(git merge-base 0.10.2 HEAD) | wc -l |
|
191 | git diff $(git merge-base 0.10.2 HEAD) | wc -l | |
192 | 288019 |
|
192 | 288019 | |
193 |
|
193 | |||
194 | git log $(git merge-base 0.10.2 HEAD)..HEAD --oneline | wc -l |
|
194 | git log $(git merge-base 0.10.2 HEAD)..HEAD --oneline | wc -l | |
195 | 2200 |
|
195 | 2200 | |
196 |
|
196 | |||
197 | Since our move to github, 511 issues were closed, 226 of which were pull |
|
197 | Since our move to github, 511 issues were closed, 226 of which were pull | |
198 | requests and 285 regular issues (:ref:`a full list with links |
|
198 | requests and 285 regular issues (:ref:`a full list with links | |
199 | <issues_list_011>` is available for those interested in the details). Github's |
|
199 | <issues_list_011>` is available for those interested in the details). Github's | |
200 | pull requests are a fantastic mechanism for reviewing code and building a |
|
200 | pull requests are a fantastic mechanism for reviewing code and building a | |
201 | shared ownership of the project, and we are making enthusiastic use of it. |
|
201 | shared ownership of the project, and we are making enthusiastic use of it. | |
202 |
|
202 | |||
203 | .. Note:: |
|
203 | .. Note:: | |
204 |
|
204 | |||
205 | This undercounts the number of issues closed in this development cycle, |
|
205 | This undercounts the number of issues closed in this development cycle, | |
206 | since we only moved to github for issue tracking in May 2010, but we have no |
|
206 | since we only moved to github for issue tracking in May 2010, but we have no | |
207 | way of collecting statistics on the number of issues closed in the old |
|
207 | way of collecting statistics on the number of issues closed in the old | |
208 | Launchpad bug tracker prior to that. |
|
208 | Launchpad bug tracker prior to that. | |
209 |
|
209 | |||
210 |
|
210 | |||
211 | .. _qtconsole_011: |
|
211 | .. _qtconsole_011: | |
212 |
|
212 | |||
213 | Qt Console |
|
213 | Qt Console | |
214 | ---------- |
|
214 | ---------- | |
215 |
|
215 | |||
216 | IPython now ships with a Qt application that feels very much like a terminal, |
|
216 | IPython now ships with a Qt application that feels very much like a terminal, | |
217 | but is in fact a rich GUI that runs an IPython client but supports inline |
|
217 | but is in fact a rich GUI that runs an IPython client but supports inline | |
218 | figures, saving sessions to PDF and HTML, multiline editing with syntax |
|
218 | figures, saving sessions to PDF and HTML, multiline editing with syntax | |
219 | highlighting, graphical calltips and much more: |
|
219 | highlighting, graphical calltips and much more: | |
220 |
|
220 | |||
221 | .. figure:: ../_static/qtconsole.png |
|
221 | .. figure:: ../_static/qtconsole.png | |
222 | :width: 400px |
|
222 | :width: 400px | |
223 | :alt: IPython Qt console with embedded plots |
|
223 | :alt: IPython Qt console with embedded plots | |
224 | :align: center |
|
224 | :align: center | |
225 | :target: ../_static/qtconsole.png |
|
225 | :target: ../_static/qtconsole.png | |
226 |
|
226 | |||
227 | The Qt console for IPython, using inline matplotlib plots. |
|
227 | The Qt console for IPython, using inline matplotlib plots. | |
228 |
|
228 | |||
229 | We hope that many projects will embed this widget, which we've kept |
|
229 | We hope that many projects will embed this widget, which we've kept | |
230 | deliberately very lightweight, into their own environments. In the future we |
|
230 | deliberately very lightweight, into their own environments. In the future we | |
231 | may also offer a slightly more featureful application (with menus and other GUI |
|
231 | may also offer a slightly more featureful application (with menus and other GUI | |
232 | elements), but we remain committed to always shipping this easy to embed |
|
232 | elements), but we remain committed to always shipping this easy to embed | |
233 | widget. |
|
233 | widget. | |
234 |
|
234 | |||
235 | See the :ref:`Qt console section <qtconsole>` of the docs for a detailed |
|
235 | See the :ref:`Qt console section <qtconsole>` of the docs for a detailed | |
236 | description of the console's features and use. |
|
236 | description of the console's features and use. | |
237 |
|
237 | |||
238 |
|
238 | |||
239 | .. _parallel_011: |
|
239 | .. _parallel_011: | |
240 |
|
240 | |||
241 | High-level parallel computing with ZeroMQ |
|
241 | High-level parallel computing with ZeroMQ | |
242 | ----------------------------------------- |
|
242 | ----------------------------------------- | |
243 |
|
243 | |||
244 | We have completely rewritten the Twisted-based code for high-level parallel |
|
244 | We have completely rewritten the Twisted-based code for high-level parallel | |
245 | computing to work atop our new ZeroMQ architecture. While we realize this will |
|
245 | computing to work atop our new ZeroMQ architecture. While we realize this will | |
246 | break compatibility for a number of users, we hope to make the transition as |
|
246 | break compatibility for a number of users, we hope to make the transition as | |
247 | easy as possible with our docs, and we are convinced the change is worth it. |
|
247 | easy as possible with our docs, and we are convinced the change is worth it. | |
248 | ZeroMQ provides us with much tighter control over memory, higher performance, |
|
248 | ZeroMQ provides us with much tighter control over memory, higher performance, | |
249 | and its communications are impervious to the Python Global Interpreter Lock |
|
249 | and its communications are impervious to the Python Global Interpreter Lock | |
250 | because they take place in a system-level C++ thread. The impact of the GIL in |
|
250 | because they take place in a system-level C++ thread. The impact of the GIL in | |
251 | our previous code was something we could simply not work around, given that |
|
251 | our previous code was something we could simply not work around, given that | |
252 | Twisted is itself a Python library. So while Twisted is a very capable |
|
252 | Twisted is itself a Python library. So while Twisted is a very capable | |
253 | framework, we think ZeroMQ fits our needs much better and we hope you will find |
|
253 | framework, we think ZeroMQ fits our needs much better and we hope you will find | |
254 | the change to be a significant improvement in the long run. |
|
254 | the change to be a significant improvement in the long run. | |
255 |
|
255 | |||
256 | Our manual contains :ref:`a full description of how to use IPython for parallel |
|
256 | Our manual contains :ref:`a full description of how to use IPython for parallel | |
257 | computing <parallel_overview>`, and the `tutorial`__ presented by Min |
|
257 | computing <parallel_overview>`, and the `tutorial`__ presented by Min | |
258 | Ragan-Kelley at the SciPy 2011 conference provides a hands-on complement to the |
|
258 | Ragan-Kelley at the SciPy 2011 conference provides a hands-on complement to the | |
259 | reference docs. |
|
259 | reference docs. | |
260 |
|
260 | |||
261 | .. __: http://minrk.github.com/scipy-tutorial-2011 |
|
261 | .. __: http://minrk.github.com/scipy-tutorial-2011 | |
262 |
|
262 | |||
263 |
|
263 | |||
264 | Refactoring |
|
264 | Refactoring | |
265 | ----------- |
|
265 | ----------- | |
266 |
|
266 | |||
267 | As of this release, a signifiant portion of IPython has been refactored. This |
|
267 | As of this release, a signifiant portion of IPython has been refactored. This | |
268 | refactoring is founded on a number of new abstractions. The main new classes |
|
268 | refactoring is founded on a number of new abstractions. The main new classes | |
269 | that implement these abstractions are: |
|
269 | that implement these abstractions are: | |
270 |
|
270 | |||
271 | * :class:`IPython.utils.traitlets.HasTraits`. |
|
271 | * :class:`IPython.utils.traitlets.HasTraits`. | |
272 | * :class:`IPython.config.configurable.Configurable`. |
|
272 | * :class:`IPython.config.configurable.Configurable`. | |
273 | * :class:`IPython.config.application.Application`. |
|
273 | * :class:`IPython.config.application.Application`. | |
274 | * :class:`IPython.config.loader.ConfigLoader`. |
|
274 | * :class:`IPython.config.loader.ConfigLoader`. | |
275 | * :class:`IPython.config.loader.Config` |
|
275 | * :class:`IPython.config.loader.Config` | |
276 |
|
276 | |||
277 | We are still in the process of writing developer focused documentation about |
|
277 | We are still in the process of writing developer focused documentation about | |
278 | these classes, but for now our :ref:`configuration documentation |
|
278 | these classes, but for now our :ref:`configuration documentation | |
279 | <config_overview>` contains a high level overview of the concepts that these |
|
279 | <config_overview>` contains a high level overview of the concepts that these | |
280 | classes express. |
|
280 | classes express. | |
281 |
|
281 | |||
282 | The biggest user-visible change is likely the move to using the config system |
|
282 | The biggest user-visible change is likely the move to using the config system | |
283 | to determine the command-line arguments for IPython applications. The benefit |
|
283 | to determine the command-line arguments for IPython applications. The benefit | |
284 | of this is that *all* configurable values in IPython are exposed on the |
|
284 | of this is that *all* configurable values in IPython are exposed on the | |
285 | command-line, but the syntax for specifying values has changed. The gist is |
|
285 | command-line, but the syntax for specifying values has changed. The gist is | |
286 | that assigning values is pure Python assignment. Simple flags exist for |
|
286 | that assigning values is pure Python assignment. Simple flags exist for | |
287 | commonly used options, these are always prefixed with '--'. |
|
287 | commonly used options, these are always prefixed with '--'. | |
288 |
|
288 | |||
289 | The IPython command-line help has the details of all the options (via |
|
289 | The IPython command-line help has the details of all the options (via | |
290 | ``ipythyon --help``), but a simple example should clarify things; the ``pylab`` |
|
290 | ``ipythyon --help``), but a simple example should clarify things; the ``pylab`` | |
291 | flag can be used to start in pylab mode with the qt4 backend:: |
|
291 | flag can be used to start in pylab mode with the qt4 backend:: | |
292 |
|
292 | |||
293 | ipython --pylab=qt |
|
293 | ipython --pylab=qt | |
294 |
|
294 | |||
295 | which is equivalent to using the fully qualified form:: |
|
295 | which is equivalent to using the fully qualified form:: | |
296 |
|
296 | |||
297 | ipython --TerminalIPythonApp.pylab=qt |
|
297 | ipython --TerminalIPythonApp.pylab=qt | |
298 |
|
298 | |||
299 | The long-form options can be listed via ``ipython --help-all``. |
|
299 | The long-form options can be listed via ``ipython --help-all``. | |
300 |
|
300 | |||
301 |
|
301 | |||
302 | ZeroMQ architecture |
|
302 | ZeroMQ architecture | |
303 | ------------------- |
|
303 | ------------------- | |
304 |
|
304 | |||
305 | There is a new GUI framework for IPython, based on a client-server model in |
|
305 | There is a new GUI framework for IPython, based on a client-server model in | |
306 | which multiple clients can communicate with one IPython kernel, using the |
|
306 | which multiple clients can communicate with one IPython kernel, using the | |
307 | ZeroMQ messaging framework. There is already a Qt console client, which can |
|
307 | ZeroMQ messaging framework. There is already a Qt console client, which can | |
308 | be started by calling ``ipython qtconsole``. The protocol is :ref:`documented |
|
308 | be started by calling ``ipython qtconsole``. The protocol is :ref:`documented | |
309 | <messaging>`. |
|
309 | <messaging>`. | |
310 |
|
310 | |||
311 | The parallel computing framework has also been rewritten using ZMQ. The |
|
311 | The parallel computing framework has also been rewritten using ZMQ. The | |
312 | protocol is described :ref:`here <parallel_messages>`, and the code is in the |
|
312 | protocol is described :ref:`here <parallel_messages>`, and the code is in the | |
313 | new :mod:`IPython.parallel` module. |
|
313 | new :mod:`IPython.parallel` module. | |
314 |
|
314 | |||
315 | .. _python3_011: |
|
315 | .. _python3_011: | |
316 |
|
316 | |||
317 | Python 3 support |
|
317 | Python 3 support | |
318 | ---------------- |
|
318 | ---------------- | |
319 |
|
319 | |||
320 | A Python 3 version of IPython has been prepared. For the time being, this is |
|
320 | A Python 3 version of IPython has been prepared. For the time being, this is | |
321 | maintained separately and updated from the main codebase. Its code can be found |
|
321 | maintained separately and updated from the main codebase. Its code can be found | |
322 | `here <https://github.com/ipython/ipython-py3k>`_. The parallel computing |
|
322 | `here <https://github.com/ipython/ipython-py3k>`_. The parallel computing | |
323 | components are not perfect on Python3, but most functionality appears to be |
|
323 | components are not perfect on Python3, but most functionality appears to be | |
324 | working. As this work is evolving quickly, the best place to find updated |
|
324 | working. As this work is evolving quickly, the best place to find updated | |
325 | information about it is our `Python 3 wiki page`__. |
|
325 | information about it is our `Python 3 wiki page`__. | |
326 |
|
326 | |||
327 | .. __: http://wiki.ipython.org/index.php?title=Python_3 |
|
327 | .. __: http://wiki.ipython.org/index.php?title=Python_3 | |
328 |
|
328 | |||
329 |
|
329 | |||
330 | Unicode |
|
330 | Unicode | |
331 | ------- |
|
331 | ------- | |
332 |
|
332 | |||
333 | Entering non-ascii characters in unicode literals (``u"β¬ΓΈ"``) now works |
|
333 | Entering non-ascii characters in unicode literals (``u"β¬ΓΈ"``) now works | |
334 | properly on all platforms. However, entering these in byte/string literals |
|
334 | properly on all platforms. However, entering these in byte/string literals | |
335 | (``"β¬ΓΈ"``) will not work as expected on Windows (or any platform where the |
|
335 | (``"β¬ΓΈ"``) will not work as expected on Windows (or any platform where the | |
336 | terminal encoding is not UTF-8, as it typically is for Linux & Mac OS X). You |
|
336 | terminal encoding is not UTF-8, as it typically is for Linux & Mac OS X). You | |
337 | can use escape sequences (``"\xe9\x82"``) to get bytes above 128, or use |
|
337 | can use escape sequences (``"\xe9\x82"``) to get bytes above 128, or use | |
338 | unicode literals and encode them. This is a limitation of Python 2 which we |
|
338 | unicode literals and encode them. This is a limitation of Python 2 which we | |
339 | cannot easily work around. |
|
339 | cannot easily work around. | |
340 |
|
340 | |||
341 | .. _ms_visual_studio_011: |
|
341 | .. _ms_visual_studio_011: | |
342 |
|
342 | |||
343 | Integration with Microsoft Visual Studio |
|
343 | Integration with Microsoft Visual Studio | |
344 | ---------------------------------------- |
|
344 | ---------------------------------------- | |
345 |
|
345 | |||
346 | IPython can be used as the interactive shell in the `Python plugin for |
|
346 | IPython can be used as the interactive shell in the `Python plugin for | |
347 | Microsoft Visual Studio`__, as seen here: |
|
347 | Microsoft Visual Studio`__, as seen here: | |
348 |
|
348 | |||
349 | .. figure:: ../_static/ms_visual_studio.png |
|
349 | .. figure:: ../_static/ms_visual_studio.png | |
350 | :width: 500px |
|
350 | :width: 500px | |
351 | :alt: IPython console embedded in Microsoft Visual Studio. |
|
351 | :alt: IPython console embedded in Microsoft Visual Studio. | |
352 | :align: center |
|
352 | :align: center | |
353 | :target: ../_static/ms_visual_studio.png |
|
353 | :target: ../_static/ms_visual_studio.png | |
354 |
|
354 | |||
355 | IPython console embedded in Microsoft Visual Studio. |
|
355 | IPython console embedded in Microsoft Visual Studio. | |
356 |
|
356 | |||
357 | The Microsoft team developing this currently has a release candidate out using |
|
357 | The Microsoft team developing this currently has a release candidate out using | |
358 | IPython 0.11. We will continue to collaborate with them to ensure that as they |
|
358 | IPython 0.11. We will continue to collaborate with them to ensure that as they | |
359 | approach their final release date, the integration with IPython remains smooth. |
|
359 | approach their final release date, the integration with IPython remains smooth. | |
360 | We'd like to thank Dino Viehland and Shahrokh Mortazavi for the work they have |
|
360 | We'd like to thank Dino Viehland and Shahrokh Mortazavi for the work they have | |
361 | done towards this feature, as well as Wenming Ye for his support of our WinHPC |
|
361 | done towards this feature, as well as Wenming Ye for his support of our WinHPC | |
362 | capabilities. |
|
362 | capabilities. | |
363 |
|
363 | |||
364 | .. __: http://pytools.codeplex.com |
|
364 | .. __: http://pytools.codeplex.com | |
365 |
|
365 | |||
366 |
|
366 | |||
367 | Additional new features |
|
367 | Additional new features | |
368 | ----------------------- |
|
368 | ----------------------- | |
369 |
|
369 | |||
370 | * Added ``Bytes`` traitlet, removing ``Str``. All 'string' traitlets should |
|
370 | * Added ``Bytes`` traitlet, removing ``Str``. All 'string' traitlets should | |
371 | either be ``Unicode`` if a real string, or ``Bytes`` if a C-string. This |
|
371 | either be ``Unicode`` if a real string, or ``Bytes`` if a C-string. This | |
372 | removes ambiguity and helps the Python 3 transition. |
|
372 | removes ambiguity and helps the Python 3 transition. | |
373 |
|
373 | |||
374 | * New magic ``%loadpy`` loads a python file from disk or web URL into |
|
374 | * New magic ``%loadpy`` loads a python file from disk or web URL into | |
375 | the current input buffer. |
|
375 | the current input buffer. | |
376 |
|
376 | |||
377 | * New magic ``%pastebin`` for sharing code via the 'Lodge it' pastebin. |
|
377 | * New magic ``%pastebin`` for sharing code via the 'Lodge it' pastebin. | |
378 |
|
378 | |||
379 | * New magic ``%precision`` for controlling float and numpy pretty printing. |
|
379 | * New magic ``%precision`` for controlling float and numpy pretty printing. | |
380 |
|
380 | |||
381 | * IPython applications initiate logging, so any object can gain access to |
|
381 | * IPython applications initiate logging, so any object can gain access to | |
382 | a the logger of the currently running Application with: |
|
382 | a the logger of the currently running Application with: | |
383 |
|
383 | |||
384 | .. sourcecode:: python |
|
384 | .. sourcecode:: python | |
385 |
|
385 | |||
386 | from IPython.config.application import Application |
|
386 | from IPython.config.application import Application | |
387 | logger = Application.instance().log |
|
387 | logger = Application.instance().log | |
388 |
|
388 | |||
389 | * You can now get help on an object halfway through typing a command. For |
|
389 | * You can now get help on an object halfway through typing a command. For | |
390 | instance, typing ``a = zip?`` shows the details of :func:`zip`. It also |
|
390 | instance, typing ``a = zip?`` shows the details of :func:`zip`. It also | |
391 | leaves the command at the next prompt so you can carry on with it. |
|
391 | leaves the command at the next prompt so you can carry on with it. | |
392 |
|
392 | |||
393 | * The input history is now written to an SQLite database. The API for |
|
393 | * The input history is now written to an SQLite database. The API for | |
394 | retrieving items from the history has also been redesigned. |
|
394 | retrieving items from the history has also been redesigned. | |
395 |
|
395 | |||
396 | * The :mod:`IPython.extensions.pretty` extension has been moved out of |
|
396 | * The :mod:`IPython.extensions.pretty` extension has been moved out of | |
397 | quarantine and fully updated to the new extension API. |
|
397 | quarantine and fully updated to the new extension API. | |
398 |
|
398 | |||
399 | * New magics for loading/unloading/reloading extensions have been added: |
|
399 | * New magics for loading/unloading/reloading extensions have been added: | |
400 | ``%load_ext``, ``%unload_ext`` and ``%reload_ext``. |
|
400 | ``%load_ext``, ``%unload_ext`` and ``%reload_ext``. | |
401 |
|
401 | |||
402 | * The configuration system and configuration files are brand new. See the |
|
402 | * The configuration system and configuration files are brand new. See the | |
403 | configuration system :ref:`documentation <config_index>` for more details. |
|
403 | configuration system :ref:`documentation <config_index>` for more details. | |
404 |
|
404 | |||
405 | * The :class:`~IPython.core.interactiveshell.InteractiveShell` class is now a |
|
405 | * The :class:`~IPython.core.interactiveshell.InteractiveShell` class is now a | |
406 | :class:`~IPython.config.configurable.Configurable` subclass and has traitlets |
|
406 | :class:`~IPython.config.configurable.Configurable` subclass and has traitlets | |
407 | that determine the defaults and runtime environment. The ``__init__`` method |
|
407 | that determine the defaults and runtime environment. The ``__init__`` method | |
408 | has also been refactored so this class can be instantiated and run without |
|
408 | has also been refactored so this class can be instantiated and run without | |
409 | the old :mod:`ipmaker` module. |
|
409 | the old :mod:`ipmaker` module. | |
410 |
|
410 | |||
411 | * The methods of :class:`~IPython.core.interactiveshell.InteractiveShell` have |
|
411 | * The methods of :class:`~IPython.core.interactiveshell.InteractiveShell` have | |
412 | been organized into sections to make it easier to turn more sections |
|
412 | been organized into sections to make it easier to turn more sections | |
413 | of functionality into components. |
|
413 | of functionality into components. | |
414 |
|
414 | |||
415 | * The embedded shell has been refactored into a truly standalone subclass of |
|
415 | * The embedded shell has been refactored into a truly standalone subclass of | |
416 | :class:`InteractiveShell` called :class:`InteractiveShellEmbed`. All |
|
416 | :class:`InteractiveShell` called :class:`InteractiveShellEmbed`. All | |
417 | embedding logic has been taken out of the base class and put into the |
|
417 | embedding logic has been taken out of the base class and put into the | |
418 | embedded subclass. |
|
418 | embedded subclass. | |
419 |
|
419 | |||
420 | * Added methods of :class:`~IPython.core.interactiveshell.InteractiveShell` to |
|
420 | * Added methods of :class:`~IPython.core.interactiveshell.InteractiveShell` to | |
421 | help it cleanup after itself. The :meth:`cleanup` method controls this. We |
|
421 | help it cleanup after itself. The :meth:`cleanup` method controls this. We | |
422 | couldn't do this in :meth:`__del__` because we have cycles in our object |
|
422 | couldn't do this in :meth:`__del__` because we have cycles in our object | |
423 | graph that prevent it from being called. |
|
423 | graph that prevent it from being called. | |
424 |
|
424 | |||
425 | * Created a new module :mod:`IPython.utils.importstring` for resolving |
|
425 | * Created a new module :mod:`IPython.utils.importstring` for resolving | |
426 | strings like ``foo.bar.Bar`` to the actual class. |
|
426 | strings like ``foo.bar.Bar`` to the actual class. | |
427 |
|
427 | |||
428 | * Completely refactored the :mod:`IPython.core.prefilter` module into |
|
428 | * Completely refactored the :mod:`IPython.core.prefilter` module into | |
429 | :class:`~IPython.config.configurable.Configurable` subclasses. Added a new |
|
429 | :class:`~IPython.config.configurable.Configurable` subclasses. Added a new | |
430 | layer into the prefilter system, called "transformations" that all new |
|
430 | layer into the prefilter system, called "transformations" that all new | |
431 | prefilter logic should use (rather than the older "checker/handler" |
|
431 | prefilter logic should use (rather than the older "checker/handler" | |
432 | approach). |
|
432 | approach). | |
433 |
|
433 | |||
434 | * Aliases are now components (:mod:`IPython.core.alias`). |
|
434 | * Aliases are now components (:mod:`IPython.core.alias`). | |
435 |
|
435 | |||
436 | * New top level :func:`~IPython.frontend.terminal.embed.embed` function that can |
|
436 | * New top level :func:`~IPython.frontend.terminal.embed.embed` function that can | |
437 | be called to embed IPython at any place in user's code. On the first call it |
|
437 | be called to embed IPython at any place in user's code. On the first call it | |
438 | will create an :class:`~IPython.frontend.terminal.embed.InteractiveShellEmbed` |
|
438 | will create an :class:`~IPython.frontend.terminal.embed.InteractiveShellEmbed` | |
439 | instance and call it. In later calls, it just calls the previously created |
|
439 | instance and call it. In later calls, it just calls the previously created | |
440 | :class:`~IPython.frontend.terminal.embed.InteractiveShellEmbed`. |
|
440 | :class:`~IPython.frontend.terminal.embed.InteractiveShellEmbed`. | |
441 |
|
441 | |||
442 | * Created a configuration system (:mod:`IPython.config.configurable`) that is |
|
442 | * Created a configuration system (:mod:`IPython.config.configurable`) that is | |
443 | based on :mod:`IPython.utils.traitlets`. Configurables are arranged into a |
|
443 | based on :mod:`IPython.utils.traitlets`. Configurables are arranged into a | |
444 | runtime containment tree (not inheritance) that i) automatically propagates |
|
444 | runtime containment tree (not inheritance) that i) automatically propagates | |
445 | configuration information and ii) allows singletons to discover each other in |
|
445 | configuration information and ii) allows singletons to discover each other in | |
446 | a loosely coupled manner. In the future all parts of IPython will be |
|
446 | a loosely coupled manner. In the future all parts of IPython will be | |
447 | subclasses of :class:`~IPython.config.configurable.Configurable`. All IPython |
|
447 | subclasses of :class:`~IPython.config.configurable.Configurable`. All IPython | |
448 | developers should become familiar with the config system. |
|
448 | developers should become familiar with the config system. | |
449 |
|
449 | |||
450 | * Created a new :class:`~IPython.config.loader.Config` for holding |
|
450 | * Created a new :class:`~IPython.config.loader.Config` for holding | |
451 | configuration information. This is a dict like class with a few extras: i) |
|
451 | configuration information. This is a dict like class with a few extras: i) | |
452 | it supports attribute style access, ii) it has a merge function that merges |
|
452 | it supports attribute style access, ii) it has a merge function that merges | |
453 | two :class:`~IPython.config.loader.Config` instances recursively and iii) it |
|
453 | two :class:`~IPython.config.loader.Config` instances recursively and iii) it | |
454 | will automatically create sub-:class:`~IPython.config.loader.Config` |
|
454 | will automatically create sub-:class:`~IPython.config.loader.Config` | |
455 | instances for attributes that start with an uppercase character. |
|
455 | instances for attributes that start with an uppercase character. | |
456 |
|
456 | |||
457 | * Created new configuration loaders in :mod:`IPython.config.loader`. These |
|
457 | * Created new configuration loaders in :mod:`IPython.config.loader`. These | |
458 | loaders provide a unified loading interface for all configuration |
|
458 | loaders provide a unified loading interface for all configuration | |
459 | information including command line arguments and configuration files. We |
|
459 | information including command line arguments and configuration files. We | |
460 | have two default implementations based on :mod:`argparse` and plain python |
|
460 | have two default implementations based on :mod:`argparse` and plain python | |
461 | files. These are used to implement the new configuration system. |
|
461 | files. These are used to implement the new configuration system. | |
462 |
|
462 | |||
463 | * Created a top-level :class:`Application` class in |
|
463 | * Created a top-level :class:`Application` class in | |
464 | :mod:`IPython.core.application` that is designed to encapsulate the starting |
|
464 | :mod:`IPython.core.application` that is designed to encapsulate the starting | |
465 | of any basic Python program. An application loads and merges all the |
|
465 | of any basic Python program. An application loads and merges all the | |
466 | configuration objects, constructs the main application, configures and |
|
466 | configuration objects, constructs the main application, configures and | |
467 | initiates logging, and creates and configures any :class:`Configurable` |
|
467 | initiates logging, and creates and configures any :class:`Configurable` | |
468 | instances and then starts the application running. An extended |
|
468 | instances and then starts the application running. An extended | |
469 | :class:`BaseIPythonApplication` class adds logic for handling the |
|
469 | :class:`BaseIPythonApplication` class adds logic for handling the | |
470 | IPython directory as well as profiles, and all IPython entry points |
|
470 | IPython directory as well as profiles, and all IPython entry points | |
471 | extend it. |
|
471 | extend it. | |
472 |
|
472 | |||
473 | * The :class:`Type` and :class:`Instance` traitlets now handle classes given |
|
473 | * The :class:`Type` and :class:`Instance` traitlets now handle classes given | |
474 | as strings, like ``foo.bar.Bar``. This is needed for forward declarations. |
|
474 | as strings, like ``foo.bar.Bar``. This is needed for forward declarations. | |
475 | But, this was implemented in a careful way so that string to class |
|
475 | But, this was implemented in a careful way so that string to class | |
476 | resolution is done at a single point, when the parent |
|
476 | resolution is done at a single point, when the parent | |
477 | :class:`~IPython.utils.traitlets.HasTraitlets` is instantiated. |
|
477 | :class:`~IPython.utils.traitlets.HasTraitlets` is instantiated. | |
478 |
|
478 | |||
479 | * :mod:`IPython.utils.ipstruct` has been refactored to be a subclass of |
|
479 | * :mod:`IPython.utils.ipstruct` has been refactored to be a subclass of | |
480 | dict. It also now has full docstrings and doctests. |
|
480 | dict. It also now has full docstrings and doctests. | |
481 |
|
481 | |||
482 | * Created a Traits like implementation in :mod:`IPython.utils.traitlets`. This |
|
482 | * Created a Traits like implementation in :mod:`IPython.utils.traitlets`. This | |
483 | is a pure Python, lightweight version of a library that is similar to |
|
483 | is a pure Python, lightweight version of a library that is similar to | |
484 | Enthought's Traits project, but has no dependencies on Enthought's code. We |
|
484 | Enthought's Traits project, but has no dependencies on Enthought's code. We | |
485 | are using this for validation, defaults and notification in our new component |
|
485 | are using this for validation, defaults and notification in our new component | |
486 | system. Although it is not 100% API compatible with Enthought's Traits, we |
|
486 | system. Although it is not 100% API compatible with Enthought's Traits, we | |
487 | plan on moving in this direction so that eventually our implementation could |
|
487 | plan on moving in this direction so that eventually our implementation could | |
488 | be replaced by a (yet to exist) pure Python version of Enthought Traits. |
|
488 | be replaced by a (yet to exist) pure Python version of Enthought Traits. | |
489 |
|
489 | |||
490 | * Added a new module :mod:`IPython.lib.inputhook` to manage the integration |
|
490 | * Added a new module :mod:`IPython.lib.inputhook` to manage the integration | |
491 | with GUI event loops using `PyOS_InputHook`. See the docstrings in this |
|
491 | with GUI event loops using `PyOS_InputHook`. See the docstrings in this | |
492 | module or the main IPython docs for details. |
|
492 | module or the main IPython docs for details. | |
493 |
|
493 | |||
494 | * For users, GUI event loop integration is now handled through the new |
|
494 | * For users, GUI event loop integration is now handled through the new | |
495 | :command:`%gui` magic command. Type ``%gui?`` at an IPython prompt for |
|
495 | :command:`%gui` magic command. Type ``%gui?`` at an IPython prompt for | |
496 | documentation. |
|
496 | documentation. | |
497 |
|
497 | |||
498 | * For developers :mod:`IPython.lib.inputhook` provides a simple interface |
|
498 | * For developers :mod:`IPython.lib.inputhook` provides a simple interface | |
499 | for managing the event loops in their interactive GUI applications. |
|
499 | for managing the event loops in their interactive GUI applications. | |
500 | Examples can be found in our :file:`docs/examples/lib` directory. |
|
500 | Examples can be found in our :file:`docs/examples/lib` directory. | |
501 |
|
501 | |||
502 | Backwards incompatible changes |
|
502 | Backwards incompatible changes | |
503 | ------------------------------ |
|
503 | ------------------------------ | |
504 |
|
504 | |||
505 | * The Twisted-based :mod:`IPython.kernel` has been removed, and completely |
|
505 | * The Twisted-based :mod:`IPython.kernel` has been removed, and completely | |
506 | rewritten as :mod:`IPython.parallel`, using ZeroMQ. |
|
506 | rewritten as :mod:`IPython.parallel`, using ZeroMQ. | |
507 |
|
507 | |||
508 | * Profiles are now directories. Instead of a profile being a single config file, |
|
508 | * Profiles are now directories. Instead of a profile being a single config file, | |
509 | profiles are now self-contained directories. By default, profiles get their |
|
509 | profiles are now self-contained directories. By default, profiles get their | |
510 | own IPython history, log files, and everything. To create a new profile, do |
|
510 | own IPython history, log files, and everything. To create a new profile, do | |
511 | ``ipython profile create <name>``. |
|
511 | ``ipython profile create <name>``. | |
512 |
|
512 | |||
513 | * All IPython applications have been rewritten to use |
|
513 | * All IPython applications have been rewritten to use | |
514 | :class:`~IPython.config.loader.KeyValueConfigLoader`. This means that |
|
514 | :class:`~IPython.config.loader.KeyValueConfigLoader`. This means that | |
515 | command-line options have changed. Now, all configurable values are accessible |
|
515 | command-line options have changed. Now, all configurable values are accessible | |
516 | from the command-line with the same syntax as in a configuration file. |
|
516 | from the command-line with the same syntax as in a configuration file. | |
517 |
|
517 | |||
518 | * The command line options ``-wthread``, ``-qthread`` and |
|
518 | * The command line options ``-wthread``, ``-qthread`` and | |
519 | ``-gthread`` have been removed. Use ``--gui=wx``, ``--gui=qt``, ``--gui=gtk`` |
|
519 | ``-gthread`` have been removed. Use ``--gui=wx``, ``--gui=qt``, ``--gui=gtk`` | |
520 | instead. |
|
520 | instead. | |
521 |
|
521 | |||
522 | * The extension loading functions have been renamed to |
|
522 | * The extension loading functions have been renamed to | |
523 | :func:`load_ipython_extension` and :func:`unload_ipython_extension`. |
|
523 | :func:`load_ipython_extension` and :func:`unload_ipython_extension`. | |
524 |
|
524 | |||
525 | * :class:`~IPython.core.interactiveshell.InteractiveShell` no longer takes an |
|
525 | * :class:`~IPython.core.interactiveshell.InteractiveShell` no longer takes an | |
526 | ``embedded`` argument. Instead just use the |
|
526 | ``embedded`` argument. Instead just use the | |
527 | :class:`~IPython.core.interactiveshell.InteractiveShellEmbed` class. |
|
527 | :class:`~IPython.core.interactiveshell.InteractiveShellEmbed` class. | |
528 |
|
528 | |||
529 | * ``__IPYTHON__`` is no longer injected into ``__builtin__``. |
|
529 | * ``__IPYTHON__`` is no longer injected into ``__builtin__``. | |
530 |
|
530 | |||
531 | * :meth:`Struct.__init__` no longer takes `None` as its first argument. It |
|
531 | * :meth:`Struct.__init__` no longer takes `None` as its first argument. It | |
532 | must be a :class:`dict` or :class:`Struct`. |
|
532 | must be a :class:`dict` or :class:`Struct`. | |
533 |
|
533 | |||
534 | * :meth:`~IPython.core.interactiveshell.InteractiveShell.ipmagic` has been |
|
534 | * :meth:`~IPython.core.interactiveshell.InteractiveShell.ipmagic` has been | |
535 | renamed :meth:`~IPython.core.interactiveshell.InteractiveShell.magic.` |
|
535 | renamed :meth:`~IPython.core.interactiveshell.InteractiveShell.magic.` | |
536 |
|
536 | |||
537 | * The functions :func:`ipmagic` and :func:`ipalias` have been removed from |
|
537 | * The functions :func:`ipmagic` and :func:`ipalias` have been removed from | |
538 | :mod:`__builtins__`. |
|
538 | :mod:`__builtins__`. | |
539 |
|
539 | |||
540 | * The references to the global |
|
540 | * The references to the global | |
541 | :class:`~IPython.core.interactivehell.InteractiveShell` instance (``_ip``, and |
|
541 | :class:`~IPython.core.interactivehell.InteractiveShell` instance (``_ip``, and | |
542 | ``__IP``) have been removed from the user's namespace. They are replaced by a |
|
542 | ``__IP``) have been removed from the user's namespace. They are replaced by a | |
543 | new function called :func:`get_ipython` that returns the current |
|
543 | new function called :func:`get_ipython` that returns the current | |
544 | :class:`~IPython.core.interactiveshell.InteractiveShell` instance. This |
|
544 | :class:`~IPython.core.interactiveshell.InteractiveShell` instance. This | |
545 | function is injected into the user's namespace and is now the main way of |
|
545 | function is injected into the user's namespace and is now the main way of | |
546 | accessing the running IPython. |
|
546 | accessing the running IPython. | |
547 |
|
547 | |||
548 | * Old style configuration files :file:`ipythonrc` and :file:`ipy_user_conf.py` |
|
548 | * Old style configuration files :file:`ipythonrc` and :file:`ipy_user_conf.py` | |
549 | are no longer supported. Users should migrate there configuration files to |
|
549 | are no longer supported. Users should migrate there configuration files to | |
550 | the new format described :ref:`here <config_overview>` and :ref:`here |
|
550 | the new format described :ref:`here <config_overview>` and :ref:`here | |
551 | <configuring_ipython>`. |
|
551 | <configuring_ipython>`. | |
552 |
|
552 | |||
553 | * The old IPython extension API that relied on :func:`ipapi` has been |
|
553 | * The old IPython extension API that relied on :func:`ipapi` has been | |
554 | completely removed. The new extension API is described :ref:`here |
|
554 | completely removed. The new extension API is described :ref:`here | |
555 | <configuring_ipython>`. |
|
555 | <configuring_ipython>`. | |
556 |
|
556 | |||
557 | * Support for ``qt3`` has been dropped. Users who need this should use |
|
557 | * Support for ``qt3`` has been dropped. Users who need this should use | |
558 | previous versions of IPython. |
|
558 | previous versions of IPython. | |
559 |
|
559 | |||
560 | * Removed :mod:`shellglobals` as it was obsolete. |
|
560 | * Removed :mod:`shellglobals` as it was obsolete. | |
561 |
|
561 | |||
562 | * Removed all the threaded shells in :mod:`IPython.core.shell`. These are no |
|
562 | * Removed all the threaded shells in :mod:`IPython.core.shell`. These are no | |
563 | longer needed because of the new capabilities in |
|
563 | longer needed because of the new capabilities in | |
564 | :mod:`IPython.lib.inputhook`. |
|
564 | :mod:`IPython.lib.inputhook`. | |
565 |
|
565 | |||
566 | * New top-level sub-packages have been created: :mod:`IPython.core`, |
|
566 | * New top-level sub-packages have been created: :mod:`IPython.core`, | |
567 | :mod:`IPython.lib`, :mod:`IPython.utils`, :mod:`IPython.deathrow`, |
|
567 | :mod:`IPython.lib`, :mod:`IPython.utils`, :mod:`IPython.deathrow`, | |
568 | :mod:`IPython.quarantine`. All existing top-level modules have been |
|
568 | :mod:`IPython.quarantine`. All existing top-level modules have been | |
569 | moved to appropriate sub-packages. All internal import statements |
|
569 | moved to appropriate sub-packages. All internal import statements | |
570 | have been updated and tests have been added. The build system (setup.py |
|
570 | have been updated and tests have been added. The build system (setup.py | |
571 | and friends) have been updated. See :ref:`this section <module_reorg>` of the |
|
571 | and friends) have been updated. See :ref:`this section <module_reorg>` of the | |
572 | documentation for descriptions of these new sub-packages. |
|
572 | documentation for descriptions of these new sub-packages. | |
573 |
|
573 | |||
574 | * :mod:`IPython.ipapi` has been moved to :mod:`IPython.core.ipapi`. |
|
574 | * :mod:`IPython.ipapi` has been moved to :mod:`IPython.core.ipapi`. | |
575 | :mod:`IPython.Shell` and :mod:`IPython.iplib` have been split and removed as |
|
575 | :mod:`IPython.Shell` and :mod:`IPython.iplib` have been split and removed as | |
576 | part of the refactor. |
|
576 | part of the refactor. | |
577 |
|
577 | |||
578 | * :mod:`Extensions` has been moved to :mod:`extensions` and all existing |
|
578 | * :mod:`Extensions` has been moved to :mod:`extensions` and all existing | |
579 | extensions have been moved to either :mod:`IPython.quarantine` or |
|
579 | extensions have been moved to either :mod:`IPython.quarantine` or | |
580 | :mod:`IPython.deathrow`. :mod:`IPython.quarantine` contains modules that we |
|
580 | :mod:`IPython.deathrow`. :mod:`IPython.quarantine` contains modules that we | |
581 | plan on keeping but that need to be updated. :mod:`IPython.deathrow` contains |
|
581 | plan on keeping but that need to be updated. :mod:`IPython.deathrow` contains | |
582 | modules that are either dead or that should be maintained as third party |
|
582 | modules that are either dead or that should be maintained as third party | |
583 | libraries. More details about this can be found :ref:`here <module_reorg>`. |
|
583 | libraries. More details about this can be found :ref:`here <module_reorg>`. | |
584 |
|
584 | |||
585 | * Previous IPython GUIs in :mod:`IPython.frontend` and :mod:`IPython.gui` are |
|
585 | * Previous IPython GUIs in :mod:`IPython.frontend` and :mod:`IPython.gui` are | |
586 | likely broken, and have been removed to :mod:`IPython.deathrow` because of the |
|
586 | likely broken, and have been removed to :mod:`IPython.deathrow` because of the | |
587 | refactoring in the core. With proper updates, these should still work. |
|
587 | refactoring in the core. With proper updates, these should still work. | |
588 |
|
588 | |||
589 |
|
589 | |||
590 | Known Regressions |
|
590 | Known Regressions | |
591 | ----------------- |
|
591 | ----------------- | |
592 |
|
592 | |||
593 | We do our best to improve IPython, but there are some known regressions in 0.11 |
|
593 | We do our best to improve IPython, but there are some known regressions in 0.11 | |
594 | relative to 0.10.2. First of all, there are features that have yet to be |
|
594 | relative to 0.10.2. First of all, there are features that have yet to be | |
595 | ported to the new APIs, and in order to ensure that all of the installed code |
|
595 | ported to the new APIs, and in order to ensure that all of the installed code | |
596 | runs for our users, we have moved them to two separate directories in the |
|
596 | runs for our users, we have moved them to two separate directories in the | |
597 | source distribution, `quarantine` and `deathrow`. Finally, we have some other |
|
597 | source distribution, `quarantine` and `deathrow`. Finally, we have some other | |
598 | miscellaneous regressions that we hope to fix as soon as possible. We now |
|
598 | miscellaneous regressions that we hope to fix as soon as possible. We now | |
599 | describe all of these in more detail. |
|
599 | describe all of these in more detail. | |
600 |
|
600 | |||
601 | Quarantine |
|
601 | Quarantine | |
602 | ~~~~~~~~~~ |
|
602 | ~~~~~~~~~~ | |
603 |
|
603 | |||
604 | These are tools and extensions that we consider relatively easy to update to |
|
604 | These are tools and extensions that we consider relatively easy to update to | |
605 | the new classes and APIs, but that we simply haven't had time for. Any user |
|
605 | the new classes and APIs, but that we simply haven't had time for. Any user | |
606 | who is interested in one of these is encouraged to help us by porting it and |
|
606 | who is interested in one of these is encouraged to help us by porting it and | |
607 | submitting a pull request on our `development site`_. |
|
607 | submitting a pull request on our `development site`_. | |
608 |
|
608 | |||
609 | .. _development site: http://github.com/ipython/ipython |
|
609 | .. _development site: http://github.com/ipython/ipython | |
610 |
|
610 | |||
611 | Currently, the quarantine directory contains:: |
|
611 | Currently, the quarantine directory contains:: | |
612 |
|
612 | |||
613 | clearcmd.py ipy_fsops.py ipy_signals.py |
|
613 | clearcmd.py ipy_fsops.py ipy_signals.py | |
614 | envpersist.py ipy_gnuglobal.py ipy_synchronize_with.py |
|
614 | envpersist.py ipy_gnuglobal.py ipy_synchronize_with.py | |
615 | ext_rescapture.py ipy_greedycompleter.py ipy_system_conf.py |
|
615 | ext_rescapture.py ipy_greedycompleter.py ipy_system_conf.py | |
616 | InterpreterExec.py ipy_jot.py ipy_which.py |
|
616 | InterpreterExec.py ipy_jot.py ipy_which.py | |
617 | ipy_app_completers.py ipy_lookfor.py ipy_winpdb.py |
|
617 | ipy_app_completers.py ipy_lookfor.py ipy_winpdb.py | |
618 | ipy_autoreload.py ipy_profile_doctest.py ipy_workdir.py |
|
618 | ipy_autoreload.py ipy_profile_doctest.py ipy_workdir.py | |
619 | ipy_completers.py ipy_pydb.py jobctrl.py |
|
619 | ipy_completers.py ipy_pydb.py jobctrl.py | |
620 | ipy_editors.py ipy_rehashdir.py ledit.py |
|
620 | ipy_editors.py ipy_rehashdir.py ledit.py | |
621 | ipy_exportdb.py ipy_render.py pspersistence.py |
|
621 | ipy_exportdb.py ipy_render.py pspersistence.py | |
622 | ipy_extutil.py ipy_server.py win32clip.py |
|
622 | ipy_extutil.py ipy_server.py win32clip.py | |
623 |
|
623 | |||
624 | Deathrow |
|
624 | Deathrow | |
625 | ~~~~~~~~ |
|
625 | ~~~~~~~~ | |
626 |
|
626 | |||
627 | These packages may be harder to update or make most sense as third-party |
|
627 | These packages may be harder to update or make most sense as third-party | |
628 | libraries. Some of them are completely obsolete and have been already replaced |
|
628 | libraries. Some of them are completely obsolete and have been already replaced | |
629 | by better functionality (we simply haven't had the time to carefully weed them |
|
629 | by better functionality (we simply haven't had the time to carefully weed them | |
630 | out so they are kept here for now). Others simply require fixes to code that |
|
630 | out so they are kept here for now). Others simply require fixes to code that | |
631 | the current core team may not be familiar with. If a tool you were used to is |
|
631 | the current core team may not be familiar with. If a tool you were used to is | |
632 | included here, we encourage you to contact the dev list and we can discuss |
|
632 | included here, we encourage you to contact the dev list and we can discuss | |
633 | whether it makes sense to keep it in IPython (if it can be maintained). |
|
633 | whether it makes sense to keep it in IPython (if it can be maintained). | |
634 |
|
634 | |||
635 | Currently, the deathrow directory contains:: |
|
635 | Currently, the deathrow directory contains:: | |
636 |
|
636 | |||
637 | astyle.py ipy_defaults.py ipy_vimserver.py |
|
637 | astyle.py ipy_defaults.py ipy_vimserver.py | |
638 | dtutils.py ipy_kitcfg.py numeric_formats.py |
|
638 | dtutils.py ipy_kitcfg.py numeric_formats.py | |
639 | Gnuplot2.py ipy_legacy.py numutils.py |
|
639 | Gnuplot2.py ipy_legacy.py numutils.py | |
640 | GnuplotInteractive.py ipy_p4.py outputtrap.py |
|
640 | GnuplotInteractive.py ipy_p4.py outputtrap.py | |
641 | GnuplotRuntime.py ipy_profile_none.py PhysicalQInput.py |
|
641 | GnuplotRuntime.py ipy_profile_none.py PhysicalQInput.py | |
642 | ibrowse.py ipy_profile_numpy.py PhysicalQInteractive.py |
|
642 | ibrowse.py ipy_profile_numpy.py PhysicalQInteractive.py | |
643 | igrid.py ipy_profile_scipy.py quitter.py* |
|
643 | igrid.py ipy_profile_scipy.py quitter.py* | |
644 | ipipe.py ipy_profile_sh.py scitedirector.py |
|
644 | ipipe.py ipy_profile_sh.py scitedirector.py | |
645 | iplib.py ipy_profile_zope.py Shell.py |
|
645 | iplib.py ipy_profile_zope.py Shell.py | |
646 | ipy_constants.py ipy_traits_completer.py twshell.py |
|
646 | ipy_constants.py ipy_traits_completer.py twshell.py | |
647 |
|
647 | |||
648 |
|
648 | |||
649 | Other regressions |
|
649 | Other regressions | |
650 | ~~~~~~~~~~~~~~~~~ |
|
650 | ~~~~~~~~~~~~~~~~~ | |
651 |
|
651 | |||
652 | * The machinery that adds functionality to the 'sh' profile for using IPython |
|
652 | * The machinery that adds functionality to the 'sh' profile for using IPython | |
653 | as your system shell has not been updated to use the new APIs. As a result, |
|
653 | as your system shell has not been updated to use the new APIs. As a result, | |
654 | only the aesthetic (prompt) changes are still implemented. We intend to fix |
|
654 | only the aesthetic (prompt) changes are still implemented. We intend to fix | |
655 | this by 0.12. Tracked as issue 547_. |
|
655 | this by 0.12. Tracked as issue 547_. | |
656 |
|
656 | |||
657 | .. _547: https://github.com/ipython/ipython/issues/547 |
|
657 | .. _547: https://github.com/ipython/ipython/issues/547 | |
658 |
|
658 | |||
659 | * The installation of scripts on Windows was broken without setuptools, so we |
|
659 | * The installation of scripts on Windows was broken without setuptools, so we | |
660 | now depend on setuptools on Windows. We hope to fix setuptools-less |
|
660 | now depend on setuptools on Windows. We hope to fix setuptools-less | |
661 | installation, and then remove the setuptools dependency. Issue 539_. |
|
661 | installation, and then remove the setuptools dependency. Issue 539_. | |
662 |
|
662 | |||
663 | .. _539: https://github.com/ipython/ipython/issues/539 |
|
663 | .. _539: https://github.com/ipython/ipython/issues/539 | |
664 |
|
664 | |||
665 | * The directory history `_dh` is not saved between sessions. Issue 634_. |
|
665 | * The directory history `_dh` is not saved between sessions. Issue 634_. | |
666 |
|
666 | |||
667 | .. _634: https://github.com/ipython/ipython/issues/634 |
|
667 | .. _634: https://github.com/ipython/ipython/issues/634 | |
668 |
|
668 | |||
669 |
|
669 | |||
670 | Removed Features |
|
670 | Removed Features | |
671 | ---------------- |
|
671 | ---------------- | |
672 |
|
672 | |||
673 | As part of the updating of IPython, we have removed a few features for the |
|
673 | As part of the updating of IPython, we have removed a few features for the | |
674 | purposes of cleaning up the codebase and interfaces. These removals are |
|
674 | purposes of cleaning up the codebase and interfaces. These removals are | |
675 | permanent, but for any item listed below, equivalent functionality is |
|
675 | permanent, but for any item listed below, equivalent functionality is | |
676 | available. |
|
676 | available. | |
677 |
|
677 | |||
678 | * The magics Exit and Quit have been dropped as ways to exit IPython. Instead, |
|
678 | * The magics Exit and Quit have been dropped as ways to exit IPython. Instead, | |
679 | the lowercase forms of both work either as a bare name (``exit``) or a |
|
679 | the lowercase forms of both work either as a bare name (``exit``) or a | |
680 | function call (``exit()``). You can assign these to other names using |
|
680 | function call (``exit()``). You can assign these to other names using | |
681 | exec_lines in the config file. |
|
681 | exec_lines in the config file. | |
682 |
|
682 | |||
683 |
|
683 | |||
684 |
.. _credits_011: |
|
684 | .. _credits_011: | |
685 |
|
685 | |||
686 | Credits |
|
686 | Credits | |
687 | ------- |
|
687 | ------- | |
688 |
|
688 | |||
689 | Many users and developers contributed code, features, bug reports and ideas to |
|
689 | Many users and developers contributed code, features, bug reports and ideas to | |
690 | this release. Please do not hesitate in contacting us if we've failed to |
|
690 | this release. Please do not hesitate in contacting us if we've failed to | |
691 | acknowledge your contribution here. In particular, for this release we have |
|
691 | acknowledge your contribution here. In particular, for this release we have | |
692 | contribution from the following people, a mix of new and regular names (in |
|
692 | contribution from the following people, a mix of new and regular names (in | |
693 | alphabetical order by first name): |
|
693 | alphabetical order by first name): | |
694 |
|
694 | |||
695 | * Aenugu Sai Kiran Reddy <saikrn08-at-gmail.com> |
|
695 | * Aenugu Sai Kiran Reddy <saikrn08-at-gmail.com> | |
696 | * andy wilson <wilson.andrew.j+github-at-gmail.com> |
|
696 | * andy wilson <wilson.andrew.j+github-at-gmail.com> | |
697 | * Antonio Cuni <antocuni> |
|
697 | * Antonio Cuni <antocuni> | |
698 | * Barry Wark <barrywark-at-gmail.com> |
|
698 | * Barry Wark <barrywark-at-gmail.com> | |
699 | * Beetoju Anuradha <anu.beethoju-at-gmail.com> |
|
699 | * Beetoju Anuradha <anu.beethoju-at-gmail.com> | |
700 | * Benjamin Ragan-Kelley <minrk-at-Mercury.local> |
|
700 | * Benjamin Ragan-Kelley <minrk-at-Mercury.local> | |
701 | * Brad Reisfeld |
|
701 | * Brad Reisfeld | |
702 | * Brian E. Granger <ellisonbg-at-gmail.com> |
|
702 | * Brian E. Granger <ellisonbg-at-gmail.com> | |
703 | * Christoph Gohlke <cgohlke-at-uci.edu> |
|
703 | * Christoph Gohlke <cgohlke-at-uci.edu> | |
704 | * Cody Precord |
|
704 | * Cody Precord | |
705 | * dan.milstein |
|
705 | * dan.milstein | |
706 | * Darren Dale <dsdale24-at-gmail.com> |
|
706 | * Darren Dale <dsdale24-at-gmail.com> | |
707 | * Dav Clark <davclark-at-berkeley.edu> |
|
707 | * Dav Clark <davclark-at-berkeley.edu> | |
708 | * David Warde-Farley <wardefar-at-iro.umontreal.ca> |
|
708 | * David Warde-Farley <wardefar-at-iro.umontreal.ca> | |
709 | * epatters <ejpatters-at-gmail.com> |
|
709 | * epatters <ejpatters-at-gmail.com> | |
710 | * epatters <epatters-at-caltech.edu> |
|
710 | * epatters <epatters-at-caltech.edu> | |
711 | * epatters <epatters-at-enthought.com> |
|
711 | * epatters <epatters-at-enthought.com> | |
712 | * Eric Firing <efiring-at-hawaii.edu> |
|
712 | * Eric Firing <efiring-at-hawaii.edu> | |
713 | * Erik Tollerud <erik.tollerud-at-gmail.com> |
|
713 | * Erik Tollerud <erik.tollerud-at-gmail.com> | |
714 | * Evan Patterson <epatters-at-enthought.com> |
|
714 | * Evan Patterson <epatters-at-enthought.com> | |
715 | * Fernando Perez <Fernando.Perez-at-berkeley.edu> |
|
715 | * Fernando Perez <Fernando.Perez-at-berkeley.edu> | |
716 | * Gael Varoquaux <gael.varoquaux-at-normalesup.org> |
|
716 | * Gael Varoquaux <gael.varoquaux-at-normalesup.org> | |
717 | * Gerardo <muzgash-at-Muzpelheim> |
|
717 | * Gerardo <muzgash-at-Muzpelheim> | |
718 | * Jason Grout <jason.grout-at-drake.edu> |
|
718 | * Jason Grout <jason.grout-at-drake.edu> | |
719 | * John Hunter <jdh2358-at-gmail.com> |
|
719 | * John Hunter <jdh2358-at-gmail.com> | |
720 | * Jens Hedegaard Nielsen <jenshnielsen-at-gmail.com> |
|
720 | * Jens Hedegaard Nielsen <jenshnielsen-at-gmail.com> | |
721 | * Johann Cohen-Tanugi <johann.cohentanugi-at-gmail.com> |
|
721 | * Johann Cohen-Tanugi <johann.cohentanugi-at-gmail.com> | |
722 | * JΓΆrgen Stenarson <jorgen.stenarson-at-bostream.nu> |
|
722 | * JΓΆrgen Stenarson <jorgen.stenarson-at-bostream.nu> | |
723 | * Justin Riley <justin.t.riley-at-gmail.com> |
|
723 | * Justin Riley <justin.t.riley-at-gmail.com> | |
724 | * Kiorky |
|
724 | * Kiorky | |
725 | * Laurent Dufrechou <laurent.dufrechou-at-gmail.com> |
|
725 | * Laurent Dufrechou <laurent.dufrechou-at-gmail.com> | |
726 | * Luis Pedro Coelho <lpc-at-cmu.edu> |
|
726 | * Luis Pedro Coelho <lpc-at-cmu.edu> | |
727 | * Mani chandra <mchandra-at-iitk.ac.in> |
|
727 | * Mani chandra <mchandra-at-iitk.ac.in> | |
728 | * Mark E. Smith |
|
728 | * Mark E. Smith | |
729 | * Mark Voorhies <mark.voorhies-at-ucsf.edu> |
|
729 | * Mark Voorhies <mark.voorhies-at-ucsf.edu> | |
730 | * Martin Spacek <git-at-mspacek.mm.st> |
|
730 | * Martin Spacek <git-at-mspacek.mm.st> | |
731 | * Michael Droettboom <mdroe-at-stsci.edu> |
|
731 | * Michael Droettboom <mdroe-at-stsci.edu> | |
732 | * MinRK <benjaminrk-at-gmail.com> |
|
732 | * MinRK <benjaminrk-at-gmail.com> | |
733 | * muzuiget <muzuiget-at-gmail.com> |
|
733 | * muzuiget <muzuiget-at-gmail.com> | |
734 | * Nick Tarleton <nick-at-quixey.com> |
|
734 | * Nick Tarleton <nick-at-quixey.com> | |
735 | * Nicolas Rougier <Nicolas.rougier-at-inria.fr> |
|
735 | * Nicolas Rougier <Nicolas.rougier-at-inria.fr> | |
736 | * Omar Andres Zapata Mesa <andresete.chaos-at-gmail.com> |
|
736 | * Omar Andres Zapata Mesa <andresete.chaos-at-gmail.com> | |
737 | * Paul Ivanov <pivanov314-at-gmail.com> |
|
737 | * Paul Ivanov <pivanov314-at-gmail.com> | |
738 | * Pauli Virtanen <pauli.virtanen-at-iki.fi> |
|
738 | * Pauli Virtanen <pauli.virtanen-at-iki.fi> | |
739 | * Prabhu Ramachandran |
|
739 | * Prabhu Ramachandran | |
740 | * Ramana <sramana9-at-gmail.com> |
|
740 | * Ramana <sramana9-at-gmail.com> | |
741 | * Robert Kern <robert.kern-at-gmail.com> |
|
741 | * Robert Kern <robert.kern-at-gmail.com> | |
742 | * Sathesh Chandra <satheshchandra88-at-gmail.com> |
|
742 | * Sathesh Chandra <satheshchandra88-at-gmail.com> | |
743 | * Satrajit Ghosh <satra-at-mit.edu> |
|
743 | * Satrajit Ghosh <satra-at-mit.edu> | |
744 | * Sebastian Busch |
|
744 | * Sebastian Busch | |
745 | * Skipper Seabold <jsseabold-at-gmail.com> |
|
745 | * Skipper Seabold <jsseabold-at-gmail.com> | |
746 | * Stefan van der Walt <bzr-at-mentat.za.net> |
|
746 | * Stefan van der Walt <bzr-at-mentat.za.net> | |
747 | * Stephan Peijnik <debian-at-sp.or.at> |
|
747 | * Stephan Peijnik <debian-at-sp.or.at> | |
748 | * Steven Bethard |
|
748 | * Steven Bethard | |
749 | * Thomas Kluyver <takowl-at-gmail.com> |
|
749 | * Thomas Kluyver <takowl-at-gmail.com> | |
750 | * Thomas Spura <tomspur-at-fedoraproject.org> |
|
750 | * Thomas Spura <tomspur-at-fedoraproject.org> | |
751 | * Tom Fetherston <tfetherston-at-aol.com> |
|
751 | * Tom Fetherston <tfetherston-at-aol.com> | |
752 | * Tom MacWright |
|
752 | * Tom MacWright | |
753 | * tzanko |
|
753 | * tzanko | |
754 | * vankayala sowjanya <hai.sowjanya-at-gmail.com> |
|
754 | * vankayala sowjanya <hai.sowjanya-at-gmail.com> | |
755 | * Vivian De Smedt <vds2212-at-VIVIAN> |
|
755 | * Vivian De Smedt <vds2212-at-VIVIAN> | |
756 | * Ville M. Vainio <vivainio-at-gmail.com> |
|
756 | * Ville M. Vainio <vivainio-at-gmail.com> | |
757 | * Vishal Vatsa <vishal.vatsa-at-gmail.com> |
|
757 | * Vishal Vatsa <vishal.vatsa-at-gmail.com> | |
758 | * Vishnu S G <sgvishnu777-at-gmail.com> |
|
758 | * Vishnu S G <sgvishnu777-at-gmail.com> | |
759 | * Walter Doerwald <walter-at-livinglogic.de> |
|
759 | * Walter Doerwald <walter-at-livinglogic.de> | |
760 |
|
760 | |||
761 | .. note:: |
|
761 | .. note:: | |
762 |
|
762 | |||
763 | This list was generated with the output of |
|
763 | This list was generated with the output of | |
764 | ``git log dev-0.11 HEAD --format='* %aN <%aE>' | sed 's/@/\-at\-/' | sed 's/<>//' | sort -u`` |
|
764 | ``git log dev-0.11 HEAD --format='* %aN <%aE>' | sed 's/@/\-at\-/' | sed 's/<>//' | sort -u`` | |
765 | after some cleanup. If you should be on this list, please add yourself. |
|
765 | after some cleanup. If you should be on this list, please add yourself. |
@@ -1,370 +1,370 b'' | |||||
1 | ============= |
|
1 | ============= | |
2 | 0.12 Series |
|
2 | 0.12 Series | |
3 | ============= |
|
3 | ============= | |
4 |
|
4 | |||
5 | Release 0.12.1 |
|
5 | Release 0.12.1 | |
6 | ============== |
|
6 | ============== | |
7 |
|
7 | |||
8 | IPython 0.12.1 is a bugfix release of 0.12, pulling only bugfixes and minor |
|
8 | IPython 0.12.1 is a bugfix release of 0.12, pulling only bugfixes and minor | |
9 | cleanup from 0.13, timed for the Ubuntu 12.04 LTS release. |
|
9 | cleanup from 0.13, timed for the Ubuntu 12.04 LTS release. | |
10 |
|
10 | |||
11 | See the :ref:`list of fixed issues <issues_list_012>` for specific backported issues. |
|
11 | See the :ref:`list of fixed issues <issues_list_012>` for specific backported issues. | |
12 |
|
12 | |||
13 |
|
13 | |||
14 | Release 0.12 |
|
14 | Release 0.12 | |
15 | ============ |
|
15 | ============ | |
16 |
|
16 | |||
17 | IPython 0.12 contains several major new features, as well as a large amount of |
|
17 | IPython 0.12 contains several major new features, as well as a large amount of | |
18 | bug and regression fixes. The 0.11 release brought with it a lot of new |
|
18 | bug and regression fixes. The 0.11 release brought with it a lot of new | |
19 | functionality and major refactorings of the codebase; by and large this has |
|
19 | functionality and major refactorings of the codebase; by and large this has | |
20 | proven to be a success as the number of contributions to the project has |
|
20 | proven to be a success as the number of contributions to the project has | |
21 | increased dramatically, proving that the code is now much more approachable. |
|
21 | increased dramatically, proving that the code is now much more approachable. | |
22 | But in the refactoring inevitably some bugs were introduced, and we have also |
|
22 | But in the refactoring inevitably some bugs were introduced, and we have also | |
23 | squashed many of those as well as recovered some functionality that had been |
|
23 | squashed many of those as well as recovered some functionality that had been | |
24 | temporarily disabled due to the API changes. |
|
24 | temporarily disabled due to the API changes. | |
25 |
|
25 | |||
26 | The following major new features appear in this version. |
|
26 | The following major new features appear in this version. | |
27 |
|
27 | |||
28 |
|
28 | |||
29 | An interactive browser-based Notebook with rich media support |
|
29 | An interactive browser-based Notebook with rich media support | |
30 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
30 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
31 |
|
31 | |||
32 | A powerful new interface puts IPython in your browser. You can start it with |
|
32 | A powerful new interface puts IPython in your browser. You can start it with | |
33 | the command ``ipython notebook``: |
|
33 | the command ``ipython notebook``: | |
34 |
|
34 | |||
35 | .. figure:: ../_static/notebook_specgram.png |
|
35 | .. figure:: ../_static/notebook_specgram.png | |
36 | :width: 400px |
|
36 | :width: 400px | |
37 | :alt: The IPython notebook with embedded text, code, math and figures. |
|
37 | :alt: The IPython notebook with embedded text, code, math and figures. | |
38 | :align: center |
|
38 | :align: center | |
39 | :target: ../_static/notebook_specgram.png |
|
39 | :target: ../_static/notebook_specgram.png | |
40 |
|
40 | |||
41 | The new IPython notebook showing text, mathematical expressions in LaTeX, |
|
41 | The new IPython notebook showing text, mathematical expressions in LaTeX, | |
42 | code, results and embedded figures created with Matplotlib. |
|
42 | code, results and embedded figures created with Matplotlib. | |
43 |
|
43 | |||
44 | This new interface maintains all the features of IPython you are used to, as it |
|
44 | This new interface maintains all the features of IPython you are used to, as it | |
45 | is a new client that communicates with the same IPython kernels used by the |
|
45 | is a new client that communicates with the same IPython kernels used by the | |
46 | terminal and Qt console. But the web notebook provides for a different |
|
46 | terminal and Qt console. But the web notebook provides for a different | |
47 | workflow where you can integrate, along with code execution, also text, |
|
47 | workflow where you can integrate, along with code execution, also text, | |
48 | mathematical expressions, graphics, video, and virtually any content that a |
|
48 | mathematical expressions, graphics, video, and virtually any content that a | |
49 | modern browser is capable of displaying. |
|
49 | modern browser is capable of displaying. | |
50 |
|
50 | |||
51 | You can save your work sessions as documents that retain all these elements and |
|
51 | You can save your work sessions as documents that retain all these elements and | |
52 | which can be version controlled, emailed to colleagues or saved as HTML or PDF |
|
52 | which can be version controlled, emailed to colleagues or saved as HTML or PDF | |
53 | files for printing or publishing statically on the web. The internal storage |
|
53 | files for printing or publishing statically on the web. The internal storage | |
54 | format is a JSON file that can be easily manipulated for manual exporting to |
|
54 | format is a JSON file that can be easily manipulated for manual exporting to | |
55 | other formats. |
|
55 | other formats. | |
56 |
|
56 | |||
57 | This Notebook is a major milestone for IPython, as for years we have tried to |
|
57 | This Notebook is a major milestone for IPython, as for years we have tried to | |
58 | build this kind of system. We were inspired originally by the excellent |
|
58 | build this kind of system. We were inspired originally by the excellent | |
59 | implementation in Mathematica, we made a number of attempts using older |
|
59 | implementation in Mathematica, we made a number of attempts using older | |
60 | technologies in earlier Summer of Code projects in 2005 (both students and |
|
60 | technologies in earlier Summer of Code projects in 2005 (both students and | |
61 | Robert Kern developed early prototypes), and in recent years we have seen the |
|
61 | Robert Kern developed early prototypes), and in recent years we have seen the | |
62 | excellent implementation offered by the `Sage <http://sagemath.org>` system. |
|
62 | excellent implementation offered by the `Sage <http://sagemath.org>` system. | |
63 | But we continued to work on something that would be consistent with the rest of |
|
63 | But we continued to work on something that would be consistent with the rest of | |
64 | IPython's design, and it is clear now that the effort was worth it: based on |
|
64 | IPython's design, and it is clear now that the effort was worth it: based on | |
65 | the ZeroMQ communications architecture introduced in version 0.11, the notebook |
|
65 | the ZeroMQ communications architecture introduced in version 0.11, the notebook | |
66 | can now retain 100% of the features of the real IPython. But it can also |
|
66 | can now retain 100% of the features of the real IPython. But it can also | |
67 | provide the rich media support and high quality Javascript libraries that were |
|
67 | provide the rich media support and high quality Javascript libraries that were | |
68 | not available in browsers even one or two years ago (such as high-quality |
|
68 | not available in browsers even one or two years ago (such as high-quality | |
69 | mathematical rendering or built-in video). |
|
69 | mathematical rendering or built-in video). | |
70 |
|
70 | |||
71 | The notebook has too many useful and important features to describe in these |
|
71 | The notebook has too many useful and important features to describe in these | |
72 | release notes; our documentation now contains a directory called |
|
72 | release notes; our documentation now contains a directory called | |
73 | ``examples/notebooks`` with several notebooks that illustrate various aspects |
|
73 | ``examples/notebooks`` with several notebooks that illustrate various aspects | |
74 | of the system. You should start by reading those named |
|
74 | of the system. You should start by reading those named | |
75 | ``00_notebook_tour.ipynb`` and ``01_notebook_introduction.ipynb`` first, and |
|
75 | ``00_notebook_tour.ipynb`` and ``01_notebook_introduction.ipynb`` first, and | |
76 | then can proceed to read the others in any order you want. |
|
76 | then can proceed to read the others in any order you want. | |
77 |
|
77 | |||
78 | To start the notebook server, go to a directory containing the notebooks you |
|
78 | To start the notebook server, go to a directory containing the notebooks you | |
79 | want to open (or where you want to create new ones) and type:: |
|
79 | want to open (or where you want to create new ones) and type:: | |
80 |
|
80 | |||
81 | ipython notebook |
|
81 | ipython notebook | |
82 |
|
82 | |||
83 | You can see all the relevant options with:: |
|
83 | You can see all the relevant options with:: | |
84 |
|
84 | |||
85 | ipython notebook --help |
|
85 | ipython notebook --help | |
86 | ipython notebook --help-all # even more |
|
86 | ipython notebook --help-all # even more | |
87 |
|
87 | |||
88 | and just like the Qt console, you can start the notebook server with pylab |
|
88 | and just like the Qt console, you can start the notebook server with pylab | |
89 | support by using:: |
|
89 | support by using:: | |
90 |
|
90 | |||
91 | ipython notebook --pylab |
|
91 | ipython notebook --pylab | |
92 |
|
92 | |||
93 | for floating matplotlib windows or:: |
|
93 | for floating matplotlib windows or:: | |
94 |
|
94 | |||
95 | ipython notebook --pylab inline |
|
95 | ipython notebook --pylab inline | |
96 |
|
96 | |||
97 | for plotting support with automatically inlined figures. Note that it is now |
|
97 | for plotting support with automatically inlined figures. Note that it is now | |
98 | possible also to activate pylab support at runtime via ``%pylab``, so you do |
|
98 | possible also to activate pylab support at runtime via ``%pylab``, so you do | |
99 | not need to make this decision when starting the server. |
|
99 | not need to make this decision when starting the server. | |
100 |
|
100 | |||
101 | See :ref:`the Notebook docs <htmlnotebook>` for technical details. |
|
101 | See :ref:`the Notebook docs <htmlnotebook>` for technical details. | |
102 |
|
102 | |||
103 | .. _two_process_console: |
|
103 | .. _two_process_console: | |
104 |
|
104 | |||
105 | Two-process terminal console |
|
105 | Two-process terminal console | |
106 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
106 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
107 |
|
107 | |||
108 | Based on the same architecture as the notebook and the Qt console, we also have |
|
108 | Based on the same architecture as the notebook and the Qt console, we also have | |
109 | now a terminal-based console that can connect to an external IPython kernel |
|
109 | now a terminal-based console that can connect to an external IPython kernel | |
110 | (the same kernels used by the Qt console or the notebook, in fact). While this |
|
110 | (the same kernels used by the Qt console or the notebook, in fact). While this | |
111 | client behaves almost identically to the usual IPython terminal application, |
|
111 | client behaves almost identically to the usual IPython terminal application, | |
112 | this capability can be very useful to attach an interactive console to an |
|
112 | this capability can be very useful to attach an interactive console to an | |
113 | existing kernel that was started externally. It lets you use the interactive |
|
113 | existing kernel that was started externally. It lets you use the interactive | |
114 | ``%debug`` facilities in a notebook, for example (the web browser can't |
|
114 | ``%debug`` facilities in a notebook, for example (the web browser can't | |
115 | interact directly with the debugger) or debug a third-party code where you may |
|
115 | interact directly with the debugger) or debug a third-party code where you may | |
116 | have embedded an IPython kernel. |
|
116 | have embedded an IPython kernel. | |
117 |
|
117 | |||
118 | This is also something that we have wanted for a long time, and which is a |
|
118 | This is also something that we have wanted for a long time, and which is a | |
119 | culmination (as a team effort) of the work started last year during the 2010 |
|
119 | culmination (as a team effort) of the work started last year during the 2010 | |
120 | Google Summer of Code project. |
|
120 | Google Summer of Code project. | |
121 |
|
121 | |||
122 | Tabbed QtConsole |
|
122 | Tabbed QtConsole | |
123 | ~~~~~~~~~~~~~~~~ |
|
123 | ~~~~~~~~~~~~~~~~ | |
124 |
|
124 | |||
125 | The QtConsole now supports starting multiple kernels in tabs, and has a |
|
125 | The QtConsole now supports starting multiple kernels in tabs, and has a | |
126 | menubar, so it looks and behaves more like a real application. Keyboard |
|
126 | menubar, so it looks and behaves more like a real application. Keyboard | |
127 | enthusiasts can disable the menubar with ctrl-shift-M (:ghpull:`887`). |
|
127 | enthusiasts can disable the menubar with ctrl-shift-M (:ghpull:`887`). | |
128 |
|
128 | |||
129 | .. figure:: ../_static/qtconsole_tabbed.png |
|
129 | .. figure:: ../_static/qtconsole_tabbed.png | |
130 | :width: 400px |
|
130 | :width: 400px | |
131 | :alt: Tabbed IPython Qt console with embedded plots and menus. |
|
131 | :alt: Tabbed IPython Qt console with embedded plots and menus. | |
132 | :align: center |
|
132 | :align: center | |
133 | :target: ../_static/qtconsole_tabbed.png |
|
133 | :target: ../_static/qtconsole_tabbed.png | |
134 |
|
134 | |||
135 | The improved Qt console for IPython, now with tabs to control multiple |
|
135 | The improved Qt console for IPython, now with tabs to control multiple | |
136 | kernels and full menu support. |
|
136 | kernels and full menu support. | |
137 |
|
137 | |||
138 |
|
138 | |||
139 | Full Python 3 compatibility |
|
139 | Full Python 3 compatibility | |
140 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
140 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
141 |
|
141 | |||
142 | IPython can now be installed from a single codebase on Python 2 and |
|
142 | IPython can now be installed from a single codebase on Python 2 and | |
143 | Python 3. The installation process for Python 3 automatically runs 2to3. The |
|
143 | Python 3. The installation process for Python 3 automatically runs 2to3. The | |
144 | same 'default' profile is now used for Python 2 and 3 (the previous version had |
|
144 | same 'default' profile is now used for Python 2 and 3 (the previous version had | |
145 | a separate 'python3' profile). |
|
145 | a separate 'python3' profile). | |
146 |
|
146 | |||
147 | Standalone Kernel |
|
147 | Standalone Kernel | |
148 | ~~~~~~~~~~~~~~~~~ |
|
148 | ~~~~~~~~~~~~~~~~~ | |
149 |
|
149 | |||
150 | The ``ipython kernel`` subcommand has been added, to allow starting a |
|
150 | The ``ipython kernel`` subcommand has been added, to allow starting a | |
151 | standalone kernel, that can be used with various frontends. You can then later |
|
151 | standalone kernel, that can be used with various frontends. You can then later | |
152 | connect a Qt console or a terminal console to this kernel by typing e.g.:: |
|
152 | connect a Qt console or a terminal console to this kernel by typing e.g.:: | |
153 |
|
153 | |||
154 | ipython qtconsole --existing |
|
154 | ipython qtconsole --existing | |
155 |
|
155 | |||
156 | if it's the only one running, or by passing explicitly the connection |
|
156 | if it's the only one running, or by passing explicitly the connection | |
157 | parameters (printed by the kernel at startup). |
|
157 | parameters (printed by the kernel at startup). | |
158 |
|
158 | |||
159 |
|
159 | |||
160 | PyPy support |
|
160 | PyPy support | |
161 | ~~~~~~~~~~~~ |
|
161 | ~~~~~~~~~~~~ | |
162 |
|
162 | |||
163 | The terminal interface to IPython now runs under `PyPy <http://pypy.org/>`_. |
|
163 | The terminal interface to IPython now runs under `PyPy <http://pypy.org/>`_. | |
164 | We will continue to monitor PyPy's progress, and hopefully before long at least |
|
164 | We will continue to monitor PyPy's progress, and hopefully before long at least | |
165 | we'll be able to also run the notebook. The Qt console may take longer, as Qt |
|
165 | we'll be able to also run the notebook. The Qt console may take longer, as Qt | |
166 | is a very complex set of bindings to a huge C++ library, and that is currently |
|
166 | is a very complex set of bindings to a huge C++ library, and that is currently | |
167 | the area where PyPy still lags most behind. But for everyday interactive use |
|
167 | the area where PyPy still lags most behind. But for everyday interactive use | |
168 | at the terminal, with this release and PyPy 1.7, things seem to work quite well |
|
168 | at the terminal, with this release and PyPy 1.7, things seem to work quite well | |
169 | from our admittedly limited testing. |
|
169 | from our admittedly limited testing. | |
170 |
|
170 | |||
171 |
|
171 | |||
172 | Other important new features |
|
172 | Other important new features | |
173 | ---------------------------- |
|
173 | ---------------------------- | |
174 |
|
174 | |||
175 | * **SSH Tunnels**: In 0.11, the :mod:`IPython.parallel` Client could tunnel its |
|
175 | * **SSH Tunnels**: In 0.11, the :mod:`IPython.parallel` Client could tunnel its | |
176 | connections to the Controller via ssh. Now, the QtConsole :ref:`supports |
|
176 | connections to the Controller via ssh. Now, the QtConsole :ref:`supports | |
177 | <ssh_tunnels>` ssh tunneling, as do parallel engines. |
|
177 | <ssh_tunnels>` ssh tunneling, as do parallel engines. | |
178 |
|
178 | |||
179 | * **relaxed command-line parsing**: 0.11 was released with overly-strict |
|
179 | * **relaxed command-line parsing**: 0.11 was released with overly-strict | |
180 | command-line parsing, preventing the ability to specify arguments with spaces, |
|
180 | command-line parsing, preventing the ability to specify arguments with spaces, | |
181 | e.g. ``ipython --pylab qt`` or ``ipython -c "print 'hi'"``. This has |
|
181 | e.g. ``ipython --pylab qt`` or ``ipython -c "print 'hi'"``. This has | |
182 | been fixed, by using argparse. The new parsing is a strict superset of 0.11, so |
|
182 | been fixed, by using argparse. The new parsing is a strict superset of 0.11, so | |
183 | any commands in 0.11 should still work in 0.12. |
|
183 | any commands in 0.11 should still work in 0.12. | |
184 |
|
184 | |||
185 | * **HistoryAccessor**: The :class:`~IPython.core.history.HistoryManager` class |
|
185 | * **HistoryAccessor**: The :class:`~IPython.core.history.HistoryManager` class | |
186 | for interacting with your IPython SQLite history database has been split, |
|
186 | for interacting with your IPython SQLite history database has been split, | |
187 | adding a parent :class:`~IPython.core.history.HistoryAccessor` class, so that |
|
187 | adding a parent :class:`~IPython.core.history.HistoryAccessor` class, so that | |
188 | users can write code to access and search their IPython history without being |
|
188 | users can write code to access and search their IPython history without being | |
189 | in an IPython session (:ghpull:`824`). |
|
189 | in an IPython session (:ghpull:`824`). | |
190 |
|
190 | |||
191 | * **kernel %gui and %pylab**: The ``%gui`` and ``%pylab`` magics have been |
|
191 | * **kernel %gui and %pylab**: The ``%gui`` and ``%pylab`` magics have been | |
192 | restored to the IPython kernel (e.g. in the qtconsole or notebook). This |
|
192 | restored to the IPython kernel (e.g. in the qtconsole or notebook). This | |
193 | allows activation of pylab-mode, or eventloop integration after starting the |
|
193 | allows activation of pylab-mode, or eventloop integration after starting the | |
194 | kernel, which was unavailable in 0.11. Unlike in the terminal, this can be |
|
194 | kernel, which was unavailable in 0.11. Unlike in the terminal, this can be | |
195 | set only once, and cannot be changed. |
|
195 | set only once, and cannot be changed. | |
196 |
|
196 | |||
197 | * **%config**: A new ``%config`` magic has been added, giving easy access to the |
|
197 | * **%config**: A new ``%config`` magic has been added, giving easy access to the | |
198 | IPython configuration system at runtime (:ghpull:`923`). |
|
198 | IPython configuration system at runtime (:ghpull:`923`). | |
199 |
|
199 | |||
200 | * **Multiline History**: Multiline readline history has been restored to the |
|
200 | * **Multiline History**: Multiline readline history has been restored to the | |
201 | Terminal frontend by default (:ghpull:`838`). |
|
201 | Terminal frontend by default (:ghpull:`838`). | |
202 |
|
202 | |||
203 | * **%store**: The ``%store`` magic from earlier versions has been updated and |
|
203 | * **%store**: The ``%store`` magic from earlier versions has been updated and | |
204 | re-enabled (:ref:`extensions_storemagic`; :ghpull:`1029`). To autorestore |
|
204 | re-enabled (:ref:`extensions_storemagic`; :ghpull:`1029`). To autorestore | |
205 | stored variables on startup, specify ``c.StoreMagic.autorestore = True`` in |
|
205 | stored variables on startup, specify ``c.StoreMagic.autorestore = True`` in | |
206 | :file:`ipython_config.py`. |
|
206 | :file:`ipython_config.py`. | |
207 |
|
207 | |||
208 |
|
208 | |||
209 | Major Bugs fixed |
|
209 | Major Bugs fixed | |
210 | ---------------- |
|
210 | ---------------- | |
211 |
|
211 | |||
212 | In this cycle, we have :ref:`closed over 500 issues <issues_list_012>`, but a |
|
212 | In this cycle, we have :ref:`closed over 500 issues <issues_list_012>`, but a | |
213 | few major ones merit special mention: |
|
213 | few major ones merit special mention: | |
214 |
|
214 | |||
215 | * Simple configuration errors should no longer crash IPython. In 0.11, errors |
|
215 | * Simple configuration errors should no longer crash IPython. In 0.11, errors | |
216 | in config files, as well as invalid trait values, could crash IPython. Now, |
|
216 | in config files, as well as invalid trait values, could crash IPython. Now, | |
217 | such errors are reported, and help is displayed. |
|
217 | such errors are reported, and help is displayed. | |
218 |
|
218 | |||
219 | * Certain SyntaxErrors no longer crash IPython (e.g. just typing keywords, such |
|
219 | * Certain SyntaxErrors no longer crash IPython (e.g. just typing keywords, such | |
220 | as ``return``, ``break``, etc.). See :ghissue:`704`. |
|
220 | as ``return``, ``break``, etc.). See :ghissue:`704`. | |
221 |
|
221 | |||
222 | * IPython path utils, such as :func:`~IPython.utils.path.get_ipython_dir` now |
|
222 | * IPython path utils, such as :func:`~IPython.utils.path.get_ipython_dir` now | |
223 | check for write permissions, so IPython should function on systems where the |
|
223 | check for write permissions, so IPython should function on systems where the | |
224 | default path resolution might point to a read-only location, such as |
|
224 | default path resolution might point to a read-only location, such as | |
225 | ``HOMESHARE`` on Windows (:ghissue:`669`). |
|
225 | ``HOMESHARE`` on Windows (:ghissue:`669`). | |
226 |
|
226 | |||
227 | * :func:`raw_input` now works in the kernel when multiple frontends are in |
|
227 | * :func:`raw_input` now works in the kernel when multiple frontends are in | |
228 | use. The request will be sent to the frontend that made the request, and an |
|
228 | use. The request will be sent to the frontend that made the request, and an | |
229 | exception is raised if that frontend does not support stdin requests |
|
229 | exception is raised if that frontend does not support stdin requests | |
230 | (e.g. the notebook) (:ghissue:`673`). |
|
230 | (e.g. the notebook) (:ghissue:`673`). | |
231 |
|
231 | |||
232 | * :mod:`zmq` version detection no longer uses simple lexicographical comparison |
|
232 | * :mod:`zmq` version detection no longer uses simple lexicographical comparison | |
233 | to check minimum version, which prevents 0.11 from working with pyzmq-2.1.10 |
|
233 | to check minimum version, which prevents 0.11 from working with pyzmq-2.1.10 | |
234 | (:ghpull:`758`). |
|
234 | (:ghpull:`758`). | |
235 |
|
235 | |||
236 | * A bug in PySide < 1.0.7 caused crashes on OSX when tooltips were shown |
|
236 | * A bug in PySide < 1.0.7 caused crashes on OSX when tooltips were shown | |
237 | (:ghissue:`711`). these tooltips are now disabled on old PySide |
|
237 | (:ghissue:`711`). these tooltips are now disabled on old PySide | |
238 | (:ghpull:`963`). |
|
238 | (:ghpull:`963`). | |
239 |
|
239 | |||
240 | * IPython no longer crashes when started on recent versions of Python 3 in |
|
240 | * IPython no longer crashes when started on recent versions of Python 3 in | |
241 | Windows (:ghissue:`737`). |
|
241 | Windows (:ghissue:`737`). | |
242 |
|
242 | |||
243 | * Instances of classes defined interactively can now be pickled (:ghissue:`29`; |
|
243 | * Instances of classes defined interactively can now be pickled (:ghissue:`29`; | |
244 | :ghpull:`648`). Note that pickling saves a reference to the class definition, |
|
244 | :ghpull:`648`). Note that pickling saves a reference to the class definition, | |
245 | so unpickling the instances will only work where the class has been defined. |
|
245 | so unpickling the instances will only work where the class has been defined. | |
246 |
|
246 | |||
247 |
|
247 | |||
248 | Backwards incompatible changes |
|
248 | Backwards incompatible changes | |
249 | ------------------------------ |
|
249 | ------------------------------ | |
250 |
|
250 | |||
251 | * IPython connection information is no longer specified via ip/port directly, |
|
251 | * IPython connection information is no longer specified via ip/port directly, | |
252 | rather via json connection files. These files are stored in the security |
|
252 | rather via json connection files. These files are stored in the security | |
253 | directory, and enable us to turn on HMAC message authentication by default, |
|
253 | directory, and enable us to turn on HMAC message authentication by default, | |
254 | significantly improving the security of kernels. Various utility functions |
|
254 | significantly improving the security of kernels. Various utility functions | |
255 | have been added to :mod:`IPython.lib.kernel`, for easier connecting to existing |
|
255 | have been added to :mod:`IPython.lib.kernel`, for easier connecting to existing | |
256 | kernels. |
|
256 | kernels. | |
257 |
|
257 | |||
258 | * :class:`~IPython.zmq.kernelmanager.KernelManager` now has one ip, and several |
|
258 | * :class:`~IPython.zmq.kernelmanager.KernelManager` now has one ip, and several | |
259 | port traits, rather than several ip/port pair ``_addr`` traits. This better |
|
259 | port traits, rather than several ip/port pair ``_addr`` traits. This better | |
260 | matches the rest of the code, where the ip cannot not be set separately for |
|
260 | matches the rest of the code, where the ip cannot not be set separately for | |
261 | each channel. |
|
261 | each channel. | |
262 |
|
262 | |||
263 | * Custom prompts are now configured using a new class, |
|
263 | * Custom prompts are now configured using a new class, | |
264 | :class:`~IPython.core.prompts.PromptManager`, which has traits for |
|
264 | :class:`~IPython.core.prompts.PromptManager`, which has traits for | |
265 | :attr:`in_template`, :attr:`in2_template` (the ``...:`` continuation prompt), |
|
265 | :attr:`in_template`, :attr:`in2_template` (the ``...:`` continuation prompt), | |
266 | :attr:`out_template` and :attr:`rewrite_template`. This uses Python's string |
|
266 | :attr:`out_template` and :attr:`rewrite_template`. This uses Python's string | |
267 | formatting system, so you can use ``{time}`` and ``{cwd}``, although we have |
|
267 | formatting system, so you can use ``{time}`` and ``{cwd}``, although we have | |
268 | preserved the abbreviations from previous versions, e.g. ``\#`` (prompt number) |
|
268 | preserved the abbreviations from previous versions, e.g. ``\#`` (prompt number) | |
269 | and ``\w`` (working directory). For the list of available fields, refer to the |
|
269 | and ``\w`` (working directory). For the list of available fields, refer to the | |
270 | source of :file:`IPython/core/prompts.py`. |
|
270 | source of :file:`IPython/core/prompts.py`. | |
271 |
|
271 | |||
272 | * The class inheritance of the Launchers in |
|
272 | * The class inheritance of the Launchers in | |
273 | :mod:`IPython.parallel.apps.launcher` used by ipcluster has changed, so that |
|
273 | :mod:`IPython.parallel.apps.launcher` used by ipcluster has changed, so that | |
274 | trait names are more consistent across batch systems. This may require a few |
|
274 | trait names are more consistent across batch systems. This may require a few | |
275 | renames in your config files, if you customized the command-line args for |
|
275 | renames in your config files, if you customized the command-line args for | |
276 | launching controllers and engines. The configurable names have also been |
|
276 | launching controllers and engines. The configurable names have also been | |
277 | changed to be clearer that they point to class names, and can now be |
|
277 | changed to be clearer that they point to class names, and can now be | |
278 | specified by name only, rather than requiring the full import path of each |
|
278 | specified by name only, rather than requiring the full import path of each | |
279 | class, e.g.:: |
|
279 | class, e.g.:: | |
280 |
|
280 | |||
281 | IPClusterEngines.engine_launcher = 'IPython.parallel.apps.launcher.MPIExecEngineSetLauncher' |
|
281 | IPClusterEngines.engine_launcher = 'IPython.parallel.apps.launcher.MPIExecEngineSetLauncher' | |
282 | IPClusterStart.controller_launcher = 'IPython.parallel.apps.launcher.SSHControllerLauncher' |
|
282 | IPClusterStart.controller_launcher = 'IPython.parallel.apps.launcher.SSHControllerLauncher' | |
283 |
|
283 | |||
284 | would now be specified as:: |
|
284 | would now be specified as:: | |
285 |
|
285 | |||
286 | IPClusterEngines.engine_launcher_class = 'MPI' |
|
286 | IPClusterEngines.engine_launcher_class = 'MPI' | |
287 | IPClusterStart.controller_launcher_class = 'SSH' |
|
287 | IPClusterStart.controller_launcher_class = 'SSH' | |
288 |
|
288 | |||
289 | The full path will still work, and is necessary for using custom launchers |
|
289 | The full path will still work, and is necessary for using custom launchers | |
290 | not in IPython's launcher module. |
|
290 | not in IPython's launcher module. | |
291 |
|
291 | |||
292 | Further, MPIExec launcher names are now prefixed with just MPI, to better match |
|
292 | Further, MPIExec launcher names are now prefixed with just MPI, to better match | |
293 | other batch launchers, and be generally more intuitive. The MPIExec names are |
|
293 | other batch launchers, and be generally more intuitive. The MPIExec names are | |
294 | deprecated, but continue to work. |
|
294 | deprecated, but continue to work. | |
295 |
|
295 | |||
296 | * For embedding a shell, note that the parameters ``user_global_ns`` and |
|
296 | * For embedding a shell, note that the parameters ``user_global_ns`` and | |
297 | ``global_ns`` have been deprectated in favour of ``user_module`` and |
|
297 | ``global_ns`` have been deprectated in favour of ``user_module`` and | |
298 | ``module`` respsectively. The new parameters expect a module-like object, |
|
298 | ``module`` respsectively. The new parameters expect a module-like object, | |
299 | rather than a namespace dict. The old parameters remain for backwards |
|
299 | rather than a namespace dict. The old parameters remain for backwards | |
300 | compatibility, although ``user_global_ns`` is now ignored. The ``user_ns`` |
|
300 | compatibility, although ``user_global_ns`` is now ignored. The ``user_ns`` | |
301 | parameter works the same way as before, and calling |
|
301 | parameter works the same way as before, and calling | |
302 | :func:`~IPython.frontend.terminal.embed.embed` with no arguments still works |
|
302 | :func:`~IPython.frontend.terminal.embed.embed` with no arguments still works | |
303 | as before. |
|
303 | as before. | |
304 |
|
304 | |||
305 |
|
305 | |||
306 | Development summary and credits |
|
306 | Development summary and credits | |
307 | ------------------------------- |
|
307 | ------------------------------- | |
308 |
|
308 | |||
309 | The previous version (IPython 0.11) was released on July 31 2011, so this |
|
309 | The previous version (IPython 0.11) was released on July 31 2011, so this | |
310 | release cycle was roughly 4 1/2 months long, we closed a total of 515 issues, |
|
310 | release cycle was roughly 4 1/2 months long, we closed a total of 515 issues, | |
311 | 257 pull requests and 258 regular issues (a :ref:`detailed list |
|
311 | 257 pull requests and 258 regular issues (a :ref:`detailed list | |
312 |
<issues_list_012>` |
|
312 | <issues_list_012>` is available). | |
313 |
|
313 | |||
314 | Many users and developers contributed code, features, bug reports and ideas to |
|
314 | Many users and developers contributed code, features, bug reports and ideas to | |
315 | this release. Please do not hesitate in contacting us if we've failed to |
|
315 | this release. Please do not hesitate in contacting us if we've failed to | |
316 | acknowledge your contribution here. In particular, for this release we have |
|
316 | acknowledge your contribution here. In particular, for this release we have | |
317 | had commits from the following 45 contributors, a mix of new and regular names |
|
317 | had commits from the following 45 contributors, a mix of new and regular names | |
318 | (in alphabetical order by first name): |
|
318 | (in alphabetical order by first name): | |
319 |
|
319 | |||
320 | * Alcides <alcides-at-do-not-span-me.com> |
|
320 | * Alcides <alcides-at-do-not-span-me.com> | |
321 | * Ben Edwards <bedwards-at-cs.unm.edu> |
|
321 | * Ben Edwards <bedwards-at-cs.unm.edu> | |
322 | * Benjamin Ragan-Kelley <benjaminrk-at-gmail.com> |
|
322 | * Benjamin Ragan-Kelley <benjaminrk-at-gmail.com> | |
323 | * Benjamin Thyreau <benjamin.thyreau-at-gmail.com> |
|
323 | * Benjamin Thyreau <benjamin.thyreau-at-gmail.com> | |
324 | * Bernardo B. Marques <bernardo.fire-at-gmail.com> |
|
324 | * Bernardo B. Marques <bernardo.fire-at-gmail.com> | |
325 | * Bernard Paulus <bprecyclebin-at-gmail.com> |
|
325 | * Bernard Paulus <bprecyclebin-at-gmail.com> | |
326 | * Bradley M. Froehle <brad.froehle-at-gmail.com> |
|
326 | * Bradley M. Froehle <brad.froehle-at-gmail.com> | |
327 | * Brian E. Granger <ellisonbg-at-gmail.com> |
|
327 | * Brian E. Granger <ellisonbg-at-gmail.com> | |
328 | * Christian Boos <cboos-at-bct-technology.com> |
|
328 | * Christian Boos <cboos-at-bct-technology.com> | |
329 | * Daniel Velkov <danielv-at-mylife.com> |
|
329 | * Daniel Velkov <danielv-at-mylife.com> | |
330 | * Erik Tollerud <erik.tollerud-at-gmail.com> |
|
330 | * Erik Tollerud <erik.tollerud-at-gmail.com> | |
331 | * Evan Patterson <epatters-at-enthought.com> |
|
331 | * Evan Patterson <epatters-at-enthought.com> | |
332 | * Felix Werner <Felix.Werner-at-kit.edu> |
|
332 | * Felix Werner <Felix.Werner-at-kit.edu> | |
333 | * Fernando Perez <Fernando.Perez-at-berkeley.edu> |
|
333 | * Fernando Perez <Fernando.Perez-at-berkeley.edu> | |
334 | * Gabriel <g2p.code-at-gmail.com> |
|
334 | * Gabriel <g2p.code-at-gmail.com> | |
335 | * Grahame Bowland <grahame-at-angrygoats.net> |
|
335 | * Grahame Bowland <grahame-at-angrygoats.net> | |
336 | * Hannes Schulz <schulz-at-ais.uni-bonn.de> |
|
336 | * Hannes Schulz <schulz-at-ais.uni-bonn.de> | |
337 | * Jens Hedegaard Nielsen <jenshnielsen-at-gmail.com> |
|
337 | * Jens Hedegaard Nielsen <jenshnielsen-at-gmail.com> | |
338 | * Jonathan March <jmarch-at-enthought.com> |
|
338 | * Jonathan March <jmarch-at-enthought.com> | |
339 | * JΓΆrgen Stenarson <jorgen.stenarson-at-bostream.nu> |
|
339 | * JΓΆrgen Stenarson <jorgen.stenarson-at-bostream.nu> | |
340 | * Julian Taylor <jtaylor.debian-at-googlemail.com> |
|
340 | * Julian Taylor <jtaylor.debian-at-googlemail.com> | |
341 | * Kefu Chai <tchaikov-at-gmail.com> |
|
341 | * Kefu Chai <tchaikov-at-gmail.com> | |
342 | * macgyver <neil.rabinowitz-at-merton.ox.ac.uk> |
|
342 | * macgyver <neil.rabinowitz-at-merton.ox.ac.uk> | |
343 | * Matt Cottingham <matt.cottingham-at-gmail.com> |
|
343 | * Matt Cottingham <matt.cottingham-at-gmail.com> | |
344 | * Matthew Brett <matthew.brett-at-gmail.com> |
|
344 | * Matthew Brett <matthew.brett-at-gmail.com> | |
345 | * Matthias BUSSONNIER <bussonniermatthias-at-gmail.com> |
|
345 | * Matthias BUSSONNIER <bussonniermatthias-at-gmail.com> | |
346 | * Michael Droettboom <mdboom-at-gmail.com> |
|
346 | * Michael Droettboom <mdboom-at-gmail.com> | |
347 | * Nicolas Rougier <Nicolas.Rougier-at-inria.fr> |
|
347 | * Nicolas Rougier <Nicolas.Rougier-at-inria.fr> | |
348 | * Olivier Verdier <olivier.verdier-at-gmail.com> |
|
348 | * Olivier Verdier <olivier.verdier-at-gmail.com> | |
349 | * Omar Andres Zapata Mesa <andresete.chaos-at-gmail.com> |
|
349 | * Omar Andres Zapata Mesa <andresete.chaos-at-gmail.com> | |
350 | * Pablo Winant <pablo.winant-at-gmail.com> |
|
350 | * Pablo Winant <pablo.winant-at-gmail.com> | |
351 | * Paul Ivanov <pivanov314-at-gmail.com> |
|
351 | * Paul Ivanov <pivanov314-at-gmail.com> | |
352 | * Pauli Virtanen <pav-at-iki.fi> |
|
352 | * Pauli Virtanen <pav-at-iki.fi> | |
353 | * Pete Aykroyd <aykroyd-at-gmail.com> |
|
353 | * Pete Aykroyd <aykroyd-at-gmail.com> | |
354 | * Prabhu Ramachandran <prabhu-at-enthought.com> |
|
354 | * Prabhu Ramachandran <prabhu-at-enthought.com> | |
355 | * Puneeth Chaganti <punchagan-at-gmail.com> |
|
355 | * Puneeth Chaganti <punchagan-at-gmail.com> | |
356 | * Robert Kern <robert.kern-at-gmail.com> |
|
356 | * Robert Kern <robert.kern-at-gmail.com> | |
357 | * Satrajit Ghosh <satra-at-mit.edu> |
|
357 | * Satrajit Ghosh <satra-at-mit.edu> | |
358 | * Stefan van der Walt <stefan-at-sun.ac.za> |
|
358 | * Stefan van der Walt <stefan-at-sun.ac.za> | |
359 | * Szabolcs HorvΓ‘t <szhorvat-at-gmail.com> |
|
359 | * Szabolcs HorvΓ‘t <szhorvat-at-gmail.com> | |
360 | * Thomas Kluyver <takowl-at-gmail.com> |
|
360 | * Thomas Kluyver <takowl-at-gmail.com> | |
361 | * Thomas Spura <thomas.spura-at-gmail.com> |
|
361 | * Thomas Spura <thomas.spura-at-gmail.com> | |
362 | * Timo Paulssen <timonator-at-perpetuum-immobile.de> |
|
362 | * Timo Paulssen <timonator-at-perpetuum-immobile.de> | |
363 | * Valentin Haenel <valentin.haenel-at-gmx.de> |
|
363 | * Valentin Haenel <valentin.haenel-at-gmx.de> | |
364 | * Yaroslav Halchenko <debian-at-onerussian.com> |
|
364 | * Yaroslav Halchenko <debian-at-onerussian.com> | |
365 |
|
365 | |||
366 | .. note:: |
|
366 | .. note:: | |
367 |
|
367 | |||
368 | This list was generated with the output of |
|
368 | This list was generated with the output of | |
369 | ``git log rel-0.11..HEAD --format='* %aN <%aE>' | sed 's/@/\-at\-/' | sed 's/<>//' | sort -u`` |
|
369 | ``git log rel-0.11..HEAD --format='* %aN <%aE>' | sed 's/@/\-at\-/' | sed 's/<>//' | sort -u`` | |
370 | after some cleanup. If you should be on this list, please add yourself. |
|
370 | after some cleanup. If you should be on this list, please add yourself. |
@@ -1,414 +1,411 b'' | |||||
1 | """Attempt to generate templates for module reference with Sphinx |
|
1 | """Attempt to generate templates for module reference with Sphinx | |
2 |
|
2 | |||
3 | XXX - we exclude extension modules |
|
3 | XXX - we exclude extension modules | |
4 |
|
4 | |||
5 | To include extension modules, first identify them as valid in the |
|
5 | To include extension modules, first identify them as valid in the | |
6 | ``_uri2path`` method, then handle them in the ``_parse_module`` script. |
|
6 | ``_uri2path`` method, then handle them in the ``_parse_module`` script. | |
7 |
|
7 | |||
8 | We get functions and classes by parsing the text of .py files. |
|
8 | We get functions and classes by parsing the text of .py files. | |
9 | Alternatively we could import the modules for discovery, and we'd have |
|
9 | Alternatively we could import the modules for discovery, and we'd have | |
10 | to do that for extension modules. This would involve changing the |
|
10 | to do that for extension modules. This would involve changing the | |
11 | ``_parse_module`` method to work via import and introspection, and |
|
11 | ``_parse_module`` method to work via import and introspection, and | |
12 | might involve changing ``discover_modules`` (which determines which |
|
12 | might involve changing ``discover_modules`` (which determines which | |
13 | files are modules, and therefore which module URIs will be passed to |
|
13 | files are modules, and therefore which module URIs will be passed to | |
14 | ``_parse_module``). |
|
14 | ``_parse_module``). | |
15 |
|
15 | |||
16 | NOTE: this is a modified version of a script originally shipped with the |
|
16 | NOTE: this is a modified version of a script originally shipped with the | |
17 | PyMVPA project, which we've adapted for NIPY use. PyMVPA is an MIT-licensed |
|
17 | PyMVPA project, which we've adapted for NIPY use. PyMVPA is an MIT-licensed | |
18 | project.""" |
|
18 | project.""" | |
19 |
|
19 | |||
20 | # Stdlib imports |
|
20 | # Stdlib imports | |
21 | import ast |
|
21 | import ast | |
22 | import os |
|
22 | import os | |
23 | import re |
|
23 | import re | |
24 |
|
24 | |||
25 | class Obj(object): |
|
25 | class Obj(object): | |
26 | '''Namespace to hold arbitrary information.''' |
|
26 | '''Namespace to hold arbitrary information.''' | |
27 | def __init__(self, **kwargs): |
|
27 | def __init__(self, **kwargs): | |
28 | for k, v in kwargs.items(): |
|
28 | for k, v in kwargs.items(): | |
29 | setattr(self, k, v) |
|
29 | setattr(self, k, v) | |
30 |
|
30 | |||
31 | class FuncClsScanner(ast.NodeVisitor): |
|
31 | class FuncClsScanner(ast.NodeVisitor): | |
32 | """Scan a module for top-level functions and classes. |
|
32 | """Scan a module for top-level functions and classes. | |
33 |
|
33 | |||
34 | Skips objects with an @undoc decorator, or a name starting with '_'. |
|
34 | Skips objects with an @undoc decorator, or a name starting with '_'. | |
35 | """ |
|
35 | """ | |
36 | def __init__(self): |
|
36 | def __init__(self): | |
37 | ast.NodeVisitor.__init__(self) |
|
37 | ast.NodeVisitor.__init__(self) | |
38 | self.classes = [] |
|
38 | self.classes = [] | |
39 | self.classes_seen = set() |
|
39 | self.classes_seen = set() | |
40 | self.functions = [] |
|
40 | self.functions = [] | |
41 |
|
41 | |||
42 | @staticmethod |
|
42 | @staticmethod | |
43 | def has_undoc_decorator(node): |
|
43 | def has_undoc_decorator(node): | |
44 | return any(isinstance(d, ast.Name) and d.id == 'undoc' \ |
|
44 | return any(isinstance(d, ast.Name) and d.id == 'undoc' \ | |
45 | for d in node.decorator_list) |
|
45 | for d in node.decorator_list) | |
46 |
|
46 | |||
47 | def visit_FunctionDef(self, node): |
|
47 | def visit_FunctionDef(self, node): | |
48 | if not (node.name.startswith('_') or self.has_undoc_decorator(node)) \ |
|
48 | if not (node.name.startswith('_') or self.has_undoc_decorator(node)) \ | |
49 | and node.name not in self.functions: |
|
49 | and node.name not in self.functions: | |
50 | self.functions.append(node.name) |
|
50 | self.functions.append(node.name) | |
51 |
|
51 | |||
52 | def visit_ClassDef(self, node): |
|
52 | def visit_ClassDef(self, node): | |
53 | if not (node.name.startswith('_') or self.has_undoc_decorator(node)) \ |
|
53 | if not (node.name.startswith('_') or self.has_undoc_decorator(node)) \ | |
54 | and node.name not in self.classes_seen: |
|
54 | and node.name not in self.classes_seen: | |
55 | cls = Obj(name=node.name) |
|
55 | cls = Obj(name=node.name) | |
56 | cls.has_init = any(isinstance(n, ast.FunctionDef) and \ |
|
56 | cls.has_init = any(isinstance(n, ast.FunctionDef) and \ | |
57 | n.name=='__init__' for n in node.body) |
|
57 | n.name=='__init__' for n in node.body) | |
58 | self.classes.append(cls) |
|
58 | self.classes.append(cls) | |
59 | self.classes_seen.add(node.name) |
|
59 | self.classes_seen.add(node.name) | |
60 |
|
60 | |||
61 | def scan(self, mod): |
|
61 | def scan(self, mod): | |
62 | self.visit(mod) |
|
62 | self.visit(mod) | |
63 | return self.functions, self.classes |
|
63 | return self.functions, self.classes | |
64 |
|
64 | |||
65 | # Functions and classes |
|
65 | # Functions and classes | |
66 | class ApiDocWriter(object): |
|
66 | class ApiDocWriter(object): | |
67 | ''' Class for automatic detection and parsing of API docs |
|
67 | ''' Class for automatic detection and parsing of API docs | |
68 | to Sphinx-parsable reST format''' |
|
68 | to Sphinx-parsable reST format''' | |
69 |
|
69 | |||
70 | # only separating first two levels |
|
70 | # only separating first two levels | |
71 | rst_section_levels = ['*', '=', '-', '~', '^'] |
|
71 | rst_section_levels = ['*', '=', '-', '~', '^'] | |
72 |
|
72 | |||
73 | def __init__(self, |
|
73 | def __init__(self, | |
74 | package_name, |
|
74 | package_name, | |
75 | rst_extension='.rst', |
|
75 | rst_extension='.rst', | |
76 | package_skip_patterns=None, |
|
76 | package_skip_patterns=None, | |
77 | module_skip_patterns=None, |
|
77 | module_skip_patterns=None, | |
78 | ): |
|
78 | ): | |
79 | ''' Initialize package for parsing |
|
79 | ''' Initialize package for parsing | |
80 |
|
80 | |||
81 | Parameters |
|
81 | Parameters | |
82 | ---------- |
|
82 | ---------- | |
83 | package_name : string |
|
83 | package_name : string | |
84 | Name of the top-level package. *package_name* must be the |
|
84 | Name of the top-level package. *package_name* must be the | |
85 | name of an importable package |
|
85 | name of an importable package | |
86 | rst_extension : string, optional |
|
86 | rst_extension : string, optional | |
87 | Extension for reST files, default '.rst' |
|
87 | Extension for reST files, default '.rst' | |
88 | package_skip_patterns : None or sequence of {strings, regexps} |
|
88 | package_skip_patterns : None or sequence of {strings, regexps} | |
89 | Sequence of strings giving URIs of packages to be excluded |
|
89 | Sequence of strings giving URIs of packages to be excluded | |
90 | Operates on the package path, starting at (including) the |
|
90 | Operates on the package path, starting at (including) the | |
91 | first dot in the package path, after *package_name* - so, |
|
91 | first dot in the package path, after *package_name* - so, | |
92 | if *package_name* is ``sphinx``, then ``sphinx.util`` will |
|
92 | if *package_name* is ``sphinx``, then ``sphinx.util`` will | |
93 | result in ``.util`` being passed for earching by these |
|
93 | result in ``.util`` being passed for earching by these | |
94 | regexps. If is None, gives default. Default is: |
|
94 | regexps. If is None, gives default. Default is: | |
95 | ['\.tests$'] |
|
95 | ['\.tests$'] | |
96 | module_skip_patterns : None or sequence |
|
96 | module_skip_patterns : None or sequence | |
97 | Sequence of strings giving URIs of modules to be excluded |
|
97 | Sequence of strings giving URIs of modules to be excluded | |
98 | Operates on the module name including preceding URI path, |
|
98 | Operates on the module name including preceding URI path, | |
99 | back to the first dot after *package_name*. For example |
|
99 | back to the first dot after *package_name*. For example | |
100 | ``sphinx.util.console`` results in the string to search of |
|
100 | ``sphinx.util.console`` results in the string to search of | |
101 | ``.util.console`` |
|
101 | ``.util.console`` | |
102 | If is None, gives default. Default is: |
|
102 | If is None, gives default. Default is: | |
103 | ['\.setup$', '\._'] |
|
103 | ['\.setup$', '\._'] | |
104 | ''' |
|
104 | ''' | |
105 | if package_skip_patterns is None: |
|
105 | if package_skip_patterns is None: | |
106 | package_skip_patterns = ['\\.tests$'] |
|
106 | package_skip_patterns = ['\\.tests$'] | |
107 | if module_skip_patterns is None: |
|
107 | if module_skip_patterns is None: | |
108 | module_skip_patterns = ['\\.setup$', '\\._'] |
|
108 | module_skip_patterns = ['\\.setup$', '\\._'] | |
109 | self.package_name = package_name |
|
109 | self.package_name = package_name | |
110 | self.rst_extension = rst_extension |
|
110 | self.rst_extension = rst_extension | |
111 | self.package_skip_patterns = package_skip_patterns |
|
111 | self.package_skip_patterns = package_skip_patterns | |
112 | self.module_skip_patterns = module_skip_patterns |
|
112 | self.module_skip_patterns = module_skip_patterns | |
113 |
|
113 | |||
114 | def get_package_name(self): |
|
114 | def get_package_name(self): | |
115 | return self._package_name |
|
115 | return self._package_name | |
116 |
|
116 | |||
117 | def set_package_name(self, package_name): |
|
117 | def set_package_name(self, package_name): | |
118 | ''' Set package_name |
|
118 | ''' Set package_name | |
119 |
|
119 | |||
120 | >>> docwriter = ApiDocWriter('sphinx') |
|
120 | >>> docwriter = ApiDocWriter('sphinx') | |
121 | >>> import sphinx |
|
121 | >>> import sphinx | |
122 | >>> docwriter.root_path == sphinx.__path__[0] |
|
122 | >>> docwriter.root_path == sphinx.__path__[0] | |
123 | True |
|
123 | True | |
124 | >>> docwriter.package_name = 'docutils' |
|
124 | >>> docwriter.package_name = 'docutils' | |
125 | >>> import docutils |
|
125 | >>> import docutils | |
126 | >>> docwriter.root_path == docutils.__path__[0] |
|
126 | >>> docwriter.root_path == docutils.__path__[0] | |
127 | True |
|
127 | True | |
128 | ''' |
|
128 | ''' | |
129 | # It's also possible to imagine caching the module parsing here |
|
129 | # It's also possible to imagine caching the module parsing here | |
130 | self._package_name = package_name |
|
130 | self._package_name = package_name | |
131 | self.root_module = __import__(package_name) |
|
131 | self.root_module = __import__(package_name) | |
132 | self.root_path = self.root_module.__path__[0] |
|
132 | self.root_path = self.root_module.__path__[0] | |
133 | self.written_modules = None |
|
133 | self.written_modules = None | |
134 |
|
134 | |||
135 | package_name = property(get_package_name, set_package_name, None, |
|
135 | package_name = property(get_package_name, set_package_name, None, | |
136 | 'get/set package_name') |
|
136 | 'get/set package_name') | |
137 |
|
137 | |||
138 | def _uri2path(self, uri): |
|
138 | def _uri2path(self, uri): | |
139 | ''' Convert uri to absolute filepath |
|
139 | ''' Convert uri to absolute filepath | |
140 |
|
140 | |||
141 | Parameters |
|
141 | Parameters | |
142 | ---------- |
|
142 | ---------- | |
143 | uri : string |
|
143 | uri : string | |
144 | URI of python module to return path for |
|
144 | URI of python module to return path for | |
145 |
|
145 | |||
146 | Returns |
|
146 | Returns | |
147 | ------- |
|
147 | ------- | |
148 | path : None or string |
|
148 | path : None or string | |
149 | Returns None if there is no valid path for this URI |
|
149 | Returns None if there is no valid path for this URI | |
150 | Otherwise returns absolute file system path for URI |
|
150 | Otherwise returns absolute file system path for URI | |
151 |
|
151 | |||
152 | Examples |
|
152 | Examples | |
153 | -------- |
|
153 | -------- | |
154 | >>> docwriter = ApiDocWriter('sphinx') |
|
154 | >>> docwriter = ApiDocWriter('sphinx') | |
155 | >>> import sphinx |
|
155 | >>> import sphinx | |
156 | >>> modpath = sphinx.__path__[0] |
|
156 | >>> modpath = sphinx.__path__[0] | |
157 | >>> res = docwriter._uri2path('sphinx.builder') |
|
157 | >>> res = docwriter._uri2path('sphinx.builder') | |
158 | >>> res == os.path.join(modpath, 'builder.py') |
|
158 | >>> res == os.path.join(modpath, 'builder.py') | |
159 | True |
|
159 | True | |
160 | >>> res = docwriter._uri2path('sphinx') |
|
160 | >>> res = docwriter._uri2path('sphinx') | |
161 | >>> res == os.path.join(modpath, '__init__.py') |
|
161 | >>> res == os.path.join(modpath, '__init__.py') | |
162 | True |
|
162 | True | |
163 | >>> docwriter._uri2path('sphinx.does_not_exist') |
|
163 | >>> docwriter._uri2path('sphinx.does_not_exist') | |
164 |
|
164 | |||
165 | ''' |
|
165 | ''' | |
166 | if uri == self.package_name: |
|
166 | if uri == self.package_name: | |
167 | return os.path.join(self.root_path, '__init__.py') |
|
167 | return os.path.join(self.root_path, '__init__.py') | |
168 | path = uri.replace('.', os.path.sep) |
|
168 | path = uri.replace('.', os.path.sep) | |
169 | path = path.replace(self.package_name + os.path.sep, '') |
|
169 | path = path.replace(self.package_name + os.path.sep, '') | |
170 | path = os.path.join(self.root_path, path) |
|
170 | path = os.path.join(self.root_path, path) | |
171 | # XXX maybe check for extensions as well? |
|
171 | # XXX maybe check for extensions as well? | |
172 | if os.path.exists(path + '.py'): # file |
|
172 | if os.path.exists(path + '.py'): # file | |
173 | path += '.py' |
|
173 | path += '.py' | |
174 | elif os.path.exists(os.path.join(path, '__init__.py')): |
|
174 | elif os.path.exists(os.path.join(path, '__init__.py')): | |
175 | path = os.path.join(path, '__init__.py') |
|
175 | path = os.path.join(path, '__init__.py') | |
176 | else: |
|
176 | else: | |
177 | return None |
|
177 | return None | |
178 | return path |
|
178 | return path | |
179 |
|
179 | |||
180 | def _path2uri(self, dirpath): |
|
180 | def _path2uri(self, dirpath): | |
181 | ''' Convert directory path to uri ''' |
|
181 | ''' Convert directory path to uri ''' | |
182 | relpath = dirpath.replace(self.root_path, self.package_name) |
|
182 | relpath = dirpath.replace(self.root_path, self.package_name) | |
183 | if relpath.startswith(os.path.sep): |
|
183 | if relpath.startswith(os.path.sep): | |
184 | relpath = relpath[1:] |
|
184 | relpath = relpath[1:] | |
185 | return relpath.replace(os.path.sep, '.') |
|
185 | return relpath.replace(os.path.sep, '.') | |
186 |
|
186 | |||
187 | def _parse_module(self, uri): |
|
187 | def _parse_module(self, uri): | |
188 | ''' Parse module defined in *uri* ''' |
|
188 | ''' Parse module defined in *uri* ''' | |
189 | filename = self._uri2path(uri) |
|
189 | filename = self._uri2path(uri) | |
190 | if filename is None: |
|
190 | if filename is None: | |
191 | # nothing that we could handle here. |
|
191 | # nothing that we could handle here. | |
192 | return ([],[]) |
|
192 | return ([],[]) | |
193 | with open(filename, 'rb') as f: |
|
193 | with open(filename, 'rb') as f: | |
194 | mod = ast.parse(f.read()) |
|
194 | mod = ast.parse(f.read()) | |
195 | return FuncClsScanner().scan(mod) |
|
195 | return FuncClsScanner().scan(mod) | |
196 |
|
196 | |||
197 | def generate_api_doc(self, uri): |
|
197 | def generate_api_doc(self, uri): | |
198 | '''Make autodoc documentation template string for a module |
|
198 | '''Make autodoc documentation template string for a module | |
199 |
|
199 | |||
200 | Parameters |
|
200 | Parameters | |
201 | ---------- |
|
201 | ---------- | |
202 | uri : string |
|
202 | uri : string | |
203 | python location of module - e.g 'sphinx.builder' |
|
203 | python location of module - e.g 'sphinx.builder' | |
204 |
|
204 | |||
205 | Returns |
|
205 | Returns | |
206 | ------- |
|
206 | ------- | |
207 | S : string |
|
207 | S : string | |
208 | Contents of API doc |
|
208 | Contents of API doc | |
209 | ''' |
|
209 | ''' | |
210 | # get the names of all classes and functions |
|
210 | # get the names of all classes and functions | |
211 | functions, classes = self._parse_module(uri) |
|
211 | functions, classes = self._parse_module(uri) | |
212 | if not len(functions) and not len(classes): |
|
212 | if not len(functions) and not len(classes): | |
213 | print 'WARNING: Empty -',uri # dbg |
|
213 | print 'WARNING: Empty -',uri # dbg | |
214 | return '' |
|
214 | return '' | |
215 |
|
215 | |||
216 | # Make a shorter version of the uri that omits the package name for |
|
216 | # Make a shorter version of the uri that omits the package name for | |
217 | # titles |
|
217 | # titles | |
218 | uri_short = re.sub(r'^%s\.' % self.package_name,'',uri) |
|
218 | uri_short = re.sub(r'^%s\.' % self.package_name,'',uri) | |
219 |
|
219 | |||
220 | ad = '.. AUTO-GENERATED FILE -- DO NOT EDIT!\n\n' |
|
220 | ad = '.. AUTO-GENERATED FILE -- DO NOT EDIT!\n\n' | |
221 |
|
221 | |||
222 | # Set the chapter title to read 'Module:' for all modules except for the |
|
222 | # Set the chapter title to read 'Module:' for all modules except for the | |
223 | # main packages |
|
223 | # main packages | |
224 | if '.' in uri: |
|
224 | if '.' in uri: | |
225 | chap_title = 'Module: :mod:`' + uri_short + '`' |
|
225 | chap_title = 'Module: :mod:`' + uri_short + '`' | |
226 | else: |
|
226 | else: | |
227 | chap_title = ':mod:`' + uri_short + '`' |
|
227 | chap_title = ':mod:`' + uri_short + '`' | |
228 | ad += chap_title + '\n' + self.rst_section_levels[1] * len(chap_title) |
|
228 | ad += chap_title + '\n' + self.rst_section_levels[1] * len(chap_title) | |
229 |
|
229 | |||
230 | ad += '\n.. automodule:: ' + uri + '\n' |
|
230 | ad += '\n.. automodule:: ' + uri + '\n' | |
231 | ad += '\n.. currentmodule:: ' + uri + '\n' |
|
231 | ad += '\n.. currentmodule:: ' + uri + '\n' | |
232 |
|
232 | |||
233 | if classes: |
|
233 | if classes: | |
234 | subhead = str(len(classes)) + (' Classes' if len(classes) > 1 else ' Class') |
|
234 | subhead = str(len(classes)) + (' Classes' if len(classes) > 1 else ' Class') | |
235 | ad += '\n'+ subhead + '\n' + \ |
|
235 | ad += '\n'+ subhead + '\n' + \ | |
236 | self.rst_section_levels[2] * len(subhead) + '\n' |
|
236 | self.rst_section_levels[2] * len(subhead) + '\n' | |
237 |
|
237 | |||
238 | for c in classes: |
|
238 | for c in classes: | |
239 | ad += '\n.. autoclass:: ' + c.name + '\n' |
|
239 | ad += '\n.. autoclass:: ' + c.name + '\n' | |
240 | # must NOT exclude from index to keep cross-refs working |
|
240 | # must NOT exclude from index to keep cross-refs working | |
241 | ad += ' :members:\n' \ |
|
241 | ad += ' :members:\n' \ | |
242 | ' :show-inheritance:\n' |
|
242 | ' :show-inheritance:\n' | |
243 | if c.has_init: |
|
243 | if c.has_init: | |
244 | ad += '\n .. automethod:: __init__\n' |
|
244 | ad += '\n .. automethod:: __init__\n' | |
245 |
|
245 | |||
246 | if functions: |
|
246 | if functions: | |
247 | subhead = str(len(functions)) + (' Functions' if len(functions) > 1 else ' Function') |
|
247 | subhead = str(len(functions)) + (' Functions' if len(functions) > 1 else ' Function') | |
248 | ad += '\n'+ subhead + '\n' + \ |
|
248 | ad += '\n'+ subhead + '\n' + \ | |
249 | self.rst_section_levels[2] * len(subhead) + '\n' |
|
249 | self.rst_section_levels[2] * len(subhead) + '\n' | |
250 | for f in functions: |
|
250 | for f in functions: | |
251 | # must NOT exclude from index to keep cross-refs working |
|
251 | # must NOT exclude from index to keep cross-refs working | |
252 | ad += '\n.. autofunction:: ' + uri + '.' + f + '\n\n' |
|
252 | ad += '\n.. autofunction:: ' + uri + '.' + f + '\n\n' | |
253 | return ad |
|
253 | return ad | |
254 |
|
254 | |||
255 | def _survives_exclude(self, matchstr, match_type): |
|
255 | def _survives_exclude(self, matchstr, match_type): | |
256 | ''' Returns True if *matchstr* does not match patterns |
|
256 | ''' Returns True if *matchstr* does not match patterns | |
257 |
|
257 | |||
258 | ``self.package_name`` removed from front of string if present |
|
258 | ``self.package_name`` removed from front of string if present | |
259 |
|
259 | |||
260 | Examples |
|
260 | Examples | |
261 | -------- |
|
261 | -------- | |
262 | >>> dw = ApiDocWriter('sphinx') |
|
262 | >>> dw = ApiDocWriter('sphinx') | |
263 | >>> dw._survives_exclude('sphinx.okpkg', 'package') |
|
263 | >>> dw._survives_exclude('sphinx.okpkg', 'package') | |
264 | True |
|
264 | True | |
265 | >>> dw.package_skip_patterns.append('^\\.badpkg$') |
|
265 | >>> dw.package_skip_patterns.append('^\\.badpkg$') | |
266 | >>> dw._survives_exclude('sphinx.badpkg', 'package') |
|
266 | >>> dw._survives_exclude('sphinx.badpkg', 'package') | |
267 | False |
|
267 | False | |
268 | >>> dw._survives_exclude('sphinx.badpkg', 'module') |
|
268 | >>> dw._survives_exclude('sphinx.badpkg', 'module') | |
269 | True |
|
269 | True | |
270 | >>> dw._survives_exclude('sphinx.badmod', 'module') |
|
270 | >>> dw._survives_exclude('sphinx.badmod', 'module') | |
271 | True |
|
271 | True | |
272 | >>> dw.module_skip_patterns.append('^\\.badmod$') |
|
272 | >>> dw.module_skip_patterns.append('^\\.badmod$') | |
273 | >>> dw._survives_exclude('sphinx.badmod', 'module') |
|
273 | >>> dw._survives_exclude('sphinx.badmod', 'module') | |
274 | False |
|
274 | False | |
275 | ''' |
|
275 | ''' | |
276 | if match_type == 'module': |
|
276 | if match_type == 'module': | |
277 | patterns = self.module_skip_patterns |
|
277 | patterns = self.module_skip_patterns | |
278 | elif match_type == 'package': |
|
278 | elif match_type == 'package': | |
279 | patterns = self.package_skip_patterns |
|
279 | patterns = self.package_skip_patterns | |
280 | else: |
|
280 | else: | |
281 | raise ValueError('Cannot interpret match type "%s"' |
|
281 | raise ValueError('Cannot interpret match type "%s"' | |
282 | % match_type) |
|
282 | % match_type) | |
283 | # Match to URI without package name |
|
283 | # Match to URI without package name | |
284 | L = len(self.package_name) |
|
284 | L = len(self.package_name) | |
285 | if matchstr[:L] == self.package_name: |
|
285 | if matchstr[:L] == self.package_name: | |
286 | matchstr = matchstr[L:] |
|
286 | matchstr = matchstr[L:] | |
287 | for pat in patterns: |
|
287 | for pat in patterns: | |
288 | try: |
|
288 | try: | |
289 | pat.search |
|
289 | pat.search | |
290 | except AttributeError: |
|
290 | except AttributeError: | |
291 | pat = re.compile(pat) |
|
291 | pat = re.compile(pat) | |
292 | if pat.search(matchstr): |
|
292 | if pat.search(matchstr): | |
293 | return False |
|
293 | return False | |
294 | return True |
|
294 | return True | |
295 |
|
295 | |||
296 | def discover_modules(self): |
|
296 | def discover_modules(self): | |
297 | ''' Return module sequence discovered from ``self.package_name`` |
|
297 | ''' Return module sequence discovered from ``self.package_name`` | |
298 |
|
298 | |||
299 |
|
299 | |||
300 | Parameters |
|
300 | Parameters | |
301 | ---------- |
|
301 | ---------- | |
302 | None |
|
302 | None | |
303 |
|
303 | |||
304 | Returns |
|
304 | Returns | |
305 | ------- |
|
305 | ------- | |
306 | mods : sequence |
|
306 | mods : sequence | |
307 | Sequence of module names within ``self.package_name`` |
|
307 | Sequence of module names within ``self.package_name`` | |
308 |
|
308 | |||
309 | Examples |
|
309 | Examples | |
310 | -------- |
|
310 | -------- | |
311 | >>> dw = ApiDocWriter('sphinx') |
|
311 | >>> dw = ApiDocWriter('sphinx') | |
312 | >>> mods = dw.discover_modules() |
|
312 | >>> mods = dw.discover_modules() | |
313 | >>> 'sphinx.util' in mods |
|
313 | >>> 'sphinx.util' in mods | |
314 | True |
|
314 | True | |
315 | >>> dw.package_skip_patterns.append('\.util$') |
|
315 | >>> dw.package_skip_patterns.append('\.util$') | |
316 | >>> 'sphinx.util' in dw.discover_modules() |
|
316 | >>> 'sphinx.util' in dw.discover_modules() | |
317 | False |
|
317 | False | |
318 | >>> |
|
318 | >>> | |
319 | ''' |
|
319 | ''' | |
320 | modules = [self.package_name] |
|
320 | modules = [self.package_name] | |
321 | # raw directory parsing |
|
321 | # raw directory parsing | |
322 | for dirpath, dirnames, filenames in os.walk(self.root_path): |
|
322 | for dirpath, dirnames, filenames in os.walk(self.root_path): | |
323 | # Check directory names for packages |
|
323 | # Check directory names for packages | |
324 | root_uri = self._path2uri(os.path.join(self.root_path, |
|
324 | root_uri = self._path2uri(os.path.join(self.root_path, | |
325 | dirpath)) |
|
325 | dirpath)) | |
326 | for dirname in dirnames[:]: # copy list - we modify inplace |
|
326 | for dirname in dirnames[:]: # copy list - we modify inplace | |
327 | package_uri = '.'.join((root_uri, dirname)) |
|
327 | package_uri = '.'.join((root_uri, dirname)) | |
328 | if (self._uri2path(package_uri) and |
|
328 | if (self._uri2path(package_uri) and | |
329 | self._survives_exclude(package_uri, 'package')): |
|
329 | self._survives_exclude(package_uri, 'package')): | |
330 | modules.append(package_uri) |
|
330 | modules.append(package_uri) | |
331 | else: |
|
331 | else: | |
332 | dirnames.remove(dirname) |
|
332 | dirnames.remove(dirname) | |
333 | # Check filenames for modules |
|
333 | # Check filenames for modules | |
334 | for filename in filenames: |
|
334 | for filename in filenames: | |
335 | module_name = filename[:-3] |
|
335 | module_name = filename[:-3] | |
336 | module_uri = '.'.join((root_uri, module_name)) |
|
336 | module_uri = '.'.join((root_uri, module_name)) | |
337 | if (self._uri2path(module_uri) and |
|
337 | if (self._uri2path(module_uri) and | |
338 | self._survives_exclude(module_uri, 'module')): |
|
338 | self._survives_exclude(module_uri, 'module')): | |
339 | modules.append(module_uri) |
|
339 | modules.append(module_uri) | |
340 | return sorted(modules) |
|
340 | return sorted(modules) | |
341 |
|
341 | |||
342 | def write_modules_api(self, modules,outdir): |
|
342 | def write_modules_api(self, modules,outdir): | |
343 | # write the list |
|
343 | # write the list | |
344 | written_modules = [] |
|
344 | written_modules = [] | |
345 | for m in modules: |
|
345 | for m in modules: | |
346 | api_str = self.generate_api_doc(m) |
|
346 | api_str = self.generate_api_doc(m) | |
347 | if not api_str: |
|
347 | if not api_str: | |
348 | continue |
|
348 | continue | |
349 | # write out to file |
|
349 | # write out to file | |
350 | outfile = os.path.join(outdir, |
|
350 | outfile = os.path.join(outdir, | |
351 | m + self.rst_extension) |
|
351 | m + self.rst_extension) | |
352 | fileobj = open(outfile, 'wt') |
|
352 | fileobj = open(outfile, 'wt') | |
353 | fileobj.write(api_str) |
|
353 | fileobj.write(api_str) | |
354 | fileobj.close() |
|
354 | fileobj.close() | |
355 | written_modules.append(m) |
|
355 | written_modules.append(m) | |
356 | self.written_modules = written_modules |
|
356 | self.written_modules = written_modules | |
357 |
|
357 | |||
358 | def write_api_docs(self, outdir): |
|
358 | def write_api_docs(self, outdir): | |
359 | """Generate API reST files. |
|
359 | """Generate API reST files. | |
360 |
|
360 | |||
361 | Parameters |
|
361 | Parameters | |
362 | ---------- |
|
362 | ---------- | |
363 | outdir : string |
|
363 | outdir : string | |
364 | Directory name in which to store files |
|
364 | Directory name in which to store files | |
365 | We create automatic filenames for each module |
|
365 | We create automatic filenames for each module | |
366 |
|
366 | |||
367 | Returns |
|
367 | Returns | |
368 | ------- |
|
368 | ------- | |
369 | None |
|
369 | None | |
370 |
|
370 | |||
371 | Notes |
|
371 | Notes | |
372 | ----- |
|
372 | ----- | |
373 | Sets self.written_modules to list of written modules |
|
373 | Sets self.written_modules to list of written modules | |
374 | """ |
|
374 | """ | |
375 | if not os.path.exists(outdir): |
|
375 | if not os.path.exists(outdir): | |
376 | os.mkdir(outdir) |
|
376 | os.mkdir(outdir) | |
377 | # compose list of modules |
|
377 | # compose list of modules | |
378 | modules = self.discover_modules() |
|
378 | modules = self.discover_modules() | |
379 | self.write_modules_api(modules,outdir) |
|
379 | self.write_modules_api(modules,outdir) | |
380 |
|
380 | |||
381 |
def write_index(self, outdir, |
|
381 | def write_index(self, outdir, path='gen.rst', relative_to=None): | |
382 | """Make a reST API index file from written files |
|
382 | """Make a reST API index file from written files | |
383 |
|
383 | |||
384 | Parameters |
|
384 | Parameters | |
385 | ---------- |
|
385 | ---------- | |
386 | path : string |
|
|||
387 | Filename to write index to |
|
|||
388 | outdir : string |
|
386 | outdir : string | |
389 | Directory to which to write generated index file |
|
387 | Directory to which to write generated index file | |
390 |
|
|
388 | path : string | |
391 | root (filename without extension) of filename to write to |
|
389 | Filename to write index to | |
392 | Defaults to 'gen'. We add ``self.rst_extension``. |
|
|||
393 | relative_to : string |
|
390 | relative_to : string | |
394 | path to which written filenames are relative. This |
|
391 | path to which written filenames are relative. This | |
395 | component of the written file path will be removed from |
|
392 | component of the written file path will be removed from | |
396 | outdir, in the generated index. Default is None, meaning, |
|
393 | outdir, in the generated index. Default is None, meaning, | |
397 | leave path as it is. |
|
394 | leave path as it is. | |
398 | """ |
|
395 | """ | |
399 | if self.written_modules is None: |
|
396 | if self.written_modules is None: | |
400 | raise ValueError('No modules written') |
|
397 | raise ValueError('No modules written') | |
401 | # Get full filename path |
|
398 | # Get full filename path | |
402 |
path = os.path.join(outdir, |
|
399 | path = os.path.join(outdir, path) | |
403 | # Path written into index is relative to rootpath |
|
400 | # Path written into index is relative to rootpath | |
404 | if relative_to is not None: |
|
401 | if relative_to is not None: | |
405 | relpath = outdir.replace(relative_to + os.path.sep, '') |
|
402 | relpath = outdir.replace(relative_to + os.path.sep, '') | |
406 | else: |
|
403 | else: | |
407 | relpath = outdir |
|
404 | relpath = outdir | |
408 | idx = open(path,'wt') |
|
405 | idx = open(path,'wt') | |
409 | w = idx.write |
|
406 | w = idx.write | |
410 | w('.. AUTO-GENERATED FILE -- DO NOT EDIT!\n\n') |
|
407 | w('.. AUTO-GENERATED FILE -- DO NOT EDIT!\n\n') | |
411 | w('.. toctree::\n\n') |
|
408 | w('.. toctree::\n\n') | |
412 | for f in self.written_modules: |
|
409 | for f in self.written_modules: | |
413 | w(' %s\n' % os.path.join(relpath,f)) |
|
410 | w(' %s\n' % os.path.join(relpath,f)) | |
414 | idx.close() |
|
411 | idx.close() |
General Comments 0
You need to be logged in to leave comments.
Login now