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