Skip to content

Commit 0fbcb25

Browse files
author
goodboy
authored
Merge pull request #102 from tgoodlet/expose_spec_opts_regresion
Self contained call loops
2 parents 607862c + 19055e5 commit 0fbcb25

File tree

4 files changed

+25
-23
lines changed

4 files changed

+25
-23
lines changed

pluggy/__init__.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,8 @@ def __init__(self, project_name, implprefix=None):
212212
self._implprefix = implprefix
213213
self._inner_hookexec = lambda hook, methods, kwargs: \
214214
hook.multicall(
215-
methods, kwargs, specopts=hook.spec_opts, hook=hook
215+
methods, kwargs,
216+
firstresult=hook.spec_opts.get('firstresult'),
216217
)
217218

218219
def _hookexec(self, hook, methods, kwargs):
@@ -528,20 +529,22 @@ def __init__(self, trace):
528529

529530

530531
class _HookCaller(object):
531-
def __init__(self, name, hook_execute, specmodule_or_class=None, spec_opts=None):
532+
def __init__(self, name, hook_execute, specmodule_or_class=None,
533+
spec_opts=None):
532534
self.name = name
533535
self._wrappers = []
534536
self._nonwrappers = []
535537
self._hookexec = hook_execute
538+
self._specmodule_or_class = None
536539
self.argnames = None
537540
self.kwargnames = None
538541
self.multicall = _multicall
542+
self.spec_opts = spec_opts or {}
539543
if specmodule_or_class is not None:
540-
assert spec_opts is not None
541544
self.set_specification(specmodule_or_class, spec_opts)
542545

543546
def has_spec(self):
544-
return hasattr(self, "_specmodule_or_class")
547+
return self._specmodule_or_class is not None
545548

546549
def set_specification(self, specmodule_or_class, spec_opts):
547550
assert not self.has_spec()
@@ -550,7 +553,7 @@ def set_specification(self, specmodule_or_class, spec_opts):
550553
# get spec arg signature
551554
argnames, self.kwargnames = varnames(specfunc)
552555
self.argnames = ["__multicall__"] + list(argnames)
553-
self.spec_opts = spec_opts
556+
self.spec_opts.update(spec_opts)
554557
if spec_opts.get("historic"):
555558
self._call_history = []
556559

pluggy/callers.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -105,17 +105,16 @@ class _LegacyMultiCall(object):
105105
# so we can remove it soon, allowing to avoid the below recursion
106106
# in execute() and simplify/speed up the execute loop.
107107

108-
def __init__(self, hook_impls, kwargs, specopts={}, hook=None):
109-
self.hook = hook
108+
def __init__(self, hook_impls, kwargs, firstresult=False):
110109
self.hook_impls = hook_impls
111110
self.caller_kwargs = kwargs # come from _HookCaller.__call__()
112111
self.caller_kwargs["__multicall__"] = self
113-
self.specopts = hook.spec_opts if hook else specopts
112+
self.firstresult = firstresult
114113

115114
def execute(self):
116115
caller_kwargs = self.caller_kwargs
117116
self.results = results = []
118-
firstresult = self.specopts.get("firstresult")
117+
firstresult = self.firstresult
119118

120119
while self.hook_impls:
121120
hook_impl = self.hook_impls.pop()
@@ -144,21 +143,19 @@ def __repr__(self):
144143
return "<_MultiCall %s, kwargs=%r>" % (status, self.caller_kwargs)
145144

146145

147-
def _legacymulticall(hook_impls, caller_kwargs, specopts={}, hook=None):
146+
def _legacymulticall(hook_impls, caller_kwargs, firstresult=False):
148147
return _LegacyMultiCall(
149-
hook_impls, caller_kwargs, specopts=specopts, hook=hook).execute()
148+
hook_impls, caller_kwargs, firstresult=firstresult).execute()
150149

151150

152-
def _multicall(hook_impls, caller_kwargs, specopts={}, hook=None):
151+
def _multicall(hook_impls, caller_kwargs, firstresult=False):
153152
"""Execute a call into multiple python functions/methods and return the
154153
result(s).
155154
156155
``caller_kwargs`` comes from _HookCaller.__call__().
157156
"""
158157
__tracebackhide__ = True
159-
specopts = hook.spec_opts if hook else specopts
160158
results = []
161-
firstresult = specopts.get("firstresult")
162159
excinfo = None
163160
try: # run impl and wrapper setup functions in a loop
164161
teardowns = []

testing/test_method_ordering.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -290,15 +290,17 @@ def he_method1(self):
290290
undo()
291291

292292

293-
def test_prefix_hookimpl():
293+
@pytest.mark.parametrize('include_hookspec', [True, False])
294+
def test_prefix_hookimpl(include_hookspec):
294295
pm = PluginManager(hookspec.project_name, "hello_")
295296

296-
class HookSpec(object):
297-
@hookspec
298-
def hello_myhook(self, arg1):
299-
""" add to arg1 """
297+
if include_hookspec:
298+
class HookSpec(object):
299+
@hookspec
300+
def hello_myhook(self, arg1):
301+
""" add to arg1 """
300302

301-
pm.add_hookspecs(HookSpec)
303+
pm.add_hookspecs(HookSpec)
302304

303305
class Plugin(object):
304306
def hello_myhook(self, arg1):

testing/test_multicall.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def MC(methods, kwargs, firstresult=False):
2626
hookfuncs.append(f)
2727
if '__multicall__' in f.argnames:
2828
caller = _legacymulticall
29-
return caller(hookfuncs, kwargs, specopts={"firstresult": firstresult})
29+
return caller(hookfuncs, kwargs, firstresult=firstresult)
3030

3131

3232
def test_call_passing():
@@ -105,7 +105,7 @@ def m1():
105105
def m2():
106106
return None
107107

108-
res = MC([m1, m2], {}, {"firstresult": True})
108+
res = MC([m1, m2], {}, firstresult=True)
109109
assert res == 1
110110
res = MC([m1, m2], {}, {})
111111
assert res == [1]
@@ -129,7 +129,7 @@ def m2():
129129
assert res == [2]
130130
assert out == ["m1 init", "m2", "m1 finish"]
131131
out[:] = []
132-
res = MC([m2, m1], {}, {"firstresult": True})
132+
res = MC([m2, m1], {}, firstresult=True)
133133
assert res == 2
134134
assert out == ["m1 init", "m2", "m1 finish"]
135135

0 commit comments

Comments
 (0)