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  | 
