Skip to content

Commit 9f7cdc2

Browse files
authored
Merge pull request #72 from tgoodlet/firstresult_madness
Firstresult madness
2 parents 060a055 + 5c6846f commit 9f7cdc2

File tree

2 files changed

+47
-5
lines changed

2 files changed

+47
-5
lines changed

pluggy/callers.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,10 @@ def execute(self):
9696
except BaseException:
9797
excinfo = sys.exc_info()
9898
finally:
99-
outcome = _Result(results, excinfo)
99+
if firstresult: # first result hooks return a single value
100+
outcome = _Result(results[0] if results else None, excinfo)
101+
else:
102+
outcome = _Result(results, excinfo)
100103

101104
# run all wrapper post-yield blocks
102105
for gen in reversed(teardowns):
@@ -106,10 +109,6 @@ def execute(self):
106109
except StopIteration:
107110
pass
108111

109-
if firstresult:
110-
result = outcome.get_result()
111-
return result[0] if result else None
112-
113112
return outcome.get_result()
114113

115114
def __repr__(self):

testing/test_hookrelay.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,56 @@ class Plugin3(object):
8787
def hello(self, arg):
8888
return None
8989

90+
class Plugin4(object):
91+
@hookimpl(hookwrapper=True)
92+
def hello(self, arg):
93+
assert arg == 3
94+
outcome = yield
95+
assert outcome.get_result() == 2
96+
9097
pm.register(Plugin1()) # discarded - not the last registered plugin
9198
pm.register(Plugin2()) # used as result
9299
pm.register(Plugin3()) # None result is ignored
100+
pm.register(Plugin4()) # hookwrapper should get same non-list result
93101
res = pm.hook.hello(arg=3)
94102
assert res == 2
95103

96104

105+
def test_firstresult_force_result(pm):
106+
"""Verify forcing a result in a wrapper.
107+
"""
108+
class Api(object):
109+
@hookspec(firstresult=True)
110+
def hello(self, arg):
111+
"api hook 1"
112+
113+
pm.add_hookspecs(Api)
114+
115+
class Plugin1(object):
116+
@hookimpl
117+
def hello(self, arg):
118+
return arg + 1
119+
120+
class Plugin2(object):
121+
@hookimpl(hookwrapper=True)
122+
def hello(self, arg):
123+
assert arg == 3
124+
outcome = yield
125+
assert outcome.get_result() == 4
126+
outcome.force_result(0)
127+
128+
class Plugin3(object):
129+
@hookimpl
130+
def hello(self, arg):
131+
return None
132+
133+
pm.register(Plugin1())
134+
pm.register(Plugin2()) # wrapper
135+
pm.register(Plugin3()) # ignored since returns None
136+
res = pm.hook.hello(arg=3)
137+
assert res == 0 # this result is forced and not a list
138+
139+
97140
def test_firstresult_returns_none(pm):
98141
"""If None results are returned by underlying implementations ensure
99142
the multi-call loop returns a None value.

0 commit comments

Comments
 (0)