[svn r63797] introduce a clean "guardedcall" interface for performing calls with exception catching and stdout/stderr capturing

--HG--
branch : trunk
This commit is contained in:
hpk 2009-04-07 16:27:57 +02:00
parent 4893c58d22
commit bba69f207b
3 changed files with 62 additions and 30 deletions

View File

@ -286,6 +286,28 @@ class Config(object):
roots.append(pydir)
return roots
def guardedcall(self, func):
excinfo = result = None
capture = self._getcapture()
try:
try:
result = func()
except KeyboardInterrupt:
raise
except:
excinfo = py.code.ExceptionInfo()
finally:
stdout, stderr = capture.reset()
return CallResult(result, excinfo, stdout, stderr)
class CallResult:
def __init__(self, result, excinfo, stdout, stderr):
self.stdout = stdout
self.stderr = stderr
self.outerr = (self.stdout, self.stderr)
self.excinfo = excinfo
if excinfo is None:
self.result = result
#
# helpers

View File

@ -198,41 +198,22 @@ class SetupState(object):
self.stack.append(col)
def do_setup(self, item):
excinfo, outerr = guarded_call(item.config._getcapture(),
lambda: self.prepare(item)
)
rep = ItemSetupReport(item, excinfo, outerr)
call = item.config.guardedcall(lambda: self.prepare(item))
rep = ItemSetupReport(item, call.excinfo, call.outerr)
item.config.pytestplugins.notify("itemsetupreport", rep)
return not excinfo
return not call.excinfo
def do_teardown(self, item):
excinfo, outerr = guarded_call(item.config._getcapture(),
lambda: self.teardown_exact(item)
)
if excinfo:
rep = ItemSetupReport(item, excinfo, outerr)
call = item.config.guardedcall(lambda: self.teardown_exact(item))
if call.excinfo:
rep = ItemSetupReport(item, call.excinfo, call.outerr)
item.config.pytestplugins.notify("itemsetupreport", rep)
def do_fixture_and_runtest(self, item):
""" setup fixture and perform actual item.runtest(). """
if self.do_setup(item):
excinfo, outerr = guarded_call(item.config._getcapture(),
lambda: item.runtest())
call = item.config.guardedcall(lambda: item.runtest())
item.config.pytestplugins.notify(
"item_runtest_finished",
item=item, excinfo=excinfo, outerr=outerr)
item=item, excinfo=call.excinfo, outerr=call.outerr)
self.do_teardown(item)
def guarded_call(capture, call):
excinfo = None
try:
try:
call()
except (KeyboardInterrupt, Exit):
raise
except:
excinfo = py.code.ExceptionInfo()
finally:
outerr = capture.reset()
return excinfo, outerr

View File

@ -137,8 +137,7 @@ class TestConfigAPI:
assert pl[1] == somepath
def test_setsessionclass_and_initsession(self, testdir):
from py.__.test.config import Config
config = Config()
config = testdir.Config()
class Session1:
def __init__(self, config):
self.config = config
@ -149,7 +148,6 @@ class TestConfigAPI:
py.test.raises(ValueError, "config.setsessionclass(Session1)")
class TestConfigApi_getcolitems:
def test_getcolitems_onedir(self, tmpdir):
config = py.test.config._reparse([tmpdir])
@ -214,6 +212,37 @@ class TestConfigApi_getcolitems:
assert col.config is config
class TestGuardedCall:
def test_guardedcall_ok(self, testdir):
config = testdir.parseconfig()
def myfunc(x):
print x
print >>py.std.sys.stderr, "hello"
return 7
call = config.guardedcall(lambda: myfunc(3))
assert call.excinfo is None
assert call.result == 7
assert call.stdout.startswith("3")
assert call.stderr.startswith("hello")
def test_guardedcall_fail(self, testdir):
config = testdir.parseconfig()
def myfunc(x):
print x
raise ValueError(17)
call = config.guardedcall(lambda: myfunc(3))
assert call.excinfo
assert call.excinfo.type == ValueError
assert not hasattr(call, 'result')
assert call.stdout.startswith("3")
assert not call.stderr
def test_guardedcall_keyboardinterrupt(self, testdir):
config = testdir.parseconfig()
def myfunc():
raise KeyboardInterrupt
py.test.raises(KeyboardInterrupt, config.guardedcall, myfunc)
class TestOptionEffects:
def test_boxed_option_default(self, testdir):
tmpdir = testdir.tmpdir.ensure("subdir", dir=1)