##// 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 49 These take no parameters, unlike regular key-value arguments.
50 50 They are typically used for setting boolean flags, or enabling
51 51 modes that involve setting multiple options together.
52
53 Flags *always* begin with '--', never just one '-'.
54 52 """.strip() # trim newlines of front and back
55 53
56 54 alias_description = """
57 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 57 <name> is replaced by the real parameter for which it is an alias.
60 58 """.strip() # trim newlines of front and back
61 59
62 60 keyvalue_description = """
63 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 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 65 """.strip() # trim newlines of front and back
68 66
69 67 #-----------------------------------------------------------------------------
@@ -210,11 +208,12 b' class Application(SingletonConfigurable):'
210 208 cls = classdict[classname]
211 209
212 210 trait = cls.class_traits(config=True)[traitname]
213 help = cls.class_get_trait_help(trait)
214 help = help.replace(longname, "%s (%s)"%(alias, longname), 1)
215 lines.append(help)
211 help = cls.class_get_trait_help(trait).splitlines()
212 # reformat first line
213 help[0] = help[0].replace(longname, alias) + ' (%s)'%longname
214 lines.extend(help)
216 215 lines.append('')
217 print '\n'.join(lines)
216 print os.linesep.join(lines)
218 217
219 218 def print_flag_help(self):
220 219 """Print the flag part of the help."""
@@ -155,7 +155,7 b' class Configurable(HasTraits):'
155 155 def class_get_trait_help(cls, trait):
156 156 """Get the help string for a single trait."""
157 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 159 lines.append(header)
160 160 try:
161 161 dvr = repr(trait.get_default_value())
@@ -326,7 +326,7 b' class CommandLineConfigLoader(ConfigLoader):'
326 326 """
327 327
328 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 331 class KeyValueConfigLoader(CommandLineConfigLoader):
332 332 """A config loader that loads key value pairs from the command line.
@@ -426,7 +426,17 b' class KeyValueConfigLoader(CommandLineConfigLoader):'
426 426 if flags is None:
427 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 440 if kv_pattern.match(item):
431 441 lhs,rhs = item.split('=',1)
432 442 # Substitute longnames for aliases.
@@ -445,26 +455,23 b' class KeyValueConfigLoader(CommandLineConfigLoader):'
445 455 # it succeeds. If it still fails, we let it raise.
446 456 exec_str = u'self.config.' + lhs + '=' + repr(rhs)
447 457 exec exec_str in locals(), globals()
448 elif flag_pattern.match(item):
449 # trim leading '--'
450 m = item[2:]
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)):
458 elif item in flags:
459 cfg,help = flags[item]
460 if isinstance(cfg, (dict, Config)):
455 461 # don't clobber whole config sections, update
456 462 # each section from config:
457 463 for sec,c in cfg.iteritems():
458 464 self.config[sec].update(c)
459 465 else:
460 raise ValueError("Invalid flag: %r"%flag)
461 elif item.startswith('-'):
462 # this shouldn't ever be valid
463 raise ArgumentError("Invalid argument: %r"%item)
466 raise ValueError("Invalid flag: '%s'"%raw)
467 elif raw.startswith('-'):
468 raise ArgumentError("invalid argument: '%s'"%raw)
464 469 else:
465 470 # keep all args that aren't valid in a list,
466 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 475 return self.config
469 476
470 477 class ArgParseConfigLoader(CommandLineConfigLoader):
@@ -79,7 +79,7 b' class TestApplication(TestCase):'
79 79
80 80 def test_config(self):
81 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 83 config = app.config
84 84 self.assertEquals(config.Foo.i, 10)
85 85 self.assertEquals(config.Foo.j, 10)
@@ -88,7 +88,7 b' class TestApplication(TestCase):'
88 88
89 89 def test_config_propagation(self):
90 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 92 app.init_foo()
93 93 app.init_bar()
94 94 self.assertEquals(app.foo.i, 10)
@@ -97,7 +97,7 b' class TestApplication(TestCase):'
97 97
98 98 def test_flags(self):
99 99 app = MyApp()
100 app.parse_command_line(["--disable"])
100 app.parse_command_line(["-disable"])
101 101 app.init_bar()
102 102 self.assertEquals(app.bar.enabled, False)
103 103 app.parse_command_line(["--enable"])
@@ -126,10 +126,10 b' class TestApplication(TestCase):'
126 126
127 127 def test_extra_args(self):
128 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 130 app.init_bar()
131 self.assertEquals(app.bar.enabled, False)
131 self.assertEquals(app.bar.enabled, True)
132 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 48 mc_help=u"""MyConfigurable options
49 49 ----------------------
50 MyConfigurable.a : Int
50 --MyConfigurable.a=<Int>
51 51 Default: 1
52 52 The integer a.
53 MyConfigurable.b : Float
53 --MyConfigurable.b=<Float>
54 54 Default: 1.0
55 55 The integer b."""
56 56
@@ -130,9 +130,11 b' class TestKeyValueCL(TestCase):'
130 130 def test_extra_args(self):
131 131 cl = KeyValueConfigLoader()
132 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 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 139 def test_unicode_args(self):
138 140 cl = KeyValueConfigLoader()
@@ -93,7 +93,7 b' shell_aliases = dict('
93 93 cache_size='InteractiveShell.cache_size',
94 94 colors='InteractiveShell.colors',
95 95 logfile='InteractiveShell.logfile',
96 log_append='InteractiveShell.logappend',
96 logappend='InteractiveShell.logappend',
97 97 c='InteractiveShellApp.code_to_run',
98 98 ext='InteractiveShellApp.extra_extension',
99 99 )
@@ -188,21 +188,28 b' class InteractiveShellApp(Configurable):'
188 188
189 189 def _exec_file(self, fname):
190 190 full_filename = filefind(fname, [u'.', self.ipython_dir])
191 if os.path.isfile(full_filename):
192 if full_filename.endswith('.ipy'):
193 self.log.info("Running file in user namespace: %s" %
194 full_filename)
195 self.shell.safe_execfile_ipy(full_filename)
196 else:
197 # default to python, even without extension
198 self.log.info("Running file in user namespace: %s" %
199 full_filename)
200 # Ensure that __file__ is always defined to match Python behavior
201 self.shell.user_ns['__file__'] = fname
202 try:
203 self.shell.safe_execfile(full_filename, self.shell.user_ns)
204 finally:
205 del self.shell.user_ns['__file__']
191 # Make sure that the running script gets a proper sys.argv as if it
192 # were run from a system shell.
193 save_argv = sys.argv
194 sys.argv = sys.argv[sys.argv.index(fname):]
195 try:
196 if os.path.isfile(full_filename):
197 if full_filename.endswith('.ipy'):
198 self.log.info("Running file in user namespace: %s" %
199 full_filename)
200 self.shell.safe_execfile_ipy(full_filename)
201 else:
202 # default to python, even without extension
203 self.log.info("Running file in user namespace: %s" %
204 full_filename)
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 214 def _run_exec_files(self):
208 215 """Run files from IPythonApp.exec_files"""
General Comments 0
You need to be logged in to leave comments. Login now