1import logging
2from pyscreenshot import plugins
3import traceback
4
5
6log = logging.getLogger(__name__)
7
8
9class FailedBackendError(Exception):
10    pass
11
12
13class Loader(object):
14
15    def __init__(self):
16        self.plugins = dict()
17
18        self.all_names = [x.name for x in self.plugin_classes()]
19
20        self.changed = True
21        self._force_backend = None
22        self.preference = []
23        self.default_preference = plugins.default_preference
24        self._backend = None
25
26    def plugin_classes(self):
27        return plugins.BACKENDS
28
29    def set_preference(self, x):
30        self.changed = True
31        self.preference = x
32
33    def force(self, name):
34        log.debug('forcing:' + str(name))
35        self.changed = True
36        self._force_backend = name
37
38    @property
39    def is_forced(self):
40        return self._force_backend is not None
41
42#     @property
43#     def loaded_plugins(self):
44#         return self.plugins.values()
45
46    def get_valid_plugin_by_name(self, name):
47        if name not in self.plugins:
48            ls = filter(lambda x: x.name == name, self.plugin_classes())
49            ls = list(ls)
50            if len(ls):
51                try:
52                    msg = ''
53                    plugin = ls[0]()
54                except Exception:
55                    msg = traceback.format_exc()
56                    log.debug(msg)
57                    plugin = None
58            else:
59                msg = 'unknown backend'
60                plugin = None
61            self.plugins[name] = (plugin, msg)
62        return self.plugins[name]
63
64    def get_valid_plugin_by_list(self, ls):
65        for name in ls:
66            x, _ = self.get_valid_plugin_by_name(name)
67            if x:
68                return x
69
70    def selected(self):
71        if self.changed:
72            if self.is_forced:
73                b, msg = self.get_valid_plugin_by_name(self._force_backend)
74                if not b:
75                    raise FailedBackendError(
76                        'Forced backend not found, or cannot be loaded:' + self._force_backend + '\n' + msg)
77            else:
78                biglist = self.preference + \
79                    self.default_preference + self.all_names
80                b = self.get_valid_plugin_by_list(biglist)
81                if not b:
82                    self.raise_exc()
83            self.changed = False
84            self._backend = b
85            log.debug('selecting plugin:' + self._backend.name)
86        return self._backend
87
88    def raise_exc(self):
89        message = 'Install at least one backend!'
90        raise FailedBackendError(message)
91