simplify method to record calls

This commit is contained in:
holger krekel 2014-10-04 15:49:31 +02:00
parent d8f4663f49
commit 3d84f35850
3 changed files with 15 additions and 60 deletions

View File

@ -416,7 +416,6 @@ class HookRelay:
def __init__(self, hookspecs, pm, prefix="pytest_"):
if not isinstance(hookspecs, list):
hookspecs = [hookspecs]
self._hookspecs = []
self._pm = pm
self.trace = pm.trace.root.get("hook")
self.prefix = prefix
@ -424,7 +423,6 @@ class HookRelay:
self._addhooks(hookspec, prefix)
def _addhooks(self, hookspec, prefix):
self._hookspecs.append(hookspec)
added = False
isclass = int(inspect.isclass(hookspec))
for name, method in vars(hookspec).items():

View File

@ -12,7 +12,7 @@ import subprocess
import py
import pytest
from py.builtin import print_
from _pytest.core import HookRelay
from _pytest.core import HookRelay, HookCaller, Wrapping
from _pytest.main import Session, EXIT_OK
@ -51,10 +51,8 @@ class PytestArg:
return hookrecorder
class ParsedCall:
def __init__(self, name, locals):
assert '_name' not in locals
self.__dict__.update(locals)
self.__dict__.pop('self')
def __init__(self, name, kwargs):
self.__dict__.update(kwargs)
self._name = name
def __repr__(self):
@ -62,64 +60,24 @@ class ParsedCall:
del d['_name']
return "<ParsedCall %r(**%r)>" %(self._name, d)
class HookRecorder:
def __init__(self, pluginmanager):
self._pluginmanager = pluginmanager
self.calls = []
self._recorders = {}
hookspecs = self._pluginmanager.hook._hookspecs
for hookspec in hookspecs:
assert hookspec not in self._recorders
class RecordCalls:
_recorder = self
for name, method in vars(hookspec).items():
if name[0] != "_":
setattr(RecordCalls, name, self._makecallparser(method))
recorder = RecordCalls()
self._recorders[hookspec] = recorder
self._pluginmanager.register(recorder)
self.hook = HookRelay(hookspecs, pm=self._pluginmanager,
prefix="pytest_")
self.wrapping = Wrapping()
@self.wrapping.method(HookCaller)
def _docall(hookcaller, methods, kwargs):
self.calls.append(ParsedCall(hookcaller.name, kwargs))
yield
def finish_recording(self):
for recorder in self._recorders.values():
if self._pluginmanager.isregistered(recorder):
self._pluginmanager.unregister(recorder)
self._recorders.clear()
def _makecallparser(self, method):
name = method.__name__
args, varargs, varkw, default = inspect.getargspec(method)
if not args or args[0] != "self":
args.insert(0, 'self')
fspec = inspect.formatargspec(args, varargs, varkw, default)
# we use exec because we want to have early type
# errors on wrong input arguments, using
# *args/**kwargs delays this and gives errors
# elsewhere
exec (py.code.compile("""
def %(name)s%(fspec)s:
self._recorder.calls.append(
ParsedCall(%(name)r, locals()))
""" % locals()))
return locals()[name]
self.wrapping.undo()
def getcalls(self, names):
if isinstance(names, str):
names = names.split()
for name in names:
for cls in self._recorders:
if name in vars(cls):
break
else:
raise ValueError("callname %r not found in %r" %(
name, self._recorders.keys()))
l = []
for call in self.calls:
if call._name in names:
l.append(call)
return l
return [call for call in self.calls if call._name in names]
def contains(self, entries):
__tracebackhide__ = True
@ -228,10 +186,9 @@ class TmpTestdir:
obj = obj.config
if hasattr(obj, 'hook'):
obj = obj.hook
assert hasattr(obj, '_hookspecs'), obj
assert isinstance(obj, HookRelay)
reprec = ReportRecorder(obj)
reprec.hookrecorder = self._pytest.gethookrecorder(obj)
reprec.hook = reprec.hookrecorder.hook
return reprec
def chdir(self):

View File

@ -94,12 +94,12 @@ def test_hookrecorder_basic(holder):
pm = PluginManager()
pm.hook._addhooks(holder, "pytest_")
rec = HookRecorder(pm)
rec.hook.pytest_xyz(arg=123)
pm.hook.pytest_xyz(arg=123)
call = rec.popcall("pytest_xyz")
assert call.arg == 123
assert call._name == "pytest_xyz"
pytest.raises(pytest.fail.Exception, "rec.popcall('abc')")
rec.hook.pytest_xyz_noarg()
pm.hook.pytest_xyz_noarg()
call = rec.popcall("pytest_xyz_noarg")
assert call._name == "pytest_xyz_noarg"
@ -119,7 +119,7 @@ def test_functional(testdir, linecomp):
def pytest_xyz(self, arg):
return arg + 1
rec._pluginmanager.register(Plugin())
res = rec.hook.pytest_xyz(arg=41)
res = pm.hook.pytest_xyz(arg=41)
assert res == [42]
""")
reprec.assertoutcome(passed=1)