# -*- coding: utf-8 -*- from __future__ import with_statement from time import sleep from os.path import exists from os.path import join from shutil import copy from traceback import print_exc IGNORE = ("FreakshareNet", "SpeedManager") #ignore this plugin configs CONF_VERSION = 1 class ConfigParser: """ holds and manage the configuration current dict layout: { section : { option : { value: type: desc: } desc: } """ #---------------------------------------------------------------------- def __init__(self): """Constructor""" self.config = {} # the config values self.plugin = {} # the config for plugins self.username = "" self.password = "" #stored outside and may not modified self.checkVersion() self.readConfig() self.deleteOldPlugins() #---------------------------------------------------------------------- def checkVersion(self, n=0): """determines if config need to be copied""" try: if not exists("pyload.conf"): copy(join(pypath,"module", "config", "default.conf"), "pyload.conf") if not exists("plugin.conf"): f = open("plugin.conf", "wb") f.write("version: "+str(CONF_VERSION)) f.close() f = open("pyload.conf", "rb") v = f.readline() f.close() v = v[v.find(":")+1:].strip() if not v or int(v) < CONF_VERSION: copy(join(pypath,"module", "config", "default.conf"), "pyload.conf") print "Old version of config was replaced" f = open("plugin.conf", "rb") v = f.readline() f.close() v = v[v.find(":")+1:].strip() if not v or int(v) < CONF_VERSION: f = open("plugin.conf", "wb") f.write("version: "+str(CONF_VERSION)) f.close() print "Old version of plugin-config replaced" except: if n < 3: sleep(0.3) self.checkVersion(n+1) else: raise #---------------------------------------------------------------------- def readConfig(self): """reads the config file""" self.config = self.parseConfig(join(pypath,"module", "config", "default.conf")) self.plugin = self.parseConfig("plugin.conf") try: homeconf = self.parseConfig("pyload.conf") self.updateValues(homeconf, self.config) except Exception, e: print "Config Warning" print_exc() self.username = self.config["remote"]["username"]["value"] del self.config["remote"]["username"] self.password = self.config["remote"]["password"]["value"] del self.config["remote"]["password"] #---------------------------------------------------------------------- def parseConfig(self, config): """parses a given configfile""" f = open(config) config = f.read() config = config.splitlines()[1:] conf = {} section, option, value, typ, desc = "","","","","" listmode = False for line in config: comment = line.rfind("#") if line.find(":", comment) < 0 and line.find("=", comment) < 0 and comment > 0: line = line.rpartition("#") # removes comments if line[1]: line = line[0] else: line = line[2] line = line.strip() try: if line == "": continue elif line.endswith(":"): section, none, desc = line[:-1].partition('-') section = section.strip() desc = desc.replace('"', "").strip() conf[section] = { "desc" : desc } else: if listmode: if line.endswith("]"): listmode = False line = line.replace("]","") value += [self.cast(typ, x.strip()) for x in line.split(",") if x] if not listmode: conf[section][option] = { "desc" : desc, "type" : typ, "value" : value} else: content, none, value = line.partition("=") content, none, desc = content.partition(":") desc = desc.replace('"', "").strip() typ, none, option = content.strip().rpartition(" ") value = value.strip() if value.startswith("["): if value.endswith("]"): listmode = False value = value[:-1] else: listmode = True value = [self.cast(typ, x.strip()) for x in value[1:].split(",") if x] else: value = self.cast(typ, value) if not listmode: conf[section][option] = { "desc" : desc, "type" : typ, "value" : value} except Exception, e: print "Config Warning" print_exc() f.close() return conf #---------------------------------------------------------------------- def updateValues(self, config, dest): """sets the config values from a parsed config file to values in destination""" for section in config.iterkeys(): if dest.has_key(section): for option in config[section].iterkeys(): if option == "desc": continue if dest[section].has_key(option): dest[section][option]["value"] = config[section][option]["value"] #else: # dest[section][option] = config[section][option] #else: # dest[section] = config[section] #---------------------------------------------------------------------- def saveConfig(self, config, filename): """saves config to filename""" with open(filename, "wb") as f: f.write("version: %i \n" % CONF_VERSION) for section in config.iterkeys(): f.write('\n%s - "%s":\n' % (section, config[section]["desc"])) for option, data in config[section].iteritems(): if option == "desc": continue if isinstance(data["value"], list): value = "[ \n" for x in data["value"]: value += "\t\t" + str(x) + ",\n" value += "\t\t]\n" else: if type(data["value"]) in (str,unicode): value = data["value"] + "\n" else: value = str(data["value"]) + "\n" f.write('\t%s %s : "%s" = %s' % (data["type"], option, data["desc"], value) ) #---------------------------------------------------------------------- def cast(self, typ, value): """cast value to given format""" if type(value) not in (str, unicode): return value elif typ == "int": return int(value) elif typ == "bool": return True if value.lower() in ("1","true", "on", "an","yes") else False elif typ == "time": if not value: value = "0:00" if not ":" in value: value+=":00" return value elif typ in ("str","file","folder"): try: return value.encode("utf8") except: return value else: return value #---------------------------------------------------------------------- def save(self): """saves the configs to disk""" self.config["remote"]["username"] = { "desc" : "Username", "type": "str", "value": self.username } self.config["remote"]["password"] = { "desc" : "Password", "type": "str", "value": self.password } self.saveConfig(self.config, "pyload.conf") del self.config["remote"]["username"] del self.config["remote"]["password"] self.saveConfig(self.plugin, "plugin.conf") #---------------------------------------------------------------------- def __getitem__(self, section): """provides dictonary like access: c['section']['option']""" return Section(self, section) #---------------------------------------------------------------------- def get(self, section, option): """get value""" val = self.config[section][option]["value"] try: if type(val) in (str,unicode): return val.decode("utf8") else: return val except: return val #---------------------------------------------------------------------- def set(self, section, option, value): """set value""" value = self.cast(self.config[section][option]["type"], value) self.config[section][option]["value"] = value self.save() #---------------------------------------------------------------------- def getPlugin(self, plugin, option): """gets a value for a plugin""" val = self.plugin[plugin][option]["value"] try: if type(val) in (str, unicode): return val.decode("utf8") else: return val except: return val #---------------------------------------------------------------------- def setPlugin(self, plugin, option, value): """sets a value for a plugin""" value = self.cast(self.plugin[plugin][option]["type"], value) self.plugin[plugin][option]["value"] = value self.save() def getMetaData(self, section, option): """ get all config data for an option """ return self.config[section][option] #---------------------------------------------------------------------- def addPluginConfig(self, config): """adds config option with tuple (plugin, name, type, desc, default)""" if not self.plugin.has_key(config[0]): self.plugin[config[0]] = { "desc" : config[0], config[1] : { "desc" : config[3], "type" : config[2], "value" : self.cast(config[2], config[4]) } } else: if not self.plugin[config[0]].has_key(config[1]): self.plugin[config[0]][config[1]] = { "desc" : config[3], "type" : config[2], "value" : self.cast(config[2], config[4]) } def deleteOldPlugins(self): """ remove old plugins from config """ for name in IGNORE: if self.plugin.has_key(name): del self.plugin[name] ######################################################################## 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")