diff --git a/IPython/config/loader.py b/IPython/config/loader.py index 056ae61..6a0b3e6 100644 --- a/IPython/config/loader.py +++ b/IPython/config/loader.py @@ -307,7 +307,64 @@ class CommandLineConfigLoader(ConfigLoader): """ +class KeyValueConfigLoader(CommandLineConfigLoader): + """A config loader that loads key value pairs from the command line. + + This allows command line options to be gives in the following form:: + + ipython Global.profile="foo" InteractiveShell.autocall=False + """ + + def __init__(self, argv=None): + """Create a key value pair config loader. + + Parameters + ---------- + argv : list + A list that has the form of sys.argv[1:] which has unicode + elements of the form u"key=value". If this is None (default), + then sys.argv[1:] will be used. + + Returns + ------- + config : Config + The resulting Config object. + + Examples + -------- + + >>> from IPython.config.loader import KeyValueConfigLoader + >>> cl = KeyValueConfigLoader() + >>> cl.load_config(["foo='bar'","A.name='brian'","B.number=0"]) + {'A': {'name': 'brian'}, 'B': {'number': 0}, 'foo': 'bar'} + """ + if argv == None: + argv = sys.argv[1:] + self.argv = argv + + def load_config(self, argv=None): + """Parse the configuration and generate the Config object. + + Parameters + ---------- + argv : list, optional + A list that has the form of sys.argv[1:] which has unicode + elements of the form u"key=value". If this is None (default), + then self.argv will be used. + """ + self.clear() + if argv is None: + argv = self.argv + for item in argv: + pair = tuple(item.split("=")) + if len(pair) == 2: + exec_str = 'self.config.' + pair[0] + '=' + pair[1] + exec exec_str in locals(), globals() + return self.config + + class ArgParseConfigLoader(CommandLineConfigLoader): + """A loader that uses the argparse module to load from the command line.""" def __init__(self, argv=None, *parser_args, **parser_kw): """Create a config loader for use with argparse. @@ -326,6 +383,11 @@ class ArgParseConfigLoader(CommandLineConfigLoader): parser_kw : dict A tuple of keyword arguments that will be passed to the constructor of :class:`argparse.ArgumentParser`. + + Returns + ------- + config : Config + The resulting Config object. """ super(CommandLineConfigLoader, self).__init__() if argv == None: @@ -337,8 +399,8 @@ class ArgParseConfigLoader(CommandLineConfigLoader): kwargs.update(parser_kw) self.parser_kw = kwargs - def load_config(self, args=None): - """Parse command line arguments and return as a Struct. + def load_config(self, argv=None): + """Parse command line arguments and return as a Config object. Parameters ---------- @@ -348,10 +410,10 @@ class ArgParseConfigLoader(CommandLineConfigLoader): arguments from. If not given, the instance's self.argv attribute (given at construction time) is used.""" self.clear() - if args is None: - args = self.argv + if argv is None: + argv = self.argv self._create_parser() - self._parse_args(args) + self._parse_args(argv) self._convert_to_config() return self.config diff --git a/IPython/config/tests/test_loader.py b/IPython/config/tests/test_loader.py index 390f1b4..5e41b73 100755 --- a/IPython/config/tests/test_loader.py +++ b/IPython/config/tests/test_loader.py @@ -26,7 +26,8 @@ from unittest import TestCase from IPython.config.loader import ( Config, - PyFileConfigLoader, + PyFileConfigLoader, + KeyValueConfigLoader, ArgParseConfigLoader, ConfigError ) @@ -38,11 +39,11 @@ from IPython.config.loader import ( pyfile = """ c = get_config() -c.a = 10 -c.b = 20 -c.Foo.Bar.value = 10 -c.Foo.Bam.value = range(10) -c.D.C.value = 'hi there' +c.a=10 +c.b=20 +c.Foo.Bar.value=10 +c.Foo.Bam.value=range(10) +c.D.C.value='hi there' """ class TestPyFileCL(TestCase): @@ -109,6 +110,19 @@ class TestArgParseCL(TestCase): self.assertEquals(config.Global.bam, 'wow') +class TestKeyValueCL(TestCase): + + def test_basic(self): + cl = KeyValueConfigLoader() + argv = [s.strip('c.') for s in pyfile.split('\n')[2:-1]] + print argv + config = cl.load_config(argv) + self.assertEquals(config.a, 10) + self.assertEquals(config.b, 20) + self.assertEquals(config.Foo.Bar.value, 10) + self.assertEquals(config.Foo.Bam.value, range(10)) + self.assertEquals(config.D.C.value, 'hi there') + class TestConfig(TestCase): def test_setget(self):