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