diff --git a/pluggy/__init__.py b/pluggy/__init__.py index 46011b8e..870b6c9c 100644 --- a/pluggy/__init__.py +++ b/pluggy/__init__.py @@ -212,7 +212,8 @@ def __init__(self, project_name, implprefix=None): self._implprefix = implprefix self._inner_hookexec = lambda hook, methods, kwargs: \ hook.multicall( - methods, kwargs, specopts=hook.spec_opts, hook=hook + methods, kwargs, + firstresult=hook.spec_opts.get('firstresult'), ) def _hookexec(self, hook, methods, kwargs): @@ -528,20 +529,22 @@ def __init__(self, trace): class _HookCaller(object): - def __init__(self, name, hook_execute, specmodule_or_class=None, spec_opts=None): + def __init__(self, name, hook_execute, specmodule_or_class=None, + spec_opts=None): self.name = name self._wrappers = [] self._nonwrappers = [] self._hookexec = hook_execute + self._specmodule_or_class = None self.argnames = None self.kwargnames = None self.multicall = _multicall + self.spec_opts = spec_opts or {} if specmodule_or_class is not None: - assert spec_opts is not None self.set_specification(specmodule_or_class, spec_opts) def has_spec(self): - return hasattr(self, "_specmodule_or_class") + return self._specmodule_or_class is not None def set_specification(self, specmodule_or_class, spec_opts): assert not self.has_spec() @@ -550,7 +553,7 @@ def set_specification(self, specmodule_or_class, spec_opts): # get spec arg signature argnames, self.kwargnames = varnames(specfunc) self.argnames = ["__multicall__"] + list(argnames) - self.spec_opts = spec_opts + self.spec_opts.update(spec_opts) if spec_opts.get("historic"): self._call_history = [] diff --git a/pluggy/callers.py b/pluggy/callers.py index 3189f8aa..3ff67bec 100644 --- a/pluggy/callers.py +++ b/pluggy/callers.py @@ -105,17 +105,16 @@ class _LegacyMultiCall(object): # so we can remove it soon, allowing to avoid the below recursion # in execute() and simplify/speed up the execute loop. - def __init__(self, hook_impls, kwargs, specopts={}, hook=None): - self.hook = hook + def __init__(self, hook_impls, kwargs, firstresult=False): self.hook_impls = hook_impls self.caller_kwargs = kwargs # come from _HookCaller.__call__() self.caller_kwargs["__multicall__"] = self - self.specopts = hook.spec_opts if hook else specopts + self.firstresult = firstresult def execute(self): caller_kwargs = self.caller_kwargs self.results = results = [] - firstresult = self.specopts.get("firstresult") + firstresult = self.firstresult while self.hook_impls: hook_impl = self.hook_impls.pop() @@ -144,21 +143,19 @@ def __repr__(self): return "<_MultiCall %s, kwargs=%r>" % (status, self.caller_kwargs) -def _legacymulticall(hook_impls, caller_kwargs, specopts={}, hook=None): +def _legacymulticall(hook_impls, caller_kwargs, firstresult=False): return _LegacyMultiCall( - hook_impls, caller_kwargs, specopts=specopts, hook=hook).execute() + hook_impls, caller_kwargs, firstresult=firstresult).execute() -def _multicall(hook_impls, caller_kwargs, specopts={}, hook=None): +def _multicall(hook_impls, caller_kwargs, firstresult=False): """Execute a call into multiple python functions/methods and return the result(s). ``caller_kwargs`` comes from _HookCaller.__call__(). """ __tracebackhide__ = True - specopts = hook.spec_opts if hook else specopts results = [] - firstresult = specopts.get("firstresult") excinfo = None try: # run impl and wrapper setup functions in a loop teardowns = [] diff --git a/testing/test_method_ordering.py b/testing/test_method_ordering.py index 168bc562..9584a0ae 100644 --- a/testing/test_method_ordering.py +++ b/testing/test_method_ordering.py @@ -290,15 +290,17 @@ def he_method1(self): undo() -def test_prefix_hookimpl(): +@pytest.mark.parametrize('include_hookspec', [True, False]) +def test_prefix_hookimpl(include_hookspec): pm = PluginManager(hookspec.project_name, "hello_") - class HookSpec(object): - @hookspec - def hello_myhook(self, arg1): - """ add to arg1 """ + if include_hookspec: + class HookSpec(object): + @hookspec + def hello_myhook(self, arg1): + """ add to arg1 """ - pm.add_hookspecs(HookSpec) + pm.add_hookspecs(HookSpec) class Plugin(object): def hello_myhook(self, arg1): diff --git a/testing/test_multicall.py b/testing/test_multicall.py index 03122319..860a209b 100644 --- a/testing/test_multicall.py +++ b/testing/test_multicall.py @@ -26,7 +26,7 @@ def MC(methods, kwargs, firstresult=False): hookfuncs.append(f) if '__multicall__' in f.argnames: caller = _legacymulticall - return caller(hookfuncs, kwargs, specopts={"firstresult": firstresult}) + return caller(hookfuncs, kwargs, firstresult=firstresult) def test_call_passing(): @@ -105,7 +105,7 @@ def m1(): def m2(): return None - res = MC([m1, m2], {}, {"firstresult": True}) + res = MC([m1, m2], {}, firstresult=True) assert res == 1 res = MC([m1, m2], {}, {}) assert res == [1] @@ -129,7 +129,7 @@ def m2(): assert res == [2] assert out == ["m1 init", "m2", "m1 finish"] out[:] = [] - res = MC([m2, m1], {}, {"firstresult": True}) + res = MC([m2, m1], {}, firstresult=True) assert res == 2 assert out == ["m1 init", "m2", "m1 finish"]