diff --git a/Lib/argparse.py b/Lib/argparse.py index 7988c447d03584..e9bcdb0a0e0c13 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -600,7 +600,11 @@ def _expand_help(self, action): if params.get('choices') is not None: choices_str = ', '.join([str(c) for c in params['choices']]) params['choices'] = choices_str - return self._get_help_string(action) % params + expanded_help = self._get_help_string(action) + for param, value in params.items(): + if f'%({param})s' in expanded_help: + expanded_help = expanded_help.replace(f'%({param})s', str(value)) + return expanded_help.replace('%%','%') def _iter_indented_subactions(self, action): try: diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index 138ff19e86acf4..9ec022da6046d7 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -3954,6 +3954,39 @@ class TestHelpUsageWithParentheses(HelpTestCase): ''' version = '' +class TestHelpWithPercentageSymbols(HelpTestCase): + """Test a help message including % symbols""" + parser_signature = Sig(prog='PROG', description='Just a test code.') + argument_signatures = [ + Sig('--somearg', metavar='somearg', + help='Now you dont need to escape this: %, and you will not get nonsensical errors!'), + Sig('--date', metavar='when', help='A date in format %Y-%m-%d', + dest=f'date', type=str, required=True), + Sig('bar', nargs='?', type=int, default=42, + help='the bar to %(prog)s (default: %(default)s)'), + Sig('--weirdarg', metavar='weird', dest=f'weird', type=str, + required=True, help='A weird arg with 1 %, 2 %%% and 3 %%%%%'), + ] + + usage = '''\ + usage: PROG [-h] [--somearg somearg] --date when --weirdarg weird [bar] + ''' + help = usage + '''\ + + Just a test code. + + positional arguments: + bar the bar to PROG (default: 42) + + options: + -h, --help show this help message and exit + --somearg somearg Now you dont need to escape this: %, and you will not get + nonsensical errors! + --date when A date in format %Y-%m-%d + --weirdarg weird A weird arg with 1 %, 2 %% and 3 %%% + ''' + version = '' + class TestHelpOnlyUserGroups(HelpTestCase): """Test basic usage messages""" diff --git a/Misc/NEWS.d/next/Library/2023-08-23-01-09-48.gh-issue-44986.euCjji.rst b/Misc/NEWS.d/next/Library/2023-08-23-01-09-48.gh-issue-44986.euCjji.rst new file mode 100644 index 00000000000000..d5d963c371845f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-08-23-01-09-48.gh-issue-44986.euCjji.rst @@ -0,0 +1,6 @@ +Added feature to argparse so that percentage symbols (%) don't have to be +escaped in help messages. Without this fix, they have to be escaped (as +stated in the documentation) but if you forget this, the error message that +is produced is completely cryptic. With this patch, 1) this does not happen +anymore, 2) single % don't need to be escaped and 3) it remains fully +compatible with the previous implementation.