diff options
Diffstat (limited to 'pyload/config/ConfigParser.py')
-rw-r--r-- | pyload/config/ConfigParser.py | 211 |
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) |