diff options
author | Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> | 2018-06-08 04:33:50 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-06-08 04:33:50 -0700 |
commit | 842985f6c70484ed7b8fc30d0bc05aec73236a98 (patch) | |
tree | 655d4d42b9d6ea6bb2c0e65c05f8774c19fca995 | |
parent | bpo-31215: Add version changed notes for OpenSSL 1.1.0 compatibility (GH-7346) (diff) | |
download | cpython-842985f6c70484ed7b8fc30d0bc05aec73236a98.tar.gz cpython-842985f6c70484ed7b8fc30d0bc05aec73236a98.tar.bz2 cpython-842985f6c70484ed7b8fc30d0bc05aec73236a98.zip |
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
(cherry picked from commit 66f02aa32f1e4adb9f24cf186f8c495399d5ce9b)
Co-authored-by: wim glenn <wim.glenn@gmail.com>
-rw-r--r-- | Lib/argparse.py | 6 | ||||
-rw-r--r-- | Lib/test/test_argparse.py | 42 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2018-05-23-00-26-27.bpo-11874.glK5iP.rst | 2 |
3 files changed, 40 insertions, 10 deletions
diff --git a/Lib/argparse.py b/Lib/argparse.py index e0e367bf20c..a0307492476 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 bcf15ce123e..85449c72990 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 00000000000..6c75f142c4b --- /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. |