summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--module/Api.py2
-rw-r--r--module/ConfigParser.py16
-rw-r--r--module/HookManager.py86
-rw-r--r--module/plugins/PluginManager.py58
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