diff options
Diffstat (limited to 'third_party/python/pluggy/testing/test_pluginmanager.py')
-rw-r--r-- | third_party/python/pluggy/testing/test_pluginmanager.py | 374 |
1 files changed, 374 insertions, 0 deletions
diff --git a/third_party/python/pluggy/testing/test_pluginmanager.py b/third_party/python/pluggy/testing/test_pluginmanager.py new file mode 100644 index 0000000000..e2c86cc644 --- /dev/null +++ b/third_party/python/pluggy/testing/test_pluginmanager.py @@ -0,0 +1,374 @@ +import pytest +import types + +from pluggy import (PluginValidationError, + HookCallError, HookimplMarker, HookspecMarker) + + +hookspec = HookspecMarker("example") +hookimpl = HookimplMarker("example") + + +def test_plugin_double_register(pm): + pm.register(42, name="abc") + with pytest.raises(ValueError): + pm.register(42, name="abc") + with pytest.raises(ValueError): + pm.register(42, name="def") + + +def test_pm(pm): + class A(object): + pass + + a1, a2 = A(), A() + pm.register(a1) + assert pm.is_registered(a1) + pm.register(a2, "hello") + assert pm.is_registered(a2) + out = pm.get_plugins() + assert a1 in out + assert a2 in out + assert pm.get_plugin('hello') == a2 + assert pm.unregister(a1) == a1 + assert not pm.is_registered(a1) + + out = pm.list_name_plugin() + assert len(out) == 1 + assert out == [("hello", a2)] + + +def test_has_plugin(pm): + class A(object): + pass + + a1 = A() + pm.register(a1, 'hello') + assert pm.is_registered(a1) + assert pm.has_plugin('hello') + + +def test_register_dynamic_attr(he_pm): + class A(object): + def __getattr__(self, name): + if name[0] != "_": + return 42 + raise AttributeError() + + a = A() + he_pm.register(a) + assert not he_pm.get_hookcallers(a) + + +def test_pm_name(pm): + class A(object): + pass + + a1 = A() + name = pm.register(a1, name="hello") + assert name == "hello" + pm.unregister(a1) + assert pm.get_plugin(a1) is None + assert not pm.is_registered(a1) + assert not pm.get_plugins() + name2 = pm.register(a1, name="hello") + assert name2 == name + pm.unregister(name="hello") + assert pm.get_plugin(a1) is None + assert not pm.is_registered(a1) + assert not pm.get_plugins() + + +def test_set_blocked(pm): + class A(object): + pass + + a1 = A() + name = pm.register(a1) + assert pm.is_registered(a1) + assert not pm.is_blocked(name) + pm.set_blocked(name) + assert pm.is_blocked(name) + assert not pm.is_registered(a1) + + pm.set_blocked("somename") + assert pm.is_blocked("somename") + assert not pm.register(A(), "somename") + pm.unregister(name="somename") + assert pm.is_blocked("somename") + + +def test_register_mismatch_method(he_pm): + class hello(object): + @hookimpl + def he_method_notexists(self): + pass + + he_pm.register(hello()) + with pytest.raises(PluginValidationError): + he_pm.check_pending() + + +def test_register_mismatch_arg(he_pm): + class hello(object): + @hookimpl + def he_method1(self, qlwkje): + pass + + with pytest.raises(PluginValidationError): + he_pm.register(hello()) + + +def test_register(pm): + class MyPlugin(object): + pass + my = MyPlugin() + pm.register(my) + assert my in pm.get_plugins() + my2 = MyPlugin() + pm.register(my2) + assert set([my, my2]).issubset(pm.get_plugins()) + + assert pm.is_registered(my) + assert pm.is_registered(my2) + pm.unregister(my) + assert not pm.is_registered(my) + assert my not in pm.get_plugins() + + +def test_register_unknown_hooks(pm): + class Plugin1(object): + @hookimpl + def he_method1(self, arg): + return arg + 1 + + pname = pm.register(Plugin1()) + + class Hooks(object): + @hookspec + def he_method1(self, arg): + pass + + pm.add_hookspecs(Hooks) + # assert not pm._unverified_hooks + assert pm.hook.he_method1(arg=1) == [2] + assert len(pm.get_hookcallers(pm.get_plugin(pname))) == 1 + + +def test_register_historic(pm): + class Hooks(object): + @hookspec(historic=True) + def he_method1(self, arg): + pass + pm.add_hookspecs(Hooks) + + pm.hook.he_method1.call_historic(kwargs=dict(arg=1)) + out = [] + + class Plugin(object): + @hookimpl + def he_method1(self, arg): + out.append(arg) + + pm.register(Plugin()) + assert out == [1] + + class Plugin2(object): + @hookimpl + def he_method1(self, arg): + out.append(arg * 10) + + pm.register(Plugin2()) + assert out == [1, 10] + pm.hook.he_method1.call_historic(kwargs=dict(arg=12)) + assert out == [1, 10, 120, 12] + + +def test_with_result_memorized(pm): + class Hooks(object): + @hookspec(historic=True) + def he_method1(self, arg): + pass + pm.add_hookspecs(Hooks) + + he_method1 = pm.hook.he_method1 + he_method1.call_historic(lambda res: out.append(res), dict(arg=1)) + out = [] + + class Plugin(object): + @hookimpl + def he_method1(self, arg): + return arg * 10 + + pm.register(Plugin()) + assert out == [10] + + +def test_with_callbacks_immediately_executed(pm): + class Hooks(object): + @hookspec(historic=True) + def he_method1(self, arg): + pass + pm.add_hookspecs(Hooks) + + class Plugin1(object): + @hookimpl + def he_method1(self, arg): + return arg * 10 + + class Plugin2(object): + @hookimpl + def he_method1(self, arg): + return arg * 20 + + class Plugin3(object): + @hookimpl + def he_method1(self, arg): + return arg * 30 + + out = [] + pm.register(Plugin1()) + pm.register(Plugin2()) + + he_method1 = pm.hook.he_method1 + he_method1.call_historic(lambda res: out.append(res), dict(arg=1)) + assert out == [20, 10] + pm.register(Plugin3()) + assert out == [20, 10, 30] + + +def test_register_historic_incompat_hookwrapper(pm): + class Hooks(object): + @hookspec(historic=True) + def he_method1(self, arg): + pass + + pm.add_hookspecs(Hooks) + + out = [] + + class Plugin(object): + @hookimpl(hookwrapper=True) + def he_method1(self, arg): + out.append(arg) + + with pytest.raises(PluginValidationError): + pm.register(Plugin()) + + +def test_call_extra(pm): + class Hooks(object): + @hookspec + def he_method1(self, arg): + pass + + pm.add_hookspecs(Hooks) + + def he_method1(arg): + return arg * 10 + + out = pm.hook.he_method1.call_extra([he_method1], dict(arg=1)) + assert out == [10] + + +def test_call_with_too_few_args(pm): + class Hooks(object): + @hookspec + def he_method1(self, arg): + pass + + pm.add_hookspecs(Hooks) + + class Plugin1(object): + @hookimpl + def he_method1(self, arg): + 0 / 0 + pm.register(Plugin1()) + with pytest.raises(HookCallError): + with pytest.warns(UserWarning): + pm.hook.he_method1() + + +def test_subset_hook_caller(pm): + class Hooks(object): + @hookspec + def he_method1(self, arg): + pass + + pm.add_hookspecs(Hooks) + + out = [] + + class Plugin1(object): + @hookimpl + def he_method1(self, arg): + out.append(arg) + + class Plugin2(object): + @hookimpl + def he_method1(self, arg): + out.append(arg * 10) + + class PluginNo(object): + pass + + plugin1, plugin2, plugin3 = Plugin1(), Plugin2(), PluginNo() + pm.register(plugin1) + pm.register(plugin2) + pm.register(plugin3) + pm.hook.he_method1(arg=1) + assert out == [10, 1] + out[:] = [] + + hc = pm.subset_hook_caller("he_method1", [plugin1]) + hc(arg=2) + assert out == [20] + out[:] = [] + + hc = pm.subset_hook_caller("he_method1", [plugin2]) + hc(arg=2) + assert out == [2] + out[:] = [] + + pm.unregister(plugin1) + hc(arg=2) + assert out == [] + out[:] = [] + + pm.hook.he_method1(arg=1) + assert out == [10] + + +def test_multicall_deprecated(pm): + class P1(object): + @hookimpl + def m(self, __multicall__, x): + pass + + pytest.deprecated_call(pm.register, P1()) + + +def test_add_hookspecs_nohooks(pm): + with pytest.raises(ValueError): + pm.add_hookspecs(10) + + +def test_reject_prefixed_module(pm): + """Verify that a module type attribute that contains the project + prefix in its name (in this case `'example_*'` isn't collected + when registering a module which imports it. + """ + pm._implprefix = 'example' + conftest = types.ModuleType("conftest") + src = (""" +def example_hook(): + pass +""") + exec(src, conftest.__dict__) + conftest.example_blah = types.ModuleType("example_blah") + name = pm.register(conftest) + assert name == 'conftest' + assert getattr(pm.hook, 'example_blah', None) is None + assert getattr(pm.hook, 'example_hook', None) # conftest.example_hook should be collected + assert pm.parse_hookimpl_opts(conftest, 'example_blah') is None + assert pm.parse_hookimpl_opts(conftest, 'example_hook') == {} |