catch IndexError exceptions when getting exception source location

This commit is contained in:
Anatoly Bubenkov 2015-09-15 01:14:58 +02:00 committed by Ryan Wooden
parent 310bada6f5
commit cf9a09e988
3 changed files with 48 additions and 1 deletions

View File

@ -526,6 +526,10 @@
directories created by this fixture (defaults to $TEMP/pytest-$USER).
Thanks Bruno Oliveira for the PR.
- catch IndexError exceptions when getting exception source location. This fixes
pytest internal error for dynamically generated code (fixtures and tests)
where source lines are fake by intention
2.7.2 (compared to 2.7.1)
=============================

View File

@ -1774,7 +1774,7 @@ class FixtureLookupError(LookupError):
fspath, lineno = getfslineno(function)
try:
lines, _ = inspect.getsourcelines(get_real_func(function))
except IOError:
except (IOError, IndexError):
error_msg = "file %s, line %s: source code not available"
addline(error_msg % (fspath, lineno+1))
else:

View File

@ -568,6 +568,49 @@ def test_makereport_getsource(testdir):
result.stdout.fnmatch_lines(['*else: assert False*'])
def test_makereport_getsource_dynamic_code(testdir):
"""Test that exception in dynamically generated code doesn't break getting the source line."""
sub = testdir.mkdir("sub")
sub.join("__init__.py").write("")
sub.join("fixtures.py").write(py.std.textwrap.dedent(
"""
import sys
import pytest
import inspect
def get_caller_module(depth=2):
frame = sys._getframe(depth)
module = inspect.getmodule(frame)
if module is None:
return get_caller_module(depth=depth)
return module
def inject():
context = {}
exec('''
import pytest
@pytest.fixture
def foo(request):
request.getfuncargvalue('sone')
''', context)
module = get_caller_module()
foo = context['foo']
module.foo = foo
inject()
"""))
sub.join("conftest.py").write("""from fixtures import foo""")
sub.join("test_dynamic.py").write(py.std.textwrap.dedent(
"""
def test_foo(foo):
pass
"""))
result = testdir.runpytest('-vv')
assert 'INTERNALERROR' not in result.stdout.str()
result.stdout.fnmatch_lines(['*else: assert False*'])
def test_store_except_info_on_eror():
""" Test that upon test failure, the exception info is stored on
sys.last_traceback and friends.