summaryrefslogtreecommitdiffstats
path: root/module/PluginManager.py
diff options
context:
space:
mode:
authorGravatar RaNaN <Mast3rRaNaN@hotmail.de> 2010-08-25 18:22:27 +0200
committerGravatar RaNaN <Mast3rRaNaN@hotmail.de> 2010-08-25 18:22:27 +0200
commit29f9dc8fb3396b03d732ebcbeb1cc8f00fe13897 (patch)
treef2a910cbea747a7b0c0a50d6c66691e54f5ef47f /module/PluginManager.py
parentmerged gui (diff)
downloadpyload-29f9dc8fb3396b03d732ebcbeb1cc8f00fe13897.tar.xz
new dirs
Diffstat (limited to 'module/PluginManager.py')
-rw-r--r--module/PluginManager.py314
1 files changed, 314 insertions, 0 deletions
diff --git a/module/PluginManager.py b/module/PluginManager.py
new file mode 100644
index 000000000..8f00b9f25
--- /dev/null
+++ b/module/PluginManager.py
@@ -0,0 +1,314 @@
+# -*- coding: utf-8 -*-
+
+"""
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License,
+ or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+ @author: mkaay, RaNaN
+"""
+
+import re
+import sys
+
+from os import listdir
+from os import makedirs
+
+from os.path import isfile
+from os.path import join
+from os.path import exists
+from os.path import abspath
+
+from sys import version_info
+from itertools import chain
+
+
+class PluginManager():
+ def __init__(self, core):
+ self.core = core
+
+ #self.config = self.core.config
+ self.log = core.log
+
+ self.crypterPlugins = {}
+ self.containerPlugins = {}
+ self.hosterPlugins = {}
+ self.captchaPlugins = {}
+ self.accountPlugins = {}
+ self.hookPlugins = {}
+
+ self.createHomeDirs()
+
+ self.createIndex()
+
+ #@TODO plugin updater
+ #----------------------------------------------------------------------
+ def createHomeDirs(self):
+ """create homedirectories containing plugins"""
+ #@TODO implement...
+ pass
+
+ def createIndex(self):
+ """create information for all plugins available"""
+
+ sys.path.append(abspath(""))
+
+ if not exists("userplugins"):
+ makedirs("userplugins")
+ if not exists(join("userplugins", "__init__.py")):
+ f = open(join("userplugins", "__init__.py"), "wb")
+ f.close()
+
+ self.rePattern = re.compile(r'__pattern__.*=.*r("|\')([^"\']+)')
+ self.reVersion = re.compile(r'__version__.*=.*("|\')([0-9.]+)')
+ self.reConfig = re.compile(r'__config__.*=.*\[([^\]]+)', re.MULTILINE)
+
+ self.crypterPlugins = self.parse(_("Crypter"), "crypter", pattern=True)
+ self.containerPlugins = self.parse(_("Container"), "container", pattern=True)
+ self.hosterPlugins = self.parse(_("Hoster") ,"hoster", pattern=True)
+
+ self.captchaPlugins = self.parse(_("Captcha"), "captcha")
+ self.accountPlugins = self.parse(_("Account"), "accounts", create=True)
+ self.hookPlugins = self.parse(_("Hook"), "hooks")
+
+ self.log.info(_("created index of plugins"))
+
+ def parse(self, typ, folder, create=False, pattern=False, home={}):
+ """
+ returns dict with information
+ home contains parsed plugins from module.
+
+ {
+ name : {path, version, config, (pattern, re), (plugin, class)}
+ }
+
+ """
+ plugins = {}
+ if home:
+ pfolder = join("userplugins", folder)
+ if not exists(pfolder):
+ makedirs(pfolder)
+ if not exists(join(pfolder, "__init__.py")):
+ f = open(join(pfolder, "__init__.py"), "wb")
+ f.close()
+
+ else:
+ pfolder = join(pypath, "module", "plugins", folder)
+
+ for f in listdir(pfolder):
+ if (isfile(join(pfolder, f)) and f.endswith(".py") or f.endswith("_25.pyc") or f.endswith("_26.pyc") or f.endswith("_27.pyc")) and not f.startswith("_"):
+ data = open(join(pfolder, f))
+ content = data.read()
+ data.close()
+
+ if f.endswith("_25.pyc") and not version_info[0:2] == (2, 5):
+ continue
+ elif f.endswith("_26.pyc") and not version_info[0:2] == (2, 6):
+ continue
+ elif f.endswith("_27.pyc") and not version_info[0:2] == (2, 7):
+ continue
+
+ name = f[:-3]
+ if name[-1] == "." : name = name[:-4]
+
+
+ version = self.reVersion.findall(content)
+ if version:
+ version = float(version[0][1])
+ else:
+ version = 0
+
+ if home and home.has_key(name):
+ if home[name]["v"] > version:
+ continue
+
+
+ plugins[name] = {}
+ plugins[name]["v"] = version
+
+
+ module = f.replace(".pyc","").replace(".py","")
+ if home:
+ path = "userplugins.%s.%s" % (folder, module)
+ else:
+ path = "module.plugins.%s.%s" % (folder, module)
+
+ plugins[name]["name"] = module
+ plugins[name]["path"] = path
+
+
+ if pattern:
+ pattern = self.rePattern.findall(content)
+
+ if pattern:
+ pattern = pattern[0][1]
+ else:
+ pattern = "^unmachtable$"
+
+ plugins[name]["pattern"] = pattern
+
+ try:
+ plugins[name]["re"] = re.compile(pattern)
+ except:
+ self.log.error(_("%s has invalid pattern.") % name)
+
+
+ config = self.reConfig.findall(content)
+
+ if config:
+ config = [ [y.strip() for y in x.replace("'","").replace('"',"").replace(")","").split(",")] for x in config[0].split("(") if x.strip()]
+
+ if folder == "hooks":
+ config.append( ["load", "bool", "Load on startup", True if name not in ("XMPPInterface", "MultiHome") else False] )
+
+ for item in config:
+ self.core.config.addPluginConfig([name]+item)
+
+ if not home:
+ temp = self.parse(typ, folder, create, pattern, plugins)
+ plugins.update(temp)
+
+ return plugins
+
+ #----------------------------------------------------------------------
+ def parseUrls(self, urls):
+ """parse plugins for given list of urls"""
+
+ last = None
+ res = [] # tupels of (url, plugin)
+
+ for url in urls:
+
+ found = False
+
+ if last and last[1]["re"].match(url):
+ res.append((url, last[0]))
+ continue
+
+ for name, value in chain(self.crypterPlugins.iteritems(), self.hosterPlugins.iteritems(), self.containerPlugins.iteritems() ):
+ if value["re"].match(url):
+ res.append((url, name))
+ last = (name, value)
+ found = True
+ break
+
+ if not found:
+ res.append((url, "BasePlugin"))
+
+ return res
+
+ #----------------------------------------------------------------------
+ def getPlugin(self, name):
+ """return plugin module from hoster|decrypter|container"""
+ plugin = None
+
+ if self.containerPlugins.has_key(name):
+ plugin = self.containerPlugins[name]
+ if self.crypterPlugins.has_key(name):
+ plugin = self.crypterPlugins[name]
+ if self.hosterPlugins.has_key(name):
+ plugin = self.hosterPlugins[name]
+
+
+ if plugin.has_key("module"):
+ return plugin["module"]
+
+ plugin["module"] = __import__(plugin["path"], globals(), locals(), [plugin["name"]] , -1)
+
+ return plugin["module"]
+
+
+ #----------------------------------------------------------------------
+ def getCaptchaPlugin(self, name):
+ """return captcha modul if existent"""
+ if self.captchaPlugins.has_key(name):
+ plugin = self.captchaPlugins[name]
+ if plugin.has_key("class"):
+ return plugin["class"]
+
+ module = __import__(plugin["path"], globals(), locals(), [plugin["name"]] , -1)
+ plugin["class"] = getattr(module, name)
+
+ return plugin["class"]
+
+ return None
+ #----------------------------------------------------------------------
+ def getAccountPlugin(self, name):
+ """return account class if existent"""
+ if self.accountPlugins.has_key(name):
+ plugin = self.accountPlugins[name]
+ if plugin.has_key("class"):
+ return plugin["class"]
+
+ module = __import__(plugin["path"], globals(), locals(), [plugin["name"]] , -1)
+ plugin["class"] = getattr(module, plugin["name"])
+
+ return plugin["class"]
+
+ return None
+
+ #----------------------------------------------------------------------
+ def getAccountPlugins(self):
+ """return list of account plugin names"""
+ res = []
+
+ for name in self.accountPlugins.keys():
+ res.append(name)
+
+ return res
+ #----------------------------------------------------------------------
+ def getHookPlugins(self):
+ """return list of hook classes"""
+
+ classes = []
+
+ for name, value in self.hookPlugins.iteritems():
+ if value.has_key("class"):
+ classes.append(value["class"])
+ continue
+
+ if not self.core.config.getPlugin(name, "load"):
+ continue
+
+ try:
+ module = __import__(value["path"], globals(), locals(), [value["name"]] , -1)
+ except Exception, e:
+ self.log.error(_("Error importing %s: %s") % (name, str(e)))
+ self.log.error(_("You should fix dependicies or deactivate load on startup."))
+ continue
+
+ pluginClass = getattr(module, name)
+
+ value["class"] = pluginClass
+
+ classes.append(pluginClass)
+
+ return classes
+
+
+if __name__ == "__main__":
+ _ = lambda x : x
+ pypath = "/home/christian/Projekte/pyload-0.4/module/plugins"
+
+ from time import time
+
+ p = PluginManager(None)
+
+ a = time()
+
+ test = [ "http://www.youtube.com/watch?v=%s" % x for x in range(0,100) ]
+ print p.parseUrls(test)
+
+ b = time()
+
+ print b-a ,"s"
+