fix issue 655: crude workarounds around python2/3 exception leaks
This commit is contained in:
parent
bca19a1156
commit
5941b2e071
|
@ -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,
|
||||||
|
@ -14,7 +17,7 @@
|
||||||
which want to wrap the execution of certain hooks for their purposes.
|
which want to wrap the execution of certain hooks for their purposes.
|
||||||
This supersedes the undocumented ``__multicall__`` protocol which
|
This supersedes the undocumented ``__multicall__`` protocol which
|
||||||
pytest itself and some external plugins use. Note that pytest-2.8
|
pytest itself and some external plugins use. Note that pytest-2.8
|
||||||
is scheduled to drop supporting the old ``__multicall__``
|
is scheduled to drop supporting the old ``__multicall__``
|
||||||
and only support the hookwrapper protocol.
|
and only support the hookwrapper protocol.
|
||||||
|
|
||||||
- use hookwrapper mechanism in builtin pytest plugins.
|
- use hookwrapper mechanism in builtin pytest plugins.
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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("""
|
||||||
|
|
Loading…
Reference in New Issue