diff options
author | RaNaN <Mast3rRaNaN@hotmail.de> | 2011-07-18 22:19:20 +0200 |
---|---|---|
committer | RaNaN <Mast3rRaNaN@hotmail.de> | 2011-07-18 22:19:20 +0200 |
commit | b0dd0234804d15e6793476dcd8da961b6709551e (patch) | |
tree | 3b2a65e70a30e4bbb8ccd1b2177e328ed14a332c | |
parent | fixed captcha on webif + configparser (diff) | |
download | pyload-b0dd0234804d15e6793476dcd8da961b6709551e.tar.xz |
improved hook loader
-rw-r--r-- | module/Api.py | 2 | ||||
-rw-r--r-- | module/ConfigParser.py | 16 | ||||
-rw-r--r-- | module/HookManager.py | 86 | ||||
-rw-r--r-- | module/plugins/PluginManager.py | 58 |
4 files changed, 99 insertions, 63 deletions
diff --git a/module/Api.py b/module/Api.py index 7d4c6c66c..648174a1f 100644 --- a/module/Api.py +++ b/module/Api.py @@ -203,7 +203,7 @@ class Api(Iface): return ['No log available'] def isTimeDownload(self): - """Checks if pyload will start new downloads according to time in config . + """Checks if pyload will start new downloads according to time in config. :return: bool """ diff --git a/module/ConfigParser.py b/module/ConfigParser.py index ddb15ecd5..e0d6af7ee 100644 --- a/module/ConfigParser.py +++ b/module/ConfigParser.py @@ -42,6 +42,8 @@ class ConfigParser: self.plugin = {} # the config for plugins self.oldRemoteData = {} + self.pluginCB = None # callback when plugin config value is changed + self.checkVersion() self.readConfig() @@ -283,7 +285,6 @@ class ConfigParser: except: return val - #---------------------------------------------------------------------- def set(self, section, option, value): """set value""" @@ -292,7 +293,6 @@ class ConfigParser: self.config[section][option]["value"] = value self.save() - #---------------------------------------------------------------------- def getPlugin(self, plugin, option): """gets a value for a plugin""" val = self.plugin[plugin][option]["value"] @@ -304,12 +304,13 @@ class ConfigParser: except: return val - #---------------------------------------------------------------------- def setPlugin(self, plugin, option, value): """sets a value for a plugin""" value = self.cast(self.plugin[plugin][option]["type"], value) + if self.pluginCB: self.pluginCB(plugin, option, value) + self.plugin[plugin][option]["value"] = value self.save() @@ -338,6 +339,12 @@ class ConfigParser: "value": self.cast(item[1], item[3]) } + values = [x[0] for x in config] + ["desc", "outline"] + #delete old values + for item in conf.keys(): + if item not in values: + del conf[item] + def deleteOldPlugins(self): """ remove old plugins from config """ @@ -349,18 +356,15 @@ class ConfigParser: class Section: """provides dictionary like access for configparser""" - #---------------------------------------------------------------------- def __init__(self, parser, section): """Constructor""" self.parser = parser self.section = section - #---------------------------------------------------------------------- def __getitem__(self, item): """getitem""" return self.parser.get(self.section, item) - #---------------------------------------------------------------------- def __setitem__(self, item, value): """setitem""" self.parser.set(self.section, item, value) diff --git a/module/HookManager.py b/module/HookManager.py index 47e7d88fb..c67acd34a 100644 --- a/module/HookManager.py +++ b/module/HookManager.py @@ -20,9 +20,12 @@ import __builtin__ import traceback +from thread import start_new_thread from threading import RLock from time import time +from types import MethodType + from module.PluginThread import HookThread from module.plugins.PluginManager import literal_eval from utils import lock @@ -41,7 +44,7 @@ class HookManager: downloadPreparing: A download was just queued and will be prepared now. Argument: fid - downloadStarts: A file will immediately starts the download afterwards. + downloadStarts: A plugin will immediately starts the download afterwards. Argument: fid linksAdded: Someone just added links, you are able to modify the links. @@ -53,6 +56,13 @@ class HookManager: Note: allDownloadsProcessed is *always* called before allDownloadsFinished. + configChanged: The config was changed via the api. + + pluginConfigChanged: The plugin config changed, due to api or internal process. + + Note: pluginConfigChanged is always called after configChanged, if it affects plugins. + + """ def __init__(self, core): @@ -68,6 +78,11 @@ class HookManager: self.events = {} # contains events + #registering callback for config event + self.config.pluginCB = MethodType(self.dispatchEvent, "pluginConfigChanged", basestring) + + self.addEvent("pluginConfigChanged", self.activateHooks) + self.lock = RLock() self.createIndex() @@ -107,52 +122,77 @@ class HookManager: active = [] deactive = [] - unloaded = [] - for pluginClass in self.core.pluginManager.getHookPlugins(): + for pluginname in self.core.pluginManager.hookPlugins: try: #hookClass = getattr(plugin, plugin.__name__) - if self.core.config.getPlugin(pluginClass.__name__, "load"): + if self.core.config.getPlugin(pluginname, "activated"): + pluginClass = self.core.pluginManager.getHookPlugin(pluginname) + if not pluginClass: continue + plugin = pluginClass(self.core, self) plugins.append(plugin) self.pluginMap[pluginClass.__name__] = plugin if plugin.isActivated(): active.append(pluginClass.__name__) - else: - deactive.append(pluginClass.__name__) - - #self.log.info(_("%(name)s loaded, activated %(value)s") % {"name": pluginClass.__name__, "value": plugin.isActivated() }) else: - #never reached, see plugin manager - unloaded.append(pluginClass.__name__) + deactive.append(pluginname) + + except: - self.log.warning(_("Failed activating %(name)s") % {"name": pluginClass.__name__}) + self.log.warning(_("Failed activating %(name)s") % {"name": pluginname}) if self.core.debug: traceback.print_exc() self.log.info(_("Activated plugins: %s") % ", ".join(sorted(active))) self.log.info(_("Deactivate plugins: %s") % ", ".join(sorted(deactive))) - #self.log.info(_("Not loaded plugins: %s") % ", ".join(unloaded)) self.plugins = plugins + def activateHooks(self, plugin, name, value): - def initPeriodical(self): - def wrapPeriodical(plugin): - plugin.lastCall = time() - try: - if plugin.isActivated(): plugin.periodical() - except Exception, e: - self.core.log.error(_("Error executing hooks: %s") % str(e)) - if self.core.debug: - traceback.print_exc() + if name != "activated" or not value: + return + + #check if already loaded + for inst in self.plugins: + if inst.__name__ == plugin: + return + + + pluginClass = self.core.pluginManager.getHookPlugin(plugin) + + if not pluginClass: return + + self.log.debug("Plugin loaded: %s" % plugin) - self.core.scheduler.addJob(plugin.interval, wrapPeriodical, args=[plugin], threaded=False) + plugin = pluginClass(self.core, self) + self.plugins.append(plugin) + self.pluginMap[pluginClass.__name__] = plugin + # call core Ready + start_new_thread(plugin.coreReady, tuple()) + + # init periodical call + self.core.scheduler.addJob(0, self.wrapPeriodical, args=[plugin], threaded=False) + + + def wrapPeriodical(self, plugin): + plugin.lastCall = time() + try: + if plugin.isActivated(): plugin.periodical() + except Exception, e: + self.core.log.error(_("Error executing hooks: %s") % str(e)) + if self.core.debug: + traceback.print_exc() + + self.core.scheduler.addJob(plugin.interval, self.wrapPeriodical, args=[plugin], threaded=False) + + def initPeriodical(self): for plugin in self.plugins: if plugin.isActivated() and plugin.interval >= 1: - self.core.scheduler.addJob(0, wrapPeriodical, args=[plugin], threaded=False) + self.core.scheduler.addJob(0, self.wrapPeriodical, args=[plugin], threaded=False) @try_catch diff --git a/module/plugins/PluginManager.py b/module/plugins/PluginManager.py index 56b18b749..62460c644 100644 --- a/module/plugins/PluginManager.py +++ b/module/plugins/PluginManager.py @@ -33,8 +33,6 @@ except ImportError: # python 2.5 from module.ConfigParser import IGNORE -NO_AUTOLOAD = ("XMPPInterface", "MultiHome", "Ev0InFetcher") - class PluginManager(): def __init__(self, core): self.core = core @@ -179,8 +177,15 @@ class PluginManager(): else: config = [list(config)] + + if folder == "hooks": - config.append(["load", "bool", "Load on startup", True if name not in NO_AUTOLOAD else False]) + append = True + for item in config: + if item[0] == "activated": append = False + + # activated flag missing + if append: config.append(["activated", "bool", "Activated", False]) try: self.core.config.addPluginConfig(name, config, desc) @@ -303,43 +308,30 @@ class PluginManager(): return res - def getHookPlugins(self): - """return list of hook classes""" + def getHookPlugin(self, name): - classes = [] + if name not in self.hookPlugins: return None - for name, value in self.hookPlugins.iteritems(): - if "class" in value: - classes.append(value["class"]) - continue + value = self.hookPlugins[name] - try: - if not self.core.config.getPlugin(name, "load"): - continue - except: - if self.core.debug: - print_exc() - - self.log.debug("Failed to load %s" % name) - continue - - try: - module = __import__(value["path"], globals(), locals(), [value["name"]], -1) - pluginClass = getattr(module, name) - except Exception, e: - self.log.error(_("Error importing %(name)s: %(msg)s") % {"name": name, "msg": str(e)}) - self.log.error(_("You should fix dependicies or deactivate load on startup.")) - if self.core.debug: - print_exc() + if "class" in value: + return value["class"] - continue + try: + module = __import__(value["path"], globals(), locals(), [value["name"]], -1) + pluginClass = getattr(module, name) + except Exception, e: + self.log.error(_("Error importing %(name)s: %(msg)s") % {"name": name, "msg": str(e)}) + self.log.error(_("You should fix dependicies or deactivate it.")) + if self.core.debug: + print_exc() + return None - value["class"] = pluginClass + value["class"] = pluginClass - classes.append(pluginClass) - - return classes + return pluginClass + def reloadPlugins(self): """ reloads and reindexes plugins """ pass |