mirror of https://github.com/mahmoud/boltons.git
Properly parse tracebacks with missing source. Resolves #30
This commit is contained in:
parent
c9b3d2452e
commit
ae21ed2a78
|
@ -6,4 +6,4 @@ python:
|
|||
- "pypy"
|
||||
|
||||
install: "pip install -r requirements-test.txt"
|
||||
script: "py.test --doctest-modules boltons"
|
||||
script: "py.test --doctest-modules boltons tests"
|
||||
|
|
|
@ -27,6 +27,12 @@ import sys
|
|||
import linecache
|
||||
|
||||
|
||||
if str is bytes: # py2
|
||||
text = unicode
|
||||
else: # py3
|
||||
text = str
|
||||
|
||||
|
||||
# TODO: chaining primitives? what are real use cases where these help?
|
||||
|
||||
# TODO: print_* for backwards compatability
|
||||
|
@ -691,7 +697,7 @@ class ParsedException(object):
|
|||
Args:
|
||||
tb_str (str): The traceback text (:class:`unicode` or UTF-8 bytes)
|
||||
"""
|
||||
if not isinstance(tb_str, unicode):
|
||||
if not isinstance(tb_str, text):
|
||||
tb_str = tb_str.decode('utf-8')
|
||||
tb_lines = tb_str.lstrip().splitlines()
|
||||
|
||||
|
@ -717,21 +723,27 @@ class ParsedException(object):
|
|||
raise ValueError('unrecognized traceback string format')
|
||||
|
||||
frames = []
|
||||
for pair_idx in range(start_line, len(tb_lines), 2):
|
||||
frame_line = tb_lines[pair_idx].strip()
|
||||
line_no = start_line
|
||||
while True:
|
||||
frame_line = tb_lines[line_no].strip()
|
||||
frame_match = frame_re.match(frame_line)
|
||||
if frame_match:
|
||||
frame_dict = frame_match.groupdict()
|
||||
next_line = tb_lines[line_no + 1].strip()
|
||||
if frame_re.match(next_line):
|
||||
frame_dict['source_line'] = ''
|
||||
else:
|
||||
frame_dict['source_line'] = next_line
|
||||
line_no += 1
|
||||
else:
|
||||
break
|
||||
frame_dict['source_line'] = tb_lines[pair_idx + 1].strip()
|
||||
line_no += 1
|
||||
frames.append(frame_dict)
|
||||
|
||||
exc_line_offset = start_line + len(frames) * 2
|
||||
try:
|
||||
exc_line = tb_lines[exc_line_offset]
|
||||
exc_line = tb_lines[line_no]
|
||||
exc_type, _, exc_msg = exc_line.partition(':')
|
||||
except:
|
||||
except Exception:
|
||||
exc_type, exc_msg = '', ''
|
||||
|
||||
return cls(exc_type, exc_msg, frames)
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
from __future__ import absolute_import
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from boltons.tbutils import ParsedException
|
||||
|
||||
|
||||
def test_normal_tb():
|
||||
tb = '''\
|
||||
Traceback (most recent call last):
|
||||
File "<string>", line 2, in _some_function
|
||||
return some_other_function(1)
|
||||
File "myfile.py", line 3, in some_other_function
|
||||
return foo(bar, baz)
|
||||
MyException: ExceptionValue
|
||||
'''
|
||||
parsed = ParsedException.from_string(tb)
|
||||
assert parsed.exc_type == 'MyException'
|
||||
assert parsed.exc_msg == ' ExceptionValue'
|
||||
assert parsed.frames == [
|
||||
{
|
||||
'source_line': 'return some_other_function(1)',
|
||||
'filepath': '<string>',
|
||||
'lineno': '2',
|
||||
'funcname': '_some_function'
|
||||
},
|
||||
{
|
||||
'source_line': 'return foo(bar, baz)',
|
||||
'filepath': 'myfile.py',
|
||||
'lineno': '3',
|
||||
'funcname': 'some_other_function',
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
def test_eval_tb():
|
||||
tb = '''\
|
||||
Traceback (most recent call last):
|
||||
File "<string>", line 2, in _some_function
|
||||
File "myfile.py", line 3, in some_other_function
|
||||
return foo(bar, baz)
|
||||
MyException: ExceptionValue
|
||||
'''
|
||||
parsed = ParsedException.from_string(tb)
|
||||
assert parsed.exc_type == 'MyException'
|
Loading…
Reference in New Issue