##// END OF EJS Templates
Merge pull request #6065 from atteroTheGreatest/i1673...
Thomas Kluyver -
r17170:2bf35f92 merge
parent child Browse files
Show More
@@ -1735,7 +1735,7 b' class InteractiveShell(SingletonConfigurable):'
1735 This hook should be used sparingly, only in places which are not likely
1735 This hook should be used sparingly, only in places which are not likely
1736 to be true IPython errors.
1736 to be true IPython errors.
1737 """
1737 """
1738 self.showtraceback((etype,value,tb),tb_offset=0)
1738 self.showtraceback((etype, value, tb), tb_offset=0)
1739
1739
1740 def _get_exc_info(self, exc_tuple=None):
1740 def _get_exc_info(self, exc_tuple=None):
1741 """get exc_info from a given tuple, sys.exc_info() or sys.last_type etc.
1741 """get exc_info from a given tuple, sys.exc_info() or sys.last_type etc.
@@ -1776,7 +1776,7 b' class InteractiveShell(SingletonConfigurable):'
1776 """
1776 """
1777 self.write_err("UsageError: %s" % exc)
1777 self.write_err("UsageError: %s" % exc)
1778
1778
1779 def showtraceback(self,exc_tuple = None,filename=None,tb_offset=None,
1779 def showtraceback(self, exc_tuple=None, filename=None, tb_offset=None,
1780 exception_only=False):
1780 exception_only=False):
1781 """Display the exception that just occurred.
1781 """Display the exception that just occurred.
1782
1782
@@ -2918,10 +2918,9 b' class InteractiveShell(SingletonConfigurable):'
2918 False : successful execution.
2918 False : successful execution.
2919 True : an error occurred.
2919 True : an error occurred.
2920 """
2920 """
2921
2922 # Set our own excepthook in case the user code tries to call it
2921 # Set our own excepthook in case the user code tries to call it
2923 # directly, so that the IPython crash handler doesn't get triggered
2922 # directly, so that the IPython crash handler doesn't get triggered
2924 old_excepthook,sys.excepthook = sys.excepthook, self.excepthook
2923 old_excepthook, sys.excepthook = sys.excepthook, self.excepthook
2925
2924
2926 # we save the original sys.excepthook in the instance, in case config
2925 # we save the original sys.excepthook in the instance, in case config
2927 # code (such as magics) needs access to it.
2926 # code (such as magics) needs access to it.
@@ -2939,8 +2938,8 b' class InteractiveShell(SingletonConfigurable):'
2939 self.showtraceback(exception_only=True)
2938 self.showtraceback(exception_only=True)
2940 warn("To exit: use 'exit', 'quit', or Ctrl-D.", level=1)
2939 warn("To exit: use 'exit', 'quit', or Ctrl-D.", level=1)
2941 except self.custom_exceptions:
2940 except self.custom_exceptions:
2942 etype,value,tb = sys.exc_info()
2941 etype, value, tb = sys.exc_info()
2943 self.CustomTB(etype,value,tb)
2942 self.CustomTB(etype, value, tb)
2944 except:
2943 except:
2945 self.showtraceback()
2944 self.showtraceback()
2946 else:
2945 else:
@@ -9,6 +9,7 b' from IPython.testing import tools as tt'
9 from IPython.testing.decorators import onlyif_unicode_paths
9 from IPython.testing.decorators import onlyif_unicode_paths
10 from IPython.utils.syspathcontext import prepended_to_syspath
10 from IPython.utils.syspathcontext import prepended_to_syspath
11 from IPython.utils.tempdir import TemporaryDirectory
11 from IPython.utils.tempdir import TemporaryDirectory
12 from IPython.utils.py3compat import PY3
12
13
13 ip = get_ipython()
14 ip = get_ipython()
14
15
@@ -147,3 +148,37 b' class SyntaxErrorTest(unittest.TestCase):'
147 except ValueError:
148 except ValueError:
148 with tt.AssertPrints('QWERTY'):
149 with tt.AssertPrints('QWERTY'):
149 ip.showsyntaxerror()
150 ip.showsyntaxerror()
151
152
153 class Python3ChainedExceptionsTest(unittest.TestCase):
154 DIRECT_CAUSE_ERROR_CODE = """
155 try:
156 x = 1 + 2
157 print(not_defined_here)
158 except Exception as e:
159 x += 55
160 x - 1
161 y = {}
162 raise KeyError('uh') from e
163 """
164
165 EXCEPTION_DURING_HANDLING_CODE = """
166 try:
167 x = 1 + 2
168 print(not_defined_here)
169 except Exception as e:
170 x += 55
171 x - 1
172 y = {}
173 raise KeyError('uh')
174 """
175
176 def test_direct_cause_error(self):
177 if PY3:
178 with tt.AssertPrints(["KeyError", "NameError", "direct cause"]):
179 ip.run_cell(self.DIRECT_CAUSE_ERROR_CODE)
180
181 def test_exception_during_handling_error(self):
182 if PY3:
183 with tt.AssertPrints(["KeyError", "NameError", "During handling"]):
184 ip.run_cell(self.EXCEPTION_DURING_HANDLING_CODE)
This diff has been collapsed as it changes many lines, (529 lines changed) Show them Hide them
@@ -39,7 +39,7 b" Give it a shot--you'll love it or you'll hate it."
39 Verbose).
39 Verbose).
40
40
41
41
42 Installation instructions for ColorTB::
42 Installation instructions for VerboseTB::
43
43
44 import sys,ultratb
44 import sys,ultratb
45 sys.excepthook = ultratb.VerboseTB()
45 sys.excepthook = ultratb.VerboseTB()
@@ -73,11 +73,11 b' Inheritance diagram:'
73 """
73 """
74
74
75 #*****************************************************************************
75 #*****************************************************************************
76 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
76 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
77 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
77 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
78 #
78 #
79 # Distributed under the terms of the BSD License. The full license is in
79 # Distributed under the terms of the BSD License. The full license is in
80 # the file COPYING, distributed as part of this software.
80 # the file COPYING, distributed as part of this software.
81 #*****************************************************************************
81 #*****************************************************************************
82
82
83 from __future__ import unicode_literals
83 from __future__ import unicode_literals
@@ -95,14 +95,14 b' import tokenize'
95 import traceback
95 import traceback
96 import types
96 import types
97
97
98 try: # Python 2
98 try: # Python 2
99 generate_tokens = tokenize.generate_tokens
99 generate_tokens = tokenize.generate_tokens
100 except AttributeError: # Python 3
100 except AttributeError: # Python 3
101 generate_tokens = tokenize.tokenize
101 generate_tokens = tokenize.tokenize
102
102
103 # For purposes of monkeypatching inspect to fix a bug in it.
103 # For purposes of monkeypatching inspect to fix a bug in it.
104 from inspect import getsourcefile, getfile, getmodule,\
104 from inspect import getsourcefile, getfile, getmodule, \
105 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
105 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
106
106
107 # IPython's own modules
107 # IPython's own modules
108 # Modified pdb which doesn't damage IPython's readline handling
108 # Modified pdb which doesn't damage IPython's readline handling
@@ -125,11 +125,11 b' INDENT_SIZE = 8'
125
125
126 # Default color scheme. This is used, for example, by the traceback
126 # Default color scheme. This is used, for example, by the traceback
127 # formatter. When running in an actual IPython instance, the user's rc.colors
127 # formatter. When running in an actual IPython instance, the user's rc.colors
128 # value is used, but havinga module global makes this functionality available
128 # value is used, but having a module global makes this functionality available
129 # to users of ultratb who are NOT running inside ipython.
129 # to users of ultratb who are NOT running inside ipython.
130 DEFAULT_SCHEME = 'NoColor'
130 DEFAULT_SCHEME = 'NoColor'
131
131
132 #---------------------------------------------------------------------------
132 # ---------------------------------------------------------------------------
133 # Code begins
133 # Code begins
134
134
135 # Utility functions
135 # Utility functions
@@ -141,6 +141,7 b' def inspect_error():'
141 error('Internal Python error in the inspect module.\n'
141 error('Internal Python error in the inspect module.\n'
142 'Below is the traceback from this internal error.\n')
142 'Below is the traceback from this internal error.\n')
143
143
144
144 # This function is a monkeypatch we apply to the Python inspect module. We have
145 # This function is a monkeypatch we apply to the Python inspect module. We have
145 # now found when it's needed (see discussion on issue gh-1456), and we have a
146 # now found when it's needed (see discussion on issue gh-1456), and we have a
146 # test case (IPython.core.tests.test_ultratb.ChangedPyFileTest) that fails if
147 # test case (IPython.core.tests.test_ultratb.ChangedPyFileTest) that fails if
@@ -212,7 +213,7 b' def findsource(object):'
212 pmatch = pat.match
213 pmatch = pat.match
213 # fperez - fix: sometimes, co_firstlineno can give a number larger than
214 # fperez - fix: sometimes, co_firstlineno can give a number larger than
214 # the length of lines, which causes an error. Safeguard against that.
215 # the length of lines, which causes an error. Safeguard against that.
215 lnum = min(object.co_firstlineno,len(lines))-1
216 lnum = min(object.co_firstlineno, len(lines)) - 1
216 while lnum > 0:
217 while lnum > 0:
217 if pmatch(lines[lnum]): break
218 if pmatch(lines[lnum]): break
218 lnum -= 1
219 lnum -= 1
@@ -220,9 +221,11 b' def findsource(object):'
220 return lines, lnum
221 return lines, lnum
221 raise IOError('could not find code object')
222 raise IOError('could not find code object')
222
223
224
223 # Monkeypatch inspect to apply our bugfix.
225 # Monkeypatch inspect to apply our bugfix.
224 def with_patch_inspect(f):
226 def with_patch_inspect(f):
225 """decorator for monkeypatching inspect.findsource"""
227 """decorator for monkeypatching inspect.findsource"""
228
226 def wrapped(*args, **kwargs):
229 def wrapped(*args, **kwargs):
227 save_findsource = inspect.findsource
230 save_findsource = inspect.findsource
228 inspect.findsource = findsource
231 inspect.findsource = findsource
@@ -230,8 +233,10 b' def with_patch_inspect(f):'
230 return f(*args, **kwargs)
233 return f(*args, **kwargs)
231 finally:
234 finally:
232 inspect.findsource = save_findsource
235 inspect.findsource = save_findsource
236
233 return wrapped
237 return wrapped
234
238
239
235 def fix_frame_records_filenames(records):
240 def fix_frame_records_filenames(records):
236 """Try to fix the filenames in each record from inspect.getinnerframes().
241 """Try to fix the filenames in each record from inspect.getinnerframes().
237
242
@@ -253,11 +258,10 b' def fix_frame_records_filenames(records):'
253
258
254
259
255 @with_patch_inspect
260 @with_patch_inspect
256 def _fixed_getinnerframes(etb, context=1,tb_offset=0):
261 def _fixed_getinnerframes(etb, context=1, tb_offset=0):
257 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
262 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
258
259 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
260
263
264 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
261 # If the error is at the console, don't build any context, since it would
265 # If the error is at the console, don't build any context, since it would
262 # otherwise produce 5 blank lines printed out (there is no file at the
266 # otherwise produce 5 blank lines printed out (there is no file at the
263 # console)
267 # console)
@@ -272,9 +276,9 b' def _fixed_getinnerframes(etb, context=1,tb_offset=0):'
272 aux = traceback.extract_tb(etb)
276 aux = traceback.extract_tb(etb)
273 assert len(records) == len(aux)
277 assert len(records) == len(aux)
274 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
278 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
275 maybeStart = lnum-1 - context//2
279 maybeStart = lnum - 1 - context // 2
276 start = max(maybeStart, 0)
280 start = max(maybeStart, 0)
277 end = start + context
281 end = start + context
278 lines = ulinecache.getlines(file)[start:end]
282 lines = ulinecache.getlines(file)[start:end]
279 buf = list(records[i])
283 buf = list(records[i])
280 buf[LNUM_POS] = lnum
284 buf[LNUM_POS] = lnum
@@ -290,7 +294,8 b' def _fixed_getinnerframes(etb, context=1,tb_offset=0):'
290
294
291 _parser = PyColorize.Parser()
295 _parser = PyColorize.Parser()
292
296
293 def _format_traceback_lines(lnum, index, lines, Colors, lvals=None,scheme=None):
297
298 def _format_traceback_lines(lnum, index, lines, Colors, lvals=None, scheme=None):
294 numbers_width = INDENT_SIZE - 1
299 numbers_width = INDENT_SIZE - 1
295 res = []
300 res = []
296 i = lnum - index
301 i = lnum - index
@@ -315,7 +320,7 b' def _format_traceback_lines(lnum, index, lines, Colors, lvals=None,scheme=None):'
315 # This is the line with the error
320 # This is the line with the error
316 pad = numbers_width - len(str(i))
321 pad = numbers_width - len(str(i))
317 if pad >= 3:
322 if pad >= 3:
318 marker = '-'*(pad-3) + '-> '
323 marker = '-' * (pad - 3) + '-> '
319 elif pad == 2:
324 elif pad == 2:
320 marker = '> '
325 marker = '> '
321 elif pad == 1:
326 elif pad == 1:
@@ -323,12 +328,12 b' def _format_traceback_lines(lnum, index, lines, Colors, lvals=None,scheme=None):'
323 else:
328 else:
324 marker = ''
329 marker = ''
325 num = marker + str(i)
330 num = marker + str(i)
326 line = '%s%s%s %s%s' %(Colors.linenoEm, num,
331 line = '%s%s%s %s%s' % (Colors.linenoEm, num,
327 Colors.line, line, Colors.Normal)
332 Colors.line, line, Colors.Normal)
328 else:
333 else:
329 num = '%*s' % (numbers_width,i)
334 num = '%*s' % (numbers_width, i)
330 line = '%s%s%s %s' %(Colors.lineno, num,
335 line = '%s%s%s %s' % (Colors.lineno, num,
331 Colors.Normal, line)
336 Colors.Normal, line)
332
337
333 res.append(line)
338 res.append(line)
334 if lvals and i == lnum:
339 if lvals and i == lnum:
@@ -389,16 +394,16 b' class TBTools(object):'
389
394
390 ostream = property(_get_ostream, _set_ostream)
395 ostream = property(_get_ostream, _set_ostream)
391
396
392 def set_colors(self,*args,**kw):
397 def set_colors(self, *args, **kw):
393 """Shorthand access to the color table scheme selector method."""
398 """Shorthand access to the color table scheme selector method."""
394
399
395 # Set own color table
400 # Set own color table
396 self.color_scheme_table.set_active_scheme(*args,**kw)
401 self.color_scheme_table.set_active_scheme(*args, **kw)
397 # for convenience, set Colors to the active scheme
402 # for convenience, set Colors to the active scheme
398 self.Colors = self.color_scheme_table.active_colors
403 self.Colors = self.color_scheme_table.active_colors
399 # Also set colors of debugger
404 # Also set colors of debugger
400 if hasattr(self,'pdb') and self.pdb is not None:
405 if hasattr(self, 'pdb') and self.pdb is not None:
401 self.pdb.set_colors(*args,**kw)
406 self.pdb.set_colors(*args, **kw)
402
407
403 def color_toggle(self):
408 def color_toggle(self):
404 """Toggle between the currently active color scheme and NoColor."""
409 """Toggle between the currently active color scheme and NoColor."""
@@ -453,7 +458,7 b' class ListTB(TBTools):'
453 Because they are meant to be called without a full traceback (only a
458 Because they are meant to be called without a full traceback (only a
454 list), instances of this class can't call the interactive pdb debugger."""
459 list), instances of this class can't call the interactive pdb debugger."""
455
460
456 def __init__(self,color_scheme = 'NoColor', call_pdb=False, ostream=None):
461 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None):
457 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
462 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
458 ostream=ostream)
463 ostream=ostream)
459
464
@@ -497,7 +502,7 b' class ListTB(TBTools):'
497 elist = elist[tb_offset:]
502 elist = elist[tb_offset:]
498
503
499 out_list.append('Traceback %s(most recent call last)%s:' %
504 out_list.append('Traceback %s(most recent call last)%s:' %
500 (Colors.normalEm, Colors.Normal) + '\n')
505 (Colors.normalEm, Colors.Normal) + '\n')
501 out_list.extend(self._format_list(elist))
506 out_list.extend(self._format_list(elist))
502 # The exception info should be a single entry in the list.
507 # The exception info should be a single entry in the list.
503 lines = ''.join(self._format_exception_only(etype, value))
508 lines = ''.join(self._format_exception_only(etype, value))
@@ -510,7 +515,7 b' class ListTB(TBTools):'
510 ## out_list.append(lines[-1])
515 ## out_list.append(lines[-1])
511
516
512 # This means it was indenting everything but the last line by a little
517 # This means it was indenting everything but the last line by a little
513 # bit. I've disabled this for now, but if we see ugliness somewhre we
518 # bit. I've disabled this for now, but if we see ugliness somewhere we
514 # can restore it.
519 # can restore it.
515
520
516 return out_list
521 return out_list
@@ -532,25 +537,24 b' class ListTB(TBTools):'
532 list = []
537 list = []
533 for filename, lineno, name, line in extracted_list[:-1]:
538 for filename, lineno, name, line in extracted_list[:-1]:
534 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
539 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
535 (Colors.filename, filename, Colors.Normal,
540 (Colors.filename, filename, Colors.Normal,
536 Colors.lineno, lineno, Colors.Normal,
541 Colors.lineno, lineno, Colors.Normal,
537 Colors.name, name, Colors.Normal)
542 Colors.name, name, Colors.Normal)
538 if line:
543 if line:
539 item += ' %s\n' % line.strip()
544 item += ' %s\n' % line.strip()
540 list.append(item)
545 list.append(item)
541 # Emphasize the last entry
546 # Emphasize the last entry
542 filename, lineno, name, line = extracted_list[-1]
547 filename, lineno, name, line = extracted_list[-1]
543 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
548 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
544 (Colors.normalEm,
549 (Colors.normalEm,
545 Colors.filenameEm, filename, Colors.normalEm,
550 Colors.filenameEm, filename, Colors.normalEm,
546 Colors.linenoEm, lineno, Colors.normalEm,
551 Colors.linenoEm, lineno, Colors.normalEm,
547 Colors.nameEm, name, Colors.normalEm,
552 Colors.nameEm, name, Colors.normalEm,
548 Colors.Normal)
553 Colors.Normal)
549 if line:
554 if line:
550 item += '%s %s%s\n' % (Colors.line, line.strip(),
555 item += '%s %s%s\n' % (Colors.line, line.strip(),
551 Colors.Normal)
556 Colors.Normal)
552 list.append(item)
557 list.append(item)
553 #from pprint import pformat; print 'LISTTB', pformat(list) # dbg
554 return list
558 return list
555
559
556 def _format_exception_only(self, etype, value):
560 def _format_exception_only(self, etype, value):
@@ -572,11 +576,10 b' class ListTB(TBTools):'
572 stype = Colors.excName + etype.__name__ + Colors.Normal
576 stype = Colors.excName + etype.__name__ + Colors.Normal
573 if value is None:
577 if value is None:
574 # Not sure if this can still happen in Python 2.6 and above
578 # Not sure if this can still happen in Python 2.6 and above
575 list.append( py3compat.cast_unicode(stype) + '\n')
579 list.append(py3compat.cast_unicode(stype) + '\n')
576 else:
580 else:
577 if issubclass(etype, SyntaxError):
581 if issubclass(etype, SyntaxError):
578 have_filedata = True
582 have_filedata = True
579 #print 'filename is',filename # dbg
580 if not value.filename: value.filename = "<string>"
583 if not value.filename: value.filename = "<string>"
581 if value.lineno:
584 if value.lineno:
582 lineno = value.lineno
585 lineno = value.lineno
@@ -585,9 +588,9 b' class ListTB(TBTools):'
585 lineno = 'unknown'
588 lineno = 'unknown'
586 textline = ''
589 textline = ''
587 list.append('%s File %s"%s"%s, line %s%s%s\n' % \
590 list.append('%s File %s"%s"%s, line %s%s%s\n' % \
588 (Colors.normalEm,
591 (Colors.normalEm,
589 Colors.filenameEm, py3compat.cast_unicode(value.filename), Colors.normalEm,
592 Colors.filenameEm, py3compat.cast_unicode(value.filename), Colors.normalEm,
590 Colors.linenoEm, lineno, Colors.Normal ))
593 Colors.linenoEm, lineno, Colors.Normal ))
591 if textline == '':
594 if textline == '':
592 textline = py3compat.cast_unicode(value.text, "utf-8")
595 textline = py3compat.cast_unicode(value.text, "utf-8")
593
596
@@ -600,13 +603,13 b' class ListTB(TBTools):'
600 Colors.Normal))
603 Colors.Normal))
601 if value.offset is not None:
604 if value.offset is not None:
602 s = ' '
605 s = ' '
603 for c in textline[i:value.offset-1]:
606 for c in textline[i:value.offset - 1]:
604 if c.isspace():
607 if c.isspace():
605 s += c
608 s += c
606 else:
609 else:
607 s += ' '
610 s += ' '
608 list.append('%s%s^%s\n' % (Colors.caret, s,
611 list.append('%s%s^%s\n' % (Colors.caret, s,
609 Colors.Normal) )
612 Colors.Normal))
610
613
611 try:
614 try:
612 s = value.msg
615 s = value.msg
@@ -636,7 +639,6 b' class ListTB(TBTools):'
636 """
639 """
637 return ListTB.structured_traceback(self, etype, value, [])
640 return ListTB.structured_traceback(self, etype, value, [])
638
641
639
640 def show_exception_only(self, etype, evalue):
642 def show_exception_only(self, etype, evalue):
641 """Only print the exception type and message, without a traceback.
643 """Only print the exception type and message, without a traceback.
642
644
@@ -659,6 +661,7 b' class ListTB(TBTools):'
659 except:
661 except:
660 return '<unprintable %s object>' % type(value).__name__
662 return '<unprintable %s object>' % type(value).__name__
661
663
664
662 #----------------------------------------------------------------------------
665 #----------------------------------------------------------------------------
663 class VerboseTB(TBTools):
666 class VerboseTB(TBTools):
664 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
667 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
@@ -668,7 +671,7 b' class VerboseTB(TBTools):'
668 traceback, to be used with alternate interpreters (because their own code
671 traceback, to be used with alternate interpreters (because their own code
669 would appear in the traceback)."""
672 would appear in the traceback)."""
670
673
671 def __init__(self,color_scheme = 'Linux', call_pdb=False, ostream=None,
674 def __init__(self, color_scheme='Linux', call_pdb=False, ostream=None,
672 tb_offset=0, long_header=False, include_vars=True,
675 tb_offset=0, long_header=False, include_vars=True,
673 check_cache=None):
676 check_cache=None):
674 """Specify traceback offset, headers and color scheme.
677 """Specify traceback offset, headers and color scheme.
@@ -691,126 +694,37 b' class VerboseTB(TBTools):'
691 check_cache = linecache.checkcache
694 check_cache = linecache.checkcache
692 self.check_cache = check_cache
695 self.check_cache = check_cache
693
696
694 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
697 def format_records(self, records):
695 context=5):
698 Colors = self.Colors # just a shorthand + quicker name lookup
696 """Return a nice text document describing the traceback."""
699 ColorsNormal = Colors.Normal # used a lot
697
700 col_scheme = self.color_scheme_table.active_scheme_name
698 tb_offset = self.tb_offset if tb_offset is None else tb_offset
701 indent = ' ' * INDENT_SIZE
699
702 em_normal = '%s\n%s%s' % (Colors.valEm, indent, ColorsNormal)
700 # some locals
703 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
701 try:
702 etype = etype.__name__
703 except AttributeError:
704 pass
705 Colors = self.Colors # just a shorthand + quicker name lookup
706 ColorsNormal = Colors.Normal # used a lot
707 col_scheme = self.color_scheme_table.active_scheme_name
708 indent = ' '*INDENT_SIZE
709 em_normal = '%s\n%s%s' % (Colors.valEm, indent,ColorsNormal)
710 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
711 exc = '%s%s%s' % (Colors.excName,etype,ColorsNormal)
712
713 # some internal-use functions
714 def text_repr(value):
715 """Hopefully pretty robust repr equivalent."""
716 # this is pretty horrible but should always return *something*
717 try:
718 return pydoc.text.repr(value)
719 except KeyboardInterrupt:
720 raise
721 except:
722 try:
723 return repr(value)
724 except KeyboardInterrupt:
725 raise
726 except:
727 try:
728 # all still in an except block so we catch
729 # getattr raising
730 name = getattr(value, '__name__', None)
731 if name:
732 # ick, recursion
733 return text_repr(name)
734 klass = getattr(value, '__class__', None)
735 if klass:
736 return '%s instance' % text_repr(klass)
737 except KeyboardInterrupt:
738 raise
739 except:
740 return 'UNRECOVERABLE REPR FAILURE'
741 def eqrepr(value, repr=text_repr): return '=%s' % repr(value)
742 def nullrepr(value, repr=text_repr): return ''
743
744 # meat of the code begins
745 try:
746 etype = etype.__name__
747 except AttributeError:
748 pass
749
750 if self.long_header:
751 # Header with the exception type, python version, and date
752 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
753 date = time.ctime(time.time())
754
755 head = '%s%s%s\n%s%s%s\n%s' % (Colors.topline, '-'*75, ColorsNormal,
756 exc, ' '*(75-len(str(etype))-len(pyver)),
757 pyver, date.rjust(75) )
758 head += "\nA problem occured executing Python code. Here is the sequence of function"\
759 "\ncalls leading up to the error, with the most recent (innermost) call last."
760 else:
761 # Simplified header
762 head = '%s%s%s\n%s%s' % (Colors.topline, '-'*75, ColorsNormal,exc,
763 'Traceback (most recent call last)'.\
764 rjust(75 - len(str(etype)) ) )
765 frames = []
704 frames = []
766 # Flush cache before calling inspect. This helps alleviate some of the
767 # problems with python 2.3's inspect.py.
768 ##self.check_cache()
769 # Drop topmost frames if requested
770 try:
771 # Try the default getinnerframes and Alex's: Alex's fixes some
772 # problems, but it generates empty tracebacks for console errors
773 # (5 blanks lines) where none should be returned.
774 #records = inspect.getinnerframes(etb, context)[tb_offset:]
775 #print 'python records:', records # dbg
776 records = _fixed_getinnerframes(etb, context, tb_offset)
777 #print 'alex records:', records # dbg
778 except:
779
780 # FIXME: I've been getting many crash reports from python 2.3
781 # users, traceable to inspect.py. If I can find a small test-case
782 # to reproduce this, I should either write a better workaround or
783 # file a bug report against inspect (if that's the real problem).
784 # So far, I haven't been able to find an isolated example to
785 # reproduce the problem.
786 inspect_error()
787 traceback.print_exc(file=self.ostream)
788 info('\nUnfortunately, your original traceback can not be constructed.\n')
789 return ''
790
791 # build some color string templates outside these nested loops
705 # build some color string templates outside these nested loops
792 tpl_link = '%s%%s%s' % (Colors.filenameEm,ColorsNormal)
706 tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal)
793 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
707 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
794 ColorsNormal)
708 ColorsNormal)
795 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
709 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
796 (Colors.vName, Colors.valEm, ColorsNormal)
710 (Colors.vName, Colors.valEm, ColorsNormal)
797 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
711 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
798 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
712 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
799 Colors.vName, ColorsNormal)
713 Colors.vName, ColorsNormal)
800 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
714 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
801 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
715
802 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm,Colors.line,
716 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
803 ColorsNormal)
717 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm, Colors.line,
718 ColorsNormal)
804
719
805 # now, loop over all records printing context and info
806 abspath = os.path.abspath
720 abspath = os.path.abspath
807 for frame, file, lnum, func, lines, index in records:
721 for frame, file, lnum, func, lines, index in records:
808 #print '*** record:',file,lnum,func,lines,index # dbg
722 #print '*** record:',file,lnum,func,lines,index # dbg
809 if not file:
723 if not file:
810 file = '?'
724 file = '?'
811 elif not(file.startswith(str("<")) and file.endswith(str(">"))):
725 elif not (file.startswith(str("<")) and file.endswith(str(">"))):
812 # Guess that filenames like <string> aren't real filenames, so
726 # Guess that filenames like <string> aren't real filenames, so
813 # don't call abspath on them.
727 # don't call abspath on them.
814 try:
728 try:
815 file = abspath(file)
729 file = abspath(file)
816 except OSError:
730 except OSError:
@@ -827,9 +741,9 b' class VerboseTB(TBTools):'
827 # Decide whether to include variable details or not
741 # Decide whether to include variable details or not
828 var_repr = self.include_vars and eqrepr or nullrepr
742 var_repr = self.include_vars and eqrepr or nullrepr
829 try:
743 try:
830 call = tpl_call % (func,inspect.formatargvalues(args,
744 call = tpl_call % (func, inspect.formatargvalues(args,
831 varargs, varkw,
745 varargs, varkw,
832 locals,formatvalue=var_repr))
746 locals, formatvalue=var_repr))
833 except KeyError:
747 except KeyError:
834 # This happens in situations like errors inside generator
748 # This happens in situations like errors inside generator
835 # expressions, where local variables are listed in the
749 # expressions, where local variables are listed in the
@@ -848,12 +762,12 b' class VerboseTB(TBTools):'
848 # will illustrate the error, if this exception catch is
762 # will illustrate the error, if this exception catch is
849 # disabled.
763 # disabled.
850 call = tpl_call_fail % func
764 call = tpl_call_fail % func
851
765
852 # Don't attempt to tokenize binary files.
766 # Don't attempt to tokenize binary files.
853 if file.endswith(('.so', '.pyd', '.dll')):
767 if file.endswith(('.so', '.pyd', '.dll')):
854 frames.append('%s %s\n' % (link,call))
768 frames.append('%s %s\n' % (link, call))
855 continue
769 continue
856 elif file.endswith(('.pyc','.pyo')):
770 elif file.endswith(('.pyc', '.pyo')):
857 # Look up the corresponding source file.
771 # Look up the corresponding source file.
858 file = openpy.source_from_cache(file)
772 file = openpy.source_from_cache(file)
859
773
@@ -867,7 +781,7 b' class VerboseTB(TBTools):'
867 try:
781 try:
868 names = []
782 names = []
869 name_cont = False
783 name_cont = False
870
784
871 for token_type, token, start, end, line in generate_tokens(linereader):
785 for token_type, token, start, end, line in generate_tokens(linereader):
872 # build composite names
786 # build composite names
873 if token_type == tokenize.NAME and token not in keyword.kwlist:
787 if token_type == tokenize.NAME and token not in keyword.kwlist:
@@ -890,7 +804,7 b' class VerboseTB(TBTools):'
890 name_cont = True
804 name_cont = True
891 elif token_type == tokenize.NEWLINE:
805 elif token_type == tokenize.NEWLINE:
892 break
806 break
893
807
894 except (IndexError, UnicodeDecodeError):
808 except (IndexError, UnicodeDecodeError):
895 # signals exit of tokenizer
809 # signals exit of tokenizer
896 pass
810 pass
@@ -909,11 +823,11 b' class VerboseTB(TBTools):'
909 lvals = []
823 lvals = []
910 if self.include_vars:
824 if self.include_vars:
911 for name_full in unique_names:
825 for name_full in unique_names:
912 name_base = name_full.split('.',1)[0]
826 name_base = name_full.split('.', 1)[0]
913 if name_base in frame.f_code.co_varnames:
827 if name_base in frame.f_code.co_varnames:
914 if name_base in locals:
828 if name_base in locals:
915 try:
829 try:
916 value = repr(eval(name_full,locals))
830 value = repr(eval(name_full, locals))
917 except:
831 except:
918 value = undefined
832 value = undefined
919 else:
833 else:
@@ -922,69 +836,191 b' class VerboseTB(TBTools):'
922 else:
836 else:
923 if name_base in frame.f_globals:
837 if name_base in frame.f_globals:
924 try:
838 try:
925 value = repr(eval(name_full,frame.f_globals))
839 value = repr(eval(name_full, frame.f_globals))
926 except:
840 except:
927 value = undefined
841 value = undefined
928 else:
842 else:
929 value = undefined
843 value = undefined
930 name = tpl_global_var % name_full
844 name = tpl_global_var % name_full
931 lvals.append(tpl_name_val % (name,value))
845 lvals.append(tpl_name_val % (name, value))
932 if lvals:
846 if lvals:
933 lvals = '%s%s' % (indent,em_normal.join(lvals))
847 lvals = '%s%s' % (indent, em_normal.join(lvals))
934 else:
848 else:
935 lvals = ''
849 lvals = ''
936
850
937 level = '%s %s\n' % (link,call)
851 level = '%s %s\n' % (link, call)
938
852
939 if index is None:
853 if index is None:
940 frames.append(level)
854 frames.append(level)
941 else:
855 else:
942 frames.append('%s%s' % (level,''.join(
856 frames.append('%s%s' % (level, ''.join(
943 _format_traceback_lines(lnum,index,lines,Colors,lvals,
857 _format_traceback_lines(lnum, index, lines, Colors, lvals,
944 col_scheme))))
858 col_scheme))))
945
859
860 return frames
861
862 def prepare_chained_exception_message(self, cause):
863 direct_cause = "\nThe above exception was the direct cause of the following exception:\n"
864 exception_during_handling = "\nDuring handling of the above exception, another exception occurred:\n"
865
866 if cause:
867 message = [[direct_cause]]
868 else:
869 message = [[exception_during_handling]]
870 return message
871
872 def prepare_header(self, etype, long_version=False):
873 colors = self.Colors # just a shorthand + quicker name lookup
874 colorsnormal = colors.Normal # used a lot
875 exc = '%s%s%s' % (colors.excName, etype, colorsnormal)
876 if long_version:
877 # Header with the exception type, python version, and date
878 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
879 date = time.ctime(time.time())
880
881 head = '%s%s%s\n%s%s%s\n%s' % (colors.topline, '-' * 75, colorsnormal,
882 exc, ' ' * (75 - len(str(etype)) - len(pyver)),
883 pyver, date.rjust(75) )
884 head += "\nA problem occurred executing Python code. Here is the sequence of function" \
885 "\ncalls leading up to the error, with the most recent (innermost) call last."
886 else:
887 # Simplified header
888 head = '%s%s' % (exc, 'Traceback (most recent call last)'. \
889 rjust(75 - len(str(etype))) )
890
891 return head
892
893 def format_exception(self, etype, evalue):
894 colors = self.Colors # just a shorthand + quicker name lookup
895 colorsnormal = colors.Normal # used a lot
896 indent = ' ' * INDENT_SIZE
946 # Get (safely) a string form of the exception info
897 # Get (safely) a string form of the exception info
947 try:
898 try:
948 etype_str,evalue_str = map(str,(etype,evalue))
899 etype_str, evalue_str = map(str, (etype, evalue))
949 except:
900 except:
950 # User exception is improperly defined.
901 # User exception is improperly defined.
951 etype,evalue = str,sys.exc_info()[:2]
902 etype, evalue = str, sys.exc_info()[:2]
952 etype_str,evalue_str = map(str,(etype,evalue))
903 etype_str, evalue_str = map(str, (etype, evalue))
953 # ... and format it
904 # ... and format it
954 exception = ['%s%s%s: %s' % (Colors.excName, etype_str,
905 exception = ['%s%s%s: %s' % (colors.excName, etype_str,
955 ColorsNormal, py3compat.cast_unicode(evalue_str))]
906 colorsnormal, py3compat.cast_unicode(evalue_str))]
907
956 if (not py3compat.PY3) and type(evalue) is types.InstanceType:
908 if (not py3compat.PY3) and type(evalue) is types.InstanceType:
957 try:
909 try:
958 names = [w for w in dir(evalue) if isinstance(w, py3compat.string_types)]
910 names = [w for w in dir(evalue) if isinstance(w, py3compat.string_types)]
959 except:
911 except:
960 # Every now and then, an object with funny inernals blows up
912 # Every now and then, an object with funny internals blows up
961 # when dir() is called on it. We do the best we can to report
913 # when dir() is called on it. We do the best we can to report
962 # the problem and continue
914 # the problem and continue
963 _m = '%sException reporting error (object with broken dir())%s:'
915 _m = '%sException reporting error (object with broken dir())%s:'
964 exception.append(_m % (Colors.excName,ColorsNormal))
916 exception.append(_m % (colors.excName, colorsnormal))
965 etype_str,evalue_str = map(str,sys.exc_info()[:2])
917 etype_str, evalue_str = map(str, sys.exc_info()[:2])
966 exception.append('%s%s%s: %s' % (Colors.excName,etype_str,
918 exception.append('%s%s%s: %s' % (colors.excName, etype_str,
967 ColorsNormal, py3compat.cast_unicode(evalue_str)))
919 colorsnormal, py3compat.cast_unicode(evalue_str)))
968 names = []
920 names = []
969 for name in names:
921 for name in names:
970 value = text_repr(getattr(evalue, name))
922 value = text_repr(getattr(evalue, name))
971 exception.append('\n%s%s = %s' % (indent, name, value))
923 exception.append('\n%s%s = %s' % (indent, name, value))
972
924
973 # vds: >>
925 return exception
926
927 def format_exception_as_a_whole(self, etype, evalue, etb, number_of_lines_of_context, tb_offset):
928 # some locals
929 try:
930 etype = etype.__name__
931 except AttributeError:
932 pass
933
934 tb_offset = self.tb_offset if tb_offset is None else tb_offset
935 head = self.prepare_header(etype, self.long_header)
936 records = self.get_records(etb, number_of_lines_of_context, tb_offset)
937
938 frames = self.format_records(records)
939 if records is None:
940 return ""
941
942 formatted_exception = self.format_exception(etype, evalue)
974 if records:
943 if records:
975 filepath, lnum = records[-1][1:3]
944 filepath, lnum = records[-1][1:3]
976 #print "file:", str(file), "linenb", str(lnum) # dbg
945 filepath = os.path.abspath(filepath)
977 filepath = os.path.abspath(filepath)
946 ipinst = get_ipython()
978 ipinst = get_ipython()
947 if ipinst is not None:
979 if ipinst is not None:
948 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
980 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
949
981 # vds: <<
950 return [[head] + frames + [''.join(formatted_exception[0])]]
982
951
983 # return all our info assembled as a single string
952 def get_records(self, etb, number_of_lines_of_context, tb_offset):
984 # return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) )
953 try:
985 return [head] + frames + [''.join(exception[0])]
954 # Try the default getinnerframes and Alex's: Alex's fixes some
986
955 # problems, but it generates empty tracebacks for console errors
987 def debugger(self,force=False):
956 # (5 blanks lines) where none should be returned.
957 return _fixed_getinnerframes(etb, number_of_lines_of_context, tb_offset)
958 except:
959 # FIXME: I've been getting many crash reports from python 2.3
960 # users, traceable to inspect.py. If I can find a small test-case
961 # to reproduce this, I should either write a better workaround or
962 # file a bug report against inspect (if that's the real problem).
963 # So far, I haven't been able to find an isolated example to
964 # reproduce the problem.
965 inspect_error()
966 traceback.print_exc(file=self.ostream)
967 info('\nUnfortunately, your original traceback can not be constructed.\n')
968 return None
969
970 def get_parts_of_chained_exception(self, evalue):
971 def get_chained_exception(exception_value):
972 cause = getattr(exception_value, '__cause__', None)
973 if cause:
974 return cause
975 return getattr(exception_value, '__context__', None)
976
977 chained_evalue = get_chained_exception(evalue)
978
979 if chained_evalue:
980 return chained_evalue.__class__, chained_evalue, chained_evalue.__traceback__
981
982 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
983 number_of_lines_of_context=5):
984 """Return a nice text document describing the traceback."""
985
986 formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,
987 tb_offset)
988
989 colors = self.Colors # just a shorthand + quicker name lookup
990 colorsnormal = colors.Normal # used a lot
991 head = '%s%s%s' % (colors.topline, '-' * 75, colorsnormal)
992 structured_traceback_parts = [head]
993 if py3compat.PY3:
994 chained_exceptions_tb_offset = 0
995 lines_of_context = 3
996 formatted_exceptions = formatted_exception
997 exception = self.get_parts_of_chained_exception(evalue)
998 if exception:
999 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1000 etype, evalue, etb = exception
1001 else:
1002 evalue = None
1003 while evalue:
1004 formatted_exceptions += self.format_exception_as_a_whole(etype, evalue, etb, lines_of_context,
1005 chained_exceptions_tb_offset)
1006 exception = self.get_parts_of_chained_exception(evalue)
1007
1008 if exception:
1009 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1010 etype, evalue, etb = exception
1011 else:
1012 evalue = None
1013
1014 # we want to see exceptions in a reversed order:
1015 # the first exception should be on top
1016 for formatted_exception in reversed(formatted_exceptions):
1017 structured_traceback_parts += formatted_exception
1018 else:
1019 structured_traceback_parts += formatted_exception[0]
1020
1021 return structured_traceback_parts
1022
1023 def debugger(self, force=False):
988 """Call up the pdb debugger if desired, always clean up the tb
1024 """Call up the pdb debugger if desired, always clean up the tb
989 reference.
1025 reference.
990
1026
@@ -1014,7 +1050,7 b' class VerboseTB(TBTools):'
1014 with display_trap:
1050 with display_trap:
1015 self.pdb.reset()
1051 self.pdb.reset()
1016 # Find the right frame so we don't pop up inside ipython itself
1052 # Find the right frame so we don't pop up inside ipython itself
1017 if hasattr(self,'tb') and self.tb is not None:
1053 if hasattr(self, 'tb') and self.tb is not None:
1018 etb = self.tb
1054 etb = self.tb
1019 else:
1055 else:
1020 etb = self.tb = sys.last_traceback
1056 etb = self.tb = sys.last_traceback
@@ -1025,7 +1061,7 b' class VerboseTB(TBTools):'
1025 self.pdb.botframe = etb.tb_frame
1061 self.pdb.botframe = etb.tb_frame
1026 self.pdb.interaction(self.tb.tb_frame, self.tb)
1062 self.pdb.interaction(self.tb.tb_frame, self.tb)
1027
1063
1028 if hasattr(self,'tb'):
1064 if hasattr(self, 'tb'):
1029 del self.tb
1065 del self.tb
1030
1066
1031 def handler(self, info=None):
1067 def handler(self, info=None):
@@ -1050,6 +1086,7 b' class VerboseTB(TBTools):'
1050 except KeyboardInterrupt:
1086 except KeyboardInterrupt:
1051 print("\nKeyboardInterrupt")
1087 print("\nKeyboardInterrupt")
1052
1088
1089
1053 #----------------------------------------------------------------------------
1090 #----------------------------------------------------------------------------
1054 class FormattedTB(VerboseTB, ListTB):
1091 class FormattedTB(VerboseTB, ListTB):
1055 """Subclass ListTB but allow calling with a traceback.
1092 """Subclass ListTB but allow calling with a traceback.
@@ -1069,7 +1106,7 b' class FormattedTB(VerboseTB, ListTB):'
1069 check_cache=None):
1106 check_cache=None):
1070
1107
1071 # NEVER change the order of this list. Put new modes at the end:
1108 # NEVER change the order of this list. Put new modes at the end:
1072 self.valid_modes = ['Plain','Context','Verbose']
1109 self.valid_modes = ['Plain', 'Context', 'Verbose']
1073 self.verbose_modes = self.valid_modes[1:3]
1110 self.verbose_modes = self.valid_modes[1:3]
1074
1111
1075 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
1112 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
@@ -1083,19 +1120,19 b' class FormattedTB(VerboseTB, ListTB):'
1083 # set_mode also sets the tb_join_char attribute
1120 # set_mode also sets the tb_join_char attribute
1084 self.set_mode(mode)
1121 self.set_mode(mode)
1085
1122
1086 def _extract_tb(self,tb):
1123 def _extract_tb(self, tb):
1087 if tb:
1124 if tb:
1088 return traceback.extract_tb(tb)
1125 return traceback.extract_tb(tb)
1089 else:
1126 else:
1090 return None
1127 return None
1091
1128
1092 def structured_traceback(self, etype, value, tb, tb_offset=None, context=5):
1129 def structured_traceback(self, etype, value, tb, tb_offset=None, number_of_lines_of_context=5):
1093 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1130 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1094 mode = self.mode
1131 mode = self.mode
1095 if mode in self.verbose_modes:
1132 if mode in self.verbose_modes:
1096 # Verbose modes need a full traceback
1133 # Verbose modes need a full traceback
1097 return VerboseTB.structured_traceback(
1134 return VerboseTB.structured_traceback(
1098 self, etype, value, tb, tb_offset, context
1135 self, etype, value, tb, tb_offset, number_of_lines_of_context
1099 )
1136 )
1100 else:
1137 else:
1101 # We must check the source cache because otherwise we can print
1138 # We must check the source cache because otherwise we can print
@@ -1104,7 +1141,7 b' class FormattedTB(VerboseTB, ListTB):'
1104 # Now we can extract and format the exception
1141 # Now we can extract and format the exception
1105 elist = self._extract_tb(tb)
1142 elist = self._extract_tb(tb)
1106 return ListTB.structured_traceback(
1143 return ListTB.structured_traceback(
1107 self, etype, value, elist, tb_offset, context
1144 self, etype, value, elist, tb_offset, number_of_lines_of_context
1108 )
1145 )
1109
1146
1110 def stb2text(self, stb):
1147 def stb2text(self, stb):
@@ -1112,18 +1149,18 b' class FormattedTB(VerboseTB, ListTB):'
1112 return self.tb_join_char.join(stb)
1149 return self.tb_join_char.join(stb)
1113
1150
1114
1151
1115 def set_mode(self,mode=None):
1152 def set_mode(self, mode=None):
1116 """Switch to the desired mode.
1153 """Switch to the desired mode.
1117
1154
1118 If mode is not specified, cycles through the available modes."""
1155 If mode is not specified, cycles through the available modes."""
1119
1156
1120 if not mode:
1157 if not mode:
1121 new_idx = ( self.valid_modes.index(self.mode) + 1 ) % \
1158 new_idx = (self.valid_modes.index(self.mode) + 1 ) % \
1122 len(self.valid_modes)
1159 len(self.valid_modes)
1123 self.mode = self.valid_modes[new_idx]
1160 self.mode = self.valid_modes[new_idx]
1124 elif mode not in self.valid_modes:
1161 elif mode not in self.valid_modes:
1125 raise ValueError('Unrecognized mode in FormattedTB: <'+mode+'>\n'
1162 raise ValueError('Unrecognized mode in FormattedTB: <' + mode + '>\n'
1126 'Valid modes: '+str(self.valid_modes))
1163 'Valid modes: ' + str(self.valid_modes))
1127 else:
1164 else:
1128 self.mode = mode
1165 self.mode = mode
1129 # include variable details only in 'Verbose' mode
1166 # include variable details only in 'Verbose' mode
@@ -1131,7 +1168,7 b' class FormattedTB(VerboseTB, ListTB):'
1131 # Set the join character for generating text tracebacks
1168 # Set the join character for generating text tracebacks
1132 self.tb_join_char = self._join_chars[self.mode]
1169 self.tb_join_char = self._join_chars[self.mode]
1133
1170
1134 # some convenient shorcuts
1171 # some convenient shortcuts
1135 def plain(self):
1172 def plain(self):
1136 self.set_mode(self.valid_modes[0])
1173 self.set_mode(self.valid_modes[0])
1137
1174
@@ -1141,6 +1178,7 b' class FormattedTB(VerboseTB, ListTB):'
1141 def verbose(self):
1178 def verbose(self):
1142 self.set_mode(self.valid_modes[2])
1179 self.set_mode(self.valid_modes[2])
1143
1180
1181
1144 #----------------------------------------------------------------------------
1182 #----------------------------------------------------------------------------
1145 class AutoFormattedTB(FormattedTB):
1183 class AutoFormattedTB(FormattedTB):
1146 """A traceback printer which can be called on the fly.
1184 """A traceback printer which can be called on the fly.
@@ -1156,8 +1194,8 b' class AutoFormattedTB(FormattedTB):'
1156 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1194 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1157 """
1195 """
1158
1196
1159 def __call__(self,etype=None,evalue=None,etb=None,
1197 def __call__(self, etype=None, evalue=None, etb=None,
1160 out=None,tb_offset=None):
1198 out=None, tb_offset=None):
1161 """Print out a formatted exception traceback.
1199 """Print out a formatted exception traceback.
1162
1200
1163 Optional arguments:
1201 Optional arguments:
@@ -1167,7 +1205,6 b' class AutoFormattedTB(FormattedTB):'
1167 per-call basis (this overrides temporarily the instance's tb_offset
1205 per-call basis (this overrides temporarily the instance's tb_offset
1168 given at initialization time. """
1206 given at initialization time. """
1169
1207
1170
1171 if out is None:
1208 if out is None:
1172 out = self.ostream
1209 out = self.ostream
1173 out.flush()
1210 out.flush()
@@ -1182,33 +1219,36 b' class AutoFormattedTB(FormattedTB):'
1182 print("\nKeyboardInterrupt")
1219 print("\nKeyboardInterrupt")
1183
1220
1184 def structured_traceback(self, etype=None, value=None, tb=None,
1221 def structured_traceback(self, etype=None, value=None, tb=None,
1185 tb_offset=None, context=5):
1222 tb_offset=None, number_of_lines_of_context=5):
1186 if etype is None:
1223 if etype is None:
1187 etype,value,tb = sys.exc_info()
1224 etype, value, tb = sys.exc_info()
1188 self.tb = tb
1225 self.tb = tb
1189 return FormattedTB.structured_traceback(
1226 return FormattedTB.structured_traceback(
1190 self, etype, value, tb, tb_offset, context)
1227 self, etype, value, tb, tb_offset, number_of_lines_of_context)
1228
1191
1229
1192 #---------------------------------------------------------------------------
1230 #---------------------------------------------------------------------------
1193
1231
1194 # A simple class to preserve Nathan's original functionality.
1232 # A simple class to preserve Nathan's original functionality.
1195 class ColorTB(FormattedTB):
1233 class ColorTB(FormattedTB):
1196 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1234 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1197 def __init__(self,color_scheme='Linux',call_pdb=0):
1235
1198 FormattedTB.__init__(self,color_scheme=color_scheme,
1236 def __init__(self, color_scheme='Linux', call_pdb=0):
1237 FormattedTB.__init__(self, color_scheme=color_scheme,
1199 call_pdb=call_pdb)
1238 call_pdb=call_pdb)
1200
1239
1201
1240
1202 class SyntaxTB(ListTB):
1241 class SyntaxTB(ListTB):
1203 """Extension which holds some state: the last exception value"""
1242 """Extension which holds some state: the last exception value"""
1204
1243
1205 def __init__(self,color_scheme = 'NoColor'):
1244 def __init__(self, color_scheme='NoColor'):
1206 ListTB.__init__(self,color_scheme)
1245 ListTB.__init__(self, color_scheme)
1207 self.last_syntax_error = None
1246 self.last_syntax_error = None
1208
1247
1209 def __call__(self, etype, value, elist):
1248 def __call__(self, etype, value, elist):
1210 self.last_syntax_error = value
1249 self.last_syntax_error = value
1211 ListTB.__call__(self,etype,value,elist)
1250
1251 ListTB.__call__(self, etype, value, elist)
1212
1252
1213 def structured_traceback(self, etype, value, elist, tb_offset=None,
1253 def structured_traceback(self, etype, value, elist, tb_offset=None,
1214 context=5):
1254 context=5):
@@ -1223,7 +1263,7 b' class SyntaxTB(ListTB):'
1223 if newtext:
1263 if newtext:
1224 value.text = newtext
1264 value.text = newtext
1225 return super(SyntaxTB, self).structured_traceback(etype, value, elist,
1265 return super(SyntaxTB, self).structured_traceback(etype, value, elist,
1226 tb_offset=tb_offset, context=context)
1266 tb_offset=tb_offset, context=context)
1227
1267
1228 def clear_err_state(self):
1268 def clear_err_state(self):
1229 """Return the current error state and clear it"""
1269 """Return the current error state and clear it"""
@@ -1236,7 +1276,46 b' class SyntaxTB(ListTB):'
1236 return ''.join(stb)
1276 return ''.join(stb)
1237
1277
1238
1278
1279 # some internal-use functions
1280 def text_repr(value):
1281 """Hopefully pretty robust repr equivalent."""
1282 # this is pretty horrible but should always return *something*
1283 try:
1284 return pydoc.text.repr(value)
1285 except KeyboardInterrupt:
1286 raise
1287 except:
1288 try:
1289 return repr(value)
1290 except KeyboardInterrupt:
1291 raise
1292 except:
1293 try:
1294 # all still in an except block so we catch
1295 # getattr raising
1296 name = getattr(value, '__name__', None)
1297 if name:
1298 # ick, recursion
1299 return text_repr(name)
1300 klass = getattr(value, '__class__', None)
1301 if klass:
1302 return '%s instance' % text_repr(klass)
1303 except KeyboardInterrupt:
1304 raise
1305 except:
1306 return 'UNRECOVERABLE REPR FAILURE'
1307
1308
1309 def eqrepr(value, repr=text_repr):
1310 return '=%s' % repr(value)
1311
1312
1313 def nullrepr(value, repr=text_repr):
1314 return ''
1315
1316
1239 #----------------------------------------------------------------------------
1317 #----------------------------------------------------------------------------
1318
1240 # module testing (minimal)
1319 # module testing (minimal)
1241 if __name__ == "__main__":
1320 if __name__ == "__main__":
1242 def spam(c, d_e):
1321 def spam(c, d_e):
@@ -1,6 +1,7 b''
1 {
1 {
2 "metadata": {
2 "metadata": {
3 "name": ""
3 "name": "",
4 "signature": "sha256:9d47889f0678e9685429071216d0f3354db59bb66489f3225bcadfb6a1a9bbba"
4 },
5 },
5 "nbformat": 3,
6 "nbformat": 3,
6 "nbformat_minor": 0,
7 "nbformat_minor": 0,
@@ -21,7 +22,8 b''
21 "evalue": "message",
22 "evalue": "message",
22 "output_type": "pyerr",
23 "output_type": "pyerr",
23 "traceback": [
24 "traceback": [
24 "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[1;31mException\u001b[0m Traceback (most recent call last)",
25 "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
26 "\u001b[1;31mException\u001b[0m Traceback (most recent call last)",
25 "\u001b[1;32m<ipython-input-1-335814d14fc1>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;32mraise\u001b[0m \u001b[0mException\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"message\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
27 "\u001b[1;32m<ipython-input-1-335814d14fc1>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;32mraise\u001b[0m \u001b[0mException\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"message\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
26 "\u001b[1;31mException\u001b[0m: message"
28 "\u001b[1;31mException\u001b[0m: message"
27 ]
29 ]
General Comments 0
You need to be logged in to leave comments. Login now