From 30e211c6e3971ceabc45e62ecc7e82789b743ad9 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 9 Oct 2024 21:42:48 +0300 Subject: [PATCH] gh-61011: Fix inheritance of nested mutually exclusive groups in argparse Previously, all nested mutually exclusive groups lost their connection to the group containing them and were displayed as belonging directly to the parser. Co-authored-by: Danica J. Sutherland --- Lib/argparse.py | 6 +++- Lib/test/test_argparse.py | 29 +++++++++++++++++++ Misc/ACKS | 1 + ...4-10-09-21-42-43.gh-issue-61011.pQXZb1.rst | 4 +++ 4 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2024-10-09-21-42-43.gh-issue-61011.pQXZb1.rst diff --git a/Lib/argparse.py b/Lib/argparse.py index 21299b69ecd74c..25b2a532e57e67 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -1521,7 +1521,11 @@ def _add_container_actions(self, container): # NOTE: if add_mutually_exclusive_group ever gains title= and # description= then this code will need to be expanded as above for group in container._mutually_exclusive_groups: - mutex_group = self.add_mutually_exclusive_group( + if group._container is container: + cont = self + else: + cont = title_group_map[group._container.title] + mutex_group = cont.add_mutually_exclusive_group( required=group.required) # map the actions to their new mutex group diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index 1bf812b36fc2c6..57d881796ffca2 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -2929,6 +2929,35 @@ def test_groups_parents(self): def test_wrong_type_parents(self): self.assertRaises(TypeError, ErrorRaisingArgumentParser, parents=[1]) + def test_mutex_groups_parents(self): + parent = ErrorRaisingArgumentParser(add_help=False) + g = parent.add_argument_group(title='g', description='gd') + g.add_argument('-w') + g.add_argument('-x') + m = g.add_mutually_exclusive_group() + m.add_argument('-y') + m.add_argument('-z') + parser = ErrorRaisingArgumentParser(prog='PROG', parents=[parent]) + + self.assertRaises(ArgumentParserError, parser.parse_args, + ['-y', 'Y', '-z', 'Z']) + + parser_help = parser.format_help() + self.assertEqual(parser_help, textwrap.dedent('''\ + usage: PROG [-h] [-w W] [-x X] [-y Y | -z Z] + + options: + -h, --help show this help message and exit + + g: + gd + + -w W + -x X + -y Y + -z Z + ''')) + # ============================== # Mutually exclusive group tests # ============================== diff --git a/Misc/ACKS b/Misc/ACKS index d94cbacf888468..a1769d9601a2ea 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1814,6 +1814,7 @@ Reuben Sumner Eryk Sun Sanjay Sundaresan Marek Ć uppa +Danica J. Sutherland Hisao Suzuki Kalle Svensson Andrew Svetlov diff --git a/Misc/NEWS.d/next/Library/2024-10-09-21-42-43.gh-issue-61011.pQXZb1.rst b/Misc/NEWS.d/next/Library/2024-10-09-21-42-43.gh-issue-61011.pQXZb1.rst new file mode 100644 index 00000000000000..20f9c0b9c78b12 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-10-09-21-42-43.gh-issue-61011.pQXZb1.rst @@ -0,0 +1,4 @@ +Fix inheritance of nested mutually exclusive groups from parent parser in +:class:`argparse.ArgumentParser`. Previously, all nested mutually exclusive +groups lost their connection to the group containing them and were displayed +as belonging directly to the parser.