fix issue 655: crude workarounds around python2/3 exception leaks

This commit is contained in:
Ronny Pfannschmidt 2015-01-09 19:55:49 +01:00
parent bca19a1156
commit 5941b2e071
3 changed files with 38 additions and 5 deletions

View File

@ -1,6 +1,9 @@
2.7.0.dev (compared to 2.6.4) 2.7.0.dev (compared to 2.6.4)
----------------------------- -----------------------------
- fix issue655: work around different ways that cause python2/3
to leak sys.exc_info into fixtures/tests causing failures in 3rd party code
- fix issue615: assertion re-writing did not correctly escape % signs - fix issue615: assertion re-writing did not correctly escape % signs
when formatting boolean operations, which tripped over mixing when formatting boolean operations, which tripped over mixing
booleans with modulo operators. Thanks to Tom Viner for the report, booleans with modulo operators. Thanks to Tom Viner for the report,

View File

@ -15,6 +15,8 @@ NOTSET = object()
isfunction = inspect.isfunction isfunction = inspect.isfunction
isclass = inspect.isclass isclass = inspect.isclass
callable = py.builtin.callable callable = py.builtin.callable
# used to work around a python2 exception info leak
exc_clear = getattr(sys, 'exc_clear', lambda: None)
def getfslineno(obj): def getfslineno(obj):
# xxx let decorators etc specify a sane ordering # xxx let decorators etc specify a sane ordering
@ -1389,10 +1391,12 @@ class FixtureRequest(FuncargnamesCompatAttr):
cached_result = (self, [0], None) cached_result = (self, [0], None)
return PseudoFixtureDef return PseudoFixtureDef
raise raise
result = self._getfuncargvalue(fixturedef) # remove indent to prevent the python3 exception
self._funcargs[argname] = result # from leaking into the call
self._fixturedefs[argname] = fixturedef result = self._getfuncargvalue(fixturedef)
return fixturedef self._funcargs[argname] = result
self._fixturedefs[argname] = fixturedef
return fixturedef
def _get_fixturestack(self): def _get_fixturestack(self):
current = self current = self
@ -1439,6 +1443,9 @@ class FixtureRequest(FuncargnamesCompatAttr):
(scope, argname, self.scope, "\n".join(lines)))) (scope, argname, self.scope, "\n".join(lines))))
__tracebackhide__ = False __tracebackhide__ = False
# clear sys.exc_info before invoking the fixture (python bug?)
# if its not explicitly cleared it will leak into the call
exc_clear()
try: try:
# call the fixture function # call the fixture function
val = fixturedef.execute(request=subrequest) val = fixturedef.execute(request=subrequest)

View File

@ -261,6 +261,29 @@ class TestFillFixtures:
]) ])
assert "INTERNAL" not in result.stdout.str() assert "INTERNAL" not in result.stdout.str()
def test_fixture_excinfo_leak(self, testdir):
# on python2 sys.excinfo would leak into fixture executions
testdir.makepyfile("""
import sys
import traceback
import pytest
@pytest.fixture
def leak():
if sys.exc_info()[0]: # python3 bug :)
traceback.print_exc()
#fails
assert sys.exc_info() == (None, None, None)
def test_leak(leak):
if sys.exc_info()[0]: # python3 bug :)
traceback.print_exc()
assert sys.exc_info() == (None, None, None)
""")
result = testdir.runpytest()
assert result.ret == 0
class TestRequestBasic: class TestRequestBasic:
def test_request_attributes(self, testdir): def test_request_attributes(self, testdir):
item = testdir.getitem(""" item = testdir.getitem("""