##// END OF EJS Templates
don't use deprecated ipapi.get...
MinRK -
Show More
@@ -1,566 +1,565 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 Pdb debugger class.
4 4
5 5 Modified from the standard pdb.Pdb class to avoid including readline, so that
6 6 the command line completion of other programs which include this isn't
7 7 damaged.
8 8
9 9 In the future, this class will be expanded with improvements over the standard
10 10 pdb.
11 11
12 12 The code in this file is mainly lifted out of cmd.py in Python 2.2, with minor
13 13 changes. Licensing should therefore be under the standard Python terms. For
14 14 details on the PSF (Python Software Foundation) standard license, see:
15 15
16 16 http://www.python.org/2.2.3/license.html"""
17 17
18 18 #*****************************************************************************
19 19 #
20 20 # This file is licensed under the PSF license.
21 21 #
22 22 # Copyright (C) 2001 Python Software Foundation, www.python.org
23 23 # Copyright (C) 2005-2006 Fernando Perez. <fperez@colorado.edu>
24 24 #
25 25 #
26 26 #*****************************************************************************
27 27 from __future__ import print_function
28 28
29 29 import bdb
30 30 import functools
31 31 import linecache
32 32 import sys
33 33
34 34 from IPython import get_ipython
35 35 from IPython.utils import PyColorize, ulinecache
36 from IPython.core import ipapi
37 36 from IPython.utils import coloransi, io, py3compat
38 37 from IPython.core.excolors import exception_colors
39 38
40 39 # See if we can use pydb.
41 40 has_pydb = False
42 41 prompt = 'ipdb> '
43 42 #We have to check this directly from sys.argv, config struct not yet available
44 43 if '--pydb' in sys.argv:
45 44 try:
46 45 import pydb
47 46 if hasattr(pydb.pydb, "runl") and pydb.version>'1.17':
48 47 # Version 1.17 is broken, and that's what ships with Ubuntu Edgy, so we
49 48 # better protect against it.
50 49 has_pydb = True
51 50 except ImportError:
52 51 print("Pydb (http://bashdb.sourceforge.net/pydb/) does not seem to be available")
53 52
54 53 if has_pydb:
55 54 from pydb import Pdb as OldPdb
56 55 #print "Using pydb for %run -d and post-mortem" #dbg
57 56 prompt = 'ipydb> '
58 57 else:
59 58 from pdb import Pdb as OldPdb
60 59
61 60 # Allow the set_trace code to operate outside of an ipython instance, even if
62 61 # it does so with some limitations. The rest of this support is implemented in
63 62 # the Tracer constructor.
64 63 def BdbQuit_excepthook(et, ev, tb, excepthook=None):
65 64 """Exception hook which handles `BdbQuit` exceptions.
66 65
67 66 All other exceptions are processed using the `excepthook`
68 67 parameter.
69 68 """
70 69 if et==bdb.BdbQuit:
71 70 print('Exiting Debugger.')
72 71 elif excepthook is not None:
73 72 excepthook(et, ev, tb)
74 73 else:
75 74 # Backwards compatibility. Raise deprecation warning?
76 75 BdbQuit_excepthook.excepthook_ori(et,ev,tb)
77 76
78 77 def BdbQuit_IPython_excepthook(self,et,ev,tb,tb_offset=None):
79 78 print('Exiting Debugger.')
80 79
81 80
82 81 class Tracer(object):
83 82 """Class for local debugging, similar to pdb.set_trace.
84 83
85 84 Instances of this class, when called, behave like pdb.set_trace, but
86 85 providing IPython's enhanced capabilities.
87 86
88 87 This is implemented as a class which must be initialized in your own code
89 88 and not as a standalone function because we need to detect at runtime
90 89 whether IPython is already active or not. That detection is done in the
91 90 constructor, ensuring that this code plays nicely with a running IPython,
92 91 while functioning acceptably (though with limitations) if outside of it.
93 92 """
94 93
95 94 def __init__(self,colors=None):
96 95 """Create a local debugger instance.
97 96
98 97 :Parameters:
99 98
100 99 - `colors` (None): a string containing the name of the color scheme to
101 100 use, it must be one of IPython's valid color schemes. If not given, the
102 101 function will default to the current IPython scheme when running inside
103 102 IPython, and to 'NoColor' otherwise.
104 103
105 104 Usage example:
106 105
107 106 from IPython.core.debugger import Tracer; debug_here = Tracer()
108 107
109 108 ... later in your code
110 109 debug_here() # -> will open up the debugger at that point.
111 110
112 111 Once the debugger activates, you can use all of its regular commands to
113 112 step through code, set breakpoints, etc. See the pdb documentation
114 113 from the Python standard library for usage details.
115 114 """
116 115
117 116 ip = get_ipython()
118 117 if ip is None:
119 118 # Outside of ipython, we set our own exception hook manually
120 119 sys.excepthook = functools.partial(BdbQuit_excepthook,
121 120 excepthook=sys.excepthook)
122 121 def_colors = 'NoColor'
123 122 try:
124 123 # Limited tab completion support
125 124 import readline
126 125 readline.parse_and_bind('tab: complete')
127 126 except ImportError:
128 127 pass
129 128 else:
130 129 # In ipython, we use its custom exception handler mechanism
131 130 def_colors = ip.colors
132 131 ip.set_custom_exc((bdb.BdbQuit,), BdbQuit_IPython_excepthook)
133 132
134 133 if colors is None:
135 134 colors = def_colors
136 135
137 136 # The stdlib debugger internally uses a modified repr from the `repr`
138 137 # module, that limits the length of printed strings to a hardcoded
139 138 # limit of 30 characters. That much trimming is too aggressive, let's
140 139 # at least raise that limit to 80 chars, which should be enough for
141 140 # most interactive uses.
142 141 try:
143 142 from repr import aRepr
144 143 aRepr.maxstring = 80
145 144 except:
146 145 # This is only a user-facing convenience, so any error we encounter
147 146 # here can be warned about but can be otherwise ignored. These
148 147 # printouts will tell us about problems if this API changes
149 148 import traceback
150 149 traceback.print_exc()
151 150
152 151 self.debugger = Pdb(colors)
153 152
154 153 def __call__(self):
155 154 """Starts an interactive debugger at the point where called.
156 155
157 156 This is similar to the pdb.set_trace() function from the std lib, but
158 157 using IPython's enhanced debugger."""
159 158
160 159 self.debugger.set_trace(sys._getframe().f_back)
161 160
162 161
163 162 def decorate_fn_with_doc(new_fn, old_fn, additional_text=""):
164 163 """Make new_fn have old_fn's doc string. This is particularly useful
165 164 for the ``do_...`` commands that hook into the help system.
166 165 Adapted from from a comp.lang.python posting
167 166 by Duncan Booth."""
168 167 def wrapper(*args, **kw):
169 168 return new_fn(*args, **kw)
170 169 if old_fn.__doc__:
171 170 wrapper.__doc__ = old_fn.__doc__ + additional_text
172 171 return wrapper
173 172
174 173
175 174 def _file_lines(fname):
176 175 """Return the contents of a named file as a list of lines.
177 176
178 177 This function never raises an IOError exception: if the file can't be
179 178 read, it simply returns an empty list."""
180 179
181 180 try:
182 181 outfile = open(fname)
183 182 except IOError:
184 183 return []
185 184 else:
186 185 out = outfile.readlines()
187 186 outfile.close()
188 187 return out
189 188
190 189
191 190 class Pdb(OldPdb):
192 191 """Modified Pdb class, does not load readline."""
193 192
194 193 def __init__(self,color_scheme='NoColor',completekey=None,
195 194 stdin=None, stdout=None):
196 195
197 196 # Parent constructor:
198 197 if has_pydb and completekey is None:
199 198 OldPdb.__init__(self,stdin=stdin,stdout=io.stdout)
200 199 else:
201 200 OldPdb.__init__(self,completekey,stdin,stdout)
202 201
203 202 self.prompt = prompt # The default prompt is '(Pdb)'
204 203
205 204 # IPython changes...
206 205 self.is_pydb = has_pydb
207 206
208 self.shell = ipapi.get()
207 self.shell = get_ipython()
209 208
210 209 if self.is_pydb:
211 210
212 211 # interactiveshell.py's ipalias seems to want pdb's checkline
213 212 # which located in pydb.fn
214 213 import pydb.fns
215 214 self.checkline = lambda filename, lineno: \
216 215 pydb.fns.checkline(self, filename, lineno)
217 216
218 217 self.curframe = None
219 218 self.do_restart = self.new_do_restart
220 219
221 220 self.old_all_completions = self.shell.Completer.all_completions
222 221 self.shell.Completer.all_completions=self.all_completions
223 222
224 223 self.do_list = decorate_fn_with_doc(self.list_command_pydb,
225 224 OldPdb.do_list)
226 225 self.do_l = self.do_list
227 226 self.do_frame = decorate_fn_with_doc(self.new_do_frame,
228 227 OldPdb.do_frame)
229 228
230 229 self.aliases = {}
231 230
232 231 # Create color table: we copy the default one from the traceback
233 232 # module and add a few attributes needed for debugging
234 233 self.color_scheme_table = exception_colors()
235 234
236 235 # shorthands
237 236 C = coloransi.TermColors
238 237 cst = self.color_scheme_table
239 238
240 239 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
241 240 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
242 241
243 242 cst['Linux'].colors.breakpoint_enabled = C.LightRed
244 243 cst['Linux'].colors.breakpoint_disabled = C.Red
245 244
246 245 cst['LightBG'].colors.breakpoint_enabled = C.LightRed
247 246 cst['LightBG'].colors.breakpoint_disabled = C.Red
248 247
249 248 self.set_colors(color_scheme)
250 249
251 250 # Add a python parser so we can syntax highlight source while
252 251 # debugging.
253 252 self.parser = PyColorize.Parser()
254 253
255 254 def set_colors(self, scheme):
256 255 """Shorthand access to the color table scheme selector method."""
257 256 self.color_scheme_table.set_active_scheme(scheme)
258 257
259 258 def interaction(self, frame, traceback):
260 259 self.shell.set_completer_frame(frame)
261 260 OldPdb.interaction(self, frame, traceback)
262 261
263 262 def new_do_up(self, arg):
264 263 OldPdb.do_up(self, arg)
265 264 self.shell.set_completer_frame(self.curframe)
266 265 do_u = do_up = decorate_fn_with_doc(new_do_up, OldPdb.do_up)
267 266
268 267 def new_do_down(self, arg):
269 268 OldPdb.do_down(self, arg)
270 269 self.shell.set_completer_frame(self.curframe)
271 270
272 271 do_d = do_down = decorate_fn_with_doc(new_do_down, OldPdb.do_down)
273 272
274 273 def new_do_frame(self, arg):
275 274 OldPdb.do_frame(self, arg)
276 275 self.shell.set_completer_frame(self.curframe)
277 276
278 277 def new_do_quit(self, arg):
279 278
280 279 if hasattr(self, 'old_all_completions'):
281 280 self.shell.Completer.all_completions=self.old_all_completions
282 281
283 282
284 283 return OldPdb.do_quit(self, arg)
285 284
286 285 do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit)
287 286
288 287 def new_do_restart(self, arg):
289 288 """Restart command. In the context of ipython this is exactly the same
290 289 thing as 'quit'."""
291 290 self.msg("Restart doesn't make sense here. Using 'quit' instead.")
292 291 return self.do_quit(arg)
293 292
294 293 def postloop(self):
295 294 self.shell.set_completer_frame(None)
296 295
297 296 def print_stack_trace(self):
298 297 try:
299 298 for frame_lineno in self.stack:
300 299 self.print_stack_entry(frame_lineno, context = 5)
301 300 except KeyboardInterrupt:
302 301 pass
303 302
304 303 def print_stack_entry(self,frame_lineno,prompt_prefix='\n-> ',
305 304 context = 3):
306 305 #frame, lineno = frame_lineno
307 306 print(self.format_stack_entry(frame_lineno, '', context), file=io.stdout)
308 307
309 308 # vds: >>
310 309 frame, lineno = frame_lineno
311 310 filename = frame.f_code.co_filename
312 311 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
313 312 # vds: <<
314 313
315 314 def format_stack_entry(self, frame_lineno, lprefix=': ', context = 3):
316 315 import repr
317 316
318 317 ret = []
319 318
320 319 Colors = self.color_scheme_table.active_colors
321 320 ColorsNormal = Colors.Normal
322 321 tpl_link = u'%s%%s%s' % (Colors.filenameEm, ColorsNormal)
323 322 tpl_call = u'%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal)
324 323 tpl_line = u'%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
325 324 tpl_line_em = u'%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line,
326 325 ColorsNormal)
327 326
328 327 frame, lineno = frame_lineno
329 328
330 329 return_value = ''
331 330 if '__return__' in frame.f_locals:
332 331 rv = frame.f_locals['__return__']
333 332 #return_value += '->'
334 333 return_value += repr.repr(rv) + '\n'
335 334 ret.append(return_value)
336 335
337 336 #s = filename + '(' + `lineno` + ')'
338 337 filename = self.canonic(frame.f_code.co_filename)
339 338 link = tpl_link % py3compat.cast_unicode(filename)
340 339
341 340 if frame.f_code.co_name:
342 341 func = frame.f_code.co_name
343 342 else:
344 343 func = "<lambda>"
345 344
346 345 call = ''
347 346 if func != '?':
348 347 if '__args__' in frame.f_locals:
349 348 args = repr.repr(frame.f_locals['__args__'])
350 349 else:
351 350 args = '()'
352 351 call = tpl_call % (func, args)
353 352
354 353 # The level info should be generated in the same format pdb uses, to
355 354 # avoid breaking the pdbtrack functionality of python-mode in *emacs.
356 355 if frame is self.curframe:
357 356 ret.append('> ')
358 357 else:
359 358 ret.append(' ')
360 359 ret.append(u'%s(%s)%s\n' % (link,lineno,call))
361 360
362 361 start = lineno - 1 - context//2
363 362 lines = ulinecache.getlines(filename)
364 363 start = min(start, len(lines) - context)
365 364 start = max(start, 0)
366 365 lines = lines[start : start + context]
367 366
368 367 for i,line in enumerate(lines):
369 368 show_arrow = (start + 1 + i == lineno)
370 369 linetpl = (frame is self.curframe or show_arrow) \
371 370 and tpl_line_em \
372 371 or tpl_line
373 372 ret.append(self.__format_line(linetpl, filename,
374 373 start + 1 + i, line,
375 374 arrow = show_arrow) )
376 375 return ''.join(ret)
377 376
378 377 def __format_line(self, tpl_line, filename, lineno, line, arrow = False):
379 378 bp_mark = ""
380 379 bp_mark_color = ""
381 380
382 381 scheme = self.color_scheme_table.active_scheme_name
383 382 new_line, err = self.parser.format2(line, 'str', scheme)
384 383 if not err: line = new_line
385 384
386 385 bp = None
387 386 if lineno in self.get_file_breaks(filename):
388 387 bps = self.get_breaks(filename, lineno)
389 388 bp = bps[-1]
390 389
391 390 if bp:
392 391 Colors = self.color_scheme_table.active_colors
393 392 bp_mark = str(bp.number)
394 393 bp_mark_color = Colors.breakpoint_enabled
395 394 if not bp.enabled:
396 395 bp_mark_color = Colors.breakpoint_disabled
397 396
398 397 numbers_width = 7
399 398 if arrow:
400 399 # This is the line with the error
401 400 pad = numbers_width - len(str(lineno)) - len(bp_mark)
402 401 if pad >= 3:
403 402 marker = '-'*(pad-3) + '-> '
404 403 elif pad == 2:
405 404 marker = '> '
406 405 elif pad == 1:
407 406 marker = '>'
408 407 else:
409 408 marker = ''
410 409 num = '%s%s' % (marker, str(lineno))
411 410 line = tpl_line % (bp_mark_color + bp_mark, num, line)
412 411 else:
413 412 num = '%*s' % (numbers_width - len(bp_mark), str(lineno))
414 413 line = tpl_line % (bp_mark_color + bp_mark, num, line)
415 414
416 415 return line
417 416
418 417 def list_command_pydb(self, arg):
419 418 """List command to use if we have a newer pydb installed"""
420 419 filename, first, last = OldPdb.parse_list_cmd(self, arg)
421 420 if filename is not None:
422 421 self.print_list_lines(filename, first, last)
423 422
424 423 def print_list_lines(self, filename, first, last):
425 424 """The printing (as opposed to the parsing part of a 'list'
426 425 command."""
427 426 try:
428 427 Colors = self.color_scheme_table.active_colors
429 428 ColorsNormal = Colors.Normal
430 429 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
431 430 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal)
432 431 src = []
433 432 if filename == "<string>" and hasattr(self, "_exec_filename"):
434 433 filename = self._exec_filename
435 434
436 435 for lineno in range(first, last+1):
437 436 line = ulinecache.getline(filename, lineno)
438 437 if not line:
439 438 break
440 439
441 440 if lineno == self.curframe.f_lineno:
442 441 line = self.__format_line(tpl_line_em, filename, lineno, line, arrow = True)
443 442 else:
444 443 line = self.__format_line(tpl_line, filename, lineno, line, arrow = False)
445 444
446 445 src.append(line)
447 446 self.lineno = lineno
448 447
449 448 print(''.join(src), file=io.stdout)
450 449
451 450 except KeyboardInterrupt:
452 451 pass
453 452
454 453 def do_list(self, arg):
455 454 self.lastcmd = 'list'
456 455 last = None
457 456 if arg:
458 457 try:
459 458 x = eval(arg, {}, {})
460 459 if type(x) == type(()):
461 460 first, last = x
462 461 first = int(first)
463 462 last = int(last)
464 463 if last < first:
465 464 # Assume it's a count
466 465 last = first + last
467 466 else:
468 467 first = max(1, int(x) - 5)
469 468 except:
470 469 print('*** Error in argument:', repr(arg))
471 470 return
472 471 elif self.lineno is None:
473 472 first = max(1, self.curframe.f_lineno - 5)
474 473 else:
475 474 first = self.lineno + 1
476 475 if last is None:
477 476 last = first + 10
478 477 self.print_list_lines(self.curframe.f_code.co_filename, first, last)
479 478
480 479 # vds: >>
481 480 lineno = first
482 481 filename = self.curframe.f_code.co_filename
483 482 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
484 483 # vds: <<
485 484
486 485 do_l = do_list
487 486
488 487 def do_pdef(self, arg):
489 488 """Print the call signature for any callable object.
490 489
491 490 The debugger interface to %pdef"""
492 491 namespaces = [('Locals', self.curframe.f_locals),
493 492 ('Globals', self.curframe.f_globals)]
494 493 self.shell.find_line_magic('pdef')(arg, namespaces=namespaces)
495 494
496 495 def do_pdoc(self, arg):
497 496 """Print the docstring for an object.
498 497
499 498 The debugger interface to %pdoc."""
500 499 namespaces = [('Locals', self.curframe.f_locals),
501 500 ('Globals', self.curframe.f_globals)]
502 501 self.shell.find_line_magic('pdoc')(arg, namespaces=namespaces)
503 502
504 503 def do_pfile(self, arg):
505 504 """Print (or run through pager) the file where an object is defined.
506 505
507 506 The debugger interface to %pfile.
508 507 """
509 508 namespaces = [('Locals', self.curframe.f_locals),
510 509 ('Globals', self.curframe.f_globals)]
511 510 self.shell.find_line_magic('pfile')(arg, namespaces=namespaces)
512 511
513 512 def do_pinfo(self, arg):
514 513 """Provide detailed information about an object.
515 514
516 515 The debugger interface to %pinfo, i.e., obj?."""
517 516 namespaces = [('Locals', self.curframe.f_locals),
518 517 ('Globals', self.curframe.f_globals)]
519 518 self.shell.find_line_magic('pinfo')(arg, namespaces=namespaces)
520 519
521 520 def do_pinfo2(self, arg):
522 521 """Provide extra detailed information about an object.
523 522
524 523 The debugger interface to %pinfo2, i.e., obj??."""
525 524 namespaces = [('Locals', self.curframe.f_locals),
526 525 ('Globals', self.curframe.f_globals)]
527 526 self.shell.find_line_magic('pinfo2')(arg, namespaces=namespaces)
528 527
529 528 def do_psource(self, arg):
530 529 """Print (or run through pager) the source code for an object."""
531 530 namespaces = [('Locals', self.curframe.f_locals),
532 531 ('Globals', self.curframe.f_globals)]
533 532 self.shell.find_line_magic('psource')(arg, namespaces=namespaces)
534 533
535 534 def checkline(self, filename, lineno):
536 535 """Check whether specified line seems to be executable.
537 536
538 537 Return `lineno` if it is, 0 if not (e.g. a docstring, comment, blank
539 538 line or EOF). Warning: testing is not comprehensive.
540 539 """
541 540 #######################################################################
542 541 # XXX Hack! Use python-2.5 compatible code for this call, because with
543 542 # all of our changes, we've drifted from the pdb api in 2.6. For now,
544 543 # changing:
545 544 #
546 545 #line = linecache.getline(filename, lineno, self.curframe.f_globals)
547 546 # to:
548 547 #
549 548 line = linecache.getline(filename, lineno)
550 549 #
551 550 # does the trick. But in reality, we need to fix this by reconciling
552 551 # our updates with the new Pdb APIs in Python 2.6.
553 552 #
554 553 # End hack. The rest of this method is copied verbatim from 2.6 pdb.py
555 554 #######################################################################
556 555
557 556 if not line:
558 557 print('End of file', file=self.stdout)
559 558 return 0
560 559 line = line.strip()
561 560 # Don't allow setting breakpoint at a blank line
562 561 if (not line or (line[0] == '#') or
563 562 (line[:3] == '"""') or line[:3] == "'''"):
564 563 print('*** Blank or comment', file=self.stdout)
565 564 return 0
566 565 return lineno
@@ -1,348 +1,348 b''
1 1 # encoding: utf-8
2 2 """
3 3 Paging capabilities for IPython.core
4 4
5 5 Authors:
6 6
7 7 * Brian Granger
8 8 * Fernando Perez
9 9
10 10 Notes
11 11 -----
12 12
13 13 For now this uses ipapi, so it can't be in IPython.utils. If we can get
14 14 rid of that dependency, we could move it there.
15 15 -----
16 16 """
17 17
18 18 #-----------------------------------------------------------------------------
19 19 # Copyright (C) 2008-2011 The IPython Development Team
20 20 #
21 21 # Distributed under the terms of the BSD License. The full license is in
22 22 # the file COPYING, distributed as part of this software.
23 23 #-----------------------------------------------------------------------------
24 24
25 25 #-----------------------------------------------------------------------------
26 26 # Imports
27 27 #-----------------------------------------------------------------------------
28 28 from __future__ import print_function
29 29
30 30 import os
31 31 import re
32 32 import sys
33 33 import tempfile
34 34
35 35 from io import UnsupportedOperation
36 36
37 from IPython.core import ipapi
37 from IPython import get_ipython
38 38 from IPython.core.error import TryNext
39 39 from IPython.utils.data import chop
40 40 from IPython.utils import io
41 41 from IPython.utils.process import system
42 42 from IPython.utils.terminal import get_terminal_size
43 43 from IPython.utils import py3compat
44 44
45 45
46 46 #-----------------------------------------------------------------------------
47 47 # Classes and functions
48 48 #-----------------------------------------------------------------------------
49 49
50 50 esc_re = re.compile(r"(\x1b[^m]+m)")
51 51
52 52 def page_dumb(strng, start=0, screen_lines=25):
53 53 """Very dumb 'pager' in Python, for when nothing else works.
54 54
55 55 Only moves forward, same interface as page(), except for pager_cmd and
56 56 mode."""
57 57
58 58 out_ln = strng.splitlines()[start:]
59 59 screens = chop(out_ln,screen_lines-1)
60 60 if len(screens) == 1:
61 61 print(os.linesep.join(screens[0]), file=io.stdout)
62 62 else:
63 63 last_escape = ""
64 64 for scr in screens[0:-1]:
65 65 hunk = os.linesep.join(scr)
66 66 print(last_escape + hunk, file=io.stdout)
67 67 if not page_more():
68 68 return
69 69 esc_list = esc_re.findall(hunk)
70 70 if len(esc_list) > 0:
71 71 last_escape = esc_list[-1]
72 72 print(last_escape + os.linesep.join(screens[-1]), file=io.stdout)
73 73
74 74 def _detect_screen_size(screen_lines_def):
75 75 """Attempt to work out the number of lines on the screen.
76 76
77 77 This is called by page(). It can raise an error (e.g. when run in the
78 78 test suite), so it's separated out so it can easily be called in a try block.
79 79 """
80 80 TERM = os.environ.get('TERM',None)
81 81 if not((TERM=='xterm' or TERM=='xterm-color') and sys.platform != 'sunos5'):
82 82 # curses causes problems on many terminals other than xterm, and
83 83 # some termios calls lock up on Sun OS5.
84 84 return screen_lines_def
85 85
86 86 try:
87 87 import termios
88 88 import curses
89 89 except ImportError:
90 90 return screen_lines_def
91 91
92 92 # There is a bug in curses, where *sometimes* it fails to properly
93 93 # initialize, and then after the endwin() call is made, the
94 94 # terminal is left in an unusable state. Rather than trying to
95 95 # check everytime for this (by requesting and comparing termios
96 96 # flags each time), we just save the initial terminal state and
97 97 # unconditionally reset it every time. It's cheaper than making
98 98 # the checks.
99 99 term_flags = termios.tcgetattr(sys.stdout)
100 100
101 101 # Curses modifies the stdout buffer size by default, which messes
102 102 # up Python's normal stdout buffering. This would manifest itself
103 103 # to IPython users as delayed printing on stdout after having used
104 104 # the pager.
105 105 #
106 106 # We can prevent this by manually setting the NCURSES_NO_SETBUF
107 107 # environment variable. For more details, see:
108 108 # http://bugs.python.org/issue10144
109 109 NCURSES_NO_SETBUF = os.environ.get('NCURSES_NO_SETBUF', None)
110 110 os.environ['NCURSES_NO_SETBUF'] = ''
111 111
112 112 # Proceed with curses initialization
113 113 try:
114 114 scr = curses.initscr()
115 115 except AttributeError:
116 116 # Curses on Solaris may not be complete, so we can't use it there
117 117 return screen_lines_def
118 118
119 119 screen_lines_real,screen_cols = scr.getmaxyx()
120 120 curses.endwin()
121 121
122 122 # Restore environment
123 123 if NCURSES_NO_SETBUF is None:
124 124 del os.environ['NCURSES_NO_SETBUF']
125 125 else:
126 126 os.environ['NCURSES_NO_SETBUF'] = NCURSES_NO_SETBUF
127 127
128 128 # Restore terminal state in case endwin() didn't.
129 129 termios.tcsetattr(sys.stdout,termios.TCSANOW,term_flags)
130 130 # Now we have what we needed: the screen size in rows/columns
131 131 return screen_lines_real
132 132 #print '***Screen size:',screen_lines_real,'lines x',\
133 133 #screen_cols,'columns.' # dbg
134 134
135 135 def page(strng, start=0, screen_lines=0, pager_cmd=None):
136 136 """Print a string, piping through a pager after a certain length.
137 137
138 138 The screen_lines parameter specifies the number of *usable* lines of your
139 139 terminal screen (total lines minus lines you need to reserve to show other
140 140 information).
141 141
142 142 If you set screen_lines to a number <=0, page() will try to auto-determine
143 143 your screen size and will only use up to (screen_size+screen_lines) for
144 144 printing, paging after that. That is, if you want auto-detection but need
145 145 to reserve the bottom 3 lines of the screen, use screen_lines = -3, and for
146 146 auto-detection without any lines reserved simply use screen_lines = 0.
147 147
148 148 If a string won't fit in the allowed lines, it is sent through the
149 149 specified pager command. If none given, look for PAGER in the environment,
150 150 and ultimately default to less.
151 151
152 152 If no system pager works, the string is sent through a 'dumb pager'
153 153 written in python, very simplistic.
154 154 """
155 155
156 156 # Some routines may auto-compute start offsets incorrectly and pass a
157 157 # negative value. Offset to 0 for robustness.
158 158 start = max(0, start)
159 159
160 160 # first, try the hook
161 ip = ipapi.get()
161 ip = get_ipython()
162 162 if ip:
163 163 try:
164 164 ip.hooks.show_in_pager(strng)
165 165 return
166 166 except TryNext:
167 167 pass
168 168
169 169 # Ugly kludge, but calling curses.initscr() flat out crashes in emacs
170 170 TERM = os.environ.get('TERM','dumb')
171 171 if TERM in ['dumb','emacs'] and os.name != 'nt':
172 172 print(strng)
173 173 return
174 174 # chop off the topmost part of the string we don't want to see
175 175 str_lines = strng.splitlines()[start:]
176 176 str_toprint = os.linesep.join(str_lines)
177 177 num_newlines = len(str_lines)
178 178 len_str = len(str_toprint)
179 179
180 180 # Dumb heuristics to guesstimate number of on-screen lines the string
181 181 # takes. Very basic, but good enough for docstrings in reasonable
182 182 # terminals. If someone later feels like refining it, it's not hard.
183 183 numlines = max(num_newlines,int(len_str/80)+1)
184 184
185 185 screen_lines_def = get_terminal_size()[1]
186 186
187 187 # auto-determine screen size
188 188 if screen_lines <= 0:
189 189 try:
190 190 screen_lines += _detect_screen_size(screen_lines_def)
191 191 except (TypeError, UnsupportedOperation):
192 192 print(str_toprint, file=io.stdout)
193 193 return
194 194
195 195 #print 'numlines',numlines,'screenlines',screen_lines # dbg
196 196 if numlines <= screen_lines :
197 197 #print '*** normal print' # dbg
198 198 print(str_toprint, file=io.stdout)
199 199 else:
200 200 # Try to open pager and default to internal one if that fails.
201 201 # All failure modes are tagged as 'retval=1', to match the return
202 202 # value of a failed system command. If any intermediate attempt
203 203 # sets retval to 1, at the end we resort to our own page_dumb() pager.
204 204 pager_cmd = get_pager_cmd(pager_cmd)
205 205 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
206 206 if os.name == 'nt':
207 207 if pager_cmd.startswith('type'):
208 208 # The default WinXP 'type' command is failing on complex strings.
209 209 retval = 1
210 210 else:
211 211 tmpname = tempfile.mktemp('.txt')
212 212 tmpfile = open(tmpname,'wt')
213 213 tmpfile.write(strng)
214 214 tmpfile.close()
215 215 cmd = "%s < %s" % (pager_cmd,tmpname)
216 216 if os.system(cmd):
217 217 retval = 1
218 218 else:
219 219 retval = None
220 220 os.remove(tmpname)
221 221 else:
222 222 try:
223 223 retval = None
224 224 # if I use popen4, things hang. No idea why.
225 225 #pager,shell_out = os.popen4(pager_cmd)
226 226 pager = os.popen(pager_cmd, 'w')
227 227 try:
228 228 pager_encoding = pager.encoding or sys.stdout.encoding
229 229 pager.write(py3compat.cast_bytes_py2(
230 230 strng, encoding=pager_encoding))
231 231 finally:
232 232 retval = pager.close()
233 233 except IOError as msg: # broken pipe when user quits
234 234 if msg.args == (32, 'Broken pipe'):
235 235 retval = None
236 236 else:
237 237 retval = 1
238 238 except OSError:
239 239 # Other strange problems, sometimes seen in Win2k/cygwin
240 240 retval = 1
241 241 if retval is not None:
242 242 page_dumb(strng,screen_lines=screen_lines)
243 243
244 244
245 245 def page_file(fname, start=0, pager_cmd=None):
246 246 """Page a file, using an optional pager command and starting line.
247 247 """
248 248
249 249 pager_cmd = get_pager_cmd(pager_cmd)
250 250 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
251 251
252 252 try:
253 253 if os.environ['TERM'] in ['emacs','dumb']:
254 254 raise EnvironmentError
255 255 system(pager_cmd + ' ' + fname)
256 256 except:
257 257 try:
258 258 if start > 0:
259 259 start -= 1
260 260 page(open(fname).read(),start)
261 261 except:
262 262 print('Unable to show file',repr(fname))
263 263
264 264
265 265 def get_pager_cmd(pager_cmd=None):
266 266 """Return a pager command.
267 267
268 268 Makes some attempts at finding an OS-correct one.
269 269 """
270 270 if os.name == 'posix':
271 271 default_pager_cmd = 'less -r' # -r for color control sequences
272 272 elif os.name in ['nt','dos']:
273 273 default_pager_cmd = 'type'
274 274
275 275 if pager_cmd is None:
276 276 try:
277 277 pager_cmd = os.environ['PAGER']
278 278 except:
279 279 pager_cmd = default_pager_cmd
280 280 return pager_cmd
281 281
282 282
283 283 def get_pager_start(pager, start):
284 284 """Return the string for paging files with an offset.
285 285
286 286 This is the '+N' argument which less and more (under Unix) accept.
287 287 """
288 288
289 289 if pager in ['less','more']:
290 290 if start:
291 291 start_string = '+' + str(start)
292 292 else:
293 293 start_string = ''
294 294 else:
295 295 start_string = ''
296 296 return start_string
297 297
298 298
299 299 # (X)emacs on win32 doesn't like to be bypassed with msvcrt.getch()
300 300 if os.name == 'nt' and os.environ.get('TERM','dumb') != 'emacs':
301 301 import msvcrt
302 302 def page_more():
303 303 """ Smart pausing between pages
304 304
305 305 @return: True if need print more lines, False if quit
306 306 """
307 307 io.stdout.write('---Return to continue, q to quit--- ')
308 308 ans = msvcrt.getch()
309 309 if ans in ("q", "Q"):
310 310 result = False
311 311 else:
312 312 result = True
313 313 io.stdout.write("\b"*37 + " "*37 + "\b"*37)
314 314 return result
315 315 else:
316 316 def page_more():
317 317 ans = raw_input('---Return to continue, q to quit--- ')
318 318 if ans.lower().startswith('q'):
319 319 return False
320 320 else:
321 321 return True
322 322
323 323
324 324 def snip_print(str,width = 75,print_full = 0,header = ''):
325 325 """Print a string snipping the midsection to fit in width.
326 326
327 327 print_full: mode control:
328 328 - 0: only snip long strings
329 329 - 1: send to page() directly.
330 330 - 2: snip long strings and ask for full length viewing with page()
331 331 Return 1 if snipping was necessary, 0 otherwise."""
332 332
333 333 if print_full == 1:
334 334 page(header+str)
335 335 return 0
336 336
337 337 print(header, end=' ')
338 338 if len(str) < width:
339 339 print(str)
340 340 snip = 0
341 341 else:
342 342 whalf = int((width -5)/2)
343 343 print(str[:whalf] + ' <...> ' + str[-whalf:])
344 344 snip = 1
345 345 if snip and print_full == 2:
346 346 if raw_input(header+' Snipped. View (y/n)? [N]').lower() == 'y':
347 347 page(str)
348 348 return snip
@@ -1,47 +1,47 b''
1 1 """Minimal script to reproduce our nasty reference counting bug.
2 2
3 3 The problem is related to https://github.com/ipython/ipython/issues/141
4 4
5 5 The original fix for that appeared to work, but John D. Hunter found a
6 6 matplotlib example which, when run twice in a row, would break. The problem
7 7 were references held by open figures to internals of Tkinter.
8 8
9 9 This code reproduces the problem that John saw, without matplotlib.
10 10
11 11 This script is meant to be called by other parts of the test suite that call it
12 12 via %run as if it were executed interactively by the user. As of 2011-05-29,
13 13 test_run.py calls it.
14 14 """
15 15
16 16 #-----------------------------------------------------------------------------
17 17 # Module imports
18 18 #-----------------------------------------------------------------------------
19 19 import sys
20 20
21 from IPython.core import ipapi
21 from IPython import get_ipython
22 22
23 23 #-----------------------------------------------------------------------------
24 24 # Globals
25 25 #-----------------------------------------------------------------------------
26 26
27 27 # This needs to be here because nose and other test runners will import
28 28 # this module. Importing this module has potential side effects that we
29 29 # want to prevent.
30 30 if __name__ == '__main__':
31 31
32 ip = ipapi.get()
32 ip = get_ipython()
33 33
34 34 if not '_refbug_cache' in ip.user_ns:
35 35 ip.user_ns['_refbug_cache'] = []
36 36
37 37
38 38 aglobal = 'Hello'
39 39 def f():
40 40 return aglobal
41 41
42 42 cache = ip.user_ns['_refbug_cache']
43 43 cache.append(f)
44 44
45 45 def call_f():
46 46 for func in cache:
47 47 print 'lowercased:',func().lower()
@@ -1,1246 +1,1247 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 ultratb.py -- Spice up your tracebacks!
4 4
5 5 * ColorTB
6 6 I've always found it a bit hard to visually parse tracebacks in Python. The
7 7 ColorTB class is a solution to that problem. It colors the different parts of a
8 8 traceback in a manner similar to what you would expect from a syntax-highlighting
9 9 text editor.
10 10
11 11 Installation instructions for ColorTB:
12 12 import sys,ultratb
13 13 sys.excepthook = ultratb.ColorTB()
14 14
15 15 * VerboseTB
16 16 I've also included a port of Ka-Ping Yee's "cgitb.py" that produces all kinds
17 17 of useful info when a traceback occurs. Ping originally had it spit out HTML
18 18 and intended it for CGI programmers, but why should they have all the fun? I
19 19 altered it to spit out colored text to the terminal. It's a bit overwhelming,
20 20 but kind of neat, and maybe useful for long-running programs that you believe
21 21 are bug-free. If a crash *does* occur in that type of program you want details.
22 22 Give it a shot--you'll love it or you'll hate it.
23 23
24 24 Note:
25 25
26 26 The Verbose mode prints the variables currently visible where the exception
27 27 happened (shortening their strings if too long). This can potentially be
28 28 very slow, if you happen to have a huge data structure whose string
29 29 representation is complex to compute. Your computer may appear to freeze for
30 30 a while with cpu usage at 100%. If this occurs, you can cancel the traceback
31 31 with Ctrl-C (maybe hitting it more than once).
32 32
33 33 If you encounter this kind of situation often, you may want to use the
34 34 Verbose_novars mode instead of the regular Verbose, which avoids formatting
35 35 variables (but otherwise includes the information and context given by
36 36 Verbose).
37 37
38 38
39 39 Installation instructions for ColorTB:
40 40 import sys,ultratb
41 41 sys.excepthook = ultratb.VerboseTB()
42 42
43 43 Note: Much of the code in this module was lifted verbatim from the standard
44 44 library module 'traceback.py' and Ka-Ping Yee's 'cgitb.py'.
45 45
46 46 * Color schemes
47 47 The colors are defined in the class TBTools through the use of the
48 48 ColorSchemeTable class. Currently the following exist:
49 49
50 50 - NoColor: allows all of this module to be used in any terminal (the color
51 51 escapes are just dummy blank strings).
52 52
53 53 - Linux: is meant to look good in a terminal like the Linux console (black
54 54 or very dark background).
55 55
56 56 - LightBG: similar to Linux but swaps dark/light colors to be more readable
57 57 in light background terminals.
58 58
59 59 You can implement other color schemes easily, the syntax is fairly
60 60 self-explanatory. Please send back new schemes you develop to the author for
61 61 possible inclusion in future releases.
62 62
63 63 Inheritance diagram:
64 64
65 65 .. inheritance-diagram:: IPython.core.ultratb
66 66 :parts: 3
67 67 """
68 68
69 69 #*****************************************************************************
70 70 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
71 71 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
72 72 #
73 73 # Distributed under the terms of the BSD License. The full license is in
74 74 # the file COPYING, distributed as part of this software.
75 75 #*****************************************************************************
76 76
77 77 from __future__ import unicode_literals
78 78
79 79 import inspect
80 80 import keyword
81 81 import linecache
82 82 import os
83 83 import pydoc
84 84 import re
85 85 import sys
86 86 import time
87 87 import tokenize
88 88 import traceback
89 89 import types
90 90
91 91 try: # Python 2
92 92 generate_tokens = tokenize.generate_tokens
93 93 except AttributeError: # Python 3
94 94 generate_tokens = tokenize.tokenize
95 95
96 96 # For purposes of monkeypatching inspect to fix a bug in it.
97 97 from inspect import getsourcefile, getfile, getmodule,\
98 98 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
99 99
100 100 # IPython's own modules
101 101 # Modified pdb which doesn't damage IPython's readline handling
102 from IPython.core import debugger, ipapi
102 from IPython import get_ipython
103 from IPython.core import debugger
103 104 from IPython.core.display_trap import DisplayTrap
104 105 from IPython.core.excolors import exception_colors
105 106 from IPython.utils import PyColorize
106 107 from IPython.utils import io
107 108 from IPython.utils import openpy
108 109 from IPython.utils import path as util_path
109 110 from IPython.utils import py3compat
110 111 from IPython.utils import ulinecache
111 112 from IPython.utils.data import uniq_stable
112 113 from IPython.utils.warn import info, error
113 114
114 115 # Globals
115 116 # amount of space to put line numbers before verbose tracebacks
116 117 INDENT_SIZE = 8
117 118
118 119 # Default color scheme. This is used, for example, by the traceback
119 120 # formatter. When running in an actual IPython instance, the user's rc.colors
120 121 # value is used, but havinga module global makes this functionality available
121 122 # to users of ultratb who are NOT running inside ipython.
122 123 DEFAULT_SCHEME = 'NoColor'
123 124
124 125 #---------------------------------------------------------------------------
125 126 # Code begins
126 127
127 128 # Utility functions
128 129 def inspect_error():
129 130 """Print a message about internal inspect errors.
130 131
131 132 These are unfortunately quite common."""
132 133
133 134 error('Internal Python error in the inspect module.\n'
134 135 'Below is the traceback from this internal error.\n')
135 136
136 137 # This function is a monkeypatch we apply to the Python inspect module. We have
137 138 # now found when it's needed (see discussion on issue gh-1456), and we have a
138 139 # test case (IPython.core.tests.test_ultratb.ChangedPyFileTest) that fails if
139 140 # the monkeypatch is not applied. TK, Aug 2012.
140 141 def findsource(object):
141 142 """Return the entire source file and starting line number for an object.
142 143
143 144 The argument may be a module, class, method, function, traceback, frame,
144 145 or code object. The source code is returned as a list of all the lines
145 146 in the file and the line number indexes a line in that list. An IOError
146 147 is raised if the source code cannot be retrieved.
147 148
148 149 FIXED version with which we monkeypatch the stdlib to work around a bug."""
149 150
150 151 file = getsourcefile(object) or getfile(object)
151 152 # If the object is a frame, then trying to get the globals dict from its
152 153 # module won't work. Instead, the frame object itself has the globals
153 154 # dictionary.
154 155 globals_dict = None
155 156 if inspect.isframe(object):
156 157 # XXX: can this ever be false?
157 158 globals_dict = object.f_globals
158 159 else:
159 160 module = getmodule(object, file)
160 161 if module:
161 162 globals_dict = module.__dict__
162 163 lines = linecache.getlines(file, globals_dict)
163 164 if not lines:
164 165 raise IOError('could not get source code')
165 166
166 167 if ismodule(object):
167 168 return lines, 0
168 169
169 170 if isclass(object):
170 171 name = object.__name__
171 172 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
172 173 # make some effort to find the best matching class definition:
173 174 # use the one with the least indentation, which is the one
174 175 # that's most probably not inside a function definition.
175 176 candidates = []
176 177 for i in range(len(lines)):
177 178 match = pat.match(lines[i])
178 179 if match:
179 180 # if it's at toplevel, it's already the best one
180 181 if lines[i][0] == 'c':
181 182 return lines, i
182 183 # else add whitespace to candidate list
183 184 candidates.append((match.group(1), i))
184 185 if candidates:
185 186 # this will sort by whitespace, and by line number,
186 187 # less whitespace first
187 188 candidates.sort()
188 189 return lines, candidates[0][1]
189 190 else:
190 191 raise IOError('could not find class definition')
191 192
192 193 if ismethod(object):
193 194 object = object.im_func
194 195 if isfunction(object):
195 196 object = object.func_code
196 197 if istraceback(object):
197 198 object = object.tb_frame
198 199 if isframe(object):
199 200 object = object.f_code
200 201 if iscode(object):
201 202 if not hasattr(object, 'co_firstlineno'):
202 203 raise IOError('could not find function definition')
203 204 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
204 205 pmatch = pat.match
205 206 # fperez - fix: sometimes, co_firstlineno can give a number larger than
206 207 # the length of lines, which causes an error. Safeguard against that.
207 208 lnum = min(object.co_firstlineno,len(lines))-1
208 209 while lnum > 0:
209 210 if pmatch(lines[lnum]): break
210 211 lnum -= 1
211 212
212 213 return lines, lnum
213 214 raise IOError('could not find code object')
214 215
215 216 # Monkeypatch inspect to apply our bugfix. This code only works with Python >= 2.5
216 217 inspect.findsource = findsource
217 218
218 219 def fix_frame_records_filenames(records):
219 220 """Try to fix the filenames in each record from inspect.getinnerframes().
220 221
221 222 Particularly, modules loaded from within zip files have useless filenames
222 223 attached to their code object, and inspect.getinnerframes() just uses it.
223 224 """
224 225 fixed_records = []
225 226 for frame, filename, line_no, func_name, lines, index in records:
226 227 # Look inside the frame's globals dictionary for __file__, which should
227 228 # be better.
228 229 better_fn = frame.f_globals.get('__file__', None)
229 230 if isinstance(better_fn, str):
230 231 # Check the type just in case someone did something weird with
231 232 # __file__. It might also be None if the error occurred during
232 233 # import.
233 234 filename = better_fn
234 235 fixed_records.append((frame, filename, line_no, func_name, lines, index))
235 236 return fixed_records
236 237
237 238
238 239 def _fixed_getinnerframes(etb, context=1,tb_offset=0):
239 240 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
240 241
241 242 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
242 243
243 244 # If the error is at the console, don't build any context, since it would
244 245 # otherwise produce 5 blank lines printed out (there is no file at the
245 246 # console)
246 247 rec_check = records[tb_offset:]
247 248 try:
248 249 rname = rec_check[0][1]
249 250 if rname == '<ipython console>' or rname.endswith('<string>'):
250 251 return rec_check
251 252 except IndexError:
252 253 pass
253 254
254 255 aux = traceback.extract_tb(etb)
255 256 assert len(records) == len(aux)
256 257 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
257 258 maybeStart = lnum-1 - context//2
258 259 start = max(maybeStart, 0)
259 260 end = start + context
260 261 lines = ulinecache.getlines(file)[start:end]
261 262 buf = list(records[i])
262 263 buf[LNUM_POS] = lnum
263 264 buf[INDEX_POS] = lnum - 1 - start
264 265 buf[LINES_POS] = lines
265 266 records[i] = tuple(buf)
266 267 return records[tb_offset:]
267 268
268 269 # Helper function -- largely belongs to VerboseTB, but we need the same
269 270 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
270 271 # can be recognized properly by ipython.el's py-traceback-line-re
271 272 # (SyntaxErrors have to be treated specially because they have no traceback)
272 273
273 274 _parser = PyColorize.Parser()
274 275
275 276 def _format_traceback_lines(lnum, index, lines, Colors, lvals=None,scheme=None):
276 277 numbers_width = INDENT_SIZE - 1
277 278 res = []
278 279 i = lnum - index
279 280
280 281 # This lets us get fully syntax-highlighted tracebacks.
281 282 if scheme is None:
282 ipinst = ipapi.get()
283 ipinst = get_ipython()
283 284 if ipinst is not None:
284 285 scheme = ipinst.colors
285 286 else:
286 287 scheme = DEFAULT_SCHEME
287 288
288 289 _line_format = _parser.format2
289 290
290 291 for line in lines:
291 292 line = py3compat.cast_unicode(line)
292 293
293 294 new_line, err = _line_format(line, 'str', scheme)
294 295 if not err: line = new_line
295 296
296 297 if i == lnum:
297 298 # This is the line with the error
298 299 pad = numbers_width - len(str(i))
299 300 if pad >= 3:
300 301 marker = '-'*(pad-3) + '-> '
301 302 elif pad == 2:
302 303 marker = '> '
303 304 elif pad == 1:
304 305 marker = '>'
305 306 else:
306 307 marker = ''
307 308 num = marker + str(i)
308 309 line = '%s%s%s %s%s' %(Colors.linenoEm, num,
309 310 Colors.line, line, Colors.Normal)
310 311 else:
311 312 num = '%*s' % (numbers_width,i)
312 313 line = '%s%s%s %s' %(Colors.lineno, num,
313 314 Colors.Normal, line)
314 315
315 316 res.append(line)
316 317 if lvals and i == lnum:
317 318 res.append(lvals + '\n')
318 319 i = i + 1
319 320 return res
320 321
321 322
322 323 #---------------------------------------------------------------------------
323 324 # Module classes
324 325 class TBTools(object):
325 326 """Basic tools used by all traceback printer classes."""
326 327
327 328 # Number of frames to skip when reporting tracebacks
328 329 tb_offset = 0
329 330
330 331 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None):
331 332 # Whether to call the interactive pdb debugger after printing
332 333 # tracebacks or not
333 334 self.call_pdb = call_pdb
334 335
335 336 # Output stream to write to. Note that we store the original value in
336 337 # a private attribute and then make the public ostream a property, so
337 338 # that we can delay accessing io.stdout until runtime. The way
338 339 # things are written now, the io.stdout object is dynamically managed
339 340 # so a reference to it should NEVER be stored statically. This
340 341 # property approach confines this detail to a single location, and all
341 342 # subclasses can simply access self.ostream for writing.
342 343 self._ostream = ostream
343 344
344 345 # Create color table
345 346 self.color_scheme_table = exception_colors()
346 347
347 348 self.set_colors(color_scheme)
348 349 self.old_scheme = color_scheme # save initial value for toggles
349 350
350 351 if call_pdb:
351 352 self.pdb = debugger.Pdb(self.color_scheme_table.active_scheme_name)
352 353 else:
353 354 self.pdb = None
354 355
355 356 def _get_ostream(self):
356 357 """Output stream that exceptions are written to.
357 358
358 359 Valid values are:
359 360
360 361 - None: the default, which means that IPython will dynamically resolve
361 362 to io.stdout. This ensures compatibility with most tools, including
362 363 Windows (where plain stdout doesn't recognize ANSI escapes).
363 364
364 365 - Any object with 'write' and 'flush' attributes.
365 366 """
366 367 return io.stdout if self._ostream is None else self._ostream
367 368
368 369 def _set_ostream(self, val):
369 370 assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush'))
370 371 self._ostream = val
371 372
372 373 ostream = property(_get_ostream, _set_ostream)
373 374
374 375 def set_colors(self,*args,**kw):
375 376 """Shorthand access to the color table scheme selector method."""
376 377
377 378 # Set own color table
378 379 self.color_scheme_table.set_active_scheme(*args,**kw)
379 380 # for convenience, set Colors to the active scheme
380 381 self.Colors = self.color_scheme_table.active_colors
381 382 # Also set colors of debugger
382 383 if hasattr(self,'pdb') and self.pdb is not None:
383 384 self.pdb.set_colors(*args,**kw)
384 385
385 386 def color_toggle(self):
386 387 """Toggle between the currently active color scheme and NoColor."""
387 388
388 389 if self.color_scheme_table.active_scheme_name == 'NoColor':
389 390 self.color_scheme_table.set_active_scheme(self.old_scheme)
390 391 self.Colors = self.color_scheme_table.active_colors
391 392 else:
392 393 self.old_scheme = self.color_scheme_table.active_scheme_name
393 394 self.color_scheme_table.set_active_scheme('NoColor')
394 395 self.Colors = self.color_scheme_table.active_colors
395 396
396 397 def stb2text(self, stb):
397 398 """Convert a structured traceback (a list) to a string."""
398 399 return '\n'.join(stb)
399 400
400 401 def text(self, etype, value, tb, tb_offset=None, context=5):
401 402 """Return formatted traceback.
402 403
403 404 Subclasses may override this if they add extra arguments.
404 405 """
405 406 tb_list = self.structured_traceback(etype, value, tb,
406 407 tb_offset, context)
407 408 return self.stb2text(tb_list)
408 409
409 410 def structured_traceback(self, etype, evalue, tb, tb_offset=None,
410 411 context=5, mode=None):
411 412 """Return a list of traceback frames.
412 413
413 414 Must be implemented by each class.
414 415 """
415 416 raise NotImplementedError()
416 417
417 418
418 419 #---------------------------------------------------------------------------
419 420 class ListTB(TBTools):
420 421 """Print traceback information from a traceback list, with optional color.
421 422
422 423 Calling requires 3 arguments: (etype, evalue, elist)
423 424 as would be obtained by::
424 425
425 426 etype, evalue, tb = sys.exc_info()
426 427 if tb:
427 428 elist = traceback.extract_tb(tb)
428 429 else:
429 430 elist = None
430 431
431 432 It can thus be used by programs which need to process the traceback before
432 433 printing (such as console replacements based on the code module from the
433 434 standard library).
434 435
435 436 Because they are meant to be called without a full traceback (only a
436 437 list), instances of this class can't call the interactive pdb debugger."""
437 438
438 439 def __init__(self,color_scheme = 'NoColor', call_pdb=False, ostream=None):
439 440 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
440 441 ostream=ostream)
441 442
442 443 def __call__(self, etype, value, elist):
443 444 self.ostream.flush()
444 445 self.ostream.write(self.text(etype, value, elist))
445 446 self.ostream.write('\n')
446 447
447 448 def structured_traceback(self, etype, value, elist, tb_offset=None,
448 449 context=5):
449 450 """Return a color formatted string with the traceback info.
450 451
451 452 Parameters
452 453 ----------
453 454 etype : exception type
454 455 Type of the exception raised.
455 456
456 457 value : object
457 458 Data stored in the exception
458 459
459 460 elist : list
460 461 List of frames, see class docstring for details.
461 462
462 463 tb_offset : int, optional
463 464 Number of frames in the traceback to skip. If not given, the
464 465 instance value is used (set in constructor).
465 466
466 467 context : int, optional
467 468 Number of lines of context information to print.
468 469
469 470 Returns
470 471 -------
471 472 String with formatted exception.
472 473 """
473 474 tb_offset = self.tb_offset if tb_offset is None else tb_offset
474 475 Colors = self.Colors
475 476 out_list = []
476 477 if elist:
477 478
478 479 if tb_offset and len(elist) > tb_offset:
479 480 elist = elist[tb_offset:]
480 481
481 482 out_list.append('Traceback %s(most recent call last)%s:' %
482 483 (Colors.normalEm, Colors.Normal) + '\n')
483 484 out_list.extend(self._format_list(elist))
484 485 # The exception info should be a single entry in the list.
485 486 lines = ''.join(self._format_exception_only(etype, value))
486 487 out_list.append(lines)
487 488
488 489 # Note: this code originally read:
489 490
490 491 ## for line in lines[:-1]:
491 492 ## out_list.append(" "+line)
492 493 ## out_list.append(lines[-1])
493 494
494 495 # This means it was indenting everything but the last line by a little
495 496 # bit. I've disabled this for now, but if we see ugliness somewhre we
496 497 # can restore it.
497 498
498 499 return out_list
499 500
500 501 def _format_list(self, extracted_list):
501 502 """Format a list of traceback entry tuples for printing.
502 503
503 504 Given a list of tuples as returned by extract_tb() or
504 505 extract_stack(), return a list of strings ready for printing.
505 506 Each string in the resulting list corresponds to the item with the
506 507 same index in the argument list. Each string ends in a newline;
507 508 the strings may contain internal newlines as well, for those items
508 509 whose source text line is not None.
509 510
510 511 Lifted almost verbatim from traceback.py
511 512 """
512 513
513 514 Colors = self.Colors
514 515 list = []
515 516 for filename, lineno, name, line in extracted_list[:-1]:
516 517 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
517 518 (Colors.filename, filename, Colors.Normal,
518 519 Colors.lineno, lineno, Colors.Normal,
519 520 Colors.name, name, Colors.Normal)
520 521 if line:
521 522 item += ' %s\n' % line.strip()
522 523 list.append(item)
523 524 # Emphasize the last entry
524 525 filename, lineno, name, line = extracted_list[-1]
525 526 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
526 527 (Colors.normalEm,
527 528 Colors.filenameEm, filename, Colors.normalEm,
528 529 Colors.linenoEm, lineno, Colors.normalEm,
529 530 Colors.nameEm, name, Colors.normalEm,
530 531 Colors.Normal)
531 532 if line:
532 533 item += '%s %s%s\n' % (Colors.line, line.strip(),
533 534 Colors.Normal)
534 535 list.append(item)
535 536 #from pprint import pformat; print 'LISTTB', pformat(list) # dbg
536 537 return list
537 538
538 539 def _format_exception_only(self, etype, value):
539 540 """Format the exception part of a traceback.
540 541
541 542 The arguments are the exception type and value such as given by
542 543 sys.exc_info()[:2]. The return value is a list of strings, each ending
543 544 in a newline. Normally, the list contains a single string; however,
544 545 for SyntaxError exceptions, it contains several lines that (when
545 546 printed) display detailed information about where the syntax error
546 547 occurred. The message indicating which exception occurred is the
547 548 always last string in the list.
548 549
549 550 Also lifted nearly verbatim from traceback.py
550 551 """
551 552 have_filedata = False
552 553 Colors = self.Colors
553 554 list = []
554 555 stype = Colors.excName + etype.__name__ + Colors.Normal
555 556 if value is None:
556 557 # Not sure if this can still happen in Python 2.6 and above
557 558 list.append( py3compat.cast_unicode(stype) + '\n')
558 559 else:
559 560 if issubclass(etype, SyntaxError):
560 561 have_filedata = True
561 562 #print 'filename is',filename # dbg
562 563 if not value.filename: value.filename = "<string>"
563 564 if value.lineno:
564 565 lineno = value.lineno
565 566 textline = ulinecache.getline(value.filename, value.lineno)
566 567 else:
567 568 lineno = 'unknown'
568 569 textline = ''
569 570 list.append('%s File %s"%s"%s, line %s%s%s\n' % \
570 571 (Colors.normalEm,
571 572 Colors.filenameEm, py3compat.cast_unicode(value.filename), Colors.normalEm,
572 573 Colors.linenoEm, lineno, Colors.Normal ))
573 574 if textline == '':
574 575 textline = py3compat.cast_unicode(value.text, "utf-8")
575 576
576 577 if textline is not None:
577 578 i = 0
578 579 while i < len(textline) and textline[i].isspace():
579 580 i += 1
580 581 list.append('%s %s%s\n' % (Colors.line,
581 582 textline.strip(),
582 583 Colors.Normal))
583 584 if value.offset is not None:
584 585 s = ' '
585 586 for c in textline[i:value.offset-1]:
586 587 if c.isspace():
587 588 s += c
588 589 else:
589 590 s += ' '
590 591 list.append('%s%s^%s\n' % (Colors.caret, s,
591 592 Colors.Normal) )
592 593
593 594 try:
594 595 s = value.msg
595 596 except Exception:
596 597 s = self._some_str(value)
597 598 if s:
598 599 list.append('%s%s:%s %s\n' % (str(stype), Colors.excName,
599 600 Colors.Normal, s))
600 601 else:
601 602 list.append('%s\n' % str(stype))
602 603
603 604 # sync with user hooks
604 605 if have_filedata:
605 ipinst = ipapi.get()
606 ipinst = get_ipython()
606 607 if ipinst is not None:
607 608 ipinst.hooks.synchronize_with_editor(value.filename, value.lineno, 0)
608 609
609 610 return list
610 611
611 612 def get_exception_only(self, etype, value):
612 613 """Only print the exception type and message, without a traceback.
613 614
614 615 Parameters
615 616 ----------
616 617 etype : exception type
617 618 value : exception value
618 619 """
619 620 return ListTB.structured_traceback(self, etype, value, [])
620 621
621 622
622 623 def show_exception_only(self, etype, evalue):
623 624 """Only print the exception type and message, without a traceback.
624 625
625 626 Parameters
626 627 ----------
627 628 etype : exception type
628 629 value : exception value
629 630 """
630 631 # This method needs to use __call__ from *this* class, not the one from
631 632 # a subclass whose signature or behavior may be different
632 633 ostream = self.ostream
633 634 ostream.flush()
634 635 ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
635 636 ostream.flush()
636 637
637 638 def _some_str(self, value):
638 639 # Lifted from traceback.py
639 640 try:
640 641 return str(value)
641 642 except:
642 643 return '<unprintable %s object>' % type(value).__name__
643 644
644 645 #----------------------------------------------------------------------------
645 646 class VerboseTB(TBTools):
646 647 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
647 648 of HTML. Requires inspect and pydoc. Crazy, man.
648 649
649 650 Modified version which optionally strips the topmost entries from the
650 651 traceback, to be used with alternate interpreters (because their own code
651 652 would appear in the traceback)."""
652 653
653 654 def __init__(self,color_scheme = 'Linux', call_pdb=False, ostream=None,
654 655 tb_offset=0, long_header=False, include_vars=True,
655 656 check_cache=None):
656 657 """Specify traceback offset, headers and color scheme.
657 658
658 659 Define how many frames to drop from the tracebacks. Calling it with
659 660 tb_offset=1 allows use of this handler in interpreters which will have
660 661 their own code at the top of the traceback (VerboseTB will first
661 662 remove that frame before printing the traceback info)."""
662 663 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
663 664 ostream=ostream)
664 665 self.tb_offset = tb_offset
665 666 self.long_header = long_header
666 667 self.include_vars = include_vars
667 668 # By default we use linecache.checkcache, but the user can provide a
668 669 # different check_cache implementation. This is used by the IPython
669 670 # kernel to provide tracebacks for interactive code that is cached,
670 671 # by a compiler instance that flushes the linecache but preserves its
671 672 # own code cache.
672 673 if check_cache is None:
673 674 check_cache = linecache.checkcache
674 675 self.check_cache = check_cache
675 676
676 677 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
677 678 context=5):
678 679 """Return a nice text document describing the traceback."""
679 680
680 681 tb_offset = self.tb_offset if tb_offset is None else tb_offset
681 682
682 683 # some locals
683 684 try:
684 685 etype = etype.__name__
685 686 except AttributeError:
686 687 pass
687 688 Colors = self.Colors # just a shorthand + quicker name lookup
688 689 ColorsNormal = Colors.Normal # used a lot
689 690 col_scheme = self.color_scheme_table.active_scheme_name
690 691 indent = ' '*INDENT_SIZE
691 692 em_normal = '%s\n%s%s' % (Colors.valEm, indent,ColorsNormal)
692 693 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
693 694 exc = '%s%s%s' % (Colors.excName,etype,ColorsNormal)
694 695
695 696 # some internal-use functions
696 697 def text_repr(value):
697 698 """Hopefully pretty robust repr equivalent."""
698 699 # this is pretty horrible but should always return *something*
699 700 try:
700 701 return pydoc.text.repr(value)
701 702 except KeyboardInterrupt:
702 703 raise
703 704 except:
704 705 try:
705 706 return repr(value)
706 707 except KeyboardInterrupt:
707 708 raise
708 709 except:
709 710 try:
710 711 # all still in an except block so we catch
711 712 # getattr raising
712 713 name = getattr(value, '__name__', None)
713 714 if name:
714 715 # ick, recursion
715 716 return text_repr(name)
716 717 klass = getattr(value, '__class__', None)
717 718 if klass:
718 719 return '%s instance' % text_repr(klass)
719 720 except KeyboardInterrupt:
720 721 raise
721 722 except:
722 723 return 'UNRECOVERABLE REPR FAILURE'
723 724 def eqrepr(value, repr=text_repr): return '=%s' % repr(value)
724 725 def nullrepr(value, repr=text_repr): return ''
725 726
726 727 # meat of the code begins
727 728 try:
728 729 etype = etype.__name__
729 730 except AttributeError:
730 731 pass
731 732
732 733 if self.long_header:
733 734 # Header with the exception type, python version, and date
734 735 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
735 736 date = time.ctime(time.time())
736 737
737 738 head = '%s%s%s\n%s%s%s\n%s' % (Colors.topline, '-'*75, ColorsNormal,
738 739 exc, ' '*(75-len(str(etype))-len(pyver)),
739 740 pyver, date.rjust(75) )
740 741 head += "\nA problem occured executing Python code. Here is the sequence of function"\
741 742 "\ncalls leading up to the error, with the most recent (innermost) call last."
742 743 else:
743 744 # Simplified header
744 745 head = '%s%s%s\n%s%s' % (Colors.topline, '-'*75, ColorsNormal,exc,
745 746 'Traceback (most recent call last)'.\
746 747 rjust(75 - len(str(etype)) ) )
747 748 frames = []
748 749 # Flush cache before calling inspect. This helps alleviate some of the
749 750 # problems with python 2.3's inspect.py.
750 751 ##self.check_cache()
751 752 # Drop topmost frames if requested
752 753 try:
753 754 # Try the default getinnerframes and Alex's: Alex's fixes some
754 755 # problems, but it generates empty tracebacks for console errors
755 756 # (5 blanks lines) where none should be returned.
756 757 #records = inspect.getinnerframes(etb, context)[tb_offset:]
757 758 #print 'python records:', records # dbg
758 759 records = _fixed_getinnerframes(etb, context, tb_offset)
759 760 #print 'alex records:', records # dbg
760 761 except:
761 762
762 763 # FIXME: I've been getting many crash reports from python 2.3
763 764 # users, traceable to inspect.py. If I can find a small test-case
764 765 # to reproduce this, I should either write a better workaround or
765 766 # file a bug report against inspect (if that's the real problem).
766 767 # So far, I haven't been able to find an isolated example to
767 768 # reproduce the problem.
768 769 inspect_error()
769 770 traceback.print_exc(file=self.ostream)
770 771 info('\nUnfortunately, your original traceback can not be constructed.\n')
771 772 return ''
772 773
773 774 # build some color string templates outside these nested loops
774 775 tpl_link = '%s%%s%s' % (Colors.filenameEm,ColorsNormal)
775 776 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
776 777 ColorsNormal)
777 778 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
778 779 (Colors.vName, Colors.valEm, ColorsNormal)
779 780 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
780 781 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
781 782 Colors.vName, ColorsNormal)
782 783 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
783 784 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
784 785 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm,Colors.line,
785 786 ColorsNormal)
786 787
787 788 # now, loop over all records printing context and info
788 789 abspath = os.path.abspath
789 790 for frame, file, lnum, func, lines, index in records:
790 791 #print '*** record:',file,lnum,func,lines,index # dbg
791 792 if not file:
792 793 file = '?'
793 794 elif not(file.startswith(str("<")) and file.endswith(str(">"))):
794 795 # Guess that filenames like <string> aren't real filenames, so
795 796 # don't call abspath on them.
796 797 try:
797 798 file = abspath(file)
798 799 except OSError:
799 800 # Not sure if this can still happen: abspath now works with
800 801 # file names like <string>
801 802 pass
802 803 file = py3compat.cast_unicode(file, util_path.fs_encoding)
803 804 link = tpl_link % file
804 805 args, varargs, varkw, locals = inspect.getargvalues(frame)
805 806
806 807 if func == '?':
807 808 call = ''
808 809 else:
809 810 # Decide whether to include variable details or not
810 811 var_repr = self.include_vars and eqrepr or nullrepr
811 812 try:
812 813 call = tpl_call % (func,inspect.formatargvalues(args,
813 814 varargs, varkw,
814 815 locals,formatvalue=var_repr))
815 816 except KeyError:
816 817 # This happens in situations like errors inside generator
817 818 # expressions, where local variables are listed in the
818 819 # line, but can't be extracted from the frame. I'm not
819 820 # 100% sure this isn't actually a bug in inspect itself,
820 821 # but since there's no info for us to compute with, the
821 822 # best we can do is report the failure and move on. Here
822 823 # we must *not* call any traceback construction again,
823 824 # because that would mess up use of %debug later on. So we
824 825 # simply report the failure and move on. The only
825 826 # limitation will be that this frame won't have locals
826 827 # listed in the call signature. Quite subtle problem...
827 828 # I can't think of a good way to validate this in a unit
828 829 # test, but running a script consisting of:
829 830 # dict( (k,v.strip()) for (k,v) in range(10) )
830 831 # will illustrate the error, if this exception catch is
831 832 # disabled.
832 833 call = tpl_call_fail % func
833 834
834 835 # Don't attempt to tokenize binary files.
835 836 if file.endswith(('.so', '.pyd', '.dll')):
836 837 frames.append('%s %s\n' % (link,call))
837 838 continue
838 839 elif file.endswith(('.pyc','.pyo')):
839 840 # Look up the corresponding source file.
840 841 file = openpy.source_from_cache(file)
841 842
842 843 def linereader(file=file, lnum=[lnum], getline=ulinecache.getline):
843 844 line = getline(file, lnum[0])
844 845 lnum[0] += 1
845 846 return line
846 847
847 848 # Build the list of names on this line of code where the exception
848 849 # occurred.
849 850 try:
850 851 names = []
851 852 name_cont = False
852 853
853 854 for token_type, token, start, end, line in generate_tokens(linereader):
854 855 # build composite names
855 856 if token_type == tokenize.NAME and token not in keyword.kwlist:
856 857 if name_cont:
857 858 # Continuation of a dotted name
858 859 try:
859 860 names[-1].append(token)
860 861 except IndexError:
861 862 names.append([token])
862 863 name_cont = False
863 864 else:
864 865 # Regular new names. We append everything, the caller
865 866 # will be responsible for pruning the list later. It's
866 867 # very tricky to try to prune as we go, b/c composite
867 868 # names can fool us. The pruning at the end is easy
868 869 # to do (or the caller can print a list with repeated
869 870 # names if so desired.
870 871 names.append([token])
871 872 elif token == '.':
872 873 name_cont = True
873 874 elif token_type == tokenize.NEWLINE:
874 875 break
875 876
876 877 except (IndexError, UnicodeDecodeError):
877 878 # signals exit of tokenizer
878 879 pass
879 880 except tokenize.TokenError as msg:
880 881 _m = ("An unexpected error occurred while tokenizing input\n"
881 882 "The following traceback may be corrupted or invalid\n"
882 883 "The error message is: %s\n" % msg)
883 884 error(_m)
884 885
885 886 # Join composite names (e.g. "dict.fromkeys")
886 887 names = ['.'.join(n) for n in names]
887 888 # prune names list of duplicates, but keep the right order
888 889 unique_names = uniq_stable(names)
889 890
890 891 # Start loop over vars
891 892 lvals = []
892 893 if self.include_vars:
893 894 for name_full in unique_names:
894 895 name_base = name_full.split('.',1)[0]
895 896 if name_base in frame.f_code.co_varnames:
896 897 if name_base in locals:
897 898 try:
898 899 value = repr(eval(name_full,locals))
899 900 except:
900 901 value = undefined
901 902 else:
902 903 value = undefined
903 904 name = tpl_local_var % name_full
904 905 else:
905 906 if name_base in frame.f_globals:
906 907 try:
907 908 value = repr(eval(name_full,frame.f_globals))
908 909 except:
909 910 value = undefined
910 911 else:
911 912 value = undefined
912 913 name = tpl_global_var % name_full
913 914 lvals.append(tpl_name_val % (name,value))
914 915 if lvals:
915 916 lvals = '%s%s' % (indent,em_normal.join(lvals))
916 917 else:
917 918 lvals = ''
918 919
919 920 level = '%s %s\n' % (link,call)
920 921
921 922 if index is None:
922 923 frames.append(level)
923 924 else:
924 925 frames.append('%s%s' % (level,''.join(
925 926 _format_traceback_lines(lnum,index,lines,Colors,lvals,
926 927 col_scheme))))
927 928
928 929 # Get (safely) a string form of the exception info
929 930 try:
930 931 etype_str,evalue_str = map(str,(etype,evalue))
931 932 except:
932 933 # User exception is improperly defined.
933 934 etype,evalue = str,sys.exc_info()[:2]
934 935 etype_str,evalue_str = map(str,(etype,evalue))
935 936 # ... and format it
936 937 exception = ['%s%s%s: %s' % (Colors.excName, etype_str,
937 938 ColorsNormal, py3compat.cast_unicode(evalue_str))]
938 939 if (not py3compat.PY3) and type(evalue) is types.InstanceType:
939 940 try:
940 941 names = [w for w in dir(evalue) if isinstance(w, basestring)]
941 942 except:
942 943 # Every now and then, an object with funny inernals blows up
943 944 # when dir() is called on it. We do the best we can to report
944 945 # the problem and continue
945 946 _m = '%sException reporting error (object with broken dir())%s:'
946 947 exception.append(_m % (Colors.excName,ColorsNormal))
947 948 etype_str,evalue_str = map(str,sys.exc_info()[:2])
948 949 exception.append('%s%s%s: %s' % (Colors.excName,etype_str,
949 950 ColorsNormal, py3compat.cast_unicode(evalue_str)))
950 951 names = []
951 952 for name in names:
952 953 value = text_repr(getattr(evalue, name))
953 954 exception.append('\n%s%s = %s' % (indent, name, value))
954 955
955 956 # vds: >>
956 957 if records:
957 958 filepath, lnum = records[-1][1:3]
958 959 #print "file:", str(file), "linenb", str(lnum) # dbg
959 960 filepath = os.path.abspath(filepath)
960 ipinst = ipapi.get()
961 ipinst = get_ipython()
961 962 if ipinst is not None:
962 963 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
963 964 # vds: <<
964 965
965 966 # return all our info assembled as a single string
966 967 # return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) )
967 968 return [head] + frames + [''.join(exception[0])]
968 969
969 970 def debugger(self,force=False):
970 971 """Call up the pdb debugger if desired, always clean up the tb
971 972 reference.
972 973
973 974 Keywords:
974 975
975 976 - force(False): by default, this routine checks the instance call_pdb
976 977 flag and does not actually invoke the debugger if the flag is false.
977 978 The 'force' option forces the debugger to activate even if the flag
978 979 is false.
979 980
980 981 If the call_pdb flag is set, the pdb interactive debugger is
981 982 invoked. In all cases, the self.tb reference to the current traceback
982 983 is deleted to prevent lingering references which hamper memory
983 984 management.
984 985
985 986 Note that each call to pdb() does an 'import readline', so if your app
986 987 requires a special setup for the readline completers, you'll have to
987 988 fix that by hand after invoking the exception handler."""
988 989
989 990 if force or self.call_pdb:
990 991 if self.pdb is None:
991 992 self.pdb = debugger.Pdb(
992 993 self.color_scheme_table.active_scheme_name)
993 994 # the system displayhook may have changed, restore the original
994 995 # for pdb
995 996 display_trap = DisplayTrap(hook=sys.__displayhook__)
996 997 with display_trap:
997 998 self.pdb.reset()
998 999 # Find the right frame so we don't pop up inside ipython itself
999 1000 if hasattr(self,'tb') and self.tb is not None:
1000 1001 etb = self.tb
1001 1002 else:
1002 1003 etb = self.tb = sys.last_traceback
1003 1004 while self.tb is not None and self.tb.tb_next is not None:
1004 1005 self.tb = self.tb.tb_next
1005 1006 if etb and etb.tb_next:
1006 1007 etb = etb.tb_next
1007 1008 self.pdb.botframe = etb.tb_frame
1008 1009 self.pdb.interaction(self.tb.tb_frame, self.tb)
1009 1010
1010 1011 if hasattr(self,'tb'):
1011 1012 del self.tb
1012 1013
1013 1014 def handler(self, info=None):
1014 1015 (etype, evalue, etb) = info or sys.exc_info()
1015 1016 self.tb = etb
1016 1017 ostream = self.ostream
1017 1018 ostream.flush()
1018 1019 ostream.write(self.text(etype, evalue, etb))
1019 1020 ostream.write('\n')
1020 1021 ostream.flush()
1021 1022
1022 1023 # Changed so an instance can just be called as VerboseTB_inst() and print
1023 1024 # out the right info on its own.
1024 1025 def __call__(self, etype=None, evalue=None, etb=None):
1025 1026 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
1026 1027 if etb is None:
1027 1028 self.handler()
1028 1029 else:
1029 1030 self.handler((etype, evalue, etb))
1030 1031 try:
1031 1032 self.debugger()
1032 1033 except KeyboardInterrupt:
1033 1034 print "\nKeyboardInterrupt"
1034 1035
1035 1036 #----------------------------------------------------------------------------
1036 1037 class FormattedTB(VerboseTB, ListTB):
1037 1038 """Subclass ListTB but allow calling with a traceback.
1038 1039
1039 1040 It can thus be used as a sys.excepthook for Python > 2.1.
1040 1041
1041 1042 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
1042 1043
1043 1044 Allows a tb_offset to be specified. This is useful for situations where
1044 1045 one needs to remove a number of topmost frames from the traceback (such as
1045 1046 occurs with python programs that themselves execute other python code,
1046 1047 like Python shells). """
1047 1048
1048 1049 def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False,
1049 1050 ostream=None,
1050 1051 tb_offset=0, long_header=False, include_vars=False,
1051 1052 check_cache=None):
1052 1053
1053 1054 # NEVER change the order of this list. Put new modes at the end:
1054 1055 self.valid_modes = ['Plain','Context','Verbose']
1055 1056 self.verbose_modes = self.valid_modes[1:3]
1056 1057
1057 1058 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
1058 1059 ostream=ostream, tb_offset=tb_offset,
1059 1060 long_header=long_header, include_vars=include_vars,
1060 1061 check_cache=check_cache)
1061 1062
1062 1063 # Different types of tracebacks are joined with different separators to
1063 1064 # form a single string. They are taken from this dict
1064 1065 self._join_chars = dict(Plain='', Context='\n', Verbose='\n')
1065 1066 # set_mode also sets the tb_join_char attribute
1066 1067 self.set_mode(mode)
1067 1068
1068 1069 def _extract_tb(self,tb):
1069 1070 if tb:
1070 1071 return traceback.extract_tb(tb)
1071 1072 else:
1072 1073 return None
1073 1074
1074 1075 def structured_traceback(self, etype, value, tb, tb_offset=None, context=5):
1075 1076 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1076 1077 mode = self.mode
1077 1078 if mode in self.verbose_modes:
1078 1079 # Verbose modes need a full traceback
1079 1080 return VerboseTB.structured_traceback(
1080 1081 self, etype, value, tb, tb_offset, context
1081 1082 )
1082 1083 else:
1083 1084 # We must check the source cache because otherwise we can print
1084 1085 # out-of-date source code.
1085 1086 self.check_cache()
1086 1087 # Now we can extract and format the exception
1087 1088 elist = self._extract_tb(tb)
1088 1089 return ListTB.structured_traceback(
1089 1090 self, etype, value, elist, tb_offset, context
1090 1091 )
1091 1092
1092 1093 def stb2text(self, stb):
1093 1094 """Convert a structured traceback (a list) to a string."""
1094 1095 return self.tb_join_char.join(stb)
1095 1096
1096 1097
1097 1098 def set_mode(self,mode=None):
1098 1099 """Switch to the desired mode.
1099 1100
1100 1101 If mode is not specified, cycles through the available modes."""
1101 1102
1102 1103 if not mode:
1103 1104 new_idx = ( self.valid_modes.index(self.mode) + 1 ) % \
1104 1105 len(self.valid_modes)
1105 1106 self.mode = self.valid_modes[new_idx]
1106 1107 elif mode not in self.valid_modes:
1107 1108 raise ValueError('Unrecognized mode in FormattedTB: <'+mode+'>\n'
1108 1109 'Valid modes: '+str(self.valid_modes))
1109 1110 else:
1110 1111 self.mode = mode
1111 1112 # include variable details only in 'Verbose' mode
1112 1113 self.include_vars = (self.mode == self.valid_modes[2])
1113 1114 # Set the join character for generating text tracebacks
1114 1115 self.tb_join_char = self._join_chars[self.mode]
1115 1116
1116 1117 # some convenient shorcuts
1117 1118 def plain(self):
1118 1119 self.set_mode(self.valid_modes[0])
1119 1120
1120 1121 def context(self):
1121 1122 self.set_mode(self.valid_modes[1])
1122 1123
1123 1124 def verbose(self):
1124 1125 self.set_mode(self.valid_modes[2])
1125 1126
1126 1127 #----------------------------------------------------------------------------
1127 1128 class AutoFormattedTB(FormattedTB):
1128 1129 """A traceback printer which can be called on the fly.
1129 1130
1130 1131 It will find out about exceptions by itself.
1131 1132
1132 1133 A brief example::
1133 1134
1134 1135 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
1135 1136 try:
1136 1137 ...
1137 1138 except:
1138 1139 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1139 1140 """
1140 1141
1141 1142 def __call__(self,etype=None,evalue=None,etb=None,
1142 1143 out=None,tb_offset=None):
1143 1144 """Print out a formatted exception traceback.
1144 1145
1145 1146 Optional arguments:
1146 1147 - out: an open file-like object to direct output to.
1147 1148
1148 1149 - tb_offset: the number of frames to skip over in the stack, on a
1149 1150 per-call basis (this overrides temporarily the instance's tb_offset
1150 1151 given at initialization time. """
1151 1152
1152 1153
1153 1154 if out is None:
1154 1155 out = self.ostream
1155 1156 out.flush()
1156 1157 out.write(self.text(etype, evalue, etb, tb_offset))
1157 1158 out.write('\n')
1158 1159 out.flush()
1159 1160 # FIXME: we should remove the auto pdb behavior from here and leave
1160 1161 # that to the clients.
1161 1162 try:
1162 1163 self.debugger()
1163 1164 except KeyboardInterrupt:
1164 1165 print "\nKeyboardInterrupt"
1165 1166
1166 1167 def structured_traceback(self, etype=None, value=None, tb=None,
1167 1168 tb_offset=None, context=5):
1168 1169 if etype is None:
1169 1170 etype,value,tb = sys.exc_info()
1170 1171 self.tb = tb
1171 1172 return FormattedTB.structured_traceback(
1172 1173 self, etype, value, tb, tb_offset, context)
1173 1174
1174 1175 #---------------------------------------------------------------------------
1175 1176
1176 1177 # A simple class to preserve Nathan's original functionality.
1177 1178 class ColorTB(FormattedTB):
1178 1179 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1179 1180 def __init__(self,color_scheme='Linux',call_pdb=0):
1180 1181 FormattedTB.__init__(self,color_scheme=color_scheme,
1181 1182 call_pdb=call_pdb)
1182 1183
1183 1184
1184 1185 class SyntaxTB(ListTB):
1185 1186 """Extension which holds some state: the last exception value"""
1186 1187
1187 1188 def __init__(self,color_scheme = 'NoColor'):
1188 1189 ListTB.__init__(self,color_scheme)
1189 1190 self.last_syntax_error = None
1190 1191
1191 1192 def __call__(self, etype, value, elist):
1192 1193 self.last_syntax_error = value
1193 1194 ListTB.__call__(self,etype,value,elist)
1194 1195
1195 1196 def clear_err_state(self):
1196 1197 """Return the current error state and clear it"""
1197 1198 e = self.last_syntax_error
1198 1199 self.last_syntax_error = None
1199 1200 return e
1200 1201
1201 1202 def stb2text(self, stb):
1202 1203 """Convert a structured traceback (a list) to a string."""
1203 1204 return ''.join(stb)
1204 1205
1205 1206
1206 1207 #----------------------------------------------------------------------------
1207 1208 # module testing (minimal)
1208 1209 if __name__ == "__main__":
1209 1210 def spam(c, d_e):
1210 1211 (d, e) = d_e
1211 1212 x = c + d
1212 1213 y = c * d
1213 1214 foo(x, y)
1214 1215
1215 1216 def foo(a, b, bar=1):
1216 1217 eggs(a, b + bar)
1217 1218
1218 1219 def eggs(f, g, z=globals()):
1219 1220 h = f + g
1220 1221 i = f - g
1221 1222 return h / i
1222 1223
1223 1224 print ''
1224 1225 print '*** Before ***'
1225 1226 try:
1226 1227 print spam(1, (2, 3))
1227 1228 except:
1228 1229 traceback.print_exc()
1229 1230 print ''
1230 1231
1231 1232 handler = ColorTB()
1232 1233 print '*** ColorTB ***'
1233 1234 try:
1234 1235 print spam(1, (2, 3))
1235 1236 except:
1236 1237 handler(*sys.exc_info())
1237 1238 print ''
1238 1239
1239 1240 handler = VerboseTB()
1240 1241 print '*** VerboseTB ***'
1241 1242 try:
1242 1243 print spam(1, (2, 3))
1243 1244 except:
1244 1245 handler(*sys.exc_info())
1245 1246 print ''
1246 1247
General Comments 0
You need to be logged in to leave comments. Login now