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