##// END OF EJS Templates
Fixing two minor bugs....
Brian Granger -
Show More
@@ -1,30 +1,30 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 """
4 4 This module is *completely* deprecated and should no longer be used for
5 5 any purpose. Currently, we have a few parts of the core that have
6 6 not been componentized and thus, still rely on this module. When everything
7 7 has been made into a component, this module will be sent to deathrow.
8 8 """
9 9
10 10 #-----------------------------------------------------------------------------
11 11 # Copyright (C) 2008-2009 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 #-----------------------------------------------------------------------------
22 22 # Classes and functions
23 23 #-----------------------------------------------------------------------------
24 24
25 25
26 26 def get():
27 27 """Get the global InteractiveShell instance."""
28 from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell
29 return TerminalInteractiveShell.instance()
28 from IPython.core.interactiveshell import InteractiveShell
29 return InteractiveShell.instance()
30 30
@@ -1,1156 +1,1156 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
64 64 #*****************************************************************************
65 65 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
66 66 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
67 67 #
68 68 # Distributed under the terms of the BSD License. The full license is in
69 69 # the file COPYING, distributed as part of this software.
70 70 #*****************************************************************************
71 71
72 72 from __future__ import with_statement
73 73
74 74 import inspect
75 75 import keyword
76 76 import linecache
77 77 import os
78 78 import pydoc
79 79 import re
80 80 import string
81 81 import sys
82 82 import time
83 83 import tokenize
84 84 import traceback
85 85 import types
86 86
87 87 # For purposes of monkeypatching inspect to fix a bug in it.
88 88 from inspect import getsourcefile, getfile, getmodule,\
89 89 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
90 90
91 91 # IPython's own modules
92 92 # Modified pdb which doesn't damage IPython's readline handling
93 93 from IPython.utils import PyColorize
94 94 from IPython.core import debugger, ipapi
95 95 from IPython.core.display_trap import DisplayTrap
96 96 from IPython.core.excolors import exception_colors
97 97 from IPython.utils.data import uniq_stable
98 98 import IPython.utils.io
99 99 from IPython.utils.warn import info, error
100 100
101 101 # Globals
102 102 # amount of space to put line numbers before verbose tracebacks
103 103 INDENT_SIZE = 8
104 104
105 105 # Default color scheme. This is used, for example, by the traceback
106 106 # formatter. When running in an actual IPython instance, the user's rc.colors
107 107 # value is used, but havinga module global makes this functionality available
108 108 # to users of ultratb who are NOT running inside ipython.
109 109 DEFAULT_SCHEME = 'NoColor'
110 110
111 111 #---------------------------------------------------------------------------
112 112 # Code begins
113 113
114 114 # Utility functions
115 115 def inspect_error():
116 116 """Print a message about internal inspect errors.
117 117
118 118 These are unfortunately quite common."""
119 119
120 120 error('Internal Python error in the inspect module.\n'
121 121 'Below is the traceback from this internal error.\n')
122 122
123 123
124 124 def findsource(object):
125 125 """Return the entire source file and starting line number for an object.
126 126
127 127 The argument may be a module, class, method, function, traceback, frame,
128 128 or code object. The source code is returned as a list of all the lines
129 129 in the file and the line number indexes a line in that list. An IOError
130 130 is raised if the source code cannot be retrieved.
131 131
132 132 FIXED version with which we monkeypatch the stdlib to work around a bug."""
133 133
134 134 file = getsourcefile(object) or getfile(object)
135 135 # If the object is a frame, then trying to get the globals dict from its
136 136 # module won't work. Instead, the frame object itself has the globals
137 137 # dictionary.
138 138 globals_dict = None
139 139 if inspect.isframe(object):
140 140 # XXX: can this ever be false?
141 141 globals_dict = object.f_globals
142 142 else:
143 143 module = getmodule(object, file)
144 144 if module:
145 145 globals_dict = module.__dict__
146 146 lines = linecache.getlines(file, globals_dict)
147 147 if not lines:
148 148 raise IOError('could not get source code')
149 149
150 150 if ismodule(object):
151 151 return lines, 0
152 152
153 153 if isclass(object):
154 154 name = object.__name__
155 155 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
156 156 # make some effort to find the best matching class definition:
157 157 # use the one with the least indentation, which is the one
158 158 # that's most probably not inside a function definition.
159 159 candidates = []
160 160 for i in range(len(lines)):
161 161 match = pat.match(lines[i])
162 162 if match:
163 163 # if it's at toplevel, it's already the best one
164 164 if lines[i][0] == 'c':
165 165 return lines, i
166 166 # else add whitespace to candidate list
167 167 candidates.append((match.group(1), i))
168 168 if candidates:
169 169 # this will sort by whitespace, and by line number,
170 170 # less whitespace first
171 171 candidates.sort()
172 172 return lines, candidates[0][1]
173 173 else:
174 174 raise IOError('could not find class definition')
175 175
176 176 if ismethod(object):
177 177 object = object.im_func
178 178 if isfunction(object):
179 179 object = object.func_code
180 180 if istraceback(object):
181 181 object = object.tb_frame
182 182 if isframe(object):
183 183 object = object.f_code
184 184 if iscode(object):
185 185 if not hasattr(object, 'co_firstlineno'):
186 186 raise IOError('could not find function definition')
187 187 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
188 188 pmatch = pat.match
189 189 # fperez - fix: sometimes, co_firstlineno can give a number larger than
190 190 # the length of lines, which causes an error. Safeguard against that.
191 191 lnum = min(object.co_firstlineno,len(lines))-1
192 192 while lnum > 0:
193 193 if pmatch(lines[lnum]): break
194 194 lnum -= 1
195 195
196 196 return lines, lnum
197 197 raise IOError('could not find code object')
198 198
199 199 # Monkeypatch inspect to apply our bugfix. This code only works with py25
200 200 if sys.version_info[:2] >= (2,5):
201 201 inspect.findsource = findsource
202 202
203 203 def fix_frame_records_filenames(records):
204 204 """Try to fix the filenames in each record from inspect.getinnerframes().
205 205
206 206 Particularly, modules loaded from within zip files have useless filenames
207 207 attached to their code object, and inspect.getinnerframes() just uses it.
208 208 """
209 209 fixed_records = []
210 210 for frame, filename, line_no, func_name, lines, index in records:
211 211 # Look inside the frame's globals dictionary for __file__, which should
212 212 # be better.
213 213 better_fn = frame.f_globals.get('__file__', None)
214 214 if isinstance(better_fn, str):
215 215 # Check the type just in case someone did something weird with
216 216 # __file__. It might also be None if the error occurred during
217 217 # import.
218 218 filename = better_fn
219 219 fixed_records.append((frame, filename, line_no, func_name, lines, index))
220 220 return fixed_records
221 221
222 222
223 223 def _fixed_getinnerframes(etb, context=1,tb_offset=0):
224 224 import linecache
225 225 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
226 226
227 227 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
228 228
229 229 # If the error is at the console, don't build any context, since it would
230 230 # otherwise produce 5 blank lines printed out (there is no file at the
231 231 # console)
232 232 rec_check = records[tb_offset:]
233 233 try:
234 234 rname = rec_check[0][1]
235 235 if rname == '<ipython console>' or rname.endswith('<string>'):
236 236 return rec_check
237 237 except IndexError:
238 238 pass
239 239
240 240 aux = traceback.extract_tb(etb)
241 241 assert len(records) == len(aux)
242 242 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
243 243 maybeStart = lnum-1 - context//2
244 244 start = max(maybeStart, 0)
245 245 end = start + context
246 246 lines = linecache.getlines(file)[start:end]
247 247 # pad with empty lines if necessary
248 248 if maybeStart < 0:
249 249 lines = (['\n'] * -maybeStart) + lines
250 250 if len(lines) < context:
251 251 lines += ['\n'] * (context - len(lines))
252 252 buf = list(records[i])
253 253 buf[LNUM_POS] = lnum
254 254 buf[INDEX_POS] = lnum - 1 - start
255 255 buf[LINES_POS] = lines
256 256 records[i] = tuple(buf)
257 257 return records[tb_offset:]
258 258
259 259 # Helper function -- largely belongs to VerboseTB, but we need the same
260 260 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
261 261 # can be recognized properly by ipython.el's py-traceback-line-re
262 262 # (SyntaxErrors have to be treated specially because they have no traceback)
263 263
264 264 _parser = PyColorize.Parser()
265 265
266 266 def _format_traceback_lines(lnum, index, lines, Colors, lvals=None,scheme=None):
267 267 numbers_width = INDENT_SIZE - 1
268 268 res = []
269 269 i = lnum - index
270 270
271 271 # This lets us get fully syntax-highlighted tracebacks.
272 272 if scheme is None:
273 273 ipinst = ipapi.get()
274 274 if ipinst is not None:
275 275 scheme = ipinst.colors
276 276 else:
277 277 scheme = DEFAULT_SCHEME
278 278
279 279 _line_format = _parser.format2
280 280
281 281 for line in lines:
282 282 new_line, err = _line_format(line,'str',scheme)
283 283 if not err: line = new_line
284 284
285 285 if i == lnum:
286 286 # This is the line with the error
287 287 pad = numbers_width - len(str(i))
288 288 if pad >= 3:
289 289 marker = '-'*(pad-3) + '-> '
290 290 elif pad == 2:
291 291 marker = '> '
292 292 elif pad == 1:
293 293 marker = '>'
294 294 else:
295 295 marker = ''
296 296 num = marker + str(i)
297 297 line = '%s%s%s %s%s' %(Colors.linenoEm, num,
298 298 Colors.line, line, Colors.Normal)
299 299 else:
300 300 num = '%*s' % (numbers_width,i)
301 301 line = '%s%s%s %s' %(Colors.lineno, num,
302 302 Colors.Normal, line)
303 303
304 304 res.append(line)
305 305 if lvals and i == lnum:
306 306 res.append(lvals + '\n')
307 307 i = i + 1
308 308 return res
309 309
310 310
311 311 #---------------------------------------------------------------------------
312 312 # Module classes
313 313 class TBTools:
314 314 """Basic tools used by all traceback printer classes."""
315 315
316 316 # This attribute us used in globalipapp.py to have stdout used for
317 317 # writting exceptions. This is needed so nose can trap them. This attribute
318 318 # should be None (the default, which will use IPython.utils.io.Term) or
319 319 # the string 'stdout' which will cause the override to sys.stdout.
320 320 out_stream = None
321 321
322 322 def __init__(self,color_scheme = 'NoColor',call_pdb=False):
323 323 # Whether to call the interactive pdb debugger after printing
324 324 # tracebacks or not
325 325 self.call_pdb = call_pdb
326 326
327 327 # Create color table
328 328 self.color_scheme_table = exception_colors()
329 329
330 330 self.set_colors(color_scheme)
331 331 self.old_scheme = color_scheme # save initial value for toggles
332 332
333 333 if call_pdb:
334 334 self.pdb = debugger.Pdb(self.color_scheme_table.active_scheme_name)
335 335 else:
336 336 self.pdb = None
337 337
338 338 def set_colors(self,*args,**kw):
339 339 """Shorthand access to the color table scheme selector method."""
340 340
341 341 # Set own color table
342 342 self.color_scheme_table.set_active_scheme(*args,**kw)
343 343 # for convenience, set Colors to the active scheme
344 344 self.Colors = self.color_scheme_table.active_colors
345 345 # Also set colors of debugger
346 346 if hasattr(self,'pdb') and self.pdb is not None:
347 347 self.pdb.set_colors(*args,**kw)
348 348
349 349 def color_toggle(self):
350 350 """Toggle between the currently active color scheme and NoColor."""
351 351
352 352 if self.color_scheme_table.active_scheme_name == 'NoColor':
353 353 self.color_scheme_table.set_active_scheme(self.old_scheme)
354 354 self.Colors = self.color_scheme_table.active_colors
355 355 else:
356 356 self.old_scheme = self.color_scheme_table.active_scheme_name
357 357 self.color_scheme_table.set_active_scheme('NoColor')
358 358 self.Colors = self.color_scheme_table.active_colors
359 359
360 360 #---------------------------------------------------------------------------
361 361 class ListTB(TBTools):
362 362 """Print traceback information from a traceback list, with optional color.
363 363
364 364 Calling: requires 3 arguments:
365 365 (etype, evalue, elist)
366 366 as would be obtained by:
367 367 etype, evalue, tb = sys.exc_info()
368 368 if tb:
369 369 elist = traceback.extract_tb(tb)
370 370 else:
371 371 elist = None
372 372
373 373 It can thus be used by programs which need to process the traceback before
374 374 printing (such as console replacements based on the code module from the
375 375 standard library).
376 376
377 377 Because they are meant to be called without a full traceback (only a
378 378 list), instances of this class can't call the interactive pdb debugger."""
379 379
380 380 def __init__(self,color_scheme = 'NoColor'):
381 381 TBTools.__init__(self,color_scheme = color_scheme,call_pdb=0)
382 382
383 383 def __call__(self, etype, value, elist):
384 384 IPython.utils.io.Term.cout.flush()
385 385 IPython.utils.io.Term.cerr.write(self.text(etype,value,elist))
386 386 IPython.utils.io.Term.cerr.write('\n')
387 387
388 388 def structured_traceback(self, etype, value, elist, context=5):
389 389 """Return a color formatted string with the traceback info.
390 390
391 391 Parameters
392 392 ----------
393 393 etype : exception type
394 394 Type of the exception raised.
395 395
396 396 value : object
397 397 Data stored in the exception
398 398
399 399 elist : list
400 400 List of frames, see class docstring for details.
401 401
402 402 Returns
403 403 -------
404 404 String with formatted exception.
405 405 """
406 406
407 407 Colors = self.Colors
408 408 out_string = []
409 409 if elist:
410 410 out_string.append('Traceback %s(most recent call last)%s:' %
411 411 (Colors.normalEm, Colors.Normal) + '\n')
412 412 out_string.extend(self._format_list(elist))
413 413 lines = self._format_exception_only(etype, value)
414 414 for line in lines[:-1]:
415 415 out_string.append(" "+line)
416 416 out_string.append(lines[-1])
417 417 return out_string
418 418
419 419 def text(self, etype, value, elist, context=5):
420 420 out_string = ListTB.structured_traceback(
421 421 self, etype, value, elist, context
422 422 )
423 423 return ''.join(out_string)
424 424
425 425 def _format_list(self, extracted_list):
426 426 """Format a list of traceback entry tuples for printing.
427 427
428 428 Given a list of tuples as returned by extract_tb() or
429 429 extract_stack(), return a list of strings ready for printing.
430 430 Each string in the resulting list corresponds to the item with the
431 431 same index in the argument list. Each string ends in a newline;
432 432 the strings may contain internal newlines as well, for those items
433 433 whose source text line is not None.
434 434
435 435 Lifted almost verbatim from traceback.py
436 436 """
437 437
438 438 Colors = self.Colors
439 439 list = []
440 440 for filename, lineno, name, line in extracted_list[:-1]:
441 441 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
442 442 (Colors.filename, filename, Colors.Normal,
443 443 Colors.lineno, lineno, Colors.Normal,
444 444 Colors.name, name, Colors.Normal)
445 445 if line:
446 446 item = item + ' %s\n' % line.strip()
447 447 list.append(item)
448 448 # Emphasize the last entry
449 449 filename, lineno, name, line = extracted_list[-1]
450 450 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
451 451 (Colors.normalEm,
452 452 Colors.filenameEm, filename, Colors.normalEm,
453 453 Colors.linenoEm, lineno, Colors.normalEm,
454 454 Colors.nameEm, name, Colors.normalEm,
455 455 Colors.Normal)
456 456 if line:
457 457 item = item + '%s %s%s\n' % (Colors.line, line.strip(),
458 458 Colors.Normal)
459 459 list.append(item)
460 460 return list
461 461
462 462 def _format_exception_only(self, etype, value):
463 463 """Format the exception part of a traceback.
464 464
465 465 The arguments are the exception type and value such as given by
466 466 sys.exc_info()[:2]. The return value is a list of strings, each ending
467 467 in a newline. Normally, the list contains a single string; however,
468 468 for SyntaxError exceptions, it contains several lines that (when
469 469 printed) display detailed information about where the syntax error
470 470 occurred. The message indicating which exception occurred is the
471 471 always last string in the list.
472 472
473 473 Also lifted nearly verbatim from traceback.py
474 474 """
475 475
476 476 have_filedata = False
477 477 Colors = self.Colors
478 478 list = []
479 479 try:
480 480 stype = Colors.excName + etype.__name__ + Colors.Normal
481 481 except AttributeError:
482 482 stype = etype # String exceptions don't get special coloring
483 483 if value is None:
484 484 list.append( str(stype) + '\n')
485 485 else:
486 486 if etype is SyntaxError:
487 487 try:
488 488 msg, (filename, lineno, offset, line) = value
489 489 except:
490 490 have_filedata = False
491 491 else:
492 492 have_filedata = True
493 493 #print 'filename is',filename # dbg
494 494 if not filename: filename = "<string>"
495 495 list.append('%s File %s"%s"%s, line %s%d%s\n' % \
496 496 (Colors.normalEm,
497 497 Colors.filenameEm, filename, Colors.normalEm,
498 498 Colors.linenoEm, lineno, Colors.Normal ))
499 499 if line is not None:
500 500 i = 0
501 501 while i < len(line) and line[i].isspace():
502 502 i = i+1
503 503 list.append('%s %s%s\n' % (Colors.line,
504 504 line.strip(),
505 505 Colors.Normal))
506 506 if offset is not None:
507 507 s = ' '
508 508 for c in line[i:offset-1]:
509 509 if c.isspace():
510 510 s = s + c
511 511 else:
512 512 s = s + ' '
513 513 list.append('%s%s^%s\n' % (Colors.caret, s,
514 514 Colors.Normal) )
515 515 value = msg
516 516 s = self._some_str(value)
517 517 if s:
518 518 list.append('%s%s:%s %s\n' % (str(stype), Colors.excName,
519 519 Colors.Normal, s))
520 520 else:
521 521 list.append('%s\n' % str(stype))
522 522
523 523 # sync with user hooks
524 524 if have_filedata:
525 525 ipinst = ipapi.get()
526 526 if ipinst is not None:
527 527 ipinst.hooks.synchronize_with_editor(filename, lineno, 0)
528 528
529 529 return list
530 530
531 531 def show_exception_only(self, etype, value):
532 532 """Only print the exception type and message, without a traceback.
533 533
534 534 Parameters
535 535 ----------
536 536 etype : exception type
537 537 value : exception value
538 538 """
539 539 # This method needs to use __call__ from *this* class, not the one from
540 540 # a subclass whose signature or behavior may be different
541 541 if self.out_stream == 'stdout':
542 542 ostream = sys.stdout
543 543 else:
544 544 ostream = IPython.utils.io.Term.cerr
545 545 ostream.flush()
546 546 ostream.write(ListTB.text(self, etype, value, []))
547 547 ostream.flush()
548 548
549 549 def _some_str(self, value):
550 550 # Lifted from traceback.py
551 551 try:
552 552 return str(value)
553 553 except:
554 554 return '<unprintable %s object>' % type(value).__name__
555 555
556 556 #----------------------------------------------------------------------------
557 557 class VerboseTB(TBTools):
558 558 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
559 559 of HTML. Requires inspect and pydoc. Crazy, man.
560 560
561 561 Modified version which optionally strips the topmost entries from the
562 562 traceback, to be used with alternate interpreters (because their own code
563 563 would appear in the traceback)."""
564 564
565 565 def __init__(self,color_scheme = 'Linux',tb_offset=0,long_header=0,
566 566 call_pdb = 0, include_vars=1):
567 567 """Specify traceback offset, headers and color scheme.
568 568
569 569 Define how many frames to drop from the tracebacks. Calling it with
570 570 tb_offset=1 allows use of this handler in interpreters which will have
571 571 their own code at the top of the traceback (VerboseTB will first
572 572 remove that frame before printing the traceback info)."""
573 573 TBTools.__init__(self,color_scheme=color_scheme,call_pdb=call_pdb)
574 574 self.tb_offset = tb_offset
575 575 self.long_header = long_header
576 576 self.include_vars = include_vars
577 577
578 578 def structured_traceback(self, etype, evalue, etb, context=5):
579 579 """Return a nice text document describing the traceback."""
580 580
581 581 # some locals
582 582 try:
583 583 etype = etype.__name__
584 584 except AttributeError:
585 585 pass
586 586 Colors = self.Colors # just a shorthand + quicker name lookup
587 587 ColorsNormal = Colors.Normal # used a lot
588 588 col_scheme = self.color_scheme_table.active_scheme_name
589 589 indent = ' '*INDENT_SIZE
590 590 em_normal = '%s\n%s%s' % (Colors.valEm, indent,ColorsNormal)
591 591 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
592 592 exc = '%s%s%s' % (Colors.excName,etype,ColorsNormal)
593 593
594 594 # some internal-use functions
595 595 def text_repr(value):
596 596 """Hopefully pretty robust repr equivalent."""
597 597 # this is pretty horrible but should always return *something*
598 598 try:
599 599 return pydoc.text.repr(value)
600 600 except KeyboardInterrupt:
601 601 raise
602 602 except:
603 603 try:
604 604 return repr(value)
605 605 except KeyboardInterrupt:
606 606 raise
607 607 except:
608 608 try:
609 609 # all still in an except block so we catch
610 610 # getattr raising
611 611 name = getattr(value, '__name__', None)
612 612 if name:
613 613 # ick, recursion
614 614 return text_repr(name)
615 615 klass = getattr(value, '__class__', None)
616 616 if klass:
617 617 return '%s instance' % text_repr(klass)
618 618 except KeyboardInterrupt:
619 619 raise
620 620 except:
621 621 return 'UNRECOVERABLE REPR FAILURE'
622 622 def eqrepr(value, repr=text_repr): return '=%s' % repr(value)
623 623 def nullrepr(value, repr=text_repr): return ''
624 624
625 625 # meat of the code begins
626 626 try:
627 627 etype = etype.__name__
628 628 except AttributeError:
629 629 pass
630 630
631 631 if self.long_header:
632 632 # Header with the exception type, python version, and date
633 633 pyver = 'Python ' + string.split(sys.version)[0] + ': ' + sys.executable
634 634 date = time.ctime(time.time())
635 635
636 636 head = '%s%s%s\n%s%s%s\n%s' % (Colors.topline, '-'*75, ColorsNormal,
637 637 exc, ' '*(75-len(str(etype))-len(pyver)),
638 638 pyver, string.rjust(date, 75) )
639 639 head += "\nA problem occured executing Python code. Here is the sequence of function"\
640 640 "\ncalls leading up to the error, with the most recent (innermost) call last."
641 641 else:
642 642 # Simplified header
643 643 head = '%s%s%s\n%s%s' % (Colors.topline, '-'*75, ColorsNormal,exc,
644 644 string.rjust('Traceback (most recent call last)',
645 645 75 - len(str(etype)) ) )
646 646 frames = []
647 647 # Flush cache before calling inspect. This helps alleviate some of the
648 648 # problems with python 2.3's inspect.py.
649 649 linecache.checkcache()
650 650 # Drop topmost frames if requested
651 651 try:
652 652 # Try the default getinnerframes and Alex's: Alex's fixes some
653 653 # problems, but it generates empty tracebacks for console errors
654 654 # (5 blanks lines) where none should be returned.
655 655 #records = inspect.getinnerframes(etb, context)[self.tb_offset:]
656 656 #print 'python records:', records # dbg
657 657 records = _fixed_getinnerframes(etb, context,self.tb_offset)
658 658 #print 'alex records:', records # dbg
659 659 except:
660 660
661 661 # FIXME: I've been getting many crash reports from python 2.3
662 662 # users, traceable to inspect.py. If I can find a small test-case
663 663 # to reproduce this, I should either write a better workaround or
664 664 # file a bug report against inspect (if that's the real problem).
665 665 # So far, I haven't been able to find an isolated example to
666 666 # reproduce the problem.
667 667 inspect_error()
668 668 traceback.print_exc(file=IPython.utils.io.Term.cerr)
669 669 info('\nUnfortunately, your original traceback can not be constructed.\n')
670 670 return ''
671 671
672 672 # build some color string templates outside these nested loops
673 673 tpl_link = '%s%%s%s' % (Colors.filenameEm,ColorsNormal)
674 674 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
675 675 ColorsNormal)
676 676 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
677 677 (Colors.vName, Colors.valEm, ColorsNormal)
678 678 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
679 679 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
680 680 Colors.vName, ColorsNormal)
681 681 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
682 682 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
683 683 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm,Colors.line,
684 684 ColorsNormal)
685 685
686 686 # now, loop over all records printing context and info
687 687 abspath = os.path.abspath
688 688 for frame, file, lnum, func, lines, index in records:
689 689 #print '*** record:',file,lnum,func,lines,index # dbg
690 690 try:
691 691 file = file and abspath(file) or '?'
692 692 except OSError:
693 693 # if file is '<console>' or something not in the filesystem,
694 694 # the abspath call will throw an OSError. Just ignore it and
695 695 # keep the original file string.
696 696 pass
697 697 link = tpl_link % file
698 698 try:
699 699 args, varargs, varkw, locals = inspect.getargvalues(frame)
700 700 except:
701 701 # This can happen due to a bug in python2.3. We should be
702 702 # able to remove this try/except when 2.4 becomes a
703 703 # requirement. Bug details at http://python.org/sf/1005466
704 704 inspect_error()
705 705 traceback.print_exc(file=IPython.utils.io.Term.cerr)
706 706 info("\nIPython's exception reporting continues...\n")
707 707
708 708 if func == '?':
709 709 call = ''
710 710 else:
711 711 # Decide whether to include variable details or not
712 712 var_repr = self.include_vars and eqrepr or nullrepr
713 713 try:
714 714 call = tpl_call % (func,inspect.formatargvalues(args,
715 715 varargs, varkw,
716 716 locals,formatvalue=var_repr))
717 717 except KeyError:
718 718 # Very odd crash from inspect.formatargvalues(). The
719 719 # scenario under which it appeared was a call to
720 720 # view(array,scale) in NumTut.view.view(), where scale had
721 721 # been defined as a scalar (it should be a tuple). Somehow
722 722 # inspect messes up resolving the argument list of view()
723 723 # and barfs out. At some point I should dig into this one
724 724 # and file a bug report about it.
725 725 inspect_error()
726 726 traceback.print_exc(file=IPython.utils.io.Term.cerr)
727 727 info("\nIPython's exception reporting continues...\n")
728 728 call = tpl_call_fail % func
729 729
730 730 # Initialize a list of names on the current line, which the
731 731 # tokenizer below will populate.
732 732 names = []
733 733
734 734 def tokeneater(token_type, token, start, end, line):
735 735 """Stateful tokeneater which builds dotted names.
736 736
737 737 The list of names it appends to (from the enclosing scope) can
738 738 contain repeated composite names. This is unavoidable, since
739 739 there is no way to disambguate partial dotted structures until
740 740 the full list is known. The caller is responsible for pruning
741 741 the final list of duplicates before using it."""
742 742
743 743 # build composite names
744 744 if token == '.':
745 745 try:
746 746 names[-1] += '.'
747 747 # store state so the next token is added for x.y.z names
748 748 tokeneater.name_cont = True
749 749 return
750 750 except IndexError:
751 751 pass
752 752 if token_type == tokenize.NAME and token not in keyword.kwlist:
753 753 if tokeneater.name_cont:
754 754 # Dotted names
755 755 names[-1] += token
756 756 tokeneater.name_cont = False
757 757 else:
758 758 # Regular new names. We append everything, the caller
759 759 # will be responsible for pruning the list later. It's
760 760 # very tricky to try to prune as we go, b/c composite
761 761 # names can fool us. The pruning at the end is easy
762 762 # to do (or the caller can print a list with repeated
763 763 # names if so desired.
764 764 names.append(token)
765 765 elif token_type == tokenize.NEWLINE:
766 766 raise IndexError
767 767 # we need to store a bit of state in the tokenizer to build
768 768 # dotted names
769 769 tokeneater.name_cont = False
770 770
771 771 def linereader(file=file, lnum=[lnum], getline=linecache.getline):
772 772 line = getline(file, lnum[0])
773 773 lnum[0] += 1
774 774 return line
775 775
776 776 # Build the list of names on this line of code where the exception
777 777 # occurred.
778 778 try:
779 779 # This builds the names list in-place by capturing it from the
780 780 # enclosing scope.
781 781 tokenize.tokenize(linereader, tokeneater)
782 782 except IndexError:
783 783 # signals exit of tokenizer
784 784 pass
785 785 except tokenize.TokenError,msg:
786 786 _m = ("An unexpected error occurred while tokenizing input\n"
787 787 "The following traceback may be corrupted or invalid\n"
788 788 "The error message is: %s\n" % msg)
789 789 error(_m)
790 790
791 791 # prune names list of duplicates, but keep the right order
792 792 unique_names = uniq_stable(names)
793 793
794 794 # Start loop over vars
795 795 lvals = []
796 796 if self.include_vars:
797 797 for name_full in unique_names:
798 798 name_base = name_full.split('.',1)[0]
799 799 if name_base in frame.f_code.co_varnames:
800 800 if locals.has_key(name_base):
801 801 try:
802 802 value = repr(eval(name_full,locals))
803 803 except:
804 804 value = undefined
805 805 else:
806 806 value = undefined
807 807 name = tpl_local_var % name_full
808 808 else:
809 809 if frame.f_globals.has_key(name_base):
810 810 try:
811 811 value = repr(eval(name_full,frame.f_globals))
812 812 except:
813 813 value = undefined
814 814 else:
815 815 value = undefined
816 816 name = tpl_global_var % name_full
817 817 lvals.append(tpl_name_val % (name,value))
818 818 if lvals:
819 819 lvals = '%s%s' % (indent,em_normal.join(lvals))
820 820 else:
821 821 lvals = ''
822 822
823 823 level = '%s %s\n' % (link,call)
824 824
825 825 if index is None:
826 826 frames.append(level)
827 827 else:
828 828 frames.append('%s%s' % (level,''.join(
829 829 _format_traceback_lines(lnum,index,lines,Colors,lvals,
830 830 col_scheme))))
831 831
832 832 # Get (safely) a string form of the exception info
833 833 try:
834 834 etype_str,evalue_str = map(str,(etype,evalue))
835 835 except:
836 836 # User exception is improperly defined.
837 837 etype,evalue = str,sys.exc_info()[:2]
838 838 etype_str,evalue_str = map(str,(etype,evalue))
839 839 # ... and format it
840 840 exception = ['%s%s%s: %s' % (Colors.excName, etype_str,
841 841 ColorsNormal, evalue_str)]
842 842 if type(evalue) is types.InstanceType:
843 843 try:
844 844 names = [w for w in dir(evalue) if isinstance(w, basestring)]
845 845 except:
846 846 # Every now and then, an object with funny inernals blows up
847 847 # when dir() is called on it. We do the best we can to report
848 848 # the problem and continue
849 849 _m = '%sException reporting error (object with broken dir())%s:'
850 850 exception.append(_m % (Colors.excName,ColorsNormal))
851 851 etype_str,evalue_str = map(str,sys.exc_info()[:2])
852 852 exception.append('%s%s%s: %s' % (Colors.excName,etype_str,
853 853 ColorsNormal, evalue_str))
854 854 names = []
855 855 for name in names:
856 856 value = text_repr(getattr(evalue, name))
857 857 exception.append('\n%s%s = %s' % (indent, name, value))
858 858
859 859 # vds: >>
860 860 if records:
861 861 filepath, lnum = records[-1][1:3]
862 862 #print "file:", str(file), "linenb", str(lnum) # dbg
863 863 filepath = os.path.abspath(filepath)
864 864 ipinst = ipapi.get()
865 865 if ipinst is not None:
866 866 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
867 867 # vds: <<
868 868
869 869 # return all our info assembled as a single string
870 870 # return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) )
871 871 return [head] + frames + [''.join(exception[0])]
872 872
873 873 def text(self, etype, evalue, etb, context=5):
874 874 tb_list = VerboseTB.structured_traceback(
875 875 self, etype, evalue, etb, context
876 876 )
877 877 return '\n'.join(tb_list)
878 878
879 879 def debugger(self,force=False):
880 880 """Call up the pdb debugger if desired, always clean up the tb
881 881 reference.
882 882
883 883 Keywords:
884 884
885 885 - force(False): by default, this routine checks the instance call_pdb
886 886 flag and does not actually invoke the debugger if the flag is false.
887 887 The 'force' option forces the debugger to activate even if the flag
888 888 is false.
889 889
890 890 If the call_pdb flag is set, the pdb interactive debugger is
891 891 invoked. In all cases, the self.tb reference to the current traceback
892 892 is deleted to prevent lingering references which hamper memory
893 893 management.
894 894
895 895 Note that each call to pdb() does an 'import readline', so if your app
896 896 requires a special setup for the readline completers, you'll have to
897 897 fix that by hand after invoking the exception handler."""
898 898
899 899 if force or self.call_pdb:
900 900 if self.pdb is None:
901 901 self.pdb = debugger.Pdb(
902 902 self.color_scheme_table.active_scheme_name)
903 903 # the system displayhook may have changed, restore the original
904 904 # for pdb
905 display_trap = DisplayTrap(None, sys.__displayhook__)
905 display_trap = DisplayTrap(hook=sys.__displayhook__)
906 906 with display_trap:
907 907 self.pdb.reset()
908 908 # Find the right frame so we don't pop up inside ipython itself
909 909 if hasattr(self,'tb') and self.tb is not None:
910 910 etb = self.tb
911 911 else:
912 912 etb = self.tb = sys.last_traceback
913 913 while self.tb is not None and self.tb.tb_next is not None:
914 914 self.tb = self.tb.tb_next
915 915 if etb and etb.tb_next:
916 916 etb = etb.tb_next
917 917 self.pdb.botframe = etb.tb_frame
918 918 self.pdb.interaction(self.tb.tb_frame, self.tb)
919 919
920 920 if hasattr(self,'tb'):
921 921 del self.tb
922 922
923 923 def handler(self, info=None):
924 924 (etype, evalue, etb) = info or sys.exc_info()
925 925 self.tb = etb
926 926 IPython.utils.io.Term.cout.flush()
927 927 IPython.utils.io.Term.cerr.write(self.text(etype, evalue, etb))
928 928 IPython.utils.io.Term.cerr.write('\n')
929 929
930 930 # Changed so an instance can just be called as VerboseTB_inst() and print
931 931 # out the right info on its own.
932 932 def __call__(self, etype=None, evalue=None, etb=None):
933 933 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
934 934 if etb is None:
935 935 self.handler()
936 936 else:
937 937 self.handler((etype, evalue, etb))
938 938 try:
939 939 self.debugger()
940 940 except KeyboardInterrupt:
941 941 print "\nKeyboardInterrupt"
942 942
943 943 #----------------------------------------------------------------------------
944 944 class FormattedTB(VerboseTB,ListTB):
945 945 """Subclass ListTB but allow calling with a traceback.
946 946
947 947 It can thus be used as a sys.excepthook for Python > 2.1.
948 948
949 949 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
950 950
951 951 Allows a tb_offset to be specified. This is useful for situations where
952 952 one needs to remove a number of topmost frames from the traceback (such as
953 953 occurs with python programs that themselves execute other python code,
954 954 like Python shells). """
955 955
956 956 def __init__(self, mode = 'Plain', color_scheme='Linux',
957 957 tb_offset = 0,long_header=0,call_pdb=0,include_vars=0):
958 958
959 959 # NEVER change the order of this list. Put new modes at the end:
960 960 self.valid_modes = ['Plain','Context','Verbose']
961 961 self.verbose_modes = self.valid_modes[1:3]
962 962
963 963 VerboseTB.__init__(self,color_scheme,tb_offset,long_header,
964 964 call_pdb=call_pdb,include_vars=include_vars)
965 965 self.set_mode(mode)
966 966
967 967 def _extract_tb(self,tb):
968 968 if tb:
969 969 return traceback.extract_tb(tb)
970 970 else:
971 971 return None
972 972
973 973 def structured_traceback(self, etype, value, tb, context=5, mode=None):
974 974 mode = self.mode if mode is None else mode
975 975 if mode in self.verbose_modes:
976 976 # Verbose modes need a full traceback
977 977 return VerboseTB.structured_traceback(
978 978 self, etype, value, tb, context
979 979 )
980 980 else:
981 981 # We must check the source cache because otherwise we can print
982 982 # out-of-date source code.
983 983 linecache.checkcache()
984 984 # Now we can extract and format the exception
985 985 elist = self._extract_tb(tb)
986 986 if len(elist) > self.tb_offset:
987 987 del elist[:self.tb_offset]
988 988 return ListTB.structured_traceback(
989 989 self, etype, value, elist, context
990 990 )
991 991
992 992 def text(self, etype, value, tb, context=5, mode=None):
993 993 """Return formatted traceback.
994 994
995 995 If the optional mode parameter is given, it overrides the current
996 996 mode."""
997 997 tb_list = FormattedTB.structured_traceback(
998 998 self, etype, value, tb, context, mode
999 999 )
1000 1000 return '\n'.join(tb_list)
1001 1001
1002 1002 def set_mode(self,mode=None):
1003 1003 """Switch to the desired mode.
1004 1004
1005 1005 If mode is not specified, cycles through the available modes."""
1006 1006
1007 1007 if not mode:
1008 1008 new_idx = ( self.valid_modes.index(self.mode) + 1 ) % \
1009 1009 len(self.valid_modes)
1010 1010 self.mode = self.valid_modes[new_idx]
1011 1011 elif mode not in self.valid_modes:
1012 1012 raise ValueError, 'Unrecognized mode in FormattedTB: <'+mode+'>\n'\
1013 1013 'Valid modes: '+str(self.valid_modes)
1014 1014 else:
1015 1015 self.mode = mode
1016 1016 # include variable details only in 'Verbose' mode
1017 1017 self.include_vars = (self.mode == self.valid_modes[2])
1018 1018
1019 1019 # some convenient shorcuts
1020 1020 def plain(self):
1021 1021 self.set_mode(self.valid_modes[0])
1022 1022
1023 1023 def context(self):
1024 1024 self.set_mode(self.valid_modes[1])
1025 1025
1026 1026 def verbose(self):
1027 1027 self.set_mode(self.valid_modes[2])
1028 1028
1029 1029 #----------------------------------------------------------------------------
1030 1030 class AutoFormattedTB(FormattedTB):
1031 1031 """A traceback printer which can be called on the fly.
1032 1032
1033 1033 It will find out about exceptions by itself.
1034 1034
1035 1035 A brief example:
1036 1036
1037 1037 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
1038 1038 try:
1039 1039 ...
1040 1040 except:
1041 1041 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1042 1042 """
1043 1043
1044 1044 def __call__(self,etype=None,evalue=None,etb=None,
1045 1045 out=None,tb_offset=None):
1046 1046 """Print out a formatted exception traceback.
1047 1047
1048 1048 Optional arguments:
1049 1049 - out: an open file-like object to direct output to.
1050 1050
1051 1051 - tb_offset: the number of frames to skip over in the stack, on a
1052 1052 per-call basis (this overrides temporarily the instance's tb_offset
1053 1053 given at initialization time. """
1054 1054
1055 1055 if out is None:
1056 1056 if self.out_stream == 'stdout':
1057 1057 out = sys.stdout
1058 1058 else:
1059 1059 out = IPython.utils.io.Term.cerr
1060 1060 out.flush()
1061 1061 if tb_offset is not None:
1062 1062 tb_offset, self.tb_offset = self.tb_offset, tb_offset
1063 1063 out.write(self.text(etype, evalue, etb))
1064 1064 out.write('\n')
1065 1065 self.tb_offset = tb_offset
1066 1066 else:
1067 1067 out.write(self.text(etype, evalue, etb))
1068 1068 out.write('\n')
1069 1069 out.flush()
1070 1070 try:
1071 1071 self.debugger()
1072 1072 except KeyboardInterrupt:
1073 1073 print "\nKeyboardInterrupt"
1074 1074
1075 1075 def structured_traceback(self, etype=None, value=None, tb=None,
1076 1076 context=5, mode=None):
1077 1077 if etype is None:
1078 1078 etype,value,tb = sys.exc_info()
1079 1079 self.tb = tb
1080 1080 return FormattedTB.structured_traceback(
1081 1081 self, etype, value, tb, context, mode
1082 1082 )
1083 1083
1084 1084 def text(self, etype=None, value=None, tb=None, context=5, mode=None):
1085 1085 tb_list = AutoFormattedTB.structured_traceback(
1086 1086 self, etype, value, tb, context, mode
1087 1087 )
1088 1088 return '\n'.join(tb_list)
1089 1089
1090 1090 #---------------------------------------------------------------------------
1091 1091
1092 1092 # A simple class to preserve Nathan's original functionality.
1093 1093 class ColorTB(FormattedTB):
1094 1094 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1095 1095 def __init__(self,color_scheme='Linux',call_pdb=0):
1096 1096 FormattedTB.__init__(self,color_scheme=color_scheme,
1097 1097 call_pdb=call_pdb)
1098 1098
1099 1099
1100 1100 class SyntaxTB(ListTB):
1101 1101 """Extension which holds some state: the last exception value"""
1102 1102
1103 1103 def __init__(self,color_scheme = 'NoColor'):
1104 1104 ListTB.__init__(self,color_scheme)
1105 1105 self.last_syntax_error = None
1106 1106
1107 1107 def __call__(self, etype, value, elist):
1108 1108 self.last_syntax_error = value
1109 1109 ListTB.__call__(self,etype,value,elist)
1110 1110
1111 1111 def clear_err_state(self):
1112 1112 """Return the current error state and clear it"""
1113 1113 e = self.last_syntax_error
1114 1114 self.last_syntax_error = None
1115 1115 return e
1116 1116
1117 1117 #----------------------------------------------------------------------------
1118 1118 # module testing (minimal)
1119 1119 if __name__ == "__main__":
1120 1120 def spam(c, (d, e)):
1121 1121 x = c + d
1122 1122 y = c * d
1123 1123 foo(x, y)
1124 1124
1125 1125 def foo(a, b, bar=1):
1126 1126 eggs(a, b + bar)
1127 1127
1128 1128 def eggs(f, g, z=globals()):
1129 1129 h = f + g
1130 1130 i = f - g
1131 1131 return h / i
1132 1132
1133 1133 print ''
1134 1134 print '*** Before ***'
1135 1135 try:
1136 1136 print spam(1, (2, 3))
1137 1137 except:
1138 1138 traceback.print_exc()
1139 1139 print ''
1140 1140
1141 1141 handler = ColorTB()
1142 1142 print '*** ColorTB ***'
1143 1143 try:
1144 1144 print spam(1, (2, 3))
1145 1145 except:
1146 1146 apply(handler, sys.exc_info() )
1147 1147 print ''
1148 1148
1149 1149 handler = VerboseTB()
1150 1150 print '*** VerboseTB ***'
1151 1151 try:
1152 1152 print spam(1, (2, 3))
1153 1153 except:
1154 1154 apply(handler, sys.exc_info() )
1155 1155 print ''
1156 1156
General Comments 0
You need to be logged in to leave comments. Login now