From 5499be89203a18ca61a21cfc7266cf0f4ebe6547 Mon Sep 17 00:00:00 2001 From: RaNaN Date: Thu, 15 Dec 2011 23:18:21 +0100 Subject: refractoring --- module/plugins/PluginManager.py | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'module/plugins/PluginManager.py') diff --git a/module/plugins/PluginManager.py b/module/plugins/PluginManager.py index f3f5f47bc..4bf41484a 100644 --- a/module/plugins/PluginManager.py +++ b/module/plugins/PluginManager.py @@ -29,6 +29,10 @@ from traceback import print_exc from module.lib.SafeEval import const_eval as literal_eval from module.ConfigParser import IGNORE +from namedtuple import namedtuple + +PluginTuple = namedtuple("PluginTuple", "version pattern desc long_desc deps user name module") + class PluginManager: ROOT = "module.plugins." USERROOT = "userplugins." @@ -40,6 +44,8 @@ class PluginManager: DESC = re.compile(r'__description__.?=.?("|"""|\')([^"\']+)') + ATTR = re.compile(r'__([a-z0-9_])__\s*=\s*({|\[|\(|"|\')([^__]+)', re.M | re.I) + def __init__(self, core): self.core = core -- cgit v1.2.3 From 4e918edba6c3808b095eab1bad137a2a8cab970d Mon Sep 17 00:00:00 2001 From: RaNaN Date: Sat, 17 Dec 2011 21:53:57 +0100 Subject: updated plugin api and plugin manager --- module/plugins/PluginManager.py | 185 ++++++++++++++++++++-------------------- 1 file changed, 94 insertions(+), 91 deletions(-) (limited to 'module/plugins/PluginManager.py') diff --git a/module/plugins/PluginManager.py b/module/plugins/PluginManager.py index 4bf41484a..744e09ef0 100644 --- a/module/plugins/PluginManager.py +++ b/module/plugins/PluginManager.py @@ -23,28 +23,27 @@ import sys from os import listdir, makedirs from os.path import isfile, join, exists, abspath from sys import version_info -from itertools import chain +from time import time from traceback import print_exc from module.lib.SafeEval import const_eval as literal_eval from module.ConfigParser import IGNORE +from module.plugins.Base import Base from namedtuple import namedtuple -PluginTuple = namedtuple("PluginTuple", "version pattern desc long_desc deps user name module") +PluginTuple = namedtuple("PluginTuple", "version re desc long_desc deps user path") class PluginManager: ROOT = "module.plugins." USERROOT = "userplugins." TYPES = ("crypter", "container", "hoster", "captcha", "accounts", "hooks", "internal") - PATTERN = re.compile(r'__pattern__.*=.*r("|\')([^"\']+)') - VERSION = re.compile(r'__version__.*=.*("|\')([0-9.]+)') - CONFIG = re.compile(r'__config__.*=.*\[([^\]]+)', re.MULTILINE) - DESC = re.compile(r'__description__.?=.?("|"""|\')([^"\']+)') + SINGLE = re.compile(r'__(?P[a-z0-9_]+)__\s*=\s*(?:r|u|_)?((?:(?[a-z0-9_]+)__\s*=\s*((?:\{|\[|"{3}).*?(?:"""|\}|\]))', re.DOTALL | re.M | re.I) def __init__(self, core): self.core = core @@ -53,12 +52,18 @@ class PluginManager: self.log = core.log self.plugins = {} + self.modules = {} # cached modules + self.names = {} # overwritten names + self.history = [] # match history to speedup parsing (type, name) self.createIndex() #register for import hook sys.meta_path.append(self) + def logDebug(self, type, plugin, msg): + self.log.debug("Plugin %s | %s: %s" % (type, plugin, msg)) + def createIndex(self): """create information for all plugins available""" @@ -70,27 +75,14 @@ class PluginManager: f = open(join("userplugins", "__init__.py"), "wb") f.close() - self.plugins["crypter"] = self.crypterPlugins = self.parse("crypter", pattern=True) - self.plugins["container"] = self.containerPlugins = self.parse("container", pattern=True) - self.plugins["hoster"] = self.hosterPlugins = self.parse("hoster", pattern=True) - - self.plugins["captcha"] = self.captchaPlugins = self.parse("captcha") - self.plugins["accounts"] = self.accountPlugins = self.parse("accounts") - self.plugins["hooks"] = self.hookPlugins = self.parse("hooks") - self.plugins["internal"] = self.internalPlugins = self.parse("internal") + a = time() + for type in self.TYPES: + self.plugins[type] = self.parse(type) - self.log.debug("created index of plugins") + self.log.debug("Created index of plugins in %.2f ms", (time() - a) * 1000 ) - def parse(self, folder, pattern=False, home={}): - """ - returns dict with information - home contains parsed plugins from module. - - { - name : {path, version, config, (pattern, re), (plugin, class)} - } - - """ + def parse(self, folder, home={}): + """ Creates a dict with PluginTuples according to parsed information """ plugins = {} if home: pfolder = join("userplugins", folder) @@ -120,55 +112,56 @@ class PluginManager: name = f[:-3] if name[-1] == ".": name = name[:-4] - version = self.VERSION.findall(content) - if version: - version = float(version[0][1]) + attrs = {} + for m in self.SINGLE.findall(content) + self.MULTI.findall(content): + #replace gettext function and eval result + attrs[m[0]] = literal_eval(m[-1].replace("_(", "(")) + if not hasattr(Base, "__%s__" % m[0]): + if m[0] != "type": #TODO remove type from all plugins, its not needed + self.logDebug(folder, name, "Unknown attribute '%s'" % m[0]) + + version = 0 + + if "version" in attrs: + try: + version = float(attrs["version"]) + except ValueError: + self.logDebug(folder, name, "Invalid version %s" % attrs["version"]) + version = 9 #TODO remove when plugins are fixed, causing update loops else: - version = 0 + self.logDebug(folder, name, "No version attribute") # home contains plugins from pyload root if home and name in home: - if home[name]["v"] >= version: + if home[name].version >= version: continue if name in IGNORE or (folder, name) in IGNORE: - continue - - plugins[name] = {} - plugins[name]["v"] = version - - module = f.replace(".pyc", "").replace(".py", "") - - # the plugin is loaded from user directory - plugins[name]["user"] = True if home else False - plugins[name]["name"] = module - - if pattern: - pattern = self.PATTERN.findall(content) - - if pattern: - pattern = pattern[0][1] - else: - pattern = "^unmachtable$" - - plugins[name]["pattern"] = pattern + continue + if "pattern" in attrs and attrs["pattern"]: try: - plugins[name]["re"] = re.compile(pattern) + plugin_re = re.compile(attrs["pattern"]) except: - self.log.error(_("%s has a invalid pattern.") % name) + self.logDebug(folder, name, "Invalid regexp pattern '%s'" % attrs["pattern"]) + plugin_re = None + else: plugin_re = None + + + # create plugin tuple + plugin = PluginTuple(version, plugin_re, None, None, None, True if home else False, + f.replace(".pyc", "").replace(".py", "")) + plugins[name] = plugin # internals have no config if folder == "internal": self.core.config.deleteConfig(name) continue - config = self.CONFIG.findall(content) - if config: - config = literal_eval(config[0].strip().replace("\n", "").replace("\r", "")) - desc = self.DESC.findall(content) - desc = desc[0][1] if desc else "" + if "config" in attrs and attrs["config"]: + config = attrs["config"] + desc = attrs["description"] if "description" in attrs else "" if type(config[0]) == tuple: config = [list(x) for x in config] @@ -189,8 +182,7 @@ class PluginManager: self.log.error("Invalid config in %s: %s" % (name, config)) elif folder == "hooks": #force config creation - desc = self.DESC.findall(content) - desc = desc[0][1] if desc else "" + desc = attrs["description"] if "description" in attrs else "" config = (["activated", "bool", "Activated", False],) try: @@ -199,39 +191,54 @@ class PluginManager: self.log.error("Invalid config in %s: %s" % (name, config)) if not home: - temp = self.parse(folder, pattern, plugins) + temp = self.parse(folder, plugins) plugins.update(temp) return plugins + def parsePlugin(self): + pass + def parseUrls(self, urls): """parse plugins for given list of urls""" - last = None res = [] # tupels of (url, plugin) for url in urls: if type(url) not in (str, unicode, buffer): continue found = False - if last and last[1]["re"].match(url): - res.append((url, last[0])) + for ptype, name in self.history: + if self.plugins[ptype][name].re.match(url): + res.append((url, name)) + found = (ptype, name) + + if found: + # found match, update history + self.history.remove(found) + self.history.insert(0, found) 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 + for ptype in ("crypter", "hoster", "container"): + for name, plugin in self.plugins[ptype].iteritems(): + if plugin.re.match(url): + res.append((url, name)) + self.history.insert(0, (ptype, name)) + del self.history[10:] # cut down to size of 10 + found = True + break if not found: res.append((url, "BasePlugin")) return res + def getPlugins(self, type): + # TODO clean this workaround + if type not in self.plugins: type+="s" # append s, so updater can find the plugins + return self.plugins[type] + def findPlugin(self, name, pluginlist=("hoster", "crypter", "container")): for ptype in pluginlist: if name in self.plugins[ptype]: @@ -244,7 +251,7 @@ class PluginManager: if not plugin: self.log.warning("Plugin %s not found." % name) - plugin = self.hosterPlugins["BasePlugin"] + plugin = self.plugins["hoster"]["BasePlugin"] if "new_module" in plugin and not original: return plugin["new_module"] @@ -268,11 +275,11 @@ class PluginManager: """ plugins = self.plugins[type] if name in plugins: - if "module" in plugins[name]: return plugins[name]["module"] + if (type, name) in self.modules: return self.modules[(type, name)] try: - module = __import__(self.ROOT + "%s.%s" % (type, plugins[name]["name"]), globals(), locals(), - plugins[name]["name"]) - plugins[name]["module"] = module #cache import, maybe unneeded + module = __import__(self.ROOT + "%s.%s" % (type, plugins[name].path), globals(), locals(), + plugins[name].path) + self.modules[(type, name)] = module # cache import, maybne unneeded return module except Exception, e: self.log.error(_("Error importing %(name)s: %(msg)s") % {"name": name, "msg": str(e)}) @@ -286,7 +293,7 @@ class PluginManager: def getAccountPlugins(self): """return list of account plugin names""" - return self.accountPlugins.keys() + return self.plugins["accounts"].keys() def find_module(self, fullname, path=None): #redirecting imports if necesarry @@ -300,10 +307,10 @@ class PluginManager: if type in self.plugins and name in self.plugins[type]: #userplugin is a newer version - if not user and self.plugins[type][name]["user"]: + if not user and self.plugins[type][name].user: return self - #imported from userdir, but pyloads is newer - if user and not self.plugins[type][name]["user"]: + #imported from userdir, but pyloads is newer + if user and not self.plugins[type][name].user: return self @@ -335,7 +342,7 @@ class PluginManager: self.log.debug("Request reload of plugins: %s" % type_plugins) as_dict = {} - for t,n in type_plugins: + for t, n in type_plugins: if t in as_dict: as_dict[t].append(n) else: @@ -348,16 +355,13 @@ class PluginManager: for type in as_dict.iterkeys(): for plugin in as_dict[type]: if plugin in self.plugins[type]: - if "module" in self.plugins[type][plugin]: + if (type, plugin) in self.modules: self.log.debug("Reloading %s" % plugin) - reload(self.plugins[type][plugin]["module"]) + reload(self.modules[(type, plugin)]) - #index creation - self.plugins["crypter"] = self.crypterPlugins = self.parse("crypter", pattern=True) - self.plugins["container"] = self.containerPlugins = self.parse("container", pattern=True) - self.plugins["hoster"] = self.hosterPlugins = self.parse("hoster", pattern=True) - self.plugins["captcha"] = self.captchaPlugins = self.parse("captcha") - self.plugins["accounts"] = self.accountPlugins = self.parse("accounts") + # index re-creation + for type in ("crypter", "container", "hoster", "captcha", "accounts"): + self.plugins[type] = self.parse(type) if "accounts" in as_dict: #accounts needs to be reloaded self.core.accountManager.initPlugins() @@ -366,7 +370,6 @@ class PluginManager: return True - if __name__ == "__main__": _ = lambda x: x pypath = "/home/christian/Projekte/pyload-0.4/module/plugins" -- cgit v1.2.3 From de5e99f3c3082b96af398c01aec49e231726a36b Mon Sep 17 00:00:00 2001 From: RaNaN Date: Sat, 17 Dec 2011 23:55:01 +0100 Subject: pluginmanager cleanup --- module/plugins/PluginManager.py | 199 +++++++++++++++++++++++----------------- 1 file changed, 116 insertions(+), 83 deletions(-) (limited to 'module/plugins/PluginManager.py') diff --git a/module/plugins/PluginManager.py b/module/plugins/PluginManager.py index 744e09ef0..b1a82bcb6 100644 --- a/module/plugins/PluginManager.py +++ b/module/plugins/PluginManager.py @@ -21,7 +21,7 @@ import re import sys from os import listdir, makedirs -from os.path import isfile, join, exists, abspath +from os.path import isfile, join, exists, abspath, basename from sys import version_info from time import time from traceback import print_exc @@ -66,7 +66,7 @@ class PluginManager: def createIndex(self): """create information for all plugins available""" - + # add to path, so we can import from userplugins sys.path.append(abspath("")) if not exists("userplugins"): @@ -79,10 +79,10 @@ class PluginManager: for type in self.TYPES: self.plugins[type] = self.parse(type) - self.log.debug("Created index of plugins in %.2f ms", (time() - a) * 1000 ) + self.log.debug("Created index of plugins in %.2f ms", (time() - a) * 1000) - def parse(self, folder, home={}): - """ Creates a dict with PluginTuples according to parsed information """ + def parse(self, folder, home=None): + """ Analyze and parses all plugins in folder """ plugins = {} if home: pfolder = join("userplugins", folder) @@ -98,10 +98,6 @@ class PluginManager: 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 version_info[0:2] != (2, 5): continue elif f.endswith("_26.pyc") and version_info[0:2] != (2, 6): @@ -109,95 +105,111 @@ class PluginManager: elif f.endswith("_27.pyc") and version_info[0:2] != (2, 7): continue + # replace suffix and version tag name = f[:-3] if name[-1] == ".": name = name[:-4] - attrs = {} - for m in self.SINGLE.findall(content) + self.MULTI.findall(content): - #replace gettext function and eval result - attrs[m[0]] = literal_eval(m[-1].replace("_(", "(")) - if not hasattr(Base, "__%s__" % m[0]): - if m[0] != "type": #TODO remove type from all plugins, its not needed - self.logDebug(folder, name, "Unknown attribute '%s'" % m[0]) - - version = 0 - - if "version" in attrs: - try: - version = float(attrs["version"]) - except ValueError: - self.logDebug(folder, name, "Invalid version %s" % attrs["version"]) - version = 9 #TODO remove when plugins are fixed, causing update loops - else: - self.logDebug(folder, name, "No version attribute") + plugin = self.parsePlugin(join(pfolder, f), folder, name, home) + if plugin: + plugins[name] = plugin - # home contains plugins from pyload root - if home and name in home: - if home[name].version >= version: - continue + if not home: + temp = self.parse(folder, plugins) + plugins.update(temp) - if name in IGNORE or (folder, name) in IGNORE: - continue + return plugins - if "pattern" in attrs and attrs["pattern"]: - try: - plugin_re = re.compile(attrs["pattern"]) - except: - self.logDebug(folder, name, "Invalid regexp pattern '%s'" % attrs["pattern"]) - plugin_re = None - else: plugin_re = None + def parsePlugin(self, filename, folder, name, home=None): + """ Parses a plugin from disk, folder means plugin type in this context. Also sets config. + :arg home: dict with plugins, of which the found one will be matched against (according version) + :returns PluginTuple""" - # create plugin tuple - plugin = PluginTuple(version, plugin_re, None, None, None, True if home else False, - f.replace(".pyc", "").replace(".py", "")) + data = open(filename, "rb") + content = data.read() + data.close() - plugins[name] = plugin + attrs = {} + for m in self.SINGLE.findall(content) + self.MULTI.findall(content): + #replace gettext function and eval result + try: + attrs[m[0]] = literal_eval(m[-1].replace("_(", "(")) + except: + self.logDebug(folder, name, "Error when parsing: %s" % m[-1]) + return + if not hasattr(Base, "__%s__" % m[0]): + if m[0] != "type": #TODO remove type from all plugins, its not needed + self.logDebug(folder, name, "Unknown attribute '%s'" % m[0]) - # internals have no config - if folder == "internal": - self.core.config.deleteConfig(name) - continue + version = 0 - if "config" in attrs and attrs["config"]: - config = attrs["config"] - desc = attrs["description"] if "description" in attrs else "" + if "version" in attrs: + try: + version = float(attrs["version"]) + except ValueError: + self.logDebug(folder, name, "Invalid version %s" % attrs["version"]) + version = 9 #TODO remove when plugins are fixed, causing update loops + else: + self.logDebug(folder, name, "No version attribute") - if type(config[0]) == tuple: - config = [list(x) for x in config] - else: - config = [list(config)] + # home contains plugins from pyload root + if home and name in home: + if home[name].version >= version: + return - if folder == "hooks": - append = True - for item in config: - if item[0] == "activated": append = False + if name in IGNORE or (folder, name) in IGNORE: + return - # activated flag missing - if append: config.append(["activated", "bool", "Activated", False]) + if "pattern" in attrs and attrs["pattern"]: + try: + plugin_re = re.compile(attrs["pattern"]) + except: + self.logDebug(folder, name, "Invalid regexp pattern '%s'" % attrs["pattern"]) + plugin_re = None + else: plugin_re = None - try: - self.core.config.addPluginConfig(name, config, desc) - except: - self.log.error("Invalid config in %s: %s" % (name, config)) - elif folder == "hooks": #force config creation - desc = attrs["description"] if "description" in attrs else "" - config = (["activated", "bool", "Activated", False],) + # create plugin tuple + plugin = PluginTuple(version, plugin_re, None, None, None, bool(home), filename) - try: - self.core.config.addPluginConfig(name, config, desc) - except: - self.log.error("Invalid config in %s: %s" % (name, config)) - if not home: - temp = self.parse(folder, plugins) - plugins.update(temp) + # internals have no config + if folder == "internal": + self.core.config.deleteConfig(name) + return plugin - return plugins + if "config" in attrs and attrs["config"]: + config = attrs["config"] + desc = attrs["description"] if "description" in attrs else "" - def parsePlugin(self): - pass + if type(config[0]) == tuple: + config = [list(x) for x in config] + else: + config = [list(config)] + + if folder == "hooks": + 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) + except: + self.log.error("Invalid config in %s: %s" % (name, config)) + + elif folder == "hooks": #force config creation + desc = attrs["description"] if "description" in attrs else "" + config = (["activated", "bool", "Activated", False],) + + try: + self.core.config.addPluginConfig(name, config, desc) + except: + self.log.error("Invalid config in %s: %s" % (name, config)) + + return plugin def parseUrls(self, urls): @@ -206,7 +218,9 @@ class PluginManager: res = [] # tupels of (url, plugin) for url in urls: - if type(url) not in (str, unicode, buffer): continue + if type(url) not in (str, unicode, buffer): + self.log.debug("Parsing invalid type %s" % type(url)) + continue found = False for ptype, name in self.history: @@ -214,7 +228,7 @@ class PluginManager: res.append((url, name)) found = (ptype, name) - if found: + if found and self.history[0] != found: # found match, update history self.history.remove(found) self.history.insert(0, found) @@ -236,7 +250,7 @@ class PluginManager: def getPlugins(self, type): # TODO clean this workaround - if type not in self.plugins: type+="s" # append s, so updater can find the plugins + if type not in self.plugins: type += "s" # append s, so updater can find the plugins return self.plugins[type] def findPlugin(self, name, pluginlist=("hoster", "crypter", "container")): @@ -277,8 +291,9 @@ class PluginManager: if name in plugins: if (type, name) in self.modules: return self.modules[(type, name)] try: - module = __import__(self.ROOT + "%s.%s" % (type, plugins[name].path), globals(), locals(), - plugins[name].path) + # convert path to python recognizable import + path = basename(plugins[name].path).replace(".pyc", "").replace(".py", "") + module = __import__(self.ROOT + "%s.%s" % (type, path), globals(), locals(), path) self.modules[(type, name)] = module # cache import, maybne unneeded return module except Exception, e: @@ -369,6 +384,24 @@ class PluginManager: return True + def loadIcons(self): + """Loads all icons from plugins, plugin type is not in result, because its not important here. + + :return: Dict of names mapped to icons + """ + pass + + def loadIcon(self, type, name): + """ load icon for single plugin, base64 encoded""" + pass + + def checkDependencies(self, type, name): + """ Check deps for given plugin + + :return: List of unfullfilled dependencies + """ + pass + if __name__ == "__main__": _ = lambda x: x -- cgit v1.2.3 From 6eae782f13953dd0ba2bbe1b582cf33fd4d7d90a Mon Sep 17 00:00:00 2001 From: RaNaN Date: Mon, 19 Dec 2011 23:10:49 +0100 Subject: configparser v2, warning CONFIG will be DELETED. --- module/plugins/PluginManager.py | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) (limited to 'module/plugins/PluginManager.py') diff --git a/module/plugins/PluginManager.py b/module/plugins/PluginManager.py index b1a82bcb6..9845590cf 100644 --- a/module/plugins/PluginManager.py +++ b/module/plugins/PluginManager.py @@ -27,12 +27,17 @@ from time import time from traceback import print_exc from module.lib.SafeEval import const_eval as literal_eval -from module.ConfigParser import IGNORE from module.plugins.Base import Base -from namedtuple import namedtuple +from new_collections import namedtuple -PluginTuple = namedtuple("PluginTuple", "version re desc long_desc deps user path") +# ignore these plugin configs, mainly because plugins were wiped out +IGNORE = ( + "FreakshareNet", "SpeedManager", "ArchiveTo", "ShareCx", ('hooks', 'UnRar'), + 'EasyShareCom', 'FlyshareCz' + ) + +PluginTuple = namedtuple("PluginTuple", "version re deps user path") class PluginManager: ROOT = "module.plugins." @@ -57,6 +62,9 @@ class PluginManager: self.history = [] # match history to speedup parsing (type, name) self.createIndex() + + self.core.config.parseValues(self.core.config.PLUGIN) + #register for import hook sys.meta_path.append(self) @@ -168,19 +176,23 @@ class PluginManager: plugin_re = None else: plugin_re = None + deps = attrs.get("dependencies", None) # create plugin tuple - plugin = PluginTuple(version, plugin_re, None, None, None, bool(home), filename) + plugin = PluginTuple(version, plugin_re, deps, bool(home), filename) # internals have no config if folder == "internal": - self.core.config.deleteConfig(name) return plugin + if folder == "hooks" and "config" not in attrs: + attrs["config"] = (["activated", "bool", "Activated", False],) + if "config" in attrs and attrs["config"]: config = attrs["config"] - desc = attrs["description"] if "description" in attrs else "" + desc = attrs.get("description", "") + long_desc = attrs.get("long_description", "") if type(config[0]) == tuple: config = [list(x) for x in config] @@ -193,21 +205,12 @@ class PluginManager: 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) - except: - self.log.error("Invalid config in %s: %s" % (name, config)) - - elif folder == "hooks": #force config creation - desc = attrs["description"] if "description" in attrs else "" - config = (["activated", "bool", "Activated", False],) + if append: config.insert(0, ("activated", "bool", "Activated", False)) try: - self.core.config.addPluginConfig(name, config, desc) + self.core.config.addConfigSection(name, name, desc, long_desc, config) except: - self.log.error("Invalid config in %s: %s" % (name, config)) + self.logDebug(folder, name, "Invalid config %s" % config) return plugin @@ -294,7 +297,7 @@ class PluginManager: # convert path to python recognizable import path = basename(plugins[name].path).replace(".pyc", "").replace(".py", "") module = __import__(self.ROOT + "%s.%s" % (type, path), globals(), locals(), path) - self.modules[(type, name)] = module # cache import, maybne unneeded + self.modules[(type, name)] = module # cache import, maybe unneeded return module except Exception, e: self.log.error(_("Error importing %(name)s: %(msg)s") % {"name": name, "msg": str(e)}) -- cgit v1.2.3 From 958bf611f5d9d117f19f824990ec6fd6b537e967 Mon Sep 17 00:00:00 2001 From: RaNaN Date: Thu, 22 Dec 2011 23:45:38 +0100 Subject: accountmanager v2, delete your accounts.conf and re-enter them in pyload, new nice debug functions, try core.shell() and core.breakpoint() --- module/plugins/PluginManager.py | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) (limited to 'module/plugins/PluginManager.py') diff --git a/module/plugins/PluginManager.py b/module/plugins/PluginManager.py index 9845590cf..5c31930a5 100644 --- a/module/plugins/PluginManager.py +++ b/module/plugins/PluginManager.py @@ -259,28 +259,28 @@ class PluginManager: def findPlugin(self, name, pluginlist=("hoster", "crypter", "container")): for ptype in pluginlist: if name in self.plugins[ptype]: - return self.plugins[ptype][name], ptype + return ptype, self.plugins[ptype][name] return None, None def getPlugin(self, name, original=False): """return plugin module from hoster|decrypter|container""" - plugin, type = self.findPlugin(name) + type, plugin = self.findPlugin(name) if not plugin: self.log.warning("Plugin %s not found." % name) - plugin = self.plugins["hoster"]["BasePlugin"] + name = "BasePlugin" - if "new_module" in plugin and not original: - return plugin["new_module"] + if (type, name) in self.modules and not original: + return self.modules[(type, name)] return self.loadModule(type, name) def getPluginName(self, name): """ used to obtain new name if other plugin was injected""" - plugin, type = self.findPlugin(name) + type, plugin = self.findPlugin(name) - if "new_name" in plugin: - return plugin["new_name"] + if (type, name) in self.names: + return self.names[(type, name)] return name @@ -309,10 +309,23 @@ class PluginManager: module = self.loadModule(type, name) if module: return getattr(module, name) + def hasAccountPlugin(self, plugin): + return plugin in self.plugins["accounts"] + def getAccountPlugins(self): """return list of account plugin names""" return self.plugins["accounts"].keys() + def injectPlugin(self, type, name, module, new_name): + self.modules[(type, name)] = module + self.names[(type, name)] = new_name + + def restoreState(self, type, name): + if (type, name) in self.modules: + del self.modules[(type, name)] + if (type, name) in self.names: + del self.names[(type, name)] + def find_module(self, fullname, path=None): #redirecting imports if necesarry if fullname.startswith(self.ROOT) or fullname.startswith(self.USERROOT): #seperate pyload plugins -- cgit v1.2.3 From f852c362fc6283246a9f9e690c456dd3fd245c29 Mon Sep 17 00:00:00 2001 From: RaNaN Date: Fri, 23 Dec 2011 12:15:56 +0100 Subject: closed #473 --- module/plugins/PluginManager.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'module/plugins/PluginManager.py') diff --git a/module/plugins/PluginManager.py b/module/plugins/PluginManager.py index 5c31930a5..18dea7699 100644 --- a/module/plugins/PluginManager.py +++ b/module/plugins/PluginManager.py @@ -309,18 +309,13 @@ class PluginManager: module = self.loadModule(type, name) if module: return getattr(module, name) - def hasAccountPlugin(self, plugin): - return plugin in self.plugins["accounts"] - - def getAccountPlugins(self): - """return list of account plugin names""" - return self.plugins["accounts"].keys() - def injectPlugin(self, type, name, module, new_name): + """ Overwrite a plugin with a other module. used by Multihoster """ self.modules[(type, name)] = module self.names[(type, name)] = new_name def restoreState(self, type, name): + """ Restore the state of a plugin after injecting """ if (type, name) in self.modules: del self.modules[(type, name)] if (type, name) in self.names: -- cgit v1.2.3 From d35c003cc53d4723d1dfe0d81eeb9bea78cee594 Mon Sep 17 00:00:00 2001 From: RaNaN Date: Sat, 31 Dec 2011 16:01:24 +0100 Subject: new crypter plugin API, now decrypting possible for now. --- module/plugins/PluginManager.py | 52 ++++++++++++++--------------------------- 1 file changed, 17 insertions(+), 35 deletions(-) (limited to 'module/plugins/PluginManager.py') diff --git a/module/plugins/PluginManager.py b/module/plugins/PluginManager.py index 18dea7699..e00c1e1f5 100644 --- a/module/plugins/PluginManager.py +++ b/module/plugins/PluginManager.py @@ -42,7 +42,7 @@ PluginTuple = namedtuple("PluginTuple", "version re deps user path") class PluginManager: ROOT = "module.plugins." USERROOT = "userplugins." - TYPES = ("crypter", "container", "hoster", "captcha", "accounts", "hooks", "internal") + TYPES = ("crypter", "hoster", "captcha", "accounts", "hooks", "internal") SINGLE = re.compile(r'__(?P[a-z0-9_]+)__\s*=\s*(?:r|u|_)?((?:(? Date: Sun, 8 Jan 2012 14:44:59 +0100 Subject: new MultiHoster hook --- module/plugins/PluginManager.py | 37 ++++++++----------------------------- 1 file changed, 8 insertions(+), 29 deletions(-) (limited to 'module/plugins/PluginManager.py') diff --git a/module/plugins/PluginManager.py b/module/plugins/PluginManager.py index e00c1e1f5..c345f765f 100644 --- a/module/plugins/PluginManager.py +++ b/module/plugins/PluginManager.py @@ -58,7 +58,6 @@ class PluginManager: self.plugins = {} self.modules = {} # cached modules - self.names = {} # overwritten names self.history = [] # match history to speedup parsing (type, name) self.createIndex() @@ -262,27 +261,19 @@ class PluginManager: return ptype, self.plugins[ptype][name] return None, None - def getPlugin(self, name, original=False): - """return plugin module from hoster|decrypter""" + def getPluginModule(self, name): + """ Decprecated: return plugin module from hoster|crypter""" + self.log.debug("Deprecated method: .getPluginModule()") type, plugin = self.findPlugin(name) - - if not plugin: - self.log.warning("Plugin %s not found." % name) - name = "BasePlugin" - - if (type, name) in self.modules and not original: - return self.modules[(type, name)] - return self.loadModule(type, name) - def getPluginName(self, name): - """ used to obtain new name if other plugin was injected""" + def getPluginClass(self, name): + """ return plugin class from hoster|crypter, always the not overwritten one """ type, plugin = self.findPlugin(name) + return self.loadClass(type, name) - if (type, name) in self.names: - return self.names[(type, name)] - - return name + # MultiHoster will overwrite this + getPlugin = getPluginClass def loadModule(self, type, name): """ Returns loaded module for plugin @@ -309,18 +300,6 @@ class PluginManager: module = self.loadModule(type, name) if module: return getattr(module, name) - def injectPlugin(self, type, name, module, new_name): - """ Overwrite a plugin with a other module. used by Multihoster """ - self.modules[(type, name)] = module - self.names[(type, name)] = new_name - - def restoreState(self, type, name): - """ Restore the state of a plugin after injecting """ - if (type, name) in self.modules: - del self.modules[(type, name)] - if (type, name) in self.names: - del self.names[(type, name)] - def find_module(self, fullname, path=None): #redirecting imports if necesarry if fullname.startswith(self.ROOT) or fullname.startswith(self.USERROOT): #seperate pyload plugins -- cgit v1.2.3 From d7eef2c28eae2e43e3ade4441810ecc0cdea6fd7 Mon Sep 17 00:00:00 2001 From: RaNaN Date: Sun, 5 Feb 2012 21:21:36 +0100 Subject: option for internal plugins --- module/plugins/PluginManager.py | 53 ++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 22 deletions(-) (limited to 'module/plugins/PluginManager.py') diff --git a/module/plugins/PluginManager.py b/module/plugins/PluginManager.py index c345f765f..4e2fa21ed 100644 --- a/module/plugins/PluginManager.py +++ b/module/plugins/PluginManager.py @@ -24,7 +24,6 @@ from os import listdir, makedirs from os.path import isfile, join, exists, abspath, basename from sys import version_info from time import time -from traceback import print_exc from module.lib.SafeEval import const_eval as literal_eval from module.plugins.Base import Base @@ -44,9 +43,9 @@ class PluginManager: USERROOT = "userplugins." TYPES = ("crypter", "hoster", "captcha", "accounts", "hooks", "internal") + BUILTIN = re.compile(r'__(?P[a-z0-9_]+)__\s*=\s?(True|False|None|[0-9x.]+)', re.I) SINGLE = re.compile(r'__(?P[a-z0-9_]+)__\s*=\s*(?:r|u|_)?((?:(?[a-z0-9_]+)__\s*=\s*((?:\{|\[|"{3}).*?(?:"""|\}|\]))', re.DOTALL | re.M | re.I) @@ -58,10 +57,9 @@ class PluginManager: self.plugins = {} self.modules = {} # cached modules - self.history = [] # match history to speedup parsing (type, name) + self.history = [] # match history to speedup parsing (type, name) self.createIndex() - self.core.config.parseValues(self.core.config.PLUGIN) #register for import hook @@ -126,28 +124,36 @@ class PluginManager: return plugins - def parsePlugin(self, filename, folder, name, home=None): - """ Parses a plugin from disk, folder means plugin type in this context. Also sets config. - - :arg home: dict with plugins, of which the found one will be matched against (according version) - :returns PluginTuple""" - + def parseAttributes(self, filename, name, folder=""): + """ Parse attribute dict from plugin""" data = open(filename, "rb") content = data.read() data.close() attrs = {} - for m in self.SINGLE.findall(content) + self.MULTI.findall(content): + for m in self.BUILTIN.findall(content) + self.SINGLE.findall(content) + self.MULTI.findall(content): #replace gettext function and eval result try: attrs[m[0]] = literal_eval(m[-1].replace("_(", "(")) except: self.logDebug(folder, name, "Error when parsing: %s" % m[-1]) - return + self.core.print_exc() + if not hasattr(Base, "__%s__" % m[0]): if m[0] != "type": #TODO remove type from all plugins, its not needed self.logDebug(folder, name, "Unknown attribute '%s'" % m[0]) + return attrs + + def parsePlugin(self, filename, folder, name, home=None): + """ Parses a plugin from disk, folder means plugin type in this context. Also sets config. + + :arg home: dict with plugins, of which the found one will be matched against (according version) + :returns PluginTuple""" + + attrs = self.parseAttributes(filename, name, folder) + if not attrs: return + version = 0 if "version" in attrs: @@ -185,7 +191,7 @@ class PluginManager: if folder == "internal": return plugin - if folder == "hooks" and "config" not in attrs: + if folder == "hooks" and "config" not in attrs and not attrs.get("internal", False): attrs["config"] = (["activated", "bool", "Activated", False],) if "config" in attrs and attrs["config"]: @@ -198,13 +204,11 @@ class PluginManager: else: config = [list(config)] - if folder == "hooks": - append = True + if folder == "hooks" and not attrs.get("internal", False): for item in config: - if item[0] == "activated": append = False - - # activated flag missing - if append: config.insert(0, ("activated", "bool", "Activated", False)) + if item[0] == "activated": break + else: # activated flag missing + config.insert(0, ("activated", "bool", "Activated", False)) try: self.core.config.addConfigSection(name, name, desc, long_desc, config) @@ -230,7 +234,7 @@ class PluginManager: if self.plugins[ptype][name].re.match(url): res[ptype].append((url, name)) found = (ptype, name) - break + break # need to exit this loop first if found: # found match if self.history[0] != found: #update history @@ -275,6 +279,12 @@ class PluginManager: # MultiHoster will overwrite this getPlugin = getPluginClass + + def loadAttributes(self, type, name): + plugin = self.plugins[type][name] + return self.parseAttributes(plugin.path, name, type) + + def loadModule(self, type, name): """ Returns loaded module for plugin @@ -292,8 +302,7 @@ class PluginManager: return module except Exception, e: self.log.error(_("Error importing %(name)s: %(msg)s") % {"name": name, "msg": str(e)}) - if self.core.debug: - print_exc() + self.core.print_exc() def loadClass(self, type, name): """Returns the class of a plugin with the same name""" -- cgit v1.2.3 From 4df2b77fdf42046fe19bd371be7c7255986b5980 Mon Sep 17 00:00:00 2001 From: RaNaN Date: Tue, 6 Mar 2012 13:36:39 +0100 Subject: renamed hooks to addons, new filemanager and database, many new api methods you will loose ALL your LINKS, webinterface will NOT work --- module/plugins/PluginManager.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'module/plugins/PluginManager.py') diff --git a/module/plugins/PluginManager.py b/module/plugins/PluginManager.py index 4e2fa21ed..733cd2c5d 100644 --- a/module/plugins/PluginManager.py +++ b/module/plugins/PluginManager.py @@ -30,9 +30,11 @@ from module.plugins.Base import Base from new_collections import namedtuple +#TODO: ignores not updatable + # ignore these plugin configs, mainly because plugins were wiped out IGNORE = ( - "FreakshareNet", "SpeedManager", "ArchiveTo", "ShareCx", ('hooks', 'UnRar'), + "FreakshareNet", "SpeedManager", "ArchiveTo", "ShareCx", ('addons', 'UnRar'), 'EasyShareCom', 'FlyshareCz' ) @@ -41,7 +43,7 @@ PluginTuple = namedtuple("PluginTuple", "version re deps user path") class PluginManager: ROOT = "module.plugins." USERROOT = "userplugins." - TYPES = ("crypter", "hoster", "captcha", "accounts", "hooks", "internal") + TYPES = ("crypter", "hoster", "accounts", "addons", "internal") BUILTIN = re.compile(r'__(?P[a-z0-9_]+)__\s*=\s?(True|False|None|[0-9x.]+)', re.I) SINGLE = re.compile(r'__(?P[a-z0-9_]+)__\s*=\s*(?:r|u|_)?((?:(? Date: Sun, 22 Apr 2012 19:56:17 +0200 Subject: a huge pile of spelling fixes --- module/plugins/PluginManager.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'module/plugins/PluginManager.py') diff --git a/module/plugins/PluginManager.py b/module/plugins/PluginManager.py index 733cd2c5d..f42bd08c6 100644 --- a/module/plugins/PluginManager.py +++ b/module/plugins/PluginManager.py @@ -221,7 +221,7 @@ class PluginManager: def parseUrls(self, urls): - """parse plugins for given list of urls, seperate to crypter and hoster""" + """parse plugins for given list of urls, separate to crypter and hoster""" res = {"hoster": [], "crypter": []} # tupels of (url, plugin) @@ -313,7 +313,7 @@ class PluginManager: def find_module(self, fullname, path=None): #redirecting imports if necesarry - if fullname.startswith(self.ROOT) or fullname.startswith(self.USERROOT): #seperate pyload plugins + if fullname.startswith(self.ROOT) or fullname.startswith(self.USERROOT): #separate pyload plugins if fullname.startswith(self.USERROOT): user = 1 else: user = 0 #used as bool and int -- cgit v1.2.3 From 0d2d6daef850ac6bcc7fafccd230e52d2a862c2c Mon Sep 17 00:00:00 2001 From: RaNaN Date: Sun, 3 Jun 2012 17:45:10 +0200 Subject: updates for database + api --- module/plugins/PluginManager.py | 405 ---------------------------------------- 1 file changed, 405 deletions(-) delete mode 100644 module/plugins/PluginManager.py (limited to 'module/plugins/PluginManager.py') diff --git a/module/plugins/PluginManager.py b/module/plugins/PluginManager.py deleted file mode 100644 index f42bd08c6..000000000 --- a/module/plugins/PluginManager.py +++ /dev/null @@ -1,405 +0,0 @@ -# -*- 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 . - - @author: mkaay, RaNaN -""" - -import re -import sys - -from os import listdir, makedirs -from os.path import isfile, join, exists, abspath, basename -from sys import version_info -from time import time - -from module.lib.SafeEval import const_eval as literal_eval -from module.plugins.Base import Base - -from new_collections import namedtuple - -#TODO: ignores not updatable - -# ignore these plugin configs, mainly because plugins were wiped out -IGNORE = ( - "FreakshareNet", "SpeedManager", "ArchiveTo", "ShareCx", ('addons', 'UnRar'), - 'EasyShareCom', 'FlyshareCz' - ) - -PluginTuple = namedtuple("PluginTuple", "version re deps user path") - -class PluginManager: - ROOT = "module.plugins." - USERROOT = "userplugins." - TYPES = ("crypter", "hoster", "accounts", "addons", "internal") - - BUILTIN = re.compile(r'__(?P[a-z0-9_]+)__\s*=\s?(True|False|None|[0-9x.]+)', re.I) - SINGLE = re.compile(r'__(?P[a-z0-9_]+)__\s*=\s*(?:r|u|_)?((?:(?[a-z0-9_]+)__\s*=\s*((?:\{|\[|"{3}).*?(?:"""|\}|\]))', re.DOTALL | re.M | re.I) - - def __init__(self, core): - self.core = core - - #self.config = self.core.config - self.log = core.log - - self.plugins = {} - self.modules = {} # cached modules - self.history = [] # match history to speedup parsing (type, name) - self.createIndex() - - self.core.config.parseValues(self.core.config.PLUGIN) - - #register for import addon - sys.meta_path.append(self) - - - def logDebug(self, type, plugin, msg): - self.log.debug("Plugin %s | %s: %s" % (type, plugin, msg)) - - def createIndex(self): - """create information for all plugins available""" - # add to path, so we can import from userplugins - 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() - - a = time() - for type in self.TYPES: - self.plugins[type] = self.parse(type) - - self.log.debug("Created index of plugins in %.2f ms", (time() - a) * 1000) - - def parse(self, folder, home=None): - """ Analyze and parses all plugins in folder """ - 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("_"): - if f.endswith("_25.pyc") and version_info[0:2] != (2, 5): - continue - elif f.endswith("_26.pyc") and version_info[0:2] != (2, 6): - continue - elif f.endswith("_27.pyc") and version_info[0:2] != (2, 7): - continue - - # replace suffix and version tag - name = f[:-3] - if name[-1] == ".": name = name[:-4] - - plugin = self.parsePlugin(join(pfolder, f), folder, name, home) - if plugin: - plugins[name] = plugin - - if not home: - temp = self.parse(folder, plugins) - plugins.update(temp) - - return plugins - - def parseAttributes(self, filename, name, folder=""): - """ Parse attribute dict from plugin""" - data = open(filename, "rb") - content = data.read() - data.close() - - attrs = {} - for m in self.BUILTIN.findall(content) + self.SINGLE.findall(content) + self.MULTI.findall(content): - #replace gettext function and eval result - try: - attrs[m[0]] = literal_eval(m[-1].replace("_(", "(")) - except: - self.logDebug(folder, name, "Error when parsing: %s" % m[-1]) - self.core.print_exc() - - if not hasattr(Base, "__%s__" % m[0]): - if m[0] != "type": #TODO remove type from all plugins, its not needed - self.logDebug(folder, name, "Unknown attribute '%s'" % m[0]) - - return attrs - - def parsePlugin(self, filename, folder, name, home=None): - """ Parses a plugin from disk, folder means plugin type in this context. Also sets config. - - :arg home: dict with plugins, of which the found one will be matched against (according version) - :returns PluginTuple""" - - attrs = self.parseAttributes(filename, name, folder) - if not attrs: return - - version = 0 - - if "version" in attrs: - try: - version = float(attrs["version"]) - except ValueError: - self.logDebug(folder, name, "Invalid version %s" % attrs["version"]) - version = 9 #TODO remove when plugins are fixed, causing update loops - else: - self.logDebug(folder, name, "No version attribute") - - # home contains plugins from pyload root - if home and name in home: - if home[name].version >= version: - return - - if name in IGNORE or (folder, name) in IGNORE: - return - - if "pattern" in attrs and attrs["pattern"]: - try: - plugin_re = re.compile(attrs["pattern"]) - except: - self.logDebug(folder, name, "Invalid regexp pattern '%s'" % attrs["pattern"]) - plugin_re = None - else: plugin_re = None - - deps = attrs.get("dependencies", None) - - # create plugin tuple - plugin = PluginTuple(version, plugin_re, deps, bool(home), filename) - - - # internals have no config - if folder == "internal": - return plugin - - if folder == "addons" and "config" not in attrs and not attrs.get("internal", False): - attrs["config"] = (["activated", "bool", "Activated", False],) - - if "config" in attrs and attrs["config"]: - config = attrs["config"] - desc = attrs.get("description", "") - long_desc = attrs.get("long_description", "") - - if type(config[0]) == tuple: - config = [list(x) for x in config] - else: - config = [list(config)] - - if folder == "addons" and not attrs.get("internal", False): - for item in config: - if item[0] == "activated": break - else: # activated flag missing - config.insert(0, ("activated", "bool", "Activated", False)) - - try: - self.core.config.addConfigSection(name, name, desc, long_desc, config) - except: - self.logDebug(folder, name, "Invalid config %s" % config) - - return plugin - - - def parseUrls(self, urls): - """parse plugins for given list of urls, separate to crypter and hoster""" - - res = {"hoster": [], "crypter": []} # tupels of (url, plugin) - - for url in urls: - if type(url) not in (str, unicode, buffer): - self.log.debug("Parsing invalid type %s" % type(url)) - continue - - found = False - - for ptype, name in self.history: - if self.plugins[ptype][name].re.match(url): - res[ptype].append((url, name)) - found = (ptype, name) - break # need to exit this loop first - - if found: # found match - if self.history[0] != found: #update history - self.history.remove(found) - self.history.insert(0, found) - continue - - for ptype in ("crypter", "hoster"): - for name, plugin in self.plugins[ptype].iteritems(): - if plugin.re.match(url): - res[ptype].append((url, name)) - self.history.insert(0, (ptype, name)) - del self.history[10:] # cut down to size of 10 - found = True - break - - if not found: - res["hoster"].append((url, "BasePlugin")) - - return res["hoster"], res["crypter"] - - def getPlugins(self, type): - return self.plugins.get(type, None) - - def findPlugin(self, name, pluginlist=("hoster", "crypter")): - for ptype in pluginlist: - if name in self.plugins[ptype]: - return ptype, self.plugins[ptype][name] - return None, None - - def getPluginModule(self, name): - """ Decprecated: return plugin module from hoster|crypter""" - self.log.debug("Deprecated method: .getPluginModule()") - type, plugin = self.findPlugin(name) - return self.loadModule(type, name) - - def getPluginClass(self, name): - """ return plugin class from hoster|crypter, always the not overwritten one """ - type, plugin = self.findPlugin(name) - return self.loadClass(type, name) - - # MultiHoster will overwrite this - getPlugin = getPluginClass - - - def loadAttributes(self, type, name): - plugin = self.plugins[type][name] - return self.parseAttributes(plugin.path, name, type) - - - def loadModule(self, type, name): - """ Returns loaded module for plugin - - :param type: plugin type, subfolder of module.plugins - :param name: - """ - plugins = self.plugins[type] - if name in plugins: - if (type, name) in self.modules: return self.modules[(type, name)] - try: - # convert path to python recognizable import - path = basename(plugins[name].path).replace(".pyc", "").replace(".py", "") - module = __import__(self.ROOT + "%s.%s" % (type, path), globals(), locals(), path) - self.modules[(type, name)] = module # cache import, maybe unneeded - return module - except Exception, e: - self.log.error(_("Error importing %(name)s: %(msg)s") % {"name": name, "msg": str(e)}) - self.core.print_exc() - - def loadClass(self, type, name): - """Returns the class of a plugin with the same name""" - module = self.loadModule(type, name) - if module: return getattr(module, name) - - def find_module(self, fullname, path=None): - #redirecting imports if necesarry - if fullname.startswith(self.ROOT) or fullname.startswith(self.USERROOT): #separate pyload plugins - if fullname.startswith(self.USERROOT): user = 1 - else: user = 0 #used as bool and int - - split = fullname.split(".") - if len(split) != 4 - user: return - type, name = split[2 - user:4 - user] - - if type in self.plugins and name in self.plugins[type]: - #userplugin is a newer version - if not user and self.plugins[type][name].user: - return self - #imported from userdir, but pyloads is newer - if user and not self.plugins[type][name].user: - return self - - - def load_module(self, name, replace=True): - if name not in sys.modules: #could be already in modules - if replace: - if self.ROOT in name: - newname = name.replace(self.ROOT, self.USERROOT) - else: - newname = name.replace(self.USERROOT, self.ROOT) - else: newname = name - - base, plugin = newname.rsplit(".", 1) - - self.log.debug("Redirected import %s -> %s" % (name, newname)) - - module = __import__(newname, globals(), locals(), [plugin]) - #inject under new an old name - sys.modules[name] = module - sys.modules[newname] = module - - return sys.modules[name] - - - def reloadPlugins(self, type_plugins): - """ reloads and reindexes plugins """ - if not type_plugins: return False - - self.log.debug("Request reload of plugins: %s" % type_plugins) - - as_dict = {} - for t, n in type_plugins: - if t in as_dict: - as_dict[t].append(n) - else: - as_dict[t] = [n] - - # we do not reload addons or internals, would cause to much side effects - if "addons" in as_dict or "internal" in as_dict: - return False - - for type in as_dict.iterkeys(): - for plugin in as_dict[type]: - if plugin in self.plugins[type]: - if (type, plugin) in self.modules: - self.log.debug("Reloading %s" % plugin) - reload(self.modules[(type, plugin)]) - - # index re-creation - for type in ("crypter", "container", "hoster", "captcha", "accounts"): - self.plugins[type] = self.parse(type) - - if "accounts" in as_dict: #accounts needs to be reloaded - self.core.accountManager.initPlugins() - self.core.scheduler.addJob(0, self.core.accountManager.getAccountInfos) - - return True - - def loadIcons(self): - """Loads all icons from plugins, plugin type is not in result, because its not important here. - - :return: Dict of names mapped to icons - """ - pass - - def loadIcon(self, type, name): - """ load icon for single plugin, base64 encoded""" - pass - - def checkDependencies(self, type, name): - """ Check deps for given plugin - - :return: List of unfullfilled dependencies - """ - pass - -- cgit v1.2.3