File: test_details.py

package info (click to toggle)
napari-plugin-engine 0.2.0-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 436 kB
  • sloc: python: 3,052; makefile: 21
file content (113 lines) | stat: -rw-r--r-- 2,770 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import warnings

import pytest

from napari_plugin_engine import (
    HookImplementationMarker,
    HookSpecificationMarker,
    PluginManager,
)

hookspec = HookSpecificationMarker("example")
hookimpl = HookImplementationMarker("example")


def test_warn_when_deprecated_specified(recwarn):
    warning = DeprecationWarning("foo is deprecated")

    class Spec:
        @hookspec(warn_on_impl=warning)
        def foo(self):
            pass

    class Plugin:
        @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():
    """napari_plugin_engine must be able to handle plugins which raise weird exceptions
    when getattr() gets called (#11).
    """

    class DontTouchMe:
        def __getattr__(self, x):
            raise Exception("cant touch me")

    class Module:
        pass

    module = Module()
    module.x = DontTouchMe()

    pm = PluginManager(hookspec.project_name)
    # register() would raise an error
    pm.register(module, "donttouch")
    assert pm.plugins.get("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 Hook:
        @hookspec
        def myhook(arg):
            ...

    class Plugin:
        @hookimpl
        def myhook(arg):
            raise NotImplementedError()

    pm = PluginManager(hookspec.project_name)
    pm.add_hookspecs(Hook)

    assert (
        repr(pm.hook.myhook.spec)
        == "<HookSpecification 'myhook' args=('arg',)>"
    )

    plugin = Plugin()
    pname = pm.register(plugin)
    expected = f"<HookImplementation plugin={pname!r} spec='myhook'>"
    assert repr(pm.hook.myhook._nonwrappers[0]) == expected