##// END OF EJS Templates
fix small bug in traceback building
fperez -
Show More
@@ -1,76 +1,76 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Release data for the IPython project.
3 3
4 $Id: Release.py 988 2006-01-02 21:21:47Z fperez $"""
4 $Id: Release.py 992 2006-01-04 18:35:40Z fperez $"""
5 5
6 6 #*****************************************************************************
7 7 # Copyright (C) 2001-2005 Fernando Perez <fperez@colorado.edu>
8 8 #
9 9 # Copyright (c) 2001 Janko Hauser <jhauser@zscout.de> and Nathaniel Gray
10 10 # <n8gray@caltech.edu>
11 11 #
12 12 # Distributed under the terms of the BSD License. The full license is in
13 13 # the file COPYING, distributed as part of this software.
14 14 #*****************************************************************************
15 15
16 16 # Name of the package for release purposes. This is the name which labels
17 17 # the tarballs and RPMs made by distutils, so it's best to lowercase it.
18 18 name = 'ipython'
19 19
20 20 # For versions with substrings (like 0.6.16.svn), use an extra . to separate
21 21 # the new substring. We have to avoid using either dashes or underscores,
22 22 # because bdist_rpm does not accept dashes (an RPM) convention, and
23 23 # bdist_deb does not accept underscores (a Debian convention).
24 24
25 version = '0.7.0.rc7'
25 version = '0.7.0.rc8'
26 26
27 revision = '$Revision: 988 $'
27 revision = '$Revision: 992 $'
28 28
29 29 description = "An enhanced interactive Python shell."
30 30
31 31 long_description = \
32 32 """
33 33 IPython provides a replacement for the interactive Python interpreter with
34 34 extra functionality.
35 35
36 36 Main features:
37 37
38 38 * Comprehensive object introspection.
39 39
40 40 * Input history, persistent across sessions.
41 41
42 42 * Caching of output results during a session with automatically generated
43 43 references.
44 44
45 45 * Readline based name completion.
46 46
47 47 * Extensible system of 'magic' commands for controlling the environment and
48 48 performing many tasks related either to IPython or the operating system.
49 49
50 50 * Configuration system with easy switching between different setups (simpler
51 51 than changing $PYTHONSTARTUP environment variables every time).
52 52
53 53 * Session logging and reloading.
54 54
55 55 * Extensible syntax processing for special purpose situations.
56 56
57 57 * Access to the system shell with user-extensible alias system.
58 58
59 59 * Easily embeddable in other Python programs.
60 60
61 61 * Integrated access to the pdb debugger and the Python profiler. """
62 62
63 63 license = 'BSD'
64 64
65 65 authors = {'Fernando' : ('Fernando Perez','fperez@colorado.edu'),
66 66 'Janko' : ('Janko Hauser','jhauser@zscout.de'),
67 67 'Nathan' : ('Nathaniel Gray','n8gray@caltech.edu')
68 68 }
69 69
70 70 url = 'http://ipython.scipy.org'
71 71
72 72 download_url = 'http://ipython.scipy.org/dist'
73 73
74 74 platforms = ['Linux','Mac OSX','Windows XP/2000/NT','Windows 95/98/ME']
75 75
76 76 keywords = ['Interactive','Interpreter','Shell']
@@ -1,855 +1,858 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 $Id: ultraTB.py 988 2006-01-02 21:21:47Z fperez $"""
63 $Id: ultraTB.py 992 2006-01-04 18:35:40Z fperez $"""
64 64
65 65 #*****************************************************************************
66 66 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
67 67 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
68 68 #
69 69 # Distributed under the terms of the BSD License. The full license is in
70 70 # the file COPYING, distributed as part of this software.
71 71 #*****************************************************************************
72 72
73 73 from IPython import Release
74 74 __author__ = '%s <%s>\n%s <%s>' % (Release.authors['Nathan']+
75 75 Release.authors['Fernando'])
76 76 __license__ = Release.license
77 77
78 78 # Required modules
79 79 import inspect
80 80 import keyword
81 81 import linecache
82 82 import os
83 83 import pydoc
84 84 import string
85 85 import sys
86 86 import time
87 87 import tokenize
88 88 import traceback
89 89 import types
90 90
91 91 # IPython's own modules
92 92 # Modified pdb which doesn't damage IPython's readline handling
93 93 from IPython import Debugger
94 94 from IPython.Struct import Struct
95 95 from IPython.excolors import ExceptionColors
96 96 from IPython.genutils import Term,uniq_stable,error,info
97 97
98 98 # Globals
99 99 # amount of space to put line numbers before verbose tracebacks
100 100 INDENT_SIZE = 8
101 101
102 102 #---------------------------------------------------------------------------
103 103 # Code begins
104 104
105 105 # Utility functions
106 106 def inspect_error():
107 107 """Print a message about internal inspect errors.
108 108
109 109 These are unfortunately quite common."""
110 110
111 111 error('Internal Python error in the inspect module.\n'
112 112 'Below is the traceback from this internal error.\n')
113 113
114 114 def _fixed_getinnerframes(etb, context=1,tb_offset=0):
115 115 import linecache
116 116 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
117 117
118 118 records = inspect.getinnerframes(etb, context)
119 119
120 120 # If the error is at the console, don't build any context, since it would
121 121 # otherwise produce 5 blank lines printed out (there is no file at the
122 122 # console)
123 123 rec_check = records[tb_offset:]
124 try:
124 125 rname = rec_check[0][1]
125 126 if rname == '<ipython console>' or rname.endswith('<string>'):
126 127 return rec_check
128 except IndexError:
129 pass
127 130
128 131 aux = traceback.extract_tb(etb)
129 132 assert len(records) == len(aux)
130 133 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
131 134 maybeStart = lnum-1 - context//2
132 135 start = max(maybeStart, 0)
133 136 end = start + context
134 137 lines = linecache.getlines(file)[start:end]
135 138 # pad with empty lines if necessary
136 139 if maybeStart < 0:
137 140 lines = (['\n'] * -maybeStart) + lines
138 141 if len(lines) < context:
139 142 lines += ['\n'] * (context - len(lines))
140 143 assert len(lines) == context
141 144 buf = list(records[i])
142 145 buf[LNUM_POS] = lnum
143 146 buf[INDEX_POS] = lnum - 1 - start
144 147 buf[LINES_POS] = lines
145 148 records[i] = tuple(buf)
146 149 return records[tb_offset:]
147 150
148 151 # Helper function -- largely belongs to VerboseTB, but we need the same
149 152 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
150 153 # can be recognized properly by ipython.el's py-traceback-line-re
151 154 # (SyntaxErrors have to be treated specially because they have no traceback)
152 155 def _formatTracebackLines(lnum, index, lines, Colors, lvals=None):
153 156 numbers_width = INDENT_SIZE - 1
154 157 res = []
155 158 i = lnum - index
156 159 for line in lines:
157 160 if i == lnum:
158 161 # This is the line with the error
159 162 pad = numbers_width - len(str(i))
160 163 if pad >= 3:
161 164 marker = '-'*(pad-3) + '-> '
162 165 elif pad == 2:
163 166 marker = '> '
164 167 elif pad == 1:
165 168 marker = '>'
166 169 else:
167 170 marker = ''
168 171 num = marker + str(i)
169 172 line = '%s%s%s %s%s' %(Colors.linenoEm, num,
170 173 Colors.line, line, Colors.Normal)
171 174 else:
172 175 num = '%*s' % (numbers_width,i)
173 176 line = '%s%s%s %s' %(Colors.lineno, num,
174 177 Colors.Normal, line)
175 178
176 179 res.append(line)
177 180 if lvals and i == lnum:
178 181 res.append(lvals + '\n')
179 182 i = i + 1
180 183 return res
181 184
182 185 #---------------------------------------------------------------------------
183 186 # Module classes
184 187 class TBTools:
185 188 """Basic tools used by all traceback printer classes."""
186 189
187 190 def __init__(self,color_scheme = 'NoColor',call_pdb=False):
188 191 # Whether to call the interactive pdb debugger after printing
189 192 # tracebacks or not
190 193 self.call_pdb = call_pdb
191 194
192 195 # Create color table
193 196 self.color_scheme_table = ExceptionColors
194 197
195 198 self.set_colors(color_scheme)
196 199 self.old_scheme = color_scheme # save initial value for toggles
197 200
198 201 if call_pdb:
199 202 self.pdb = Debugger.Pdb(self.color_scheme_table.active_scheme_name)
200 203 else:
201 204 self.pdb = None
202 205
203 206 def set_colors(self,*args,**kw):
204 207 """Shorthand access to the color table scheme selector method."""
205 208
206 209 self.color_scheme_table.set_active_scheme(*args,**kw)
207 210 # for convenience, set Colors to the active scheme
208 211 self.Colors = self.color_scheme_table.active_colors
209 212
210 213 def color_toggle(self):
211 214 """Toggle between the currently active color scheme and NoColor."""
212 215
213 216 if self.color_scheme_table.active_scheme_name == 'NoColor':
214 217 self.color_scheme_table.set_active_scheme(self.old_scheme)
215 218 self.Colors = self.color_scheme_table.active_colors
216 219 else:
217 220 self.old_scheme = self.color_scheme_table.active_scheme_name
218 221 self.color_scheme_table.set_active_scheme('NoColor')
219 222 self.Colors = self.color_scheme_table.active_colors
220 223
221 224 #---------------------------------------------------------------------------
222 225 class ListTB(TBTools):
223 226 """Print traceback information from a traceback list, with optional color.
224 227
225 228 Calling: requires 3 arguments:
226 229 (etype, evalue, elist)
227 230 as would be obtained by:
228 231 etype, evalue, tb = sys.exc_info()
229 232 if tb:
230 233 elist = traceback.extract_tb(tb)
231 234 else:
232 235 elist = None
233 236
234 237 It can thus be used by programs which need to process the traceback before
235 238 printing (such as console replacements based on the code module from the
236 239 standard library).
237 240
238 241 Because they are meant to be called without a full traceback (only a
239 242 list), instances of this class can't call the interactive pdb debugger."""
240 243
241 244 def __init__(self,color_scheme = 'NoColor'):
242 245 TBTools.__init__(self,color_scheme = color_scheme,call_pdb=0)
243 246
244 247 def __call__(self, etype, value, elist):
245 248 print >> Term.cerr, self.text(etype,value,elist)
246 249
247 250 def text(self,etype, value, elist,context=5):
248 251 """Return a color formatted string with the traceback info."""
249 252
250 253 Colors = self.Colors
251 254 out_string = ['%s%s%s\n' % (Colors.topline,'-'*60,Colors.Normal)]
252 255 if elist:
253 256 out_string.append('Traceback %s(most recent call last)%s:' % \
254 257 (Colors.normalEm, Colors.Normal) + '\n')
255 258 out_string.extend(self._format_list(elist))
256 259 lines = self._format_exception_only(etype, value)
257 260 for line in lines[:-1]:
258 261 out_string.append(" "+line)
259 262 out_string.append(lines[-1])
260 263 return ''.join(out_string)
261 264
262 265 def _format_list(self, extracted_list):
263 266 """Format a list of traceback entry tuples for printing.
264 267
265 268 Given a list of tuples as returned by extract_tb() or
266 269 extract_stack(), return a list of strings ready for printing.
267 270 Each string in the resulting list corresponds to the item with the
268 271 same index in the argument list. Each string ends in a newline;
269 272 the strings may contain internal newlines as well, for those items
270 273 whose source text line is not None.
271 274
272 275 Lifted almost verbatim from traceback.py
273 276 """
274 277
275 278 Colors = self.Colors
276 279 list = []
277 280 for filename, lineno, name, line in extracted_list[:-1]:
278 281 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
279 282 (Colors.filename, filename, Colors.Normal,
280 283 Colors.lineno, lineno, Colors.Normal,
281 284 Colors.name, name, Colors.Normal)
282 285 if line:
283 286 item = item + ' %s\n' % line.strip()
284 287 list.append(item)
285 288 # Emphasize the last entry
286 289 filename, lineno, name, line = extracted_list[-1]
287 290 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
288 291 (Colors.normalEm,
289 292 Colors.filenameEm, filename, Colors.normalEm,
290 293 Colors.linenoEm, lineno, Colors.normalEm,
291 294 Colors.nameEm, name, Colors.normalEm,
292 295 Colors.Normal)
293 296 if line:
294 297 item = item + '%s %s%s\n' % (Colors.line, line.strip(),
295 298 Colors.Normal)
296 299 list.append(item)
297 300 return list
298 301
299 302 def _format_exception_only(self, etype, value):
300 303 """Format the exception part of a traceback.
301 304
302 305 The arguments are the exception type and value such as given by
303 306 sys.exc_info()[:2]. The return value is a list of strings, each ending
304 307 in a newline. Normally, the list contains a single string; however,
305 308 for SyntaxError exceptions, it contains several lines that (when
306 309 printed) display detailed information about where the syntax error
307 310 occurred. The message indicating which exception occurred is the
308 311 always last string in the list.
309 312
310 313 Also lifted nearly verbatim from traceback.py
311 314 """
312 315
313 316 Colors = self.Colors
314 317 list = []
315 318 if type(etype) == types.ClassType:
316 319 stype = Colors.excName + etype.__name__ + Colors.Normal
317 320 else:
318 321 stype = etype # String exceptions don't get special coloring
319 322 if value is None:
320 323 list.append( str(stype) + '\n')
321 324 else:
322 325 if etype is SyntaxError:
323 326 try:
324 327 msg, (filename, lineno, offset, line) = value
325 328 except:
326 329 pass
327 330 else:
328 331 #print 'filename is',filename # dbg
329 332 if not filename: filename = "<string>"
330 333 list.append('%s File %s"%s"%s, line %s%d%s\n' % \
331 334 (Colors.normalEm,
332 335 Colors.filenameEm, filename, Colors.normalEm,
333 336 Colors.linenoEm, lineno, Colors.Normal ))
334 337 if line is not None:
335 338 i = 0
336 339 while i < len(line) and line[i].isspace():
337 340 i = i+1
338 341 list.append('%s %s%s\n' % (Colors.line,
339 342 line.strip(),
340 343 Colors.Normal))
341 344 if offset is not None:
342 345 s = ' '
343 346 for c in line[i:offset-1]:
344 347 if c.isspace():
345 348 s = s + c
346 349 else:
347 350 s = s + ' '
348 351 list.append('%s%s^%s\n' % (Colors.caret, s,
349 352 Colors.Normal) )
350 353 value = msg
351 354 s = self._some_str(value)
352 355 if s:
353 356 list.append('%s%s:%s %s\n' % (str(stype), Colors.excName,
354 357 Colors.Normal, s))
355 358 else:
356 359 list.append('%s\n' % str(stype))
357 360 return list
358 361
359 362 def _some_str(self, value):
360 363 # Lifted from traceback.py
361 364 try:
362 365 return str(value)
363 366 except:
364 367 return '<unprintable %s object>' % type(value).__name__
365 368
366 369 #----------------------------------------------------------------------------
367 370 class VerboseTB(TBTools):
368 371 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
369 372 of HTML. Requires inspect and pydoc. Crazy, man.
370 373
371 374 Modified version which optionally strips the topmost entries from the
372 375 traceback, to be used with alternate interpreters (because their own code
373 376 would appear in the traceback)."""
374 377
375 378 def __init__(self,color_scheme = 'Linux',tb_offset=0,long_header=0,
376 379 call_pdb = 0, include_vars=1):
377 380 """Specify traceback offset, headers and color scheme.
378 381
379 382 Define how many frames to drop from the tracebacks. Calling it with
380 383 tb_offset=1 allows use of this handler in interpreters which will have
381 384 their own code at the top of the traceback (VerboseTB will first
382 385 remove that frame before printing the traceback info)."""
383 386 TBTools.__init__(self,color_scheme=color_scheme,call_pdb=call_pdb)
384 387 self.tb_offset = tb_offset
385 388 self.long_header = long_header
386 389 self.include_vars = include_vars
387 390
388 391 def text(self, etype, evalue, etb, context=5):
389 392 """Return a nice text document describing the traceback."""
390 393
391 394 # some locals
392 395 Colors = self.Colors # just a shorthand + quicker name lookup
393 396 ColorsNormal = Colors.Normal # used a lot
394 397 indent = ' '*INDENT_SIZE
395 398 text_repr = pydoc.text.repr
396 399 exc = '%s%s%s' % (Colors.excName, str(etype), ColorsNormal)
397 400 em_normal = '%s\n%s%s' % (Colors.valEm, indent,ColorsNormal)
398 401 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
399 402
400 403 # some internal-use functions
401 404 def eqrepr(value, repr=text_repr): return '=%s' % repr(value)
402 405 def nullrepr(value, repr=text_repr): return ''
403 406
404 407 # meat of the code begins
405 408 if type(etype) is types.ClassType:
406 409 etype = etype.__name__
407 410
408 411 if self.long_header:
409 412 # Header with the exception type, python version, and date
410 413 pyver = 'Python ' + string.split(sys.version)[0] + ': ' + sys.executable
411 414 date = time.ctime(time.time())
412 415
413 416 head = '%s%s%s\n%s%s%s\n%s' % (Colors.topline, '-'*75, ColorsNormal,
414 417 exc, ' '*(75-len(str(etype))-len(pyver)),
415 418 pyver, string.rjust(date, 75) )
416 419 head += "\nA problem occured executing Python code. Here is the sequence of function"\
417 420 "\ncalls leading up to the error, with the most recent (innermost) call last."
418 421 else:
419 422 # Simplified header
420 423 head = '%s%s%s\n%s%s' % (Colors.topline, '-'*75, ColorsNormal,exc,
421 424 string.rjust('Traceback (most recent call last)',
422 425 75 - len(str(etype)) ) )
423 426 frames = []
424 427 # Flush cache before calling inspect. This helps alleviate some of the
425 428 # problems with python 2.3's inspect.py.
426 429 linecache.checkcache()
427 430 # Drop topmost frames if requested
428 431 try:
429 432 # Try the default getinnerframes and Alex's: Alex's fixes some
430 433 # problems, but it generates empty tracebacks for console errors
431 434 # (5 blanks lines) where none should be returned.
432 435 #records = inspect.getinnerframes(etb, context)[self.tb_offset:]
433 436 #print 'python records:', records # dbg
434 437 records = _fixed_getinnerframes(etb, context,self.tb_offset)
435 438 #print 'alex records:', records # dbg
436 439 except:
437 440
438 441 # FIXME: I've been getting many crash reports from python 2.3
439 442 # users, traceable to inspect.py. If I can find a small test-case
440 443 # to reproduce this, I should either write a better workaround or
441 444 # file a bug report against inspect (if that's the real problem).
442 445 # So far, I haven't been able to find an isolated example to
443 446 # reproduce the problem.
444 447 inspect_error()
445 448 traceback.print_exc(file=Term.cerr)
446 449 info('\nUnfortunately, your original traceback can not be constructed.\n')
447 450 return ''
448 451
449 452 # build some color string templates outside these nested loops
450 453 tpl_link = '%s%%s%s' % (Colors.filenameEm,ColorsNormal)
451 454 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
452 455 ColorsNormal)
453 456 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
454 457 (Colors.vName, Colors.valEm, ColorsNormal)
455 458 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
456 459 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
457 460 Colors.vName, ColorsNormal)
458 461 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
459 462 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
460 463 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm,Colors.line,
461 464 ColorsNormal)
462 465
463 466 # now, loop over all records printing context and info
464 467 abspath = os.path.abspath
465 468 for frame, file, lnum, func, lines, index in records:
466 469 #print '*** record:',file,lnum,func,lines,index # dbg
467 470 try:
468 471 file = file and abspath(file) or '?'
469 472 except OSError:
470 473 # if file is '<console>' or something not in the filesystem,
471 474 # the abspath call will throw an OSError. Just ignore it and
472 475 # keep the original file string.
473 476 pass
474 477 link = tpl_link % file
475 478 try:
476 479 args, varargs, varkw, locals = inspect.getargvalues(frame)
477 480 except:
478 481 # This can happen due to a bug in python2.3. We should be
479 482 # able to remove this try/except when 2.4 becomes a
480 483 # requirement. Bug details at http://python.org/sf/1005466
481 484 inspect_error()
482 485 traceback.print_exc(file=Term.cerr)
483 486 info("\nIPython's exception reporting continues...\n")
484 487
485 488 if func == '?':
486 489 call = ''
487 490 else:
488 491 # Decide whether to include variable details or not
489 492 var_repr = self.include_vars and eqrepr or nullrepr
490 493 try:
491 494 call = tpl_call % (func,inspect.formatargvalues(args,
492 495 varargs, varkw,
493 496 locals,formatvalue=var_repr))
494 497 except KeyError:
495 498 # Very odd crash from inspect.formatargvalues(). The
496 499 # scenario under which it appeared was a call to
497 500 # view(array,scale) in NumTut.view.view(), where scale had
498 501 # been defined as a scalar (it should be a tuple). Somehow
499 502 # inspect messes up resolving the argument list of view()
500 503 # and barfs out. At some point I should dig into this one
501 504 # and file a bug report about it.
502 505 inspect_error()
503 506 traceback.print_exc(file=Term.cerr)
504 507 info("\nIPython's exception reporting continues...\n")
505 508 call = tpl_call_fail % func
506 509
507 510 # Initialize a list of names on the current line, which the
508 511 # tokenizer below will populate.
509 512 names = []
510 513
511 514 def tokeneater(token_type, token, start, end, line):
512 515 """Stateful tokeneater which builds dotted names.
513 516
514 517 The list of names it appends to (from the enclosing scope) can
515 518 contain repeated composite names. This is unavoidable, since
516 519 there is no way to disambguate partial dotted structures until
517 520 the full list is known. The caller is responsible for pruning
518 521 the final list of duplicates before using it."""
519 522
520 523 # build composite names
521 524 if token == '.':
522 525 try:
523 526 names[-1] += '.'
524 527 # store state so the next token is added for x.y.z names
525 528 tokeneater.name_cont = True
526 529 return
527 530 except IndexError:
528 531 pass
529 532 if token_type == tokenize.NAME and token not in keyword.kwlist:
530 533 if tokeneater.name_cont:
531 534 # Dotted names
532 535 names[-1] += token
533 536 tokeneater.name_cont = False
534 537 else:
535 538 # Regular new names. We append everything, the caller
536 539 # will be responsible for pruning the list later. It's
537 540 # very tricky to try to prune as we go, b/c composite
538 541 # names can fool us. The pruning at the end is easy
539 542 # to do (or the caller can print a list with repeated
540 543 # names if so desired.
541 544 names.append(token)
542 545 elif token_type == tokenize.NEWLINE:
543 546 raise IndexError
544 547 # we need to store a bit of state in the tokenizer to build
545 548 # dotted names
546 549 tokeneater.name_cont = False
547 550
548 551 def linereader(file=file, lnum=[lnum], getline=linecache.getline):
549 552 line = getline(file, lnum[0])
550 553 lnum[0] += 1
551 554 return line
552 555
553 556 # Build the list of names on this line of code where the exception
554 557 # occurred.
555 558 try:
556 559 # This builds the names list in-place by capturing it from the
557 560 # enclosing scope.
558 561 tokenize.tokenize(linereader, tokeneater)
559 562 except IndexError:
560 563 # signals exit of tokenizer
561 564 pass
562 565 except tokenize.TokenError,msg:
563 566 _m = ("An unexpected error occurred while tokenizing input\n"
564 567 "The following traceback may be corrupted or invalid\n"
565 568 "The error message is: %s\n" % msg)
566 569 error(_m)
567 570
568 571 # prune names list of duplicates, but keep the right order
569 572 unique_names = uniq_stable(names)
570 573
571 574 # Start loop over vars
572 575 lvals = []
573 576 if self.include_vars:
574 577 for name_full in unique_names:
575 578 name_base = name_full.split('.',1)[0]
576 579 if name_base in frame.f_code.co_varnames:
577 580 if locals.has_key(name_base):
578 581 try:
579 582 value = repr(eval(name_full,locals))
580 583 except:
581 584 value = undefined
582 585 else:
583 586 value = undefined
584 587 name = tpl_local_var % name_full
585 588 else:
586 589 if frame.f_globals.has_key(name_base):
587 590 try:
588 591 value = repr(eval(name_full,frame.f_globals))
589 592 except:
590 593 value = undefined
591 594 else:
592 595 value = undefined
593 596 name = tpl_global_var % name_full
594 597 lvals.append(tpl_name_val % (name,value))
595 598 if lvals:
596 599 lvals = '%s%s' % (indent,em_normal.join(lvals))
597 600 else:
598 601 lvals = ''
599 602
600 603 level = '%s %s\n' % (link,call)
601 604
602 605 if index is None:
603 606 frames.append(level)
604 607 else:
605 608 frames.append('%s%s' % (level,''.join(
606 609 _formatTracebackLines(lnum,index,lines,self.Colors,lvals))))
607 610
608 611 # Get (safely) a string form of the exception info
609 612 try:
610 613 etype_str,evalue_str = map(str,(etype,evalue))
611 614 except:
612 615 # User exception is improperly defined.
613 616 etype,evalue = str,sys.exc_info()[:2]
614 617 etype_str,evalue_str = map(str,(etype,evalue))
615 618 # ... and format it
616 619 exception = ['%s%s%s: %s' % (Colors.excName, etype_str,
617 620 ColorsNormal, evalue_str)]
618 621 if type(evalue) is types.InstanceType:
619 622 try:
620 623 names = [w for w in dir(evalue) if isinstance(w, basestring)]
621 624 except:
622 625 # Every now and then, an object with funny inernals blows up
623 626 # when dir() is called on it. We do the best we can to report
624 627 # the problem and continue
625 628 _m = '%sException reporting error (object with broken dir())%s:'
626 629 exception.append(_m % (Colors.excName,ColorsNormal))
627 630 etype_str,evalue_str = map(str,sys.exc_info()[:2])
628 631 exception.append('%s%s%s: %s' % (Colors.excName,etype_str,
629 632 ColorsNormal, evalue_str))
630 633 names = []
631 634 for name in names:
632 635 value = text_repr(getattr(evalue, name))
633 636 exception.append('\n%s%s = %s' % (indent, name, value))
634 637 # return all our info assembled as a single string
635 638 return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) )
636 639
637 640 def debugger(self):
638 641 """Call up the pdb debugger if desired, always clean up the tb reference.
639 642
640 643 If the call_pdb flag is set, the pdb interactive debugger is
641 644 invoked. In all cases, the self.tb reference to the current traceback
642 645 is deleted to prevent lingering references which hamper memory
643 646 management.
644 647
645 648 Note that each call to pdb() does an 'import readline', so if your app
646 649 requires a special setup for the readline completers, you'll have to
647 650 fix that by hand after invoking the exception handler."""
648 651
649 652 if self.call_pdb:
650 653 if self.pdb is None:
651 654 self.pdb = Debugger.Pdb(
652 655 self.color_scheme_table.active_scheme_name)
653 656 # the system displayhook may have changed, restore the original
654 657 # for pdb
655 658 dhook = sys.displayhook
656 659 sys.displayhook = sys.__displayhook__
657 660 self.pdb.reset()
658 661 # Find the right frame so we don't pop up inside ipython itself
659 662 etb = self.tb
660 663 while self.tb.tb_next is not None:
661 664 self.tb = self.tb.tb_next
662 665 try:
663 666 if etb and etb.tb_next:
664 667 etb = etb.tb_next
665 668 self.pdb.botframe = etb.tb_frame
666 669 self.pdb.interaction(self.tb.tb_frame, self.tb)
667 670 except:
668 671 print '*** ERROR ***'
669 672 print 'This version of pdb has a bug and crashed.'
670 673 print 'Returning to IPython...'
671 674 sys.displayhook = dhook
672 675 del self.tb
673 676
674 677 def handler(self, info=None):
675 678 (etype, evalue, etb) = info or sys.exc_info()
676 679 self.tb = etb
677 680 print >> Term.cerr, self.text(etype, evalue, etb)
678 681
679 682 # Changed so an instance can just be called as VerboseTB_inst() and print
680 683 # out the right info on its own.
681 684 def __call__(self, etype=None, evalue=None, etb=None):
682 685 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
683 686 if etb is None:
684 687 self.handler()
685 688 else:
686 689 self.handler((etype, evalue, etb))
687 690 self.debugger()
688 691
689 692 #----------------------------------------------------------------------------
690 693 class FormattedTB(VerboseTB,ListTB):
691 694 """Subclass ListTB but allow calling with a traceback.
692 695
693 696 It can thus be used as a sys.excepthook for Python > 2.1.
694 697
695 698 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
696 699
697 700 Allows a tb_offset to be specified. This is useful for situations where
698 701 one needs to remove a number of topmost frames from the traceback (such as
699 702 occurs with python programs that themselves execute other python code,
700 703 like Python shells). """
701 704
702 705 def __init__(self, mode = 'Plain', color_scheme='Linux',
703 706 tb_offset = 0,long_header=0,call_pdb=0,include_vars=0):
704 707
705 708 # NEVER change the order of this list. Put new modes at the end:
706 709 self.valid_modes = ['Plain','Context','Verbose']
707 710 self.verbose_modes = self.valid_modes[1:3]
708 711
709 712 VerboseTB.__init__(self,color_scheme,tb_offset,long_header,
710 713 call_pdb=call_pdb,include_vars=include_vars)
711 714 self.set_mode(mode)
712 715
713 716 def _extract_tb(self,tb):
714 717 if tb:
715 718 return traceback.extract_tb(tb)
716 719 else:
717 720 return None
718 721
719 722 def text(self, etype, value, tb,context=5,mode=None):
720 723 """Return formatted traceback.
721 724
722 725 If the optional mode parameter is given, it overrides the current
723 726 mode."""
724 727
725 728 if mode is None:
726 729 mode = self.mode
727 730 if mode in self.verbose_modes:
728 731 # verbose modes need a full traceback
729 732 return VerboseTB.text(self,etype, value, tb,context=5)
730 733 else:
731 734 # We must check the source cache because otherwise we can print
732 735 # out-of-date source code.
733 736 linecache.checkcache()
734 737 # Now we can extract and format the exception
735 738 elist = self._extract_tb(tb)
736 739 if len(elist) > self.tb_offset:
737 740 del elist[:self.tb_offset]
738 741 return ListTB.text(self,etype,value,elist)
739 742
740 743 def set_mode(self,mode=None):
741 744 """Switch to the desired mode.
742 745
743 746 If mode is not specified, cycles through the available modes."""
744 747
745 748 if not mode:
746 749 new_idx = ( self.valid_modes.index(self.mode) + 1 ) % \
747 750 len(self.valid_modes)
748 751 self.mode = self.valid_modes[new_idx]
749 752 elif mode not in self.valid_modes:
750 753 raise ValueError, 'Unrecognized mode in FormattedTB: <'+mode+'>\n'\
751 754 'Valid modes: '+str(self.valid_modes)
752 755 else:
753 756 self.mode = mode
754 757 # include variable details only in 'Verbose' mode
755 758 self.include_vars = (self.mode == self.valid_modes[2])
756 759
757 760 # some convenient shorcuts
758 761 def plain(self):
759 762 self.set_mode(self.valid_modes[0])
760 763
761 764 def context(self):
762 765 self.set_mode(self.valid_modes[1])
763 766
764 767 def verbose(self):
765 768 self.set_mode(self.valid_modes[2])
766 769
767 770 #----------------------------------------------------------------------------
768 771 class AutoFormattedTB(FormattedTB):
769 772 """A traceback printer which can be called on the fly.
770 773
771 774 It will find out about exceptions by itself.
772 775
773 776 A brief example:
774 777
775 778 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
776 779 try:
777 780 ...
778 781 except:
779 782 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
780 783 """
781 784 def __call__(self,etype=None,evalue=None,etb=None,
782 785 out=None,tb_offset=None):
783 786 """Print out a formatted exception traceback.
784 787
785 788 Optional arguments:
786 789 - out: an open file-like object to direct output to.
787 790
788 791 - tb_offset: the number of frames to skip over in the stack, on a
789 792 per-call basis (this overrides temporarily the instance's tb_offset
790 793 given at initialization time. """
791 794
792 795 if out is None:
793 796 out = Term.cerr
794 797 if tb_offset is not None:
795 798 tb_offset, self.tb_offset = self.tb_offset, tb_offset
796 799 print >> out, self.text(etype, evalue, etb)
797 800 self.tb_offset = tb_offset
798 801 else:
799 802 print >> out, self.text(etype, evalue, etb)
800 803 self.debugger()
801 804
802 805 def text(self,etype=None,value=None,tb=None,context=5,mode=None):
803 806 if etype is None:
804 807 etype,value,tb = sys.exc_info()
805 808 self.tb = tb
806 809 return FormattedTB.text(self,etype,value,tb,context=5,mode=mode)
807 810
808 811 #---------------------------------------------------------------------------
809 812 # A simple class to preserve Nathan's original functionality.
810 813 class ColorTB(FormattedTB):
811 814 """Shorthand to initialize a FormattedTB in Linux colors mode."""
812 815 def __init__(self,color_scheme='Linux',call_pdb=0):
813 816 FormattedTB.__init__(self,color_scheme=color_scheme,
814 817 call_pdb=call_pdb)
815 818
816 819 #----------------------------------------------------------------------------
817 820 # module testing (minimal)
818 821 if __name__ == "__main__":
819 822 def spam(c, (d, e)):
820 823 x = c + d
821 824 y = c * d
822 825 foo(x, y)
823 826
824 827 def foo(a, b, bar=1):
825 828 eggs(a, b + bar)
826 829
827 830 def eggs(f, g, z=globals()):
828 831 h = f + g
829 832 i = f - g
830 833 return h / i
831 834
832 835 print ''
833 836 print '*** Before ***'
834 837 try:
835 838 print spam(1, (2, 3))
836 839 except:
837 840 traceback.print_exc()
838 841 print ''
839 842
840 843 handler = ColorTB()
841 844 print '*** ColorTB ***'
842 845 try:
843 846 print spam(1, (2, 3))
844 847 except:
845 848 apply(handler, sys.exc_info() )
846 849 print ''
847 850
848 851 handler = VerboseTB()
849 852 print '*** VerboseTB ***'
850 853 try:
851 854 print spam(1, (2, 3))
852 855 except:
853 856 apply(handler, sys.exc_info() )
854 857 print ''
855 858
General Comments 0
You need to be logged in to leave comments. Login now