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 66f02aa32f
)
Co-authored-by: wim glenn <wim.glenn@gmail.com>
This commit is contained in:
parent
458ed1b237
commit
4e6bd247aa
|
@ -324,7 +324,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)
|
||||
|
|
|
@ -4652,7 +4652,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"))
|
||||
|
@ -4669,7 +4669,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"))
|
||||
|
@ -4686,7 +4686,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"))
|
||||
|
@ -4703,7 +4703,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"))
|
||||
|
@ -4720,7 +4720,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"))
|
||||
|
@ -4737,7 +4737,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"))
|
||||
|
@ -4754,7 +4754,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"))
|
||||
|
@ -4771,7 +4771,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"))
|
||||
|
@ -4788,7 +4788,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"))
|
||||
|
@ -4815,6 +4815,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():
|
||||
# silence warnings about version argument - these are expected
|
||||
with test_support.check_warnings(
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Use a better regex when breaking usage into wrappable parts. Avoids bogus
|
||||
assertion errors from custom metavar strings.
|
Loading…
Reference in New Issue