gh-88753: Make BooleanOptionalAction's addition of default to help more similar to other actions (#27808)

Help for other actions omit the default value if default is SUPPRESS or
already contains the special format string '%(default)'.  Add those
special cases to BooleanOptionalAction's help formatting too.

Fixes https://bugs.python.org/issue44587 so that default=SUPPRESS is not
emitted.

Fixes https://bugs.python.org/issue38956 as this code will detect
whether '%(default)s' has already been specified in the help string.

Signed-off-by: Micky Yun Chan (michiboo): <chanmickyyun@gmail.com>
Co-authored-by: Micky Yun Chan <michan@redhat.com>
This commit is contained in:
Toshio Kuratomi 2022-05-03 09:38:18 -07:00 committed by GitHub
parent 6c25bf07e8
commit 20490d5018
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 32 additions and 16 deletions

View file

@ -153,6 +153,7 @@ def _copy_items(items):
# Formatting Help # Formatting Help
# =============== # ===============
class HelpFormatter(object): class HelpFormatter(object):
"""Formatter for generating usage messages and argument help strings. """Formatter for generating usage messages and argument help strings.
@ -695,8 +696,19 @@ class ArgumentDefaultsHelpFormatter(HelpFormatter):
""" """
def _get_help_string(self, action): def _get_help_string(self, action):
"""
Add the default value to the option help message.
ArgumentDefaultsHelpFormatter and BooleanOptionalAction when it isn't
already present. This code will do that, detecting cornercases to
prevent duplicates or cases where it wouldn't make sense to the end
user.
"""
help = action.help help = action.help
if '%(default)' not in action.help: if help is None:
help = ''
if '%(default)' not in help:
if action.default is not SUPPRESS: if action.default is not SUPPRESS:
defaulting_nargs = [OPTIONAL, ZERO_OR_MORE] defaulting_nargs = [OPTIONAL, ZERO_OR_MORE]
if action.option_strings or action.nargs in defaulting_nargs: if action.option_strings or action.nargs in defaulting_nargs:
@ -704,6 +716,7 @@ class ArgumentDefaultsHelpFormatter(HelpFormatter):
return help return help
class MetavarTypeHelpFormatter(HelpFormatter): class MetavarTypeHelpFormatter(HelpFormatter):
"""Help message formatter which uses the argument 'type' as the default """Help message formatter which uses the argument 'type' as the default
metavar value (instead of the argument 'dest') metavar value (instead of the argument 'dest')
@ -719,7 +732,6 @@ class MetavarTypeHelpFormatter(HelpFormatter):
return action.type.__name__ return action.type.__name__
# ===================== # =====================
# Options and Arguments # Options and Arguments
# ===================== # =====================
@ -882,9 +894,6 @@ class BooleanOptionalAction(Action):
option_string = '--no-' + option_string[2:] option_string = '--no-' + option_string[2:]
_option_strings.append(option_string) _option_strings.append(option_string)
if help is not None and default is not None and default is not SUPPRESS:
help += " (default: %(default)s)"
super().__init__( super().__init__(
option_strings=_option_strings, option_strings=_option_strings,
dest=dest, dest=dest,
@ -896,6 +905,7 @@ class BooleanOptionalAction(Action):
help=help, help=help,
metavar=metavar) metavar=metavar)
def __call__(self, parser, namespace, values, option_string=None): def __call__(self, parser, namespace, values, option_string=None):
if option_string in self.option_strings: if option_string in self.option_strings:
setattr(namespace, self.dest, not option_string.startswith('--no-')) setattr(namespace, self.dest, not option_string.startswith('--no-'))

View file

@ -3348,6 +3348,7 @@ class TestHelpFormattingMetaclass(type):
def _test(self, tester, parser_text): def _test(self, tester, parser_text):
expected_text = getattr(tester, self.func_suffix) expected_text = getattr(tester, self.func_suffix)
expected_text = textwrap.dedent(expected_text) expected_text = textwrap.dedent(expected_text)
tester.maxDiff = None
tester.assertEqual(expected_text, parser_text) tester.assertEqual(expected_text, parser_text)
def test_format(self, tester): def test_format(self, tester):
@ -3743,7 +3744,7 @@ class TestHelpUsage(HelpTestCase):
-w W [W ...] w -w W [W ...] w
-x [X ...] x -x [X ...] x
--foo, --no-foo Whether to foo --foo, --no-foo Whether to foo
--bar, --no-bar Whether to bar (default: True) --bar, --no-bar Whether to bar
-f, --foobar, --no-foobar, --barfoo, --no-barfoo -f, --foobar, --no-foobar, --barfoo, --no-barfoo
--bazz, --no-bazz Bazz! --bazz, --no-bazz Bazz!
@ -4423,6 +4424,8 @@ class TestHelpArgumentDefaults(HelpTestCase):
Sig('--bar', action='store_true', help='bar help'), Sig('--bar', action='store_true', help='bar help'),
Sig('--taz', action=argparse.BooleanOptionalAction, Sig('--taz', action=argparse.BooleanOptionalAction,
help='Whether to taz it', default=True), help='Whether to taz it', default=True),
Sig('--corge', action=argparse.BooleanOptionalAction,
help='Whether to corge it', default=argparse.SUPPRESS),
Sig('--quux', help="Set the quux", default=42), Sig('--quux', help="Set the quux", default=42),
Sig('spam', help='spam help'), Sig('spam', help='spam help'),
Sig('badger', nargs='?', default='wooden', help='badger help'), Sig('badger', nargs='?', default='wooden', help='badger help'),
@ -4432,8 +4435,8 @@ class TestHelpArgumentDefaults(HelpTestCase):
[Sig('--baz', type=int, default=42, help='baz help')]), [Sig('--baz', type=int, default=42, help='baz help')]),
] ]
usage = '''\ usage = '''\
usage: PROG [-h] [--foo FOO] [--bar] [--taz | --no-taz] [--quux QUUX] usage: PROG [-h] [--foo FOO] [--bar] [--taz | --no-taz] [--corge | --no-corge]
[--baz BAZ] [--quux QUUX] [--baz BAZ]
spam [badger] spam [badger]
''' '''
help = usage + '''\ help = usage + '''\
@ -4449,6 +4452,7 @@ class TestHelpArgumentDefaults(HelpTestCase):
--foo FOO foo help - oh and by the way, None --foo FOO foo help - oh and by the way, None
--bar bar help (default: False) --bar bar help (default: False)
--taz, --no-taz Whether to taz it (default: True) --taz, --no-taz Whether to taz it (default: True)
--corge, --no-corge Whether to corge it
--quux QUUX Set the quux (default: 42) --quux QUUX Set the quux (default: 42)
title: title:

View file

@ -0,0 +1,2 @@
Fix BooleanOptionalAction to not automatically add a default string. If a
default string is desired, use a formatter to add it.