# -*- coding: utf-8 -*- from __future__ import with_statement 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_configdata, from_string CONF_VERSION = 2 SectionTuple = namedtuple("SectionTuple", "label description explanation config") 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 tuple as used in plugin api defined as: The order of the config elements is preserved with OrderedDict """ d = OrderedDict() for entry in config: name, data = to_configdata(entry) d[name] = data 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)