diff --git a/_pytest/core.py b/_pytest/core.py index 04752dd71..d871e7418 100644 --- a/_pytest/core.py +++ b/_pytest/core.py @@ -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): diff --git a/_pytest/hookspec.py b/_pytest/hookspec.py index 6d1420740..0cc59f259 100644 --- a/_pytest/hookspec.py +++ b/_pytest/hookspec.py @@ -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): diff --git a/testing/test_core.py b/testing/test_core.py index 018532cc2..2fd7ace10 100644 --- a/testing/test_core.py +++ b/testing/test_core.py @@ -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__):