1from ..plugin_registry import PluginRegistry
2from typing import Callable
3
4
5class TypedCallableRegistry(PluginRegistry[Callable[[int], int]]):
6    pass
7
8
9class GeneralCallableRegistry(PluginRegistry):
10    _global_settings = {"global_setting": None}
11
12    @property
13    def global_setting(self):
14        return self._global_settings["global_setting"]
15
16    @global_setting.setter
17    def global_setting(self, val):
18        self._global_settings["global_setting"] = val
19
20
21def test_plugin_registry():
22    plugins = TypedCallableRegistry()
23
24    assert plugins.names() == []
25    assert plugins.active == ""
26    assert plugins.get() is None
27    assert repr(plugins) == "TypedCallableRegistry(active='', registered=[])"
28
29    plugins.register("new_plugin", lambda x: x ** 2)
30    assert plugins.names() == ["new_plugin"]
31    assert plugins.active == ""
32    assert plugins.get() is None
33    assert repr(plugins) == (
34        "TypedCallableRegistry(active='', " "registered=['new_plugin'])"
35    )
36
37    plugins.enable("new_plugin")
38    assert plugins.names() == ["new_plugin"]
39    assert plugins.active == "new_plugin"
40    assert plugins.get()(3) == 9
41    assert repr(plugins) == (
42        "TypedCallableRegistry(active='new_plugin', " "registered=['new_plugin'])"
43    )
44
45
46def test_plugin_registry_extra_options():
47    plugins = GeneralCallableRegistry()
48
49    plugins.register("metadata_plugin", lambda x, p=2: x ** p)
50    plugins.enable("metadata_plugin")
51    assert plugins.get()(3) == 9
52
53    plugins.enable("metadata_plugin", p=3)
54    assert plugins.active == "metadata_plugin"
55    assert plugins.get()(3) == 27
56
57    # enabling without changing name
58    plugins.enable(p=2)
59    assert plugins.active == "metadata_plugin"
60    assert plugins.get()(3) == 9
61
62
63def test_plugin_registry_global_settings():
64    plugins = GeneralCallableRegistry()
65
66    # we need some default plugin, but we won't do anything with it
67    plugins.register("default", lambda x: x)
68    plugins.enable("default")
69
70    # default value of the global flag
71    assert plugins.global_setting is None
72
73    # enabling changes the global state, not the options
74    plugins.enable(global_setting=True)
75    assert plugins.global_setting is True
76    assert plugins._options == {}
77
78    # context manager changes global state temporarily
79    with plugins.enable(global_setting="temp"):
80        assert plugins.global_setting == "temp"
81        assert plugins._options == {}
82    assert plugins.global_setting is True
83    assert plugins._options == {}
84
85
86def test_plugin_registry_context():
87    plugins = GeneralCallableRegistry()
88
89    plugins.register("default", lambda x, p=2: x ** p)
90
91    # At first there is no plugin enabled
92    assert plugins.active == ""
93    assert plugins.options == {}
94
95    # Make sure the context is set and reset correctly
96    with plugins.enable("default", p=6):
97        assert plugins.active == "default"
98        assert plugins.options == {"p": 6}
99
100    assert plugins.active == ""
101    assert plugins.options == {}
102
103    # Make sure the context is reset even if there is an error
104    try:
105        with plugins.enable("default", p=6):
106            assert plugins.active == "default"
107            assert plugins.options == {"p": 6}
108            raise ValueError()
109    except ValueError:
110        pass
111
112    assert plugins.active == ""
113    assert plugins.options == {}
114
115    # Enabling without specifying name uses current name
116    plugins.enable("default", p=2)
117
118    with plugins.enable(p=6):
119        assert plugins.active == "default"
120        assert plugins.options == {"p": 6}
121
122    assert plugins.active == "default"
123    assert plugins.options == {"p": 2}
124