diff options
| -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 | 
