summaryrefslogtreecommitdiffstats
path: root/module/config/ConfigParser.py
diff options
context:
space:
mode:
authorGravatar RaNaN <Mast3rRaNaN@hotmail.de> 2011-12-19 23:10:49 +0100
committerGravatar RaNaN <Mast3rRaNaN@hotmail.de> 2011-12-19 23:10:49 +0100
commit6eae782f13953dd0ba2bbe1b582cf33fd4d7d90a (patch)
treea7e80bc89b1a523854e1f3e3d9ec945023193212 /module/config/ConfigParser.py
parentpluginmanager cleanup (diff)
downloadpyload-6eae782f13953dd0ba2bbe1b582cf33fd4d7d90a.tar.xz
configparser v2, warning CONFIG will be DELETED.
Diffstat (limited to 'module/config/ConfigParser.py')
-rw-r--r--module/config/ConfigParser.py251
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")