diff options
author | RaNaN <Mast3rRaNaN@hotmail.de> | 2011-12-19 23:10:49 +0100 |
---|---|---|
committer | RaNaN <Mast3rRaNaN@hotmail.de> | 2011-12-19 23:10:49 +0100 |
commit | 6eae782f13953dd0ba2bbe1b582cf33fd4d7d90a (patch) | |
tree | a7e80bc89b1a523854e1f3e3d9ec945023193212 /module/config/ConfigParser.py | |
parent | pluginmanager cleanup (diff) | |
download | pyload-6eae782f13953dd0ba2bbe1b582cf33fd4d7d90a.tar.xz |
configparser v2, warning CONFIG will be DELETED.
Diffstat (limited to 'module/config/ConfigParser.py')
-rw-r--r-- | module/config/ConfigParser.py | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/module/config/ConfigParser.py b/module/config/ConfigParser.py new file mode 100644 index 000000000..01f4268cb --- /dev/null +++ b/module/config/ConfigParser.py @@ -0,0 +1,251 @@ +# -*- coding: utf-8 -*- + +from __future__ import with_statement +from time import sleep +from os.path import exists +from gettext import gettext + +from module.utils import chmod, decode + +CONF_VERSION = 2 + +from converter import from_string +from new_collections import namedtuple, OrderedDict +from default import make_config + +SectionTuple = namedtuple("SectionTuple", "name description long_desc config") +ConfigData = namedtuple("ConfigData", "name type description default") + +class ConfigParser: + """ + Holds and manage the configuration + meta data. + Actually only the values are read from disk, all meta data have to be provided first via addConfigSection. + """ + + CONFIG = "pyload.conf" + PLUGIN = "plugin.conf" + + def __init__(self): + """Constructor""" + + # core config sections from pyload + self.baseSections = [] + + # Meta data information + self.config = OrderedDict() + # The actual config values + self.values = {} + + self.changeCB = None # callback when config value was changed + + self.checkVersion() + + self.loadDefault() + self.parseValues(self.CONFIG) + + def loadDefault(self): + make_config(self) + + def checkVersion(self): + """Determines if config need to be deleted""" + e = None + # workaround conflict, with GUI (which also access the config) so try read in 3 times + for i in range(0, 3): + try: + for conf in (self.CONFIG, self.PLUGIN): + if exists(conf): + f = open(conf, "rb") + v = f.readline() + f.close() + v = v[v.find(":") + 1:].strip() + + if not v or int(v) < CONF_VERSION: + f = open(conf, "wb") + f.write("version: " + str(CONF_VERSION)) + f.close() + print "Old version of %s deleted" % conf + + except Exception, ex: + e = ex + sleep(0.3) + if e: raise e + + + 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 "Unrecognzied 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) + else: + print "Unrecognized option", section, name + + + def save(self): + """saves config to filename""" + + # seperate pyload and plugin conf + configs = [] + for c in (self.CONFIG, self.PLUGIN): + f = open(c, "wb") + configs.append(f) + chmod(c) + f.write("version: %i\n\n" % CONF_VERSION) + + + # write on 2 files + for section, data in self.config.iteritems(): + f = configs[0] if section in self.baseSections else configs[1] + + 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() for f in configs] + + def __getitem__(self, section): + """provides dictonary like access: c['section']['option']""" + return Section(self, section) + + def get(self, section, option): + """get value""" + if option in self.values[section]: + return self.values[section][option] + else: + return self.config[section].config[option].default + + def set(self, section, option, value): + """set value""" + + data = self.config[section].config[option] + value = from_string(value, data.type) + + # only save when different to defaul values + if value != data.default or (option in self.values[section] and value != self.values[section][option]): + self.values[section][option] = value + if self.changeCB: self.changeCB(section, option, value) + self.save() + + def getPlugin(self, *args): + """gets a value for a plugin""" + ret = self.get(*args) + print "Deprecated method getPlugin%s -> %s" % (str(args), ret) + return ret + + def setPlugin(self, *args): + """sets a value for a plugin""" + print "Deprecated method setPlugin%s" % str(args) + self.set(*args) + + def getMetaData(self, section, option): + """ get all config data for an option """ + return self.config[section].config[option] + + def getBaseSections(self): + for section, data in self.config.iteritems(): + if section in self.baseSections: + yield section, data + return + + def getPluginSections(self): + for section, data in self.config.iteritems(): + if section not in self.baseSections: + yield section, data + return + + def addConfigSection(self, section, name, desc, long_desc, config, base=False): + """Adds a section to the config. `config` is a list of config tuples as used in plugin api definied as: + Either (name, type, verbose_name, default_value) or + (name, type, verbose_name, short_description, default_value) + The ordner of the config elements are preserved with OrdererDict + """ + d = OrderedDict() + + for entry in config: + if len(entry) == 5: + conf_name, type, conf_desc, conf_verbose, default = entry + else: # config options without tooltip / description + conf_name, type, conf_desc, default = entry + conf_verbose = "" + + d[conf_name] = ConfigData(gettext(conf_desc), type, gettext(conf_verbose), from_string(default, type)) + + if base: + self.baseSections.append(section) + else: + if section in self.config: + print "Section already exists", section + return + + data = SectionTuple(gettext(name), gettext(desc), gettext(long_desc), d) + self.config[section] = data + + if section not in self.values: + self.values[section] = {} + +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) + + +if __name__ == "__main__": + pypath = "" + + from time import time + + a = time() + + c = ConfigParser() + + b = time() + + print "sec", b - a + + print c.config + + c.saveConfig(c.config, "user.conf") |