diff --git a/testing/test_deprecations.py b/testing/test_deprecations.py new file mode 100644 index 00000000..3000a374 --- /dev/null +++ b/testing/test_deprecations.py @@ -0,0 +1,53 @@ +""" +Deprecation warnings testing roundup. +""" +import pytest +from pluggy.callers import _Result +from pluggy import PluginManager, HookimplMarker, HookspecMarker + +hookspec = HookspecMarker("example") +hookimpl = HookimplMarker("example") + + +def test_result_deprecated(): + r = _Result(10, None) + with pytest.deprecated_call(): + assert r.result == 10 + + +def test_implprefix_deprecated(): + with pytest.deprecated_call(): + pm = PluginManager('blah', implprefix='blah_') + + class Plugin: + def blah_myhook(self, arg1): + return arg1 + + with pytest.deprecated_call(): + pm.register(Plugin()) + + +def test_callhistoric_proc_deprecated(pm): + """``proc`` kwarg to `PluginMananger.call_historic()` is now officially + deprecated. + """ + class P1(object): + @hookspec(historic=True) + @hookimpl + def m(self, x): + pass + + p1 = P1() + pm.add_hookspecs(p1) + pm.register(p1) + with pytest.deprecated_call(): + pm.hook.m.call_historic(kwargs=dict(x=10), proc=lambda res: res) + + +def test_multicall_deprecated(pm): + class P1(object): + @hookimpl + def m(self, __multicall__, x): + pass + + pytest.deprecated_call(pm.register, P1()) diff --git a/testing/test_details.py b/testing/test_details.py index 179dde6b..66a1b65f 100644 --- a/testing/test_details.py +++ b/testing/test_details.py @@ -1,7 +1,6 @@ import warnings import pytest from pluggy import PluginManager, HookimplMarker, HookspecMarker -from pluggy.callers import _Result hookspec = HookspecMarker("example") hookimpl = HookimplMarker("example") @@ -118,21 +117,3 @@ def myhook(self, arg1): warning = warns[-1] assert issubclass(warning.category, Warning) assert "Argument(s) ('arg2',)" in str(warning.message) - - -def test_result_deprecated(): - r = _Result(10, None) - with pytest.deprecated_call(): - assert r.result == 10 - - -def test_implprefix_deprecated(): - with pytest.deprecated_call(): - pm = PluginManager('blah', implprefix='blah_') - - class Plugin: - def blah_myhook(self, arg1): - return arg1 - - with pytest.deprecated_call(): - pm.register(Plugin()) diff --git a/testing/test_method_ordering.py b/testing/test_hookcaller.py similarity index 50% rename from testing/test_method_ordering.py rename to testing/test_hookcaller.py index 308aa592..a58e6402 100644 --- a/testing/test_method_ordering.py +++ b/testing/test_hookcaller.py @@ -1,8 +1,6 @@ import pytest -import sys -import types -from pluggy import PluginManager, HookimplMarker, HookspecMarker +from pluggy import HookimplMarker, HookspecMarker from pluggy.hooks import HookImpl hookspec = HookspecMarker("example") @@ -11,10 +9,12 @@ @pytest.fixture def hc(pm): + class Hooks(object): @hookspec def he_method1(self, arg): pass + pm.add_hookspecs(Hooks) return pm.hook.he_method1 @@ -179,146 +179,28 @@ def he_myhook1(arg1): assert not hasattr(he_myhook1, name) -def test_load_setuptools_instantiation(monkeypatch, pm): - pkg_resources = pytest.importorskip("pkg_resources") - - def my_iter(name): - assert name == "hello" - - class EntryPoint(object): - name = "myname" - dist = None - - def load(self): - class PseudoPlugin(object): - x = 42 - return PseudoPlugin() - - return iter([EntryPoint()]) - - monkeypatch.setattr(pkg_resources, 'iter_entry_points', my_iter) - num = pm.load_setuptools_entrypoints("hello") - assert num == 1 - plugin = pm.get_plugin("myname") - assert plugin.x == 42 - assert pm.list_plugin_distinfo() == [(plugin, None)] - - -def test_load_setuptools_not_installed(monkeypatch, pm): - monkeypatch.setitem( - sys.modules, 'pkg_resources', - types.ModuleType("pkg_resources")) - - with pytest.raises(ImportError): - pm.load_setuptools_entrypoints("qwe") - - -def test_add_tracefuncs(he_pm): - out = [] - - class api1(object): - @hookimpl - def he_method1(self): - out.append("he_method1-api1") - - class api2(object): - @hookimpl - def he_method1(self): - out.append("he_method1-api2") - - he_pm.register(api1()) - he_pm.register(api2()) - - def before(hook_name, hook_impls, kwargs): - out.append((hook_name, list(hook_impls), kwargs)) - - def after(outcome, hook_name, hook_impls, kwargs): - out.append((outcome, hook_name, list(hook_impls), kwargs)) - - undo = he_pm.add_hookcall_monitoring(before, after) - - he_pm.hook.he_method1(arg=1) - assert len(out) == 4 - assert out[0][0] == "he_method1" - assert len(out[0][1]) == 2 - assert isinstance(out[0][2], dict) - assert out[1] == "he_method1-api2" - assert out[2] == "he_method1-api1" - assert len(out[3]) == 4 - assert out[3][1] == out[0][0] - - undo() - he_pm.hook.he_method1(arg=1) - assert len(out) == 4 + 2 - - -def test_hook_tracing(he_pm): - saveindent = [] - - class api1(object): - @hookimpl - def he_method1(self): - saveindent.append(he_pm.trace.root.indent) +def test_hookrelay_registry(pm): + """Verify hook caller instances are registered by name onto the relay + and can be likewise unregistered.""" + class Api(object): + @hookspec + def hello(self, arg): + "api hook 1" - class api2(object): - @hookimpl - def he_method1(self): - saveindent.append(he_pm.trace.root.indent) - raise ValueError() - - he_pm.register(api1()) - out = [] - he_pm.trace.root.setwriter(out.append) - undo = he_pm.enable_tracing() - try: - indent = he_pm.trace.root.indent - he_pm.hook.he_method1(arg=1) - assert indent == he_pm.trace.root.indent - assert len(out) == 2 - assert 'he_method1' in out[0] - assert 'finish' in out[1] - - out[:] = [] - he_pm.register(api2()) - - with pytest.raises(ValueError): - he_pm.hook.he_method1(arg=1) - assert he_pm.trace.root.indent == indent - assert saveindent[0] > indent - finally: - undo() - - -@pytest.mark.parametrize('include_hookspec', [True, False]) -def test_prefix_hookimpl(include_hookspec): - with pytest.deprecated_call(): - pm = PluginManager(hookspec.project_name, "hello_") - - if include_hookspec: - class HookSpec(object): - @hookspec - def hello_myhook(self, arg1): - """ add to arg1 """ - - pm.add_hookspecs(HookSpec) + pm.add_hookspecs(Api) + hook = pm.hook + assert hasattr(hook, 'hello') + assert repr(hook.hello).find("hello") != -1 class Plugin(object): - def hello_myhook(self, arg1): - return arg1 + 1 - - with pytest.deprecated_call(): - pm.register(Plugin()) - pm.register(Plugin()) - results = pm.hook.hello_myhook(arg1=17) - assert results == [18, 18] - - -def test_prefix_hookimpl_dontmatch_module(): - with pytest.deprecated_call(): - pm = PluginManager(hookspec.project_name, "hello_") - - class BadPlugin(object): - hello_module = __import__('email') - - pm.register(BadPlugin()) - pm.check_pending() + @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) == [] diff --git a/testing/test_hookrelay.py b/testing/test_invocations.py similarity index 89% rename from testing/test_hookrelay.py rename to testing/test_invocations.py index 5e7821be..2725f0e7 100644 --- a/testing/test_hookrelay.py +++ b/testing/test_invocations.py @@ -6,31 +6,6 @@ hookimpl = HookimplMarker("example") -def test_happypath(pm): - class Api(object): - @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(object): - @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_argmismatch(pm): class Api(object): @hookspec diff --git a/testing/test_pluginmanager.py b/testing/test_pluginmanager.py index 351bdce6..f04300be 100644 --- a/testing/test_pluginmanager.py +++ b/testing/test_pluginmanager.py @@ -1,7 +1,13 @@ +""" +``PluginManager`` unit and public API testing. +""" import pytest import types -from pluggy import (PluginValidationError, - HookCallError, HookimplMarker, HookspecMarker) +import sys +from pluggy import ( + PluginManager, PluginValidationError, + HookCallError, HookimplMarker, HookspecMarker +) hookspec = HookspecMarker("example") @@ -9,6 +15,7 @@ def test_plugin_double_register(pm): + """Registering the same plugin more then once isn't allowed""" pm.register(42, name="abc") with pytest.raises(ValueError): pm.register(42, name="abc") @@ -17,6 +24,7 @@ def test_plugin_double_register(pm): def test_pm(pm): + """Basic registration with objects""" class A(object): pass @@ -366,15 +374,6 @@ class PluginNo(object): 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) @@ -403,18 +402,146 @@ def example_hook(): assert pm.parse_hookimpl_opts(conftest, 'example_hook') == {} -def test_callhistoric_proc_deprecated(pm): - """``proc`` kwarg to `PluginMananger.call_historic()` is now officially - deprecated. - """ - class P1(object): - @hookspec(historic=True) +def test_load_setuptools_instantiation(monkeypatch, pm): + pkg_resources = pytest.importorskip("pkg_resources") + + def my_iter(name): + assert name == "hello" + + class EntryPoint(object): + name = "myname" + dist = None + + def load(self): + class PseudoPlugin(object): + x = 42 + return PseudoPlugin() + + return iter([EntryPoint()]) + + monkeypatch.setattr(pkg_resources, 'iter_entry_points', my_iter) + num = pm.load_setuptools_entrypoints("hello") + assert num == 1 + plugin = pm.get_plugin("myname") + assert plugin.x == 42 + assert pm.list_plugin_distinfo() == [(plugin, None)] + + +def test_load_setuptools_not_installed(monkeypatch, pm): + monkeypatch.setitem( + sys.modules, 'pkg_resources', + types.ModuleType("pkg_resources")) + + with pytest.raises(ImportError): + pm.load_setuptools_entrypoints("qwe") + + +def test_add_tracefuncs(he_pm): + out = [] + + class api1(object): @hookimpl - def m(self, x): - pass + def he_method1(self): + out.append("he_method1-api1") + + class api2(object): + @hookimpl + def he_method1(self): + out.append("he_method1-api2") + + he_pm.register(api1()) + he_pm.register(api2()) + + def before(hook_name, hook_impls, kwargs): + out.append((hook_name, list(hook_impls), kwargs)) - p1 = P1() - pm.add_hookspecs(p1) - pm.register(p1) + def after(outcome, hook_name, hook_impls, kwargs): + out.append((outcome, hook_name, list(hook_impls), kwargs)) + + undo = he_pm.add_hookcall_monitoring(before, after) + + he_pm.hook.he_method1(arg=1) + assert len(out) == 4 + assert out[0][0] == "he_method1" + assert len(out[0][1]) == 2 + assert isinstance(out[0][2], dict) + assert out[1] == "he_method1-api2" + assert out[2] == "he_method1-api1" + assert len(out[3]) == 4 + assert out[3][1] == out[0][0] + + undo() + he_pm.hook.he_method1(arg=1) + assert len(out) == 4 + 2 + + +def test_hook_tracing(he_pm): + saveindent = [] + + class api1(object): + @hookimpl + def he_method1(self): + saveindent.append(he_pm.trace.root.indent) + + class api2(object): + @hookimpl + def he_method1(self): + saveindent.append(he_pm.trace.root.indent) + raise ValueError() + + he_pm.register(api1()) + out = [] + he_pm.trace.root.setwriter(out.append) + undo = he_pm.enable_tracing() + try: + indent = he_pm.trace.root.indent + he_pm.hook.he_method1(arg=1) + assert indent == he_pm.trace.root.indent + assert len(out) == 2 + assert 'he_method1' in out[0] + assert 'finish' in out[1] + + out[:] = [] + he_pm.register(api2()) + + with pytest.raises(ValueError): + he_pm.hook.he_method1(arg=1) + assert he_pm.trace.root.indent == indent + assert saveindent[0] > indent + finally: + undo() + + +@pytest.mark.parametrize('include_hookspec', [True, False]) +def test_prefix_hookimpl(include_hookspec): + with pytest.deprecated_call(): + pm = PluginManager(hookspec.project_name, "hello_") + + if include_hookspec: + class HookSpec(object): + @hookspec + def hello_myhook(self, arg1): + """ add to arg1 """ + + pm.add_hookspecs(HookSpec) + + class Plugin(object): + def hello_myhook(self, arg1): + return arg1 + 1 + + with pytest.deprecated_call(): + pm.register(Plugin()) + pm.register(Plugin()) + results = pm.hook.hello_myhook(arg1=17) + assert results == [18, 18] + + +def test_prefix_hookimpl_dontmatch_module(): with pytest.deprecated_call(): - pm.hook.m.call_historic(kwargs=dict(x=10), proc=lambda res: res) + pm = PluginManager(hookspec.project_name, "hello_") + + class BadPlugin(object): + hello_module = __import__('email') + + pm.register(BadPlugin()) + pm.check_pending()