Fix situation where a traceback entry "path" returns a str object

Fix #1133
This commit is contained in:
Bruno Oliveira 2015-10-16 20:08:12 -03:00
parent 3b11995dbe
commit 311b0a9683
3 changed files with 47 additions and 16 deletions

View File

@ -7,6 +7,10 @@
- fix #331: don't collect tests if their failure cannot be reported correctly - fix #331: don't collect tests if their failure cannot be reported correctly
e.g. they are a callable instance of a class. e.g. they are a callable instance of a class.
- fix #1133: fixed internal error when filtering tracebacks where one entry
belongs to a file which is no longer available.
Thanks Bruno Oliveira for the PR.
2.8.2 2.8.2
----- -----
@ -50,9 +54,9 @@
"pytest-xdist" plugin, with test reports being assigned to the wrong tests. "pytest-xdist" plugin, with test reports being assigned to the wrong tests.
Thanks Daniel Grunwald for the report and Bruno Oliveira for the PR. Thanks Daniel Grunwald for the report and Bruno Oliveira for the PR.
- (experimental) adapt more SEMVER style versioning and change meaning of - (experimental) adapt more SEMVER style versioning and change meaning of
master branch in git repo: "master" branch now keeps the bugfixes, changes master branch in git repo: "master" branch now keeps the bugfixes, changes
aimed for micro releases. "features" branch will only be be released aimed for micro releases. "features" branch will only be be released
with minor or major pytest releases. with minor or major pytest releases.
- Fix issue #766 by removing documentation references to distutils. - Fix issue #766 by removing documentation references to distutils.
@ -77,7 +81,7 @@
----------------------------- -----------------------------
- new ``--lf`` and ``-ff`` options to run only the last failing tests or - new ``--lf`` and ``-ff`` options to run only the last failing tests or
"failing tests first" from the last run. This functionality is provided "failing tests first" from the last run. This functionality is provided
through porting the formerly external pytest-cache plugin into pytest core. through porting the formerly external pytest-cache plugin into pytest core.
BACKWARD INCOMPAT: if you used pytest-cache's functionality to persist BACKWARD INCOMPAT: if you used pytest-cache's functionality to persist
data between test runs be aware that we don't serialize sets anymore. data between test runs be aware that we don't serialize sets anymore.
@ -183,9 +187,9 @@
- fix issue735: assertion failures on debug versions of Python 3.4+ - fix issue735: assertion failures on debug versions of Python 3.4+
- new option ``--import-mode`` to allow to change test module importing - new option ``--import-mode`` to allow to change test module importing
behaviour to append to sys.path instead of prepending. This better allows behaviour to append to sys.path instead of prepending. This better allows
to run test modules against installated versions of a package even if the to run test modules against installated versions of a package even if the
package under test has the same import root. In this example:: package under test has the same import root. In this example::
testing/__init__.py testing/__init__.py
@ -193,7 +197,7 @@
pkg_under_test/ pkg_under_test/
the tests will run against the installed version the tests will run against the installed version
of pkg_under_test when ``--import-mode=append`` is used whereas of pkg_under_test when ``--import-mode=append`` is used whereas
by default they would always pick up the local version. Thanks Holger Krekel. by default they would always pick up the local version. Thanks Holger Krekel.
- pytester: add method ``TmpTestdir.delete_loaded_modules()``, and call it - pytester: add method ``TmpTestdir.delete_loaded_modules()``, and call it

View File

@ -58,14 +58,17 @@ def _has_positional_arg(func):
def filter_traceback(entry): def filter_traceback(entry):
# entry.path might sometimes return a str() object when the entry # entry.path might sometimes return a str object when the entry
# points to dynamically generated code # points to dynamically generated code
# see https://bitbucket.org/pytest-dev/py/issues/71 # see https://bitbucket.org/pytest-dev/py/issues/71
raw_filename = entry.frame.code.raw.co_filename raw_filename = entry.frame.code.raw.co_filename
is_generated = '<' in raw_filename and '>' in raw_filename is_generated = '<' in raw_filename and '>' in raw_filename
if is_generated: if is_generated:
return False return False
return entry.path != cutdir1 and not entry.path.relto(cutdir2) # entry.path might point to an inexisting file, in which case it will
# alsso return a str object. see #1133
p = py.path.local(entry.path)
return p != cutdir1 and not p.relto(cutdir2)
def get_real_func(obj): def get_real_func(obj):

View File

@ -771,10 +771,12 @@ class TestTracebackCutting:
"* 1 error in *", "* 1 error in *",
]) ])
def test_filter_traceback_accepts_non_paths(self): def test_filter_traceback_generated_code(self):
"""test that filter_traceback() works around py.code.Code bug """test that filter_traceback() works with the fact that
where sometimes its "path" attribute is not a py.path.local object: py.code.Code.path attribute might return an str object.
https://bitbucket.org/pytest-dev/py/issues/71 In this case, one of the entries on the traceback was produced by
dynamically generated code.
See: https://bitbucket.org/pytest-dev/py/issues/71
This fixes #995. This fixes #995.
""" """
from _pytest.python import filter_traceback from _pytest.python import filter_traceback
@ -783,13 +785,35 @@ class TestTracebackCutting:
exec('def foo(): raise ValueError', ns) exec('def foo(): raise ValueError', ns)
ns['foo']() ns['foo']()
except ValueError: except ValueError:
import sys
_, _, tb = sys.exc_info() _, _, tb = sys.exc_info()
tb = py.code.Traceback(tb) tb = py.code.Traceback(tb)
assert isinstance(tb[-1].path, str) # symptom of the py.code bug assert isinstance(tb[-1].path, str)
assert not filter_traceback(tb[-1]) assert not filter_traceback(tb[-1])
def test_filter_traceback_path_no_longer_valid(self, testdir):
"""test that filter_traceback() works with the fact that
py.code.Code.path attribute might return an str object.
In this case, one of the files in the traceback no longer exists.
This fixes #1133.
"""
from _pytest.python import filter_traceback
testdir.syspathinsert()
testdir.makepyfile(filter_traceback_entry_as_str='''
def foo():
raise ValueError
''')
try:
import filter_traceback_entry_as_str
filter_traceback_entry_as_str.foo()
except ValueError:
_, _, tb = sys.exc_info()
testdir.tmpdir.join('filter_traceback_entry_as_str.py').remove()
tb = py.code.Traceback(tb)
assert isinstance(tb[-1].path, str)
assert filter_traceback(tb[-1])
class TestReportInfo: class TestReportInfo:
def test_itemreport_reportinfo(self, testdir, linecomp): def test_itemreport_reportinfo(self, testdir, linecomp):