This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: argparse unexpected behavior with argument group inside mutually exclusive group
Type: behavior Stage: resolved
Components: Library (Lib) Versions: Python 3.9, Python 3.8, Python 3.7, Python 3.6, Python 3.5, Python 2.7
process
Status: closed Resolution: duplicate
Dependencies: Superseder: Deprecate unsupported nesting of argparse groups
View: 22047
Assigned To: Nosy List: Tim Sanders, iritkatriel, paul.j3
Priority: normal Keywords:

Created on 2019-10-25 18:13 by Tim Sanders, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Messages (3)
msg355370 - (view) Author: Tim Sanders (Tim Sanders) Date: 2019-10-25 18:13
argparse allows adding argument_groups inside of mutually_exclusive_groups, but the behavior is unintuitive and a bit buggy.

Demo:


import argparse

parser = argparse.ArgumentParser()
single_group = parser.add_argument_group(title='single_group')
single_group.add_argument('--a', action='store_true')

mutex_group = parser.add_mutually_exclusive_group()
mutex_group.add_argument('--b', action='store_true')

nested_group = mutex_group.add_argument_group(title='nested_group')
nested_group.add_argument('--c', action='store_true')
nested_group.add_argument('--d', action='store_true')

parser.print_help()
print(parser.parse_args())


Example output:


$ ~/test_args.py --a --b --c --d
usage: test_args.py [-h] [--a] [--b] [--c] [--d]

optional arguments:
  -h, --help  show this help message and exit
  --b

single_group:
  --a
Namespace(a=True, b=True, c=True, d=True)



Two issues I've noticed with this:
 - Arguments in the nested group show up in the usage string, but not in the help text.  The nested arguments are still parsed and available in the result, as normal.
 - Arguments in the nested group are not mutually exclusive with any arguments in the containing mutually_exclusive_group.  
   - I would expect:
       --b          ok
       --c          ok
       --d          ok
       --b --c      error
       --b --d      error
       --c --d      error*
       --b --c --d  error

*From a design perspective, it seems like argument_groups are meant to control display, and mutually_exclusive_groups are meant to control logic, so I think "error" makes sense here.  I personally would like the ability to allow "--c --d", but I think that's a separate discussion and probably a new type of group.
msg356004 - (view) Author: paul j3 (paul.j3) * (Python triager) Date: 2019-11-05 06:19
With one exception, groups are not designed or intended to be nested.  But by inheritance (from _ActionsContainer) nesting isn't blocked nor does it raise any errors.

As you surmise, an ArgumentGroup, is used only for grouping the help lines.  By default that are two groups, with 'optionals' and 'required' names (actually the later should be 'positional').  The rest are user defined.  They don't affect parsing in any way.

MutuallyExclusiveGroup is used in parsing.  It also is used, to the extent possible, when formatting usage.

If a MutuallyExclusiveGroup is nested inside another MutuallyExclusiveGroup the parsing effect is just one flat group.  Usage can be messed up - that's been the subject of another bug/issue.

A MutuallyExclusiveGroup may be put in an ArgumentGroup.  This is a way of giving the exclusive group a title and/or description in the help.

There is a bug/issue requesting some sort of inclusive group.  I tried to develop such a patch, implementing nesting, complete logic control (not just the current xor).  But the usage formatting needs a complete rewrite.  Overall this is too complex of an addition.  On StackOverFlow I tell people to implement their own post-parsing testing.
msg408716 - (view) Author: Irit Katriel (iritkatriel) * (Python committer) Date: 2021-12-16 15:39
Nesting argument groups and mutually exclusive groups is now deprecated (see issue22047). Thank you for the bug report.
History
Date User Action Args
2022-04-11 14:59:22adminsetgithub: 82771
2021-12-16 15:39:12iritkatrielsetstatus: open -> closed

superseder: Deprecate unsupported nesting of argparse groups

nosy: + iritkatriel
messages: + msg408716
resolution: duplicate
stage: resolved
2019-11-05 06:19:40paul.j3setnosy: + paul.j3
messages: + msg356004
2019-10-25 18:13:04Tim Sanderscreate