From: Tony Mack Date: Wed, 12 Sep 2012 19:58:53 +0000 (-0400) Subject: rewrite to use ConfigParser X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=7ae8744cb81c32f66d03d92829509b7de742c5ba;p=plcapi.git rewrite to use ConfigParser --- diff --git a/PLC/Config.py b/PLC/Config.py index c1dbe70f..5e16bf23 100644 --- a/PLC/Config.py +++ b/PLC/Config.py @@ -1,94 +1,241 @@ #!/usr/bin/python -# -# PLCAPI configuration store. Supports XML-based configuration file -# format exported by MyPLC. -# -# Mark Huang -# Copyright (C) 2004-2006 The Trustees of Princeton University -# - -import os import sys +import os +import time +import ConfigParser +import tempfile +import codecs +from StringIO import StringIO +from sfa.util.xml import XML -from PLC.Faults import * -from PLC.Debug import profile +default_config = \ +""" +""" -# If we have been checked out into a directory at the same -# level as myplc, where plc_config.py lives. If we are in a -# MyPLC environment, plc_config.py has already been installed -# in site-packages. -myplc = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + \ - os.sep + "myplc" +def isbool(v): + return v.lower() in ("true", "false") + +def str2bool(v): + return v.lower() in ("true", "1") class Config: - """ - Parse the bash/Python/PHP version of the configuration file. Very - fast but no type conversions. - """ + + def __init__(self, config_file='/etc/planetlab/plc_config'): + self._files = [] + self.config_path = os.path.dirname(config_file) + self.config = ConfigParser.ConfigParser() + self.filename = config_file + if not os.path.isfile(self.filename): + self.create(self.filename) + self.load(self.filename) + - def __init__(self, file = "/etc/planetlab/plc_config"): - # Load plc_config - try: - execfile(file, self.__dict__) - except: - # Try myplc directory + def _header(self): + header = """ +DO NOT EDIT. This file was automatically generated at +%s from: + +%s +""" % (time.asctime(), os.linesep.join(self._files)) + + # Get rid of the surrounding newlines + return header.strip().split(os.linesep) + + def create(self, filename): + if not os.path.exists(os.path.dirname(filename)): + os.makedirs(os.path.dirname(filename)) + configfile = open(filename, 'w') + configfile.write(default_config) + configfile.close() + + + def load(self, filename): + if filename: + try: + self.config.read(filename) + except ConfigParser.MissingSectionHeaderError: + if filename.endswith('.xml'): + self.load_xml(filename) + else: + self.load_shell(filename) + self._files.append(filename) + self.set_attributes() + + def load_xml(self, filename): + xml = XML(filename) + categories = xml.xpath('//configuration/variables/category') + for category in categories: + section_name = category.get('id') + if not self.config.has_section(section_name): + self.config.add_section(section_name) + options = category.xpath('./variablelist/variable') + for option in options: + option_name = option.get('id') + value = option.xpath('./value')[0].text + if not value: + value = "" + self.config.set(section_name, option_name, value) + + def load_shell(self, filename): + f = open(filename, 'r') + for line in f: try: - execfile(myplc + os.sep + "plc_config", self.__dict__) + if line.startswith('#'): + continue + parts = line.strip().split("=") + if len(parts) < 2: + continue + option = parts[0] + value = parts[1].replace('"', '').replace("'","") + section, var = self.locate_varname(option, strict=False) + if section and var: + self.set(section, var, value) except: - raise PLCAPIError("Could not find plc_config in " + \ - file + ", " + \ - myplc + os.sep + "plc_config") + pass + f.close() -class XMLConfig: - """ - Parse the XML configuration file directly. Takes longer but is - presumably more accurate. - """ + def locate_varname(self, varname, strict=True): + varname = varname.lower() + sections = self.config.sections() + section_name = "" + var_name = "" + for section in sections: + if varname.startswith(section.lower()) and len(section) > len(section_name): + section_name = section.lower() + var_name = varname.replace(section_name, "")[1:] + if strict and not self.config.has_option(section_name, var_name): + raise ConfigParser.NoOptionError(var_name, section_name) + return (section_name, var_name) - def __init__(self, file = "/etc/planetlab/plc_config.xml"): + def set_attributes(self): + sections = self.config.sections() + for section in sections: + for item in self.config.items(section): + name = "%s_%s" % (section, item[0]) + value = item[1] + if isbool(value): + value = str2bool(value) + elif value.isdigit(): + value = int(value) + setattr(self, name, value) + setattr(self, name.upper(), value) + + + def verify(self, config1, config2, validate_method): + return True + + def validate_type(self, var_type, value): + return True + + @staticmethod + def is_xml(config_file): try: - from plc_config import PLCConfiguration + x = Xml(config_file) + return True except: - sys.path.append(myplc) - from plc_config import PLCConfiguration + return False - # Load plc_config.xml + @staticmethod + def is_ini(config_file): try: - cfg = PLCConfiguration(file) - except: - # Try myplc directory - try: - cfg = PLCConfiguration(myplc + os.sep + "plc_config.xml") - except: - raise PLCAPIError("Could not find plc_config.xml in " + \ - file + ", " + \ - myplc + os.sep + "plc_config.xml") - - for (category, variablelist) in cfg.variables().values(): - for variable in variablelist.values(): - # Try to cast each variable to an appropriate Python - # type. - if variable['type'] == "int": - value = int(variable['value']) - elif variable['type'] == "double": - value = float(variable['value']) - elif variable['type'] == "boolean": - if variable['value'] == "true": - value = True - else: - value = False - else: - value = variable['value'] + c = ConfigParser.ConfigParser() + c.read(config_file) + return True + except ConfigParser.MissingSectionHeaderError: + return False + + + def dump(self, sections = []): + sys.stdout.write(output_python()) + + def output_python(self, encoding = "utf-8"): + buf = codecs.lookup(encoding)[3](StringIO()) + buf.writelines(["# " + line + os.linesep for line in self._header()]) + + for section in self.sections(): + buf.write("[%s]%s" % (section, os.linesep)) + for (name,value) in self.items(section): + buf.write("%s=%s%s" % (name,value,os.linesep)) + buf.write(os.linesep) + return buf.getvalue() + + def output_shell(self, show_comments = True, encoding = "utf-8"): + """ + Return variables as a shell script. + """ + + buf = codecs.lookup(encoding)[3](StringIO()) + buf.writelines(["# " + line + os.linesep for line in self._header()]) + + for section in self.sections(): + for (name,value) in self.items(section): + # bash does not have the concept of NULL + if value: + option = "%s_%s" % (section.upper(), name.upper()) + if isbool(value): + value = str(str2bool(value)) + elif not value.isdigit(): + value = '"%s"' % value + buf.write(option + "=" + value + os.linesep) + return buf.getvalue() + + def output_php(selfi, encoding = "utf-8"): + """ + Return variables as a PHP script. + """ + + buf = codecs.lookup(encoding)[3](StringIO()) + buf.write("" + os.linesep) + + return buf.getvalue() + + def output_xml(self, encoding = "utf-8"): + pass + + def output_variables(self, encoding="utf-8"): + """ + Return list of all variable names. + """ + + buf = codecs.lookup(encoding)[3](StringIO()) + for section in self.sections(): + for (name,value) in self.items(section): + option = "%s_%s" % (section,name) + buf.write(option + os.linesep) + + return buf.getvalue() + pass + + def write(self, filename=None): + if not filename: + filename = self.filename + configfile = open(filename, 'w') + self.config.write(configfile) + + def save(self, filename=None): + self.write(filename) - # Variables are split into categories such as - # "plc_api", "plc_db", etc. Within each category are - # variables such as "host", "port", etc. For backward - # compatibility, refer to variables by their shell - # names. - shell_name = category['id'].upper() + "_" + variable['id'].upper() - setattr(self, shell_name, value) + def __getattr__(self, attr): + return getattr(self.config, attr) if __name__ == '__main__': - import pprint - pprint = pprint.PrettyPrinter() - pprint.pprint(Config().__dict__.items()) + filename = None + if len(sys.argv) > 1: + filename = sys.argv[1] + config = Config(filename) + else: + config = Config() + config.dump() +