##// END OF EJS Templates
parse cl_args agnostic of leading '-'...
MinRK -
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 '\n'.join(lines)
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 : %s" % (cls.__name__, trait.name, trait.__class__.__name__)
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'\-\-\w+(\-\w)*')
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 flag_pattern.match(item):
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: %r"%flag)
466 raise ValueError("Invalid flag: '%s'"%raw)
461 elif item.startswith('-'):
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(["--disable"])
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', "Bar.b=5", "--disable", 'args'])
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, False)
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 : Int
50 --MyConfigurable.a=<Int>
51 Default: 1
51 Default: 1
52 The integer a.
52 The integer a.
53 MyConfigurable.b : Float
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.assertEquals(config.c, 10)
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_append='InteractiveShell.logappend',
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