https://github.com/python/cpython/commit/1dfe219fec324611c3fe6282fd8628e94d940ada commit: 1dfe219fec324611c3fe6282fd8628e94d940ada branch: 3.14 author: Miss Islington (bot) <[email protected]> committer: serhiy-storchaka <[email protected]> date: 2025-12-06T18:28:54Z summary:
[3.14] gh-142332: Fix usage formatting for positional arguments in mutually exclusive groups in argparse (GH-142333) (GH-142356) (cherry picked from commit 70c27ce94b2c18f375c10e508e7d9323ae795496) Co-authored-by: Serhiy Storchaka <[email protected]> files: A Misc/NEWS.d/next/Library/2025-12-06-13-02-13.gh-issue-142332.PNvXCV.rst M Lib/argparse.py M Lib/test/test_argparse.py diff --git a/Lib/argparse.py b/Lib/argparse.py index 8fda5b844aef6c..665d4429461208 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -470,16 +470,12 @@ def _get_actions_usage_parts_with_split(self, actions, groups, opt_count=None): # produce all arg strings elif not action.option_strings: default = self._get_default_metavar_for_positional(action) - part = ( - t.summary_action - + self._format_args(action, default) - + t.reset - ) - + part = self._format_args(action, default) # if it's in a group, strip the outer [] if action in group_actions: if part[0] == '[' and part[-1] == ']': part = part[1:-1] + part = t.summary_action + part + t.reset # produce the first way to invoke the option in brackets else: diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index aa32cb00325aeb..02753b2fd35ec2 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -7275,7 +7275,28 @@ def test_argparse_color(self): ), ) - def test_argparse_color_usage(self): + def test_argparse_color_mutually_exclusive_group_usage(self): + parser = argparse.ArgumentParser(color=True, prog="PROG") + group = parser.add_mutually_exclusive_group() + group.add_argument('--foo', action='store_true', help='FOO') + group.add_argument('--spam', help='SPAM') + group.add_argument('badger', nargs='*', help='BADGER') + + prog = self.theme.prog + heading = self.theme.heading + long = self.theme.summary_long_option + short = self.theme.summary_short_option + label = self.theme.summary_label + pos = self.theme.summary_action + reset = self.theme.reset + + self.assertEqual(parser.format_usage(), + f"{heading}usage: {reset}{prog}PROG{reset} [{short}-h{reset}] " + f"[{long}--foo{reset} | " + f"{long}--spam {label}SPAM{reset} | " + f"{pos}badger ...{reset}]\n") + + def test_argparse_color_custom_usage(self): # Arrange parser = argparse.ArgumentParser( add_help=False, diff --git a/Misc/NEWS.d/next/Library/2025-12-06-13-02-13.gh-issue-142332.PNvXCV.rst b/Misc/NEWS.d/next/Library/2025-12-06-13-02-13.gh-issue-142332.PNvXCV.rst new file mode 100644 index 00000000000000..ee2d5e1d4911a7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-12-06-13-02-13.gh-issue-142332.PNvXCV.rst @@ -0,0 +1,2 @@ +Fix usage formatting for positional arguments in mutually exclusive groups in :mod:`argparse`. +in :mod:`argparse`. _______________________________________________ Python-checkins mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3//lists/python-checkins.python.org Member address: [email protected]
