aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/pluggy/py2/tests
diff options
context:
space:
mode:
authorshadchin <shadchin@yandex-team.ru>2022-02-10 16:44:39 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:44:39 +0300
commite9656aae26e0358d5378e5b63dcac5c8dbe0e4d0 (patch)
tree64175d5cadab313b3e7039ebaa06c5bc3295e274 /contrib/python/pluggy/py2/tests
parent2598ef1d0aee359b4b6d5fdd1758916d5907d04f (diff)
downloadydb-e9656aae26e0358d5378e5b63dcac5c8dbe0e4d0.tar.gz
Restoring authorship annotation for <shadchin@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'contrib/python/pluggy/py2/tests')
-rw-r--r--contrib/python/pluggy/py2/tests/benchmark.py102
-rw-r--r--contrib/python/pluggy/py2/tests/conftest.py52
-rw-r--r--contrib/python/pluggy/py2/tests/test_deprecations.py108
-rw-r--r--contrib/python/pluggy/py2/tests/test_details.py270
-rw-r--r--contrib/python/pluggy/py2/tests/test_helpers.py180
-rw-r--r--contrib/python/pluggy/py2/tests/test_hookcaller.py430
-rw-r--r--contrib/python/pluggy/py2/tests/test_invocations.py432
-rw-r--r--contrib/python/pluggy/py2/tests/test_multicall.py372
-rw-r--r--contrib/python/pluggy/py2/tests/test_pluginmanager.py1200
-rw-r--r--contrib/python/pluggy/py2/tests/test_tracer.py156
-rw-r--r--contrib/python/pluggy/py2/tests/ya.make46
11 files changed, 1674 insertions, 1674 deletions
diff --git a/contrib/python/pluggy/py2/tests/benchmark.py b/contrib/python/pluggy/py2/tests/benchmark.py
index cb99660adb..aa8de92911 100644
--- a/contrib/python/pluggy/py2/tests/benchmark.py
+++ b/contrib/python/pluggy/py2/tests/benchmark.py
@@ -1,51 +1,51 @@
-"""
-Benchmarking and performance tests.
-"""
-import pytest
-from pluggy import HookspecMarker, HookimplMarker
-from pluggy.hooks import HookImpl
-from pluggy.callers import _multicall, _legacymulticall
-
-hookspec = HookspecMarker("example")
-hookimpl = HookimplMarker("example")
-
-
-def MC(methods, kwargs, callertype, firstresult=False):
- hookfuncs = []
- for method in methods:
- f = HookImpl(None, "<temp>", method, method.example_impl)
- hookfuncs.append(f)
- return callertype(hookfuncs, kwargs, firstresult=firstresult)
-
-
-@hookimpl
-def hook(arg1, arg2, arg3):
- return arg1, arg2, arg3
-
-
-@hookimpl(hookwrapper=True)
-def wrapper(arg1, arg2, arg3):
- yield
-
-
-@pytest.fixture(params=[10, 100], ids="hooks={}".format)
-def hooks(request):
- return [hook for i in range(request.param)]
-
-
-@pytest.fixture(params=[10, 100], ids="wrappers={}".format)
-def wrappers(request):
- return [wrapper for i in range(request.param)]
-
-
-@pytest.fixture(params=[_multicall, _legacymulticall], ids=lambda item: item.__name__)
-def callertype(request):
- return request.param
-
-
-def inner_exec(methods, callertype):
- return MC(methods, {"arg1": 1, "arg2": 2, "arg3": 3}, callertype)
-
-
-def test_hook_and_wrappers_speed(benchmark, hooks, wrappers, callertype):
- benchmark(inner_exec, hooks + wrappers, callertype)
+"""
+Benchmarking and performance tests.
+"""
+import pytest
+from pluggy import HookspecMarker, HookimplMarker
+from pluggy.hooks import HookImpl
+from pluggy.callers import _multicall, _legacymulticall
+
+hookspec = HookspecMarker("example")
+hookimpl = HookimplMarker("example")
+
+
+def MC(methods, kwargs, callertype, firstresult=False):
+ hookfuncs = []
+ for method in methods:
+ f = HookImpl(None, "<temp>", method, method.example_impl)
+ hookfuncs.append(f)
+ return callertype(hookfuncs, kwargs, firstresult=firstresult)
+
+
+@hookimpl
+def hook(arg1, arg2, arg3):
+ return arg1, arg2, arg3
+
+
+@hookimpl(hookwrapper=True)
+def wrapper(arg1, arg2, arg3):
+ yield
+
+
+@pytest.fixture(params=[10, 100], ids="hooks={}".format)
+def hooks(request):
+ return [hook for i in range(request.param)]
+
+
+@pytest.fixture(params=[10, 100], ids="wrappers={}".format)
+def wrappers(request):
+ return [wrapper for i in range(request.param)]
+
+
+@pytest.fixture(params=[_multicall, _legacymulticall], ids=lambda item: item.__name__)
+def callertype(request):
+ return request.param
+
+
+def inner_exec(methods, callertype):
+ return MC(methods, {"arg1": 1, "arg2": 2, "arg3": 3}, callertype)
+
+
+def test_hook_and_wrappers_speed(benchmark, hooks, wrappers, callertype):
+ benchmark(inner_exec, hooks + wrappers, callertype)
diff --git a/contrib/python/pluggy/py2/tests/conftest.py b/contrib/python/pluggy/py2/tests/conftest.py
index 3e40b0f9ca..e44667ef5f 100644
--- a/contrib/python/pluggy/py2/tests/conftest.py
+++ b/contrib/python/pluggy/py2/tests/conftest.py
@@ -1,26 +1,26 @@
-import pytest
-
-
-@pytest.fixture(
- params=[lambda spec: spec, lambda spec: spec()],
- ids=["spec-is-class", "spec-is-instance"],
-)
-def he_pm(request, pm):
- from pluggy import HookspecMarker
-
- hookspec = HookspecMarker("example")
-
- class Hooks(object):
- @hookspec
- def he_method1(self, arg):
- return arg + 1
-
- pm.add_hookspecs(request.param(Hooks))
- return pm
-
-
-@pytest.fixture
-def pm():
- from pluggy import PluginManager
-
- return PluginManager("example")
+import pytest
+
+
+@pytest.fixture(
+ params=[lambda spec: spec, lambda spec: spec()],
+ ids=["spec-is-class", "spec-is-instance"],
+)
+def he_pm(request, pm):
+ from pluggy import HookspecMarker
+
+ hookspec = HookspecMarker("example")
+
+ class Hooks(object):
+ @hookspec
+ def he_method1(self, arg):
+ return arg + 1
+
+ pm.add_hookspecs(request.param(Hooks))
+ return pm
+
+
+@pytest.fixture
+def pm():
+ from pluggy import PluginManager
+
+ return PluginManager("example")
diff --git a/contrib/python/pluggy/py2/tests/test_deprecations.py b/contrib/python/pluggy/py2/tests/test_deprecations.py
index 72048397d7..7151921b66 100644
--- a/contrib/python/pluggy/py2/tests/test_deprecations.py
+++ b/contrib/python/pluggy/py2/tests/test_deprecations.py
@@ -1,54 +1,54 @@
-"""
-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())
+"""
+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/contrib/python/pluggy/py2/tests/test_details.py b/contrib/python/pluggy/py2/tests/test_details.py
index 4745a155df..fc49fc308d 100644
--- a/contrib/python/pluggy/py2/tests/test_details.py
+++ b/contrib/python/pluggy/py2/tests/test_details.py
@@ -1,135 +1,135 @@
-import warnings
-import pytest
-from pluggy import PluginManager, HookimplMarker, HookspecMarker
-
-hookspec = HookspecMarker("example")
-hookimpl = HookimplMarker("example")
-
-
-def test_parse_hookimpl_override():
- class MyPluginManager(PluginManager):
- def parse_hookimpl_opts(self, module_or_class, name):
- opts = PluginManager.parse_hookimpl_opts(self, module_or_class, name)
- if opts is None:
- if name.startswith("x1"):
- opts = {}
- return opts
-
- class Plugin(object):
- def x1meth(self):
- pass
-
- @hookimpl(hookwrapper=True, tryfirst=True)
- def x1meth2(self):
- pass
-
- class Spec(object):
- @hookspec
- def x1meth(self):
- pass
-
- @hookspec
- def x1meth2(self):
- pass
-
- pm = MyPluginManager(hookspec.project_name)
- pm.register(Plugin())
- pm.add_hookspecs(Spec)
- assert not pm.hook.x1meth._nonwrappers[0].hookwrapper
- assert not pm.hook.x1meth._nonwrappers[0].tryfirst
- assert not pm.hook.x1meth._nonwrappers[0].trylast
- assert not pm.hook.x1meth._nonwrappers[0].optionalhook
-
- assert pm.hook.x1meth2._wrappers[0].tryfirst
- assert pm.hook.x1meth2._wrappers[0].hookwrapper
-
-
-def test_warn_when_deprecated_specified(recwarn):
- warning = DeprecationWarning("foo is deprecated")
-
- class Spec(object):
- @hookspec(warn_on_impl=warning)
- def foo(self):
- pass
-
- class Plugin(object):
- @hookimpl
- def foo(self):
- pass
-
- pm = PluginManager(hookspec.project_name)
- pm.add_hookspecs(Spec)
-
- with pytest.warns(DeprecationWarning) as records:
- pm.register(Plugin())
- (record,) = records
- assert record.message is warning
- assert record.filename == Plugin.foo.__code__.co_filename
- assert record.lineno == Plugin.foo.__code__.co_firstlineno
-
-
-def test_plugin_getattr_raises_errors():
- """Pluggy must be able to handle plugins which raise weird exceptions
- when getattr() gets called (#11).
- """
-
- class DontTouchMe(object):
- def __getattr__(self, x):
- raise Exception("cant touch me")
-
- class Module(object):
- pass
-
- module = Module()
- module.x = DontTouchMe()
-
- pm = PluginManager(hookspec.project_name)
- # register() would raise an error
- pm.register(module, "donttouch")
- assert pm.get_plugin("donttouch") is module
-
-
-def test_warning_on_call_vs_hookspec_arg_mismatch():
- """Verify that is a hook is called with less arguments then defined in the
- spec that a warning is emitted.
- """
-
- class Spec:
- @hookspec
- def myhook(self, arg1, arg2):
- pass
-
- class Plugin:
- @hookimpl
- def myhook(self, arg1):
- pass
-
- pm = PluginManager(hookspec.project_name)
- pm.register(Plugin())
- pm.add_hookspecs(Spec())
-
- with warnings.catch_warnings(record=True) as warns:
- warnings.simplefilter("always")
-
- # calling should trigger a warning
- pm.hook.myhook(arg1=1)
-
- assert len(warns) == 1
- warning = warns[-1]
- assert issubclass(warning.category, Warning)
- assert "Argument(s) ('arg2',)" in str(warning.message)
-
-
-def test_repr():
- class Plugin:
- @hookimpl
- def myhook():
- raise NotImplementedError()
-
- pm = PluginManager(hookspec.project_name)
-
- plugin = Plugin()
- pname = pm.register(plugin)
- assert repr(pm.hook.myhook._nonwrappers[0]) == (
- "<HookImpl plugin_name=%r, plugin=%r>" % (pname, plugin)
- )
+import warnings
+import pytest
+from pluggy import PluginManager, HookimplMarker, HookspecMarker
+
+hookspec = HookspecMarker("example")
+hookimpl = HookimplMarker("example")
+
+
+def test_parse_hookimpl_override():
+ class MyPluginManager(PluginManager):
+ def parse_hookimpl_opts(self, module_or_class, name):
+ opts = PluginManager.parse_hookimpl_opts(self, module_or_class, name)
+ if opts is None:
+ if name.startswith("x1"):
+ opts = {}
+ return opts
+
+ class Plugin(object):
+ def x1meth(self):
+ pass
+
+ @hookimpl(hookwrapper=True, tryfirst=True)
+ def x1meth2(self):
+ pass
+
+ class Spec(object):
+ @hookspec
+ def x1meth(self):
+ pass
+
+ @hookspec
+ def x1meth2(self):
+ pass
+
+ pm = MyPluginManager(hookspec.project_name)
+ pm.register(Plugin())
+ pm.add_hookspecs(Spec)
+ assert not pm.hook.x1meth._nonwrappers[0].hookwrapper
+ assert not pm.hook.x1meth._nonwrappers[0].tryfirst
+ assert not pm.hook.x1meth._nonwrappers[0].trylast
+ assert not pm.hook.x1meth._nonwrappers[0].optionalhook
+
+ assert pm.hook.x1meth2._wrappers[0].tryfirst
+ assert pm.hook.x1meth2._wrappers[0].hookwrapper
+
+
+def test_warn_when_deprecated_specified(recwarn):
+ warning = DeprecationWarning("foo is deprecated")
+
+ class Spec(object):
+ @hookspec(warn_on_impl=warning)
+ def foo(self):
+ pass
+
+ class Plugin(object):
+ @hookimpl
+ def foo(self):
+ pass
+
+ pm = PluginManager(hookspec.project_name)
+ pm.add_hookspecs(Spec)
+
+ with pytest.warns(DeprecationWarning) as records:
+ pm.register(Plugin())
+ (record,) = records
+ assert record.message is warning
+ assert record.filename == Plugin.foo.__code__.co_filename
+ assert record.lineno == Plugin.foo.__code__.co_firstlineno
+
+
+def test_plugin_getattr_raises_errors():
+ """Pluggy must be able to handle plugins which raise weird exceptions
+ when getattr() gets called (#11).
+ """
+
+ class DontTouchMe(object):
+ def __getattr__(self, x):
+ raise Exception("cant touch me")
+
+ class Module(object):
+ pass
+
+ module = Module()
+ module.x = DontTouchMe()
+
+ pm = PluginManager(hookspec.project_name)
+ # register() would raise an error
+ pm.register(module, "donttouch")
+ assert pm.get_plugin("donttouch") is module
+
+
+def test_warning_on_call_vs_hookspec_arg_mismatch():
+ """Verify that is a hook is called with less arguments then defined in the
+ spec that a warning is emitted.
+ """
+
+ class Spec:
+ @hookspec
+ def myhook(self, arg1, arg2):
+ pass
+
+ class Plugin:
+ @hookimpl
+ def myhook(self, arg1):
+ pass
+
+ pm = PluginManager(hookspec.project_name)
+ pm.register(Plugin())
+ pm.add_hookspecs(Spec())
+
+ with warnings.catch_warnings(record=True) as warns:
+ warnings.simplefilter("always")
+
+ # calling should trigger a warning
+ pm.hook.myhook(arg1=1)
+
+ assert len(warns) == 1
+ warning = warns[-1]
+ assert issubclass(warning.category, Warning)
+ assert "Argument(s) ('arg2',)" in str(warning.message)
+
+
+def test_repr():
+ class Plugin:
+ @hookimpl
+ def myhook():
+ raise NotImplementedError()
+
+ pm = PluginManager(hookspec.project_name)
+
+ plugin = Plugin()
+ pname = pm.register(plugin)
+ assert repr(pm.hook.myhook._nonwrappers[0]) == (
+ "<HookImpl plugin_name=%r, plugin=%r>" % (pname, plugin)
+ )
diff --git a/contrib/python/pluggy/py2/tests/test_helpers.py b/contrib/python/pluggy/py2/tests/test_helpers.py
index 63e56ebde8..64c3edaa0a 100644
--- a/contrib/python/pluggy/py2/tests/test_helpers.py
+++ b/contrib/python/pluggy/py2/tests/test_helpers.py
@@ -1,90 +1,90 @@
-from pluggy.hooks import varnames
-from pluggy.manager import _formatdef
-
-import sys
-import pytest
-
-
-def test_varnames():
- def f(x):
- i = 3 # noqa
-
- class A(object):
- def f(self, y):
- pass
-
- class B(object):
- def __call__(self, z):
- pass
-
- assert varnames(f) == (("x",), ())
- assert varnames(A().f) == (("y",), ())
- assert varnames(B()) == (("z",), ())
-
-
-def test_varnames_default():
- def f(x, y=3):
- pass
-
- assert varnames(f) == (("x",), ("y",))
-
-
-def test_varnames_class():
- class C(object):
- def __init__(self, x):
- pass
-
- class D(object):
- pass
-
- class E(object):
- def __init__(self, x):
- pass
-
- class F(object):
- pass
-
- assert varnames(C) == (("x",), ())
- assert varnames(D) == ((), ())
- assert varnames(E) == (("x",), ())
- assert varnames(F) == ((), ())
-
-
-@pytest.mark.skipif(
- sys.version_info < (3,), reason="Keyword only arguments are Python 3 only"
-)
-def test_varnames_keyword_only():
- # SyntaxError on Python 2, so we exec
- ns = {}
- exec(
- "def f1(x, *, y): pass\n"
- "def f2(x, *, y=3): pass\n"
- "def f3(x=1, *, y=3): pass\n",
- ns,
- )
-
- assert varnames(ns["f1"]) == (("x",), ())
- assert varnames(ns["f2"]) == (("x",), ())
- assert varnames(ns["f3"]) == ((), ("x",))
-
-
-def test_formatdef():
- def function1():
- pass
-
- assert _formatdef(function1) == "function1()"
-
- def function2(arg1):
- pass
-
- assert _formatdef(function2) == "function2(arg1)"
-
- def function3(arg1, arg2="qwe"):
- pass
-
- assert _formatdef(function3) == "function3(arg1, arg2='qwe')"
-
- def function4(arg1, *args, **kwargs):
- pass
-
- assert _formatdef(function4) == "function4(arg1, *args, **kwargs)"
+from pluggy.hooks import varnames
+from pluggy.manager import _formatdef
+
+import sys
+import pytest
+
+
+def test_varnames():
+ def f(x):
+ i = 3 # noqa
+
+ class A(object):
+ def f(self, y):
+ pass
+
+ class B(object):
+ def __call__(self, z):
+ pass
+
+ assert varnames(f) == (("x",), ())
+ assert varnames(A().f) == (("y",), ())
+ assert varnames(B()) == (("z",), ())
+
+
+def test_varnames_default():
+ def f(x, y=3):
+ pass
+
+ assert varnames(f) == (("x",), ("y",))
+
+
+def test_varnames_class():
+ class C(object):
+ def __init__(self, x):
+ pass
+
+ class D(object):
+ pass
+
+ class E(object):
+ def __init__(self, x):
+ pass
+
+ class F(object):
+ pass
+
+ assert varnames(C) == (("x",), ())
+ assert varnames(D) == ((), ())
+ assert varnames(E) == (("x",), ())
+ assert varnames(F) == ((), ())
+
+
+@pytest.mark.skipif(
+ sys.version_info < (3,), reason="Keyword only arguments are Python 3 only"
+)
+def test_varnames_keyword_only():
+ # SyntaxError on Python 2, so we exec
+ ns = {}
+ exec(
+ "def f1(x, *, y): pass\n"
+ "def f2(x, *, y=3): pass\n"
+ "def f3(x=1, *, y=3): pass\n",
+ ns,
+ )
+
+ assert varnames(ns["f1"]) == (("x",), ())
+ assert varnames(ns["f2"]) == (("x",), ())
+ assert varnames(ns["f3"]) == ((), ("x",))
+
+
+def test_formatdef():
+ def function1():
+ pass
+
+ assert _formatdef(function1) == "function1()"
+
+ def function2(arg1):
+ pass
+
+ assert _formatdef(function2) == "function2(arg1)"
+
+ def function3(arg1, arg2="qwe"):
+ pass
+
+ assert _formatdef(function3) == "function3(arg1, arg2='qwe')"
+
+ def function4(arg1, *args, **kwargs):
+ pass
+
+ assert _formatdef(function4) == "function4(arg1, *args, **kwargs)"
diff --git a/contrib/python/pluggy/py2/tests/test_hookcaller.py b/contrib/python/pluggy/py2/tests/test_hookcaller.py
index 87ab929f2f..5664f2bbf6 100644
--- a/contrib/python/pluggy/py2/tests/test_hookcaller.py
+++ b/contrib/python/pluggy/py2/tests/test_hookcaller.py
@@ -1,215 +1,215 @@
-import pytest
-
-from pluggy import HookimplMarker, HookspecMarker
-from pluggy.hooks import HookImpl
-
-hookspec = HookspecMarker("example")
-hookimpl = HookimplMarker("example")
-
-
-@pytest.fixture
-def hc(pm):
- class Hooks(object):
- @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(object):
- @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(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) == []
+import pytest
+
+from pluggy import HookimplMarker, HookspecMarker
+from pluggy.hooks import HookImpl
+
+hookspec = HookspecMarker("example")
+hookimpl = HookimplMarker("example")
+
+
+@pytest.fixture
+def hc(pm):
+ class Hooks(object):
+ @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(object):
+ @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(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) == []
diff --git a/contrib/python/pluggy/py2/tests/test_invocations.py b/contrib/python/pluggy/py2/tests/test_invocations.py
index 95d0be5bda..a6ec63cfc7 100644
--- a/contrib/python/pluggy/py2/tests/test_invocations.py
+++ b/contrib/python/pluggy/py2/tests/test_invocations.py
@@ -1,216 +1,216 @@
-import pytest
-from pluggy import PluginValidationError, HookimplMarker, HookspecMarker
-
-
-hookspec = HookspecMarker("example")
-hookimpl = HookimplMarker("example")
-
-
-def test_argmismatch(pm):
- class Api(object):
- @hookspec
- def hello(self, arg):
- "api hook 1"
-
- pm.add_hookspecs(Api)
-
- class Plugin(object):
- @hookimpl
- def hello(self, argwrong):
- pass
-
- with pytest.raises(PluginValidationError) as exc:
- pm.register(Plugin())
-
- assert "argwrong" in str(exc.value)
-
-
-def test_only_kwargs(pm):
- class Api(object):
- @hookspec
- def hello(self, arg):
- "api hook 1"
-
- pm.add_hookspecs(Api)
- with pytest.raises(TypeError) as exc:
- pm.hook.hello(3)
-
- comprehensible = "hook calling supports only keyword arguments"
- assert comprehensible in str(exc.value)
-
-
-def test_opt_in_args(pm):
- """Verfiy that two hookimpls with mutex args can serve
- under the same spec.
- """
-
- class Api(object):
- @hookspec
- def hello(self, arg1, arg2, common_arg):
- "api hook 1"
-
- class Plugin1(object):
- @hookimpl
- def hello(self, arg1, common_arg):
- return arg1 + common_arg
-
- class Plugin2(object):
- @hookimpl
- def hello(self, arg2, common_arg):
- return arg2 + common_arg
-
- pm.add_hookspecs(Api)
- pm.register(Plugin1())
- pm.register(Plugin2())
-
- results = pm.hook.hello(arg1=1, arg2=2, common_arg=0)
- assert results == [2, 1]
-
-
-def test_call_order(pm):
- class Api(object):
- @hookspec
- def hello(self, arg):
- "api hook 1"
-
- pm.add_hookspecs(Api)
-
- class Plugin1(object):
- @hookimpl
- def hello(self, arg):
- return 1
-
- class Plugin2(object):
- @hookimpl
- def hello(self, arg):
- return 2
-
- class Plugin3(object):
- @hookimpl
- def hello(self, arg):
- return 3
-
- class Plugin4(object):
- @hookimpl(hookwrapper=True)
- def hello(self, arg):
- assert arg == 0
- outcome = yield
- assert outcome.get_result() == [3, 2, 1]
-
- pm.register(Plugin1())
- pm.register(Plugin2())
- pm.register(Plugin3())
- pm.register(Plugin4()) # hookwrapper should get same list result
- res = pm.hook.hello(arg=0)
- assert res == [3, 2, 1]
-
-
-def test_firstresult_definition(pm):
- 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 arg + 1
-
- class Plugin2(object):
- @hookimpl
- def hello(self, arg):
- return arg - 1
-
- class Plugin3(object):
- @hookimpl
- def hello(self, arg):
- return None
-
- class Plugin4(object):
- @hookimpl(hookwrapper=True)
- def hello(self, arg):
- assert arg == 3
- outcome = yield
- assert outcome.get_result() == 2
-
- pm.register(Plugin1()) # discarded - not the last registered plugin
- pm.register(Plugin2()) # used as result
- pm.register(Plugin3()) # None result is ignored
- pm.register(Plugin4()) # hookwrapper should get same non-list result
- res = pm.hook.hello(arg=3)
- assert res == 2
-
-
-def test_firstresult_force_result(pm):
- """Verify forcing a result in a wrapper.
- """
-
- 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 arg + 1
-
- class Plugin2(object):
- @hookimpl(hookwrapper=True)
- def hello(self, arg):
- assert arg == 3
- outcome = yield
- assert outcome.get_result() == 4
- outcome.force_result(0)
-
- class Plugin3(object):
- @hookimpl
- def hello(self, arg):
- return None
-
- pm.register(Plugin1())
- pm.register(Plugin2()) # wrapper
- pm.register(Plugin3()) # ignored since returns None
- res = pm.hook.hello(arg=3)
- assert res == 0 # this result is forced and not a list
-
-
-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 is 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 is None
+import pytest
+from pluggy import PluginValidationError, HookimplMarker, HookspecMarker
+
+
+hookspec = HookspecMarker("example")
+hookimpl = HookimplMarker("example")
+
+
+def test_argmismatch(pm):
+ class Api(object):
+ @hookspec
+ def hello(self, arg):
+ "api hook 1"
+
+ pm.add_hookspecs(Api)
+
+ class Plugin(object):
+ @hookimpl
+ def hello(self, argwrong):
+ pass
+
+ with pytest.raises(PluginValidationError) as exc:
+ pm.register(Plugin())
+
+ assert "argwrong" in str(exc.value)
+
+
+def test_only_kwargs(pm):
+ class Api(object):
+ @hookspec
+ def hello(self, arg):
+ "api hook 1"
+
+ pm.add_hookspecs(Api)
+ with pytest.raises(TypeError) as exc:
+ pm.hook.hello(3)
+
+ comprehensible = "hook calling supports only keyword arguments"
+ assert comprehensible in str(exc.value)
+
+
+def test_opt_in_args(pm):
+ """Verfiy that two hookimpls with mutex args can serve
+ under the same spec.
+ """
+
+ class Api(object):
+ @hookspec
+ def hello(self, arg1, arg2, common_arg):
+ "api hook 1"
+
+ class Plugin1(object):
+ @hookimpl
+ def hello(self, arg1, common_arg):
+ return arg1 + common_arg
+
+ class Plugin2(object):
+ @hookimpl
+ def hello(self, arg2, common_arg):
+ return arg2 + common_arg
+
+ pm.add_hookspecs(Api)
+ pm.register(Plugin1())
+ pm.register(Plugin2())
+
+ results = pm.hook.hello(arg1=1, arg2=2, common_arg=0)
+ assert results == [2, 1]
+
+
+def test_call_order(pm):
+ class Api(object):
+ @hookspec
+ def hello(self, arg):
+ "api hook 1"
+
+ pm.add_hookspecs(Api)
+
+ class Plugin1(object):
+ @hookimpl
+ def hello(self, arg):
+ return 1
+
+ class Plugin2(object):
+ @hookimpl
+ def hello(self, arg):
+ return 2
+
+ class Plugin3(object):
+ @hookimpl
+ def hello(self, arg):
+ return 3
+
+ class Plugin4(object):
+ @hookimpl(hookwrapper=True)
+ def hello(self, arg):
+ assert arg == 0
+ outcome = yield
+ assert outcome.get_result() == [3, 2, 1]
+
+ pm.register(Plugin1())
+ pm.register(Plugin2())
+ pm.register(Plugin3())
+ pm.register(Plugin4()) # hookwrapper should get same list result
+ res = pm.hook.hello(arg=0)
+ assert res == [3, 2, 1]
+
+
+def test_firstresult_definition(pm):
+ 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 arg + 1
+
+ class Plugin2(object):
+ @hookimpl
+ def hello(self, arg):
+ return arg - 1
+
+ class Plugin3(object):
+ @hookimpl
+ def hello(self, arg):
+ return None
+
+ class Plugin4(object):
+ @hookimpl(hookwrapper=True)
+ def hello(self, arg):
+ assert arg == 3
+ outcome = yield
+ assert outcome.get_result() == 2
+
+ pm.register(Plugin1()) # discarded - not the last registered plugin
+ pm.register(Plugin2()) # used as result
+ pm.register(Plugin3()) # None result is ignored
+ pm.register(Plugin4()) # hookwrapper should get same non-list result
+ res = pm.hook.hello(arg=3)
+ assert res == 2
+
+
+def test_firstresult_force_result(pm):
+ """Verify forcing a result in a wrapper.
+ """
+
+ 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 arg + 1
+
+ class Plugin2(object):
+ @hookimpl(hookwrapper=True)
+ def hello(self, arg):
+ assert arg == 3
+ outcome = yield
+ assert outcome.get_result() == 4
+ outcome.force_result(0)
+
+ class Plugin3(object):
+ @hookimpl
+ def hello(self, arg):
+ return None
+
+ pm.register(Plugin1())
+ pm.register(Plugin2()) # wrapper
+ pm.register(Plugin3()) # ignored since returns None
+ res = pm.hook.hello(arg=3)
+ assert res == 0 # this result is forced and not a list
+
+
+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 is 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 is None
diff --git a/contrib/python/pluggy/py2/tests/test_multicall.py b/contrib/python/pluggy/py2/tests/test_multicall.py
index 7a6f0a87ec..eaf534a016 100644
--- a/contrib/python/pluggy/py2/tests/test_multicall.py
+++ b/contrib/python/pluggy/py2/tests/test_multicall.py
@@ -1,186 +1,186 @@
-import pytest
-from pluggy import HookCallError, HookspecMarker, HookimplMarker
-from pluggy.hooks import HookImpl
-from pluggy.callers import _multicall, _legacymulticall
-
-
-hookspec = HookspecMarker("example")
-hookimpl = HookimplMarker("example")
-
-
-def MC(methods, kwargs, firstresult=False):
- caller = _multicall
- hookfuncs = []
- for method in methods:
- f = HookImpl(None, "<temp>", method, method.example_impl)
- hookfuncs.append(f)
- if "__multicall__" in f.argnames:
- caller = _legacymulticall
- return caller(hookfuncs, kwargs, firstresult=firstresult)
-
-
-def test_call_passing():
- class P1(object):
- @hookimpl
- def m(self, __multicall__, x):
- assert len(__multicall__.results) == 1
- assert not __multicall__.hook_impls
- return 17
-
- class P2(object):
- @hookimpl
- def m(self, __multicall__, x):
- assert __multicall__.results == []
- assert __multicall__.hook_impls
- return 23
-
- p1 = P1()
- p2 = P2()
- reslist = MC([p1.m, p2.m], {"x": 23})
- assert len(reslist) == 2
- # ensure reversed order
- assert reslist == [23, 17]
-
-
-def test_keyword_args():
- @hookimpl
- def f(x):
- return x + 1
-
- class A(object):
- @hookimpl
- def f(self, x, y):
- return x + y
-
- reslist = MC([f, A().f], dict(x=23, y=24))
- assert reslist == [24 + 23, 24]
-
-
-def test_keyword_args_with_defaultargs():
- @hookimpl
- def f(x, z=1):
- return x + z
-
- reslist = MC([f], dict(x=23, y=24))
- assert reslist == [24]
-
-
-def test_tags_call_error():
- @hookimpl
- def f(x):
- return x
-
- with pytest.raises(HookCallError):
- MC([f], {})
-
-
-def test_call_subexecute():
- @hookimpl
- def m(__multicall__):
- subresult = __multicall__.execute()
- return subresult + 1
-
- @hookimpl
- def n():
- return 1
-
- res = MC([n, m], {}, firstresult=True)
- assert res == 2
-
-
-def test_call_none_is_no_result():
- @hookimpl
- def m1():
- return 1
-
- @hookimpl
- def m2():
- return None
-
- res = MC([m1, m2], {}, firstresult=True)
- assert res == 1
- res = MC([m1, m2], {}, {})
- assert res == [1]
-
-
-def test_hookwrapper():
- out = []
-
- @hookimpl(hookwrapper=True)
- def m1():
- out.append("m1 init")
- yield None
- out.append("m1 finish")
-
- @hookimpl
- def m2():
- out.append("m2")
- return 2
-
- res = MC([m2, m1], {})
- assert res == [2]
- assert out == ["m1 init", "m2", "m1 finish"]
- out[:] = []
- res = MC([m2, m1], {}, firstresult=True)
- assert res == 2
- assert out == ["m1 init", "m2", "m1 finish"]
-
-
-def test_hookwrapper_order():
- out = []
-
- @hookimpl(hookwrapper=True)
- def m1():
- out.append("m1 init")
- yield 1
- out.append("m1 finish")
-
- @hookimpl(hookwrapper=True)
- def m2():
- out.append("m2 init")
- yield 2
- out.append("m2 finish")
-
- res = MC([m2, m1], {})
- assert res == []
- assert out == ["m1 init", "m2 init", "m2 finish", "m1 finish"]
-
-
-def test_hookwrapper_not_yield():
- @hookimpl(hookwrapper=True)
- def m1():
- pass
-
- with pytest.raises(TypeError):
- MC([m1], {})
-
-
-def test_hookwrapper_too_many_yield():
- @hookimpl(hookwrapper=True)
- def m1():
- yield 1
- yield 2
-
- with pytest.raises(RuntimeError) as ex:
- MC([m1], {})
- assert "m1" in str(ex.value)
- assert (__file__ + ":") in str(ex.value)
-
-
-@pytest.mark.parametrize("exc", [ValueError, SystemExit])
-def test_hookwrapper_exception(exc):
- out = []
-
- @hookimpl(hookwrapper=True)
- def m1():
- out.append("m1 init")
- yield None
- out.append("m1 finish")
-
- @hookimpl
- def m2():
- raise exc
-
- with pytest.raises(exc):
- MC([m2, m1], {})
- assert out == ["m1 init", "m1 finish"]
+import pytest
+from pluggy import HookCallError, HookspecMarker, HookimplMarker
+from pluggy.hooks import HookImpl
+from pluggy.callers import _multicall, _legacymulticall
+
+
+hookspec = HookspecMarker("example")
+hookimpl = HookimplMarker("example")
+
+
+def MC(methods, kwargs, firstresult=False):
+ caller = _multicall
+ hookfuncs = []
+ for method in methods:
+ f = HookImpl(None, "<temp>", method, method.example_impl)
+ hookfuncs.append(f)
+ if "__multicall__" in f.argnames:
+ caller = _legacymulticall
+ return caller(hookfuncs, kwargs, firstresult=firstresult)
+
+
+def test_call_passing():
+ class P1(object):
+ @hookimpl
+ def m(self, __multicall__, x):
+ assert len(__multicall__.results) == 1
+ assert not __multicall__.hook_impls
+ return 17
+
+ class P2(object):
+ @hookimpl
+ def m(self, __multicall__, x):
+ assert __multicall__.results == []
+ assert __multicall__.hook_impls
+ return 23
+
+ p1 = P1()
+ p2 = P2()
+ reslist = MC([p1.m, p2.m], {"x": 23})
+ assert len(reslist) == 2
+ # ensure reversed order
+ assert reslist == [23, 17]
+
+
+def test_keyword_args():
+ @hookimpl
+ def f(x):
+ return x + 1
+
+ class A(object):
+ @hookimpl
+ def f(self, x, y):
+ return x + y
+
+ reslist = MC([f, A().f], dict(x=23, y=24))
+ assert reslist == [24 + 23, 24]
+
+
+def test_keyword_args_with_defaultargs():
+ @hookimpl
+ def f(x, z=1):
+ return x + z
+
+ reslist = MC([f], dict(x=23, y=24))
+ assert reslist == [24]
+
+
+def test_tags_call_error():
+ @hookimpl
+ def f(x):
+ return x
+
+ with pytest.raises(HookCallError):
+ MC([f], {})
+
+
+def test_call_subexecute():
+ @hookimpl
+ def m(__multicall__):
+ subresult = __multicall__.execute()
+ return subresult + 1
+
+ @hookimpl
+ def n():
+ return 1
+
+ res = MC([n, m], {}, firstresult=True)
+ assert res == 2
+
+
+def test_call_none_is_no_result():
+ @hookimpl
+ def m1():
+ return 1
+
+ @hookimpl
+ def m2():
+ return None
+
+ res = MC([m1, m2], {}, firstresult=True)
+ assert res == 1
+ res = MC([m1, m2], {}, {})
+ assert res == [1]
+
+
+def test_hookwrapper():
+ out = []
+
+ @hookimpl(hookwrapper=True)
+ def m1():
+ out.append("m1 init")
+ yield None
+ out.append("m1 finish")
+
+ @hookimpl
+ def m2():
+ out.append("m2")
+ return 2
+
+ res = MC([m2, m1], {})
+ assert res == [2]
+ assert out == ["m1 init", "m2", "m1 finish"]
+ out[:] = []
+ res = MC([m2, m1], {}, firstresult=True)
+ assert res == 2
+ assert out == ["m1 init", "m2", "m1 finish"]
+
+
+def test_hookwrapper_order():
+ out = []
+
+ @hookimpl(hookwrapper=True)
+ def m1():
+ out.append("m1 init")
+ yield 1
+ out.append("m1 finish")
+
+ @hookimpl(hookwrapper=True)
+ def m2():
+ out.append("m2 init")
+ yield 2
+ out.append("m2 finish")
+
+ res = MC([m2, m1], {})
+ assert res == []
+ assert out == ["m1 init", "m2 init", "m2 finish", "m1 finish"]
+
+
+def test_hookwrapper_not_yield():
+ @hookimpl(hookwrapper=True)
+ def m1():
+ pass
+
+ with pytest.raises(TypeError):
+ MC([m1], {})
+
+
+def test_hookwrapper_too_many_yield():
+ @hookimpl(hookwrapper=True)
+ def m1():
+ yield 1
+ yield 2
+
+ with pytest.raises(RuntimeError) as ex:
+ MC([m1], {})
+ assert "m1" in str(ex.value)
+ assert (__file__ + ":") in str(ex.value)
+
+
+@pytest.mark.parametrize("exc", [ValueError, SystemExit])
+def test_hookwrapper_exception(exc):
+ out = []
+
+ @hookimpl(hookwrapper=True)
+ def m1():
+ out.append("m1 init")
+ yield None
+ out.append("m1 finish")
+
+ @hookimpl
+ def m2():
+ raise exc
+
+ with pytest.raises(exc):
+ MC([m2, m1], {})
+ assert out == ["m1 init", "m1 finish"]
diff --git a/contrib/python/pluggy/py2/tests/test_pluginmanager.py b/contrib/python/pluggy/py2/tests/test_pluginmanager.py
index 09d83ab9d4..67261aaa7b 100644
--- a/contrib/python/pluggy/py2/tests/test_pluginmanager.py
+++ b/contrib/python/pluggy/py2/tests/test_pluginmanager.py
@@ -1,600 +1,600 @@
-"""
-``PluginManager`` unit and public API testing.
-"""
-import pytest
-import types
-
-from pluggy import (
- PluginManager,
- PluginValidationError,
- HookCallError,
- HookimplMarker,
- HookspecMarker,
-)
-from pluggy.manager import importlib_metadata
-
-
-hookspec = HookspecMarker("example")
-hookimpl = HookimplMarker("example")
-
-
-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")
- with pytest.raises(ValueError):
- pm.register(42, name="def")
-
-
-def test_pm(pm):
- """Basic registration with objects"""
-
- 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
-
- plugin = hello()
-
- he_pm.register(plugin)
- with pytest.raises(PluginValidationError) as excinfo:
- he_pm.check_pending()
- assert excinfo.value.plugin is plugin
-
-
-def test_register_mismatch_arg(he_pm):
- class hello(object):
- @hookimpl
- def he_method1(self, qlwkje):
- pass
-
- plugin = hello()
-
- with pytest.raises(PluginValidationError) as excinfo:
- he_pm.register(plugin)
- assert excinfo.value.plugin is plugin
-
-
-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]
-
-
-@pytest.mark.parametrize("result_callback", [True, False])
-def test_with_result_memorized(pm, result_callback):
- """Verify that ``_HookCaller._maybe_apply_history()`
- correctly applies the ``result_callback`` function, when provided,
- to the result from calling each newly registered hook.
- """
- out = []
- if result_callback:
-
- def callback(res):
- out.append(res)
-
- else:
- callback = None
-
- 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
-
- pm.register(Plugin1())
-
- he_method1 = pm.hook.he_method1
- he_method1.call_historic(result_callback=callback, kwargs=dict(arg=1))
-
- class Plugin2(object):
- @hookimpl
- def he_method1(self, arg):
- return arg * 10
-
- pm.register(Plugin2())
- if result_callback:
- assert out == [10, 10]
- else:
- assert out == []
-
-
-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_get_hookimpls(pm):
- class Hooks(object):
- @hookspec
- def he_method1(self, arg):
- pass
-
- pm.add_hookspecs(Hooks)
- assert pm.hook.he_method1.get_hookimpls() == []
-
- class Plugin1(object):
- @hookimpl
- def he_method1(self, arg):
- pass
-
- class Plugin2(object):
- @hookimpl
- def he_method1(self, arg):
- pass
-
- class PluginNo(object):
- pass
-
- plugin1, plugin2, plugin3 = Plugin1(), Plugin2(), PluginNo()
- pm.register(plugin1)
- pm.register(plugin2)
- pm.register(plugin3)
-
- hookimpls = pm.hook.he_method1.get_hookimpls()
- hook_plugins = [item.plugin for item in hookimpls]
- assert hook_plugins == [plugin1, plugin2]
-
-
-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")
- with pytest.deprecated_call():
- 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
- with pytest.deprecated_call():
- assert pm.parse_hookimpl_opts(conftest, "example_blah") is None
- assert pm.parse_hookimpl_opts(conftest, "example_hook") == {}
-
-
-def test_load_setuptools_instantiation(monkeypatch, pm):
- class EntryPoint(object):
- name = "myname"
- group = "hello"
- value = "myname:foo"
-
- def load(self):
- class PseudoPlugin(object):
- x = 42
-
- return PseudoPlugin()
-
- class Distribution(object):
- entry_points = (EntryPoint(),)
-
- dist = Distribution()
-
- def my_distributions():
- return (dist,)
-
- monkeypatch.setattr(importlib_metadata, "distributions", my_distributions)
- num = pm.load_setuptools_entrypoints("hello")
- assert num == 1
- plugin = pm.get_plugin("myname")
- assert plugin.x == 42
- ret = pm.list_plugin_distinfo()
- # poor man's `assert ret == [(plugin, mock.ANY)]`
- assert len(ret) == 1
- assert len(ret[0]) == 2
- assert ret[0][0] == plugin
- assert ret[0][1]._dist == dist
- num = pm.load_setuptools_entrypoints("hello")
- assert num == 0 # no plugin loaded by this call
-
-
-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)
-
- 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()
-
-
-def test_implprefix_warning(recwarn):
- PluginManager(hookspec.project_name, "hello_")
- w = recwarn.pop(DeprecationWarning)
- assert "test_pluginmanager.py" in w.filename
-
-
-@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 = PluginManager(hookspec.project_name, "hello_")
-
- class BadPlugin(object):
- hello_module = __import__("email")
-
- pm.register(BadPlugin())
- pm.check_pending()
+"""
+``PluginManager`` unit and public API testing.
+"""
+import pytest
+import types
+
+from pluggy import (
+ PluginManager,
+ PluginValidationError,
+ HookCallError,
+ HookimplMarker,
+ HookspecMarker,
+)
+from pluggy.manager import importlib_metadata
+
+
+hookspec = HookspecMarker("example")
+hookimpl = HookimplMarker("example")
+
+
+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")
+ with pytest.raises(ValueError):
+ pm.register(42, name="def")
+
+
+def test_pm(pm):
+ """Basic registration with objects"""
+
+ 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
+
+ plugin = hello()
+
+ he_pm.register(plugin)
+ with pytest.raises(PluginValidationError) as excinfo:
+ he_pm.check_pending()
+ assert excinfo.value.plugin is plugin
+
+
+def test_register_mismatch_arg(he_pm):
+ class hello(object):
+ @hookimpl
+ def he_method1(self, qlwkje):
+ pass
+
+ plugin = hello()
+
+ with pytest.raises(PluginValidationError) as excinfo:
+ he_pm.register(plugin)
+ assert excinfo.value.plugin is plugin
+
+
+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]
+
+
+@pytest.mark.parametrize("result_callback", [True, False])
+def test_with_result_memorized(pm, result_callback):
+ """Verify that ``_HookCaller._maybe_apply_history()`
+ correctly applies the ``result_callback`` function, when provided,
+ to the result from calling each newly registered hook.
+ """
+ out = []
+ if result_callback:
+
+ def callback(res):
+ out.append(res)
+
+ else:
+ callback = None
+
+ 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
+
+ pm.register(Plugin1())
+
+ he_method1 = pm.hook.he_method1
+ he_method1.call_historic(result_callback=callback, kwargs=dict(arg=1))
+
+ class Plugin2(object):
+ @hookimpl
+ def he_method1(self, arg):
+ return arg * 10
+
+ pm.register(Plugin2())
+ if result_callback:
+ assert out == [10, 10]
+ else:
+ assert out == []
+
+
+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_get_hookimpls(pm):
+ class Hooks(object):
+ @hookspec
+ def he_method1(self, arg):
+ pass
+
+ pm.add_hookspecs(Hooks)
+ assert pm.hook.he_method1.get_hookimpls() == []
+
+ class Plugin1(object):
+ @hookimpl
+ def he_method1(self, arg):
+ pass
+
+ class Plugin2(object):
+ @hookimpl
+ def he_method1(self, arg):
+ pass
+
+ class PluginNo(object):
+ pass
+
+ plugin1, plugin2, plugin3 = Plugin1(), Plugin2(), PluginNo()
+ pm.register(plugin1)
+ pm.register(plugin2)
+ pm.register(plugin3)
+
+ hookimpls = pm.hook.he_method1.get_hookimpls()
+ hook_plugins = [item.plugin for item in hookimpls]
+ assert hook_plugins == [plugin1, plugin2]
+
+
+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")
+ with pytest.deprecated_call():
+ 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
+ with pytest.deprecated_call():
+ assert pm.parse_hookimpl_opts(conftest, "example_blah") is None
+ assert pm.parse_hookimpl_opts(conftest, "example_hook") == {}
+
+
+def test_load_setuptools_instantiation(monkeypatch, pm):
+ class EntryPoint(object):
+ name = "myname"
+ group = "hello"
+ value = "myname:foo"
+
+ def load(self):
+ class PseudoPlugin(object):
+ x = 42
+
+ return PseudoPlugin()
+
+ class Distribution(object):
+ entry_points = (EntryPoint(),)
+
+ dist = Distribution()
+
+ def my_distributions():
+ return (dist,)
+
+ monkeypatch.setattr(importlib_metadata, "distributions", my_distributions)
+ num = pm.load_setuptools_entrypoints("hello")
+ assert num == 1
+ plugin = pm.get_plugin("myname")
+ assert plugin.x == 42
+ ret = pm.list_plugin_distinfo()
+ # poor man's `assert ret == [(plugin, mock.ANY)]`
+ assert len(ret) == 1
+ assert len(ret[0]) == 2
+ assert ret[0][0] == plugin
+ assert ret[0][1]._dist == dist
+ num = pm.load_setuptools_entrypoints("hello")
+ assert num == 0 # no plugin loaded by this call
+
+
+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)
+
+ 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()
+
+
+def test_implprefix_warning(recwarn):
+ PluginManager(hookspec.project_name, "hello_")
+ w = recwarn.pop(DeprecationWarning)
+ assert "test_pluginmanager.py" in w.filename
+
+
+@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 = PluginManager(hookspec.project_name, "hello_")
+
+ class BadPlugin(object):
+ hello_module = __import__("email")
+
+ pm.register(BadPlugin())
+ pm.check_pending()
diff --git a/contrib/python/pluggy/py2/tests/test_tracer.py b/contrib/python/pluggy/py2/tests/test_tracer.py
index 7915f0ee75..992ec67914 100644
--- a/contrib/python/pluggy/py2/tests/test_tracer.py
+++ b/contrib/python/pluggy/py2/tests/test_tracer.py
@@ -1,78 +1,78 @@
-from pluggy._tracing import TagTracer
-
-import pytest
-
-
-@pytest.fixture
-def rootlogger():
- return TagTracer()
-
-
-def test_simple(rootlogger):
- log = rootlogger.get("pytest")
- log("hello")
- out = []
- rootlogger.setwriter(out.append)
- log("world")
- assert len(out) == 1
- assert out[0] == "world [pytest]\n"
- sublog = log.get("collection")
- sublog("hello")
- assert out[1] == "hello [pytest:collection]\n"
-
-
-def test_indent(rootlogger):
- log = rootlogger.get("1")
- out = []
- log.root.setwriter(lambda arg: out.append(arg))
- log("hello")
- log.root.indent += 1
- log("line1")
- log("line2")
- log.root.indent += 1
- log("line3")
- log("line4")
- log.root.indent -= 1
- log("line5")
- log.root.indent -= 1
- log("last")
- assert len(out) == 7
- names = [x[: x.rfind(" [")] for x in out]
- assert names == [
- "hello",
- " line1",
- " line2",
- " line3",
- " line4",
- " line5",
- "last",
- ]
-
-
-def test_readable_output_dictargs(rootlogger):
-
- out = rootlogger._format_message(["test"], [1])
- assert out == "1 [test]\n"
-
- out2 = rootlogger._format_message(["test"], ["test", {"a": 1}])
- assert out2 == "test [test]\n a: 1\n"
-
-
-def test_setprocessor(rootlogger):
- log = rootlogger.get("1")
- log2 = log.get("2")
- assert log2.tags == tuple("12")
- out = []
- rootlogger.setprocessor(tuple("12"), lambda *args: out.append(args))
- log("not seen")
- log2("seen")
- assert len(out) == 1
- tags, args = out[0]
- assert "1" in tags
- assert "2" in tags
- assert args == ("seen",)
- l2 = []
- rootlogger.setprocessor("1:2", lambda *args: l2.append(args))
- log2("seen")
- tags, args = l2[0]
- assert args == ("seen",)
+from pluggy._tracing import TagTracer
+
+import pytest
+
+
+@pytest.fixture
+def rootlogger():
+ return TagTracer()
+
+
+def test_simple(rootlogger):
+ log = rootlogger.get("pytest")
+ log("hello")
+ out = []
+ rootlogger.setwriter(out.append)
+ log("world")
+ assert len(out) == 1
+ assert out[0] == "world [pytest]\n"
+ sublog = log.get("collection")
+ sublog("hello")
+ assert out[1] == "hello [pytest:collection]\n"
+
+
+def test_indent(rootlogger):
+ log = rootlogger.get("1")
+ out = []
+ log.root.setwriter(lambda arg: out.append(arg))
+ log("hello")
+ log.root.indent += 1
+ log("line1")
+ log("line2")
+ log.root.indent += 1
+ log("line3")
+ log("line4")
+ log.root.indent -= 1
+ log("line5")
+ log.root.indent -= 1
+ log("last")
+ assert len(out) == 7
+ names = [x[: x.rfind(" [")] for x in out]
+ assert names == [
+ "hello",
+ " line1",
+ " line2",
+ " line3",
+ " line4",
+ " line5",
+ "last",
+ ]
+
+
+def test_readable_output_dictargs(rootlogger):
+
+ out = rootlogger._format_message(["test"], [1])
+ assert out == "1 [test]\n"
+
+ out2 = rootlogger._format_message(["test"], ["test", {"a": 1}])
+ assert out2 == "test [test]\n a: 1\n"
+
+
+def test_setprocessor(rootlogger):
+ log = rootlogger.get("1")
+ log2 = log.get("2")
+ assert log2.tags == tuple("12")
+ out = []
+ rootlogger.setprocessor(tuple("12"), lambda *args: out.append(args))
+ log("not seen")
+ log2("seen")
+ assert len(out) == 1
+ tags, args = out[0]
+ assert "1" in tags
+ assert "2" in tags
+ assert args == ("seen",)
+ l2 = []
+ rootlogger.setprocessor("1:2", lambda *args: l2.append(args))
+ log2("seen")
+ tags, args = l2[0]
+ assert args == ("seen",)
diff --git a/contrib/python/pluggy/py2/tests/ya.make b/contrib/python/pluggy/py2/tests/ya.make
index 2091a66adf..a0bd221149 100644
--- a/contrib/python/pluggy/py2/tests/ya.make
+++ b/contrib/python/pluggy/py2/tests/ya.make
@@ -1,23 +1,23 @@
-PY2TEST()
-
-OWNER(g:python-contrib)
-
-PEERDIR (
- contrib/python/pluggy
-)
-
-TEST_SRCS(
- conftest.py
- test_deprecations.py
- test_details.py
- test_helpers.py
- test_hookcaller.py
- test_invocations.py
- test_multicall.py
- test_pluginmanager.py
- test_tracer.py
-)
-
-NO_LINT()
-
-END()
+PY2TEST()
+
+OWNER(g:python-contrib)
+
+PEERDIR (
+ contrib/python/pluggy
+)
+
+TEST_SRCS(
+ conftest.py
+ test_deprecations.py
+ test_details.py
+ test_helpers.py
+ test_hookcaller.py
+ test_invocations.py
+ test_multicall.py
+ test_pluginmanager.py
+ test_tracer.py
+)
+
+NO_LINT()
+
+END()