msg152839 - (view) |
Author: László Attila Tóth (Laszlo.Attila.Toth) * |
Date: 2012-02-08 07:49 |
If someone ports his code from optparse to argparse, there is a limit, that options and non-options can be mixed by default, and this behaviour cannot be disabled easily, an extra '--' argument is required in the command line. In some cases it is much prettier to explicitly disable this, as was available in the deprecated optparse module. I attach a patch that does this, adds disable_interspersed_args() to argparse.ArgumentParser. |
|
|
msg153044 - (view) |
Author: Christophe Kalt (kalt) |
Date: 2012-02-10 13:50 |
nice, thank you! |
|
|
msg153087 - (view) |
Author: Steven Bethard (bethard) *  |
Date: 2012-02-11 03:54 |
The idea and patch seem okay to me. Needs tests though. |
|
|
msg153552 - (view) |
Author: László Attila Tóth (Laszlo.Attila.Toth) * |
Date: 2012-02-17 15:46 |
I added unit test, which revealed some bugs. These are fixe now. The attached file contains both the unit tests and the updated patch. |
|
|
msg166079 - (view) |
Author: Steven Bethard (bethard) *  |
Date: 2012-07-21 21:51 |
The argparse changes and tests look good. The new method needs to be documented. You can see some other things (e.g. Misc/NEWS) that also need to be updated by running "make patchcheck" as described here: http://docs.python.org/devguide/patch.html |
|
|
msg181164 - (view) |
Author: László Attila Tóth (Laszlo.Attila.Toth) * |
Date: 2013-02-02 11:54 |
Unfortunatelly the implementation bugous as of now. I wrote additional tests. self.parser = ErrorRaisingArgumentParser() self.parser.add_argument('-a', action='store_true') self.parser.add_argument('-b') self.parser.add_argument('rem', nargs=argparse.REMAINDER) self.assertEquals(self.parser.parse_args('-b 4 -a -b 5'.split()), NS(a=True, b='5', rem=[])) This part is OK. But with the new option: self.parser.disable_interspersed_args() self.assertEquals(self.parser.parse_args('-b 4 -a -b 5'.split()), NS(a=False, b='4', rem=['-a', '-b', '5'])) This assertation also passes because it contains the actual result, which is unexpected. This is because the code doesn't handle properly the arguments that are non-options, such as '-b' in this case. I can't see a good solution for this. |
|
|
msg185993 - (view) |
Author: paul j3 (paul.j3) *  |
Date: 2013-04-04 02:12 |
The optparse page gives a reason for disable_interspersed_args(): "Use this if you have a command processor which runs another command which has options of its own and you want to make sure these options don’t get confused. For example, each command might have a different set of options." In argparse: "argparse.REMAINDER. All the remaining command-line arguments are gathered into a list. This is commonly useful for command line utilities that dispatch to other command line utilities:" If you have only one positional argument, and its nargs is REMAINDER, you have effectively disabled interspersed. Argparse doesn't prohibit all interspersed positionals. You could, for example, have one or more positionals with other nargs that could be interspersed. But the REMAINDER one has to be last. In the library, profile.py uses 'optparse.disable_interspersed'. I just replaced optparse with argparse using the REMAINDER, and got the same behavior. (Actually I used argparse.PARSER which effectively requires at least one argument.) |
|
|
msg186000 - (view) |
Author: paul j3 (paul.j3) *  |
Date: 2013-04-04 03:26 |
Oops, I was wrong about this: "Argparse doesn't prohibit all interspersed positionals. You could, for example, have one or more positionals with other nargs that could be interspersed. But the REMAINDER one has to be last." parser.add_argument('a') parser.add_argument('--foo') parser.add_argument('rest', nargs='...') parser.parse_args('a --foo b c'.split(' ') produces: Namespace(a='a', foo=None, rest=['--foo', 'b', 'c']) That is because, 'rest' matches an empty list of arguments. With an nargs='*' or '?', the same thing happens, both 'a' and 'rest' are used up when processing the first positional argument string. nargs=argparse.PARSER (= 'A...') gives the expected Namespace(a='a', foo='b', rest=['c']) In this case, 'rest' has to wait till the second set of positionals. Documentation warns "Note that it generally doesn’t make much sense to have more than one positional argument with nargs='*'". Maybe it should warn against combining any of the 'zero or more' positionals with other positionals. |
|
|
msg186046 - (view) |
Author: paul j3 (paul.j3) *  |
Date: 2013-04-04 17:39 |
Looking further at test_argparse.py, I should say that the behavior of multiple positionals when there is one cluster of positional argstrings is well illustrated in the tests. It's the behavior when there are multiple clusters (interspersed positionals) that can go against some intuitions. |
|
|
msg216882 - (view) |
Author: paul j3 (paul.j3) *  |
Date: 2014-04-19 21:48 |
http://bugs.python.org/issue14191 implements the other side of optparse behavior - allowing a complete intermixing of optionals and positionals. It does that with a new 'ArgumentParser.parse_intermixed_args()' method. |
|
|
msg236882 - (view) |
Author: László Attila Tóth (Laszlo.Attila.Toth) * |
Date: 2015-02-28 13:35 |
It seems I found the solution in the attached file argparse.disable_interspersed_args.python35.diff, and it's much-much easier than I thought. I assume that this patch can cleanly applied to earlier versions (python 3.2-3.4), but I didn't check it. |
|
|