diff --git a/IPython/config/application.py b/IPython/config/application.py index ec9431c..85cfed6 100644 --- a/IPython/config/application.py +++ b/IPython/config/application.py @@ -112,6 +112,9 @@ class Application(SingletonConfigurable): # parse_command_line will initialize a subapp, if requested subapp = Instance('IPython.config.application.Application', allow_none=True) + # extra command-line arguments that don't set config values + extra_args = List(Unicode) + def __init__(self, **kwargs): SingletonConfigurable.__init__(self, **kwargs) @@ -266,13 +269,7 @@ class Application(SingletonConfigurable): def initialize_subcommand(self, subc, argv=None): """Initialize a subcommand with argv""" - subapp,help = self.subcommands.get(subc, (None,None)) - if subapp is None: - self.print_description() - print "No such subcommand: %r"%subc - print - self.print_subcommands() - self.exit(1) + subapp,help = self.subcommands.get(subc) if isinstance(subapp, basestring): subapp = import_item(subapp) @@ -289,7 +286,7 @@ class Application(SingletonConfigurable): if self.subcommands and len(argv) > 0: # we have subcommands, and one may have been specified subc, subargv = argv[0], argv[1:] - if re.match(r'^\w(\-?\w)*$', subc): + if re.match(r'^\w(\-?\w)*$', subc) and subc in self.subcommands: # it's a subcommand, and *not* a flag or class parameter return self.initialize_subcommand(subc, subargv) @@ -312,6 +309,8 @@ class Application(SingletonConfigurable): self.print_help() self.exit(1) self.update_config(config) + # store unparsed args in extra_args + self.extra_args = loader.extra_args def load_config_file(self, filename, path=None): """Load a .py based config file by filename and path.""" diff --git a/IPython/config/loader.py b/IPython/config/loader.py index 2a0238f..69a228b 100644 --- a/IPython/config/loader.py +++ b/IPython/config/loader.py @@ -382,7 +382,9 @@ class KeyValueConfigLoader(CommandLineConfigLoader): aliases = self.aliases if flags is None: flags = self.flags - + + self.extra_args = [] + for item in argv: if kv_pattern.match(item): lhs,rhs = item.split('=',1) @@ -414,8 +416,13 @@ class KeyValueConfigLoader(CommandLineConfigLoader): self.config[sec].update(c) else: raise ValueError("Invalid flag: %r"%flag) - else: + elif item.startswith('-'): + # this shouldn't ever be valid raise ArgumentError("Invalid argument: %r"%item) + else: + # keep all args that aren't valid in a list, + # in case our parent knows what to do with them. + self.extra_args.append(item) return self.config class ArgParseConfigLoader(CommandLineConfigLoader): diff --git a/IPython/config/tests/test_application.py b/IPython/config/tests/test_application.py index 31221eb..b9be7d2 100644 --- a/IPython/config/tests/test_application.py +++ b/IPython/config/tests/test_application.py @@ -116,14 +116,20 @@ class TestApplication(TestCase): """test that setting flags doesn't clobber existing settings""" app = MyApp() app.parse_command_line(["Bar.b=5", "--disable"]) - print app.config app.init_bar() self.assertEquals(app.bar.enabled, False) self.assertEquals(app.bar.b, 5) app.parse_command_line(["--enable", "Bar.b=10"]) - print app.config app.init_bar() self.assertEquals(app.bar.enabled, True) self.assertEquals(app.bar.b, 10) + def test_extra_args(self): + app = MyApp() + app.parse_command_line(['extra', "Bar.b=5", "--disable", 'args']) + app.init_bar() + self.assertEquals(app.bar.enabled, False) + self.assertEquals(app.bar.b, 5) + self.assertEquals(app.extra_args, ['extra', 'args']) + diff --git a/IPython/config/tests/test_loader.py b/IPython/config/tests/test_loader.py index f5439ce..bafaa6b 100755 --- a/IPython/config/tests/test_loader.py +++ b/IPython/config/tests/test_loader.py @@ -123,6 +123,13 @@ class TestKeyValueCL(TestCase): self.assertEquals(config.Foo.Bar.value, 10) self.assertEquals(config.Foo.Bam.value, range(10)) self.assertEquals(config.D.C.value, 'hi there') + + def test_extra_args(self): + cl = KeyValueConfigLoader() + config = cl.load_config(['a=5', 'b', 'c=10', 'd']) + self.assertEquals(cl.extra_args, ['b', 'd']) + self.assertEquals(config.a, 5) + self.assertEquals(config.c, 10) class TestConfig(TestCase):