From: Daniel Mach Date: Wed, 21 Feb 2024 13:58:04 +0000 (+0100) Subject: gh-96310: Fix a traceback in argparse when all options in a mutually exclusive group... X-Git-Tag: v3.13.0a5~294 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5f7df88821347c5f44fc4e2c691e83a60a6c6cd5;p=thirdparty%2FPython%2Fcpython.git gh-96310: Fix a traceback in argparse when all options in a mutually exclusive group are suppressed (GH-96311) Reproducer depends on terminal size - the traceback occurs when there's an option long enough so the usage line doesn't fit the terminal width. Option order is also important for reproducibility. Excluding empty groups (with all options suppressed) from inserts fixes the problem. --- diff --git a/Lib/argparse.py b/Lib/argparse.py index ea39d26687b9..f86658baf7f2 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -413,6 +413,8 @@ class HelpFormatter(object): suppressed_actions_count += 1 exposed_actions_count = group_action_count - suppressed_actions_count + if not exposed_actions_count: + continue if not group.required: if start in inserts: diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index 65fd9cf1a4a5..617b1721f3db 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -2864,6 +2864,27 @@ class TestMutuallyExclusiveGroupErrors(TestCase): ''' self.assertEqual(parser.format_help(), textwrap.dedent(expected)) + def test_help_subparser_all_mutually_exclusive_group_members_suppressed(self): + self.maxDiff = None + parser = ErrorRaisingArgumentParser(prog='PROG') + commands = parser.add_subparsers(title="commands", dest="command") + cmd_foo = commands.add_parser("foo") + group = cmd_foo.add_mutually_exclusive_group() + group.add_argument('--verbose', action='store_true', help=argparse.SUPPRESS) + group.add_argument('--quiet', action='store_true', help=argparse.SUPPRESS) + longopt = '--' + 'long'*32 + longmeta = 'LONG'*32 + cmd_foo.add_argument(longopt) + expected = f'''\ + usage: PROG foo [-h] + [{longopt} {longmeta}] + + options: + -h, --help show this help message and exit + {longopt} {longmeta} + ''' + self.assertEqual(cmd_foo.format_help(), textwrap.dedent(expected)) + def test_empty_group(self): # See issue 26952 parser = argparse.ArgumentParser() diff --git a/Misc/NEWS.d/next/Library/2022-08-26-15-50-53.gh-issue-96310.0NssDh.rst b/Misc/NEWS.d/next/Library/2022-08-26-15-50-53.gh-issue-96310.0NssDh.rst new file mode 100644 index 000000000000..f8efb0002e10 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-08-26-15-50-53.gh-issue-96310.0NssDh.rst @@ -0,0 +1,2 @@ +Fix a traceback in :mod:`argparse` when all options in a mutually exclusive +group are suppressed.