I have an option in OptionParser as seen below:
foo_choices = ['foo', 'bar', 'mac', 'win']
parser.add_option('-t', '--test',
type='choice',
action='store',
dest='test',
choices=foo_choices,
default='foo')
However, I want the option to be able to take in more than one choice (can be comma delimited, or allow > 1 argument). Just setting nargs=2 works forpassing in multiple args, so I assume this can be done for type choices. I cannot figure out how to do it to variable number of nargs.
Syntax like:
./demo.py -t foo -o out.out
./demo.py -t foo,bar -o out.out
Or
./demo.py -t foo -o out.out
./demo.py -t foo bar -o out.out
I've tried using a callback to split on commas, but if the callback returns an array, it errors out because the option is an invalid choice 'foo,bar'. The error makes sense, but I'm unsure where to go from here.
def foo_callback(option, opt, value, parser):
setattr(parser.values, option.dest, value.split(','))
Trying to go for an nargs approach, I tried implementing Callback Example 6,
#!/usr/bin/python
from optparse import OptionParser
def main():
parser = OptionParser()
foo_choices = ['foo', 'bar', 'mac', 'win']
parser.add_option('-t', '--test',
type='choice',
action='callback',
dest='test',
choices=foo_choices,
callback=vararg_callback)
(options, args) = parser.parse_args()
print options
print args
def vararg_callback(option, opt_str, value, parser):
assert value is None
value = []
def floatable(str):
try:
float(str)
return True
except ValueError:
return False
for arg in parser.rargs:
# stop on --foo like options
if arg[:2] == "--" and len(arg) > 2:
break
# stop on -a, but not on -3 or -3.0
if arg[:1] == "-" and len(arg) > 1 and not floatable(arg):
break
value.append(arg)
del parser.rargs[:len(value)]
setattr(parser.values, option.dest, value)
if __name__ == '__main__':
main()
This snippet introduces a way to implement a variable number of nargs. However, the only way I got this to work was to remove the type and choices from my option (defeating the purpose of what I'm trying to do). If I didn't, the error I would get is:
[vagrant@machine a]$ ./demo.py -t foo
Traceback (most recent call last):
File "./demo.py", line 43, in <module>
main()
File "./demo.py", line 14, in main
(options, args) = parser.parse_args()
File "/usr/lib64/python2.6/optparse.py", line 1394, in parse_args
stop = self._process_args(largs, rargs, values)
File "/usr/lib64/python2.6/optparse.py", line 1438, in _process_args
self._process_short_opts(rargs, values)
File "/usr/lib64/python2.6/optparse.py", line 1545, in _process_short_opts
option.process(opt, value, values, self)
File "/usr/lib64/python2.6/optparse.py", line 788, in process
self.action, self.dest, opt, value, values, parser)
File "/usr/lib64/python2.6/optparse.py", line 808, in take_action
self.callback(self, opt, value, parser, *args, **kwargs)
File "./demo.py", line 20, in vararg_callback
assert value is None
AssertionError