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"
|
- "pypy"
|
||||||
|
|
||||||
install: "pip install -r requirements-test.txt"
|
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
|
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: chaining primitives? what are real use cases where these help?
|
||||||
|
|
||||||
# TODO: print_* for backwards compatability
|
# TODO: print_* for backwards compatability
|
||||||
|
@ -691,7 +697,7 @@ class ParsedException(object):
|
||||||
Args:
|
Args:
|
||||||
tb_str (str): The traceback text (:class:`unicode` or UTF-8 bytes)
|
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_str = tb_str.decode('utf-8')
|
||||||
tb_lines = tb_str.lstrip().splitlines()
|
tb_lines = tb_str.lstrip().splitlines()
|
||||||
|
|
||||||
|
@ -717,21 +723,27 @@ class ParsedException(object):
|
||||||
raise ValueError('unrecognized traceback string format')
|
raise ValueError('unrecognized traceback string format')
|
||||||
|
|
||||||
frames = []
|
frames = []
|
||||||
for pair_idx in range(start_line, len(tb_lines), 2):
|
line_no = start_line
|
||||||
frame_line = tb_lines[pair_idx].strip()
|
while True:
|
||||||
|
frame_line = tb_lines[line_no].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()
|
||||||
|
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:
|
else:
|
||||||
break
|
break
|
||||||
frame_dict['source_line'] = tb_lines[pair_idx + 1].strip()
|
line_no += 1
|
||||||
frames.append(frame_dict)
|
frames.append(frame_dict)
|
||||||
|
|
||||||
exc_line_offset = start_line + len(frames) * 2
|
|
||||||
try:
|
try:
|
||||||
exc_line = tb_lines[exc_line_offset]
|
exc_line = tb_lines[line_no]
|
||||||
exc_type, _, exc_msg = exc_line.partition(':')
|
exc_type, _, exc_msg = exc_line.partition(':')
|
||||||
except:
|
except Exception:
|
||||||
exc_type, exc_msg = '', ''
|
exc_type, exc_msg = '', ''
|
||||||
|
|
||||||
return cls(exc_type, exc_msg, frames)
|
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