optimize argument slicing when calling plugin hooks
This commit is contained in:
parent
f250e912eb
commit
c7c4f62f77
|
@ -292,6 +292,7 @@ class MultiCall:
|
|||
def __init__(self, methods, kwargs, firstresult=False):
|
||||
self.methods = list(methods)
|
||||
self.kwargs = kwargs
|
||||
self.kwargs["__multicall__"] = self
|
||||
self.results = []
|
||||
self.firstresult = firstresult
|
||||
|
||||
|
@ -302,11 +303,12 @@ class MultiCall:
|
|||
def execute(self):
|
||||
next_finalizers = []
|
||||
try:
|
||||
all_kwargs = self.kwargs
|
||||
while self.methods:
|
||||
method = self.methods.pop()
|
||||
kwargs = self.getkwargs(method)
|
||||
args = [all_kwargs[argname] for argname in varnames(method)]
|
||||
if hasattr(method, "hookwrapper"):
|
||||
it = method(**kwargs)
|
||||
it = method(*args)
|
||||
next = getattr(it, "next", None)
|
||||
if next is None:
|
||||
next = getattr(it, "__next__", None)
|
||||
|
@ -316,7 +318,7 @@ class MultiCall:
|
|||
res = next()
|
||||
next_finalizers.append((method, next))
|
||||
else:
|
||||
res = method(**kwargs)
|
||||
res = method(*args)
|
||||
if res is not None:
|
||||
self.results.append(res)
|
||||
if self.firstresult:
|
||||
|
@ -334,16 +336,6 @@ class MultiCall:
|
|||
"wrapper contain more than one yield")
|
||||
|
||||
|
||||
def getkwargs(self, method):
|
||||
kwargs = {}
|
||||
for argname in varnames(method):
|
||||
try:
|
||||
kwargs[argname] = self.kwargs[argname]
|
||||
except KeyError:
|
||||
if argname == "__multicall__":
|
||||
kwargs[argname] = self
|
||||
return kwargs
|
||||
|
||||
def varnames(func):
|
||||
""" return argument name tuple for a function, method, class or callable.
|
||||
|
||||
|
@ -371,12 +363,17 @@ def varnames(func):
|
|||
x = rawcode.co_varnames[ismethod:rawcode.co_argcount]
|
||||
except AttributeError:
|
||||
x = ()
|
||||
else:
|
||||
defaults = func.__defaults__
|
||||
if defaults:
|
||||
x = x[:-len(defaults)]
|
||||
try:
|
||||
cache["_varnames"] = x
|
||||
except TypeError:
|
||||
pass
|
||||
return x
|
||||
|
||||
|
||||
class HookRelay:
|
||||
def __init__(self, hookspecs, pm, prefix="pytest_"):
|
||||
if not isinstance(hookspecs, list):
|
||||
|
|
|
@ -142,7 +142,7 @@ def pytest_generate_tests(metafunc):
|
|||
# -------------------------------------------------------------------------
|
||||
# generic runtest related hooks
|
||||
# -------------------------------------------------------------------------
|
||||
def pytest_itemstart(item, node=None):
|
||||
def pytest_itemstart(item, node):
|
||||
""" (deprecated, use pytest_runtest_logstart). """
|
||||
|
||||
def pytest_runtest_protocol(item, nextitem):
|
||||
|
|
|
@ -436,6 +436,11 @@ def test_varnames():
|
|||
assert varnames(A().f) == ('y',)
|
||||
assert varnames(B()) == ('z',)
|
||||
|
||||
def test_varnames_default():
|
||||
def f(x, y=3):
|
||||
pass
|
||||
assert varnames(f) == ("x",)
|
||||
|
||||
def test_varnames_class():
|
||||
class C:
|
||||
def __init__(self, x):
|
||||
|
@ -494,12 +499,10 @@ class TestMultiCall:
|
|||
return x + z
|
||||
reslist = MultiCall([f], dict(x=23, y=24)).execute()
|
||||
assert reslist == [24]
|
||||
reslist = MultiCall([f], dict(x=23, z=2)).execute()
|
||||
assert reslist == [25]
|
||||
|
||||
def test_tags_call_error(self):
|
||||
multicall = MultiCall([lambda x: x], {})
|
||||
pytest.raises(TypeError, multicall.execute)
|
||||
pytest.raises(KeyError, multicall.execute)
|
||||
|
||||
def test_call_subexecute(self):
|
||||
def m(__multicall__):
|
||||
|
|
Loading…
Reference in New Issue