You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
argparse.add_mutually_exclusive_group fails for optional positional arguments #86020
group=parser.add_mutually_exclusive_group()
group.add_argument('--install-only', action='store_true',
help='just install the program, do not run it')
group.add_argument('args', metavar='ARGUMENT', nargs='*', default=None,
help='arguments to PROGRAM')
group.add_argument('args', metavar='ARGUMENT', nargs='*', default=[],
help='arguments to PROGRAM')
Since a '*' or '?' positional works with an empty list of arguments, it is "always seen". It requires some special handling to allow it to work in the mutually exclusive context. It's a tricky piece of code that might not be well documented (if at all).
rrt commented on Oct 17, 2020
rrtmannequin
MannequinAuthor
More actions
Thanks for the hint; could this be documented, please?
There's another issue here, even with the workaround above: help output for positional parameters appearing as part of mutually exclusive groups is often broken.
Specifically: when a mutually exclusive group contains positional arguments and the usage line in the --help output is long enough that it needs to be wrapped, the group is no longer displayed as mutually exclusive.
If you ask for --help with a wide enough terminal, you'll see correct output, with the "only" flags marked as mutually exclusive to the positional parameters:
Removing the position parameters (ie: delete the group.add_argument('positional', ...)) gives the correct output. Even in very small terminals (30 columns), it absolutely refuses to ever split the group onto multiple lines:
but considers them separately in case the output is too long:
# wrap the usage parts if it's too longtext_width=self._width-self._current_indentiflen(prefix) +len(usage) >text_width:
...
opt_usage=format(optionals, groups)
pos_usage=format(positionals, groups)
which is exacerbated by this code in _format_actions_usage() which assumes that the actions will be presented for formatting, complete, and in exactly the same order as they appear in the group:
Indeed, if you insert the positional parameters into group before the flag parameters, the grouping will always be broken, even if the terminal is infinitely wide:
The original issue was fixed (see #72795). Now positional arguments with nargs='*' are always considered optional, independently from the default value.
The bug reported in #86020 (comment) is unrelated to this. It is either a duplicate of #75949 or closely related.
Activity
rrt commentedon Sep 24, 2020
The following code:
gives the following error:
But the 'args' argument *is* optional, as there can be 0 of them.
paulj3 commentedon Oct 17, 2020
Give the positional a non-none default:
e.g.
Since a '*' or '?' positional works with an empty list of arguments, it is "always seen". It requires some special handling to allow it to work in the mutually exclusive context. It's a tricky piece of code that might not be well documented (if at all).
rrt commentedon Oct 17, 2020
Thanks for the hint; could this be documented, please?
allisonkarlitskaya commentedon May 2, 2022
There's another issue here, even with the workaround above: help output for positional parameters appearing as part of mutually exclusive groups is often broken.
Specifically: when a mutually exclusive group contains positional arguments and the usage line in the
--helpoutput is long enough that it needs to be wrapped, the group is no longer displayed as mutually exclusive.Here's an example:
If you ask for
--helpwith a wide enough terminal, you'll see correct output, with the "only" flags marked as mutually exclusive to the positional parameters:but if you make your terminal smaller, you get (incorrect):
Removing the position parameters (ie: delete the
group.add_argument('positional', ...)) gives the correct output. Even in very small terminals (30 columns), it absolutely refuses to ever split the group onto multiple lines:This seems to be caused by the code in
_format_usage()which attempts to consideroptionalsandpositionalstogether in the unwrapped case:but considers them separately in case the output is too long:
which is exacerbated by this code in
_format_actions_usage()which assumes that the actions will be presented for formatting, complete, and in exactly the same order as they appear in the group:Indeed, if you insert the positional parameters into group before the flag parameters, the grouping will always be broken, even if the terminal is infinitely wide:
produces this incorrect output:
serhiy-storchaka commentedon Oct 10, 2024
The original issue was fixed (see #72795). Now positional arguments with
nargs='*'are always considered optional, independently from the default value.The bug reported in #86020 (comment) is unrelated to this. It is either a duplicate of #75949 or closely related.