diff options
author | RaNaN <Mast3rRaNaN@hotmail.de> | 2012-01-06 17:54:53 +0100 |
---|---|---|
committer | RaNaN <Mast3rRaNaN@hotmail.de> | 2012-01-06 17:54:53 +0100 |
commit | b877847094b0ba03a098dff0fd769eb456b48dd1 (patch) | |
tree | 2d4a4e6b5c4dcba8eec952724a0dd065ef781ced /module/HookManager.py | |
parent | xmpp: disconnect on unload / deactivate (diff) | |
download | pyload-b877847094b0ba03a098dff0fd769eb456b48dd1.tar.xz |
Diffstat (limited to 'module/HookManager.py')
-rw-r--r-- | module/HookManager.py | 191 |
1 files changed, 62 insertions, 129 deletions
diff --git a/module/HookManager.py b/module/HookManager.py index 7057b6ee6..41908bc47 100644 --- a/module/HookManager.py +++ b/module/HookManager.py @@ -18,7 +18,7 @@ """ import __builtin__ -import traceback +from traceback import print_exc from thread import start_new_thread from threading import RLock @@ -38,11 +38,9 @@ class HookManager: __builtin__.hookManager = self #needed to let hooks register themself self.log = self.core.log - self.plugins = [] - self.pluginMap = {} - self.methods = {} #dict of names and list of methods usable by rpc - - self.events = {} # contains events + self.plugins = {} + self.methods = {} # dict of names and list of methods usable by rpc + self.events = {} # Contains event that will be registred self.lock = RLock() self.createIndex() @@ -53,17 +51,19 @@ class HookManager: # manage hooks an config change self.addEvent("configChanged", self.manageHooks) - def try_catch(func): - def new(*args): + @lock + def callInHooks(self, event, *args): + """ Calls a method in hook and catch / log errors""" + for plugin in self.plugins.itervalues(): try: + func = getattr(plugin, event) return func(*args) except Exception, e: - args[0].log.error(_("Error executing hooks: %s") % str(e)) - if args[0].core.debug: - traceback.print_exc() - - return new + plugin.logError(_("Error executing %s" % event), e) + if self.core.debug: + print_exc() + self.dispatchEvent(event, *args) def addRPC(self, plugin, func, doc): plugin = plugin.rpartition(".")[2] @@ -79,14 +79,12 @@ class HookManager: else: args = literal_eval(args) - plugin = self.pluginMap[plugin] + plugin = self.plugins[plugin] f = getattr(plugin, func) return f(*args) - + @lock def createIndex(self): - plugins = [] - active = [] deactive = [] @@ -97,10 +95,9 @@ class HookManager: if self.core.config.get(pluginname, "activated"): pluginClass = self.core.pluginManager.loadClass("hooks", pluginname) if not pluginClass: continue - + plugin = pluginClass(self.core, self) - plugins.append(plugin) - self.pluginMap[pluginClass.__name__] = plugin + self.plugins[pluginClass.__name__] = plugin if plugin.isActivated(): active.append(pluginClass.__name__) else: @@ -110,15 +107,12 @@ class HookManager: except: self.log.warning(_("Failed activating %(name)s") % {"name": pluginname}) if self.core.debug: - traceback.print_exc() + print_exc() self.log.info(_("Activated plugins: %s") % ", ".join(sorted(active))) self.log.info(_("Deactivate plugins: %s") % ", ".join(sorted(deactive))) - self.plugins = plugins - def manageHooks(self, plugin, name, value): - # check if section was a plugin if plugin not in self.core.pluginManager.getPlugins("hooks"): return @@ -128,12 +122,11 @@ class HookManager: elif name == "activated" and not value: self.deactivateHook(plugin) + @lock def activateHook(self, plugin): - #check if already loaded - for inst in self.plugins: - if inst.__name__ == plugin: - return + if plugin in self.plugins: + return pluginClass = self.core.pluginManager.loadClass("hooks", plugin) @@ -142,105 +135,63 @@ class HookManager: self.log.debug("Plugin loaded: %s" % plugin) plugin = pluginClass(self.core, self) - self.plugins.append(plugin) - self.pluginMap[pluginClass.__name__] = plugin + self.plugins[pluginClass.__name__] = plugin - # call core Ready - start_new_thread(plugin.coreReady, tuple()) + # active the hook in new thread + start_new_thread(plugin.activate, tuple()) + @lock def deactivateHook(self, plugin): + if plugin not in self.plugins: + return + else: + hook = self.plugins[plugin] - hook = None - for inst in self.plugins: - if inst.__name__ == plugin: - hook = inst - - if not hook: return - - hook.unload() - self.log.debug("Plugin unloaded: %s" % plugin) + hook.deactivate() + self.log.debug("Plugin deactivated: %s" % plugin) #remove periodic call self.log.debug("Removed callback %s" % self.core.scheduler.removeJob(hook.cb)) - self.plugins.remove(hook) - del self.pluginMap[hook.__name__] + del self.plugins[hook.__name__] + #remove event listener + for f in dir(hook): + if f.startswith("__") or type(getattr(hook, f)) != MethodType: + continue + self.core.eventManager.removeFromEvents(getattr(hook, f)) - @try_catch - def coreReady(self): - for plugin in self.plugins: + def activateHooks(self): + for plugin in self.plugins.itervalues(): if plugin.isActivated(): - plugin.coreReady() - - self.dispatchEvent("coreReady") + plugin.activate() - @try_catch - def coreExiting(self): - for plugin in self.plugins: + def deactivateHooks(self): + """ Called when core is shutting down """ + for plugin in self.plugins.itervalues(): if plugin.isActivated(): - plugin.coreExiting() - - self.dispatchEvent("coreExiting") + plugin.deactivate() - @lock def downloadPreparing(self, pyfile): - for plugin in self.plugins: - if plugin.isActivated(): - plugin.downloadPreparing(pyfile) + self.callInHooks("downloadPreparing", pyfile) - self.dispatchEvent("downloadPreparing", pyfile) - - @lock def downloadFinished(self, pyfile): - for plugin in self.plugins: - if plugin.isActivated(): - if "downloadFinished" in plugin.__threaded__: - self.startThread(plugin.downloadFinished, pyfile) - else: - plugin.downloadFinished(pyfile) - - self.dispatchEvent("downloadFinished", pyfile) + self.callInHooks("downloadFinished", pyfile) - @lock - @try_catch def downloadFailed(self, pyfile): - for plugin in self.plugins: - if plugin.isActivated(): - if "downloadFailed" in plugin.__threaded__: - self.startThread(plugin.downloadFinished, pyfile) - else: - plugin.downloadFailed(pyfile) - - self.dispatchEvent("downloadFailed", pyfile) + self.callInHooks("downloadFailed", pyfile) - @lock def packageFinished(self, package): - for plugin in self.plugins: - if plugin.isActivated(): - if "packageFinished" in plugin.__threaded__: - self.startThread(plugin.packageFinished, package) - else: - plugin.packageFinished(package) - - self.dispatchEvent("packageFinished", package) + self.callInHooks("packageFinished", package) - @lock def beforeReconnecting(self, ip): - for plugin in self.plugins: - plugin.beforeReconnecting(ip) + self.callInHooks("beforeReconnecting", ip) - self.dispatchEvent("beforeReconnecting", ip) - - @lock def afterReconnecting(self, ip): - for plugin in self.plugins: - if plugin.isActivated(): - plugin.afterReconnecting(ip) - - self.dispatchEvent("afterReconnecting", ip) + self.callInHooks("afterReconnecting", ip) + @lock def startThread(self, function, *args, **kwargs): - t = HookThread(self.core.threadManager, function, args, kwargs) + HookThread(self.core.threadManager, function, args, kwargs) def activePlugins(self): """ returns all active plugins """ @@ -249,42 +200,24 @@ class HookManager: def getAllInfo(self): """returns info stored by hook plugins""" info = {} - for name, plugin in self.pluginMap.iteritems(): + for name, plugin in self.plugins.iteritems(): if plugin.info: #copy and convert so str - info[name] = dict([(x, str(y) if not isinstance(y, basestring) else y) for x, y in plugin.info.iteritems()]) + info[name] = dict( + [(x, str(y) if not isinstance(y, basestring) else y) for x, y in plugin.info.iteritems()]) return info - def getInfo(self, plugin): info = {} - if plugin in self.pluginMap and self.pluginMap[plugin].info: + if plugin in self.plugins and self.plugins[plugin].info: info = dict([(x, str(y) if not isinstance(y, basestring) else y) - for x, y in self.pluginMap[plugin].info.iteritems()]) + for x, y in self.plugins[plugin].info.iteritems()]) return info - def addEvent(self, event, func): - """Adds an event listener for event name""" - if event in self.events: - self.events[event].append(func) - else: - self.events[event] = [func] - - def removeEvent(self, event, func): - """removes previously added event listener""" - if event in self.events: - self.events[event].remove(func) - - def dispatchEvent(self, event, *args): - """dispatches event with args""" - if event in self.events: - for f in self.events[event]: - try: - f(*args) - except Exception, e: - self.log.warning("Error calling event handler %s: %s, %s, %s" - % (event, f, args, str(e))) - if self.core.debug: - traceback.print_exc() + def addEvent(self, *args): + self.core.eventManager.addEvent(*args) + + def dispatchEvent(self, *args): + self.core.eventManager.dispatchEvent(*args) |