summaryrefslogtreecommitdiffstats
path: root/pyload/AddonManager.py
diff options
context:
space:
mode:
Diffstat (limited to 'pyload/AddonManager.py')
-rw-r--r--pyload/AddonManager.py224
1 files changed, 224 insertions, 0 deletions
diff --git a/pyload/AddonManager.py b/pyload/AddonManager.py
new file mode 100644
index 000000000..75ff4ebc9
--- /dev/null
+++ b/pyload/AddonManager.py
@@ -0,0 +1,224 @@
+# -*- coding: utf-8 -*-
+
+###############################################################################
+# Copyright(c) 2008-2013 pyLoad Team
+# http://www.pyload.org
+#
+# This file is part of pyLoad.
+# pyLoad is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# Subjected to the terms and conditions in LICENSE
+#
+# @author: RaNaN
+###############################################################################
+
+import __builtin__
+
+from thread import start_new_thread
+from threading import RLock
+
+from types import MethodType
+
+from pyload.threads.AddonThread import AddonThread
+from pyload.PluginManager import literal_eval
+from utils import lock, to_string
+
+class AddonManager:
+ """ Manages addons, loading, unloading. """
+
+ def __init__(self, core):
+ self.core = core
+ self.config = self.core.config
+
+ __builtin__.addonManager = self #needed to let addons register themselves
+
+ self.log = self.core.log
+ # TODO: multiuser, addons can store the user itself, probably not needed here
+ self.plugins = {}
+ self.methods = {} # dict of names and list of methods usable by rpc
+ self.events = {} # Contains event that will be registered
+
+ self.lock = RLock()
+ self.createIndex()
+
+ # manage addons on config change
+ self.listenTo("config:changed", self.manageAddon)
+
+ @lock
+ def callInHooks(self, event, eventName, *args):
+ """ Calls a method in all addons and catch / log errors"""
+ for plugin in self.plugins.itervalues():
+ self.call(plugin, event, *args)
+ self.dispatchEvent(eventName, *args)
+
+ def call(self, addon, f, *args):
+ try:
+ func = getattr(addon, f)
+ return func(*args)
+ except Exception, e:
+ addon.logError(_("Error when executing %s" % f), e)
+ self.core.print_exc()
+
+ @lock
+ def createIndex(self):
+ active = []
+ deactive = []
+
+ for pluginname in self.core.pluginManager.getPlugins("addons"):
+ try:
+ # check first for builtin plugin
+ attrs = self.core.pluginManager.loadAttributes("addons", pluginname)
+ internal = attrs.get("internal", False)
+
+ if internal or self.core.config.get(pluginname, "activated"):
+ pluginClass = self.core.pluginManager.loadClass("addons", pluginname)
+
+ if not pluginClass: continue
+
+ plugin = pluginClass(self.core, self)
+ self.plugins[pluginClass.__name__] = plugin
+
+ # hide internals from printing
+ if not internal and plugin.isActivated():
+ active.append(pluginClass.__name__)
+ else:
+ self.log.debug("Loaded internal plugin: %s" % pluginClass.__name__)
+ else:
+ deactive.append(pluginname)
+
+ except:
+ self.log.warning(_("Failed activating %(name)s") % {"name": pluginname})
+ self.core.print_exc()
+
+ self.log.info(_("Activated addons: %s") % ", ".join(sorted(active)))
+ self.log.info(_("Deactivated addons: %s") % ", ".join(sorted(deactive)))
+
+ def manageAddon(self, plugin, name, value):
+ # TODO: user
+
+ # check if section was a plugin
+ if plugin not in self.core.pluginManager.getPlugins("addons"):
+ return
+
+ if name == "activated" and value:
+ self.activateAddon(plugin)
+ elif name == "activated" and not value:
+ self.deactivateAddon(plugin)
+
+ @lock
+ def activateAddon(self, plugin):
+ #check if already loaded
+ if plugin in self.plugins:
+ return
+
+ pluginClass = self.core.pluginManager.loadClass("addons", plugin)
+
+ if not pluginClass: return
+
+ self.log.debug("Plugin loaded: %s" % plugin)
+
+ plugin = pluginClass(self.core, self)
+ self.plugins[pluginClass.__name__] = plugin
+
+ # active the addon in new thread
+ start_new_thread(plugin.activate, tuple())
+ self.registerEvents() # TODO: BUG: events will be destroyed and not re-registered
+
+ @lock
+ def deactivateAddon(self, plugin):
+ if plugin not in self.plugins:
+ return
+ else:
+ addon = self.plugins[plugin]
+
+ if addon.__internal__: return
+
+ self.call(addon, "deactivate")
+ self.log.debug("Plugin deactivated: %s" % plugin)
+
+ #remove periodic call
+ self.log.debug("Removed callback %s" % self.core.scheduler.removeJob(addon.cb))
+ del self.plugins[addon.__name__]
+
+ #remove event listener
+ for f in dir(addon):
+ if f.startswith("__") or type(getattr(addon, f)) != MethodType:
+ continue
+ self.core.eventManager.removeFromEvents(getattr(addon, f))
+
+ def activateAddons(self):
+ self.log.info(_("Activating Plugins..."))
+ for plugin in self.plugins.itervalues():
+ if plugin.isActivated():
+ self.call(plugin, "activate")
+
+ self.registerEvents()
+
+ def deactivateAddons(self):
+ """ Called when core is shutting down """
+ self.log.info(_("Deactivating Plugins..."))
+ for plugin in self.plugins.itervalues():
+ self.call(plugin, "deactivate")
+
+ def downloadPreparing(self, pyfile):
+ self.callInHooks("downloadPreparing", "download:preparing", pyfile)
+
+ def downloadFinished(self, pyfile):
+ self.callInHooks("downloadFinished", "download:finished", pyfile)
+
+ def downloadFailed(self, pyfile):
+ self.callInHooks("downloadFailed", "download:failed", pyfile)
+
+ def packageFinished(self, package):
+ self.callInHooks("packageFinished", "package:finished", package)
+
+ @lock
+ def startThread(self, function, *args, **kwargs):
+ AddonThread(self.core.threadManager, function, args, kwargs)
+
+ def activePlugins(self):
+ """ returns all active plugins """
+ return [x for x in self.plugins.itervalues() if x.isActivated()]
+
+ def getAllInfo(self):
+ """returns info stored by addon plugins"""
+ info = {}
+ for name, plugin in self.plugins.iteritems():
+ if plugin.info:
+ #copy and convert so str
+ info[name] = dict(
+ [(x, to_string(y)) for x, y in plugin.info.iteritems()])
+ return info
+
+ def getInfo(self, plugin):
+ info = {}
+ if plugin in self.plugins and self.plugins[plugin].info:
+ info = dict([(x, to_string(y))
+ for x, y in self.plugins[plugin].info.iteritems()])
+
+ return info
+
+ def addEventListener(self, plugin, func, event):
+ """ add the event to the list """
+ if plugin not in self.events:
+ self.events[plugin] = []
+ self.events[plugin].append((func, event))
+
+ def registerEvents(self):
+ """ actually register all saved events """
+ for name, plugin in self.plugins.iteritems():
+ if name in self.events:
+ for func, event in self.events[name]:
+ self.listenTo(event, getattr(plugin, func))
+ # clean up
+ del self.events[name]
+
+ def listenTo(self, *args):
+ self.core.eventManager.listenTo(*args)
+
+ def dispatchEvent(self, *args):
+ self.core.eventManager.dispatchEvent(*args)
+