change the way exceptions are parsed out of tracebacks

This commit is contained in:
Mahmoud Hashemi 2015-02-21 19:57:16 -08:00
parent 0394d93b93
commit e2a0868f74
1 changed files with 24 additions and 19 deletions

View File

@ -463,39 +463,44 @@ class ParsedTB(object):
if not isinstance(tb_str, unicode): if not isinstance(tb_str, unicode):
tb_str = tb_str.decode('utf-8') tb_str = tb_str.decode('utf-8')
tb_lines = tb_str.lstrip().splitlines() tb_lines = tb_str.lstrip().splitlines()
if tb_lines[0].strip() == 'Traceback (most recent call last):':
frame_lines = tb_lines[1:-1] # first off, handle some ignored exceptions. these can be the
frame_re = _frame_re # result of exceptions raised by __del__ during garbage
elif len(tb_lines) > 1 and tb_lines[-2].lstrip().startswith('^'): # collection
frame_lines = tb_lines[:-2]
frame_re = _se_frame_re
else:
raise ValueError('unrecognized traceback string format')
while tb_lines: while tb_lines:
cl = tb_lines[-1] cl = tb_lines[-1]
if cl.startswith('Exception ') and cl.endswith('ignored'): if cl.startswith('Exception ') and cl.endswith('ignored'):
# handle some ignored exceptions
tb_lines.pop() tb_lines.pop()
else: else:
break break
for line in reversed(tb_lines):
# get the bottom-most line that looks like an actual Exception if tb_lines and tb_lines[0].strip() == 'Traceback (most recent call last):':
# repr(), (i.e., "Exception: message") start_line = 1
exc_type, sep, exc_msg = line.partition(':') frame_re = _frame_re
if sep and exc_type and len(exc_type.split()) == 1: elif len(tb_lines) > 1 and tb_lines[-2].lstrip().startswith('^'):
break start_line = 0
frame_re = _se_frame_re
else:
raise ValueError('unrecognized traceback string format')
frames = [] frames = []
for pair_idx in range(0, len(frame_lines), 2): for pair_idx in range(start_line, len(tb_lines), 2):
frame_line = frame_lines[pair_idx].strip() frame_line = tb_lines[pair_idx].strip()
frame_match = frame_re.match(frame_line) frame_match = frame_re.match(frame_line)
if frame_match: if frame_match:
frame_dict = frame_match.groupdict() frame_dict = frame_match.groupdict()
else: else:
continue break
frame_dict['source_line'] = frame_lines[pair_idx + 1].strip() frame_dict['source_line'] = tb_lines[pair_idx + 1].strip()
frames.append(frame_dict) frames.append(frame_dict)
exc_line_offset = start_line + len(frames) * 2
try:
exc_line = tb_lines[exc_line_offset]
exc_type, _, exc_msg = exc_line.partition(':')
except:
exc_type, exc_msg = '', ''
return cls(exc_type, exc_msg, frames) return cls(exc_type, exc_msg, frames)