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