Skip to content

GH-55797: Add ArgumentParser.add_mutually_inclusive_group#150981

Draft
savannahostrowski wants to merge 6 commits into
python:mainfrom
savannahostrowski:mutually-inclusive
Draft

GH-55797: Add ArgumentParser.add_mutually_inclusive_group#150981
savannahostrowski wants to merge 6 commits into
python:mainfrom
savannahostrowski:mutually-inclusive

Conversation

@savannahostrowski

@savannahostrowski savannahostrowski commented Jun 5, 2026

Copy link
Copy Markdown
Member

Adds ArgumentParser.add_mutually_inclusive_group(), a flat, symmetric
"all-or-nothing" group: the arguments in the group must either all be
provided together, or none of them.

group = parser.add_mutually_inclusive_group()
group.add_argument("--lport")
group.add_argument("--rport")
# both --lport and --rport, or neither; one alone is an error

It mirrors add_mutually_exclusive_group: required=True makes the group
mandatory, usage renders with & (e.g. [--lport LPORT & --rport RPORT]),
and parents=/subparsers are handled.

I have scoped deliberately to the flat, symmetric case and not nested boolean
composition which was deprecated 3.11 / removed 3.14, see #127133.

I'm still collecting some feedback on the issue so leaving this as a draft for now.

@savannahostrowski savannahostrowski added DO-NOT-MERGE 3.16 new features, bugs and security fixes labels Jun 5, 2026
@read-the-docs-community

read-the-docs-community Bot commented Jun 5, 2026

Copy link
Copy Markdown

Documentation build overview

📚 cpython-previews | 🛠️ Build #33204588 | 📁 Comparing e99601e against main (6544bf4)

  🔍 Preview build  

75 files changed · + 1 added · ± 74 modified

+ Added

± Modified

@savannahostrowski savannahostrowski changed the title gh-55797: Add ArgumentParser.add_mutually_inclusive_group GH-55797: Add ArgumentParser.add_mutually_inclusive_group Jun 5, 2026
@savannahostrowski savannahostrowski linked an issue Jun 9, 2026 that may be closed by this pull request

@clytaemnestra clytaemnestra left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand correctly, this is meant to mirror add_mutually_exclusive_group(). One thing I noticed: the exclusive group rejects a required=True member at setup time (ValueError: mutually exclusive arguments must be optional), but the inclusive group accepts it. I'm wondering how add_mutually_inclusive_group() should behave in that case?

For example, with a non-required group where one member is required=True:

>>> g = p.add_mutually_inclusive_group()
>>> g.add_argument("--foo")
_StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, required=False, help=None, metavar=None, deprecated=False)
>>> g.add_argument("--bar", required=True)
_StoreAction(option_strings=['--bar'], dest='bar', nargs=None, const=None, default=None, type=None, choices=None, required=True, help=None, metavar=None, deprecated=False)
>>> p.parse_args([])
usage: [-h] [--foo FOO & --bar BAR]
: error: the following arguments are required: --bar

Since the group is all-or-nothing, I'd have expected nothing (empty args) to be accepted, but --bar being required makes that impossible. Should this combination be guarded against (like the exclusive group does) or is it intended? Apologies if I'm missing something.

@savannahostrowski

Copy link
Copy Markdown
Member Author

@clytaemnestra Good catch - you're right, we need to add a guard to raise if someone tries to add required=True to an argument, since it doesn't really make sense at the member level.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3.16 new features, bugs and security fixes DO-NOT-MERGE

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add "necessarily inclusive" groups to argparse

2 participants