summaryrefslogtreecommitdiffstats
path: root/pyload/config/ConfigParser.py
diff options
context:
space:
mode:
Diffstat (limited to 'pyload/config/ConfigParser.py')
-rw-r--r--pyload/config/ConfigParser.py211
1 files changed, 211 insertions, 0 deletions
diff --git a/pyload/config/ConfigParser.py b/pyload/config/ConfigParser.py
new file mode 100644
index 000000000..bda3f7bd4
--- /dev/null
+++ b/pyload/config/ConfigParser.py
@@ -0,0 +1,211 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import with_statement
+from time import sleep
+from os.path import exists
+from gettext import gettext
+from new_collections import namedtuple, OrderedDict
+
+
+from pyload.Api import Input, InputType
+from pyload.utils.fs import chmod
+
+from default import make_config
+from convert import to_input, from_string
+
+CONF_VERSION = 2
+SectionTuple = namedtuple("SectionTuple", "label description explanation config")
+ConfigData = namedtuple("ConfigData", "label description input")
+
+class ConfigParser:
+ """
+ Holds and manages the configuration + meta data for config read from file.
+ """
+
+ CONFIG = "pyload.conf"
+
+ def __init__(self, config=None):
+
+ if config: self.CONFIG = config
+
+ # Meta data information
+ self.config = OrderedDict()
+ # The actual config values
+ self.values = {}
+
+ self.checkVersion()
+
+ self.loadDefault()
+ self.parseValues(self.CONFIG)
+
+ def loadDefault(self):
+ make_config(self)
+
+ def checkVersion(self):
+ """Determines if config needs to be deleted"""
+ if exists(self.CONFIG):
+ f = open(self.CONFIG, "rb")
+ v = f.readline()
+ f.close()
+ v = v[v.find(":") + 1:].strip()
+
+ if not v or int(v) < CONF_VERSION:
+ f = open(self.CONFIG, "wb")
+ f.write("version: " + str(CONF_VERSION))
+ f.close()
+ print "Old version of %s deleted" % self.CONFIG
+ else:
+ f = open(self.CONFIG, "wb")
+ f.write("version:" + str(CONF_VERSION))
+ f.close()
+
+ def parseValues(self, filename):
+ """read config values from file"""
+ f = open(filename, "rb")
+ config = f.readlines()[1:]
+
+ # save the current section
+ section = ""
+
+ for line in config:
+ line = line.strip()
+
+ # comment line, different variants
+ if not line or line.startswith("#") or line.startswith("//") or line.startswith(";"): continue
+
+ if line.startswith("["):
+ section = line.replace("[", "").replace("]", "")
+
+ if section not in self.config:
+ print "Unrecognized section", section
+ section = ""
+
+ else:
+ name, non, value = line.rpartition("=")
+ name = name.strip()
+ value = value.strip()
+
+ if not section:
+ print "Value without section", name
+ continue
+
+ if name in self.config[section].config:
+ self.set(section, name, value, sync=False)
+ else:
+ print "Unrecognized option", section, name
+
+
+ def save(self):
+ """saves config to filename"""
+
+ configs = []
+ f = open(self.CONFIG, "wb")
+ configs.append(f)
+ chmod(self.CONFIG, 0600)
+ f.write("version: %i\n\n" % CONF_VERSION)
+
+ for section, data in self.config.iteritems():
+ f.write("[%s]\n" % section)
+
+ for option, data in data.config.iteritems():
+ value = self.get(section, option)
+ if type(value) == unicode: value = value.encode("utf8")
+ else: value = str(value)
+
+ f.write('%s = %s\n' % (option, value))
+
+ f.write("\n")
+
+ f.close()
+
+ def __getitem__(self, section):
+ """provides dictionary like access: c['section']['option']"""
+ return Section(self, section)
+
+ def __contains__(self, section):
+ """ checks if parser contains section """
+ return section in self.config
+
+ def get(self, section, option):
+ """get value or default"""
+ try:
+ return self.values[section][option]
+ except KeyError:
+ return self.config[section].config[option].input.default_value
+
+ def set(self, section, option, value, sync=True):
+ """set value"""
+
+ data = self.config[section].config[option]
+ value = from_string(value, data.input.type)
+ old_value = self.get(section, option)
+
+ # only save when different values
+ if value != old_value:
+ if section not in self.values: self.values[section] = {}
+ self.values[section][option] = value
+ if sync:
+ self.save()
+ return True
+
+ return False
+
+ def getMetaData(self, section, option):
+ """ get all config data for an option """
+ return self.config[section].config[option]
+
+ def iterSections(self):
+ """ Yields section, config info, values, for all sections """
+
+ for name, config in self.config.iteritems():
+ yield name, config, self.values[name] if name in self.values else {}
+
+ def getSection(self, section):
+ """ Retrieves single config as tuple (section, values) """
+ return self.config[section], self.values[section] if section in self.values else {}
+
+ def addConfigSection(self, section, label, desc, expl, config):
+ """Adds a section to the config. `config` is a list of config tuples as used in plugin api defined as:
+ The order of the config elements is preserved with OrderedDict
+ """
+ d = OrderedDict()
+
+ for entry in config:
+ if len(entry) != 4:
+ raise ValueError("Config entry must be of length 4")
+
+ # Values can have different roles depending on the two config formats
+ conf_name, type_label, label_desc, default_input = entry
+
+ # name, label, desc, input
+ if isinstance(default_input, Input):
+ input = default_input
+ conf_label = type_label
+ conf_desc = label_desc
+ # name, type, label, default
+ else:
+ input = Input(to_input(type_label))
+ input.default_value = from_string(default_input, input.type)
+ conf_label = label_desc
+ conf_desc = ""
+
+ d[conf_name] = ConfigData(gettext(conf_label), gettext(conf_desc), input)
+
+ data = SectionTuple(gettext(label), gettext(desc), gettext(expl), d)
+ self.config[section] = data
+
+class Section:
+ """provides dictionary like access for configparser"""
+
+ def __init__(self, parser, section):
+ """Constructor"""
+ self.parser = parser
+ self.section = section
+
+ def __getitem__(self, item):
+ """getitem"""
+ return self.parser.get(self.section, item)
+
+ def __setitem__(self, item, value):
+ """setitem"""
+ self.parser.set(self.section, item, value)