##// END OF EJS Templates
excolors.py => core/excolors.py and updated import statements.
Brian Granger -
Show More
@@ -1,523 +1,523 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
28 28 import bdb
29 29 import cmd
30 30 import linecache
31 31 import os
32 32 import sys
33 33
34 34 from IPython import PyColorize, ipapi
35 35 from IPython.utils import coloransi
36 36 from IPython.genutils import Term
37 from IPython.excolors import exception_colors
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):
64 64 if et==bdb.BdbQuit:
65 65 print 'Exiting Debugger.'
66 66 else:
67 67 BdbQuit_excepthook.excepthook_ori(et,ev,tb)
68 68
69 69 def BdbQuit_IPython_excepthook(self,et,ev,tb):
70 70 print 'Exiting Debugger.'
71 71
72 72 class Tracer(object):
73 73 """Class for local debugging, similar to pdb.set_trace.
74 74
75 75 Instances of this class, when called, behave like pdb.set_trace, but
76 76 providing IPython's enhanced capabilities.
77 77
78 78 This is implemented as a class which must be initialized in your own code
79 79 and not as a standalone function because we need to detect at runtime
80 80 whether IPython is already active or not. That detection is done in the
81 81 constructor, ensuring that this code plays nicely with a running IPython,
82 82 while functioning acceptably (though with limitations) if outside of it.
83 83 """
84 84
85 85 def __init__(self,colors=None):
86 86 """Create a local debugger instance.
87 87
88 88 :Parameters:
89 89
90 90 - `colors` (None): a string containing the name of the color scheme to
91 91 use, it must be one of IPython's valid color schemes. If not given, the
92 92 function will default to the current IPython scheme when running inside
93 93 IPython, and to 'NoColor' otherwise.
94 94
95 95 Usage example:
96 96
97 97 from IPython.core.debugger import Tracer; debug_here = Tracer()
98 98
99 99 ... later in your code
100 100 debug_here() # -> will open up the debugger at that point.
101 101
102 102 Once the debugger activates, you can use all of its regular commands to
103 103 step through code, set breakpoints, etc. See the pdb documentation
104 104 from the Python standard library for usage details.
105 105 """
106 106
107 107 global __IPYTHON__
108 108 try:
109 109 __IPYTHON__
110 110 except NameError:
111 111 # Outside of ipython, we set our own exception hook manually
112 112 __IPYTHON__ = ipapi.get(True,False)
113 113 BdbQuit_excepthook.excepthook_ori = sys.excepthook
114 114 sys.excepthook = BdbQuit_excepthook
115 115 def_colors = 'NoColor'
116 116 try:
117 117 # Limited tab completion support
118 118 import readline
119 119 readline.parse_and_bind('tab: complete')
120 120 except ImportError:
121 121 pass
122 122 else:
123 123 # In ipython, we use its custom exception handler mechanism
124 124 ip = ipapi.get()
125 125 def_colors = ip.options.colors
126 126 ip.set_custom_exc((bdb.BdbQuit,),BdbQuit_IPython_excepthook)
127 127
128 128 if colors is None:
129 129 colors = def_colors
130 130 self.debugger = Pdb(colors)
131 131
132 132 def __call__(self):
133 133 """Starts an interactive debugger at the point where called.
134 134
135 135 This is similar to the pdb.set_trace() function from the std lib, but
136 136 using IPython's enhanced debugger."""
137 137
138 138 self.debugger.set_trace(sys._getframe().f_back)
139 139
140 140 def decorate_fn_with_doc(new_fn, old_fn, additional_text=""):
141 141 """Make new_fn have old_fn's doc string. This is particularly useful
142 142 for the do_... commands that hook into the help system.
143 143 Adapted from from a comp.lang.python posting
144 144 by Duncan Booth."""
145 145 def wrapper(*args, **kw):
146 146 return new_fn(*args, **kw)
147 147 if old_fn.__doc__:
148 148 wrapper.__doc__ = old_fn.__doc__ + additional_text
149 149 return wrapper
150 150
151 151 def _file_lines(fname):
152 152 """Return the contents of a named file as a list of lines.
153 153
154 154 This function never raises an IOError exception: if the file can't be
155 155 read, it simply returns an empty list."""
156 156
157 157 try:
158 158 outfile = open(fname)
159 159 except IOError:
160 160 return []
161 161 else:
162 162 out = outfile.readlines()
163 163 outfile.close()
164 164 return out
165 165
166 166 class Pdb(OldPdb):
167 167 """Modified Pdb class, does not load readline."""
168 168
169 169 if sys.version[:3] >= '2.5' or has_pydb:
170 170 def __init__(self,color_scheme='NoColor',completekey=None,
171 171 stdin=None, stdout=None):
172 172
173 173 # Parent constructor:
174 174 if has_pydb and completekey is None:
175 175 OldPdb.__init__(self,stdin=stdin,stdout=Term.cout)
176 176 else:
177 177 OldPdb.__init__(self,completekey,stdin,stdout)
178 178
179 179 self.prompt = prompt # The default prompt is '(Pdb)'
180 180
181 181 # IPython changes...
182 182 self.is_pydb = has_pydb
183 183
184 184 if self.is_pydb:
185 185
186 186 # iplib.py's ipalias seems to want pdb's checkline
187 187 # which located in pydb.fn
188 188 import pydb.fns
189 189 self.checkline = lambda filename, lineno: \
190 190 pydb.fns.checkline(self, filename, lineno)
191 191
192 192 self.curframe = None
193 193 self.do_restart = self.new_do_restart
194 194
195 195 self.old_all_completions = __IPYTHON__.Completer.all_completions
196 196 __IPYTHON__.Completer.all_completions=self.all_completions
197 197
198 198 self.do_list = decorate_fn_with_doc(self.list_command_pydb,
199 199 OldPdb.do_list)
200 200 self.do_l = self.do_list
201 201 self.do_frame = decorate_fn_with_doc(self.new_do_frame,
202 202 OldPdb.do_frame)
203 203
204 204 self.aliases = {}
205 205
206 206 # Create color table: we copy the default one from the traceback
207 207 # module and add a few attributes needed for debugging
208 208 self.color_scheme_table = exception_colors()
209 209
210 210 # shorthands
211 211 C = coloransi.TermColors
212 212 cst = self.color_scheme_table
213 213
214 214 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
215 215 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
216 216
217 217 cst['Linux'].colors.breakpoint_enabled = C.LightRed
218 218 cst['Linux'].colors.breakpoint_disabled = C.Red
219 219
220 220 cst['LightBG'].colors.breakpoint_enabled = C.LightRed
221 221 cst['LightBG'].colors.breakpoint_disabled = C.Red
222 222
223 223 self.set_colors(color_scheme)
224 224
225 225 # Add a python parser so we can syntax highlight source while
226 226 # debugging.
227 227 self.parser = PyColorize.Parser()
228 228
229 229
230 230 else:
231 231 # Ugly hack: for Python 2.3-2.4, we can't call the parent constructor,
232 232 # because it binds readline and breaks tab-completion. This means we
233 233 # have to COPY the constructor here.
234 234 def __init__(self,color_scheme='NoColor'):
235 235 bdb.Bdb.__init__(self)
236 236 cmd.Cmd.__init__(self,completekey=None) # don't load readline
237 237 self.prompt = 'ipdb> ' # The default prompt is '(Pdb)'
238 238 self.aliases = {}
239 239
240 240 # These two lines are part of the py2.4 constructor, let's put them
241 241 # unconditionally here as they won't cause any problems in 2.3.
242 242 self.mainpyfile = ''
243 243 self._wait_for_mainpyfile = 0
244 244
245 245 # Read $HOME/.pdbrc and ./.pdbrc
246 246 try:
247 247 self.rcLines = _file_lines(os.path.join(os.environ['HOME'],
248 248 ".pdbrc"))
249 249 except KeyError:
250 250 self.rcLines = []
251 251 self.rcLines.extend(_file_lines(".pdbrc"))
252 252
253 253 # Create color table: we copy the default one from the traceback
254 254 # module and add a few attributes needed for debugging
255 255 self.color_scheme_table = exception_colors()
256 256
257 257 # shorthands
258 258 C = coloransi.TermColors
259 259 cst = self.color_scheme_table
260 260
261 261 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
262 262 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
263 263
264 264 cst['Linux'].colors.breakpoint_enabled = C.LightRed
265 265 cst['Linux'].colors.breakpoint_disabled = C.Red
266 266
267 267 cst['LightBG'].colors.breakpoint_enabled = C.LightRed
268 268 cst['LightBG'].colors.breakpoint_disabled = C.Red
269 269
270 270 self.set_colors(color_scheme)
271 271
272 272 # Add a python parser so we can syntax highlight source while
273 273 # debugging.
274 274 self.parser = PyColorize.Parser()
275 275
276 276 def set_colors(self, scheme):
277 277 """Shorthand access to the color table scheme selector method."""
278 278 self.color_scheme_table.set_active_scheme(scheme)
279 279
280 280 def interaction(self, frame, traceback):
281 281 __IPYTHON__.set_completer_frame(frame)
282 282 OldPdb.interaction(self, frame, traceback)
283 283
284 284 def new_do_up(self, arg):
285 285 OldPdb.do_up(self, arg)
286 286 __IPYTHON__.set_completer_frame(self.curframe)
287 287 do_u = do_up = decorate_fn_with_doc(new_do_up, OldPdb.do_up)
288 288
289 289 def new_do_down(self, arg):
290 290 OldPdb.do_down(self, arg)
291 291 __IPYTHON__.set_completer_frame(self.curframe)
292 292
293 293 do_d = do_down = decorate_fn_with_doc(new_do_down, OldPdb.do_down)
294 294
295 295 def new_do_frame(self, arg):
296 296 OldPdb.do_frame(self, arg)
297 297 __IPYTHON__.set_completer_frame(self.curframe)
298 298
299 299 def new_do_quit(self, arg):
300 300
301 301 if hasattr(self, 'old_all_completions'):
302 302 __IPYTHON__.Completer.all_completions=self.old_all_completions
303 303
304 304
305 305 return OldPdb.do_quit(self, arg)
306 306
307 307 do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit)
308 308
309 309 def new_do_restart(self, arg):
310 310 """Restart command. In the context of ipython this is exactly the same
311 311 thing as 'quit'."""
312 312 self.msg("Restart doesn't make sense here. Using 'quit' instead.")
313 313 return self.do_quit(arg)
314 314
315 315 def postloop(self):
316 316 __IPYTHON__.set_completer_frame(None)
317 317
318 318 def print_stack_trace(self):
319 319 try:
320 320 for frame_lineno in self.stack:
321 321 self.print_stack_entry(frame_lineno, context = 5)
322 322 except KeyboardInterrupt:
323 323 pass
324 324
325 325 def print_stack_entry(self,frame_lineno,prompt_prefix='\n-> ',
326 326 context = 3):
327 327 #frame, lineno = frame_lineno
328 328 print >>Term.cout, self.format_stack_entry(frame_lineno, '', context)
329 329
330 330 # vds: >>
331 331 frame, lineno = frame_lineno
332 332 filename = frame.f_code.co_filename
333 333 __IPYTHON__.hooks.synchronize_with_editor(filename, lineno, 0)
334 334 # vds: <<
335 335
336 336 def format_stack_entry(self, frame_lineno, lprefix=': ', context = 3):
337 337 import linecache, repr
338 338
339 339 ret = []
340 340
341 341 Colors = self.color_scheme_table.active_colors
342 342 ColorsNormal = Colors.Normal
343 343 tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal)
344 344 tpl_call = '%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal)
345 345 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
346 346 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line,
347 347 ColorsNormal)
348 348
349 349 frame, lineno = frame_lineno
350 350
351 351 return_value = ''
352 352 if '__return__' in frame.f_locals:
353 353 rv = frame.f_locals['__return__']
354 354 #return_value += '->'
355 355 return_value += repr.repr(rv) + '\n'
356 356 ret.append(return_value)
357 357
358 358 #s = filename + '(' + `lineno` + ')'
359 359 filename = self.canonic(frame.f_code.co_filename)
360 360 link = tpl_link % filename
361 361
362 362 if frame.f_code.co_name:
363 363 func = frame.f_code.co_name
364 364 else:
365 365 func = "<lambda>"
366 366
367 367 call = ''
368 368 if func != '?':
369 369 if '__args__' in frame.f_locals:
370 370 args = repr.repr(frame.f_locals['__args__'])
371 371 else:
372 372 args = '()'
373 373 call = tpl_call % (func, args)
374 374
375 375 # The level info should be generated in the same format pdb uses, to
376 376 # avoid breaking the pdbtrack functionality of python-mode in *emacs.
377 377 if frame is self.curframe:
378 378 ret.append('> ')
379 379 else:
380 380 ret.append(' ')
381 381 ret.append('%s(%s)%s\n' % (link,lineno,call))
382 382
383 383 start = lineno - 1 - context//2
384 384 lines = linecache.getlines(filename)
385 385 start = max(start, 0)
386 386 start = min(start, len(lines) - context)
387 387 lines = lines[start : start + context]
388 388
389 389 for i,line in enumerate(lines):
390 390 show_arrow = (start + 1 + i == lineno)
391 391 linetpl = (frame is self.curframe or show_arrow) \
392 392 and tpl_line_em \
393 393 or tpl_line
394 394 ret.append(self.__format_line(linetpl, filename,
395 395 start + 1 + i, line,
396 396 arrow = show_arrow) )
397 397
398 398 return ''.join(ret)
399 399
400 400 def __format_line(self, tpl_line, filename, lineno, line, arrow = False):
401 401 bp_mark = ""
402 402 bp_mark_color = ""
403 403
404 404 scheme = self.color_scheme_table.active_scheme_name
405 405 new_line, err = self.parser.format2(line, 'str', scheme)
406 406 if not err: line = new_line
407 407
408 408 bp = None
409 409 if lineno in self.get_file_breaks(filename):
410 410 bps = self.get_breaks(filename, lineno)
411 411 bp = bps[-1]
412 412
413 413 if bp:
414 414 Colors = self.color_scheme_table.active_colors
415 415 bp_mark = str(bp.number)
416 416 bp_mark_color = Colors.breakpoint_enabled
417 417 if not bp.enabled:
418 418 bp_mark_color = Colors.breakpoint_disabled
419 419
420 420 numbers_width = 7
421 421 if arrow:
422 422 # This is the line with the error
423 423 pad = numbers_width - len(str(lineno)) - len(bp_mark)
424 424 if pad >= 3:
425 425 marker = '-'*(pad-3) + '-> '
426 426 elif pad == 2:
427 427 marker = '> '
428 428 elif pad == 1:
429 429 marker = '>'
430 430 else:
431 431 marker = ''
432 432 num = '%s%s' % (marker, str(lineno))
433 433 line = tpl_line % (bp_mark_color + bp_mark, num, line)
434 434 else:
435 435 num = '%*s' % (numbers_width - len(bp_mark), str(lineno))
436 436 line = tpl_line % (bp_mark_color + bp_mark, num, line)
437 437
438 438 return line
439 439
440 440 def list_command_pydb(self, arg):
441 441 """List command to use if we have a newer pydb installed"""
442 442 filename, first, last = OldPdb.parse_list_cmd(self, arg)
443 443 if filename is not None:
444 444 self.print_list_lines(filename, first, last)
445 445
446 446 def print_list_lines(self, filename, first, last):
447 447 """The printing (as opposed to the parsing part of a 'list'
448 448 command."""
449 449 try:
450 450 Colors = self.color_scheme_table.active_colors
451 451 ColorsNormal = Colors.Normal
452 452 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
453 453 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal)
454 454 src = []
455 455 for lineno in range(first, last+1):
456 456 line = linecache.getline(filename, lineno)
457 457 if not line:
458 458 break
459 459
460 460 if lineno == self.curframe.f_lineno:
461 461 line = self.__format_line(tpl_line_em, filename, lineno, line, arrow = True)
462 462 else:
463 463 line = self.__format_line(tpl_line, filename, lineno, line, arrow = False)
464 464
465 465 src.append(line)
466 466 self.lineno = lineno
467 467
468 468 print >>Term.cout, ''.join(src)
469 469
470 470 except KeyboardInterrupt:
471 471 pass
472 472
473 473 def do_list(self, arg):
474 474 self.lastcmd = 'list'
475 475 last = None
476 476 if arg:
477 477 try:
478 478 x = eval(arg, {}, {})
479 479 if type(x) == type(()):
480 480 first, last = x
481 481 first = int(first)
482 482 last = int(last)
483 483 if last < first:
484 484 # Assume it's a count
485 485 last = first + last
486 486 else:
487 487 first = max(1, int(x) - 5)
488 488 except:
489 489 print '*** Error in argument:', `arg`
490 490 return
491 491 elif self.lineno is None:
492 492 first = max(1, self.curframe.f_lineno - 5)
493 493 else:
494 494 first = self.lineno + 1
495 495 if last is None:
496 496 last = first + 10
497 497 self.print_list_lines(self.curframe.f_code.co_filename, first, last)
498 498
499 499 # vds: >>
500 500 lineno = first
501 501 filename = self.curframe.f_code.co_filename
502 502 __IPYTHON__.hooks.synchronize_with_editor(filename, lineno, 0)
503 503 # vds: <<
504 504
505 505 do_l = do_list
506 506
507 507 def do_pdef(self, arg):
508 508 """The debugger interface to magic_pdef"""
509 509 namespaces = [('Locals', self.curframe.f_locals),
510 510 ('Globals', self.curframe.f_globals)]
511 511 __IPYTHON__.magic_pdef(arg, namespaces=namespaces)
512 512
513 513 def do_pdoc(self, arg):
514 514 """The debugger interface to magic_pdoc"""
515 515 namespaces = [('Locals', self.curframe.f_locals),
516 516 ('Globals', self.curframe.f_globals)]
517 517 __IPYTHON__.magic_pdoc(arg, namespaces=namespaces)
518 518
519 519 def do_pinfo(self, arg):
520 520 """The debugger equivalant of ?obj"""
521 521 namespaces = [('Locals', self.curframe.f_locals),
522 522 ('Globals', self.curframe.f_globals)]
523 523 __IPYTHON__.magic_pinfo("pinfo %s" % arg, namespaces=namespaces)
1 NO CONTENT: file renamed from IPython/excolors.py to IPython/core/excolors.py
@@ -1,15 +1,18 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3
4 4 def test_import_completer():
5 5 from IPython.core import completer
6 6
7 7 def test_import_crashhandler():
8 8 from IPython.core import crashhandler
9 9
10 10 def test_import_debugger():
11 11 from IPython.core import debugger
12 12
13 13 def test_import_fakemodule():
14 14 from IPython.core import fakemodule
15 15
16 def test_import_excolors():
17 from IPython.core import excolors
18
@@ -1,1067 +1,1067 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 # Required modules
73 73 import inspect
74 74 import keyword
75 75 import linecache
76 76 import os
77 77 import pydoc
78 78 import re
79 79 import string
80 80 import sys
81 81 import time
82 82 import tokenize
83 83 import traceback
84 84 import types
85 85
86 86 # For purposes of monkeypatching inspect to fix a bug in it.
87 87 from inspect import getsourcefile, getfile, getmodule,\
88 88 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
89 89
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 PyColorize
94 94 from IPython.core import debugger
95 95 from IPython.ipstruct import Struct
96 from IPython.excolors import exception_colors
96 from IPython.core.excolors import exception_colors
97 97 from IPython.genutils import Term,uniq_stable,error,info
98 98
99 99 # Globals
100 100 # amount of space to put line numbers before verbose tracebacks
101 101 INDENT_SIZE = 8
102 102
103 103 # Default color scheme. This is used, for example, by the traceback
104 104 # formatter. When running in an actual IPython instance, the user's rc.colors
105 105 # value is used, but havinga module global makes this functionality available
106 106 # to users of ultraTB who are NOT running inside ipython.
107 107 DEFAULT_SCHEME = 'NoColor'
108 108
109 109 #---------------------------------------------------------------------------
110 110 # Code begins
111 111
112 112 # Utility functions
113 113 def inspect_error():
114 114 """Print a message about internal inspect errors.
115 115
116 116 These are unfortunately quite common."""
117 117
118 118 error('Internal Python error in the inspect module.\n'
119 119 'Below is the traceback from this internal error.\n')
120 120
121 121
122 122 def findsource(object):
123 123 """Return the entire source file and starting line number for an object.
124 124
125 125 The argument may be a module, class, method, function, traceback, frame,
126 126 or code object. The source code is returned as a list of all the lines
127 127 in the file and the line number indexes a line in that list. An IOError
128 128 is raised if the source code cannot be retrieved.
129 129
130 130 FIXED version with which we monkeypatch the stdlib to work around a bug."""
131 131
132 132 file = getsourcefile(object) or getfile(object)
133 133 # If the object is a frame, then trying to get the globals dict from its
134 134 # module won't work. Instead, the frame object itself has the globals
135 135 # dictionary.
136 136 globals_dict = None
137 137 if inspect.isframe(object):
138 138 # XXX: can this ever be false?
139 139 globals_dict = object.f_globals
140 140 else:
141 141 module = getmodule(object, file)
142 142 if module:
143 143 globals_dict = module.__dict__
144 144 lines = linecache.getlines(file, globals_dict)
145 145 if not lines:
146 146 raise IOError('could not get source code')
147 147
148 148 if ismodule(object):
149 149 return lines, 0
150 150
151 151 if isclass(object):
152 152 name = object.__name__
153 153 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
154 154 # make some effort to find the best matching class definition:
155 155 # use the one with the least indentation, which is the one
156 156 # that's most probably not inside a function definition.
157 157 candidates = []
158 158 for i in range(len(lines)):
159 159 match = pat.match(lines[i])
160 160 if match:
161 161 # if it's at toplevel, it's already the best one
162 162 if lines[i][0] == 'c':
163 163 return lines, i
164 164 # else add whitespace to candidate list
165 165 candidates.append((match.group(1), i))
166 166 if candidates:
167 167 # this will sort by whitespace, and by line number,
168 168 # less whitespace first
169 169 candidates.sort()
170 170 return lines, candidates[0][1]
171 171 else:
172 172 raise IOError('could not find class definition')
173 173
174 174 if ismethod(object):
175 175 object = object.im_func
176 176 if isfunction(object):
177 177 object = object.func_code
178 178 if istraceback(object):
179 179 object = object.tb_frame
180 180 if isframe(object):
181 181 object = object.f_code
182 182 if iscode(object):
183 183 if not hasattr(object, 'co_firstlineno'):
184 184 raise IOError('could not find function definition')
185 185 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
186 186 pmatch = pat.match
187 187 # fperez - fix: sometimes, co_firstlineno can give a number larger than
188 188 # the length of lines, which causes an error. Safeguard against that.
189 189 lnum = min(object.co_firstlineno,len(lines))-1
190 190 while lnum > 0:
191 191 if pmatch(lines[lnum]): break
192 192 lnum -= 1
193 193
194 194 return lines, lnum
195 195 raise IOError('could not find code object')
196 196
197 197 # Monkeypatch inspect to apply our bugfix. This code only works with py25
198 198 if sys.version_info[:2] >= (2,5):
199 199 inspect.findsource = findsource
200 200
201 201 def fix_frame_records_filenames(records):
202 202 """Try to fix the filenames in each record from inspect.getinnerframes().
203 203
204 204 Particularly, modules loaded from within zip files have useless filenames
205 205 attached to their code object, and inspect.getinnerframes() just uses it.
206 206 """
207 207 fixed_records = []
208 208 for frame, filename, line_no, func_name, lines, index in records:
209 209 # Look inside the frame's globals dictionary for __file__, which should
210 210 # be better.
211 211 better_fn = frame.f_globals.get('__file__', None)
212 212 if isinstance(better_fn, str):
213 213 # Check the type just in case someone did something weird with
214 214 # __file__. It might also be None if the error occurred during
215 215 # import.
216 216 filename = better_fn
217 217 fixed_records.append((frame, filename, line_no, func_name, lines, index))
218 218 return fixed_records
219 219
220 220
221 221 def _fixed_getinnerframes(etb, context=1,tb_offset=0):
222 222 import linecache
223 223 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
224 224
225 225 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
226 226
227 227 # If the error is at the console, don't build any context, since it would
228 228 # otherwise produce 5 blank lines printed out (there is no file at the
229 229 # console)
230 230 rec_check = records[tb_offset:]
231 231 try:
232 232 rname = rec_check[0][1]
233 233 if rname == '<ipython console>' or rname.endswith('<string>'):
234 234 return rec_check
235 235 except IndexError:
236 236 pass
237 237
238 238 aux = traceback.extract_tb(etb)
239 239 assert len(records) == len(aux)
240 240 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
241 241 maybeStart = lnum-1 - context//2
242 242 start = max(maybeStart, 0)
243 243 end = start + context
244 244 lines = linecache.getlines(file)[start:end]
245 245 # pad with empty lines if necessary
246 246 if maybeStart < 0:
247 247 lines = (['\n'] * -maybeStart) + lines
248 248 if len(lines) < context:
249 249 lines += ['\n'] * (context - len(lines))
250 250 buf = list(records[i])
251 251 buf[LNUM_POS] = lnum
252 252 buf[INDEX_POS] = lnum - 1 - start
253 253 buf[LINES_POS] = lines
254 254 records[i] = tuple(buf)
255 255 return records[tb_offset:]
256 256
257 257 # Helper function -- largely belongs to VerboseTB, but we need the same
258 258 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
259 259 # can be recognized properly by ipython.el's py-traceback-line-re
260 260 # (SyntaxErrors have to be treated specially because they have no traceback)
261 261
262 262 _parser = PyColorize.Parser()
263 263
264 264 def _formatTracebackLines(lnum, index, lines, Colors, lvals=None,scheme=None):
265 265 numbers_width = INDENT_SIZE - 1
266 266 res = []
267 267 i = lnum - index
268 268
269 269 # This lets us get fully syntax-highlighted tracebacks.
270 270 if scheme is None:
271 271 try:
272 272 # Again, reference to a global __IPYTHON__ that doesn't exist.
273 273 # XXX
274 274 scheme = __IPYTHON__.rc.colors
275 275 except:
276 276 scheme = DEFAULT_SCHEME
277 277 _line_format = _parser.format2
278 278
279 279 for line in lines:
280 280 new_line, err = _line_format(line,'str',scheme)
281 281 if not err: line = new_line
282 282
283 283 if i == lnum:
284 284 # This is the line with the error
285 285 pad = numbers_width - len(str(i))
286 286 if pad >= 3:
287 287 marker = '-'*(pad-3) + '-> '
288 288 elif pad == 2:
289 289 marker = '> '
290 290 elif pad == 1:
291 291 marker = '>'
292 292 else:
293 293 marker = ''
294 294 num = marker + str(i)
295 295 line = '%s%s%s %s%s' %(Colors.linenoEm, num,
296 296 Colors.line, line, Colors.Normal)
297 297 else:
298 298 num = '%*s' % (numbers_width,i)
299 299 line = '%s%s%s %s' %(Colors.lineno, num,
300 300 Colors.Normal, line)
301 301
302 302 res.append(line)
303 303 if lvals and i == lnum:
304 304 res.append(lvals + '\n')
305 305 i = i + 1
306 306 return res
307 307
308 308
309 309 #---------------------------------------------------------------------------
310 310 # Module classes
311 311 class TBTools:
312 312 """Basic tools used by all traceback printer classes."""
313 313
314 314 def __init__(self,color_scheme = 'NoColor',call_pdb=False):
315 315 # Whether to call the interactive pdb debugger after printing
316 316 # tracebacks or not
317 317 self.call_pdb = call_pdb
318 318
319 319 # Create color table
320 320 self.color_scheme_table = exception_colors()
321 321
322 322 self.set_colors(color_scheme)
323 323 self.old_scheme = color_scheme # save initial value for toggles
324 324
325 325 if call_pdb:
326 326 self.pdb = debugger.Pdb(self.color_scheme_table.active_scheme_name)
327 327 else:
328 328 self.pdb = None
329 329
330 330 def set_colors(self,*args,**kw):
331 331 """Shorthand access to the color table scheme selector method."""
332 332
333 333 # Set own color table
334 334 self.color_scheme_table.set_active_scheme(*args,**kw)
335 335 # for convenience, set Colors to the active scheme
336 336 self.Colors = self.color_scheme_table.active_colors
337 337 # Also set colors of debugger
338 338 if hasattr(self,'pdb') and self.pdb is not None:
339 339 self.pdb.set_colors(*args,**kw)
340 340
341 341 def color_toggle(self):
342 342 """Toggle between the currently active color scheme and NoColor."""
343 343
344 344 if self.color_scheme_table.active_scheme_name == 'NoColor':
345 345 self.color_scheme_table.set_active_scheme(self.old_scheme)
346 346 self.Colors = self.color_scheme_table.active_colors
347 347 else:
348 348 self.old_scheme = self.color_scheme_table.active_scheme_name
349 349 self.color_scheme_table.set_active_scheme('NoColor')
350 350 self.Colors = self.color_scheme_table.active_colors
351 351
352 352 #---------------------------------------------------------------------------
353 353 class ListTB(TBTools):
354 354 """Print traceback information from a traceback list, with optional color.
355 355
356 356 Calling: requires 3 arguments:
357 357 (etype, evalue, elist)
358 358 as would be obtained by:
359 359 etype, evalue, tb = sys.exc_info()
360 360 if tb:
361 361 elist = traceback.extract_tb(tb)
362 362 else:
363 363 elist = None
364 364
365 365 It can thus be used by programs which need to process the traceback before
366 366 printing (such as console replacements based on the code module from the
367 367 standard library).
368 368
369 369 Because they are meant to be called without a full traceback (only a
370 370 list), instances of this class can't call the interactive pdb debugger."""
371 371
372 372 def __init__(self,color_scheme = 'NoColor'):
373 373 TBTools.__init__(self,color_scheme = color_scheme,call_pdb=0)
374 374
375 375 def __call__(self, etype, value, elist):
376 376 Term.cout.flush()
377 377 print >> Term.cerr, self.text(etype,value,elist)
378 378 Term.cerr.flush()
379 379
380 380 def text(self,etype, value, elist,context=5):
381 381 """Return a color formatted string with the traceback info."""
382 382
383 383 Colors = self.Colors
384 384 out_string = ['%s%s%s\n' % (Colors.topline,'-'*60,Colors.Normal)]
385 385 if elist:
386 386 out_string.append('Traceback %s(most recent call last)%s:' % \
387 387 (Colors.normalEm, Colors.Normal) + '\n')
388 388 out_string.extend(self._format_list(elist))
389 389 lines = self._format_exception_only(etype, value)
390 390 for line in lines[:-1]:
391 391 out_string.append(" "+line)
392 392 out_string.append(lines[-1])
393 393 return ''.join(out_string)
394 394
395 395 def _format_list(self, extracted_list):
396 396 """Format a list of traceback entry tuples for printing.
397 397
398 398 Given a list of tuples as returned by extract_tb() or
399 399 extract_stack(), return a list of strings ready for printing.
400 400 Each string in the resulting list corresponds to the item with the
401 401 same index in the argument list. Each string ends in a newline;
402 402 the strings may contain internal newlines as well, for those items
403 403 whose source text line is not None.
404 404
405 405 Lifted almost verbatim from traceback.py
406 406 """
407 407
408 408 Colors = self.Colors
409 409 list = []
410 410 for filename, lineno, name, line in extracted_list[:-1]:
411 411 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
412 412 (Colors.filename, filename, Colors.Normal,
413 413 Colors.lineno, lineno, Colors.Normal,
414 414 Colors.name, name, Colors.Normal)
415 415 if line:
416 416 item = item + ' %s\n' % line.strip()
417 417 list.append(item)
418 418 # Emphasize the last entry
419 419 filename, lineno, name, line = extracted_list[-1]
420 420 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
421 421 (Colors.normalEm,
422 422 Colors.filenameEm, filename, Colors.normalEm,
423 423 Colors.linenoEm, lineno, Colors.normalEm,
424 424 Colors.nameEm, name, Colors.normalEm,
425 425 Colors.Normal)
426 426 if line:
427 427 item = item + '%s %s%s\n' % (Colors.line, line.strip(),
428 428 Colors.Normal)
429 429 list.append(item)
430 430 return list
431 431
432 432 def _format_exception_only(self, etype, value):
433 433 """Format the exception part of a traceback.
434 434
435 435 The arguments are the exception type and value such as given by
436 436 sys.exc_info()[:2]. The return value is a list of strings, each ending
437 437 in a newline. Normally, the list contains a single string; however,
438 438 for SyntaxError exceptions, it contains several lines that (when
439 439 printed) display detailed information about where the syntax error
440 440 occurred. The message indicating which exception occurred is the
441 441 always last string in the list.
442 442
443 443 Also lifted nearly verbatim from traceback.py
444 444 """
445 445
446 446 have_filedata = False
447 447 Colors = self.Colors
448 448 list = []
449 449 try:
450 450 stype = Colors.excName + etype.__name__ + Colors.Normal
451 451 except AttributeError:
452 452 stype = etype # String exceptions don't get special coloring
453 453 if value is None:
454 454 list.append( str(stype) + '\n')
455 455 else:
456 456 if etype is SyntaxError:
457 457 try:
458 458 msg, (filename, lineno, offset, line) = value
459 459 except:
460 460 have_filedata = False
461 461 else:
462 462 have_filedata = True
463 463 #print 'filename is',filename # dbg
464 464 if not filename: filename = "<string>"
465 465 list.append('%s File %s"%s"%s, line %s%d%s\n' % \
466 466 (Colors.normalEm,
467 467 Colors.filenameEm, filename, Colors.normalEm,
468 468 Colors.linenoEm, lineno, Colors.Normal ))
469 469 if line is not None:
470 470 i = 0
471 471 while i < len(line) and line[i].isspace():
472 472 i = i+1
473 473 list.append('%s %s%s\n' % (Colors.line,
474 474 line.strip(),
475 475 Colors.Normal))
476 476 if offset is not None:
477 477 s = ' '
478 478 for c in line[i:offset-1]:
479 479 if c.isspace():
480 480 s = s + c
481 481 else:
482 482 s = s + ' '
483 483 list.append('%s%s^%s\n' % (Colors.caret, s,
484 484 Colors.Normal) )
485 485 value = msg
486 486 s = self._some_str(value)
487 487 if s:
488 488 list.append('%s%s:%s %s\n' % (str(stype), Colors.excName,
489 489 Colors.Normal, s))
490 490 else:
491 491 list.append('%s\n' % str(stype))
492 492
493 493 # This is being commented out for now as the __IPYTHON__ variable
494 494 # referenced here is not resolved and causes massive test failures
495 495 # and errors. B. Granger, 04/2009. XXX
496 496 # See https://bugs.launchpad.net/bugs/362137
497 497 # # vds:>>
498 498 # if have_filedata:
499 499 # __IPYTHON__.hooks.synchronize_with_editor(filename, lineno, 0)
500 500 # # vds:<<
501 501
502 502 return list
503 503
504 504 def _some_str(self, value):
505 505 # Lifted from traceback.py
506 506 try:
507 507 return str(value)
508 508 except:
509 509 return '<unprintable %s object>' % type(value).__name__
510 510
511 511 #----------------------------------------------------------------------------
512 512 class VerboseTB(TBTools):
513 513 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
514 514 of HTML. Requires inspect and pydoc. Crazy, man.
515 515
516 516 Modified version which optionally strips the topmost entries from the
517 517 traceback, to be used with alternate interpreters (because their own code
518 518 would appear in the traceback)."""
519 519
520 520 def __init__(self,color_scheme = 'Linux',tb_offset=0,long_header=0,
521 521 call_pdb = 0, include_vars=1):
522 522 """Specify traceback offset, headers and color scheme.
523 523
524 524 Define how many frames to drop from the tracebacks. Calling it with
525 525 tb_offset=1 allows use of this handler in interpreters which will have
526 526 their own code at the top of the traceback (VerboseTB will first
527 527 remove that frame before printing the traceback info)."""
528 528 TBTools.__init__(self,color_scheme=color_scheme,call_pdb=call_pdb)
529 529 self.tb_offset = tb_offset
530 530 self.long_header = long_header
531 531 self.include_vars = include_vars
532 532
533 533 def text(self, etype, evalue, etb, context=5):
534 534 """Return a nice text document describing the traceback."""
535 535
536 536 # some locals
537 537 try:
538 538 etype = etype.__name__
539 539 except AttributeError:
540 540 pass
541 541 Colors = self.Colors # just a shorthand + quicker name lookup
542 542 ColorsNormal = Colors.Normal # used a lot
543 543 col_scheme = self.color_scheme_table.active_scheme_name
544 544 indent = ' '*INDENT_SIZE
545 545 em_normal = '%s\n%s%s' % (Colors.valEm, indent,ColorsNormal)
546 546 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
547 547 exc = '%s%s%s' % (Colors.excName,etype,ColorsNormal)
548 548
549 549 # some internal-use functions
550 550 def text_repr(value):
551 551 """Hopefully pretty robust repr equivalent."""
552 552 # this is pretty horrible but should always return *something*
553 553 try:
554 554 return pydoc.text.repr(value)
555 555 except KeyboardInterrupt:
556 556 raise
557 557 except:
558 558 try:
559 559 return repr(value)
560 560 except KeyboardInterrupt:
561 561 raise
562 562 except:
563 563 try:
564 564 # all still in an except block so we catch
565 565 # getattr raising
566 566 name = getattr(value, '__name__', None)
567 567 if name:
568 568 # ick, recursion
569 569 return text_repr(name)
570 570 klass = getattr(value, '__class__', None)
571 571 if klass:
572 572 return '%s instance' % text_repr(klass)
573 573 except KeyboardInterrupt:
574 574 raise
575 575 except:
576 576 return 'UNRECOVERABLE REPR FAILURE'
577 577 def eqrepr(value, repr=text_repr): return '=%s' % repr(value)
578 578 def nullrepr(value, repr=text_repr): return ''
579 579
580 580 # meat of the code begins
581 581 try:
582 582 etype = etype.__name__
583 583 except AttributeError:
584 584 pass
585 585
586 586 if self.long_header:
587 587 # Header with the exception type, python version, and date
588 588 pyver = 'Python ' + string.split(sys.version)[0] + ': ' + sys.executable
589 589 date = time.ctime(time.time())
590 590
591 591 head = '%s%s%s\n%s%s%s\n%s' % (Colors.topline, '-'*75, ColorsNormal,
592 592 exc, ' '*(75-len(str(etype))-len(pyver)),
593 593 pyver, string.rjust(date, 75) )
594 594 head += "\nA problem occured executing Python code. Here is the sequence of function"\
595 595 "\ncalls leading up to the error, with the most recent (innermost) call last."
596 596 else:
597 597 # Simplified header
598 598 head = '%s%s%s\n%s%s' % (Colors.topline, '-'*75, ColorsNormal,exc,
599 599 string.rjust('Traceback (most recent call last)',
600 600 75 - len(str(etype)) ) )
601 601 frames = []
602 602 # Flush cache before calling inspect. This helps alleviate some of the
603 603 # problems with python 2.3's inspect.py.
604 604 linecache.checkcache()
605 605 # Drop topmost frames if requested
606 606 try:
607 607 # Try the default getinnerframes and Alex's: Alex's fixes some
608 608 # problems, but it generates empty tracebacks for console errors
609 609 # (5 blanks lines) where none should be returned.
610 610 #records = inspect.getinnerframes(etb, context)[self.tb_offset:]
611 611 #print 'python records:', records # dbg
612 612 records = _fixed_getinnerframes(etb, context,self.tb_offset)
613 613 #print 'alex records:', records # dbg
614 614 except:
615 615
616 616 # FIXME: I've been getting many crash reports from python 2.3
617 617 # users, traceable to inspect.py. If I can find a small test-case
618 618 # to reproduce this, I should either write a better workaround or
619 619 # file a bug report against inspect (if that's the real problem).
620 620 # So far, I haven't been able to find an isolated example to
621 621 # reproduce the problem.
622 622 inspect_error()
623 623 traceback.print_exc(file=Term.cerr)
624 624 info('\nUnfortunately, your original traceback can not be constructed.\n')
625 625 return ''
626 626
627 627 # build some color string templates outside these nested loops
628 628 tpl_link = '%s%%s%s' % (Colors.filenameEm,ColorsNormal)
629 629 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
630 630 ColorsNormal)
631 631 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
632 632 (Colors.vName, Colors.valEm, ColorsNormal)
633 633 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
634 634 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
635 635 Colors.vName, ColorsNormal)
636 636 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
637 637 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
638 638 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm,Colors.line,
639 639 ColorsNormal)
640 640
641 641 # now, loop over all records printing context and info
642 642 abspath = os.path.abspath
643 643 for frame, file, lnum, func, lines, index in records:
644 644 #print '*** record:',file,lnum,func,lines,index # dbg
645 645 try:
646 646 file = file and abspath(file) or '?'
647 647 except OSError:
648 648 # if file is '<console>' or something not in the filesystem,
649 649 # the abspath call will throw an OSError. Just ignore it and
650 650 # keep the original file string.
651 651 pass
652 652 link = tpl_link % file
653 653 try:
654 654 args, varargs, varkw, locals = inspect.getargvalues(frame)
655 655 except:
656 656 # This can happen due to a bug in python2.3. We should be
657 657 # able to remove this try/except when 2.4 becomes a
658 658 # requirement. Bug details at http://python.org/sf/1005466
659 659 inspect_error()
660 660 traceback.print_exc(file=Term.cerr)
661 661 info("\nIPython's exception reporting continues...\n")
662 662
663 663 if func == '?':
664 664 call = ''
665 665 else:
666 666 # Decide whether to include variable details or not
667 667 var_repr = self.include_vars and eqrepr or nullrepr
668 668 try:
669 669 call = tpl_call % (func,inspect.formatargvalues(args,
670 670 varargs, varkw,
671 671 locals,formatvalue=var_repr))
672 672 except KeyError:
673 673 # Very odd crash from inspect.formatargvalues(). The
674 674 # scenario under which it appeared was a call to
675 675 # view(array,scale) in NumTut.view.view(), where scale had
676 676 # been defined as a scalar (it should be a tuple). Somehow
677 677 # inspect messes up resolving the argument list of view()
678 678 # and barfs out. At some point I should dig into this one
679 679 # and file a bug report about it.
680 680 inspect_error()
681 681 traceback.print_exc(file=Term.cerr)
682 682 info("\nIPython's exception reporting continues...\n")
683 683 call = tpl_call_fail % func
684 684
685 685 # Initialize a list of names on the current line, which the
686 686 # tokenizer below will populate.
687 687 names = []
688 688
689 689 def tokeneater(token_type, token, start, end, line):
690 690 """Stateful tokeneater which builds dotted names.
691 691
692 692 The list of names it appends to (from the enclosing scope) can
693 693 contain repeated composite names. This is unavoidable, since
694 694 there is no way to disambguate partial dotted structures until
695 695 the full list is known. The caller is responsible for pruning
696 696 the final list of duplicates before using it."""
697 697
698 698 # build composite names
699 699 if token == '.':
700 700 try:
701 701 names[-1] += '.'
702 702 # store state so the next token is added for x.y.z names
703 703 tokeneater.name_cont = True
704 704 return
705 705 except IndexError:
706 706 pass
707 707 if token_type == tokenize.NAME and token not in keyword.kwlist:
708 708 if tokeneater.name_cont:
709 709 # Dotted names
710 710 names[-1] += token
711 711 tokeneater.name_cont = False
712 712 else:
713 713 # Regular new names. We append everything, the caller
714 714 # will be responsible for pruning the list later. It's
715 715 # very tricky to try to prune as we go, b/c composite
716 716 # names can fool us. The pruning at the end is easy
717 717 # to do (or the caller can print a list with repeated
718 718 # names if so desired.
719 719 names.append(token)
720 720 elif token_type == tokenize.NEWLINE:
721 721 raise IndexError
722 722 # we need to store a bit of state in the tokenizer to build
723 723 # dotted names
724 724 tokeneater.name_cont = False
725 725
726 726 def linereader(file=file, lnum=[lnum], getline=linecache.getline):
727 727 line = getline(file, lnum[0])
728 728 lnum[0] += 1
729 729 return line
730 730
731 731 # Build the list of names on this line of code where the exception
732 732 # occurred.
733 733 try:
734 734 # This builds the names list in-place by capturing it from the
735 735 # enclosing scope.
736 736 tokenize.tokenize(linereader, tokeneater)
737 737 except IndexError:
738 738 # signals exit of tokenizer
739 739 pass
740 740 except tokenize.TokenError,msg:
741 741 _m = ("An unexpected error occurred while tokenizing input\n"
742 742 "The following traceback may be corrupted or invalid\n"
743 743 "The error message is: %s\n" % msg)
744 744 error(_m)
745 745
746 746 # prune names list of duplicates, but keep the right order
747 747 unique_names = uniq_stable(names)
748 748
749 749 # Start loop over vars
750 750 lvals = []
751 751 if self.include_vars:
752 752 for name_full in unique_names:
753 753 name_base = name_full.split('.',1)[0]
754 754 if name_base in frame.f_code.co_varnames:
755 755 if locals.has_key(name_base):
756 756 try:
757 757 value = repr(eval(name_full,locals))
758 758 except:
759 759 value = undefined
760 760 else:
761 761 value = undefined
762 762 name = tpl_local_var % name_full
763 763 else:
764 764 if frame.f_globals.has_key(name_base):
765 765 try:
766 766 value = repr(eval(name_full,frame.f_globals))
767 767 except:
768 768 value = undefined
769 769 else:
770 770 value = undefined
771 771 name = tpl_global_var % name_full
772 772 lvals.append(tpl_name_val % (name,value))
773 773 if lvals:
774 774 lvals = '%s%s' % (indent,em_normal.join(lvals))
775 775 else:
776 776 lvals = ''
777 777
778 778 level = '%s %s\n' % (link,call)
779 779
780 780 if index is None:
781 781 frames.append(level)
782 782 else:
783 783 frames.append('%s%s' % (level,''.join(
784 784 _formatTracebackLines(lnum,index,lines,Colors,lvals,
785 785 col_scheme))))
786 786
787 787 # Get (safely) a string form of the exception info
788 788 try:
789 789 etype_str,evalue_str = map(str,(etype,evalue))
790 790 except:
791 791 # User exception is improperly defined.
792 792 etype,evalue = str,sys.exc_info()[:2]
793 793 etype_str,evalue_str = map(str,(etype,evalue))
794 794 # ... and format it
795 795 exception = ['%s%s%s: %s' % (Colors.excName, etype_str,
796 796 ColorsNormal, evalue_str)]
797 797 if type(evalue) is types.InstanceType:
798 798 try:
799 799 names = [w for w in dir(evalue) if isinstance(w, basestring)]
800 800 except:
801 801 # Every now and then, an object with funny inernals blows up
802 802 # when dir() is called on it. We do the best we can to report
803 803 # the problem and continue
804 804 _m = '%sException reporting error (object with broken dir())%s:'
805 805 exception.append(_m % (Colors.excName,ColorsNormal))
806 806 etype_str,evalue_str = map(str,sys.exc_info()[:2])
807 807 exception.append('%s%s%s: %s' % (Colors.excName,etype_str,
808 808 ColorsNormal, evalue_str))
809 809 names = []
810 810 for name in names:
811 811 value = text_repr(getattr(evalue, name))
812 812 exception.append('\n%s%s = %s' % (indent, name, value))
813 813
814 814 # This is being commented out for now as the __IPYTHON__ variable
815 815 # referenced here is not resolved and causes massive test failures
816 816 # and errors. B. Granger, 04/2009. XXX
817 817 # See https://bugs.launchpad.net/bugs/362137
818 818 # # vds: >>
819 819 # if records:
820 820 # filepath, lnum = records[-1][1:3]
821 821 # #print "file:", str(file), "linenb", str(lnum) # dbg
822 822 # filepath = os.path.abspath(filepath)
823 823 # __IPYTHON__.hooks.synchronize_with_editor(filepath, lnum, 0)
824 824 # # vds: <<
825 825
826 826 # return all our info assembled as a single string
827 827 return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) )
828 828
829 829 def debugger(self,force=False):
830 830 """Call up the pdb debugger if desired, always clean up the tb
831 831 reference.
832 832
833 833 Keywords:
834 834
835 835 - force(False): by default, this routine checks the instance call_pdb
836 836 flag and does not actually invoke the debugger if the flag is false.
837 837 The 'force' option forces the debugger to activate even if the flag
838 838 is false.
839 839
840 840 If the call_pdb flag is set, the pdb interactive debugger is
841 841 invoked. In all cases, the self.tb reference to the current traceback
842 842 is deleted to prevent lingering references which hamper memory
843 843 management.
844 844
845 845 Note that each call to pdb() does an 'import readline', so if your app
846 846 requires a special setup for the readline completers, you'll have to
847 847 fix that by hand after invoking the exception handler."""
848 848
849 849 if force or self.call_pdb:
850 850 if self.pdb is None:
851 851 self.pdb = debugger.Pdb(
852 852 self.color_scheme_table.active_scheme_name)
853 853 # the system displayhook may have changed, restore the original
854 854 # for pdb
855 855 dhook = sys.displayhook
856 856 sys.displayhook = sys.__displayhook__
857 857 self.pdb.reset()
858 858 # Find the right frame so we don't pop up inside ipython itself
859 859 if hasattr(self,'tb'):
860 860 etb = self.tb
861 861 else:
862 862 etb = self.tb = sys.last_traceback
863 863 while self.tb.tb_next is not None:
864 864 self.tb = self.tb.tb_next
865 865 try:
866 866 if etb and etb.tb_next:
867 867 etb = etb.tb_next
868 868 self.pdb.botframe = etb.tb_frame
869 869 self.pdb.interaction(self.tb.tb_frame, self.tb)
870 870 finally:
871 871 sys.displayhook = dhook
872 872
873 873 if hasattr(self,'tb'):
874 874 del self.tb
875 875
876 876 def handler(self, info=None):
877 877 (etype, evalue, etb) = info or sys.exc_info()
878 878 self.tb = etb
879 879 Term.cout.flush()
880 880 print >> Term.cerr, self.text(etype, evalue, etb)
881 881 Term.cerr.flush()
882 882
883 883 # Changed so an instance can just be called as VerboseTB_inst() and print
884 884 # out the right info on its own.
885 885 def __call__(self, etype=None, evalue=None, etb=None):
886 886 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
887 887 if etb is None:
888 888 self.handler()
889 889 else:
890 890 self.handler((etype, evalue, etb))
891 891 try:
892 892 self.debugger()
893 893 except KeyboardInterrupt:
894 894 print "\nKeyboardInterrupt"
895 895
896 896 #----------------------------------------------------------------------------
897 897 class FormattedTB(VerboseTB,ListTB):
898 898 """Subclass ListTB but allow calling with a traceback.
899 899
900 900 It can thus be used as a sys.excepthook for Python > 2.1.
901 901
902 902 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
903 903
904 904 Allows a tb_offset to be specified. This is useful for situations where
905 905 one needs to remove a number of topmost frames from the traceback (such as
906 906 occurs with python programs that themselves execute other python code,
907 907 like Python shells). """
908 908
909 909 def __init__(self, mode = 'Plain', color_scheme='Linux',
910 910 tb_offset = 0,long_header=0,call_pdb=0,include_vars=0):
911 911
912 912 # NEVER change the order of this list. Put new modes at the end:
913 913 self.valid_modes = ['Plain','Context','Verbose']
914 914 self.verbose_modes = self.valid_modes[1:3]
915 915
916 916 VerboseTB.__init__(self,color_scheme,tb_offset,long_header,
917 917 call_pdb=call_pdb,include_vars=include_vars)
918 918 self.set_mode(mode)
919 919
920 920 def _extract_tb(self,tb):
921 921 if tb:
922 922 return traceback.extract_tb(tb)
923 923 else:
924 924 return None
925 925
926 926 def text(self, etype, value, tb,context=5,mode=None):
927 927 """Return formatted traceback.
928 928
929 929 If the optional mode parameter is given, it overrides the current
930 930 mode."""
931 931
932 932 if mode is None:
933 933 mode = self.mode
934 934 if mode in self.verbose_modes:
935 935 # verbose modes need a full traceback
936 936 return VerboseTB.text(self,etype, value, tb,context=5)
937 937 else:
938 938 # We must check the source cache because otherwise we can print
939 939 # out-of-date source code.
940 940 linecache.checkcache()
941 941 # Now we can extract and format the exception
942 942 elist = self._extract_tb(tb)
943 943 if len(elist) > self.tb_offset:
944 944 del elist[:self.tb_offset]
945 945 return ListTB.text(self,etype,value,elist)
946 946
947 947 def set_mode(self,mode=None):
948 948 """Switch to the desired mode.
949 949
950 950 If mode is not specified, cycles through the available modes."""
951 951
952 952 if not mode:
953 953 new_idx = ( self.valid_modes.index(self.mode) + 1 ) % \
954 954 len(self.valid_modes)
955 955 self.mode = self.valid_modes[new_idx]
956 956 elif mode not in self.valid_modes:
957 957 raise ValueError, 'Unrecognized mode in FormattedTB: <'+mode+'>\n'\
958 958 'Valid modes: '+str(self.valid_modes)
959 959 else:
960 960 self.mode = mode
961 961 # include variable details only in 'Verbose' mode
962 962 self.include_vars = (self.mode == self.valid_modes[2])
963 963
964 964 # some convenient shorcuts
965 965 def plain(self):
966 966 self.set_mode(self.valid_modes[0])
967 967
968 968 def context(self):
969 969 self.set_mode(self.valid_modes[1])
970 970
971 971 def verbose(self):
972 972 self.set_mode(self.valid_modes[2])
973 973
974 974 #----------------------------------------------------------------------------
975 975 class AutoFormattedTB(FormattedTB):
976 976 """A traceback printer which can be called on the fly.
977 977
978 978 It will find out about exceptions by itself.
979 979
980 980 A brief example:
981 981
982 982 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
983 983 try:
984 984 ...
985 985 except:
986 986 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
987 987 """
988 988 def __call__(self,etype=None,evalue=None,etb=None,
989 989 out=None,tb_offset=None):
990 990 """Print out a formatted exception traceback.
991 991
992 992 Optional arguments:
993 993 - out: an open file-like object to direct output to.
994 994
995 995 - tb_offset: the number of frames to skip over in the stack, on a
996 996 per-call basis (this overrides temporarily the instance's tb_offset
997 997 given at initialization time. """
998 998
999 999 if out is None:
1000 1000 out = Term.cerr
1001 1001 Term.cout.flush()
1002 1002 if tb_offset is not None:
1003 1003 tb_offset, self.tb_offset = self.tb_offset, tb_offset
1004 1004 print >> out, self.text(etype, evalue, etb)
1005 1005 self.tb_offset = tb_offset
1006 1006 else:
1007 1007 print >> out, self.text(etype, evalue, etb)
1008 1008 out.flush()
1009 1009 try:
1010 1010 self.debugger()
1011 1011 except KeyboardInterrupt:
1012 1012 print "\nKeyboardInterrupt"
1013 1013
1014 1014 def text(self,etype=None,value=None,tb=None,context=5,mode=None):
1015 1015 if etype is None:
1016 1016 etype,value,tb = sys.exc_info()
1017 1017 self.tb = tb
1018 1018 return FormattedTB.text(self,etype,value,tb,context=5,mode=mode)
1019 1019
1020 1020 #---------------------------------------------------------------------------
1021 1021 # A simple class to preserve Nathan's original functionality.
1022 1022 class ColorTB(FormattedTB):
1023 1023 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1024 1024 def __init__(self,color_scheme='Linux',call_pdb=0):
1025 1025 FormattedTB.__init__(self,color_scheme=color_scheme,
1026 1026 call_pdb=call_pdb)
1027 1027
1028 1028 #----------------------------------------------------------------------------
1029 1029 # module testing (minimal)
1030 1030 if __name__ == "__main__":
1031 1031 def spam(c, (d, e)):
1032 1032 x = c + d
1033 1033 y = c * d
1034 1034 foo(x, y)
1035 1035
1036 1036 def foo(a, b, bar=1):
1037 1037 eggs(a, b + bar)
1038 1038
1039 1039 def eggs(f, g, z=globals()):
1040 1040 h = f + g
1041 1041 i = f - g
1042 1042 return h / i
1043 1043
1044 1044 print ''
1045 1045 print '*** Before ***'
1046 1046 try:
1047 1047 print spam(1, (2, 3))
1048 1048 except:
1049 1049 traceback.print_exc()
1050 1050 print ''
1051 1051
1052 1052 handler = ColorTB()
1053 1053 print '*** ColorTB ***'
1054 1054 try:
1055 1055 print spam(1, (2, 3))
1056 1056 except:
1057 1057 apply(handler, sys.exc_info() )
1058 1058 print ''
1059 1059
1060 1060 handler = VerboseTB()
1061 1061 print '*** VerboseTB ***'
1062 1062 try:
1063 1063 print spam(1, (2, 3))
1064 1064 except:
1065 1065 apply(handler, sys.exc_info() )
1066 1066 print ''
1067 1067
@@ -1,74 +1,74 b''
1 1 # Set this prefix to where you want to install the plugin
2 2 PREFIX=/usr/local
3 3
4 4 NOSE0=nosetests -vs --with-doctest --doctest-tests --detailed-errors
5 5 NOSE=nosetests -vvs --with-ipdoctest --doctest-tests --doctest-extension=txt \
6 6 --detailed-errors
7 7
8 8 SRC=ipdoctest.py setup.py ../decorators.py
9 9
10 10 # Default target for clean 'make'
11 11 default: iplib
12 12
13 13 # The actual plugin installation
14 14 plugin: IPython_doctest_plugin.egg-info
15 15
16 16 # Simple targets that test one thing
17 17 simple: plugin simple.py
18 18 $(NOSE) simple.py
19 19
20 20 dtest: plugin dtexample.py
21 21 $(NOSE) dtexample.py
22 22
23 23 rtest: plugin test_refs.py
24 24 $(NOSE) test_refs.py
25 25
26 26 test: plugin dtexample.py
27 27 $(NOSE) dtexample.py test*.py test*.txt
28 28
29 29 deb: plugin dtexample.py
30 30 $(NOSE) test_combo.txt
31 31
32 32 # IPython tests
33 33 deco:
34 34 $(NOSE0) IPython.testing.decorators
35 35
36 36 magic: plugin
37 37 $(NOSE) IPython.Magic
38 38
39 39 excolors: plugin
40 $(NOSE) IPython.excolors
40 $(NOSE) IPython.core.excolors
41 41
42 42 iplib: plugin
43 43 $(NOSE) IPython.iplib
44 44
45 45 strd: plugin
46 46 $(NOSE) IPython.strdispatch
47 47
48 48 engine: plugin
49 49 $(NOSE) IPython.kernel
50 50
51 51 tf: plugin
52 52 $(NOSE) IPython.config.traitlets
53 53
54 54 # All of ipython itself
55 55 ipython: plugin
56 56 $(NOSE) IPython
57 57
58 58
59 59 # Combined targets
60 60 sr: rtest strd
61 61
62 62 base: dtest rtest test strd deco
63 63
64 64 quick: base iplib ipipe
65 65
66 66 all: base ipython
67 67
68 68 # Main plugin and cleanup
69 69 IPython_doctest_plugin.egg-info: $(SRC)
70 70 python setup.py install --prefix=$(PREFIX)
71 71 touch $@
72 72
73 73 clean:
74 74 rm -rf IPython_doctest_plugin.egg-info *~ *pyc build/ dist/
@@ -1,1057 +1,1057 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 # Required modules
73 73 import inspect
74 74 import keyword
75 75 import linecache
76 76 import os
77 77 import pydoc
78 78 import re
79 79 import string
80 80 import sys
81 81 import time
82 82 import tokenize
83 83 import traceback
84 84 import types
85 85
86 86 # For purposes of monkeypatching inspect to fix a bug in it.
87 87 from inspect import getsourcefile, getfile, getmodule,\
88 88 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
89 89
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 PyColorize
94 94 from IPython.core import debugger
95 95 from IPython.ipstruct import Struct
96 from IPython.excolors import exception_colors
96 from IPython.core.excolors import exception_colors
97 97 from IPython.genutils import Term,uniq_stable,error,info
98 98
99 99 # Globals
100 100 # amount of space to put line numbers before verbose tracebacks
101 101 INDENT_SIZE = 8
102 102
103 103 # Default color scheme. This is used, for example, by the traceback
104 104 # formatter. When running in an actual IPython instance, the user's rc.colors
105 105 # value is used, but havinga module global makes this functionality available
106 106 # to users of ultraTB who are NOT running inside ipython.
107 107 DEFAULT_SCHEME = 'NoColor'
108 108
109 109 #---------------------------------------------------------------------------
110 110 # Code begins
111 111
112 112 # Utility functions
113 113 def inspect_error():
114 114 """Print a message about internal inspect errors.
115 115
116 116 These are unfortunately quite common."""
117 117
118 118 error('Internal Python error in the inspect module.\n'
119 119 'Below is the traceback from this internal error.\n')
120 120
121 121
122 122 def findsource(object):
123 123 """Return the entire source file and starting line number for an object.
124 124
125 125 The argument may be a module, class, method, function, traceback, frame,
126 126 or code object. The source code is returned as a list of all the lines
127 127 in the file and the line number indexes a line in that list. An IOError
128 128 is raised if the source code cannot be retrieved.
129 129
130 130 FIXED version with which we monkeypatch the stdlib to work around a bug."""
131 131
132 132 file = getsourcefile(object) or getfile(object)
133 133 # If the object is a frame, then trying to get the globals dict from its
134 134 # module won't work. Instead, the frame object itself has the globals
135 135 # dictionary.
136 136 globals_dict = None
137 137 if inspect.isframe(object):
138 138 # XXX: can this ever be false?
139 139 globals_dict = object.f_globals
140 140 else:
141 141 module = getmodule(object, file)
142 142 if module:
143 143 globals_dict = module.__dict__
144 144 lines = linecache.getlines(file, globals_dict)
145 145 if not lines:
146 146 raise IOError('could not get source code')
147 147
148 148 if ismodule(object):
149 149 return lines, 0
150 150
151 151 if isclass(object):
152 152 name = object.__name__
153 153 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
154 154 # make some effort to find the best matching class definition:
155 155 # use the one with the least indentation, which is the one
156 156 # that's most probably not inside a function definition.
157 157 candidates = []
158 158 for i in range(len(lines)):
159 159 match = pat.match(lines[i])
160 160 if match:
161 161 # if it's at toplevel, it's already the best one
162 162 if lines[i][0] == 'c':
163 163 return lines, i
164 164 # else add whitespace to candidate list
165 165 candidates.append((match.group(1), i))
166 166 if candidates:
167 167 # this will sort by whitespace, and by line number,
168 168 # less whitespace first
169 169 candidates.sort()
170 170 return lines, candidates[0][1]
171 171 else:
172 172 raise IOError('could not find class definition')
173 173
174 174 if ismethod(object):
175 175 object = object.im_func
176 176 if isfunction(object):
177 177 object = object.func_code
178 178 if istraceback(object):
179 179 object = object.tb_frame
180 180 if isframe(object):
181 181 object = object.f_code
182 182 if iscode(object):
183 183 if not hasattr(object, 'co_firstlineno'):
184 184 raise IOError('could not find function definition')
185 185 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
186 186 pmatch = pat.match
187 187 # fperez - fix: sometimes, co_firstlineno can give a number larger than
188 188 # the length of lines, which causes an error. Safeguard against that.
189 189 lnum = min(object.co_firstlineno,len(lines))-1
190 190 while lnum > 0:
191 191 if pmatch(lines[lnum]): break
192 192 lnum -= 1
193 193
194 194 return lines, lnum
195 195 raise IOError('could not find code object')
196 196
197 197 # Monkeypatch inspect to apply our bugfix. This code only works with py25
198 198 if sys.version_info[:2] >= (2,5):
199 199 inspect.findsource = findsource
200 200
201 201 def fix_frame_records_filenames(records):
202 202 """Try to fix the filenames in each record from inspect.getinnerframes().
203 203
204 204 Particularly, modules loaded from within zip files have useless filenames
205 205 attached to their code object, and inspect.getinnerframes() just uses it.
206 206 """
207 207 fixed_records = []
208 208 for frame, filename, line_no, func_name, lines, index in records:
209 209 # Look inside the frame's globals dictionary for __file__, which should
210 210 # be better.
211 211 better_fn = frame.f_globals.get('__file__', None)
212 212 if isinstance(better_fn, str):
213 213 # Check the type just in case someone did something weird with
214 214 # __file__. It might also be None if the error occurred during
215 215 # import.
216 216 filename = better_fn
217 217 fixed_records.append((frame, filename, line_no, func_name, lines, index))
218 218 return fixed_records
219 219
220 220
221 221 def _fixed_getinnerframes(etb, context=1,tb_offset=0):
222 222 import linecache
223 223 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
224 224
225 225 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
226 226
227 227 # If the error is at the console, don't build any context, since it would
228 228 # otherwise produce 5 blank lines printed out (there is no file at the
229 229 # console)
230 230 rec_check = records[tb_offset:]
231 231 try:
232 232 rname = rec_check[0][1]
233 233 if rname == '<ipython console>' or rname.endswith('<string>'):
234 234 return rec_check
235 235 except IndexError:
236 236 pass
237 237
238 238 aux = traceback.extract_tb(etb)
239 239 assert len(records) == len(aux)
240 240 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
241 241 maybeStart = lnum-1 - context//2
242 242 start = max(maybeStart, 0)
243 243 end = start + context
244 244 lines = linecache.getlines(file)[start:end]
245 245 # pad with empty lines if necessary
246 246 if maybeStart < 0:
247 247 lines = (['\n'] * -maybeStart) + lines
248 248 if len(lines) < context:
249 249 lines += ['\n'] * (context - len(lines))
250 250 buf = list(records[i])
251 251 buf[LNUM_POS] = lnum
252 252 buf[INDEX_POS] = lnum - 1 - start
253 253 buf[LINES_POS] = lines
254 254 records[i] = tuple(buf)
255 255 return records[tb_offset:]
256 256
257 257 # Helper function -- largely belongs to VerboseTB, but we need the same
258 258 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
259 259 # can be recognized properly by ipython.el's py-traceback-line-re
260 260 # (SyntaxErrors have to be treated specially because they have no traceback)
261 261
262 262 _parser = PyColorize.Parser()
263 263
264 264 def _formatTracebackLines(lnum, index, lines, Colors, lvals=None,scheme=None):
265 265 numbers_width = INDENT_SIZE - 1
266 266 res = []
267 267 i = lnum - index
268 268
269 269 # This lets us get fully syntax-highlighted tracebacks.
270 270 if scheme is None:
271 271 try:
272 272 scheme = __IPYTHON__.rc.colors
273 273 except:
274 274 scheme = DEFAULT_SCHEME
275 275 _line_format = _parser.format2
276 276
277 277 for line in lines:
278 278 new_line, err = _line_format(line,'str',scheme)
279 279 if not err: line = new_line
280 280
281 281 if i == lnum:
282 282 # This is the line with the error
283 283 pad = numbers_width - len(str(i))
284 284 if pad >= 3:
285 285 marker = '-'*(pad-3) + '-> '
286 286 elif pad == 2:
287 287 marker = '> '
288 288 elif pad == 1:
289 289 marker = '>'
290 290 else:
291 291 marker = ''
292 292 num = marker + str(i)
293 293 line = '%s%s%s %s%s' %(Colors.linenoEm, num,
294 294 Colors.line, line, Colors.Normal)
295 295 else:
296 296 num = '%*s' % (numbers_width,i)
297 297 line = '%s%s%s %s' %(Colors.lineno, num,
298 298 Colors.Normal, line)
299 299
300 300 res.append(line)
301 301 if lvals and i == lnum:
302 302 res.append(lvals + '\n')
303 303 i = i + 1
304 304 return res
305 305
306 306
307 307 #---------------------------------------------------------------------------
308 308 # Module classes
309 309 class TBTools:
310 310 """Basic tools used by all traceback printer classes."""
311 311
312 312 def __init__(self,color_scheme = 'NoColor',call_pdb=False):
313 313 # Whether to call the interactive pdb debugger after printing
314 314 # tracebacks or not
315 315 self.call_pdb = call_pdb
316 316
317 317 # Create color table
318 318 self.color_scheme_table = exception_colors()
319 319
320 320 self.set_colors(color_scheme)
321 321 self.old_scheme = color_scheme # save initial value for toggles
322 322
323 323 if call_pdb:
324 324 self.pdb = debugger.Pdb(self.color_scheme_table.active_scheme_name)
325 325 else:
326 326 self.pdb = None
327 327
328 328 def set_colors(self,*args,**kw):
329 329 """Shorthand access to the color table scheme selector method."""
330 330
331 331 # Set own color table
332 332 self.color_scheme_table.set_active_scheme(*args,**kw)
333 333 # for convenience, set Colors to the active scheme
334 334 self.Colors = self.color_scheme_table.active_colors
335 335 # Also set colors of debugger
336 336 if hasattr(self,'pdb') and self.pdb is not None:
337 337 self.pdb.set_colors(*args,**kw)
338 338
339 339 def color_toggle(self):
340 340 """Toggle between the currently active color scheme and NoColor."""
341 341
342 342 if self.color_scheme_table.active_scheme_name == 'NoColor':
343 343 self.color_scheme_table.set_active_scheme(self.old_scheme)
344 344 self.Colors = self.color_scheme_table.active_colors
345 345 else:
346 346 self.old_scheme = self.color_scheme_table.active_scheme_name
347 347 self.color_scheme_table.set_active_scheme('NoColor')
348 348 self.Colors = self.color_scheme_table.active_colors
349 349
350 350 #---------------------------------------------------------------------------
351 351 class ListTB(TBTools):
352 352 """Print traceback information from a traceback list, with optional color.
353 353
354 354 Calling: requires 3 arguments:
355 355 (etype, evalue, elist)
356 356 as would be obtained by:
357 357 etype, evalue, tb = sys.exc_info()
358 358 if tb:
359 359 elist = traceback.extract_tb(tb)
360 360 else:
361 361 elist = None
362 362
363 363 It can thus be used by programs which need to process the traceback before
364 364 printing (such as console replacements based on the code module from the
365 365 standard library).
366 366
367 367 Because they are meant to be called without a full traceback (only a
368 368 list), instances of this class can't call the interactive pdb debugger."""
369 369
370 370 def __init__(self,color_scheme = 'NoColor'):
371 371 TBTools.__init__(self,color_scheme = color_scheme,call_pdb=0)
372 372
373 373 def __call__(self, etype, value, elist):
374 374 Term.cout.flush()
375 375 print >> Term.cerr, self.text(etype,value,elist)
376 376 Term.cerr.flush()
377 377
378 378 def text(self,etype, value, elist,context=5):
379 379 """Return a color formatted string with the traceback info."""
380 380
381 381 Colors = self.Colors
382 382 out_string = ['%s%s%s\n' % (Colors.topline,'-'*60,Colors.Normal)]
383 383 if elist:
384 384 out_string.append('Traceback %s(most recent call last)%s:' % \
385 385 (Colors.normalEm, Colors.Normal) + '\n')
386 386 out_string.extend(self._format_list(elist))
387 387 lines = self._format_exception_only(etype, value)
388 388 for line in lines[:-1]:
389 389 out_string.append(" "+line)
390 390 out_string.append(lines[-1])
391 391 return ''.join(out_string)
392 392
393 393 def _format_list(self, extracted_list):
394 394 """Format a list of traceback entry tuples for printing.
395 395
396 396 Given a list of tuples as returned by extract_tb() or
397 397 extract_stack(), return a list of strings ready for printing.
398 398 Each string in the resulting list corresponds to the item with the
399 399 same index in the argument list. Each string ends in a newline;
400 400 the strings may contain internal newlines as well, for those items
401 401 whose source text line is not None.
402 402
403 403 Lifted almost verbatim from traceback.py
404 404 """
405 405
406 406 Colors = self.Colors
407 407 list = []
408 408 for filename, lineno, name, line in extracted_list[:-1]:
409 409 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
410 410 (Colors.filename, filename, Colors.Normal,
411 411 Colors.lineno, lineno, Colors.Normal,
412 412 Colors.name, name, Colors.Normal)
413 413 if line:
414 414 item = item + ' %s\n' % line.strip()
415 415 list.append(item)
416 416 # Emphasize the last entry
417 417 filename, lineno, name, line = extracted_list[-1]
418 418 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
419 419 (Colors.normalEm,
420 420 Colors.filenameEm, filename, Colors.normalEm,
421 421 Colors.linenoEm, lineno, Colors.normalEm,
422 422 Colors.nameEm, name, Colors.normalEm,
423 423 Colors.Normal)
424 424 if line:
425 425 item = item + '%s %s%s\n' % (Colors.line, line.strip(),
426 426 Colors.Normal)
427 427 list.append(item)
428 428 return list
429 429
430 430 def _format_exception_only(self, etype, value):
431 431 """Format the exception part of a traceback.
432 432
433 433 The arguments are the exception type and value such as given by
434 434 sys.exc_info()[:2]. The return value is a list of strings, each ending
435 435 in a newline. Normally, the list contains a single string; however,
436 436 for SyntaxError exceptions, it contains several lines that (when
437 437 printed) display detailed information about where the syntax error
438 438 occurred. The message indicating which exception occurred is the
439 439 always last string in the list.
440 440
441 441 Also lifted nearly verbatim from traceback.py
442 442 """
443 443
444 444 have_filedata = False
445 445 Colors = self.Colors
446 446 list = []
447 447 try:
448 448 stype = Colors.excName + etype.__name__ + Colors.Normal
449 449 except AttributeError:
450 450 stype = etype # String exceptions don't get special coloring
451 451 if value is None:
452 452 list.append( str(stype) + '\n')
453 453 else:
454 454 if etype is SyntaxError:
455 455 try:
456 456 msg, (filename, lineno, offset, line) = value
457 457 except:
458 458 have_filedata = False
459 459 else:
460 460 have_filedata = True
461 461 #print 'filename is',filename # dbg
462 462 if not filename: filename = "<string>"
463 463 list.append('%s File %s"%s"%s, line %s%d%s\n' % \
464 464 (Colors.normalEm,
465 465 Colors.filenameEm, filename, Colors.normalEm,
466 466 Colors.linenoEm, lineno, Colors.Normal ))
467 467 if line is not None:
468 468 i = 0
469 469 while i < len(line) and line[i].isspace():
470 470 i = i+1
471 471 list.append('%s %s%s\n' % (Colors.line,
472 472 line.strip(),
473 473 Colors.Normal))
474 474 if offset is not None:
475 475 s = ' '
476 476 for c in line[i:offset-1]:
477 477 if c.isspace():
478 478 s = s + c
479 479 else:
480 480 s = s + ' '
481 481 list.append('%s%s^%s\n' % (Colors.caret, s,
482 482 Colors.Normal) )
483 483 value = msg
484 484 s = self._some_str(value)
485 485 if s:
486 486 list.append('%s%s:%s %s\n' % (str(stype), Colors.excName,
487 487 Colors.Normal, s))
488 488 else:
489 489 list.append('%s\n' % str(stype))
490 490
491 491 # vds:>>
492 492 if have_filedata:
493 493 __IPYTHON__.hooks.synchronize_with_editor(filename, lineno, 0)
494 494 # vds:<<
495 495
496 496 return list
497 497
498 498 def _some_str(self, value):
499 499 # Lifted from traceback.py
500 500 try:
501 501 return str(value)
502 502 except:
503 503 return '<unprintable %s object>' % type(value).__name__
504 504
505 505 #----------------------------------------------------------------------------
506 506 class VerboseTB(TBTools):
507 507 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
508 508 of HTML. Requires inspect and pydoc. Crazy, man.
509 509
510 510 Modified version which optionally strips the topmost entries from the
511 511 traceback, to be used with alternate interpreters (because their own code
512 512 would appear in the traceback)."""
513 513
514 514 def __init__(self,color_scheme = 'Linux',tb_offset=0,long_header=0,
515 515 call_pdb = 0, include_vars=1):
516 516 """Specify traceback offset, headers and color scheme.
517 517
518 518 Define how many frames to drop from the tracebacks. Calling it with
519 519 tb_offset=1 allows use of this handler in interpreters which will have
520 520 their own code at the top of the traceback (VerboseTB will first
521 521 remove that frame before printing the traceback info)."""
522 522 TBTools.__init__(self,color_scheme=color_scheme,call_pdb=call_pdb)
523 523 self.tb_offset = tb_offset
524 524 self.long_header = long_header
525 525 self.include_vars = include_vars
526 526
527 527 def text(self, etype, evalue, etb, context=5):
528 528 """Return a nice text document describing the traceback."""
529 529
530 530 # some locals
531 531 try:
532 532 etype = etype.__name__
533 533 except AttributeError:
534 534 pass
535 535 Colors = self.Colors # just a shorthand + quicker name lookup
536 536 ColorsNormal = Colors.Normal # used a lot
537 537 col_scheme = self.color_scheme_table.active_scheme_name
538 538 indent = ' '*INDENT_SIZE
539 539 em_normal = '%s\n%s%s' % (Colors.valEm, indent,ColorsNormal)
540 540 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
541 541 exc = '%s%s%s' % (Colors.excName,etype,ColorsNormal)
542 542
543 543 # some internal-use functions
544 544 def text_repr(value):
545 545 """Hopefully pretty robust repr equivalent."""
546 546 # this is pretty horrible but should always return *something*
547 547 try:
548 548 return pydoc.text.repr(value)
549 549 except KeyboardInterrupt:
550 550 raise
551 551 except:
552 552 try:
553 553 return repr(value)
554 554 except KeyboardInterrupt:
555 555 raise
556 556 except:
557 557 try:
558 558 # all still in an except block so we catch
559 559 # getattr raising
560 560 name = getattr(value, '__name__', None)
561 561 if name:
562 562 # ick, recursion
563 563 return text_repr(name)
564 564 klass = getattr(value, '__class__', None)
565 565 if klass:
566 566 return '%s instance' % text_repr(klass)
567 567 except KeyboardInterrupt:
568 568 raise
569 569 except:
570 570 return 'UNRECOVERABLE REPR FAILURE'
571 571 def eqrepr(value, repr=text_repr): return '=%s' % repr(value)
572 572 def nullrepr(value, repr=text_repr): return ''
573 573
574 574 # meat of the code begins
575 575 try:
576 576 etype = etype.__name__
577 577 except AttributeError:
578 578 pass
579 579
580 580 if self.long_header:
581 581 # Header with the exception type, python version, and date
582 582 pyver = 'Python ' + string.split(sys.version)[0] + ': ' + sys.executable
583 583 date = time.ctime(time.time())
584 584
585 585 head = '%s%s%s\n%s%s%s\n%s' % (Colors.topline, '-'*75, ColorsNormal,
586 586 exc, ' '*(75-len(str(etype))-len(pyver)),
587 587 pyver, string.rjust(date, 75) )
588 588 head += "\nA problem occured executing Python code. Here is the sequence of function"\
589 589 "\ncalls leading up to the error, with the most recent (innermost) call last."
590 590 else:
591 591 # Simplified header
592 592 head = '%s%s%s\n%s%s' % (Colors.topline, '-'*75, ColorsNormal,exc,
593 593 string.rjust('Traceback (most recent call last)',
594 594 75 - len(str(etype)) ) )
595 595 frames = []
596 596 # Flush cache before calling inspect. This helps alleviate some of the
597 597 # problems with python 2.3's inspect.py.
598 598 linecache.checkcache()
599 599 # Drop topmost frames if requested
600 600 try:
601 601 # Try the default getinnerframes and Alex's: Alex's fixes some
602 602 # problems, but it generates empty tracebacks for console errors
603 603 # (5 blanks lines) where none should be returned.
604 604 #records = inspect.getinnerframes(etb, context)[self.tb_offset:]
605 605 #print 'python records:', records # dbg
606 606 records = _fixed_getinnerframes(etb, context,self.tb_offset)
607 607 #print 'alex records:', records # dbg
608 608 except:
609 609
610 610 # FIXME: I've been getting many crash reports from python 2.3
611 611 # users, traceable to inspect.py. If I can find a small test-case
612 612 # to reproduce this, I should either write a better workaround or
613 613 # file a bug report against inspect (if that's the real problem).
614 614 # So far, I haven't been able to find an isolated example to
615 615 # reproduce the problem.
616 616 inspect_error()
617 617 traceback.print_exc(file=Term.cerr)
618 618 info('\nUnfortunately, your original traceback can not be constructed.\n')
619 619 return ''
620 620
621 621 # build some color string templates outside these nested loops
622 622 tpl_link = '%s%%s%s' % (Colors.filenameEm,ColorsNormal)
623 623 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
624 624 ColorsNormal)
625 625 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
626 626 (Colors.vName, Colors.valEm, ColorsNormal)
627 627 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
628 628 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
629 629 Colors.vName, ColorsNormal)
630 630 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
631 631 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
632 632 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm,Colors.line,
633 633 ColorsNormal)
634 634
635 635 # now, loop over all records printing context and info
636 636 abspath = os.path.abspath
637 637 for frame, file, lnum, func, lines, index in records:
638 638 #print '*** record:',file,lnum,func,lines,index # dbg
639 639 try:
640 640 file = file and abspath(file) or '?'
641 641 except OSError:
642 642 # if file is '<console>' or something not in the filesystem,
643 643 # the abspath call will throw an OSError. Just ignore it and
644 644 # keep the original file string.
645 645 pass
646 646 link = tpl_link % file
647 647 try:
648 648 args, varargs, varkw, locals = inspect.getargvalues(frame)
649 649 except:
650 650 # This can happen due to a bug in python2.3. We should be
651 651 # able to remove this try/except when 2.4 becomes a
652 652 # requirement. Bug details at http://python.org/sf/1005466
653 653 inspect_error()
654 654 traceback.print_exc(file=Term.cerr)
655 655 info("\nIPython's exception reporting continues...\n")
656 656
657 657 if func == '?':
658 658 call = ''
659 659 else:
660 660 # Decide whether to include variable details or not
661 661 var_repr = self.include_vars and eqrepr or nullrepr
662 662 try:
663 663 call = tpl_call % (func,inspect.formatargvalues(args,
664 664 varargs, varkw,
665 665 locals,formatvalue=var_repr))
666 666 except KeyError:
667 667 # Very odd crash from inspect.formatargvalues(). The
668 668 # scenario under which it appeared was a call to
669 669 # view(array,scale) in NumTut.view.view(), where scale had
670 670 # been defined as a scalar (it should be a tuple). Somehow
671 671 # inspect messes up resolving the argument list of view()
672 672 # and barfs out. At some point I should dig into this one
673 673 # and file a bug report about it.
674 674 inspect_error()
675 675 traceback.print_exc(file=Term.cerr)
676 676 info("\nIPython's exception reporting continues...\n")
677 677 call = tpl_call_fail % func
678 678
679 679 # Initialize a list of names on the current line, which the
680 680 # tokenizer below will populate.
681 681 names = []
682 682
683 683 def tokeneater(token_type, token, start, end, line):
684 684 """Stateful tokeneater which builds dotted names.
685 685
686 686 The list of names it appends to (from the enclosing scope) can
687 687 contain repeated composite names. This is unavoidable, since
688 688 there is no way to disambguate partial dotted structures until
689 689 the full list is known. The caller is responsible for pruning
690 690 the final list of duplicates before using it."""
691 691
692 692 # build composite names
693 693 if token == '.':
694 694 try:
695 695 names[-1] += '.'
696 696 # store state so the next token is added for x.y.z names
697 697 tokeneater.name_cont = True
698 698 return
699 699 except IndexError:
700 700 pass
701 701 if token_type == tokenize.NAME and token not in keyword.kwlist:
702 702 if tokeneater.name_cont:
703 703 # Dotted names
704 704 names[-1] += token
705 705 tokeneater.name_cont = False
706 706 else:
707 707 # Regular new names. We append everything, the caller
708 708 # will be responsible for pruning the list later. It's
709 709 # very tricky to try to prune as we go, b/c composite
710 710 # names can fool us. The pruning at the end is easy
711 711 # to do (or the caller can print a list with repeated
712 712 # names if so desired.
713 713 names.append(token)
714 714 elif token_type == tokenize.NEWLINE:
715 715 raise IndexError
716 716 # we need to store a bit of state in the tokenizer to build
717 717 # dotted names
718 718 tokeneater.name_cont = False
719 719
720 720 def linereader(file=file, lnum=[lnum], getline=linecache.getline):
721 721 line = getline(file, lnum[0])
722 722 lnum[0] += 1
723 723 return line
724 724
725 725 # Build the list of names on this line of code where the exception
726 726 # occurred.
727 727 try:
728 728 # This builds the names list in-place by capturing it from the
729 729 # enclosing scope.
730 730 tokenize.tokenize(linereader, tokeneater)
731 731 except IndexError:
732 732 # signals exit of tokenizer
733 733 pass
734 734 except tokenize.TokenError,msg:
735 735 _m = ("An unexpected error occurred while tokenizing input\n"
736 736 "The following traceback may be corrupted or invalid\n"
737 737 "The error message is: %s\n" % msg)
738 738 error(_m)
739 739
740 740 # prune names list of duplicates, but keep the right order
741 741 unique_names = uniq_stable(names)
742 742
743 743 # Start loop over vars
744 744 lvals = []
745 745 if self.include_vars:
746 746 for name_full in unique_names:
747 747 name_base = name_full.split('.',1)[0]
748 748 if name_base in frame.f_code.co_varnames:
749 749 if locals.has_key(name_base):
750 750 try:
751 751 value = repr(eval(name_full,locals))
752 752 except:
753 753 value = undefined
754 754 else:
755 755 value = undefined
756 756 name = tpl_local_var % name_full
757 757 else:
758 758 if frame.f_globals.has_key(name_base):
759 759 try:
760 760 value = repr(eval(name_full,frame.f_globals))
761 761 except:
762 762 value = undefined
763 763 else:
764 764 value = undefined
765 765 name = tpl_global_var % name_full
766 766 lvals.append(tpl_name_val % (name,value))
767 767 if lvals:
768 768 lvals = '%s%s' % (indent,em_normal.join(lvals))
769 769 else:
770 770 lvals = ''
771 771
772 772 level = '%s %s\n' % (link,call)
773 773
774 774 if index is None:
775 775 frames.append(level)
776 776 else:
777 777 frames.append('%s%s' % (level,''.join(
778 778 _formatTracebackLines(lnum,index,lines,Colors,lvals,
779 779 col_scheme))))
780 780
781 781 # Get (safely) a string form of the exception info
782 782 try:
783 783 etype_str,evalue_str = map(str,(etype,evalue))
784 784 except:
785 785 # User exception is improperly defined.
786 786 etype,evalue = str,sys.exc_info()[:2]
787 787 etype_str,evalue_str = map(str,(etype,evalue))
788 788 # ... and format it
789 789 exception = ['%s%s%s: %s' % (Colors.excName, etype_str,
790 790 ColorsNormal, evalue_str)]
791 791 if type(evalue) is types.InstanceType:
792 792 try:
793 793 names = [w for w in dir(evalue) if isinstance(w, basestring)]
794 794 except:
795 795 # Every now and then, an object with funny inernals blows up
796 796 # when dir() is called on it. We do the best we can to report
797 797 # the problem and continue
798 798 _m = '%sException reporting error (object with broken dir())%s:'
799 799 exception.append(_m % (Colors.excName,ColorsNormal))
800 800 etype_str,evalue_str = map(str,sys.exc_info()[:2])
801 801 exception.append('%s%s%s: %s' % (Colors.excName,etype_str,
802 802 ColorsNormal, evalue_str))
803 803 names = []
804 804 for name in names:
805 805 value = text_repr(getattr(evalue, name))
806 806 exception.append('\n%s%s = %s' % (indent, name, value))
807 807
808 808 # vds: >>
809 809 if records:
810 810 filepath, lnum = records[-1][1:3]
811 811 #print "file:", str(file), "linenb", str(lnum) # dbg
812 812 filepath = os.path.abspath(filepath)
813 813 __IPYTHON__.hooks.synchronize_with_editor(filepath, lnum, 0)
814 814 # vds: <<
815 815
816 816 # return all our info assembled as a single string
817 817 return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) )
818 818
819 819 def debugger(self,force=False):
820 820 """Call up the pdb debugger if desired, always clean up the tb
821 821 reference.
822 822
823 823 Keywords:
824 824
825 825 - force(False): by default, this routine checks the instance call_pdb
826 826 flag and does not actually invoke the debugger if the flag is false.
827 827 The 'force' option forces the debugger to activate even if the flag
828 828 is false.
829 829
830 830 If the call_pdb flag is set, the pdb interactive debugger is
831 831 invoked. In all cases, the self.tb reference to the current traceback
832 832 is deleted to prevent lingering references which hamper memory
833 833 management.
834 834
835 835 Note that each call to pdb() does an 'import readline', so if your app
836 836 requires a special setup for the readline completers, you'll have to
837 837 fix that by hand after invoking the exception handler."""
838 838
839 839 if force or self.call_pdb:
840 840 if self.pdb is None:
841 841 self.pdb = debugger.Pdb(
842 842 self.color_scheme_table.active_scheme_name)
843 843 # the system displayhook may have changed, restore the original
844 844 # for pdb
845 845 dhook = sys.displayhook
846 846 sys.displayhook = sys.__displayhook__
847 847 self.pdb.reset()
848 848 # Find the right frame so we don't pop up inside ipython itself
849 849 if hasattr(self,'tb'):
850 850 etb = self.tb
851 851 else:
852 852 etb = self.tb = sys.last_traceback
853 853 while self.tb.tb_next is not None:
854 854 self.tb = self.tb.tb_next
855 855 try:
856 856 if etb and etb.tb_next:
857 857 etb = etb.tb_next
858 858 self.pdb.botframe = etb.tb_frame
859 859 self.pdb.interaction(self.tb.tb_frame, self.tb)
860 860 finally:
861 861 sys.displayhook = dhook
862 862
863 863 if hasattr(self,'tb'):
864 864 del self.tb
865 865
866 866 def handler(self, info=None):
867 867 (etype, evalue, etb) = info or sys.exc_info()
868 868 self.tb = etb
869 869 Term.cout.flush()
870 870 print >> Term.cerr, self.text(etype, evalue, etb)
871 871 Term.cerr.flush()
872 872
873 873 # Changed so an instance can just be called as VerboseTB_inst() and print
874 874 # out the right info on its own.
875 875 def __call__(self, etype=None, evalue=None, etb=None):
876 876 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
877 877 if etb is None:
878 878 self.handler()
879 879 else:
880 880 self.handler((etype, evalue, etb))
881 881 try:
882 882 self.debugger()
883 883 except KeyboardInterrupt:
884 884 print "\nKeyboardInterrupt"
885 885
886 886 #----------------------------------------------------------------------------
887 887 class FormattedTB(VerboseTB,ListTB):
888 888 """Subclass ListTB but allow calling with a traceback.
889 889
890 890 It can thus be used as a sys.excepthook for Python > 2.1.
891 891
892 892 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
893 893
894 894 Allows a tb_offset to be specified. This is useful for situations where
895 895 one needs to remove a number of topmost frames from the traceback (such as
896 896 occurs with python programs that themselves execute other python code,
897 897 like Python shells). """
898 898
899 899 def __init__(self, mode = 'Plain', color_scheme='Linux',
900 900 tb_offset = 0,long_header=0,call_pdb=0,include_vars=0):
901 901
902 902 # NEVER change the order of this list. Put new modes at the end:
903 903 self.valid_modes = ['Plain','Context','Verbose']
904 904 self.verbose_modes = self.valid_modes[1:3]
905 905
906 906 VerboseTB.__init__(self,color_scheme,tb_offset,long_header,
907 907 call_pdb=call_pdb,include_vars=include_vars)
908 908 self.set_mode(mode)
909 909
910 910 def _extract_tb(self,tb):
911 911 if tb:
912 912 return traceback.extract_tb(tb)
913 913 else:
914 914 return None
915 915
916 916 def text(self, etype, value, tb,context=5,mode=None):
917 917 """Return formatted traceback.
918 918
919 919 If the optional mode parameter is given, it overrides the current
920 920 mode."""
921 921
922 922 if mode is None:
923 923 mode = self.mode
924 924 if mode in self.verbose_modes:
925 925 # verbose modes need a full traceback
926 926 return VerboseTB.text(self,etype, value, tb,context=5)
927 927 else:
928 928 # We must check the source cache because otherwise we can print
929 929 # out-of-date source code.
930 930 linecache.checkcache()
931 931 # Now we can extract and format the exception
932 932 elist = self._extract_tb(tb)
933 933 if len(elist) > self.tb_offset:
934 934 del elist[:self.tb_offset]
935 935 return ListTB.text(self,etype,value,elist)
936 936
937 937 def set_mode(self,mode=None):
938 938 """Switch to the desired mode.
939 939
940 940 If mode is not specified, cycles through the available modes."""
941 941
942 942 if not mode:
943 943 new_idx = ( self.valid_modes.index(self.mode) + 1 ) % \
944 944 len(self.valid_modes)
945 945 self.mode = self.valid_modes[new_idx]
946 946 elif mode not in self.valid_modes:
947 947 raise ValueError, 'Unrecognized mode in FormattedTB: <'+mode+'>\n'\
948 948 'Valid modes: '+str(self.valid_modes)
949 949 else:
950 950 self.mode = mode
951 951 # include variable details only in 'Verbose' mode
952 952 self.include_vars = (self.mode == self.valid_modes[2])
953 953
954 954 # some convenient shorcuts
955 955 def plain(self):
956 956 self.set_mode(self.valid_modes[0])
957 957
958 958 def context(self):
959 959 self.set_mode(self.valid_modes[1])
960 960
961 961 def verbose(self):
962 962 self.set_mode(self.valid_modes[2])
963 963
964 964 #----------------------------------------------------------------------------
965 965 class AutoFormattedTB(FormattedTB):
966 966 """A traceback printer which can be called on the fly.
967 967
968 968 It will find out about exceptions by itself.
969 969
970 970 A brief example:
971 971
972 972 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
973 973 try:
974 974 ...
975 975 except:
976 976 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
977 977 """
978 978 def __call__(self,etype=None,evalue=None,etb=None,
979 979 out=None,tb_offset=None):
980 980 """Print out a formatted exception traceback.
981 981
982 982 Optional arguments:
983 983 - out: an open file-like object to direct output to.
984 984
985 985 - tb_offset: the number of frames to skip over in the stack, on a
986 986 per-call basis (this overrides temporarily the instance's tb_offset
987 987 given at initialization time. """
988 988
989 989 if out is None:
990 990 out = Term.cerr
991 991 Term.cout.flush()
992 992 if tb_offset is not None:
993 993 tb_offset, self.tb_offset = self.tb_offset, tb_offset
994 994 print >> out, self.text(etype, evalue, etb)
995 995 self.tb_offset = tb_offset
996 996 else:
997 997 print >> out, self.text(etype, evalue, etb)
998 998 out.flush()
999 999 try:
1000 1000 self.debugger()
1001 1001 except KeyboardInterrupt:
1002 1002 print "\nKeyboardInterrupt"
1003 1003
1004 1004 def text(self,etype=None,value=None,tb=None,context=5,mode=None):
1005 1005 if etype is None:
1006 1006 etype,value,tb = sys.exc_info()
1007 1007 self.tb = tb
1008 1008 return FormattedTB.text(self,etype,value,tb,context=5,mode=mode)
1009 1009
1010 1010 #---------------------------------------------------------------------------
1011 1011 # A simple class to preserve Nathan's original functionality.
1012 1012 class ColorTB(FormattedTB):
1013 1013 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1014 1014 def __init__(self,color_scheme='Linux',call_pdb=0):
1015 1015 FormattedTB.__init__(self,color_scheme=color_scheme,
1016 1016 call_pdb=call_pdb)
1017 1017
1018 1018 #----------------------------------------------------------------------------
1019 1019 # module testing (minimal)
1020 1020 if __name__ == "__main__":
1021 1021 def spam(c, (d, e)):
1022 1022 x = c + d
1023 1023 y = c * d
1024 1024 foo(x, y)
1025 1025
1026 1026 def foo(a, b, bar=1):
1027 1027 eggs(a, b + bar)
1028 1028
1029 1029 def eggs(f, g, z=globals()):
1030 1030 h = f + g
1031 1031 i = f - g
1032 1032 return h / i
1033 1033
1034 1034 print ''
1035 1035 print '*** Before ***'
1036 1036 try:
1037 1037 print spam(1, (2, 3))
1038 1038 except:
1039 1039 traceback.print_exc()
1040 1040 print ''
1041 1041
1042 1042 handler = ColorTB()
1043 1043 print '*** ColorTB ***'
1044 1044 try:
1045 1045 print spam(1, (2, 3))
1046 1046 except:
1047 1047 apply(handler, sys.exc_info() )
1048 1048 print ''
1049 1049
1050 1050 handler = VerboseTB()
1051 1051 print '*** VerboseTB ***'
1052 1052 try:
1053 1053 print spam(1, (2, 3))
1054 1054 except:
1055 1055 apply(handler, sys.exc_info() )
1056 1056 print ''
1057 1057
General Comments 0
You need to be logged in to leave comments. Login now