From e129923bce4563f44d83e4d3690e47963e027e07 Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Thu, 17 May 2018 21:28:54 -0400 Subject: [PATCH] Drop __multicall__! Drop the `_LegacyMultiCall` type and it's recursion "fun". We've got a faster and simpler function-loop approach now with `pluggy.callers._multicall()` it's been doing great in production! Resolves #59 --- pluggy/callers.py | 71 ----------------------------------------------- pluggy/hooks.py | 15 ++-------- 2 files changed, 3 insertions(+), 83 deletions(-) diff --git a/pluggy/callers.py b/pluggy/callers.py index 3ff67bec..97ce88bf 100644 --- a/pluggy/callers.py +++ b/pluggy/callers.py @@ -77,77 +77,6 @@ def get_result(self): _reraise(*ex) # noqa -def _wrapped_call(wrap_controller, func): - """ Wrap calling to a function with a generator which needs to yield - exactly once. The yield point will trigger calling the wrapped function - and return its ``_Result`` to the yield point. The generator then needs - to finish (raise StopIteration) in order for the wrapped call to complete. - """ - try: - next(wrap_controller) # first yield - except StopIteration: - _raise_wrapfail(wrap_controller, "did not yield") - call_outcome = _Result.from_call(func) - try: - wrap_controller.send(call_outcome) - _raise_wrapfail(wrap_controller, "has second yield") - except StopIteration: - pass - return call_outcome.get_result() - - -class _LegacyMultiCall(object): - """ execute a call into multiple python functions/methods. """ - - # XXX note that the __multicall__ argument is supported only - # for pytest compatibility reasons. It was never officially - # supported there and is explicitely deprecated since 2.8 - # 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, firstresult=False): - self.hook_impls = hook_impls - self.caller_kwargs = kwargs # come from _HookCaller.__call__() - self.caller_kwargs["__multicall__"] = self - self.firstresult = firstresult - - def execute(self): - caller_kwargs = self.caller_kwargs - self.results = results = [] - firstresult = self.firstresult - - while self.hook_impls: - hook_impl = self.hook_impls.pop() - try: - args = [caller_kwargs[argname] for argname in hook_impl.argnames] - except KeyError: - for argname in hook_impl.argnames: - if argname not in caller_kwargs: - raise HookCallError( - "hook call must provide argument %r" % (argname,)) - if hook_impl.hookwrapper: - return _wrapped_call(hook_impl.function(*args), self.execute) - res = hook_impl.function(*args) - if res is not None: - if firstresult: - return res - results.append(res) - - if not firstresult: - return results - - def __repr__(self): - status = "%d meths" % (len(self.hook_impls),) - if hasattr(self, "results"): - status = ("%d results, " % len(self.results)) + status - return "<_MultiCall %s, kwargs=%r>" % (status, self.caller_kwargs) - - -def _legacymulticall(hook_impls, caller_kwargs, firstresult=False): - return _LegacyMultiCall( - hook_impls, caller_kwargs, firstresult=firstresult).execute() - - def _multicall(hook_impls, caller_kwargs, firstresult=False): """Execute a call into multiple python functions/methods and return the result(s). diff --git a/pluggy/hooks.py b/pluggy/hooks.py index 6841ba32..fa09885c 100644 --- a/pluggy/hooks.py +++ b/pluggy/hooks.py @@ -3,7 +3,7 @@ """ import inspect import warnings -from .callers import _legacymulticall, _multicall +from .callers import _multicall class HookspecMarker(object): @@ -192,7 +192,7 @@ def set_specification(self, specmodule_or_class, spec_opts): specfunc = getattr(specmodule_or_class, self.name) # get spec arg signature argnames, self.kwargnames = varnames(specfunc) - self.argnames = ["__multicall__"] + list(argnames) + self.argnames = list(argnames) self.spec_opts.update(spec_opts) if spec_opts.get("historic"): self._call_history = [] @@ -230,14 +230,6 @@ def _add_hookimpl(self, hookimpl): i -= 1 methods.insert(i + 1, hookimpl) - if '__multicall__' in hookimpl.argnames: - warnings.warn( - "Support for __multicall__ is now deprecated and will be" - "removed in an upcoming release.", - DeprecationWarning - ) - self.multicall = _legacymulticall - def __repr__(self): return "<_HookCaller %r>" % (self.name,) @@ -246,8 +238,7 @@ def __call__(self, *args, **kwargs): raise TypeError("hook calling supports only keyword arguments") assert not self.is_historic() if self.argnames: - notincall = set(self.argnames) - set(['__multicall__']) - set( - kwargs.keys()) + notincall = set(self.argnames) - set(kwargs.keys()) if notincall: warnings.warn( "Argument(s) {} which are declared in the hookspec "