Show More
@@ -49,21 +49,19 b" Flags are command-line arguments passed as '--<flag>'." | |||||
49 | These take no parameters, unlike regular key-value arguments. |
|
49 | These take no parameters, unlike regular key-value arguments. | |
50 | They are typically used for setting boolean flags, or enabling |
|
50 | They are typically used for setting boolean flags, or enabling | |
51 | modes that involve setting multiple options together. |
|
51 | modes that involve setting multiple options together. | |
52 |
|
||||
53 | Flags *always* begin with '--', never just one '-'. |
|
|||
54 | """.strip() # trim newlines of front and back |
|
52 | """.strip() # trim newlines of front and back | |
55 |
|
53 | |||
56 | alias_description = """ |
|
54 | alias_description = """ | |
57 | These are commonly set parameters, given abbreviated aliases for convenience. |
|
55 | These are commonly set parameters, given abbreviated aliases for convenience. | |
58 | They are set in the same `name=value` way as class parameters, where |
|
56 | They are set in the same `--name=value` way as class parameters, where | |
59 | <name> is replaced by the real parameter for which it is an alias. |
|
57 | <name> is replaced by the real parameter for which it is an alias. | |
60 | """.strip() # trim newlines of front and back |
|
58 | """.strip() # trim newlines of front and back | |
61 |
|
59 | |||
62 | keyvalue_description = """ |
|
60 | keyvalue_description = """ | |
63 | Parameters are set from command-line arguments of the form: |
|
61 | Parameters are set from command-line arguments of the form: | |
64 | `Class.trait=value`. Parameters will *never* be prefixed with '-'. |
|
62 | `--Class.trait=value`. | |
65 | This line is evaluated in Python, so simple expressions are allowed, e.g. |
|
63 | This line is evaluated in Python, so simple expressions are allowed, e.g. | |
66 | `C.a='range(3)'` For setting C.a=[0,1,2] |
|
64 | `--C.a='range(3)'` For setting C.a=[0,1,2] | |
67 | """.strip() # trim newlines of front and back |
|
65 | """.strip() # trim newlines of front and back | |
68 |
|
66 | |||
69 | #----------------------------------------------------------------------------- |
|
67 | #----------------------------------------------------------------------------- | |
@@ -210,11 +208,12 b' class Application(SingletonConfigurable):' | |||||
210 | cls = classdict[classname] |
|
208 | cls = classdict[classname] | |
211 |
|
209 | |||
212 | trait = cls.class_traits(config=True)[traitname] |
|
210 | trait = cls.class_traits(config=True)[traitname] | |
213 | help = cls.class_get_trait_help(trait) |
|
211 | help = cls.class_get_trait_help(trait).splitlines() | |
214 | help = help.replace(longname, "%s (%s)"%(alias, longname), 1) |
|
212 | # reformat first line | |
215 | lines.append(help) |
|
213 | help[0] = help[0].replace(longname, alias) + ' (%s)'%longname | |
|
214 | lines.extend(help) | |||
216 | lines.append('') |
|
215 | lines.append('') | |
217 |
print |
|
216 | print os.linesep.join(lines) | |
218 |
|
217 | |||
219 | def print_flag_help(self): |
|
218 | def print_flag_help(self): | |
220 | """Print the flag part of the help.""" |
|
219 | """Print the flag part of the help.""" |
@@ -155,7 +155,7 b' class Configurable(HasTraits):' | |||||
155 | def class_get_trait_help(cls, trait): |
|
155 | def class_get_trait_help(cls, trait): | |
156 | """Get the help string for a single trait.""" |
|
156 | """Get the help string for a single trait.""" | |
157 | lines = [] |
|
157 | lines = [] | |
158 |
header = "%s.%s |
|
158 | header = "--%s.%s=<%s>" % (cls.__name__, trait.name, trait.__class__.__name__) | |
159 | lines.append(header) |
|
159 | lines.append(header) | |
160 | try: |
|
160 | try: | |
161 | dvr = repr(trait.get_default_value()) |
|
161 | dvr = repr(trait.get_default_value()) |
@@ -326,7 +326,7 b' class CommandLineConfigLoader(ConfigLoader):' | |||||
326 | """ |
|
326 | """ | |
327 |
|
327 | |||
328 | kv_pattern = re.compile(r'[A-Za-z]\w*(\.\w+)*\=.*') |
|
328 | kv_pattern = re.compile(r'[A-Za-z]\w*(\.\w+)*\=.*') | |
329 |
flag_pattern = re.compile(r'\ |
|
329 | flag_pattern = re.compile(r'\w+(\-\w)*') | |
330 |
|
330 | |||
331 | class KeyValueConfigLoader(CommandLineConfigLoader): |
|
331 | class KeyValueConfigLoader(CommandLineConfigLoader): | |
332 | """A config loader that loads key value pairs from the command line. |
|
332 | """A config loader that loads key value pairs from the command line. | |
@@ -426,7 +426,17 b' class KeyValueConfigLoader(CommandLineConfigLoader):' | |||||
426 | if flags is None: |
|
426 | if flags is None: | |
427 | flags = self.flags |
|
427 | flags = self.flags | |
428 |
|
428 | |||
429 | for item in self._decode_argv(argv): |
|
429 | # ensure argv is a list of unicode strings: | |
|
430 | uargv = self._decode_argv(argv) | |||
|
431 | for idx,raw in enumerate(uargv): | |||
|
432 | # strip leading '-' | |||
|
433 | item = raw.lstrip('-') | |||
|
434 | ||||
|
435 | if raw == '--': | |||
|
436 | # don't parse arguments after '--' | |||
|
437 | self.extra_args.extend(uargv[idx+1:]) | |||
|
438 | break | |||
|
439 | ||||
430 | if kv_pattern.match(item): |
|
440 | if kv_pattern.match(item): | |
431 | lhs,rhs = item.split('=',1) |
|
441 | lhs,rhs = item.split('=',1) | |
432 | # Substitute longnames for aliases. |
|
442 | # Substitute longnames for aliases. | |
@@ -445,26 +455,23 b' class KeyValueConfigLoader(CommandLineConfigLoader):' | |||||
445 | # it succeeds. If it still fails, we let it raise. |
|
455 | # it succeeds. If it still fails, we let it raise. | |
446 | exec_str = u'self.config.' + lhs + '=' + repr(rhs) |
|
456 | exec_str = u'self.config.' + lhs + '=' + repr(rhs) | |
447 | exec exec_str in locals(), globals() |
|
457 | exec exec_str in locals(), globals() | |
448 |
elif |
|
458 | elif item in flags: | |
449 | # trim leading '--' |
|
459 | cfg,help = flags[item] | |
450 | m = item[2:] |
|
460 | if isinstance(cfg, (dict, Config)): | |
451 | cfg,_ = flags.get(m, (None,None)) |
|
|||
452 | if cfg is None: |
|
|||
453 | raise ArgumentError("Unrecognized flag: %r"%item) |
|
|||
454 | elif isinstance(cfg, (dict, Config)): |
|
|||
455 | # don't clobber whole config sections, update |
|
461 | # don't clobber whole config sections, update | |
456 | # each section from config: |
|
462 | # each section from config: | |
457 | for sec,c in cfg.iteritems(): |
|
463 | for sec,c in cfg.iteritems(): | |
458 | self.config[sec].update(c) |
|
464 | self.config[sec].update(c) | |
459 | else: |
|
465 | else: | |
460 |
raise ValueError("Invalid flag: |
|
466 | raise ValueError("Invalid flag: '%s'"%raw) | |
461 |
elif |
|
467 | elif raw.startswith('-'): | |
462 | # this shouldn't ever be valid |
|
468 | raise ArgumentError("invalid argument: '%s'"%raw) | |
463 | raise ArgumentError("Invalid argument: %r"%item) |
|
|||
464 | else: |
|
469 | else: | |
465 | # keep all args that aren't valid in a list, |
|
470 | # keep all args that aren't valid in a list, | |
466 | # in case our parent knows what to do with them. |
|
471 | # in case our parent knows what to do with them. | |
467 | self.extra_args.append(item) |
|
472 | # self.extra_args.append(item) | |
|
473 | self.extra_args.extend(uargv[idx:]) | |||
|
474 | break | |||
468 | return self.config |
|
475 | return self.config | |
469 |
|
476 | |||
470 | class ArgParseConfigLoader(CommandLineConfigLoader): |
|
477 | class ArgParseConfigLoader(CommandLineConfigLoader): |
@@ -79,7 +79,7 b' class TestApplication(TestCase):' | |||||
79 |
|
79 | |||
80 | def test_config(self): |
|
80 | def test_config(self): | |
81 | app = MyApp() |
|
81 | app = MyApp() | |
82 | app.parse_command_line(["i=10","Foo.j=10","enabled=False","log_level=50"]) |
|
82 | app.parse_command_line(["--i=10","Foo.j=10","--enabled=False","-log_level=50"]) | |
83 | config = app.config |
|
83 | config = app.config | |
84 | self.assertEquals(config.Foo.i, 10) |
|
84 | self.assertEquals(config.Foo.i, 10) | |
85 | self.assertEquals(config.Foo.j, 10) |
|
85 | self.assertEquals(config.Foo.j, 10) | |
@@ -88,7 +88,7 b' class TestApplication(TestCase):' | |||||
88 |
|
88 | |||
89 | def test_config_propagation(self): |
|
89 | def test_config_propagation(self): | |
90 | app = MyApp() |
|
90 | app = MyApp() | |
91 | app.parse_command_line(["i=10","Foo.j=10","enabled=False","log_level=50"]) |
|
91 | app.parse_command_line(["i=10","--Foo.j=10","enabled=False","log_level=50"]) | |
92 | app.init_foo() |
|
92 | app.init_foo() | |
93 | app.init_bar() |
|
93 | app.init_bar() | |
94 | self.assertEquals(app.foo.i, 10) |
|
94 | self.assertEquals(app.foo.i, 10) | |
@@ -97,7 +97,7 b' class TestApplication(TestCase):' | |||||
97 |
|
97 | |||
98 | def test_flags(self): |
|
98 | def test_flags(self): | |
99 | app = MyApp() |
|
99 | app = MyApp() | |
100 |
app.parse_command_line([" |
|
100 | app.parse_command_line(["-disable"]) | |
101 | app.init_bar() |
|
101 | app.init_bar() | |
102 | self.assertEquals(app.bar.enabled, False) |
|
102 | self.assertEquals(app.bar.enabled, False) | |
103 | app.parse_command_line(["--enable"]) |
|
103 | app.parse_command_line(["--enable"]) | |
@@ -126,10 +126,10 b' class TestApplication(TestCase):' | |||||
126 |
|
126 | |||
127 | def test_extra_args(self): |
|
127 | def test_extra_args(self): | |
128 | app = MyApp() |
|
128 | app = MyApp() | |
129 |
app.parse_command_line(['extra' |
|
129 | app.parse_command_line(["Bar.b=5", 'extra', "--disable", 'args']) | |
130 | app.init_bar() |
|
130 | app.init_bar() | |
131 |
self.assertEquals(app.bar.enabled, |
|
131 | self.assertEquals(app.bar.enabled, True) | |
132 | self.assertEquals(app.bar.b, 5) |
|
132 | self.assertEquals(app.bar.b, 5) | |
133 | self.assertEquals(app.extra_args, ['extra', 'args']) |
|
133 | self.assertEquals(app.extra_args, ['extra', "--disable", 'args']) | |
134 |
|
134 | |||
135 |
|
135 |
@@ -47,10 +47,10 b' class MyConfigurable(Configurable):' | |||||
47 |
|
47 | |||
48 | mc_help=u"""MyConfigurable options |
|
48 | mc_help=u"""MyConfigurable options | |
49 | ---------------------- |
|
49 | ---------------------- | |
50 |
MyConfigurable.a |
|
50 | --MyConfigurable.a=<Int> | |
51 | Default: 1 |
|
51 | Default: 1 | |
52 | The integer a. |
|
52 | The integer a. | |
53 |
MyConfigurable.b |
|
53 | --MyConfigurable.b=<Float> | |
54 | Default: 1.0 |
|
54 | Default: 1.0 | |
55 | The integer b.""" |
|
55 | The integer b.""" | |
56 |
|
56 |
@@ -130,9 +130,11 b' class TestKeyValueCL(TestCase):' | |||||
130 | def test_extra_args(self): |
|
130 | def test_extra_args(self): | |
131 | cl = KeyValueConfigLoader() |
|
131 | cl = KeyValueConfigLoader() | |
132 | config = cl.load_config(['a=5', 'b', 'c=10', 'd']) |
|
132 | config = cl.load_config(['a=5', 'b', 'c=10', 'd']) | |
133 | self.assertEquals(cl.extra_args, ['b', 'd']) |
|
133 | self.assertEquals(cl.extra_args, ['b', 'c=10' , 'd']) | |
134 | self.assertEquals(config.a, 5) |
|
134 | self.assertEquals(config.a, 5) | |
135 |
self.assert |
|
135 | self.assertRaises(AttributeError, getattr, config, 'c') | |
|
136 | config = cl.load_config(['--', 'a=5', 'c=10']) | |||
|
137 | self.assertEquals(cl.extra_args, ['a=5', 'c=10']) | |||
136 |
|
138 | |||
137 | def test_unicode_args(self): |
|
139 | def test_unicode_args(self): | |
138 | cl = KeyValueConfigLoader() |
|
140 | cl = KeyValueConfigLoader() |
@@ -93,7 +93,7 b' shell_aliases = dict(' | |||||
93 | cache_size='InteractiveShell.cache_size', |
|
93 | cache_size='InteractiveShell.cache_size', | |
94 | colors='InteractiveShell.colors', |
|
94 | colors='InteractiveShell.colors', | |
95 | logfile='InteractiveShell.logfile', |
|
95 | logfile='InteractiveShell.logfile', | |
96 |
log |
|
96 | logappend='InteractiveShell.logappend', | |
97 | c='InteractiveShellApp.code_to_run', |
|
97 | c='InteractiveShellApp.code_to_run', | |
98 | ext='InteractiveShellApp.extra_extension', |
|
98 | ext='InteractiveShellApp.extra_extension', | |
99 | ) |
|
99 | ) | |
@@ -188,21 +188,28 b' class InteractiveShellApp(Configurable):' | |||||
188 |
|
188 | |||
189 | def _exec_file(self, fname): |
|
189 | def _exec_file(self, fname): | |
190 | full_filename = filefind(fname, [u'.', self.ipython_dir]) |
|
190 | full_filename = filefind(fname, [u'.', self.ipython_dir]) | |
191 | if os.path.isfile(full_filename): |
|
191 | # Make sure that the running script gets a proper sys.argv as if it | |
192 | if full_filename.endswith('.ipy'): |
|
192 | # were run from a system shell. | |
193 | self.log.info("Running file in user namespace: %s" % |
|
193 | save_argv = sys.argv | |
194 | full_filename) |
|
194 | sys.argv = sys.argv[sys.argv.index(fname):] | |
195 | self.shell.safe_execfile_ipy(full_filename) |
|
195 | try: | |
196 | else: |
|
196 | if os.path.isfile(full_filename): | |
197 | # default to python, even without extension |
|
197 | if full_filename.endswith('.ipy'): | |
198 | self.log.info("Running file in user namespace: %s" % |
|
198 | self.log.info("Running file in user namespace: %s" % | |
199 | full_filename) |
|
199 | full_filename) | |
200 | # Ensure that __file__ is always defined to match Python behavior |
|
200 | self.shell.safe_execfile_ipy(full_filename) | |
201 | self.shell.user_ns['__file__'] = fname |
|
201 | else: | |
202 | try: |
|
202 | # default to python, even without extension | |
203 | self.shell.safe_execfile(full_filename, self.shell.user_ns) |
|
203 | self.log.info("Running file in user namespace: %s" % | |
204 | finally: |
|
204 | full_filename) | |
205 | del self.shell.user_ns['__file__'] |
|
205 | # Ensure that __file__ is always defined to match Python behavior | |
|
206 | self.shell.user_ns['__file__'] = fname | |||
|
207 | try: | |||
|
208 | self.shell.safe_execfile(full_filename, self.shell.user_ns) | |||
|
209 | finally: | |||
|
210 | del self.shell.user_ns['__file__'] | |||
|
211 | finally: | |||
|
212 | sys.argv = save_argv | |||
206 |
|
213 | |||
207 | def _run_exec_files(self): |
|
214 | def _run_exec_files(self): | |
208 | """Run files from IPythonApp.exec_files""" |
|
215 | """Run files from IPythonApp.exec_files""" |
General Comments 0
You need to be logged in to leave comments.
Login now