Show More
The requested changes are too big and content was truncated. Show full diff
@@ -1,566 +1,566 b'' | |||
|
1 | 1 | # -*- coding: utf-8 -*- |
|
2 | 2 | """ |
|
3 | 3 | Pdb debugger class. |
|
4 | 4 | |
|
5 | 5 | Modified from the standard pdb.Pdb class to avoid including readline, so that |
|
6 | 6 | the command line completion of other programs which include this isn't |
|
7 | 7 | damaged. |
|
8 | 8 | |
|
9 | 9 | In the future, this class will be expanded with improvements over the standard |
|
10 | 10 | pdb. |
|
11 | 11 | |
|
12 | 12 | The code in this file is mainly lifted out of cmd.py in Python 2.2, with minor |
|
13 | 13 | changes. Licensing should therefore be under the standard Python terms. For |
|
14 | 14 | details on the PSF (Python Software Foundation) standard license, see: |
|
15 | 15 | |
|
16 | 16 | http://www.python.org/2.2.3/license.html""" |
|
17 | 17 | |
|
18 | 18 | #***************************************************************************** |
|
19 | 19 | # |
|
20 | 20 | # This file is licensed under the PSF license. |
|
21 | 21 | # |
|
22 | 22 | # Copyright (C) 2001 Python Software Foundation, www.python.org |
|
23 | 23 | # Copyright (C) 2005-2006 Fernando Perez. <fperez@colorado.edu> |
|
24 | 24 | # |
|
25 | 25 | # |
|
26 | 26 | #***************************************************************************** |
|
27 | 27 | from __future__ import print_function |
|
28 | 28 | |
|
29 | 29 | import bdb |
|
30 | 30 | import functools |
|
31 | 31 | import linecache |
|
32 | 32 | import sys |
|
33 | 33 | |
|
34 | 34 | from IPython.utils import PyColorize, ulinecache |
|
35 | 35 | from IPython.core import ipapi |
|
36 | 36 | from IPython.utils import coloransi, io, openpy, py3compat |
|
37 | 37 | from IPython.core.excolors import exception_colors |
|
38 | 38 | |
|
39 | 39 | # See if we can use pydb. |
|
40 | 40 | has_pydb = False |
|
41 | 41 | prompt = 'ipdb> ' |
|
42 | 42 | #We have to check this directly from sys.argv, config struct not yet available |
|
43 | 43 | if '--pydb' in sys.argv: |
|
44 | 44 | try: |
|
45 | 45 | import pydb |
|
46 | 46 | if hasattr(pydb.pydb, "runl") and pydb.version>'1.17': |
|
47 | 47 | # Version 1.17 is broken, and that's what ships with Ubuntu Edgy, so we |
|
48 | 48 | # better protect against it. |
|
49 | 49 | has_pydb = True |
|
50 | 50 | except ImportError: |
|
51 | 51 | print("Pydb (http://bashdb.sourceforge.net/pydb/) does not seem to be available") |
|
52 | 52 | |
|
53 | 53 | if has_pydb: |
|
54 | 54 | from pydb import Pdb as OldPdb |
|
55 | 55 | #print "Using pydb for %run -d and post-mortem" #dbg |
|
56 | 56 | prompt = 'ipydb> ' |
|
57 | 57 | else: |
|
58 | 58 | from pdb import Pdb as OldPdb |
|
59 | 59 | |
|
60 | 60 | # Allow the set_trace code to operate outside of an ipython instance, even if |
|
61 | 61 | # it does so with some limitations. The rest of this support is implemented in |
|
62 | 62 | # the Tracer constructor. |
|
63 | 63 | def BdbQuit_excepthook(et, ev, tb, excepthook=None): |
|
64 | 64 | """Exception hook which handles `BdbQuit` exceptions. |
|
65 | 65 | |
|
66 | 66 | All other exceptions are processed using the `excepthook` |
|
67 | 67 | parameter. |
|
68 | 68 | """ |
|
69 | 69 | if et==bdb.BdbQuit: |
|
70 | 70 | print('Exiting Debugger.') |
|
71 | 71 | elif excepthook is not None: |
|
72 | 72 | excepthook(et, ev, tb) |
|
73 | 73 | else: |
|
74 | 74 | # Backwards compatibility. Raise deprecation warning? |
|
75 | 75 | BdbQuit_excepthook.excepthook_ori(et,ev,tb) |
|
76 | 76 | |
|
77 | 77 | def BdbQuit_IPython_excepthook(self,et,ev,tb,tb_offset=None): |
|
78 | 78 | print('Exiting Debugger.') |
|
79 | 79 | |
|
80 | 80 | |
|
81 | 81 | class Tracer(object): |
|
82 | 82 | """Class for local debugging, similar to pdb.set_trace. |
|
83 | 83 | |
|
84 | 84 | Instances of this class, when called, behave like pdb.set_trace, but |
|
85 | 85 | providing IPython's enhanced capabilities. |
|
86 | 86 | |
|
87 | 87 | This is implemented as a class which must be initialized in your own code |
|
88 | 88 | and not as a standalone function because we need to detect at runtime |
|
89 | 89 | whether IPython is already active or not. That detection is done in the |
|
90 | 90 | constructor, ensuring that this code plays nicely with a running IPython, |
|
91 | 91 | while functioning acceptably (though with limitations) if outside of it. |
|
92 | 92 | """ |
|
93 | 93 | |
|
94 | 94 | def __init__(self,colors=None): |
|
95 | 95 | """Create a local debugger instance. |
|
96 | 96 | |
|
97 | 97 | :Parameters: |
|
98 | 98 | |
|
99 | 99 | - `colors` (None): a string containing the name of the color scheme to |
|
100 | 100 | use, it must be one of IPython's valid color schemes. If not given, the |
|
101 | 101 | function will default to the current IPython scheme when running inside |
|
102 | 102 | IPython, and to 'NoColor' otherwise. |
|
103 | 103 | |
|
104 | 104 | Usage example: |
|
105 | 105 | |
|
106 | 106 | from IPython.core.debugger import Tracer; debug_here = Tracer() |
|
107 | 107 | |
|
108 | 108 | ... later in your code |
|
109 | 109 | debug_here() # -> will open up the debugger at that point. |
|
110 | 110 | |
|
111 | 111 | Once the debugger activates, you can use all of its regular commands to |
|
112 | 112 | step through code, set breakpoints, etc. See the pdb documentation |
|
113 | 113 | from the Python standard library for usage details. |
|
114 | 114 | """ |
|
115 | 115 | |
|
116 | 116 | try: |
|
117 | 117 | ip = get_ipython() |
|
118 | 118 | except NameError: |
|
119 | 119 | # Outside of ipython, we set our own exception hook manually |
|
120 | 120 | sys.excepthook = functools.partial(BdbQuit_excepthook, |
|
121 | 121 | excepthook=sys.excepthook) |
|
122 | 122 | def_colors = 'NoColor' |
|
123 | 123 | try: |
|
124 | 124 | # Limited tab completion support |
|
125 | 125 | import readline |
|
126 | 126 | readline.parse_and_bind('tab: complete') |
|
127 | 127 | except ImportError: |
|
128 | 128 | pass |
|
129 | 129 | else: |
|
130 | 130 | # In ipython, we use its custom exception handler mechanism |
|
131 | 131 | def_colors = ip.colors |
|
132 | 132 | ip.set_custom_exc((bdb.BdbQuit,), BdbQuit_IPython_excepthook) |
|
133 | 133 | |
|
134 | 134 | if colors is None: |
|
135 | 135 | colors = def_colors |
|
136 | 136 | |
|
137 | 137 | # The stdlib debugger internally uses a modified repr from the `repr` |
|
138 | 138 | # module, that limits the length of printed strings to a hardcoded |
|
139 | 139 | # limit of 30 characters. That much trimming is too aggressive, let's |
|
140 | 140 | # at least raise that limit to 80 chars, which should be enough for |
|
141 | 141 | # most interactive uses. |
|
142 | 142 | try: |
|
143 | 143 | from repr import aRepr |
|
144 | 144 | aRepr.maxstring = 80 |
|
145 | 145 | except: |
|
146 | 146 | # This is only a user-facing convenience, so any error we encounter |
|
147 | 147 | # here can be warned about but can be otherwise ignored. These |
|
148 | 148 | # printouts will tell us about problems if this API changes |
|
149 | 149 | import traceback |
|
150 | 150 | traceback.print_exc() |
|
151 | 151 | |
|
152 | 152 | self.debugger = Pdb(colors) |
|
153 | 153 | |
|
154 | 154 | def __call__(self): |
|
155 | 155 | """Starts an interactive debugger at the point where called. |
|
156 | 156 | |
|
157 | 157 | This is similar to the pdb.set_trace() function from the std lib, but |
|
158 | 158 | using IPython's enhanced debugger.""" |
|
159 | 159 | |
|
160 | 160 | self.debugger.set_trace(sys._getframe().f_back) |
|
161 | 161 | |
|
162 | 162 | |
|
163 | 163 | def decorate_fn_with_doc(new_fn, old_fn, additional_text=""): |
|
164 | 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 | 166 | Adapted from from a comp.lang.python posting |
|
167 | 167 | by Duncan Booth.""" |
|
168 | 168 | def wrapper(*args, **kw): |
|
169 | 169 | return new_fn(*args, **kw) |
|
170 | 170 | if old_fn.__doc__: |
|
171 | 171 | wrapper.__doc__ = old_fn.__doc__ + additional_text |
|
172 | 172 | return wrapper |
|
173 | 173 | |
|
174 | 174 | |
|
175 | 175 | def _file_lines(fname): |
|
176 | 176 | """Return the contents of a named file as a list of lines. |
|
177 | 177 | |
|
178 | 178 | This function never raises an IOError exception: if the file can't be |
|
179 | 179 | read, it simply returns an empty list.""" |
|
180 | 180 | |
|
181 | 181 | try: |
|
182 | 182 | outfile = open(fname) |
|
183 | 183 | except IOError: |
|
184 | 184 | return [] |
|
185 | 185 | else: |
|
186 | 186 | out = outfile.readlines() |
|
187 | 187 | outfile.close() |
|
188 | 188 | return out |
|
189 | 189 | |
|
190 | 190 | |
|
191 | 191 | class Pdb(OldPdb): |
|
192 | 192 | """Modified Pdb class, does not load readline.""" |
|
193 | 193 | |
|
194 | 194 | def __init__(self,color_scheme='NoColor',completekey=None, |
|
195 | 195 | stdin=None, stdout=None): |
|
196 | 196 | |
|
197 | 197 | # Parent constructor: |
|
198 | 198 | if has_pydb and completekey is None: |
|
199 | 199 | OldPdb.__init__(self,stdin=stdin,stdout=io.stdout) |
|
200 | 200 | else: |
|
201 | 201 | OldPdb.__init__(self,completekey,stdin,stdout) |
|
202 | 202 | |
|
203 | 203 | self.prompt = prompt # The default prompt is '(Pdb)' |
|
204 | 204 | |
|
205 | 205 | # IPython changes... |
|
206 | 206 | self.is_pydb = has_pydb |
|
207 | 207 | |
|
208 | 208 | self.shell = ipapi.get() |
|
209 | 209 | |
|
210 | 210 | if self.is_pydb: |
|
211 | 211 | |
|
212 | 212 | # interactiveshell.py's ipalias seems to want pdb's checkline |
|
213 | 213 | # which located in pydb.fn |
|
214 | 214 | import pydb.fns |
|
215 | 215 | self.checkline = lambda filename, lineno: \ |
|
216 | 216 | pydb.fns.checkline(self, filename, lineno) |
|
217 | 217 | |
|
218 | 218 | self.curframe = None |
|
219 | 219 | self.do_restart = self.new_do_restart |
|
220 | 220 | |
|
221 | 221 | self.old_all_completions = self.shell.Completer.all_completions |
|
222 | 222 | self.shell.Completer.all_completions=self.all_completions |
|
223 | 223 | |
|
224 | 224 | self.do_list = decorate_fn_with_doc(self.list_command_pydb, |
|
225 | 225 | OldPdb.do_list) |
|
226 | 226 | self.do_l = self.do_list |
|
227 | 227 | self.do_frame = decorate_fn_with_doc(self.new_do_frame, |
|
228 | 228 | OldPdb.do_frame) |
|
229 | 229 | |
|
230 | 230 | self.aliases = {} |
|
231 | 231 | |
|
232 | 232 | # Create color table: we copy the default one from the traceback |
|
233 | 233 | # module and add a few attributes needed for debugging |
|
234 | 234 | self.color_scheme_table = exception_colors() |
|
235 | 235 | |
|
236 | 236 | # shorthands |
|
237 | 237 | C = coloransi.TermColors |
|
238 | 238 | cst = self.color_scheme_table |
|
239 | 239 | |
|
240 | 240 | cst['NoColor'].colors.breakpoint_enabled = C.NoColor |
|
241 | 241 | cst['NoColor'].colors.breakpoint_disabled = C.NoColor |
|
242 | 242 | |
|
243 | 243 | cst['Linux'].colors.breakpoint_enabled = C.LightRed |
|
244 | 244 | cst['Linux'].colors.breakpoint_disabled = C.Red |
|
245 | 245 | |
|
246 | 246 | cst['LightBG'].colors.breakpoint_enabled = C.LightRed |
|
247 | 247 | cst['LightBG'].colors.breakpoint_disabled = C.Red |
|
248 | 248 | |
|
249 | 249 | self.set_colors(color_scheme) |
|
250 | 250 | |
|
251 | 251 | # Add a python parser so we can syntax highlight source while |
|
252 | 252 | # debugging. |
|
253 | 253 | self.parser = PyColorize.Parser() |
|
254 | 254 | |
|
255 | 255 | def set_colors(self, scheme): |
|
256 | 256 | """Shorthand access to the color table scheme selector method.""" |
|
257 | 257 | self.color_scheme_table.set_active_scheme(scheme) |
|
258 | 258 | |
|
259 | 259 | def interaction(self, frame, traceback): |
|
260 | 260 | self.shell.set_completer_frame(frame) |
|
261 | 261 | OldPdb.interaction(self, frame, traceback) |
|
262 | 262 | |
|
263 | 263 | def new_do_up(self, arg): |
|
264 | 264 | OldPdb.do_up(self, arg) |
|
265 | 265 | self.shell.set_completer_frame(self.curframe) |
|
266 | 266 | do_u = do_up = decorate_fn_with_doc(new_do_up, OldPdb.do_up) |
|
267 | 267 | |
|
268 | 268 | def new_do_down(self, arg): |
|
269 | 269 | OldPdb.do_down(self, arg) |
|
270 | 270 | self.shell.set_completer_frame(self.curframe) |
|
271 | 271 | |
|
272 | 272 | do_d = do_down = decorate_fn_with_doc(new_do_down, OldPdb.do_down) |
|
273 | 273 | |
|
274 | 274 | def new_do_frame(self, arg): |
|
275 | 275 | OldPdb.do_frame(self, arg) |
|
276 | 276 | self.shell.set_completer_frame(self.curframe) |
|
277 | 277 | |
|
278 | 278 | def new_do_quit(self, arg): |
|
279 | 279 | |
|
280 | 280 | if hasattr(self, 'old_all_completions'): |
|
281 | 281 | self.shell.Completer.all_completions=self.old_all_completions |
|
282 | 282 | |
|
283 | 283 | |
|
284 | 284 | return OldPdb.do_quit(self, arg) |
|
285 | 285 | |
|
286 | 286 | do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit) |
|
287 | 287 | |
|
288 | 288 | def new_do_restart(self, arg): |
|
289 | 289 | """Restart command. In the context of ipython this is exactly the same |
|
290 | 290 | thing as 'quit'.""" |
|
291 | 291 | self.msg("Restart doesn't make sense here. Using 'quit' instead.") |
|
292 | 292 | return self.do_quit(arg) |
|
293 | 293 | |
|
294 | 294 | def postloop(self): |
|
295 | 295 | self.shell.set_completer_frame(None) |
|
296 | 296 | |
|
297 | 297 | def print_stack_trace(self): |
|
298 | 298 | try: |
|
299 | 299 | for frame_lineno in self.stack: |
|
300 | 300 | self.print_stack_entry(frame_lineno, context = 5) |
|
301 | 301 | except KeyboardInterrupt: |
|
302 | 302 | pass |
|
303 | 303 | |
|
304 | 304 | def print_stack_entry(self,frame_lineno,prompt_prefix='\n-> ', |
|
305 | 305 | context = 3): |
|
306 | 306 | #frame, lineno = frame_lineno |
|
307 | 307 | print(self.format_stack_entry(frame_lineno, '', context), file=io.stdout) |
|
308 | 308 | |
|
309 | 309 | # vds: >> |
|
310 | 310 | frame, lineno = frame_lineno |
|
311 | 311 | filename = frame.f_code.co_filename |
|
312 | 312 | self.shell.hooks.synchronize_with_editor(filename, lineno, 0) |
|
313 | 313 | # vds: << |
|
314 | 314 | |
|
315 | 315 | def format_stack_entry(self, frame_lineno, lprefix=': ', context = 3): |
|
316 | 316 | import repr |
|
317 | 317 | |
|
318 | 318 | ret = [] |
|
319 | 319 | |
|
320 | 320 | Colors = self.color_scheme_table.active_colors |
|
321 | 321 | ColorsNormal = Colors.Normal |
|
322 | 322 | tpl_link = u'%s%%s%s' % (Colors.filenameEm, ColorsNormal) |
|
323 | 323 | tpl_call = u'%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal) |
|
324 | 324 | tpl_line = u'%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal) |
|
325 | 325 | tpl_line_em = u'%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, |
|
326 | 326 | ColorsNormal) |
|
327 | 327 | |
|
328 | 328 | frame, lineno = frame_lineno |
|
329 | 329 | |
|
330 | 330 | return_value = '' |
|
331 | 331 | if '__return__' in frame.f_locals: |
|
332 | 332 | rv = frame.f_locals['__return__'] |
|
333 | 333 | #return_value += '->' |
|
334 | 334 | return_value += repr.repr(rv) + '\n' |
|
335 | 335 | ret.append(return_value) |
|
336 | 336 | |
|
337 | 337 | #s = filename + '(' + `lineno` + ')' |
|
338 | 338 | filename = self.canonic(frame.f_code.co_filename) |
|
339 | 339 | link = tpl_link % py3compat.cast_unicode(filename) |
|
340 | 340 | |
|
341 | 341 | if frame.f_code.co_name: |
|
342 | 342 | func = frame.f_code.co_name |
|
343 | 343 | else: |
|
344 | 344 | func = "<lambda>" |
|
345 | 345 | |
|
346 | 346 | call = '' |
|
347 | 347 | if func != '?': |
|
348 | 348 | if '__args__' in frame.f_locals: |
|
349 | 349 | args = repr.repr(frame.f_locals['__args__']) |
|
350 | 350 | else: |
|
351 | 351 | args = '()' |
|
352 | 352 | call = tpl_call % (func, args) |
|
353 | 353 | |
|
354 | 354 | # The level info should be generated in the same format pdb uses, to |
|
355 | 355 | # avoid breaking the pdbtrack functionality of python-mode in *emacs. |
|
356 | 356 | if frame is self.curframe: |
|
357 | 357 | ret.append('> ') |
|
358 | 358 | else: |
|
359 | 359 | ret.append(' ') |
|
360 | 360 | ret.append(u'%s(%s)%s\n' % (link,lineno,call)) |
|
361 | 361 | |
|
362 | 362 | start = lineno - 1 - context//2 |
|
363 | 363 | lines = ulinecache.getlines(filename) |
|
364 | 364 | start = min(start, len(lines) - context) |
|
365 | 365 | start = max(start, 0) |
|
366 | 366 | lines = lines[start : start + context] |
|
367 | 367 | |
|
368 | 368 | for i,line in enumerate(lines): |
|
369 | 369 | show_arrow = (start + 1 + i == lineno) |
|
370 | 370 | linetpl = (frame is self.curframe or show_arrow) \ |
|
371 | 371 | and tpl_line_em \ |
|
372 | 372 | or tpl_line |
|
373 | 373 | ret.append(self.__format_line(linetpl, filename, |
|
374 | 374 | start + 1 + i, line, |
|
375 | 375 | arrow = show_arrow) ) |
|
376 | 376 | return ''.join(ret) |
|
377 | 377 | |
|
378 | 378 | def __format_line(self, tpl_line, filename, lineno, line, arrow = False): |
|
379 | 379 | bp_mark = "" |
|
380 | 380 | bp_mark_color = "" |
|
381 | 381 | |
|
382 | 382 | scheme = self.color_scheme_table.active_scheme_name |
|
383 | 383 | new_line, err = self.parser.format2(line, 'str', scheme) |
|
384 | 384 | if not err: line = new_line |
|
385 | 385 | |
|
386 | 386 | bp = None |
|
387 | 387 | if lineno in self.get_file_breaks(filename): |
|
388 | 388 | bps = self.get_breaks(filename, lineno) |
|
389 | 389 | bp = bps[-1] |
|
390 | 390 | |
|
391 | 391 | if bp: |
|
392 | 392 | Colors = self.color_scheme_table.active_colors |
|
393 | 393 | bp_mark = str(bp.number) |
|
394 | 394 | bp_mark_color = Colors.breakpoint_enabled |
|
395 | 395 | if not bp.enabled: |
|
396 | 396 | bp_mark_color = Colors.breakpoint_disabled |
|
397 | 397 | |
|
398 | 398 | numbers_width = 7 |
|
399 | 399 | if arrow: |
|
400 | 400 | # This is the line with the error |
|
401 | 401 | pad = numbers_width - len(str(lineno)) - len(bp_mark) |
|
402 | 402 | if pad >= 3: |
|
403 | 403 | marker = '-'*(pad-3) + '-> ' |
|
404 | 404 | elif pad == 2: |
|
405 | 405 | marker = '> ' |
|
406 | 406 | elif pad == 1: |
|
407 | 407 | marker = '>' |
|
408 | 408 | else: |
|
409 | 409 | marker = '' |
|
410 | 410 | num = '%s%s' % (marker, str(lineno)) |
|
411 | 411 | line = tpl_line % (bp_mark_color + bp_mark, num, line) |
|
412 | 412 | else: |
|
413 | 413 | num = '%*s' % (numbers_width - len(bp_mark), str(lineno)) |
|
414 | 414 | line = tpl_line % (bp_mark_color + bp_mark, num, line) |
|
415 | 415 | |
|
416 | 416 | return line |
|
417 | 417 | |
|
418 | 418 | def list_command_pydb(self, arg): |
|
419 | 419 | """List command to use if we have a newer pydb installed""" |
|
420 | 420 | filename, first, last = OldPdb.parse_list_cmd(self, arg) |
|
421 | 421 | if filename is not None: |
|
422 | 422 | self.print_list_lines(filename, first, last) |
|
423 | 423 | |
|
424 | 424 | def print_list_lines(self, filename, first, last): |
|
425 | 425 | """The printing (as opposed to the parsing part of a 'list' |
|
426 | 426 | command.""" |
|
427 | 427 | try: |
|
428 | 428 | Colors = self.color_scheme_table.active_colors |
|
429 | 429 | ColorsNormal = Colors.Normal |
|
430 | 430 | tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal) |
|
431 | 431 | tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal) |
|
432 | 432 | src = [] |
|
433 | 433 | if filename == "<string>" and hasattr(self, "_exec_filename"): |
|
434 | 434 | filename = self._exec_filename |
|
435 | 435 | |
|
436 | 436 | for lineno in range(first, last+1): |
|
437 | 437 | line = ulinecache.getline(filename, lineno) |
|
438 | 438 | if not line: |
|
439 | 439 | break |
|
440 | 440 | |
|
441 | 441 | if lineno == self.curframe.f_lineno: |
|
442 | 442 | line = self.__format_line(tpl_line_em, filename, lineno, line, arrow = True) |
|
443 | 443 | else: |
|
444 | 444 | line = self.__format_line(tpl_line, filename, lineno, line, arrow = False) |
|
445 | 445 | |
|
446 | 446 | src.append(line) |
|
447 | 447 | self.lineno = lineno |
|
448 | 448 | |
|
449 | 449 | print(''.join(src), file=io.stdout) |
|
450 | 450 | |
|
451 | 451 | except KeyboardInterrupt: |
|
452 | 452 | pass |
|
453 | 453 | |
|
454 | 454 | def do_list(self, arg): |
|
455 | 455 | self.lastcmd = 'list' |
|
456 | 456 | last = None |
|
457 | 457 | if arg: |
|
458 | 458 | try: |
|
459 | 459 | x = eval(arg, {}, {}) |
|
460 | 460 | if type(x) == type(()): |
|
461 | 461 | first, last = x |
|
462 | 462 | first = int(first) |
|
463 | 463 | last = int(last) |
|
464 | 464 | if last < first: |
|
465 | 465 | # Assume it's a count |
|
466 | 466 | last = first + last |
|
467 | 467 | else: |
|
468 | 468 | first = max(1, int(x) - 5) |
|
469 | 469 | except: |
|
470 | 470 | print('*** Error in argument:', repr(arg)) |
|
471 | 471 | return |
|
472 | 472 | elif self.lineno is None: |
|
473 | 473 | first = max(1, self.curframe.f_lineno - 5) |
|
474 | 474 | else: |
|
475 | 475 | first = self.lineno + 1 |
|
476 | 476 | if last is None: |
|
477 | 477 | last = first + 10 |
|
478 | 478 | self.print_list_lines(self.curframe.f_code.co_filename, first, last) |
|
479 | 479 | |
|
480 | 480 | # vds: >> |
|
481 | 481 | lineno = first |
|
482 | 482 | filename = self.curframe.f_code.co_filename |
|
483 | 483 | self.shell.hooks.synchronize_with_editor(filename, lineno, 0) |
|
484 | 484 | # vds: << |
|
485 | 485 | |
|
486 | 486 | do_l = do_list |
|
487 | 487 | |
|
488 | 488 | def do_pdef(self, arg): |
|
489 | 489 | """Print the call signature for any callable object. |
|
490 | 490 | |
|
491 | 491 | The debugger interface to %pdef""" |
|
492 | 492 | namespaces = [('Locals', self.curframe.f_locals), |
|
493 | 493 | ('Globals', self.curframe.f_globals)] |
|
494 | 494 | self.shell.find_line_magic('pdef')(arg, namespaces=namespaces) |
|
495 | 495 | |
|
496 | 496 | def do_pdoc(self, arg): |
|
497 | 497 | """Print the docstring for an object. |
|
498 | 498 | |
|
499 | 499 | The debugger interface to %pdoc.""" |
|
500 | 500 | namespaces = [('Locals', self.curframe.f_locals), |
|
501 | 501 | ('Globals', self.curframe.f_globals)] |
|
502 | 502 | self.shell.find_line_magic('pdoc')(arg, namespaces=namespaces) |
|
503 | 503 | |
|
504 | 504 | def do_pfile(self, arg): |
|
505 | 505 | """Print (or run through pager) the file where an object is defined. |
|
506 | 506 | |
|
507 | 507 | The debugger interface to %pfile. |
|
508 | 508 | """ |
|
509 | 509 | namespaces = [('Locals', self.curframe.f_locals), |
|
510 | 510 | ('Globals', self.curframe.f_globals)] |
|
511 | 511 | self.shell.find_line_magic('pfile')(arg, namespaces=namespaces) |
|
512 | 512 | |
|
513 | 513 | def do_pinfo(self, arg): |
|
514 | 514 | """Provide detailed information about an object. |
|
515 | 515 | |
|
516 | 516 | The debugger interface to %pinfo, i.e., obj?.""" |
|
517 | 517 | namespaces = [('Locals', self.curframe.f_locals), |
|
518 | 518 | ('Globals', self.curframe.f_globals)] |
|
519 | 519 | self.shell.find_line_magic('pinfo')(arg, namespaces=namespaces) |
|
520 | 520 | |
|
521 | 521 | def do_pinfo2(self, arg): |
|
522 | 522 | """Provide extra detailed information about an object. |
|
523 | 523 | |
|
524 | 524 | The debugger interface to %pinfo2, i.e., obj??.""" |
|
525 | 525 | namespaces = [('Locals', self.curframe.f_locals), |
|
526 | 526 | ('Globals', self.curframe.f_globals)] |
|
527 | 527 | self.shell.find_line_magic('pinfo2')(arg, namespaces=namespaces) |
|
528 | 528 | |
|
529 | 529 | def do_psource(self, arg): |
|
530 | 530 | """Print (or run through pager) the source code for an object.""" |
|
531 | 531 | namespaces = [('Locals', self.curframe.f_locals), |
|
532 | 532 | ('Globals', self.curframe.f_globals)] |
|
533 | 533 | self.shell.find_line_magic('psource')(arg, namespaces=namespaces) |
|
534 | 534 | |
|
535 | 535 | def checkline(self, filename, lineno): |
|
536 | 536 | """Check whether specified line seems to be executable. |
|
537 | 537 | |
|
538 | 538 | Return `lineno` if it is, 0 if not (e.g. a docstring, comment, blank |
|
539 | 539 | line or EOF). Warning: testing is not comprehensive. |
|
540 | 540 | """ |
|
541 | 541 | ####################################################################### |
|
542 | 542 | # XXX Hack! Use python-2.5 compatible code for this call, because with |
|
543 | 543 | # all of our changes, we've drifted from the pdb api in 2.6. For now, |
|
544 | 544 | # changing: |
|
545 | 545 | # |
|
546 | 546 | #line = linecache.getline(filename, lineno, self.curframe.f_globals) |
|
547 | 547 | # to: |
|
548 | 548 | # |
|
549 | 549 | line = linecache.getline(filename, lineno) |
|
550 | 550 | # |
|
551 | 551 | # does the trick. But in reality, we need to fix this by reconciling |
|
552 | 552 | # our updates with the new Pdb APIs in Python 2.6. |
|
553 | 553 | # |
|
554 | 554 | # End hack. The rest of this method is copied verbatim from 2.6 pdb.py |
|
555 | 555 | ####################################################################### |
|
556 | 556 | |
|
557 | 557 | if not line: |
|
558 | 558 | print('End of file', file=self.stdout) |
|
559 | 559 | return 0 |
|
560 | 560 | line = line.strip() |
|
561 | 561 | # Don't allow setting breakpoint at a blank line |
|
562 | 562 | if (not line or (line[0] == '#') or |
|
563 | 563 | (line[:3] == '"""') or line[:3] == "'''"): |
|
564 | 564 | print('*** Blank or comment', file=self.stdout) |
|
565 | 565 | return 0 |
|
566 | 566 | return lineno |
@@ -1,230 +1,224 b'' | |||
|
1 |
""" |
|
|
1 | """Hooks for IPython. | |
|
2 | 2 | |
|
3 | 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 | 5 | be overwritten by users for customization purposes. This module defines the |
|
6 | 6 | default versions of all such hooks, which get used by IPython if not |
|
7 | 7 | overridden by the user. |
|
8 | 8 | |
|
9 |
|
|
|
9 | Hooks are simple functions, but they should be declared with ``self`` as their | |
|
10 | 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 | 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 |
|
|
15 | necessary code into a python file which can be either imported or execfile()'d | |
|
16 | from within your profile's ipython_config.py configuration. | |
|
14 | If you wish to define a new hook and activate it, you can make an :doc:`extension | |
|
15 | </config/extensions/index>` or a :ref:`startup script <startup_files>`. For | |
|
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 | |
|
19 | PYTHONPATH, which contains the following definition: | |
|
18 | import os | |
|
20 | 19 | |
|
21 | import os | |
|
22 | from IPython.core import ipapi | |
|
23 | ip = ipapi.get() | |
|
24 | ||
|
25 | def calljed(self,filename, linenum): | |
|
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() | |
|
20 | def calljed(self,filename, linenum): | |
|
21 | "My editor hook calls the jed editor directly." | |
|
22 | print "Calling my own editor, jed ..." | |
|
23 | if os.system('jed +%d %s' % (linenum,filename)) != 0: | |
|
24 | 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 | 32 | # Copyright (C) 2005 Fernando Perez. <fperez@colorado.edu> |
|
39 | 33 | # |
|
40 | 34 | # Distributed under the terms of the BSD License. The full license is in |
|
41 | 35 | # the file COPYING, distributed as part of this software. |
|
42 | 36 | #***************************************************************************** |
|
43 | 37 | |
|
44 | 38 | import os |
|
45 | 39 | import subprocess |
|
46 | 40 | import sys |
|
47 | 41 | |
|
48 | 42 | from IPython.core.error import TryNext |
|
49 | 43 | |
|
50 | 44 | # List here all the default hooks. For now it's just the editor functions |
|
51 | 45 | # but over time we'll move here all the public API for user-accessible things. |
|
52 | 46 | |
|
53 | 47 | __all__ = ['editor', 'fix_error_editor', 'synchronize_with_editor', |
|
54 | 48 | 'input_prefilter', 'shutdown_hook', 'late_startup_hook', |
|
55 | 49 | 'show_in_pager','pre_prompt_hook', |
|
56 | 50 | 'pre_run_code_hook', 'clipboard_get'] |
|
57 | 51 | |
|
58 | 52 | def editor(self, filename, linenum=None, wait=True): |
|
59 | 53 | """Open the default editor at the given filename and linenumber. |
|
60 | 54 | |
|
61 | 55 | This is IPython's default editor hook, you can use it as an example to |
|
62 | 56 | write your own modified one. To set your own editor function as the |
|
63 | 57 | new editor hook, call ip.set_hook('editor',yourfunc).""" |
|
64 | 58 | |
|
65 | 59 | # IPython configures a default editor at startup by reading $EDITOR from |
|
66 | 60 | # the environment, and falling back on vi (unix) or notepad (win32). |
|
67 | 61 | editor = self.editor |
|
68 | 62 | |
|
69 | 63 | # marker for at which line to open the file (for existing objects) |
|
70 | 64 | if linenum is None or editor=='notepad': |
|
71 | 65 | linemark = '' |
|
72 | 66 | else: |
|
73 | 67 | linemark = '+%d' % int(linenum) |
|
74 | 68 | |
|
75 | 69 | # Enclose in quotes if necessary and legal |
|
76 | 70 | if ' ' in editor and os.path.isfile(editor) and editor[0] != '"': |
|
77 | 71 | editor = '"%s"' % editor |
|
78 | 72 | |
|
79 | 73 | # Call the actual editor |
|
80 | 74 | proc = subprocess.Popen('%s %s %s' % (editor, linemark, filename), |
|
81 | 75 | shell=True) |
|
82 | 76 | if wait and proc.wait() != 0: |
|
83 | 77 | raise TryNext() |
|
84 | 78 | |
|
85 | 79 | import tempfile |
|
86 | 80 | def fix_error_editor(self,filename,linenum,column,msg): |
|
87 | 81 | """Open the editor at the given filename, linenumber, column and |
|
88 | 82 | show an error message. This is used for correcting syntax errors. |
|
89 | 83 | The current implementation only has special support for the VIM editor, |
|
90 | 84 | and falls back on the 'editor' hook if VIM is not used. |
|
91 | 85 | |
|
92 | 86 | Call ip.set_hook('fix_error_editor',youfunc) to use your own function, |
|
93 | 87 | """ |
|
94 | 88 | def vim_quickfix_file(): |
|
95 | 89 | t = tempfile.NamedTemporaryFile() |
|
96 | 90 | t.write('%s:%d:%d:%s\n' % (filename,linenum,column,msg)) |
|
97 | 91 | t.flush() |
|
98 | 92 | return t |
|
99 | 93 | if os.path.basename(self.editor) != 'vim': |
|
100 | 94 | self.hooks.editor(filename,linenum) |
|
101 | 95 | return |
|
102 | 96 | t = vim_quickfix_file() |
|
103 | 97 | try: |
|
104 | 98 | if os.system('vim --cmd "set errorformat=%f:%l:%c:%m" -q ' + t.name): |
|
105 | 99 | raise TryNext() |
|
106 | 100 | finally: |
|
107 | 101 | t.close() |
|
108 | 102 | |
|
109 | 103 | |
|
110 | 104 | def synchronize_with_editor(self, filename, linenum, column): |
|
111 | 105 | pass |
|
112 | 106 | |
|
113 | 107 | |
|
114 | 108 | class CommandChainDispatcher: |
|
115 | 109 | """ Dispatch calls to a chain of commands until some func can handle it |
|
116 | 110 | |
|
117 | 111 | Usage: instantiate, execute "add" to add commands (with optional |
|
118 | 112 | priority), execute normally via f() calling mechanism. |
|
119 | 113 | |
|
120 | 114 | """ |
|
121 | 115 | def __init__(self,commands=None): |
|
122 | 116 | if commands is None: |
|
123 | 117 | self.chain = [] |
|
124 | 118 | else: |
|
125 | 119 | self.chain = commands |
|
126 | 120 | |
|
127 | 121 | |
|
128 | 122 | def __call__(self,*args, **kw): |
|
129 | 123 | """ Command chain is called just like normal func. |
|
130 | 124 | |
|
131 | 125 | This will call all funcs in chain with the same args as were given to |
|
132 | 126 | this function, and return the result of first func that didn't raise |
|
133 | 127 | TryNext""" |
|
134 | 128 | last_exc = TryNext() |
|
135 | 129 | for prio,cmd in self.chain: |
|
136 | 130 | #print "prio",prio,"cmd",cmd #dbg |
|
137 | 131 | try: |
|
138 | 132 | return cmd(*args, **kw) |
|
139 | 133 | except TryNext as exc: |
|
140 | 134 | last_exc = exc |
|
141 | 135 | # if no function will accept it, raise TryNext up to the caller |
|
142 | 136 | raise last_exc |
|
143 | 137 | |
|
144 | 138 | def __str__(self): |
|
145 | 139 | return str(self.chain) |
|
146 | 140 | |
|
147 | 141 | def add(self, func, priority=0): |
|
148 | 142 | """ Add a func to the cmd chain with given priority """ |
|
149 | 143 | self.chain.append((priority, func)) |
|
150 | 144 | self.chain.sort(key=lambda x: x[0]) |
|
151 | 145 | |
|
152 | 146 | def __iter__(self): |
|
153 | 147 | """ Return all objects in chain. |
|
154 | 148 | |
|
155 | 149 | Handy if the objects are not callable. |
|
156 | 150 | """ |
|
157 | 151 | return iter(self.chain) |
|
158 | 152 | |
|
159 | 153 | |
|
160 | 154 | def input_prefilter(self,line): |
|
161 | 155 | """ Default input prefilter |
|
162 | 156 | |
|
163 | 157 | This returns the line as unchanged, so that the interpreter |
|
164 | 158 | knows that nothing was done and proceeds with "classic" prefiltering |
|
165 | 159 | (%magics, !shell commands etc.). |
|
166 | 160 | |
|
167 | 161 | Note that leading whitespace is not passed to this hook. Prefilter |
|
168 | 162 | can't alter indentation. |
|
169 | 163 | |
|
170 | 164 | """ |
|
171 | 165 | #print "attempt to rewrite",line #dbg |
|
172 | 166 | return line |
|
173 | 167 | |
|
174 | 168 | |
|
175 | 169 | def shutdown_hook(self): |
|
176 | 170 | """ default shutdown hook |
|
177 | 171 | |
|
178 | 172 | Typically, shotdown hooks should raise TryNext so all shutdown ops are done |
|
179 | 173 | """ |
|
180 | 174 | |
|
181 | 175 | #print "default shutdown hook ok" # dbg |
|
182 | 176 | return |
|
183 | 177 | |
|
184 | 178 | |
|
185 | 179 | def late_startup_hook(self): |
|
186 | 180 | """ Executed after ipython has been constructed and configured |
|
187 | 181 | |
|
188 | 182 | """ |
|
189 | 183 | #print "default startup hook ok" # dbg |
|
190 | 184 | |
|
191 | 185 | |
|
192 | 186 | def show_in_pager(self,s): |
|
193 | 187 | """ Run a string through pager """ |
|
194 | 188 | # raising TryNext here will use the default paging functionality |
|
195 | 189 | raise TryNext |
|
196 | 190 | |
|
197 | 191 | |
|
198 | 192 | def pre_prompt_hook(self): |
|
199 | 193 | """ Run before displaying the next prompt |
|
200 | 194 | |
|
201 | 195 | Use this e.g. to display output from asynchronous operations (in order |
|
202 | 196 | to not mess up text entry) |
|
203 | 197 | """ |
|
204 | 198 | |
|
205 | 199 | return None |
|
206 | 200 | |
|
207 | 201 | |
|
208 | 202 | def pre_run_code_hook(self): |
|
209 | 203 | """ Executed before running the (prefiltered) code in IPython """ |
|
210 | 204 | return None |
|
211 | 205 | |
|
212 | 206 | |
|
213 | 207 | def clipboard_get(self): |
|
214 | 208 | """ Get text from the clipboard. |
|
215 | 209 | """ |
|
216 | 210 | from IPython.lib.clipboard import ( |
|
217 | 211 | osx_clipboard_get, tkinter_clipboard_get, |
|
218 | 212 | win32_clipboard_get |
|
219 | 213 | ) |
|
220 | 214 | if sys.platform == 'win32': |
|
221 | 215 | chain = [win32_clipboard_get, tkinter_clipboard_get] |
|
222 | 216 | elif sys.platform == 'darwin': |
|
223 | 217 | chain = [osx_clipboard_get, tkinter_clipboard_get] |
|
224 | 218 | else: |
|
225 | 219 | chain = [tkinter_clipboard_get] |
|
226 | 220 | dispatcher = CommandChainDispatcher() |
|
227 | 221 | for func in chain: |
|
228 | 222 | dispatcher.add(func) |
|
229 | 223 | text = dispatcher() |
|
230 | 224 | return text |
|
1 | 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 | 1 | """Implementation of magic functions related to History. |
|
2 | 2 | """ |
|
3 | 3 | #----------------------------------------------------------------------------- |
|
4 | 4 | # Copyright (c) 2012, IPython Development Team. |
|
5 | 5 | # |
|
6 | 6 | # Distributed under the terms of the Modified BSD License. |
|
7 | 7 | # |
|
8 | 8 | # The full license is in the file COPYING.txt, distributed with this software. |
|
9 | 9 | #----------------------------------------------------------------------------- |
|
10 | 10 | |
|
11 | 11 | #----------------------------------------------------------------------------- |
|
12 | 12 | # Imports |
|
13 | 13 | #----------------------------------------------------------------------------- |
|
14 | 14 | from __future__ import print_function |
|
15 | 15 | |
|
16 | 16 | # Stdlib |
|
17 | 17 | import os |
|
18 | 18 | from io import open as io_open |
|
19 | 19 | from IPython.external.argparse import Action |
|
20 | 20 | |
|
21 | 21 | # Our own packages |
|
22 | 22 | from IPython.core.error import StdinNotImplementedError |
|
23 | 23 | from IPython.core.magic import Magics, magics_class, line_magic |
|
24 | 24 | from IPython.core.magic_arguments import (argument, magic_arguments, |
|
25 | 25 | parse_argstring) |
|
26 | 26 | from IPython.testing.skipdoctest import skip_doctest |
|
27 | 27 | from IPython.utils import io |
|
28 | 28 | |
|
29 | 29 | #----------------------------------------------------------------------------- |
|
30 | 30 | # Magics class implementation |
|
31 | 31 | #----------------------------------------------------------------------------- |
|
32 | 32 | |
|
33 | 33 | |
|
34 | 34 | _unspecified = object() |
|
35 | 35 | |
|
36 | 36 | |
|
37 | 37 | @magics_class |
|
38 | 38 | class HistoryMagics(Magics): |
|
39 | 39 | |
|
40 | 40 | @magic_arguments() |
|
41 | 41 | @argument( |
|
42 | 42 | '-n', dest='print_nums', action='store_true', default=False, |
|
43 | 43 | help=""" |
|
44 | 44 | print line numbers for each input. |
|
45 | 45 | This feature is only available if numbered prompts are in use. |
|
46 | 46 | """) |
|
47 | 47 | @argument( |
|
48 | 48 | '-o', dest='get_output', action='store_true', default=False, |
|
49 | 49 | help="also print outputs for each input.") |
|
50 | 50 | @argument( |
|
51 | 51 | '-p', dest='pyprompts', action='store_true', default=False, |
|
52 | 52 | help=""" |
|
53 | 53 | print classic '>>>' python prompts before each input. |
|
54 | 54 | This is useful for making documentation, and in conjunction |
|
55 | 55 | with -o, for producing doctest-ready output. |
|
56 | 56 | """) |
|
57 | 57 | @argument( |
|
58 | 58 | '-t', dest='raw', action='store_false', default=True, |
|
59 | 59 | help=""" |
|
60 | 60 | print the 'translated' history, as IPython understands it. |
|
61 | 61 | IPython filters your input and converts it all into valid Python |
|
62 | 62 | source before executing it (things like magics or aliases are turned |
|
63 | 63 | into function calls, for example). With this option, you'll see the |
|
64 | 64 | native history instead of the user-entered version: '%%cd /' will be |
|
65 | 65 | seen as 'get_ipython().magic("%%cd /")' instead of '%%cd /'. |
|
66 | 66 | """) |
|
67 | 67 | @argument( |
|
68 | 68 | '-f', dest='filename', |
|
69 | 69 | help=""" |
|
70 | 70 | FILENAME: instead of printing the output to the screen, redirect |
|
71 | 71 | it to the given file. The file is always overwritten, though *when |
|
72 | 72 | it can*, IPython asks for confirmation first. In particular, running |
|
73 | 73 | the command 'history -f FILENAME' from the IPython Notebook |
|
74 | 74 | interface will replace FILENAME even if it already exists *without* |
|
75 | 75 | confirmation. |
|
76 | 76 | """) |
|
77 | 77 | @argument( |
|
78 | 78 | '-g', dest='pattern', nargs='*', default=None, |
|
79 | 79 | help=""" |
|
80 | 80 | treat the arg as a glob pattern to search for in (full) history. |
|
81 | 81 | This includes the saved history (almost all commands ever written). |
|
82 | 82 | The pattern may contain '?' to match one unknown character and '*' |
|
83 | 83 | to match any number of unknown characters. Use '%%hist -g' to show |
|
84 | 84 | full saved history (may be very long). |
|
85 | 85 | """) |
|
86 | 86 | @argument( |
|
87 | 87 | '-l', dest='limit', type=int, nargs='?', default=_unspecified, |
|
88 | 88 | help=""" |
|
89 | 89 | get the last n lines from all sessions. Specify n as a single |
|
90 | 90 | arg, or the default is the last 10 lines. |
|
91 | 91 | """) |
|
92 | 92 | @argument( |
|
93 | 93 | '-u', dest='unique', action='store_true', |
|
94 | 94 | help=""" |
|
95 | 95 | when searching history using `-g`, show only unique history. |
|
96 | 96 | """) |
|
97 | 97 | @argument('range', nargs='*') |
|
98 | 98 | @skip_doctest |
|
99 | 99 | @line_magic |
|
100 | 100 | def history(self, parameter_s = ''): |
|
101 | 101 | """Print input history (_i<n> variables), with most recent last. |
|
102 | 102 | |
|
103 | 103 | By default, input history is printed without line numbers so it can be |
|
104 | 104 | directly pasted into an editor. Use -n to show them. |
|
105 | 105 | |
|
106 | 106 | By default, all input history from the current session is displayed. |
|
107 | 107 | Ranges of history can be indicated using the syntax: |
|
108 | 4 : Line 4, current session | |
|
109 | 4-6 : Lines 4-6, current session | |
|
110 |
|
|
|
111 | ~2/7 : Line 7, session 2 before current | |
|
112 | ~8/1-~6/5 : From the first line of 8 sessions ago, to the fifth line | |
|
113 | of 6 sessions ago. | |
|
108 | ||
|
109 | ``4`` | |
|
110 | Line 4, current session | |
|
111 | ``4-6`` | |
|
112 | Lines 4-6, current session | |
|
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 | 121 | Multiple ranges can be entered, separated by spaces |
|
115 | 122 | |
|
116 | 123 | The same syntax is used by %macro, %save, %edit, %rerun |
|
117 | 124 | |
|
118 | 125 | Examples |
|
119 | 126 | -------- |
|
120 | 127 | :: |
|
121 | 128 | |
|
122 | 129 | In [6]: %history -n 4-6 |
|
123 | 130 | 4:a = 12 |
|
124 | 131 | 5:print a**2 |
|
125 | 132 | 6:%history -n 4-6 |
|
126 | 133 | |
|
127 | 134 | """ |
|
128 | 135 | |
|
129 | 136 | args = parse_argstring(self.history, parameter_s) |
|
130 | 137 | |
|
131 | 138 | # For brevity |
|
132 | 139 | history_manager = self.shell.history_manager |
|
133 | 140 | |
|
134 | 141 | def _format_lineno(session, line): |
|
135 | 142 | """Helper function to format line numbers properly.""" |
|
136 | 143 | if session in (0, history_manager.session_number): |
|
137 | 144 | return str(line) |
|
138 | 145 | return "%s/%s" % (session, line) |
|
139 | 146 | |
|
140 | 147 | # Check if output to specific file was requested. |
|
141 | 148 | outfname = args.filename |
|
142 | 149 | if not outfname: |
|
143 | 150 | outfile = io.stdout # default |
|
144 | 151 | # We don't want to close stdout at the end! |
|
145 | 152 | close_at_end = False |
|
146 | 153 | else: |
|
147 | 154 | if os.path.exists(outfname): |
|
148 | 155 | try: |
|
149 | 156 | ans = io.ask_yes_no("File %r exists. Overwrite?" % outfname) |
|
150 | 157 | except StdinNotImplementedError: |
|
151 | 158 | ans = True |
|
152 | 159 | if not ans: |
|
153 | 160 | print('Aborting.') |
|
154 | 161 | return |
|
155 | 162 | print("Overwriting file.") |
|
156 | 163 | outfile = io_open(outfname, 'w', encoding='utf-8') |
|
157 | 164 | close_at_end = True |
|
158 | 165 | |
|
159 | 166 | print_nums = args.print_nums |
|
160 | 167 | get_output = args.get_output |
|
161 | 168 | pyprompts = args.pyprompts |
|
162 | 169 | raw = args.raw |
|
163 | 170 | |
|
164 | 171 | pattern = None |
|
165 | 172 | limit = None if args.limit is _unspecified else args.limit |
|
166 | 173 | |
|
167 | 174 | if args.pattern is not None: |
|
168 | 175 | if args.pattern: |
|
169 | 176 | pattern = "*" + " ".join(args.pattern) + "*" |
|
170 | 177 | else: |
|
171 | 178 | pattern = "*" |
|
172 | 179 | hist = history_manager.search(pattern, raw=raw, output=get_output, |
|
173 | 180 | n=limit, unique=args.unique) |
|
174 | 181 | print_nums = True |
|
175 | 182 | elif args.limit is not _unspecified: |
|
176 | 183 | n = 10 if limit is None else limit |
|
177 | 184 | hist = history_manager.get_tail(n, raw=raw, output=get_output) |
|
178 | 185 | else: |
|
179 | 186 | if args.range: # Get history by ranges |
|
180 | 187 | hist = history_manager.get_range_by_str(" ".join(args.range), |
|
181 | 188 | raw, get_output) |
|
182 | 189 | else: # Just get history for the current session |
|
183 | 190 | hist = history_manager.get_range(raw=raw, output=get_output) |
|
184 | 191 | |
|
185 | 192 | # We could be displaying the entire history, so let's not try to pull |
|
186 | 193 | # it into a list in memory. Anything that needs more space will just |
|
187 | 194 | # misalign. |
|
188 | 195 | width = 4 |
|
189 | 196 | |
|
190 | 197 | for session, lineno, inline in hist: |
|
191 | 198 | # Print user history with tabs expanded to 4 spaces. The GUI |
|
192 | 199 | # clients use hard tabs for easier usability in auto-indented code, |
|
193 | 200 | # but we want to produce PEP-8 compliant history for safe pasting |
|
194 | 201 | # into an editor. |
|
195 | 202 | if get_output: |
|
196 | 203 | inline, output = inline |
|
197 | 204 | inline = inline.expandtabs(4).rstrip() |
|
198 | 205 | |
|
199 | 206 | multiline = "\n" in inline |
|
200 | 207 | line_sep = '\n' if multiline else ' ' |
|
201 | 208 | if print_nums: |
|
202 | 209 | print(u'%s:%s' % (_format_lineno(session, lineno).rjust(width), |
|
203 | 210 | line_sep), file=outfile, end=u'') |
|
204 | 211 | if pyprompts: |
|
205 | 212 | print(u">>> ", end=u"", file=outfile) |
|
206 | 213 | if multiline: |
|
207 | 214 | inline = "\n... ".join(inline.splitlines()) + "\n..." |
|
208 | 215 | print(inline, file=outfile) |
|
209 | 216 | if get_output and output: |
|
210 | 217 | print(output, file=outfile) |
|
211 | 218 | |
|
212 | 219 | if close_at_end: |
|
213 | 220 | outfile.close() |
|
214 | 221 | |
|
215 | 222 | @line_magic |
|
216 | 223 | def recall(self, arg): |
|
217 | 224 | r"""Repeat a command, or get command to input line for editing. |
|
218 | 225 | |
|
219 | 226 | %recall and %rep are equivalent. |
|
220 | 227 | |
|
221 | 228 | - %recall (no arguments): |
|
222 | 229 | |
|
223 | 230 | Place a string version of last computation result (stored in the |
|
224 | 231 | special '_' variable) to the next input prompt. Allows you to create |
|
225 | 232 | elaborate command lines without using copy-paste:: |
|
226 | 233 | |
|
227 | 234 | In[1]: l = ["hei", "vaan"] |
|
228 | 235 | In[2]: "".join(l) |
|
229 | 236 | Out[2]: heivaan |
|
230 | 237 | In[3]: %recall |
|
231 | 238 | In[4]: heivaan_ <== cursor blinking |
|
232 | 239 | |
|
233 | 240 | %recall 45 |
|
234 | 241 | |
|
235 | 242 | Place history line 45 on the next input prompt. Use %hist to find |
|
236 | 243 | out the number. |
|
237 | 244 | |
|
238 | 245 | %recall 1-4 |
|
239 | 246 | |
|
240 | 247 | Combine the specified lines into one cell, and place it on the next |
|
241 | 248 | input prompt. See %history for the slice syntax. |
|
242 | 249 | |
|
243 | 250 | %recall foo+bar |
|
244 | 251 | |
|
245 | 252 | If foo+bar can be evaluated in the user namespace, the result is |
|
246 | 253 | placed at the next input prompt. Otherwise, the history is searched |
|
247 | 254 | for lines which contain that substring, and the most recent one is |
|
248 | 255 | placed at the next input prompt. |
|
249 | 256 | """ |
|
250 | 257 | if not arg: # Last output |
|
251 | 258 | self.shell.set_next_input(str(self.shell.user_ns["_"])) |
|
252 | 259 | return |
|
253 | 260 | # Get history range |
|
254 | 261 | histlines = self.shell.history_manager.get_range_by_str(arg) |
|
255 | 262 | cmd = "\n".join(x[2] for x in histlines) |
|
256 | 263 | if cmd: |
|
257 | 264 | self.shell.set_next_input(cmd.rstrip()) |
|
258 | 265 | return |
|
259 | 266 | |
|
260 | 267 | try: # Variable in user namespace |
|
261 | 268 | cmd = str(eval(arg, self.shell.user_ns)) |
|
262 | 269 | except Exception: # Search for term in history |
|
263 | 270 | histlines = self.shell.history_manager.search("*"+arg+"*") |
|
264 | 271 | for h in reversed([x[2] for x in histlines]): |
|
265 | 272 | if 'recall' in h or 'rep' in h: |
|
266 | 273 | continue |
|
267 | 274 | self.shell.set_next_input(h.rstrip()) |
|
268 | 275 | return |
|
269 | 276 | else: |
|
270 | 277 | self.shell.set_next_input(cmd.rstrip()) |
|
271 | 278 | print("Couldn't evaluate or find in history:", arg) |
|
272 | 279 | |
|
273 | 280 | @line_magic |
|
274 | 281 | def rerun(self, parameter_s=''): |
|
275 | 282 | """Re-run previous input |
|
276 | 283 | |
|
277 | 284 | By default, you can specify ranges of input history to be repeated |
|
278 | 285 | (as with %history). With no arguments, it will repeat the last line. |
|
279 | 286 | |
|
280 | 287 | Options: |
|
281 | 288 | |
|
282 | 289 | -l <n> : Repeat the last n lines of input, not including the |
|
283 | 290 | current command. |
|
284 | 291 | |
|
285 | 292 | -g foo : Repeat the most recent line which contains foo |
|
286 | 293 | """ |
|
287 | 294 | opts, args = self.parse_options(parameter_s, 'l:g:', mode='string') |
|
288 | 295 | if "l" in opts: # Last n lines |
|
289 | 296 | n = int(opts['l']) |
|
290 | 297 | hist = self.shell.history_manager.get_tail(n) |
|
291 | 298 | elif "g" in opts: # Search |
|
292 | 299 | p = "*"+opts['g']+"*" |
|
293 | 300 | hist = list(self.shell.history_manager.search(p)) |
|
294 | 301 | for l in reversed(hist): |
|
295 | 302 | if "rerun" not in l[2]: |
|
296 | 303 | hist = [l] # The last match which isn't a %rerun |
|
297 | 304 | break |
|
298 | 305 | else: |
|
299 | 306 | hist = [] # No matches except %rerun |
|
300 | 307 | elif args: # Specify history ranges |
|
301 | 308 | hist = self.shell.history_manager.get_range_by_str(args) |
|
302 | 309 | else: # Last line |
|
303 | 310 | hist = self.shell.history_manager.get_tail(1) |
|
304 | 311 | hist = [x[2] for x in hist] |
|
305 | 312 | if not hist: |
|
306 | 313 | print("No lines in history match specification") |
|
307 | 314 | return |
|
308 | 315 | histlines = "\n".join(hist) |
|
309 | 316 | print("=== Executing: ===") |
|
310 | 317 | print(histlines) |
|
311 | 318 | print("=== Output: ===") |
|
312 | 319 | self.shell.run_cell("\n".join(hist), store_history=False) |
@@ -1,96 +1,96 b'' | |||
|
1 | 1 | # encoding: utf-8 |
|
2 | 2 | """ |
|
3 | 3 | A payload based version of page. |
|
4 | 4 | |
|
5 | 5 | Authors: |
|
6 | 6 | |
|
7 | 7 | * Brian Granger |
|
8 | 8 | * Fernando Perez |
|
9 | 9 | """ |
|
10 | 10 | |
|
11 | 11 | #----------------------------------------------------------------------------- |
|
12 | 12 | # Copyright (C) 2008-2011 The IPython Development Team |
|
13 | 13 | # |
|
14 | 14 | # Distributed under the terms of the BSD License. The full license is in |
|
15 | 15 | # the file COPYING, distributed as part of this software. |
|
16 | 16 | #----------------------------------------------------------------------------- |
|
17 | 17 | |
|
18 | 18 | #----------------------------------------------------------------------------- |
|
19 | 19 | # Imports |
|
20 | 20 | #----------------------------------------------------------------------------- |
|
21 | 21 | |
|
22 | 22 | # Third-party |
|
23 | 23 | try: |
|
24 | 24 | from docutils.core import publish_string |
|
25 | 25 | except ImportError: |
|
26 | 26 | # html paging won't be available, but we don't raise any errors. It's a |
|
27 | 27 | # purely optional feature. |
|
28 | 28 | pass |
|
29 | 29 | |
|
30 | 30 | # Our own |
|
31 | 31 | from IPython.core.interactiveshell import InteractiveShell |
|
32 | 32 | |
|
33 | 33 | #----------------------------------------------------------------------------- |
|
34 | 34 | # Classes and functions |
|
35 | 35 | #----------------------------------------------------------------------------- |
|
36 | 36 | |
|
37 | 37 | def page(strng, start=0, screen_lines=0, pager_cmd=None, |
|
38 | 38 | html=None, auto_html=False): |
|
39 | 39 | """Print a string, piping through a pager. |
|
40 | 40 | |
|
41 | 41 | This version ignores the screen_lines and pager_cmd arguments and uses |
|
42 | 42 | IPython's payload system instead. |
|
43 | 43 | |
|
44 | 44 | Parameters |
|
45 | 45 | ---------- |
|
46 | 46 | strng : str |
|
47 | 47 | Text to page. |
|
48 | 48 | |
|
49 | 49 | start : int |
|
50 | 50 | Starting line at which to place the display. |
|
51 | 51 | |
|
52 | 52 | html : str, optional |
|
53 | 53 | If given, an html string to send as well. |
|
54 | 54 | |
|
55 | 55 | auto_html : bool, optional |
|
56 | 56 | If true, the input string is assumed to be valid reStructuredText and is |
|
57 | 57 | converted to HTML with docutils. Note that if docutils is not found, |
|
58 | 58 | this option is silently ignored. |
|
59 | 59 | |
|
60 | Note | |
|
61 | ---- | |
|
60 | Notes | |
|
61 | ----- | |
|
62 | 62 | |
|
63 | 63 | Only one of the ``html`` and ``auto_html`` options can be given, not |
|
64 | 64 | both. |
|
65 | 65 | """ |
|
66 | 66 | |
|
67 | 67 | # Some routines may auto-compute start offsets incorrectly and pass a |
|
68 | 68 | # negative value. Offset to 0 for robustness. |
|
69 | 69 | start = max(0, start) |
|
70 | 70 | shell = InteractiveShell.instance() |
|
71 | 71 | |
|
72 | 72 | if auto_html: |
|
73 | 73 | try: |
|
74 | 74 | # These defaults ensure user configuration variables for docutils |
|
75 | 75 | # are not loaded, only our config is used here. |
|
76 | 76 | defaults = {'file_insertion_enabled': 0, |
|
77 | 77 | 'raw_enabled': 0, |
|
78 | 78 | '_disable_config': 1} |
|
79 | 79 | html = publish_string(strng, writer_name='html', |
|
80 | 80 | settings_overrides=defaults) |
|
81 | 81 | except: |
|
82 | 82 | pass |
|
83 | 83 | |
|
84 | 84 | payload = dict( |
|
85 | 85 | source='IPython.zmq.page.page', |
|
86 | 86 | text=strng, |
|
87 | 87 | html=html, |
|
88 | 88 | start_line_number=start |
|
89 | 89 | ) |
|
90 | 90 | shell.payload_manager.write_payload(payload) |
|
91 | 91 | |
|
92 | 92 | |
|
93 | 93 | def install_payload_page(): |
|
94 | 94 | """Install this version of page as IPython.core.page.page.""" |
|
95 | 95 | from IPython.core import page as corepage |
|
96 | 96 | corepage.page = page |
@@ -1,1247 +1,1247 b'' | |||
|
1 | 1 | # -*- coding: utf-8 -*- |
|
2 | 2 | """ |
|
3 | 3 | ultratb.py -- Spice up your tracebacks! |
|
4 | 4 | |
|
5 | 5 | * ColorTB |
|
6 | 6 | I've always found it a bit hard to visually parse tracebacks in Python. The |
|
7 | 7 | ColorTB class is a solution to that problem. It colors the different parts of a |
|
8 | 8 | traceback in a manner similar to what you would expect from a syntax-highlighting |
|
9 | 9 | text editor. |
|
10 | 10 | |
|
11 | 11 | Installation instructions for ColorTB: |
|
12 | 12 | import sys,ultratb |
|
13 | 13 | sys.excepthook = ultratb.ColorTB() |
|
14 | 14 | |
|
15 | 15 | * VerboseTB |
|
16 | 16 | I've also included a port of Ka-Ping Yee's "cgitb.py" that produces all kinds |
|
17 | 17 | of useful info when a traceback occurs. Ping originally had it spit out HTML |
|
18 | 18 | and intended it for CGI programmers, but why should they have all the fun? I |
|
19 | 19 | altered it to spit out colored text to the terminal. It's a bit overwhelming, |
|
20 | 20 | but kind of neat, and maybe useful for long-running programs that you believe |
|
21 | 21 | are bug-free. If a crash *does* occur in that type of program you want details. |
|
22 | 22 | Give it a shot--you'll love it or you'll hate it. |
|
23 | 23 | |
|
24 | 24 | Note: |
|
25 | 25 | |
|
26 | 26 | The Verbose mode prints the variables currently visible where the exception |
|
27 | 27 | happened (shortening their strings if too long). This can potentially be |
|
28 | 28 | very slow, if you happen to have a huge data structure whose string |
|
29 | 29 | representation is complex to compute. Your computer may appear to freeze for |
|
30 | 30 | a while with cpu usage at 100%. If this occurs, you can cancel the traceback |
|
31 | 31 | with Ctrl-C (maybe hitting it more than once). |
|
32 | 32 | |
|
33 | 33 | If you encounter this kind of situation often, you may want to use the |
|
34 | 34 | Verbose_novars mode instead of the regular Verbose, which avoids formatting |
|
35 | 35 | variables (but otherwise includes the information and context given by |
|
36 | 36 | Verbose). |
|
37 | 37 | |
|
38 | 38 | |
|
39 | 39 | Installation instructions for ColorTB: |
|
40 | 40 | import sys,ultratb |
|
41 | 41 | sys.excepthook = ultratb.VerboseTB() |
|
42 | 42 | |
|
43 | 43 | Note: Much of the code in this module was lifted verbatim from the standard |
|
44 | 44 | library module 'traceback.py' and Ka-Ping Yee's 'cgitb.py'. |
|
45 | 45 | |
|
46 | 46 | * Color schemes |
|
47 | 47 | The colors are defined in the class TBTools through the use of the |
|
48 | 48 | ColorSchemeTable class. Currently the following exist: |
|
49 | 49 | |
|
50 | 50 | - NoColor: allows all of this module to be used in any terminal (the color |
|
51 | 51 | escapes are just dummy blank strings). |
|
52 | 52 | |
|
53 | 53 | - Linux: is meant to look good in a terminal like the Linux console (black |
|
54 | 54 | or very dark background). |
|
55 | 55 | |
|
56 | 56 | - LightBG: similar to Linux but swaps dark/light colors to be more readable |
|
57 | 57 | in light background terminals. |
|
58 | 58 | |
|
59 | 59 | You can implement other color schemes easily, the syntax is fairly |
|
60 | 60 | self-explanatory. Please send back new schemes you develop to the author for |
|
61 | 61 | possible inclusion in future releases. |
|
62 | 62 | |
|
63 | 63 | Inheritance diagram: |
|
64 | 64 | |
|
65 | 65 | .. inheritance-diagram:: IPython.core.ultratb |
|
66 | 66 | :parts: 3 |
|
67 | 67 | """ |
|
68 | 68 | |
|
69 | 69 | #***************************************************************************** |
|
70 | 70 | # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu> |
|
71 | 71 | # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu> |
|
72 | 72 | # |
|
73 | 73 | # Distributed under the terms of the BSD License. The full license is in |
|
74 | 74 | # the file COPYING, distributed as part of this software. |
|
75 | 75 | #***************************************************************************** |
|
76 | 76 | |
|
77 | 77 | from __future__ import unicode_literals |
|
78 | 78 | |
|
79 | 79 | import inspect |
|
80 | 80 | import keyword |
|
81 | 81 | import linecache |
|
82 | 82 | import os |
|
83 | 83 | import pydoc |
|
84 | 84 | import re |
|
85 | 85 | import sys |
|
86 | 86 | import time |
|
87 | 87 | import tokenize |
|
88 | 88 | import traceback |
|
89 | 89 | import types |
|
90 | 90 | |
|
91 | 91 | try: # Python 2 |
|
92 | 92 | generate_tokens = tokenize.generate_tokens |
|
93 | 93 | except AttributeError: # Python 3 |
|
94 | 94 | generate_tokens = tokenize.tokenize |
|
95 | 95 | |
|
96 | 96 | # For purposes of monkeypatching inspect to fix a bug in it. |
|
97 | 97 | from inspect import getsourcefile, getfile, getmodule,\ |
|
98 | 98 | ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode |
|
99 | 99 | |
|
100 | 100 | # IPython's own modules |
|
101 | 101 | # Modified pdb which doesn't damage IPython's readline handling |
|
102 | 102 | from IPython.core import debugger, ipapi |
|
103 | 103 | from IPython.core.display_trap import DisplayTrap |
|
104 | 104 | from IPython.core.excolors import exception_colors |
|
105 | 105 | from IPython.utils import PyColorize |
|
106 | 106 | from IPython.utils import io |
|
107 | 107 | from IPython.utils import path as util_path |
|
108 | 108 | from IPython.utils import py3compat |
|
109 | 109 | from IPython.utils import pyfile |
|
110 | 110 | from IPython.utils import ulinecache |
|
111 | 111 | from IPython.utils.data import uniq_stable |
|
112 | 112 | from IPython.utils.openpy import read_py_file |
|
113 | 113 | from IPython.utils.warn import info, error |
|
114 | 114 | |
|
115 | 115 | # Globals |
|
116 | 116 | # amount of space to put line numbers before verbose tracebacks |
|
117 | 117 | INDENT_SIZE = 8 |
|
118 | 118 | |
|
119 | 119 | # Default color scheme. This is used, for example, by the traceback |
|
120 | 120 | # formatter. When running in an actual IPython instance, the user's rc.colors |
|
121 | 121 | # value is used, but havinga module global makes this functionality available |
|
122 | 122 | # to users of ultratb who are NOT running inside ipython. |
|
123 | 123 | DEFAULT_SCHEME = 'NoColor' |
|
124 | 124 | |
|
125 | 125 | #--------------------------------------------------------------------------- |
|
126 | 126 | # Code begins |
|
127 | 127 | |
|
128 | 128 | # Utility functions |
|
129 | 129 | def inspect_error(): |
|
130 | 130 | """Print a message about internal inspect errors. |
|
131 | 131 | |
|
132 | 132 | These are unfortunately quite common.""" |
|
133 | 133 | |
|
134 | 134 | error('Internal Python error in the inspect module.\n' |
|
135 | 135 | 'Below is the traceback from this internal error.\n') |
|
136 | 136 | |
|
137 | 137 | # This function is a monkeypatch we apply to the Python inspect module. We have |
|
138 | 138 | # now found when it's needed (see discussion on issue gh-1456), and we have a |
|
139 | 139 | # test case (IPython.core.tests.test_ultratb.ChangedPyFileTest) that fails if |
|
140 | 140 | # the monkeypatch is not applied. TK, Aug 2012. |
|
141 | 141 | def findsource(object): |
|
142 | 142 | """Return the entire source file and starting line number for an object. |
|
143 | 143 | |
|
144 | 144 | The argument may be a module, class, method, function, traceback, frame, |
|
145 | 145 | or code object. The source code is returned as a list of all the lines |
|
146 | 146 | in the file and the line number indexes a line in that list. An IOError |
|
147 | 147 | is raised if the source code cannot be retrieved. |
|
148 | 148 | |
|
149 | 149 | FIXED version with which we monkeypatch the stdlib to work around a bug.""" |
|
150 | 150 | |
|
151 | 151 | file = getsourcefile(object) or getfile(object) |
|
152 | 152 | # If the object is a frame, then trying to get the globals dict from its |
|
153 | 153 | # module won't work. Instead, the frame object itself has the globals |
|
154 | 154 | # dictionary. |
|
155 | 155 | globals_dict = None |
|
156 | 156 | if inspect.isframe(object): |
|
157 | 157 | # XXX: can this ever be false? |
|
158 | 158 | globals_dict = object.f_globals |
|
159 | 159 | else: |
|
160 | 160 | module = getmodule(object, file) |
|
161 | 161 | if module: |
|
162 | 162 | globals_dict = module.__dict__ |
|
163 | 163 | lines = linecache.getlines(file, globals_dict) |
|
164 | 164 | if not lines: |
|
165 | 165 | raise IOError('could not get source code') |
|
166 | 166 | |
|
167 | 167 | if ismodule(object): |
|
168 | 168 | return lines, 0 |
|
169 | 169 | |
|
170 | 170 | if isclass(object): |
|
171 | 171 | name = object.__name__ |
|
172 | 172 | pat = re.compile(r'^(\s*)class\s*' + name + r'\b') |
|
173 | 173 | # make some effort to find the best matching class definition: |
|
174 | 174 | # use the one with the least indentation, which is the one |
|
175 | 175 | # that's most probably not inside a function definition. |
|
176 | 176 | candidates = [] |
|
177 | 177 | for i in range(len(lines)): |
|
178 | 178 | match = pat.match(lines[i]) |
|
179 | 179 | if match: |
|
180 | 180 | # if it's at toplevel, it's already the best one |
|
181 | 181 | if lines[i][0] == 'c': |
|
182 | 182 | return lines, i |
|
183 | 183 | # else add whitespace to candidate list |
|
184 | 184 | candidates.append((match.group(1), i)) |
|
185 | 185 | if candidates: |
|
186 | 186 | # this will sort by whitespace, and by line number, |
|
187 | 187 | # less whitespace first |
|
188 | 188 | candidates.sort() |
|
189 | 189 | return lines, candidates[0][1] |
|
190 | 190 | else: |
|
191 | 191 | raise IOError('could not find class definition') |
|
192 | 192 | |
|
193 | 193 | if ismethod(object): |
|
194 | 194 | object = object.im_func |
|
195 | 195 | if isfunction(object): |
|
196 | 196 | object = object.func_code |
|
197 | 197 | if istraceback(object): |
|
198 | 198 | object = object.tb_frame |
|
199 | 199 | if isframe(object): |
|
200 | 200 | object = object.f_code |
|
201 | 201 | if iscode(object): |
|
202 | 202 | if not hasattr(object, 'co_firstlineno'): |
|
203 | 203 | raise IOError('could not find function definition') |
|
204 | 204 | pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)') |
|
205 | 205 | pmatch = pat.match |
|
206 | 206 | # fperez - fix: sometimes, co_firstlineno can give a number larger than |
|
207 | 207 | # the length of lines, which causes an error. Safeguard against that. |
|
208 | 208 | lnum = min(object.co_firstlineno,len(lines))-1 |
|
209 | 209 | while lnum > 0: |
|
210 | 210 | if pmatch(lines[lnum]): break |
|
211 | 211 | lnum -= 1 |
|
212 | 212 | |
|
213 | 213 | return lines, lnum |
|
214 | 214 | raise IOError('could not find code object') |
|
215 | 215 | |
|
216 | 216 | # Monkeypatch inspect to apply our bugfix. This code only works with Python >= 2.5 |
|
217 | 217 | inspect.findsource = findsource |
|
218 | 218 | |
|
219 | 219 | def fix_frame_records_filenames(records): |
|
220 | 220 | """Try to fix the filenames in each record from inspect.getinnerframes(). |
|
221 | 221 | |
|
222 | 222 | Particularly, modules loaded from within zip files have useless filenames |
|
223 | 223 | attached to their code object, and inspect.getinnerframes() just uses it. |
|
224 | 224 | """ |
|
225 | 225 | fixed_records = [] |
|
226 | 226 | for frame, filename, line_no, func_name, lines, index in records: |
|
227 | 227 | # Look inside the frame's globals dictionary for __file__, which should |
|
228 | 228 | # be better. |
|
229 | 229 | better_fn = frame.f_globals.get('__file__', None) |
|
230 | 230 | if isinstance(better_fn, str): |
|
231 | 231 | # Check the type just in case someone did something weird with |
|
232 | 232 | # __file__. It might also be None if the error occurred during |
|
233 | 233 | # import. |
|
234 | 234 | filename = better_fn |
|
235 | 235 | fixed_records.append((frame, filename, line_no, func_name, lines, index)) |
|
236 | 236 | return fixed_records |
|
237 | 237 | |
|
238 | 238 | |
|
239 | 239 | def _fixed_getinnerframes(etb, context=1,tb_offset=0): |
|
240 | 240 | LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5 |
|
241 | 241 | |
|
242 | 242 | records = fix_frame_records_filenames(inspect.getinnerframes(etb, context)) |
|
243 | 243 | |
|
244 | 244 | # If the error is at the console, don't build any context, since it would |
|
245 | 245 | # otherwise produce 5 blank lines printed out (there is no file at the |
|
246 | 246 | # console) |
|
247 | 247 | rec_check = records[tb_offset:] |
|
248 | 248 | try: |
|
249 | 249 | rname = rec_check[0][1] |
|
250 | 250 | if rname == '<ipython console>' or rname.endswith('<string>'): |
|
251 | 251 | return rec_check |
|
252 | 252 | except IndexError: |
|
253 | 253 | pass |
|
254 | 254 | |
|
255 | 255 | aux = traceback.extract_tb(etb) |
|
256 | 256 | assert len(records) == len(aux) |
|
257 | 257 | for i, (file, lnum, _, _) in zip(range(len(records)), aux): |
|
258 | 258 | maybeStart = lnum-1 - context//2 |
|
259 | 259 | start = max(maybeStart, 0) |
|
260 | 260 | end = start + context |
|
261 | 261 | lines = ulinecache.getlines(file)[start:end] |
|
262 | 262 | buf = list(records[i]) |
|
263 | 263 | buf[LNUM_POS] = lnum |
|
264 | 264 | buf[INDEX_POS] = lnum - 1 - start |
|
265 | 265 | buf[LINES_POS] = lines |
|
266 | 266 | records[i] = tuple(buf) |
|
267 | 267 | return records[tb_offset:] |
|
268 | 268 | |
|
269 | 269 | # Helper function -- largely belongs to VerboseTB, but we need the same |
|
270 | 270 | # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they |
|
271 | 271 | # can be recognized properly by ipython.el's py-traceback-line-re |
|
272 | 272 | # (SyntaxErrors have to be treated specially because they have no traceback) |
|
273 | 273 | |
|
274 | 274 | _parser = PyColorize.Parser() |
|
275 | 275 | |
|
276 | 276 | def _format_traceback_lines(lnum, index, lines, Colors, lvals=None,scheme=None): |
|
277 | 277 | numbers_width = INDENT_SIZE - 1 |
|
278 | 278 | res = [] |
|
279 | 279 | i = lnum - index |
|
280 | 280 | |
|
281 | 281 | # This lets us get fully syntax-highlighted tracebacks. |
|
282 | 282 | if scheme is None: |
|
283 | 283 | ipinst = ipapi.get() |
|
284 | 284 | if ipinst is not None: |
|
285 | 285 | scheme = ipinst.colors |
|
286 | 286 | else: |
|
287 | 287 | scheme = DEFAULT_SCHEME |
|
288 | 288 | |
|
289 | 289 | _line_format = _parser.format2 |
|
290 | 290 | |
|
291 | 291 | for line in lines: |
|
292 | 292 | line = py3compat.cast_unicode(line) |
|
293 | 293 | |
|
294 | 294 | new_line, err = _line_format(line, 'str', scheme) |
|
295 | 295 | if not err: line = new_line |
|
296 | 296 | |
|
297 | 297 | if i == lnum: |
|
298 | 298 | # This is the line with the error |
|
299 | 299 | pad = numbers_width - len(str(i)) |
|
300 | 300 | if pad >= 3: |
|
301 | 301 | marker = '-'*(pad-3) + '-> ' |
|
302 | 302 | elif pad == 2: |
|
303 | 303 | marker = '> ' |
|
304 | 304 | elif pad == 1: |
|
305 | 305 | marker = '>' |
|
306 | 306 | else: |
|
307 | 307 | marker = '' |
|
308 | 308 | num = marker + str(i) |
|
309 | 309 | line = '%s%s%s %s%s' %(Colors.linenoEm, num, |
|
310 | 310 | Colors.line, line, Colors.Normal) |
|
311 | 311 | else: |
|
312 | 312 | num = '%*s' % (numbers_width,i) |
|
313 | 313 | line = '%s%s%s %s' %(Colors.lineno, num, |
|
314 | 314 | Colors.Normal, line) |
|
315 | 315 | |
|
316 | 316 | res.append(line) |
|
317 | 317 | if lvals and i == lnum: |
|
318 | 318 | res.append(lvals + '\n') |
|
319 | 319 | i = i + 1 |
|
320 | 320 | return res |
|
321 | 321 | |
|
322 | 322 | |
|
323 | 323 | #--------------------------------------------------------------------------- |
|
324 | 324 | # Module classes |
|
325 | 325 | class TBTools(object): |
|
326 | 326 | """Basic tools used by all traceback printer classes.""" |
|
327 | 327 | |
|
328 | 328 | # Number of frames to skip when reporting tracebacks |
|
329 | 329 | tb_offset = 0 |
|
330 | 330 | |
|
331 | 331 | def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None): |
|
332 | 332 | # Whether to call the interactive pdb debugger after printing |
|
333 | 333 | # tracebacks or not |
|
334 | 334 | self.call_pdb = call_pdb |
|
335 | 335 | |
|
336 | 336 | # Output stream to write to. Note that we store the original value in |
|
337 | 337 | # a private attribute and then make the public ostream a property, so |
|
338 | 338 | # that we can delay accessing io.stdout until runtime. The way |
|
339 | 339 | # things are written now, the io.stdout object is dynamically managed |
|
340 | 340 | # so a reference to it should NEVER be stored statically. This |
|
341 | 341 | # property approach confines this detail to a single location, and all |
|
342 | 342 | # subclasses can simply access self.ostream for writing. |
|
343 | 343 | self._ostream = ostream |
|
344 | 344 | |
|
345 | 345 | # Create color table |
|
346 | 346 | self.color_scheme_table = exception_colors() |
|
347 | 347 | |
|
348 | 348 | self.set_colors(color_scheme) |
|
349 | 349 | self.old_scheme = color_scheme # save initial value for toggles |
|
350 | 350 | |
|
351 | 351 | if call_pdb: |
|
352 | 352 | self.pdb = debugger.Pdb(self.color_scheme_table.active_scheme_name) |
|
353 | 353 | else: |
|
354 | 354 | self.pdb = None |
|
355 | 355 | |
|
356 | 356 | def _get_ostream(self): |
|
357 | 357 | """Output stream that exceptions are written to. |
|
358 | 358 | |
|
359 | 359 | Valid values are: |
|
360 | 360 | |
|
361 | 361 | - None: the default, which means that IPython will dynamically resolve |
|
362 | 362 | to io.stdout. This ensures compatibility with most tools, including |
|
363 | 363 | Windows (where plain stdout doesn't recognize ANSI escapes). |
|
364 | 364 | |
|
365 | 365 | - Any object with 'write' and 'flush' attributes. |
|
366 | 366 | """ |
|
367 | 367 | return io.stdout if self._ostream is None else self._ostream |
|
368 | 368 | |
|
369 | 369 | def _set_ostream(self, val): |
|
370 | 370 | assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush')) |
|
371 | 371 | self._ostream = val |
|
372 | 372 | |
|
373 | 373 | ostream = property(_get_ostream, _set_ostream) |
|
374 | 374 | |
|
375 | 375 | def set_colors(self,*args,**kw): |
|
376 | 376 | """Shorthand access to the color table scheme selector method.""" |
|
377 | 377 | |
|
378 | 378 | # Set own color table |
|
379 | 379 | self.color_scheme_table.set_active_scheme(*args,**kw) |
|
380 | 380 | # for convenience, set Colors to the active scheme |
|
381 | 381 | self.Colors = self.color_scheme_table.active_colors |
|
382 | 382 | # Also set colors of debugger |
|
383 | 383 | if hasattr(self,'pdb') and self.pdb is not None: |
|
384 | 384 | self.pdb.set_colors(*args,**kw) |
|
385 | 385 | |
|
386 | 386 | def color_toggle(self): |
|
387 | 387 | """Toggle between the currently active color scheme and NoColor.""" |
|
388 | 388 | |
|
389 | 389 | if self.color_scheme_table.active_scheme_name == 'NoColor': |
|
390 | 390 | self.color_scheme_table.set_active_scheme(self.old_scheme) |
|
391 | 391 | self.Colors = self.color_scheme_table.active_colors |
|
392 | 392 | else: |
|
393 | 393 | self.old_scheme = self.color_scheme_table.active_scheme_name |
|
394 | 394 | self.color_scheme_table.set_active_scheme('NoColor') |
|
395 | 395 | self.Colors = self.color_scheme_table.active_colors |
|
396 | 396 | |
|
397 | 397 | def stb2text(self, stb): |
|
398 | 398 | """Convert a structured traceback (a list) to a string.""" |
|
399 | 399 | return '\n'.join(stb) |
|
400 | 400 | |
|
401 | 401 | def text(self, etype, value, tb, tb_offset=None, context=5): |
|
402 | 402 | """Return formatted traceback. |
|
403 | 403 | |
|
404 | 404 | Subclasses may override this if they add extra arguments. |
|
405 | 405 | """ |
|
406 | 406 | tb_list = self.structured_traceback(etype, value, tb, |
|
407 | 407 | tb_offset, context) |
|
408 | 408 | return self.stb2text(tb_list) |
|
409 | 409 | |
|
410 | 410 | def structured_traceback(self, etype, evalue, tb, tb_offset=None, |
|
411 | 411 | context=5, mode=None): |
|
412 | 412 | """Return a list of traceback frames. |
|
413 | 413 | |
|
414 | 414 | Must be implemented by each class. |
|
415 | 415 | """ |
|
416 | 416 | raise NotImplementedError() |
|
417 | 417 | |
|
418 | 418 | |
|
419 | 419 | #--------------------------------------------------------------------------- |
|
420 | 420 | class ListTB(TBTools): |
|
421 | 421 | """Print traceback information from a traceback list, with optional color. |
|
422 | 422 | |
|
423 |
Calling |
|
|
424 | (etype, evalue, elist) | |
|
425 | as would be obtained by: | |
|
423 | Calling requires 3 arguments: (etype, evalue, elist) | |
|
424 | as would be obtained by:: | |
|
425 | ||
|
426 | 426 | etype, evalue, tb = sys.exc_info() |
|
427 | 427 | if tb: |
|
428 | 428 | elist = traceback.extract_tb(tb) |
|
429 | 429 | else: |
|
430 | 430 | elist = None |
|
431 | 431 | |
|
432 | 432 | It can thus be used by programs which need to process the traceback before |
|
433 | 433 | printing (such as console replacements based on the code module from the |
|
434 | 434 | standard library). |
|
435 | 435 | |
|
436 | 436 | Because they are meant to be called without a full traceback (only a |
|
437 | 437 | list), instances of this class can't call the interactive pdb debugger.""" |
|
438 | 438 | |
|
439 | 439 | def __init__(self,color_scheme = 'NoColor', call_pdb=False, ostream=None): |
|
440 | 440 | TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb, |
|
441 | 441 | ostream=ostream) |
|
442 | 442 | |
|
443 | 443 | def __call__(self, etype, value, elist): |
|
444 | 444 | self.ostream.flush() |
|
445 | 445 | self.ostream.write(self.text(etype, value, elist)) |
|
446 | 446 | self.ostream.write('\n') |
|
447 | 447 | |
|
448 | 448 | def structured_traceback(self, etype, value, elist, tb_offset=None, |
|
449 | 449 | context=5): |
|
450 | 450 | """Return a color formatted string with the traceback info. |
|
451 | 451 | |
|
452 | 452 | Parameters |
|
453 | 453 | ---------- |
|
454 | 454 | etype : exception type |
|
455 | 455 | Type of the exception raised. |
|
456 | 456 | |
|
457 | 457 | value : object |
|
458 | 458 | Data stored in the exception |
|
459 | 459 | |
|
460 | 460 | elist : list |
|
461 | 461 | List of frames, see class docstring for details. |
|
462 | 462 | |
|
463 | 463 | tb_offset : int, optional |
|
464 | 464 | Number of frames in the traceback to skip. If not given, the |
|
465 | 465 | instance value is used (set in constructor). |
|
466 | 466 | |
|
467 | 467 | context : int, optional |
|
468 | 468 | Number of lines of context information to print. |
|
469 | 469 | |
|
470 | 470 | Returns |
|
471 | 471 | ------- |
|
472 | 472 | String with formatted exception. |
|
473 | 473 | """ |
|
474 | 474 | tb_offset = self.tb_offset if tb_offset is None else tb_offset |
|
475 | 475 | Colors = self.Colors |
|
476 | 476 | out_list = [] |
|
477 | 477 | if elist: |
|
478 | 478 | |
|
479 | 479 | if tb_offset and len(elist) > tb_offset: |
|
480 | 480 | elist = elist[tb_offset:] |
|
481 | 481 | |
|
482 | 482 | out_list.append('Traceback %s(most recent call last)%s:' % |
|
483 | 483 | (Colors.normalEm, Colors.Normal) + '\n') |
|
484 | 484 | out_list.extend(self._format_list(elist)) |
|
485 | 485 | # The exception info should be a single entry in the list. |
|
486 | 486 | lines = ''.join(self._format_exception_only(etype, value)) |
|
487 | 487 | out_list.append(lines) |
|
488 | 488 | |
|
489 | 489 | # Note: this code originally read: |
|
490 | 490 | |
|
491 | 491 | ## for line in lines[:-1]: |
|
492 | 492 | ## out_list.append(" "+line) |
|
493 | 493 | ## out_list.append(lines[-1]) |
|
494 | 494 | |
|
495 | 495 | # This means it was indenting everything but the last line by a little |
|
496 | 496 | # bit. I've disabled this for now, but if we see ugliness somewhre we |
|
497 | 497 | # can restore it. |
|
498 | 498 | |
|
499 | 499 | return out_list |
|
500 | 500 | |
|
501 | 501 | def _format_list(self, extracted_list): |
|
502 | 502 | """Format a list of traceback entry tuples for printing. |
|
503 | 503 | |
|
504 | 504 | Given a list of tuples as returned by extract_tb() or |
|
505 | 505 | extract_stack(), return a list of strings ready for printing. |
|
506 | 506 | Each string in the resulting list corresponds to the item with the |
|
507 | 507 | same index in the argument list. Each string ends in a newline; |
|
508 | 508 | the strings may contain internal newlines as well, for those items |
|
509 | 509 | whose source text line is not None. |
|
510 | 510 | |
|
511 | 511 | Lifted almost verbatim from traceback.py |
|
512 | 512 | """ |
|
513 | 513 | |
|
514 | 514 | Colors = self.Colors |
|
515 | 515 | list = [] |
|
516 | 516 | for filename, lineno, name, line in extracted_list[:-1]: |
|
517 | 517 | item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \ |
|
518 | 518 | (Colors.filename, filename, Colors.Normal, |
|
519 | 519 | Colors.lineno, lineno, Colors.Normal, |
|
520 | 520 | Colors.name, name, Colors.Normal) |
|
521 | 521 | if line: |
|
522 | 522 | item += ' %s\n' % line.strip() |
|
523 | 523 | list.append(item) |
|
524 | 524 | # Emphasize the last entry |
|
525 | 525 | filename, lineno, name, line = extracted_list[-1] |
|
526 | 526 | item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \ |
|
527 | 527 | (Colors.normalEm, |
|
528 | 528 | Colors.filenameEm, filename, Colors.normalEm, |
|
529 | 529 | Colors.linenoEm, lineno, Colors.normalEm, |
|
530 | 530 | Colors.nameEm, name, Colors.normalEm, |
|
531 | 531 | Colors.Normal) |
|
532 | 532 | if line: |
|
533 | 533 | item += '%s %s%s\n' % (Colors.line, line.strip(), |
|
534 | 534 | Colors.Normal) |
|
535 | 535 | list.append(item) |
|
536 | 536 | #from pprint import pformat; print 'LISTTB', pformat(list) # dbg |
|
537 | 537 | return list |
|
538 | 538 | |
|
539 | 539 | def _format_exception_only(self, etype, value): |
|
540 | 540 | """Format the exception part of a traceback. |
|
541 | 541 | |
|
542 | 542 | The arguments are the exception type and value such as given by |
|
543 | 543 | sys.exc_info()[:2]. The return value is a list of strings, each ending |
|
544 | 544 | in a newline. Normally, the list contains a single string; however, |
|
545 | 545 | for SyntaxError exceptions, it contains several lines that (when |
|
546 | 546 | printed) display detailed information about where the syntax error |
|
547 | 547 | occurred. The message indicating which exception occurred is the |
|
548 | 548 | always last string in the list. |
|
549 | 549 | |
|
550 | 550 | Also lifted nearly verbatim from traceback.py |
|
551 | 551 | """ |
|
552 | 552 | have_filedata = False |
|
553 | 553 | Colors = self.Colors |
|
554 | 554 | list = [] |
|
555 | 555 | stype = Colors.excName + etype.__name__ + Colors.Normal |
|
556 | 556 | if value is None: |
|
557 | 557 | # Not sure if this can still happen in Python 2.6 and above |
|
558 | 558 | list.append( py3compat.cast_unicode(stype) + '\n') |
|
559 | 559 | else: |
|
560 | 560 | if issubclass(etype, SyntaxError): |
|
561 | 561 | have_filedata = True |
|
562 | 562 | #print 'filename is',filename # dbg |
|
563 | 563 | if not value.filename: value.filename = "<string>" |
|
564 | 564 | if value.lineno: |
|
565 | 565 | lineno = value.lineno |
|
566 | 566 | textline = ulinecache.getline(value.filename, value.lineno) |
|
567 | 567 | else: |
|
568 | 568 | lineno = 'unknown' |
|
569 | 569 | textline = '' |
|
570 | 570 | list.append('%s File %s"%s"%s, line %s%s%s\n' % \ |
|
571 | 571 | (Colors.normalEm, |
|
572 | 572 | Colors.filenameEm, py3compat.cast_unicode(value.filename), Colors.normalEm, |
|
573 | 573 | Colors.linenoEm, lineno, Colors.Normal )) |
|
574 | 574 | if textline == '': |
|
575 | 575 | textline = py3compat.cast_unicode(value.text, "utf-8") |
|
576 | 576 | |
|
577 | 577 | if textline is not None: |
|
578 | 578 | i = 0 |
|
579 | 579 | while i < len(textline) and textline[i].isspace(): |
|
580 | 580 | i += 1 |
|
581 | 581 | list.append('%s %s%s\n' % (Colors.line, |
|
582 | 582 | textline.strip(), |
|
583 | 583 | Colors.Normal)) |
|
584 | 584 | if value.offset is not None: |
|
585 | 585 | s = ' ' |
|
586 | 586 | for c in textline[i:value.offset-1]: |
|
587 | 587 | if c.isspace(): |
|
588 | 588 | s += c |
|
589 | 589 | else: |
|
590 | 590 | s += ' ' |
|
591 | 591 | list.append('%s%s^%s\n' % (Colors.caret, s, |
|
592 | 592 | Colors.Normal) ) |
|
593 | 593 | |
|
594 | 594 | try: |
|
595 | 595 | s = value.msg |
|
596 | 596 | except Exception: |
|
597 | 597 | s = self._some_str(value) |
|
598 | 598 | if s: |
|
599 | 599 | list.append('%s%s:%s %s\n' % (str(stype), Colors.excName, |
|
600 | 600 | Colors.Normal, s)) |
|
601 | 601 | else: |
|
602 | 602 | list.append('%s\n' % str(stype)) |
|
603 | 603 | |
|
604 | 604 | # sync with user hooks |
|
605 | 605 | if have_filedata: |
|
606 | 606 | ipinst = ipapi.get() |
|
607 | 607 | if ipinst is not None: |
|
608 | 608 | ipinst.hooks.synchronize_with_editor(value.filename, value.lineno, 0) |
|
609 | 609 | |
|
610 | 610 | return list |
|
611 | 611 | |
|
612 | 612 | def get_exception_only(self, etype, value): |
|
613 | 613 | """Only print the exception type and message, without a traceback. |
|
614 | 614 | |
|
615 | 615 | Parameters |
|
616 | 616 | ---------- |
|
617 | 617 | etype : exception type |
|
618 | 618 | value : exception value |
|
619 | 619 | """ |
|
620 | 620 | return ListTB.structured_traceback(self, etype, value, []) |
|
621 | 621 | |
|
622 | 622 | |
|
623 | 623 | def show_exception_only(self, etype, evalue): |
|
624 | 624 | """Only print the exception type and message, without a traceback. |
|
625 | 625 | |
|
626 | 626 | Parameters |
|
627 | 627 | ---------- |
|
628 | 628 | etype : exception type |
|
629 | 629 | value : exception value |
|
630 | 630 | """ |
|
631 | 631 | # This method needs to use __call__ from *this* class, not the one from |
|
632 | 632 | # a subclass whose signature or behavior may be different |
|
633 | 633 | ostream = self.ostream |
|
634 | 634 | ostream.flush() |
|
635 | 635 | ostream.write('\n'.join(self.get_exception_only(etype, evalue))) |
|
636 | 636 | ostream.flush() |
|
637 | 637 | |
|
638 | 638 | def _some_str(self, value): |
|
639 | 639 | # Lifted from traceback.py |
|
640 | 640 | try: |
|
641 | 641 | return str(value) |
|
642 | 642 | except: |
|
643 | 643 | return '<unprintable %s object>' % type(value).__name__ |
|
644 | 644 | |
|
645 | 645 | #---------------------------------------------------------------------------- |
|
646 | 646 | class VerboseTB(TBTools): |
|
647 | 647 | """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead |
|
648 | 648 | of HTML. Requires inspect and pydoc. Crazy, man. |
|
649 | 649 | |
|
650 | 650 | Modified version which optionally strips the topmost entries from the |
|
651 | 651 | traceback, to be used with alternate interpreters (because their own code |
|
652 | 652 | would appear in the traceback).""" |
|
653 | 653 | |
|
654 | 654 | def __init__(self,color_scheme = 'Linux', call_pdb=False, ostream=None, |
|
655 | 655 | tb_offset=0, long_header=False, include_vars=True, |
|
656 | 656 | check_cache=None): |
|
657 | 657 | """Specify traceback offset, headers and color scheme. |
|
658 | 658 | |
|
659 | 659 | Define how many frames to drop from the tracebacks. Calling it with |
|
660 | 660 | tb_offset=1 allows use of this handler in interpreters which will have |
|
661 | 661 | their own code at the top of the traceback (VerboseTB will first |
|
662 | 662 | remove that frame before printing the traceback info).""" |
|
663 | 663 | TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb, |
|
664 | 664 | ostream=ostream) |
|
665 | 665 | self.tb_offset = tb_offset |
|
666 | 666 | self.long_header = long_header |
|
667 | 667 | self.include_vars = include_vars |
|
668 | 668 | # By default we use linecache.checkcache, but the user can provide a |
|
669 | 669 | # different check_cache implementation. This is used by the IPython |
|
670 | 670 | # kernel to provide tracebacks for interactive code that is cached, |
|
671 | 671 | # by a compiler instance that flushes the linecache but preserves its |
|
672 | 672 | # own code cache. |
|
673 | 673 | if check_cache is None: |
|
674 | 674 | check_cache = linecache.checkcache |
|
675 | 675 | self.check_cache = check_cache |
|
676 | 676 | |
|
677 | 677 | def structured_traceback(self, etype, evalue, etb, tb_offset=None, |
|
678 | 678 | context=5): |
|
679 | 679 | """Return a nice text document describing the traceback.""" |
|
680 | 680 | |
|
681 | 681 | tb_offset = self.tb_offset if tb_offset is None else tb_offset |
|
682 | 682 | |
|
683 | 683 | # some locals |
|
684 | 684 | try: |
|
685 | 685 | etype = etype.__name__ |
|
686 | 686 | except AttributeError: |
|
687 | 687 | pass |
|
688 | 688 | Colors = self.Colors # just a shorthand + quicker name lookup |
|
689 | 689 | ColorsNormal = Colors.Normal # used a lot |
|
690 | 690 | col_scheme = self.color_scheme_table.active_scheme_name |
|
691 | 691 | indent = ' '*INDENT_SIZE |
|
692 | 692 | em_normal = '%s\n%s%s' % (Colors.valEm, indent,ColorsNormal) |
|
693 | 693 | undefined = '%sundefined%s' % (Colors.em, ColorsNormal) |
|
694 | 694 | exc = '%s%s%s' % (Colors.excName,etype,ColorsNormal) |
|
695 | 695 | |
|
696 | 696 | # some internal-use functions |
|
697 | 697 | def text_repr(value): |
|
698 | 698 | """Hopefully pretty robust repr equivalent.""" |
|
699 | 699 | # this is pretty horrible but should always return *something* |
|
700 | 700 | try: |
|
701 | 701 | return pydoc.text.repr(value) |
|
702 | 702 | except KeyboardInterrupt: |
|
703 | 703 | raise |
|
704 | 704 | except: |
|
705 | 705 | try: |
|
706 | 706 | return repr(value) |
|
707 | 707 | except KeyboardInterrupt: |
|
708 | 708 | raise |
|
709 | 709 | except: |
|
710 | 710 | try: |
|
711 | 711 | # all still in an except block so we catch |
|
712 | 712 | # getattr raising |
|
713 | 713 | name = getattr(value, '__name__', None) |
|
714 | 714 | if name: |
|
715 | 715 | # ick, recursion |
|
716 | 716 | return text_repr(name) |
|
717 | 717 | klass = getattr(value, '__class__', None) |
|
718 | 718 | if klass: |
|
719 | 719 | return '%s instance' % text_repr(klass) |
|
720 | 720 | except KeyboardInterrupt: |
|
721 | 721 | raise |
|
722 | 722 | except: |
|
723 | 723 | return 'UNRECOVERABLE REPR FAILURE' |
|
724 | 724 | def eqrepr(value, repr=text_repr): return '=%s' % repr(value) |
|
725 | 725 | def nullrepr(value, repr=text_repr): return '' |
|
726 | 726 | |
|
727 | 727 | # meat of the code begins |
|
728 | 728 | try: |
|
729 | 729 | etype = etype.__name__ |
|
730 | 730 | except AttributeError: |
|
731 | 731 | pass |
|
732 | 732 | |
|
733 | 733 | if self.long_header: |
|
734 | 734 | # Header with the exception type, python version, and date |
|
735 | 735 | pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable |
|
736 | 736 | date = time.ctime(time.time()) |
|
737 | 737 | |
|
738 | 738 | head = '%s%s%s\n%s%s%s\n%s' % (Colors.topline, '-'*75, ColorsNormal, |
|
739 | 739 | exc, ' '*(75-len(str(etype))-len(pyver)), |
|
740 | 740 | pyver, date.rjust(75) ) |
|
741 | 741 | head += "\nA problem occured executing Python code. Here is the sequence of function"\ |
|
742 | 742 | "\ncalls leading up to the error, with the most recent (innermost) call last." |
|
743 | 743 | else: |
|
744 | 744 | # Simplified header |
|
745 | 745 | head = '%s%s%s\n%s%s' % (Colors.topline, '-'*75, ColorsNormal,exc, |
|
746 | 746 | 'Traceback (most recent call last)'.\ |
|
747 | 747 | rjust(75 - len(str(etype)) ) ) |
|
748 | 748 | frames = [] |
|
749 | 749 | # Flush cache before calling inspect. This helps alleviate some of the |
|
750 | 750 | # problems with python 2.3's inspect.py. |
|
751 | 751 | ##self.check_cache() |
|
752 | 752 | # Drop topmost frames if requested |
|
753 | 753 | try: |
|
754 | 754 | # Try the default getinnerframes and Alex's: Alex's fixes some |
|
755 | 755 | # problems, but it generates empty tracebacks for console errors |
|
756 | 756 | # (5 blanks lines) where none should be returned. |
|
757 | 757 | #records = inspect.getinnerframes(etb, context)[tb_offset:] |
|
758 | 758 | #print 'python records:', records # dbg |
|
759 | 759 | records = _fixed_getinnerframes(etb, context, tb_offset) |
|
760 | 760 | #print 'alex records:', records # dbg |
|
761 | 761 | except: |
|
762 | 762 | |
|
763 | 763 | # FIXME: I've been getting many crash reports from python 2.3 |
|
764 | 764 | # users, traceable to inspect.py. If I can find a small test-case |
|
765 | 765 | # to reproduce this, I should either write a better workaround or |
|
766 | 766 | # file a bug report against inspect (if that's the real problem). |
|
767 | 767 | # So far, I haven't been able to find an isolated example to |
|
768 | 768 | # reproduce the problem. |
|
769 | 769 | inspect_error() |
|
770 | 770 | traceback.print_exc(file=self.ostream) |
|
771 | 771 | info('\nUnfortunately, your original traceback can not be constructed.\n') |
|
772 | 772 | return '' |
|
773 | 773 | |
|
774 | 774 | # build some color string templates outside these nested loops |
|
775 | 775 | tpl_link = '%s%%s%s' % (Colors.filenameEm,ColorsNormal) |
|
776 | 776 | tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm, |
|
777 | 777 | ColorsNormal) |
|
778 | 778 | tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \ |
|
779 | 779 | (Colors.vName, Colors.valEm, ColorsNormal) |
|
780 | 780 | tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal) |
|
781 | 781 | tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal, |
|
782 | 782 | Colors.vName, ColorsNormal) |
|
783 | 783 | tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal) |
|
784 | 784 | tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal) |
|
785 | 785 | tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm,Colors.line, |
|
786 | 786 | ColorsNormal) |
|
787 | 787 | |
|
788 | 788 | # now, loop over all records printing context and info |
|
789 | 789 | abspath = os.path.abspath |
|
790 | 790 | for frame, file, lnum, func, lines, index in records: |
|
791 | 791 | #print '*** record:',file,lnum,func,lines,index # dbg |
|
792 | 792 | if not file: |
|
793 | 793 | file = '?' |
|
794 | 794 | elif not(file.startswith(str("<")) and file.endswith(str(">"))): |
|
795 | 795 | # Guess that filenames like <string> aren't real filenames, so |
|
796 | 796 | # don't call abspath on them. |
|
797 | 797 | try: |
|
798 | 798 | file = abspath(file) |
|
799 | 799 | except OSError: |
|
800 | 800 | # Not sure if this can still happen: abspath now works with |
|
801 | 801 | # file names like <string> |
|
802 | 802 | pass |
|
803 | 803 | file = py3compat.cast_unicode(file, util_path.fs_encoding) |
|
804 | 804 | link = tpl_link % file |
|
805 | 805 | args, varargs, varkw, locals = inspect.getargvalues(frame) |
|
806 | 806 | |
|
807 | 807 | if func == '?': |
|
808 | 808 | call = '' |
|
809 | 809 | else: |
|
810 | 810 | # Decide whether to include variable details or not |
|
811 | 811 | var_repr = self.include_vars and eqrepr or nullrepr |
|
812 | 812 | try: |
|
813 | 813 | call = tpl_call % (func,inspect.formatargvalues(args, |
|
814 | 814 | varargs, varkw, |
|
815 | 815 | locals,formatvalue=var_repr)) |
|
816 | 816 | except KeyError: |
|
817 | 817 | # This happens in situations like errors inside generator |
|
818 | 818 | # expressions, where local variables are listed in the |
|
819 | 819 | # line, but can't be extracted from the frame. I'm not |
|
820 | 820 | # 100% sure this isn't actually a bug in inspect itself, |
|
821 | 821 | # but since there's no info for us to compute with, the |
|
822 | 822 | # best we can do is report the failure and move on. Here |
|
823 | 823 | # we must *not* call any traceback construction again, |
|
824 | 824 | # because that would mess up use of %debug later on. So we |
|
825 | 825 | # simply report the failure and move on. The only |
|
826 | 826 | # limitation will be that this frame won't have locals |
|
827 | 827 | # listed in the call signature. Quite subtle problem... |
|
828 | 828 | # I can't think of a good way to validate this in a unit |
|
829 | 829 | # test, but running a script consisting of: |
|
830 | 830 | # dict( (k,v.strip()) for (k,v) in range(10) ) |
|
831 | 831 | # will illustrate the error, if this exception catch is |
|
832 | 832 | # disabled. |
|
833 | 833 | call = tpl_call_fail % func |
|
834 | 834 | |
|
835 | 835 | # Don't attempt to tokenize binary files. |
|
836 | 836 | if file.endswith(('.so', '.pyd', '.dll')): |
|
837 | 837 | frames.append('%s %s\n' % (link,call)) |
|
838 | 838 | continue |
|
839 | 839 | elif file.endswith(('.pyc','.pyo')): |
|
840 | 840 | # Look up the corresponding source file. |
|
841 | 841 | file = pyfile.source_from_cache(file) |
|
842 | 842 | |
|
843 | 843 | def linereader(file=file, lnum=[lnum], getline=ulinecache.getline): |
|
844 | 844 | line = getline(file, lnum[0]) |
|
845 | 845 | lnum[0] += 1 |
|
846 | 846 | return line |
|
847 | 847 | |
|
848 | 848 | # Build the list of names on this line of code where the exception |
|
849 | 849 | # occurred. |
|
850 | 850 | try: |
|
851 | 851 | names = [] |
|
852 | 852 | name_cont = False |
|
853 | 853 | |
|
854 | 854 | for token_type, token, start, end, line in generate_tokens(linereader): |
|
855 | 855 | # build composite names |
|
856 | 856 | if token_type == tokenize.NAME and token not in keyword.kwlist: |
|
857 | 857 | if name_cont: |
|
858 | 858 | # Continuation of a dotted name |
|
859 | 859 | try: |
|
860 | 860 | names[-1].append(token) |
|
861 | 861 | except IndexError: |
|
862 | 862 | names.append([token]) |
|
863 | 863 | name_cont = False |
|
864 | 864 | else: |
|
865 | 865 | # Regular new names. We append everything, the caller |
|
866 | 866 | # will be responsible for pruning the list later. It's |
|
867 | 867 | # very tricky to try to prune as we go, b/c composite |
|
868 | 868 | # names can fool us. The pruning at the end is easy |
|
869 | 869 | # to do (or the caller can print a list with repeated |
|
870 | 870 | # names if so desired. |
|
871 | 871 | names.append([token]) |
|
872 | 872 | elif token == '.': |
|
873 | 873 | name_cont = True |
|
874 | 874 | elif token_type == tokenize.NEWLINE: |
|
875 | 875 | break |
|
876 | 876 | |
|
877 | 877 | except (IndexError, UnicodeDecodeError): |
|
878 | 878 | # signals exit of tokenizer |
|
879 | 879 | pass |
|
880 | 880 | except tokenize.TokenError as msg: |
|
881 | 881 | _m = ("An unexpected error occurred while tokenizing input\n" |
|
882 | 882 | "The following traceback may be corrupted or invalid\n" |
|
883 | 883 | "The error message is: %s\n" % msg) |
|
884 | 884 | error(_m) |
|
885 | 885 | |
|
886 | 886 | # Join composite names (e.g. "dict.fromkeys") |
|
887 | 887 | names = ['.'.join(n) for n in names] |
|
888 | 888 | # prune names list of duplicates, but keep the right order |
|
889 | 889 | unique_names = uniq_stable(names) |
|
890 | 890 | |
|
891 | 891 | # Start loop over vars |
|
892 | 892 | lvals = [] |
|
893 | 893 | if self.include_vars: |
|
894 | 894 | for name_full in unique_names: |
|
895 | 895 | name_base = name_full.split('.',1)[0] |
|
896 | 896 | if name_base in frame.f_code.co_varnames: |
|
897 | 897 | if name_base in locals: |
|
898 | 898 | try: |
|
899 | 899 | value = repr(eval(name_full,locals)) |
|
900 | 900 | except: |
|
901 | 901 | value = undefined |
|
902 | 902 | else: |
|
903 | 903 | value = undefined |
|
904 | 904 | name = tpl_local_var % name_full |
|
905 | 905 | else: |
|
906 | 906 | if name_base in frame.f_globals: |
|
907 | 907 | try: |
|
908 | 908 | value = repr(eval(name_full,frame.f_globals)) |
|
909 | 909 | except: |
|
910 | 910 | value = undefined |
|
911 | 911 | else: |
|
912 | 912 | value = undefined |
|
913 | 913 | name = tpl_global_var % name_full |
|
914 | 914 | lvals.append(tpl_name_val % (name,value)) |
|
915 | 915 | if lvals: |
|
916 | 916 | lvals = '%s%s' % (indent,em_normal.join(lvals)) |
|
917 | 917 | else: |
|
918 | 918 | lvals = '' |
|
919 | 919 | |
|
920 | 920 | level = '%s %s\n' % (link,call) |
|
921 | 921 | |
|
922 | 922 | if index is None: |
|
923 | 923 | frames.append(level) |
|
924 | 924 | else: |
|
925 | 925 | frames.append('%s%s' % (level,''.join( |
|
926 | 926 | _format_traceback_lines(lnum,index,lines,Colors,lvals, |
|
927 | 927 | col_scheme)))) |
|
928 | 928 | |
|
929 | 929 | # Get (safely) a string form of the exception info |
|
930 | 930 | try: |
|
931 | 931 | etype_str,evalue_str = map(str,(etype,evalue)) |
|
932 | 932 | except: |
|
933 | 933 | # User exception is improperly defined. |
|
934 | 934 | etype,evalue = str,sys.exc_info()[:2] |
|
935 | 935 | etype_str,evalue_str = map(str,(etype,evalue)) |
|
936 | 936 | # ... and format it |
|
937 | 937 | exception = ['%s%s%s: %s' % (Colors.excName, etype_str, |
|
938 | 938 | ColorsNormal, py3compat.cast_unicode(evalue_str))] |
|
939 | 939 | if (not py3compat.PY3) and type(evalue) is types.InstanceType: |
|
940 | 940 | try: |
|
941 | 941 | names = [w for w in dir(evalue) if isinstance(w, basestring)] |
|
942 | 942 | except: |
|
943 | 943 | # Every now and then, an object with funny inernals blows up |
|
944 | 944 | # when dir() is called on it. We do the best we can to report |
|
945 | 945 | # the problem and continue |
|
946 | 946 | _m = '%sException reporting error (object with broken dir())%s:' |
|
947 | 947 | exception.append(_m % (Colors.excName,ColorsNormal)) |
|
948 | 948 | etype_str,evalue_str = map(str,sys.exc_info()[:2]) |
|
949 | 949 | exception.append('%s%s%s: %s' % (Colors.excName,etype_str, |
|
950 | 950 | ColorsNormal, py3compat.cast_unicode(evalue_str))) |
|
951 | 951 | names = [] |
|
952 | 952 | for name in names: |
|
953 | 953 | value = text_repr(getattr(evalue, name)) |
|
954 | 954 | exception.append('\n%s%s = %s' % (indent, name, value)) |
|
955 | 955 | |
|
956 | 956 | # vds: >> |
|
957 | 957 | if records: |
|
958 | 958 | filepath, lnum = records[-1][1:3] |
|
959 | 959 | #print "file:", str(file), "linenb", str(lnum) # dbg |
|
960 | 960 | filepath = os.path.abspath(filepath) |
|
961 | 961 | ipinst = ipapi.get() |
|
962 | 962 | if ipinst is not None: |
|
963 | 963 | ipinst.hooks.synchronize_with_editor(filepath, lnum, 0) |
|
964 | 964 | # vds: << |
|
965 | 965 | |
|
966 | 966 | # return all our info assembled as a single string |
|
967 | 967 | # return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) ) |
|
968 | 968 | return [head] + frames + [''.join(exception[0])] |
|
969 | 969 | |
|
970 | 970 | def debugger(self,force=False): |
|
971 | 971 | """Call up the pdb debugger if desired, always clean up the tb |
|
972 | 972 | reference. |
|
973 | 973 | |
|
974 | 974 | Keywords: |
|
975 | 975 | |
|
976 | 976 | - force(False): by default, this routine checks the instance call_pdb |
|
977 | 977 | flag and does not actually invoke the debugger if the flag is false. |
|
978 | 978 | The 'force' option forces the debugger to activate even if the flag |
|
979 | 979 | is false. |
|
980 | 980 | |
|
981 | 981 | If the call_pdb flag is set, the pdb interactive debugger is |
|
982 | 982 | invoked. In all cases, the self.tb reference to the current traceback |
|
983 | 983 | is deleted to prevent lingering references which hamper memory |
|
984 | 984 | management. |
|
985 | 985 | |
|
986 | 986 | Note that each call to pdb() does an 'import readline', so if your app |
|
987 | 987 | requires a special setup for the readline completers, you'll have to |
|
988 | 988 | fix that by hand after invoking the exception handler.""" |
|
989 | 989 | |
|
990 | 990 | if force or self.call_pdb: |
|
991 | 991 | if self.pdb is None: |
|
992 | 992 | self.pdb = debugger.Pdb( |
|
993 | 993 | self.color_scheme_table.active_scheme_name) |
|
994 | 994 | # the system displayhook may have changed, restore the original |
|
995 | 995 | # for pdb |
|
996 | 996 | display_trap = DisplayTrap(hook=sys.__displayhook__) |
|
997 | 997 | with display_trap: |
|
998 | 998 | self.pdb.reset() |
|
999 | 999 | # Find the right frame so we don't pop up inside ipython itself |
|
1000 | 1000 | if hasattr(self,'tb') and self.tb is not None: |
|
1001 | 1001 | etb = self.tb |
|
1002 | 1002 | else: |
|
1003 | 1003 | etb = self.tb = sys.last_traceback |
|
1004 | 1004 | while self.tb is not None and self.tb.tb_next is not None: |
|
1005 | 1005 | self.tb = self.tb.tb_next |
|
1006 | 1006 | if etb and etb.tb_next: |
|
1007 | 1007 | etb = etb.tb_next |
|
1008 | 1008 | self.pdb.botframe = etb.tb_frame |
|
1009 | 1009 | self.pdb.interaction(self.tb.tb_frame, self.tb) |
|
1010 | 1010 | |
|
1011 | 1011 | if hasattr(self,'tb'): |
|
1012 | 1012 | del self.tb |
|
1013 | 1013 | |
|
1014 | 1014 | def handler(self, info=None): |
|
1015 | 1015 | (etype, evalue, etb) = info or sys.exc_info() |
|
1016 | 1016 | self.tb = etb |
|
1017 | 1017 | ostream = self.ostream |
|
1018 | 1018 | ostream.flush() |
|
1019 | 1019 | ostream.write(self.text(etype, evalue, etb)) |
|
1020 | 1020 | ostream.write('\n') |
|
1021 | 1021 | ostream.flush() |
|
1022 | 1022 | |
|
1023 | 1023 | # Changed so an instance can just be called as VerboseTB_inst() and print |
|
1024 | 1024 | # out the right info on its own. |
|
1025 | 1025 | def __call__(self, etype=None, evalue=None, etb=None): |
|
1026 | 1026 | """This hook can replace sys.excepthook (for Python 2.1 or higher).""" |
|
1027 | 1027 | if etb is None: |
|
1028 | 1028 | self.handler() |
|
1029 | 1029 | else: |
|
1030 | 1030 | self.handler((etype, evalue, etb)) |
|
1031 | 1031 | try: |
|
1032 | 1032 | self.debugger() |
|
1033 | 1033 | except KeyboardInterrupt: |
|
1034 | 1034 | print "\nKeyboardInterrupt" |
|
1035 | 1035 | |
|
1036 | 1036 | #---------------------------------------------------------------------------- |
|
1037 | 1037 | class FormattedTB(VerboseTB, ListTB): |
|
1038 | 1038 | """Subclass ListTB but allow calling with a traceback. |
|
1039 | 1039 | |
|
1040 | 1040 | It can thus be used as a sys.excepthook for Python > 2.1. |
|
1041 | 1041 | |
|
1042 | 1042 | Also adds 'Context' and 'Verbose' modes, not available in ListTB. |
|
1043 | 1043 | |
|
1044 | 1044 | Allows a tb_offset to be specified. This is useful for situations where |
|
1045 | 1045 | one needs to remove a number of topmost frames from the traceback (such as |
|
1046 | 1046 | occurs with python programs that themselves execute other python code, |
|
1047 | 1047 | like Python shells). """ |
|
1048 | 1048 | |
|
1049 | 1049 | def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False, |
|
1050 | 1050 | ostream=None, |
|
1051 | 1051 | tb_offset=0, long_header=False, include_vars=False, |
|
1052 | 1052 | check_cache=None): |
|
1053 | 1053 | |
|
1054 | 1054 | # NEVER change the order of this list. Put new modes at the end: |
|
1055 | 1055 | self.valid_modes = ['Plain','Context','Verbose'] |
|
1056 | 1056 | self.verbose_modes = self.valid_modes[1:3] |
|
1057 | 1057 | |
|
1058 | 1058 | VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb, |
|
1059 | 1059 | ostream=ostream, tb_offset=tb_offset, |
|
1060 | 1060 | long_header=long_header, include_vars=include_vars, |
|
1061 | 1061 | check_cache=check_cache) |
|
1062 | 1062 | |
|
1063 | 1063 | # Different types of tracebacks are joined with different separators to |
|
1064 | 1064 | # form a single string. They are taken from this dict |
|
1065 | 1065 | self._join_chars = dict(Plain='', Context='\n', Verbose='\n') |
|
1066 | 1066 | # set_mode also sets the tb_join_char attribute |
|
1067 | 1067 | self.set_mode(mode) |
|
1068 | 1068 | |
|
1069 | 1069 | def _extract_tb(self,tb): |
|
1070 | 1070 | if tb: |
|
1071 | 1071 | return traceback.extract_tb(tb) |
|
1072 | 1072 | else: |
|
1073 | 1073 | return None |
|
1074 | 1074 | |
|
1075 | 1075 | def structured_traceback(self, etype, value, tb, tb_offset=None, context=5): |
|
1076 | 1076 | tb_offset = self.tb_offset if tb_offset is None else tb_offset |
|
1077 | 1077 | mode = self.mode |
|
1078 | 1078 | if mode in self.verbose_modes: |
|
1079 | 1079 | # Verbose modes need a full traceback |
|
1080 | 1080 | return VerboseTB.structured_traceback( |
|
1081 | 1081 | self, etype, value, tb, tb_offset, context |
|
1082 | 1082 | ) |
|
1083 | 1083 | else: |
|
1084 | 1084 | # We must check the source cache because otherwise we can print |
|
1085 | 1085 | # out-of-date source code. |
|
1086 | 1086 | self.check_cache() |
|
1087 | 1087 | # Now we can extract and format the exception |
|
1088 | 1088 | elist = self._extract_tb(tb) |
|
1089 | 1089 | return ListTB.structured_traceback( |
|
1090 | 1090 | self, etype, value, elist, tb_offset, context |
|
1091 | 1091 | ) |
|
1092 | 1092 | |
|
1093 | 1093 | def stb2text(self, stb): |
|
1094 | 1094 | """Convert a structured traceback (a list) to a string.""" |
|
1095 | 1095 | return self.tb_join_char.join(stb) |
|
1096 | 1096 | |
|
1097 | 1097 | |
|
1098 | 1098 | def set_mode(self,mode=None): |
|
1099 | 1099 | """Switch to the desired mode. |
|
1100 | 1100 | |
|
1101 | 1101 | If mode is not specified, cycles through the available modes.""" |
|
1102 | 1102 | |
|
1103 | 1103 | if not mode: |
|
1104 | 1104 | new_idx = ( self.valid_modes.index(self.mode) + 1 ) % \ |
|
1105 | 1105 | len(self.valid_modes) |
|
1106 | 1106 | self.mode = self.valid_modes[new_idx] |
|
1107 | 1107 | elif mode not in self.valid_modes: |
|
1108 | 1108 | raise ValueError('Unrecognized mode in FormattedTB: <'+mode+'>\n' |
|
1109 | 1109 | 'Valid modes: '+str(self.valid_modes)) |
|
1110 | 1110 | else: |
|
1111 | 1111 | self.mode = mode |
|
1112 | 1112 | # include variable details only in 'Verbose' mode |
|
1113 | 1113 | self.include_vars = (self.mode == self.valid_modes[2]) |
|
1114 | 1114 | # Set the join character for generating text tracebacks |
|
1115 | 1115 | self.tb_join_char = self._join_chars[self.mode] |
|
1116 | 1116 | |
|
1117 | 1117 | # some convenient shorcuts |
|
1118 | 1118 | def plain(self): |
|
1119 | 1119 | self.set_mode(self.valid_modes[0]) |
|
1120 | 1120 | |
|
1121 | 1121 | def context(self): |
|
1122 | 1122 | self.set_mode(self.valid_modes[1]) |
|
1123 | 1123 | |
|
1124 | 1124 | def verbose(self): |
|
1125 | 1125 | self.set_mode(self.valid_modes[2]) |
|
1126 | 1126 | |
|
1127 | 1127 | #---------------------------------------------------------------------------- |
|
1128 | 1128 | class AutoFormattedTB(FormattedTB): |
|
1129 | 1129 | """A traceback printer which can be called on the fly. |
|
1130 | 1130 | |
|
1131 | 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') | |
|
1136 | try: | |
|
1137 | ... | |
|
1138 | except: | |
|
1139 | AutoTB() # or AutoTB(out=logfile) where logfile is an open file object | |
|
1135 | AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux') | |
|
1136 | try: | |
|
1137 | ... | |
|
1138 | except: | |
|
1139 | AutoTB() # or AutoTB(out=logfile) where logfile is an open file object | |
|
1140 | 1140 | """ |
|
1141 | 1141 | |
|
1142 | 1142 | def __call__(self,etype=None,evalue=None,etb=None, |
|
1143 | 1143 | out=None,tb_offset=None): |
|
1144 | 1144 | """Print out a formatted exception traceback. |
|
1145 | 1145 | |
|
1146 | 1146 | Optional arguments: |
|
1147 | 1147 | - out: an open file-like object to direct output to. |
|
1148 | 1148 | |
|
1149 | 1149 | - tb_offset: the number of frames to skip over in the stack, on a |
|
1150 | 1150 | per-call basis (this overrides temporarily the instance's tb_offset |
|
1151 | 1151 | given at initialization time. """ |
|
1152 | 1152 | |
|
1153 | 1153 | |
|
1154 | 1154 | if out is None: |
|
1155 | 1155 | out = self.ostream |
|
1156 | 1156 | out.flush() |
|
1157 | 1157 | out.write(self.text(etype, evalue, etb, tb_offset)) |
|
1158 | 1158 | out.write('\n') |
|
1159 | 1159 | out.flush() |
|
1160 | 1160 | # FIXME: we should remove the auto pdb behavior from here and leave |
|
1161 | 1161 | # that to the clients. |
|
1162 | 1162 | try: |
|
1163 | 1163 | self.debugger() |
|
1164 | 1164 | except KeyboardInterrupt: |
|
1165 | 1165 | print "\nKeyboardInterrupt" |
|
1166 | 1166 | |
|
1167 | 1167 | def structured_traceback(self, etype=None, value=None, tb=None, |
|
1168 | 1168 | tb_offset=None, context=5): |
|
1169 | 1169 | if etype is None: |
|
1170 | 1170 | etype,value,tb = sys.exc_info() |
|
1171 | 1171 | self.tb = tb |
|
1172 | 1172 | return FormattedTB.structured_traceback( |
|
1173 | 1173 | self, etype, value, tb, tb_offset, context) |
|
1174 | 1174 | |
|
1175 | 1175 | #--------------------------------------------------------------------------- |
|
1176 | 1176 | |
|
1177 | 1177 | # A simple class to preserve Nathan's original functionality. |
|
1178 | 1178 | class ColorTB(FormattedTB): |
|
1179 | 1179 | """Shorthand to initialize a FormattedTB in Linux colors mode.""" |
|
1180 | 1180 | def __init__(self,color_scheme='Linux',call_pdb=0): |
|
1181 | 1181 | FormattedTB.__init__(self,color_scheme=color_scheme, |
|
1182 | 1182 | call_pdb=call_pdb) |
|
1183 | 1183 | |
|
1184 | 1184 | |
|
1185 | 1185 | class SyntaxTB(ListTB): |
|
1186 | 1186 | """Extension which holds some state: the last exception value""" |
|
1187 | 1187 | |
|
1188 | 1188 | def __init__(self,color_scheme = 'NoColor'): |
|
1189 | 1189 | ListTB.__init__(self,color_scheme) |
|
1190 | 1190 | self.last_syntax_error = None |
|
1191 | 1191 | |
|
1192 | 1192 | def __call__(self, etype, value, elist): |
|
1193 | 1193 | self.last_syntax_error = value |
|
1194 | 1194 | ListTB.__call__(self,etype,value,elist) |
|
1195 | 1195 | |
|
1196 | 1196 | def clear_err_state(self): |
|
1197 | 1197 | """Return the current error state and clear it""" |
|
1198 | 1198 | e = self.last_syntax_error |
|
1199 | 1199 | self.last_syntax_error = None |
|
1200 | 1200 | return e |
|
1201 | 1201 | |
|
1202 | 1202 | def stb2text(self, stb): |
|
1203 | 1203 | """Convert a structured traceback (a list) to a string.""" |
|
1204 | 1204 | return ''.join(stb) |
|
1205 | 1205 | |
|
1206 | 1206 | |
|
1207 | 1207 | #---------------------------------------------------------------------------- |
|
1208 | 1208 | # module testing (minimal) |
|
1209 | 1209 | if __name__ == "__main__": |
|
1210 | 1210 | def spam(c, d_e): |
|
1211 | 1211 | (d, e) = d_e |
|
1212 | 1212 | x = c + d |
|
1213 | 1213 | y = c * d |
|
1214 | 1214 | foo(x, y) |
|
1215 | 1215 | |
|
1216 | 1216 | def foo(a, b, bar=1): |
|
1217 | 1217 | eggs(a, b + bar) |
|
1218 | 1218 | |
|
1219 | 1219 | def eggs(f, g, z=globals()): |
|
1220 | 1220 | h = f + g |
|
1221 | 1221 | i = f - g |
|
1222 | 1222 | return h / i |
|
1223 | 1223 | |
|
1224 | 1224 | print '' |
|
1225 | 1225 | print '*** Before ***' |
|
1226 | 1226 | try: |
|
1227 | 1227 | print spam(1, (2, 3)) |
|
1228 | 1228 | except: |
|
1229 | 1229 | traceback.print_exc() |
|
1230 | 1230 | print '' |
|
1231 | 1231 | |
|
1232 | 1232 | handler = ColorTB() |
|
1233 | 1233 | print '*** ColorTB ***' |
|
1234 | 1234 | try: |
|
1235 | 1235 | print spam(1, (2, 3)) |
|
1236 | 1236 | except: |
|
1237 | 1237 | handler(*sys.exc_info()) |
|
1238 | 1238 | print '' |
|
1239 | 1239 | |
|
1240 | 1240 | handler = VerboseTB() |
|
1241 | 1241 | print '*** VerboseTB ***' |
|
1242 | 1242 | try: |
|
1243 | 1243 | print spam(1, (2, 3)) |
|
1244 | 1244 | except: |
|
1245 | 1245 | handler(*sys.exc_info()) |
|
1246 | 1246 | print '' |
|
1247 | 1247 |
@@ -1,287 +1,291 b'' | |||
|
1 | 1 | """Various display related classes. |
|
2 | 2 | |
|
3 | 3 | Authors : MinRK, gregcaporaso, dannystaple |
|
4 | 4 | """ |
|
5 | 5 | import urllib |
|
6 | 6 | |
|
7 | 7 | from os.path import exists, isfile, splitext, abspath, join, isdir |
|
8 | 8 | from os import walk |
|
9 | 9 | |
|
10 | 10 | |
|
11 | 11 | class YouTubeVideo(object): |
|
12 | 12 | """Class for embedding a YouTube Video in an IPython session, based on its video id. |
|
13 | 13 | |
|
14 | 14 | e.g. to embed the video on this page: |
|
15 | 15 | |
|
16 | 16 | http://www.youtube.com/watch?v=foo |
|
17 | 17 | |
|
18 | 18 | you would do: |
|
19 | 19 | |
|
20 | 20 | vid = YouTubeVideo("foo") |
|
21 | 21 | display(vid) |
|
22 | 22 | |
|
23 | 23 | To start from 30 seconds: |
|
24 | 24 | |
|
25 | 25 | vid = YouTubeVideo("abc", start=30) |
|
26 | 26 | display(vid) |
|
27 | 27 | |
|
28 | 28 | To calculate seconds from time as hours, minutes, seconds use: |
|
29 | 29 | start=int(timedelta(hours=1, minutes=46, seconds=40).total_seconds()) |
|
30 | 30 | |
|
31 | 31 | Other parameters can be provided as documented at |
|
32 | 32 | https://developers.google.com/youtube/player_parameters#parameter-subheader |
|
33 | 33 | """ |
|
34 | 34 | |
|
35 | 35 | def __init__(self, id, width=400, height=300, **kwargs): |
|
36 | 36 | self.id = id |
|
37 | 37 | self.width = width |
|
38 | 38 | self.height = height |
|
39 | 39 | self.params = kwargs |
|
40 | 40 | |
|
41 | 41 | def _repr_html_(self): |
|
42 | 42 | """return YouTube embed iframe for this video id""" |
|
43 | 43 | if self.params: |
|
44 | 44 | params = "?" + urllib.urlencode(self.params) |
|
45 | 45 | else: |
|
46 | 46 | params = "" |
|
47 | 47 | return """ |
|
48 | 48 | <iframe |
|
49 | 49 | width="%i" |
|
50 | 50 | height="%i" |
|
51 | 51 | src="http://www.youtube.com/embed/%s%s" |
|
52 | 52 | frameborder="0" |
|
53 | 53 | allowfullscreen |
|
54 | 54 | ></iframe> |
|
55 | 55 | """ % (self.width, self.height, self.id, params) |
|
56 | 56 | |
|
57 | 57 | class FileLink(object): |
|
58 | 58 | """Class for embedding a local file link in an IPython session, based on path |
|
59 | 59 | |
|
60 | 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") | |
|
65 | display(local_file) | |
|
64 | local_file = FileLink("my/data.txt") | |
|
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 | 72 | html_link_str = "<a href='%s' target='_blank'>%s</a>" |
|
73 | 73 | |
|
74 | 74 | def __init__(self, |
|
75 | 75 | path, |
|
76 | 76 | url_prefix='files/', |
|
77 | 77 | result_html_prefix='', |
|
78 | 78 | result_html_suffix='<br>'): |
|
79 | 79 | """ |
|
80 | path : path to the file or directory that should be formatted | |
|
81 | directory_prefix : prefix to be prepended to all files to form a | |
|
82 | working link [default: 'files'] | |
|
83 | result_html_prefix : text to append to beginning to link | |
|
84 | [default: none] | |
|
85 | result_html_suffix : text to append at the end of link | |
|
86 |
|
|
|
80 | Parameters | |
|
81 | ---------- | |
|
82 | path : str | |
|
83 | path to the file or directory that should be formatted | |
|
84 | directory_prefix : str | |
|
85 | prefix to be prepended to all files to form a working link [default: | |
|
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 | 92 | if isdir(path): |
|
89 | 93 | raise ValueError,\ |
|
90 | 94 | ("Cannot display a directory using FileLink. " |
|
91 | 95 | "Use FileLinks to display '%s'." % path) |
|
92 | 96 | self.path = path |
|
93 | 97 | self.url_prefix = url_prefix |
|
94 | 98 | self.result_html_prefix = result_html_prefix |
|
95 | 99 | self.result_html_suffix = result_html_suffix |
|
96 | 100 | |
|
97 | 101 | def _format_path(self): |
|
98 | 102 | fp = ''.join([self.url_prefix,self.path]) |
|
99 | 103 | return ''.join([self.result_html_prefix, |
|
100 | 104 | self.html_link_str % (fp, self.path), |
|
101 | 105 | self.result_html_suffix]) |
|
102 | 106 | |
|
103 | 107 | def _repr_html_(self): |
|
104 | 108 | """return html link to file |
|
105 | 109 | """ |
|
106 | 110 | if not exists(self.path): |
|
107 | 111 | return ("Path (<tt>%s</tt>) doesn't exist. " |
|
108 | 112 | "It may still be in the process of " |
|
109 | 113 | "being generated, or you may have the " |
|
110 | 114 | "incorrect path." % self.path) |
|
111 | 115 | |
|
112 | 116 | return self._format_path() |
|
113 | 117 | |
|
114 | 118 | def __repr__(self): |
|
115 | 119 | """return absolute path to file |
|
116 | 120 | """ |
|
117 | 121 | return abspath(self.path) |
|
118 | 122 | |
|
119 | 123 | class FileLinks(FileLink): |
|
120 | 124 | """Class for embedding local file links in an IPython session, based on path |
|
121 | 125 | |
|
122 | 126 | e.g. to embed links to files that were generated in the IPython notebook under my/data |
|
123 | 127 | |
|
124 | 128 | you would do: |
|
125 | 129 | |
|
126 | 130 | local_files = FileLinks("my/data") |
|
127 | 131 | display(local_files) |
|
128 | 132 | |
|
129 | 133 | or in the HTML notebook, just |
|
130 | 134 | |
|
131 | 135 | FileLinks("my/data") |
|
132 | 136 | |
|
133 | 137 | """ |
|
134 | 138 | def __init__(self, |
|
135 | 139 | path, |
|
136 | 140 | url_prefix='files/', |
|
137 | 141 | included_suffixes=None, |
|
138 | 142 | result_html_prefix='', |
|
139 | 143 | result_html_suffix='<br>', |
|
140 | 144 | notebook_display_formatter=None, |
|
141 | 145 | terminal_display_formatter=None): |
|
142 | 146 | """ |
|
143 | 147 | included_suffixes : list of filename suffixes to include when |
|
144 | 148 | formatting output [default: include all files] |
|
145 | 149 | |
|
146 | 150 | See the FileLink (baseclass of LocalDirectory) docstring for |
|
147 | 151 | information on additional parameters. |
|
148 | 152 | |
|
149 | 153 | notebook_display_formatter : func used to format links for display |
|
150 | 154 | in the notebook. See discussion of formatter function below. |
|
151 | 155 | |
|
152 | 156 | terminal_display_formatter : func used to format links for display |
|
153 | 157 | in the terminal. See discussion of formatter function below. |
|
154 | 158 | |
|
155 | 159 | |
|
156 | 160 | Passing custom formatter functions |
|
157 | 161 | ---------------------------------- |
|
158 | 162 | Formatter functions must be of the form: |
|
159 | 163 | f(dirname, fnames, included_suffixes) |
|
160 | 164 | dirname : the name of a directory (a string), |
|
161 | 165 | fnames : a list of the files in that directory |
|
162 | 166 | included_suffixes : a list of the file suffixes that should be |
|
163 | 167 | included in the output (passing None means |
|
164 | 168 | to include all suffixes in the output in |
|
165 | 169 | the built-in formatters) |
|
166 | 170 | |
|
167 | 171 | returns a list of lines that should will be print in the |
|
168 | 172 | notebook (if passing notebook_display_formatter) or the terminal |
|
169 | 173 | (if passing terminal_display_formatter). This function is iterated |
|
170 | 174 | over for each directory in self.path. Default formatters are in |
|
171 | 175 | place, can be passed here to support alternative formatting. |
|
172 | 176 | |
|
173 | 177 | """ |
|
174 | 178 | if isfile(path): |
|
175 | 179 | raise ValueError,\ |
|
176 | 180 | ("Cannot display a file using FileLinks. " |
|
177 | 181 | "Use FileLink to display '%s'." % path) |
|
178 | 182 | self.included_suffixes = included_suffixes |
|
179 | 183 | # remove trailing slashs for more consistent output formatting |
|
180 | 184 | path = path.rstrip('/') |
|
181 | 185 | |
|
182 | 186 | self.path = path |
|
183 | 187 | self.url_prefix = url_prefix |
|
184 | 188 | self.result_html_prefix = result_html_prefix |
|
185 | 189 | self.result_html_suffix = result_html_suffix |
|
186 | 190 | |
|
187 | 191 | self.notebook_display_formatter = \ |
|
188 | 192 | notebook_display_formatter or self._get_notebook_display_formatter() |
|
189 | 193 | self.terminal_display_formatter = \ |
|
190 | 194 | terminal_display_formatter or self._get_terminal_display_formatter() |
|
191 | 195 | |
|
192 | 196 | def _get_display_formatter(self, |
|
193 | 197 | dirname_output_format, |
|
194 | 198 | fname_output_format, |
|
195 | 199 | fp_format): |
|
196 | 200 | """ generate built-in formatter function |
|
197 | 201 | |
|
198 | 202 | this is used to define both the notebook and terminal built-in |
|
199 | 203 | formatters as they only differ by some wrapper text for each entry |
|
200 | 204 | |
|
201 | 205 | dirname_output_format: string to use for formatting directory |
|
202 | 206 | names, dirname will be substituted for a single "%s" which |
|
203 | 207 | must appear in this string |
|
204 | 208 | fname_output_format: string to use for formatting file names, |
|
205 | 209 | if a single "%s" appears in the string, fname will be substituted |
|
206 | 210 | if two "%s" appear in the string, the path to fname will be |
|
207 | 211 | substituted for the first and fname will be substituted for the |
|
208 | 212 | second |
|
209 | 213 | fp_format: string to use for formatting filepaths, must contain |
|
210 | 214 | exactly two "%s" and the dirname will be subsituted for the first |
|
211 | 215 | and fname will be substituted for the second |
|
212 | 216 | """ |
|
213 | 217 | def f(dirname, fnames, included_suffixes=None): |
|
214 | 218 | result = [] |
|
215 | 219 | # begin by figuring out which filenames, if any, |
|
216 | 220 | # are going to be displayed |
|
217 | 221 | display_fnames = [] |
|
218 | 222 | for fname in fnames: |
|
219 | 223 | if (isfile(join(dirname,fname)) and |
|
220 | 224 | (included_suffixes == None or |
|
221 | 225 | splitext(fname)[1] in included_suffixes)): |
|
222 | 226 | display_fnames.append(fname) |
|
223 | 227 | |
|
224 | 228 | if len(display_fnames) == 0: |
|
225 | 229 | # if there are no filenames to display, don't print anything |
|
226 | 230 | # (not even the directory name) |
|
227 | 231 | pass |
|
228 | 232 | else: |
|
229 | 233 | # otherwise print the formatted directory name followed by |
|
230 | 234 | # the formatted filenames |
|
231 | 235 | dirname_output_line = dirname_output_format % dirname |
|
232 | 236 | result.append(dirname_output_line) |
|
233 | 237 | for fname in display_fnames: |
|
234 | 238 | fp = fp_format % (dirname,fname) |
|
235 | 239 | try: |
|
236 | 240 | # output can include both a filepath and a filename... |
|
237 | 241 | fname_output_line = fname_output_format % (fp, fname) |
|
238 | 242 | except TypeError: |
|
239 | 243 | # ... or just a single filepath |
|
240 | 244 | fname_output_line = fname_output_format % fname |
|
241 | 245 | result.append(fname_output_line) |
|
242 | 246 | return result |
|
243 | 247 | return f |
|
244 | 248 | |
|
245 | 249 | def _get_notebook_display_formatter(self, |
|
246 | 250 | spacer=" "): |
|
247 | 251 | """ generate function to use for notebook formatting |
|
248 | 252 | """ |
|
249 | 253 | dirname_output_format = \ |
|
250 | 254 | self.result_html_prefix + "%s/" + self.result_html_suffix |
|
251 | 255 | fname_output_format = \ |
|
252 | 256 | self.result_html_prefix + spacer + self.html_link_str + self.result_html_suffix |
|
253 | 257 | fp_format = self.url_prefix + '%s/%s' |
|
254 | 258 | |
|
255 | 259 | return self._get_display_formatter(dirname_output_format, |
|
256 | 260 | fname_output_format, |
|
257 | 261 | fp_format) |
|
258 | 262 | |
|
259 | 263 | def _get_terminal_display_formatter(self, |
|
260 | 264 | spacer=" "): |
|
261 | 265 | """ generate function to use for terminal formatting |
|
262 | 266 | """ |
|
263 | 267 | dirname_output_format = "%s/" |
|
264 | 268 | fname_output_format = spacer + "%s" |
|
265 | 269 | fp_format = '%s/%s' |
|
266 | 270 | |
|
267 | 271 | return self._get_display_formatter(dirname_output_format, |
|
268 | 272 | fname_output_format, |
|
269 | 273 | fp_format) |
|
270 | 274 | |
|
271 | 275 | def _format_path(self): |
|
272 | 276 | result_lines = [] |
|
273 | 277 | walked_dir = list(walk(self.path)) |
|
274 | 278 | walked_dir.sort() |
|
275 | 279 | for dirname, subdirs, fnames in walked_dir: |
|
276 | 280 | result_lines += self.notebook_display_formatter(dirname, fnames, self.included_suffixes) |
|
277 | 281 | return '\n'.join(result_lines) |
|
278 | 282 | |
|
279 | 283 | def __repr__(self): |
|
280 | 284 | """return newline-separated absolute paths |
|
281 | 285 | """ |
|
282 | 286 | result_lines = [] |
|
283 | 287 | walked_dir = list(walk(self.path)) |
|
284 | 288 | walked_dir.sort() |
|
285 | 289 | for dirname, subdirs, fnames in walked_dir: |
|
286 | 290 | result_lines += self.terminal_display_formatter(dirname, fnames, self.included_suffixes) |
|
287 | 291 | return '\n'.join(result_lines) |
@@ -1,529 +1,529 b'' | |||
|
1 | 1 | # coding: utf-8 |
|
2 | 2 | """ |
|
3 | 3 | Inputhook management for GUI event loop integration. |
|
4 | 4 | """ |
|
5 | 5 | |
|
6 | 6 | #----------------------------------------------------------------------------- |
|
7 | 7 | # Copyright (C) 2008-2011 The IPython Development Team |
|
8 | 8 | # |
|
9 | 9 | # Distributed under the terms of the BSD License. The full license is in |
|
10 | 10 | # the file COPYING, distributed as part of this software. |
|
11 | 11 | #----------------------------------------------------------------------------- |
|
12 | 12 | |
|
13 | 13 | #----------------------------------------------------------------------------- |
|
14 | 14 | # Imports |
|
15 | 15 | #----------------------------------------------------------------------------- |
|
16 | 16 | |
|
17 | 17 | try: |
|
18 | 18 | import ctypes |
|
19 | 19 | except ImportError: |
|
20 | 20 | ctypes = None |
|
21 | 21 | import os |
|
22 | 22 | import sys |
|
23 | 23 | from distutils.version import LooseVersion as V |
|
24 | 24 | |
|
25 | 25 | from IPython.utils.warn import warn |
|
26 | 26 | |
|
27 | 27 | #----------------------------------------------------------------------------- |
|
28 | 28 | # Constants |
|
29 | 29 | #----------------------------------------------------------------------------- |
|
30 | 30 | |
|
31 | 31 | # Constants for identifying the GUI toolkits. |
|
32 | 32 | GUI_WX = 'wx' |
|
33 | 33 | GUI_QT = 'qt' |
|
34 | 34 | GUI_QT4 = 'qt4' |
|
35 | 35 | GUI_GTK = 'gtk' |
|
36 | 36 | GUI_TK = 'tk' |
|
37 | 37 | GUI_OSX = 'osx' |
|
38 | 38 | GUI_GLUT = 'glut' |
|
39 | 39 | GUI_PYGLET = 'pyglet' |
|
40 | 40 | GUI_GTK3 = 'gtk3' |
|
41 | 41 | GUI_NONE = 'none' # i.e. disable |
|
42 | 42 | |
|
43 | 43 | #----------------------------------------------------------------------------- |
|
44 | 44 | # Utilities |
|
45 | 45 | #----------------------------------------------------------------------------- |
|
46 | 46 | |
|
47 | 47 | def _stdin_ready_posix(): |
|
48 | 48 | """Return True if there's something to read on stdin (posix version).""" |
|
49 | 49 | infds, outfds, erfds = select.select([sys.stdin],[],[],0) |
|
50 | 50 | return bool(infds) |
|
51 | 51 | |
|
52 | 52 | def _stdin_ready_nt(): |
|
53 | 53 | """Return True if there's something to read on stdin (nt version).""" |
|
54 | 54 | return msvcrt.kbhit() |
|
55 | 55 | |
|
56 | 56 | def _stdin_ready_other(): |
|
57 | 57 | """Return True, assuming there's something to read on stdin.""" |
|
58 | 58 | return True # |
|
59 | 59 | |
|
60 | 60 | |
|
61 | 61 | def _ignore_CTRL_C_posix(): |
|
62 | 62 | """Ignore CTRL+C (SIGINT).""" |
|
63 | 63 | signal.signal(signal.SIGINT, signal.SIG_IGN) |
|
64 | 64 | |
|
65 | 65 | def _allow_CTRL_C_posix(): |
|
66 | 66 | """Take CTRL+C into account (SIGINT).""" |
|
67 | 67 | signal.signal(signal.SIGINT, signal.default_int_handler) |
|
68 | 68 | |
|
69 | 69 | def _ignore_CTRL_C_other(): |
|
70 | 70 | """Ignore CTRL+C (not implemented).""" |
|
71 | 71 | pass |
|
72 | 72 | |
|
73 | 73 | def _allow_CTRL_C_other(): |
|
74 | 74 | """Take CTRL+C into account (not implemented).""" |
|
75 | 75 | pass |
|
76 | 76 | |
|
77 | 77 | if os.name == 'posix': |
|
78 | 78 | import select |
|
79 | 79 | import signal |
|
80 | 80 | stdin_ready = _stdin_ready_posix |
|
81 | 81 | ignore_CTRL_C = _ignore_CTRL_C_posix |
|
82 | 82 | allow_CTRL_C = _allow_CTRL_C_posix |
|
83 | 83 | elif os.name == 'nt': |
|
84 | 84 | import msvcrt |
|
85 | 85 | stdin_ready = _stdin_ready_nt |
|
86 | 86 | ignore_CTRL_C = _ignore_CTRL_C_other |
|
87 | 87 | allow_CTRL_C = _allow_CTRL_C_other |
|
88 | 88 | else: |
|
89 | 89 | stdin_ready = _stdin_ready_other |
|
90 | 90 | ignore_CTRL_C = _ignore_CTRL_C_other |
|
91 | 91 | allow_CTRL_C = _allow_CTRL_C_other |
|
92 | 92 | |
|
93 | 93 | |
|
94 | 94 | #----------------------------------------------------------------------------- |
|
95 | 95 | # Main InputHookManager class |
|
96 | 96 | #----------------------------------------------------------------------------- |
|
97 | 97 | |
|
98 | 98 | |
|
99 | 99 | class InputHookManager(object): |
|
100 | 100 | """Manage PyOS_InputHook for different GUI toolkits. |
|
101 | 101 | |
|
102 | 102 | This class installs various hooks under ``PyOSInputHook`` to handle |
|
103 | 103 | GUI event loop integration. |
|
104 | 104 | """ |
|
105 | 105 | |
|
106 | 106 | def __init__(self): |
|
107 | 107 | if ctypes is None: |
|
108 | 108 | warn("IPython GUI event loop requires ctypes, %gui will not be available") |
|
109 | 109 | return |
|
110 | 110 | self.PYFUNC = ctypes.PYFUNCTYPE(ctypes.c_int) |
|
111 | 111 | self._apps = {} |
|
112 | 112 | self._reset() |
|
113 | 113 | |
|
114 | 114 | def _reset(self): |
|
115 | 115 | self._callback_pyfunctype = None |
|
116 | 116 | self._callback = None |
|
117 | 117 | self._installed = False |
|
118 | 118 | self._current_gui = None |
|
119 | 119 | |
|
120 | 120 | def get_pyos_inputhook(self): |
|
121 | 121 | """Return the current PyOS_InputHook as a ctypes.c_void_p.""" |
|
122 | 122 | return ctypes.c_void_p.in_dll(ctypes.pythonapi,"PyOS_InputHook") |
|
123 | 123 | |
|
124 | 124 | def get_pyos_inputhook_as_func(self): |
|
125 | 125 | """Return the current PyOS_InputHook as a ctypes.PYFUNCYPE.""" |
|
126 | 126 | return self.PYFUNC.in_dll(ctypes.pythonapi,"PyOS_InputHook") |
|
127 | 127 | |
|
128 | 128 | def set_inputhook(self, callback): |
|
129 | 129 | """Set PyOS_InputHook to callback and return the previous one.""" |
|
130 | 130 | # On platforms with 'readline' support, it's all too likely to |
|
131 | 131 | # have a KeyboardInterrupt signal delivered *even before* an |
|
132 | 132 | # initial ``try:`` clause in the callback can be executed, so |
|
133 | 133 | # we need to disable CTRL+C in this situation. |
|
134 | 134 | ignore_CTRL_C() |
|
135 | 135 | self._callback = callback |
|
136 | 136 | self._callback_pyfunctype = self.PYFUNC(callback) |
|
137 | 137 | pyos_inputhook_ptr = self.get_pyos_inputhook() |
|
138 | 138 | original = self.get_pyos_inputhook_as_func() |
|
139 | 139 | pyos_inputhook_ptr.value = \ |
|
140 | 140 | ctypes.cast(self._callback_pyfunctype, ctypes.c_void_p).value |
|
141 | 141 | self._installed = True |
|
142 | 142 | return original |
|
143 | 143 | |
|
144 | 144 | def clear_inputhook(self, app=None): |
|
145 | 145 | """Set PyOS_InputHook to NULL and return the previous one. |
|
146 | 146 | |
|
147 | 147 | Parameters |
|
148 | 148 | ---------- |
|
149 | 149 | app : optional, ignored |
|
150 | 150 | This parameter is allowed only so that clear_inputhook() can be |
|
151 | 151 | called with a similar interface as all the ``enable_*`` methods. But |
|
152 | 152 | the actual value of the parameter is ignored. This uniform interface |
|
153 | 153 | makes it easier to have user-level entry points in the main IPython |
|
154 | 154 | app like :meth:`enable_gui`.""" |
|
155 | 155 | pyos_inputhook_ptr = self.get_pyos_inputhook() |
|
156 | 156 | original = self.get_pyos_inputhook_as_func() |
|
157 | 157 | pyos_inputhook_ptr.value = ctypes.c_void_p(None).value |
|
158 | 158 | allow_CTRL_C() |
|
159 | 159 | self._reset() |
|
160 | 160 | return original |
|
161 | 161 | |
|
162 | 162 | def clear_app_refs(self, gui=None): |
|
163 | 163 | """Clear IPython's internal reference to an application instance. |
|
164 | 164 | |
|
165 | 165 | Whenever we create an app for a user on qt4 or wx, we hold a |
|
166 | 166 | reference to the app. This is needed because in some cases bad things |
|
167 | 167 | can happen if a user doesn't hold a reference themselves. This |
|
168 | 168 | method is provided to clear the references we are holding. |
|
169 | 169 | |
|
170 | 170 | Parameters |
|
171 | 171 | ---------- |
|
172 | 172 | gui : None or str |
|
173 | 173 | If None, clear all app references. If ('wx', 'qt4') clear |
|
174 | 174 | the app for that toolkit. References are not held for gtk or tk |
|
175 | 175 | as those toolkits don't have the notion of an app. |
|
176 | 176 | """ |
|
177 | 177 | if gui is None: |
|
178 | 178 | self._apps = {} |
|
179 | 179 | elif gui in self._apps: |
|
180 | 180 | del self._apps[gui] |
|
181 | 181 | |
|
182 | 182 | def enable_wx(self, app=None): |
|
183 | 183 | """Enable event loop integration with wxPython. |
|
184 | 184 | |
|
185 | 185 | Parameters |
|
186 | 186 | ---------- |
|
187 | 187 | app : WX Application, optional. |
|
188 | 188 | Running application to use. If not given, we probe WX for an |
|
189 | 189 | existing application object, and create a new one if none is found. |
|
190 | 190 | |
|
191 | 191 | Notes |
|
192 | 192 | ----- |
|
193 | 193 | This methods sets the ``PyOS_InputHook`` for wxPython, which allows |
|
194 | 194 | the wxPython to integrate with terminal based applications like |
|
195 | 195 | IPython. |
|
196 | 196 | |
|
197 | 197 | If ``app`` is not given we probe for an existing one, and return it if |
|
198 | 198 | found. If no existing app is found, we create an :class:`wx.App` as |
|
199 | 199 | follows:: |
|
200 | 200 | |
|
201 | 201 | import wx |
|
202 | 202 | app = wx.App(redirect=False, clearSigInt=False) |
|
203 | 203 | """ |
|
204 | 204 | import wx |
|
205 | 205 | |
|
206 | 206 | wx_version = V(wx.__version__).version |
|
207 | 207 | |
|
208 | 208 | if wx_version < [2, 8]: |
|
209 | 209 | raise ValueError("requires wxPython >= 2.8, but you have %s" % wx.__version__) |
|
210 | 210 | |
|
211 | 211 | from IPython.lib.inputhookwx import inputhook_wx |
|
212 | 212 | self.set_inputhook(inputhook_wx) |
|
213 | 213 | self._current_gui = GUI_WX |
|
214 | 214 | import wx |
|
215 | 215 | if app is None: |
|
216 | 216 | app = wx.GetApp() |
|
217 | 217 | if app is None: |
|
218 | 218 | app = wx.App(redirect=False, clearSigInt=False) |
|
219 | 219 | app._in_event_loop = True |
|
220 | 220 | self._apps[GUI_WX] = app |
|
221 | 221 | return app |
|
222 | 222 | |
|
223 | 223 | def disable_wx(self): |
|
224 | 224 | """Disable event loop integration with wxPython. |
|
225 | 225 | |
|
226 | 226 | This merely sets PyOS_InputHook to NULL. |
|
227 | 227 | """ |
|
228 | 228 | if GUI_WX in self._apps: |
|
229 | 229 | self._apps[GUI_WX]._in_event_loop = False |
|
230 | 230 | self.clear_inputhook() |
|
231 | 231 | |
|
232 | 232 | def enable_qt4(self, app=None): |
|
233 | 233 | """Enable event loop integration with PyQt4. |
|
234 | 234 | |
|
235 | 235 | Parameters |
|
236 | 236 | ---------- |
|
237 | 237 | app : Qt Application, optional. |
|
238 | 238 | Running application to use. If not given, we probe Qt for an |
|
239 | 239 | existing application object, and create a new one if none is found. |
|
240 | 240 | |
|
241 | 241 | Notes |
|
242 | 242 | ----- |
|
243 | 243 | This methods sets the PyOS_InputHook for PyQt4, which allows |
|
244 | 244 | the PyQt4 to integrate with terminal based applications like |
|
245 | 245 | IPython. |
|
246 | 246 | |
|
247 | 247 | If ``app`` is not given we probe for an existing one, and return it if |
|
248 | 248 | found. If no existing app is found, we create an :class:`QApplication` |
|
249 | 249 | as follows:: |
|
250 | 250 | |
|
251 | 251 | from PyQt4 import QtCore |
|
252 | 252 | app = QtGui.QApplication(sys.argv) |
|
253 | 253 | """ |
|
254 | 254 | from IPython.lib.inputhookqt4 import create_inputhook_qt4 |
|
255 | 255 | app, inputhook_qt4 = create_inputhook_qt4(self, app) |
|
256 | 256 | self.set_inputhook(inputhook_qt4) |
|
257 | 257 | |
|
258 | 258 | self._current_gui = GUI_QT4 |
|
259 | 259 | app._in_event_loop = True |
|
260 | 260 | self._apps[GUI_QT4] = app |
|
261 | 261 | return app |
|
262 | 262 | |
|
263 | 263 | def disable_qt4(self): |
|
264 | 264 | """Disable event loop integration with PyQt4. |
|
265 | 265 | |
|
266 | 266 | This merely sets PyOS_InputHook to NULL. |
|
267 | 267 | """ |
|
268 | 268 | if GUI_QT4 in self._apps: |
|
269 | 269 | self._apps[GUI_QT4]._in_event_loop = False |
|
270 | 270 | self.clear_inputhook() |
|
271 | 271 | |
|
272 | 272 | def enable_gtk(self, app=None): |
|
273 | 273 | """Enable event loop integration with PyGTK. |
|
274 | 274 | |
|
275 | 275 | Parameters |
|
276 | 276 | ---------- |
|
277 | 277 | app : ignored |
|
278 | 278 | Ignored, it's only a placeholder to keep the call signature of all |
|
279 | 279 | gui activation methods consistent, which simplifies the logic of |
|
280 | 280 | supporting magics. |
|
281 | 281 | |
|
282 | 282 | Notes |
|
283 | 283 | ----- |
|
284 | 284 | This methods sets the PyOS_InputHook for PyGTK, which allows |
|
285 | 285 | the PyGTK to integrate with terminal based applications like |
|
286 | 286 | IPython. |
|
287 | 287 | """ |
|
288 | 288 | import gtk |
|
289 | 289 | try: |
|
290 | 290 | gtk.set_interactive(True) |
|
291 | 291 | self._current_gui = GUI_GTK |
|
292 | 292 | except AttributeError: |
|
293 | 293 | # For older versions of gtk, use our own ctypes version |
|
294 | 294 | from IPython.lib.inputhookgtk import inputhook_gtk |
|
295 | 295 | self.set_inputhook(inputhook_gtk) |
|
296 | 296 | self._current_gui = GUI_GTK |
|
297 | 297 | |
|
298 | 298 | def disable_gtk(self): |
|
299 | 299 | """Disable event loop integration with PyGTK. |
|
300 | 300 | |
|
301 | 301 | This merely sets PyOS_InputHook to NULL. |
|
302 | 302 | """ |
|
303 | 303 | self.clear_inputhook() |
|
304 | 304 | |
|
305 | 305 | def enable_tk(self, app=None): |
|
306 | 306 | """Enable event loop integration with Tk. |
|
307 | 307 | |
|
308 | 308 | Parameters |
|
309 | 309 | ---------- |
|
310 | 310 | app : toplevel :class:`Tkinter.Tk` widget, optional. |
|
311 | 311 | Running toplevel widget to use. If not given, we probe Tk for an |
|
312 | 312 | existing one, and create a new one if none is found. |
|
313 | 313 | |
|
314 | 314 | Notes |
|
315 | 315 | ----- |
|
316 | 316 | If you have already created a :class:`Tkinter.Tk` object, the only |
|
317 | 317 | thing done by this method is to register with the |
|
318 | 318 | :class:`InputHookManager`, since creating that object automatically |
|
319 | 319 | sets ``PyOS_InputHook``. |
|
320 | 320 | """ |
|
321 | 321 | self._current_gui = GUI_TK |
|
322 | 322 | if app is None: |
|
323 | 323 | import Tkinter |
|
324 | 324 | app = Tkinter.Tk() |
|
325 | 325 | app.withdraw() |
|
326 | 326 | self._apps[GUI_TK] = app |
|
327 | 327 | return app |
|
328 | 328 | |
|
329 | 329 | def disable_tk(self): |
|
330 | 330 | """Disable event loop integration with Tkinter. |
|
331 | 331 | |
|
332 | 332 | This merely sets PyOS_InputHook to NULL. |
|
333 | 333 | """ |
|
334 | 334 | self.clear_inputhook() |
|
335 | 335 | |
|
336 | 336 | |
|
337 | 337 | def enable_glut(self, app=None): |
|
338 | 338 | """ Enable event loop integration with GLUT. |
|
339 | 339 | |
|
340 | 340 | Parameters |
|
341 | 341 | ---------- |
|
342 | 342 | |
|
343 | 343 | app : ignored |
|
344 | 344 | Ignored, it's only a placeholder to keep the call signature of all |
|
345 | 345 | gui activation methods consistent, which simplifies the logic of |
|
346 | 346 | supporting magics. |
|
347 | 347 | |
|
348 | 348 | Notes |
|
349 | 349 | ----- |
|
350 | 350 | |
|
351 | 351 | This methods sets the PyOS_InputHook for GLUT, which allows the GLUT to |
|
352 | 352 | integrate with terminal based applications like IPython. Due to GLUT |
|
353 | 353 | limitations, it is currently not possible to start the event loop |
|
354 | 354 | without first creating a window. You should thus not create another |
|
355 | 355 | window but use instead the created one. See 'gui-glut.py' in the |
|
356 | 356 | docs/examples/lib directory. |
|
357 | 357 | |
|
358 | 358 | The default screen mode is set to: |
|
359 | 359 | glut.GLUT_DOUBLE | glut.GLUT_RGBA | glut.GLUT_DEPTH |
|
360 | 360 | """ |
|
361 | 361 | |
|
362 | 362 | import OpenGL.GLUT as glut |
|
363 | 363 | from IPython.lib.inputhookglut import glut_display_mode, \ |
|
364 | 364 | glut_close, glut_display, \ |
|
365 | 365 | glut_idle, inputhook_glut |
|
366 | 366 | |
|
367 | 367 | if GUI_GLUT not in self._apps: |
|
368 | 368 | glut.glutInit( sys.argv ) |
|
369 | 369 | glut.glutInitDisplayMode( glut_display_mode ) |
|
370 | 370 | # This is specific to freeglut |
|
371 | 371 | if bool(glut.glutSetOption): |
|
372 | 372 | glut.glutSetOption( glut.GLUT_ACTION_ON_WINDOW_CLOSE, |
|
373 | 373 | glut.GLUT_ACTION_GLUTMAINLOOP_RETURNS ) |
|
374 | 374 | glut.glutCreateWindow( sys.argv[0] ) |
|
375 | 375 | glut.glutReshapeWindow( 1, 1 ) |
|
376 | 376 | glut.glutHideWindow( ) |
|
377 | 377 | glut.glutWMCloseFunc( glut_close ) |
|
378 | 378 | glut.glutDisplayFunc( glut_display ) |
|
379 | 379 | glut.glutIdleFunc( glut_idle ) |
|
380 | 380 | else: |
|
381 | 381 | glut.glutWMCloseFunc( glut_close ) |
|
382 | 382 | glut.glutDisplayFunc( glut_display ) |
|
383 | 383 | glut.glutIdleFunc( glut_idle) |
|
384 | 384 | self.set_inputhook( inputhook_glut ) |
|
385 | 385 | self._current_gui = GUI_GLUT |
|
386 | 386 | self._apps[GUI_GLUT] = True |
|
387 | 387 | |
|
388 | 388 | |
|
389 | 389 | def disable_glut(self): |
|
390 | 390 | """Disable event loop integration with glut. |
|
391 | 391 | |
|
392 | 392 | This sets PyOS_InputHook to NULL and set the display function to a |
|
393 | 393 | dummy one and set the timer to a dummy timer that will be triggered |
|
394 | 394 | very far in the future. |
|
395 | 395 | """ |
|
396 | 396 | import OpenGL.GLUT as glut |
|
397 | 397 | from glut_support import glutMainLoopEvent |
|
398 | 398 | |
|
399 | 399 | glut.glutHideWindow() # This is an event to be processed below |
|
400 | 400 | glutMainLoopEvent() |
|
401 | 401 | self.clear_inputhook() |
|
402 | 402 | |
|
403 | 403 | def enable_pyglet(self, app=None): |
|
404 | 404 | """Enable event loop integration with pyglet. |
|
405 | 405 | |
|
406 | 406 | Parameters |
|
407 | 407 | ---------- |
|
408 | 408 | app : ignored |
|
409 | 409 | Ignored, it's only a placeholder to keep the call signature of all |
|
410 | 410 | gui activation methods consistent, which simplifies the logic of |
|
411 | 411 | supporting magics. |
|
412 | 412 | |
|
413 | 413 | Notes |
|
414 | 414 | ----- |
|
415 | 415 | This methods sets the ``PyOS_InputHook`` for pyglet, which allows |
|
416 | 416 | pyglet to integrate with terminal based applications like |
|
417 | 417 | IPython. |
|
418 | 418 | |
|
419 | 419 | """ |
|
420 | 420 | import pyglet |
|
421 | 421 | from IPython.lib.inputhookpyglet import inputhook_pyglet |
|
422 | 422 | self.set_inputhook(inputhook_pyglet) |
|
423 | 423 | self._current_gui = GUI_PYGLET |
|
424 | 424 | return app |
|
425 | 425 | |
|
426 | 426 | def disable_pyglet(self): |
|
427 | 427 | """Disable event loop integration with pyglet. |
|
428 | 428 | |
|
429 | 429 | This merely sets PyOS_InputHook to NULL. |
|
430 | 430 | """ |
|
431 | 431 | self.clear_inputhook() |
|
432 | 432 | |
|
433 | 433 | def enable_gtk3(self, app=None): |
|
434 | 434 | """Enable event loop integration with Gtk3 (gir bindings). |
|
435 | 435 | |
|
436 | 436 | Parameters |
|
437 | 437 | ---------- |
|
438 | 438 | app : ignored |
|
439 | 439 | Ignored, it's only a placeholder to keep the call signature of all |
|
440 | 440 | gui activation methods consistent, which simplifies the logic of |
|
441 | 441 | supporting magics. |
|
442 | 442 | |
|
443 | 443 | Notes |
|
444 | 444 | ----- |
|
445 | 445 | This methods sets the PyOS_InputHook for Gtk3, which allows |
|
446 | 446 | the Gtk3 to integrate with terminal based applications like |
|
447 | 447 | IPython. |
|
448 | 448 | """ |
|
449 | 449 | from IPython.lib.inputhookgtk3 import inputhook_gtk3 |
|
450 | 450 | self.set_inputhook(inputhook_gtk3) |
|
451 | 451 | self._current_gui = GUI_GTK |
|
452 | 452 | |
|
453 | 453 | def disable_gtk3(self): |
|
454 | 454 | """Disable event loop integration with PyGTK. |
|
455 | 455 | |
|
456 | 456 | This merely sets PyOS_InputHook to NULL. |
|
457 | 457 | """ |
|
458 | 458 | self.clear_inputhook() |
|
459 | 459 | |
|
460 | 460 | def current_gui(self): |
|
461 | 461 | """Return a string indicating the currently active GUI or None.""" |
|
462 | 462 | return self._current_gui |
|
463 | 463 | |
|
464 | 464 | inputhook_manager = InputHookManager() |
|
465 | 465 | |
|
466 | 466 | enable_wx = inputhook_manager.enable_wx |
|
467 | 467 | disable_wx = inputhook_manager.disable_wx |
|
468 | 468 | enable_qt4 = inputhook_manager.enable_qt4 |
|
469 | 469 | disable_qt4 = inputhook_manager.disable_qt4 |
|
470 | 470 | enable_gtk = inputhook_manager.enable_gtk |
|
471 | 471 | disable_gtk = inputhook_manager.disable_gtk |
|
472 | 472 | enable_tk = inputhook_manager.enable_tk |
|
473 | 473 | disable_tk = inputhook_manager.disable_tk |
|
474 | 474 | enable_glut = inputhook_manager.enable_glut |
|
475 | 475 | disable_glut = inputhook_manager.disable_glut |
|
476 | 476 | enable_pyglet = inputhook_manager.enable_pyglet |
|
477 | 477 | disable_pyglet = inputhook_manager.disable_pyglet |
|
478 | 478 | enable_gtk3 = inputhook_manager.enable_gtk3 |
|
479 | 479 | disable_gtk3 = inputhook_manager.disable_gtk3 |
|
480 | 480 | clear_inputhook = inputhook_manager.clear_inputhook |
|
481 | 481 | set_inputhook = inputhook_manager.set_inputhook |
|
482 | 482 | current_gui = inputhook_manager.current_gui |
|
483 | 483 | clear_app_refs = inputhook_manager.clear_app_refs |
|
484 | 484 | |
|
485 | 485 | |
|
486 | 486 | # Convenience function to switch amongst them |
|
487 | 487 | def enable_gui(gui=None, app=None): |
|
488 | 488 | """Switch amongst GUI input hooks by name. |
|
489 | 489 | |
|
490 | 490 | This is just a utility wrapper around the methods of the InputHookManager |
|
491 | 491 | object. |
|
492 | 492 | |
|
493 | 493 | Parameters |
|
494 | 494 | ---------- |
|
495 | 495 | gui : optional, string or None |
|
496 | 496 | If None (or 'none'), clears input hook, otherwise it must be one |
|
497 | 497 | of the recognized GUI names (see ``GUI_*`` constants in module). |
|
498 | 498 | |
|
499 | 499 | app : optional, existing application object. |
|
500 | 500 | For toolkits that have the concept of a global app, you can supply an |
|
501 | 501 | existing one. If not given, the toolkit will be probed for one, and if |
|
502 | 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 | 505 | Returns |
|
506 | 506 | ------- |
|
507 | 507 | The output of the underlying gui switch routine, typically the actual |
|
508 | 508 | PyOS_InputHook wrapper object or the GUI toolkit app created, if there was |
|
509 | 509 | one. |
|
510 | 510 | """ |
|
511 | 511 | guis = {None: clear_inputhook, |
|
512 | 512 | GUI_NONE: clear_inputhook, |
|
513 | 513 | GUI_OSX: lambda app=False: None, |
|
514 | 514 | GUI_TK: enable_tk, |
|
515 | 515 | GUI_GTK: enable_gtk, |
|
516 | 516 | GUI_WX: enable_wx, |
|
517 | 517 | GUI_QT: enable_qt4, # qt3 not supported |
|
518 | 518 | GUI_QT4: enable_qt4, |
|
519 | 519 | GUI_GLUT: enable_glut, |
|
520 | 520 | GUI_PYGLET: enable_pyglet, |
|
521 | 521 | GUI_GTK3: enable_gtk3, |
|
522 | 522 | } |
|
523 | 523 | try: |
|
524 | 524 | gui_hook = guis[gui] |
|
525 | 525 | except KeyError: |
|
526 | 526 | e = "Invalid GUI request %r, valid ones are:%s" % (gui, guis.keys()) |
|
527 | 527 | raise ValueError(e) |
|
528 | 528 | return gui_hook(app) |
|
529 | 529 |
@@ -1,358 +1,358 b'' | |||
|
1 | 1 | # -*- coding: utf-8 -*- |
|
2 | 2 | """Decorators for labeling test objects. |
|
3 | 3 | |
|
4 | 4 | Decorators that merely return a modified version of the original function |
|
5 | 5 | object are straightforward. Decorators that return a new function object need |
|
6 | 6 | to use nose.tools.make_decorator(original_function)(decorator) in returning the |
|
7 | 7 | decorator, in order to preserve metadata such as function name, setup and |
|
8 | 8 | teardown functions and so on - see nose.tools for more information. |
|
9 | 9 | |
|
10 | 10 | This module provides a set of useful decorators meant to be ready to use in |
|
11 | 11 | your own tests. See the bottom of the file for the ready-made ones, and if you |
|
12 | 12 | find yourself writing a new one that may be of generic use, add it here. |
|
13 | 13 | |
|
14 | 14 | Included decorators: |
|
15 | 15 | |
|
16 | 16 | |
|
17 | 17 | Lightweight testing that remains unittest-compatible. |
|
18 | 18 | |
|
19 | 19 | - @parametric, for parametric test support that is vastly easier to use than |
|
20 | 20 | nose's for debugging. With ours, if a test fails, the stack under inspection |
|
21 | 21 | is that of the test and not that of the test framework. |
|
22 | 22 | |
|
23 | 23 | - An @as_unittest decorator can be used to tag any normal parameter-less |
|
24 | 24 | function as a unittest TestCase. Then, both nose and normal unittest will |
|
25 | 25 | recognize it as such. This will make it easier to migrate away from Nose if |
|
26 | 26 | we ever need/want to while maintaining very lightweight tests. |
|
27 | 27 | |
|
28 | 28 | NOTE: This file contains IPython-specific decorators. Using the machinery in |
|
29 | 29 | IPython.external.decorators, we import either numpy.testing.decorators if numpy is |
|
30 | 30 | available, OR use equivalent code in IPython.external._decorators, which |
|
31 | 31 | we've copied verbatim from numpy. |
|
32 | 32 | |
|
33 | 33 | Authors |
|
34 | 34 | ------- |
|
35 | 35 | |
|
36 | 36 | - Fernando Perez <Fernando.Perez@berkeley.edu> |
|
37 | 37 | """ |
|
38 | 38 | |
|
39 | 39 | #----------------------------------------------------------------------------- |
|
40 | 40 | # Copyright (C) 2009-2011 The IPython Development Team |
|
41 | 41 | # |
|
42 | 42 | # Distributed under the terms of the BSD License. The full license is in |
|
43 | 43 | # the file COPYING, distributed as part of this software. |
|
44 | 44 | #----------------------------------------------------------------------------- |
|
45 | 45 | |
|
46 | 46 | #----------------------------------------------------------------------------- |
|
47 | 47 | # Imports |
|
48 | 48 | #----------------------------------------------------------------------------- |
|
49 | 49 | |
|
50 | 50 | # Stdlib imports |
|
51 | 51 | import inspect |
|
52 | 52 | import sys |
|
53 | 53 | import tempfile |
|
54 | 54 | import unittest |
|
55 | 55 | |
|
56 | 56 | # Third-party imports |
|
57 | 57 | |
|
58 | 58 | # This is Michele Simionato's decorator module, kept verbatim. |
|
59 | 59 | from IPython.external.decorator import decorator |
|
60 | 60 | |
|
61 | 61 | # We already have python3-compliant code for parametric tests |
|
62 | 62 | if sys.version[0]=='2': |
|
63 | 63 | from _paramtestpy2 import parametric, ParametricTestCase |
|
64 | 64 | else: |
|
65 | 65 | from _paramtestpy3 import parametric, ParametricTestCase |
|
66 | 66 | |
|
67 | 67 | # Expose the unittest-driven decorators |
|
68 | 68 | from ipunittest import ipdoctest, ipdocstring |
|
69 | 69 | |
|
70 | 70 | # Grab the numpy-specific decorators which we keep in a file that we |
|
71 | 71 | # occasionally update from upstream: decorators.py is a copy of |
|
72 | 72 | # numpy.testing.decorators, we expose all of it here. |
|
73 | 73 | from IPython.external.decorators import * |
|
74 | 74 | |
|
75 | 75 | # For onlyif_cmd_exists decorator |
|
76 | 76 | from IPython.utils.process import is_cmd_found |
|
77 | 77 | |
|
78 | 78 | #----------------------------------------------------------------------------- |
|
79 | 79 | # Classes and functions |
|
80 | 80 | #----------------------------------------------------------------------------- |
|
81 | 81 | |
|
82 | 82 | # Simple example of the basic idea |
|
83 | 83 | def as_unittest(func): |
|
84 | 84 | """Decorator to make a simple function into a normal test via unittest.""" |
|
85 | 85 | class Tester(unittest.TestCase): |
|
86 | 86 | def test(self): |
|
87 | 87 | func() |
|
88 | 88 | |
|
89 | 89 | Tester.__name__ = func.__name__ |
|
90 | 90 | |
|
91 | 91 | return Tester |
|
92 | 92 | |
|
93 | 93 | # Utility functions |
|
94 | 94 | |
|
95 | 95 | def apply_wrapper(wrapper,func): |
|
96 | 96 | """Apply a wrapper to a function for decoration. |
|
97 | 97 | |
|
98 | 98 | This mixes Michele Simionato's decorator tool with nose's make_decorator, |
|
99 | 99 | to apply a wrapper in a decorator so that all nose attributes, as well as |
|
100 | 100 | function signature and other properties, survive the decoration cleanly. |
|
101 | 101 | This will ensure that wrapped functions can still be well introspected via |
|
102 | 102 | IPython, for example. |
|
103 | 103 | """ |
|
104 | 104 | import nose.tools |
|
105 | 105 | |
|
106 | 106 | return decorator(wrapper,nose.tools.make_decorator(func)(wrapper)) |
|
107 | 107 | |
|
108 | 108 | |
|
109 | 109 | def make_label_dec(label,ds=None): |
|
110 | 110 | """Factory function to create a decorator that applies one or more labels. |
|
111 | 111 | |
|
112 | 112 | Parameters |
|
113 | 113 | ---------- |
|
114 | 114 | label : string or sequence |
|
115 | 115 | One or more labels that will be applied by the decorator to the functions |
|
116 | 116 | it decorates. Labels are attributes of the decorated function with their |
|
117 | 117 | value set to True. |
|
118 | 118 | |
|
119 | 119 | ds : string |
|
120 | 120 | An optional docstring for the resulting decorator. If not given, a |
|
121 | 121 | default docstring is auto-generated. |
|
122 | 122 | |
|
123 | 123 | Returns |
|
124 | 124 | ------- |
|
125 | 125 | A decorator. |
|
126 | 126 | |
|
127 | 127 | Examples |
|
128 | 128 | -------- |
|
129 | 129 | |
|
130 | 130 | A simple labeling decorator: |
|
131 | 131 | >>> slow = make_label_dec('slow') |
|
132 | 132 | >>> print slow.__doc__ |
|
133 | 133 | Labels a test as 'slow'. |
|
134 | 134 | |
|
135 | 135 | And one that uses multiple labels and a custom docstring: |
|
136 | 136 | >>> rare = make_label_dec(['slow','hard'], |
|
137 | 137 | ... "Mix labels 'slow' and 'hard' for rare tests.") |
|
138 | 138 | >>> print rare.__doc__ |
|
139 | 139 | Mix labels 'slow' and 'hard' for rare tests. |
|
140 | 140 | |
|
141 | 141 | Now, let's test using this one: |
|
142 | 142 | >>> @rare |
|
143 | 143 | ... def f(): pass |
|
144 | 144 | ... |
|
145 | 145 | >>> |
|
146 | 146 | >>> f.slow |
|
147 | 147 | True |
|
148 | 148 | >>> f.hard |
|
149 | 149 | True |
|
150 | 150 | """ |
|
151 | 151 | |
|
152 | 152 | if isinstance(label,basestring): |
|
153 | 153 | labels = [label] |
|
154 | 154 | else: |
|
155 | 155 | labels = label |
|
156 | 156 | |
|
157 | 157 | # Validate that the given label(s) are OK for use in setattr() by doing a |
|
158 | 158 | # dry run on a dummy function. |
|
159 | 159 | tmp = lambda : None |
|
160 | 160 | for label in labels: |
|
161 | 161 | setattr(tmp,label,True) |
|
162 | 162 | |
|
163 | 163 | # This is the actual decorator we'll return |
|
164 | 164 | def decor(f): |
|
165 | 165 | for label in labels: |
|
166 | 166 | setattr(f,label,True) |
|
167 | 167 | return f |
|
168 | 168 | |
|
169 | 169 | # Apply the user's docstring, or autogenerate a basic one |
|
170 | 170 | if ds is None: |
|
171 | 171 | ds = "Labels a test as %r." % label |
|
172 | 172 | decor.__doc__ = ds |
|
173 | 173 | |
|
174 | 174 | return decor |
|
175 | 175 | |
|
176 | 176 | |
|
177 | 177 | # Inspired by numpy's skipif, but uses the full apply_wrapper utility to |
|
178 | 178 | # preserve function metadata better and allows the skip condition to be a |
|
179 | 179 | # callable. |
|
180 | 180 | def skipif(skip_condition, msg=None): |
|
181 | 181 | ''' Make function raise SkipTest exception if skip_condition is true |
|
182 | 182 | |
|
183 | 183 | Parameters |
|
184 | 184 | ---------- |
|
185 | 185 | skip_condition : bool or callable. |
|
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 | |
|
188 | is useful for tests that may require costly imports, to delay the cost | |
|
189 | until the test suite is actually executed. | |
|
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 | |
|
188 | is useful for tests that may require costly imports, to delay the cost | |
|
189 | until the test suite is actually executed. | |
|
190 | 190 | msg : string |
|
191 | 191 | Message to give on raising a SkipTest exception |
|
192 | 192 | |
|
193 | 193 | Returns |
|
194 | 194 | ------- |
|
195 | 195 | decorator : function |
|
196 | 196 | Decorator, which, when applied to a function, causes SkipTest |
|
197 | 197 | to be raised when the skip_condition was True, and the function |
|
198 | 198 | to be called normally otherwise. |
|
199 | 199 | |
|
200 | 200 | Notes |
|
201 | 201 | ----- |
|
202 | 202 | You will see from the code that we had to further decorate the |
|
203 | 203 | decorator with the nose.tools.make_decorator function in order to |
|
204 | 204 | transmit function name, and various other metadata. |
|
205 | 205 | ''' |
|
206 | 206 | |
|
207 | 207 | def skip_decorator(f): |
|
208 | 208 | # Local import to avoid a hard nose dependency and only incur the |
|
209 | 209 | # import time overhead at actual test-time. |
|
210 | 210 | import nose |
|
211 | 211 | |
|
212 | 212 | # Allow for both boolean or callable skip conditions. |
|
213 | 213 | if callable(skip_condition): |
|
214 | 214 | skip_val = skip_condition |
|
215 | 215 | else: |
|
216 | 216 | skip_val = lambda : skip_condition |
|
217 | 217 | |
|
218 | 218 | def get_msg(func,msg=None): |
|
219 | 219 | """Skip message with information about function being skipped.""" |
|
220 | 220 | if msg is None: out = 'Test skipped due to test condition.' |
|
221 | 221 | else: out = msg |
|
222 | 222 | return "Skipping test: %s. %s" % (func.__name__,out) |
|
223 | 223 | |
|
224 | 224 | # We need to define *two* skippers because Python doesn't allow both |
|
225 | 225 | # return with value and yield inside the same function. |
|
226 | 226 | def skipper_func(*args, **kwargs): |
|
227 | 227 | """Skipper for normal test functions.""" |
|
228 | 228 | if skip_val(): |
|
229 | 229 | raise nose.SkipTest(get_msg(f,msg)) |
|
230 | 230 | else: |
|
231 | 231 | return f(*args, **kwargs) |
|
232 | 232 | |
|
233 | 233 | def skipper_gen(*args, **kwargs): |
|
234 | 234 | """Skipper for test generators.""" |
|
235 | 235 | if skip_val(): |
|
236 | 236 | raise nose.SkipTest(get_msg(f,msg)) |
|
237 | 237 | else: |
|
238 | 238 | for x in f(*args, **kwargs): |
|
239 | 239 | yield x |
|
240 | 240 | |
|
241 | 241 | # Choose the right skipper to use when building the actual generator. |
|
242 | 242 | if nose.util.isgenerator(f): |
|
243 | 243 | skipper = skipper_gen |
|
244 | 244 | else: |
|
245 | 245 | skipper = skipper_func |
|
246 | 246 | |
|
247 | 247 | return nose.tools.make_decorator(f)(skipper) |
|
248 | 248 | |
|
249 | 249 | return skip_decorator |
|
250 | 250 | |
|
251 | 251 | # A version with the condition set to true, common case just to attach a message |
|
252 | 252 | # to a skip decorator |
|
253 | 253 | def skip(msg=None): |
|
254 | 254 | """Decorator factory - mark a test function for skipping from test suite. |
|
255 | 255 | |
|
256 | 256 | Parameters |
|
257 | 257 | ---------- |
|
258 | 258 | msg : string |
|
259 | 259 | Optional message to be added. |
|
260 | 260 | |
|
261 | 261 | Returns |
|
262 | 262 | ------- |
|
263 | 263 | decorator : function |
|
264 | 264 | Decorator, which, when applied to a function, causes SkipTest |
|
265 | 265 | to be raised, with the optional message added. |
|
266 | 266 | """ |
|
267 | 267 | |
|
268 | 268 | return skipif(True,msg) |
|
269 | 269 | |
|
270 | 270 | |
|
271 | 271 | def onlyif(condition, msg): |
|
272 | 272 | """The reverse from skipif, see skipif for details.""" |
|
273 | 273 | |
|
274 | 274 | if callable(condition): |
|
275 | 275 | skip_condition = lambda : not condition() |
|
276 | 276 | else: |
|
277 | 277 | skip_condition = lambda : not condition |
|
278 | 278 | |
|
279 | 279 | return skipif(skip_condition, msg) |
|
280 | 280 | |
|
281 | 281 | #----------------------------------------------------------------------------- |
|
282 | 282 | # Utility functions for decorators |
|
283 | 283 | def module_not_available(module): |
|
284 | 284 | """Can module be imported? Returns true if module does NOT import. |
|
285 | 285 | |
|
286 | 286 | This is used to make a decorator to skip tests that require module to be |
|
287 | 287 | available, but delay the 'import numpy' to test execution time. |
|
288 | 288 | """ |
|
289 | 289 | try: |
|
290 | 290 | mod = __import__(module) |
|
291 | 291 | mod_not_avail = False |
|
292 | 292 | except ImportError: |
|
293 | 293 | mod_not_avail = True |
|
294 | 294 | |
|
295 | 295 | return mod_not_avail |
|
296 | 296 | |
|
297 | 297 | #----------------------------------------------------------------------------- |
|
298 | 298 | # Decorators for public use |
|
299 | 299 | |
|
300 | 300 | # Decorators to skip certain tests on specific platforms. |
|
301 | 301 | skip_win32 = skipif(sys.platform == 'win32', |
|
302 | 302 | "This test does not run under Windows") |
|
303 | 303 | skip_linux = skipif(sys.platform.startswith('linux'), |
|
304 | 304 | "This test does not run under Linux") |
|
305 | 305 | skip_osx = skipif(sys.platform == 'darwin',"This test does not run under OS X") |
|
306 | 306 | |
|
307 | 307 | |
|
308 | 308 | # Decorators to skip tests if not on specific platforms. |
|
309 | 309 | skip_if_not_win32 = skipif(sys.platform != 'win32', |
|
310 | 310 | "This test only runs under Windows") |
|
311 | 311 | skip_if_not_linux = skipif(not sys.platform.startswith('linux'), |
|
312 | 312 | "This test only runs under Linux") |
|
313 | 313 | skip_if_not_osx = skipif(sys.platform != 'darwin', |
|
314 | 314 | "This test only runs under OSX") |
|
315 | 315 | |
|
316 | 316 | # Other skip decorators |
|
317 | 317 | |
|
318 | 318 | # generic skip without module |
|
319 | 319 | skip_without = lambda mod: skipif(module_not_available(mod), "This test requires %s" % mod) |
|
320 | 320 | |
|
321 | 321 | skipif_not_numpy = skip_without('numpy') |
|
322 | 322 | |
|
323 | 323 | skipif_not_matplotlib = skip_without('matplotlib') |
|
324 | 324 | |
|
325 | 325 | skipif_not_sympy = skip_without('sympy') |
|
326 | 326 | |
|
327 | 327 | skip_known_failure = knownfailureif(True,'This test is known to fail') |
|
328 | 328 | |
|
329 | 329 | known_failure_py3 = knownfailureif(sys.version_info[0] >= 3, |
|
330 | 330 | 'This test is known to fail on Python 3.') |
|
331 | 331 | |
|
332 | 332 | # A null 'decorator', useful to make more readable code that needs to pick |
|
333 | 333 | # between different decorators based on OS or other conditions |
|
334 | 334 | null_deco = lambda f: f |
|
335 | 335 | |
|
336 | 336 | # Some tests only run where we can use unicode paths. Note that we can't just |
|
337 | 337 | # check os.path.supports_unicode_filenames, which is always False on Linux. |
|
338 | 338 | try: |
|
339 | 339 | f = tempfile.NamedTemporaryFile(prefix=u"tmpβ¬") |
|
340 | 340 | except UnicodeEncodeError: |
|
341 | 341 | unicode_paths = False |
|
342 | 342 | else: |
|
343 | 343 | unicode_paths = True |
|
344 | 344 | f.close() |
|
345 | 345 | |
|
346 | 346 | onlyif_unicode_paths = onlyif(unicode_paths, ("This test is only applicable " |
|
347 | 347 | "where we can use unicode in filenames.")) |
|
348 | 348 | |
|
349 | 349 | |
|
350 | 350 | def onlyif_cmds_exist(*commands): |
|
351 | 351 | """ |
|
352 | 352 | Decorator to skip test when at least one of `commands` is not found. |
|
353 | 353 | """ |
|
354 | 354 | for cmd in commands: |
|
355 | 355 | if not is_cmd_found(cmd): |
|
356 | 356 | return skip("This test runs only if command '{0}' " |
|
357 | 357 | "is installed".format(cmd)) |
|
358 | 358 | return null_deco |
@@ -1,391 +1,392 b'' | |||
|
1 | 1 | """Generic testing tools. |
|
2 | 2 | |
|
3 | 3 | Authors |
|
4 | 4 | ------- |
|
5 | 5 | - Fernando Perez <Fernando.Perez@berkeley.edu> |
|
6 | 6 | """ |
|
7 | 7 | |
|
8 | 8 | from __future__ import absolute_import |
|
9 | 9 | |
|
10 | 10 | #----------------------------------------------------------------------------- |
|
11 | 11 | # Copyright (C) 2009-2011 The IPython Development Team |
|
12 | 12 | # |
|
13 | 13 | # Distributed under the terms of the BSD License. The full license is in |
|
14 | 14 | # the file COPYING, distributed as part of this software. |
|
15 | 15 | #----------------------------------------------------------------------------- |
|
16 | 16 | |
|
17 | 17 | #----------------------------------------------------------------------------- |
|
18 | 18 | # Imports |
|
19 | 19 | #----------------------------------------------------------------------------- |
|
20 | 20 | |
|
21 | 21 | import os |
|
22 | 22 | import re |
|
23 | 23 | import sys |
|
24 | 24 | import tempfile |
|
25 | 25 | |
|
26 | 26 | from contextlib import contextmanager |
|
27 | 27 | from io import StringIO |
|
28 | 28 | |
|
29 | 29 | try: |
|
30 | 30 | # These tools are used by parts of the runtime, so we make the nose |
|
31 | 31 | # dependency optional at this point. Nose is a hard dependency to run the |
|
32 | 32 | # test suite, but NOT to use ipython itself. |
|
33 | 33 | import nose.tools as nt |
|
34 | 34 | has_nose = True |
|
35 | 35 | except ImportError: |
|
36 | 36 | has_nose = False |
|
37 | 37 | |
|
38 | 38 | from IPython.config.loader import Config |
|
39 | 39 | from IPython.utils.process import find_cmd, getoutputerror |
|
40 | 40 | from IPython.utils.text import list_strings |
|
41 | 41 | from IPython.utils.io import temp_pyfile, Tee |
|
42 | 42 | from IPython.utils import py3compat |
|
43 | 43 | from IPython.utils.encoding import DEFAULT_ENCODING |
|
44 | 44 | |
|
45 | 45 | from . import decorators as dec |
|
46 | 46 | from . import skipdoctest |
|
47 | 47 | |
|
48 | 48 | #----------------------------------------------------------------------------- |
|
49 | 49 | # Functions and classes |
|
50 | 50 | #----------------------------------------------------------------------------- |
|
51 | 51 | |
|
52 | 52 | # The docstring for full_path doctests differently on win32 (different path |
|
53 | 53 | # separator) so just skip the doctest there. The example remains informative. |
|
54 | 54 | doctest_deco = skipdoctest.skip_doctest if sys.platform == 'win32' else dec.null_deco |
|
55 | 55 | |
|
56 | 56 | @doctest_deco |
|
57 | 57 | def full_path(startPath,files): |
|
58 | 58 | """Make full paths for all the listed files, based on startPath. |
|
59 | 59 | |
|
60 | 60 | Only the base part of startPath is kept, since this routine is typically |
|
61 | 61 | used with a script's __file__ variable as startPath. The base of startPath |
|
62 | 62 | is then prepended to all the listed files, forming the output list. |
|
63 | 63 | |
|
64 | 64 | Parameters |
|
65 | 65 | ---------- |
|
66 | 66 | startPath : string |
|
67 | 67 | Initial path to use as the base for the results. This path is split |
|
68 | 68 | using os.path.split() and only its first component is kept. |
|
69 | 69 | |
|
70 | 70 | files : string or list |
|
71 | 71 | One or more files. |
|
72 | 72 | |
|
73 | 73 | Examples |
|
74 | 74 | -------- |
|
75 | 75 | |
|
76 | 76 | >>> full_path('/foo/bar.py',['a.txt','b.txt']) |
|
77 | 77 | ['/foo/a.txt', '/foo/b.txt'] |
|
78 | 78 | |
|
79 | 79 | >>> full_path('/foo',['a.txt','b.txt']) |
|
80 | 80 | ['/a.txt', '/b.txt'] |
|
81 | 81 | |
|
82 | 82 | If a single file is given, the output is still a list: |
|
83 | 83 | >>> full_path('/foo','a.txt') |
|
84 | 84 | ['/a.txt'] |
|
85 | 85 | """ |
|
86 | 86 | |
|
87 | 87 | files = list_strings(files) |
|
88 | 88 | base = os.path.split(startPath)[0] |
|
89 | 89 | return [ os.path.join(base,f) for f in files ] |
|
90 | 90 | |
|
91 | 91 | |
|
92 | 92 | def parse_test_output(txt): |
|
93 | 93 | """Parse the output of a test run and return errors, failures. |
|
94 | 94 | |
|
95 | 95 | Parameters |
|
96 | 96 | ---------- |
|
97 | 97 | txt : str |
|
98 | 98 | Text output of a test run, assumed to contain a line of one of the |
|
99 | 99 | following forms:: |
|
100 | ||
|
100 | 101 | 'FAILED (errors=1)' |
|
101 | 102 | 'FAILED (failures=1)' |
|
102 | 103 | 'FAILED (errors=1, failures=1)' |
|
103 | 104 | |
|
104 | 105 | Returns |
|
105 | 106 | ------- |
|
106 | 107 | nerr, nfail: number of errors and failures. |
|
107 | 108 | """ |
|
108 | 109 | |
|
109 | 110 | err_m = re.search(r'^FAILED \(errors=(\d+)\)', txt, re.MULTILINE) |
|
110 | 111 | if err_m: |
|
111 | 112 | nerr = int(err_m.group(1)) |
|
112 | 113 | nfail = 0 |
|
113 | 114 | return nerr, nfail |
|
114 | 115 | |
|
115 | 116 | fail_m = re.search(r'^FAILED \(failures=(\d+)\)', txt, re.MULTILINE) |
|
116 | 117 | if fail_m: |
|
117 | 118 | nerr = 0 |
|
118 | 119 | nfail = int(fail_m.group(1)) |
|
119 | 120 | return nerr, nfail |
|
120 | 121 | |
|
121 | 122 | both_m = re.search(r'^FAILED \(errors=(\d+), failures=(\d+)\)', txt, |
|
122 | 123 | re.MULTILINE) |
|
123 | 124 | if both_m: |
|
124 | 125 | nerr = int(both_m.group(1)) |
|
125 | 126 | nfail = int(both_m.group(2)) |
|
126 | 127 | return nerr, nfail |
|
127 | 128 | |
|
128 | 129 | # If the input didn't match any of these forms, assume no error/failures |
|
129 | 130 | return 0, 0 |
|
130 | 131 | |
|
131 | 132 | |
|
132 | 133 | # So nose doesn't think this is a test |
|
133 | 134 | parse_test_output.__test__ = False |
|
134 | 135 | |
|
135 | 136 | |
|
136 | 137 | def default_argv(): |
|
137 | 138 | """Return a valid default argv for creating testing instances of ipython""" |
|
138 | 139 | |
|
139 | 140 | return ['--quick', # so no config file is loaded |
|
140 | 141 | # Other defaults to minimize side effects on stdout |
|
141 | 142 | '--colors=NoColor', '--no-term-title','--no-banner', |
|
142 | 143 | '--autocall=0'] |
|
143 | 144 | |
|
144 | 145 | |
|
145 | 146 | def default_config(): |
|
146 | 147 | """Return a config object with good defaults for testing.""" |
|
147 | 148 | config = Config() |
|
148 | 149 | config.TerminalInteractiveShell.colors = 'NoColor' |
|
149 | 150 | config.TerminalTerminalInteractiveShell.term_title = False, |
|
150 | 151 | config.TerminalInteractiveShell.autocall = 0 |
|
151 | 152 | config.HistoryManager.hist_file = tempfile.mktemp(u'test_hist.sqlite') |
|
152 | 153 | config.HistoryManager.db_cache_size = 10000 |
|
153 | 154 | return config |
|
154 | 155 | |
|
155 | 156 | |
|
156 | 157 | def ipexec(fname, options=None): |
|
157 | 158 | """Utility to call 'ipython filename'. |
|
158 | 159 | |
|
159 | 160 | Starts IPython witha minimal and safe configuration to make startup as fast |
|
160 | 161 | as possible. |
|
161 | 162 | |
|
162 | 163 | Note that this starts IPython in a subprocess! |
|
163 | 164 | |
|
164 | 165 | Parameters |
|
165 | 166 | ---------- |
|
166 | 167 | fname : str |
|
167 | 168 | Name of file to be executed (should have .py or .ipy extension). |
|
168 | 169 | |
|
169 | 170 | options : optional, list |
|
170 | 171 | Extra command-line flags to be passed to IPython. |
|
171 | 172 | |
|
172 | 173 | Returns |
|
173 | 174 | ------- |
|
174 | 175 | (stdout, stderr) of ipython subprocess. |
|
175 | 176 | """ |
|
176 | 177 | if options is None: options = [] |
|
177 | 178 | |
|
178 | 179 | # For these subprocess calls, eliminate all prompt printing so we only see |
|
179 | 180 | # output from script execution |
|
180 | 181 | prompt_opts = [ '--PromptManager.in_template=""', |
|
181 | 182 | '--PromptManager.in2_template=""', |
|
182 | 183 | '--PromptManager.out_template=""' |
|
183 | 184 | ] |
|
184 | 185 | cmdargs = ' '.join(default_argv() + prompt_opts + options) |
|
185 | 186 | |
|
186 | 187 | _ip = get_ipython() |
|
187 | 188 | test_dir = os.path.dirname(__file__) |
|
188 | 189 | |
|
189 | 190 | ipython_cmd = find_cmd('ipython3' if py3compat.PY3 else 'ipython') |
|
190 | 191 | # Absolute path for filename |
|
191 | 192 | full_fname = os.path.join(test_dir, fname) |
|
192 | 193 | full_cmd = '%s %s %s' % (ipython_cmd, cmdargs, full_fname) |
|
193 | 194 | #print >> sys.stderr, 'FULL CMD:', full_cmd # dbg |
|
194 | 195 | out, err = getoutputerror(full_cmd) |
|
195 | 196 | # `import readline` causes 'ESC[?1034h' to be output sometimes, |
|
196 | 197 | # so strip that out before doing comparisons |
|
197 | 198 | if out: |
|
198 | 199 | out = re.sub(r'\x1b\[[^h]+h', '', out) |
|
199 | 200 | return out, err |
|
200 | 201 | |
|
201 | 202 | |
|
202 | 203 | def ipexec_validate(fname, expected_out, expected_err='', |
|
203 | 204 | options=None): |
|
204 | 205 | """Utility to call 'ipython filename' and validate output/error. |
|
205 | 206 | |
|
206 | 207 | This function raises an AssertionError if the validation fails. |
|
207 | 208 | |
|
208 | 209 | Note that this starts IPython in a subprocess! |
|
209 | 210 | |
|
210 | 211 | Parameters |
|
211 | 212 | ---------- |
|
212 | 213 | fname : str |
|
213 | 214 | Name of the file to be executed (should have .py or .ipy extension). |
|
214 | 215 | |
|
215 | 216 | expected_out : str |
|
216 | 217 | Expected stdout of the process. |
|
217 | 218 | |
|
218 | 219 | expected_err : optional, str |
|
219 | 220 | Expected stderr of the process. |
|
220 | 221 | |
|
221 | 222 | options : optional, list |
|
222 | 223 | Extra command-line flags to be passed to IPython. |
|
223 | 224 | |
|
224 | 225 | Returns |
|
225 | 226 | ------- |
|
226 | 227 | None |
|
227 | 228 | """ |
|
228 | 229 | |
|
229 | 230 | import nose.tools as nt |
|
230 | 231 | |
|
231 | 232 | out, err = ipexec(fname, options) |
|
232 | 233 | #print 'OUT', out # dbg |
|
233 | 234 | #print 'ERR', err # dbg |
|
234 | 235 | # If there are any errors, we must check those befor stdout, as they may be |
|
235 | 236 | # more informative than simply having an empty stdout. |
|
236 | 237 | if err: |
|
237 | 238 | if expected_err: |
|
238 | 239 | nt.assert_equal("\n".join(err.strip().splitlines()), "\n".join(expected_err.strip().splitlines())) |
|
239 | 240 | else: |
|
240 | 241 | raise ValueError('Running file %r produced error: %r' % |
|
241 | 242 | (fname, err)) |
|
242 | 243 | # If no errors or output on stderr was expected, match stdout |
|
243 | 244 | nt.assert_equal("\n".join(out.strip().splitlines()), "\n".join(expected_out.strip().splitlines())) |
|
244 | 245 | |
|
245 | 246 | |
|
246 | 247 | class TempFileMixin(object): |
|
247 | 248 | """Utility class to create temporary Python/IPython files. |
|
248 | 249 | |
|
249 | 250 | Meant as a mixin class for test cases.""" |
|
250 | 251 | |
|
251 | 252 | def mktmp(self, src, ext='.py'): |
|
252 | 253 | """Make a valid python temp file.""" |
|
253 | 254 | fname, f = temp_pyfile(src, ext) |
|
254 | 255 | self.tmpfile = f |
|
255 | 256 | self.fname = fname |
|
256 | 257 | |
|
257 | 258 | def tearDown(self): |
|
258 | 259 | if hasattr(self, 'tmpfile'): |
|
259 | 260 | # If the tmpfile wasn't made because of skipped tests, like in |
|
260 | 261 | # win32, there's nothing to cleanup. |
|
261 | 262 | self.tmpfile.close() |
|
262 | 263 | try: |
|
263 | 264 | os.unlink(self.fname) |
|
264 | 265 | except: |
|
265 | 266 | # On Windows, even though we close the file, we still can't |
|
266 | 267 | # delete it. I have no clue why |
|
267 | 268 | pass |
|
268 | 269 | |
|
269 | 270 | pair_fail_msg = ("Testing {0}\n\n" |
|
270 | 271 | "In:\n" |
|
271 | 272 | " {1!r}\n" |
|
272 | 273 | "Expected:\n" |
|
273 | 274 | " {2!r}\n" |
|
274 | 275 | "Got:\n" |
|
275 | 276 | " {3!r}\n") |
|
276 | 277 | def check_pairs(func, pairs): |
|
277 | 278 | """Utility function for the common case of checking a function with a |
|
278 | 279 | sequence of input/output pairs. |
|
279 | 280 | |
|
280 | 281 | Parameters |
|
281 | 282 | ---------- |
|
282 | 283 | func : callable |
|
283 | 284 | The function to be tested. Should accept a single argument. |
|
284 | 285 | pairs : iterable |
|
285 | 286 | A list of (input, expected_output) tuples. |
|
286 | 287 | |
|
287 | 288 | Returns |
|
288 | 289 | ------- |
|
289 | 290 | None. Raises an AssertionError if any output does not match the expected |
|
290 | 291 | value. |
|
291 | 292 | """ |
|
292 | 293 | name = getattr(func, "func_name", getattr(func, "__name__", "<unknown>")) |
|
293 | 294 | for inp, expected in pairs: |
|
294 | 295 | out = func(inp) |
|
295 | 296 | assert out == expected, pair_fail_msg.format(name, inp, expected, out) |
|
296 | 297 | |
|
297 | 298 | |
|
298 | 299 | if py3compat.PY3: |
|
299 | 300 | MyStringIO = StringIO |
|
300 | 301 | else: |
|
301 | 302 | # In Python 2, stdout/stderr can have either bytes or unicode written to them, |
|
302 | 303 | # so we need a class that can handle both. |
|
303 | 304 | class MyStringIO(StringIO): |
|
304 | 305 | def write(self, s): |
|
305 | 306 | s = py3compat.cast_unicode(s, encoding=DEFAULT_ENCODING) |
|
306 | 307 | super(MyStringIO, self).write(s) |
|
307 | 308 | |
|
308 | 309 | notprinted_msg = """Did not find {0!r} in printed output (on {1}): |
|
309 | 310 | ------- |
|
310 | 311 | {2!s} |
|
311 | 312 | ------- |
|
312 | 313 | """ |
|
313 | 314 | |
|
314 | 315 | class AssertPrints(object): |
|
315 | 316 | """Context manager for testing that code prints certain text. |
|
316 | 317 | |
|
317 | 318 | Examples |
|
318 | 319 | -------- |
|
319 | 320 | >>> with AssertPrints("abc", suppress=False): |
|
320 | 321 | ... print "abcd" |
|
321 | 322 | ... print "def" |
|
322 | 323 | ... |
|
323 | 324 | abcd |
|
324 | 325 | def |
|
325 | 326 | """ |
|
326 | 327 | def __init__(self, s, channel='stdout', suppress=True): |
|
327 | 328 | self.s = s |
|
328 | 329 | self.channel = channel |
|
329 | 330 | self.suppress = suppress |
|
330 | 331 | |
|
331 | 332 | def __enter__(self): |
|
332 | 333 | self.orig_stream = getattr(sys, self.channel) |
|
333 | 334 | self.buffer = MyStringIO() |
|
334 | 335 | self.tee = Tee(self.buffer, channel=self.channel) |
|
335 | 336 | setattr(sys, self.channel, self.buffer if self.suppress else self.tee) |
|
336 | 337 | |
|
337 | 338 | def __exit__(self, etype, value, traceback): |
|
338 | 339 | self.tee.flush() |
|
339 | 340 | setattr(sys, self.channel, self.orig_stream) |
|
340 | 341 | printed = self.buffer.getvalue() |
|
341 | 342 | assert self.s in printed, notprinted_msg.format(self.s, self.channel, printed) |
|
342 | 343 | return False |
|
343 | 344 | |
|
344 | 345 | printed_msg = """Found {0!r} in printed output (on {1}): |
|
345 | 346 | ------- |
|
346 | 347 | {2!s} |
|
347 | 348 | ------- |
|
348 | 349 | """ |
|
349 | 350 | |
|
350 | 351 | class AssertNotPrints(AssertPrints): |
|
351 | 352 | """Context manager for checking that certain output *isn't* produced. |
|
352 | 353 | |
|
353 | 354 | Counterpart of AssertPrints""" |
|
354 | 355 | def __exit__(self, etype, value, traceback): |
|
355 | 356 | self.tee.flush() |
|
356 | 357 | setattr(sys, self.channel, self.orig_stream) |
|
357 | 358 | printed = self.buffer.getvalue() |
|
358 | 359 | assert self.s not in printed, printed_msg.format(self.s, self.channel, printed) |
|
359 | 360 | return False |
|
360 | 361 | |
|
361 | 362 | @contextmanager |
|
362 | 363 | def mute_warn(): |
|
363 | 364 | from IPython.utils import warn |
|
364 | 365 | save_warn = warn.warn |
|
365 | 366 | warn.warn = lambda *a, **kw: None |
|
366 | 367 | try: |
|
367 | 368 | yield |
|
368 | 369 | finally: |
|
369 | 370 | warn.warn = save_warn |
|
370 | 371 | |
|
371 | 372 | @contextmanager |
|
372 | 373 | def make_tempfile(name): |
|
373 | 374 | """ Create an empty, named, temporary file for the duration of the context. |
|
374 | 375 | """ |
|
375 | 376 | f = open(name, 'w') |
|
376 | 377 | f.close() |
|
377 | 378 | try: |
|
378 | 379 | yield |
|
379 | 380 | finally: |
|
380 | 381 | os.unlink(name) |
|
381 | 382 | |
|
382 | 383 | |
|
383 | 384 | @contextmanager |
|
384 | 385 | def monkeypatch(obj, name, attr): |
|
385 | 386 | """ |
|
386 | 387 | Context manager to replace attribute named `name` in `obj` with `attr`. |
|
387 | 388 | """ |
|
388 | 389 | orig = getattr(obj, name) |
|
389 | 390 | setattr(obj, name, attr) |
|
390 | 391 | yield |
|
391 | 392 | setattr(obj, name, orig) |
@@ -1,56 +1,56 b'' | |||
|
1 | 1 | # coding: utf-8 |
|
2 | 2 | """ |
|
3 | 3 | Utilities for dealing with text encodings |
|
4 | 4 | """ |
|
5 | 5 | |
|
6 | 6 | #----------------------------------------------------------------------------- |
|
7 | 7 | # Copyright (C) 2008-2012 The IPython Development Team |
|
8 | 8 | # |
|
9 | 9 | # Distributed under the terms of the BSD License. The full license is in |
|
10 | 10 | # the file COPYING, distributed as part of this software. |
|
11 | 11 | #----------------------------------------------------------------------------- |
|
12 | 12 | |
|
13 | 13 | #----------------------------------------------------------------------------- |
|
14 | 14 | # Imports |
|
15 | 15 | #----------------------------------------------------------------------------- |
|
16 | 16 | import sys |
|
17 | 17 | import locale |
|
18 | 18 | |
|
19 | 19 | # to deal with the possibility of sys.std* not being a stream at all |
|
20 | 20 | def get_stream_enc(stream, default=None): |
|
21 | 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 | 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 | 26 | is None if not provided. |
|
27 | 27 | """ |
|
28 | 28 | if not hasattr(stream, 'encoding') or not stream.encoding: |
|
29 | 29 | return default |
|
30 | 30 | else: |
|
31 | 31 | return stream.encoding |
|
32 | 32 | |
|
33 | 33 | # Less conservative replacement for sys.getdefaultencoding, that will try |
|
34 | 34 | # to match the environment. |
|
35 | 35 | # Defined here as central function, so if we find better choices, we |
|
36 | 36 | # won't need to make changes all over IPython. |
|
37 | 37 | def getdefaultencoding(): |
|
38 | 38 | """Return IPython's guess for the default encoding for bytes as text. |
|
39 | 39 | |
|
40 | 40 | Asks for stdin.encoding first, to match the calling Terminal, but that |
|
41 | 41 | is often None for subprocesses. Fall back on locale.getpreferredencoding() |
|
42 | 42 | which should be a sensible platform default (that respects LANG environment), |
|
43 | 43 | and finally to sys.getdefaultencoding() which is the most conservative option, |
|
44 | 44 | and usually ASCII. |
|
45 | 45 | """ |
|
46 | 46 | enc = get_stream_enc(sys.stdin) |
|
47 | 47 | if not enc or enc=='ascii': |
|
48 | 48 | try: |
|
49 | 49 | # There are reports of getpreferredencoding raising errors |
|
50 | 50 | # in some cases, which may well be fixed, but let's be conservative here. |
|
51 | 51 | enc = locale.getpreferredencoding() |
|
52 | 52 | except Exception: |
|
53 | 53 | pass |
|
54 | 54 | return enc or sys.getdefaultencoding() |
|
55 | 55 | |
|
56 | 56 | DEFAULT_ENCODING = getdefaultencoding() |
@@ -1,50 +1,50 b'' | |||
|
1 | 1 | """Backwards compatibility - we use contextlib.nested to support Python 2.6, |
|
2 | 2 | but it's removed in Python 3.2.""" |
|
3 | 3 | |
|
4 | 4 | # TODO : Remove this once we drop support for Python 2.6, and use |
|
5 | 5 | # "with a, b:" instead. |
|
6 | 6 | |
|
7 | 7 | import sys |
|
8 | 8 | |
|
9 | 9 | from contextlib import contextmanager |
|
10 | 10 | |
|
11 | 11 | @contextmanager |
|
12 | 12 | def nested(*managers): |
|
13 | 13 | """Combine multiple context managers into a single nested context manager. |
|
14 | 14 | |
|
15 | 15 | This function has been deprecated in favour of the multiple manager form |
|
16 | 16 | of the with statement. |
|
17 | 17 | |
|
18 | 18 | The one advantage of this function over the multiple manager form of the |
|
19 | 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 | 22 | with nested(*managers): |
|
23 | 23 | do_something() |
|
24 | 24 | |
|
25 | 25 | """ |
|
26 | 26 | exits = [] |
|
27 | 27 | vars = [] |
|
28 | 28 | exc = (None, None, None) |
|
29 | 29 | try: |
|
30 | 30 | for mgr in managers: |
|
31 | 31 | exit = mgr.__exit__ |
|
32 | 32 | enter = mgr.__enter__ |
|
33 | 33 | vars.append(enter()) |
|
34 | 34 | exits.append(exit) |
|
35 | 35 | yield vars |
|
36 | 36 | except: |
|
37 | 37 | exc = sys.exc_info() |
|
38 | 38 | finally: |
|
39 | 39 | while exits: |
|
40 | 40 | exit = exits.pop() |
|
41 | 41 | try: |
|
42 | 42 | if exit(*exc): |
|
43 | 43 | exc = (None, None, None) |
|
44 | 44 | except: |
|
45 | 45 | exc = sys.exc_info() |
|
46 | 46 | if exc != (None, None, None): |
|
47 | 47 | # Don't rely on sys.exc_info() still containing |
|
48 | 48 | # the right information. Another exception may |
|
49 | 49 | # have been raised and caught by an exit method |
|
50 | 50 | raise exc[0], exc[1], exc[2] |
@@ -1,142 +1,142 b'' | |||
|
1 | 1 | # encoding: utf-8 |
|
2 | 2 | """ |
|
3 | 3 | The IPython Core Notification Center. |
|
4 | 4 | |
|
5 | 5 | See docs/source/development/notification_blueprint.txt for an overview of the |
|
6 | 6 | notification module. |
|
7 | 7 | |
|
8 | 8 | Authors: |
|
9 | 9 | |
|
10 | 10 | * Barry Wark |
|
11 | 11 | * Brian Granger |
|
12 | 12 | """ |
|
13 | 13 | |
|
14 | 14 | #----------------------------------------------------------------------------- |
|
15 | 15 | # Copyright (C) 2008-2011 The IPython Development Team |
|
16 | 16 | # |
|
17 | 17 | # Distributed under the terms of the BSD License. The full license is in |
|
18 | 18 | # the file COPYING, distributed as part of this software. |
|
19 | 19 | #----------------------------------------------------------------------------- |
|
20 | 20 | |
|
21 | 21 | #----------------------------------------------------------------------------- |
|
22 | 22 | # Code |
|
23 | 23 | #----------------------------------------------------------------------------- |
|
24 | 24 | |
|
25 | 25 | |
|
26 | 26 | class NotificationError(Exception): |
|
27 | 27 | pass |
|
28 | 28 | |
|
29 | 29 | |
|
30 | 30 | class NotificationCenter(object): |
|
31 | 31 | """Synchronous notification center. |
|
32 | 32 | |
|
33 | 33 | Examples |
|
34 | 34 | -------- |
|
35 | 35 | Here is a simple example of how to use this:: |
|
36 | 36 | |
|
37 | 37 | import IPython.util.notification as notification |
|
38 | 38 | def callback(ntype, theSender, args={}): |
|
39 | 39 | print ntype,theSender,args |
|
40 | 40 | |
|
41 | 41 | notification.sharedCenter.add_observer(callback, 'NOTIFICATION_TYPE', None) |
|
42 | 42 | notification.sharedCenter.post_notification('NOTIFICATION_TYPE', object()) # doctest:+ELLIPSIS |
|
43 | 43 | NOTIFICATION_TYPE ... |
|
44 | 44 | """ |
|
45 | 45 | def __init__(self): |
|
46 | 46 | super(NotificationCenter, self).__init__() |
|
47 | 47 | self._init_observers() |
|
48 | 48 | |
|
49 | 49 | def _init_observers(self): |
|
50 | 50 | """Initialize observer storage""" |
|
51 | 51 | |
|
52 | 52 | self.registered_types = set() #set of types that are observed |
|
53 | 53 | self.registered_senders = set() #set of senders that are observed |
|
54 | 54 | self.observers = {} #map (type,sender) => callback (callable) |
|
55 | 55 | |
|
56 | 56 | def post_notification(self, ntype, sender, *args, **kwargs): |
|
57 | 57 | """Post notification to all registered observers. |
|
58 | 58 | |
|
59 | 59 | The registered callback will be called as:: |
|
60 | 60 | |
|
61 | 61 | callback(ntype, sender, *args, **kwargs) |
|
62 | 62 | |
|
63 | 63 | Parameters |
|
64 | 64 | ---------- |
|
65 | 65 | ntype : hashable |
|
66 | 66 | The notification type. |
|
67 | 67 | sender : hashable |
|
68 | 68 | The object sending the notification. |
|
69 | 69 | *args : tuple |
|
70 | 70 | The positional arguments to be passed to the callback. |
|
71 | 71 | **kwargs : dict |
|
72 | 72 | The keyword argument to be passed to the callback. |
|
73 | 73 | |
|
74 | 74 | Notes |
|
75 | 75 | ----- |
|
76 | 76 | * If no registered observers, performance is O(1). |
|
77 | 77 | * Notificaiton order is undefined. |
|
78 | 78 | * Notifications are posted synchronously. |
|
79 | 79 | """ |
|
80 | 80 | |
|
81 | 81 | if(ntype==None or sender==None): |
|
82 | 82 | raise NotificationError( |
|
83 | 83 | "Notification type and sender are required.") |
|
84 | 84 | |
|
85 | 85 | # If there are no registered observers for the type/sender pair |
|
86 | 86 | if((ntype not in self.registered_types and |
|
87 | 87 | None not in self.registered_types) or |
|
88 | 88 | (sender not in self.registered_senders and |
|
89 | 89 | None not in self.registered_senders)): |
|
90 | 90 | return |
|
91 | 91 | |
|
92 | 92 | for o in self._observers_for_notification(ntype, sender): |
|
93 | 93 | o(ntype, sender, *args, **kwargs) |
|
94 | 94 | |
|
95 | 95 | def _observers_for_notification(self, ntype, sender): |
|
96 | 96 | """Find all registered observers that should recieve notification""" |
|
97 | 97 | |
|
98 | 98 | keys = ( |
|
99 | 99 | (ntype,sender), |
|
100 | 100 | (ntype, None), |
|
101 | 101 | (None, sender), |
|
102 | 102 | (None,None) |
|
103 | 103 | ) |
|
104 | 104 | |
|
105 | 105 | obs = set() |
|
106 | 106 | for k in keys: |
|
107 | 107 | obs.update(self.observers.get(k, set())) |
|
108 | 108 | |
|
109 | 109 | return obs |
|
110 | 110 | |
|
111 | 111 | def add_observer(self, callback, ntype, sender): |
|
112 | 112 | """Add an observer callback to this notification center. |
|
113 | 113 | |
|
114 | 114 | The given callback will be called upon posting of notifications of |
|
115 | 115 | the given type/sender and will receive any additional arguments passed |
|
116 | 116 | to post_notification. |
|
117 | 117 | |
|
118 | 118 | Parameters |
|
119 | 119 | ---------- |
|
120 | 120 | callback : callable |
|
121 | 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 | 123 | ntype : hashable |
|
124 | 124 | The notification type. If None, all notifications from sender |
|
125 | 125 | will be posted. |
|
126 | 126 | sender : hashable |
|
127 | 127 | The notification sender. If None, all notifications of ntype |
|
128 | 128 | will be posted. |
|
129 | 129 | """ |
|
130 | 130 | assert(callback != None) |
|
131 | 131 | self.registered_types.add(ntype) |
|
132 | 132 | self.registered_senders.add(sender) |
|
133 | 133 | self.observers.setdefault((ntype,sender), set()).add(callback) |
|
134 | 134 | |
|
135 | 135 | def remove_all_observers(self): |
|
136 | 136 | """Removes all observers from this notification center""" |
|
137 | 137 | |
|
138 | 138 | self._init_observers() |
|
139 | 139 | |
|
140 | 140 | |
|
141 | 141 | |
|
142 | 142 | shared_center = NotificationCenter() |
@@ -1,850 +1,850 b'' | |||
|
1 | 1 | # encoding: utf-8 |
|
2 | 2 | """ |
|
3 | 3 | Utilities for working with strings and text. |
|
4 | 4 | |
|
5 | 5 | Inheritance diagram: |
|
6 | 6 | |
|
7 | 7 | .. inheritance-diagram:: IPython.utils.text |
|
8 | 8 | :parts: 3 |
|
9 | 9 | """ |
|
10 | 10 | |
|
11 | 11 | #----------------------------------------------------------------------------- |
|
12 | 12 | # Copyright (C) 2008-2011 The IPython Development Team |
|
13 | 13 | # |
|
14 | 14 | # Distributed under the terms of the BSD License. The full license is in |
|
15 | 15 | # the file COPYING, distributed as part of this software. |
|
16 | 16 | #----------------------------------------------------------------------------- |
|
17 | 17 | |
|
18 | 18 | #----------------------------------------------------------------------------- |
|
19 | 19 | # Imports |
|
20 | 20 | #----------------------------------------------------------------------------- |
|
21 | 21 | |
|
22 | 22 | import __main__ |
|
23 | 23 | |
|
24 | 24 | import os |
|
25 | 25 | import re |
|
26 | 26 | import shutil |
|
27 | 27 | import sys |
|
28 | 28 | import textwrap |
|
29 | 29 | from string import Formatter |
|
30 | 30 | |
|
31 | 31 | from IPython.external.path import path |
|
32 | 32 | from IPython.testing.skipdoctest import skip_doctest_py3, skip_doctest |
|
33 | 33 | from IPython.utils import py3compat |
|
34 | 34 | from IPython.utils.io import nlprint |
|
35 | 35 | from IPython.utils.data import flatten |
|
36 | 36 | |
|
37 | 37 | #----------------------------------------------------------------------------- |
|
38 | 38 | # Code |
|
39 | 39 | #----------------------------------------------------------------------------- |
|
40 | 40 | |
|
41 | 41 | def unquote_ends(istr): |
|
42 | 42 | """Remove a single pair of quotes from the endpoints of a string.""" |
|
43 | 43 | |
|
44 | 44 | if not istr: |
|
45 | 45 | return istr |
|
46 | 46 | if (istr[0]=="'" and istr[-1]=="'") or \ |
|
47 | 47 | (istr[0]=='"' and istr[-1]=='"'): |
|
48 | 48 | return istr[1:-1] |
|
49 | 49 | else: |
|
50 | 50 | return istr |
|
51 | 51 | |
|
52 | 52 | |
|
53 | 53 | class LSString(str): |
|
54 | 54 | """String derivative with a special access attributes. |
|
55 | 55 | |
|
56 | 56 | These are normal strings, but with the special attributes: |
|
57 | 57 | |
|
58 | 58 | .l (or .list) : value as list (split on newlines). |
|
59 | 59 | .n (or .nlstr): original value (the string itself). |
|
60 | 60 | .s (or .spstr): value as whitespace-separated string. |
|
61 | 61 | .p (or .paths): list of path objects |
|
62 | 62 | |
|
63 | 63 | Any values which require transformations are computed only once and |
|
64 | 64 | cached. |
|
65 | 65 | |
|
66 | 66 | Such strings are very useful to efficiently interact with the shell, which |
|
67 | 67 | typically only understands whitespace-separated options for commands.""" |
|
68 | 68 | |
|
69 | 69 | def get_list(self): |
|
70 | 70 | try: |
|
71 | 71 | return self.__list |
|
72 | 72 | except AttributeError: |
|
73 | 73 | self.__list = self.split('\n') |
|
74 | 74 | return self.__list |
|
75 | 75 | |
|
76 | 76 | l = list = property(get_list) |
|
77 | 77 | |
|
78 | 78 | def get_spstr(self): |
|
79 | 79 | try: |
|
80 | 80 | return self.__spstr |
|
81 | 81 | except AttributeError: |
|
82 | 82 | self.__spstr = self.replace('\n',' ') |
|
83 | 83 | return self.__spstr |
|
84 | 84 | |
|
85 | 85 | s = spstr = property(get_spstr) |
|
86 | 86 | |
|
87 | 87 | def get_nlstr(self): |
|
88 | 88 | return self |
|
89 | 89 | |
|
90 | 90 | n = nlstr = property(get_nlstr) |
|
91 | 91 | |
|
92 | 92 | def get_paths(self): |
|
93 | 93 | try: |
|
94 | 94 | return self.__paths |
|
95 | 95 | except AttributeError: |
|
96 | 96 | self.__paths = [path(p) for p in self.split('\n') if os.path.exists(p)] |
|
97 | 97 | return self.__paths |
|
98 | 98 | |
|
99 | 99 | p = paths = property(get_paths) |
|
100 | 100 | |
|
101 | 101 | # FIXME: We need to reimplement type specific displayhook and then add this |
|
102 | 102 | # back as a custom printer. This should also be moved outside utils into the |
|
103 | 103 | # core. |
|
104 | 104 | |
|
105 | 105 | # def print_lsstring(arg): |
|
106 | 106 | # """ Prettier (non-repr-like) and more informative printer for LSString """ |
|
107 | 107 | # print "LSString (.p, .n, .l, .s available). Value:" |
|
108 | 108 | # print arg |
|
109 | 109 | # |
|
110 | 110 | # |
|
111 | 111 | # print_lsstring = result_display.when_type(LSString)(print_lsstring) |
|
112 | 112 | |
|
113 | 113 | |
|
114 | 114 | class SList(list): |
|
115 | 115 | """List derivative with a special access attributes. |
|
116 | 116 | |
|
117 | 117 | These are normal lists, but with the special attributes: |
|
118 | 118 | |
|
119 | 119 | .l (or .list) : value as list (the list itself). |
|
120 | 120 | .n (or .nlstr): value as a string, joined on newlines. |
|
121 | 121 | .s (or .spstr): value as a string, joined on spaces. |
|
122 | 122 | .p (or .paths): list of path objects |
|
123 | 123 | |
|
124 | 124 | Any values which require transformations are computed only once and |
|
125 | 125 | cached.""" |
|
126 | 126 | |
|
127 | 127 | def get_list(self): |
|
128 | 128 | return self |
|
129 | 129 | |
|
130 | 130 | l = list = property(get_list) |
|
131 | 131 | |
|
132 | 132 | def get_spstr(self): |
|
133 | 133 | try: |
|
134 | 134 | return self.__spstr |
|
135 | 135 | except AttributeError: |
|
136 | 136 | self.__spstr = ' '.join(self) |
|
137 | 137 | return self.__spstr |
|
138 | 138 | |
|
139 | 139 | s = spstr = property(get_spstr) |
|
140 | 140 | |
|
141 | 141 | def get_nlstr(self): |
|
142 | 142 | try: |
|
143 | 143 | return self.__nlstr |
|
144 | 144 | except AttributeError: |
|
145 | 145 | self.__nlstr = '\n'.join(self) |
|
146 | 146 | return self.__nlstr |
|
147 | 147 | |
|
148 | 148 | n = nlstr = property(get_nlstr) |
|
149 | 149 | |
|
150 | 150 | def get_paths(self): |
|
151 | 151 | try: |
|
152 | 152 | return self.__paths |
|
153 | 153 | except AttributeError: |
|
154 | 154 | self.__paths = [path(p) for p in self if os.path.exists(p)] |
|
155 | 155 | return self.__paths |
|
156 | 156 | |
|
157 | 157 | p = paths = property(get_paths) |
|
158 | 158 | |
|
159 | 159 | def grep(self, pattern, prune = False, field = None): |
|
160 | 160 | """ Return all strings matching 'pattern' (a regex or callable) |
|
161 | 161 | |
|
162 | 162 | This is case-insensitive. If prune is true, return all items |
|
163 | 163 | NOT matching the pattern. |
|
164 | 164 | |
|
165 | 165 | If field is specified, the match must occur in the specified |
|
166 | 166 | whitespace-separated field. |
|
167 | 167 | |
|
168 | 168 | Examples:: |
|
169 | 169 | |
|
170 | 170 | a.grep( lambda x: x.startswith('C') ) |
|
171 | 171 | a.grep('Cha.*log', prune=1) |
|
172 | 172 | a.grep('chm', field=-1) |
|
173 | 173 | """ |
|
174 | 174 | |
|
175 | 175 | def match_target(s): |
|
176 | 176 | if field is None: |
|
177 | 177 | return s |
|
178 | 178 | parts = s.split() |
|
179 | 179 | try: |
|
180 | 180 | tgt = parts[field] |
|
181 | 181 | return tgt |
|
182 | 182 | except IndexError: |
|
183 | 183 | return "" |
|
184 | 184 | |
|
185 | 185 | if isinstance(pattern, basestring): |
|
186 | 186 | pred = lambda x : re.search(pattern, x, re.IGNORECASE) |
|
187 | 187 | else: |
|
188 | 188 | pred = pattern |
|
189 | 189 | if not prune: |
|
190 | 190 | return SList([el for el in self if pred(match_target(el))]) |
|
191 | 191 | else: |
|
192 | 192 | return SList([el for el in self if not pred(match_target(el))]) |
|
193 | 193 | |
|
194 | 194 | def fields(self, *fields): |
|
195 | 195 | """ Collect whitespace-separated fields from string list |
|
196 | 196 | |
|
197 | 197 | Allows quick awk-like usage of string lists. |
|
198 | 198 | |
|
199 | 199 | Example data (in var a, created by 'a = !ls -l'):: |
|
200 | 200 | -rwxrwxrwx 1 ville None 18 Dec 14 2006 ChangeLog |
|
201 | 201 | drwxrwxrwx+ 6 ville None 0 Oct 24 18:05 IPython |
|
202 | 202 | |
|
203 | 203 | a.fields(0) is ['-rwxrwxrwx', 'drwxrwxrwx+'] |
|
204 | 204 | a.fields(1,0) is ['1 -rwxrwxrwx', '6 drwxrwxrwx+'] |
|
205 | 205 | (note the joining by space). |
|
206 | 206 | a.fields(-1) is ['ChangeLog', 'IPython'] |
|
207 | 207 | |
|
208 | 208 | IndexErrors are ignored. |
|
209 | 209 | |
|
210 | 210 | Without args, fields() just split()'s the strings. |
|
211 | 211 | """ |
|
212 | 212 | if len(fields) == 0: |
|
213 | 213 | return [el.split() for el in self] |
|
214 | 214 | |
|
215 | 215 | res = SList() |
|
216 | 216 | for el in [f.split() for f in self]: |
|
217 | 217 | lineparts = [] |
|
218 | 218 | |
|
219 | 219 | for fd in fields: |
|
220 | 220 | try: |
|
221 | 221 | lineparts.append(el[fd]) |
|
222 | 222 | except IndexError: |
|
223 | 223 | pass |
|
224 | 224 | if lineparts: |
|
225 | 225 | res.append(" ".join(lineparts)) |
|
226 | 226 | |
|
227 | 227 | return res |
|
228 | 228 | |
|
229 | 229 | def sort(self,field= None, nums = False): |
|
230 | 230 | """ sort by specified fields (see fields()) |
|
231 | 231 | |
|
232 | 232 | Example:: |
|
233 | 233 | a.sort(1, nums = True) |
|
234 | 234 | |
|
235 | 235 | Sorts a by second field, in numerical order (so that 21 > 3) |
|
236 | 236 | |
|
237 | 237 | """ |
|
238 | 238 | |
|
239 | 239 | #decorate, sort, undecorate |
|
240 | 240 | if field is not None: |
|
241 | 241 | dsu = [[SList([line]).fields(field), line] for line in self] |
|
242 | 242 | else: |
|
243 | 243 | dsu = [[line, line] for line in self] |
|
244 | 244 | if nums: |
|
245 | 245 | for i in range(len(dsu)): |
|
246 | 246 | numstr = "".join([ch for ch in dsu[i][0] if ch.isdigit()]) |
|
247 | 247 | try: |
|
248 | 248 | n = int(numstr) |
|
249 | 249 | except ValueError: |
|
250 | 250 | n = 0; |
|
251 | 251 | dsu[i][0] = n |
|
252 | 252 | |
|
253 | 253 | |
|
254 | 254 | dsu.sort() |
|
255 | 255 | return SList([t[1] for t in dsu]) |
|
256 | 256 | |
|
257 | 257 | |
|
258 | 258 | # FIXME: We need to reimplement type specific displayhook and then add this |
|
259 | 259 | # back as a custom printer. This should also be moved outside utils into the |
|
260 | 260 | # core. |
|
261 | 261 | |
|
262 | 262 | # def print_slist(arg): |
|
263 | 263 | # """ Prettier (non-repr-like) and more informative printer for SList """ |
|
264 | 264 | # print "SList (.p, .n, .l, .s, .grep(), .fields(), sort() available):" |
|
265 | 265 | # if hasattr(arg, 'hideonce') and arg.hideonce: |
|
266 | 266 | # arg.hideonce = False |
|
267 | 267 | # return |
|
268 | 268 | # |
|
269 | 269 | # nlprint(arg) |
|
270 | 270 | # |
|
271 | 271 | # print_slist = result_display.when_type(SList)(print_slist) |
|
272 | 272 | |
|
273 | 273 | |
|
274 | 274 | def esc_quotes(strng): |
|
275 | 275 | """Return the input string with single and double quotes escaped out""" |
|
276 | 276 | |
|
277 | 277 | return strng.replace('"','\\"').replace("'","\\'") |
|
278 | 278 | |
|
279 | 279 | |
|
280 | 280 | def qw(words,flat=0,sep=None,maxsplit=-1): |
|
281 | 281 | """Similar to Perl's qw() operator, but with some more options. |
|
282 | 282 | |
|
283 | 283 | qw(words,flat=0,sep=' ',maxsplit=-1) -> words.split(sep,maxsplit) |
|
284 | 284 | |
|
285 | 285 | words can also be a list itself, and with flat=1, the output will be |
|
286 | 286 | recursively flattened. |
|
287 | 287 | |
|
288 | 288 | Examples: |
|
289 | 289 | |
|
290 | 290 | >>> qw('1 2') |
|
291 | 291 | ['1', '2'] |
|
292 | 292 | |
|
293 | 293 | >>> qw(['a b','1 2',['m n','p q']]) |
|
294 | 294 | [['a', 'b'], ['1', '2'], [['m', 'n'], ['p', 'q']]] |
|
295 | 295 | |
|
296 | 296 | >>> qw(['a b','1 2',['m n','p q']],flat=1) |
|
297 | 297 | ['a', 'b', '1', '2', 'm', 'n', 'p', 'q'] |
|
298 | 298 | """ |
|
299 | 299 | |
|
300 | 300 | if isinstance(words, basestring): |
|
301 | 301 | return [word.strip() for word in words.split(sep,maxsplit) |
|
302 | 302 | if word and not word.isspace() ] |
|
303 | 303 | if flat: |
|
304 | 304 | return flatten(map(qw,words,[1]*len(words))) |
|
305 | 305 | return map(qw,words) |
|
306 | 306 | |
|
307 | 307 | |
|
308 | 308 | def qwflat(words,sep=None,maxsplit=-1): |
|
309 | 309 | """Calls qw(words) in flat mode. It's just a convenient shorthand.""" |
|
310 | 310 | return qw(words,1,sep,maxsplit) |
|
311 | 311 | |
|
312 | 312 | |
|
313 | 313 | def qw_lol(indata): |
|
314 | 314 | """qw_lol('a b') -> [['a','b']], |
|
315 | 315 | otherwise it's just a call to qw(). |
|
316 | 316 | |
|
317 | 317 | We need this to make sure the modules_some keys *always* end up as a |
|
318 | 318 | list of lists.""" |
|
319 | 319 | |
|
320 | 320 | if isinstance(indata, basestring): |
|
321 | 321 | return [qw(indata)] |
|
322 | 322 | else: |
|
323 | 323 | return qw(indata) |
|
324 | 324 | |
|
325 | 325 | |
|
326 | 326 | def grep(pat,list,case=1): |
|
327 | 327 | """Simple minded grep-like function. |
|
328 | 328 | grep(pat,list) returns occurrences of pat in list, None on failure. |
|
329 | 329 | |
|
330 | 330 | It only does simple string matching, with no support for regexps. Use the |
|
331 | 331 | option case=0 for case-insensitive matching.""" |
|
332 | 332 | |
|
333 | 333 | # This is pretty crude. At least it should implement copying only references |
|
334 | 334 | # to the original data in case it's big. Now it copies the data for output. |
|
335 | 335 | out=[] |
|
336 | 336 | if case: |
|
337 | 337 | for term in list: |
|
338 | 338 | if term.find(pat)>-1: out.append(term) |
|
339 | 339 | else: |
|
340 | 340 | lpat=pat.lower() |
|
341 | 341 | for term in list: |
|
342 | 342 | if term.lower().find(lpat)>-1: out.append(term) |
|
343 | 343 | |
|
344 | 344 | if len(out): return out |
|
345 | 345 | else: return None |
|
346 | 346 | |
|
347 | 347 | |
|
348 | 348 | def dgrep(pat,*opts): |
|
349 | 349 | """Return grep() on dir()+dir(__builtins__). |
|
350 | 350 | |
|
351 | 351 | A very common use of grep() when working interactively.""" |
|
352 | 352 | |
|
353 | 353 | return grep(pat,dir(__main__)+dir(__main__.__builtins__),*opts) |
|
354 | 354 | |
|
355 | 355 | |
|
356 | 356 | def idgrep(pat): |
|
357 | 357 | """Case-insensitive dgrep()""" |
|
358 | 358 | |
|
359 | 359 | return dgrep(pat,0) |
|
360 | 360 | |
|
361 | 361 | |
|
362 | 362 | def igrep(pat,list): |
|
363 | 363 | """Synonym for case-insensitive grep.""" |
|
364 | 364 | |
|
365 | 365 | return grep(pat,list,case=0) |
|
366 | 366 | |
|
367 | 367 | |
|
368 | 368 | def indent(instr,nspaces=4, ntabs=0, flatten=False): |
|
369 | 369 | """Indent a string a given number of spaces or tabstops. |
|
370 | 370 | |
|
371 | 371 | indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces. |
|
372 | 372 | |
|
373 | 373 | Parameters |
|
374 | 374 | ---------- |
|
375 | 375 | |
|
376 | 376 | instr : basestring |
|
377 | 377 | The string to be indented. |
|
378 | 378 | nspaces : int (default: 4) |
|
379 | 379 | The number of spaces to be indented. |
|
380 | 380 | ntabs : int (default: 0) |
|
381 | 381 | The number of tabs to be indented. |
|
382 | 382 | flatten : bool (default: False) |
|
383 | 383 | Whether to scrub existing indentation. If True, all lines will be |
|
384 | 384 | aligned to the same indentation. If False, existing indentation will |
|
385 | 385 | be strictly increased. |
|
386 | 386 | |
|
387 | 387 | Returns |
|
388 | 388 | ------- |
|
389 | 389 | |
|
390 | 390 | str|unicode : string indented by ntabs and nspaces. |
|
391 | 391 | |
|
392 | 392 | """ |
|
393 | 393 | if instr is None: |
|
394 | 394 | return |
|
395 | 395 | ind = '\t'*ntabs+' '*nspaces |
|
396 | 396 | if flatten: |
|
397 | 397 | pat = re.compile(r'^\s*', re.MULTILINE) |
|
398 | 398 | else: |
|
399 | 399 | pat = re.compile(r'^', re.MULTILINE) |
|
400 | 400 | outstr = re.sub(pat, ind, instr) |
|
401 | 401 | if outstr.endswith(os.linesep+ind): |
|
402 | 402 | return outstr[:-len(ind)] |
|
403 | 403 | else: |
|
404 | 404 | return outstr |
|
405 | 405 | |
|
406 | 406 | def native_line_ends(filename,backup=1): |
|
407 | 407 | """Convert (in-place) a file to line-ends native to the current OS. |
|
408 | 408 | |
|
409 | 409 | If the optional backup argument is given as false, no backup of the |
|
410 | 410 | original file is left. """ |
|
411 | 411 | |
|
412 | 412 | backup_suffixes = {'posix':'~','dos':'.bak','nt':'.bak','mac':'.bak'} |
|
413 | 413 | |
|
414 | 414 | bak_filename = filename + backup_suffixes[os.name] |
|
415 | 415 | |
|
416 | 416 | original = open(filename).read() |
|
417 | 417 | shutil.copy2(filename,bak_filename) |
|
418 | 418 | try: |
|
419 | 419 | new = open(filename,'wb') |
|
420 | 420 | new.write(os.linesep.join(original.splitlines())) |
|
421 | 421 | new.write(os.linesep) # ALWAYS put an eol at the end of the file |
|
422 | 422 | new.close() |
|
423 | 423 | except: |
|
424 | 424 | os.rename(bak_filename,filename) |
|
425 | 425 | if not backup: |
|
426 | 426 | try: |
|
427 | 427 | os.remove(bak_filename) |
|
428 | 428 | except: |
|
429 | 429 | pass |
|
430 | 430 | |
|
431 | 431 | |
|
432 | 432 | def list_strings(arg): |
|
433 | 433 | """Always return a list of strings, given a string or list of strings |
|
434 | 434 | as input. |
|
435 | 435 | |
|
436 | 436 | :Examples: |
|
437 | 437 | |
|
438 | 438 | In [7]: list_strings('A single string') |
|
439 | 439 | Out[7]: ['A single string'] |
|
440 | 440 | |
|
441 | 441 | In [8]: list_strings(['A single string in a list']) |
|
442 | 442 | Out[8]: ['A single string in a list'] |
|
443 | 443 | |
|
444 | 444 | In [9]: list_strings(['A','list','of','strings']) |
|
445 | 445 | Out[9]: ['A', 'list', 'of', 'strings'] |
|
446 | 446 | """ |
|
447 | 447 | |
|
448 | 448 | if isinstance(arg,basestring): return [arg] |
|
449 | 449 | else: return arg |
|
450 | 450 | |
|
451 | 451 | |
|
452 | 452 | def marquee(txt='',width=78,mark='*'): |
|
453 | 453 | """Return the input string centered in a 'marquee'. |
|
454 | 454 | |
|
455 | 455 | :Examples: |
|
456 | 456 | |
|
457 | 457 | In [16]: marquee('A test',40) |
|
458 | 458 | Out[16]: '**************** A test ****************' |
|
459 | 459 | |
|
460 | 460 | In [17]: marquee('A test',40,'-') |
|
461 | 461 | Out[17]: '---------------- A test ----------------' |
|
462 | 462 | |
|
463 | 463 | In [18]: marquee('A test',40,' ') |
|
464 | 464 | Out[18]: ' A test ' |
|
465 | 465 | |
|
466 | 466 | """ |
|
467 | 467 | if not txt: |
|
468 | 468 | return (mark*width)[:width] |
|
469 | 469 | nmark = (width-len(txt)-2)//len(mark)//2 |
|
470 | 470 | if nmark < 0: nmark =0 |
|
471 | 471 | marks = mark*nmark |
|
472 | 472 | return '%s %s %s' % (marks,txt,marks) |
|
473 | 473 | |
|
474 | 474 | |
|
475 | 475 | ini_spaces_re = re.compile(r'^(\s+)') |
|
476 | 476 | |
|
477 | 477 | def num_ini_spaces(strng): |
|
478 | 478 | """Return the number of initial spaces in a string""" |
|
479 | 479 | |
|
480 | 480 | ini_spaces = ini_spaces_re.match(strng) |
|
481 | 481 | if ini_spaces: |
|
482 | 482 | return ini_spaces.end() |
|
483 | 483 | else: |
|
484 | 484 | return 0 |
|
485 | 485 | |
|
486 | 486 | |
|
487 | 487 | def format_screen(strng): |
|
488 | 488 | """Format a string for screen printing. |
|
489 | 489 | |
|
490 | 490 | This removes some latex-type format codes.""" |
|
491 | 491 | # Paragraph continue |
|
492 | 492 | par_re = re.compile(r'\\$',re.MULTILINE) |
|
493 | 493 | strng = par_re.sub('',strng) |
|
494 | 494 | return strng |
|
495 | 495 | |
|
496 | 496 | |
|
497 | 497 | def dedent(text): |
|
498 | 498 | """Equivalent of textwrap.dedent that ignores unindented first line. |
|
499 | 499 | |
|
500 | 500 | This means it will still dedent strings like: |
|
501 | 501 | '''foo |
|
502 | 502 | is a bar |
|
503 | 503 | ''' |
|
504 | 504 | |
|
505 | 505 | For use in wrap_paragraphs. |
|
506 | 506 | """ |
|
507 | 507 | |
|
508 | 508 | if text.startswith('\n'): |
|
509 | 509 | # text starts with blank line, don't ignore the first line |
|
510 | 510 | return textwrap.dedent(text) |
|
511 | 511 | |
|
512 | 512 | # split first line |
|
513 | 513 | splits = text.split('\n',1) |
|
514 | 514 | if len(splits) == 1: |
|
515 | 515 | # only one line |
|
516 | 516 | return textwrap.dedent(text) |
|
517 | 517 | |
|
518 | 518 | first, rest = splits |
|
519 | 519 | # dedent everything but the first line |
|
520 | 520 | rest = textwrap.dedent(rest) |
|
521 | 521 | return '\n'.join([first, rest]) |
|
522 | 522 | |
|
523 | 523 | |
|
524 | 524 | def wrap_paragraphs(text, ncols=80): |
|
525 | 525 | """Wrap multiple paragraphs to fit a specified width. |
|
526 | 526 | |
|
527 | 527 | This is equivalent to textwrap.wrap, but with support for multiple |
|
528 | 528 | paragraphs, as separated by empty lines. |
|
529 | 529 | |
|
530 | 530 | Returns |
|
531 | 531 | ------- |
|
532 | 532 | |
|
533 | 533 | list of complete paragraphs, wrapped to fill `ncols` columns. |
|
534 | 534 | """ |
|
535 | 535 | paragraph_re = re.compile(r'\n(\s*\n)+', re.MULTILINE) |
|
536 | 536 | text = dedent(text).strip() |
|
537 | 537 | paragraphs = paragraph_re.split(text)[::2] # every other entry is space |
|
538 | 538 | out_ps = [] |
|
539 | 539 | indent_re = re.compile(r'\n\s+', re.MULTILINE) |
|
540 | 540 | for p in paragraphs: |
|
541 | 541 | # presume indentation that survives dedent is meaningful formatting, |
|
542 | 542 | # so don't fill unless text is flush. |
|
543 | 543 | if indent_re.search(p) is None: |
|
544 | 544 | # wrap paragraph |
|
545 | 545 | p = textwrap.fill(p, ncols) |
|
546 | 546 | out_ps.append(p) |
|
547 | 547 | return out_ps |
|
548 | 548 | |
|
549 | 549 | |
|
550 | 550 | def long_substr(data): |
|
551 | 551 | """Return the longest common substring in a list of strings. |
|
552 | 552 | |
|
553 | 553 | Credit: http://stackoverflow.com/questions/2892931/longest-common-substring-from-more-than-two-strings-python |
|
554 | 554 | """ |
|
555 | 555 | substr = '' |
|
556 | 556 | if len(data) > 1 and len(data[0]) > 0: |
|
557 | 557 | for i in range(len(data[0])): |
|
558 | 558 | for j in range(len(data[0])-i+1): |
|
559 | 559 | if j > len(substr) and all(data[0][i:i+j] in x for x in data): |
|
560 | 560 | substr = data[0][i:i+j] |
|
561 | 561 | elif len(data) == 1: |
|
562 | 562 | substr = data[0] |
|
563 | 563 | return substr |
|
564 | 564 | |
|
565 | 565 | |
|
566 | 566 | def strip_email_quotes(text): |
|
567 | 567 | """Strip leading email quotation characters ('>'). |
|
568 | 568 | |
|
569 | 569 | Removes any combination of leading '>' interspersed with whitespace that |
|
570 | 570 | appears *identically* in all lines of the input text. |
|
571 | 571 | |
|
572 | 572 | Parameters |
|
573 | 573 | ---------- |
|
574 | 574 | text : str |
|
575 | 575 | |
|
576 | 576 | Examples |
|
577 | 577 | -------- |
|
578 | 578 | |
|
579 | 579 | Simple uses:: |
|
580 | 580 | |
|
581 | 581 | In [2]: strip_email_quotes('> > text') |
|
582 | 582 | Out[2]: 'text' |
|
583 | 583 | |
|
584 | 584 | In [3]: strip_email_quotes('> > text\\n> > more') |
|
585 | 585 | Out[3]: 'text\\nmore' |
|
586 | 586 | |
|
587 | 587 | Note how only the common prefix that appears in all lines is stripped:: |
|
588 | 588 | |
|
589 | 589 | In [4]: strip_email_quotes('> > text\\n> > more\\n> more...') |
|
590 | 590 | Out[4]: '> text\\n> more\\nmore...' |
|
591 | 591 | |
|
592 | 592 | So if any line has no quote marks ('>') , then none are stripped from any |
|
593 | 593 | of them :: |
|
594 | 594 | |
|
595 | 595 | In [5]: strip_email_quotes('> > text\\n> > more\\nlast different') |
|
596 | 596 | Out[5]: '> > text\\n> > more\\nlast different' |
|
597 | 597 | """ |
|
598 | 598 | lines = text.splitlines() |
|
599 | 599 | matches = set() |
|
600 | 600 | for line in lines: |
|
601 | 601 | prefix = re.match(r'^(\s*>[ >]*)', line) |
|
602 | 602 | if prefix: |
|
603 | 603 | matches.add(prefix.group(1)) |
|
604 | 604 | else: |
|
605 | 605 | break |
|
606 | 606 | else: |
|
607 | 607 | prefix = long_substr(list(matches)) |
|
608 | 608 | if prefix: |
|
609 | 609 | strip = len(prefix) |
|
610 | 610 | text = '\n'.join([ ln[strip:] for ln in lines]) |
|
611 | 611 | return text |
|
612 | 612 | |
|
613 | 613 | |
|
614 | 614 | class EvalFormatter(Formatter): |
|
615 | 615 | """A String Formatter that allows evaluation of simple expressions. |
|
616 | 616 | |
|
617 | 617 | Note that this version interprets a : as specifying a format string (as per |
|
618 | 618 | standard string formatting), so if slicing is required, you must explicitly |
|
619 | 619 | create a slice. |
|
620 | 620 | |
|
621 | 621 | This is to be used in templating cases, such as the parallel batch |
|
622 | 622 | script templates, where simple arithmetic on arguments is useful. |
|
623 | 623 | |
|
624 | 624 | Examples |
|
625 | 625 | -------- |
|
626 | 626 | |
|
627 | 627 | In [1]: f = EvalFormatter() |
|
628 | 628 | In [2]: f.format('{n//4}', n=8) |
|
629 | 629 | Out [2]: '2' |
|
630 | 630 | |
|
631 | 631 | In [3]: f.format("{greeting[slice(2,4)]}", greeting="Hello") |
|
632 | 632 | Out [3]: 'll' |
|
633 | 633 | """ |
|
634 | 634 | def get_field(self, name, args, kwargs): |
|
635 | 635 | v = eval(name, kwargs) |
|
636 | 636 | return v, name |
|
637 | 637 | |
|
638 | 638 | |
|
639 | 639 | @skip_doctest_py3 |
|
640 | 640 | class FullEvalFormatter(Formatter): |
|
641 | 641 | """A String Formatter that allows evaluation of simple expressions. |
|
642 | 642 | |
|
643 | 643 | Any time a format key is not found in the kwargs, |
|
644 | 644 | it will be tried as an expression in the kwargs namespace. |
|
645 | 645 | |
|
646 | 646 | Note that this version allows slicing using [1:2], so you cannot specify |
|
647 | 647 | a format string. Use :class:`EvalFormatter` to permit format strings. |
|
648 | 648 | |
|
649 | 649 | Examples |
|
650 | 650 | -------- |
|
651 | 651 | |
|
652 | 652 | In [1]: f = FullEvalFormatter() |
|
653 | 653 | In [2]: f.format('{n//4}', n=8) |
|
654 | 654 | Out[2]: u'2' |
|
655 | 655 | |
|
656 | 656 | In [3]: f.format('{list(range(5))[2:4]}') |
|
657 | 657 | Out[3]: u'[2, 3]' |
|
658 | 658 | |
|
659 | 659 | In [4]: f.format('{3*2}') |
|
660 | 660 | Out[4]: u'6' |
|
661 | 661 | """ |
|
662 | 662 | # copied from Formatter._vformat with minor changes to allow eval |
|
663 | 663 | # and replace the format_spec code with slicing |
|
664 | 664 | def _vformat(self, format_string, args, kwargs, used_args, recursion_depth): |
|
665 | 665 | if recursion_depth < 0: |
|
666 | 666 | raise ValueError('Max string recursion exceeded') |
|
667 | 667 | result = [] |
|
668 | 668 | for literal_text, field_name, format_spec, conversion in \ |
|
669 | 669 | self.parse(format_string): |
|
670 | 670 | |
|
671 | 671 | # output the literal text |
|
672 | 672 | if literal_text: |
|
673 | 673 | result.append(literal_text) |
|
674 | 674 | |
|
675 | 675 | # if there's a field, output it |
|
676 | 676 | if field_name is not None: |
|
677 | 677 | # this is some markup, find the object and do |
|
678 | 678 | # the formatting |
|
679 | 679 | |
|
680 | 680 | if format_spec: |
|
681 | 681 | # override format spec, to allow slicing: |
|
682 | 682 | field_name = ':'.join([field_name, format_spec]) |
|
683 | 683 | |
|
684 | 684 | # eval the contents of the field for the object |
|
685 | 685 | # to be formatted |
|
686 | 686 | obj = eval(field_name, kwargs) |
|
687 | 687 | |
|
688 | 688 | # do any conversion on the resulting object |
|
689 | 689 | obj = self.convert_field(obj, conversion) |
|
690 | 690 | |
|
691 | 691 | # format the object and append to the result |
|
692 | 692 | result.append(self.format_field(obj, '')) |
|
693 | 693 | |
|
694 | 694 | return u''.join(py3compat.cast_unicode(s) for s in result) |
|
695 | 695 | |
|
696 | 696 | |
|
697 | 697 | @skip_doctest_py3 |
|
698 | 698 | class DollarFormatter(FullEvalFormatter): |
|
699 | 699 | """Formatter allowing Itpl style $foo replacement, for names and attribute |
|
700 | 700 | access only. Standard {foo} replacement also works, and allows full |
|
701 | 701 | evaluation of its arguments. |
|
702 | 702 | |
|
703 | 703 | Examples |
|
704 | 704 | -------- |
|
705 | 705 | In [1]: f = DollarFormatter() |
|
706 | 706 | In [2]: f.format('{n//4}', n=8) |
|
707 | 707 | Out[2]: u'2' |
|
708 | 708 | |
|
709 | 709 | In [3]: f.format('23 * 76 is $result', result=23*76) |
|
710 | 710 | Out[3]: u'23 * 76 is 1748' |
|
711 | 711 | |
|
712 | 712 | In [4]: f.format('$a or {b}', a=1, b=2) |
|
713 | 713 | Out[4]: u'1 or 2' |
|
714 | 714 | """ |
|
715 | 715 | _dollar_pattern = re.compile("(.*?)\$(\$?[\w\.]+)") |
|
716 | 716 | def parse(self, fmt_string): |
|
717 | 717 | for literal_txt, field_name, format_spec, conversion \ |
|
718 | 718 | in Formatter.parse(self, fmt_string): |
|
719 | 719 | |
|
720 | 720 | # Find $foo patterns in the literal text. |
|
721 | 721 | continue_from = 0 |
|
722 | 722 | txt = "" |
|
723 | 723 | for m in self._dollar_pattern.finditer(literal_txt): |
|
724 | 724 | new_txt, new_field = m.group(1,2) |
|
725 | 725 | # $$foo --> $foo |
|
726 | 726 | if new_field.startswith("$"): |
|
727 | 727 | txt += new_txt + new_field |
|
728 | 728 | else: |
|
729 | 729 | yield (txt + new_txt, new_field, "", None) |
|
730 | 730 | txt = "" |
|
731 | 731 | continue_from = m.end() |
|
732 | 732 | |
|
733 | 733 | # Re-yield the {foo} style pattern |
|
734 | 734 | yield (txt + literal_txt[continue_from:], field_name, format_spec, conversion) |
|
735 | 735 | |
|
736 | 736 | #----------------------------------------------------------------------------- |
|
737 | 737 | # Utils to columnize a list of string |
|
738 | 738 | #----------------------------------------------------------------------------- |
|
739 | 739 | |
|
740 | 740 | def _chunks(l, n): |
|
741 | 741 | """Yield successive n-sized chunks from l.""" |
|
742 | 742 | for i in xrange(0, len(l), n): |
|
743 | 743 | yield l[i:i+n] |
|
744 | 744 | |
|
745 | 745 | |
|
746 | 746 | def _find_optimal(rlist , separator_size=2 , displaywidth=80): |
|
747 | 747 | """Calculate optimal info to columnize a list of string""" |
|
748 | 748 | for nrow in range(1, len(rlist)+1) : |
|
749 | 749 | chk = map(max,_chunks(rlist, nrow)) |
|
750 | 750 | sumlength = sum(chk) |
|
751 | 751 | ncols = len(chk) |
|
752 | 752 | if sumlength+separator_size*(ncols-1) <= displaywidth : |
|
753 | 753 | break; |
|
754 | 754 | return {'columns_numbers' : ncols, |
|
755 | 755 | 'optimal_separator_width':(displaywidth - sumlength)/(ncols-1) if (ncols -1) else 0, |
|
756 | 756 | 'rows_numbers' : nrow, |
|
757 | 757 | 'columns_width' : chk |
|
758 | 758 | } |
|
759 | 759 | |
|
760 | 760 | |
|
761 | 761 | def _get_or_default(mylist, i, default=None): |
|
762 | 762 | """return list item number, or default if don't exist""" |
|
763 | 763 | if i >= len(mylist): |
|
764 | 764 | return default |
|
765 | 765 | else : |
|
766 | 766 | return mylist[i] |
|
767 | 767 | |
|
768 | 768 | |
|
769 | 769 | @skip_doctest |
|
770 | 770 | def compute_item_matrix(items, empty=None, *args, **kwargs) : |
|
771 | 771 | """Returns a nested list, and info to columnize items |
|
772 | 772 | |
|
773 |
Parameters |
|
|
774 |
---------- |
|
|
773 | Parameters | |
|
774 | ---------- | |
|
775 | 775 | |
|
776 | 776 | items : |
|
777 | 777 | list of strings to columize |
|
778 | 778 | empty : (default None) |
|
779 | 779 | default value to fill list if needed |
|
780 | 780 | separator_size : int (default=2) |
|
781 | 781 | How much caracters will be used as a separation between each columns. |
|
782 | 782 | displaywidth : int (default=80) |
|
783 | 783 | The width of the area onto wich the columns should enter |
|
784 | 784 | |
|
785 |
Returns |
|
|
786 |
------- |
|
|
785 | Returns | |
|
786 | ------- | |
|
787 | 787 | |
|
788 | 788 | Returns a tuple of (strings_matrix, dict_info) |
|
789 | 789 | |
|
790 | 790 | strings_matrix : |
|
791 | 791 | |
|
792 | 792 | nested list of string, the outer most list contains as many list as |
|
793 | 793 | rows, the innermost lists have each as many element as colums. If the |
|
794 | 794 | total number of elements in `items` does not equal the product of |
|
795 | 795 | rows*columns, the last element of some lists are filled with `None`. |
|
796 | 796 | |
|
797 | 797 | dict_info : |
|
798 | 798 | some info to make columnize easier: |
|
799 | 799 | |
|
800 | 800 | columns_numbers : number of columns |
|
801 | 801 | rows_numbers : number of rows |
|
802 | 802 | columns_width : list of with of each columns |
|
803 | 803 | optimal_separator_width : best separator width between columns |
|
804 | 804 | |
|
805 |
Ex |
|
|
806 |
-------- |
|
|
805 | Examples | |
|
806 | -------- | |
|
807 | 807 | |
|
808 | 808 | In [1]: l = ['aaa','b','cc','d','eeeee','f','g','h','i','j','k','l'] |
|
809 | 809 | ...: compute_item_matrix(l,displaywidth=12) |
|
810 | 810 | Out[1]: |
|
811 | 811 | ([['aaa', 'f', 'k'], |
|
812 | 812 | ['b', 'g', 'l'], |
|
813 | 813 | ['cc', 'h', None], |
|
814 | 814 | ['d', 'i', None], |
|
815 | 815 | ['eeeee', 'j', None]], |
|
816 | 816 | {'columns_numbers': 3, |
|
817 | 817 | 'columns_width': [5, 1, 1], |
|
818 | 818 | 'optimal_separator_width': 2, |
|
819 | 819 | 'rows_numbers': 5}) |
|
820 | 820 | |
|
821 | 821 | """ |
|
822 | 822 | info = _find_optimal(map(len, items), *args, **kwargs) |
|
823 | 823 | nrow, ncol = info['rows_numbers'], info['columns_numbers'] |
|
824 | 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 | 827 | def columnize(items, separator=' ', displaywidth=80): |
|
828 | 828 | """ Transform a list of strings into a single string with columns. |
|
829 | 829 | |
|
830 | 830 | Parameters |
|
831 | 831 | ---------- |
|
832 | 832 | items : sequence of strings |
|
833 | 833 | The strings to process. |
|
834 | 834 | |
|
835 | 835 | separator : str, optional [default is two spaces] |
|
836 | 836 | The string that separates columns. |
|
837 | 837 | |
|
838 | 838 | displaywidth : int, optional [default is 80] |
|
839 | 839 | Width of the display in number of characters. |
|
840 | 840 | |
|
841 | 841 | Returns |
|
842 | 842 | ------- |
|
843 | 843 | The formatted string. |
|
844 | 844 | """ |
|
845 | 845 | if not items : |
|
846 | 846 | return '\n' |
|
847 | 847 | matrix, info = compute_item_matrix(items, separator_size=len(separator), displaywidth=displaywidth) |
|
848 | 848 | fmatrix = [filter(None, x) for x in matrix] |
|
849 | 849 | sjoin = lambda x : separator.join([ y.ljust(w, ' ') for y, w in zip(x, info['columns_width'])]) |
|
850 | 850 | return '\n'.join(map(sjoin, fmatrix))+'\n' |
@@ -1,63 +1,65 b'' | |||
|
1 | 1 | #!/usr/bin/env python |
|
2 | 2 | """Script to auto-generate our API docs. |
|
3 | 3 | """ |
|
4 | 4 | # stdlib imports |
|
5 | 5 | import os |
|
6 | 6 | import sys |
|
7 | 7 | |
|
8 | 8 | # local imports |
|
9 | 9 | sys.path.append(os.path.abspath('sphinxext')) |
|
10 | 10 | from apigen import ApiDocWriter |
|
11 | 11 | |
|
12 | 12 | #***************************************************************************** |
|
13 | 13 | if __name__ == '__main__': |
|
14 | 14 | pjoin = os.path.join |
|
15 | 15 | package = 'IPython' |
|
16 | 16 | outdir = pjoin('source','api','generated') |
|
17 | 17 | docwriter = ApiDocWriter(package,rst_extension='.txt') |
|
18 | 18 | # You have to escape the . here because . is a special char for regexps. |
|
19 | 19 | # You must do make clean if you change this! |
|
20 | 20 | docwriter.package_skip_patterns += [r'\.fixes$', |
|
21 | 21 | r'\.external$', |
|
22 | 22 | r'\.extensions', |
|
23 | 23 | r'\.kernel\.config', |
|
24 | 24 | r'\.attic', |
|
25 | 25 | r'\.quarantine', |
|
26 | 26 | r'\.deathrow', |
|
27 | 27 | r'\.config\.default', |
|
28 | 28 | r'\.config\.profile', |
|
29 | 29 | r'\.frontend', |
|
30 | 30 | r'\.gui', |
|
31 | 31 | r'\.kernel', |
|
32 | 32 | # For now, the zmq code has |
|
33 | 33 | # unconditional top-level code so it's |
|
34 | 34 | # not import safe. This needs fixing |
|
35 | 35 | r'\.zmq', |
|
36 | 36 | ] |
|
37 | 37 | |
|
38 | 38 | docwriter.module_skip_patterns += [ r'\.core\.fakemodule', |
|
39 | 39 | r'\.testing\.iptest', |
|
40 | 40 | # Keeping these disabled is OK |
|
41 | 41 | r'\.parallel\.controller\.mongodb', |
|
42 | 42 | r'\.lib\.inputhookwx', |
|
43 | 43 | r'\.lib\.inputhookgtk', |
|
44 | 44 | r'\.cocoa', |
|
45 | 45 | r'\.ipdoctest', |
|
46 | 46 | r'\.Gnuplot', |
|
47 | 47 | r'\.frontend\.process\.winprocess', |
|
48 | 48 | r'\.Shell', |
|
49 | 49 | ] |
|
50 | 50 | |
|
51 | 51 | # If we don't have pexpect, we can't load irunner, so skip any code that |
|
52 | 52 | # depends on it |
|
53 | 53 | try: |
|
54 | 54 | import pexpect |
|
55 | 55 | except ImportError: |
|
56 | 56 | docwriter.module_skip_patterns += [r'\.lib\.irunner', |
|
57 | 57 | r'\.testing\.mkdoctests'] |
|
58 | 58 | # Now, generate the outputs |
|
59 | 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 | 63 | relative_to = pjoin('source','api') |
|
62 | 64 | ) |
|
63 | 65 | print '%d files written' % len(docwriter.written_modules) |
@@ -1,12 +1,12 b'' | |||
|
1 | 1 | .. _api-index: |
|
2 | 2 | |
|
3 | 3 | ################### |
|
4 | 4 | The IPython API |
|
5 | 5 | ################### |
|
6 | 6 | |
|
7 | 7 | .. htmlonly:: |
|
8 | 8 | |
|
9 | 9 | :Release: |version| |
|
10 | 10 | :Date: |today| |
|
11 | 11 | |
|
12 |
.. include:: generated/gen. |
|
|
12 | .. include:: generated/gen.rst |
@@ -1,8 +1,8 b'' | |||
|
1 | 1 | .. _extensions_storemagic: |
|
2 | 2 | |
|
3 | 3 | ========== |
|
4 | 4 | storemagic |
|
5 | 5 | ========== |
|
6 | 6 | |
|
7 | 7 | .. automodule:: IPython.extensions.storemagic |
|
8 |
:members: |
|
|
8 | :members: store |
@@ -1,552 +1,554 b'' | |||
|
1 | 1 | .. _config_overview: |
|
2 | 2 | |
|
3 | 3 | ============================================ |
|
4 | 4 | Overview of the IPython configuration system |
|
5 | 5 | ============================================ |
|
6 | 6 | |
|
7 | 7 | This section describes the IPython configuration system. Starting with version |
|
8 | 8 | 0.11, IPython has a completely new configuration system that is quite |
|
9 | 9 | different from the older :file:`ipythonrc` or :file:`ipy_user_conf.py` |
|
10 | 10 | approaches. The new configuration system was designed from scratch to address |
|
11 | 11 | the particular configuration needs of IPython. While there are many |
|
12 | 12 | other excellent configuration systems out there, we found that none of them |
|
13 | 13 | met our requirements. |
|
14 | 14 | |
|
15 | 15 | .. warning:: |
|
16 | 16 | |
|
17 | 17 | If you are upgrading to version 0.11 of IPython, you will need to migrate |
|
18 | 18 | your old :file:`ipythonrc` or :file:`ipy_user_conf.py` configuration files |
|
19 | 19 | to the new system. You may want to read the section on |
|
20 | 20 | :ref:`configuring IPython <configuring_ipython>`. There are also some ideas |
|
21 | 21 | `on the IPython wiki <http://wiki.ipython.org/Cookbook/Moving_config_to_IPython_0.11>`_ |
|
22 | 22 | about this. |
|
23 | 23 | |
|
24 | 24 | The discussion that follows is focused on teaching users how to configure |
|
25 | 25 | IPython to their liking. Developers who want to know more about how they |
|
26 | 26 | can enable their objects to take advantage of the configuration system |
|
27 | 27 | should consult our :ref:`developer guide <developer_guide>` |
|
28 | 28 | |
|
29 | 29 | The main concepts |
|
30 | 30 | ================= |
|
31 | 31 | |
|
32 | 32 | There are a number of abstractions that the IPython configuration system uses. |
|
33 | 33 | Each of these abstractions is represented by a Python class. |
|
34 | 34 | |
|
35 | 35 | Configuration object: :class:`~IPython.config.loader.Config` |
|
36 | 36 | A configuration object is a simple dictionary-like class that holds |
|
37 | 37 | configuration attributes and sub-configuration objects. These classes |
|
38 | 38 | support dotted attribute style access (``Foo.bar``) in addition to the |
|
39 | 39 | regular dictionary style access (``Foo['bar']``). Configuration objects |
|
40 | 40 | are smart. They know how to merge themselves with other configuration |
|
41 | 41 | objects and they automatically create sub-configuration objects. |
|
42 | 42 | |
|
43 | 43 | Application: :class:`~IPython.config.application.Application` |
|
44 | 44 | An application is a process that does a specific job. The most obvious |
|
45 | 45 | application is the :command:`ipython` command line program. Each |
|
46 | 46 | application reads *one or more* configuration files and a single set of |
|
47 | 47 | command line options |
|
48 | 48 | and then produces a master configuration object for the application. This |
|
49 | 49 | configuration object is then passed to the configurable objects that the |
|
50 | 50 | application creates. These configurable objects implement the actual logic |
|
51 | 51 | of the application and know how to configure themselves given the |
|
52 | 52 | configuration object. |
|
53 | 53 | |
|
54 | 54 | Applications always have a `log` attribute that is a configured Logger. |
|
55 | 55 | This allows centralized logging configuration per-application. |
|
56 | 56 | |
|
57 | 57 | Configurable: :class:`~IPython.config.configurable.Configurable` |
|
58 | 58 | A configurable is a regular Python class that serves as a base class for |
|
59 | 59 | all main classes in an application. The |
|
60 | 60 | :class:`~IPython.config.configurable.Configurable` base class is |
|
61 | 61 | lightweight and only does one things. |
|
62 | 62 | |
|
63 | 63 | This :class:`~IPython.config.configurable.Configurable` is a subclass |
|
64 | 64 | of :class:`~IPython.utils.traitlets.HasTraits` that knows how to configure |
|
65 | 65 | itself. Class level traits with the metadata ``config=True`` become |
|
66 | 66 | values that can be configured from the command line and configuration |
|
67 | 67 | files. |
|
68 | 68 | |
|
69 | 69 | Developers create :class:`~IPython.config.configurable.Configurable` |
|
70 | 70 | subclasses that implement all of the logic in the application. Each of |
|
71 | 71 | these subclasses has its own configuration information that controls how |
|
72 | 72 | instances are created. |
|
73 | 73 | |
|
74 | 74 | Singletons: :class:`~IPython.config.configurable.SingletonConfigurable` |
|
75 | 75 | Any object for which there is a single canonical instance. These are |
|
76 | 76 | just like Configurables, except they have a class method |
|
77 | 77 | :meth:`~IPython.config.configurable.SingletonConfigurable.instance`, |
|
78 | 78 | that returns the current active instance (or creates one if it |
|
79 | 79 | does not exist). Examples of singletons include |
|
80 | 80 | :class:`~IPython.config.application.Application`s and |
|
81 | 81 | :class:`~IPython.core.interactiveshell.InteractiveShell`. This lets |
|
82 | 82 | objects easily connect to the current running Application without passing |
|
83 | 83 | objects around everywhere. For instance, to get the current running |
|
84 | 84 | Application instance, simply do: ``app = Application.instance()``. |
|
85 | 85 | |
|
86 | 86 | |
|
87 | 87 | .. note:: |
|
88 | 88 | |
|
89 | 89 | Singletons are not strictly enforced - you can have many instances |
|
90 | 90 | of a given singleton class, but the :meth:`instance` method will always |
|
91 | 91 | return the same one. |
|
92 | 92 | |
|
93 | 93 | Having described these main concepts, we can now state the main idea in our |
|
94 | 94 | configuration system: *"configuration" allows the default values of class |
|
95 | 95 | attributes to be controlled on a class by class basis*. Thus all instances of |
|
96 | 96 | a given class are configured in the same way. Furthermore, if two instances |
|
97 | 97 | need to be configured differently, they need to be instances of two different |
|
98 | 98 | classes. While this model may seem a bit restrictive, we have found that it |
|
99 | 99 | expresses most things that need to be configured extremely well. However, it |
|
100 | 100 | is possible to create two instances of the same class that have different |
|
101 | 101 | trait values. This is done by overriding the configuration. |
|
102 | 102 | |
|
103 | 103 | Now, we show what our configuration objects and files look like. |
|
104 | 104 | |
|
105 | 105 | Configuration objects and files |
|
106 | 106 | =============================== |
|
107 | 107 | |
|
108 | 108 | A configuration file is simply a pure Python file that sets the attributes |
|
109 | 109 | of a global, pre-created configuration object. This configuration object is a |
|
110 | 110 | :class:`~IPython.config.loader.Config` instance. While in a configuration |
|
111 | 111 | file, to get a reference to this object, simply call the :func:`get_config` |
|
112 | 112 | function. We inject this function into the global namespace that the |
|
113 | 113 | configuration file is executed in. |
|
114 | 114 | |
|
115 | 115 | Here is an example of a super simple configuration file that does nothing:: |
|
116 | 116 | |
|
117 | 117 | c = get_config() |
|
118 | 118 | |
|
119 | 119 | Once you get a reference to the configuration object, you simply set |
|
120 | 120 | attributes on it. All you have to know is: |
|
121 | 121 | |
|
122 | 122 | * The name of each attribute. |
|
123 | 123 | * The type of each attribute. |
|
124 | 124 | |
|
125 | 125 | The answers to these two questions are provided by the various |
|
126 | 126 | :class:`~IPython.config.configurable.Configurable` subclasses that an |
|
127 | 127 | application uses. Let's look at how this would work for a simple configurable |
|
128 | 128 | subclass:: |
|
129 | 129 | |
|
130 | 130 | # Sample configurable: |
|
131 | 131 | from IPython.config.configurable import Configurable |
|
132 | 132 | from IPython.utils.traitlets import Int, Float, Unicode, Bool |
|
133 | 133 | |
|
134 | 134 | class MyClass(Configurable): |
|
135 | 135 | name = Unicode(u'defaultname', config=True) |
|
136 | 136 | ranking = Int(0, config=True) |
|
137 | 137 | value = Float(99.0) |
|
138 | 138 | # The rest of the class implementation would go here.. |
|
139 | 139 | |
|
140 | 140 | In this example, we see that :class:`MyClass` has three attributes, two |
|
141 | 141 | of whom (``name``, ``ranking``) can be configured. All of the attributes |
|
142 | 142 | are given types and default values. If a :class:`MyClass` is instantiated, |
|
143 | 143 | but not configured, these default values will be used. But let's see how |
|
144 | 144 | to configure this class in a configuration file:: |
|
145 | 145 | |
|
146 | 146 | # Sample config file |
|
147 | 147 | c = get_config() |
|
148 | 148 | |
|
149 | 149 | c.MyClass.name = 'coolname' |
|
150 | 150 | c.MyClass.ranking = 10 |
|
151 | 151 | |
|
152 | 152 | After this configuration file is loaded, the values set in it will override |
|
153 | 153 | the class defaults anytime a :class:`MyClass` is created. Furthermore, |
|
154 | 154 | these attributes will be type checked and validated anytime they are set. |
|
155 | 155 | This type checking is handled by the :mod:`IPython.utils.traitlets` module, |
|
156 | 156 | which provides the :class:`Unicode`, :class:`Int` and :class:`Float` types. |
|
157 | 157 | In addition to these traitlets, the :mod:`IPython.utils.traitlets` provides |
|
158 | 158 | traitlets for a number of other types. |
|
159 | 159 | |
|
160 | 160 | .. note:: |
|
161 | 161 | |
|
162 | 162 | Underneath the hood, the :class:`Configurable` base class is a subclass of |
|
163 | 163 | :class:`IPython.utils.traitlets.HasTraits`. The |
|
164 | 164 | :mod:`IPython.utils.traitlets` module is a lightweight version of |
|
165 | 165 | :mod:`enthought.traits`. Our implementation is a pure Python subset |
|
166 | 166 | (mostly API compatible) of :mod:`enthought.traits` that does not have any |
|
167 | 167 | of the automatic GUI generation capabilities. Our plan is to achieve 100% |
|
168 | 168 | API compatibility to enable the actual :mod:`enthought.traits` to |
|
169 | 169 | eventually be used instead. Currently, we cannot use |
|
170 | 170 | :mod:`enthought.traits` as we are committed to the core of IPython being |
|
171 | 171 | pure Python. |
|
172 | 172 | |
|
173 | 173 | It should be very clear at this point what the naming convention is for |
|
174 | 174 | configuration attributes:: |
|
175 | 175 | |
|
176 | 176 | c.ClassName.attribute_name = attribute_value |
|
177 | 177 | |
|
178 | 178 | Here, ``ClassName`` is the name of the class whose configuration attribute you |
|
179 | 179 | want to set, ``attribute_name`` is the name of the attribute you want to set |
|
180 | 180 | and ``attribute_value`` the the value you want it to have. The ``ClassName`` |
|
181 | 181 | attribute of ``c`` is not the actual class, but instead is another |
|
182 | 182 | :class:`~IPython.config.loader.Config` instance. |
|
183 | 183 | |
|
184 | 184 | .. note:: |
|
185 | 185 | |
|
186 | 186 | The careful reader may wonder how the ``ClassName`` (``MyClass`` in |
|
187 | 187 | the above example) attribute of the configuration object ``c`` gets |
|
188 | 188 | created. These attributes are created on the fly by the |
|
189 | 189 | :class:`~IPython.config.loader.Config` instance, using a simple naming |
|
190 | 190 | convention. Any attribute of a :class:`~IPython.config.loader.Config` |
|
191 | 191 | instance whose name begins with an uppercase character is assumed to be a |
|
192 | 192 | sub-configuration and a new empty :class:`~IPython.config.loader.Config` |
|
193 | 193 | instance is dynamically created for that attribute. This allows deeply |
|
194 | 194 | hierarchical information created easily (``c.Foo.Bar.value``) on the fly. |
|
195 | 195 | |
|
196 | 196 | Configuration files inheritance |
|
197 | 197 | =============================== |
|
198 | 198 | |
|
199 | 199 | Let's say you want to have different configuration files for various purposes. |
|
200 | 200 | Our configuration system makes it easy for one configuration file to inherit |
|
201 | 201 | the information in another configuration file. The :func:`load_subconfig` |
|
202 | 202 | command can be used in a configuration file for this purpose. Here is a simple |
|
203 | 203 | example that loads all of the values from the file :file:`base_config.py`:: |
|
204 | 204 | |
|
205 | 205 | # base_config.py |
|
206 | 206 | c = get_config() |
|
207 | 207 | c.MyClass.name = 'coolname' |
|
208 | 208 | c.MyClass.ranking = 100 |
|
209 | 209 | |
|
210 | 210 | into the configuration file :file:`main_config.py`:: |
|
211 | 211 | |
|
212 | 212 | # main_config.py |
|
213 | 213 | c = get_config() |
|
214 | 214 | |
|
215 | 215 | # Load everything from base_config.py |
|
216 | 216 | load_subconfig('base_config.py') |
|
217 | 217 | |
|
218 | 218 | # Now override one of the values |
|
219 | 219 | c.MyClass.name = 'bettername' |
|
220 | 220 | |
|
221 | 221 | In a situation like this the :func:`load_subconfig` makes sure that the |
|
222 | 222 | search path for sub-configuration files is inherited from that of the parent. |
|
223 | 223 | Thus, you can typically put the two in the same directory and everything will |
|
224 | 224 | just work. |
|
225 | 225 | |
|
226 | 226 | You can also load configuration files by profile, for instance: |
|
227 | 227 | |
|
228 | 228 | .. sourcecode:: python |
|
229 | 229 | |
|
230 | 230 | load_subconfig('ipython_config.py', profile='default') |
|
231 | 231 | |
|
232 | 232 | to inherit your default configuration as a starting point. |
|
233 | 233 | |
|
234 | 234 | |
|
235 | 235 | Class based configuration inheritance |
|
236 | 236 | ===================================== |
|
237 | 237 | |
|
238 | 238 | There is another aspect of configuration where inheritance comes into play. |
|
239 | 239 | Sometimes, your classes will have an inheritance hierarchy that you want |
|
240 | 240 | to be reflected in the configuration system. Here is a simple example:: |
|
241 | 241 | |
|
242 | 242 | from IPython.config.configurable import Configurable |
|
243 | 243 | from IPython.utils.traitlets import Int, Float, Unicode, Bool |
|
244 | 244 | |
|
245 | 245 | class Foo(Configurable): |
|
246 | 246 | name = Unicode(u'fooname', config=True) |
|
247 | 247 | value = Float(100.0, config=True) |
|
248 | 248 | |
|
249 | 249 | class Bar(Foo): |
|
250 | 250 | name = Unicode(u'barname', config=True) |
|
251 | 251 | othervalue = Int(0, config=True) |
|
252 | 252 | |
|
253 | 253 | Now, we can create a configuration file to configure instances of :class:`Foo` |
|
254 | 254 | and :class:`Bar`:: |
|
255 | 255 | |
|
256 | 256 | # config file |
|
257 | 257 | c = get_config() |
|
258 | 258 | |
|
259 | 259 | c.Foo.name = u'bestname' |
|
260 | 260 | c.Bar.othervalue = 10 |
|
261 | 261 | |
|
262 | 262 | This class hierarchy and configuration file accomplishes the following: |
|
263 | 263 | |
|
264 | 264 | * The default value for :attr:`Foo.name` and :attr:`Bar.name` will be |
|
265 | 265 | 'bestname'. Because :class:`Bar` is a :class:`Foo` subclass it also |
|
266 | 266 | picks up the configuration information for :class:`Foo`. |
|
267 | 267 | * The default value for :attr:`Foo.value` and :attr:`Bar.value` will be |
|
268 | 268 | ``100.0``, which is the value specified as the class default. |
|
269 | 269 | * The default value for :attr:`Bar.othervalue` will be 10 as set in the |
|
270 | 270 | configuration file. Because :class:`Foo` is the parent of :class:`Bar` |
|
271 | 271 | it doesn't know anything about the :attr:`othervalue` attribute. |
|
272 | 272 | |
|
273 | 273 | |
|
274 | 274 | .. _ipython_dir: |
|
275 | 275 | |
|
276 | 276 | Configuration file location |
|
277 | 277 | =========================== |
|
278 | 278 | |
|
279 | 279 | So where should you put your configuration files? IPython uses "profiles" for |
|
280 | 280 | configuration, and by default, all profiles will be stored in the so called |
|
281 | 281 | "IPython directory". The location of this directory is determined by the |
|
282 | 282 | following algorithm: |
|
283 | 283 | |
|
284 | 284 | * If the ``ipython-dir`` command line flag is given, its value is used. |
|
285 | 285 | |
|
286 | 286 | * If not, the value returned by :func:`IPython.utils.path.get_ipython_dir` |
|
287 | 287 | is used. This function will first look at the :envvar:`IPYTHONDIR` |
|
288 | 288 | environment variable and then default to a platform-specific default. |
|
289 | 289 | Historical support for the :envvar:`IPYTHON_DIR` environment variable will |
|
290 | 290 | be removed in a future release. |
|
291 | 291 | |
|
292 | 292 | On posix systems (Linux, Unix, etc.), IPython respects the ``$XDG_CONFIG_HOME`` |
|
293 | 293 | part of the `XDG Base Directory`_ specification. If ``$XDG_CONFIG_HOME`` is |
|
294 | 294 | defined and exists ( ``XDG_CONFIG_HOME`` has a default interpretation of |
|
295 | 295 | :file:`$HOME/.config`), then IPython's config directory will be located in |
|
296 | 296 | :file:`$XDG_CONFIG_HOME/ipython`. If users still have an IPython directory |
|
297 | 297 | in :file:`$HOME/.ipython`, then that will be used. in preference to the |
|
298 | 298 | system default. |
|
299 | 299 | |
|
300 | 300 | For most users, the default value will simply be something like |
|
301 | 301 | :file:`$HOME/.config/ipython` on Linux, or :file:`$HOME/.ipython` |
|
302 | 302 | elsewhere. |
|
303 | 303 | |
|
304 | 304 | Once the location of the IPython directory has been determined, you need to know |
|
305 | 305 | which profile you are using. For users with a single configuration, this will |
|
306 | 306 | simply be 'default', and will be located in |
|
307 | 307 | :file:`<IPYTHONDIR>/profile_default`. |
|
308 | 308 | |
|
309 | 309 | The next thing you need to know is what to call your configuration file. The |
|
310 | 310 | basic idea is that each application has its own default configuration filename. |
|
311 | 311 | The default named used by the :command:`ipython` command line program is |
|
312 | 312 | :file:`ipython_config.py`, and *all* IPython applications will use this file. |
|
313 | 313 | Other applications, such as the parallel :command:`ipcluster` scripts or the |
|
314 | 314 | QtConsole will load their own config files *after* :file:`ipython_config.py`. To |
|
315 | 315 | load a particular configuration file instead of the default, the name can be |
|
316 | 316 | overridden by the ``config_file`` command line flag. |
|
317 | 317 | |
|
318 | 318 | To generate the default configuration files, do:: |
|
319 | 319 | |
|
320 | 320 | $> ipython profile create |
|
321 | 321 | |
|
322 | 322 | and you will have a default :file:`ipython_config.py` in your IPython directory |
|
323 | 323 | under :file:`profile_default`. If you want the default config files for the |
|
324 | 324 | :mod:`IPython.parallel` applications, add ``--parallel`` to the end of the |
|
325 | 325 | command-line args. |
|
326 | 326 | |
|
327 | 327 | |
|
328 | 328 | Locating these files |
|
329 | 329 | -------------------- |
|
330 | 330 | |
|
331 | 331 | From the command-line, you can quickly locate the IPYTHONDIR or a specific |
|
332 | 332 | profile with: |
|
333 | 333 | |
|
334 | 334 | .. sourcecode:: bash |
|
335 | 335 | |
|
336 | 336 | $> ipython locate |
|
337 | 337 | /home/you/.ipython |
|
338 | 338 | |
|
339 | 339 | $> ipython locate profile foo |
|
340 | 340 | /home/you/.ipython/profile_foo |
|
341 | 341 | |
|
342 | 342 | These map to the utility functions: :func:`IPython.utils.path.get_ipython_dir` |
|
343 | 343 | and :func:`IPython.utils.path.locate_profile` respectively. |
|
344 | 344 | |
|
345 | 345 | |
|
346 | 346 | .. _Profiles: |
|
347 | 347 | |
|
348 | 348 | Profiles |
|
349 | 349 | ======== |
|
350 | 350 | |
|
351 | 351 | A profile is a directory containing configuration and runtime files, such as |
|
352 | 352 | logs, connection info for the parallel apps, and your IPython command history. |
|
353 | 353 | |
|
354 | 354 | The idea is that users often want to maintain a set of configuration files for |
|
355 | 355 | different purposes: one for doing numerical computing with NumPy and SciPy and |
|
356 | 356 | another for doing symbolic computing with SymPy. Profiles make it easy to keep a |
|
357 | 357 | separate configuration files, logs, and histories for each of these purposes. |
|
358 | 358 | |
|
359 | 359 | Let's start by showing how a profile is used: |
|
360 | 360 | |
|
361 | 361 | .. code-block:: bash |
|
362 | 362 | |
|
363 | 363 | $ ipython --profile=sympy |
|
364 | 364 | |
|
365 | 365 | This tells the :command:`ipython` command line program to get its configuration |
|
366 | 366 | from the "sympy" profile. The file names for various profiles do not change. The |
|
367 | 367 | only difference is that profiles are named in a special way. In the case above, |
|
368 | 368 | the "sympy" profile means looking for :file:`ipython_config.py` in :file:`<IPYTHONDIR>/profile_sympy`. |
|
369 | 369 | |
|
370 | 370 | The general pattern is this: simply create a new profile with: |
|
371 | 371 | |
|
372 | 372 | .. code-block:: bash |
|
373 | 373 | |
|
374 | 374 | ipython profile create <name> |
|
375 | 375 | |
|
376 | 376 | which adds a directory called ``profile_<name>`` to your IPython directory. Then |
|
377 | 377 | you can load this profile by adding ``--profile=<name>`` to your command line |
|
378 | 378 | options. Profiles are supported by all IPython applications. |
|
379 | 379 | |
|
380 | 380 | IPython ships with some sample profiles in :file:`IPython/config/profile`. If |
|
381 | 381 | you create profiles with the name of one of our shipped profiles, these config |
|
382 | 382 | files will be copied over instead of starting with the automatically generated |
|
383 | 383 | config files. |
|
384 | 384 | |
|
385 | 385 | Security Files |
|
386 | 386 | -------------- |
|
387 | 387 | |
|
388 | 388 | If you are using the notebook, qtconsole, or parallel code, IPython stores |
|
389 | 389 | connection information in small JSON files in the active profile's security |
|
390 | 390 | directory. This directory is made private, so only you can see the files inside. If |
|
391 | 391 | you need to move connection files around to other computers, this is where they will |
|
392 | 392 | be. If you want your code to be able to open security files by name, we have a |
|
393 | 393 | convenience function :func:`IPython.utils.path.get_security_file`, which will return |
|
394 | 394 | the absolute path to a security file from its filename and [optionally] profile |
|
395 | 395 | name. |
|
396 | 396 | |
|
397 | .. _startup_files: | |
|
398 | ||
|
397 | 399 | Startup Files |
|
398 | 400 | ------------- |
|
399 | 401 | |
|
400 | 402 | If you want some code to be run at the beginning of every IPython session with a |
|
401 | 403 | particular profile, the easiest way is to add Python (.py) or IPython (.ipy) scripts |
|
402 | 404 | to your :file:`<profile>/startup` directory. Files in this directory will always be |
|
403 | 405 | executed as soon as the IPython shell is constructed, and before any other code or |
|
404 | 406 | scripts you have specified. If you have multiple files in the startup directory, |
|
405 | 407 | they will be run in lexicographical order, so you can control the ordering by adding |
|
406 | 408 | a '00-' prefix. |
|
407 | 409 | |
|
408 | 410 | .. note:: |
|
409 | 411 | |
|
410 | 412 | Automatic startup files are new in IPython 0.12. Use the |
|
411 | 413 | InteractiveShellApp.exec_files configurable for similar behavior in 0.11. |
|
412 | 414 | |
|
413 | 415 | |
|
414 | 416 | .. _commandline: |
|
415 | 417 | |
|
416 | 418 | Command-line arguments |
|
417 | 419 | ====================== |
|
418 | 420 | |
|
419 | 421 | IPython exposes *all* configurable options on the command-line. The command-line |
|
420 | 422 | arguments are generated from the Configurable traits of the classes associated |
|
421 | 423 | with a given Application. Configuring IPython from the command-line may look |
|
422 | 424 | very similar to an IPython config file |
|
423 | 425 | |
|
424 | 426 | IPython applications use a parser called |
|
425 | 427 | :class:`~IPython.config.loader.KeyValueLoader` to load values into a Config |
|
426 | 428 | object. Values are assigned in much the same way as in a config file: |
|
427 | 429 | |
|
428 | 430 | .. code-block:: bash |
|
429 | 431 | |
|
430 | 432 | $> ipython --InteractiveShell.use_readline=False --BaseIPythonApplication.profile='myprofile' |
|
431 | 433 | |
|
432 | 434 | Is the same as adding: |
|
433 | 435 | |
|
434 | 436 | .. sourcecode:: python |
|
435 | 437 | |
|
436 | 438 | c.InteractiveShell.use_readline=False |
|
437 | 439 | c.BaseIPythonApplication.profile='myprofile' |
|
438 | 440 | |
|
439 | 441 | to your config file. Key/Value arguments *always* take a value, separated by '=' |
|
440 | 442 | and no spaces. |
|
441 | 443 | |
|
442 | 444 | Common Arguments |
|
443 | **************** | |
|
445 | ---------------- | |
|
444 | 446 | |
|
445 | 447 | Since the strictness and verbosity of the KVLoader above are not ideal for everyday |
|
446 | 448 | use, common arguments can be specified as flags_ or aliases_. |
|
447 | 449 | |
|
448 | 450 | Flags and Aliases are handled by :mod:`argparse` instead, allowing for more flexible |
|
449 | 451 | parsing. In general, flags and aliases are prefixed by ``--``, except for those |
|
450 | 452 | that are single characters, in which case they can be specified with a single ``-``, e.g.: |
|
451 | 453 | |
|
452 | 454 | .. code-block:: bash |
|
453 | 455 | |
|
454 | 456 | $> ipython -i -c "import numpy; x=numpy.linspace(0,1)" --profile testing --colors=lightbg |
|
455 | 457 | |
|
456 | 458 | Aliases |
|
457 | ------- | |
|
459 | ******* | |
|
458 | 460 | |
|
459 | 461 | For convenience, applications have a mapping of commonly used traits, so you don't have |
|
460 | 462 | to specify the whole class name: |
|
461 | 463 | |
|
462 | 464 | .. code-block:: bash |
|
463 | 465 | |
|
464 | 466 | $> ipython --profile myprofile |
|
465 | 467 | # and |
|
466 | 468 | $> ipython --profile='myprofile' |
|
467 | 469 | # are equivalent to |
|
468 | 470 | $> ipython --BaseIPythonApplication.profile='myprofile' |
|
469 | 471 | |
|
470 | 472 | Flags |
|
471 | ----- | |
|
473 | ***** | |
|
472 | 474 | |
|
473 | 475 | Applications can also be passed **flags**. Flags are options that take no |
|
474 | 476 | arguments. They are simply wrappers for |
|
475 | 477 | setting one or more configurables with predefined values, often True/False. |
|
476 | 478 | |
|
477 | 479 | For instance: |
|
478 | 480 | |
|
479 | 481 | .. code-block:: bash |
|
480 | 482 | |
|
481 | 483 | $> ipcontroller --debug |
|
482 | 484 | # is equivalent to |
|
483 | 485 | $> ipcontroller --Application.log_level=DEBUG |
|
484 | 486 | # and |
|
485 | 487 | $> ipython --pylab |
|
486 | 488 | # is equivalent to |
|
487 | 489 | $> ipython --pylab=auto |
|
488 | 490 | # or |
|
489 | 491 | $> ipython --no-banner |
|
490 | 492 | # is equivalent to |
|
491 | 493 | $> ipython --TerminalIPythonApp.display_banner=False |
|
492 | 494 | |
|
493 | 495 | Subcommands |
|
494 | *********** | |
|
496 | ----------- | |
|
495 | 497 | |
|
496 | 498 | |
|
497 | 499 | Some IPython applications have **subcommands**. Subcommands are modeled after |
|
498 | 500 | :command:`git`, and are called with the form :command:`command subcommand |
|
499 | 501 | [...args]`. Currently, the QtConsole is a subcommand of terminal IPython: |
|
500 | 502 | |
|
501 | 503 | .. code-block:: bash |
|
502 | 504 | |
|
503 | 505 | $> ipython qtconsole --profile=myprofile |
|
504 | 506 | |
|
505 | 507 | and :command:`ipcluster` is simply a wrapper for its various subcommands (start, |
|
506 | 508 | stop, engines). |
|
507 | 509 | |
|
508 | 510 | .. code-block:: bash |
|
509 | 511 | |
|
510 | 512 | $> ipcluster start --profile=myprofile --n=4 |
|
511 | 513 | |
|
512 | 514 | |
|
513 | 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 | 518 | Design requirements |
|
517 | 519 | =================== |
|
518 | 520 | |
|
519 | 521 | Here are the main requirements we wanted our configuration system to have: |
|
520 | 522 | |
|
521 | 523 | * Support for hierarchical configuration information. |
|
522 | 524 | |
|
523 | 525 | * Full integration with command line option parsers. Often, you want to read |
|
524 | 526 | a configuration file, but then override some of the values with command line |
|
525 | 527 | options. Our configuration system automates this process and allows each |
|
526 | 528 | command line option to be linked to a particular attribute in the |
|
527 | 529 | configuration hierarchy that it will override. |
|
528 | 530 | |
|
529 | 531 | * Configuration files that are themselves valid Python code. This accomplishes |
|
530 | 532 | many things. First, it becomes possible to put logic in your configuration |
|
531 | 533 | files that sets attributes based on your operating system, network setup, |
|
532 | 534 | Python version, etc. Second, Python has a super simple syntax for accessing |
|
533 | 535 | hierarchical data structures, namely regular attribute access |
|
534 | 536 | (``Foo.Bar.Bam.name``). Third, using Python makes it easy for users to |
|
535 | 537 | import configuration attributes from one configuration file to another. |
|
536 | 538 | Fourth, even though Python is dynamically typed, it does have types that can |
|
537 | 539 | be checked at runtime. Thus, a ``1`` in a config file is the integer '1', |
|
538 | 540 | while a ``'1'`` is a string. |
|
539 | 541 | |
|
540 | 542 | * A fully automated method for getting the configuration information to the |
|
541 | 543 | classes that need it at runtime. Writing code that walks a configuration |
|
542 | 544 | hierarchy to extract a particular attribute is painful. When you have |
|
543 | 545 | complex configuration information with hundreds of attributes, this makes |
|
544 | 546 | you want to cry. |
|
545 | 547 | |
|
546 | 548 | * Type checking and validation that doesn't require the entire configuration |
|
547 | 549 | hierarchy to be specified statically before runtime. Python is a very |
|
548 | 550 | dynamic language and you don't always know everything that needs to be |
|
549 | 551 | configured when a program starts. |
|
550 | 552 | |
|
551 | 553 | |
|
552 | 554 | .. _`XDG Base Directory`: http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html |
@@ -1,1150 +1,1150 b'' | |||
|
1 | 1 | ================= |
|
2 | 2 | IPython reference |
|
3 | 3 | ================= |
|
4 | 4 | |
|
5 | 5 | .. _command_line_options: |
|
6 | 6 | |
|
7 | 7 | Command-line usage |
|
8 | 8 | ================== |
|
9 | 9 | |
|
10 | 10 | You start IPython with the command:: |
|
11 | 11 | |
|
12 | 12 | $ ipython [options] files |
|
13 | 13 | |
|
14 | 14 | .. note:: |
|
15 | 15 | |
|
16 | 16 | For IPython on Python 3, use ``ipython3`` in place of ``ipython``. |
|
17 | 17 | |
|
18 | 18 | If invoked with no options, it executes all the files listed in sequence |
|
19 | 19 | and drops you into the interpreter while still acknowledging any options |
|
20 | 20 | you may have set in your ipython_config.py. This behavior is different from |
|
21 | 21 | standard Python, which when called as python -i will only execute one |
|
22 | 22 | file and ignore your configuration setup. |
|
23 | 23 | |
|
24 | 24 | Please note that some of the configuration options are not available at |
|
25 | 25 | the command line, simply because they are not practical here. Look into |
|
26 | 26 | your configuration files for details on those. There are separate configuration |
|
27 | 27 | files for each profile, and the files look like "ipython_config.py" or |
|
28 | 28 | "ipython_config_<frontendname>.py". Profile directories look like |
|
29 | 29 | "profile_profilename" and are typically installed in the IPYTHONDIR directory. |
|
30 | 30 | For Linux users, this will be $HOME/.config/ipython, and for other users it |
|
31 | 31 | will be $HOME/.ipython. For Windows users, $HOME resolves to C:\\Documents and |
|
32 | 32 | Settings\\YourUserName in most instances. |
|
33 | 33 | |
|
34 | 34 | |
|
35 | 35 | Eventloop integration |
|
36 | 36 | --------------------- |
|
37 | 37 | |
|
38 | 38 | Previously IPython had command line options for controlling GUI event loop |
|
39 | 39 | integration (-gthread, -qthread, -q4thread, -wthread, -pylab). As of IPython |
|
40 | 40 | version 0.11, these have been removed. Please see the new ``%gui`` |
|
41 | 41 | magic command or :ref:`this section <gui_support>` for details on the new |
|
42 | 42 | interface, or specify the gui at the commandline:: |
|
43 | 43 | |
|
44 | 44 | $ ipython --gui=qt |
|
45 | 45 | |
|
46 | 46 | |
|
47 | 47 | Command-line Options |
|
48 | 48 | -------------------- |
|
49 | 49 | |
|
50 | 50 | To see the options IPython accepts, use ``ipython --help`` (and you probably |
|
51 | 51 | should run the output through a pager such as ``ipython --help | less`` for |
|
52 | 52 | more convenient reading). This shows all the options that have a single-word |
|
53 | 53 | alias to control them, but IPython lets you configure all of its objects from |
|
54 | 54 | the command-line by passing the full class name and a corresponding value; type |
|
55 | 55 | ``ipython --help-all`` to see this full list. For example:: |
|
56 | 56 | |
|
57 | 57 | ipython --pylab qt |
|
58 | 58 | |
|
59 | 59 | is equivalent to:: |
|
60 | 60 | |
|
61 | 61 | ipython --TerminalIPythonApp.pylab='qt' |
|
62 | 62 | |
|
63 | 63 | Note that in the second form, you *must* use the equal sign, as the expression |
|
64 | 64 | is evaluated as an actual Python assignment. While in the above example the |
|
65 | 65 | short form is more convenient, only the most common options have a short form, |
|
66 | 66 | while any configurable variable in IPython can be set at the command-line by |
|
67 | 67 | using the long form. This long form is the same syntax used in the |
|
68 | 68 | configuration files, if you want to set these options permanently. |
|
69 | 69 | |
|
70 | 70 | |
|
71 | 71 | Interactive use |
|
72 | 72 | =============== |
|
73 | 73 | |
|
74 | 74 | IPython is meant to work as a drop-in replacement for the standard interactive |
|
75 | 75 | interpreter. As such, any code which is valid python should execute normally |
|
76 | 76 | under IPython (cases where this is not true should be reported as bugs). It |
|
77 | 77 | does, however, offer many features which are not available at a standard python |
|
78 | 78 | prompt. What follows is a list of these. |
|
79 | 79 | |
|
80 | 80 | |
|
81 | 81 | Caution for Windows users |
|
82 | 82 | ------------------------- |
|
83 | 83 | |
|
84 | 84 | Windows, unfortunately, uses the '\\' character as a path separator. This is a |
|
85 | 85 | terrible choice, because '\\' also represents the escape character in most |
|
86 | 86 | modern programming languages, including Python. For this reason, using '/' |
|
87 | 87 | character is recommended if you have problems with ``\``. However, in Windows |
|
88 | 88 | commands '/' flags options, so you can not use it for the root directory. This |
|
89 | 89 | means that paths beginning at the root must be typed in a contrived manner |
|
90 | 90 | like: ``%copy \opt/foo/bar.txt \tmp`` |
|
91 | 91 | |
|
92 | 92 | .. _magic: |
|
93 | 93 | |
|
94 | 94 | Magic command system |
|
95 | 95 | -------------------- |
|
96 | 96 | |
|
97 | 97 | IPython will treat any line whose first character is a % as a special |
|
98 | 98 | call to a 'magic' function. These allow you to control the behavior of |
|
99 | 99 | IPython itself, plus a lot of system-type features. They are all |
|
100 | 100 | prefixed with a % character, but parameters are given without |
|
101 | 101 | parentheses or quotes. |
|
102 | 102 | |
|
103 | 103 | Lines that begin with ``%%`` signal a *cell magic*: they take as arguments not |
|
104 | 104 | only the rest of the current line, but all lines below them as well, in the |
|
105 | 105 | current execution block. Cell magics can in fact make arbitrary modifications |
|
106 | 106 | to the input they receive, which need not even be valid Python code at all. |
|
107 | 107 | They receive the whole block as a single string. |
|
108 | 108 | |
|
109 | 109 | As a line magic example, the ``%cd`` magic works just like the OS command of |
|
110 | 110 | the same name:: |
|
111 | 111 | |
|
112 | 112 | In [8]: %cd |
|
113 | 113 | /home/fperez |
|
114 | 114 | |
|
115 | 115 | The following uses the builtin ``timeit`` in cell mode:: |
|
116 | 116 | |
|
117 | 117 | In [10]: %%timeit x = range(10000) |
|
118 | 118 | ...: min(x) |
|
119 | 119 | ...: max(x) |
|
120 | 120 | ...: |
|
121 | 121 | 1000 loops, best of 3: 438 us per loop |
|
122 | 122 | |
|
123 | 123 | In this case, ``x = range(10000)`` is called as the line argument, and the |
|
124 | 124 | block with ``min(x)`` and ``max(x)`` is called as the cell body. The |
|
125 | 125 | ``timeit`` magic receives both. |
|
126 | 126 | |
|
127 | 127 | If you have 'automagic' enabled (as it by default), you don't need to type in |
|
128 | 128 | the single ``%`` explicitly for line magics; IPython will scan its internal |
|
129 | 129 | list of magic functions and call one if it exists. With automagic on you can |
|
130 | 130 | then just type ``cd mydir`` to go to directory 'mydir':: |
|
131 | 131 | |
|
132 | 132 | In [9]: cd mydir |
|
133 | 133 | /home/fperez/mydir |
|
134 | 134 | |
|
135 | 135 | Note that cell magics *always* require an explicit ``%%`` prefix, automagic |
|
136 | 136 | calling only works for line magics. |
|
137 | 137 | |
|
138 | 138 | The automagic system has the lowest possible precedence in name searches, so |
|
139 | 139 | defining an identifier with the same name as an existing magic function will |
|
140 | 140 | shadow it for automagic use. You can still access the shadowed magic function |
|
141 | 141 | by explicitly using the ``%`` character at the beginning of the line. |
|
142 | 142 | |
|
143 | 143 | An example (with automagic on) should clarify all this: |
|
144 | 144 | |
|
145 | 145 | .. sourcecode:: ipython |
|
146 | 146 | |
|
147 | 147 | In [1]: cd ipython # %cd is called by automagic |
|
148 | 148 | /home/fperez/ipython |
|
149 | 149 | |
|
150 | 150 | In [2]: cd=1 # now cd is just a variable |
|
151 | 151 | |
|
152 | 152 | In [3]: cd .. # and doesn't work as a function anymore |
|
153 | 153 | File "<ipython-input-3-9fedb3aff56c>", line 1 |
|
154 | 154 | cd .. |
|
155 | 155 | ^ |
|
156 | 156 | SyntaxError: invalid syntax |
|
157 | 157 | |
|
158 | 158 | |
|
159 | 159 | In [4]: %cd .. # but %cd always works |
|
160 | 160 | /home/fperez |
|
161 | 161 | |
|
162 | 162 | In [5]: del cd # if you remove the cd variable, automagic works again |
|
163 | 163 | |
|
164 | 164 | In [6]: cd ipython |
|
165 | 165 | |
|
166 | 166 | /home/fperez/ipython |
|
167 | 167 | |
|
168 | 168 | Defining your own magics |
|
169 | ~~~~~~~~~~~~~~~~~~~~~~~~ | |
|
169 | ++++++++++++++++++++++++ | |
|
170 | 170 | |
|
171 | 171 | There are two main ways to define your own magic functions: from standalone |
|
172 | 172 | functions and by inheriting from a base class provided by IPython: |
|
173 | 173 | :class:`IPython.core.magic.Magics`. Below we show code you can place in a file |
|
174 | 174 | that you load from your configuration, such as any file in the ``startup`` |
|
175 | 175 | subdirectory of your default IPython profile. |
|
176 | 176 | |
|
177 | 177 | First, let us see the simplest case. The following shows how to create a line |
|
178 | 178 | magic, a cell one and one that works in both modes, using just plain functions: |
|
179 | 179 | |
|
180 | 180 | .. sourcecode:: python |
|
181 | 181 | |
|
182 | 182 | from IPython.core.magic import (register_line_magic, register_cell_magic, |
|
183 | 183 | register_line_cell_magic) |
|
184 | 184 | |
|
185 | 185 | @register_line_magic |
|
186 | 186 | def lmagic(line): |
|
187 | 187 | "my line magic" |
|
188 | 188 | return line |
|
189 | 189 | |
|
190 | 190 | @register_cell_magic |
|
191 | 191 | def cmagic(line, cell): |
|
192 | 192 | "my cell magic" |
|
193 | 193 | return line, cell |
|
194 | 194 | |
|
195 | 195 | @register_line_cell_magic |
|
196 | 196 | def lcmagic(line, cell=None): |
|
197 | 197 | "Magic that works both as %lcmagic and as %%lcmagic" |
|
198 | 198 | if cell is None: |
|
199 | 199 | print "Called as line magic" |
|
200 | 200 | return line |
|
201 | 201 | else: |
|
202 | 202 | print "Called as cell magic" |
|
203 | 203 | return line, cell |
|
204 | 204 | |
|
205 | 205 | # We delete these to avoid name conflicts for automagic to work |
|
206 | 206 | del lmagic, lcmagic |
|
207 | 207 | |
|
208 | 208 | |
|
209 | 209 | You can also create magics of all three kinds by inheriting from the |
|
210 | 210 | :class:`IPython.core.magic.Magics` class. This lets you create magics that can |
|
211 | 211 | potentially hold state in between calls, and that have full access to the main |
|
212 | 212 | IPython object: |
|
213 | 213 | |
|
214 | 214 | .. sourcecode:: python |
|
215 | 215 | |
|
216 | 216 | # This code can be put in any Python module, it does not require IPython |
|
217 | 217 | # itself to be running already. It only creates the magics subclass but |
|
218 | 218 | # doesn't instantiate it yet. |
|
219 | 219 | from IPython.core.magic import (Magics, magics_class, line_magic, |
|
220 | 220 | cell_magic, line_cell_magic) |
|
221 | 221 | |
|
222 | 222 | # The class MUST call this class decorator at creation time |
|
223 | 223 | @magics_class |
|
224 | 224 | class MyMagics(Magics): |
|
225 | 225 | |
|
226 | 226 | @line_magic |
|
227 | 227 | def lmagic(self, line): |
|
228 | 228 | "my line magic" |
|
229 | 229 | print "Full access to the main IPython object:", self.shell |
|
230 | 230 | print "Variables in the user namespace:", self.shell.user_ns.keys() |
|
231 | 231 | return line |
|
232 | 232 | |
|
233 | 233 | @cell_magic |
|
234 | 234 | def cmagic(self, line, cell): |
|
235 | 235 | "my cell magic" |
|
236 | 236 | return line, cell |
|
237 | 237 | |
|
238 | 238 | @line_cell_magic |
|
239 | 239 | def lcmagic(self, line, cell=None): |
|
240 | 240 | "Magic that works both as %lcmagic and as %%lcmagic" |
|
241 | 241 | if cell is None: |
|
242 | 242 | print "Called as line magic" |
|
243 | 243 | return line |
|
244 | 244 | else: |
|
245 | 245 | print "Called as cell magic" |
|
246 | 246 | return line, cell |
|
247 | 247 | |
|
248 | 248 | |
|
249 | 249 | # In order to actually use these magics, you must register them with a |
|
250 | 250 | # running IPython. This code must be placed in a file that is loaded once |
|
251 | 251 | # IPython is up and running: |
|
252 | 252 | ip = get_ipython() |
|
253 | 253 | # You can register the class itself without instantiating it. IPython will |
|
254 | 254 | # call the default constructor on it. |
|
255 | 255 | ip.register_magics(MyMagics) |
|
256 | 256 | |
|
257 | 257 | If you want to create a class with a different constructor that holds |
|
258 | 258 | additional state, then you should always call the parent constructor and |
|
259 | 259 | instantiate the class yourself before registration: |
|
260 | 260 | |
|
261 | 261 | .. sourcecode:: python |
|
262 | 262 | |
|
263 | 263 | @magics_class |
|
264 | 264 | class StatefulMagics(Magics): |
|
265 | 265 | "Magics that hold additional state" |
|
266 | 266 | |
|
267 | 267 | def __init__(self, shell, data): |
|
268 | 268 | # You must call the parent constructor |
|
269 | 269 | super(StatefulMagics, self).__init__(shell) |
|
270 | 270 | self.data = data |
|
271 | 271 | |
|
272 | 272 | # etc... |
|
273 | 273 | |
|
274 | 274 | # This class must then be registered with a manually created instance, |
|
275 | 275 | # since its constructor has different arguments from the default: |
|
276 | 276 | ip = get_ipython() |
|
277 | 277 | magics = StatefulMagics(ip, some_data) |
|
278 | 278 | ip.register_magics(magics) |
|
279 | 279 | |
|
280 | 280 | |
|
281 | 281 | In earlier versions, IPython had an API for the creation of line magics (cell |
|
282 | 282 | magics did not exist at the time) that required you to create functions with a |
|
283 | 283 | method-looking signature and to manually pass both the function and the name. |
|
284 | 284 | While this API is no longer recommended, it remains indefinitely supported for |
|
285 | 285 | backwards compatibility purposes. With the old API, you'd create a magic as |
|
286 | 286 | follows: |
|
287 | 287 | |
|
288 | 288 | .. sourcecode:: python |
|
289 | 289 | |
|
290 | 290 | def func(self, line): |
|
291 | 291 | print "Line magic called with line:", line |
|
292 | 292 | print "IPython object:", self.shell |
|
293 | 293 | |
|
294 | 294 | ip = get_ipython() |
|
295 | 295 | # Declare this function as the magic %mycommand |
|
296 | 296 | ip.define_magic('mycommand', func) |
|
297 | 297 | |
|
298 | 298 | Type ``%magic`` for more information, including a list of all available magic |
|
299 | 299 | functions at any time and their docstrings. You can also type |
|
300 | 300 | ``%magic_function_name?`` (see :ref:`below <dynamic_object_info>` for |
|
301 | 301 | information on the '?' system) to get information about any particular magic |
|
302 | 302 | function you are interested in. |
|
303 | 303 | |
|
304 | 304 | The API documentation for the :mod:`IPython.core.magic` module contains the full |
|
305 | 305 | docstrings of all currently available magic commands. |
|
306 | 306 | |
|
307 | 307 | |
|
308 | 308 | Access to the standard Python help |
|
309 | 309 | ---------------------------------- |
|
310 | 310 | |
|
311 | 311 | Simply type ``help()`` to access Python's standard help system. You can |
|
312 | 312 | also type ``help(object)`` for information about a given object, or |
|
313 | 313 | ``help('keyword')`` for information on a keyword. You may need to configure your |
|
314 | 314 | PYTHONDOCS environment variable for this feature to work correctly. |
|
315 | 315 | |
|
316 | 316 | .. _dynamic_object_info: |
|
317 | 317 | |
|
318 | 318 | Dynamic object information |
|
319 | 319 | -------------------------- |
|
320 | 320 | |
|
321 | 321 | Typing ``?word`` or ``word?`` prints detailed information about an object. If |
|
322 | 322 | certain strings in the object are too long (e.g. function signatures) they get |
|
323 | 323 | snipped in the center for brevity. This system gives access variable types and |
|
324 | 324 | values, docstrings, function prototypes and other useful information. |
|
325 | 325 | |
|
326 | 326 | If the information will not fit in the terminal, it is displayed in a pager |
|
327 | 327 | (``less`` if available, otherwise a basic internal pager). |
|
328 | 328 | |
|
329 | 329 | Typing ``??word`` or ``word??`` gives access to the full information, including |
|
330 | 330 | the source code where possible. Long strings are not snipped. |
|
331 | 331 | |
|
332 | 332 | The following magic functions are particularly useful for gathering |
|
333 | 333 | information about your working environment. You can get more details by |
|
334 | 334 | typing ``%magic`` or querying them individually (``%function_name?``); |
|
335 | 335 | this is just a summary: |
|
336 | 336 | |
|
337 | 337 | * **%pdoc <object>**: Print (or run through a pager if too long) the |
|
338 | 338 | docstring for an object. If the given object is a class, it will |
|
339 | 339 | print both the class and the constructor docstrings. |
|
340 | 340 | * **%pdef <object>**: Print the call signature for any callable |
|
341 | 341 | object. If the object is a class, print the constructor information. |
|
342 | 342 | * **%psource <object>**: Print (or run through a pager if too long) |
|
343 | 343 | the source code for an object. |
|
344 | 344 | * **%pfile <object>**: Show the entire source file where an object was |
|
345 | 345 | defined via a pager, opening it at the line where the object |
|
346 | 346 | definition begins. |
|
347 | 347 | * **%who/%whos**: These functions give information about identifiers |
|
348 | 348 | you have defined interactively (not things you loaded or defined |
|
349 | 349 | in your configuration files). %who just prints a list of |
|
350 | 350 | identifiers and %whos prints a table with some basic details about |
|
351 | 351 | each identifier. |
|
352 | 352 | |
|
353 | 353 | Note that the dynamic object information functions (?/??, ``%pdoc``, |
|
354 | 354 | ``%pfile``, ``%pdef``, ``%psource``) work on object attributes, as well as |
|
355 | 355 | directly on variables. For example, after doing ``import os``, you can use |
|
356 | 356 | ``os.path.abspath??``. |
|
357 | 357 | |
|
358 | 358 | .. _readline: |
|
359 | 359 | |
|
360 | 360 | Readline-based features |
|
361 | 361 | ----------------------- |
|
362 | 362 | |
|
363 | 363 | These features require the GNU readline library, so they won't work if your |
|
364 | 364 | Python installation lacks readline support. We will first describe the default |
|
365 | 365 | behavior IPython uses, and then how to change it to suit your preferences. |
|
366 | 366 | |
|
367 | 367 | |
|
368 | 368 | Command line completion |
|
369 | 369 | +++++++++++++++++++++++ |
|
370 | 370 | |
|
371 | 371 | At any time, hitting TAB will complete any available python commands or |
|
372 | 372 | variable names, and show you a list of the possible completions if |
|
373 | 373 | there's no unambiguous one. It will also complete filenames in the |
|
374 | 374 | current directory if no python names match what you've typed so far. |
|
375 | 375 | |
|
376 | 376 | |
|
377 | 377 | Search command history |
|
378 | 378 | ++++++++++++++++++++++ |
|
379 | 379 | |
|
380 | 380 | IPython provides two ways for searching through previous input and thus |
|
381 | 381 | reduce the need for repetitive typing: |
|
382 | 382 | |
|
383 | 383 | 1. Start typing, and then use Ctrl-p (previous,up) and Ctrl-n |
|
384 | 384 | (next,down) to search through only the history items that match |
|
385 | 385 | what you've typed so far. If you use Ctrl-p/Ctrl-n at a blank |
|
386 | 386 | prompt, they just behave like normal arrow keys. |
|
387 | 387 | 2. Hit Ctrl-r: opens a search prompt. Begin typing and the system |
|
388 | 388 | searches your history for lines that contain what you've typed so |
|
389 | 389 | far, completing as much as it can. |
|
390 | 390 | |
|
391 | 391 | |
|
392 | 392 | Persistent command history across sessions |
|
393 | 393 | ++++++++++++++++++++++++++++++++++++++++++ |
|
394 | 394 | |
|
395 | 395 | IPython will save your input history when it leaves and reload it next |
|
396 | 396 | time you restart it. By default, the history file is named |
|
397 | 397 | $IPYTHONDIR/profile_<name>/history.sqlite. This allows you to keep |
|
398 | 398 | separate histories related to various tasks: commands related to |
|
399 | 399 | numerical work will not be clobbered by a system shell history, for |
|
400 | 400 | example. |
|
401 | 401 | |
|
402 | 402 | |
|
403 | 403 | Autoindent |
|
404 | 404 | ++++++++++ |
|
405 | 405 | |
|
406 | 406 | IPython can recognize lines ending in ':' and indent the next line, |
|
407 | 407 | while also un-indenting automatically after 'raise' or 'return'. |
|
408 | 408 | |
|
409 | 409 | This feature uses the readline library, so it will honor your |
|
410 | 410 | :file:`~/.inputrc` configuration (or whatever file your INPUTRC variable points |
|
411 | 411 | to). Adding the following lines to your :file:`.inputrc` file can make |
|
412 | 412 | indenting/unindenting more convenient (M-i indents, M-u unindents):: |
|
413 | 413 | |
|
414 | 414 | $if Python |
|
415 | 415 | "\M-i": " " |
|
416 | 416 | "\M-u": "\d\d\d\d" |
|
417 | 417 | $endif |
|
418 | 418 | |
|
419 | 419 | Note that there are 4 spaces between the quote marks after "M-i" above. |
|
420 | 420 | |
|
421 | 421 | .. warning:: |
|
422 | 422 | |
|
423 | 423 | Setting the above indents will cause problems with unicode text entry in |
|
424 | 424 | the terminal. |
|
425 | 425 | |
|
426 | 426 | .. warning:: |
|
427 | 427 | |
|
428 | 428 | Autoindent is ON by default, but it can cause problems with the pasting of |
|
429 | 429 | multi-line indented code (the pasted code gets re-indented on each line). A |
|
430 | 430 | magic function %autoindent allows you to toggle it on/off at runtime. You |
|
431 | 431 | can also disable it permanently on in your :file:`ipython_config.py` file |
|
432 | 432 | (set TerminalInteractiveShell.autoindent=False). |
|
433 | 433 | |
|
434 | 434 | If you want to paste multiple lines in the terminal, it is recommended that |
|
435 | 435 | you use ``%paste``. |
|
436 | 436 | |
|
437 | 437 | |
|
438 | 438 | Customizing readline behavior |
|
439 | 439 | +++++++++++++++++++++++++++++ |
|
440 | 440 | |
|
441 | 441 | All these features are based on the GNU readline library, which has an |
|
442 | 442 | extremely customizable interface. Normally, readline is configured via a |
|
443 | 443 | file which defines the behavior of the library; the details of the |
|
444 | 444 | syntax for this can be found in the readline documentation available |
|
445 | 445 | with your system or on the Internet. IPython doesn't read this file (if |
|
446 | 446 | it exists) directly, but it does support passing to readline valid |
|
447 | 447 | options via a simple interface. In brief, you can customize readline by |
|
448 | 448 | setting the following options in your configuration file (note |
|
449 | 449 | that these options can not be specified at the command line): |
|
450 | 450 | |
|
451 | 451 | * **readline_parse_and_bind**: this holds a list of strings to be executed |
|
452 | 452 | via a readline.parse_and_bind() command. The syntax for valid commands |
|
453 | 453 | of this kind can be found by reading the documentation for the GNU |
|
454 | 454 | readline library, as these commands are of the kind which readline |
|
455 | 455 | accepts in its configuration file. |
|
456 | 456 | * **readline_remove_delims**: a string of characters to be removed |
|
457 | 457 | from the default word-delimiters list used by readline, so that |
|
458 | 458 | completions may be performed on strings which contain them. Do not |
|
459 | 459 | change the default value unless you know what you're doing. |
|
460 | 460 | |
|
461 | 461 | You will find the default values in your configuration file. |
|
462 | 462 | |
|
463 | 463 | |
|
464 | 464 | Session logging and restoring |
|
465 | 465 | ----------------------------- |
|
466 | 466 | |
|
467 | 467 | You can log all input from a session either by starting IPython with the |
|
468 | 468 | command line switch ``--logfile=foo.py`` (see :ref:`here <command_line_options>`) |
|
469 | 469 | or by activating the logging at any moment with the magic function %logstart. |
|
470 | 470 | |
|
471 | 471 | Log files can later be reloaded by running them as scripts and IPython |
|
472 | 472 | will attempt to 'replay' the log by executing all the lines in it, thus |
|
473 | 473 | restoring the state of a previous session. This feature is not quite |
|
474 | 474 | perfect, but can still be useful in many cases. |
|
475 | 475 | |
|
476 | 476 | The log files can also be used as a way to have a permanent record of |
|
477 | 477 | any code you wrote while experimenting. Log files are regular text files |
|
478 | 478 | which you can later open in your favorite text editor to extract code or |
|
479 | 479 | to 'clean them up' before using them to replay a session. |
|
480 | 480 | |
|
481 | 481 | The `%logstart` function for activating logging in mid-session is used as |
|
482 | 482 | follows:: |
|
483 | 483 | |
|
484 | 484 | %logstart [log_name [log_mode]] |
|
485 | 485 | |
|
486 | 486 | If no name is given, it defaults to a file named 'ipython_log.py' in your |
|
487 | 487 | current working directory, in 'rotate' mode (see below). |
|
488 | 488 | |
|
489 | 489 | '%logstart name' saves to file 'name' in 'backup' mode. It saves your |
|
490 | 490 | history up to that point and then continues logging. |
|
491 | 491 | |
|
492 | 492 | %logstart takes a second optional parameter: logging mode. This can be |
|
493 | 493 | one of (note that the modes are given unquoted): |
|
494 | 494 | |
|
495 | 495 | * [over:] overwrite existing log_name. |
|
496 | 496 | * [backup:] rename (if exists) to log_name~ and start log_name. |
|
497 | 497 | * [append:] well, that says it. |
|
498 | 498 | * [rotate:] create rotating logs log_name.1~, log_name.2~, etc. |
|
499 | 499 | |
|
500 | 500 | The %logoff and %logon functions allow you to temporarily stop and |
|
501 | 501 | resume logging to a file which had previously been started with |
|
502 | 502 | %logstart. They will fail (with an explanation) if you try to use them |
|
503 | 503 | before logging has been started. |
|
504 | 504 | |
|
505 | 505 | .. _system_shell_access: |
|
506 | 506 | |
|
507 | 507 | System shell access |
|
508 | 508 | ------------------- |
|
509 | 509 | |
|
510 | 510 | Any input line beginning with a ! character is passed verbatim (minus |
|
511 | 511 | the !, of course) to the underlying operating system. For example, |
|
512 | 512 | typing ``!ls`` will run 'ls' in the current directory. |
|
513 | 513 | |
|
514 | 514 | Manual capture of command output |
|
515 | 515 | -------------------------------- |
|
516 | 516 | |
|
517 | 517 | You can assign the result of a system command to a Python variable with the |
|
518 | 518 | syntax ``myfiles = !ls``. This gets machine readable output from stdout |
|
519 | 519 | (e.g. without colours), and splits on newlines. To explicitly get this sort of |
|
520 | 520 | output without assigning to a variable, use two exclamation marks (``!!ls``) or |
|
521 | 521 | the ``%sx`` magic command. |
|
522 | 522 | |
|
523 | 523 | The captured list has some convenience features. ``myfiles.n`` or ``myfiles.s`` |
|
524 | 524 | returns a string delimited by newlines or spaces, respectively. ``myfiles.p`` |
|
525 | 525 | produces `path objects <http://pypi.python.org/pypi/path.py>`_ from the list items. |
|
526 | 526 | See :ref:`string_lists` for details. |
|
527 | 527 | |
|
528 | 528 | IPython also allows you to expand the value of python variables when |
|
529 | 529 | making system calls. Wrap variables or expressions in {braces}:: |
|
530 | 530 | |
|
531 | 531 | In [1]: pyvar = 'Hello world' |
|
532 | 532 | In [2]: !echo "A python variable: {pyvar}" |
|
533 | 533 | A python variable: Hello world |
|
534 | 534 | In [3]: import math |
|
535 | 535 | In [4]: x = 8 |
|
536 | 536 | In [5]: !echo {math.factorial(x)} |
|
537 | 537 | 40320 |
|
538 | 538 | |
|
539 | 539 | For simple cases, you can alternatively prepend $ to a variable name:: |
|
540 | 540 | |
|
541 | 541 | In [6]: !echo $sys.argv |
|
542 | 542 | [/home/fperez/usr/bin/ipython] |
|
543 | 543 | In [7]: !echo "A system variable: $$HOME" # Use $$ for literal $ |
|
544 | 544 | A system variable: /home/fperez |
|
545 | 545 | |
|
546 | 546 | System command aliases |
|
547 | 547 | ---------------------- |
|
548 | 548 | |
|
549 | 549 | The %alias magic function allows you to define magic functions which are in fact |
|
550 | 550 | system shell commands. These aliases can have parameters. |
|
551 | 551 | |
|
552 | 552 | ``%alias alias_name cmd`` defines 'alias_name' as an alias for 'cmd' |
|
553 | 553 | |
|
554 | 554 | Then, typing ``alias_name params`` will execute the system command 'cmd |
|
555 | 555 | params' (from your underlying operating system). |
|
556 | 556 | |
|
557 | 557 | You can also define aliases with parameters using %s specifiers (one per |
|
558 | 558 | parameter). The following example defines the parts function as an |
|
559 | 559 | alias to the command 'echo first %s second %s' where each %s will be |
|
560 | 560 | replaced by a positional parameter to the call to %parts:: |
|
561 | 561 | |
|
562 | 562 | In [1]: %alias parts echo first %s second %s |
|
563 | 563 | In [2]: parts A B |
|
564 | 564 | first A second B |
|
565 | 565 | In [3]: parts A |
|
566 | 566 | ERROR: Alias <parts> requires 2 arguments, 1 given. |
|
567 | 567 | |
|
568 | 568 | If called with no parameters, %alias prints the table of currently |
|
569 | 569 | defined aliases. |
|
570 | 570 | |
|
571 | 571 | The %rehashx magic allows you to load your entire $PATH as |
|
572 | 572 | ipython aliases. See its docstring for further details. |
|
573 | 573 | |
|
574 | 574 | |
|
575 | 575 | .. _dreload: |
|
576 | 576 | |
|
577 | 577 | Recursive reload |
|
578 | 578 | ---------------- |
|
579 | 579 | |
|
580 | 580 | The :mod:`IPython.lib.deepreload` module allows you to recursively reload a |
|
581 | 581 | module: changes made to any of its dependencies will be reloaded without |
|
582 | 582 | having to exit. To start using it, do:: |
|
583 | 583 | |
|
584 | 584 | from IPython.lib.deepreload import reload as dreload |
|
585 | 585 | |
|
586 | 586 | |
|
587 | 587 | Verbose and colored exception traceback printouts |
|
588 | 588 | ------------------------------------------------- |
|
589 | 589 | |
|
590 | 590 | IPython provides the option to see very detailed exception tracebacks, |
|
591 | 591 | which can be especially useful when debugging large programs. You can |
|
592 | 592 | run any Python file with the %run function to benefit from these |
|
593 | 593 | detailed tracebacks. Furthermore, both normal and verbose tracebacks can |
|
594 | 594 | be colored (if your terminal supports it) which makes them much easier |
|
595 | 595 | to parse visually. |
|
596 | 596 | |
|
597 | 597 | See the magic xmode and colors functions for details (just type %magic). |
|
598 | 598 | |
|
599 | 599 | These features are basically a terminal version of Ka-Ping Yee's cgitb |
|
600 | 600 | module, now part of the standard Python library. |
|
601 | 601 | |
|
602 | 602 | |
|
603 | 603 | .. _input_caching: |
|
604 | 604 | |
|
605 | 605 | Input caching system |
|
606 | 606 | -------------------- |
|
607 | 607 | |
|
608 | 608 | IPython offers numbered prompts (In/Out) with input and output caching |
|
609 | 609 | (also referred to as 'input history'). All input is saved and can be |
|
610 | 610 | retrieved as variables (besides the usual arrow key recall), in |
|
611 | 611 | addition to the %rep magic command that brings a history entry |
|
612 | 612 | up for editing on the next command line. |
|
613 | 613 | |
|
614 | 614 | The following GLOBAL variables always exist (so don't overwrite them!): |
|
615 | 615 | |
|
616 | 616 | * _i, _ii, _iii: store previous, next previous and next-next previous inputs. |
|
617 | 617 | * In, _ih : a list of all inputs; _ih[n] is the input from line n. If you |
|
618 | 618 | overwrite In with a variable of your own, you can remake the assignment to the |
|
619 | 619 | internal list with a simple ``In=_ih``. |
|
620 | 620 | |
|
621 | 621 | Additionally, global variables named _i<n> are dynamically created (<n> |
|
622 | 622 | being the prompt counter), so ``_i<n> == _ih[<n>] == In[<n>]``. |
|
623 | 623 | |
|
624 | 624 | For example, what you typed at prompt 14 is available as _i14, _ih[14] |
|
625 | 625 | and In[14]. |
|
626 | 626 | |
|
627 | 627 | This allows you to easily cut and paste multi line interactive prompts |
|
628 | 628 | by printing them out: they print like a clean string, without prompt |
|
629 | 629 | characters. You can also manipulate them like regular variables (they |
|
630 | 630 | are strings), modify or exec them (typing ``exec _i9`` will re-execute the |
|
631 | 631 | contents of input prompt 9. |
|
632 | 632 | |
|
633 | 633 | You can also re-execute multiple lines of input easily by using the |
|
634 | 634 | magic %rerun or %macro functions. The macro system also allows you to re-execute |
|
635 | 635 | previous lines which include magic function calls (which require special |
|
636 | 636 | processing). Type %macro? for more details on the macro system. |
|
637 | 637 | |
|
638 | 638 | A history function %hist allows you to see any part of your input |
|
639 | 639 | history by printing a range of the _i variables. |
|
640 | 640 | |
|
641 | 641 | You can also search ('grep') through your history by typing |
|
642 | 642 | ``%hist -g somestring``. This is handy for searching for URLs, IP addresses, |
|
643 | 643 | etc. You can bring history entries listed by '%hist -g' up for editing |
|
644 | 644 | with the %recall command, or run them immediately with %rerun. |
|
645 | 645 | |
|
646 | 646 | .. _output_caching: |
|
647 | 647 | |
|
648 | 648 | Output caching system |
|
649 | 649 | --------------------- |
|
650 | 650 | |
|
651 | 651 | For output that is returned from actions, a system similar to the input |
|
652 | 652 | cache exists but using _ instead of _i. Only actions that produce a |
|
653 | 653 | result (NOT assignments, for example) are cached. If you are familiar |
|
654 | 654 | with Mathematica, IPython's _ variables behave exactly like |
|
655 | 655 | Mathematica's % variables. |
|
656 | 656 | |
|
657 | 657 | The following GLOBAL variables always exist (so don't overwrite them!): |
|
658 | 658 | |
|
659 | 659 | * [_] (a single underscore) : stores previous output, like Python's |
|
660 | 660 | default interpreter. |
|
661 | 661 | * [__] (two underscores): next previous. |
|
662 | 662 | * [___] (three underscores): next-next previous. |
|
663 | 663 | |
|
664 | 664 | Additionally, global variables named _<n> are dynamically created (<n> |
|
665 | 665 | being the prompt counter), such that the result of output <n> is always |
|
666 | 666 | available as _<n> (don't use the angle brackets, just the number, e.g. |
|
667 | 667 | _21). |
|
668 | 668 | |
|
669 | 669 | These variables are also stored in a global dictionary (not a |
|
670 | 670 | list, since it only has entries for lines which returned a result) |
|
671 | 671 | available under the names _oh and Out (similar to _ih and In). So the |
|
672 | 672 | output from line 12 can be obtained as _12, Out[12] or _oh[12]. If you |
|
673 | 673 | accidentally overwrite the Out variable you can recover it by typing |
|
674 | 674 | 'Out=_oh' at the prompt. |
|
675 | 675 | |
|
676 | 676 | This system obviously can potentially put heavy memory demands on your |
|
677 | 677 | system, since it prevents Python's garbage collector from removing any |
|
678 | 678 | previously computed results. You can control how many results are kept |
|
679 | 679 | in memory with the option (at the command line or in your configuration |
|
680 | 680 | file) cache_size. If you set it to 0, the whole system is completely |
|
681 | 681 | disabled and the prompts revert to the classic '>>>' of normal Python. |
|
682 | 682 | |
|
683 | 683 | |
|
684 | 684 | Directory history |
|
685 | 685 | ----------------- |
|
686 | 686 | |
|
687 | 687 | Your history of visited directories is kept in the global list _dh, and |
|
688 | 688 | the magic %cd command can be used to go to any entry in that list. The |
|
689 | 689 | %dhist command allows you to view this history. Do ``cd -<TAB>`` to |
|
690 | 690 | conveniently view the directory history. |
|
691 | 691 | |
|
692 | 692 | |
|
693 | 693 | Automatic parentheses and quotes |
|
694 | 694 | -------------------------------- |
|
695 | 695 | |
|
696 | 696 | These features were adapted from Nathan Gray's LazyPython. They are |
|
697 | 697 | meant to allow less typing for common situations. |
|
698 | 698 | |
|
699 | 699 | |
|
700 | 700 | Automatic parentheses |
|
701 | 701 | +++++++++++++++++++++ |
|
702 | 702 | |
|
703 | 703 | Callable objects (i.e. functions, methods, etc) can be invoked like this |
|
704 | 704 | (notice the commas between the arguments):: |
|
705 | 705 | |
|
706 | 706 | In [1]: callable_ob arg1, arg2, arg3 |
|
707 | 707 | ------> callable_ob(arg1, arg2, arg3) |
|
708 | 708 | |
|
709 | 709 | You can force automatic parentheses by using '/' as the first character |
|
710 | 710 | of a line. For example:: |
|
711 | 711 | |
|
712 | 712 | In [2]: /globals # becomes 'globals()' |
|
713 | 713 | |
|
714 | 714 | Note that the '/' MUST be the first character on the line! This won't work:: |
|
715 | 715 | |
|
716 | 716 | In [3]: print /globals # syntax error |
|
717 | 717 | |
|
718 | 718 | In most cases the automatic algorithm should work, so you should rarely |
|
719 | 719 | need to explicitly invoke /. One notable exception is if you are trying |
|
720 | 720 | to call a function with a list of tuples as arguments (the parenthesis |
|
721 | 721 | will confuse IPython):: |
|
722 | 722 | |
|
723 | 723 | In [4]: zip (1,2,3),(4,5,6) # won't work |
|
724 | 724 | |
|
725 | 725 | but this will work:: |
|
726 | 726 | |
|
727 | 727 | In [5]: /zip (1,2,3),(4,5,6) |
|
728 | 728 | ------> zip ((1,2,3),(4,5,6)) |
|
729 | 729 | Out[5]: [(1, 4), (2, 5), (3, 6)] |
|
730 | 730 | |
|
731 | 731 | IPython tells you that it has altered your command line by displaying |
|
732 | 732 | the new command line preceded by ->. e.g.:: |
|
733 | 733 | |
|
734 | 734 | In [6]: callable list |
|
735 | 735 | ------> callable(list) |
|
736 | 736 | |
|
737 | 737 | |
|
738 | 738 | Automatic quoting |
|
739 | 739 | +++++++++++++++++ |
|
740 | 740 | |
|
741 | 741 | You can force automatic quoting of a function's arguments by using ',' |
|
742 | 742 | or ';' as the first character of a line. For example:: |
|
743 | 743 | |
|
744 | 744 | In [1]: ,my_function /home/me # becomes my_function("/home/me") |
|
745 | 745 | |
|
746 | 746 | If you use ';' the whole argument is quoted as a single string, while ',' splits |
|
747 | 747 | on whitespace:: |
|
748 | 748 | |
|
749 | 749 | In [2]: ,my_function a b c # becomes my_function("a","b","c") |
|
750 | 750 | |
|
751 | 751 | In [3]: ;my_function a b c # becomes my_function("a b c") |
|
752 | 752 | |
|
753 | 753 | Note that the ',' or ';' MUST be the first character on the line! This |
|
754 | 754 | won't work:: |
|
755 | 755 | |
|
756 | 756 | In [4]: x = ,my_function /home/me # syntax error |
|
757 | 757 | |
|
758 | 758 | IPython as your default Python environment |
|
759 | 759 | ========================================== |
|
760 | 760 | |
|
761 | 761 | Python honors the environment variable PYTHONSTARTUP and will execute at |
|
762 | 762 | startup the file referenced by this variable. If you put the following code at |
|
763 | 763 | the end of that file, then IPython will be your working environment anytime you |
|
764 | 764 | start Python:: |
|
765 | 765 | |
|
766 | 766 | from IPython.frontend.terminal.ipapp import launch_new_instance |
|
767 | 767 | launch_new_instance() |
|
768 | 768 | raise SystemExit |
|
769 | 769 | |
|
770 | 770 | The ``raise SystemExit`` is needed to exit Python when |
|
771 | 771 | it finishes, otherwise you'll be back at the normal Python '>>>' |
|
772 | 772 | prompt. |
|
773 | 773 | |
|
774 | 774 | This is probably useful to developers who manage multiple Python |
|
775 | 775 | versions and don't want to have correspondingly multiple IPython |
|
776 | 776 | versions. Note that in this mode, there is no way to pass IPython any |
|
777 | 777 | command-line options, as those are trapped first by Python itself. |
|
778 | 778 | |
|
779 | 779 | .. _Embedding: |
|
780 | 780 | |
|
781 | 781 | Embedding IPython |
|
782 | 782 | ================= |
|
783 | 783 | |
|
784 | 784 | It is possible to start an IPython instance inside your own Python |
|
785 | 785 | programs. This allows you to evaluate dynamically the state of your |
|
786 | 786 | code, operate with your variables, analyze them, etc. Note however that |
|
787 | 787 | any changes you make to values while in the shell do not propagate back |
|
788 | 788 | to the running code, so it is safe to modify your values because you |
|
789 | 789 | won't break your code in bizarre ways by doing so. |
|
790 | 790 | |
|
791 | 791 | .. note:: |
|
792 | 792 | |
|
793 | 793 | At present, trying to embed IPython from inside IPython causes problems. Run |
|
794 | 794 | the code samples below outside IPython. |
|
795 | 795 | |
|
796 | 796 | This feature allows you to easily have a fully functional python |
|
797 | 797 | environment for doing object introspection anywhere in your code with a |
|
798 | 798 | simple function call. In some cases a simple print statement is enough, |
|
799 | 799 | but if you need to do more detailed analysis of a code fragment this |
|
800 | 800 | feature can be very valuable. |
|
801 | 801 | |
|
802 | 802 | It can also be useful in scientific computing situations where it is |
|
803 | 803 | common to need to do some automatic, computationally intensive part and |
|
804 | 804 | then stop to look at data, plots, etc. |
|
805 | 805 | Opening an IPython instance will give you full access to your data and |
|
806 | 806 | functions, and you can resume program execution once you are done with |
|
807 | 807 | the interactive part (perhaps to stop again later, as many times as |
|
808 | 808 | needed). |
|
809 | 809 | |
|
810 | 810 | The following code snippet is the bare minimum you need to include in |
|
811 | 811 | your Python programs for this to work (detailed examples follow later):: |
|
812 | 812 | |
|
813 | 813 | from IPython import embed |
|
814 | 814 | |
|
815 | 815 | embed() # this call anywhere in your program will start IPython |
|
816 | 816 | |
|
817 | 817 | .. note:: |
|
818 | 818 | |
|
819 | 819 | As of 0.13, you can embed an IPython *kernel*, for use with qtconsole, |
|
820 | 820 | etc. via ``IPython.embed_kernel()`` instead of ``IPython.embed()``. |
|
821 | 821 | It should function just the same as regular embed, but you connect |
|
822 | 822 | an external frontend rather than IPython starting up in the local |
|
823 | 823 | terminal. |
|
824 | 824 | |
|
825 | 825 | You can run embedded instances even in code which is itself being run at |
|
826 | 826 | the IPython interactive prompt with '%run <filename>'. Since it's easy |
|
827 | 827 | to get lost as to where you are (in your top-level IPython or in your |
|
828 | 828 | embedded one), it's a good idea in such cases to set the in/out prompts |
|
829 | 829 | to something different for the embedded instances. The code examples |
|
830 | 830 | below illustrate this. |
|
831 | 831 | |
|
832 | 832 | You can also have multiple IPython instances in your program and open |
|
833 | 833 | them separately, for example with different options for data |
|
834 | 834 | presentation. If you close and open the same instance multiple times, |
|
835 | 835 | its prompt counters simply continue from each execution to the next. |
|
836 | 836 | |
|
837 | 837 | Please look at the docstrings in the :mod:`~IPython.frontend.terminal.embed` |
|
838 | 838 | module for more details on the use of this system. |
|
839 | 839 | |
|
840 | 840 | The following sample file illustrating how to use the embedding |
|
841 | 841 | functionality is provided in the examples directory as example-embed.py. |
|
842 | 842 | It should be fairly self-explanatory: |
|
843 | 843 | |
|
844 | 844 | .. literalinclude:: ../../../examples/core/example-embed.py |
|
845 | 845 | :language: python |
|
846 | 846 | |
|
847 | 847 | Once you understand how the system functions, you can use the following |
|
848 | 848 | code fragments in your programs which are ready for cut and paste: |
|
849 | 849 | |
|
850 | 850 | .. literalinclude:: ../../../examples/core/example-embed-short.py |
|
851 | 851 | :language: python |
|
852 | 852 | |
|
853 | 853 | Using the Python debugger (pdb) |
|
854 | 854 | =============================== |
|
855 | 855 | |
|
856 | 856 | Running entire programs via pdb |
|
857 | 857 | ------------------------------- |
|
858 | 858 | |
|
859 | 859 | pdb, the Python debugger, is a powerful interactive debugger which |
|
860 | 860 | allows you to step through code, set breakpoints, watch variables, |
|
861 | 861 | etc. IPython makes it very easy to start any script under the control |
|
862 | 862 | of pdb, regardless of whether you have wrapped it into a 'main()' |
|
863 | 863 | function or not. For this, simply type '%run -d myscript' at an |
|
864 | 864 | IPython prompt. See the %run command's documentation (via '%run?' or |
|
865 | 865 | in Sec. magic_ for more details, including how to control where pdb |
|
866 | 866 | will stop execution first. |
|
867 | 867 | |
|
868 | 868 | For more information on the use of the pdb debugger, read the included |
|
869 | 869 | pdb.doc file (part of the standard Python distribution). On a stock |
|
870 | 870 | Linux system it is located at /usr/lib/python2.3/pdb.doc, but the |
|
871 | 871 | easiest way to read it is by using the help() function of the pdb module |
|
872 | 872 | as follows (in an IPython prompt):: |
|
873 | 873 | |
|
874 | 874 | In [1]: import pdb |
|
875 | 875 | In [2]: pdb.help() |
|
876 | 876 | |
|
877 | 877 | This will load the pdb.doc document in a file viewer for you automatically. |
|
878 | 878 | |
|
879 | 879 | |
|
880 | 880 | Automatic invocation of pdb on exceptions |
|
881 | 881 | ----------------------------------------- |
|
882 | 882 | |
|
883 | 883 | IPython, if started with the ``--pdb`` option (or if the option is set in |
|
884 | 884 | your config file) can call the Python pdb debugger every time your code |
|
885 | 885 | triggers an uncaught exception. This feature |
|
886 | 886 | can also be toggled at any time with the %pdb magic command. This can be |
|
887 | 887 | extremely useful in order to find the origin of subtle bugs, because pdb |
|
888 | 888 | opens up at the point in your code which triggered the exception, and |
|
889 | 889 | while your program is at this point 'dead', all the data is still |
|
890 | 890 | available and you can walk up and down the stack frame and understand |
|
891 | 891 | the origin of the problem. |
|
892 | 892 | |
|
893 | 893 | Furthermore, you can use these debugging facilities both with the |
|
894 | 894 | embedded IPython mode and without IPython at all. For an embedded shell |
|
895 | 895 | (see sec. Embedding_), simply call the constructor with |
|
896 | 896 | ``--pdb`` in the argument string and pdb will automatically be called if an |
|
897 | 897 | uncaught exception is triggered by your code. |
|
898 | 898 | |
|
899 | 899 | For stand-alone use of the feature in your programs which do not use |
|
900 | 900 | IPython at all, put the following lines toward the top of your 'main' |
|
901 | 901 | routine:: |
|
902 | 902 | |
|
903 | 903 | import sys |
|
904 | 904 | from IPython.core import ultratb |
|
905 | 905 | sys.excepthook = ultratb.FormattedTB(mode='Verbose', |
|
906 | 906 | color_scheme='Linux', call_pdb=1) |
|
907 | 907 | |
|
908 | 908 | The mode keyword can be either 'Verbose' or 'Plain', giving either very |
|
909 | 909 | detailed or normal tracebacks respectively. The color_scheme keyword can |
|
910 | 910 | be one of 'NoColor', 'Linux' (default) or 'LightBG'. These are the same |
|
911 | 911 | options which can be set in IPython with ``--colors`` and ``--xmode``. |
|
912 | 912 | |
|
913 | 913 | This will give any of your programs detailed, colored tracebacks with |
|
914 | 914 | automatic invocation of pdb. |
|
915 | 915 | |
|
916 | 916 | |
|
917 | 917 | Extensions for syntax processing |
|
918 | 918 | ================================ |
|
919 | 919 | |
|
920 | 920 | This isn't for the faint of heart, because the potential for breaking |
|
921 | 921 | things is quite high. But it can be a very powerful and useful feature. |
|
922 | 922 | In a nutshell, you can redefine the way IPython processes the user input |
|
923 | 923 | line to accept new, special extensions to the syntax without needing to |
|
924 | 924 | change any of IPython's own code. |
|
925 | 925 | |
|
926 | 926 | In the IPython/extensions directory you will find some examples |
|
927 | 927 | supplied, which we will briefly describe now. These can be used 'as is' |
|
928 | 928 | (and both provide very useful functionality), or you can use them as a |
|
929 | 929 | starting point for writing your own extensions. |
|
930 | 930 | |
|
931 | 931 | .. _pasting_with_prompts: |
|
932 | 932 | |
|
933 | 933 | Pasting of code starting with Python or IPython prompts |
|
934 | 934 | ------------------------------------------------------- |
|
935 | 935 | |
|
936 |
IPython is smart enough to filter |
|
|
937 |
(``>>>`` and ``...``) or IPython ones (``In [N]:`` and `` |
|
|
936 | IPython is smart enough to filter out input prompts, be they plain Python ones | |
|
937 | (``>>>`` and ``...``) or IPython ones (``In [N]:`` and ``...:``). You can | |
|
938 | 938 | therefore copy and paste from existing interactive sessions without worry. |
|
939 | 939 | |
|
940 | 940 | The following is a 'screenshot' of how things work, copying an example from the |
|
941 | 941 | standard Python tutorial:: |
|
942 | 942 | |
|
943 | 943 | In [1]: >>> # Fibonacci series: |
|
944 | 944 | |
|
945 | 945 | In [2]: ... # the sum of two elements defines the next |
|
946 | 946 | |
|
947 | 947 | In [3]: ... a, b = 0, 1 |
|
948 | 948 | |
|
949 | 949 | In [4]: >>> while b < 10: |
|
950 | 950 | ...: ... print b |
|
951 | 951 | ...: ... a, b = b, a+b |
|
952 | 952 | ...: |
|
953 | 953 | 1 |
|
954 | 954 | 1 |
|
955 | 955 | 2 |
|
956 | 956 | 3 |
|
957 | 957 | 5 |
|
958 | 958 | 8 |
|
959 | 959 | |
|
960 | 960 | And pasting from IPython sessions works equally well:: |
|
961 | 961 | |
|
962 | 962 | In [1]: In [5]: def f(x): |
|
963 | 963 | ...: ...: "A simple function" |
|
964 | 964 | ...: ...: return x**2 |
|
965 | 965 | ...: ...: |
|
966 | 966 | |
|
967 | 967 | In [2]: f(3) |
|
968 | 968 | Out[2]: 9 |
|
969 | 969 | |
|
970 | 970 | .. _gui_support: |
|
971 | 971 | |
|
972 | 972 | GUI event loop support |
|
973 | 973 | ====================== |
|
974 | 974 | |
|
975 | 975 | .. versionadded:: 0.11 |
|
976 | 976 | The ``%gui`` magic and :mod:`IPython.lib.inputhook`. |
|
977 | 977 | |
|
978 | 978 | IPython has excellent support for working interactively with Graphical User |
|
979 | 979 | Interface (GUI) toolkits, such as wxPython, PyQt4/PySide, PyGTK and Tk. This is |
|
980 | 980 | implemented using Python's builtin ``PyOSInputHook`` hook. This implementation |
|
981 | 981 | is extremely robust compared to our previous thread-based version. The |
|
982 | 982 | advantages of this are: |
|
983 | 983 | |
|
984 | 984 | * GUIs can be enabled and disabled dynamically at runtime. |
|
985 | 985 | * The active GUI can be switched dynamically at runtime. |
|
986 | 986 | * In some cases, multiple GUIs can run simultaneously with no problems. |
|
987 | 987 | * There is a developer API in :mod:`IPython.lib.inputhook` for customizing |
|
988 | 988 | all of these things. |
|
989 | 989 | |
|
990 | 990 | For users, enabling GUI event loop integration is simple. You simple use the |
|
991 | 991 | ``%gui`` magic as follows:: |
|
992 | 992 | |
|
993 | 993 | %gui [GUINAME] |
|
994 | 994 | |
|
995 | 995 | With no arguments, ``%gui`` removes all GUI support. Valid ``GUINAME`` |
|
996 | 996 | arguments are ``wx``, ``qt``, ``gtk`` and ``tk``. |
|
997 | 997 | |
|
998 | 998 | Thus, to use wxPython interactively and create a running :class:`wx.App` |
|
999 | 999 | object, do:: |
|
1000 | 1000 | |
|
1001 | 1001 | %gui wx |
|
1002 | 1002 | |
|
1003 | 1003 | For information on IPython's Matplotlib integration (and the ``pylab`` mode) |
|
1004 | 1004 | see :ref:`this section <matplotlib_support>`. |
|
1005 | 1005 | |
|
1006 | 1006 | For developers that want to use IPython's GUI event loop integration in the |
|
1007 | 1007 | form of a library, these capabilities are exposed in library form in the |
|
1008 | 1008 | :mod:`IPython.lib.inputhook` and :mod:`IPython.lib.guisupport` modules. |
|
1009 | 1009 | Interested developers should see the module docstrings for more information, |
|
1010 | 1010 | but there are a few points that should be mentioned here. |
|
1011 | 1011 | |
|
1012 | 1012 | First, the ``PyOSInputHook`` approach only works in command line settings |
|
1013 | 1013 | where readline is activated. The integration with various eventloops |
|
1014 | 1014 | is handled somewhat differently (and more simply) when using the standalone |
|
1015 | 1015 | kernel, as in the qtconsole and notebook. |
|
1016 | 1016 | |
|
1017 | 1017 | Second, when using the ``PyOSInputHook`` approach, a GUI application should |
|
1018 | 1018 | *not* start its event loop. Instead all of this is handled by the |
|
1019 | 1019 | ``PyOSInputHook``. This means that applications that are meant to be used both |
|
1020 | 1020 | in IPython and as standalone apps need to have special code to detects how the |
|
1021 | 1021 | application is being run. We highly recommend using IPython's support for this. |
|
1022 | 1022 | Since the details vary slightly between toolkits, we point you to the various |
|
1023 | 1023 | examples in our source directory :file:`docs/examples/lib` that demonstrate |
|
1024 | 1024 | these capabilities. |
|
1025 | 1025 | |
|
1026 | 1026 | Third, unlike previous versions of IPython, we no longer "hijack" (replace |
|
1027 | 1027 | them with no-ops) the event loops. This is done to allow applications that |
|
1028 | 1028 | actually need to run the real event loops to do so. This is often needed to |
|
1029 | 1029 | process pending events at critical points. |
|
1030 | 1030 | |
|
1031 | 1031 | Finally, we also have a number of examples in our source directory |
|
1032 | 1032 | :file:`docs/examples/lib` that demonstrate these capabilities. |
|
1033 | 1033 | |
|
1034 | 1034 | PyQt and PySide |
|
1035 | 1035 | --------------- |
|
1036 | 1036 | |
|
1037 | 1037 | .. attempt at explanation of the complete mess that is Qt support |
|
1038 | 1038 | |
|
1039 | 1039 | When you use ``--gui=qt`` or ``--pylab=qt``, IPython can work with either |
|
1040 | 1040 | PyQt4 or PySide. There are three options for configuration here, because |
|
1041 | 1041 | PyQt4 has two APIs for QString and QVariant - v1, which is the default on |
|
1042 | 1042 | Python 2, and the more natural v2, which is the only API supported by PySide. |
|
1043 | 1043 | v2 is also the default for PyQt4 on Python 3. IPython's code for the QtConsole |
|
1044 | 1044 | uses v2, but you can still use any interface in your code, since the |
|
1045 | 1045 | Qt frontend is in a different process. |
|
1046 | 1046 | |
|
1047 | 1047 | The default will be to import PyQt4 without configuration of the APIs, thus |
|
1048 | 1048 | matching what most applications would expect. It will fall back of PySide if |
|
1049 | 1049 | PyQt4 is unavailable. |
|
1050 | 1050 | |
|
1051 | 1051 | If specified, IPython will respect the environment variable ``QT_API`` used |
|
1052 | 1052 | by ETS. ETS 4.0 also works with both PyQt4 and PySide, but it requires |
|
1053 | 1053 | PyQt4 to use its v2 API. So if ``QT_API=pyside`` PySide will be used, |
|
1054 | 1054 | and if ``QT_API=pyqt`` then PyQt4 will be used *with the v2 API* for |
|
1055 | 1055 | QString and QVariant, so ETS codes like MayaVi will also work with IPython. |
|
1056 | 1056 | |
|
1057 | 1057 | If you launch IPython in pylab mode with ``ipython --pylab=qt``, then IPython |
|
1058 | 1058 | will ask matplotlib which Qt library to use (only if QT_API is *not set*), via |
|
1059 | 1059 | the 'backend.qt4' rcParam. If matplotlib is version 1.0.1 or older, then |
|
1060 | 1060 | IPython will always use PyQt4 without setting the v2 APIs, since neither v2 |
|
1061 | 1061 | PyQt nor PySide work. |
|
1062 | 1062 | |
|
1063 | 1063 | .. warning:: |
|
1064 | 1064 | |
|
1065 | 1065 | Note that this means for ETS 4 to work with PyQt4, ``QT_API`` *must* be set |
|
1066 | 1066 | to work with IPython's qt integration, because otherwise PyQt4 will be |
|
1067 | 1067 | loaded in an incompatible mode. |
|
1068 | 1068 | |
|
1069 | 1069 | It also means that you must *not* have ``QT_API`` set if you want to |
|
1070 | 1070 | use ``--gui=qt`` with code that requires PyQt4 API v1. |
|
1071 | 1071 | |
|
1072 | 1072 | |
|
1073 | 1073 | .. _matplotlib_support: |
|
1074 | 1074 | |
|
1075 | 1075 | Plotting with matplotlib |
|
1076 | 1076 | ======================== |
|
1077 | 1077 | |
|
1078 | 1078 | `Matplotlib`_ provides high quality 2D and 3D plotting for Python. Matplotlib |
|
1079 | 1079 | can produce plots on screen using a variety of GUI toolkits, including Tk, |
|
1080 | 1080 | PyGTK, PyQt4 and wxPython. It also provides a number of commands useful for |
|
1081 | 1081 | scientific computing, all with a syntax compatible with that of the popular |
|
1082 | 1082 | Matlab program. |
|
1083 | 1083 | |
|
1084 | 1084 | To start IPython with matplotlib support, use the ``--pylab`` switch. If no |
|
1085 | 1085 | arguments are given, IPython will automatically detect your choice of |
|
1086 | 1086 | matplotlib backend. You can also request a specific backend with ``--pylab |
|
1087 | 1087 | backend``, where ``backend`` must be one of: 'tk', 'qt', 'wx', 'gtk', 'osx'. |
|
1088 | 1088 | In the web notebook and Qt console, 'inline' is also a valid backend value, |
|
1089 | 1089 | which produces static figures inlined inside the application window instead of |
|
1090 | 1090 | matplotlib's interactive figures that live in separate windows. |
|
1091 | 1091 | |
|
1092 | 1092 | .. _Matplotlib: http://matplotlib.sourceforge.net |
|
1093 | 1093 | |
|
1094 | 1094 | .. _interactive_demos: |
|
1095 | 1095 | |
|
1096 | 1096 | Interactive demos with IPython |
|
1097 | 1097 | ============================== |
|
1098 | 1098 | |
|
1099 | 1099 | IPython ships with a basic system for running scripts interactively in |
|
1100 | 1100 | sections, useful when presenting code to audiences. A few tags embedded |
|
1101 | 1101 | in comments (so that the script remains valid Python code) divide a file |
|
1102 | 1102 | into separate blocks, and the demo can be run one block at a time, with |
|
1103 | 1103 | IPython printing (with syntax highlighting) the block before executing |
|
1104 | 1104 | it, and returning to the interactive prompt after each block. The |
|
1105 | 1105 | interactive namespace is updated after each block is run with the |
|
1106 | 1106 | contents of the demo's namespace. |
|
1107 | 1107 | |
|
1108 | 1108 | This allows you to show a piece of code, run it and then execute |
|
1109 | 1109 | interactively commands based on the variables just created. Once you |
|
1110 | 1110 | want to continue, you simply execute the next block of the demo. The |
|
1111 | 1111 | following listing shows the markup necessary for dividing a script into |
|
1112 | 1112 | sections for execution as a demo: |
|
1113 | 1113 | |
|
1114 | 1114 | .. literalinclude:: ../../../examples/lib/example-demo.py |
|
1115 | 1115 | :language: python |
|
1116 | 1116 | |
|
1117 | 1117 | In order to run a file as a demo, you must first make a Demo object out |
|
1118 | 1118 | of it. If the file is named myscript.py, the following code will make a |
|
1119 | 1119 | demo:: |
|
1120 | 1120 | |
|
1121 | 1121 | from IPython.lib.demo import Demo |
|
1122 | 1122 | |
|
1123 | 1123 | mydemo = Demo('myscript.py') |
|
1124 | 1124 | |
|
1125 | 1125 | This creates the mydemo object, whose blocks you run one at a time by |
|
1126 | 1126 | simply calling the object with no arguments. If you have autocall active |
|
1127 | 1127 | in IPython (the default), all you need to do is type:: |
|
1128 | 1128 | |
|
1129 | 1129 | mydemo |
|
1130 | 1130 | |
|
1131 | 1131 | and IPython will call it, executing each block. Demo objects can be |
|
1132 | 1132 | restarted, you can move forward or back skipping blocks, re-execute the |
|
1133 | 1133 | last block, etc. Simply use the Tab key on a demo object to see its |
|
1134 | 1134 | methods, and call '?' on them to see their docstrings for more usage |
|
1135 | 1135 | details. In addition, the demo module itself contains a comprehensive |
|
1136 | 1136 | docstring, which you can access via:: |
|
1137 | 1137 | |
|
1138 | 1138 | from IPython.lib import demo |
|
1139 | 1139 | |
|
1140 | 1140 | demo? |
|
1141 | 1141 | |
|
1142 | 1142 | Limitations: It is important to note that these demos are limited to |
|
1143 | 1143 | fairly simple uses. In particular, you cannot break up sections within |
|
1144 | 1144 | indented code (loops, if statements, function definitions, etc.) |
|
1145 | 1145 | Supporting something like this would basically require tracking the |
|
1146 | 1146 | internal execution state of the Python interpreter, so only top-level |
|
1147 | 1147 | divisions are allowed. If you want to be able to open an IPython |
|
1148 | 1148 | instance at an arbitrary point in a program, you can use IPython's |
|
1149 | 1149 | embedding facilities, see :func:`IPython.embed` for details. |
|
1150 | 1150 |
@@ -1,765 +1,765 b'' | |||
|
1 | 1 | ============= |
|
2 | 2 | 0.11 Series |
|
3 | 3 | ============= |
|
4 | 4 | |
|
5 | 5 | Release 0.11 |
|
6 | 6 | ============ |
|
7 | 7 | |
|
8 | 8 | IPython 0.11 is a *major* overhaul of IPython, two years in the making. Most |
|
9 | 9 | of the code base has been rewritten or at least reorganized, breaking backward |
|
10 | 10 | compatibility with several APIs in previous versions. It is the first major |
|
11 | 11 | release in two years, and probably the most significant change to IPython since |
|
12 | 12 | its inception. We plan to have a relatively quick succession of releases, as |
|
13 | 13 | people discover new bugs and regressions. Once we iron out any significant |
|
14 | 14 | bugs in this process and settle down the new APIs, this series will become |
|
15 | 15 | IPython 1.0. We encourage feedback now on the core APIs, which we hope to |
|
16 | 16 | maintain stable during the 1.0 series. |
|
17 | 17 | |
|
18 | 18 | Since the internal APIs have changed so much, projects using IPython as a |
|
19 | 19 | library (as opposed to end-users of the application) are the most likely to |
|
20 | 20 | encounter regressions or changes that break their existing use patterns. We |
|
21 | 21 | will make every effort to provide updated versions of the APIs to facilitate |
|
22 | 22 | the transition, and we encourage you to contact us on the `development mailing |
|
23 | 23 | list`__ with questions and feedback. |
|
24 | 24 | |
|
25 | 25 | .. __: http://mail.scipy.org/mailman/listinfo/ipython-dev |
|
26 | 26 | |
|
27 | 27 | Chris Fonnesbeck recently wrote an `excellent post`__ that highlights some of |
|
28 | 28 | our major new features, with examples and screenshots. We encourage you to |
|
29 | 29 | read it as it provides an illustrated, high-level overview complementing the |
|
30 | 30 | detailed feature breakdown in this document. |
|
31 | 31 | |
|
32 | 32 | .. __: http://fonnesbeck.calepin.co/innovations-in-ipython.html |
|
33 | 33 | |
|
34 | 34 | A quick summary of the major changes (see below for details): |
|
35 | 35 | |
|
36 | 36 | * **Standalone Qt console**: a new rich console has been added to IPython, |
|
37 | 37 | started with `ipython qtconsole`. In this application we have tried to |
|
38 | 38 | retain the feel of a terminal for fast and efficient workflows, while adding |
|
39 | 39 | many features that a line-oriented terminal simply can not support, such as |
|
40 | 40 | inline figures, full multiline editing with syntax highlighting, graphical |
|
41 | 41 | tooltips for function calls and much more. This development was sponsored by |
|
42 | 42 | `Enthought Inc.`__. See :ref:`below <qtconsole_011>` for details. |
|
43 | 43 | |
|
44 | 44 | .. __: http://enthought.com |
|
45 | 45 | |
|
46 | 46 | * **High-level parallel computing with ZeroMQ**. Using the same architecture |
|
47 | 47 | that our Qt console is based on, we have completely rewritten our high-level |
|
48 | 48 | parallel computing machinery that in prior versions used the Twisted |
|
49 | 49 | networking framework. While this change will require users to update their |
|
50 | 50 | codes, the improvements in performance, memory control and internal |
|
51 | 51 | consistency across our codebase convinced us it was a price worth paying. We |
|
52 | 52 | have tried to explain how to best proceed with this update, and will be happy |
|
53 | 53 | to answer questions that may arise. A full tutorial describing these |
|
54 | 54 | features `was presented at SciPy'11`__, more details :ref:`below |
|
55 | 55 | <parallel_011>`. |
|
56 | 56 | |
|
57 | 57 | .. __: http://minrk.github.com/scipy-tutorial-2011 |
|
58 | 58 | |
|
59 | 59 | * **New model for GUI/plotting support in the terminal**. Now instead of the |
|
60 | 60 | various `-Xthread` flags we had before, GUI support is provided without the |
|
61 | 61 | use of any threads, by directly integrating GUI event loops with Python's |
|
62 | 62 | `PyOS_InputHook` API. A new command-line flag `--gui` controls GUI support, |
|
63 | 63 | and it can also be enabled after IPython startup via the new `%gui` magic. |
|
64 | 64 | This requires some changes if you want to execute GUI-using scripts inside |
|
65 | 65 | IPython, see :ref:`the GUI support section <gui_support>` for more details. |
|
66 | 66 | |
|
67 | 67 | * **A two-process architecture.** The Qt console is the first use of a new |
|
68 | 68 | model that splits IPython between a kernel process where code is executed and |
|
69 | 69 | a client that handles user interaction. We plan on also providing terminal |
|
70 | 70 | and web-browser based clients using this infrastructure in future releases. |
|
71 | 71 | This model allows multiple clients to interact with an IPython process |
|
72 | 72 | through a :ref:`well-documented messaging protocol <messaging>` using the |
|
73 | 73 | ZeroMQ networking library. |
|
74 | 74 | |
|
75 | 75 | * **Refactoring.** the entire codebase has been refactored, in order to make it |
|
76 | 76 | more modular and easier to contribute to. IPython has traditionally been a |
|
77 | 77 | hard project to participate because the old codebase was very monolithic. We |
|
78 | 78 | hope this (ongoing) restructuring will make it easier for new developers to |
|
79 | 79 | join us. |
|
80 | 80 | |
|
81 | 81 | * **Vim integration**. Vim can be configured to seamlessly control an IPython |
|
82 | 82 | kernel, see the files in :file:`docs/examples/vim` for the full details. |
|
83 | 83 | This work was done by Paul Ivanov, who prepared a nice `video |
|
84 | 84 | demonstration`__ of the features it provides. |
|
85 | 85 | |
|
86 | 86 | .. __: http://pirsquared.org/blog/2011/07/28/vim-ipython/ |
|
87 | 87 | |
|
88 | 88 | * **Integration into Microsoft Visual Studio**. Thanks to the work of the |
|
89 | 89 | Microsoft `Python Tools for Visual Studio`__ team, this version of IPython |
|
90 | 90 | has been integrated into Microsoft Visual Studio's Python tools open source |
|
91 | 91 | plug-in. `Details below`_ |
|
92 | 92 | |
|
93 | 93 | .. __: http://pytools.codeplex.com |
|
94 | 94 | .. _details below: ms_visual_studio_011_ |
|
95 | 95 | |
|
96 | 96 | * **Improved unicode support**. We closed many bugs related to unicode input. |
|
97 | 97 | |
|
98 | 98 | * **Python 3**. IPython now runs on Python 3.x. See :ref:`python3_011` for |
|
99 | 99 | details. |
|
100 | 100 | |
|
101 | 101 | * **New profile model**. Profiles are now directories that contain all relevant |
|
102 | 102 | infromation for that session, and thus better isolate IPython use-cases. |
|
103 | 103 | |
|
104 | 104 | * **SQLite storage for history**. All history is now stored in a SQLite |
|
105 | 105 | database, providing support for multiple simultaneous sessions that won't |
|
106 | 106 | clobber each other as well as the ability to perform queries on all stored |
|
107 | 107 | data. |
|
108 | 108 | |
|
109 | 109 | * **New configuration system**. All parts of IPython are now configured via a |
|
110 | 110 | mechanism inspired by the Enthought Traits library. Any configurable element |
|
111 | 111 | can have its attributes set either via files that now use real Python syntax |
|
112 | 112 | or from the command-line. |
|
113 | 113 | |
|
114 | 114 | * **Pasting of code with prompts**. IPython now intelligently strips out input |
|
115 | 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 | 119 | Authors and support |
|
120 | 120 | ------------------- |
|
121 | 121 | |
|
122 | 122 | Over 60 separate authors have contributed to this release, see :ref:`below |
|
123 | 123 | <credits_011>` for a full list. In particular, we want to highlight the |
|
124 | 124 | extremely active participation of two new core team members: Evan Patterson |
|
125 | 125 | implemented the Qt console, and Thomas Kluyver started with our Python 3 port |
|
126 | 126 | and by now has made major contributions to just about every area of IPython. |
|
127 | 127 | |
|
128 | 128 | We are also grateful for the support we have received during this development |
|
129 | 129 | cycle from several institutions: |
|
130 | 130 | |
|
131 | 131 | - `Enthought Inc`__ funded the development of our new Qt console, an effort that |
|
132 | 132 | required developing major pieces of underlying infrastructure, which now |
|
133 | 133 | power not only the Qt console but also our new parallel machinery. We'd like |
|
134 | 134 | to thank Eric Jones and Travis Oliphant for their support, as well as Ilan |
|
135 | 135 | Schnell for his tireless work integrating and testing IPython in the |
|
136 | 136 | `Enthought Python Distribution`_. |
|
137 | 137 | |
|
138 | 138 | .. __: http://enthought.com |
|
139 | 139 | .. _Enthought Python Distribution: http://www.enthought.com/products/epd.php |
|
140 | 140 | |
|
141 | 141 | - Nipy/NIH: funding via the `NiPy project`__ (NIH grant 5R01MH081909-02) helped |
|
142 | 142 | us jumpstart the development of this series by restructuring the entire |
|
143 | 143 | codebase two years ago in a way that would make modular development and |
|
144 | 144 | testing more approachable. Without this initial groundwork, all the new |
|
145 | 145 | features we have added would have been impossible to develop. |
|
146 | 146 | |
|
147 | 147 | .. __: http://nipy.org |
|
148 | 148 | |
|
149 | 149 | - Sage/NSF: funding via the grant `Sage: Unifying Mathematical Software for |
|
150 | 150 | Scientists, Engineers, and Mathematicians`__ (NSF grant DMS-1015114) |
|
151 | 151 | supported a meeting in spring 2011 of several of the core IPython developers |
|
152 | 152 | where major progress was made integrating the last key pieces leading to this |
|
153 | 153 | release. |
|
154 | 154 | |
|
155 | 155 | .. __: http://modular.math.washington.edu/grants/compmath09 |
|
156 | 156 | |
|
157 | 157 | - Microsoft's team working on `Python Tools for Visual Studio`__ developed the |
|
158 | 158 | integraton of IPython into the Python plugin for Visual Studio 2010. |
|
159 | 159 | |
|
160 | 160 | .. __: http://pytools.codeplex.com |
|
161 | 161 | |
|
162 | 162 | - Google Summer of Code: in 2010, we had two students developing prototypes of |
|
163 | 163 | the new machinery that is now maturing in this release: `Omar Zapata`_ and |
|
164 | 164 | `Gerardo GutiΓ©rrez`_. |
|
165 | 165 | |
|
166 | 166 | .. _Omar Zapata: http://ipythonzmq.blogspot.com/2010/08/ipython-zmq-status.html |
|
167 | 167 | .. _Gerardo GutiΓ©rrez: http://ipythonqt.blogspot.com/2010/04/ipython-qt-interface-gsoc-2010-proposal.html> |
|
168 | 168 | |
|
169 | 169 | |
|
170 | 170 | Development summary: moving to Git and Github |
|
171 | 171 | --------------------------------------------- |
|
172 | 172 | |
|
173 | 173 | In April 2010, after `one breakage too many with bzr`__, we decided to move our |
|
174 | 174 | entire development process to Git and Github.com. This has proven to be one of |
|
175 | 175 | the best decisions in the project's history, as the combination of git and |
|
176 | 176 | github have made us far, far more productive than we could be with our previous |
|
177 | 177 | tools. We first converted our bzr repo to a git one without losing history, |
|
178 | 178 | and a few weeks later ported all open Launchpad bugs to github issues with |
|
179 | 179 | their comments mostly intact (modulo some formatting changes). This ensured a |
|
180 | 180 | smooth transition where no development history or submitted bugs were lost. |
|
181 | 181 | Feel free to use our little Launchpad to Github issues `porting script`_ if you |
|
182 | 182 | need to make a similar transition. |
|
183 | 183 | |
|
184 | 184 | .. __: http://mail.scipy.org/pipermail/ipython-dev/2010-April/005944.html |
|
185 | 185 | .. _porting script: https://gist.github.com/835577 |
|
186 | 186 | |
|
187 | 187 | These simple statistics show how much work has been done on the new release, by |
|
188 | 188 | comparing the current code to the last point it had in common with the 0.10 |
|
189 | 189 | series. A huge diff and ~2200 commits make up this cycle:: |
|
190 | 190 | |
|
191 | 191 | git diff $(git merge-base 0.10.2 HEAD) | wc -l |
|
192 | 192 | 288019 |
|
193 | 193 | |
|
194 | 194 | git log $(git merge-base 0.10.2 HEAD)..HEAD --oneline | wc -l |
|
195 | 195 | 2200 |
|
196 | 196 | |
|
197 | 197 | Since our move to github, 511 issues were closed, 226 of which were pull |
|
198 | 198 | requests and 285 regular issues (:ref:`a full list with links |
|
199 | 199 | <issues_list_011>` is available for those interested in the details). Github's |
|
200 | 200 | pull requests are a fantastic mechanism for reviewing code and building a |
|
201 | 201 | shared ownership of the project, and we are making enthusiastic use of it. |
|
202 | 202 | |
|
203 | 203 | .. Note:: |
|
204 | 204 | |
|
205 | 205 | This undercounts the number of issues closed in this development cycle, |
|
206 | 206 | since we only moved to github for issue tracking in May 2010, but we have no |
|
207 | 207 | way of collecting statistics on the number of issues closed in the old |
|
208 | 208 | Launchpad bug tracker prior to that. |
|
209 | 209 | |
|
210 | 210 | |
|
211 | 211 | .. _qtconsole_011: |
|
212 | 212 | |
|
213 | 213 | Qt Console |
|
214 | 214 | ---------- |
|
215 | 215 | |
|
216 | 216 | IPython now ships with a Qt application that feels very much like a terminal, |
|
217 | 217 | but is in fact a rich GUI that runs an IPython client but supports inline |
|
218 | 218 | figures, saving sessions to PDF and HTML, multiline editing with syntax |
|
219 | 219 | highlighting, graphical calltips and much more: |
|
220 | 220 | |
|
221 | 221 | .. figure:: ../_static/qtconsole.png |
|
222 | 222 | :width: 400px |
|
223 | 223 | :alt: IPython Qt console with embedded plots |
|
224 | 224 | :align: center |
|
225 | 225 | :target: ../_static/qtconsole.png |
|
226 | 226 | |
|
227 | 227 | The Qt console for IPython, using inline matplotlib plots. |
|
228 | 228 | |
|
229 | 229 | We hope that many projects will embed this widget, which we've kept |
|
230 | 230 | deliberately very lightweight, into their own environments. In the future we |
|
231 | 231 | may also offer a slightly more featureful application (with menus and other GUI |
|
232 | 232 | elements), but we remain committed to always shipping this easy to embed |
|
233 | 233 | widget. |
|
234 | 234 | |
|
235 | 235 | See the :ref:`Qt console section <qtconsole>` of the docs for a detailed |
|
236 | 236 | description of the console's features and use. |
|
237 | 237 | |
|
238 | 238 | |
|
239 | 239 | .. _parallel_011: |
|
240 | 240 | |
|
241 | 241 | High-level parallel computing with ZeroMQ |
|
242 | 242 | ----------------------------------------- |
|
243 | 243 | |
|
244 | 244 | We have completely rewritten the Twisted-based code for high-level parallel |
|
245 | 245 | computing to work atop our new ZeroMQ architecture. While we realize this will |
|
246 | 246 | break compatibility for a number of users, we hope to make the transition as |
|
247 | 247 | easy as possible with our docs, and we are convinced the change is worth it. |
|
248 | 248 | ZeroMQ provides us with much tighter control over memory, higher performance, |
|
249 | 249 | and its communications are impervious to the Python Global Interpreter Lock |
|
250 | 250 | because they take place in a system-level C++ thread. The impact of the GIL in |
|
251 | 251 | our previous code was something we could simply not work around, given that |
|
252 | 252 | Twisted is itself a Python library. So while Twisted is a very capable |
|
253 | 253 | framework, we think ZeroMQ fits our needs much better and we hope you will find |
|
254 | 254 | the change to be a significant improvement in the long run. |
|
255 | 255 | |
|
256 | 256 | Our manual contains :ref:`a full description of how to use IPython for parallel |
|
257 | 257 | computing <parallel_overview>`, and the `tutorial`__ presented by Min |
|
258 | 258 | Ragan-Kelley at the SciPy 2011 conference provides a hands-on complement to the |
|
259 | 259 | reference docs. |
|
260 | 260 | |
|
261 | 261 | .. __: http://minrk.github.com/scipy-tutorial-2011 |
|
262 | 262 | |
|
263 | 263 | |
|
264 | 264 | Refactoring |
|
265 | 265 | ----------- |
|
266 | 266 | |
|
267 | 267 | As of this release, a signifiant portion of IPython has been refactored. This |
|
268 | 268 | refactoring is founded on a number of new abstractions. The main new classes |
|
269 | 269 | that implement these abstractions are: |
|
270 | 270 | |
|
271 | 271 | * :class:`IPython.utils.traitlets.HasTraits`. |
|
272 | 272 | * :class:`IPython.config.configurable.Configurable`. |
|
273 | 273 | * :class:`IPython.config.application.Application`. |
|
274 | 274 | * :class:`IPython.config.loader.ConfigLoader`. |
|
275 | 275 | * :class:`IPython.config.loader.Config` |
|
276 | 276 | |
|
277 | 277 | We are still in the process of writing developer focused documentation about |
|
278 | 278 | these classes, but for now our :ref:`configuration documentation |
|
279 | 279 | <config_overview>` contains a high level overview of the concepts that these |
|
280 | 280 | classes express. |
|
281 | 281 | |
|
282 | 282 | The biggest user-visible change is likely the move to using the config system |
|
283 | 283 | to determine the command-line arguments for IPython applications. The benefit |
|
284 | 284 | of this is that *all* configurable values in IPython are exposed on the |
|
285 | 285 | command-line, but the syntax for specifying values has changed. The gist is |
|
286 | 286 | that assigning values is pure Python assignment. Simple flags exist for |
|
287 | 287 | commonly used options, these are always prefixed with '--'. |
|
288 | 288 | |
|
289 | 289 | The IPython command-line help has the details of all the options (via |
|
290 | 290 | ``ipythyon --help``), but a simple example should clarify things; the ``pylab`` |
|
291 | 291 | flag can be used to start in pylab mode with the qt4 backend:: |
|
292 | 292 | |
|
293 | 293 | ipython --pylab=qt |
|
294 | 294 | |
|
295 | 295 | which is equivalent to using the fully qualified form:: |
|
296 | 296 | |
|
297 | 297 | ipython --TerminalIPythonApp.pylab=qt |
|
298 | 298 | |
|
299 | 299 | The long-form options can be listed via ``ipython --help-all``. |
|
300 | 300 | |
|
301 | 301 | |
|
302 | 302 | ZeroMQ architecture |
|
303 | 303 | ------------------- |
|
304 | 304 | |
|
305 | 305 | There is a new GUI framework for IPython, based on a client-server model in |
|
306 | 306 | which multiple clients can communicate with one IPython kernel, using the |
|
307 | 307 | ZeroMQ messaging framework. There is already a Qt console client, which can |
|
308 | 308 | be started by calling ``ipython qtconsole``. The protocol is :ref:`documented |
|
309 | 309 | <messaging>`. |
|
310 | 310 | |
|
311 | 311 | The parallel computing framework has also been rewritten using ZMQ. The |
|
312 | 312 | protocol is described :ref:`here <parallel_messages>`, and the code is in the |
|
313 | 313 | new :mod:`IPython.parallel` module. |
|
314 | 314 | |
|
315 | 315 | .. _python3_011: |
|
316 | 316 | |
|
317 | 317 | Python 3 support |
|
318 | 318 | ---------------- |
|
319 | 319 | |
|
320 | 320 | A Python 3 version of IPython has been prepared. For the time being, this is |
|
321 | 321 | maintained separately and updated from the main codebase. Its code can be found |
|
322 | 322 | `here <https://github.com/ipython/ipython-py3k>`_. The parallel computing |
|
323 | 323 | components are not perfect on Python3, but most functionality appears to be |
|
324 | 324 | working. As this work is evolving quickly, the best place to find updated |
|
325 | 325 | information about it is our `Python 3 wiki page`__. |
|
326 | 326 | |
|
327 | 327 | .. __: http://wiki.ipython.org/index.php?title=Python_3 |
|
328 | 328 | |
|
329 | 329 | |
|
330 | 330 | Unicode |
|
331 | 331 | ------- |
|
332 | 332 | |
|
333 | 333 | Entering non-ascii characters in unicode literals (``u"β¬ΓΈ"``) now works |
|
334 | 334 | properly on all platforms. However, entering these in byte/string literals |
|
335 | 335 | (``"β¬ΓΈ"``) will not work as expected on Windows (or any platform where the |
|
336 | 336 | terminal encoding is not UTF-8, as it typically is for Linux & Mac OS X). You |
|
337 | 337 | can use escape sequences (``"\xe9\x82"``) to get bytes above 128, or use |
|
338 | 338 | unicode literals and encode them. This is a limitation of Python 2 which we |
|
339 | 339 | cannot easily work around. |
|
340 | 340 | |
|
341 | 341 | .. _ms_visual_studio_011: |
|
342 | 342 | |
|
343 | 343 | Integration with Microsoft Visual Studio |
|
344 | 344 | ---------------------------------------- |
|
345 | 345 | |
|
346 | 346 | IPython can be used as the interactive shell in the `Python plugin for |
|
347 | 347 | Microsoft Visual Studio`__, as seen here: |
|
348 | 348 | |
|
349 | 349 | .. figure:: ../_static/ms_visual_studio.png |
|
350 | 350 | :width: 500px |
|
351 | 351 | :alt: IPython console embedded in Microsoft Visual Studio. |
|
352 | 352 | :align: center |
|
353 | 353 | :target: ../_static/ms_visual_studio.png |
|
354 | 354 | |
|
355 | 355 | IPython console embedded in Microsoft Visual Studio. |
|
356 | 356 | |
|
357 | 357 | The Microsoft team developing this currently has a release candidate out using |
|
358 | 358 | IPython 0.11. We will continue to collaborate with them to ensure that as they |
|
359 | 359 | approach their final release date, the integration with IPython remains smooth. |
|
360 | 360 | We'd like to thank Dino Viehland and Shahrokh Mortazavi for the work they have |
|
361 | 361 | done towards this feature, as well as Wenming Ye for his support of our WinHPC |
|
362 | 362 | capabilities. |
|
363 | 363 | |
|
364 | 364 | .. __: http://pytools.codeplex.com |
|
365 | 365 | |
|
366 | 366 | |
|
367 | 367 | Additional new features |
|
368 | 368 | ----------------------- |
|
369 | 369 | |
|
370 | 370 | * Added ``Bytes`` traitlet, removing ``Str``. All 'string' traitlets should |
|
371 | 371 | either be ``Unicode`` if a real string, or ``Bytes`` if a C-string. This |
|
372 | 372 | removes ambiguity and helps the Python 3 transition. |
|
373 | 373 | |
|
374 | 374 | * New magic ``%loadpy`` loads a python file from disk or web URL into |
|
375 | 375 | the current input buffer. |
|
376 | 376 | |
|
377 | 377 | * New magic ``%pastebin`` for sharing code via the 'Lodge it' pastebin. |
|
378 | 378 | |
|
379 | 379 | * New magic ``%precision`` for controlling float and numpy pretty printing. |
|
380 | 380 | |
|
381 | 381 | * IPython applications initiate logging, so any object can gain access to |
|
382 | 382 | a the logger of the currently running Application with: |
|
383 | 383 | |
|
384 | 384 | .. sourcecode:: python |
|
385 | 385 | |
|
386 | 386 | from IPython.config.application import Application |
|
387 | 387 | logger = Application.instance().log |
|
388 | 388 | |
|
389 | 389 | * You can now get help on an object halfway through typing a command. For |
|
390 | 390 | instance, typing ``a = zip?`` shows the details of :func:`zip`. It also |
|
391 | 391 | leaves the command at the next prompt so you can carry on with it. |
|
392 | 392 | |
|
393 | 393 | * The input history is now written to an SQLite database. The API for |
|
394 | 394 | retrieving items from the history has also been redesigned. |
|
395 | 395 | |
|
396 | 396 | * The :mod:`IPython.extensions.pretty` extension has been moved out of |
|
397 | 397 | quarantine and fully updated to the new extension API. |
|
398 | 398 | |
|
399 | 399 | * New magics for loading/unloading/reloading extensions have been added: |
|
400 | 400 | ``%load_ext``, ``%unload_ext`` and ``%reload_ext``. |
|
401 | 401 | |
|
402 | 402 | * The configuration system and configuration files are brand new. See the |
|
403 | 403 | configuration system :ref:`documentation <config_index>` for more details. |
|
404 | 404 | |
|
405 | 405 | * The :class:`~IPython.core.interactiveshell.InteractiveShell` class is now a |
|
406 | 406 | :class:`~IPython.config.configurable.Configurable` subclass and has traitlets |
|
407 | 407 | that determine the defaults and runtime environment. The ``__init__`` method |
|
408 | 408 | has also been refactored so this class can be instantiated and run without |
|
409 | 409 | the old :mod:`ipmaker` module. |
|
410 | 410 | |
|
411 | 411 | * The methods of :class:`~IPython.core.interactiveshell.InteractiveShell` have |
|
412 | 412 | been organized into sections to make it easier to turn more sections |
|
413 | 413 | of functionality into components. |
|
414 | 414 | |
|
415 | 415 | * The embedded shell has been refactored into a truly standalone subclass of |
|
416 | 416 | :class:`InteractiveShell` called :class:`InteractiveShellEmbed`. All |
|
417 | 417 | embedding logic has been taken out of the base class and put into the |
|
418 | 418 | embedded subclass. |
|
419 | 419 | |
|
420 | 420 | * Added methods of :class:`~IPython.core.interactiveshell.InteractiveShell` to |
|
421 | 421 | help it cleanup after itself. The :meth:`cleanup` method controls this. We |
|
422 | 422 | couldn't do this in :meth:`__del__` because we have cycles in our object |
|
423 | 423 | graph that prevent it from being called. |
|
424 | 424 | |
|
425 | 425 | * Created a new module :mod:`IPython.utils.importstring` for resolving |
|
426 | 426 | strings like ``foo.bar.Bar`` to the actual class. |
|
427 | 427 | |
|
428 | 428 | * Completely refactored the :mod:`IPython.core.prefilter` module into |
|
429 | 429 | :class:`~IPython.config.configurable.Configurable` subclasses. Added a new |
|
430 | 430 | layer into the prefilter system, called "transformations" that all new |
|
431 | 431 | prefilter logic should use (rather than the older "checker/handler" |
|
432 | 432 | approach). |
|
433 | 433 | |
|
434 | 434 | * Aliases are now components (:mod:`IPython.core.alias`). |
|
435 | 435 | |
|
436 | 436 | * New top level :func:`~IPython.frontend.terminal.embed.embed` function that can |
|
437 | 437 | be called to embed IPython at any place in user's code. On the first call it |
|
438 | 438 | will create an :class:`~IPython.frontend.terminal.embed.InteractiveShellEmbed` |
|
439 | 439 | instance and call it. In later calls, it just calls the previously created |
|
440 | 440 | :class:`~IPython.frontend.terminal.embed.InteractiveShellEmbed`. |
|
441 | 441 | |
|
442 | 442 | * Created a configuration system (:mod:`IPython.config.configurable`) that is |
|
443 | 443 | based on :mod:`IPython.utils.traitlets`. Configurables are arranged into a |
|
444 | 444 | runtime containment tree (not inheritance) that i) automatically propagates |
|
445 | 445 | configuration information and ii) allows singletons to discover each other in |
|
446 | 446 | a loosely coupled manner. In the future all parts of IPython will be |
|
447 | 447 | subclasses of :class:`~IPython.config.configurable.Configurable`. All IPython |
|
448 | 448 | developers should become familiar with the config system. |
|
449 | 449 | |
|
450 | 450 | * Created a new :class:`~IPython.config.loader.Config` for holding |
|
451 | 451 | configuration information. This is a dict like class with a few extras: i) |
|
452 | 452 | it supports attribute style access, ii) it has a merge function that merges |
|
453 | 453 | two :class:`~IPython.config.loader.Config` instances recursively and iii) it |
|
454 | 454 | will automatically create sub-:class:`~IPython.config.loader.Config` |
|
455 | 455 | instances for attributes that start with an uppercase character. |
|
456 | 456 | |
|
457 | 457 | * Created new configuration loaders in :mod:`IPython.config.loader`. These |
|
458 | 458 | loaders provide a unified loading interface for all configuration |
|
459 | 459 | information including command line arguments and configuration files. We |
|
460 | 460 | have two default implementations based on :mod:`argparse` and plain python |
|
461 | 461 | files. These are used to implement the new configuration system. |
|
462 | 462 | |
|
463 | 463 | * Created a top-level :class:`Application` class in |
|
464 | 464 | :mod:`IPython.core.application` that is designed to encapsulate the starting |
|
465 | 465 | of any basic Python program. An application loads and merges all the |
|
466 | 466 | configuration objects, constructs the main application, configures and |
|
467 | 467 | initiates logging, and creates and configures any :class:`Configurable` |
|
468 | 468 | instances and then starts the application running. An extended |
|
469 | 469 | :class:`BaseIPythonApplication` class adds logic for handling the |
|
470 | 470 | IPython directory as well as profiles, and all IPython entry points |
|
471 | 471 | extend it. |
|
472 | 472 | |
|
473 | 473 | * The :class:`Type` and :class:`Instance` traitlets now handle classes given |
|
474 | 474 | as strings, like ``foo.bar.Bar``. This is needed for forward declarations. |
|
475 | 475 | But, this was implemented in a careful way so that string to class |
|
476 | 476 | resolution is done at a single point, when the parent |
|
477 | 477 | :class:`~IPython.utils.traitlets.HasTraitlets` is instantiated. |
|
478 | 478 | |
|
479 | 479 | * :mod:`IPython.utils.ipstruct` has been refactored to be a subclass of |
|
480 | 480 | dict. It also now has full docstrings and doctests. |
|
481 | 481 | |
|
482 | 482 | * Created a Traits like implementation in :mod:`IPython.utils.traitlets`. This |
|
483 | 483 | is a pure Python, lightweight version of a library that is similar to |
|
484 | 484 | Enthought's Traits project, but has no dependencies on Enthought's code. We |
|
485 | 485 | are using this for validation, defaults and notification in our new component |
|
486 | 486 | system. Although it is not 100% API compatible with Enthought's Traits, we |
|
487 | 487 | plan on moving in this direction so that eventually our implementation could |
|
488 | 488 | be replaced by a (yet to exist) pure Python version of Enthought Traits. |
|
489 | 489 | |
|
490 | 490 | * Added a new module :mod:`IPython.lib.inputhook` to manage the integration |
|
491 | 491 | with GUI event loops using `PyOS_InputHook`. See the docstrings in this |
|
492 | 492 | module or the main IPython docs for details. |
|
493 | 493 | |
|
494 | 494 | * For users, GUI event loop integration is now handled through the new |
|
495 | 495 | :command:`%gui` magic command. Type ``%gui?`` at an IPython prompt for |
|
496 | 496 | documentation. |
|
497 | 497 | |
|
498 | 498 | * For developers :mod:`IPython.lib.inputhook` provides a simple interface |
|
499 | 499 | for managing the event loops in their interactive GUI applications. |
|
500 | 500 | Examples can be found in our :file:`docs/examples/lib` directory. |
|
501 | 501 | |
|
502 | 502 | Backwards incompatible changes |
|
503 | 503 | ------------------------------ |
|
504 | 504 | |
|
505 | 505 | * The Twisted-based :mod:`IPython.kernel` has been removed, and completely |
|
506 | 506 | rewritten as :mod:`IPython.parallel`, using ZeroMQ. |
|
507 | 507 | |
|
508 | 508 | * Profiles are now directories. Instead of a profile being a single config file, |
|
509 | 509 | profiles are now self-contained directories. By default, profiles get their |
|
510 | 510 | own IPython history, log files, and everything. To create a new profile, do |
|
511 | 511 | ``ipython profile create <name>``. |
|
512 | 512 | |
|
513 | 513 | * All IPython applications have been rewritten to use |
|
514 | 514 | :class:`~IPython.config.loader.KeyValueConfigLoader`. This means that |
|
515 | 515 | command-line options have changed. Now, all configurable values are accessible |
|
516 | 516 | from the command-line with the same syntax as in a configuration file. |
|
517 | 517 | |
|
518 | 518 | * The command line options ``-wthread``, ``-qthread`` and |
|
519 | 519 | ``-gthread`` have been removed. Use ``--gui=wx``, ``--gui=qt``, ``--gui=gtk`` |
|
520 | 520 | instead. |
|
521 | 521 | |
|
522 | 522 | * The extension loading functions have been renamed to |
|
523 | 523 | :func:`load_ipython_extension` and :func:`unload_ipython_extension`. |
|
524 | 524 | |
|
525 | 525 | * :class:`~IPython.core.interactiveshell.InteractiveShell` no longer takes an |
|
526 | 526 | ``embedded`` argument. Instead just use the |
|
527 | 527 | :class:`~IPython.core.interactiveshell.InteractiveShellEmbed` class. |
|
528 | 528 | |
|
529 | 529 | * ``__IPYTHON__`` is no longer injected into ``__builtin__``. |
|
530 | 530 | |
|
531 | 531 | * :meth:`Struct.__init__` no longer takes `None` as its first argument. It |
|
532 | 532 | must be a :class:`dict` or :class:`Struct`. |
|
533 | 533 | |
|
534 | 534 | * :meth:`~IPython.core.interactiveshell.InteractiveShell.ipmagic` has been |
|
535 | 535 | renamed :meth:`~IPython.core.interactiveshell.InteractiveShell.magic.` |
|
536 | 536 | |
|
537 | 537 | * The functions :func:`ipmagic` and :func:`ipalias` have been removed from |
|
538 | 538 | :mod:`__builtins__`. |
|
539 | 539 | |
|
540 | 540 | * The references to the global |
|
541 | 541 | :class:`~IPython.core.interactivehell.InteractiveShell` instance (``_ip``, and |
|
542 | 542 | ``__IP``) have been removed from the user's namespace. They are replaced by a |
|
543 | 543 | new function called :func:`get_ipython` that returns the current |
|
544 | 544 | :class:`~IPython.core.interactiveshell.InteractiveShell` instance. This |
|
545 | 545 | function is injected into the user's namespace and is now the main way of |
|
546 | 546 | accessing the running IPython. |
|
547 | 547 | |
|
548 | 548 | * Old style configuration files :file:`ipythonrc` and :file:`ipy_user_conf.py` |
|
549 | 549 | are no longer supported. Users should migrate there configuration files to |
|
550 | 550 | the new format described :ref:`here <config_overview>` and :ref:`here |
|
551 | 551 | <configuring_ipython>`. |
|
552 | 552 | |
|
553 | 553 | * The old IPython extension API that relied on :func:`ipapi` has been |
|
554 | 554 | completely removed. The new extension API is described :ref:`here |
|
555 | 555 | <configuring_ipython>`. |
|
556 | 556 | |
|
557 | 557 | * Support for ``qt3`` has been dropped. Users who need this should use |
|
558 | 558 | previous versions of IPython. |
|
559 | 559 | |
|
560 | 560 | * Removed :mod:`shellglobals` as it was obsolete. |
|
561 | 561 | |
|
562 | 562 | * Removed all the threaded shells in :mod:`IPython.core.shell`. These are no |
|
563 | 563 | longer needed because of the new capabilities in |
|
564 | 564 | :mod:`IPython.lib.inputhook`. |
|
565 | 565 | |
|
566 | 566 | * New top-level sub-packages have been created: :mod:`IPython.core`, |
|
567 | 567 | :mod:`IPython.lib`, :mod:`IPython.utils`, :mod:`IPython.deathrow`, |
|
568 | 568 | :mod:`IPython.quarantine`. All existing top-level modules have been |
|
569 | 569 | moved to appropriate sub-packages. All internal import statements |
|
570 | 570 | have been updated and tests have been added. The build system (setup.py |
|
571 | 571 | and friends) have been updated. See :ref:`this section <module_reorg>` of the |
|
572 | 572 | documentation for descriptions of these new sub-packages. |
|
573 | 573 | |
|
574 | 574 | * :mod:`IPython.ipapi` has been moved to :mod:`IPython.core.ipapi`. |
|
575 | 575 | :mod:`IPython.Shell` and :mod:`IPython.iplib` have been split and removed as |
|
576 | 576 | part of the refactor. |
|
577 | 577 | |
|
578 | 578 | * :mod:`Extensions` has been moved to :mod:`extensions` and all existing |
|
579 | 579 | extensions have been moved to either :mod:`IPython.quarantine` or |
|
580 | 580 | :mod:`IPython.deathrow`. :mod:`IPython.quarantine` contains modules that we |
|
581 | 581 | plan on keeping but that need to be updated. :mod:`IPython.deathrow` contains |
|
582 | 582 | modules that are either dead or that should be maintained as third party |
|
583 | 583 | libraries. More details about this can be found :ref:`here <module_reorg>`. |
|
584 | 584 | |
|
585 | 585 | * Previous IPython GUIs in :mod:`IPython.frontend` and :mod:`IPython.gui` are |
|
586 | 586 | likely broken, and have been removed to :mod:`IPython.deathrow` because of the |
|
587 | 587 | refactoring in the core. With proper updates, these should still work. |
|
588 | 588 | |
|
589 | 589 | |
|
590 | 590 | Known Regressions |
|
591 | 591 | ----------------- |
|
592 | 592 | |
|
593 | 593 | We do our best to improve IPython, but there are some known regressions in 0.11 |
|
594 | 594 | relative to 0.10.2. First of all, there are features that have yet to be |
|
595 | 595 | ported to the new APIs, and in order to ensure that all of the installed code |
|
596 | 596 | runs for our users, we have moved them to two separate directories in the |
|
597 | 597 | source distribution, `quarantine` and `deathrow`. Finally, we have some other |
|
598 | 598 | miscellaneous regressions that we hope to fix as soon as possible. We now |
|
599 | 599 | describe all of these in more detail. |
|
600 | 600 | |
|
601 | 601 | Quarantine |
|
602 | 602 | ~~~~~~~~~~ |
|
603 | 603 | |
|
604 | 604 | These are tools and extensions that we consider relatively easy to update to |
|
605 | 605 | the new classes and APIs, but that we simply haven't had time for. Any user |
|
606 | 606 | who is interested in one of these is encouraged to help us by porting it and |
|
607 | 607 | submitting a pull request on our `development site`_. |
|
608 | 608 | |
|
609 | 609 | .. _development site: http://github.com/ipython/ipython |
|
610 | 610 | |
|
611 | 611 | Currently, the quarantine directory contains:: |
|
612 | 612 | |
|
613 | 613 | clearcmd.py ipy_fsops.py ipy_signals.py |
|
614 | 614 | envpersist.py ipy_gnuglobal.py ipy_synchronize_with.py |
|
615 | 615 | ext_rescapture.py ipy_greedycompleter.py ipy_system_conf.py |
|
616 | 616 | InterpreterExec.py ipy_jot.py ipy_which.py |
|
617 | 617 | ipy_app_completers.py ipy_lookfor.py ipy_winpdb.py |
|
618 | 618 | ipy_autoreload.py ipy_profile_doctest.py ipy_workdir.py |
|
619 | 619 | ipy_completers.py ipy_pydb.py jobctrl.py |
|
620 | 620 | ipy_editors.py ipy_rehashdir.py ledit.py |
|
621 | 621 | ipy_exportdb.py ipy_render.py pspersistence.py |
|
622 | 622 | ipy_extutil.py ipy_server.py win32clip.py |
|
623 | 623 | |
|
624 | 624 | Deathrow |
|
625 | 625 | ~~~~~~~~ |
|
626 | 626 | |
|
627 | 627 | These packages may be harder to update or make most sense as third-party |
|
628 | 628 | libraries. Some of them are completely obsolete and have been already replaced |
|
629 | 629 | by better functionality (we simply haven't had the time to carefully weed them |
|
630 | 630 | out so they are kept here for now). Others simply require fixes to code that |
|
631 | 631 | the current core team may not be familiar with. If a tool you were used to is |
|
632 | 632 | included here, we encourage you to contact the dev list and we can discuss |
|
633 | 633 | whether it makes sense to keep it in IPython (if it can be maintained). |
|
634 | 634 | |
|
635 | 635 | Currently, the deathrow directory contains:: |
|
636 | 636 | |
|
637 | 637 | astyle.py ipy_defaults.py ipy_vimserver.py |
|
638 | 638 | dtutils.py ipy_kitcfg.py numeric_formats.py |
|
639 | 639 | Gnuplot2.py ipy_legacy.py numutils.py |
|
640 | 640 | GnuplotInteractive.py ipy_p4.py outputtrap.py |
|
641 | 641 | GnuplotRuntime.py ipy_profile_none.py PhysicalQInput.py |
|
642 | 642 | ibrowse.py ipy_profile_numpy.py PhysicalQInteractive.py |
|
643 | 643 | igrid.py ipy_profile_scipy.py quitter.py* |
|
644 | 644 | ipipe.py ipy_profile_sh.py scitedirector.py |
|
645 | 645 | iplib.py ipy_profile_zope.py Shell.py |
|
646 | 646 | ipy_constants.py ipy_traits_completer.py twshell.py |
|
647 | 647 | |
|
648 | 648 | |
|
649 | 649 | Other regressions |
|
650 | 650 | ~~~~~~~~~~~~~~~~~ |
|
651 | 651 | |
|
652 | 652 | * The machinery that adds functionality to the 'sh' profile for using IPython |
|
653 | 653 | as your system shell has not been updated to use the new APIs. As a result, |
|
654 | 654 | only the aesthetic (prompt) changes are still implemented. We intend to fix |
|
655 | 655 | this by 0.12. Tracked as issue 547_. |
|
656 | 656 | |
|
657 | 657 | .. _547: https://github.com/ipython/ipython/issues/547 |
|
658 | 658 | |
|
659 | 659 | * The installation of scripts on Windows was broken without setuptools, so we |
|
660 | 660 | now depend on setuptools on Windows. We hope to fix setuptools-less |
|
661 | 661 | installation, and then remove the setuptools dependency. Issue 539_. |
|
662 | 662 | |
|
663 | 663 | .. _539: https://github.com/ipython/ipython/issues/539 |
|
664 | 664 | |
|
665 | 665 | * The directory history `_dh` is not saved between sessions. Issue 634_. |
|
666 | 666 | |
|
667 | 667 | .. _634: https://github.com/ipython/ipython/issues/634 |
|
668 | 668 | |
|
669 | 669 | |
|
670 | 670 | Removed Features |
|
671 | 671 | ---------------- |
|
672 | 672 | |
|
673 | 673 | As part of the updating of IPython, we have removed a few features for the |
|
674 | 674 | purposes of cleaning up the codebase and interfaces. These removals are |
|
675 | 675 | permanent, but for any item listed below, equivalent functionality is |
|
676 | 676 | available. |
|
677 | 677 | |
|
678 | 678 | * The magics Exit and Quit have been dropped as ways to exit IPython. Instead, |
|
679 | 679 | the lowercase forms of both work either as a bare name (``exit``) or a |
|
680 | 680 | function call (``exit()``). You can assign these to other names using |
|
681 | 681 | exec_lines in the config file. |
|
682 | 682 | |
|
683 | 683 | |
|
684 |
.. _credits_011: |
|
|
684 | .. _credits_011: | |
|
685 | 685 | |
|
686 | 686 | Credits |
|
687 | 687 | ------- |
|
688 | 688 | |
|
689 | 689 | Many users and developers contributed code, features, bug reports and ideas to |
|
690 | 690 | this release. Please do not hesitate in contacting us if we've failed to |
|
691 | 691 | acknowledge your contribution here. In particular, for this release we have |
|
692 | 692 | contribution from the following people, a mix of new and regular names (in |
|
693 | 693 | alphabetical order by first name): |
|
694 | 694 | |
|
695 | 695 | * Aenugu Sai Kiran Reddy <saikrn08-at-gmail.com> |
|
696 | 696 | * andy wilson <wilson.andrew.j+github-at-gmail.com> |
|
697 | 697 | * Antonio Cuni <antocuni> |
|
698 | 698 | * Barry Wark <barrywark-at-gmail.com> |
|
699 | 699 | * Beetoju Anuradha <anu.beethoju-at-gmail.com> |
|
700 | 700 | * Benjamin Ragan-Kelley <minrk-at-Mercury.local> |
|
701 | 701 | * Brad Reisfeld |
|
702 | 702 | * Brian E. Granger <ellisonbg-at-gmail.com> |
|
703 | 703 | * Christoph Gohlke <cgohlke-at-uci.edu> |
|
704 | 704 | * Cody Precord |
|
705 | 705 | * dan.milstein |
|
706 | 706 | * Darren Dale <dsdale24-at-gmail.com> |
|
707 | 707 | * Dav Clark <davclark-at-berkeley.edu> |
|
708 | 708 | * David Warde-Farley <wardefar-at-iro.umontreal.ca> |
|
709 | 709 | * epatters <ejpatters-at-gmail.com> |
|
710 | 710 | * epatters <epatters-at-caltech.edu> |
|
711 | 711 | * epatters <epatters-at-enthought.com> |
|
712 | 712 | * Eric Firing <efiring-at-hawaii.edu> |
|
713 | 713 | * Erik Tollerud <erik.tollerud-at-gmail.com> |
|
714 | 714 | * Evan Patterson <epatters-at-enthought.com> |
|
715 | 715 | * Fernando Perez <Fernando.Perez-at-berkeley.edu> |
|
716 | 716 | * Gael Varoquaux <gael.varoquaux-at-normalesup.org> |
|
717 | 717 | * Gerardo <muzgash-at-Muzpelheim> |
|
718 | 718 | * Jason Grout <jason.grout-at-drake.edu> |
|
719 | 719 | * John Hunter <jdh2358-at-gmail.com> |
|
720 | 720 | * Jens Hedegaard Nielsen <jenshnielsen-at-gmail.com> |
|
721 | 721 | * Johann Cohen-Tanugi <johann.cohentanugi-at-gmail.com> |
|
722 | 722 | * JΓΆrgen Stenarson <jorgen.stenarson-at-bostream.nu> |
|
723 | 723 | * Justin Riley <justin.t.riley-at-gmail.com> |
|
724 | 724 | * Kiorky |
|
725 | 725 | * Laurent Dufrechou <laurent.dufrechou-at-gmail.com> |
|
726 | 726 | * Luis Pedro Coelho <lpc-at-cmu.edu> |
|
727 | 727 | * Mani chandra <mchandra-at-iitk.ac.in> |
|
728 | 728 | * Mark E. Smith |
|
729 | 729 | * Mark Voorhies <mark.voorhies-at-ucsf.edu> |
|
730 | 730 | * Martin Spacek <git-at-mspacek.mm.st> |
|
731 | 731 | * Michael Droettboom <mdroe-at-stsci.edu> |
|
732 | 732 | * MinRK <benjaminrk-at-gmail.com> |
|
733 | 733 | * muzuiget <muzuiget-at-gmail.com> |
|
734 | 734 | * Nick Tarleton <nick-at-quixey.com> |
|
735 | 735 | * Nicolas Rougier <Nicolas.rougier-at-inria.fr> |
|
736 | 736 | * Omar Andres Zapata Mesa <andresete.chaos-at-gmail.com> |
|
737 | 737 | * Paul Ivanov <pivanov314-at-gmail.com> |
|
738 | 738 | * Pauli Virtanen <pauli.virtanen-at-iki.fi> |
|
739 | 739 | * Prabhu Ramachandran |
|
740 | 740 | * Ramana <sramana9-at-gmail.com> |
|
741 | 741 | * Robert Kern <robert.kern-at-gmail.com> |
|
742 | 742 | * Sathesh Chandra <satheshchandra88-at-gmail.com> |
|
743 | 743 | * Satrajit Ghosh <satra-at-mit.edu> |
|
744 | 744 | * Sebastian Busch |
|
745 | 745 | * Skipper Seabold <jsseabold-at-gmail.com> |
|
746 | 746 | * Stefan van der Walt <bzr-at-mentat.za.net> |
|
747 | 747 | * Stephan Peijnik <debian-at-sp.or.at> |
|
748 | 748 | * Steven Bethard |
|
749 | 749 | * Thomas Kluyver <takowl-at-gmail.com> |
|
750 | 750 | * Thomas Spura <tomspur-at-fedoraproject.org> |
|
751 | 751 | * Tom Fetherston <tfetherston-at-aol.com> |
|
752 | 752 | * Tom MacWright |
|
753 | 753 | * tzanko |
|
754 | 754 | * vankayala sowjanya <hai.sowjanya-at-gmail.com> |
|
755 | 755 | * Vivian De Smedt <vds2212-at-VIVIAN> |
|
756 | 756 | * Ville M. Vainio <vivainio-at-gmail.com> |
|
757 | 757 | * Vishal Vatsa <vishal.vatsa-at-gmail.com> |
|
758 | 758 | * Vishnu S G <sgvishnu777-at-gmail.com> |
|
759 | 759 | * Walter Doerwald <walter-at-livinglogic.de> |
|
760 | 760 | |
|
761 | 761 | .. note:: |
|
762 | 762 | |
|
763 | 763 | This list was generated with the output of |
|
764 | 764 | ``git log dev-0.11 HEAD --format='* %aN <%aE>' | sed 's/@/\-at\-/' | sed 's/<>//' | sort -u`` |
|
765 | 765 | after some cleanup. If you should be on this list, please add yourself. |
@@ -1,370 +1,370 b'' | |||
|
1 | 1 | ============= |
|
2 | 2 | 0.12 Series |
|
3 | 3 | ============= |
|
4 | 4 | |
|
5 | 5 | Release 0.12.1 |
|
6 | 6 | ============== |
|
7 | 7 | |
|
8 | 8 | IPython 0.12.1 is a bugfix release of 0.12, pulling only bugfixes and minor |
|
9 | 9 | cleanup from 0.13, timed for the Ubuntu 12.04 LTS release. |
|
10 | 10 | |
|
11 | 11 | See the :ref:`list of fixed issues <issues_list_012>` for specific backported issues. |
|
12 | 12 | |
|
13 | 13 | |
|
14 | 14 | Release 0.12 |
|
15 | 15 | ============ |
|
16 | 16 | |
|
17 | 17 | IPython 0.12 contains several major new features, as well as a large amount of |
|
18 | 18 | bug and regression fixes. The 0.11 release brought with it a lot of new |
|
19 | 19 | functionality and major refactorings of the codebase; by and large this has |
|
20 | 20 | proven to be a success as the number of contributions to the project has |
|
21 | 21 | increased dramatically, proving that the code is now much more approachable. |
|
22 | 22 | But in the refactoring inevitably some bugs were introduced, and we have also |
|
23 | 23 | squashed many of those as well as recovered some functionality that had been |
|
24 | 24 | temporarily disabled due to the API changes. |
|
25 | 25 | |
|
26 | 26 | The following major new features appear in this version. |
|
27 | 27 | |
|
28 | 28 | |
|
29 | 29 | An interactive browser-based Notebook with rich media support |
|
30 | 30 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
31 | 31 | |
|
32 | 32 | A powerful new interface puts IPython in your browser. You can start it with |
|
33 | 33 | the command ``ipython notebook``: |
|
34 | 34 | |
|
35 | 35 | .. figure:: ../_static/notebook_specgram.png |
|
36 | 36 | :width: 400px |
|
37 | 37 | :alt: The IPython notebook with embedded text, code, math and figures. |
|
38 | 38 | :align: center |
|
39 | 39 | :target: ../_static/notebook_specgram.png |
|
40 | 40 | |
|
41 | 41 | The new IPython notebook showing text, mathematical expressions in LaTeX, |
|
42 | 42 | code, results and embedded figures created with Matplotlib. |
|
43 | 43 | |
|
44 | 44 | This new interface maintains all the features of IPython you are used to, as it |
|
45 | 45 | is a new client that communicates with the same IPython kernels used by the |
|
46 | 46 | terminal and Qt console. But the web notebook provides for a different |
|
47 | 47 | workflow where you can integrate, along with code execution, also text, |
|
48 | 48 | mathematical expressions, graphics, video, and virtually any content that a |
|
49 | 49 | modern browser is capable of displaying. |
|
50 | 50 | |
|
51 | 51 | You can save your work sessions as documents that retain all these elements and |
|
52 | 52 | which can be version controlled, emailed to colleagues or saved as HTML or PDF |
|
53 | 53 | files for printing or publishing statically on the web. The internal storage |
|
54 | 54 | format is a JSON file that can be easily manipulated for manual exporting to |
|
55 | 55 | other formats. |
|
56 | 56 | |
|
57 | 57 | This Notebook is a major milestone for IPython, as for years we have tried to |
|
58 | 58 | build this kind of system. We were inspired originally by the excellent |
|
59 | 59 | implementation in Mathematica, we made a number of attempts using older |
|
60 | 60 | technologies in earlier Summer of Code projects in 2005 (both students and |
|
61 | 61 | Robert Kern developed early prototypes), and in recent years we have seen the |
|
62 | 62 | excellent implementation offered by the `Sage <http://sagemath.org>` system. |
|
63 | 63 | But we continued to work on something that would be consistent with the rest of |
|
64 | 64 | IPython's design, and it is clear now that the effort was worth it: based on |
|
65 | 65 | the ZeroMQ communications architecture introduced in version 0.11, the notebook |
|
66 | 66 | can now retain 100% of the features of the real IPython. But it can also |
|
67 | 67 | provide the rich media support and high quality Javascript libraries that were |
|
68 | 68 | not available in browsers even one or two years ago (such as high-quality |
|
69 | 69 | mathematical rendering or built-in video). |
|
70 | 70 | |
|
71 | 71 | The notebook has too many useful and important features to describe in these |
|
72 | 72 | release notes; our documentation now contains a directory called |
|
73 | 73 | ``examples/notebooks`` with several notebooks that illustrate various aspects |
|
74 | 74 | of the system. You should start by reading those named |
|
75 | 75 | ``00_notebook_tour.ipynb`` and ``01_notebook_introduction.ipynb`` first, and |
|
76 | 76 | then can proceed to read the others in any order you want. |
|
77 | 77 | |
|
78 | 78 | To start the notebook server, go to a directory containing the notebooks you |
|
79 | 79 | want to open (or where you want to create new ones) and type:: |
|
80 | 80 | |
|
81 | 81 | ipython notebook |
|
82 | 82 | |
|
83 | 83 | You can see all the relevant options with:: |
|
84 | 84 | |
|
85 | 85 | ipython notebook --help |
|
86 | 86 | ipython notebook --help-all # even more |
|
87 | 87 | |
|
88 | 88 | and just like the Qt console, you can start the notebook server with pylab |
|
89 | 89 | support by using:: |
|
90 | 90 | |
|
91 | 91 | ipython notebook --pylab |
|
92 | 92 | |
|
93 | 93 | for floating matplotlib windows or:: |
|
94 | 94 | |
|
95 | 95 | ipython notebook --pylab inline |
|
96 | 96 | |
|
97 | 97 | for plotting support with automatically inlined figures. Note that it is now |
|
98 | 98 | possible also to activate pylab support at runtime via ``%pylab``, so you do |
|
99 | 99 | not need to make this decision when starting the server. |
|
100 | 100 | |
|
101 | 101 | See :ref:`the Notebook docs <htmlnotebook>` for technical details. |
|
102 | 102 | |
|
103 | 103 | .. _two_process_console: |
|
104 | 104 | |
|
105 | 105 | Two-process terminal console |
|
106 | 106 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
107 | 107 | |
|
108 | 108 | Based on the same architecture as the notebook and the Qt console, we also have |
|
109 | 109 | now a terminal-based console that can connect to an external IPython kernel |
|
110 | 110 | (the same kernels used by the Qt console or the notebook, in fact). While this |
|
111 | 111 | client behaves almost identically to the usual IPython terminal application, |
|
112 | 112 | this capability can be very useful to attach an interactive console to an |
|
113 | 113 | existing kernel that was started externally. It lets you use the interactive |
|
114 | 114 | ``%debug`` facilities in a notebook, for example (the web browser can't |
|
115 | 115 | interact directly with the debugger) or debug a third-party code where you may |
|
116 | 116 | have embedded an IPython kernel. |
|
117 | 117 | |
|
118 | 118 | This is also something that we have wanted for a long time, and which is a |
|
119 | 119 | culmination (as a team effort) of the work started last year during the 2010 |
|
120 | 120 | Google Summer of Code project. |
|
121 | 121 | |
|
122 | 122 | Tabbed QtConsole |
|
123 | 123 | ~~~~~~~~~~~~~~~~ |
|
124 | 124 | |
|
125 | 125 | The QtConsole now supports starting multiple kernels in tabs, and has a |
|
126 | 126 | menubar, so it looks and behaves more like a real application. Keyboard |
|
127 | 127 | enthusiasts can disable the menubar with ctrl-shift-M (:ghpull:`887`). |
|
128 | 128 | |
|
129 | 129 | .. figure:: ../_static/qtconsole_tabbed.png |
|
130 | 130 | :width: 400px |
|
131 | 131 | :alt: Tabbed IPython Qt console with embedded plots and menus. |
|
132 | 132 | :align: center |
|
133 | 133 | :target: ../_static/qtconsole_tabbed.png |
|
134 | 134 | |
|
135 | 135 | The improved Qt console for IPython, now with tabs to control multiple |
|
136 | 136 | kernels and full menu support. |
|
137 | 137 | |
|
138 | 138 | |
|
139 | 139 | Full Python 3 compatibility |
|
140 | 140 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
141 | 141 | |
|
142 | 142 | IPython can now be installed from a single codebase on Python 2 and |
|
143 | 143 | Python 3. The installation process for Python 3 automatically runs 2to3. The |
|
144 | 144 | same 'default' profile is now used for Python 2 and 3 (the previous version had |
|
145 | 145 | a separate 'python3' profile). |
|
146 | 146 | |
|
147 | 147 | Standalone Kernel |
|
148 | 148 | ~~~~~~~~~~~~~~~~~ |
|
149 | 149 | |
|
150 | 150 | The ``ipython kernel`` subcommand has been added, to allow starting a |
|
151 | 151 | standalone kernel, that can be used with various frontends. You can then later |
|
152 | 152 | connect a Qt console or a terminal console to this kernel by typing e.g.:: |
|
153 | 153 | |
|
154 | 154 | ipython qtconsole --existing |
|
155 | 155 | |
|
156 | 156 | if it's the only one running, or by passing explicitly the connection |
|
157 | 157 | parameters (printed by the kernel at startup). |
|
158 | 158 | |
|
159 | 159 | |
|
160 | 160 | PyPy support |
|
161 | 161 | ~~~~~~~~~~~~ |
|
162 | 162 | |
|
163 | 163 | The terminal interface to IPython now runs under `PyPy <http://pypy.org/>`_. |
|
164 | 164 | We will continue to monitor PyPy's progress, and hopefully before long at least |
|
165 | 165 | we'll be able to also run the notebook. The Qt console may take longer, as Qt |
|
166 | 166 | is a very complex set of bindings to a huge C++ library, and that is currently |
|
167 | 167 | the area where PyPy still lags most behind. But for everyday interactive use |
|
168 | 168 | at the terminal, with this release and PyPy 1.7, things seem to work quite well |
|
169 | 169 | from our admittedly limited testing. |
|
170 | 170 | |
|
171 | 171 | |
|
172 | 172 | Other important new features |
|
173 | 173 | ---------------------------- |
|
174 | 174 | |
|
175 | 175 | * **SSH Tunnels**: In 0.11, the :mod:`IPython.parallel` Client could tunnel its |
|
176 | 176 | connections to the Controller via ssh. Now, the QtConsole :ref:`supports |
|
177 | 177 | <ssh_tunnels>` ssh tunneling, as do parallel engines. |
|
178 | 178 | |
|
179 | 179 | * **relaxed command-line parsing**: 0.11 was released with overly-strict |
|
180 | 180 | command-line parsing, preventing the ability to specify arguments with spaces, |
|
181 | 181 | e.g. ``ipython --pylab qt`` or ``ipython -c "print 'hi'"``. This has |
|
182 | 182 | been fixed, by using argparse. The new parsing is a strict superset of 0.11, so |
|
183 | 183 | any commands in 0.11 should still work in 0.12. |
|
184 | 184 | |
|
185 | 185 | * **HistoryAccessor**: The :class:`~IPython.core.history.HistoryManager` class |
|
186 | 186 | for interacting with your IPython SQLite history database has been split, |
|
187 | 187 | adding a parent :class:`~IPython.core.history.HistoryAccessor` class, so that |
|
188 | 188 | users can write code to access and search their IPython history without being |
|
189 | 189 | in an IPython session (:ghpull:`824`). |
|
190 | 190 | |
|
191 | 191 | * **kernel %gui and %pylab**: The ``%gui`` and ``%pylab`` magics have been |
|
192 | 192 | restored to the IPython kernel (e.g. in the qtconsole or notebook). This |
|
193 | 193 | allows activation of pylab-mode, or eventloop integration after starting the |
|
194 | 194 | kernel, which was unavailable in 0.11. Unlike in the terminal, this can be |
|
195 | 195 | set only once, and cannot be changed. |
|
196 | 196 | |
|
197 | 197 | * **%config**: A new ``%config`` magic has been added, giving easy access to the |
|
198 | 198 | IPython configuration system at runtime (:ghpull:`923`). |
|
199 | 199 | |
|
200 | 200 | * **Multiline History**: Multiline readline history has been restored to the |
|
201 | 201 | Terminal frontend by default (:ghpull:`838`). |
|
202 | 202 | |
|
203 | 203 | * **%store**: The ``%store`` magic from earlier versions has been updated and |
|
204 | 204 | re-enabled (:ref:`extensions_storemagic`; :ghpull:`1029`). To autorestore |
|
205 | 205 | stored variables on startup, specify ``c.StoreMagic.autorestore = True`` in |
|
206 | 206 | :file:`ipython_config.py`. |
|
207 | 207 | |
|
208 | 208 | |
|
209 | 209 | Major Bugs fixed |
|
210 | 210 | ---------------- |
|
211 | 211 | |
|
212 | 212 | In this cycle, we have :ref:`closed over 500 issues <issues_list_012>`, but a |
|
213 | 213 | few major ones merit special mention: |
|
214 | 214 | |
|
215 | 215 | * Simple configuration errors should no longer crash IPython. In 0.11, errors |
|
216 | 216 | in config files, as well as invalid trait values, could crash IPython. Now, |
|
217 | 217 | such errors are reported, and help is displayed. |
|
218 | 218 | |
|
219 | 219 | * Certain SyntaxErrors no longer crash IPython (e.g. just typing keywords, such |
|
220 | 220 | as ``return``, ``break``, etc.). See :ghissue:`704`. |
|
221 | 221 | |
|
222 | 222 | * IPython path utils, such as :func:`~IPython.utils.path.get_ipython_dir` now |
|
223 | 223 | check for write permissions, so IPython should function on systems where the |
|
224 | 224 | default path resolution might point to a read-only location, such as |
|
225 | 225 | ``HOMESHARE`` on Windows (:ghissue:`669`). |
|
226 | 226 | |
|
227 | 227 | * :func:`raw_input` now works in the kernel when multiple frontends are in |
|
228 | 228 | use. The request will be sent to the frontend that made the request, and an |
|
229 | 229 | exception is raised if that frontend does not support stdin requests |
|
230 | 230 | (e.g. the notebook) (:ghissue:`673`). |
|
231 | 231 | |
|
232 | 232 | * :mod:`zmq` version detection no longer uses simple lexicographical comparison |
|
233 | 233 | to check minimum version, which prevents 0.11 from working with pyzmq-2.1.10 |
|
234 | 234 | (:ghpull:`758`). |
|
235 | 235 | |
|
236 | 236 | * A bug in PySide < 1.0.7 caused crashes on OSX when tooltips were shown |
|
237 | 237 | (:ghissue:`711`). these tooltips are now disabled on old PySide |
|
238 | 238 | (:ghpull:`963`). |
|
239 | 239 | |
|
240 | 240 | * IPython no longer crashes when started on recent versions of Python 3 in |
|
241 | 241 | Windows (:ghissue:`737`). |
|
242 | 242 | |
|
243 | 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, | |
|
245 | so unpickling the instances will only work where the class has been defined. | |
|
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. | |
|
246 | 246 | |
|
247 | 247 | |
|
248 | 248 | Backwards incompatible changes |
|
249 | 249 | ------------------------------ |
|
250 | 250 | |
|
251 | 251 | * IPython connection information is no longer specified via ip/port directly, |
|
252 | 252 | rather via json connection files. These files are stored in the security |
|
253 | 253 | directory, and enable us to turn on HMAC message authentication by default, |
|
254 | 254 | significantly improving the security of kernels. Various utility functions |
|
255 | 255 | have been added to :mod:`IPython.lib.kernel`, for easier connecting to existing |
|
256 | 256 | kernels. |
|
257 | 257 | |
|
258 | 258 | * :class:`~IPython.zmq.kernelmanager.KernelManager` now has one ip, and several |
|
259 | 259 | port traits, rather than several ip/port pair ``_addr`` traits. This better |
|
260 | 260 | matches the rest of the code, where the ip cannot not be set separately for |
|
261 | 261 | each channel. |
|
262 | 262 | |
|
263 | 263 | * Custom prompts are now configured using a new class, |
|
264 | :class:`~IPython.core.prompts.PromptManager`, which has traits for | |
|
265 | :attr:`in_template`, :attr:`in2_template` (the ``...:`` continuation prompt), | |
|
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 | |
|
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 | |
|
270 | source of :file:`IPython/core/prompts.py`. | |
|
264 | :class:`~IPython.core.prompts.PromptManager`, which has traits for | |
|
265 | :attr:`in_template`, :attr:`in2_template` (the ``...:`` continuation prompt), | |
|
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 | |
|
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 | |
|
270 | source of :file:`IPython/core/prompts.py`. | |
|
271 | 271 | |
|
272 | 272 | * The class inheritance of the Launchers in |
|
273 | 273 | :mod:`IPython.parallel.apps.launcher` used by ipcluster has changed, so that |
|
274 | 274 | trait names are more consistent across batch systems. This may require a few |
|
275 | 275 | renames in your config files, if you customized the command-line args for |
|
276 | 276 | launching controllers and engines. The configurable names have also been |
|
277 | 277 | changed to be clearer that they point to class names, and can now be |
|
278 | 278 | specified by name only, rather than requiring the full import path of each |
|
279 | 279 | class, e.g.:: |
|
280 | 280 | |
|
281 | 281 | IPClusterEngines.engine_launcher = 'IPython.parallel.apps.launcher.MPIExecEngineSetLauncher' |
|
282 | 282 | IPClusterStart.controller_launcher = 'IPython.parallel.apps.launcher.SSHControllerLauncher' |
|
283 | 283 | |
|
284 | 284 | would now be specified as:: |
|
285 | 285 | |
|
286 | 286 | IPClusterEngines.engine_launcher_class = 'MPI' |
|
287 | 287 | IPClusterStart.controller_launcher_class = 'SSH' |
|
288 | 288 | |
|
289 | 289 | The full path will still work, and is necessary for using custom launchers |
|
290 | 290 | not in IPython's launcher module. |
|
291 | 291 | |
|
292 | 292 | Further, MPIExec launcher names are now prefixed with just MPI, to better match |
|
293 | 293 | other batch launchers, and be generally more intuitive. The MPIExec names are |
|
294 | 294 | deprecated, but continue to work. |
|
295 | 295 | |
|
296 | 296 | * For embedding a shell, note that the parameters ``user_global_ns`` and |
|
297 | 297 | ``global_ns`` have been deprectated in favour of ``user_module`` and |
|
298 | 298 | ``module`` respsectively. The new parameters expect a module-like object, |
|
299 | 299 | rather than a namespace dict. The old parameters remain for backwards |
|
300 | 300 | compatibility, although ``user_global_ns`` is now ignored. The ``user_ns`` |
|
301 | 301 | parameter works the same way as before, and calling |
|
302 | 302 | :func:`~IPython.frontend.terminal.embed.embed` with no arguments still works |
|
303 | 303 | as before. |
|
304 | 304 | |
|
305 | 305 | |
|
306 | 306 | Development summary and credits |
|
307 | 307 | ------------------------------- |
|
308 | 308 | |
|
309 | 309 | The previous version (IPython 0.11) was released on July 31 2011, so this |
|
310 | 310 | release cycle was roughly 4 1/2 months long, we closed a total of 515 issues, |
|
311 | 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 | 314 | Many users and developers contributed code, features, bug reports and ideas to |
|
315 | 315 | this release. Please do not hesitate in contacting us if we've failed to |
|
316 | 316 | acknowledge your contribution here. In particular, for this release we have |
|
317 | 317 | had commits from the following 45 contributors, a mix of new and regular names |
|
318 | 318 | (in alphabetical order by first name): |
|
319 | 319 | |
|
320 | 320 | * Alcides <alcides-at-do-not-span-me.com> |
|
321 | 321 | * Ben Edwards <bedwards-at-cs.unm.edu> |
|
322 | 322 | * Benjamin Ragan-Kelley <benjaminrk-at-gmail.com> |
|
323 | 323 | * Benjamin Thyreau <benjamin.thyreau-at-gmail.com> |
|
324 | 324 | * Bernardo B. Marques <bernardo.fire-at-gmail.com> |
|
325 | 325 | * Bernard Paulus <bprecyclebin-at-gmail.com> |
|
326 | 326 | * Bradley M. Froehle <brad.froehle-at-gmail.com> |
|
327 | 327 | * Brian E. Granger <ellisonbg-at-gmail.com> |
|
328 | 328 | * Christian Boos <cboos-at-bct-technology.com> |
|
329 | 329 | * Daniel Velkov <danielv-at-mylife.com> |
|
330 | 330 | * Erik Tollerud <erik.tollerud-at-gmail.com> |
|
331 | 331 | * Evan Patterson <epatters-at-enthought.com> |
|
332 | 332 | * Felix Werner <Felix.Werner-at-kit.edu> |
|
333 | 333 | * Fernando Perez <Fernando.Perez-at-berkeley.edu> |
|
334 | 334 | * Gabriel <g2p.code-at-gmail.com> |
|
335 | 335 | * Grahame Bowland <grahame-at-angrygoats.net> |
|
336 | 336 | * Hannes Schulz <schulz-at-ais.uni-bonn.de> |
|
337 | 337 | * Jens Hedegaard Nielsen <jenshnielsen-at-gmail.com> |
|
338 | 338 | * Jonathan March <jmarch-at-enthought.com> |
|
339 | 339 | * JΓΆrgen Stenarson <jorgen.stenarson-at-bostream.nu> |
|
340 | 340 | * Julian Taylor <jtaylor.debian-at-googlemail.com> |
|
341 | 341 | * Kefu Chai <tchaikov-at-gmail.com> |
|
342 | 342 | * macgyver <neil.rabinowitz-at-merton.ox.ac.uk> |
|
343 | 343 | * Matt Cottingham <matt.cottingham-at-gmail.com> |
|
344 | 344 | * Matthew Brett <matthew.brett-at-gmail.com> |
|
345 | 345 | * Matthias BUSSONNIER <bussonniermatthias-at-gmail.com> |
|
346 | 346 | * Michael Droettboom <mdboom-at-gmail.com> |
|
347 | 347 | * Nicolas Rougier <Nicolas.Rougier-at-inria.fr> |
|
348 | 348 | * Olivier Verdier <olivier.verdier-at-gmail.com> |
|
349 | 349 | * Omar Andres Zapata Mesa <andresete.chaos-at-gmail.com> |
|
350 | 350 | * Pablo Winant <pablo.winant-at-gmail.com> |
|
351 | 351 | * Paul Ivanov <pivanov314-at-gmail.com> |
|
352 | 352 | * Pauli Virtanen <pav-at-iki.fi> |
|
353 | 353 | * Pete Aykroyd <aykroyd-at-gmail.com> |
|
354 | 354 | * Prabhu Ramachandran <prabhu-at-enthought.com> |
|
355 | 355 | * Puneeth Chaganti <punchagan-at-gmail.com> |
|
356 | 356 | * Robert Kern <robert.kern-at-gmail.com> |
|
357 | 357 | * Satrajit Ghosh <satra-at-mit.edu> |
|
358 | 358 | * Stefan van der Walt <stefan-at-sun.ac.za> |
|
359 | 359 | * Szabolcs HorvΓ‘t <szhorvat-at-gmail.com> |
|
360 | 360 | * Thomas Kluyver <takowl-at-gmail.com> |
|
361 | 361 | * Thomas Spura <thomas.spura-at-gmail.com> |
|
362 | 362 | * Timo Paulssen <timonator-at-perpetuum-immobile.de> |
|
363 | 363 | * Valentin Haenel <valentin.haenel-at-gmx.de> |
|
364 | 364 | * Yaroslav Halchenko <debian-at-onerussian.com> |
|
365 | 365 | |
|
366 | 366 | .. note:: |
|
367 | 367 | |
|
368 | 368 | This list was generated with the output of |
|
369 | 369 | ``git log rel-0.11..HEAD --format='* %aN <%aE>' | sed 's/@/\-at\-/' | sed 's/<>//' | sort -u`` |
|
370 | 370 | after some cleanup. If you should be on this list, please add yourself. |
@@ -1,414 +1,411 b'' | |||
|
1 | 1 | """Attempt to generate templates for module reference with Sphinx |
|
2 | 2 | |
|
3 | 3 | XXX - we exclude extension modules |
|
4 | 4 | |
|
5 | 5 | To include extension modules, first identify them as valid in the |
|
6 | 6 | ``_uri2path`` method, then handle them in the ``_parse_module`` script. |
|
7 | 7 | |
|
8 | 8 | We get functions and classes by parsing the text of .py files. |
|
9 | 9 | Alternatively we could import the modules for discovery, and we'd have |
|
10 | 10 | to do that for extension modules. This would involve changing the |
|
11 | 11 | ``_parse_module`` method to work via import and introspection, and |
|
12 | 12 | might involve changing ``discover_modules`` (which determines which |
|
13 | 13 | files are modules, and therefore which module URIs will be passed to |
|
14 | 14 | ``_parse_module``). |
|
15 | 15 | |
|
16 | 16 | NOTE: this is a modified version of a script originally shipped with the |
|
17 | 17 | PyMVPA project, which we've adapted for NIPY use. PyMVPA is an MIT-licensed |
|
18 | 18 | project.""" |
|
19 | 19 | |
|
20 | 20 | # Stdlib imports |
|
21 | 21 | import ast |
|
22 | 22 | import os |
|
23 | 23 | import re |
|
24 | 24 | |
|
25 | 25 | class Obj(object): |
|
26 | 26 | '''Namespace to hold arbitrary information.''' |
|
27 | 27 | def __init__(self, **kwargs): |
|
28 | 28 | for k, v in kwargs.items(): |
|
29 | 29 | setattr(self, k, v) |
|
30 | 30 | |
|
31 | 31 | class FuncClsScanner(ast.NodeVisitor): |
|
32 | 32 | """Scan a module for top-level functions and classes. |
|
33 | 33 | |
|
34 | 34 | Skips objects with an @undoc decorator, or a name starting with '_'. |
|
35 | 35 | """ |
|
36 | 36 | def __init__(self): |
|
37 | 37 | ast.NodeVisitor.__init__(self) |
|
38 | 38 | self.classes = [] |
|
39 | 39 | self.classes_seen = set() |
|
40 | 40 | self.functions = [] |
|
41 | 41 | |
|
42 | 42 | @staticmethod |
|
43 | 43 | def has_undoc_decorator(node): |
|
44 | 44 | return any(isinstance(d, ast.Name) and d.id == 'undoc' \ |
|
45 | 45 | for d in node.decorator_list) |
|
46 | 46 | |
|
47 | 47 | def visit_FunctionDef(self, node): |
|
48 | 48 | if not (node.name.startswith('_') or self.has_undoc_decorator(node)) \ |
|
49 | 49 | and node.name not in self.functions: |
|
50 | 50 | self.functions.append(node.name) |
|
51 | 51 | |
|
52 | 52 | def visit_ClassDef(self, node): |
|
53 | 53 | if not (node.name.startswith('_') or self.has_undoc_decorator(node)) \ |
|
54 | 54 | and node.name not in self.classes_seen: |
|
55 | 55 | cls = Obj(name=node.name) |
|
56 | 56 | cls.has_init = any(isinstance(n, ast.FunctionDef) and \ |
|
57 | 57 | n.name=='__init__' for n in node.body) |
|
58 | 58 | self.classes.append(cls) |
|
59 | 59 | self.classes_seen.add(node.name) |
|
60 | 60 | |
|
61 | 61 | def scan(self, mod): |
|
62 | 62 | self.visit(mod) |
|
63 | 63 | return self.functions, self.classes |
|
64 | 64 | |
|
65 | 65 | # Functions and classes |
|
66 | 66 | class ApiDocWriter(object): |
|
67 | 67 | ''' Class for automatic detection and parsing of API docs |
|
68 | 68 | to Sphinx-parsable reST format''' |
|
69 | 69 | |
|
70 | 70 | # only separating first two levels |
|
71 | 71 | rst_section_levels = ['*', '=', '-', '~', '^'] |
|
72 | 72 | |
|
73 | 73 | def __init__(self, |
|
74 | 74 | package_name, |
|
75 | 75 | rst_extension='.rst', |
|
76 | 76 | package_skip_patterns=None, |
|
77 | 77 | module_skip_patterns=None, |
|
78 | 78 | ): |
|
79 | 79 | ''' Initialize package for parsing |
|
80 | 80 | |
|
81 | 81 | Parameters |
|
82 | 82 | ---------- |
|
83 | 83 | package_name : string |
|
84 | 84 | Name of the top-level package. *package_name* must be the |
|
85 | 85 | name of an importable package |
|
86 | 86 | rst_extension : string, optional |
|
87 | 87 | Extension for reST files, default '.rst' |
|
88 | 88 | package_skip_patterns : None or sequence of {strings, regexps} |
|
89 | 89 | Sequence of strings giving URIs of packages to be excluded |
|
90 | 90 | Operates on the package path, starting at (including) the |
|
91 | 91 | first dot in the package path, after *package_name* - so, |
|
92 | 92 | if *package_name* is ``sphinx``, then ``sphinx.util`` will |
|
93 | 93 | result in ``.util`` being passed for earching by these |
|
94 | 94 | regexps. If is None, gives default. Default is: |
|
95 | 95 | ['\.tests$'] |
|
96 | 96 | module_skip_patterns : None or sequence |
|
97 | 97 | Sequence of strings giving URIs of modules to be excluded |
|
98 | 98 | Operates on the module name including preceding URI path, |
|
99 | 99 | back to the first dot after *package_name*. For example |
|
100 | 100 | ``sphinx.util.console`` results in the string to search of |
|
101 | 101 | ``.util.console`` |
|
102 | 102 | If is None, gives default. Default is: |
|
103 | 103 | ['\.setup$', '\._'] |
|
104 | 104 | ''' |
|
105 | 105 | if package_skip_patterns is None: |
|
106 | 106 | package_skip_patterns = ['\\.tests$'] |
|
107 | 107 | if module_skip_patterns is None: |
|
108 | 108 | module_skip_patterns = ['\\.setup$', '\\._'] |
|
109 | 109 | self.package_name = package_name |
|
110 | 110 | self.rst_extension = rst_extension |
|
111 | 111 | self.package_skip_patterns = package_skip_patterns |
|
112 | 112 | self.module_skip_patterns = module_skip_patterns |
|
113 | 113 | |
|
114 | 114 | def get_package_name(self): |
|
115 | 115 | return self._package_name |
|
116 | 116 | |
|
117 | 117 | def set_package_name(self, package_name): |
|
118 | 118 | ''' Set package_name |
|
119 | 119 | |
|
120 | 120 | >>> docwriter = ApiDocWriter('sphinx') |
|
121 | 121 | >>> import sphinx |
|
122 | 122 | >>> docwriter.root_path == sphinx.__path__[0] |
|
123 | 123 | True |
|
124 | 124 | >>> docwriter.package_name = 'docutils' |
|
125 | 125 | >>> import docutils |
|
126 | 126 | >>> docwriter.root_path == docutils.__path__[0] |
|
127 | 127 | True |
|
128 | 128 | ''' |
|
129 | 129 | # It's also possible to imagine caching the module parsing here |
|
130 | 130 | self._package_name = package_name |
|
131 | 131 | self.root_module = __import__(package_name) |
|
132 | 132 | self.root_path = self.root_module.__path__[0] |
|
133 | 133 | self.written_modules = None |
|
134 | 134 | |
|
135 | 135 | package_name = property(get_package_name, set_package_name, None, |
|
136 | 136 | 'get/set package_name') |
|
137 | 137 | |
|
138 | 138 | def _uri2path(self, uri): |
|
139 | 139 | ''' Convert uri to absolute filepath |
|
140 | 140 | |
|
141 | 141 | Parameters |
|
142 | 142 | ---------- |
|
143 | 143 | uri : string |
|
144 | 144 | URI of python module to return path for |
|
145 | 145 | |
|
146 | 146 | Returns |
|
147 | 147 | ------- |
|
148 | 148 | path : None or string |
|
149 | 149 | Returns None if there is no valid path for this URI |
|
150 | 150 | Otherwise returns absolute file system path for URI |
|
151 | 151 | |
|
152 | 152 | Examples |
|
153 | 153 | -------- |
|
154 | 154 | >>> docwriter = ApiDocWriter('sphinx') |
|
155 | 155 | >>> import sphinx |
|
156 | 156 | >>> modpath = sphinx.__path__[0] |
|
157 | 157 | >>> res = docwriter._uri2path('sphinx.builder') |
|
158 | 158 | >>> res == os.path.join(modpath, 'builder.py') |
|
159 | 159 | True |
|
160 | 160 | >>> res = docwriter._uri2path('sphinx') |
|
161 | 161 | >>> res == os.path.join(modpath, '__init__.py') |
|
162 | 162 | True |
|
163 | 163 | >>> docwriter._uri2path('sphinx.does_not_exist') |
|
164 | 164 | |
|
165 | 165 | ''' |
|
166 | 166 | if uri == self.package_name: |
|
167 | 167 | return os.path.join(self.root_path, '__init__.py') |
|
168 | 168 | path = uri.replace('.', os.path.sep) |
|
169 | 169 | path = path.replace(self.package_name + os.path.sep, '') |
|
170 | 170 | path = os.path.join(self.root_path, path) |
|
171 | 171 | # XXX maybe check for extensions as well? |
|
172 | 172 | if os.path.exists(path + '.py'): # file |
|
173 | 173 | path += '.py' |
|
174 | 174 | elif os.path.exists(os.path.join(path, '__init__.py')): |
|
175 | 175 | path = os.path.join(path, '__init__.py') |
|
176 | 176 | else: |
|
177 | 177 | return None |
|
178 | 178 | return path |
|
179 | 179 | |
|
180 | 180 | def _path2uri(self, dirpath): |
|
181 | 181 | ''' Convert directory path to uri ''' |
|
182 | 182 | relpath = dirpath.replace(self.root_path, self.package_name) |
|
183 | 183 | if relpath.startswith(os.path.sep): |
|
184 | 184 | relpath = relpath[1:] |
|
185 | 185 | return relpath.replace(os.path.sep, '.') |
|
186 | 186 | |
|
187 | 187 | def _parse_module(self, uri): |
|
188 | 188 | ''' Parse module defined in *uri* ''' |
|
189 | 189 | filename = self._uri2path(uri) |
|
190 | 190 | if filename is None: |
|
191 | 191 | # nothing that we could handle here. |
|
192 | 192 | return ([],[]) |
|
193 | 193 | with open(filename, 'rb') as f: |
|
194 | 194 | mod = ast.parse(f.read()) |
|
195 | 195 | return FuncClsScanner().scan(mod) |
|
196 | 196 | |
|
197 | 197 | def generate_api_doc(self, uri): |
|
198 | 198 | '''Make autodoc documentation template string for a module |
|
199 | 199 | |
|
200 | 200 | Parameters |
|
201 | 201 | ---------- |
|
202 | 202 | uri : string |
|
203 | 203 | python location of module - e.g 'sphinx.builder' |
|
204 | 204 | |
|
205 | 205 | Returns |
|
206 | 206 | ------- |
|
207 | 207 | S : string |
|
208 | 208 | Contents of API doc |
|
209 | 209 | ''' |
|
210 | 210 | # get the names of all classes and functions |
|
211 | 211 | functions, classes = self._parse_module(uri) |
|
212 | 212 | if not len(functions) and not len(classes): |
|
213 | 213 | print 'WARNING: Empty -',uri # dbg |
|
214 | 214 | return '' |
|
215 | 215 | |
|
216 | 216 | # Make a shorter version of the uri that omits the package name for |
|
217 | 217 | # titles |
|
218 | 218 | uri_short = re.sub(r'^%s\.' % self.package_name,'',uri) |
|
219 | 219 | |
|
220 | 220 | ad = '.. AUTO-GENERATED FILE -- DO NOT EDIT!\n\n' |
|
221 | 221 | |
|
222 | 222 | # Set the chapter title to read 'Module:' for all modules except for the |
|
223 | 223 | # main packages |
|
224 | 224 | if '.' in uri: |
|
225 | 225 | chap_title = 'Module: :mod:`' + uri_short + '`' |
|
226 | 226 | else: |
|
227 | 227 | chap_title = ':mod:`' + uri_short + '`' |
|
228 | 228 | ad += chap_title + '\n' + self.rst_section_levels[1] * len(chap_title) |
|
229 | 229 | |
|
230 | 230 | ad += '\n.. automodule:: ' + uri + '\n' |
|
231 | 231 | ad += '\n.. currentmodule:: ' + uri + '\n' |
|
232 | 232 | |
|
233 | 233 | if classes: |
|
234 | 234 | subhead = str(len(classes)) + (' Classes' if len(classes) > 1 else ' Class') |
|
235 | 235 | ad += '\n'+ subhead + '\n' + \ |
|
236 | 236 | self.rst_section_levels[2] * len(subhead) + '\n' |
|
237 | 237 | |
|
238 | 238 | for c in classes: |
|
239 | 239 | ad += '\n.. autoclass:: ' + c.name + '\n' |
|
240 | 240 | # must NOT exclude from index to keep cross-refs working |
|
241 | 241 | ad += ' :members:\n' \ |
|
242 | 242 | ' :show-inheritance:\n' |
|
243 | 243 | if c.has_init: |
|
244 | 244 | ad += '\n .. automethod:: __init__\n' |
|
245 | 245 | |
|
246 | 246 | if functions: |
|
247 | 247 | subhead = str(len(functions)) + (' Functions' if len(functions) > 1 else ' Function') |
|
248 | 248 | ad += '\n'+ subhead + '\n' + \ |
|
249 | 249 | self.rst_section_levels[2] * len(subhead) + '\n' |
|
250 | 250 | for f in functions: |
|
251 | 251 | # must NOT exclude from index to keep cross-refs working |
|
252 | 252 | ad += '\n.. autofunction:: ' + uri + '.' + f + '\n\n' |
|
253 | 253 | return ad |
|
254 | 254 | |
|
255 | 255 | def _survives_exclude(self, matchstr, match_type): |
|
256 | 256 | ''' Returns True if *matchstr* does not match patterns |
|
257 | 257 | |
|
258 | 258 | ``self.package_name`` removed from front of string if present |
|
259 | 259 | |
|
260 | 260 | Examples |
|
261 | 261 | -------- |
|
262 | 262 | >>> dw = ApiDocWriter('sphinx') |
|
263 | 263 | >>> dw._survives_exclude('sphinx.okpkg', 'package') |
|
264 | 264 | True |
|
265 | 265 | >>> dw.package_skip_patterns.append('^\\.badpkg$') |
|
266 | 266 | >>> dw._survives_exclude('sphinx.badpkg', 'package') |
|
267 | 267 | False |
|
268 | 268 | >>> dw._survives_exclude('sphinx.badpkg', 'module') |
|
269 | 269 | True |
|
270 | 270 | >>> dw._survives_exclude('sphinx.badmod', 'module') |
|
271 | 271 | True |
|
272 | 272 | >>> dw.module_skip_patterns.append('^\\.badmod$') |
|
273 | 273 | >>> dw._survives_exclude('sphinx.badmod', 'module') |
|
274 | 274 | False |
|
275 | 275 | ''' |
|
276 | 276 | if match_type == 'module': |
|
277 | 277 | patterns = self.module_skip_patterns |
|
278 | 278 | elif match_type == 'package': |
|
279 | 279 | patterns = self.package_skip_patterns |
|
280 | 280 | else: |
|
281 | 281 | raise ValueError('Cannot interpret match type "%s"' |
|
282 | 282 | % match_type) |
|
283 | 283 | # Match to URI without package name |
|
284 | 284 | L = len(self.package_name) |
|
285 | 285 | if matchstr[:L] == self.package_name: |
|
286 | 286 | matchstr = matchstr[L:] |
|
287 | 287 | for pat in patterns: |
|
288 | 288 | try: |
|
289 | 289 | pat.search |
|
290 | 290 | except AttributeError: |
|
291 | 291 | pat = re.compile(pat) |
|
292 | 292 | if pat.search(matchstr): |
|
293 | 293 | return False |
|
294 | 294 | return True |
|
295 | 295 | |
|
296 | 296 | def discover_modules(self): |
|
297 | 297 | ''' Return module sequence discovered from ``self.package_name`` |
|
298 | 298 | |
|
299 | 299 | |
|
300 | 300 | Parameters |
|
301 | 301 | ---------- |
|
302 | 302 | None |
|
303 | 303 | |
|
304 | 304 | Returns |
|
305 | 305 | ------- |
|
306 | 306 | mods : sequence |
|
307 | 307 | Sequence of module names within ``self.package_name`` |
|
308 | 308 | |
|
309 | 309 | Examples |
|
310 | 310 | -------- |
|
311 | 311 | >>> dw = ApiDocWriter('sphinx') |
|
312 | 312 | >>> mods = dw.discover_modules() |
|
313 | 313 | >>> 'sphinx.util' in mods |
|
314 | 314 | True |
|
315 | 315 | >>> dw.package_skip_patterns.append('\.util$') |
|
316 | 316 | >>> 'sphinx.util' in dw.discover_modules() |
|
317 | 317 | False |
|
318 | 318 | >>> |
|
319 | 319 | ''' |
|
320 | 320 | modules = [self.package_name] |
|
321 | 321 | # raw directory parsing |
|
322 | 322 | for dirpath, dirnames, filenames in os.walk(self.root_path): |
|
323 | 323 | # Check directory names for packages |
|
324 | 324 | root_uri = self._path2uri(os.path.join(self.root_path, |
|
325 | 325 | dirpath)) |
|
326 | 326 | for dirname in dirnames[:]: # copy list - we modify inplace |
|
327 | 327 | package_uri = '.'.join((root_uri, dirname)) |
|
328 | 328 | if (self._uri2path(package_uri) and |
|
329 | 329 | self._survives_exclude(package_uri, 'package')): |
|
330 | 330 | modules.append(package_uri) |
|
331 | 331 | else: |
|
332 | 332 | dirnames.remove(dirname) |
|
333 | 333 | # Check filenames for modules |
|
334 | 334 | for filename in filenames: |
|
335 | 335 | module_name = filename[:-3] |
|
336 | 336 | module_uri = '.'.join((root_uri, module_name)) |
|
337 | 337 | if (self._uri2path(module_uri) and |
|
338 | 338 | self._survives_exclude(module_uri, 'module')): |
|
339 | 339 | modules.append(module_uri) |
|
340 | 340 | return sorted(modules) |
|
341 | 341 | |
|
342 | 342 | def write_modules_api(self, modules,outdir): |
|
343 | 343 | # write the list |
|
344 | 344 | written_modules = [] |
|
345 | 345 | for m in modules: |
|
346 | 346 | api_str = self.generate_api_doc(m) |
|
347 | 347 | if not api_str: |
|
348 | 348 | continue |
|
349 | 349 | # write out to file |
|
350 | 350 | outfile = os.path.join(outdir, |
|
351 | 351 | m + self.rst_extension) |
|
352 | 352 | fileobj = open(outfile, 'wt') |
|
353 | 353 | fileobj.write(api_str) |
|
354 | 354 | fileobj.close() |
|
355 | 355 | written_modules.append(m) |
|
356 | 356 | self.written_modules = written_modules |
|
357 | 357 | |
|
358 | 358 | def write_api_docs(self, outdir): |
|
359 | 359 | """Generate API reST files. |
|
360 | 360 | |
|
361 | 361 | Parameters |
|
362 | 362 | ---------- |
|
363 | 363 | outdir : string |
|
364 | 364 | Directory name in which to store files |
|
365 | 365 | We create automatic filenames for each module |
|
366 | 366 | |
|
367 | 367 | Returns |
|
368 | 368 | ------- |
|
369 | 369 | None |
|
370 | 370 | |
|
371 | 371 | Notes |
|
372 | 372 | ----- |
|
373 | 373 | Sets self.written_modules to list of written modules |
|
374 | 374 | """ |
|
375 | 375 | if not os.path.exists(outdir): |
|
376 | 376 | os.mkdir(outdir) |
|
377 | 377 | # compose list of modules |
|
378 | 378 | modules = self.discover_modules() |
|
379 | 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 | 382 | """Make a reST API index file from written files |
|
383 | 383 | |
|
384 | 384 | Parameters |
|
385 | 385 | ---------- |
|
386 | path : string | |
|
387 | Filename to write index to | |
|
388 | 386 | outdir : string |
|
389 | 387 | Directory to which to write generated index file |
|
390 |
|
|
|
391 | root (filename without extension) of filename to write to | |
|
392 | Defaults to 'gen'. We add ``self.rst_extension``. | |
|
388 | path : string | |
|
389 | Filename to write index to | |
|
393 | 390 | relative_to : string |
|
394 | 391 | path to which written filenames are relative. This |
|
395 | 392 | component of the written file path will be removed from |
|
396 | 393 | outdir, in the generated index. Default is None, meaning, |
|
397 | 394 | leave path as it is. |
|
398 | 395 | """ |
|
399 | 396 | if self.written_modules is None: |
|
400 | 397 | raise ValueError('No modules written') |
|
401 | 398 | # Get full filename path |
|
402 |
path = os.path.join(outdir, |
|
|
399 | path = os.path.join(outdir, path) | |
|
403 | 400 | # Path written into index is relative to rootpath |
|
404 | 401 | if relative_to is not None: |
|
405 | 402 | relpath = outdir.replace(relative_to + os.path.sep, '') |
|
406 | 403 | else: |
|
407 | 404 | relpath = outdir |
|
408 | 405 | idx = open(path,'wt') |
|
409 | 406 | w = idx.write |
|
410 | 407 | w('.. AUTO-GENERATED FILE -- DO NOT EDIT!\n\n') |
|
411 | 408 | w('.. toctree::\n\n') |
|
412 | 409 | for f in self.written_modules: |
|
413 | 410 | w(' %s\n' % os.path.join(relpath,f)) |
|
414 | 411 | idx.close() |
General Comments 0
You need to be logged in to leave comments.
Login now