From 5ab312cc07408138e15b6b1f00ce45bf2d7e9319 Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Tue, 29 Aug 2017 10:06:06 -0400 Subject: [PATCH 1/2] Add an edge case test for firstresult hooks When calling a firstresult hook, if no implementation returns a non-None value a bug is exposed in the new `_MultiCall` which assumes there will be a least one result. --- testing/test_hookrelay.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/testing/test_hookrelay.py b/testing/test_hookrelay.py index 9fbcd121..8d0447fd 100644 --- a/testing/test_hookrelay.py +++ b/testing/test_hookrelay.py @@ -92,3 +92,38 @@ def hello(self, arg): pm.register(Plugin3()) # None result is ignored res = pm.hook.hello(arg=3) assert res == 2 + + +def test_firstresult_returns_none(pm): + """If None results are returned by underlying implementations ensure + the multi-call loop returns a None value. + """ + class Api(object): + @hookspec(firstresult=True) + def hello(self, arg): + "api hook 1" + + pm.add_hookspecs(Api) + + class Plugin1(object): + @hookimpl + def hello(self, arg): + return None + + pm.register(Plugin1()) + res = pm.hook.hello(arg=3) + assert res == None + + +def test_firstresult_no_plugin(pm): + """If no implementations/plugins have been registered for a firstresult + hook the multi-call loop should return a None value. + """ + class Api(object): + @hookspec(firstresult=True) + def hello(self, arg): + "api hook 1" + + pm.add_hookspecs(Api) + res = pm.hook.hello(arg=3) + assert res == None From f1a227086408437dd9e52350200bdabc8e6fe22f Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Tue, 29 Aug 2017 10:09:02 -0400 Subject: [PATCH 2/2] Handle firstresult hooks that return None Only return the first result when at least one result has been returned by underlying hook implementations. Fixes #68 --- pluggy/callers.py | 3 ++- testing/test_hookrelay.py | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pluggy/callers.py b/pluggy/callers.py index abe36e78..c5934b96 100644 --- a/pluggy/callers.py +++ b/pluggy/callers.py @@ -107,7 +107,8 @@ def execute(self): pass if firstresult: - return outcome.get_result()[0] + result = outcome.get_result() + return result[0] if result else None return outcome.get_result() diff --git a/testing/test_hookrelay.py b/testing/test_hookrelay.py index 8d0447fd..3653151b 100644 --- a/testing/test_hookrelay.py +++ b/testing/test_hookrelay.py @@ -112,7 +112,7 @@ def hello(self, arg): pm.register(Plugin1()) res = pm.hook.hello(arg=3) - assert res == None + assert res is None def test_firstresult_no_plugin(pm): @@ -126,4 +126,4 @@ def hello(self, arg): pm.add_hookspecs(Api) res = pm.hook.hello(arg=3) - assert res == None + assert res is None