#9444: use first of prefix_chars for help opt instead of raising error
An argparse option parser created with a prefix_chars that did not
include a '-' would happily add -h and --help options, and then throw
an error when it tried to format the help because the - was an invalid
prefix character. This patch makes it use the first character of
prefix_chars as the character for the help options if and only if '-'
is not one of the valid prefix_chars.
Fix by Theodore Turocy, unit tests by Catherine Devlin.
diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py
index 94cd3d3..cf0f8e4 100644
--- a/Lib/test/test_argparse.py
+++ b/Lib/test/test_argparse.py
@@ -417,7 +417,7 @@
class TestOptionalsAlternatePrefixChars(ParserTestCase):
- """Test an Optional with a double-dash option string"""
+ """Test an Optional with option strings with custom prefixes"""
parser_signature = Sig(prefix_chars='+:/', add_help=False)
argument_signatures = [
@@ -425,6 +425,28 @@
Sig('::bar'),
Sig('/baz', action='store_const', const=42),
]
+ failures = ['--bar', '-fbar', '-b B', 'B', '-f', '--bar B', '-baz', '-h', '--help', '+h', '::help', '/help']
+ successes = [
+ ('', NS(f=False, bar=None, baz=None)),
+ ('+f', NS(f=True, bar=None, baz=None)),
+ ('::ba B', NS(f=False, bar='B', baz=None)),
+ ('+f ::bar B', NS(f=True, bar='B', baz=None)),
+ ('+f /b', NS(f=True, bar=None, baz=42)),
+ ('/ba +f', NS(f=True, bar=None, baz=42)),
+ ]
+
+
+class TestOptionalsAlternatePrefixCharsAddedHelp(ParserTestCase):
+ """When ``-`` not in prefix_chars, default operators created for help
+ should use the prefix_chars in use rather than - or --
+ http://bugs.python.org/issue9444"""
+
+ parser_signature = Sig(prefix_chars='+:/', add_help=True)
+ argument_signatures = [
+ Sig('+f', action='store_true'),
+ Sig('::bar'),
+ Sig('/baz', action='store_const', const=42),
+ ]
failures = ['--bar', '-fbar', '-b B', 'B', '-f', '--bar B', '-baz']
successes = [
('', NS(f=False, bar=None, baz=None)),
@@ -432,10 +454,9 @@
('::ba B', NS(f=False, bar='B', baz=None)),
('+f ::bar B', NS(f=True, bar='B', baz=None)),
('+f /b', NS(f=True, bar=None, baz=42)),
- ('/ba +f', NS(f=True, bar=None, baz=42)),
+ ('/ba +f', NS(f=True, bar=None, baz=42))
]
-
class TestOptionalsShortLong(ParserTestCase):
"""Test a combination of single- and double-dash option strings"""
@@ -1655,12 +1676,18 @@
def assertArgumentParserError(self, *args, **kwargs):
self.assertRaises(ArgumentParserError, *args, **kwargs)
- def _get_parser(self, subparser_help=False):
+ def _get_parser(self, subparser_help=False, prefix_chars=None):
# create a parser with a subparsers argument
- parser = ErrorRaisingArgumentParser(
- prog='PROG', description='main description')
- parser.add_argument(
- '--foo', action='store_true', help='foo help')
+ if prefix_chars:
+ parser = ErrorRaisingArgumentParser(
+ prog='PROG', description='main description', prefix_chars=prefix_chars)
+ parser.add_argument(
+ prefix_chars[0] * 2 + 'foo', action='store_true', help='foo help')
+ else:
+ parser = ErrorRaisingArgumentParser(
+ prog='PROG', description='main description')
+ parser.add_argument(
+ '--foo', action='store_true', help='foo help')
parser.add_argument(
'bar', type=float, help='bar help')
@@ -1739,6 +1766,44 @@
--foo foo help
'''))
+ def test_help_extra_prefix_chars(self):
+ # Make sure - is still used for help if it is a non-first prefix char
+ parser = self._get_parser(prefix_chars='+:-')
+ self.assertEqual(parser.format_usage(),
+ 'usage: PROG [-h] [++foo] bar {1,2} ...\n')
+ self.assertEqual(parser.format_help(), textwrap.dedent('''\
+ usage: PROG [-h] [++foo] bar {1,2} ...
+
+ main description
+
+ positional arguments:
+ bar bar help
+ {1,2} command help
+
+ optional arguments:
+ -h, --help show this help message and exit
+ ++foo foo help
+ '''))
+
+
+ def test_help_alternate_prefix_chars(self):
+ parser = self._get_parser(prefix_chars='+:/')
+ self.assertEqual(parser.format_usage(),
+ 'usage: PROG [+h] [++foo] bar {1,2} ...\n')
+ self.assertEqual(parser.format_help(), textwrap.dedent('''\
+ usage: PROG [+h] [++foo] bar {1,2} ...
+
+ main description
+
+ positional arguments:
+ bar bar help
+ {1,2} command help
+
+ optional arguments:
+ +h, ++help show this help message and exit
+ ++foo foo help
+ '''))
+
def test_parser_command_help(self):
self.assertEqual(self.command_help_parser.format_usage(),
'usage: PROG [-h] [--foo] bar {1,2} ...\n')