buildframework/helium/tools/common/python/lib/configuration.py
changeset 179 d8ac696cc51f
parent 1 be27ed110b50
equal deleted inserted replaced
1:be27ed110b50 179:d8ac696cc51f
    41 
    41 
    42 _logger = logging.getLogger('configuration')
    42 _logger = logging.getLogger('configuration')
    43 logging.basicConfig(level=logging.INFO)
    43 logging.basicConfig(level=logging.INFO)
    44 
    44 
    45 class Configuration(object, UserDict.DictMixin):
    45 class Configuration(object, UserDict.DictMixin):
    46     """ Base Configuration objects. """
    46     """ Base Configuration object. """
    47     
    47     
    48     key_re = re.compile(r'\${(?P<name>[._a-zA-Z0-9]+)}', re.M)
    48     key_re = re.compile(r'\${(?P<name>[._a-zA-Z0-9]+)}', re.M)
    49     
    49     
    50     def __init__(self, data=None):
    50     def __init__(self, data=None):
    51         """ Initialization. """
    51         """ Initialization. """
    52         if data == None:
    52         #super(UserDict.DictMixin, self).__init__(data)
    53             data = {}
       
    54         self.name = None
    53         self.name = None
    55         self.data = data
    54         self.data = {}
       
    55         if data is not None:
       
    56             self.data.update(data)
    56 
    57 
    57     def __contains__(self, key):
    58     def __contains__(self, key):
    58         """ Check if a keys is defined in the dict. """
    59         """ Check if a keys is defined in the dict. """
    59         return self.data.__contains__(key)
    60         return self.data.__contains__(key)
    60     
    61     
    73         del self.data[key]
    74         del self.data[key]
    74 
    75 
    75     def keys(self):
    76     def keys(self):
    76         """ Get the list of item keys. """
    77         """ Get the list of item keys. """
    77         return self.data.keys()
    78         return self.data.keys()
       
    79     
       
    80     def has_key(self, key):
       
    81         """ Check if key exists. """
       
    82         return self.data.has_key(key)
    78 
    83 
    79     def match_name(self, name):
    84     def match_name(self, name):
    80         """ See if the given name matches the name of this configuration. """
    85         """ See if the given name matches the name of this configuration. """
    81         return self.name == name
    86         return self.name == name
    82 
    87 
    86             return self.__getitem__(key)
    91             return self.__getitem__(key)
    87         except KeyError:
    92         except KeyError:
    88             return default_value
    93             return default_value
    89 
    94 
    90     def get_list(self, key, default_value):
    95     def get_list(self, key, default_value):
       
    96         """ Get a value as a list. """
    91         try:
    97         try:
    92             itemlist = self.__getitem__(key)
    98             itemlist = self.__getitem__(key)
    93             if not isinstance(itemlist, types.ListType):
    99             if not isinstance(itemlist, types.ListType):
    94                 itemlist = [itemlist]
   100                 itemlist = [itemlist]
    95             return itemlist
   101             return itemlist
    96         except KeyError:
   102         except KeyError:
    97             return default_value
   103             return default_value
    98         
   104         
    99     def get_int(self, key, default_value):
   105     def get_int(self, key, default_value):
       
   106         """ Get a value as an int. """
   100         try:
   107         try:
   101             value = self.__getitem__(key)
   108             value = self.__getitem__(key)
   102             return int(value)
   109             return int(value)
   103         except KeyError:
   110         except KeyError:
   104             return default_value
   111             return default_value
   105         
   112         
   106     def get_boolean(self, key, default_value):
   113     def get_boolean(self, key, default_value):
       
   114         """ Get a value as a boolean. """
   107         try:
   115         try:
   108             value = self.__getitem__(key)
   116             value = self.__getitem__(key)
   109             return value == "true" or value == "yes" or value == "1"
   117             return value == "true" or value == "yes" or value == "1"
   110         except KeyError:
   118         except KeyError:
   111             return default_value
   119             return default_value
   119                isinstance(value, types.UnicodeType) or \
   127                isinstance(value, types.UnicodeType) or \
   120                isinstance(value, types.ListType):
   128                isinstance(value, types.ListType):
   121                 for match in self.key_re.finditer(value):
   129                 for match in self.key_re.finditer(value):
   122                     for property_name in match.groups():
   130                     for property_name in match.groups():
   123                         if self.has_key(property_name):
   131                         if self.has_key(property_name):
       
   132                             # See if interpolation may cause infinite recursion
       
   133                             raw_property_value = self.__getitem__(property_name, False)
       
   134                             #print 'raw_property_value: ' + raw_property_value
       
   135                             if raw_property_value == None:
       
   136                                 raw_property_value = ''
       
   137                             if isinstance(raw_property_value, types.ListType):
       
   138                                 for prop in raw_property_value:
       
   139                                     if re.search('\${' + property_name + '}', prop) != None:
       
   140                                         raise Exception("Key '%s' will cause recursive interpolation with value %s" % (property_name, raw_property_value))
       
   141                             else:
       
   142                                 if re.search('\${' + property_name + '}', raw_property_value) != None:
       
   143                                     raise Exception("Key '%s' will cause recursive interpolation with value %s" % (property_name, raw_property_value))
       
   144                                     
       
   145                             # Get the property value
   124                             property_value = self.__getitem__(property_name)
   146                             property_value = self.__getitem__(property_name)
   125                             if isinstance(property_value, types.ListType):
   147                             if isinstance(property_value, types.ListType):
   126                                 property_value = ",".join(property_value)
   148                                 property_value = ",".join(property_value)
   127                             else:
   149                             else:
   128                                 property_value = re.sub(r'\\', r'\\\\', property_value, re.M)
   150                                 property_value = re.sub(r'\\', r'\\\\', property_value, re.M)
   129                             value = re.sub('\${' + property_name + '}', property_value, value, re.M)
   151                             value = re.sub('\${' + property_name + '}', property_value, value, re.M)
   130         return value
   152         return value
   131     
   153     
   132     def __str__(self):
   154     def __str__(self):
       
   155         """ A string representation. """
   133         return self.__class__.__name__ + '[' + str(self.name) + ']'
   156         return self.__class__.__name__ + '[' + str(self.name) + ']'
   134         
   157         
   135     def __cmp__(self, other):
   158     def __cmp__(self, other):
       
   159         """ Compare with another object. """
   136         return cmp(self.__str__, other.__str__)
   160         return cmp(self.__str__, other.__str__)
   137        
   161        
   138        
   162        
   139 class PropertiesConfiguration(Configuration):
   163 class PropertiesConfiguration(Configuration):
   140     """ A Configuration that parses a plain text properties file.
   164     """ A Configuration that parses a plain text properties file.
   366         except IOError, e:
   390         except IOError, e:
   367             raise
   391             raise
   368             
   392             
   369 
   393 
   370 class NestedConfiguration(Configuration):
   394 class NestedConfiguration(Configuration):
       
   395     """ A nested configuration that may have a parent or child configurations. """
   371     def __init__(self):
   396     def __init__(self):
   372         """ Initialization. """
   397         """ Initialization. """
   373         Configuration.__init__(self, None)
   398         Configuration.__init__(self, None)
   374         self.parent = None
   399         self.parent = None
   375         self.type = None
   400         self.type = None
   376         self.abstract = None
   401         self.abstract = None
   377 
   402 
   378     def isBuildable(self):
   403     def isBuildable(self):
       
   404         """ Is this a buildable configuration? """
   379         return self.abstract == None
   405         return self.abstract == None
   380 
   406 
   381     def _addPropertyValue(self, key, value, parseList=True):
   407     def _addPropertyValue(self, key, value, parseList=True):
   382         """Adds a property value to the configuration.
   408         """Adds a property value to the configuration.
   383 
   409 
   409             self.data[key] = currentValue
   435             self.data[key] = currentValue
   410         else:
   436         else:
   411             self.data[key] = value
   437             self.data[key] = value
   412 
   438 
   413     def __getitem__(self, key, interpolate=True):
   439     def __getitem__(self, key, interpolate=True):
       
   440         """ Get an item. """
   414         #print "__getitem__(%s, %s)" % (self.name, key)
   441         #print "__getitem__(%s, %s)" % (self.name, key)
   415         if self.data.has_key(key):
   442         if self.data.has_key(key):
   416             value = super(NestedConfiguration, self).__getitem__(key, False)
   443             value = super(NestedConfiguration, self).__getitem__(key, False)
   417             if interpolate:
   444             if interpolate:
   418                 return self.interpolate(value)
   445                 return self.interpolate(value)
   423                 return self.interpolate(value)
   450                 return self.interpolate(value)
   424             return value
   451             return value
   425         raise KeyError('Cannot find key: ' + key)
   452         raise KeyError('Cannot find key: ' + key)
   426 
   453 
   427     def __setitem__(self, key, item):
   454     def __setitem__(self, key, item):
       
   455         """ Set the value of an item. """
   428         self.data[key] = item
   456         self.data[key] = item
   429 
   457 
   430     def __delitem__(self, key):
   458     def __delitem__(self, key):
       
   459         """ Remove an item. """
   431         del self.data[key]
   460         del self.data[key]
   432 
   461 
   433     def __contains__(self, key):
   462     def __contains__(self, key):
   434         """ Check if a keys is defined in the dict. """
   463         """ Check if a keys is defined in the dict. """
   435         if self.data.__contains__(key):
   464         if self.data.__contains__(key):
   437         elif self.parent:
   466         elif self.parent:
   438             return self.parent.__contains__(key)
   467             return self.parent.__contains__(key)
   439         return False
   468         return False
   440             
   469             
   441     def keys(self):
   470     def keys(self):
       
   471         """ Get the list of item keys. """
   442         myKeys = self.data.keys()
   472         myKeys = self.data.keys()
   443         if self.parent != None:
   473         if self.parent != None:
   444             parentKeys = self.parent.keys()
   474             parentKeys = self.parent.keys()
   445             for key in parentKeys:
   475             for key in parentKeys:
   446                 if not key in myKeys:
   476                 if not key in myKeys:
   447                     myKeys.append(key)
   477                     myKeys.append(key)
   448         return myKeys
   478         return myKeys
       
   479         
       
   480     def has_key(self, key):
       
   481         """ Check if key exists. """
       
   482         if self.data.has_key(key):
       
   483             return True
       
   484         if self.parent != None:
       
   485             return self.parent.has_key(key)
       
   486         return False
   449 
   487 
   450     def match_name(self, name):
   488     def match_name(self, name):
       
   489         """ See if the configuration name matches the argument. """
   451         if self.name == name:
   490         if self.name == name:
   452             return True
   491             return True
   453         if self.parent != None:
   492         if self.parent != None:
   454             return self.parent.match_name(name)
   493             return self.parent.match_name(name)
   455         return False
   494         return False
   663                 elif self._constructors.has_key(child.nodeName):
   702                 elif self._constructors.has_key(child.nodeName):
   664                     configChildNodes.append(child)
   703                     configChildNodes.append(child)
   665                 else:
   704                 else:
   666                     raise Exception('Bad configuration xml element: ' + child.nodeName)
   705                     raise Exception('Bad configuration xml element: ' + child.nodeName)
   667 
   706 
   668         for childConfigNode in configChildNodes:
       
   669             self.parseConfiguration(childConfigNode, configs, config)
       
   670 
       
   671         # Only save the buildable configurations
   707         # Only save the buildable configurations
   672         if config.isBuildable():
   708         if config.isBuildable():
   673             _logger.debug('Adding config to buildable set: ' + str(config))
   709             _logger.debug('Adding config to buildable set: ' + str(config))
   674             configs.append(config)
   710             configs.append(config)
       
   711             
       
   712         for childConfigNode in configChildNodes:
       
   713             self.parseConfiguration(childConfigNode, configs, config)
   675 
   714 
   676     def getNodeByReference(self, refName):
   715     def getNodeByReference(self, refName):
   677         """ Find a node based on a reference to it. """
   716         """ Find a node based on a reference to it. """
   678         for child in self.rootNode.childNodes:
   717         for child in self.rootNode.childNodes:
   679             if child.nodeType == xml.dom.Node.ELEMENT_NODE:
   718             if child.nodeType == xml.dom.Node.ELEMENT_NODE:
   698         value = ','.join(values)
   737         value = ','.join(values)
   699         if interpolate:
   738         if interpolate:
   700             value = self.interpolate(value)
   739             value = self.interpolate(value)
   701         return value
   740         return value
   702         
   741         
       
   742     def has_key(self, key):
       
   743         """ Check if key exists. """
       
   744         elements = self._root.xpath(_Key(key).to_xpath())
       
   745         if len(elements) > 0:
       
   746             return True
       
   747         return False
       
   748         
   703     
   749     
   704 class _Key(object):
   750 class _Key(object):
   705     """ A hierarchical configuration key. """
   751     """ A hierarchical configuration key. """
   706     
   752     
   707     def __init__(self, string):
   753     def __init__(self, string):
   708         """ Initialization. """
   754         """ Initialization. """
   709         self.string = string
   755         self.string = string
   710         
   756         
   711     def to_xpath(self):
   757     def to_xpath(self):
       
   758         """ Convert the key to XPath syntax. """
   712         return self.string.replace('.', '/')
   759         return self.string.replace('.', '/')
   713         
   760         
   714         
   761         
   715 class XMLConfiguration(HierarchicalConfiguration):
   762 class XMLConfiguration(HierarchicalConfiguration):
   716     """ A XML-based hierarchical configuration. """
   763     """ A XML-based hierarchical configuration. """