# HG changeset patch # User Jeff Hammel # Date 1332801985 25200 # Node ID 39f2611db9be30378683d5301f56d10e64ed216f # Parent 73e72a764c3a7985bae9809b7530e0338db49cf5 rename a bunch of things and begin to work on the sanity of validation diff -r 73e72a764c3a -r 39f2611db9be configuration/config.py --- a/configuration/config.py Mon Mar 26 15:14:26 2012 -0700 +++ b/configuration/config.py Mon Mar 26 15:46:25 2012 -0700 @@ -20,7 +20,7 @@ except ImportError: yaml = None -__all__ = ['Configuration', 'configuration_providers'] +__all__ = ['Configuration', 'configuration_providers', 'types'] configuration_providers = [] if json: @@ -108,6 +108,7 @@ float: float_cli, list: list_cli, None: base_cli} # default +__all__ += [i.__name__ for i in types.values()] class Configuration(object): options = {} @@ -121,22 +122,45 @@ # TODO: allow options to be a list of 2-tuples return self.options.items() - def check(self, config): - """check validity of configuration""" + ### methods for validating configuration - # TODO: ensure options in configuration are in self.options - unknown_options = [] + def check(self, config): + """ + check validity of configuration to be added + """ + # TODO: should probably deepcopy config + + # ensure options in configuration are in self.options + unknown_options = [i for i in config if i in self.options] + if unknown_options: + # TODO: more specific error type + raise Exception("Unknown options: %s" % ', '.join(unknown_options)) # TODO: ensure options are of the right type (if specified) + for key, value in config.items(): + _type = self.options[key].get('type') + if _type is not None: + config[key] = _type(value) + + return config + + def validate(self): + """validate resultant configuration""" + # TODO: configuration should be locked after this is called + + ### methods for adding configuration def __call__(self, *args): """add items to configuration and check it""" + for config in args: + self.add(config) + self.valdate() # validate total configuration + # TODO: configuration should be locked after this is called - def add(self, config): + def add(self, config, check=True): """update configuration: not undoable""" - self.check(config) - + self.check(config) # check config to be added self.config.update(config) # TODO: option to extend; augment lists/dicts @@ -176,13 +200,20 @@ self.optparse_options(parser) return parser - def parse(self, args=sys.argv[1:], parser=None): + def parse(self, args=sys.argv[1:], parser=None, configuration_provider_option=None): """parse configuration including command line options""" # parse arguments if parser is None: - parser = self.parser() + parser = self.parser(configuration_provider_option=configuration_provider_option) options, args = parser.parse_args(args) + # get CLI configuration options + cli_config = dict([(key, value) for key, value in options.__dict__.items() + if key in self.options]) + + # generate configuration + self(cli_config) + # return parsed arguments return options, args diff -r 73e72a764c3a -r 39f2611db9be tests/unit.py --- a/tests/unit.py Mon Mar 26 15:14:26 2012 -0700 +++ b/tests/unit.py Mon Mar 26 15:46:25 2012 -0700 @@ -13,15 +13,16 @@ # globals here = os.path.dirname(os.path.abspath(__file__)) -class configurationUnitTest(unittest.TestCase): +class ConfigurationUnitTest(unittest.TestCase): - def test_configuration(self): + def test_cli(self): example = ExampleConfiguration() # parse command line arguments options, args = example.parse(['-a', 'ts', '--develop', '-e', '/home/jhammel/bin/firefox']) self.assertEqual(bool(args), False) # no arguments self.assertEqual(options.develop, True) + self.assertEqual(options.activeTests, 'ts') if __name__ == '__main__': unittest.main()