Package web :: Package pluginmanager :: Module pluginmanager
[hide private]
[frames] | no frames]

Source Code for Module web.pluginmanager.pluginmanager

  1  import config 
  2  import db 
  3  import os 
  4  from shutil import rmtree 
  5   
  6  from plugins.model import Plugin 
  7   
8 -class PluginManager:
9 - def __init__(self):
10 # Instance list 11 self.plugins = [] 12 orm = db.connect() 13 14 for plugin_name in self.__get_plugins_directories(): 15 instance = self.__instance_plugin(plugin_name) 16 self.plugins.append(instance) 17 18 enabled_plugins = [i.name for i in orm.query(Plugin).filter(Plugin.enabled==True).all()] 19 20 for plugin in self.plugins: 21 if plugin.name in enabled_plugins: 22 self.enable_plugin(plugin.name)
23
24 - def enable_plugin(self, name):
25 ''' 26 Enables a plugin if all the deps are met. Else it raises UnmetDependencyException. 27 Returns the list of enabled plugins. In this case, enable means this plugins will be enabled 28 in the future: this function will only be called when the user enables a plugin in the 29 pluginmanager.PluginListView. 30 ''' 31 enabled_plugins = [] 32 plugin = self.get_plugin_by_name(name) 33 if plugin == None: 34 return enabled_plugins 35 36 plugins_deps = self.__get_dependencies(plugin) 37 38 for plugin_dep in plugins_deps: 39 if not plugin_dep.is_enabled(): 40 self.__enable_plugin(plugin_dep) 41 enabled_plugins.append(plugin_dep) 42 43 return enabled_plugins
44
45 - def disable_plugin(self, name):
46 ''' 47 Disables a plugin and all plugins that have given plugin as a dependency. 48 Returns the list of disabled plugins. In this case, disable means this plugins will be disabled 49 in the future: this function will only be called when the user disables a plugin in the 50 pluginmanager.PluginListView. 51 ''' 52 disabled_plugins = [] 53 plugin = self.get_plugin_by_name(name) 54 if plugin == None: 55 return disabled_plugins 56 57 plugins_deps = self.__get_reverse_dependencies(plugin) 58 59 for plugin_dep in plugins_deps: 60 if plugin_dep.is_enabled(): 61 self.__disable_plugin(plugin_dep) 62 disabled_plugins.append(plugin_dep) 63 64 return disabled_plugins
65
66 - def uninstall_plugin(self, name, delete_files):
67 ''' 68 Uninstall the given plugin. There are two ways of uninstall: 69 * When delete_files is false, then this function only deletes 70 all plugin's data in the db. In this way you can reinstall the 71 plugin when you want. 72 * When delete_files is true, then this function delete all plugin's 73 data in the db and plugin's directory. In this way all data is 74 deleted, so you have to get the whole plugin to reinstall. 75 76 Either way, this function always removes the installed files in static/ 77 and templates/ for this plugin. 78 79 Before uninstalling a plugin, it MUST be disabled and obviously all 80 the plugins that have the plugin as a dependency. 81 ''' 82 plugin = self.get_plugin_by_name(name) 83 if plugin.enabled == True: 84 return False 85 86 plugin.uninstall() 87 88 # Remove from the plugins' table of data base 89 orm = db.connect() 90 query = orm.query(Plugin).filter(Plugin.name == name) 91 if query.count() == 1: 92 orm.delete(query.first()) 93 orm.commit() 94 95 static_dir = os.path.join(config.curdir, 'static/plugins', name) 96 if os.path.islink(static_dir): 97 os.unlink(static_dir) 98 templates_dir = os.path.join(config.curdir, 'templates/plugins', name) 99 if os.path.islink(templates_dir): 100 os.unlink(templates_dir) 101 102 # Deleting 103 if delete_files: 104 path = os.path.join(config.pluginsdir, name) 105 rmtree(path) 106 # Remove from the list of plugin 107 self.plugins.remove(plugin) 108 109 # removing plugin tables from database 110 pmodule = __import__('pluginmanager.plugins.%s.%s' % (plugin.name, 'model'), fromlist=["true"]) 111 db.drop_from_model(pmodule) 112 113 return True
114
115 - def check_for_new_plugins(self):
116 ''' 117 Look for new instances in plugins' directory and 118 add to self.plugins. 119 ''' 120 plugins_name = (p.name for p in self.plugins) 121 122 for plugin_name in self.__get_plugins_directories(): 123 if not plugin_name in plugins_name: 124 instance = self.__instance_plugin(plugin_name) 125 self.plugins.append(instance)
126
127 - def get_plugin_by_name(self, name):
128 ''' 129 Return the instance of the plugin whose name is given. 130 None is returned if the instance is not found. 131 ''' 132 for plugin in self.plugins: 133 if plugin.name == name: 134 return plugin 135 return None
136
137 - def get_enabled_plugins(self):
138 ''' 139 Return a instance list of the enabled plugins. 140 ''' 141 return (i for i in self.plugins if i.is_enabled())
142
143 - def __enable_plugin(self, plugin):
144 ''' 145 Enable a plugin without verify the dependencies. 146 ''' 147 orm = db.connect() 148 dbplugin = orm.query(Plugin).filter_by(name=plugin.name).first() 149 150 if not dbplugin: 151 # This means that the plugin is not installed, so we proceed to install it now 152 self.__install_plugin(plugin) 153 154 else: 155 dbplugin.enabled = True 156 orm.commit() 157 158 plugin.enable() 159 plugin.enabled = True
160 161
162 - def __install_plugin(self, plugin):
163 ''' 164 Called only by __enable_plugin when a plugin has not been installed before. 165 166 * Creates the tables in the database from the plugin model 167 * installs the static/ and templates/ plugin directories in 168 static/plugins/<pluginname> and templates/plugins/<pluginname>/ 169 * calls to the install() function of the given plugin 170 ''' 171 172 # * Create tables in the db from the plugin model 173 orm = db.connect() 174 dbplugin = Plugin(plugin) 175 dbplugin.enabled = True 176 orm.add(dbplugin) 177 orm.commit() 178 pmodule = __import__('pluginmanager.plugins.%s.%s' % (plugin.name, 'model'), fromlist=["true"]) 179 db.create_from_model(pmodule) 180 181 # * install static 182 plugin_static_dir = os.path.join(config.pluginsdir, plugin.name, 'static') 183 if os.path.isdir(plugin_static_dir): 184 # only will install it if the plugin has a static/ dir, obviously 185 plugins_static_dir = os.path.join(config.curdir, 'static/plugins') 186 if not os.path.isdir(plugins_static_dir): 187 # the static/plugins directory might not exist because we cannot create 188 # a directory in git 189 os.mkdir(plugins_static_dir) 190 191 # finally copy the files 192 new_static_dir = os.path.join(plugins_static_dir, plugin.name) 193 os.symlink(plugin_static_dir, new_static_dir) 194 195 # * install templates 196 plugin_templates_dir = os.path.join(config.pluginsdir, plugin.name, 'templates') 197 if os.path.isdir(plugin_templates_dir): 198 plugins_templates_dir = os.path.join(config.curdir, 'templates/plugins') 199 if not os.path.isdir(plugins_templates_dir): 200 os.mkdir(plugins_templates_dir) 201 new_templates_dir = os.path.join(plugins_templates_dir, plugin.name) 202 os.symlink(plugin_templates_dir, new_templates_dir) 203 204 plugin.install()
205
206 - def __disable_plugin(self, plugin):
207 ''' 208 Disable a plugin without verify the dependencies. 209 ''' 210 orm = db.connect() 211 orm.query(Plugin).filter_by(name=plugin.name).first().enabled = False 212 plugin.disable() 213 plugin.enabled = False 214 orm.commit()
215
216 - def __get_dependencies(self, plugin, checked_deps=None, 217 checked_plugins=None):
218 ''' 219 Recursively returns the list of the dependencies of the given plugins. 220 If any of the dependencies is not met then it will raise a 221 UnMetDependencyException. 222 223 The list of plugins dependencies will include the plugin itself which 224 will be at the end of the list, and the list of dependencies will be 225 ordered in such a way that they can be safely activated one by one, 226 because any of the listed plugins will be preceded by its dependencies. 227 228 It will only be called by enable_plugin(). 229 ''' 230 231 if checked_deps is None: checked_deps = [] 232 if checked_plugins is None: checked_plugins = [] 233 234 # With this avoid infinite recursion with two plugins have mutual 235 # dependency. 236 checked_plugins.append(plugin.name) 237 for dep in plugin.get_dependencies(): 238 if dep.dependon in (i.name for i in checked_deps): 239 continue 240 if dep.dependon in checked_plugins: 241 continue 242 if not dep.is_met(): 243 # raise UnmetDependencyException(dep.dependon) 244 # FIXME 245 pass 246 self.__get_dependencies(dep.get_plugin(), checked_deps, 247 checked_plugins) 248 249 checked_deps.append(plugin) 250 return checked_deps
251
252 - def __get_reverse_dependencies(self, plugin, checked_deps=None, 253 checked_plugins=None):
254 ''' 255 Recursively returns the list of the reverse dependencies of the given 256 plugins. 257 258 The list of plugins dependencies will include the plugin itself which 259 will be at the end of the list, and the list of dependencies will be 260 ordered in such a way that they can be safely desactivated one by one, 261 because any of the listed plugins will be preceded by its dependencies. 262 263 It will only be called by disable_plugin(). 264 ''' 265 266 if checked_deps is None: checked_deps = [] 267 if checked_plugins is None: checked_plugins = [] 268 # With this avoid infinite recursion with two plugins have mutual 269 # dependency. 270 checked_plugins.append(plugin.name) 271 # For each enabled plugin 272 for p in self.get_enabled_plugins(): 273 # not checked before 274 if p in checked_plugins: 275 continue 276 if p.name in checked_plugins: 277 continue 278 # looking for a dependency which is the given 279 for dep in p.get_dependencies(): 280 if dep.is_met_by(plugin): 281 self.__get_reverse_dependencies(self, p, checked_deps, 282 checked_plugins) 283 284 checked_deps.append(plugin) 285 return checked_deps
286
287 - def __instance_plugin(self, name):
288 #FIXME throw exception 289 pmodule = __import__('pluginmanager.plugins.' + name, fromlist=["true"]) 290 plugin = pmodule.Plugin() 291 plugin.read_config(name) 292 return plugin
293
295 ''' 296 Return the list of the directories of plugins that there are 297 in the plugins directory. 298 ''' 299 return (i for i in os.listdir(config.pluginsdir) 300 if os.path.isdir(os.path.join(config.pluginsdir, i)))
301