123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- import pytest
- from pluggy import HookimplMarker, HookspecMarker, PluginValidationError
- from pluggy._hooks import HookImpl
- hookspec = HookspecMarker("example")
- hookimpl = HookimplMarker("example")
- @pytest.fixture
- def hc(pm):
- class Hooks:
- @hookspec
- def he_method1(self, arg):
- pass
- pm.add_hookspecs(Hooks)
- return pm.hook.he_method1
- @pytest.fixture
- def addmeth(hc):
- def addmeth(tryfirst=False, trylast=False, hookwrapper=False):
- def wrap(func):
- hookimpl(tryfirst=tryfirst, trylast=trylast, hookwrapper=hookwrapper)(func)
- hc._add_hookimpl(HookImpl(None, "<temp>", func, func.example_impl))
- return func
- return wrap
- return addmeth
- def funcs(hookmethods):
- return [hookmethod.function for hookmethod in hookmethods]
- def test_adding_nonwrappers(hc, addmeth):
- @addmeth()
- def he_method1():
- pass
- @addmeth()
- def he_method2():
- pass
- @addmeth()
- def he_method3():
- pass
- assert funcs(hc._nonwrappers) == [he_method1, he_method2, he_method3]
- def test_adding_nonwrappers_trylast(hc, addmeth):
- @addmeth()
- def he_method1_middle():
- pass
- @addmeth(trylast=True)
- def he_method1():
- pass
- @addmeth()
- def he_method1_b():
- pass
- assert funcs(hc._nonwrappers) == [he_method1, he_method1_middle, he_method1_b]
- def test_adding_nonwrappers_trylast3(hc, addmeth):
- @addmeth()
- def he_method1_a():
- pass
- @addmeth(trylast=True)
- def he_method1_b():
- pass
- @addmeth()
- def he_method1_c():
- pass
- @addmeth(trylast=True)
- def he_method1_d():
- pass
- assert funcs(hc._nonwrappers) == [
- he_method1_d,
- he_method1_b,
- he_method1_a,
- he_method1_c,
- ]
- def test_adding_nonwrappers_trylast2(hc, addmeth):
- @addmeth()
- def he_method1_middle():
- pass
- @addmeth()
- def he_method1_b():
- pass
- @addmeth(trylast=True)
- def he_method1():
- pass
- assert funcs(hc._nonwrappers) == [he_method1, he_method1_middle, he_method1_b]
- def test_adding_nonwrappers_tryfirst(hc, addmeth):
- @addmeth(tryfirst=True)
- def he_method1():
- pass
- @addmeth()
- def he_method1_middle():
- pass
- @addmeth()
- def he_method1_b():
- pass
- assert funcs(hc._nonwrappers) == [he_method1_middle, he_method1_b, he_method1]
- def test_adding_wrappers_ordering(hc, addmeth):
- @addmeth(hookwrapper=True)
- def he_method1():
- pass
- @addmeth()
- def he_method1_middle():
- pass
- @addmeth(hookwrapper=True)
- def he_method3():
- pass
- assert funcs(hc._nonwrappers) == [he_method1_middle]
- assert funcs(hc._wrappers) == [he_method1, he_method3]
- def test_adding_wrappers_ordering_tryfirst(hc, addmeth):
- @addmeth(hookwrapper=True, tryfirst=True)
- def he_method1():
- pass
- @addmeth(hookwrapper=True)
- def he_method2():
- pass
- assert hc._nonwrappers == []
- assert funcs(hc._wrappers) == [he_method2, he_method1]
- def test_hookspec(pm):
- class HookSpec:
- @hookspec()
- def he_myhook1(arg1):
- pass
- @hookspec(firstresult=True)
- def he_myhook2(arg1):
- pass
- @hookspec(firstresult=False)
- def he_myhook3(arg1):
- pass
- pm.add_hookspecs(HookSpec)
- assert not pm.hook.he_myhook1.spec.opts["firstresult"]
- assert pm.hook.he_myhook2.spec.opts["firstresult"]
- assert not pm.hook.he_myhook3.spec.opts["firstresult"]
- @pytest.mark.parametrize("name", ["hookwrapper", "optionalhook", "tryfirst", "trylast"])
- @pytest.mark.parametrize("val", [True, False])
- def test_hookimpl(name, val):
- @hookimpl(**{name: val})
- def he_myhook1(arg1):
- pass
- if val:
- assert he_myhook1.example_impl.get(name)
- else:
- assert not hasattr(he_myhook1, name)
- def test_hookrelay_registry(pm):
- """Verify hook caller instances are registered by name onto the relay
- and can be likewise unregistered."""
- class Api:
- @hookspec
- def hello(self, arg):
- "api hook 1"
- pm.add_hookspecs(Api)
- hook = pm.hook
- assert hasattr(hook, "hello")
- assert repr(hook.hello).find("hello") != -1
- class Plugin:
- @hookimpl
- def hello(self, arg):
- return arg + 1
- plugin = Plugin()
- pm.register(plugin)
- out = hook.hello(arg=3)
- assert out == [4]
- assert not hasattr(hook, "world")
- pm.unregister(plugin)
- assert hook.hello(arg=3) == []
- def test_hookrelay_registration_by_specname(pm):
- """Verify hook caller instances may also be registered by specifying a
- specname option to the hookimpl"""
- class Api:
- @hookspec
- def hello(self, arg):
- "api hook 1"
- pm.add_hookspecs(Api)
- hook = pm.hook
- assert hasattr(hook, "hello")
- assert len(pm.hook.hello.get_hookimpls()) == 0
- class Plugin:
- @hookimpl(specname="hello")
- def foo(self, arg):
- return arg + 1
- plugin = Plugin()
- pm.register(plugin)
- out = hook.hello(arg=3)
- assert out == [4]
- def test_hookrelay_registration_by_specname_raises(pm):
- """Verify using specname still raises the types of errors during registration as it
- would have without using specname."""
- class Api:
- @hookspec
- def hello(self, arg):
- "api hook 1"
- pm.add_hookspecs(Api)
- # make sure a bad signature still raises an error when using specname
- class Plugin:
- @hookimpl(specname="hello")
- def foo(self, arg, too, many, args):
- return arg + 1
- with pytest.raises(PluginValidationError):
- pm.register(Plugin())
- # make sure check_pending still fails if specname doesn't have a
- # corresponding spec. EVEN if the function name matches one.
- class Plugin2:
- @hookimpl(specname="bar")
- def hello(self, arg):
- return arg + 1
- pm.register(Plugin2())
- with pytest.raises(PluginValidationError):
- pm.check_pending()
|