blob: b61572270e95a0626b4d4d5a70cbb5759e89ec14 [file] [log] [blame]
Steven Bethardcd4ec0e2010-03-24 23:07:31 +00001# Author: Steven J. Bethard <steven.bethard@gmail.com>.
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002
3import codecs
Steven Bethard72c55382010-11-01 15:23:12 +00004import inspect
Benjamin Peterson698a18a2010-03-02 22:34:37 +00005import os
6import shutil
Steven Bethardb0270112011-01-24 21:02:50 +00007import stat
Benjamin Peterson698a18a2010-03-02 22:34:37 +00008import sys
9import textwrap
10import tempfile
11import unittest
Benjamin Peterson698a18a2010-03-02 22:34:37 +000012import argparse
13
Benjamin Peterson16f2fd02010-03-02 23:09:38 +000014from io import StringIO
15
Benjamin Peterson698a18a2010-03-02 22:34:37 +000016from test import support
Petri Lehtinen74d6c252012-12-15 22:39:32 +020017from unittest import mock
Benjamin Petersonb48af542010-04-11 20:43:16 +000018class StdIOBuffer(StringIO):
19 pass
Benjamin Peterson698a18a2010-03-02 22:34:37 +000020
Benjamin Peterson698a18a2010-03-02 22:34:37 +000021class TestCase(unittest.TestCase):
22
23 def assertEqual(self, obj1, obj2):
24 if obj1 != obj2:
25 print('')
26 print(repr(obj1))
27 print(repr(obj2))
28 print(obj1)
29 print(obj2)
30 super(TestCase, self).assertEqual(obj1, obj2)
31
Steven Bethard1f1c2472010-11-01 13:56:09 +000032 def setUp(self):
33 # The tests assume that line wrapping occurs at 80 columns, but this
34 # behaviour can be overridden by setting the COLUMNS environment
35 # variable. To ensure that this assumption is true, unset COLUMNS.
36 env = support.EnvironmentVarGuard()
37 env.unset("COLUMNS")
38 self.addCleanup(env.__exit__)
Benjamin Peterson698a18a2010-03-02 22:34:37 +000039
Benjamin Petersonb48af542010-04-11 20:43:16 +000040
Benjamin Peterson698a18a2010-03-02 22:34:37 +000041class TempDirMixin(object):
42
43 def setUp(self):
44 self.temp_dir = tempfile.mkdtemp()
45 self.old_dir = os.getcwd()
46 os.chdir(self.temp_dir)
47
48 def tearDown(self):
49 os.chdir(self.old_dir)
Benjamin Peterson511e2222014-04-04 13:55:56 -040050 for root, dirs, files in os.walk(self.temp_dir, topdown=False):
51 for name in files:
52 os.chmod(os.path.join(self.temp_dir, name), stat.S_IWRITE)
Steven Bethardb0270112011-01-24 21:02:50 +000053 shutil.rmtree(self.temp_dir, True)
Benjamin Peterson698a18a2010-03-02 22:34:37 +000054
Steven Bethardb0270112011-01-24 21:02:50 +000055 def create_readonly_file(self, filename):
56 file_path = os.path.join(self.temp_dir, filename)
57 with open(file_path, 'w') as file:
58 file.write(filename)
59 os.chmod(file_path, stat.S_IREAD)
Benjamin Peterson698a18a2010-03-02 22:34:37 +000060
61class Sig(object):
62
63 def __init__(self, *args, **kwargs):
64 self.args = args
65 self.kwargs = kwargs
66
67
68class NS(object):
69
70 def __init__(self, **kwargs):
71 self.__dict__.update(kwargs)
72
73 def __repr__(self):
74 sorted_items = sorted(self.__dict__.items())
75 kwarg_str = ', '.join(['%s=%r' % tup for tup in sorted_items])
76 return '%s(%s)' % (type(self).__name__, kwarg_str)
77
78 def __eq__(self, other):
79 return vars(self) == vars(other)
80
81 def __ne__(self, other):
82 return not (self == other)
83
84
85class ArgumentParserError(Exception):
86
87 def __init__(self, message, stdout=None, stderr=None, error_code=None):
88 Exception.__init__(self, message, stdout, stderr)
89 self.message = message
90 self.stdout = stdout
91 self.stderr = stderr
92 self.error_code = error_code
93
94
95def stderr_to_parser_error(parse_args, *args, **kwargs):
96 # if this is being called recursively and stderr or stdout is already being
97 # redirected, simply call the function and let the enclosing function
98 # catch the exception
Benjamin Petersonb48af542010-04-11 20:43:16 +000099 if isinstance(sys.stderr, StdIOBuffer) or isinstance(sys.stdout, StdIOBuffer):
Benjamin Peterson698a18a2010-03-02 22:34:37 +0000100 return parse_args(*args, **kwargs)
101
102 # if this is not being called recursively, redirect stderr and
103 # use it as the ArgumentParserError message
104 old_stdout = sys.stdout
105 old_stderr = sys.stderr
Benjamin Petersonb48af542010-04-11 20:43:16 +0000106 sys.stdout = StdIOBuffer()
107 sys.stderr = StdIOBuffer()
Benjamin Peterson698a18a2010-03-02 22:34:37 +0000108 try:
109 try:
110 result = parse_args(*args, **kwargs)
111 for key in list(vars(result)):
112 if getattr(result, key) is sys.stdout:
113 setattr(result, key, old_stdout)
114 if getattr(result, key) is sys.stderr:
115 setattr(result, key, old_stderr)
116 return result
117 except SystemExit:
118 code = sys.exc_info()[1].code
119 stdout = sys.stdout.getvalue()
120 stderr = sys.stderr.getvalue()
121 raise ArgumentParserError("SystemExit", stdout, stderr, code)
122 finally:
123 sys.stdout = old_stdout
124 sys.stderr = old_stderr
125
126
127class ErrorRaisingArgumentParser(argparse.ArgumentParser):
128
129 def parse_args(self, *args, **kwargs):
130 parse_args = super(ErrorRaisingArgumentParser, self).parse_args
131 return stderr_to_parser_error(parse_args, *args, **kwargs)
132
133 def exit(self, *args, **kwargs):
134 exit = super(ErrorRaisingArgumentParser, self).exit
135 return stderr_to_parser_error(exit, *args, **kwargs)
136
137 def error(self, *args, **kwargs):
138 error = super(ErrorRaisingArgumentParser, self).error
139 return stderr_to_parser_error(error, *args, **kwargs)
140
141
142class ParserTesterMetaclass(type):
143 """Adds parser tests using the class attributes.
144
145 Classes of this type should specify the following attributes:
146
147 argument_signatures -- a list of Sig objects which specify
148 the signatures of Argument objects to be created
149 failures -- a list of args lists that should cause the parser
150 to fail
151 successes -- a list of (initial_args, options, remaining_args) tuples
152 where initial_args specifies the string args to be parsed,
153 options is a dict that should match the vars() of the options
154 parsed out of initial_args, and remaining_args should be any
155 remaining unparsed arguments
156 """
157
158 def __init__(cls, name, bases, bodydict):
159 if name == 'ParserTestCase':
160 return
161
162 # default parser signature is empty
163 if not hasattr(cls, 'parser_signature'):
164 cls.parser_signature = Sig()
165 if not hasattr(cls, 'parser_class'):
166 cls.parser_class = ErrorRaisingArgumentParser
167
168 # ---------------------------------------
169 # functions for adding optional arguments
170 # ---------------------------------------
171 def no_groups(parser, argument_signatures):
172 """Add all arguments directly to the parser"""
173 for sig in argument_signatures:
174 parser.add_argument(*sig.args, **sig.kwargs)
175
176 def one_group(parser, argument_signatures):
177 """Add all arguments under a single group in the parser"""
178 group = parser.add_argument_group('foo')
179 for sig in argument_signatures:
180 group.add_argument(*sig.args, **sig.kwargs)
181
182 def many_groups(parser, argument_signatures):
183 """Add each argument in its own group to the parser"""
184 for i, sig in enumerate(argument_signatures):
185 group = parser.add_argument_group('foo:%i' % i)
186 group.add_argument(*sig.args, **sig.kwargs)
187
188 # --------------------------
189 # functions for parsing args
190 # --------------------------
191 def listargs(parser, args):
192 """Parse the args by passing in a list"""
193 return parser.parse_args(args)
194
195 def sysargs(parser, args):
196 """Parse the args by defaulting to sys.argv"""
197 old_sys_argv = sys.argv
198 sys.argv = [old_sys_argv[0]] + args
199 try:
200 return parser.parse_args()
201 finally:
202 sys.argv = old_sys_argv
203
204 # class that holds the combination of one optional argument
205 # addition method and one arg parsing method
206 class AddTests(object):
207
208 def __init__(self, tester_cls, add_arguments, parse_args):
209 self._add_arguments = add_arguments
210 self._parse_args = parse_args
211
212 add_arguments_name = self._add_arguments.__name__
213 parse_args_name = self._parse_args.__name__
214 for test_func in [self.test_failures, self.test_successes]:
215 func_name = test_func.__name__
216 names = func_name, add_arguments_name, parse_args_name
217 test_name = '_'.join(names)
218
219 def wrapper(self, test_func=test_func):
220 test_func(self)
221 try:
222 wrapper.__name__ = test_name
223 except TypeError:
224 pass
225 setattr(tester_cls, test_name, wrapper)
226
227 def _get_parser(self, tester):
228 args = tester.parser_signature.args
229 kwargs = tester.parser_signature.kwargs
230 parser = tester.parser_class(*args, **kwargs)
231 self._add_arguments(parser, tester.argument_signatures)
232 return parser
233
234 def test_failures(self, tester):
235 parser = self._get_parser(tester)
236 for args_str in tester.failures:
237 args = args_str.split()
Ezio Melotti12b7f482014-08-05 02:24:03 +0300238 with tester.assertRaises(ArgumentParserError, msg=args):
239 parser.parse_args(args)
Benjamin Peterson698a18a2010-03-02 22:34:37 +0000240
241 def test_successes(self, tester):
242 parser = self._get_parser(tester)
243 for args, expected_ns in tester.successes:
244 if isinstance(args, str):
245 args = args.split()
246 result_ns = self._parse_args(parser, args)
247 tester.assertEqual(expected_ns, result_ns)
248
249 # add tests for each combination of an optionals adding method
250 # and an arg parsing method
251 for add_arguments in [no_groups, one_group, many_groups]:
252 for parse_args in [listargs, sysargs]:
253 AddTests(cls, add_arguments, parse_args)
254
255bases = TestCase,
256ParserTestCase = ParserTesterMetaclass('ParserTestCase', bases, {})
257
258# ===============
259# Optionals tests
260# ===============
261
262class TestOptionalsSingleDash(ParserTestCase):
263 """Test an Optional with a single-dash option string"""
264
265 argument_signatures = [Sig('-x')]
266 failures = ['-x', 'a', '--foo', '-x --foo', '-x -y']
267 successes = [
268 ('', NS(x=None)),
269 ('-x a', NS(x='a')),
270 ('-xa', NS(x='a')),
271 ('-x -1', NS(x='-1')),
272 ('-x-1', NS(x='-1')),
273 ]
274
275
276class TestOptionalsSingleDashCombined(ParserTestCase):
277 """Test an Optional with a single-dash option string"""
278
279 argument_signatures = [
280 Sig('-x', action='store_true'),
281 Sig('-yyy', action='store_const', const=42),
282 Sig('-z'),
283 ]
284 failures = ['a', '--foo', '-xa', '-x --foo', '-x -z', '-z -x',
285 '-yx', '-yz a', '-yyyx', '-yyyza', '-xyza']
286 successes = [
287 ('', NS(x=False, yyy=None, z=None)),
288 ('-x', NS(x=True, yyy=None, z=None)),
289 ('-za', NS(x=False, yyy=None, z='a')),
290 ('-z a', NS(x=False, yyy=None, z='a')),
291 ('-xza', NS(x=True, yyy=None, z='a')),
292 ('-xz a', NS(x=True, yyy=None, z='a')),
293 ('-x -za', NS(x=True, yyy=None, z='a')),
294 ('-x -z a', NS(x=True, yyy=None, z='a')),
295 ('-y', NS(x=False, yyy=42, z=None)),
296 ('-yyy', NS(x=False, yyy=42, z=None)),
297 ('-x -yyy -za', NS(x=True, yyy=42, z='a')),
298 ('-x -yyy -z a', NS(x=True, yyy=42, z='a')),
299 ]
300
301
302class TestOptionalsSingleDashLong(ParserTestCase):
303 """Test an Optional with a multi-character single-dash option string"""
304
305 argument_signatures = [Sig('-foo')]
306 failures = ['-foo', 'a', '--foo', '-foo --foo', '-foo -y', '-fooa']
307 successes = [
308 ('', NS(foo=None)),
309 ('-foo a', NS(foo='a')),
310 ('-foo -1', NS(foo='-1')),
311 ('-fo a', NS(foo='a')),
312 ('-f a', NS(foo='a')),
313 ]
314
315
316class TestOptionalsSingleDashSubsetAmbiguous(ParserTestCase):
317 """Test Optionals where option strings are subsets of each other"""
318
319 argument_signatures = [Sig('-f'), Sig('-foobar'), Sig('-foorab')]
320 failures = ['-f', '-foo', '-fo', '-foo b', '-foob', '-fooba', '-foora']
321 successes = [
322 ('', NS(f=None, foobar=None, foorab=None)),
323 ('-f a', NS(f='a', foobar=None, foorab=None)),
324 ('-fa', NS(f='a', foobar=None, foorab=None)),
325 ('-foa', NS(f='oa', foobar=None, foorab=None)),
326 ('-fooa', NS(f='ooa', foobar=None, foorab=None)),
327 ('-foobar a', NS(f=None, foobar='a', foorab=None)),
328 ('-foorab a', NS(f=None, foobar=None, foorab='a')),
329 ]
330
331
332class TestOptionalsSingleDashAmbiguous(ParserTestCase):
333 """Test Optionals that partially match but are not subsets"""
334
335 argument_signatures = [Sig('-foobar'), Sig('-foorab')]
336 failures = ['-f', '-f a', '-fa', '-foa', '-foo', '-fo', '-foo b']
337 successes = [
338 ('', NS(foobar=None, foorab=None)),
339 ('-foob a', NS(foobar='a', foorab=None)),
340 ('-foor a', NS(foobar=None, foorab='a')),
341 ('-fooba a', NS(foobar='a', foorab=None)),
342 ('-foora a', NS(foobar=None, foorab='a')),
343 ('-foobar a', NS(foobar='a', foorab=None)),
344 ('-foorab a', NS(foobar=None, foorab='a')),
345 ]
346
347
348class TestOptionalsNumeric(ParserTestCase):
349 """Test an Optional with a short opt string"""
350
351 argument_signatures = [Sig('-1', dest='one')]
352 failures = ['-1', 'a', '-1 --foo', '-1 -y', '-1 -1', '-1 -2']
353 successes = [
354 ('', NS(one=None)),
355 ('-1 a', NS(one='a')),
356 ('-1a', NS(one='a')),
357 ('-1-2', NS(one='-2')),
358 ]
359
360
361class TestOptionalsDoubleDash(ParserTestCase):
362 """Test an Optional with a double-dash option string"""
363
364 argument_signatures = [Sig('--foo')]
365 failures = ['--foo', '-f', '-f a', 'a', '--foo -x', '--foo --bar']
366 successes = [
367 ('', NS(foo=None)),
368 ('--foo a', NS(foo='a')),
369 ('--foo=a', NS(foo='a')),
370 ('--foo -2.5', NS(foo='-2.5')),
371 ('--foo=-2.5', NS(foo='-2.5')),
372 ]
373
374
375class TestOptionalsDoubleDashPartialMatch(ParserTestCase):
376 """Tests partial matching with a double-dash option string"""
377
378 argument_signatures = [
379 Sig('--badger', action='store_true'),
380 Sig('--bat'),
381 ]
382 failures = ['--bar', '--b', '--ba', '--b=2', '--ba=4', '--badge 5']
383 successes = [
384 ('', NS(badger=False, bat=None)),
385 ('--bat X', NS(badger=False, bat='X')),
386 ('--bad', NS(badger=True, bat=None)),
387 ('--badg', NS(badger=True, bat=None)),
388 ('--badge', NS(badger=True, bat=None)),
389 ('--badger', NS(badger=True, bat=None)),
390 ]
391
392
393class TestOptionalsDoubleDashPrefixMatch(ParserTestCase):
394 """Tests when one double-dash option string is a prefix of another"""
395
396 argument_signatures = [
397 Sig('--badger', action='store_true'),
398 Sig('--ba'),
399 ]
400 failures = ['--bar', '--b', '--ba', '--b=2', '--badge 5']
401 successes = [
402 ('', NS(badger=False, ba=None)),
403 ('--ba X', NS(badger=False, ba='X')),
404 ('--ba=X', NS(badger=False, ba='X')),
405 ('--bad', NS(badger=True, ba=None)),
406 ('--badg', NS(badger=True, ba=None)),
407 ('--badge', NS(badger=True, ba=None)),
408 ('--badger', NS(badger=True, ba=None)),
409 ]
410
411
412class TestOptionalsSingleDoubleDash(ParserTestCase):
413 """Test an Optional with single- and double-dash option strings"""
414
415 argument_signatures = [
416 Sig('-f', action='store_true'),
417 Sig('--bar'),
418 Sig('-baz', action='store_const', const=42),
419 ]
420 failures = ['--bar', '-fbar', '-fbaz', '-bazf', '-b B', 'B']
421 successes = [
422 ('', NS(f=False, bar=None, baz=None)),
423 ('-f', NS(f=True, bar=None, baz=None)),
424 ('--ba B', NS(f=False, bar='B', baz=None)),
425 ('-f --bar B', NS(f=True, bar='B', baz=None)),
426 ('-f -b', NS(f=True, bar=None, baz=42)),
427 ('-ba -f', NS(f=True, bar=None, baz=42)),
428 ]
429
430
431class TestOptionalsAlternatePrefixChars(ParserTestCase):
R. David Murray88c49fe2010-08-03 17:56:09 +0000432 """Test an Optional with option strings with custom prefixes"""
Benjamin Peterson698a18a2010-03-02 22:34:37 +0000433
434 parser_signature = Sig(prefix_chars='+:/', add_help=False)
435 argument_signatures = [
436 Sig('+f', action='store_true'),
437 Sig('::bar'),
438 Sig('/baz', action='store_const', const=42),
439 ]
R. David Murray88c49fe2010-08-03 17:56:09 +0000440 failures = ['--bar', '-fbar', '-b B', 'B', '-f', '--bar B', '-baz', '-h', '--help', '+h', '::help', '/help']
441 successes = [
442 ('', NS(f=False, bar=None, baz=None)),
443 ('+f', NS(f=True, bar=None, baz=None)),
444 ('::ba B', NS(f=False, bar='B', baz=None)),
445 ('+f ::bar B', NS(f=True, bar='B', baz=None)),
446 ('+f /b', NS(f=True, bar=None, baz=42)),
447 ('/ba +f', NS(f=True, bar=None, baz=42)),
448 ]
449
450
451class TestOptionalsAlternatePrefixCharsAddedHelp(ParserTestCase):
452 """When ``-`` not in prefix_chars, default operators created for help
453 should use the prefix_chars in use rather than - or --
454 http://bugs.python.org/issue9444"""
455
456 parser_signature = Sig(prefix_chars='+:/', add_help=True)
457 argument_signatures = [
458 Sig('+f', action='store_true'),
459 Sig('::bar'),
460 Sig('/baz', action='store_const', const=42),
461 ]
Benjamin Peterson698a18a2010-03-02 22:34:37 +0000462 failures = ['--bar', '-fbar', '-b B', 'B', '-f', '--bar B', '-baz']
463 successes = [
464 ('', NS(f=False, bar=None, baz=None)),
465 ('+f', NS(f=True, bar=None, baz=None)),
466 ('::ba B', NS(f=False, bar='B', baz=None)),
467 ('+f ::bar B', NS(f=True, bar='B', baz=None)),
468 ('+f /b', NS(f=True, bar=None, baz=42)),
R. David Murray88c49fe2010-08-03 17:56:09 +0000469 ('/ba +f', NS(f=True, bar=None, baz=42))
Benjamin Peterson698a18a2010-03-02 22:34:37 +0000470 ]
471
Steven Bethard1ca45a52010-11-01 15:57:36 +0000472
473class TestOptionalsAlternatePrefixCharsMultipleShortArgs(ParserTestCase):
474 """Verify that Optionals must be called with their defined prefixes"""
475
476 parser_signature = Sig(prefix_chars='+-', add_help=False)
477 argument_signatures = [
478 Sig('-x', action='store_true'),
479 Sig('+y', action='store_true'),
480 Sig('+z', action='store_true'),
481 ]
482 failures = ['-w',
483 '-xyz',
484 '+x',
485 '-y',
486 '+xyz',
487 ]
488 successes = [
489 ('', NS(x=False, y=False, z=False)),
490 ('-x', NS(x=True, y=False, z=False)),
491 ('+y -x', NS(x=True, y=True, z=False)),
492 ('+yz -x', NS(x=True, y=True, z=True)),
493 ]
494
495
Benjamin Peterson698a18a2010-03-02 22:34:37 +0000496class TestOptionalsShortLong(ParserTestCase):
497 """Test a combination of single- and double-dash option strings"""
498
499 argument_signatures = [
500 Sig('-v', '--verbose', '-n', '--noisy', action='store_true'),
501 ]
502 failures = ['--x --verbose', '-N', 'a', '-v x']
503 successes = [
504 ('', NS(verbose=False)),
505 ('-v', NS(verbose=True)),
506 ('--verbose', NS(verbose=True)),
507 ('-n', NS(verbose=True)),
508 ('--noisy', NS(verbose=True)),
509 ]
510
511
512class TestOptionalsDest(ParserTestCase):
513 """Tests various means of setting destination"""
514
515 argument_signatures = [Sig('--foo-bar'), Sig('--baz', dest='zabbaz')]
516 failures = ['a']
517 successes = [
518 ('--foo-bar f', NS(foo_bar='f', zabbaz=None)),
519 ('--baz g', NS(foo_bar=None, zabbaz='g')),
520 ('--foo-bar h --baz i', NS(foo_bar='h', zabbaz='i')),
521 ('--baz j --foo-bar k', NS(foo_bar='k', zabbaz='j')),
522 ]
523
524
525class TestOptionalsDefault(ParserTestCase):
526 """Tests specifying a default for an Optional"""
527
528 argument_signatures = [Sig('-x'), Sig('-y', default=42)]
529 failures = ['a']
530 successes = [
531 ('', NS(x=None, y=42)),
532 ('-xx', NS(x='x', y=42)),
533 ('-yy', NS(x=None, y='y')),
534 ]
535
536
537class TestOptionalsNargsDefault(ParserTestCase):
538 """Tests not specifying the number of args for an Optional"""
539
540 argument_signatures = [Sig('-x')]
541 failures = ['a', '-x']
542 successes = [
543 ('', NS(x=None)),
544 ('-x a', NS(x='a')),
545 ]
546
547
548class TestOptionalsNargs1(ParserTestCase):
549 """Tests specifying the 1 arg for an Optional"""
550
551 argument_signatures = [Sig('-x', nargs=1)]
552 failures = ['a', '-x']
553 successes = [
554 ('', NS(x=None)),
555 ('-x a', NS(x=['a'])),
556 ]
557
558
559class TestOptionalsNargs3(ParserTestCase):
560 """Tests specifying the 3 args for an Optional"""
561
562 argument_signatures = [Sig('-x', nargs=3)]
563 failures = ['a', '-x', '-x a', '-x a b', 'a -x', 'a -x b']
564 successes = [
565 ('', NS(x=None)),
566 ('-x a b c', NS(x=['a', 'b', 'c'])),
567 ]
568
569
570class TestOptionalsNargsOptional(ParserTestCase):
571 """Tests specifying an Optional arg for an Optional"""
572
573 argument_signatures = [
574 Sig('-w', nargs='?'),
575 Sig('-x', nargs='?', const=42),
576 Sig('-y', nargs='?', default='spam'),
577 Sig('-z', nargs='?', type=int, const='42', default='84'),
578 ]
579 failures = ['2']
580 successes = [
581 ('', NS(w=None, x=None, y='spam', z=84)),
582 ('-w', NS(w=None, x=None, y='spam', z=84)),
583 ('-w 2', NS(w='2', x=None, y='spam', z=84)),
584 ('-x', NS(w=None, x=42, y='spam', z=84)),
585 ('-x 2', NS(w=None, x='2', y='spam', z=84)),
586 ('-y', NS(w=None, x=None, y=None, z=84)),
587 ('-y 2', NS(w=None, x=None, y='2', z=84)),
588 ('-z', NS(w=None, x=None, y='spam', z=42)),
589 ('-z 2', NS(w=None, x=None, y='spam', z=2)),
590 ]
591
592
593class TestOptionalsNargsZeroOrMore(ParserTestCase):
594 """Tests specifying an args for an Optional that accepts zero or more"""
595
596 argument_signatures = [
597 Sig('-x', nargs='*'),
598 Sig('-y', nargs='*', default='spam'),
599 ]
600 failures = ['a']
601 successes = [
602 ('', NS(x=None, y='spam')),
603 ('-x', NS(x=[], y='spam')),
604 ('-x a', NS(x=['a'], y='spam')),
605 ('-x a b', NS(x=['a', 'b'], y='spam')),
606 ('-y', NS(x=None, y=[])),
607 ('-y a', NS(x=None, y=['a'])),
608 ('-y a b', NS(x=None, y=['a', 'b'])),
609 ]
610
611
612class TestOptionalsNargsOneOrMore(ParserTestCase):
613 """Tests specifying an args for an Optional that accepts one or more"""
614
615 argument_signatures = [
616 Sig('-x', nargs='+'),
617 Sig('-y', nargs='+', default='spam'),
618 ]
619 failures = ['a', '-x', '-y', 'a -x', 'a -y b']
620 successes = [
621 ('', NS(x=None, y='spam')),
622 ('-x a', NS(x=['a'], y='spam')),
623 ('-x a b', NS(x=['a', 'b'], y='spam')),
624 ('-y a', NS(x=None, y=['a'])),
625 ('-y a b', NS(x=None, y=['a', 'b'])),
626 ]
627
628
629class TestOptionalsChoices(ParserTestCase):
630 """Tests specifying the choices for an Optional"""
631
632 argument_signatures = [
633 Sig('-f', choices='abc'),
634 Sig('-g', type=int, choices=range(5))]
635 failures = ['a', '-f d', '-fad', '-ga', '-g 6']
636 successes = [
637 ('', NS(f=None, g=None)),
638 ('-f a', NS(f='a', g=None)),
639 ('-f c', NS(f='c', g=None)),
640 ('-g 0', NS(f=None, g=0)),
641 ('-g 03', NS(f=None, g=3)),
642 ('-fb -g4', NS(f='b', g=4)),
643 ]
644
645
646class TestOptionalsRequired(ParserTestCase):
647 """Tests the an optional action that is required"""
648
649 argument_signatures = [
650 Sig('-x', type=int, required=True),
651 ]
652 failures = ['a', '']
653 successes = [
654 ('-x 1', NS(x=1)),
655 ('-x42', NS(x=42)),
656 ]
657
658
659class TestOptionalsActionStore(ParserTestCase):
660 """Tests the store action for an Optional"""
661
662 argument_signatures = [Sig('-x', action='store')]
663 failures = ['a', 'a -x']
664 successes = [
665 ('', NS(x=None)),
666 ('-xfoo', NS(x='foo')),
667 ]
668
669
670class TestOptionalsActionStoreConst(ParserTestCase):
671 """Tests the store_const action for an Optional"""
672
673 argument_signatures = [Sig('-y', action='store_const', const=object)]
674 failures = ['a']
675 successes = [
676 ('', NS(y=None)),
677 ('-y', NS(y=object)),
678 ]
679
680
681class TestOptionalsActionStoreFalse(ParserTestCase):
682 """Tests the store_false action for an Optional"""
683
684 argument_signatures = [Sig('-z', action='store_false')]
685 failures = ['a', '-za', '-z a']
686 successes = [
687 ('', NS(z=True)),
688 ('-z', NS(z=False)),
689 ]
690
691
692class TestOptionalsActionStoreTrue(ParserTestCase):
693 """Tests the store_true action for an Optional"""
694
695 argument_signatures = [Sig('--apple', action='store_true')]
696 failures = ['a', '--apple=b', '--apple b']
697 successes = [
698 ('', NS(apple=False)),
699 ('--apple', NS(apple=True)),
700 ]
701
702
703class TestOptionalsActionAppend(ParserTestCase):
704 """Tests the append action for an Optional"""
705
706 argument_signatures = [Sig('--baz', action='append')]
707 failures = ['a', '--baz', 'a --baz', '--baz a b']
708 successes = [
709 ('', NS(baz=None)),
710 ('--baz a', NS(baz=['a'])),
711 ('--baz a --baz b', NS(baz=['a', 'b'])),
712 ]
713
714
715class TestOptionalsActionAppendWithDefault(ParserTestCase):
716 """Tests the append action for an Optional"""
717
718 argument_signatures = [Sig('--baz', action='append', default=['X'])]
719 failures = ['a', '--baz', 'a --baz', '--baz a b']
720 successes = [
721 ('', NS(baz=['X'])),
722 ('--baz a', NS(baz=['X', 'a'])),
723 ('--baz a --baz b', NS(baz=['X', 'a', 'b'])),
724 ]
725
726
727class TestOptionalsActionAppendConst(ParserTestCase):
728 """Tests the append_const action for an Optional"""
729
730 argument_signatures = [
731 Sig('-b', action='append_const', const=Exception),
732 Sig('-c', action='append', dest='b'),
733 ]
734 failures = ['a', '-c', 'a -c', '-bx', '-b x']
735 successes = [
736 ('', NS(b=None)),
737 ('-b', NS(b=[Exception])),
738 ('-b -cx -b -cyz', NS(b=[Exception, 'x', Exception, 'yz'])),
739 ]
740
741
742class TestOptionalsActionAppendConstWithDefault(ParserTestCase):
743 """Tests the append_const action for an Optional"""
744
745 argument_signatures = [
746 Sig('-b', action='append_const', const=Exception, default=['X']),
747 Sig('-c', action='append', dest='b'),
748 ]
749 failures = ['a', '-c', 'a -c', '-bx', '-b x']
750 successes = [
751 ('', NS(b=['X'])),
752 ('-b', NS(b=['X', Exception])),
753 ('-b -cx -b -cyz', NS(b=['X', Exception, 'x', Exception, 'yz'])),
754 ]
755
756
757class TestOptionalsActionCount(ParserTestCase):
758 """Tests the count action for an Optional"""
759
760 argument_signatures = [Sig('-x', action='count')]
761 failures = ['a', '-x a', '-x b', '-x a -x b']
762 successes = [
763 ('', NS(x=None)),
764 ('-x', NS(x=1)),
765 ]
766
767
768# ================
769# Positional tests
770# ================
771
772class TestPositionalsNargsNone(ParserTestCase):
773 """Test a Positional that doesn't specify nargs"""
774
775 argument_signatures = [Sig('foo')]
776 failures = ['', '-x', 'a b']
777 successes = [
778 ('a', NS(foo='a')),
779 ]
780
781
782class TestPositionalsNargs1(ParserTestCase):
783 """Test a Positional that specifies an nargs of 1"""
784
785 argument_signatures = [Sig('foo', nargs=1)]
786 failures = ['', '-x', 'a b']
787 successes = [
788 ('a', NS(foo=['a'])),
789 ]
790
791
792class TestPositionalsNargs2(ParserTestCase):
793 """Test a Positional that specifies an nargs of 2"""
794
795 argument_signatures = [Sig('foo', nargs=2)]
796 failures = ['', 'a', '-x', 'a b c']
797 successes = [
798 ('a b', NS(foo=['a', 'b'])),
799 ]
800
801
802class TestPositionalsNargsZeroOrMore(ParserTestCase):
803 """Test a Positional that specifies unlimited nargs"""
804
805 argument_signatures = [Sig('foo', nargs='*')]
806 failures = ['-x']
807 successes = [
808 ('', NS(foo=[])),
809 ('a', NS(foo=['a'])),
810 ('a b', NS(foo=['a', 'b'])),
811 ]
812
813
814class TestPositionalsNargsZeroOrMoreDefault(ParserTestCase):
815 """Test a Positional that specifies unlimited nargs and a default"""
816
817 argument_signatures = [Sig('foo', nargs='*', default='bar')]
818 failures = ['-x']
819 successes = [
820 ('', NS(foo='bar')),
821 ('a', NS(foo=['a'])),
822 ('a b', NS(foo=['a', 'b'])),
823 ]
824
825
826class TestPositionalsNargsOneOrMore(ParserTestCase):
827 """Test a Positional that specifies one or more nargs"""
828
829 argument_signatures = [Sig('foo', nargs='+')]
830 failures = ['', '-x']
831 successes = [
832 ('a', NS(foo=['a'])),
833 ('a b', NS(foo=['a', 'b'])),
834 ]
835
836
837class TestPositionalsNargsOptional(ParserTestCase):
838 """Tests an Optional Positional"""
839
840 argument_signatures = [Sig('foo', nargs='?')]
841 failures = ['-x', 'a b']
842 successes = [
843 ('', NS(foo=None)),
844 ('a', NS(foo='a')),
845 ]
846
847
848class TestPositionalsNargsOptionalDefault(ParserTestCase):
849 """Tests an Optional Positional with a default value"""
850
851 argument_signatures = [Sig('foo', nargs='?', default=42)]
852 failures = ['-x', 'a b']
853 successes = [
854 ('', NS(foo=42)),
855 ('a', NS(foo='a')),
856 ]
857
858
859class TestPositionalsNargsOptionalConvertedDefault(ParserTestCase):
860 """Tests an Optional Positional with a default value
861 that needs to be converted to the appropriate type.
862 """
863
864 argument_signatures = [
865 Sig('foo', nargs='?', type=int, default='42'),
866 ]
867 failures = ['-x', 'a b', '1 2']
868 successes = [
869 ('', NS(foo=42)),
870 ('1', NS(foo=1)),
871 ]
872
873
874class TestPositionalsNargsNoneNone(ParserTestCase):
875 """Test two Positionals that don't specify nargs"""
876
877 argument_signatures = [Sig('foo'), Sig('bar')]
878 failures = ['', '-x', 'a', 'a b c']
879 successes = [
880 ('a b', NS(foo='a', bar='b')),
881 ]
882
883
884class TestPositionalsNargsNone1(ParserTestCase):
885 """Test a Positional with no nargs followed by one with 1"""
886
887 argument_signatures = [Sig('foo'), Sig('bar', nargs=1)]
888 failures = ['', '--foo', 'a', 'a b c']
889 successes = [
890 ('a b', NS(foo='a', bar=['b'])),
891 ]
892
893
894class TestPositionalsNargs2None(ParserTestCase):
895 """Test a Positional with 2 nargs followed by one with none"""
896
897 argument_signatures = [Sig('foo', nargs=2), Sig('bar')]
898 failures = ['', '--foo', 'a', 'a b', 'a b c d']
899 successes = [
900 ('a b c', NS(foo=['a', 'b'], bar='c')),
901 ]
902
903
904class TestPositionalsNargsNoneZeroOrMore(ParserTestCase):
905 """Test a Positional with no nargs followed by one with unlimited"""
906
907 argument_signatures = [Sig('foo'), Sig('bar', nargs='*')]
908 failures = ['', '--foo']
909 successes = [
910 ('a', NS(foo='a', bar=[])),
911 ('a b', NS(foo='a', bar=['b'])),
912 ('a b c', NS(foo='a', bar=['b', 'c'])),
913 ]
914
915
916class TestPositionalsNargsNoneOneOrMore(ParserTestCase):
917 """Test a Positional with no nargs followed by one with one or more"""
918
919 argument_signatures = [Sig('foo'), Sig('bar', nargs='+')]
920 failures = ['', '--foo', 'a']
921 successes = [
922 ('a b', NS(foo='a', bar=['b'])),
923 ('a b c', NS(foo='a', bar=['b', 'c'])),
924 ]
925
926
927class TestPositionalsNargsNoneOptional(ParserTestCase):
928 """Test a Positional with no nargs followed by one with an Optional"""
929
930 argument_signatures = [Sig('foo'), Sig('bar', nargs='?')]
931 failures = ['', '--foo', 'a b c']
932 successes = [
933 ('a', NS(foo='a', bar=None)),
934 ('a b', NS(foo='a', bar='b')),
935 ]
936
937
938class TestPositionalsNargsZeroOrMoreNone(ParserTestCase):
939 """Test a Positional with unlimited nargs followed by one with none"""
940
941 argument_signatures = [Sig('foo', nargs='*'), Sig('bar')]
942 failures = ['', '--foo']
943 successes = [
944 ('a', NS(foo=[], bar='a')),
945 ('a b', NS(foo=['a'], bar='b')),
946 ('a b c', NS(foo=['a', 'b'], bar='c')),
947 ]
948
949
950class TestPositionalsNargsOneOrMoreNone(ParserTestCase):
951 """Test a Positional with one or more nargs followed by one with none"""
952
953 argument_signatures = [Sig('foo', nargs='+'), Sig('bar')]
954 failures = ['', '--foo', 'a']
955 successes = [
956 ('a b', NS(foo=['a'], bar='b')),
957 ('a b c', NS(foo=['a', 'b'], bar='c')),
958 ]
959
960
961class TestPositionalsNargsOptionalNone(ParserTestCase):
962 """Test a Positional with an Optional nargs followed by one with none"""
963
964 argument_signatures = [Sig('foo', nargs='?', default=42), Sig('bar')]
965 failures = ['', '--foo', 'a b c']
966 successes = [
967 ('a', NS(foo=42, bar='a')),
968 ('a b', NS(foo='a', bar='b')),
969 ]
970
971
972class TestPositionalsNargs2ZeroOrMore(ParserTestCase):
973 """Test a Positional with 2 nargs followed by one with unlimited"""
974
975 argument_signatures = [Sig('foo', nargs=2), Sig('bar', nargs='*')]
976 failures = ['', '--foo', 'a']
977 successes = [
978 ('a b', NS(foo=['a', 'b'], bar=[])),
979 ('a b c', NS(foo=['a', 'b'], bar=['c'])),
980 ]
981
982
983class TestPositionalsNargs2OneOrMore(ParserTestCase):
984 """Test a Positional with 2 nargs followed by one with one or more"""
985
986 argument_signatures = [Sig('foo', nargs=2), Sig('bar', nargs='+')]
987 failures = ['', '--foo', 'a', 'a b']
988 successes = [
989 ('a b c', NS(foo=['a', 'b'], bar=['c'])),
990 ]
991
992
993class TestPositionalsNargs2Optional(ParserTestCase):
994 """Test a Positional with 2 nargs followed by one optional"""
995
996 argument_signatures = [Sig('foo', nargs=2), Sig('bar', nargs='?')]
997 failures = ['', '--foo', 'a', 'a b c d']
998 successes = [
999 ('a b', NS(foo=['a', 'b'], bar=None)),
1000 ('a b c', NS(foo=['a', 'b'], bar='c')),
1001 ]
1002
1003
1004class TestPositionalsNargsZeroOrMore1(ParserTestCase):
1005 """Test a Positional with unlimited nargs followed by one with 1"""
1006
1007 argument_signatures = [Sig('foo', nargs='*'), Sig('bar', nargs=1)]
1008 failures = ['', '--foo', ]
1009 successes = [
1010 ('a', NS(foo=[], bar=['a'])),
1011 ('a b', NS(foo=['a'], bar=['b'])),
1012 ('a b c', NS(foo=['a', 'b'], bar=['c'])),
1013 ]
1014
1015
1016class TestPositionalsNargsOneOrMore1(ParserTestCase):
1017 """Test a Positional with one or more nargs followed by one with 1"""
1018
1019 argument_signatures = [Sig('foo', nargs='+'), Sig('bar', nargs=1)]
1020 failures = ['', '--foo', 'a']
1021 successes = [
1022 ('a b', NS(foo=['a'], bar=['b'])),
1023 ('a b c', NS(foo=['a', 'b'], bar=['c'])),
1024 ]
1025
1026
1027class TestPositionalsNargsOptional1(ParserTestCase):
1028 """Test a Positional with an Optional nargs followed by one with 1"""
1029
1030 argument_signatures = [Sig('foo', nargs='?'), Sig('bar', nargs=1)]
1031 failures = ['', '--foo', 'a b c']
1032 successes = [
1033 ('a', NS(foo=None, bar=['a'])),
1034 ('a b', NS(foo='a', bar=['b'])),
1035 ]
1036
1037
1038class TestPositionalsNargsNoneZeroOrMore1(ParserTestCase):
1039 """Test three Positionals: no nargs, unlimited nargs and 1 nargs"""
1040
1041 argument_signatures = [
1042 Sig('foo'),
1043 Sig('bar', nargs='*'),
1044 Sig('baz', nargs=1),
1045 ]
1046 failures = ['', '--foo', 'a']
1047 successes = [
1048 ('a b', NS(foo='a', bar=[], baz=['b'])),
1049 ('a b c', NS(foo='a', bar=['b'], baz=['c'])),
1050 ]
1051
1052
1053class TestPositionalsNargsNoneOneOrMore1(ParserTestCase):
1054 """Test three Positionals: no nargs, one or more nargs and 1 nargs"""
1055
1056 argument_signatures = [
1057 Sig('foo'),
1058 Sig('bar', nargs='+'),
1059 Sig('baz', nargs=1),
1060 ]
1061 failures = ['', '--foo', 'a', 'b']
1062 successes = [
1063 ('a b c', NS(foo='a', bar=['b'], baz=['c'])),
1064 ('a b c d', NS(foo='a', bar=['b', 'c'], baz=['d'])),
1065 ]
1066
1067
1068class TestPositionalsNargsNoneOptional1(ParserTestCase):
1069 """Test three Positionals: no nargs, optional narg and 1 nargs"""
1070
1071 argument_signatures = [
1072 Sig('foo'),
1073 Sig('bar', nargs='?', default=0.625),
1074 Sig('baz', nargs=1),
1075 ]
1076 failures = ['', '--foo', 'a']
1077 successes = [
1078 ('a b', NS(foo='a', bar=0.625, baz=['b'])),
1079 ('a b c', NS(foo='a', bar='b', baz=['c'])),
1080 ]
1081
1082
1083class TestPositionalsNargsOptionalOptional(ParserTestCase):
1084 """Test two optional nargs"""
1085
1086 argument_signatures = [
1087 Sig('foo', nargs='?'),
1088 Sig('bar', nargs='?', default=42),
1089 ]
1090 failures = ['--foo', 'a b c']
1091 successes = [
1092 ('', NS(foo=None, bar=42)),
1093 ('a', NS(foo='a', bar=42)),
1094 ('a b', NS(foo='a', bar='b')),
1095 ]
1096
1097
1098class TestPositionalsNargsOptionalZeroOrMore(ParserTestCase):
1099 """Test an Optional narg followed by unlimited nargs"""
1100
1101 argument_signatures = [Sig('foo', nargs='?'), Sig('bar', nargs='*')]
1102 failures = ['--foo']
1103 successes = [
1104 ('', NS(foo=None, bar=[])),
1105 ('a', NS(foo='a', bar=[])),
1106 ('a b', NS(foo='a', bar=['b'])),
1107 ('a b c', NS(foo='a', bar=['b', 'c'])),
1108 ]
1109
1110
1111class TestPositionalsNargsOptionalOneOrMore(ParserTestCase):
1112 """Test an Optional narg followed by one or more nargs"""
1113
1114 argument_signatures = [Sig('foo', nargs='?'), Sig('bar', nargs='+')]
1115 failures = ['', '--foo']
1116 successes = [
1117 ('a', NS(foo=None, bar=['a'])),
1118 ('a b', NS(foo='a', bar=['b'])),
1119 ('a b c', NS(foo='a', bar=['b', 'c'])),
1120 ]
1121
1122
1123class TestPositionalsChoicesString(ParserTestCase):
1124 """Test a set of single-character choices"""
1125
1126 argument_signatures = [Sig('spam', choices=set('abcdefg'))]
1127 failures = ['', '--foo', 'h', '42', 'ef']
1128 successes = [
1129 ('a', NS(spam='a')),
1130 ('g', NS(spam='g')),
1131 ]
1132
1133
1134class TestPositionalsChoicesInt(ParserTestCase):
1135 """Test a set of integer choices"""
1136
1137 argument_signatures = [Sig('spam', type=int, choices=range(20))]
1138 failures = ['', '--foo', 'h', '42', 'ef']
1139 successes = [
1140 ('4', NS(spam=4)),
1141 ('15', NS(spam=15)),
1142 ]
1143
1144
1145class TestPositionalsActionAppend(ParserTestCase):
1146 """Test the 'append' action"""
1147
1148 argument_signatures = [
1149 Sig('spam', action='append'),
1150 Sig('spam', action='append', nargs=2),
1151 ]
1152 failures = ['', '--foo', 'a', 'a b', 'a b c d']
1153 successes = [
1154 ('a b c', NS(spam=['a', ['b', 'c']])),
1155 ]
1156
1157# ========================================
1158# Combined optionals and positionals tests
1159# ========================================
1160
1161class TestOptionalsNumericAndPositionals(ParserTestCase):
1162 """Tests negative number args when numeric options are present"""
1163
1164 argument_signatures = [
1165 Sig('x', nargs='?'),
1166 Sig('-4', dest='y', action='store_true'),
1167 ]
1168 failures = ['-2', '-315']
1169 successes = [
1170 ('', NS(x=None, y=False)),
1171 ('a', NS(x='a', y=False)),
1172 ('-4', NS(x=None, y=True)),
1173 ('-4 a', NS(x='a', y=True)),
1174 ]
1175
1176
1177class TestOptionalsAlmostNumericAndPositionals(ParserTestCase):
1178 """Tests negative number args when almost numeric options are present"""
1179
1180 argument_signatures = [
1181 Sig('x', nargs='?'),
1182 Sig('-k4', dest='y', action='store_true'),
1183 ]
1184 failures = ['-k3']
1185 successes = [
1186 ('', NS(x=None, y=False)),
1187 ('-2', NS(x='-2', y=False)),
1188 ('a', NS(x='a', y=False)),
1189 ('-k4', NS(x=None, y=True)),
1190 ('-k4 a', NS(x='a', y=True)),
1191 ]
1192
1193
1194class TestEmptyAndSpaceContainingArguments(ParserTestCase):
1195
1196 argument_signatures = [
1197 Sig('x', nargs='?'),
1198 Sig('-y', '--yyy', dest='y'),
1199 ]
1200 failures = ['-y']
1201 successes = [
1202 ([''], NS(x='', y=None)),
1203 (['a badger'], NS(x='a badger', y=None)),
1204 (['-a badger'], NS(x='-a badger', y=None)),
1205 (['-y', ''], NS(x=None, y='')),
1206 (['-y', 'a badger'], NS(x=None, y='a badger')),
1207 (['-y', '-a badger'], NS(x=None, y='-a badger')),
1208 (['--yyy=a badger'], NS(x=None, y='a badger')),
1209 (['--yyy=-a badger'], NS(x=None, y='-a badger')),
1210 ]
1211
1212
1213class TestPrefixCharacterOnlyArguments(ParserTestCase):
1214
1215 parser_signature = Sig(prefix_chars='-+')
1216 argument_signatures = [
1217 Sig('-', dest='x', nargs='?', const='badger'),
1218 Sig('+', dest='y', type=int, default=42),
1219 Sig('-+-', dest='z', action='store_true'),
1220 ]
1221 failures = ['-y', '+ -']
1222 successes = [
1223 ('', NS(x=None, y=42, z=False)),
1224 ('-', NS(x='badger', y=42, z=False)),
1225 ('- X', NS(x='X', y=42, z=False)),
1226 ('+ -3', NS(x=None, y=-3, z=False)),
1227 ('-+-', NS(x=None, y=42, z=True)),
1228 ('- ===', NS(x='===', y=42, z=False)),
1229 ]
1230
1231
1232class TestNargsZeroOrMore(ParserTestCase):
1233 """Tests specifying an args for an Optional that accepts zero or more"""
1234
1235 argument_signatures = [Sig('-x', nargs='*'), Sig('y', nargs='*')]
1236 failures = []
1237 successes = [
1238 ('', NS(x=None, y=[])),
1239 ('-x', NS(x=[], y=[])),
1240 ('-x a', NS(x=['a'], y=[])),
1241 ('-x a -- b', NS(x=['a'], y=['b'])),
1242 ('a', NS(x=None, y=['a'])),
1243 ('a -x', NS(x=[], y=['a'])),
1244 ('a -x b', NS(x=['b'], y=['a'])),
1245 ]
1246
1247
1248class TestNargsRemainder(ParserTestCase):
1249 """Tests specifying a positional with nargs=REMAINDER"""
1250
1251 argument_signatures = [Sig('x'), Sig('y', nargs='...'), Sig('-z')]
1252 failures = ['', '-z', '-z Z']
1253 successes = [
1254 ('X', NS(x='X', y=[], z=None)),
1255 ('-z Z X', NS(x='X', y=[], z='Z')),
1256 ('X A B -z Z', NS(x='X', y=['A', 'B', '-z', 'Z'], z=None)),
1257 ('X Y --foo', NS(x='X', y=['Y', '--foo'], z=None)),
1258 ]
1259
1260
1261class TestOptionLike(ParserTestCase):
1262 """Tests options that may or may not be arguments"""
1263
1264 argument_signatures = [
1265 Sig('-x', type=float),
1266 Sig('-3', type=float, dest='y'),
1267 Sig('z', nargs='*'),
1268 ]
1269 failures = ['-x', '-y2.5', '-xa', '-x -a',
1270 '-x -3', '-x -3.5', '-3 -3.5',
1271 '-x -2.5', '-x -2.5 a', '-3 -.5',
1272 'a x -1', '-x -1 a', '-3 -1 a']
1273 successes = [
1274 ('', NS(x=None, y=None, z=[])),
1275 ('-x 2.5', NS(x=2.5, y=None, z=[])),
1276 ('-x 2.5 a', NS(x=2.5, y=None, z=['a'])),
1277 ('-3.5', NS(x=None, y=0.5, z=[])),
1278 ('-3-.5', NS(x=None, y=-0.5, z=[])),
1279 ('-3 .5', NS(x=None, y=0.5, z=[])),
1280 ('a -3.5', NS(x=None, y=0.5, z=['a'])),
1281 ('a', NS(x=None, y=None, z=['a'])),
1282 ('a -x 1', NS(x=1.0, y=None, z=['a'])),
1283 ('-x 1 a', NS(x=1.0, y=None, z=['a'])),
1284 ('-3 1 a', NS(x=None, y=1.0, z=['a'])),
1285 ]
1286
1287
1288class TestDefaultSuppress(ParserTestCase):
1289 """Test actions with suppressed defaults"""
1290
1291 argument_signatures = [
1292 Sig('foo', nargs='?', default=argparse.SUPPRESS),
1293 Sig('bar', nargs='*', default=argparse.SUPPRESS),
1294 Sig('--baz', action='store_true', default=argparse.SUPPRESS),
1295 ]
1296 failures = ['-x']
1297 successes = [
1298 ('', NS()),
1299 ('a', NS(foo='a')),
1300 ('a b', NS(foo='a', bar=['b'])),
1301 ('--baz', NS(baz=True)),
1302 ('a --baz', NS(foo='a', baz=True)),
1303 ('--baz a b', NS(foo='a', bar=['b'], baz=True)),
1304 ]
1305
1306
1307class TestParserDefaultSuppress(ParserTestCase):
1308 """Test actions with a parser-level default of SUPPRESS"""
1309
1310 parser_signature = Sig(argument_default=argparse.SUPPRESS)
1311 argument_signatures = [
1312 Sig('foo', nargs='?'),
1313 Sig('bar', nargs='*'),
1314 Sig('--baz', action='store_true'),
1315 ]
1316 failures = ['-x']
1317 successes = [
1318 ('', NS()),
1319 ('a', NS(foo='a')),
1320 ('a b', NS(foo='a', bar=['b'])),
1321 ('--baz', NS(baz=True)),
1322 ('a --baz', NS(foo='a', baz=True)),
1323 ('--baz a b', NS(foo='a', bar=['b'], baz=True)),
1324 ]
1325
1326
1327class TestParserDefault42(ParserTestCase):
1328 """Test actions with a parser-level default of 42"""
1329
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02001330 parser_signature = Sig(argument_default=42)
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001331 argument_signatures = [
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02001332 Sig('--version', action='version', version='1.0'),
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001333 Sig('foo', nargs='?'),
1334 Sig('bar', nargs='*'),
1335 Sig('--baz', action='store_true'),
1336 ]
1337 failures = ['-x']
1338 successes = [
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02001339 ('', NS(foo=42, bar=42, baz=42, version=42)),
1340 ('a', NS(foo='a', bar=42, baz=42, version=42)),
1341 ('a b', NS(foo='a', bar=['b'], baz=42, version=42)),
1342 ('--baz', NS(foo=42, bar=42, baz=True, version=42)),
1343 ('a --baz', NS(foo='a', bar=42, baz=True, version=42)),
1344 ('--baz a b', NS(foo='a', bar=['b'], baz=True, version=42)),
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001345 ]
1346
1347
1348class TestArgumentsFromFile(TempDirMixin, ParserTestCase):
1349 """Test reading arguments from a file"""
1350
1351 def setUp(self):
1352 super(TestArgumentsFromFile, self).setUp()
1353 file_texts = [
1354 ('hello', 'hello world!\n'),
1355 ('recursive', '-a\n'
1356 'A\n'
1357 '@hello'),
1358 ('invalid', '@no-such-path\n'),
1359 ]
1360 for path, text in file_texts:
1361 file = open(path, 'w')
1362 file.write(text)
1363 file.close()
1364
1365 parser_signature = Sig(fromfile_prefix_chars='@')
1366 argument_signatures = [
1367 Sig('-a'),
1368 Sig('x'),
1369 Sig('y', nargs='+'),
1370 ]
1371 failures = ['', '-b', 'X', '@invalid', '@missing']
1372 successes = [
1373 ('X Y', NS(a=None, x='X', y=['Y'])),
1374 ('X -a A Y Z', NS(a='A', x='X', y=['Y', 'Z'])),
1375 ('@hello X', NS(a=None, x='hello world!', y=['X'])),
1376 ('X @hello', NS(a=None, x='X', y=['hello world!'])),
1377 ('-a B @recursive Y Z', NS(a='A', x='hello world!', y=['Y', 'Z'])),
1378 ('X @recursive Z -a B', NS(a='B', x='X', y=['hello world!', 'Z'])),
R David Murrayb94082a2012-07-21 22:20:11 -04001379 (["-a", "", "X", "Y"], NS(a='', x='X', y=['Y'])),
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001380 ]
1381
1382
1383class TestArgumentsFromFileConverter(TempDirMixin, ParserTestCase):
1384 """Test reading arguments from a file"""
1385
1386 def setUp(self):
1387 super(TestArgumentsFromFileConverter, self).setUp()
1388 file_texts = [
1389 ('hello', 'hello world!\n'),
1390 ]
1391 for path, text in file_texts:
1392 file = open(path, 'w')
1393 file.write(text)
1394 file.close()
1395
1396 class FromFileConverterArgumentParser(ErrorRaisingArgumentParser):
1397
1398 def convert_arg_line_to_args(self, arg_line):
1399 for arg in arg_line.split():
1400 if not arg.strip():
1401 continue
1402 yield arg
1403 parser_class = FromFileConverterArgumentParser
1404 parser_signature = Sig(fromfile_prefix_chars='@')
1405 argument_signatures = [
1406 Sig('y', nargs='+'),
1407 ]
1408 failures = []
1409 successes = [
1410 ('@hello X', NS(y=['hello', 'world!', 'X'])),
1411 ]
1412
1413
1414# =====================
1415# Type conversion tests
1416# =====================
1417
1418class TestFileTypeRepr(TestCase):
1419
1420 def test_r(self):
1421 type = argparse.FileType('r')
1422 self.assertEqual("FileType('r')", repr(type))
1423
1424 def test_wb_1(self):
1425 type = argparse.FileType('wb', 1)
1426 self.assertEqual("FileType('wb', 1)", repr(type))
1427
Petri Lehtinen74d6c252012-12-15 22:39:32 +02001428 def test_r_latin(self):
1429 type = argparse.FileType('r', encoding='latin_1')
1430 self.assertEqual("FileType('r', encoding='latin_1')", repr(type))
1431
1432 def test_w_big5_ignore(self):
1433 type = argparse.FileType('w', encoding='big5', errors='ignore')
1434 self.assertEqual("FileType('w', encoding='big5', errors='ignore')",
1435 repr(type))
1436
1437 def test_r_1_replace(self):
1438 type = argparse.FileType('r', 1, errors='replace')
1439 self.assertEqual("FileType('r', 1, errors='replace')", repr(type))
1440
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001441
1442class RFile(object):
1443 seen = {}
1444
1445 def __init__(self, name):
1446 self.name = name
1447
1448 def __eq__(self, other):
1449 if other in self.seen:
1450 text = self.seen[other]
1451 else:
1452 text = self.seen[other] = other.read()
1453 other.close()
1454 if not isinstance(text, str):
1455 text = text.decode('ascii')
1456 return self.name == other.name == text
1457
1458
1459class TestFileTypeR(TempDirMixin, ParserTestCase):
1460 """Test the FileType option/argument type for reading files"""
1461
1462 def setUp(self):
1463 super(TestFileTypeR, self).setUp()
1464 for file_name in ['foo', 'bar']:
1465 file = open(os.path.join(self.temp_dir, file_name), 'w')
1466 file.write(file_name)
1467 file.close()
Steven Bethardb0270112011-01-24 21:02:50 +00001468 self.create_readonly_file('readonly')
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001469
1470 argument_signatures = [
1471 Sig('-x', type=argparse.FileType()),
1472 Sig('spam', type=argparse.FileType('r')),
1473 ]
Steven Bethardb0270112011-01-24 21:02:50 +00001474 failures = ['-x', '', 'non-existent-file.txt']
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001475 successes = [
1476 ('foo', NS(x=None, spam=RFile('foo'))),
1477 ('-x foo bar', NS(x=RFile('foo'), spam=RFile('bar'))),
1478 ('bar -x foo', NS(x=RFile('foo'), spam=RFile('bar'))),
1479 ('-x - -', NS(x=sys.stdin, spam=sys.stdin)),
Steven Bethardb0270112011-01-24 21:02:50 +00001480 ('readonly', NS(x=None, spam=RFile('readonly'))),
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001481 ]
1482
R David Murray6fb8fb12012-08-31 22:45:20 -04001483class TestFileTypeDefaults(TempDirMixin, ParserTestCase):
1484 """Test that a file is not created unless the default is needed"""
1485 def setUp(self):
1486 super(TestFileTypeDefaults, self).setUp()
1487 file = open(os.path.join(self.temp_dir, 'good'), 'w')
1488 file.write('good')
1489 file.close()
1490
1491 argument_signatures = [
1492 Sig('-c', type=argparse.FileType('r'), default='no-file.txt'),
1493 ]
1494 # should provoke no such file error
1495 failures = ['']
1496 # should not provoke error because default file is created
1497 successes = [('-c good', NS(c=RFile('good')))]
1498
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001499
1500class TestFileTypeRB(TempDirMixin, ParserTestCase):
1501 """Test the FileType option/argument type for reading files"""
1502
1503 def setUp(self):
1504 super(TestFileTypeRB, self).setUp()
1505 for file_name in ['foo', 'bar']:
1506 file = open(os.path.join(self.temp_dir, file_name), 'w')
1507 file.write(file_name)
1508 file.close()
1509
1510 argument_signatures = [
1511 Sig('-x', type=argparse.FileType('rb')),
1512 Sig('spam', type=argparse.FileType('rb')),
1513 ]
1514 failures = ['-x', '']
1515 successes = [
1516 ('foo', NS(x=None, spam=RFile('foo'))),
1517 ('-x foo bar', NS(x=RFile('foo'), spam=RFile('bar'))),
1518 ('bar -x foo', NS(x=RFile('foo'), spam=RFile('bar'))),
1519 ('-x - -', NS(x=sys.stdin, spam=sys.stdin)),
1520 ]
1521
1522
1523class WFile(object):
1524 seen = set()
1525
1526 def __init__(self, name):
1527 self.name = name
1528
1529 def __eq__(self, other):
1530 if other not in self.seen:
1531 text = 'Check that file is writable.'
1532 if 'b' in other.mode:
1533 text = text.encode('ascii')
1534 other.write(text)
1535 other.close()
1536 self.seen.add(other)
1537 return self.name == other.name
1538
1539
Victor Stinnera04b39b2011-11-20 23:09:09 +01001540@unittest.skipIf(hasattr(os, 'geteuid') and os.geteuid() == 0,
1541 "non-root user required")
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001542class TestFileTypeW(TempDirMixin, ParserTestCase):
1543 """Test the FileType option/argument type for writing files"""
1544
Steven Bethardb0270112011-01-24 21:02:50 +00001545 def setUp(self):
1546 super(TestFileTypeW, self).setUp()
1547 self.create_readonly_file('readonly')
1548
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001549 argument_signatures = [
1550 Sig('-x', type=argparse.FileType('w')),
1551 Sig('spam', type=argparse.FileType('w')),
1552 ]
Steven Bethardb0270112011-01-24 21:02:50 +00001553 failures = ['-x', '', 'readonly']
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001554 successes = [
1555 ('foo', NS(x=None, spam=WFile('foo'))),
1556 ('-x foo bar', NS(x=WFile('foo'), spam=WFile('bar'))),
1557 ('bar -x foo', NS(x=WFile('foo'), spam=WFile('bar'))),
1558 ('-x - -', NS(x=sys.stdout, spam=sys.stdout)),
1559 ]
1560
1561
1562class TestFileTypeWB(TempDirMixin, ParserTestCase):
1563
1564 argument_signatures = [
1565 Sig('-x', type=argparse.FileType('wb')),
1566 Sig('spam', type=argparse.FileType('wb')),
1567 ]
1568 failures = ['-x', '']
1569 successes = [
1570 ('foo', NS(x=None, spam=WFile('foo'))),
1571 ('-x foo bar', NS(x=WFile('foo'), spam=WFile('bar'))),
1572 ('bar -x foo', NS(x=WFile('foo'), spam=WFile('bar'))),
1573 ('-x - -', NS(x=sys.stdout, spam=sys.stdout)),
1574 ]
1575
1576
Petri Lehtinen74d6c252012-12-15 22:39:32 +02001577class TestFileTypeOpenArgs(TestCase):
1578 """Test that open (the builtin) is correctly called"""
1579
1580 def test_open_args(self):
1581 FT = argparse.FileType
1582 cases = [
1583 (FT('rb'), ('rb', -1, None, None)),
1584 (FT('w', 1), ('w', 1, None, None)),
1585 (FT('w', errors='replace'), ('w', -1, None, 'replace')),
1586 (FT('wb', encoding='big5'), ('wb', -1, 'big5', None)),
1587 (FT('w', 0, 'l1', 'strict'), ('w', 0, 'l1', 'strict')),
1588 ]
1589 with mock.patch('builtins.open') as m:
1590 for type, args in cases:
1591 type('foo')
1592 m.assert_called_with('foo', *args)
1593
1594
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001595class TestTypeCallable(ParserTestCase):
1596 """Test some callables as option/argument types"""
1597
1598 argument_signatures = [
1599 Sig('--eggs', type=complex),
1600 Sig('spam', type=float),
1601 ]
1602 failures = ['a', '42j', '--eggs a', '--eggs 2i']
1603 successes = [
1604 ('--eggs=42 42', NS(eggs=42, spam=42.0)),
1605 ('--eggs 2j -- -1.5', NS(eggs=2j, spam=-1.5)),
1606 ('1024.675', NS(eggs=None, spam=1024.675)),
1607 ]
1608
1609
1610class TestTypeUserDefined(ParserTestCase):
1611 """Test a user-defined option/argument type"""
1612
1613 class MyType(TestCase):
1614
1615 def __init__(self, value):
1616 self.value = value
1617
1618 def __eq__(self, other):
1619 return (type(self), self.value) == (type(other), other.value)
1620
1621 argument_signatures = [
1622 Sig('-x', type=MyType),
1623 Sig('spam', type=MyType),
1624 ]
1625 failures = []
1626 successes = [
1627 ('a -x b', NS(x=MyType('b'), spam=MyType('a'))),
1628 ('-xf g', NS(x=MyType('f'), spam=MyType('g'))),
1629 ]
1630
1631
1632class TestTypeClassicClass(ParserTestCase):
1633 """Test a classic class type"""
1634
1635 class C:
1636
1637 def __init__(self, value):
1638 self.value = value
1639
1640 def __eq__(self, other):
1641 return (type(self), self.value) == (type(other), other.value)
1642
1643 argument_signatures = [
1644 Sig('-x', type=C),
1645 Sig('spam', type=C),
1646 ]
1647 failures = []
1648 successes = [
1649 ('a -x b', NS(x=C('b'), spam=C('a'))),
1650 ('-xf g', NS(x=C('f'), spam=C('g'))),
1651 ]
1652
1653
1654class TestTypeRegistration(TestCase):
1655 """Test a user-defined type by registering it"""
1656
1657 def test(self):
1658
1659 def get_my_type(string):
1660 return 'my_type{%s}' % string
1661
1662 parser = argparse.ArgumentParser()
1663 parser.register('type', 'my_type', get_my_type)
1664 parser.add_argument('-x', type='my_type')
1665 parser.add_argument('y', type='my_type')
1666
1667 self.assertEqual(parser.parse_args('1'.split()),
1668 NS(x=None, y='my_type{1}'))
1669 self.assertEqual(parser.parse_args('-x 1 42'.split()),
1670 NS(x='my_type{1}', y='my_type{42}'))
1671
1672
1673# ============
1674# Action tests
1675# ============
1676
1677class TestActionUserDefined(ParserTestCase):
1678 """Test a user-defined option/argument action"""
1679
1680 class OptionalAction(argparse.Action):
1681
1682 def __call__(self, parser, namespace, value, option_string=None):
1683 try:
1684 # check destination and option string
1685 assert self.dest == 'spam', 'dest: %s' % self.dest
1686 assert option_string == '-s', 'flag: %s' % option_string
1687 # when option is before argument, badger=2, and when
1688 # option is after argument, badger=<whatever was set>
1689 expected_ns = NS(spam=0.25)
1690 if value in [0.125, 0.625]:
1691 expected_ns.badger = 2
1692 elif value in [2.0]:
1693 expected_ns.badger = 84
1694 else:
1695 raise AssertionError('value: %s' % value)
1696 assert expected_ns == namespace, ('expected %s, got %s' %
1697 (expected_ns, namespace))
1698 except AssertionError:
1699 e = sys.exc_info()[1]
1700 raise ArgumentParserError('opt_action failed: %s' % e)
1701 setattr(namespace, 'spam', value)
1702
1703 class PositionalAction(argparse.Action):
1704
1705 def __call__(self, parser, namespace, value, option_string=None):
1706 try:
1707 assert option_string is None, ('option_string: %s' %
1708 option_string)
1709 # check destination
1710 assert self.dest == 'badger', 'dest: %s' % self.dest
1711 # when argument is before option, spam=0.25, and when
1712 # option is after argument, spam=<whatever was set>
1713 expected_ns = NS(badger=2)
1714 if value in [42, 84]:
1715 expected_ns.spam = 0.25
1716 elif value in [1]:
1717 expected_ns.spam = 0.625
1718 elif value in [2]:
1719 expected_ns.spam = 0.125
1720 else:
1721 raise AssertionError('value: %s' % value)
1722 assert expected_ns == namespace, ('expected %s, got %s' %
1723 (expected_ns, namespace))
1724 except AssertionError:
1725 e = sys.exc_info()[1]
1726 raise ArgumentParserError('arg_action failed: %s' % e)
1727 setattr(namespace, 'badger', value)
1728
1729 argument_signatures = [
1730 Sig('-s', dest='spam', action=OptionalAction,
1731 type=float, default=0.25),
1732 Sig('badger', action=PositionalAction,
1733 type=int, nargs='?', default=2),
1734 ]
1735 failures = []
1736 successes = [
1737 ('-s0.125', NS(spam=0.125, badger=2)),
1738 ('42', NS(spam=0.25, badger=42)),
1739 ('-s 0.625 1', NS(spam=0.625, badger=1)),
1740 ('84 -s2', NS(spam=2.0, badger=84)),
1741 ]
1742
1743
1744class TestActionRegistration(TestCase):
1745 """Test a user-defined action supplied by registering it"""
1746
1747 class MyAction(argparse.Action):
1748
1749 def __call__(self, parser, namespace, values, option_string=None):
1750 setattr(namespace, self.dest, 'foo[%s]' % values)
1751
1752 def test(self):
1753
1754 parser = argparse.ArgumentParser()
1755 parser.register('action', 'my_action', self.MyAction)
1756 parser.add_argument('badger', action='my_action')
1757
1758 self.assertEqual(parser.parse_args(['1']), NS(badger='foo[1]'))
1759 self.assertEqual(parser.parse_args(['42']), NS(badger='foo[42]'))
1760
1761
1762# ================
1763# Subparsers tests
1764# ================
1765
1766class TestAddSubparsers(TestCase):
1767 """Test the add_subparsers method"""
1768
1769 def assertArgumentParserError(self, *args, **kwargs):
1770 self.assertRaises(ArgumentParserError, *args, **kwargs)
1771
Steven Bethardfd311a72010-12-18 11:19:23 +00001772 def _get_parser(self, subparser_help=False, prefix_chars=None,
1773 aliases=False):
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001774 # create a parser with a subparsers argument
R. David Murray88c49fe2010-08-03 17:56:09 +00001775 if prefix_chars:
1776 parser = ErrorRaisingArgumentParser(
1777 prog='PROG', description='main description', prefix_chars=prefix_chars)
1778 parser.add_argument(
1779 prefix_chars[0] * 2 + 'foo', action='store_true', help='foo help')
1780 else:
1781 parser = ErrorRaisingArgumentParser(
1782 prog='PROG', description='main description')
1783 parser.add_argument(
1784 '--foo', action='store_true', help='foo help')
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001785 parser.add_argument(
1786 'bar', type=float, help='bar help')
1787
1788 # check that only one subparsers argument can be added
Steven Bethardfd311a72010-12-18 11:19:23 +00001789 subparsers_kwargs = {}
1790 if aliases:
1791 subparsers_kwargs['metavar'] = 'COMMAND'
1792 subparsers_kwargs['title'] = 'commands'
1793 else:
1794 subparsers_kwargs['help'] = 'command help'
1795 subparsers = parser.add_subparsers(**subparsers_kwargs)
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001796 self.assertArgumentParserError(parser.add_subparsers)
1797
1798 # add first sub-parser
1799 parser1_kwargs = dict(description='1 description')
1800 if subparser_help:
1801 parser1_kwargs['help'] = '1 help'
Steven Bethardfd311a72010-12-18 11:19:23 +00001802 if aliases:
1803 parser1_kwargs['aliases'] = ['1alias1', '1alias2']
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001804 parser1 = subparsers.add_parser('1', **parser1_kwargs)
1805 parser1.add_argument('-w', type=int, help='w help')
1806 parser1.add_argument('x', choices='abc', help='x help')
1807
1808 # add second sub-parser
1809 parser2_kwargs = dict(description='2 description')
1810 if subparser_help:
1811 parser2_kwargs['help'] = '2 help'
1812 parser2 = subparsers.add_parser('2', **parser2_kwargs)
1813 parser2.add_argument('-y', choices='123', help='y help')
1814 parser2.add_argument('z', type=complex, nargs='*', help='z help')
1815
R David Murray00528e82012-07-21 22:48:35 -04001816 # add third sub-parser
1817 parser3_kwargs = dict(description='3 description')
1818 if subparser_help:
1819 parser3_kwargs['help'] = '3 help'
1820 parser3 = subparsers.add_parser('3', **parser3_kwargs)
1821 parser3.add_argument('t', type=int, help='t help')
1822 parser3.add_argument('u', nargs='...', help='u help')
1823
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001824 # return the main parser
1825 return parser
1826
1827 def setUp(self):
Steven Bethard1f1c2472010-11-01 13:56:09 +00001828 super().setUp()
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001829 self.parser = self._get_parser()
1830 self.command_help_parser = self._get_parser(subparser_help=True)
1831
1832 def test_parse_args_failures(self):
1833 # check some failure cases:
1834 for args_str in ['', 'a', 'a a', '0.5 a', '0.5 1',
1835 '0.5 1 -y', '0.5 2 -w']:
1836 args = args_str.split()
1837 self.assertArgumentParserError(self.parser.parse_args, args)
1838
1839 def test_parse_args(self):
1840 # check some non-failure cases:
1841 self.assertEqual(
1842 self.parser.parse_args('0.5 1 b -w 7'.split()),
1843 NS(foo=False, bar=0.5, w=7, x='b'),
1844 )
1845 self.assertEqual(
1846 self.parser.parse_args('0.25 --foo 2 -y 2 3j -- -1j'.split()),
1847 NS(foo=True, bar=0.25, y='2', z=[3j, -1j]),
1848 )
1849 self.assertEqual(
1850 self.parser.parse_args('--foo 0.125 1 c'.split()),
1851 NS(foo=True, bar=0.125, w=None, x='c'),
1852 )
R David Murray00528e82012-07-21 22:48:35 -04001853 self.assertEqual(
1854 self.parser.parse_args('-1.5 3 11 -- a --foo 7 -- b'.split()),
1855 NS(foo=False, bar=-1.5, t=11, u=['a', '--foo', '7', '--', 'b']),
1856 )
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001857
Steven Bethardfca2e8a2010-11-02 12:47:22 +00001858 def test_parse_known_args(self):
1859 self.assertEqual(
1860 self.parser.parse_known_args('0.5 1 b -w 7'.split()),
1861 (NS(foo=False, bar=0.5, w=7, x='b'), []),
1862 )
1863 self.assertEqual(
1864 self.parser.parse_known_args('0.5 -p 1 b -w 7'.split()),
1865 (NS(foo=False, bar=0.5, w=7, x='b'), ['-p']),
1866 )
1867 self.assertEqual(
1868 self.parser.parse_known_args('0.5 1 b -w 7 -p'.split()),
1869 (NS(foo=False, bar=0.5, w=7, x='b'), ['-p']),
1870 )
1871 self.assertEqual(
1872 self.parser.parse_known_args('0.5 1 b -q -rs -w 7'.split()),
1873 (NS(foo=False, bar=0.5, w=7, x='b'), ['-q', '-rs']),
1874 )
1875 self.assertEqual(
1876 self.parser.parse_known_args('0.5 -W 1 b -X Y -w 7 Z'.split()),
1877 (NS(foo=False, bar=0.5, w=7, x='b'), ['-W', '-X', 'Y', 'Z']),
1878 )
1879
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001880 def test_dest(self):
1881 parser = ErrorRaisingArgumentParser()
1882 parser.add_argument('--foo', action='store_true')
1883 subparsers = parser.add_subparsers(dest='bar')
1884 parser1 = subparsers.add_parser('1')
1885 parser1.add_argument('baz')
1886 self.assertEqual(NS(foo=False, bar='1', baz='2'),
1887 parser.parse_args('1 2'.split()))
1888
1889 def test_help(self):
1890 self.assertEqual(self.parser.format_usage(),
R David Murray00528e82012-07-21 22:48:35 -04001891 'usage: PROG [-h] [--foo] bar {1,2,3} ...\n')
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001892 self.assertEqual(self.parser.format_help(), textwrap.dedent('''\
R David Murray00528e82012-07-21 22:48:35 -04001893 usage: PROG [-h] [--foo] bar {1,2,3} ...
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001894
1895 main description
1896
1897 positional arguments:
1898 bar bar help
R David Murray00528e82012-07-21 22:48:35 -04001899 {1,2,3} command help
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001900
1901 optional arguments:
1902 -h, --help show this help message and exit
1903 --foo foo help
1904 '''))
1905
R. David Murray88c49fe2010-08-03 17:56:09 +00001906 def test_help_extra_prefix_chars(self):
1907 # Make sure - is still used for help if it is a non-first prefix char
1908 parser = self._get_parser(prefix_chars='+:-')
1909 self.assertEqual(parser.format_usage(),
R David Murray00528e82012-07-21 22:48:35 -04001910 'usage: PROG [-h] [++foo] bar {1,2,3} ...\n')
R. David Murray88c49fe2010-08-03 17:56:09 +00001911 self.assertEqual(parser.format_help(), textwrap.dedent('''\
R David Murray00528e82012-07-21 22:48:35 -04001912 usage: PROG [-h] [++foo] bar {1,2,3} ...
R. David Murray88c49fe2010-08-03 17:56:09 +00001913
1914 main description
1915
1916 positional arguments:
1917 bar bar help
R David Murray00528e82012-07-21 22:48:35 -04001918 {1,2,3} command help
R. David Murray88c49fe2010-08-03 17:56:09 +00001919
1920 optional arguments:
1921 -h, --help show this help message and exit
1922 ++foo foo help
1923 '''))
1924
1925
1926 def test_help_alternate_prefix_chars(self):
1927 parser = self._get_parser(prefix_chars='+:/')
1928 self.assertEqual(parser.format_usage(),
R David Murray00528e82012-07-21 22:48:35 -04001929 'usage: PROG [+h] [++foo] bar {1,2,3} ...\n')
R. David Murray88c49fe2010-08-03 17:56:09 +00001930 self.assertEqual(parser.format_help(), textwrap.dedent('''\
R David Murray00528e82012-07-21 22:48:35 -04001931 usage: PROG [+h] [++foo] bar {1,2,3} ...
R. David Murray88c49fe2010-08-03 17:56:09 +00001932
1933 main description
1934
1935 positional arguments:
1936 bar bar help
R David Murray00528e82012-07-21 22:48:35 -04001937 {1,2,3} command help
R. David Murray88c49fe2010-08-03 17:56:09 +00001938
1939 optional arguments:
1940 +h, ++help show this help message and exit
1941 ++foo foo help
1942 '''))
1943
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001944 def test_parser_command_help(self):
1945 self.assertEqual(self.command_help_parser.format_usage(),
R David Murray00528e82012-07-21 22:48:35 -04001946 'usage: PROG [-h] [--foo] bar {1,2,3} ...\n')
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001947 self.assertEqual(self.command_help_parser.format_help(),
1948 textwrap.dedent('''\
R David Murray00528e82012-07-21 22:48:35 -04001949 usage: PROG [-h] [--foo] bar {1,2,3} ...
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001950
1951 main description
1952
1953 positional arguments:
1954 bar bar help
R David Murray00528e82012-07-21 22:48:35 -04001955 {1,2,3} command help
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001956 1 1 help
1957 2 2 help
R David Murray00528e82012-07-21 22:48:35 -04001958 3 3 help
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001959
1960 optional arguments:
1961 -h, --help show this help message and exit
1962 --foo foo help
1963 '''))
1964
1965 def test_subparser_title_help(self):
1966 parser = ErrorRaisingArgumentParser(prog='PROG',
1967 description='main description')
1968 parser.add_argument('--foo', action='store_true', help='foo help')
1969 parser.add_argument('bar', help='bar help')
1970 subparsers = parser.add_subparsers(title='subcommands',
1971 description='command help',
1972 help='additional text')
1973 parser1 = subparsers.add_parser('1')
1974 parser2 = subparsers.add_parser('2')
1975 self.assertEqual(parser.format_usage(),
1976 'usage: PROG [-h] [--foo] bar {1,2} ...\n')
1977 self.assertEqual(parser.format_help(), textwrap.dedent('''\
1978 usage: PROG [-h] [--foo] bar {1,2} ...
1979
1980 main description
1981
1982 positional arguments:
1983 bar bar help
1984
1985 optional arguments:
1986 -h, --help show this help message and exit
1987 --foo foo help
1988
1989 subcommands:
1990 command help
1991
1992 {1,2} additional text
1993 '''))
1994
1995 def _test_subparser_help(self, args_str, expected_help):
1996 try:
1997 self.parser.parse_args(args_str.split())
1998 except ArgumentParserError:
1999 err = sys.exc_info()[1]
2000 if err.stdout != expected_help:
2001 print(repr(expected_help))
2002 print(repr(err.stdout))
2003 self.assertEqual(err.stdout, expected_help)
2004
2005 def test_subparser1_help(self):
2006 self._test_subparser_help('5.0 1 -h', textwrap.dedent('''\
2007 usage: PROG bar 1 [-h] [-w W] {a,b,c}
2008
2009 1 description
2010
2011 positional arguments:
2012 {a,b,c} x help
2013
2014 optional arguments:
2015 -h, --help show this help message and exit
2016 -w W w help
2017 '''))
2018
2019 def test_subparser2_help(self):
2020 self._test_subparser_help('5.0 2 -h', textwrap.dedent('''\
2021 usage: PROG bar 2 [-h] [-y {1,2,3}] [z [z ...]]
2022
2023 2 description
2024
2025 positional arguments:
2026 z z help
2027
2028 optional arguments:
2029 -h, --help show this help message and exit
2030 -y {1,2,3} y help
2031 '''))
2032
Steven Bethardfd311a72010-12-18 11:19:23 +00002033 def test_alias_invocation(self):
2034 parser = self._get_parser(aliases=True)
2035 self.assertEqual(
2036 parser.parse_known_args('0.5 1alias1 b'.split()),
2037 (NS(foo=False, bar=0.5, w=None, x='b'), []),
2038 )
2039 self.assertEqual(
2040 parser.parse_known_args('0.5 1alias2 b'.split()),
2041 (NS(foo=False, bar=0.5, w=None, x='b'), []),
2042 )
2043
2044 def test_error_alias_invocation(self):
2045 parser = self._get_parser(aliases=True)
2046 self.assertArgumentParserError(parser.parse_args,
2047 '0.5 1alias3 b'.split())
2048
2049 def test_alias_help(self):
2050 parser = self._get_parser(aliases=True, subparser_help=True)
2051 self.maxDiff = None
2052 self.assertEqual(parser.format_help(), textwrap.dedent("""\
2053 usage: PROG [-h] [--foo] bar COMMAND ...
2054
2055 main description
2056
2057 positional arguments:
2058 bar bar help
2059
2060 optional arguments:
2061 -h, --help show this help message and exit
2062 --foo foo help
2063
2064 commands:
2065 COMMAND
2066 1 (1alias1, 1alias2)
2067 1 help
2068 2 2 help
R David Murray00528e82012-07-21 22:48:35 -04002069 3 3 help
Steven Bethardfd311a72010-12-18 11:19:23 +00002070 """))
2071
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002072# ============
2073# Groups tests
2074# ============
2075
2076class TestPositionalsGroups(TestCase):
2077 """Tests that order of group positionals matches construction order"""
2078
2079 def test_nongroup_first(self):
2080 parser = ErrorRaisingArgumentParser()
2081 parser.add_argument('foo')
2082 group = parser.add_argument_group('g')
2083 group.add_argument('bar')
2084 parser.add_argument('baz')
2085 expected = NS(foo='1', bar='2', baz='3')
2086 result = parser.parse_args('1 2 3'.split())
2087 self.assertEqual(expected, result)
2088
2089 def test_group_first(self):
2090 parser = ErrorRaisingArgumentParser()
2091 group = parser.add_argument_group('xxx')
2092 group.add_argument('foo')
2093 parser.add_argument('bar')
2094 parser.add_argument('baz')
2095 expected = NS(foo='1', bar='2', baz='3')
2096 result = parser.parse_args('1 2 3'.split())
2097 self.assertEqual(expected, result)
2098
2099 def test_interleaved_groups(self):
2100 parser = ErrorRaisingArgumentParser()
2101 group = parser.add_argument_group('xxx')
2102 parser.add_argument('foo')
2103 group.add_argument('bar')
2104 parser.add_argument('baz')
2105 group = parser.add_argument_group('yyy')
2106 group.add_argument('frell')
2107 expected = NS(foo='1', bar='2', baz='3', frell='4')
2108 result = parser.parse_args('1 2 3 4'.split())
2109 self.assertEqual(expected, result)
2110
2111# ===================
2112# Parent parser tests
2113# ===================
2114
2115class TestParentParsers(TestCase):
2116 """Tests that parsers can be created with parent parsers"""
2117
2118 def assertArgumentParserError(self, *args, **kwargs):
2119 self.assertRaises(ArgumentParserError, *args, **kwargs)
2120
2121 def setUp(self):
Steven Bethard1f1c2472010-11-01 13:56:09 +00002122 super().setUp()
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002123 self.wxyz_parent = ErrorRaisingArgumentParser(add_help=False)
2124 self.wxyz_parent.add_argument('--w')
2125 x_group = self.wxyz_parent.add_argument_group('x')
2126 x_group.add_argument('-y')
2127 self.wxyz_parent.add_argument('z')
2128
2129 self.abcd_parent = ErrorRaisingArgumentParser(add_help=False)
2130 self.abcd_parent.add_argument('a')
2131 self.abcd_parent.add_argument('-b')
2132 c_group = self.abcd_parent.add_argument_group('c')
2133 c_group.add_argument('--d')
2134
2135 self.w_parent = ErrorRaisingArgumentParser(add_help=False)
2136 self.w_parent.add_argument('--w')
2137
2138 self.z_parent = ErrorRaisingArgumentParser(add_help=False)
2139 self.z_parent.add_argument('z')
2140
2141 # parents with mutually exclusive groups
2142 self.ab_mutex_parent = ErrorRaisingArgumentParser(add_help=False)
2143 group = self.ab_mutex_parent.add_mutually_exclusive_group()
2144 group.add_argument('-a', action='store_true')
2145 group.add_argument('-b', action='store_true')
2146
2147 self.main_program = os.path.basename(sys.argv[0])
2148
2149 def test_single_parent(self):
2150 parser = ErrorRaisingArgumentParser(parents=[self.wxyz_parent])
2151 self.assertEqual(parser.parse_args('-y 1 2 --w 3'.split()),
2152 NS(w='3', y='1', z='2'))
2153
2154 def test_single_parent_mutex(self):
2155 self._test_mutex_ab(self.ab_mutex_parent.parse_args)
2156 parser = ErrorRaisingArgumentParser(parents=[self.ab_mutex_parent])
2157 self._test_mutex_ab(parser.parse_args)
2158
2159 def test_single_granparent_mutex(self):
2160 parents = [self.ab_mutex_parent]
2161 parser = ErrorRaisingArgumentParser(add_help=False, parents=parents)
2162 parser = ErrorRaisingArgumentParser(parents=[parser])
2163 self._test_mutex_ab(parser.parse_args)
2164
2165 def _test_mutex_ab(self, parse_args):
2166 self.assertEqual(parse_args([]), NS(a=False, b=False))
2167 self.assertEqual(parse_args(['-a']), NS(a=True, b=False))
2168 self.assertEqual(parse_args(['-b']), NS(a=False, b=True))
2169 self.assertArgumentParserError(parse_args, ['-a', '-b'])
2170 self.assertArgumentParserError(parse_args, ['-b', '-a'])
2171 self.assertArgumentParserError(parse_args, ['-c'])
2172 self.assertArgumentParserError(parse_args, ['-a', '-c'])
2173 self.assertArgumentParserError(parse_args, ['-b', '-c'])
2174
2175 def test_multiple_parents(self):
2176 parents = [self.abcd_parent, self.wxyz_parent]
2177 parser = ErrorRaisingArgumentParser(parents=parents)
2178 self.assertEqual(parser.parse_args('--d 1 --w 2 3 4'.split()),
2179 NS(a='3', b=None, d='1', w='2', y=None, z='4'))
2180
2181 def test_multiple_parents_mutex(self):
2182 parents = [self.ab_mutex_parent, self.wxyz_parent]
2183 parser = ErrorRaisingArgumentParser(parents=parents)
2184 self.assertEqual(parser.parse_args('-a --w 2 3'.split()),
2185 NS(a=True, b=False, w='2', y=None, z='3'))
2186 self.assertArgumentParserError(
2187 parser.parse_args, '-a --w 2 3 -b'.split())
2188 self.assertArgumentParserError(
2189 parser.parse_args, '-a -b --w 2 3'.split())
2190
2191 def test_conflicting_parents(self):
2192 self.assertRaises(
2193 argparse.ArgumentError,
2194 argparse.ArgumentParser,
2195 parents=[self.w_parent, self.wxyz_parent])
2196
2197 def test_conflicting_parents_mutex(self):
2198 self.assertRaises(
2199 argparse.ArgumentError,
2200 argparse.ArgumentParser,
2201 parents=[self.abcd_parent, self.ab_mutex_parent])
2202
2203 def test_same_argument_name_parents(self):
2204 parents = [self.wxyz_parent, self.z_parent]
2205 parser = ErrorRaisingArgumentParser(parents=parents)
2206 self.assertEqual(parser.parse_args('1 2'.split()),
2207 NS(w=None, y=None, z='2'))
2208
2209 def test_subparser_parents(self):
2210 parser = ErrorRaisingArgumentParser()
2211 subparsers = parser.add_subparsers()
2212 abcde_parser = subparsers.add_parser('bar', parents=[self.abcd_parent])
2213 abcde_parser.add_argument('e')
2214 self.assertEqual(parser.parse_args('bar -b 1 --d 2 3 4'.split()),
2215 NS(a='3', b='1', d='2', e='4'))
2216
2217 def test_subparser_parents_mutex(self):
2218 parser = ErrorRaisingArgumentParser()
2219 subparsers = parser.add_subparsers()
2220 parents = [self.ab_mutex_parent]
2221 abc_parser = subparsers.add_parser('foo', parents=parents)
2222 c_group = abc_parser.add_argument_group('c_group')
2223 c_group.add_argument('c')
2224 parents = [self.wxyz_parent, self.ab_mutex_parent]
2225 wxyzabe_parser = subparsers.add_parser('bar', parents=parents)
2226 wxyzabe_parser.add_argument('e')
2227 self.assertEqual(parser.parse_args('foo -a 4'.split()),
2228 NS(a=True, b=False, c='4'))
2229 self.assertEqual(parser.parse_args('bar -b --w 2 3 4'.split()),
2230 NS(a=False, b=True, w='2', y=None, z='3', e='4'))
2231 self.assertArgumentParserError(
2232 parser.parse_args, 'foo -a -b 4'.split())
2233 self.assertArgumentParserError(
2234 parser.parse_args, 'bar -b -a 4'.split())
2235
2236 def test_parent_help(self):
2237 parents = [self.abcd_parent, self.wxyz_parent]
2238 parser = ErrorRaisingArgumentParser(parents=parents)
2239 parser_help = parser.format_help()
Terry Jan Reedyee91e092012-01-09 18:20:09 -05002240 progname = self.main_program
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002241 self.assertEqual(parser_help, textwrap.dedent('''\
Terry Jan Reedyee91e092012-01-09 18:20:09 -05002242 usage: {}{}[-h] [-b B] [--d D] [--w W] [-y Y] a z
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002243
2244 positional arguments:
2245 a
2246 z
2247
2248 optional arguments:
2249 -h, --help show this help message and exit
2250 -b B
2251 --w W
2252
2253 c:
2254 --d D
2255
2256 x:
2257 -y Y
Terry Jan Reedyee91e092012-01-09 18:20:09 -05002258 '''.format(progname, ' ' if progname else '' )))
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002259
2260 def test_groups_parents(self):
2261 parent = ErrorRaisingArgumentParser(add_help=False)
2262 g = parent.add_argument_group(title='g', description='gd')
2263 g.add_argument('-w')
2264 g.add_argument('-x')
2265 m = parent.add_mutually_exclusive_group()
2266 m.add_argument('-y')
2267 m.add_argument('-z')
2268 parser = ErrorRaisingArgumentParser(parents=[parent])
2269
2270 self.assertRaises(ArgumentParserError, parser.parse_args,
2271 ['-y', 'Y', '-z', 'Z'])
2272
2273 parser_help = parser.format_help()
Terry Jan Reedyee91e092012-01-09 18:20:09 -05002274 progname = self.main_program
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002275 self.assertEqual(parser_help, textwrap.dedent('''\
Terry Jan Reedyee91e092012-01-09 18:20:09 -05002276 usage: {}{}[-h] [-w W] [-x X] [-y Y | -z Z]
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002277
2278 optional arguments:
2279 -h, --help show this help message and exit
2280 -y Y
2281 -z Z
2282
2283 g:
2284 gd
2285
2286 -w W
2287 -x X
Terry Jan Reedyee91e092012-01-09 18:20:09 -05002288 '''.format(progname, ' ' if progname else '' )))
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002289
2290# ==============================
2291# Mutually exclusive group tests
2292# ==============================
2293
2294class TestMutuallyExclusiveGroupErrors(TestCase):
2295
2296 def test_invalid_add_argument_group(self):
2297 parser = ErrorRaisingArgumentParser()
2298 raises = self.assertRaises
2299 raises(TypeError, parser.add_mutually_exclusive_group, title='foo')
2300
2301 def test_invalid_add_argument(self):
2302 parser = ErrorRaisingArgumentParser()
2303 group = parser.add_mutually_exclusive_group()
2304 add_argument = group.add_argument
2305 raises = self.assertRaises
2306 raises(ValueError, add_argument, '--foo', required=True)
2307 raises(ValueError, add_argument, 'bar')
2308 raises(ValueError, add_argument, 'bar', nargs='+')
2309 raises(ValueError, add_argument, 'bar', nargs=1)
2310 raises(ValueError, add_argument, 'bar', nargs=argparse.PARSER)
2311
Steven Bethard49998ee2010-11-01 16:29:26 +00002312 def test_help(self):
2313 parser = ErrorRaisingArgumentParser(prog='PROG')
2314 group1 = parser.add_mutually_exclusive_group()
2315 group1.add_argument('--foo', action='store_true')
2316 group1.add_argument('--bar', action='store_false')
2317 group2 = parser.add_mutually_exclusive_group()
2318 group2.add_argument('--soup', action='store_true')
2319 group2.add_argument('--nuts', action='store_false')
2320 expected = '''\
2321 usage: PROG [-h] [--foo | --bar] [--soup | --nuts]
2322
2323 optional arguments:
2324 -h, --help show this help message and exit
2325 --foo
2326 --bar
2327 --soup
2328 --nuts
2329 '''
2330 self.assertEqual(parser.format_help(), textwrap.dedent(expected))
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002331
2332class MEMixin(object):
2333
2334 def test_failures_when_not_required(self):
2335 parse_args = self.get_parser(required=False).parse_args
2336 error = ArgumentParserError
2337 for args_string in self.failures:
2338 self.assertRaises(error, parse_args, args_string.split())
2339
2340 def test_failures_when_required(self):
2341 parse_args = self.get_parser(required=True).parse_args
2342 error = ArgumentParserError
2343 for args_string in self.failures + ['']:
2344 self.assertRaises(error, parse_args, args_string.split())
2345
2346 def test_successes_when_not_required(self):
2347 parse_args = self.get_parser(required=False).parse_args
2348 successes = self.successes + self.successes_when_not_required
2349 for args_string, expected_ns in successes:
2350 actual_ns = parse_args(args_string.split())
2351 self.assertEqual(actual_ns, expected_ns)
2352
2353 def test_successes_when_required(self):
2354 parse_args = self.get_parser(required=True).parse_args
2355 for args_string, expected_ns in self.successes:
2356 actual_ns = parse_args(args_string.split())
2357 self.assertEqual(actual_ns, expected_ns)
2358
2359 def test_usage_when_not_required(self):
2360 format_usage = self.get_parser(required=False).format_usage
2361 expected_usage = self.usage_when_not_required
2362 self.assertEqual(format_usage(), textwrap.dedent(expected_usage))
2363
2364 def test_usage_when_required(self):
2365 format_usage = self.get_parser(required=True).format_usage
2366 expected_usage = self.usage_when_required
2367 self.assertEqual(format_usage(), textwrap.dedent(expected_usage))
2368
2369 def test_help_when_not_required(self):
2370 format_help = self.get_parser(required=False).format_help
2371 help = self.usage_when_not_required + self.help
2372 self.assertEqual(format_help(), textwrap.dedent(help))
2373
2374 def test_help_when_required(self):
2375 format_help = self.get_parser(required=True).format_help
2376 help = self.usage_when_required + self.help
2377 self.assertEqual(format_help(), textwrap.dedent(help))
2378
2379
2380class TestMutuallyExclusiveSimple(MEMixin, TestCase):
2381
2382 def get_parser(self, required=None):
2383 parser = ErrorRaisingArgumentParser(prog='PROG')
2384 group = parser.add_mutually_exclusive_group(required=required)
2385 group.add_argument('--bar', help='bar help')
2386 group.add_argument('--baz', nargs='?', const='Z', help='baz help')
2387 return parser
2388
2389 failures = ['--bar X --baz Y', '--bar X --baz']
2390 successes = [
2391 ('--bar X', NS(bar='X', baz=None)),
2392 ('--bar X --bar Z', NS(bar='Z', baz=None)),
2393 ('--baz Y', NS(bar=None, baz='Y')),
2394 ('--baz', NS(bar=None, baz='Z')),
2395 ]
2396 successes_when_not_required = [
2397 ('', NS(bar=None, baz=None)),
2398 ]
2399
2400 usage_when_not_required = '''\
2401 usage: PROG [-h] [--bar BAR | --baz [BAZ]]
2402 '''
2403 usage_when_required = '''\
2404 usage: PROG [-h] (--bar BAR | --baz [BAZ])
2405 '''
2406 help = '''\
2407
2408 optional arguments:
2409 -h, --help show this help message and exit
2410 --bar BAR bar help
2411 --baz [BAZ] baz help
2412 '''
2413
2414
2415class TestMutuallyExclusiveLong(MEMixin, TestCase):
2416
2417 def get_parser(self, required=None):
2418 parser = ErrorRaisingArgumentParser(prog='PROG')
2419 parser.add_argument('--abcde', help='abcde help')
2420 parser.add_argument('--fghij', help='fghij help')
2421 group = parser.add_mutually_exclusive_group(required=required)
2422 group.add_argument('--klmno', help='klmno help')
2423 group.add_argument('--pqrst', help='pqrst help')
2424 return parser
2425
2426 failures = ['--klmno X --pqrst Y']
2427 successes = [
2428 ('--klmno X', NS(abcde=None, fghij=None, klmno='X', pqrst=None)),
2429 ('--abcde Y --klmno X',
2430 NS(abcde='Y', fghij=None, klmno='X', pqrst=None)),
2431 ('--pqrst X', NS(abcde=None, fghij=None, klmno=None, pqrst='X')),
2432 ('--pqrst X --fghij Y',
2433 NS(abcde=None, fghij='Y', klmno=None, pqrst='X')),
2434 ]
2435 successes_when_not_required = [
2436 ('', NS(abcde=None, fghij=None, klmno=None, pqrst=None)),
2437 ]
2438
2439 usage_when_not_required = '''\
2440 usage: PROG [-h] [--abcde ABCDE] [--fghij FGHIJ]
2441 [--klmno KLMNO | --pqrst PQRST]
2442 '''
2443 usage_when_required = '''\
2444 usage: PROG [-h] [--abcde ABCDE] [--fghij FGHIJ]
2445 (--klmno KLMNO | --pqrst PQRST)
2446 '''
2447 help = '''\
2448
2449 optional arguments:
2450 -h, --help show this help message and exit
2451 --abcde ABCDE abcde help
2452 --fghij FGHIJ fghij help
2453 --klmno KLMNO klmno help
2454 --pqrst PQRST pqrst help
2455 '''
2456
2457
2458class TestMutuallyExclusiveFirstSuppressed(MEMixin, TestCase):
2459
2460 def get_parser(self, required):
2461 parser = ErrorRaisingArgumentParser(prog='PROG')
2462 group = parser.add_mutually_exclusive_group(required=required)
2463 group.add_argument('-x', help=argparse.SUPPRESS)
2464 group.add_argument('-y', action='store_false', help='y help')
2465 return parser
2466
2467 failures = ['-x X -y']
2468 successes = [
2469 ('-x X', NS(x='X', y=True)),
2470 ('-x X -x Y', NS(x='Y', y=True)),
2471 ('-y', NS(x=None, y=False)),
2472 ]
2473 successes_when_not_required = [
2474 ('', NS(x=None, y=True)),
2475 ]
2476
2477 usage_when_not_required = '''\
2478 usage: PROG [-h] [-y]
2479 '''
2480 usage_when_required = '''\
2481 usage: PROG [-h] -y
2482 '''
2483 help = '''\
2484
2485 optional arguments:
2486 -h, --help show this help message and exit
2487 -y y help
2488 '''
2489
2490
2491class TestMutuallyExclusiveManySuppressed(MEMixin, TestCase):
2492
2493 def get_parser(self, required):
2494 parser = ErrorRaisingArgumentParser(prog='PROG')
2495 group = parser.add_mutually_exclusive_group(required=required)
2496 add = group.add_argument
2497 add('--spam', action='store_true', help=argparse.SUPPRESS)
2498 add('--badger', action='store_false', help=argparse.SUPPRESS)
2499 add('--bladder', help=argparse.SUPPRESS)
2500 return parser
2501
2502 failures = [
2503 '--spam --badger',
2504 '--badger --bladder B',
2505 '--bladder B --spam',
2506 ]
2507 successes = [
2508 ('--spam', NS(spam=True, badger=True, bladder=None)),
2509 ('--badger', NS(spam=False, badger=False, bladder=None)),
2510 ('--bladder B', NS(spam=False, badger=True, bladder='B')),
2511 ('--spam --spam', NS(spam=True, badger=True, bladder=None)),
2512 ]
2513 successes_when_not_required = [
2514 ('', NS(spam=False, badger=True, bladder=None)),
2515 ]
2516
2517 usage_when_required = usage_when_not_required = '''\
2518 usage: PROG [-h]
2519 '''
2520 help = '''\
2521
2522 optional arguments:
2523 -h, --help show this help message and exit
2524 '''
2525
2526
2527class TestMutuallyExclusiveOptionalAndPositional(MEMixin, TestCase):
2528
2529 def get_parser(self, required):
2530 parser = ErrorRaisingArgumentParser(prog='PROG')
2531 group = parser.add_mutually_exclusive_group(required=required)
2532 group.add_argument('--foo', action='store_true', help='FOO')
2533 group.add_argument('--spam', help='SPAM')
2534 group.add_argument('badger', nargs='*', default='X', help='BADGER')
2535 return parser
2536
2537 failures = [
2538 '--foo --spam S',
2539 '--spam S X',
2540 'X --foo',
2541 'X Y Z --spam S',
2542 '--foo X Y',
2543 ]
2544 successes = [
2545 ('--foo', NS(foo=True, spam=None, badger='X')),
2546 ('--spam S', NS(foo=False, spam='S', badger='X')),
2547 ('X', NS(foo=False, spam=None, badger=['X'])),
2548 ('X Y Z', NS(foo=False, spam=None, badger=['X', 'Y', 'Z'])),
2549 ]
2550 successes_when_not_required = [
2551 ('', NS(foo=False, spam=None, badger='X')),
2552 ]
2553
2554 usage_when_not_required = '''\
2555 usage: PROG [-h] [--foo | --spam SPAM | badger [badger ...]]
2556 '''
2557 usage_when_required = '''\
2558 usage: PROG [-h] (--foo | --spam SPAM | badger [badger ...])
2559 '''
2560 help = '''\
2561
2562 positional arguments:
2563 badger BADGER
2564
2565 optional arguments:
2566 -h, --help show this help message and exit
2567 --foo FOO
2568 --spam SPAM SPAM
2569 '''
2570
2571
2572class TestMutuallyExclusiveOptionalsMixed(MEMixin, TestCase):
2573
2574 def get_parser(self, required):
2575 parser = ErrorRaisingArgumentParser(prog='PROG')
2576 parser.add_argument('-x', action='store_true', help='x help')
2577 group = parser.add_mutually_exclusive_group(required=required)
2578 group.add_argument('-a', action='store_true', help='a help')
2579 group.add_argument('-b', action='store_true', help='b help')
2580 parser.add_argument('-y', action='store_true', help='y help')
2581 group.add_argument('-c', action='store_true', help='c help')
2582 return parser
2583
2584 failures = ['-a -b', '-b -c', '-a -c', '-a -b -c']
2585 successes = [
2586 ('-a', NS(a=True, b=False, c=False, x=False, y=False)),
2587 ('-b', NS(a=False, b=True, c=False, x=False, y=False)),
2588 ('-c', NS(a=False, b=False, c=True, x=False, y=False)),
2589 ('-a -x', NS(a=True, b=False, c=False, x=True, y=False)),
2590 ('-y -b', NS(a=False, b=True, c=False, x=False, y=True)),
2591 ('-x -y -c', NS(a=False, b=False, c=True, x=True, y=True)),
2592 ]
2593 successes_when_not_required = [
2594 ('', NS(a=False, b=False, c=False, x=False, y=False)),
2595 ('-x', NS(a=False, b=False, c=False, x=True, y=False)),
2596 ('-y', NS(a=False, b=False, c=False, x=False, y=True)),
2597 ]
2598
2599 usage_when_required = usage_when_not_required = '''\
2600 usage: PROG [-h] [-x] [-a] [-b] [-y] [-c]
2601 '''
2602 help = '''\
2603
2604 optional arguments:
2605 -h, --help show this help message and exit
2606 -x x help
2607 -a a help
2608 -b b help
2609 -y y help
2610 -c c help
2611 '''
2612
2613
Georg Brandl0f6b47a2011-01-30 12:19:35 +00002614class TestMutuallyExclusiveInGroup(MEMixin, TestCase):
2615
2616 def get_parser(self, required=None):
2617 parser = ErrorRaisingArgumentParser(prog='PROG')
2618 titled_group = parser.add_argument_group(
2619 title='Titled group', description='Group description')
2620 mutex_group = \
2621 titled_group.add_mutually_exclusive_group(required=required)
2622 mutex_group.add_argument('--bar', help='bar help')
2623 mutex_group.add_argument('--baz', help='baz help')
2624 return parser
2625
2626 failures = ['--bar X --baz Y', '--baz X --bar Y']
2627 successes = [
2628 ('--bar X', NS(bar='X', baz=None)),
2629 ('--baz Y', NS(bar=None, baz='Y')),
2630 ]
2631 successes_when_not_required = [
2632 ('', NS(bar=None, baz=None)),
2633 ]
2634
2635 usage_when_not_required = '''\
2636 usage: PROG [-h] [--bar BAR | --baz BAZ]
2637 '''
2638 usage_when_required = '''\
2639 usage: PROG [-h] (--bar BAR | --baz BAZ)
2640 '''
2641 help = '''\
2642
2643 optional arguments:
2644 -h, --help show this help message and exit
2645
2646 Titled group:
2647 Group description
2648
2649 --bar BAR bar help
2650 --baz BAZ baz help
2651 '''
2652
2653
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002654class TestMutuallyExclusiveOptionalsAndPositionalsMixed(MEMixin, TestCase):
2655
2656 def get_parser(self, required):
2657 parser = ErrorRaisingArgumentParser(prog='PROG')
2658 parser.add_argument('x', help='x help')
2659 parser.add_argument('-y', action='store_true', help='y help')
2660 group = parser.add_mutually_exclusive_group(required=required)
2661 group.add_argument('a', nargs='?', help='a help')
2662 group.add_argument('-b', action='store_true', help='b help')
2663 group.add_argument('-c', action='store_true', help='c help')
2664 return parser
2665
2666 failures = ['X A -b', '-b -c', '-c X A']
2667 successes = [
2668 ('X A', NS(a='A', b=False, c=False, x='X', y=False)),
2669 ('X -b', NS(a=None, b=True, c=False, x='X', y=False)),
2670 ('X -c', NS(a=None, b=False, c=True, x='X', y=False)),
2671 ('X A -y', NS(a='A', b=False, c=False, x='X', y=True)),
2672 ('X -y -b', NS(a=None, b=True, c=False, x='X', y=True)),
2673 ]
2674 successes_when_not_required = [
2675 ('X', NS(a=None, b=False, c=False, x='X', y=False)),
2676 ('X -y', NS(a=None, b=False, c=False, x='X', y=True)),
2677 ]
2678
2679 usage_when_required = usage_when_not_required = '''\
2680 usage: PROG [-h] [-y] [-b] [-c] x [a]
2681 '''
2682 help = '''\
2683
2684 positional arguments:
2685 x x help
2686 a a help
2687
2688 optional arguments:
2689 -h, --help show this help message and exit
2690 -y y help
2691 -b b help
2692 -c c help
2693 '''
2694
2695# =================================================
2696# Mutually exclusive group in parent parser tests
2697# =================================================
2698
2699class MEPBase(object):
2700
2701 def get_parser(self, required=None):
2702 parent = super(MEPBase, self).get_parser(required=required)
2703 parser = ErrorRaisingArgumentParser(
2704 prog=parent.prog, add_help=False, parents=[parent])
2705 return parser
2706
2707
2708class TestMutuallyExclusiveGroupErrorsParent(
2709 MEPBase, TestMutuallyExclusiveGroupErrors):
2710 pass
2711
2712
2713class TestMutuallyExclusiveSimpleParent(
2714 MEPBase, TestMutuallyExclusiveSimple):
2715 pass
2716
2717
2718class TestMutuallyExclusiveLongParent(
2719 MEPBase, TestMutuallyExclusiveLong):
2720 pass
2721
2722
2723class TestMutuallyExclusiveFirstSuppressedParent(
2724 MEPBase, TestMutuallyExclusiveFirstSuppressed):
2725 pass
2726
2727
2728class TestMutuallyExclusiveManySuppressedParent(
2729 MEPBase, TestMutuallyExclusiveManySuppressed):
2730 pass
2731
2732
2733class TestMutuallyExclusiveOptionalAndPositionalParent(
2734 MEPBase, TestMutuallyExclusiveOptionalAndPositional):
2735 pass
2736
2737
2738class TestMutuallyExclusiveOptionalsMixedParent(
2739 MEPBase, TestMutuallyExclusiveOptionalsMixed):
2740 pass
2741
2742
2743class TestMutuallyExclusiveOptionalsAndPositionalsMixedParent(
2744 MEPBase, TestMutuallyExclusiveOptionalsAndPositionalsMixed):
2745 pass
2746
2747# =================
2748# Set default tests
2749# =================
2750
2751class TestSetDefaults(TestCase):
2752
2753 def test_set_defaults_no_args(self):
2754 parser = ErrorRaisingArgumentParser()
2755 parser.set_defaults(x='foo')
2756 parser.set_defaults(y='bar', z=1)
2757 self.assertEqual(NS(x='foo', y='bar', z=1),
2758 parser.parse_args([]))
2759 self.assertEqual(NS(x='foo', y='bar', z=1),
2760 parser.parse_args([], NS()))
2761 self.assertEqual(NS(x='baz', y='bar', z=1),
2762 parser.parse_args([], NS(x='baz')))
2763 self.assertEqual(NS(x='baz', y='bar', z=2),
2764 parser.parse_args([], NS(x='baz', z=2)))
2765
2766 def test_set_defaults_with_args(self):
2767 parser = ErrorRaisingArgumentParser()
2768 parser.set_defaults(x='foo', y='bar')
2769 parser.add_argument('-x', default='xfoox')
2770 self.assertEqual(NS(x='xfoox', y='bar'),
2771 parser.parse_args([]))
2772 self.assertEqual(NS(x='xfoox', y='bar'),
2773 parser.parse_args([], NS()))
2774 self.assertEqual(NS(x='baz', y='bar'),
2775 parser.parse_args([], NS(x='baz')))
2776 self.assertEqual(NS(x='1', y='bar'),
2777 parser.parse_args('-x 1'.split()))
2778 self.assertEqual(NS(x='1', y='bar'),
2779 parser.parse_args('-x 1'.split(), NS()))
2780 self.assertEqual(NS(x='1', y='bar'),
2781 parser.parse_args('-x 1'.split(), NS(x='baz')))
2782
2783 def test_set_defaults_subparsers(self):
2784 parser = ErrorRaisingArgumentParser()
2785 parser.set_defaults(x='foo')
2786 subparsers = parser.add_subparsers()
2787 parser_a = subparsers.add_parser('a')
2788 parser_a.set_defaults(y='bar')
2789 self.assertEqual(NS(x='foo', y='bar'),
2790 parser.parse_args('a'.split()))
2791
2792 def test_set_defaults_parents(self):
2793 parent = ErrorRaisingArgumentParser(add_help=False)
2794 parent.set_defaults(x='foo')
2795 parser = ErrorRaisingArgumentParser(parents=[parent])
2796 self.assertEqual(NS(x='foo'), parser.parse_args([]))
2797
2798 def test_set_defaults_same_as_add_argument(self):
2799 parser = ErrorRaisingArgumentParser()
2800 parser.set_defaults(w='W', x='X', y='Y', z='Z')
2801 parser.add_argument('-w')
2802 parser.add_argument('-x', default='XX')
2803 parser.add_argument('y', nargs='?')
2804 parser.add_argument('z', nargs='?', default='ZZ')
2805
2806 # defaults set previously
2807 self.assertEqual(NS(w='W', x='XX', y='Y', z='ZZ'),
2808 parser.parse_args([]))
2809
2810 # reset defaults
2811 parser.set_defaults(w='WW', x='X', y='YY', z='Z')
2812 self.assertEqual(NS(w='WW', x='X', y='YY', z='Z'),
2813 parser.parse_args([]))
2814
2815 def test_set_defaults_same_as_add_argument_group(self):
2816 parser = ErrorRaisingArgumentParser()
2817 parser.set_defaults(w='W', x='X', y='Y', z='Z')
2818 group = parser.add_argument_group('foo')
2819 group.add_argument('-w')
2820 group.add_argument('-x', default='XX')
2821 group.add_argument('y', nargs='?')
2822 group.add_argument('z', nargs='?', default='ZZ')
2823
2824
2825 # defaults set previously
2826 self.assertEqual(NS(w='W', x='XX', y='Y', z='ZZ'),
2827 parser.parse_args([]))
2828
2829 # reset defaults
2830 parser.set_defaults(w='WW', x='X', y='YY', z='Z')
2831 self.assertEqual(NS(w='WW', x='X', y='YY', z='Z'),
2832 parser.parse_args([]))
2833
2834# =================
2835# Get default tests
2836# =================
2837
2838class TestGetDefault(TestCase):
2839
2840 def test_get_default(self):
2841 parser = ErrorRaisingArgumentParser()
2842 self.assertEqual(None, parser.get_default("foo"))
2843 self.assertEqual(None, parser.get_default("bar"))
2844
2845 parser.add_argument("--foo")
2846 self.assertEqual(None, parser.get_default("foo"))
2847 self.assertEqual(None, parser.get_default("bar"))
2848
2849 parser.add_argument("--bar", type=int, default=42)
2850 self.assertEqual(None, parser.get_default("foo"))
2851 self.assertEqual(42, parser.get_default("bar"))
2852
2853 parser.set_defaults(foo="badger")
2854 self.assertEqual("badger", parser.get_default("foo"))
2855 self.assertEqual(42, parser.get_default("bar"))
2856
2857# ==========================
2858# Namespace 'contains' tests
2859# ==========================
2860
2861class TestNamespaceContainsSimple(TestCase):
2862
2863 def test_empty(self):
2864 ns = argparse.Namespace()
Ezio Melottib3aedd42010-11-20 19:04:17 +00002865 self.assertEqual('' in ns, False)
2866 self.assertEqual('' not in ns, True)
2867 self.assertEqual('x' in ns, False)
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002868
2869 def test_non_empty(self):
2870 ns = argparse.Namespace(x=1, y=2)
Ezio Melottib3aedd42010-11-20 19:04:17 +00002871 self.assertEqual('x' in ns, True)
2872 self.assertEqual('x' not in ns, False)
2873 self.assertEqual('y' in ns, True)
2874 self.assertEqual('' in ns, False)
2875 self.assertEqual('xx' in ns, False)
2876 self.assertEqual('z' in ns, False)
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002877
2878# =====================
2879# Help formatting tests
2880# =====================
2881
2882class TestHelpFormattingMetaclass(type):
2883
2884 def __init__(cls, name, bases, bodydict):
2885 if name == 'HelpTestCase':
2886 return
2887
2888 class AddTests(object):
2889
2890 def __init__(self, test_class, func_suffix, std_name):
2891 self.func_suffix = func_suffix
2892 self.std_name = std_name
2893
2894 for test_func in [self.test_format,
2895 self.test_print,
2896 self.test_print_file]:
2897 test_name = '%s_%s' % (test_func.__name__, func_suffix)
2898
2899 def test_wrapper(self, test_func=test_func):
2900 test_func(self)
2901 try:
2902 test_wrapper.__name__ = test_name
2903 except TypeError:
2904 pass
2905 setattr(test_class, test_name, test_wrapper)
2906
2907 def _get_parser(self, tester):
2908 parser = argparse.ArgumentParser(
2909 *tester.parser_signature.args,
2910 **tester.parser_signature.kwargs)
Steven Bethard8a6a1982011-03-27 13:53:53 +02002911 for argument_sig in getattr(tester, 'argument_signatures', []):
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002912 parser.add_argument(*argument_sig.args,
2913 **argument_sig.kwargs)
Steven Bethard8a6a1982011-03-27 13:53:53 +02002914 group_sigs = getattr(tester, 'argument_group_signatures', [])
2915 for group_sig, argument_sigs in group_sigs:
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002916 group = parser.add_argument_group(*group_sig.args,
2917 **group_sig.kwargs)
2918 for argument_sig in argument_sigs:
2919 group.add_argument(*argument_sig.args,
2920 **argument_sig.kwargs)
Steven Bethard8a6a1982011-03-27 13:53:53 +02002921 subparsers_sigs = getattr(tester, 'subparsers_signatures', [])
2922 if subparsers_sigs:
2923 subparsers = parser.add_subparsers()
2924 for subparser_sig in subparsers_sigs:
2925 subparsers.add_parser(*subparser_sig.args,
2926 **subparser_sig.kwargs)
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002927 return parser
2928
2929 def _test(self, tester, parser_text):
2930 expected_text = getattr(tester, self.func_suffix)
2931 expected_text = textwrap.dedent(expected_text)
2932 if expected_text != parser_text:
2933 print(repr(expected_text))
2934 print(repr(parser_text))
2935 for char1, char2 in zip(expected_text, parser_text):
2936 if char1 != char2:
2937 print('first diff: %r %r' % (char1, char2))
2938 break
2939 tester.assertEqual(expected_text, parser_text)
2940
2941 def test_format(self, tester):
2942 parser = self._get_parser(tester)
2943 format = getattr(parser, 'format_%s' % self.func_suffix)
2944 self._test(tester, format())
2945
2946 def test_print(self, tester):
2947 parser = self._get_parser(tester)
2948 print_ = getattr(parser, 'print_%s' % self.func_suffix)
2949 old_stream = getattr(sys, self.std_name)
Benjamin Petersonb48af542010-04-11 20:43:16 +00002950 setattr(sys, self.std_name, StdIOBuffer())
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002951 try:
2952 print_()
2953 parser_text = getattr(sys, self.std_name).getvalue()
2954 finally:
2955 setattr(sys, self.std_name, old_stream)
2956 self._test(tester, parser_text)
2957
2958 def test_print_file(self, tester):
2959 parser = self._get_parser(tester)
2960 print_ = getattr(parser, 'print_%s' % self.func_suffix)
Benjamin Petersonb48af542010-04-11 20:43:16 +00002961 sfile = StdIOBuffer()
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002962 print_(sfile)
2963 parser_text = sfile.getvalue()
2964 self._test(tester, parser_text)
2965
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02002966 # add tests for {format,print}_{usage,help}
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002967 for func_suffix, std_name in [('usage', 'stdout'),
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02002968 ('help', 'stdout')]:
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002969 AddTests(cls, func_suffix, std_name)
2970
2971bases = TestCase,
2972HelpTestCase = TestHelpFormattingMetaclass('HelpTestCase', bases, {})
2973
2974
2975class TestHelpBiggerOptionals(HelpTestCase):
2976 """Make sure that argument help aligns when options are longer"""
2977
2978 parser_signature = Sig(prog='PROG', description='DESCRIPTION',
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02002979 epilog='EPILOG')
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002980 argument_signatures = [
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02002981 Sig('-v', '--version', action='version', version='0.1'),
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002982 Sig('-x', action='store_true', help='X HELP'),
2983 Sig('--y', help='Y HELP'),
2984 Sig('foo', help='FOO HELP'),
2985 Sig('bar', help='BAR HELP'),
2986 ]
2987 argument_group_signatures = []
2988 usage = '''\
2989 usage: PROG [-h] [-v] [-x] [--y Y] foo bar
2990 '''
2991 help = usage + '''\
2992
2993 DESCRIPTION
2994
2995 positional arguments:
2996 foo FOO HELP
2997 bar BAR HELP
2998
2999 optional arguments:
3000 -h, --help show this help message and exit
3001 -v, --version show program's version number and exit
3002 -x X HELP
3003 --y Y Y HELP
3004
3005 EPILOG
3006 '''
3007 version = '''\
3008 0.1
3009 '''
3010
Serhiy Storchakaf4511122014-01-09 23:14:27 +02003011class TestShortColumns(HelpTestCase):
3012 '''Test extremely small number of columns.
3013
3014 TestCase prevents "COLUMNS" from being too small in the tests themselves,
3015 but we don't want any exceptions thrown in such case. Only ugly representation.
3016 '''
3017 def setUp(self):
3018 env = support.EnvironmentVarGuard()
3019 env.set("COLUMNS", '15')
3020 self.addCleanup(env.__exit__)
3021
3022 parser_signature = TestHelpBiggerOptionals.parser_signature
3023 argument_signatures = TestHelpBiggerOptionals.argument_signatures
3024 argument_group_signatures = TestHelpBiggerOptionals.argument_group_signatures
3025 usage = '''\
3026 usage: PROG
3027 [-h]
3028 [-v]
3029 [-x]
3030 [--y Y]
3031 foo
3032 bar
3033 '''
3034 help = usage + '''\
3035
3036 DESCRIPTION
3037
3038 positional arguments:
3039 foo
3040 FOO HELP
3041 bar
3042 BAR HELP
3043
3044 optional arguments:
3045 -h, --help
3046 show this
3047 help
3048 message and
3049 exit
3050 -v, --version
3051 show
3052 program's
3053 version
3054 number and
3055 exit
3056 -x
3057 X HELP
3058 --y Y
3059 Y HELP
3060
3061 EPILOG
3062 '''
3063 version = TestHelpBiggerOptionals.version
3064
Benjamin Peterson698a18a2010-03-02 22:34:37 +00003065
3066class TestHelpBiggerOptionalGroups(HelpTestCase):
3067 """Make sure that argument help aligns when options are longer"""
3068
3069 parser_signature = Sig(prog='PROG', description='DESCRIPTION',
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02003070 epilog='EPILOG')
Benjamin Peterson698a18a2010-03-02 22:34:37 +00003071 argument_signatures = [
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02003072 Sig('-v', '--version', action='version', version='0.1'),
Benjamin Peterson698a18a2010-03-02 22:34:37 +00003073 Sig('-x', action='store_true', help='X HELP'),
3074 Sig('--y', help='Y HELP'),
3075 Sig('foo', help='FOO HELP'),
3076 Sig('bar', help='BAR HELP'),
3077 ]
3078 argument_group_signatures = [
3079 (Sig('GROUP TITLE', description='GROUP DESCRIPTION'), [
3080 Sig('baz', help='BAZ HELP'),
3081 Sig('-z', nargs='+', help='Z HELP')]),
3082 ]
3083 usage = '''\
3084 usage: PROG [-h] [-v] [-x] [--y Y] [-z Z [Z ...]] foo bar baz
3085 '''
3086 help = usage + '''\
3087
3088 DESCRIPTION
3089
3090 positional arguments:
3091 foo FOO HELP
3092 bar BAR HELP
3093
3094 optional arguments:
3095 -h, --help show this help message and exit
3096 -v, --version show program's version number and exit
3097 -x X HELP
3098 --y Y Y HELP
3099
3100 GROUP TITLE:
3101 GROUP DESCRIPTION
3102
3103 baz BAZ HELP
3104 -z Z [Z ...] Z HELP
3105
3106 EPILOG
3107 '''
3108 version = '''\
3109 0.1
3110 '''
3111
3112
3113class TestHelpBiggerPositionals(HelpTestCase):
3114 """Make sure that help aligns when arguments are longer"""
3115
3116 parser_signature = Sig(usage='USAGE', description='DESCRIPTION')
3117 argument_signatures = [
3118 Sig('-x', action='store_true', help='X HELP'),
3119 Sig('--y', help='Y HELP'),
3120 Sig('ekiekiekifekang', help='EKI HELP'),
3121 Sig('bar', help='BAR HELP'),
3122 ]
3123 argument_group_signatures = []
3124 usage = '''\
3125 usage: USAGE
3126 '''
3127 help = usage + '''\
3128
3129 DESCRIPTION
3130
3131 positional arguments:
3132 ekiekiekifekang EKI HELP
3133 bar BAR HELP
3134
3135 optional arguments:
3136 -h, --help show this help message and exit
3137 -x X HELP
3138 --y Y Y HELP
3139 '''
3140
3141 version = ''
3142
3143
3144class TestHelpReformatting(HelpTestCase):
3145 """Make sure that text after short names starts on the first line"""
3146
3147 parser_signature = Sig(
3148 prog='PROG',
3149 description=' oddly formatted\n'
3150 'description\n'
3151 '\n'
3152 'that is so long that it should go onto multiple '
3153 'lines when wrapped')
3154 argument_signatures = [
3155 Sig('-x', metavar='XX', help='oddly\n'
3156 ' formatted -x help'),
3157 Sig('y', metavar='yyy', help='normal y help'),
3158 ]
3159 argument_group_signatures = [
3160 (Sig('title', description='\n'
3161 ' oddly formatted group\n'
3162 '\n'
3163 'description'),
3164 [Sig('-a', action='store_true',
3165 help=' oddly \n'
3166 'formatted -a help \n'
3167 ' again, so long that it should be wrapped over '
3168 'multiple lines')]),
3169 ]
3170 usage = '''\
3171 usage: PROG [-h] [-x XX] [-a] yyy
3172 '''
3173 help = usage + '''\
3174
3175 oddly formatted description that is so long that it should go onto \
3176multiple
3177 lines when wrapped
3178
3179 positional arguments:
3180 yyy normal y help
3181
3182 optional arguments:
3183 -h, --help show this help message and exit
3184 -x XX oddly formatted -x help
3185
3186 title:
3187 oddly formatted group description
3188
3189 -a oddly formatted -a help again, so long that it should \
3190be wrapped
3191 over multiple lines
3192 '''
3193 version = ''
3194
3195
3196class TestHelpWrappingShortNames(HelpTestCase):
3197 """Make sure that text after short names starts on the first line"""
3198
3199 parser_signature = Sig(prog='PROG', description= 'D\nD' * 30)
3200 argument_signatures = [
3201 Sig('-x', metavar='XX', help='XHH HX' * 20),
3202 Sig('y', metavar='yyy', help='YH YH' * 20),
3203 ]
3204 argument_group_signatures = [
3205 (Sig('ALPHAS'), [
3206 Sig('-a', action='store_true', help='AHHH HHA' * 10)]),
3207 ]
3208 usage = '''\
3209 usage: PROG [-h] [-x XX] [-a] yyy
3210 '''
3211 help = usage + '''\
3212
3213 D DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD \
3214DD DD DD
3215 DD DD DD DD D
3216
3217 positional arguments:
3218 yyy YH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH \
3219YHYH YHYH
3220 YHYH YHYH YHYH YHYH YHYH YHYH YHYH YH
3221
3222 optional arguments:
3223 -h, --help show this help message and exit
3224 -x XX XHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH \
3225HXXHH HXXHH
3226 HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HX
3227
3228 ALPHAS:
3229 -a AHHH HHAAHHH HHAAHHH HHAAHHH HHAAHHH HHAAHHH HHAAHHH \
3230HHAAHHH
3231 HHAAHHH HHAAHHH HHA
3232 '''
3233 version = ''
3234
3235
3236class TestHelpWrappingLongNames(HelpTestCase):
3237 """Make sure that text after long names starts on the next line"""
3238
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02003239 parser_signature = Sig(usage='USAGE', description= 'D D' * 30)
Benjamin Peterson698a18a2010-03-02 22:34:37 +00003240 argument_signatures = [
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02003241 Sig('-v', '--version', action='version', version='V V' * 30),
Benjamin Peterson698a18a2010-03-02 22:34:37 +00003242 Sig('-x', metavar='X' * 25, help='XH XH' * 20),
3243 Sig('y', metavar='y' * 25, help='YH YH' * 20),
3244 ]
3245 argument_group_signatures = [
3246 (Sig('ALPHAS'), [
3247 Sig('-a', metavar='A' * 25, help='AH AH' * 20),
3248 Sig('z', metavar='z' * 25, help='ZH ZH' * 20)]),
3249 ]
3250 usage = '''\
3251 usage: USAGE
3252 '''
3253 help = usage + '''\
3254
3255 D DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD \
3256DD DD DD
3257 DD DD DD DD D
3258
3259 positional arguments:
3260 yyyyyyyyyyyyyyyyyyyyyyyyy
3261 YH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH \
3262YHYH YHYH
3263 YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YH
3264
3265 optional arguments:
3266 -h, --help show this help message and exit
3267 -v, --version show program's version number and exit
3268 -x XXXXXXXXXXXXXXXXXXXXXXXXX
3269 XH XHXH XHXH XHXH XHXH XHXH XHXH XHXH XHXH \
3270XHXH XHXH
3271 XHXH XHXH XHXH XHXH XHXH XHXH XHXH XHXH XHXH XH
3272
3273 ALPHAS:
3274 -a AAAAAAAAAAAAAAAAAAAAAAAAA
3275 AH AHAH AHAH AHAH AHAH AHAH AHAH AHAH AHAH \
3276AHAH AHAH
3277 AHAH AHAH AHAH AHAH AHAH AHAH AHAH AHAH AHAH AH
3278 zzzzzzzzzzzzzzzzzzzzzzzzz
3279 ZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH \
3280ZHZH ZHZH
3281 ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZH
3282 '''
3283 version = '''\
3284 V VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV \
3285VV VV VV
3286 VV VV VV VV V
3287 '''
3288
3289
3290class TestHelpUsage(HelpTestCase):
3291 """Test basic usage messages"""
3292
3293 parser_signature = Sig(prog='PROG')
3294 argument_signatures = [
3295 Sig('-w', nargs='+', help='w'),
3296 Sig('-x', nargs='*', help='x'),
3297 Sig('a', help='a'),
3298 Sig('b', help='b', nargs=2),
3299 Sig('c', help='c', nargs='?'),
3300 ]
3301 argument_group_signatures = [
3302 (Sig('group'), [
3303 Sig('-y', nargs='?', help='y'),
3304 Sig('-z', nargs=3, help='z'),
3305 Sig('d', help='d', nargs='*'),
3306 Sig('e', help='e', nargs='+'),
3307 ])
3308 ]
3309 usage = '''\
3310 usage: PROG [-h] [-w W [W ...]] [-x [X [X ...]]] [-y [Y]] [-z Z Z Z]
3311 a b b [c] [d [d ...]] e [e ...]
3312 '''
3313 help = usage + '''\
3314
3315 positional arguments:
3316 a a
3317 b b
3318 c c
3319
3320 optional arguments:
3321 -h, --help show this help message and exit
3322 -w W [W ...] w
3323 -x [X [X ...]] x
3324
3325 group:
3326 -y [Y] y
3327 -z Z Z Z z
3328 d d
3329 e e
3330 '''
3331 version = ''
3332
3333
3334class TestHelpOnlyUserGroups(HelpTestCase):
3335 """Test basic usage messages"""
3336
3337 parser_signature = Sig(prog='PROG', add_help=False)
3338 argument_signatures = []
3339 argument_group_signatures = [
3340 (Sig('xxxx'), [
3341 Sig('-x', help='x'),
3342 Sig('a', help='a'),
3343 ]),
3344 (Sig('yyyy'), [
3345 Sig('b', help='b'),
3346 Sig('-y', help='y'),
3347 ]),
3348 ]
3349 usage = '''\
3350 usage: PROG [-x X] [-y Y] a b
3351 '''
3352 help = usage + '''\
3353
3354 xxxx:
3355 -x X x
3356 a a
3357
3358 yyyy:
3359 b b
3360 -y Y y
3361 '''
3362 version = ''
3363
3364
3365class TestHelpUsageLongProg(HelpTestCase):
3366 """Test usage messages where the prog is long"""
3367
3368 parser_signature = Sig(prog='P' * 60)
3369 argument_signatures = [
3370 Sig('-w', metavar='W'),
3371 Sig('-x', metavar='X'),
3372 Sig('a'),
3373 Sig('b'),
3374 ]
3375 argument_group_signatures = []
3376 usage = '''\
3377 usage: PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
3378 [-h] [-w W] [-x X] a b
3379 '''
3380 help = usage + '''\
3381
3382 positional arguments:
3383 a
3384 b
3385
3386 optional arguments:
3387 -h, --help show this help message and exit
3388 -w W
3389 -x X
3390 '''
3391 version = ''
3392
3393
3394class TestHelpUsageLongProgOptionsWrap(HelpTestCase):
3395 """Test usage messages where the prog is long and the optionals wrap"""
3396
3397 parser_signature = Sig(prog='P' * 60)
3398 argument_signatures = [
3399 Sig('-w', metavar='W' * 25),
3400 Sig('-x', metavar='X' * 25),
3401 Sig('-y', metavar='Y' * 25),
3402 Sig('-z', metavar='Z' * 25),
3403 Sig('a'),
3404 Sig('b'),
3405 ]
3406 argument_group_signatures = []
3407 usage = '''\
3408 usage: PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
3409 [-h] [-w WWWWWWWWWWWWWWWWWWWWWWWWW] \
3410[-x XXXXXXXXXXXXXXXXXXXXXXXXX]
3411 [-y YYYYYYYYYYYYYYYYYYYYYYYYY] [-z ZZZZZZZZZZZZZZZZZZZZZZZZZ]
3412 a b
3413 '''
3414 help = usage + '''\
3415
3416 positional arguments:
3417 a
3418 b
3419
3420 optional arguments:
3421 -h, --help show this help message and exit
3422 -w WWWWWWWWWWWWWWWWWWWWWWWWW
3423 -x XXXXXXXXXXXXXXXXXXXXXXXXX
3424 -y YYYYYYYYYYYYYYYYYYYYYYYYY
3425 -z ZZZZZZZZZZZZZZZZZZZZZZZZZ
3426 '''
3427 version = ''
3428
3429
3430class TestHelpUsageLongProgPositionalsWrap(HelpTestCase):
3431 """Test usage messages where the prog is long and the positionals wrap"""
3432
3433 parser_signature = Sig(prog='P' * 60, add_help=False)
3434 argument_signatures = [
3435 Sig('a' * 25),
3436 Sig('b' * 25),
3437 Sig('c' * 25),
3438 ]
3439 argument_group_signatures = []
3440 usage = '''\
3441 usage: PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
3442 aaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbb
3443 ccccccccccccccccccccccccc
3444 '''
3445 help = usage + '''\
3446
3447 positional arguments:
3448 aaaaaaaaaaaaaaaaaaaaaaaaa
3449 bbbbbbbbbbbbbbbbbbbbbbbbb
3450 ccccccccccccccccccccccccc
3451 '''
3452 version = ''
3453
3454
3455class TestHelpUsageOptionalsWrap(HelpTestCase):
3456 """Test usage messages where the optionals wrap"""
3457
3458 parser_signature = Sig(prog='PROG')
3459 argument_signatures = [
3460 Sig('-w', metavar='W' * 25),
3461 Sig('-x', metavar='X' * 25),
3462 Sig('-y', metavar='Y' * 25),
3463 Sig('-z', metavar='Z' * 25),
3464 Sig('a'),
3465 Sig('b'),
3466 Sig('c'),
3467 ]
3468 argument_group_signatures = []
3469 usage = '''\
3470 usage: PROG [-h] [-w WWWWWWWWWWWWWWWWWWWWWWWWW] \
3471[-x XXXXXXXXXXXXXXXXXXXXXXXXX]
3472 [-y YYYYYYYYYYYYYYYYYYYYYYYYY] \
3473[-z ZZZZZZZZZZZZZZZZZZZZZZZZZ]
3474 a b c
3475 '''
3476 help = usage + '''\
3477
3478 positional arguments:
3479 a
3480 b
3481 c
3482
3483 optional arguments:
3484 -h, --help show this help message and exit
3485 -w WWWWWWWWWWWWWWWWWWWWWWWWW
3486 -x XXXXXXXXXXXXXXXXXXXXXXXXX
3487 -y YYYYYYYYYYYYYYYYYYYYYYYYY
3488 -z ZZZZZZZZZZZZZZZZZZZZZZZZZ
3489 '''
3490 version = ''
3491
3492
3493class TestHelpUsagePositionalsWrap(HelpTestCase):
3494 """Test usage messages where the positionals wrap"""
3495
3496 parser_signature = Sig(prog='PROG')
3497 argument_signatures = [
3498 Sig('-x'),
3499 Sig('-y'),
3500 Sig('-z'),
3501 Sig('a' * 25),
3502 Sig('b' * 25),
3503 Sig('c' * 25),
3504 ]
3505 argument_group_signatures = []
3506 usage = '''\
3507 usage: PROG [-h] [-x X] [-y Y] [-z Z]
3508 aaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbb
3509 ccccccccccccccccccccccccc
3510 '''
3511 help = usage + '''\
3512
3513 positional arguments:
3514 aaaaaaaaaaaaaaaaaaaaaaaaa
3515 bbbbbbbbbbbbbbbbbbbbbbbbb
3516 ccccccccccccccccccccccccc
3517
3518 optional arguments:
3519 -h, --help show this help message and exit
3520 -x X
3521 -y Y
3522 -z Z
3523 '''
3524 version = ''
3525
3526
3527class TestHelpUsageOptionalsPositionalsWrap(HelpTestCase):
3528 """Test usage messages where the optionals and positionals wrap"""
3529
3530 parser_signature = Sig(prog='PROG')
3531 argument_signatures = [
3532 Sig('-x', metavar='X' * 25),
3533 Sig('-y', metavar='Y' * 25),
3534 Sig('-z', metavar='Z' * 25),
3535 Sig('a' * 25),
3536 Sig('b' * 25),
3537 Sig('c' * 25),
3538 ]
3539 argument_group_signatures = []
3540 usage = '''\
3541 usage: PROG [-h] [-x XXXXXXXXXXXXXXXXXXXXXXXXX] \
3542[-y YYYYYYYYYYYYYYYYYYYYYYYYY]
3543 [-z ZZZZZZZZZZZZZZZZZZZZZZZZZ]
3544 aaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbb
3545 ccccccccccccccccccccccccc
3546 '''
3547 help = usage + '''\
3548
3549 positional arguments:
3550 aaaaaaaaaaaaaaaaaaaaaaaaa
3551 bbbbbbbbbbbbbbbbbbbbbbbbb
3552 ccccccccccccccccccccccccc
3553
3554 optional arguments:
3555 -h, --help show this help message and exit
3556 -x XXXXXXXXXXXXXXXXXXXXXXXXX
3557 -y YYYYYYYYYYYYYYYYYYYYYYYYY
3558 -z ZZZZZZZZZZZZZZZZZZZZZZZZZ
3559 '''
3560 version = ''
3561
3562
3563class TestHelpUsageOptionalsOnlyWrap(HelpTestCase):
3564 """Test usage messages where there are only optionals and they wrap"""
3565
3566 parser_signature = Sig(prog='PROG')
3567 argument_signatures = [
3568 Sig('-x', metavar='X' * 25),
3569 Sig('-y', metavar='Y' * 25),
3570 Sig('-z', metavar='Z' * 25),
3571 ]
3572 argument_group_signatures = []
3573 usage = '''\
3574 usage: PROG [-h] [-x XXXXXXXXXXXXXXXXXXXXXXXXX] \
3575[-y YYYYYYYYYYYYYYYYYYYYYYYYY]
3576 [-z ZZZZZZZZZZZZZZZZZZZZZZZZZ]
3577 '''
3578 help = usage + '''\
3579
3580 optional arguments:
3581 -h, --help show this help message and exit
3582 -x XXXXXXXXXXXXXXXXXXXXXXXXX
3583 -y YYYYYYYYYYYYYYYYYYYYYYYYY
3584 -z ZZZZZZZZZZZZZZZZZZZZZZZZZ
3585 '''
3586 version = ''
3587
3588
3589class TestHelpUsagePositionalsOnlyWrap(HelpTestCase):
3590 """Test usage messages where there are only positionals and they wrap"""
3591
3592 parser_signature = Sig(prog='PROG', add_help=False)
3593 argument_signatures = [
3594 Sig('a' * 25),
3595 Sig('b' * 25),
3596 Sig('c' * 25),
3597 ]
3598 argument_group_signatures = []
3599 usage = '''\
3600 usage: PROG aaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbb
3601 ccccccccccccccccccccccccc
3602 '''
3603 help = usage + '''\
3604
3605 positional arguments:
3606 aaaaaaaaaaaaaaaaaaaaaaaaa
3607 bbbbbbbbbbbbbbbbbbbbbbbbb
3608 ccccccccccccccccccccccccc
3609 '''
3610 version = ''
3611
3612
3613class TestHelpVariableExpansion(HelpTestCase):
3614 """Test that variables are expanded properly in help messages"""
3615
3616 parser_signature = Sig(prog='PROG')
3617 argument_signatures = [
3618 Sig('-x', type=int,
3619 help='x %(prog)s %(default)s %(type)s %%'),
3620 Sig('-y', action='store_const', default=42, const='XXX',
3621 help='y %(prog)s %(default)s %(const)s'),
3622 Sig('--foo', choices='abc',
3623 help='foo %(prog)s %(default)s %(choices)s'),
3624 Sig('--bar', default='baz', choices=[1, 2], metavar='BBB',
3625 help='bar %(prog)s %(default)s %(dest)s'),
3626 Sig('spam', help='spam %(prog)s %(default)s'),
3627 Sig('badger', default=0.5, help='badger %(prog)s %(default)s'),
3628 ]
3629 argument_group_signatures = [
3630 (Sig('group'), [
3631 Sig('-a', help='a %(prog)s %(default)s'),
3632 Sig('-b', default=-1, help='b %(prog)s %(default)s'),
3633 ])
3634 ]
3635 usage = ('''\
3636 usage: PROG [-h] [-x X] [-y] [--foo {a,b,c}] [--bar BBB] [-a A] [-b B]
3637 spam badger
3638 ''')
3639 help = usage + '''\
3640
3641 positional arguments:
3642 spam spam PROG None
3643 badger badger PROG 0.5
3644
3645 optional arguments:
3646 -h, --help show this help message and exit
3647 -x X x PROG None int %
3648 -y y PROG 42 XXX
3649 --foo {a,b,c} foo PROG None a, b, c
3650 --bar BBB bar PROG baz bar
3651
3652 group:
3653 -a A a PROG None
3654 -b B b PROG -1
3655 '''
3656 version = ''
3657
3658
3659class TestHelpVariableExpansionUsageSupplied(HelpTestCase):
3660 """Test that variables are expanded properly when usage= is present"""
3661
3662 parser_signature = Sig(prog='PROG', usage='%(prog)s FOO')
3663 argument_signatures = []
3664 argument_group_signatures = []
3665 usage = ('''\
3666 usage: PROG FOO
3667 ''')
3668 help = usage + '''\
3669
3670 optional arguments:
3671 -h, --help show this help message and exit
3672 '''
3673 version = ''
3674
3675
3676class TestHelpVariableExpansionNoArguments(HelpTestCase):
3677 """Test that variables are expanded properly with no arguments"""
3678
3679 parser_signature = Sig(prog='PROG', add_help=False)
3680 argument_signatures = []
3681 argument_group_signatures = []
3682 usage = ('''\
3683 usage: PROG
3684 ''')
3685 help = usage
3686 version = ''
3687
3688
3689class TestHelpSuppressUsage(HelpTestCase):
3690 """Test that items can be suppressed in usage messages"""
3691
3692 parser_signature = Sig(prog='PROG', usage=argparse.SUPPRESS)
3693 argument_signatures = [
3694 Sig('--foo', help='foo help'),
3695 Sig('spam', help='spam help'),
3696 ]
3697 argument_group_signatures = []
3698 help = '''\
3699 positional arguments:
3700 spam spam help
3701
3702 optional arguments:
3703 -h, --help show this help message and exit
3704 --foo FOO foo help
3705 '''
3706 usage = ''
3707 version = ''
3708
3709
3710class TestHelpSuppressOptional(HelpTestCase):
3711 """Test that optional arguments can be suppressed in help messages"""
3712
3713 parser_signature = Sig(prog='PROG', add_help=False)
3714 argument_signatures = [
3715 Sig('--foo', help=argparse.SUPPRESS),
3716 Sig('spam', help='spam help'),
3717 ]
3718 argument_group_signatures = []
3719 usage = '''\
3720 usage: PROG spam
3721 '''
3722 help = usage + '''\
3723
3724 positional arguments:
3725 spam spam help
3726 '''
3727 version = ''
3728
3729
3730class TestHelpSuppressOptionalGroup(HelpTestCase):
3731 """Test that optional groups can be suppressed in help messages"""
3732
3733 parser_signature = Sig(prog='PROG')
3734 argument_signatures = [
3735 Sig('--foo', help='foo help'),
3736 Sig('spam', help='spam help'),
3737 ]
3738 argument_group_signatures = [
3739 (Sig('group'), [Sig('--bar', help=argparse.SUPPRESS)]),
3740 ]
3741 usage = '''\
3742 usage: PROG [-h] [--foo FOO] spam
3743 '''
3744 help = usage + '''\
3745
3746 positional arguments:
3747 spam spam help
3748
3749 optional arguments:
3750 -h, --help show this help message and exit
3751 --foo FOO foo help
3752 '''
3753 version = ''
3754
3755
3756class TestHelpSuppressPositional(HelpTestCase):
3757 """Test that positional arguments can be suppressed in help messages"""
3758
3759 parser_signature = Sig(prog='PROG')
3760 argument_signatures = [
3761 Sig('--foo', help='foo help'),
3762 Sig('spam', help=argparse.SUPPRESS),
3763 ]
3764 argument_group_signatures = []
3765 usage = '''\
3766 usage: PROG [-h] [--foo FOO]
3767 '''
3768 help = usage + '''\
3769
3770 optional arguments:
3771 -h, --help show this help message and exit
3772 --foo FOO foo help
3773 '''
3774 version = ''
3775
3776
3777class TestHelpRequiredOptional(HelpTestCase):
3778 """Test that required options don't look optional"""
3779
3780 parser_signature = Sig(prog='PROG')
3781 argument_signatures = [
3782 Sig('--foo', required=True, help='foo help'),
3783 ]
3784 argument_group_signatures = []
3785 usage = '''\
3786 usage: PROG [-h] --foo FOO
3787 '''
3788 help = usage + '''\
3789
3790 optional arguments:
3791 -h, --help show this help message and exit
3792 --foo FOO foo help
3793 '''
3794 version = ''
3795
3796
3797class TestHelpAlternatePrefixChars(HelpTestCase):
3798 """Test that options display with different prefix characters"""
3799
3800 parser_signature = Sig(prog='PROG', prefix_chars='^;', add_help=False)
3801 argument_signatures = [
3802 Sig('^^foo', action='store_true', help='foo help'),
3803 Sig(';b', ';;bar', help='bar help'),
3804 ]
3805 argument_group_signatures = []
3806 usage = '''\
3807 usage: PROG [^^foo] [;b BAR]
3808 '''
3809 help = usage + '''\
3810
3811 optional arguments:
3812 ^^foo foo help
3813 ;b BAR, ;;bar BAR bar help
3814 '''
3815 version = ''
3816
3817
3818class TestHelpNoHelpOptional(HelpTestCase):
3819 """Test that the --help argument can be suppressed help messages"""
3820
3821 parser_signature = Sig(prog='PROG', add_help=False)
3822 argument_signatures = [
3823 Sig('--foo', help='foo help'),
3824 Sig('spam', help='spam help'),
3825 ]
3826 argument_group_signatures = []
3827 usage = '''\
3828 usage: PROG [--foo FOO] spam
3829 '''
3830 help = usage + '''\
3831
3832 positional arguments:
3833 spam spam help
3834
3835 optional arguments:
3836 --foo FOO foo help
3837 '''
3838 version = ''
3839
3840
3841class TestHelpVersionOptional(HelpTestCase):
3842 """Test that the --version argument can be suppressed help messages"""
3843
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02003844 parser_signature = Sig(prog='PROG')
Benjamin Peterson698a18a2010-03-02 22:34:37 +00003845 argument_signatures = [
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02003846 Sig('-v', '--version', action='version', version='1.0'),
Benjamin Peterson698a18a2010-03-02 22:34:37 +00003847 Sig('--foo', help='foo help'),
3848 Sig('spam', help='spam help'),
3849 ]
3850 argument_group_signatures = []
3851 usage = '''\
3852 usage: PROG [-h] [-v] [--foo FOO] spam
3853 '''
3854 help = usage + '''\
3855
3856 positional arguments:
3857 spam spam help
3858
3859 optional arguments:
3860 -h, --help show this help message and exit
3861 -v, --version show program's version number and exit
3862 --foo FOO foo help
3863 '''
3864 version = '''\
3865 1.0
3866 '''
3867
3868
3869class TestHelpNone(HelpTestCase):
3870 """Test that no errors occur if no help is specified"""
3871
3872 parser_signature = Sig(prog='PROG')
3873 argument_signatures = [
3874 Sig('--foo'),
3875 Sig('spam'),
3876 ]
3877 argument_group_signatures = []
3878 usage = '''\
3879 usage: PROG [-h] [--foo FOO] spam
3880 '''
3881 help = usage + '''\
3882
3883 positional arguments:
3884 spam
3885
3886 optional arguments:
3887 -h, --help show this help message and exit
3888 --foo FOO
3889 '''
3890 version = ''
3891
3892
3893class TestHelpTupleMetavar(HelpTestCase):
3894 """Test specifying metavar as a tuple"""
3895
3896 parser_signature = Sig(prog='PROG')
3897 argument_signatures = [
3898 Sig('-w', help='w', nargs='+', metavar=('W1', 'W2')),
3899 Sig('-x', help='x', nargs='*', metavar=('X1', 'X2')),
3900 Sig('-y', help='y', nargs=3, metavar=('Y1', 'Y2', 'Y3')),
3901 Sig('-z', help='z', nargs='?', metavar=('Z1', )),
3902 ]
3903 argument_group_signatures = []
3904 usage = '''\
3905 usage: PROG [-h] [-w W1 [W2 ...]] [-x [X1 [X2 ...]]] [-y Y1 Y2 Y3] \
3906[-z [Z1]]
3907 '''
3908 help = usage + '''\
3909
3910 optional arguments:
3911 -h, --help show this help message and exit
3912 -w W1 [W2 ...] w
3913 -x [X1 [X2 ...]] x
3914 -y Y1 Y2 Y3 y
3915 -z [Z1] z
3916 '''
3917 version = ''
3918
3919
3920class TestHelpRawText(HelpTestCase):
3921 """Test the RawTextHelpFormatter"""
3922
3923 parser_signature = Sig(
3924 prog='PROG', formatter_class=argparse.RawTextHelpFormatter,
3925 description='Keep the formatting\n'
3926 ' exactly as it is written\n'
3927 '\n'
3928 'here\n')
3929
3930 argument_signatures = [
3931 Sig('--foo', help=' foo help should also\n'
3932 'appear as given here'),
3933 Sig('spam', help='spam help'),
3934 ]
3935 argument_group_signatures = [
3936 (Sig('title', description=' This text\n'
3937 ' should be indented\n'
3938 ' exactly like it is here\n'),
3939 [Sig('--bar', help='bar help')]),
3940 ]
3941 usage = '''\
3942 usage: PROG [-h] [--foo FOO] [--bar BAR] spam
3943 '''
3944 help = usage + '''\
3945
3946 Keep the formatting
3947 exactly as it is written
3948
3949 here
3950
3951 positional arguments:
3952 spam spam help
3953
3954 optional arguments:
3955 -h, --help show this help message and exit
3956 --foo FOO foo help should also
3957 appear as given here
3958
3959 title:
3960 This text
3961 should be indented
3962 exactly like it is here
3963
3964 --bar BAR bar help
3965 '''
3966 version = ''
3967
3968
3969class TestHelpRawDescription(HelpTestCase):
3970 """Test the RawTextHelpFormatter"""
3971
3972 parser_signature = Sig(
3973 prog='PROG', formatter_class=argparse.RawDescriptionHelpFormatter,
3974 description='Keep the formatting\n'
3975 ' exactly as it is written\n'
3976 '\n'
3977 'here\n')
3978
3979 argument_signatures = [
3980 Sig('--foo', help=' foo help should not\n'
3981 ' retain this odd formatting'),
3982 Sig('spam', help='spam help'),
3983 ]
3984 argument_group_signatures = [
3985 (Sig('title', description=' This text\n'
3986 ' should be indented\n'
3987 ' exactly like it is here\n'),
3988 [Sig('--bar', help='bar help')]),
3989 ]
3990 usage = '''\
3991 usage: PROG [-h] [--foo FOO] [--bar BAR] spam
3992 '''
3993 help = usage + '''\
3994
3995 Keep the formatting
3996 exactly as it is written
3997
3998 here
3999
4000 positional arguments:
4001 spam spam help
4002
4003 optional arguments:
4004 -h, --help show this help message and exit
4005 --foo FOO foo help should not retain this odd formatting
4006
4007 title:
4008 This text
4009 should be indented
4010 exactly like it is here
4011
4012 --bar BAR bar help
4013 '''
4014 version = ''
4015
4016
4017class TestHelpArgumentDefaults(HelpTestCase):
4018 """Test the ArgumentDefaultsHelpFormatter"""
4019
4020 parser_signature = Sig(
4021 prog='PROG', formatter_class=argparse.ArgumentDefaultsHelpFormatter,
4022 description='description')
4023
4024 argument_signatures = [
4025 Sig('--foo', help='foo help - oh and by the way, %(default)s'),
4026 Sig('--bar', action='store_true', help='bar help'),
4027 Sig('spam', help='spam help'),
4028 Sig('badger', nargs='?', default='wooden', help='badger help'),
4029 ]
4030 argument_group_signatures = [
4031 (Sig('title', description='description'),
4032 [Sig('--baz', type=int, default=42, help='baz help')]),
4033 ]
4034 usage = '''\
4035 usage: PROG [-h] [--foo FOO] [--bar] [--baz BAZ] spam [badger]
4036 '''
4037 help = usage + '''\
4038
4039 description
4040
4041 positional arguments:
4042 spam spam help
4043 badger badger help (default: wooden)
4044
4045 optional arguments:
4046 -h, --help show this help message and exit
4047 --foo FOO foo help - oh and by the way, None
4048 --bar bar help (default: False)
4049
4050 title:
4051 description
4052
4053 --baz BAZ baz help (default: 42)
4054 '''
4055 version = ''
4056
Steven Bethard50fe5932010-05-24 03:47:38 +00004057class TestHelpVersionAction(HelpTestCase):
4058 """Test the default help for the version action"""
4059
4060 parser_signature = Sig(prog='PROG', description='description')
4061 argument_signatures = [Sig('-V', '--version', action='version', version='3.6')]
4062 argument_group_signatures = []
4063 usage = '''\
4064 usage: PROG [-h] [-V]
4065 '''
4066 help = usage + '''\
4067
4068 description
4069
4070 optional arguments:
4071 -h, --help show this help message and exit
4072 -V, --version show program's version number and exit
4073 '''
4074 version = ''
4075
Steven Bethard8a6a1982011-03-27 13:53:53 +02004076class TestHelpSubparsersOrdering(HelpTestCase):
4077 """Test ordering of subcommands in help matches the code"""
4078 parser_signature = Sig(prog='PROG',
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02004079 description='display some subcommands')
4080 argument_signatures = [Sig('-v', '--version', action='version', version='0.1')]
Steven Bethard8a6a1982011-03-27 13:53:53 +02004081
4082 subparsers_signatures = [Sig(name=name)
4083 for name in ('a', 'b', 'c', 'd', 'e')]
4084
4085 usage = '''\
4086 usage: PROG [-h] [-v] {a,b,c,d,e} ...
4087 '''
4088
4089 help = usage + '''\
4090
4091 display some subcommands
4092
4093 positional arguments:
4094 {a,b,c,d,e}
4095
4096 optional arguments:
4097 -h, --help show this help message and exit
4098 -v, --version show program's version number and exit
4099 '''
4100
4101 version = '''\
4102 0.1
4103 '''
4104
4105class TestHelpSubparsersWithHelpOrdering(HelpTestCase):
4106 """Test ordering of subcommands in help matches the code"""
4107 parser_signature = Sig(prog='PROG',
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02004108 description='display some subcommands')
4109 argument_signatures = [Sig('-v', '--version', action='version', version='0.1')]
Steven Bethard8a6a1982011-03-27 13:53:53 +02004110
4111 subcommand_data = (('a', 'a subcommand help'),
4112 ('b', 'b subcommand help'),
4113 ('c', 'c subcommand help'),
4114 ('d', 'd subcommand help'),
4115 ('e', 'e subcommand help'),
4116 )
4117
4118 subparsers_signatures = [Sig(name=name, help=help)
4119 for name, help in subcommand_data]
4120
4121 usage = '''\
4122 usage: PROG [-h] [-v] {a,b,c,d,e} ...
4123 '''
4124
4125 help = usage + '''\
4126
4127 display some subcommands
4128
4129 positional arguments:
4130 {a,b,c,d,e}
4131 a a subcommand help
4132 b b subcommand help
4133 c c subcommand help
4134 d d subcommand help
4135 e e subcommand help
4136
4137 optional arguments:
4138 -h, --help show this help message and exit
4139 -v, --version show program's version number and exit
4140 '''
4141
4142 version = '''\
4143 0.1
4144 '''
4145
4146
Steven Bethard0331e902011-03-26 14:48:04 +01004147
4148class TestHelpMetavarTypeFormatter(HelpTestCase):
4149 """"""
4150
4151 def custom_type(string):
4152 return string
4153
4154 parser_signature = Sig(prog='PROG', description='description',
4155 formatter_class=argparse.MetavarTypeHelpFormatter)
4156 argument_signatures = [Sig('a', type=int),
4157 Sig('-b', type=custom_type),
4158 Sig('-c', type=float, metavar='SOME FLOAT')]
4159 argument_group_signatures = []
4160 usage = '''\
4161 usage: PROG [-h] [-b custom_type] [-c SOME FLOAT] int
4162 '''
4163 help = usage + '''\
4164
4165 description
4166
4167 positional arguments:
4168 int
4169
4170 optional arguments:
4171 -h, --help show this help message and exit
4172 -b custom_type
4173 -c SOME FLOAT
4174 '''
4175 version = ''
4176
4177
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004178# =====================================
4179# Optional/Positional constructor tests
4180# =====================================
4181
4182class TestInvalidArgumentConstructors(TestCase):
4183 """Test a bunch of invalid Argument constructors"""
4184
4185 def assertTypeError(self, *args, **kwargs):
4186 parser = argparse.ArgumentParser()
4187 self.assertRaises(TypeError, parser.add_argument,
4188 *args, **kwargs)
4189
4190 def assertValueError(self, *args, **kwargs):
4191 parser = argparse.ArgumentParser()
4192 self.assertRaises(ValueError, parser.add_argument,
4193 *args, **kwargs)
4194
4195 def test_invalid_keyword_arguments(self):
4196 self.assertTypeError('-x', bar=None)
4197 self.assertTypeError('-y', callback='foo')
4198 self.assertTypeError('-y', callback_args=())
4199 self.assertTypeError('-y', callback_kwargs={})
4200
4201 def test_missing_destination(self):
4202 self.assertTypeError()
4203 for action in ['append', 'store']:
4204 self.assertTypeError(action=action)
4205
4206 def test_invalid_option_strings(self):
4207 self.assertValueError('--')
4208 self.assertValueError('---')
4209
4210 def test_invalid_type(self):
4211 self.assertValueError('--foo', type='int')
Steven Bethard7cb20a82011-04-04 01:53:02 +02004212 self.assertValueError('--foo', type=(int, float))
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004213
4214 def test_invalid_action(self):
4215 self.assertValueError('-x', action='foo')
4216 self.assertValueError('foo', action='baz')
Steven Bethard7cb20a82011-04-04 01:53:02 +02004217 self.assertValueError('--foo', action=('store', 'append'))
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004218 parser = argparse.ArgumentParser()
4219 try:
4220 parser.add_argument("--foo", action="store-true")
4221 except ValueError:
4222 e = sys.exc_info()[1]
4223 expected = 'unknown action'
4224 msg = 'expected %r, found %r' % (expected, e)
4225 self.assertTrue(expected in str(e), msg)
4226
4227 def test_multiple_dest(self):
4228 parser = argparse.ArgumentParser()
4229 parser.add_argument(dest='foo')
4230 try:
4231 parser.add_argument('bar', dest='baz')
4232 except ValueError:
4233 e = sys.exc_info()[1]
4234 expected = 'dest supplied twice for positional argument'
4235 msg = 'expected %r, found %r' % (expected, e)
4236 self.assertTrue(expected in str(e), msg)
4237
4238 def test_no_argument_actions(self):
4239 for action in ['store_const', 'store_true', 'store_false',
4240 'append_const', 'count']:
4241 for attrs in [dict(type=int), dict(nargs='+'),
4242 dict(choices='ab')]:
4243 self.assertTypeError('-x', action=action, **attrs)
4244
4245 def test_no_argument_no_const_actions(self):
4246 # options with zero arguments
4247 for action in ['store_true', 'store_false', 'count']:
4248
4249 # const is always disallowed
4250 self.assertTypeError('-x', const='foo', action=action)
4251
4252 # nargs is always disallowed
4253 self.assertTypeError('-x', nargs='*', action=action)
4254
4255 def test_more_than_one_argument_actions(self):
4256 for action in ['store', 'append']:
4257
4258 # nargs=0 is disallowed
4259 self.assertValueError('-x', nargs=0, action=action)
4260 self.assertValueError('spam', nargs=0, action=action)
4261
4262 # const is disallowed with non-optional arguments
4263 for nargs in [1, '*', '+']:
4264 self.assertValueError('-x', const='foo',
4265 nargs=nargs, action=action)
4266 self.assertValueError('spam', const='foo',
4267 nargs=nargs, action=action)
4268
4269 def test_required_const_actions(self):
4270 for action in ['store_const', 'append_const']:
4271
4272 # nargs is always disallowed
4273 self.assertTypeError('-x', nargs='+', action=action)
4274
4275 def test_parsers_action_missing_params(self):
4276 self.assertTypeError('command', action='parsers')
4277 self.assertTypeError('command', action='parsers', prog='PROG')
4278 self.assertTypeError('command', action='parsers',
4279 parser_class=argparse.ArgumentParser)
4280
4281 def test_required_positional(self):
4282 self.assertTypeError('foo', required=True)
4283
4284 def test_user_defined_action(self):
4285
4286 class Success(Exception):
4287 pass
4288
4289 class Action(object):
4290
4291 def __init__(self,
4292 option_strings,
4293 dest,
4294 const,
4295 default,
4296 required=False):
4297 if dest == 'spam':
4298 if const is Success:
4299 if default is Success:
4300 raise Success()
4301
4302 def __call__(self, *args, **kwargs):
4303 pass
4304
4305 parser = argparse.ArgumentParser()
4306 self.assertRaises(Success, parser.add_argument, '--spam',
4307 action=Action, default=Success, const=Success)
4308 self.assertRaises(Success, parser.add_argument, 'spam',
4309 action=Action, default=Success, const=Success)
4310
4311# ================================
4312# Actions returned by add_argument
4313# ================================
4314
4315class TestActionsReturned(TestCase):
4316
4317 def test_dest(self):
4318 parser = argparse.ArgumentParser()
4319 action = parser.add_argument('--foo')
4320 self.assertEqual(action.dest, 'foo')
4321 action = parser.add_argument('-b', '--bar')
4322 self.assertEqual(action.dest, 'bar')
4323 action = parser.add_argument('-x', '-y')
4324 self.assertEqual(action.dest, 'x')
4325
4326 def test_misc(self):
4327 parser = argparse.ArgumentParser()
4328 action = parser.add_argument('--foo', nargs='?', const=42,
4329 default=84, type=int, choices=[1, 2],
4330 help='FOO', metavar='BAR', dest='baz')
4331 self.assertEqual(action.nargs, '?')
4332 self.assertEqual(action.const, 42)
4333 self.assertEqual(action.default, 84)
4334 self.assertEqual(action.type, int)
4335 self.assertEqual(action.choices, [1, 2])
4336 self.assertEqual(action.help, 'FOO')
4337 self.assertEqual(action.metavar, 'BAR')
4338 self.assertEqual(action.dest, 'baz')
4339
4340
4341# ================================
4342# Argument conflict handling tests
4343# ================================
4344
4345class TestConflictHandling(TestCase):
4346
4347 def test_bad_type(self):
4348 self.assertRaises(ValueError, argparse.ArgumentParser,
4349 conflict_handler='foo')
4350
4351 def test_conflict_error(self):
4352 parser = argparse.ArgumentParser()
4353 parser.add_argument('-x')
4354 self.assertRaises(argparse.ArgumentError,
4355 parser.add_argument, '-x')
4356 parser.add_argument('--spam')
4357 self.assertRaises(argparse.ArgumentError,
4358 parser.add_argument, '--spam')
4359
4360 def test_resolve_error(self):
4361 get_parser = argparse.ArgumentParser
4362 parser = get_parser(prog='PROG', conflict_handler='resolve')
4363
4364 parser.add_argument('-x', help='OLD X')
4365 parser.add_argument('-x', help='NEW X')
4366 self.assertEqual(parser.format_help(), textwrap.dedent('''\
4367 usage: PROG [-h] [-x X]
4368
4369 optional arguments:
4370 -h, --help show this help message and exit
4371 -x X NEW X
4372 '''))
4373
4374 parser.add_argument('--spam', metavar='OLD_SPAM')
4375 parser.add_argument('--spam', metavar='NEW_SPAM')
4376 self.assertEqual(parser.format_help(), textwrap.dedent('''\
4377 usage: PROG [-h] [-x X] [--spam NEW_SPAM]
4378
4379 optional arguments:
4380 -h, --help show this help message and exit
4381 -x X NEW X
4382 --spam NEW_SPAM
4383 '''))
4384
4385
4386# =============================
4387# Help and Version option tests
4388# =============================
4389
4390class TestOptionalsHelpVersionActions(TestCase):
4391 """Test the help and version actions"""
4392
4393 def _get_error(self, func, *args, **kwargs):
4394 try:
4395 func(*args, **kwargs)
4396 except ArgumentParserError:
4397 return sys.exc_info()[1]
4398 else:
4399 self.assertRaises(ArgumentParserError, func, *args, **kwargs)
4400
4401 def assertPrintHelpExit(self, parser, args_str):
4402 self.assertEqual(
4403 parser.format_help(),
4404 self._get_error(parser.parse_args, args_str.split()).stdout)
4405
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004406 def assertArgumentParserError(self, parser, *args):
4407 self.assertRaises(ArgumentParserError, parser.parse_args, args)
4408
4409 def test_version(self):
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02004410 parser = ErrorRaisingArgumentParser()
4411 parser.add_argument('-v', '--version', action='version', version='1.0')
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004412 self.assertPrintHelpExit(parser, '-h')
4413 self.assertPrintHelpExit(parser, '--help')
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02004414 self.assertRaises(AttributeError, getattr, parser, 'format_version')
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004415
4416 def test_version_format(self):
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02004417 parser = ErrorRaisingArgumentParser(prog='PPP')
4418 parser.add_argument('-v', '--version', action='version', version='%(prog)s 3.5')
Eli Benderskycdac5512013-09-06 06:49:15 -07004419 msg = self._get_error(parser.parse_args, ['-v']).stdout
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004420 self.assertEqual('PPP 3.5\n', msg)
4421
4422 def test_version_no_help(self):
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02004423 parser = ErrorRaisingArgumentParser(add_help=False)
4424 parser.add_argument('-v', '--version', action='version', version='1.0')
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004425 self.assertArgumentParserError(parser, '-h')
4426 self.assertArgumentParserError(parser, '--help')
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02004427 self.assertRaises(AttributeError, getattr, parser, 'format_version')
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004428
4429 def test_version_action(self):
4430 parser = ErrorRaisingArgumentParser(prog='XXX')
4431 parser.add_argument('-V', action='version', version='%(prog)s 3.7')
Eli Benderskycdac5512013-09-06 06:49:15 -07004432 msg = self._get_error(parser.parse_args, ['-V']).stdout
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004433 self.assertEqual('XXX 3.7\n', msg)
4434
4435 def test_no_help(self):
4436 parser = ErrorRaisingArgumentParser(add_help=False)
4437 self.assertArgumentParserError(parser, '-h')
4438 self.assertArgumentParserError(parser, '--help')
4439 self.assertArgumentParserError(parser, '-v')
4440 self.assertArgumentParserError(parser, '--version')
4441
4442 def test_alternate_help_version(self):
4443 parser = ErrorRaisingArgumentParser()
4444 parser.add_argument('-x', action='help')
4445 parser.add_argument('-y', action='version')
4446 self.assertPrintHelpExit(parser, '-x')
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004447 self.assertArgumentParserError(parser, '-v')
4448 self.assertArgumentParserError(parser, '--version')
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02004449 self.assertRaises(AttributeError, getattr, parser, 'format_version')
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004450
4451 def test_help_version_extra_arguments(self):
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02004452 parser = ErrorRaisingArgumentParser()
4453 parser.add_argument('--version', action='version', version='1.0')
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004454 parser.add_argument('-x', action='store_true')
4455 parser.add_argument('y')
4456
4457 # try all combinations of valid prefixes and suffixes
4458 valid_prefixes = ['', '-x', 'foo', '-x bar', 'baz -x']
4459 valid_suffixes = valid_prefixes + ['--bad-option', 'foo bar baz']
4460 for prefix in valid_prefixes:
4461 for suffix in valid_suffixes:
4462 format = '%s %%s %s' % (prefix, suffix)
4463 self.assertPrintHelpExit(parser, format % '-h')
4464 self.assertPrintHelpExit(parser, format % '--help')
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02004465 self.assertRaises(AttributeError, getattr, parser, 'format_version')
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004466
4467
4468# ======================
4469# str() and repr() tests
4470# ======================
4471
4472class TestStrings(TestCase):
4473 """Test str() and repr() on Optionals and Positionals"""
4474
4475 def assertStringEqual(self, obj, result_string):
4476 for func in [str, repr]:
4477 self.assertEqual(func(obj), result_string)
4478
4479 def test_optional(self):
4480 option = argparse.Action(
4481 option_strings=['--foo', '-a', '-b'],
4482 dest='b',
4483 type='int',
4484 nargs='+',
4485 default=42,
4486 choices=[1, 2, 3],
4487 help='HELP',
4488 metavar='METAVAR')
4489 string = (
4490 "Action(option_strings=['--foo', '-a', '-b'], dest='b', "
4491 "nargs='+', const=None, default=42, type='int', "
4492 "choices=[1, 2, 3], help='HELP', metavar='METAVAR')")
4493 self.assertStringEqual(option, string)
4494
4495 def test_argument(self):
4496 argument = argparse.Action(
4497 option_strings=[],
4498 dest='x',
4499 type=float,
4500 nargs='?',
4501 default=2.5,
4502 choices=[0.5, 1.5, 2.5],
4503 help='H HH H',
4504 metavar='MV MV MV')
4505 string = (
4506 "Action(option_strings=[], dest='x', nargs='?', "
4507 "const=None, default=2.5, type=%r, choices=[0.5, 1.5, 2.5], "
4508 "help='H HH H', metavar='MV MV MV')" % float)
4509 self.assertStringEqual(argument, string)
4510
4511 def test_namespace(self):
4512 ns = argparse.Namespace(foo=42, bar='spam')
4513 string = "Namespace(bar='spam', foo=42)"
4514 self.assertStringEqual(ns, string)
4515
4516 def test_parser(self):
4517 parser = argparse.ArgumentParser(prog='PROG')
4518 string = (
4519 "ArgumentParser(prog='PROG', usage=None, description=None, "
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02004520 "formatter_class=%r, conflict_handler='error', "
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004521 "add_help=True)" % argparse.HelpFormatter)
4522 self.assertStringEqual(parser, string)
4523
4524# ===============
4525# Namespace tests
4526# ===============
4527
4528class TestNamespace(TestCase):
4529
4530 def test_constructor(self):
4531 ns = argparse.Namespace()
4532 self.assertRaises(AttributeError, getattr, ns, 'x')
4533
4534 ns = argparse.Namespace(a=42, b='spam')
4535 self.assertEqual(ns.a, 42)
4536 self.assertEqual(ns.b, 'spam')
4537
4538 def test_equality(self):
4539 ns1 = argparse.Namespace(a=1, b=2)
4540 ns2 = argparse.Namespace(b=2, a=1)
4541 ns3 = argparse.Namespace(a=1)
4542 ns4 = argparse.Namespace(b=2)
4543
4544 self.assertEqual(ns1, ns2)
4545 self.assertNotEqual(ns1, ns3)
4546 self.assertNotEqual(ns1, ns4)
4547 self.assertNotEqual(ns2, ns3)
4548 self.assertNotEqual(ns2, ns4)
4549 self.assertTrue(ns1 != ns3)
4550 self.assertTrue(ns1 != ns4)
4551 self.assertTrue(ns2 != ns3)
4552 self.assertTrue(ns2 != ns4)
4553
Raymond Hettingerdea46ec2014-05-26 00:43:27 -07004554 def test_equality_returns_notimplemeted(self):
4555 # See issue 21481
4556 ns = argparse.Namespace(a=1, b=2)
4557 self.assertIs(ns.__eq__(None), NotImplemented)
4558 self.assertIs(ns.__ne__(None), NotImplemented)
4559
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004560
4561# ===================
4562# File encoding tests
4563# ===================
4564
4565class TestEncoding(TestCase):
4566
4567 def _test_module_encoding(self, path):
4568 path, _ = os.path.splitext(path)
4569 path += ".py"
Marc-André Lemburg8f36af72011-02-25 15:42:01 +00004570 with codecs.open(path, 'r', 'utf-8') as f:
Antoine Pitroub86680e2010-10-14 21:15:17 +00004571 f.read()
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004572
4573 def test_argparse_module_encoding(self):
4574 self._test_module_encoding(argparse.__file__)
4575
4576 def test_test_argparse_module_encoding(self):
4577 self._test_module_encoding(__file__)
4578
4579# ===================
4580# ArgumentError tests
4581# ===================
4582
4583class TestArgumentError(TestCase):
4584
4585 def test_argument_error(self):
4586 msg = "my error here"
4587 error = argparse.ArgumentError(None, msg)
4588 self.assertEqual(str(error), msg)
4589
4590# =======================
4591# ArgumentTypeError tests
4592# =======================
4593
R. David Murray722b5fd2010-11-20 03:48:58 +00004594class TestArgumentTypeError(TestCase):
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004595
4596 def test_argument_type_error(self):
4597
4598 def spam(string):
4599 raise argparse.ArgumentTypeError('spam!')
4600
4601 parser = ErrorRaisingArgumentParser(prog='PROG', add_help=False)
4602 parser.add_argument('x', type=spam)
4603 try:
4604 parser.parse_args(['XXX'])
4605 except ArgumentParserError:
4606 expected = 'usage: PROG x\nPROG: error: argument x: spam!\n'
4607 msg = sys.exc_info()[1].stderr
4608 self.assertEqual(expected, msg)
4609 else:
4610 self.fail()
4611
R David Murrayf97c59a2011-06-09 12:34:07 -04004612# =========================
4613# MessageContentError tests
4614# =========================
4615
4616class TestMessageContentError(TestCase):
4617
4618 def test_missing_argument_name_in_message(self):
4619 parser = ErrorRaisingArgumentParser(prog='PROG', usage='')
4620 parser.add_argument('req_pos', type=str)
4621 parser.add_argument('-req_opt', type=int, required=True)
4622 parser.add_argument('need_one', type=str, nargs='+')
4623
4624 with self.assertRaises(ArgumentParserError) as cm:
4625 parser.parse_args([])
4626 msg = str(cm.exception)
4627 self.assertRegex(msg, 'req_pos')
4628 self.assertRegex(msg, 'req_opt')
4629 self.assertRegex(msg, 'need_one')
4630 with self.assertRaises(ArgumentParserError) as cm:
4631 parser.parse_args(['myXargument'])
4632 msg = str(cm.exception)
4633 self.assertNotIn(msg, 'req_pos')
4634 self.assertRegex(msg, 'req_opt')
4635 self.assertRegex(msg, 'need_one')
4636 with self.assertRaises(ArgumentParserError) as cm:
4637 parser.parse_args(['myXargument', '-req_opt=1'])
4638 msg = str(cm.exception)
4639 self.assertNotIn(msg, 'req_pos')
4640 self.assertNotIn(msg, 'req_opt')
4641 self.assertRegex(msg, 'need_one')
4642
4643 def test_optional_optional_not_in_message(self):
4644 parser = ErrorRaisingArgumentParser(prog='PROG', usage='')
4645 parser.add_argument('req_pos', type=str)
4646 parser.add_argument('--req_opt', type=int, required=True)
4647 parser.add_argument('--opt_opt', type=bool, nargs='?',
4648 default=True)
4649 with self.assertRaises(ArgumentParserError) as cm:
4650 parser.parse_args([])
4651 msg = str(cm.exception)
4652 self.assertRegex(msg, 'req_pos')
4653 self.assertRegex(msg, 'req_opt')
4654 self.assertNotIn(msg, 'opt_opt')
4655 with self.assertRaises(ArgumentParserError) as cm:
4656 parser.parse_args(['--req_opt=1'])
4657 msg = str(cm.exception)
4658 self.assertRegex(msg, 'req_pos')
4659 self.assertNotIn(msg, 'req_opt')
4660 self.assertNotIn(msg, 'opt_opt')
4661
4662 def test_optional_positional_not_in_message(self):
4663 parser = ErrorRaisingArgumentParser(prog='PROG', usage='')
4664 parser.add_argument('req_pos')
4665 parser.add_argument('optional_positional', nargs='?', default='eggs')
4666 with self.assertRaises(ArgumentParserError) as cm:
4667 parser.parse_args([])
4668 msg = str(cm.exception)
4669 self.assertRegex(msg, 'req_pos')
4670 self.assertNotIn(msg, 'optional_positional')
4671
4672
R David Murray6fb8fb12012-08-31 22:45:20 -04004673# ================================================
4674# Check that the type function is called only once
4675# ================================================
4676
4677class TestTypeFunctionCallOnlyOnce(TestCase):
4678
4679 def test_type_function_call_only_once(self):
4680 def spam(string_to_convert):
4681 self.assertEqual(string_to_convert, 'spam!')
4682 return 'foo_converted'
4683
4684 parser = argparse.ArgumentParser()
4685 parser.add_argument('--foo', type=spam, default='bar')
4686 args = parser.parse_args('--foo spam!'.split())
4687 self.assertEqual(NS(foo='foo_converted'), args)
4688
Barry Warsaweaae1b72012-09-12 14:34:50 -04004689# ==================================================================
4690# Check semantics regarding the default argument and type conversion
4691# ==================================================================
R David Murray6fb8fb12012-08-31 22:45:20 -04004692
Barry Warsaweaae1b72012-09-12 14:34:50 -04004693class TestTypeFunctionCalledOnDefault(TestCase):
R David Murray6fb8fb12012-08-31 22:45:20 -04004694
4695 def test_type_function_call_with_non_string_default(self):
4696 def spam(int_to_convert):
4697 self.assertEqual(int_to_convert, 0)
4698 return 'foo_converted'
4699
4700 parser = argparse.ArgumentParser()
4701 parser.add_argument('--foo', type=spam, default=0)
4702 args = parser.parse_args([])
Barry Warsaweaae1b72012-09-12 14:34:50 -04004703 # foo should *not* be converted because its default is not a string.
4704 self.assertEqual(NS(foo=0), args)
4705
4706 def test_type_function_call_with_string_default(self):
4707 def spam(int_to_convert):
4708 return 'foo_converted'
4709
4710 parser = argparse.ArgumentParser()
4711 parser.add_argument('--foo', type=spam, default='0')
4712 args = parser.parse_args([])
4713 # foo is converted because its default is a string.
R David Murray6fb8fb12012-08-31 22:45:20 -04004714 self.assertEqual(NS(foo='foo_converted'), args)
4715
Barry Warsaweaae1b72012-09-12 14:34:50 -04004716 def test_no_double_type_conversion_of_default(self):
4717 def extend(str_to_convert):
4718 return str_to_convert + '*'
4719
4720 parser = argparse.ArgumentParser()
4721 parser.add_argument('--test', type=extend, default='*')
4722 args = parser.parse_args([])
4723 # The test argument will be two stars, one coming from the default
4724 # value and one coming from the type conversion being called exactly
4725 # once.
4726 self.assertEqual(NS(test='**'), args)
4727
Barry Warsaw4b2f9e92012-09-11 22:38:47 -04004728 def test_issue_15906(self):
4729 # Issue #15906: When action='append', type=str, default=[] are
4730 # providing, the dest value was the string representation "[]" when it
4731 # should have been an empty list.
4732 parser = argparse.ArgumentParser()
4733 parser.add_argument('--test', dest='test', type=str,
4734 default=[], action='append')
4735 args = parser.parse_args([])
4736 self.assertEqual(args.test, [])
4737
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004738# ======================
4739# parse_known_args tests
4740# ======================
4741
4742class TestParseKnownArgs(TestCase):
4743
R David Murrayb5228282012-09-08 12:08:01 -04004744 def test_arguments_tuple(self):
4745 parser = argparse.ArgumentParser()
4746 parser.parse_args(())
4747
4748 def test_arguments_list(self):
4749 parser = argparse.ArgumentParser()
4750 parser.parse_args([])
4751
4752 def test_arguments_tuple_positional(self):
4753 parser = argparse.ArgumentParser()
4754 parser.add_argument('x')
4755 parser.parse_args(('x',))
4756
4757 def test_arguments_list_positional(self):
4758 parser = argparse.ArgumentParser()
4759 parser.add_argument('x')
4760 parser.parse_args(['x'])
4761
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004762 def test_optionals(self):
4763 parser = argparse.ArgumentParser()
4764 parser.add_argument('--foo')
4765 args, extras = parser.parse_known_args('--foo F --bar --baz'.split())
4766 self.assertEqual(NS(foo='F'), args)
4767 self.assertEqual(['--bar', '--baz'], extras)
4768
4769 def test_mixed(self):
4770 parser = argparse.ArgumentParser()
4771 parser.add_argument('-v', nargs='?', const=1, type=int)
4772 parser.add_argument('--spam', action='store_false')
4773 parser.add_argument('badger')
4774
4775 argv = ["B", "C", "--foo", "-v", "3", "4"]
4776 args, extras = parser.parse_known_args(argv)
4777 self.assertEqual(NS(v=3, spam=True, badger="B"), args)
4778 self.assertEqual(["C", "--foo", "4"], extras)
4779
Steven Bethard8d9a4622011-03-26 17:33:56 +01004780# ==========================
4781# add_argument metavar tests
4782# ==========================
4783
4784class TestAddArgumentMetavar(TestCase):
4785
4786 EXPECTED_MESSAGE = "length of metavar tuple does not match nargs"
4787
4788 def do_test_no_exception(self, nargs, metavar):
4789 parser = argparse.ArgumentParser()
4790 parser.add_argument("--foo", nargs=nargs, metavar=metavar)
4791
4792 def do_test_exception(self, nargs, metavar):
4793 parser = argparse.ArgumentParser()
4794 with self.assertRaises(ValueError) as cm:
4795 parser.add_argument("--foo", nargs=nargs, metavar=metavar)
4796 self.assertEqual(cm.exception.args[0], self.EXPECTED_MESSAGE)
4797
4798 # Unit tests for different values of metavar when nargs=None
4799
4800 def test_nargs_None_metavar_string(self):
4801 self.do_test_no_exception(nargs=None, metavar="1")
4802
4803 def test_nargs_None_metavar_length0(self):
4804 self.do_test_exception(nargs=None, metavar=tuple())
4805
4806 def test_nargs_None_metavar_length1(self):
4807 self.do_test_no_exception(nargs=None, metavar=("1"))
4808
4809 def test_nargs_None_metavar_length2(self):
4810 self.do_test_exception(nargs=None, metavar=("1", "2"))
4811
4812 def test_nargs_None_metavar_length3(self):
4813 self.do_test_exception(nargs=None, metavar=("1", "2", "3"))
4814
4815 # Unit tests for different values of metavar when nargs=?
4816
4817 def test_nargs_optional_metavar_string(self):
4818 self.do_test_no_exception(nargs="?", metavar="1")
4819
4820 def test_nargs_optional_metavar_length0(self):
4821 self.do_test_exception(nargs="?", metavar=tuple())
4822
4823 def test_nargs_optional_metavar_length1(self):
4824 self.do_test_no_exception(nargs="?", metavar=("1"))
4825
4826 def test_nargs_optional_metavar_length2(self):
4827 self.do_test_exception(nargs="?", metavar=("1", "2"))
4828
4829 def test_nargs_optional_metavar_length3(self):
4830 self.do_test_exception(nargs="?", metavar=("1", "2", "3"))
4831
4832 # Unit tests for different values of metavar when nargs=*
4833
4834 def test_nargs_zeroormore_metavar_string(self):
4835 self.do_test_no_exception(nargs="*", metavar="1")
4836
4837 def test_nargs_zeroormore_metavar_length0(self):
4838 self.do_test_exception(nargs="*", metavar=tuple())
4839
4840 def test_nargs_zeroormore_metavar_length1(self):
4841 self.do_test_no_exception(nargs="*", metavar=("1"))
4842
4843 def test_nargs_zeroormore_metavar_length2(self):
4844 self.do_test_no_exception(nargs="*", metavar=("1", "2"))
4845
4846 def test_nargs_zeroormore_metavar_length3(self):
4847 self.do_test_exception(nargs="*", metavar=("1", "2", "3"))
4848
4849 # Unit tests for different values of metavar when nargs=+
4850
4851 def test_nargs_oneormore_metavar_string(self):
4852 self.do_test_no_exception(nargs="+", metavar="1")
4853
4854 def test_nargs_oneormore_metavar_length0(self):
4855 self.do_test_exception(nargs="+", metavar=tuple())
4856
4857 def test_nargs_oneormore_metavar_length1(self):
4858 self.do_test_no_exception(nargs="+", metavar=("1"))
4859
4860 def test_nargs_oneormore_metavar_length2(self):
4861 self.do_test_no_exception(nargs="+", metavar=("1", "2"))
4862
4863 def test_nargs_oneormore_metavar_length3(self):
4864 self.do_test_exception(nargs="+", metavar=("1", "2", "3"))
4865
4866 # Unit tests for different values of metavar when nargs=...
4867
4868 def test_nargs_remainder_metavar_string(self):
4869 self.do_test_no_exception(nargs="...", metavar="1")
4870
4871 def test_nargs_remainder_metavar_length0(self):
4872 self.do_test_no_exception(nargs="...", metavar=tuple())
4873
4874 def test_nargs_remainder_metavar_length1(self):
4875 self.do_test_no_exception(nargs="...", metavar=("1"))
4876
4877 def test_nargs_remainder_metavar_length2(self):
4878 self.do_test_no_exception(nargs="...", metavar=("1", "2"))
4879
4880 def test_nargs_remainder_metavar_length3(self):
4881 self.do_test_no_exception(nargs="...", metavar=("1", "2", "3"))
4882
4883 # Unit tests for different values of metavar when nargs=A...
4884
4885 def test_nargs_parser_metavar_string(self):
4886 self.do_test_no_exception(nargs="A...", metavar="1")
4887
4888 def test_nargs_parser_metavar_length0(self):
4889 self.do_test_exception(nargs="A...", metavar=tuple())
4890
4891 def test_nargs_parser_metavar_length1(self):
4892 self.do_test_no_exception(nargs="A...", metavar=("1"))
4893
4894 def test_nargs_parser_metavar_length2(self):
4895 self.do_test_exception(nargs="A...", metavar=("1", "2"))
4896
4897 def test_nargs_parser_metavar_length3(self):
4898 self.do_test_exception(nargs="A...", metavar=("1", "2", "3"))
4899
4900 # Unit tests for different values of metavar when nargs=1
4901
4902 def test_nargs_1_metavar_string(self):
4903 self.do_test_no_exception(nargs=1, metavar="1")
4904
4905 def test_nargs_1_metavar_length0(self):
4906 self.do_test_exception(nargs=1, metavar=tuple())
4907
4908 def test_nargs_1_metavar_length1(self):
4909 self.do_test_no_exception(nargs=1, metavar=("1"))
4910
4911 def test_nargs_1_metavar_length2(self):
4912 self.do_test_exception(nargs=1, metavar=("1", "2"))
4913
4914 def test_nargs_1_metavar_length3(self):
4915 self.do_test_exception(nargs=1, metavar=("1", "2", "3"))
4916
4917 # Unit tests for different values of metavar when nargs=2
4918
4919 def test_nargs_2_metavar_string(self):
4920 self.do_test_no_exception(nargs=2, metavar="1")
4921
4922 def test_nargs_2_metavar_length0(self):
4923 self.do_test_exception(nargs=2, metavar=tuple())
4924
4925 def test_nargs_2_metavar_length1(self):
4926 self.do_test_no_exception(nargs=2, metavar=("1"))
4927
4928 def test_nargs_2_metavar_length2(self):
4929 self.do_test_no_exception(nargs=2, metavar=("1", "2"))
4930
4931 def test_nargs_2_metavar_length3(self):
4932 self.do_test_exception(nargs=2, metavar=("1", "2", "3"))
4933
4934 # Unit tests for different values of metavar when nargs=3
4935
4936 def test_nargs_3_metavar_string(self):
4937 self.do_test_no_exception(nargs=3, metavar="1")
4938
4939 def test_nargs_3_metavar_length0(self):
4940 self.do_test_exception(nargs=3, metavar=tuple())
4941
4942 def test_nargs_3_metavar_length1(self):
4943 self.do_test_no_exception(nargs=3, metavar=("1"))
4944
4945 def test_nargs_3_metavar_length2(self):
4946 self.do_test_exception(nargs=3, metavar=("1", "2"))
4947
4948 def test_nargs_3_metavar_length3(self):
4949 self.do_test_no_exception(nargs=3, metavar=("1", "2", "3"))
4950
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004951# ============================
4952# from argparse import * tests
4953# ============================
4954
4955class TestImportStar(TestCase):
4956
4957 def test(self):
4958 for name in argparse.__all__:
4959 self.assertTrue(hasattr(argparse, name))
4960
Steven Bethard72c55382010-11-01 15:23:12 +00004961 def test_all_exports_everything_but_modules(self):
4962 items = [
4963 name
4964 for name, value in vars(argparse).items()
Éric Araujo12159152010-12-04 17:31:49 +00004965 if not (name.startswith("_") or name == 'ngettext')
Steven Bethard72c55382010-11-01 15:23:12 +00004966 if not inspect.ismodule(value)
4967 ]
4968 self.assertEqual(sorted(items), sorted(argparse.__all__))
4969
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004970def test_main():
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02004971 support.run_unittest(__name__)
Benjamin Peterson4fd181c2010-03-02 23:46:42 +00004972 # Remove global references to avoid looking like we have refleaks.
4973 RFile.seen = {}
4974 WFile.seen = set()
4975
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004976
4977
4978if __name__ == '__main__':
4979 test_main()