global_config.py revision 0afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181
1ed4d6ddc79993492b22aeeb36574b3cb7c8bad44mbligh"""A singleton class for accessing global config values
2ed4d6ddc79993492b22aeeb36574b3cb7c8bad44mbligh
3ed4d6ddc79993492b22aeeb36574b3cb7c8bad44mblighprovides access to global configuration file
4ed4d6ddc79993492b22aeeb36574b3cb7c8bad44mbligh"""
5ed4d6ddc79993492b22aeeb36574b3cb7c8bad44mbligh
6ed4d6ddc79993492b22aeeb36574b3cb7c8bad44mbligh__author__ = 'raphtee@google.com (Travis Miller)'
7ed4d6ddc79993492b22aeeb36574b3cb7c8bad44mbligh
8ed4d6ddc79993492b22aeeb36574b3cb7c8bad44mblighimport os
98375088a4ed43357a7abe1b6cab83c0e5ce79cfamblighimport sys
10ed4d6ddc79993492b22aeeb36574b3cb7c8bad44mblighimport ConfigParser
11ed4d6ddc79993492b22aeeb36574b3cb7c8bad44mblighimport error
12ed4d6ddc79993492b22aeeb36574b3cb7c8bad44mbligh
13f97513351c77d4d47bbe30063b7faca25d530667mblighdirname = os.path.dirname(sys.modules[__name__].__file__)
140afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanskiDEFAULT_CONFIG_FILE = os.path.abspath(os.path.join(dirname,
150afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski                                                "../../global_config.ini"))
160afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanskiDEFAULT_SHADOW_FILE = os.path.abspath(os.path.join(dirname,
170afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski                                                "../../shadow_config.ini"))
180afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski
19104e9ce7a74041fd673ceac5c8b0bc67c74edcd5mbligh
20ed4d6ddc79993492b22aeeb36574b3cb7c8bad44mblighclass ConfigError(error.AutotestError):
210afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    pass
22ed4d6ddc79993492b22aeeb36574b3cb7c8bad44mbligh
23ed4d6ddc79993492b22aeeb36574b3cb7c8bad44mbligh
24104e9ce7a74041fd673ceac5c8b0bc67c74edcd5mblighclass ConfigValueError(ConfigError):
250afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    pass
26104e9ce7a74041fd673ceac5c8b0bc67c74edcd5mbligh
27104e9ce7a74041fd673ceac5c8b0bc67c74edcd5mbligh
28ed4d6ddc79993492b22aeeb36574b3cb7c8bad44mblighclass global_config(object):
290afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    config = None
300afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    config_file = DEFAULT_CONFIG_FILE
310afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    shadow_file = DEFAULT_SHADOW_FILE
320afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski
330afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski
340afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    def set_config_files(self, config_file=DEFAULT_CONFIG_FILE,
350afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski                            shadow_file=DEFAULT_SHADOW_FILE):
360afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        self.config_file = config_file
370afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        self.shadow_file = shadow_file
380afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        self.config = None
390afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski
400afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski
410afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    def get_config_value(self, section, key, type=str, default=None):
420afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        if self.config == None:
430afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski            self.parse_config_file()
440afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski
450afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        try:
460afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski            val = self.config.get(section, key)
470afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        except:
480afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski            if default == None:
490afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski                msg = ("Value '%s' not found in section '%s'" %
500afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski                      (key, section))
510afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski                raise ConfigError(msg)
520afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski            else:
530afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski                return default
540afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski
550afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        return self.convert_value(key, section, val, type, default)
560afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski
570afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski
580afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    def merge_configs(self, shadow_config):
590afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        # overwrite whats in config with whats in shadow_config
600afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        sections = shadow_config.sections()
610afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        for section in sections:
620afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski            # add the section if need be
630afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski            if not self.config.has_section(section):
640afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski                self.config.add_section(section)
650afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski            # now run through all options and set them
660afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski            options = shadow_config.options(section)
670afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski            for option in options:
680afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski                val = shadow_config.get(section, option)
690afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski                self.config.set(section, option, val)
700afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski
710afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski
720afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    def parse_config_file(self):
730afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        if not os.path.exists(self.config_file):
740afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski            raise ConfigError('%s not found' % (self.config_file))
750afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        self.config = ConfigParser.ConfigParser()
760afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        self.config.read(self.config_file)
770afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski
780afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        # now also read the shadow file if there is one
790afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        # this will overwrite anything that is found in the
800afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        # other config
810afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        if os.path.exists(self.shadow_file):
820afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski            shadow_config = ConfigParser.ConfigParser()
830afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski            shadow_config.read(self.shadow_file)
840afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski            # now we merge shadow into global
850afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski            self.merge_configs(shadow_config)
860afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski
870afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski
880afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    # the values that are pulled from ini
890afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    # are strings.  But we should attempt to
900afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    # convert them to other types if needed.
910afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski    def convert_value(self, key, section, value, type, default):
920afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        # strip off leading and trailing white space
930afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        sval = value.strip()
940afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski
950afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        # if length of string is zero then return None
960afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        if len(sval) == 0:
970afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski            if type == str:
980afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski                return ""
990afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski            elif type == bool:
1000afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski                return False
1010afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski            elif type == int:
1020afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski                return 0
1030afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski            elif type == float:
1040afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski                return 0.0
1050afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski            else:
1060afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski                return None
1070afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski
1080afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        if type == bool:
1090afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski            if sval.lower() == "false":
1100afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski                return False
1110afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski            else:
1120afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski                return True
1130afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski
1140afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        try:
1150afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski            conv_val = type(sval)
1160afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski            return conv_val
1170afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski        except:
1180afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski            msg = ("Could not covert %s in section %s" %
1190afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski                    (key, section))
1200afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski            raise ConfigValueError(msg)
1210afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski
1220afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski
1230afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski# insure the class is a singleton.  Now the symbol global_config
124ed4d6ddc79993492b22aeeb36574b3cb7c8bad44mbligh# will point to the one and only one instace of the class
125ed4d6ddc79993492b22aeeb36574b3cb7c8bad44mblighglobal_config = global_config()
126