1 # Copyright (C) 2013 Ipsilon project Contributors, for license see COPYING
8 from ipsilon.util.data import AdminStore, Store
9 from ipsilon.util.log import Log
12 class Plugins(object):
15 self._providers_tree = None
17 def _load_class(self, tree, class_type, file_name, *pargs):
18 cherrypy.log.error('Check module %s for class %s' % (file_name,
19 class_type), severity=logging.DEBUG)
20 name, ext = os.path.splitext(os.path.split(file_name)[-1])
22 if ext.lower() == '.py':
23 mod = imp.load_source(name, file_name)
24 # elif ext.lower() == '.pyc':
25 # mod = imp.load_compiled(name, file_name)
28 except Exception, e: # pylint: disable=broad-except
29 cherrypy.log.error('Failed to load "%s" module: [%s]' % (name, e),
30 severity=logging.ERROR)
33 if hasattr(mod, class_type):
34 instance = getattr(mod, class_type)(*pargs)
35 public_name = getattr(instance, 'name', name)
36 tree[public_name] = instance
37 cherrypy.log.error('Added module %s as %s' % (name, public_name),
38 severity=logging.DEBUG)
40 def _load_classes(self, tree, path, class_type, *pargs):
43 files = os.listdir(path)
44 except Exception, e: # pylint: disable=broad-except
45 cherrypy.log.error('No modules in %s: [%s]' % (path, e),
46 severity=logging.ERROR)
50 filename = os.path.join(path, name)
51 self._load_class(tree, class_type, filename, *pargs)
53 def get_plugins(self, path, class_type, *pargs):
55 self._load_classes(plugins, path, class_type, *pargs)
59 class PluginLoader(Log):
61 def __init__(self, baseobj, facility, plugin_type, uses_store=True):
62 self._pathname, _ = os.path.split(inspect.getfile(baseobj))
63 self.facility = facility
64 self._plugin_type = plugin_type
65 self.available = dict()
68 self.uses_store = uses_store
70 # Defer initialization or instantiating the store will fail at load
71 # time when used with Installer plugins as the cherrypy config context
72 # is created after all Installer plugins are loaded.
75 if not self.uses_store:
76 raise Exception('Tried to get plugin data while ' +
77 'uses_store=False (%s)' % self.facility)
79 self.__data = AdminStore()
83 def is_readonly(self):
84 return self._data.is_readonly
86 def get_plugins(self):
88 return p.get_plugins(self._pathname, self._plugin_type, self)
90 def refresh_enabled(self):
91 config = self._data.load_options(self.facility, name='global')
94 if 'enabled' in config:
95 self.enabled = config['enabled'].split(',')
97 def get_plugin_data(self):
98 self.available = self.get_plugins()
100 self.refresh_enabled()
102 def save_enabled(self, enabled):
104 self._data.save_options(self.facility, 'global',
105 {'enabled': ','.join(enabled)})
107 self._data.delete_options(self.facility, 'global',
109 self.debug('Plugin enabled state saved: %s' % enabled)
110 self.refresh_enabled()
113 class PluginInstaller(PluginLoader):
114 def __init__(self, baseobj, facility):
115 super(PluginInstaller, self).__init__(baseobj, facility, 'Installer')
118 class PluginObject(Log):
120 def __init__(self, plugins):
123 self._data = AdminStore()
124 self._plugins = plugins
125 self.is_enabled = False
128 def is_readonly(self):
129 return self._data.is_readonly
134 def on_disable(self):
137 def save_enabled_state(self):
139 self._plugins.refresh_enabled()
140 enabled.extend(self._plugins.enabled)
142 if self.name not in enabled:
143 enabled.append(self.name)
145 if self.name in enabled:
146 enabled.remove(self.name)
147 self._plugins.save_enabled(enabled)
153 self.refresh_plugin_config()
154 is_upgrade = Store._is_upgrade # pylint: disable=protected-access
156 Store._is_upgrade = True # pylint: disable=protected-access
158 self._data.create_plugin_data_table(self.name)
159 for store in self.used_datastores():
160 store.upgrade_database()
162 Store._is_upgrade = is_upgrade # pylint: disable=protected-access
163 self.is_enabled = True
164 self.debug('Plugin enabled: %s' % self.name)
167 if not self.is_enabled:
172 self.is_enabled = False
173 self.debug('Plugin disabled: %s' % self.name)
175 def used_datastores(self):
178 def import_config(self, config):
179 self._config = config
181 def export_config(self):
184 def get_plugin_config(self):
185 return self._data.load_options(self._plugins.facility, self.name)
187 def refresh_plugin_config(self):
188 config = self.get_plugin_config()
191 self.import_config(config)
192 except Exception, e: # pylint: disable=broad-except
193 self.error('Failed to refresh config for %s (%s)' %
196 def save_plugin_config(self, config=None):
198 config = self.export_config()
200 self._data.save_options(self._plugins.facility, self.name, config)
202 def get_data(self, idval=None, name=None, value=None):
203 return self._data.get_data(self.name, idval=idval, name=name,
206 def save_data(self, data):
207 self._data.save_data(self.name, data)
209 def new_datum(self, datum):
210 self._data.new_datum(self.name, datum)
212 def del_datum(self, idval):
213 self._data.del_datum(self.name, idval)
215 def wipe_config_values(self):
216 self._data.delete_options(self._plugins.facility, self.name, None)
219 self._data.wipe_data(self.name)