diff configuration/configuration.py @ 102:c530f6265deb

allow extensible configuration; also start using deepcopy heavily since otherwise you have artefacts
author Jeff Hammel <jhammel@mozilla.com>
date Tue, 01 May 2012 10:33:37 -0700
parents f4590492cb4c
children 982a775bf3d2
line wrap: on
line diff
--- a/configuration/configuration.py	Mon Apr 30 13:21:48 2012 -0700
+++ b/configuration/configuration.py	Tue May 01 10:33:37 2012 -0700
@@ -225,6 +225,7 @@
 
     options = {}         # configuration basis definition
     load_option = 'load' # where to put the load option
+    extend = set()       # if dicts/lists should be extended
 
     def __init__(self, configuration_providers=configuration_providers, types=types, load=None, dump='--dump', **parser_args):
 
@@ -326,17 +327,24 @@
 
     ### methods for adding configuration
 
+    def default_config(self):
+        """configuration defaults"""
+        defaults = {}
+        for key, value in self.options.items():
+            if 'default' in value:
+                defaults[key] = value['default']
+        return copy.deepcopy(defaults)
+
     def __call__(self, *args):
         """add items to configuration and check it"""
 
+        # start with defaults
+        self.config = self.default_config()
+
+        # add the configuration
         for config in args:
             self.add(config)
 
-        # add defaults if not present
-        for key, value in self.items():
-            if 'default' in value and key not in self.config:
-                self.config[key] = value['default']
-
         # validate total configuration
         self.validate()
         # TODO: configuration should be locked after this is called
@@ -344,9 +352,24 @@
     def add(self, config, check=True):
         """update configuration: not undoable"""
 
-        self.check(config) # check config to be added
-        self.config.update(config)
-        # TODO: option to extend; augment lists/dicts
+        # check config to be added
+        self.check(config)
+
+        # add the configuration
+        for key, value in config.items():
+            value = copy.deepcopy(value)
+            if key in self.extend and key in self.config:
+                type1 = type(self.config[key])
+                type2 = type(value)
+                assert type1 == type2 # XXX hack
+                if type1 == dict:
+                    self.config[key].update(value)
+                elif type1 == list:
+                    self.config[key].extend(value)
+                else:
+                    raise NotImplementedError
+            else:
+                self.config[key] = value
 
     ### methods for optparse
     ### XXX could go in a subclass