Skip to content

Commit fa9c5ae

Browse files
author
Tyler Goodlet
committed
Convert _MultiCall into a function
Avoids a class with a single method `execute()` at the expense of dropping the `__repr__()` support. This should make cython-izing that much simpler. Resolves #84
1 parent dee4fd9 commit fa9c5ae

File tree

2 files changed

+58
-64
lines changed

2 files changed

+58
-64
lines changed

pluggy/__init__.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import inspect
22
import warnings
3-
from .callers import _MultiCall, HookCallError, _Result, _LegacyMultiCall
3+
from .callers import _multicall, HookCallError, _Result, _legacymulticall
44

55
__version__ = '0.5.3.dev'
66

@@ -213,7 +213,7 @@ def __init__(self, project_name, implprefix=None):
213213
self._inner_hookexec = lambda hook, methods, kwargs: \
214214
hook.multicall(
215215
methods, kwargs, specopts=hook.spec_opts, hook=hook
216-
).execute()
216+
)
217217

218218
def _hookexec(self, hook, methods, kwargs):
219219
# called from all hookcaller instances.
@@ -535,7 +535,7 @@ def __init__(self, name, hook_execute, specmodule_or_class=None, spec_opts=None)
535535
self._hookexec = hook_execute
536536
self.argnames = None
537537
self.kwargnames = None
538-
self.multicall = _MultiCall
538+
self.multicall = _multicall
539539
if specmodule_or_class is not None:
540540
assert spec_opts is not None
541541
self.set_specification(specmodule_or_class, spec_opts)
@@ -592,7 +592,7 @@ def _add_hookimpl(self, hookimpl):
592592
"removed in an upcoming release.",
593593
DeprecationWarning
594594
)
595-
self.multicall = _LegacyMultiCall
595+
self.multicall = _legacymulticall
596596

597597
def __repr__(self):
598598
return "<_HookCaller %r>" % (self.name,)

pluggy/callers.py

Lines changed: 54 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -144,67 +144,61 @@ def __repr__(self):
144144
return "<_MultiCall %s, kwargs=%r>" % (status, self.caller_kwargs)
145145

146146

147-
class _MultiCall(object):
148-
"""Execute a call into multiple python functions/methods.
149-
"""
150-
def __init__(self, hook_impls, kwargs, specopts={}, hook=None):
151-
self.hook = hook
152-
self.hook_impls = hook_impls
153-
self.caller_kwargs = kwargs # come from _HookCaller.__call__()
154-
self.specopts = hook.spec_opts if hook else specopts
147+
def _legacymulticall(hook_impls, caller_kwargs, specopts={}, hook=None):
148+
return _LegacyMultiCall(
149+
hook_impls, caller_kwargs, specopts=specopts, hook=hook).execute()
155150

156-
def execute(self):
157-
__tracebackhide__ = True
158-
caller_kwargs = self.caller_kwargs
159-
self.results = results = []
160-
firstresult = self.specopts.get("firstresult")
161-
excinfo = None
162-
try: # run impl and wrapper setup functions in a loop
163-
teardowns = []
164-
try:
165-
for hook_impl in reversed(self.hook_impls):
166-
try:
167-
args = [caller_kwargs[argname] for argname in hook_impl.argnames]
168-
# args = operator.itemgetter(hookimpl.argnames)(caller_kwargs)
169-
except KeyError:
170-
for argname in hook_impl.argnames:
171-
if argname not in caller_kwargs:
172-
raise HookCallError(
173-
"hook call must provide argument %r" % (argname,))
174-
175-
if hook_impl.hookwrapper:
176-
try:
177-
gen = hook_impl.function(*args)
178-
next(gen) # first yield
179-
teardowns.append(gen)
180-
except StopIteration:
181-
_raise_wrapfail(gen, "did not yield")
182-
else:
183-
res = hook_impl.function(*args)
184-
if res is not None:
185-
results.append(res)
186-
if firstresult: # halt further impl calls
187-
break
188-
except BaseException:
189-
excinfo = sys.exc_info()
190-
finally:
191-
if firstresult: # first result hooks return a single value
192-
outcome = _Result(results[0] if results else None, excinfo)
193-
else:
194-
outcome = _Result(results, excinfo)
195-
196-
# run all wrapper post-yield blocks
197-
for gen in reversed(teardowns):
151+
152+
def _multicall(hook_impls, caller_kwargs, specopts={}, hook=None):
153+
"""Execute a call into multiple python functions/methods and return the
154+
result(s).
155+
156+
``caller_kwargs`` comes from _HookCaller.__call__().
157+
"""
158+
__tracebackhide__ = True
159+
specopts = hook.spec_opts if hook else specopts
160+
results = []
161+
firstresult = specopts.get("firstresult")
162+
excinfo = None
163+
try: # run impl and wrapper setup functions in a loop
164+
teardowns = []
165+
try:
166+
for hook_impl in reversed(hook_impls):
198167
try:
199-
gen.send(outcome)
200-
_raise_wrapfail(gen, "has second yield")
201-
except StopIteration:
202-
pass
168+
args = [caller_kwargs[argname] for argname in hook_impl.argnames]
169+
except KeyError:
170+
for argname in hook_impl.argnames:
171+
if argname not in caller_kwargs:
172+
raise HookCallError(
173+
"hook call must provide argument %r" % (argname,))
174+
175+
if hook_impl.hookwrapper:
176+
try:
177+
gen = hook_impl.function(*args)
178+
next(gen) # first yield
179+
teardowns.append(gen)
180+
except StopIteration:
181+
_raise_wrapfail(gen, "did not yield")
182+
else:
183+
res = hook_impl.function(*args)
184+
if res is not None:
185+
results.append(res)
186+
if firstresult: # halt further impl calls
187+
break
188+
except BaseException:
189+
excinfo = sys.exc_info()
190+
finally:
191+
if firstresult: # first result hooks return a single value
192+
outcome = _Result(results[0] if results else None, excinfo)
193+
else:
194+
outcome = _Result(results, excinfo)
203195

204-
return outcome.get_result()
196+
# run all wrapper post-yield blocks
197+
for gen in reversed(teardowns):
198+
try:
199+
gen.send(outcome)
200+
_raise_wrapfail(gen, "has second yield")
201+
except StopIteration:
202+
pass
205203

206-
def __repr__(self):
207-
status = "%d meths" % (len(self.hook_impls),)
208-
if hasattr(self, "results"):
209-
status = ("%d results, " % len(self.results)) + status
210-
return "<_MultiCall %s, kwargs=%r>" % (status, self.caller_kwargs)
204+
return outcome.get_result()

0 commit comments

Comments
 (0)