summaryrefslogtreecommitdiffstats
path: root/module/HookManager.py
diff options
context:
space:
mode:
authorGravatar RaNaN <Mast3rRaNaN@hotmail.de> 2012-01-06 17:54:53 +0100
committerGravatar RaNaN <Mast3rRaNaN@hotmail.de> 2012-01-06 17:54:53 +0100
commitb877847094b0ba03a098dff0fd769eb456b48dd1 (patch)
tree2d4a4e6b5c4dcba8eec952724a0dd065ef781ced /module/HookManager.py
parentxmpp: disconnect on unload / deactivate (diff)
downloadpyload-b877847094b0ba03a098dff0fd769eb456b48dd1.tar.xz
several improvements, also closes #486, #487
Diffstat (limited to 'module/HookManager.py')
-rw-r--r--module/HookManager.py191
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)