Completed
Push — master ( 8473d5...821f0f )
by Felipe A.
01:23
created

browsepy.PluginManagerBase.load_plugin()   B

Complexity

Conditions 7

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 7
dl 0
loc 18
rs 7.3333
1
#!/usr/bin/env python
2
# -*- coding: UTF-8 -*-
3
4
import sys
5
import collections
6
7
from . import mimetype
8
from . import widget
9
from .compat import isnonstriterable
10
11
12
class PluginNotFoundError(ImportError):
13
    pass
14
15
16
class PluginManagerBase(object):
17
18
    @property
19
    def namespaces(self):
20
        return self.app.config['plugin_namespaces']
21
22
    def __init__(self, app=None):
23
        if not app is None:
24
            self.init_app(app)
25
26
    def init_app(self, app):
27
        self.app = app
28
        if not hasattr(app, 'extensions'):
29
            app.extensions = {}
30
        app.extensions['plugin_manager'] = self
31
        self.reload()
32
33
    def reload(self):
34
        for plugin in self.app.config.get('plugin_modules', ()):
35
            self.load_plugin(plugin)
36
37
    def load_plugin(self, plugin):
38
        names = [
39
            '%s.%s' % (namespace, plugin) if namespace else plugin
40
            for namespace in self.namespaces
41
            ]
42
43
        for name in names:
44
            if name in sys.modules:
45
                return sys.modules[name]
46
47
        for name in names:
48
            try:
49
                __import__(name)
50
                return sys.modules[name]
51
            except (ImportError, IndexError):
52
                pass
53
54
        raise PluginNotFoundError('No plugin module %r found, tried %r' % (plugin, names), plugin, names)
55
56
57
class BlueprintPluginManager(PluginManagerBase):
58
    def register_blueprint(self, blueprint):
59
        self.app.register_blueprint(blueprint)
60
61
    def load_plugin(self, plugin):
62
        module = super(BlueprintPluginManager, self).load_plugin(plugin)
63
        if hasattr(module, 'register_plugin'):
64
            module.register_plugin(self)
65
        return module
66
67
68
class MimetypeActionPluginManager(PluginManagerBase):
69
    action_class = collections.namedtuple('MimetypeAction', ('endpoint', 'widget'))
70
    button_class = widget.ButtonWidget
71
    style_class = widget.StyleWidget
72
    javascript_class = widget.JavascriptWidget
73
    link_class = widget.LinkWidget
74
75
    _default_mimetype_functions = [
76
        mimetype.by_python,
77
        mimetype.by_file,
78
        mimetype.by_default,
79
    ]
80
81
    def __init__(self, app=None):
82
        self._root = {}
83
        self._widgets = {}
84
        self._mimetype_functions = list(self._default_mimetype_functions)
85
        super(MimetypeActionPluginManager, self).__init__(app=app)
86
87
    def get_mimetype(self, path):
88
        for fnc in self._mimetype_functions:
89
            mime = fnc(path)
90
            if mime:
91
                return mime
92
        return mimetype.by_default(path)
93
94
    def get_widgets(self, place):
95
        return self._widgets.get(place, [])
96
97
    def get_actions(self, file):
98
        category, variant = file.mimetype.split('/')
99
        return [
100
            self.action_class(endpoint, widget.for_file(file))
101
            for tree_category in (category, '*')
102
            for tree_variant in (variant, '*')
103
            for endpoint, widget in self._root.get(tree_category, {}).get(tree_variant, ())
104
            ]
105
106
    def register_mimetype_function(self, fnc):
107
        self._mimetype_functions.insert(0, fnc)
108
109
    def register_widget(self, widget):
110
        self._widgets.setdefault(widget.place, []).append(widget)
111
112
    def register_action(self, endpoint, widget, mimetypes=(), **kwargs):
113
        mimetypes = mimetypes if isnonstriterable(mimetypes) else (mimetypes,)
114
        action = (endpoint, widget)
115
        for mimetype in mimetypes:
116
            category, variant = mimetype.split('/')
117
            self._root.setdefault(category, {}).setdefault(variant, []).append(action)
118
119
120
class PluginManager(BlueprintPluginManager, MimetypeActionPluginManager):
121
    pass
122