Repository navigation
argparse.ArgumentParser.add_mutually_exclusive_group : metavar create parenthesis undefined behavior #89743
Description
Activity
Hi,
I'm getting a kind of undefined behavior where parenthesis seem handled in a strange way. On display, it has a conflict between parenthesis of the option, and nested parenthesis within a metavar.
## Reproduction script
import argparse def main(): parser = argparse.ArgumentParser() group = parser.add_mutually_exclusive_group(required=True) group.add_argument("-p", "--path", metavar="/var/www/html", help="DocumentRoot path") group.add_argument("-r", "--reverse", metavar="http)s(://Host:Port", help="Reverse proxy address") parser.add_argument("--last-args") return parser.parse_args() main()## Output of help menu
usage: crash.py [-h] (-p /var/www/html | -r http)s://Host:Port [--last-args LAST_ARGS]## Expected behavior
usage: crash.py [-h] (-p /var/www/html | -r http)s(://Host:Port) [--last-args LAST_ARGS]- addedinterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)3.9 (EOL)end of lifeend of life
on Oct 22, 2021 I confirm this happens on all recent Python versions.
The source of this problem is that
argparseusesregexmodule to replace some substrings. Direct link: https://github.com/python/cpython/blame/8ce20bbdd6d2b1277a5e74154fcdcef2cb0fee49/Lib/argparse.py#L487Quick debug showed that without this line these tests fail:
====================================================================== FAIL: test_help_when_required (test.test_argparse.TestMutuallyExclusiveFirstSuppressed) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/sobolev/Desktop/cpython/Lib/test/test_argparse.py", line 2649, in test_help_when_required self.assertEqual(format_help(), textwrap.dedent(help)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ AssertionError: 'usage: PROG [-h] (-y)\n\noptions:\n -h, --help show this[42 chars]lp\n' != 'usage: PROG [-h] -y\n\noptions:\n -h, --help show this h[40 chars]lp\n' - usage: PROG [-h] (-y) ? - - + usage: PROG [-h] -y options: -h, --help show this help message and exit -y y help ====================================================================== FAIL: test_usage_when_required (test.test_argparse.TestMutuallyExclusiveFirstSuppressed) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/sobolev/Desktop/cpython/Lib/test/test_argparse.py", line 2639, in test_usage_when_required self.assertEqual(format_usage(), textwrap.dedent(expected_usage)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ AssertionError: 'usage: PROG [-h] (-y)\n' != 'usage: PROG [-h] -y\n' - usage: PROG [-h] (-y) ? - - + usage: PROG [-h] -y ====================================================================== FAIL: test_help_when_required (test.test_argparse.TestMutuallyExclusiveFirstSuppressedParent) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/sobolev/Desktop/cpython/Lib/test/test_argparse.py", line 2649, in test_help_when_required self.assertEqual(format_help(), textwrap.dedent(help)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ AssertionError: 'usage: PROG [-h] (-y)\n\noptions:\n -h, --help show this[42 chars]lp\n' != 'usage: PROG [-h] -y\n\noptions:\n -h, --help show this h[40 chars]lp\n' - usage: PROG [-h] (-y) ? - - + usage: PROG [-h] -y options: -h, --help show this help message and exit -y y help ====================================================================== FAIL: test_usage_when_required (test.test_argparse.TestMutuallyExclusiveFirstSuppressedParent) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/sobolev/Desktop/cpython/Lib/test/test_argparse.py", line 2639, in test_usage_when_required self.assertEqual(format_usage(), textwrap.dedent(expected_usage)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ AssertionError: 'usage: PROG [-h] (-y)\n' != 'usage: PROG [-h] -y\n' - usage: PROG [-h] (-y) ? - - + usage: PROG [-h] -y ---------------------------------------------------------------------- Ran 1672 tests in 23.258s FAILED (failures=4) test test_argparse failed test_argparse failed (4 failures) == Tests result: FAILURE == 1 test failed: test_argparse Total duration: 25.6 sec Tests result: FAILUREMaybe instead we can show users something like:
usage: ex.py [-h] (-p '/var/www/html' | -r 'http)s(://Host:Port') [--last-args LAST_ARGS]?
- addedstdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directory3.10 (EOL)end of lifeend of life3.11only security fixesonly security fixestype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or errorand removedinterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)
on Oct 23, 2021 The usage formatting is fragile, with many associated bug reports. Until someone does a major rewrite, it is best to avoid special characters, especially
()and[]in thedestormetavar.Usage uses () to encolde mutually_exclusive_groups and [] to mark non-required arguments. Don't confuse your users (or argparse) with other uses of these characters.
- added a commit that references this issue
on May 28, 2023 This was fixed in #102318.
Metadata
Metadata
Assignees
Labels
Projects
- StatusShow more project fieldsDoc issues
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields: