]> git.proxmox.com Git - ceph.git/blame - ceph/src/pybind/mgr/dashboard/plugins/__init__.py
import ceph quincy 17.2.4
[ceph.git] / ceph / src / pybind / mgr / dashboard / plugins / __init__.py
CommitLineData
11fdf7f2 1# -*- coding: utf-8 -*-
11fdf7f2
TL
2
3import abc
11fdf7f2 4
f67539c2 5from .pluggy import HookimplMarker, HookspecMarker, PluginManager
11fdf7f2
TL
6
7
f67539c2 8class Interface(object, metaclass=abc.ABCMeta):
11fdf7f2
TL
9 pass
10
11
92f5a8d4
TL
12class Mixin(object):
13 pass
14
15
11fdf7f2
TL
16class DashboardPluginManager(object):
17 def __init__(self, project_name):
18 self.__pm = PluginManager(project_name)
19 self.__add_spec = HookspecMarker(project_name)
20 self.__add_abcspec = lambda *args, **kwargs: abc.abstractmethod(
21 self.__add_spec(*args, **kwargs))
22 self.__add_hook = HookimplMarker(project_name)
23
24 pm = property(lambda self: self.__pm)
25 hook = property(lambda self: self.pm.hook)
26
27 add_spec = property(lambda self: self.__add_spec)
28 add_abcspec = property(lambda self: self.__add_abcspec)
29 add_hook = property(lambda self: self.__add_hook)
30
31 def add_interface(self, cls):
32 assert issubclass(cls, Interface)
33 self.pm.add_hookspecs(cls)
34 return cls
35
92f5a8d4
TL
36 @staticmethod
37 def final(func):
38 setattr(func, '__final__', True)
39 return func
40
11fdf7f2
TL
41 def add_plugin(self, plugin):
42 """ Provides decorator interface for PluginManager.register():
43 @PLUGIN_MANAGER.add_plugin
44 class Plugin(...):
45 ...
46 Additionally it checks whether the Plugin instance has all Interface
47 methods implemented and marked with add_hook decorator.
48 As a con of this approach, plugins cannot call super() from __init__()
49 """
50 assert issubclass(plugin, Interface)
51 from inspect import getmembers, ismethod
52 for interface in plugin.__bases__:
53 for method_name, _ in getmembers(interface, predicate=ismethod):
92f5a8d4
TL
54 if hasattr(getattr(interface, method_name), '__final__'):
55 continue
56
11fdf7f2
TL
57 if self.pm.parse_hookimpl_opts(plugin, method_name) is None:
58 raise NotImplementedError(
59 "Plugin '{}' implements interface '{}' but existing"
60 " method '{}' is not declared added as hook".format(
61 plugin.__name__,
62 interface.__name__,
63 method_name))
64 self.pm.register(plugin())
65 return plugin
66
67
68PLUGIN_MANAGER = DashboardPluginManager("ceph-mgr.dashboard")
69
70# Load all interfaces and their hooks
f67539c2 71from . import interfaces # noqa pylint: disable=C0413,W0406