factor out a small "wrapping" helper
This commit is contained in:
parent
69ff29bf44
commit
d8f4663f49
|
@ -67,6 +67,24 @@ class TagTracerSub:
|
||||||
def get(self, name):
|
def get(self, name):
|
||||||
return self.__class__(self.root, self.tags + (name,))
|
return self.__class__(self.root, self.tags + (name,))
|
||||||
|
|
||||||
|
def add_method_controller(cls, func):
|
||||||
|
name = func.__name__
|
||||||
|
oldcall = getattr(cls, name)
|
||||||
|
def wrap_exec(*args, **kwargs):
|
||||||
|
gen = func(*args, **kwargs)
|
||||||
|
gen.next() # first yield
|
||||||
|
res = oldcall(*args, **kwargs)
|
||||||
|
try:
|
||||||
|
gen.send(res)
|
||||||
|
except StopIteration:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
raise ValueError("expected StopIteration")
|
||||||
|
return res
|
||||||
|
setattr(cls, name, wrap_exec)
|
||||||
|
return lambda: setattr(cls, name, oldcall)
|
||||||
|
|
||||||
|
|
||||||
class PluginManager(object):
|
class PluginManager(object):
|
||||||
def __init__(self, hookspecs=None, prefix="pytest_"):
|
def __init__(self, hookspecs=None, prefix="pytest_"):
|
||||||
self._name2plugin = {}
|
self._name2plugin = {}
|
||||||
|
@ -80,23 +98,24 @@ class PluginManager(object):
|
||||||
|
|
||||||
def set_tracing(self, writer):
|
def set_tracing(self, writer):
|
||||||
self.trace.root.setwriter(writer)
|
self.trace.root.setwriter(writer)
|
||||||
# we reconfigure HookCalling to perform tracing
|
# reconfigure HookCalling to perform tracing
|
||||||
# and we avoid doing the "do we need to trace" check dynamically
|
assert not hasattr(self, "_wrapping")
|
||||||
# for speed reasons
|
self._wrapping = True
|
||||||
assert HookCaller._docall.__name__ == "_docall"
|
|
||||||
real_docall = HookCaller._docall
|
def _docall(self, methods, kwargs):
|
||||||
def docall_tracing(self, methods, kwargs):
|
|
||||||
trace = self.hookrelay.trace
|
trace = self.hookrelay.trace
|
||||||
trace.root.indent += 1
|
trace.root.indent += 1
|
||||||
trace(self.name, kwargs)
|
trace(self.name, kwargs)
|
||||||
|
res = None
|
||||||
try:
|
try:
|
||||||
res = real_docall(self, methods, kwargs)
|
res = yield
|
||||||
|
finally:
|
||||||
if res:
|
if res:
|
||||||
trace("finish", self.name, "-->", res)
|
trace("finish", self.name, "-->", res)
|
||||||
finally:
|
|
||||||
trace.root.indent -= 1
|
trace.root.indent -= 1
|
||||||
return res
|
|
||||||
HookCaller._docall = docall_tracing
|
undo = add_method_controller(HookCaller, _docall)
|
||||||
|
self.add_shutdown(undo)
|
||||||
|
|
||||||
def do_configure(self, config):
|
def do_configure(self, config):
|
||||||
# backward compatibility
|
# backward compatibility
|
||||||
|
|
|
@ -765,3 +765,23 @@ def test_importplugin_issue375(testdir):
|
||||||
assert "qwe" not in str(excinfo.value)
|
assert "qwe" not in str(excinfo.value)
|
||||||
assert "aaaa" in str(excinfo.value)
|
assert "aaaa" in str(excinfo.value)
|
||||||
|
|
||||||
|
|
||||||
|
def test_wrapping():
|
||||||
|
class A:
|
||||||
|
def f(self):
|
||||||
|
return "A.f"
|
||||||
|
|
||||||
|
shutdown = []
|
||||||
|
l = []
|
||||||
|
def f(self):
|
||||||
|
l.append(1)
|
||||||
|
x = yield
|
||||||
|
l.append(2)
|
||||||
|
undo = add_method_controller(A, f)
|
||||||
|
|
||||||
|
assert A().f() == "A.f"
|
||||||
|
assert l == [1,2]
|
||||||
|
undo()
|
||||||
|
l[:] = []
|
||||||
|
assert A().f() == "A.f"
|
||||||
|
assert l == []
|
||||||
|
|
Loading…
Reference in New Issue