summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwim glenn <wim.glenn@gmail.com>2018-06-08 10:12:49 (GMT)
committerNick Coghlan <ncoghlan@gmail.com>2018-06-08 10:12:49 (GMT)
commit66f02aa32f1e4adb9f24cf186f8c495399d5ce9b (patch)
treea054fae38e3c08132961014dfa76961ac132f326
parentff6c07729211fb98431a2793e074d07a21e0650a (diff)
downloadcpython-66f02aa32f1e4adb9f24cf186f8c495399d5ce9b.zip
cpython-66f02aa32f1e4adb9f24cf186f8c495399d5ce9b.tar.gz
cpython-66f02aa32f1e4adb9f24cf186f8c495399d5ce9b.tar.bz2
bpo-11874: fix assertion failure in argparse metavar handling (GH-1826)
- bugfix and test for fragile metavar handling in argparse (see bpo-24089, bpo-14046, bpo-25058, bpo-11874) - also fixes some incorrect tests that did not make 1-element tuples correctly
-rw-r--r--Lib/argparse.py6
-rw-r--r--Lib/test/test_argparse.py42
-rw-r--r--Misc/NEWS.d/next/Library/2018-05-23-00-26-27.bpo-11874.glK5iP.rst2
3 files changed, 40 insertions, 10 deletions
diff --git a/Lib/argparse.py b/Lib/argparse.py
index e0e367b..a030749 100644
--- a/Lib/argparse.py
+++ b/Lib/argparse.py
@@ -327,7 +327,11 @@ class HelpFormatter(object):
if len(prefix) + len(usage) > text_width:
# break usage into wrappable parts
- part_regexp = r'\(.*?\)+|\[.*?\]+|\S+'
+ part_regexp = (
+ r'\(.*?\)+(?=\s|$)|'
+ r'\[.*?\]+(?=\s|$)|'
+ r'\S+'
+ )
opt_usage = format(optionals, groups)
pos_usage = format(positionals, groups)
opt_parts = _re.findall(part_regexp, opt_usage)
diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py
index bcf15ce..85449c7 100644
--- a/Lib/test/test_argparse.py
+++ b/Lib/test/test_argparse.py
@@ -4955,7 +4955,7 @@ class TestAddArgumentMetavar(TestCase):
self.do_test_exception(nargs=None, metavar=tuple())
def test_nargs_None_metavar_length1(self):
- self.do_test_no_exception(nargs=None, metavar=("1"))
+ self.do_test_no_exception(nargs=None, metavar=("1",))
def test_nargs_None_metavar_length2(self):
self.do_test_exception(nargs=None, metavar=("1", "2"))
@@ -4972,7 +4972,7 @@ class TestAddArgumentMetavar(TestCase):
self.do_test_exception(nargs="?", metavar=tuple())
def test_nargs_optional_metavar_length1(self):
- self.do_test_no_exception(nargs="?", metavar=("1"))
+ self.do_test_no_exception(nargs="?", metavar=("1",))
def test_nargs_optional_metavar_length2(self):
self.do_test_exception(nargs="?", metavar=("1", "2"))
@@ -4989,7 +4989,7 @@ class TestAddArgumentMetavar(TestCase):
self.do_test_exception(nargs="*", metavar=tuple())
def test_nargs_zeroormore_metavar_length1(self):
- self.do_test_no_exception(nargs="*", metavar=("1"))
+ self.do_test_exception(nargs="*", metavar=("1",))
def test_nargs_zeroormore_metavar_length2(self):
self.do_test_no_exception(nargs="*", metavar=("1", "2"))
@@ -5006,7 +5006,7 @@ class TestAddArgumentMetavar(TestCase):
self.do_test_exception(nargs="+", metavar=tuple())
def test_nargs_oneormore_metavar_length1(self):
- self.do_test_no_exception(nargs="+", metavar=("1"))
+ self.do_test_exception(nargs="+", metavar=("1",))
def test_nargs_oneormore_metavar_length2(self):
self.do_test_no_exception(nargs="+", metavar=("1", "2"))
@@ -5023,7 +5023,7 @@ class TestAddArgumentMetavar(TestCase):
self.do_test_no_exception(nargs="...", metavar=tuple())
def test_nargs_remainder_metavar_length1(self):
- self.do_test_no_exception(nargs="...", metavar=("1"))
+ self.do_test_no_exception(nargs="...", metavar=("1",))
def test_nargs_remainder_metavar_length2(self):
self.do_test_no_exception(nargs="...", metavar=("1", "2"))
@@ -5040,7 +5040,7 @@ class TestAddArgumentMetavar(TestCase):
self.do_test_exception(nargs="A...", metavar=tuple())
def test_nargs_parser_metavar_length1(self):
- self.do_test_no_exception(nargs="A...", metavar=("1"))
+ self.do_test_no_exception(nargs="A...", metavar=("1",))
def test_nargs_parser_metavar_length2(self):
self.do_test_exception(nargs="A...", metavar=("1", "2"))
@@ -5057,7 +5057,7 @@ class TestAddArgumentMetavar(TestCase):
self.do_test_exception(nargs=1, metavar=tuple())
def test_nargs_1_metavar_length1(self):
- self.do_test_no_exception(nargs=1, metavar=("1"))
+ self.do_test_no_exception(nargs=1, metavar=("1",))
def test_nargs_1_metavar_length2(self):
self.do_test_exception(nargs=1, metavar=("1", "2"))
@@ -5074,7 +5074,7 @@ class TestAddArgumentMetavar(TestCase):
self.do_test_exception(nargs=2, metavar=tuple())
def test_nargs_2_metavar_length1(self):
- self.do_test_no_exception(nargs=2, metavar=("1"))
+ self.do_test_exception(nargs=2, metavar=("1",))
def test_nargs_2_metavar_length2(self):
self.do_test_no_exception(nargs=2, metavar=("1", "2"))
@@ -5091,7 +5091,7 @@ class TestAddArgumentMetavar(TestCase):
self.do_test_exception(nargs=3, metavar=tuple())
def test_nargs_3_metavar_length1(self):
- self.do_test_no_exception(nargs=3, metavar=("1"))
+ self.do_test_exception(nargs=3, metavar=("1",))
def test_nargs_3_metavar_length2(self):
self.do_test_exception(nargs=3, metavar=("1", "2"))
@@ -5118,6 +5118,30 @@ class TestImportStar(TestCase):
]
self.assertEqual(sorted(items), sorted(argparse.__all__))
+
+class TestWrappingMetavar(TestCase):
+
+ def setUp(self):
+ self.parser = ErrorRaisingArgumentParser(
+ 'this_is_spammy_prog_with_a_long_name_sorry_about_the_name'
+ )
+ # this metavar was triggering library assertion errors due to usage
+ # message formatting incorrectly splitting on the ] chars within
+ metavar = '<http[s]://example:1234>'
+ self.parser.add_argument('--proxy', metavar=metavar)
+
+ def test_help_with_metavar(self):
+ help_text = self.parser.format_help()
+ self.assertEqual(help_text, textwrap.dedent('''\
+ usage: this_is_spammy_prog_with_a_long_name_sorry_about_the_name
+ [-h] [--proxy <http[s]://example:1234>]
+
+ optional arguments:
+ -h, --help show this help message and exit
+ --proxy <http[s]://example:1234>
+ '''))
+
+
def test_main():
support.run_unittest(__name__)
# Remove global references to avoid looking like we have refleaks.
diff --git a/Misc/NEWS.d/next/Library/2018-05-23-00-26-27.bpo-11874.glK5iP.rst b/Misc/NEWS.d/next/Library/2018-05-23-00-26-27.bpo-11874.glK5iP.rst
new file mode 100644
index 0000000..6c75f14
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2018-05-23-00-26-27.bpo-11874.glK5iP.rst
@@ -0,0 +1,2 @@
+Use a better regex when breaking usage into wrappable parts. Avoids bogus
+assertion errors from custom metavar strings.