Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(6)

Delta Between Two Patch Sets: Lib/test/test_argparse.py

Issue 14191: argparse: nargs='*' doesn't get out-of-order positional parameters
Left Patch Set: Created 7 years, 1 month ago
Right Patch Set: Created 7 years ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « Lib/argparse.py ('k') | no next file » | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 # Author: Steven J. Bethard <steven.bethard@gmail.com>. 1 # Author: Steven J. Bethard <steven.bethard@gmail.com>.
2 2
3 import codecs 3 import codecs
4 import inspect 4 import inspect
5 import os 5 import os
6 import shutil 6 import shutil
7 import stat 7 import stat
8 import sys 8 import sys
9 import textwrap 9 import textwrap
10 import tempfile 10 import tempfile
(...skipping 1236 matching lines...) Expand 10 before | Expand all | Expand 10 after
1247 1247
1248 argument_signatures = [Sig('x'), Sig('y', nargs='...'), Sig('-z')] 1248 argument_signatures = [Sig('x'), Sig('y', nargs='...'), Sig('-z')]
1249 failures = ['', '-z', '-z Z'] 1249 failures = ['', '-z', '-z Z']
1250 successes = [ 1250 successes = [
1251 ('X', NS(x='X', y=[], z=None)), 1251 ('X', NS(x='X', y=[], z=None)),
1252 ('-z Z X', NS(x='X', y=[], z='Z')), 1252 ('-z Z X', NS(x='X', y=[], z='Z')),
1253 ('X A B -z Z', NS(x='X', y=['A', 'B', '-z', 'Z'], z=None)), 1253 ('X A B -z Z', NS(x='X', y=['A', 'B', '-z', 'Z'], z=None)),
1254 ('X Y --foo', NS(x='X', y=['Y', '--foo'], z=None)), 1254 ('X Y --foo', NS(x='X', y=['Y', '--foo'], z=None)),
1255 ] 1255 ]
1256 1256
1257 class TestOptionalsBetween2PositionalsZeroOrMore(ParserTestCase):
1258 """Tests optionals within positionals, '*' 2nd positional
1259 2nd positional is not consumed by the 1st argument set"""
1260
1261 argument_signatures = [Sig('cmd'),
1262 Sig('-f', '--foo'),
1263 Sig('rest',nargs='*')]
1264 failures = ['', # the following arguments are required: cmd, rest
1265 'cmd 1 -f1 2', # unrecognized arguments: 2
1266 'cmd 1 --foo 1 2',
1267 # optional cannot split arguments for 'rest'
1268 ]
1269 successes = [
1270 ('-f1 cmd 1 2', NS(cmd='cmd', foo='1', rest=['1', '2'])),
1271 ('cmd -f1 1 2', NS(cmd='cmd', foo='1', rest=['1', '2'])),
1272 ('cmd 1 2 --foo 1', NS(cmd='cmd', foo='1', rest=['1', '2'])),
1273 ('cmd --foo 1 1 2',NS(cmd='cmd', foo='1', rest=['1', '2']))
1274 ]
1275
1276 class TestOptionalsBetween2PositionalsOptional(ParserTestCase):
1277 """Tests optionals within positionals, '?' 2nd positional
1278 2nd positional is not consumed by the 1st argument set"""
1279
1280 argument_signatures = [
1281 Sig('cmd'),
1282 Sig('-f', '--foo'),
1283 Sig('rest',nargs='?')
1284 ]
1285 failures = []
1286 successes = [
1287 ('-f1 cmd 1', NS(cmd='cmd', foo='1', rest='1')),
1288 ('cmd -f1 1', NS(cmd='cmd', foo='1', rest='1')),
1289 ]
1290
1291 class TestOptionalsBetween3PositionalsZeroOrMore(ParserTestCase):
1292 """Tests optionals within positionals, '*' 2nd positional
1293 2 positionals that might not be consumed by the 1st argument"""
1294
1295 argument_signatures = [
1296 Sig('cmd'),
1297 Sig('-f', '--foo'),
1298 Sig('resta',nargs='?'),
1299 Sig('restb',nargs='*')
1300 ]
1301 failures = ['cmd 1 2 -f1 3']
1302 successes = [
1303 ('-f1 cmd 1 2 3', NS(cmd='cmd', foo='1', resta='1', restb=['2', '3'])),
1304 ('cmd -f1 1 2 3', NS(cmd='cmd', foo='1', resta='1', restb=['2', '3'])),
1305 ('cmd 1 -f1 2 3', NS(cmd='cmd', foo='1', resta='1', restb=['2', '3'])),
1306 ('cmd 1 2 3 -f1', NS(cmd='cmd', foo='1', resta='1', restb=['2', '3'])),
1307 ]
1308
1309 class TestOptionalsBetween3PositionalsOptional(ParserTestCase):
1310 """Tests optionals within positionals, '?' 2nd positional
1311 2 positionals that might not be consumed by the 1st argument set"""
1312
1313 argument_signatures = [
1314 Sig('cmd'),
1315 Sig('-f', '--foo'),
1316 Sig('resta', nargs='?'),
1317 Sig('restb', nargs='?')
1318 ]
1319 failures = []
1320 successes = [
1321 ('-f1 cmd 1 2', NS(cmd='cmd', foo='1', resta='1', restb='2')),
1322 ('cmd -f1 1 2', NS(cmd='cmd', foo='1', resta='1', restb='2')),
1323 ('cmd 1 -f1 2', NS(cmd='cmd', foo='1', resta='1', restb='2')),
1324 ('cmd 1 2 -f1', NS(cmd='cmd', foo='1', resta='1', restb='2')),
1325 ]
1326
1327 1257
1328 class TestOptionLike(ParserTestCase): 1258 class TestOptionLike(ParserTestCase):
1329 """Tests options that may or may not be arguments""" 1259 """Tests options that may or may not be arguments"""
1330 1260
1331 argument_signatures = [ 1261 argument_signatures = [
1332 Sig('-x', type=float), 1262 Sig('-x', type=float),
1333 Sig('-3', type=float, dest='y'), 1263 Sig('-3', type=float, dest='y'),
1334 Sig('z', nargs='*'), 1264 Sig('z', nargs='*'),
1335 ] 1265 ]
1336 failures = ['-x', '-y2.5', '-xa', '-x -a', 1266 failures = ['-x', '-y2.5', '-xa', '-x -a',
(...skipping 3440 matching lines...) Expand 10 before | Expand all | Expand 10 after
4777 parser = argparse.ArgumentParser() 4707 parser = argparse.ArgumentParser()
4778 parser.add_argument('-v', nargs='?', const=1, type=int) 4708 parser.add_argument('-v', nargs='?', const=1, type=int)
4779 parser.add_argument('--spam', action='store_false') 4709 parser.add_argument('--spam', action='store_false')
4780 parser.add_argument('badger') 4710 parser.add_argument('badger')
4781 4711
4782 argv = ["B", "C", "--foo", "-v", "3", "4"] 4712 argv = ["B", "C", "--foo", "-v", "3", "4"]
4783 args, extras = parser.parse_known_args(argv) 4713 args, extras = parser.parse_known_args(argv)
4784 self.assertEqual(NS(v=3, spam=True, badger="B"), args) 4714 self.assertEqual(NS(v=3, spam=True, badger="B"), args)
4785 self.assertEqual(["C", "--foo", "4"], extras) 4715 self.assertEqual(["C", "--foo", "4"], extras)
4786 4716
4717 # ===========================
4718 # parse_intermixed_args tests
4719 # ===========================
4720
4721 class TestIntermixedArgs(TestCase):
4722 def test_basic(self):
4723 # test parsing intermixed optionals and positionals
4724 parser = argparse.ArgumentParser(prog='PROG')
4725 parser.add_argument('--foo', dest='foo')
4726 bar = parser.add_argument('--bar', dest='bar', required=True)
4727 parser.add_argument('cmd')
4728 parser.add_argument('rest', nargs='*', type=int)
4729 argv = 'cmd --foo x 1 --bar y 2 3'.split()
4730 args = parser.parse_intermixed_args(argv)
4731 # rest gets [1,2,3] despite the foo and bar strings
4732 self.assertEqual(NS(bar='y', cmd='cmd', foo='x', rest=[1, 2, 3]), args)
4733
4734 args, extras = parser.parse_known_args(argv)
4735 # cannot parse the '1,2,3'
4736 self.assertEqual(NS(bar='y', cmd='cmd', foo='x', rest=[]), args)
4737 self.assertEqual(["1", "2", "3"], extras)
4738
4739 argv = 'cmd --foo x 1 --error 2 --bar y 3'.split()
4740 args, extras = parser.parse_known_intermixed_args(argv)
4741 # unknown optionals go into extras
4742 self.assertEqual(NS(bar='y', cmd='cmd', foo='x', rest=[1]), args)
4743 self.assertEqual(['--error', '2', '3'], extras)
4744
4745 # restores attributes that were temporarily changed
4746 self.assertIsNone(parser.usage)
4747 self.assertEqual(bar.required, True)
4748
4749 def test_remainder(self):
4750 # Intermixed and remainder are incompatible
4751 parser = ErrorRaisingArgumentParser(prog='PROG')
4752 parser.add_argument('-z')
4753 parser.add_argument('x')
4754 parser.add_argument('y', nargs='...')
4755 argv = 'X A B -z Z'.split()
4756 # intermixed fails with '...' (also 'A...')
4757 # self.assertRaises(TypeError, parser.parse_intermixed_args, argv)
4758 with self.assertRaises(TypeError) as cm:
4759 parser.parse_intermixed_args(argv)
4760 self.assertRegex(str(cm.exception), '\.\.\.')
4761
4762 def test_exclusive(self):
4763 # mutually exclusive group; intermixed works fine
4764 parser = ErrorRaisingArgumentParser(prog='PROG')
4765 group = parser.add_mutually_exclusive_group(required=True)
4766 group.add_argument('--foo', action='store_true', help='FOO')
4767 group.add_argument('--spam', help='SPAM')
4768 parser.add_argument('badger', nargs='*', default='X', help='BADGER')
4769 args = parser.parse_intermixed_args('1 --foo 2'.split())
4770 self.assertEqual(NS(badger=['1', '2'], foo=True, spam=None), args)
4771 self.assertRaises(ArgumentParserError, parser.parse_intermixed_args, '1 2'.split())
4772 self.assertEqual(group.required, True)
4773
4774 def test_exclusive_incompatible(self):
4775 # mutually exclusive group including positional - fail
4776 parser = ErrorRaisingArgumentParser(prog='PROG')
4777 group = parser.add_mutually_exclusive_group(required=True)
4778 group.add_argument('--foo', action='store_true', help='FOO')
4779 group.add_argument('--spam', help='SPAM')
4780 group.add_argument('badger', nargs='*', default='X', help='BADGER')
4781 self.assertRaises(TypeError, parser.parse_intermixed_args, [])
4782 self.assertEqual(group.required, True)
4783
4784 class TestIntermixedMessageContentError(TestCase):
4785 # case where Intermixed gives different error message
4786 # error is raised by 1st parsing step
4787 def test_missing_argument_name_in_message(self):
4788 parser = ErrorRaisingArgumentParser(prog='PROG', usage='')
4789 parser.add_argument('req_pos', type=str)
4790 parser.add_argument('-req_opt', type=int, required=True)
4791
4792 with self.assertRaises(ArgumentParserError) as cm:
4793 parser.parse_args([])
4794 msg = str(cm.exception)
4795 self.assertRegex(msg, 'req_pos')
4796 self.assertRegex(msg, 'req_opt')
4797
4798 with self.assertRaises(ArgumentParserError) as cm:
4799 parser.parse_intermixed_args([])
4800 msg = str(cm.exception)
4801 self.assertNotRegex(msg, 'req_pos')
4802 self.assertRegex(msg, 'req_opt')
4803
4787 # ========================== 4804 # ==========================
4788 # add_argument metavar tests 4805 # add_argument metavar tests
4789 # ========================== 4806 # ==========================
4790 4807
4791 class TestAddArgumentMetavar(TestCase): 4808 class TestAddArgumentMetavar(TestCase):
4792 4809
4793 EXPECTED_MESSAGE = "length of metavar tuple does not match nargs" 4810 EXPECTED_MESSAGE = "length of metavar tuple does not match nargs"
4794 4811
4795 def do_test_no_exception(self, nargs, metavar): 4812 def do_test_no_exception(self, nargs, metavar):
4796 parser = argparse.ArgumentParser() 4813 parser = argparse.ArgumentParser()
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
4977 def test_main(): 4994 def test_main():
4978 support.run_unittest(__name__) 4995 support.run_unittest(__name__)
4979 # Remove global references to avoid looking like we have refleaks. 4996 # Remove global references to avoid looking like we have refleaks.
4980 RFile.seen = {} 4997 RFile.seen = {}
4981 WFile.seen = set() 4998 WFile.seen = set()
4982 4999
4983 5000
4984 5001
4985 if __name__ == '__main__': 5002 if __name__ == '__main__':
4986 test_main() 5003 test_main()
LEFTRIGHT

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+