diff options
-rw-r--r-- | module/Api.py | 9 | ||||
-rw-r--r-- | module/ConfigParser.py | 234 | ||||
-rw-r--r-- | module/plugins/PluginManager.py | 10 | ||||
-rw-r--r-- | module/remote/thriftbackend/pyload.thrift | 3 | ||||
-rw-r--r-- | module/remote/thriftbackend/thriftgen/pyload/ttypes.py | 6 | ||||
-rw-r--r-- | module/web/json_app.py | 14 | ||||
-rw-r--r-- | module/web/templates/default/settings_item.html | 87 |
7 files changed, 189 insertions, 174 deletions
diff --git a/module/Api.py b/module/Api.py index 8c32f4b7a..ffb88c6af 100644 --- a/module/Api.py +++ b/module/Api.py @@ -54,7 +54,7 @@ class Api(Iface): section = ConfigSection(sectionName, sub["desc"]) items = [] for key, data in sub.iteritems(): - if key == "desc": + if key in ("desc","outline"): continue item = ConfigItem() item.name = key @@ -64,6 +64,8 @@ class Api(Iface): items.append(item) section.items = items sections[sectionName] = section + if sub.has_key("outline"): + section.outline = sub["outline"] return sections def getConfigValue(self, category, option, section="core"): @@ -87,6 +89,9 @@ class Api(Iface): :param value: new config value :param section: 'plugin' or 'core """ + self.core.hookManager.dispatchEvent("configChanged", category, option, value, section) + print category, option, value, section + if section == "core": self.core.config[category][option] = value @@ -565,7 +570,7 @@ class Api(Iface): task = self.core.captchaManager.getTask() return not task is None - def getCaptchaTask(self, exclusive): + def getCaptchaTask(self, exclusive=False): """Returns a captcha task :param exclusive: unused diff --git a/module/ConfigParser.py b/module/ConfigParser.py index 5804a15cf..aa8367fb4 100644 --- a/module/ConfigParser.py +++ b/module/ConfigParser.py @@ -41,181 +41,175 @@ class ConfigParser: self.config = {} # the config values self.plugin = {} # the config for plugins self.oldRemoteData = {} - + self.checkVersion() - + self.readConfig() self.deleteOldPlugins() - + #---------------------------------------------------------------------- def checkVersion(self, n=0): """determines if config need to be copied""" try: if not exists("pyload.conf"): - copy(join(pypath,"module", "config", "default.conf"), "pyload.conf") - + copy(join(pypath, "module", "config", "default.conf"), "pyload.conf") + if not exists("plugin.conf"): f = open("plugin.conf", "wb") - f.write("version: "+str(CONF_VERSION)) + f.write("version: " + str(CONF_VERSION)) f.close() - + f = open("pyload.conf", "rb") v = f.readline() f.close() - v = v[v.find(":")+1:].strip() - + v = v[v.find(":") + 1:].strip() + if not v or int(v) < CONF_VERSION: - copy(join(pypath,"module", "config", "default.conf"), "pyload.conf") + copy(join(pypath, "module", "config", "default.conf"), "pyload.conf") print "Old version of config was replaced" - + f = open("plugin.conf", "rb") v = f.readline() f.close() - v = v[v.find(":")+1:].strip() - + v = v[v.find(":") + 1:].strip() + if not v or int(v) < CONF_VERSION: f = open("plugin.conf", "wb") - f.write("version: "+str(CONF_VERSION)) + f.write("version: " + str(CONF_VERSION)) f.close() print "Old version of plugin-config replaced" except: if n < 3: sleep(0.3) - self.checkVersion(n+1) + self.checkVersion(n + 1) else: raise - + #---------------------------------------------------------------------- def readConfig(self): """reads the config file""" - - self.config = self.parseConfig(join(pypath,"module", "config", "default.conf")) + + self.config = self.parseConfig(join(pypath, "module", "config", "default.conf")) self.plugin = self.parseConfig("plugin.conf") - + try: homeconf = self.parseConfig("pyload.conf") if homeconf["remote"].has_key("username"): if homeconf["remote"].has_key("password"): - self.oldRemoteData = {"username": homeconf["remote"]["username"]["value"], "password": homeconf["remote"]["username"]["value"]} + self.oldRemoteData = {"username": homeconf["remote"]["username"]["value"], + "password": homeconf["remote"]["username"]["value"]} del homeconf["remote"]["password"] del homeconf["remote"]["username"] self.updateValues(homeconf, self.config) - + except Exception, e: print "Config Warning" print_exc() - + #---------------------------------------------------------------------- def parseConfig(self, config): """parses a given configfile""" - + f = open(config) - + config = f.read() config = config.splitlines()[1:] - + conf = {} - - section, option, value, typ, desc = "","","","","" - + + section, option, value, typ, desc = "", "", "", "", "" + listmode = False - - for line in config: + for line in config: comment = line.rfind("#") - if line.find(":", comment) < 0 and line.find("=", comment) < 0 and comment > 0 and line[comment-1].isspace(): + if line.find(":", comment) < 0 and line.find("=", comment) < 0 and comment > 0 and line[ + comment - 1].isspace(): line = line.rpartition("#") # removes comments if line[1]: line = line[0] else: line = line[2] - + line = line.strip() - + try: - if line == "": continue elif line.endswith(":"): section, none, desc = line[:-1].partition('-') section = section.strip() desc = desc.replace('"', "").strip() - conf[section] = { "desc" : desc } + conf[section] = {"desc": desc} else: if listmode: - if line.endswith("]"): listmode = False - line = line.replace("]","") - + line = line.replace("]", "") + value += [self.cast(typ, x.strip()) for x in line.split(",") if x] - + if not listmode: - conf[section][option] = { "desc" : desc, - "type" : typ, - "value" : value} - - + conf[section][option] = {"desc": desc, + "type": typ, + "value": value} + + else: content, none, value = line.partition("=") - + content, none, desc = content.partition(":") - + desc = desc.replace('"', "").strip() - + typ, none, option = content.strip().rpartition(" ") value = value.strip() - + if value.startswith("["): - if value.endswith("]"): + if value.endswith("]"): listmode = False value = value[:-1] else: listmode = True - + value = [self.cast(typ, x.strip()) for x in value[1:].split(",") if x] else: value = self.cast(typ, value) - + if not listmode: - conf[section][option] = { "desc" : desc, - "type" : typ, - "value" : value} - + conf[section][option] = {"desc": desc, + "type": typ, + "value": value} + except Exception, e: print "Config Warning" print_exc() - f.close() return conf - - - + + #---------------------------------------------------------------------- def updateValues(self, config, dest): """sets the config values from a parsed config file to values in destination""" - + for section in config.iterkeys(): - if dest.has_key(section): - for option in config[section].iterkeys(): - - if option == "desc": continue - + if option in ("desc", "outline"): continue + if dest[section].has_key(option): dest[section][option]["value"] = config[section][option]["value"] - - #else: - # dest[section][option] = config[section][option] - - - #else: - # dest[section] = config[section] + + #else: + # dest[section][option] = config[section][option] + + + #else: + # dest[section] = config[section] #---------------------------------------------------------------------- def saveConfig(self, config, filename): @@ -225,80 +219,79 @@ class ConfigParser: f.write("version: %i \n" % CONF_VERSION) for section in config.iterkeys(): f.write('\n%s - "%s":\n' % (section, config[section]["desc"])) - + for option, data in config[section].iteritems(): - - if option == "desc": continue - + if option in ("desc", "outline"): continue + if isinstance(data["value"], list): value = "[ \n" for x in data["value"]: value += "\t\t" + str(x) + ",\n" value += "\t\t]\n" else: - if type(data["value"]) in (str,unicode): + if type(data["value"]) in (str, unicode): value = data["value"] + "\n" else: value = str(data["value"]) + "\n" try: - f.write('\t%s %s : "%s" = %s' % (data["type"], option, data["desc"], value) ) + f.write('\t%s %s : "%s" = %s' % (data["type"], option, data["desc"], value)) except UnicodeEncodeError: - f.write('\t%s %s : "%s" = %s' % (data["type"], option, data["desc"], value.encode("utf8")) ) + f.write('\t%s %s : "%s" = %s' % (data["type"], option, data["desc"], value.encode("utf8"))) def cast(self, typ, value): """cast value to given format""" if type(value) not in (str, unicode): return value - + elif typ == "int": return int(value) elif typ == "bool": - return True if value.lower() in ("1","true", "on", "an","yes") else False + return True if value.lower() in ("1", "true", "on", "an", "yes") else False elif typ == "time": if not value: value = "0:00" - if not ":" in value: value+=":00" + if not ":" in value: value += ":00" return value - elif typ in ("str","file","folder"): + elif typ in ("str", "file", "folder"): try: return value.encode("utf8") except: return value else: return value - + #---------------------------------------------------------------------- def save(self): """saves the configs to disk""" - + self.saveConfig(self.config, "pyload.conf") self.saveConfig(self.plugin, "plugin.conf") - + #---------------------------------------------------------------------- def __getitem__(self, section): """provides dictonary like access: c['section']['option']""" return Section(self, section) - + #---------------------------------------------------------------------- def get(self, section, option): """get value""" val = self.config[section][option]["value"] try: - if type(val) in (str,unicode): + if type(val) in (str, unicode): return val.decode("utf8") else: return val except: return val - + #---------------------------------------------------------------------- def set(self, section, option, value): """set value""" value = self.cast(self.config[section][option]["type"], value) - + self.config[section][option]["value"] = value self.save() - + #---------------------------------------------------------------------- def getPlugin(self, plugin, option): """gets a value for a plugin""" @@ -310,13 +303,13 @@ class ConfigParser: return val except: return val - + #---------------------------------------------------------------------- def setPlugin(self, plugin, option, value): """sets a value for a plugin""" value = self.cast(self.plugin[plugin][option]["type"], value) - + self.plugin[plugin][option]["value"] = value self.save() @@ -325,23 +318,25 @@ class ConfigParser: return self.config[section][option] #---------------------------------------------------------------------- - def addPluginConfig(self, config): - """adds config option with tuple (plugin, name, type, desc, default)""" - - if not self.plugin.has_key(config[0]): - self.plugin[config[0]] = { "desc" : config[0], - config[1] : { - "desc" : config[3], - "type" : config[2], - "value" : self.cast(config[2], config[4]) - } } + def addPluginConfig(self, name, config, outline=""): + """adds config options with tuples (name, type, desc, default)""" + if not self.plugin.has_key(name): + conf = {"desc": name, + "outline": outline} + self.plugin[name] = conf else: - if not self.plugin[config[0]].has_key(config[1]): - self.plugin[config[0]][config[1]] = { - "desc" : config[3], - "type" : config[2], - "value" : self.cast(config[2], config[4]) - } + conf = self.plugin[name] + conf["outline"] = outline + + for item in config: + if conf.has_key(item[0]): + conf[item[0]]["type"] = item[1] + else: + conf[item[0]] = { + "desc": item[2], + "type": item[1], + "value": self.cast(config[1], config[3]) + } def deleteOldPlugins(self): """ remove old plugins from config """ @@ -359,32 +354,31 @@ class 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) - - + if __name__ == "__main__": pypath = "" from time import time - + a = time() - + c = ConfigParser() - + b = time() - - print "sec", b-a - + + print "sec", b - a + print c.config - + c.saveConfig(c.config, "user.conf") diff --git a/module/plugins/PluginManager.py b/module/plugins/PluginManager.py index f583f91de..17405ce8b 100644 --- a/module/plugins/PluginManager.py +++ b/module/plugins/PluginManager.py @@ -73,6 +73,7 @@ class PluginManager(): self.rePattern = re.compile(r'__pattern__.*=.*r("|\')([^"\']+)') self.reVersion = re.compile(r'__version__.*=.*("|\')([0-9.]+)') self.reConfig = re.compile(r'__config__.*=.*\[([^\]]+)', re.MULTILINE) + self.reDesc = re.compile(r'__description__.?=.?("|"""|\')([^"\']+)') self.crypterPlugins = self.parse(_("Crypter"), "crypter", pattern=True) self.containerPlugins = self.parse(_("Container"), "container", pattern=True) @@ -167,6 +168,12 @@ class PluginManager(): if config: config = literal_eval(config[0].strip().replace("\n", "").replace("\r", "")) + desc = self.reDesc.findall(content) + if desc: + desc = desc[0][1] + else: + desc = "" + if type(config[0]) == tuple: config = [list(x) for x in config] else: @@ -175,8 +182,7 @@ class PluginManager(): if folder == "hooks": config.append(["load", "bool", "Load on startup", True if name not in NO_AUTOLOAD else False]) - for item in config: - self.core.config.addPluginConfig([name] + item) + self.core.config.addPluginConfig(name, config, desc) if not home: temp = self.parse(typ, folder, create, pattern, plugins) diff --git a/module/remote/thriftbackend/pyload.thrift b/module/remote/thriftbackend/pyload.thrift index 32fe69d13..eff697d05 100644 --- a/module/remote/thriftbackend/pyload.thrift +++ b/module/remote/thriftbackend/pyload.thrift @@ -77,7 +77,8 @@ struct ConfigItem { struct ConfigSection { 1: string name, 2: string description, - 3: list<ConfigItem> items + 3: list<ConfigItem> items, + 4: optional string outline } struct FileData { diff --git a/module/remote/thriftbackend/thriftgen/pyload/ttypes.py b/module/remote/thriftbackend/thriftgen/pyload/ttypes.py index da8a2477e..fcff55ed8 100644 --- a/module/remote/thriftbackend/thriftgen/pyload/ttypes.py +++ b/module/remote/thriftbackend/thriftgen/pyload/ttypes.py @@ -252,12 +252,14 @@ class ConfigSection(TBase): - name - description - items + - outline """ __slots__ = [ 'name', 'description', 'items', + 'outline', ] thrift_spec = ( @@ -265,12 +267,14 @@ class ConfigSection(TBase): (1, TType.STRING, 'name', None, None, ), # 1 (2, TType.STRING, 'description', None, None, ), # 2 (3, TType.LIST, 'items', (TType.STRUCT,(ConfigItem, ConfigItem.thrift_spec)), None, ), # 3 + (4, TType.STRING, 'outline', None, None, ), # 4 ) - def __init__(self, name=None, description=None, items=None,): + def __init__(self, name=None, description=None, items=None, outline=None,): self.name = name self.description = description self.items = items + self.outline = outline class FileData(TBase): diff --git a/module/web/json_app.py b/module/web/json_app.py index bc95b5ffd..91c33c622 100644 --- a/module/web/json_app.py +++ b/module/web/json_app.py @@ -356,15 +356,17 @@ def restart_failed(): def load_config(category, section): conf = None if category == "general": - conf = PYLOAD.getConfig() + conf = PYLOAD.getConfigDict() elif category == "plugin": - conf = PYLOAD.getPluginConfig() + conf = PYLOAD.getPluginConfigDict() - for option in conf[section].items: - if ";" in option.type: - option.type = option.type.split(";") + for key, option in conf[section].iteritems(): + if key in ("desc","outline"): continue - option.value = decode(option.value) + if ";" in option["type"]: + option["list"] = option["type"].split(";") + + option["value"] = decode(option["value"]) return render_to_response("settings_item.html", {"skey": section, "section": conf[section]}) diff --git a/module/web/templates/default/settings_item.html b/module/web/templates/default/settings_item.html index 92223557d..813383343 100644 --- a/module/web/templates/default/settings_item.html +++ b/module/web/templates/default/settings_item.html @@ -1,45 +1,48 @@ <table class="settable"> - {% set skey = section.name %} - {% for option in section.items %} - {% set okey = option.name %} - <tr> - <td><label for="{{skey}}|{{okey}}" - style="color:#424242;">{{ option.description }}:</label></td> - <td> - {% if option.type == "bool" %} - <select id="{{skey}}|{{okey}}" name="{{skey}}|{{okey}}"> - <option {% if option.value %} selected="selected" - {% endif %}value="True">{{ _("on") }}</option> - <option {% if not option.value %} selected="selected" - {% endif %}value="False">{{ _("off") }}</option> - </select> - {% elif option.type|type == "<type 'list'>" %} - <select id="{{skey}}|{{okey}}" name="{{skey}}|{{okey}}"> - {% for entry in option.type %} - <option {% if option.value == entry %} - selected="selected" {% endif %}>{{ entry }}</option> - {% endfor %} - </select> - {% elif option.type == "folder" %} - <input name="{{skey}}|{{okey}}" type="text" - id="{{skey}}|{{okey}}" value="{{option.value}}"/> - <input name="browsebutton" type="button" - onclick="ifield = document.getElementById('{{skey}}|{{okey}}'); pathchooser = window.open('{% if option.value %}{{ "/pathchooser/" + option.value|quotepath }}{% else %}{{ pathroot }}{% endif %}', 'pathchooser', 'scrollbars=yes,toolbar=no,menubar=no,statusbar=no,width=650,height=300'); pathchooser.ifield = ifield; window.ifield = ifield;" - value="{{_("Browse")}}"/> - {% elif option.type == "file" %} - <input name="{{skey}}|{{okey}}" type="text" - id="{{skey}}|{{okey}}" value="{{option.value}}"/> - <input name="browsebutton" type="button" - onclick="ifield = document.getElementById('{{skey}}|{{okey}}'); filechooser = window.open('{% if option.value %}{{ "/filechooser/" + option.value|quotepath }}{% else %}{{ fileroot }}{% endif %}', 'filechooser', 'scrollbars=yes,toolbar=no,menubar=no,statusbar=no,width=650,height=300'); filechooser.ifield = ifield; window.ifield = ifield;" - value="{{_("Browse")}}"/> - {% elif option.type == "password" %} - <input id="{{skey}}|{{okey}}" name="{{skey}}|{{okey}}" - type="password" value="{{option.value}}"/> - {% else %} - <input id="{{skey}}|{{okey}}" name="{{skey}}|{{okey}}" - type="text" value="{{option.value}}"/> - {% endif %} - </td> - </tr> + {% if section.outline %} + <tr><th colspan="2">{{ section.outline }}</th></tr> + {% endif %} + {% for okey, option in section.iteritems() %} + {% if okey not in ("desc","outline") %} + <tr> + <td><label for="{{skey}}|{{okey}}" + style="color:#424242;">{{ option.desc }}:</label></td> + <td> + {% if option.type == "bool" %} + <select id="{{skey}}|{{okey}}" name="{{skey}}|{{okey}}"> + <option {% if option.value %} selected="selected" + {% endif %}value="True">{{ _("on") }}</option> + <option {% if not option.value %} selected="selected" + {% endif %}value="False">{{ _("off") }}</option> + </select> + {% elif ";" in option.type %} + <select id="{{skey}}|{{okey}}" name="{{skey}}|{{okey}}"> + {% for entry in option.list %} + <option {% if option.value == entry %} + selected="selected" {% endif %}>{{ entry }}</option> + {% endfor %} + </select> + {% elif option.type == "folder" %} + <input name="{{skey}}|{{okey}}" type="text" + id="{{skey}}|{{okey}}" value="{{option.value}}"/> + <input name="browsebutton" type="button" + onclick="ifield = document.getElementById('{{skey}}|{{okey}}'); pathchooser = window.open('{% if option.value %}{{ "/pathchooser/" + option.value|quotepath }}{% else %}{{ pathroot }}{% endif %}', 'pathchooser', 'scrollbars=yes,toolbar=no,menubar=no,statusbar=no,width=650,height=300'); pathchooser.ifield = ifield; window.ifield = ifield;" + value="{{_("Browse")}}"/> + {% elif option.type == "file" %} + <input name="{{skey}}|{{okey}}" type="text" + id="{{skey}}|{{okey}}" value="{{option.value}}"/> + <input name="browsebutton" type="button" + onclick="ifield = document.getElementById('{{skey}}|{{okey}}'); filechooser = window.open('{% if option.value %}{{ "/filechooser/" + option.value|quotepath }}{% else %}{{ fileroot }}{% endif %}', 'filechooser', 'scrollbars=yes,toolbar=no,menubar=no,statusbar=no,width=650,height=300'); filechooser.ifield = ifield; window.ifield = ifield;" + value="{{_("Browse")}}"/> + {% elif option.type == "password" %} + <input id="{{skey}}|{{okey}}" name="{{skey}}|{{okey}}" + type="password" value="{{option.value}}"/> + {% else %} + <input id="{{skey}}|{{okey}}" name="{{skey}}|{{okey}}" + type="text" value="{{option.value}}"/> + {% endif %} + </td> + </tr> + {% endif %} {% endfor %} </table>
\ No newline at end of file |