GNU getopt, and command line tools that use it, allow options and arguments to be interleaved, known as permuting options (see http://www.gnu.org/software/libc/manual/html_node/Using-Getopt.html#Using-Getopt). Perl's Getopt::Long module also supports this (with qw(:config gnu_getopt)). argparse seems to not support (or even mention) permuting options.
There are many SO questions related to arg/opt order, but none seem answer this question: Can argparse be made to permute argument order like getopt?
The use case is a prototypical command line signature like GNU sort:
sort [opts] [files]
in which 1) options and files are permuted, and 2) the file list may contain zero or more arguments.
For example:
import argparse
p = argparse.ArgumentParser();
p.add_argument('files',nargs='*',default=['-']);
p.add_argument('-z',action='store_true')
p.parse_args(['-z','bar','foo']) # ok
p.parse_args(['bar','foo','-z']) # ok
p.parse_args(['bar','-z','foo']) # not okay
usage: ipython [-h] [-z] [files [files ...]]
I've tried:
- p.parse_known_args -- doesn't complain, but doesn't actually permute either and it doesn't balk about arguments that look like invalid options (e.g., --bogus or -b above).
- p.add_argument('files',nargs=argparse.REMAINDER) -- option -z is included in files unless before positional args
- p.add_argument('files',nargs='*',action='append');
I want to implement something close to the GNU sort prototype above. I am not interested in a flag that can be specified for each file (e.g., -f file1 -f file2).
Here's a quick solution which decodes the argument list one (options, positional arguments) pair at a time.
Output:
Note: Don't try to use this with other non-flag arguments (besides a single
nargs='*'
argument and theargs_tail
argument). The parser won't know about previous invocations ofparse_args
so it will store the wrong value for these non-flag arguments. As a workaround, you can parse thenargs='*'
argument manually after usinginterleaved_parse
.I've seen nothing definitive in the argparse documentation stating that it can or cannot permute. Based on your own observations, where permutation failed, and the following doc quotes, I'm going to conclude it cannot be done.
There's already a module explicitly named 'getopt':
Even the default for getopt does not permute, there's a more explicitly defined method named
gnu_getopt()
:In the getopt docs, the above reference to argparse is further exaggerated by the inclusion of the following:
Again, nothing definitive, but, to me, a very sharp divide is being drawn between getopt and argparse with the documentation favoring/advocating argparse.
Here's an example using
gnu_getop()
which satifies your-z [file [file]]
test:Edit 1: Go Permute Yourself, with argparse
Inspired by the definition of "permute" in the 'Using Getopt' page you linked to,
how about permuting the arg string before passing it to
parse_args()
?Rolling your own:
Leveraging getopt: