blob: 5d213c42f417ba339725b7fe3eb2877c330eed6a [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
Victor Stinnera04b39b2011-11-20 23:09:09 +01001505@unittest.skipIf(hasattr(os, 'geteuid') and os.geteuid() == 0,
1506 "non-root user required")
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001507class TestFileTypeW(TempDirMixin, ParserTestCase):
1508 """Test the FileType option/argument type for writing files"""
1509
Steven Bethardb0270112011-01-24 21:02:50 +00001510 def setUp(self):
1511 super(TestFileTypeW, self).setUp()
1512 self.create_readonly_file('readonly')
1513
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001514 argument_signatures = [
1515 Sig('-x', type=argparse.FileType('w')),
1516 Sig('spam', type=argparse.FileType('w')),
1517 ]
Steven Bethardb0270112011-01-24 21:02:50 +00001518 failures = ['-x', '', 'readonly']
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001519 successes = [
1520 ('foo', NS(x=None, spam=WFile('foo'))),
1521 ('-x foo bar', NS(x=WFile('foo'), spam=WFile('bar'))),
1522 ('bar -x foo', NS(x=WFile('foo'), spam=WFile('bar'))),
1523 ('-x - -', NS(x=sys.stdout, spam=sys.stdout)),
1524 ]
1525
1526
1527class TestFileTypeWB(TempDirMixin, ParserTestCase):
1528
1529 argument_signatures = [
1530 Sig('-x', type=argparse.FileType('wb')),
1531 Sig('spam', type=argparse.FileType('wb')),
1532 ]
1533 failures = ['-x', '']
1534 successes = [
1535 ('foo', NS(x=None, spam=WFile('foo'))),
1536 ('-x foo bar', NS(x=WFile('foo'), spam=WFile('bar'))),
1537 ('bar -x foo', NS(x=WFile('foo'), spam=WFile('bar'))),
1538 ('-x - -', NS(x=sys.stdout, spam=sys.stdout)),
1539 ]
1540
1541
1542class TestTypeCallable(ParserTestCase):
1543 """Test some callables as option/argument types"""
1544
1545 argument_signatures = [
1546 Sig('--eggs', type=complex),
1547 Sig('spam', type=float),
1548 ]
1549 failures = ['a', '42j', '--eggs a', '--eggs 2i']
1550 successes = [
1551 ('--eggs=42 42', NS(eggs=42, spam=42.0)),
1552 ('--eggs 2j -- -1.5', NS(eggs=2j, spam=-1.5)),
1553 ('1024.675', NS(eggs=None, spam=1024.675)),
1554 ]
1555
1556
1557class TestTypeUserDefined(ParserTestCase):
1558 """Test a user-defined option/argument type"""
1559
1560 class MyType(TestCase):
1561
1562 def __init__(self, value):
1563 self.value = value
1564
1565 def __eq__(self, other):
1566 return (type(self), self.value) == (type(other), other.value)
1567
1568 argument_signatures = [
1569 Sig('-x', type=MyType),
1570 Sig('spam', type=MyType),
1571 ]
1572 failures = []
1573 successes = [
1574 ('a -x b', NS(x=MyType('b'), spam=MyType('a'))),
1575 ('-xf g', NS(x=MyType('f'), spam=MyType('g'))),
1576 ]
1577
1578
1579class TestTypeClassicClass(ParserTestCase):
1580 """Test a classic class type"""
1581
1582 class C:
1583
1584 def __init__(self, value):
1585 self.value = value
1586
1587 def __eq__(self, other):
1588 return (type(self), self.value) == (type(other), other.value)
1589
1590 argument_signatures = [
1591 Sig('-x', type=C),
1592 Sig('spam', type=C),
1593 ]
1594 failures = []
1595 successes = [
1596 ('a -x b', NS(x=C('b'), spam=C('a'))),
1597 ('-xf g', NS(x=C('f'), spam=C('g'))),
1598 ]
1599
1600
1601class TestTypeRegistration(TestCase):
1602 """Test a user-defined type by registering it"""
1603
1604 def test(self):
1605
1606 def get_my_type(string):
1607 return 'my_type{%s}' % string
1608
1609 parser = argparse.ArgumentParser()
1610 parser.register('type', 'my_type', get_my_type)
1611 parser.add_argument('-x', type='my_type')
1612 parser.add_argument('y', type='my_type')
1613
1614 self.assertEqual(parser.parse_args('1'.split()),
1615 NS(x=None, y='my_type{1}'))
1616 self.assertEqual(parser.parse_args('-x 1 42'.split()),
1617 NS(x='my_type{1}', y='my_type{42}'))
1618
1619
1620# ============
1621# Action tests
1622# ============
1623
1624class TestActionUserDefined(ParserTestCase):
1625 """Test a user-defined option/argument action"""
1626
1627 class OptionalAction(argparse.Action):
1628
1629 def __call__(self, parser, namespace, value, option_string=None):
1630 try:
1631 # check destination and option string
1632 assert self.dest == 'spam', 'dest: %s' % self.dest
1633 assert option_string == '-s', 'flag: %s' % option_string
1634 # when option is before argument, badger=2, and when
1635 # option is after argument, badger=<whatever was set>
1636 expected_ns = NS(spam=0.25)
1637 if value in [0.125, 0.625]:
1638 expected_ns.badger = 2
1639 elif value in [2.0]:
1640 expected_ns.badger = 84
1641 else:
1642 raise AssertionError('value: %s' % value)
1643 assert expected_ns == namespace, ('expected %s, got %s' %
1644 (expected_ns, namespace))
1645 except AssertionError:
1646 e = sys.exc_info()[1]
1647 raise ArgumentParserError('opt_action failed: %s' % e)
1648 setattr(namespace, 'spam', value)
1649
1650 class PositionalAction(argparse.Action):
1651
1652 def __call__(self, parser, namespace, value, option_string=None):
1653 try:
1654 assert option_string is None, ('option_string: %s' %
1655 option_string)
1656 # check destination
1657 assert self.dest == 'badger', 'dest: %s' % self.dest
1658 # when argument is before option, spam=0.25, and when
1659 # option is after argument, spam=<whatever was set>
1660 expected_ns = NS(badger=2)
1661 if value in [42, 84]:
1662 expected_ns.spam = 0.25
1663 elif value in [1]:
1664 expected_ns.spam = 0.625
1665 elif value in [2]:
1666 expected_ns.spam = 0.125
1667 else:
1668 raise AssertionError('value: %s' % value)
1669 assert expected_ns == namespace, ('expected %s, got %s' %
1670 (expected_ns, namespace))
1671 except AssertionError:
1672 e = sys.exc_info()[1]
1673 raise ArgumentParserError('arg_action failed: %s' % e)
1674 setattr(namespace, 'badger', value)
1675
1676 argument_signatures = [
1677 Sig('-s', dest='spam', action=OptionalAction,
1678 type=float, default=0.25),
1679 Sig('badger', action=PositionalAction,
1680 type=int, nargs='?', default=2),
1681 ]
1682 failures = []
1683 successes = [
1684 ('-s0.125', NS(spam=0.125, badger=2)),
1685 ('42', NS(spam=0.25, badger=42)),
1686 ('-s 0.625 1', NS(spam=0.625, badger=1)),
1687 ('84 -s2', NS(spam=2.0, badger=84)),
1688 ]
1689
1690
1691class TestActionRegistration(TestCase):
1692 """Test a user-defined action supplied by registering it"""
1693
1694 class MyAction(argparse.Action):
1695
1696 def __call__(self, parser, namespace, values, option_string=None):
1697 setattr(namespace, self.dest, 'foo[%s]' % values)
1698
1699 def test(self):
1700
1701 parser = argparse.ArgumentParser()
1702 parser.register('action', 'my_action', self.MyAction)
1703 parser.add_argument('badger', action='my_action')
1704
1705 self.assertEqual(parser.parse_args(['1']), NS(badger='foo[1]'))
1706 self.assertEqual(parser.parse_args(['42']), NS(badger='foo[42]'))
1707
1708
1709# ================
1710# Subparsers tests
1711# ================
1712
1713class TestAddSubparsers(TestCase):
1714 """Test the add_subparsers method"""
1715
1716 def assertArgumentParserError(self, *args, **kwargs):
1717 self.assertRaises(ArgumentParserError, *args, **kwargs)
1718
Steven Bethardfd311a72010-12-18 11:19:23 +00001719 def _get_parser(self, subparser_help=False, prefix_chars=None,
1720 aliases=False):
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001721 # create a parser with a subparsers argument
R. David Murray88c49fe2010-08-03 17:56:09 +00001722 if prefix_chars:
1723 parser = ErrorRaisingArgumentParser(
1724 prog='PROG', description='main description', prefix_chars=prefix_chars)
1725 parser.add_argument(
1726 prefix_chars[0] * 2 + 'foo', action='store_true', help='foo help')
1727 else:
1728 parser = ErrorRaisingArgumentParser(
1729 prog='PROG', description='main description')
1730 parser.add_argument(
1731 '--foo', action='store_true', help='foo help')
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001732 parser.add_argument(
1733 'bar', type=float, help='bar help')
1734
1735 # check that only one subparsers argument can be added
Steven Bethardfd311a72010-12-18 11:19:23 +00001736 subparsers_kwargs = {}
1737 if aliases:
1738 subparsers_kwargs['metavar'] = 'COMMAND'
1739 subparsers_kwargs['title'] = 'commands'
1740 else:
1741 subparsers_kwargs['help'] = 'command help'
1742 subparsers = parser.add_subparsers(**subparsers_kwargs)
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001743 self.assertArgumentParserError(parser.add_subparsers)
1744
1745 # add first sub-parser
1746 parser1_kwargs = dict(description='1 description')
1747 if subparser_help:
1748 parser1_kwargs['help'] = '1 help'
Steven Bethardfd311a72010-12-18 11:19:23 +00001749 if aliases:
1750 parser1_kwargs['aliases'] = ['1alias1', '1alias2']
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001751 parser1 = subparsers.add_parser('1', **parser1_kwargs)
1752 parser1.add_argument('-w', type=int, help='w help')
1753 parser1.add_argument('x', choices='abc', help='x help')
1754
1755 # add second sub-parser
1756 parser2_kwargs = dict(description='2 description')
1757 if subparser_help:
1758 parser2_kwargs['help'] = '2 help'
1759 parser2 = subparsers.add_parser('2', **parser2_kwargs)
1760 parser2.add_argument('-y', choices='123', help='y help')
1761 parser2.add_argument('z', type=complex, nargs='*', help='z help')
1762
1763 # return the main parser
1764 return parser
1765
1766 def setUp(self):
Steven Bethard1f1c2472010-11-01 13:56:09 +00001767 super().setUp()
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001768 self.parser = self._get_parser()
1769 self.command_help_parser = self._get_parser(subparser_help=True)
1770
1771 def test_parse_args_failures(self):
1772 # check some failure cases:
1773 for args_str in ['', 'a', 'a a', '0.5 a', '0.5 1',
1774 '0.5 1 -y', '0.5 2 -w']:
1775 args = args_str.split()
1776 self.assertArgumentParserError(self.parser.parse_args, args)
1777
1778 def test_parse_args(self):
1779 # check some non-failure cases:
1780 self.assertEqual(
1781 self.parser.parse_args('0.5 1 b -w 7'.split()),
1782 NS(foo=False, bar=0.5, w=7, x='b'),
1783 )
1784 self.assertEqual(
1785 self.parser.parse_args('0.25 --foo 2 -y 2 3j -- -1j'.split()),
1786 NS(foo=True, bar=0.25, y='2', z=[3j, -1j]),
1787 )
1788 self.assertEqual(
1789 self.parser.parse_args('--foo 0.125 1 c'.split()),
1790 NS(foo=True, bar=0.125, w=None, x='c'),
1791 )
1792
Steven Bethardfca2e8a2010-11-02 12:47:22 +00001793 def test_parse_known_args(self):
1794 self.assertEqual(
1795 self.parser.parse_known_args('0.5 1 b -w 7'.split()),
1796 (NS(foo=False, bar=0.5, w=7, x='b'), []),
1797 )
1798 self.assertEqual(
1799 self.parser.parse_known_args('0.5 -p 1 b -w 7'.split()),
1800 (NS(foo=False, bar=0.5, w=7, x='b'), ['-p']),
1801 )
1802 self.assertEqual(
1803 self.parser.parse_known_args('0.5 1 b -w 7 -p'.split()),
1804 (NS(foo=False, bar=0.5, w=7, x='b'), ['-p']),
1805 )
1806 self.assertEqual(
1807 self.parser.parse_known_args('0.5 1 b -q -rs -w 7'.split()),
1808 (NS(foo=False, bar=0.5, w=7, x='b'), ['-q', '-rs']),
1809 )
1810 self.assertEqual(
1811 self.parser.parse_known_args('0.5 -W 1 b -X Y -w 7 Z'.split()),
1812 (NS(foo=False, bar=0.5, w=7, x='b'), ['-W', '-X', 'Y', 'Z']),
1813 )
1814
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001815 def test_dest(self):
1816 parser = ErrorRaisingArgumentParser()
1817 parser.add_argument('--foo', action='store_true')
1818 subparsers = parser.add_subparsers(dest='bar')
1819 parser1 = subparsers.add_parser('1')
1820 parser1.add_argument('baz')
1821 self.assertEqual(NS(foo=False, bar='1', baz='2'),
1822 parser.parse_args('1 2'.split()))
1823
1824 def test_help(self):
1825 self.assertEqual(self.parser.format_usage(),
1826 'usage: PROG [-h] [--foo] bar {1,2} ...\n')
1827 self.assertEqual(self.parser.format_help(), textwrap.dedent('''\
1828 usage: PROG [-h] [--foo] bar {1,2} ...
1829
1830 main description
1831
1832 positional arguments:
1833 bar bar help
1834 {1,2} command help
1835
1836 optional arguments:
1837 -h, --help show this help message and exit
1838 --foo foo help
1839 '''))
1840
R. David Murray88c49fe2010-08-03 17:56:09 +00001841 def test_help_extra_prefix_chars(self):
1842 # Make sure - is still used for help if it is a non-first prefix char
1843 parser = self._get_parser(prefix_chars='+:-')
1844 self.assertEqual(parser.format_usage(),
1845 'usage: PROG [-h] [++foo] bar {1,2} ...\n')
1846 self.assertEqual(parser.format_help(), textwrap.dedent('''\
1847 usage: PROG [-h] [++foo] bar {1,2} ...
1848
1849 main description
1850
1851 positional arguments:
1852 bar bar help
1853 {1,2} command help
1854
1855 optional arguments:
1856 -h, --help show this help message and exit
1857 ++foo foo help
1858 '''))
1859
1860
1861 def test_help_alternate_prefix_chars(self):
1862 parser = self._get_parser(prefix_chars='+:/')
1863 self.assertEqual(parser.format_usage(),
1864 'usage: PROG [+h] [++foo] bar {1,2} ...\n')
1865 self.assertEqual(parser.format_help(), textwrap.dedent('''\
1866 usage: PROG [+h] [++foo] bar {1,2} ...
1867
1868 main description
1869
1870 positional arguments:
1871 bar bar help
1872 {1,2} command help
1873
1874 optional arguments:
1875 +h, ++help show this help message and exit
1876 ++foo foo help
1877 '''))
1878
Benjamin Peterson698a18a2010-03-02 22:34:37 +00001879 def test_parser_command_help(self):
1880 self.assertEqual(self.command_help_parser.format_usage(),
1881 'usage: PROG [-h] [--foo] bar {1,2} ...\n')
1882 self.assertEqual(self.command_help_parser.format_help(),
1883 textwrap.dedent('''\
1884 usage: PROG [-h] [--foo] bar {1,2} ...
1885
1886 main description
1887
1888 positional arguments:
1889 bar bar help
1890 {1,2} command help
1891 1 1 help
1892 2 2 help
1893
1894 optional arguments:
1895 -h, --help show this help message and exit
1896 --foo foo help
1897 '''))
1898
1899 def test_subparser_title_help(self):
1900 parser = ErrorRaisingArgumentParser(prog='PROG',
1901 description='main description')
1902 parser.add_argument('--foo', action='store_true', help='foo help')
1903 parser.add_argument('bar', help='bar help')
1904 subparsers = parser.add_subparsers(title='subcommands',
1905 description='command help',
1906 help='additional text')
1907 parser1 = subparsers.add_parser('1')
1908 parser2 = subparsers.add_parser('2')
1909 self.assertEqual(parser.format_usage(),
1910 'usage: PROG [-h] [--foo] bar {1,2} ...\n')
1911 self.assertEqual(parser.format_help(), textwrap.dedent('''\
1912 usage: PROG [-h] [--foo] bar {1,2} ...
1913
1914 main description
1915
1916 positional arguments:
1917 bar bar help
1918
1919 optional arguments:
1920 -h, --help show this help message and exit
1921 --foo foo help
1922
1923 subcommands:
1924 command help
1925
1926 {1,2} additional text
1927 '''))
1928
1929 def _test_subparser_help(self, args_str, expected_help):
1930 try:
1931 self.parser.parse_args(args_str.split())
1932 except ArgumentParserError:
1933 err = sys.exc_info()[1]
1934 if err.stdout != expected_help:
1935 print(repr(expected_help))
1936 print(repr(err.stdout))
1937 self.assertEqual(err.stdout, expected_help)
1938
1939 def test_subparser1_help(self):
1940 self._test_subparser_help('5.0 1 -h', textwrap.dedent('''\
1941 usage: PROG bar 1 [-h] [-w W] {a,b,c}
1942
1943 1 description
1944
1945 positional arguments:
1946 {a,b,c} x help
1947
1948 optional arguments:
1949 -h, --help show this help message and exit
1950 -w W w help
1951 '''))
1952
1953 def test_subparser2_help(self):
1954 self._test_subparser_help('5.0 2 -h', textwrap.dedent('''\
1955 usage: PROG bar 2 [-h] [-y {1,2,3}] [z [z ...]]
1956
1957 2 description
1958
1959 positional arguments:
1960 z z help
1961
1962 optional arguments:
1963 -h, --help show this help message and exit
1964 -y {1,2,3} y help
1965 '''))
1966
Steven Bethardfd311a72010-12-18 11:19:23 +00001967 def test_alias_invocation(self):
1968 parser = self._get_parser(aliases=True)
1969 self.assertEqual(
1970 parser.parse_known_args('0.5 1alias1 b'.split()),
1971 (NS(foo=False, bar=0.5, w=None, x='b'), []),
1972 )
1973 self.assertEqual(
1974 parser.parse_known_args('0.5 1alias2 b'.split()),
1975 (NS(foo=False, bar=0.5, w=None, x='b'), []),
1976 )
1977
1978 def test_error_alias_invocation(self):
1979 parser = self._get_parser(aliases=True)
1980 self.assertArgumentParserError(parser.parse_args,
1981 '0.5 1alias3 b'.split())
1982
1983 def test_alias_help(self):
1984 parser = self._get_parser(aliases=True, subparser_help=True)
1985 self.maxDiff = None
1986 self.assertEqual(parser.format_help(), textwrap.dedent("""\
1987 usage: PROG [-h] [--foo] bar COMMAND ...
1988
1989 main description
1990
1991 positional arguments:
1992 bar bar help
1993
1994 optional arguments:
1995 -h, --help show this help message and exit
1996 --foo foo help
1997
1998 commands:
1999 COMMAND
2000 1 (1alias1, 1alias2)
2001 1 help
2002 2 2 help
2003 """))
2004
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002005# ============
2006# Groups tests
2007# ============
2008
2009class TestPositionalsGroups(TestCase):
2010 """Tests that order of group positionals matches construction order"""
2011
2012 def test_nongroup_first(self):
2013 parser = ErrorRaisingArgumentParser()
2014 parser.add_argument('foo')
2015 group = parser.add_argument_group('g')
2016 group.add_argument('bar')
2017 parser.add_argument('baz')
2018 expected = NS(foo='1', bar='2', baz='3')
2019 result = parser.parse_args('1 2 3'.split())
2020 self.assertEqual(expected, result)
2021
2022 def test_group_first(self):
2023 parser = ErrorRaisingArgumentParser()
2024 group = parser.add_argument_group('xxx')
2025 group.add_argument('foo')
2026 parser.add_argument('bar')
2027 parser.add_argument('baz')
2028 expected = NS(foo='1', bar='2', baz='3')
2029 result = parser.parse_args('1 2 3'.split())
2030 self.assertEqual(expected, result)
2031
2032 def test_interleaved_groups(self):
2033 parser = ErrorRaisingArgumentParser()
2034 group = parser.add_argument_group('xxx')
2035 parser.add_argument('foo')
2036 group.add_argument('bar')
2037 parser.add_argument('baz')
2038 group = parser.add_argument_group('yyy')
2039 group.add_argument('frell')
2040 expected = NS(foo='1', bar='2', baz='3', frell='4')
2041 result = parser.parse_args('1 2 3 4'.split())
2042 self.assertEqual(expected, result)
2043
2044# ===================
2045# Parent parser tests
2046# ===================
2047
2048class TestParentParsers(TestCase):
2049 """Tests that parsers can be created with parent parsers"""
2050
2051 def assertArgumentParserError(self, *args, **kwargs):
2052 self.assertRaises(ArgumentParserError, *args, **kwargs)
2053
2054 def setUp(self):
Steven Bethard1f1c2472010-11-01 13:56:09 +00002055 super().setUp()
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002056 self.wxyz_parent = ErrorRaisingArgumentParser(add_help=False)
2057 self.wxyz_parent.add_argument('--w')
2058 x_group = self.wxyz_parent.add_argument_group('x')
2059 x_group.add_argument('-y')
2060 self.wxyz_parent.add_argument('z')
2061
2062 self.abcd_parent = ErrorRaisingArgumentParser(add_help=False)
2063 self.abcd_parent.add_argument('a')
2064 self.abcd_parent.add_argument('-b')
2065 c_group = self.abcd_parent.add_argument_group('c')
2066 c_group.add_argument('--d')
2067
2068 self.w_parent = ErrorRaisingArgumentParser(add_help=False)
2069 self.w_parent.add_argument('--w')
2070
2071 self.z_parent = ErrorRaisingArgumentParser(add_help=False)
2072 self.z_parent.add_argument('z')
2073
2074 # parents with mutually exclusive groups
2075 self.ab_mutex_parent = ErrorRaisingArgumentParser(add_help=False)
2076 group = self.ab_mutex_parent.add_mutually_exclusive_group()
2077 group.add_argument('-a', action='store_true')
2078 group.add_argument('-b', action='store_true')
2079
2080 self.main_program = os.path.basename(sys.argv[0])
2081
2082 def test_single_parent(self):
2083 parser = ErrorRaisingArgumentParser(parents=[self.wxyz_parent])
2084 self.assertEqual(parser.parse_args('-y 1 2 --w 3'.split()),
2085 NS(w='3', y='1', z='2'))
2086
2087 def test_single_parent_mutex(self):
2088 self._test_mutex_ab(self.ab_mutex_parent.parse_args)
2089 parser = ErrorRaisingArgumentParser(parents=[self.ab_mutex_parent])
2090 self._test_mutex_ab(parser.parse_args)
2091
2092 def test_single_granparent_mutex(self):
2093 parents = [self.ab_mutex_parent]
2094 parser = ErrorRaisingArgumentParser(add_help=False, parents=parents)
2095 parser = ErrorRaisingArgumentParser(parents=[parser])
2096 self._test_mutex_ab(parser.parse_args)
2097
2098 def _test_mutex_ab(self, parse_args):
2099 self.assertEqual(parse_args([]), NS(a=False, b=False))
2100 self.assertEqual(parse_args(['-a']), NS(a=True, b=False))
2101 self.assertEqual(parse_args(['-b']), NS(a=False, b=True))
2102 self.assertArgumentParserError(parse_args, ['-a', '-b'])
2103 self.assertArgumentParserError(parse_args, ['-b', '-a'])
2104 self.assertArgumentParserError(parse_args, ['-c'])
2105 self.assertArgumentParserError(parse_args, ['-a', '-c'])
2106 self.assertArgumentParserError(parse_args, ['-b', '-c'])
2107
2108 def test_multiple_parents(self):
2109 parents = [self.abcd_parent, self.wxyz_parent]
2110 parser = ErrorRaisingArgumentParser(parents=parents)
2111 self.assertEqual(parser.parse_args('--d 1 --w 2 3 4'.split()),
2112 NS(a='3', b=None, d='1', w='2', y=None, z='4'))
2113
2114 def test_multiple_parents_mutex(self):
2115 parents = [self.ab_mutex_parent, self.wxyz_parent]
2116 parser = ErrorRaisingArgumentParser(parents=parents)
2117 self.assertEqual(parser.parse_args('-a --w 2 3'.split()),
2118 NS(a=True, b=False, w='2', y=None, z='3'))
2119 self.assertArgumentParserError(
2120 parser.parse_args, '-a --w 2 3 -b'.split())
2121 self.assertArgumentParserError(
2122 parser.parse_args, '-a -b --w 2 3'.split())
2123
2124 def test_conflicting_parents(self):
2125 self.assertRaises(
2126 argparse.ArgumentError,
2127 argparse.ArgumentParser,
2128 parents=[self.w_parent, self.wxyz_parent])
2129
2130 def test_conflicting_parents_mutex(self):
2131 self.assertRaises(
2132 argparse.ArgumentError,
2133 argparse.ArgumentParser,
2134 parents=[self.abcd_parent, self.ab_mutex_parent])
2135
2136 def test_same_argument_name_parents(self):
2137 parents = [self.wxyz_parent, self.z_parent]
2138 parser = ErrorRaisingArgumentParser(parents=parents)
2139 self.assertEqual(parser.parse_args('1 2'.split()),
2140 NS(w=None, y=None, z='2'))
2141
2142 def test_subparser_parents(self):
2143 parser = ErrorRaisingArgumentParser()
2144 subparsers = parser.add_subparsers()
2145 abcde_parser = subparsers.add_parser('bar', parents=[self.abcd_parent])
2146 abcde_parser.add_argument('e')
2147 self.assertEqual(parser.parse_args('bar -b 1 --d 2 3 4'.split()),
2148 NS(a='3', b='1', d='2', e='4'))
2149
2150 def test_subparser_parents_mutex(self):
2151 parser = ErrorRaisingArgumentParser()
2152 subparsers = parser.add_subparsers()
2153 parents = [self.ab_mutex_parent]
2154 abc_parser = subparsers.add_parser('foo', parents=parents)
2155 c_group = abc_parser.add_argument_group('c_group')
2156 c_group.add_argument('c')
2157 parents = [self.wxyz_parent, self.ab_mutex_parent]
2158 wxyzabe_parser = subparsers.add_parser('bar', parents=parents)
2159 wxyzabe_parser.add_argument('e')
2160 self.assertEqual(parser.parse_args('foo -a 4'.split()),
2161 NS(a=True, b=False, c='4'))
2162 self.assertEqual(parser.parse_args('bar -b --w 2 3 4'.split()),
2163 NS(a=False, b=True, w='2', y=None, z='3', e='4'))
2164 self.assertArgumentParserError(
2165 parser.parse_args, 'foo -a -b 4'.split())
2166 self.assertArgumentParserError(
2167 parser.parse_args, 'bar -b -a 4'.split())
2168
2169 def test_parent_help(self):
2170 parents = [self.abcd_parent, self.wxyz_parent]
2171 parser = ErrorRaisingArgumentParser(parents=parents)
2172 parser_help = parser.format_help()
2173 self.assertEqual(parser_help, textwrap.dedent('''\
2174 usage: {} [-h] [-b B] [--d D] [--w W] [-y Y] a z
2175
2176 positional arguments:
2177 a
2178 z
2179
2180 optional arguments:
2181 -h, --help show this help message and exit
2182 -b B
2183 --w W
2184
2185 c:
2186 --d D
2187
2188 x:
2189 -y Y
2190 '''.format(self.main_program)))
2191
2192 def test_groups_parents(self):
2193 parent = ErrorRaisingArgumentParser(add_help=False)
2194 g = parent.add_argument_group(title='g', description='gd')
2195 g.add_argument('-w')
2196 g.add_argument('-x')
2197 m = parent.add_mutually_exclusive_group()
2198 m.add_argument('-y')
2199 m.add_argument('-z')
2200 parser = ErrorRaisingArgumentParser(parents=[parent])
2201
2202 self.assertRaises(ArgumentParserError, parser.parse_args,
2203 ['-y', 'Y', '-z', 'Z'])
2204
2205 parser_help = parser.format_help()
2206 self.assertEqual(parser_help, textwrap.dedent('''\
2207 usage: {} [-h] [-w W] [-x X] [-y Y | -z Z]
2208
2209 optional arguments:
2210 -h, --help show this help message and exit
2211 -y Y
2212 -z Z
2213
2214 g:
2215 gd
2216
2217 -w W
2218 -x X
2219 '''.format(self.main_program)))
2220
2221# ==============================
2222# Mutually exclusive group tests
2223# ==============================
2224
2225class TestMutuallyExclusiveGroupErrors(TestCase):
2226
2227 def test_invalid_add_argument_group(self):
2228 parser = ErrorRaisingArgumentParser()
2229 raises = self.assertRaises
2230 raises(TypeError, parser.add_mutually_exclusive_group, title='foo')
2231
2232 def test_invalid_add_argument(self):
2233 parser = ErrorRaisingArgumentParser()
2234 group = parser.add_mutually_exclusive_group()
2235 add_argument = group.add_argument
2236 raises = self.assertRaises
2237 raises(ValueError, add_argument, '--foo', required=True)
2238 raises(ValueError, add_argument, 'bar')
2239 raises(ValueError, add_argument, 'bar', nargs='+')
2240 raises(ValueError, add_argument, 'bar', nargs=1)
2241 raises(ValueError, add_argument, 'bar', nargs=argparse.PARSER)
2242
Steven Bethard49998ee2010-11-01 16:29:26 +00002243 def test_help(self):
2244 parser = ErrorRaisingArgumentParser(prog='PROG')
2245 group1 = parser.add_mutually_exclusive_group()
2246 group1.add_argument('--foo', action='store_true')
2247 group1.add_argument('--bar', action='store_false')
2248 group2 = parser.add_mutually_exclusive_group()
2249 group2.add_argument('--soup', action='store_true')
2250 group2.add_argument('--nuts', action='store_false')
2251 expected = '''\
2252 usage: PROG [-h] [--foo | --bar] [--soup | --nuts]
2253
2254 optional arguments:
2255 -h, --help show this help message and exit
2256 --foo
2257 --bar
2258 --soup
2259 --nuts
2260 '''
2261 self.assertEqual(parser.format_help(), textwrap.dedent(expected))
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002262
2263class MEMixin(object):
2264
2265 def test_failures_when_not_required(self):
2266 parse_args = self.get_parser(required=False).parse_args
2267 error = ArgumentParserError
2268 for args_string in self.failures:
2269 self.assertRaises(error, parse_args, args_string.split())
2270
2271 def test_failures_when_required(self):
2272 parse_args = self.get_parser(required=True).parse_args
2273 error = ArgumentParserError
2274 for args_string in self.failures + ['']:
2275 self.assertRaises(error, parse_args, args_string.split())
2276
2277 def test_successes_when_not_required(self):
2278 parse_args = self.get_parser(required=False).parse_args
2279 successes = self.successes + self.successes_when_not_required
2280 for args_string, expected_ns in successes:
2281 actual_ns = parse_args(args_string.split())
2282 self.assertEqual(actual_ns, expected_ns)
2283
2284 def test_successes_when_required(self):
2285 parse_args = self.get_parser(required=True).parse_args
2286 for args_string, expected_ns in self.successes:
2287 actual_ns = parse_args(args_string.split())
2288 self.assertEqual(actual_ns, expected_ns)
2289
2290 def test_usage_when_not_required(self):
2291 format_usage = self.get_parser(required=False).format_usage
2292 expected_usage = self.usage_when_not_required
2293 self.assertEqual(format_usage(), textwrap.dedent(expected_usage))
2294
2295 def test_usage_when_required(self):
2296 format_usage = self.get_parser(required=True).format_usage
2297 expected_usage = self.usage_when_required
2298 self.assertEqual(format_usage(), textwrap.dedent(expected_usage))
2299
2300 def test_help_when_not_required(self):
2301 format_help = self.get_parser(required=False).format_help
2302 help = self.usage_when_not_required + self.help
2303 self.assertEqual(format_help(), textwrap.dedent(help))
2304
2305 def test_help_when_required(self):
2306 format_help = self.get_parser(required=True).format_help
2307 help = self.usage_when_required + self.help
2308 self.assertEqual(format_help(), textwrap.dedent(help))
2309
2310
2311class TestMutuallyExclusiveSimple(MEMixin, TestCase):
2312
2313 def get_parser(self, required=None):
2314 parser = ErrorRaisingArgumentParser(prog='PROG')
2315 group = parser.add_mutually_exclusive_group(required=required)
2316 group.add_argument('--bar', help='bar help')
2317 group.add_argument('--baz', nargs='?', const='Z', help='baz help')
2318 return parser
2319
2320 failures = ['--bar X --baz Y', '--bar X --baz']
2321 successes = [
2322 ('--bar X', NS(bar='X', baz=None)),
2323 ('--bar X --bar Z', NS(bar='Z', baz=None)),
2324 ('--baz Y', NS(bar=None, baz='Y')),
2325 ('--baz', NS(bar=None, baz='Z')),
2326 ]
2327 successes_when_not_required = [
2328 ('', NS(bar=None, baz=None)),
2329 ]
2330
2331 usage_when_not_required = '''\
2332 usage: PROG [-h] [--bar BAR | --baz [BAZ]]
2333 '''
2334 usage_when_required = '''\
2335 usage: PROG [-h] (--bar BAR | --baz [BAZ])
2336 '''
2337 help = '''\
2338
2339 optional arguments:
2340 -h, --help show this help message and exit
2341 --bar BAR bar help
2342 --baz [BAZ] baz help
2343 '''
2344
2345
2346class TestMutuallyExclusiveLong(MEMixin, TestCase):
2347
2348 def get_parser(self, required=None):
2349 parser = ErrorRaisingArgumentParser(prog='PROG')
2350 parser.add_argument('--abcde', help='abcde help')
2351 parser.add_argument('--fghij', help='fghij help')
2352 group = parser.add_mutually_exclusive_group(required=required)
2353 group.add_argument('--klmno', help='klmno help')
2354 group.add_argument('--pqrst', help='pqrst help')
2355 return parser
2356
2357 failures = ['--klmno X --pqrst Y']
2358 successes = [
2359 ('--klmno X', NS(abcde=None, fghij=None, klmno='X', pqrst=None)),
2360 ('--abcde Y --klmno X',
2361 NS(abcde='Y', fghij=None, klmno='X', pqrst=None)),
2362 ('--pqrst X', NS(abcde=None, fghij=None, klmno=None, pqrst='X')),
2363 ('--pqrst X --fghij Y',
2364 NS(abcde=None, fghij='Y', klmno=None, pqrst='X')),
2365 ]
2366 successes_when_not_required = [
2367 ('', NS(abcde=None, fghij=None, klmno=None, pqrst=None)),
2368 ]
2369
2370 usage_when_not_required = '''\
2371 usage: PROG [-h] [--abcde ABCDE] [--fghij FGHIJ]
2372 [--klmno KLMNO | --pqrst PQRST]
2373 '''
2374 usage_when_required = '''\
2375 usage: PROG [-h] [--abcde ABCDE] [--fghij FGHIJ]
2376 (--klmno KLMNO | --pqrst PQRST)
2377 '''
2378 help = '''\
2379
2380 optional arguments:
2381 -h, --help show this help message and exit
2382 --abcde ABCDE abcde help
2383 --fghij FGHIJ fghij help
2384 --klmno KLMNO klmno help
2385 --pqrst PQRST pqrst help
2386 '''
2387
2388
2389class TestMutuallyExclusiveFirstSuppressed(MEMixin, TestCase):
2390
2391 def get_parser(self, required):
2392 parser = ErrorRaisingArgumentParser(prog='PROG')
2393 group = parser.add_mutually_exclusive_group(required=required)
2394 group.add_argument('-x', help=argparse.SUPPRESS)
2395 group.add_argument('-y', action='store_false', help='y help')
2396 return parser
2397
2398 failures = ['-x X -y']
2399 successes = [
2400 ('-x X', NS(x='X', y=True)),
2401 ('-x X -x Y', NS(x='Y', y=True)),
2402 ('-y', NS(x=None, y=False)),
2403 ]
2404 successes_when_not_required = [
2405 ('', NS(x=None, y=True)),
2406 ]
2407
2408 usage_when_not_required = '''\
2409 usage: PROG [-h] [-y]
2410 '''
2411 usage_when_required = '''\
2412 usage: PROG [-h] -y
2413 '''
2414 help = '''\
2415
2416 optional arguments:
2417 -h, --help show this help message and exit
2418 -y y help
2419 '''
2420
2421
2422class TestMutuallyExclusiveManySuppressed(MEMixin, TestCase):
2423
2424 def get_parser(self, required):
2425 parser = ErrorRaisingArgumentParser(prog='PROG')
2426 group = parser.add_mutually_exclusive_group(required=required)
2427 add = group.add_argument
2428 add('--spam', action='store_true', help=argparse.SUPPRESS)
2429 add('--badger', action='store_false', help=argparse.SUPPRESS)
2430 add('--bladder', help=argparse.SUPPRESS)
2431 return parser
2432
2433 failures = [
2434 '--spam --badger',
2435 '--badger --bladder B',
2436 '--bladder B --spam',
2437 ]
2438 successes = [
2439 ('--spam', NS(spam=True, badger=True, bladder=None)),
2440 ('--badger', NS(spam=False, badger=False, bladder=None)),
2441 ('--bladder B', NS(spam=False, badger=True, bladder='B')),
2442 ('--spam --spam', NS(spam=True, badger=True, bladder=None)),
2443 ]
2444 successes_when_not_required = [
2445 ('', NS(spam=False, badger=True, bladder=None)),
2446 ]
2447
2448 usage_when_required = usage_when_not_required = '''\
2449 usage: PROG [-h]
2450 '''
2451 help = '''\
2452
2453 optional arguments:
2454 -h, --help show this help message and exit
2455 '''
2456
2457
2458class TestMutuallyExclusiveOptionalAndPositional(MEMixin, TestCase):
2459
2460 def get_parser(self, required):
2461 parser = ErrorRaisingArgumentParser(prog='PROG')
2462 group = parser.add_mutually_exclusive_group(required=required)
2463 group.add_argument('--foo', action='store_true', help='FOO')
2464 group.add_argument('--spam', help='SPAM')
2465 group.add_argument('badger', nargs='*', default='X', help='BADGER')
2466 return parser
2467
2468 failures = [
2469 '--foo --spam S',
2470 '--spam S X',
2471 'X --foo',
2472 'X Y Z --spam S',
2473 '--foo X Y',
2474 ]
2475 successes = [
2476 ('--foo', NS(foo=True, spam=None, badger='X')),
2477 ('--spam S', NS(foo=False, spam='S', badger='X')),
2478 ('X', NS(foo=False, spam=None, badger=['X'])),
2479 ('X Y Z', NS(foo=False, spam=None, badger=['X', 'Y', 'Z'])),
2480 ]
2481 successes_when_not_required = [
2482 ('', NS(foo=False, spam=None, badger='X')),
2483 ]
2484
2485 usage_when_not_required = '''\
2486 usage: PROG [-h] [--foo | --spam SPAM | badger [badger ...]]
2487 '''
2488 usage_when_required = '''\
2489 usage: PROG [-h] (--foo | --spam SPAM | badger [badger ...])
2490 '''
2491 help = '''\
2492
2493 positional arguments:
2494 badger BADGER
2495
2496 optional arguments:
2497 -h, --help show this help message and exit
2498 --foo FOO
2499 --spam SPAM SPAM
2500 '''
2501
2502
2503class TestMutuallyExclusiveOptionalsMixed(MEMixin, TestCase):
2504
2505 def get_parser(self, required):
2506 parser = ErrorRaisingArgumentParser(prog='PROG')
2507 parser.add_argument('-x', action='store_true', help='x help')
2508 group = parser.add_mutually_exclusive_group(required=required)
2509 group.add_argument('-a', action='store_true', help='a help')
2510 group.add_argument('-b', action='store_true', help='b help')
2511 parser.add_argument('-y', action='store_true', help='y help')
2512 group.add_argument('-c', action='store_true', help='c help')
2513 return parser
2514
2515 failures = ['-a -b', '-b -c', '-a -c', '-a -b -c']
2516 successes = [
2517 ('-a', NS(a=True, b=False, c=False, x=False, y=False)),
2518 ('-b', NS(a=False, b=True, c=False, x=False, y=False)),
2519 ('-c', NS(a=False, b=False, c=True, x=False, y=False)),
2520 ('-a -x', NS(a=True, b=False, c=False, x=True, y=False)),
2521 ('-y -b', NS(a=False, b=True, c=False, x=False, y=True)),
2522 ('-x -y -c', NS(a=False, b=False, c=True, x=True, y=True)),
2523 ]
2524 successes_when_not_required = [
2525 ('', NS(a=False, b=False, c=False, x=False, y=False)),
2526 ('-x', NS(a=False, b=False, c=False, x=True, y=False)),
2527 ('-y', NS(a=False, b=False, c=False, x=False, y=True)),
2528 ]
2529
2530 usage_when_required = usage_when_not_required = '''\
2531 usage: PROG [-h] [-x] [-a] [-b] [-y] [-c]
2532 '''
2533 help = '''\
2534
2535 optional arguments:
2536 -h, --help show this help message and exit
2537 -x x help
2538 -a a help
2539 -b b help
2540 -y y help
2541 -c c help
2542 '''
2543
2544
Georg Brandl0f6b47a2011-01-30 12:19:35 +00002545class TestMutuallyExclusiveInGroup(MEMixin, TestCase):
2546
2547 def get_parser(self, required=None):
2548 parser = ErrorRaisingArgumentParser(prog='PROG')
2549 titled_group = parser.add_argument_group(
2550 title='Titled group', description='Group description')
2551 mutex_group = \
2552 titled_group.add_mutually_exclusive_group(required=required)
2553 mutex_group.add_argument('--bar', help='bar help')
2554 mutex_group.add_argument('--baz', help='baz help')
2555 return parser
2556
2557 failures = ['--bar X --baz Y', '--baz X --bar Y']
2558 successes = [
2559 ('--bar X', NS(bar='X', baz=None)),
2560 ('--baz Y', NS(bar=None, baz='Y')),
2561 ]
2562 successes_when_not_required = [
2563 ('', NS(bar=None, baz=None)),
2564 ]
2565
2566 usage_when_not_required = '''\
2567 usage: PROG [-h] [--bar BAR | --baz BAZ]
2568 '''
2569 usage_when_required = '''\
2570 usage: PROG [-h] (--bar BAR | --baz BAZ)
2571 '''
2572 help = '''\
2573
2574 optional arguments:
2575 -h, --help show this help message and exit
2576
2577 Titled group:
2578 Group description
2579
2580 --bar BAR bar help
2581 --baz BAZ baz help
2582 '''
2583
2584
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002585class TestMutuallyExclusiveOptionalsAndPositionalsMixed(MEMixin, TestCase):
2586
2587 def get_parser(self, required):
2588 parser = ErrorRaisingArgumentParser(prog='PROG')
2589 parser.add_argument('x', help='x help')
2590 parser.add_argument('-y', action='store_true', help='y help')
2591 group = parser.add_mutually_exclusive_group(required=required)
2592 group.add_argument('a', nargs='?', help='a help')
2593 group.add_argument('-b', action='store_true', help='b help')
2594 group.add_argument('-c', action='store_true', help='c help')
2595 return parser
2596
2597 failures = ['X A -b', '-b -c', '-c X A']
2598 successes = [
2599 ('X A', NS(a='A', b=False, c=False, x='X', y=False)),
2600 ('X -b', NS(a=None, b=True, c=False, x='X', y=False)),
2601 ('X -c', NS(a=None, b=False, c=True, x='X', y=False)),
2602 ('X A -y', NS(a='A', b=False, c=False, x='X', y=True)),
2603 ('X -y -b', NS(a=None, b=True, c=False, x='X', y=True)),
2604 ]
2605 successes_when_not_required = [
2606 ('X', NS(a=None, b=False, c=False, x='X', y=False)),
2607 ('X -y', NS(a=None, b=False, c=False, x='X', y=True)),
2608 ]
2609
2610 usage_when_required = usage_when_not_required = '''\
2611 usage: PROG [-h] [-y] [-b] [-c] x [a]
2612 '''
2613 help = '''\
2614
2615 positional arguments:
2616 x x help
2617 a a help
2618
2619 optional arguments:
2620 -h, --help show this help message and exit
2621 -y y help
2622 -b b help
2623 -c c help
2624 '''
2625
2626# =================================================
2627# Mutually exclusive group in parent parser tests
2628# =================================================
2629
2630class MEPBase(object):
2631
2632 def get_parser(self, required=None):
2633 parent = super(MEPBase, self).get_parser(required=required)
2634 parser = ErrorRaisingArgumentParser(
2635 prog=parent.prog, add_help=False, parents=[parent])
2636 return parser
2637
2638
2639class TestMutuallyExclusiveGroupErrorsParent(
2640 MEPBase, TestMutuallyExclusiveGroupErrors):
2641 pass
2642
2643
2644class TestMutuallyExclusiveSimpleParent(
2645 MEPBase, TestMutuallyExclusiveSimple):
2646 pass
2647
2648
2649class TestMutuallyExclusiveLongParent(
2650 MEPBase, TestMutuallyExclusiveLong):
2651 pass
2652
2653
2654class TestMutuallyExclusiveFirstSuppressedParent(
2655 MEPBase, TestMutuallyExclusiveFirstSuppressed):
2656 pass
2657
2658
2659class TestMutuallyExclusiveManySuppressedParent(
2660 MEPBase, TestMutuallyExclusiveManySuppressed):
2661 pass
2662
2663
2664class TestMutuallyExclusiveOptionalAndPositionalParent(
2665 MEPBase, TestMutuallyExclusiveOptionalAndPositional):
2666 pass
2667
2668
2669class TestMutuallyExclusiveOptionalsMixedParent(
2670 MEPBase, TestMutuallyExclusiveOptionalsMixed):
2671 pass
2672
2673
2674class TestMutuallyExclusiveOptionalsAndPositionalsMixedParent(
2675 MEPBase, TestMutuallyExclusiveOptionalsAndPositionalsMixed):
2676 pass
2677
2678# =================
2679# Set default tests
2680# =================
2681
2682class TestSetDefaults(TestCase):
2683
2684 def test_set_defaults_no_args(self):
2685 parser = ErrorRaisingArgumentParser()
2686 parser.set_defaults(x='foo')
2687 parser.set_defaults(y='bar', z=1)
2688 self.assertEqual(NS(x='foo', y='bar', z=1),
2689 parser.parse_args([]))
2690 self.assertEqual(NS(x='foo', y='bar', z=1),
2691 parser.parse_args([], NS()))
2692 self.assertEqual(NS(x='baz', y='bar', z=1),
2693 parser.parse_args([], NS(x='baz')))
2694 self.assertEqual(NS(x='baz', y='bar', z=2),
2695 parser.parse_args([], NS(x='baz', z=2)))
2696
2697 def test_set_defaults_with_args(self):
2698 parser = ErrorRaisingArgumentParser()
2699 parser.set_defaults(x='foo', y='bar')
2700 parser.add_argument('-x', default='xfoox')
2701 self.assertEqual(NS(x='xfoox', y='bar'),
2702 parser.parse_args([]))
2703 self.assertEqual(NS(x='xfoox', y='bar'),
2704 parser.parse_args([], NS()))
2705 self.assertEqual(NS(x='baz', y='bar'),
2706 parser.parse_args([], NS(x='baz')))
2707 self.assertEqual(NS(x='1', y='bar'),
2708 parser.parse_args('-x 1'.split()))
2709 self.assertEqual(NS(x='1', y='bar'),
2710 parser.parse_args('-x 1'.split(), NS()))
2711 self.assertEqual(NS(x='1', y='bar'),
2712 parser.parse_args('-x 1'.split(), NS(x='baz')))
2713
2714 def test_set_defaults_subparsers(self):
2715 parser = ErrorRaisingArgumentParser()
2716 parser.set_defaults(x='foo')
2717 subparsers = parser.add_subparsers()
2718 parser_a = subparsers.add_parser('a')
2719 parser_a.set_defaults(y='bar')
2720 self.assertEqual(NS(x='foo', y='bar'),
2721 parser.parse_args('a'.split()))
2722
2723 def test_set_defaults_parents(self):
2724 parent = ErrorRaisingArgumentParser(add_help=False)
2725 parent.set_defaults(x='foo')
2726 parser = ErrorRaisingArgumentParser(parents=[parent])
2727 self.assertEqual(NS(x='foo'), parser.parse_args([]))
2728
2729 def test_set_defaults_same_as_add_argument(self):
2730 parser = ErrorRaisingArgumentParser()
2731 parser.set_defaults(w='W', x='X', y='Y', z='Z')
2732 parser.add_argument('-w')
2733 parser.add_argument('-x', default='XX')
2734 parser.add_argument('y', nargs='?')
2735 parser.add_argument('z', nargs='?', default='ZZ')
2736
2737 # defaults set previously
2738 self.assertEqual(NS(w='W', x='XX', y='Y', z='ZZ'),
2739 parser.parse_args([]))
2740
2741 # reset defaults
2742 parser.set_defaults(w='WW', x='X', y='YY', z='Z')
2743 self.assertEqual(NS(w='WW', x='X', y='YY', z='Z'),
2744 parser.parse_args([]))
2745
2746 def test_set_defaults_same_as_add_argument_group(self):
2747 parser = ErrorRaisingArgumentParser()
2748 parser.set_defaults(w='W', x='X', y='Y', z='Z')
2749 group = parser.add_argument_group('foo')
2750 group.add_argument('-w')
2751 group.add_argument('-x', default='XX')
2752 group.add_argument('y', nargs='?')
2753 group.add_argument('z', nargs='?', default='ZZ')
2754
2755
2756 # defaults set previously
2757 self.assertEqual(NS(w='W', x='XX', y='Y', z='ZZ'),
2758 parser.parse_args([]))
2759
2760 # reset defaults
2761 parser.set_defaults(w='WW', x='X', y='YY', z='Z')
2762 self.assertEqual(NS(w='WW', x='X', y='YY', z='Z'),
2763 parser.parse_args([]))
2764
2765# =================
2766# Get default tests
2767# =================
2768
2769class TestGetDefault(TestCase):
2770
2771 def test_get_default(self):
2772 parser = ErrorRaisingArgumentParser()
2773 self.assertEqual(None, parser.get_default("foo"))
2774 self.assertEqual(None, parser.get_default("bar"))
2775
2776 parser.add_argument("--foo")
2777 self.assertEqual(None, parser.get_default("foo"))
2778 self.assertEqual(None, parser.get_default("bar"))
2779
2780 parser.add_argument("--bar", type=int, default=42)
2781 self.assertEqual(None, parser.get_default("foo"))
2782 self.assertEqual(42, parser.get_default("bar"))
2783
2784 parser.set_defaults(foo="badger")
2785 self.assertEqual("badger", parser.get_default("foo"))
2786 self.assertEqual(42, parser.get_default("bar"))
2787
2788# ==========================
2789# Namespace 'contains' tests
2790# ==========================
2791
2792class TestNamespaceContainsSimple(TestCase):
2793
2794 def test_empty(self):
2795 ns = argparse.Namespace()
Ezio Melottib3aedd42010-11-20 19:04:17 +00002796 self.assertEqual('' in ns, False)
2797 self.assertEqual('' not in ns, True)
2798 self.assertEqual('x' in ns, False)
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002799
2800 def test_non_empty(self):
2801 ns = argparse.Namespace(x=1, y=2)
Ezio Melottib3aedd42010-11-20 19:04:17 +00002802 self.assertEqual('x' in ns, True)
2803 self.assertEqual('x' not in ns, False)
2804 self.assertEqual('y' in ns, True)
2805 self.assertEqual('' in ns, False)
2806 self.assertEqual('xx' in ns, False)
2807 self.assertEqual('z' in ns, False)
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002808
2809# =====================
2810# Help formatting tests
2811# =====================
2812
2813class TestHelpFormattingMetaclass(type):
2814
2815 def __init__(cls, name, bases, bodydict):
2816 if name == 'HelpTestCase':
2817 return
2818
2819 class AddTests(object):
2820
2821 def __init__(self, test_class, func_suffix, std_name):
2822 self.func_suffix = func_suffix
2823 self.std_name = std_name
2824
2825 for test_func in [self.test_format,
2826 self.test_print,
2827 self.test_print_file]:
2828 test_name = '%s_%s' % (test_func.__name__, func_suffix)
2829
2830 def test_wrapper(self, test_func=test_func):
2831 test_func(self)
2832 try:
2833 test_wrapper.__name__ = test_name
2834 except TypeError:
2835 pass
2836 setattr(test_class, test_name, test_wrapper)
2837
2838 def _get_parser(self, tester):
2839 parser = argparse.ArgumentParser(
2840 *tester.parser_signature.args,
2841 **tester.parser_signature.kwargs)
Steven Bethard8a6a1982011-03-27 13:53:53 +02002842 for argument_sig in getattr(tester, 'argument_signatures', []):
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002843 parser.add_argument(*argument_sig.args,
2844 **argument_sig.kwargs)
Steven Bethard8a6a1982011-03-27 13:53:53 +02002845 group_sigs = getattr(tester, 'argument_group_signatures', [])
2846 for group_sig, argument_sigs in group_sigs:
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002847 group = parser.add_argument_group(*group_sig.args,
2848 **group_sig.kwargs)
2849 for argument_sig in argument_sigs:
2850 group.add_argument(*argument_sig.args,
2851 **argument_sig.kwargs)
Steven Bethard8a6a1982011-03-27 13:53:53 +02002852 subparsers_sigs = getattr(tester, 'subparsers_signatures', [])
2853 if subparsers_sigs:
2854 subparsers = parser.add_subparsers()
2855 for subparser_sig in subparsers_sigs:
2856 subparsers.add_parser(*subparser_sig.args,
2857 **subparser_sig.kwargs)
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002858 return parser
2859
2860 def _test(self, tester, parser_text):
2861 expected_text = getattr(tester, self.func_suffix)
2862 expected_text = textwrap.dedent(expected_text)
2863 if expected_text != parser_text:
2864 print(repr(expected_text))
2865 print(repr(parser_text))
2866 for char1, char2 in zip(expected_text, parser_text):
2867 if char1 != char2:
2868 print('first diff: %r %r' % (char1, char2))
2869 break
2870 tester.assertEqual(expected_text, parser_text)
2871
2872 def test_format(self, tester):
2873 parser = self._get_parser(tester)
2874 format = getattr(parser, 'format_%s' % self.func_suffix)
2875 self._test(tester, format())
2876
2877 def test_print(self, tester):
2878 parser = self._get_parser(tester)
2879 print_ = getattr(parser, 'print_%s' % self.func_suffix)
2880 old_stream = getattr(sys, self.std_name)
Benjamin Petersonb48af542010-04-11 20:43:16 +00002881 setattr(sys, self.std_name, StdIOBuffer())
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002882 try:
2883 print_()
2884 parser_text = getattr(sys, self.std_name).getvalue()
2885 finally:
2886 setattr(sys, self.std_name, old_stream)
2887 self._test(tester, parser_text)
2888
2889 def test_print_file(self, tester):
2890 parser = self._get_parser(tester)
2891 print_ = getattr(parser, 'print_%s' % self.func_suffix)
Benjamin Petersonb48af542010-04-11 20:43:16 +00002892 sfile = StdIOBuffer()
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002893 print_(sfile)
2894 parser_text = sfile.getvalue()
2895 self._test(tester, parser_text)
2896
2897 # add tests for {format,print}_{usage,help,version}
2898 for func_suffix, std_name in [('usage', 'stdout'),
2899 ('help', 'stdout'),
2900 ('version', 'stderr')]:
2901 AddTests(cls, func_suffix, std_name)
2902
2903bases = TestCase,
2904HelpTestCase = TestHelpFormattingMetaclass('HelpTestCase', bases, {})
2905
2906
2907class TestHelpBiggerOptionals(HelpTestCase):
2908 """Make sure that argument help aligns when options are longer"""
2909
2910 parser_signature = Sig(prog='PROG', description='DESCRIPTION',
2911 epilog='EPILOG', version='0.1')
2912 argument_signatures = [
2913 Sig('-x', action='store_true', help='X HELP'),
2914 Sig('--y', help='Y HELP'),
2915 Sig('foo', help='FOO HELP'),
2916 Sig('bar', help='BAR HELP'),
2917 ]
2918 argument_group_signatures = []
2919 usage = '''\
2920 usage: PROG [-h] [-v] [-x] [--y Y] foo bar
2921 '''
2922 help = usage + '''\
2923
2924 DESCRIPTION
2925
2926 positional arguments:
2927 foo FOO HELP
2928 bar BAR HELP
2929
2930 optional arguments:
2931 -h, --help show this help message and exit
2932 -v, --version show program's version number and exit
2933 -x X HELP
2934 --y Y Y HELP
2935
2936 EPILOG
2937 '''
2938 version = '''\
2939 0.1
2940 '''
2941
2942
2943class TestHelpBiggerOptionalGroups(HelpTestCase):
2944 """Make sure that argument help aligns when options are longer"""
2945
2946 parser_signature = Sig(prog='PROG', description='DESCRIPTION',
2947 epilog='EPILOG', version='0.1')
2948 argument_signatures = [
2949 Sig('-x', action='store_true', help='X HELP'),
2950 Sig('--y', help='Y HELP'),
2951 Sig('foo', help='FOO HELP'),
2952 Sig('bar', help='BAR HELP'),
2953 ]
2954 argument_group_signatures = [
2955 (Sig('GROUP TITLE', description='GROUP DESCRIPTION'), [
2956 Sig('baz', help='BAZ HELP'),
2957 Sig('-z', nargs='+', help='Z HELP')]),
2958 ]
2959 usage = '''\
2960 usage: PROG [-h] [-v] [-x] [--y Y] [-z Z [Z ...]] foo bar baz
2961 '''
2962 help = usage + '''\
2963
2964 DESCRIPTION
2965
2966 positional arguments:
2967 foo FOO HELP
2968 bar BAR HELP
2969
2970 optional arguments:
2971 -h, --help show this help message and exit
2972 -v, --version show program's version number and exit
2973 -x X HELP
2974 --y Y Y HELP
2975
2976 GROUP TITLE:
2977 GROUP DESCRIPTION
2978
2979 baz BAZ HELP
2980 -z Z [Z ...] Z HELP
2981
2982 EPILOG
2983 '''
2984 version = '''\
2985 0.1
2986 '''
2987
2988
2989class TestHelpBiggerPositionals(HelpTestCase):
2990 """Make sure that help aligns when arguments are longer"""
2991
2992 parser_signature = Sig(usage='USAGE', description='DESCRIPTION')
2993 argument_signatures = [
2994 Sig('-x', action='store_true', help='X HELP'),
2995 Sig('--y', help='Y HELP'),
2996 Sig('ekiekiekifekang', help='EKI HELP'),
2997 Sig('bar', help='BAR HELP'),
2998 ]
2999 argument_group_signatures = []
3000 usage = '''\
3001 usage: USAGE
3002 '''
3003 help = usage + '''\
3004
3005 DESCRIPTION
3006
3007 positional arguments:
3008 ekiekiekifekang EKI HELP
3009 bar BAR HELP
3010
3011 optional arguments:
3012 -h, --help show this help message and exit
3013 -x X HELP
3014 --y Y Y HELP
3015 '''
3016
3017 version = ''
3018
3019
3020class TestHelpReformatting(HelpTestCase):
3021 """Make sure that text after short names starts on the first line"""
3022
3023 parser_signature = Sig(
3024 prog='PROG',
3025 description=' oddly formatted\n'
3026 'description\n'
3027 '\n'
3028 'that is so long that it should go onto multiple '
3029 'lines when wrapped')
3030 argument_signatures = [
3031 Sig('-x', metavar='XX', help='oddly\n'
3032 ' formatted -x help'),
3033 Sig('y', metavar='yyy', help='normal y help'),
3034 ]
3035 argument_group_signatures = [
3036 (Sig('title', description='\n'
3037 ' oddly formatted group\n'
3038 '\n'
3039 'description'),
3040 [Sig('-a', action='store_true',
3041 help=' oddly \n'
3042 'formatted -a help \n'
3043 ' again, so long that it should be wrapped over '
3044 'multiple lines')]),
3045 ]
3046 usage = '''\
3047 usage: PROG [-h] [-x XX] [-a] yyy
3048 '''
3049 help = usage + '''\
3050
3051 oddly formatted description that is so long that it should go onto \
3052multiple
3053 lines when wrapped
3054
3055 positional arguments:
3056 yyy normal y help
3057
3058 optional arguments:
3059 -h, --help show this help message and exit
3060 -x XX oddly formatted -x help
3061
3062 title:
3063 oddly formatted group description
3064
3065 -a oddly formatted -a help again, so long that it should \
3066be wrapped
3067 over multiple lines
3068 '''
3069 version = ''
3070
3071
3072class TestHelpWrappingShortNames(HelpTestCase):
3073 """Make sure that text after short names starts on the first line"""
3074
3075 parser_signature = Sig(prog='PROG', description= 'D\nD' * 30)
3076 argument_signatures = [
3077 Sig('-x', metavar='XX', help='XHH HX' * 20),
3078 Sig('y', metavar='yyy', help='YH YH' * 20),
3079 ]
3080 argument_group_signatures = [
3081 (Sig('ALPHAS'), [
3082 Sig('-a', action='store_true', help='AHHH HHA' * 10)]),
3083 ]
3084 usage = '''\
3085 usage: PROG [-h] [-x XX] [-a] yyy
3086 '''
3087 help = usage + '''\
3088
3089 D DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD \
3090DD DD DD
3091 DD DD DD DD D
3092
3093 positional arguments:
3094 yyy YH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH \
3095YHYH YHYH
3096 YHYH YHYH YHYH YHYH YHYH YHYH YHYH YH
3097
3098 optional arguments:
3099 -h, --help show this help message and exit
3100 -x XX XHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH \
3101HXXHH HXXHH
3102 HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HX
3103
3104 ALPHAS:
3105 -a AHHH HHAAHHH HHAAHHH HHAAHHH HHAAHHH HHAAHHH HHAAHHH \
3106HHAAHHH
3107 HHAAHHH HHAAHHH HHA
3108 '''
3109 version = ''
3110
3111
3112class TestHelpWrappingLongNames(HelpTestCase):
3113 """Make sure that text after long names starts on the next line"""
3114
3115 parser_signature = Sig(usage='USAGE', description= 'D D' * 30,
3116 version='V V'*30)
3117 argument_signatures = [
3118 Sig('-x', metavar='X' * 25, help='XH XH' * 20),
3119 Sig('y', metavar='y' * 25, help='YH YH' * 20),
3120 ]
3121 argument_group_signatures = [
3122 (Sig('ALPHAS'), [
3123 Sig('-a', metavar='A' * 25, help='AH AH' * 20),
3124 Sig('z', metavar='z' * 25, help='ZH ZH' * 20)]),
3125 ]
3126 usage = '''\
3127 usage: USAGE
3128 '''
3129 help = usage + '''\
3130
3131 D DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD \
3132DD DD DD
3133 DD DD DD DD D
3134
3135 positional arguments:
3136 yyyyyyyyyyyyyyyyyyyyyyyyy
3137 YH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH \
3138YHYH YHYH
3139 YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YH
3140
3141 optional arguments:
3142 -h, --help show this help message and exit
3143 -v, --version show program's version number and exit
3144 -x XXXXXXXXXXXXXXXXXXXXXXXXX
3145 XH XHXH XHXH XHXH XHXH XHXH XHXH XHXH XHXH \
3146XHXH XHXH
3147 XHXH XHXH XHXH XHXH XHXH XHXH XHXH XHXH XHXH XH
3148
3149 ALPHAS:
3150 -a AAAAAAAAAAAAAAAAAAAAAAAAA
3151 AH AHAH AHAH AHAH AHAH AHAH AHAH AHAH AHAH \
3152AHAH AHAH
3153 AHAH AHAH AHAH AHAH AHAH AHAH AHAH AHAH AHAH AH
3154 zzzzzzzzzzzzzzzzzzzzzzzzz
3155 ZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH \
3156ZHZH ZHZH
3157 ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZH
3158 '''
3159 version = '''\
3160 V VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV \
3161VV VV VV
3162 VV VV VV VV V
3163 '''
3164
3165
3166class TestHelpUsage(HelpTestCase):
3167 """Test basic usage messages"""
3168
3169 parser_signature = Sig(prog='PROG')
3170 argument_signatures = [
3171 Sig('-w', nargs='+', help='w'),
3172 Sig('-x', nargs='*', help='x'),
3173 Sig('a', help='a'),
3174 Sig('b', help='b', nargs=2),
3175 Sig('c', help='c', nargs='?'),
3176 ]
3177 argument_group_signatures = [
3178 (Sig('group'), [
3179 Sig('-y', nargs='?', help='y'),
3180 Sig('-z', nargs=3, help='z'),
3181 Sig('d', help='d', nargs='*'),
3182 Sig('e', help='e', nargs='+'),
3183 ])
3184 ]
3185 usage = '''\
3186 usage: PROG [-h] [-w W [W ...]] [-x [X [X ...]]] [-y [Y]] [-z Z Z Z]
3187 a b b [c] [d [d ...]] e [e ...]
3188 '''
3189 help = usage + '''\
3190
3191 positional arguments:
3192 a a
3193 b b
3194 c c
3195
3196 optional arguments:
3197 -h, --help show this help message and exit
3198 -w W [W ...] w
3199 -x [X [X ...]] x
3200
3201 group:
3202 -y [Y] y
3203 -z Z Z Z z
3204 d d
3205 e e
3206 '''
3207 version = ''
3208
3209
3210class TestHelpOnlyUserGroups(HelpTestCase):
3211 """Test basic usage messages"""
3212
3213 parser_signature = Sig(prog='PROG', add_help=False)
3214 argument_signatures = []
3215 argument_group_signatures = [
3216 (Sig('xxxx'), [
3217 Sig('-x', help='x'),
3218 Sig('a', help='a'),
3219 ]),
3220 (Sig('yyyy'), [
3221 Sig('b', help='b'),
3222 Sig('-y', help='y'),
3223 ]),
3224 ]
3225 usage = '''\
3226 usage: PROG [-x X] [-y Y] a b
3227 '''
3228 help = usage + '''\
3229
3230 xxxx:
3231 -x X x
3232 a a
3233
3234 yyyy:
3235 b b
3236 -y Y y
3237 '''
3238 version = ''
3239
3240
3241class TestHelpUsageLongProg(HelpTestCase):
3242 """Test usage messages where the prog is long"""
3243
3244 parser_signature = Sig(prog='P' * 60)
3245 argument_signatures = [
3246 Sig('-w', metavar='W'),
3247 Sig('-x', metavar='X'),
3248 Sig('a'),
3249 Sig('b'),
3250 ]
3251 argument_group_signatures = []
3252 usage = '''\
3253 usage: PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
3254 [-h] [-w W] [-x X] a b
3255 '''
3256 help = usage + '''\
3257
3258 positional arguments:
3259 a
3260 b
3261
3262 optional arguments:
3263 -h, --help show this help message and exit
3264 -w W
3265 -x X
3266 '''
3267 version = ''
3268
3269
3270class TestHelpUsageLongProgOptionsWrap(HelpTestCase):
3271 """Test usage messages where the prog is long and the optionals wrap"""
3272
3273 parser_signature = Sig(prog='P' * 60)
3274 argument_signatures = [
3275 Sig('-w', metavar='W' * 25),
3276 Sig('-x', metavar='X' * 25),
3277 Sig('-y', metavar='Y' * 25),
3278 Sig('-z', metavar='Z' * 25),
3279 Sig('a'),
3280 Sig('b'),
3281 ]
3282 argument_group_signatures = []
3283 usage = '''\
3284 usage: PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
3285 [-h] [-w WWWWWWWWWWWWWWWWWWWWWWWWW] \
3286[-x XXXXXXXXXXXXXXXXXXXXXXXXX]
3287 [-y YYYYYYYYYYYYYYYYYYYYYYYYY] [-z ZZZZZZZZZZZZZZZZZZZZZZZZZ]
3288 a b
3289 '''
3290 help = usage + '''\
3291
3292 positional arguments:
3293 a
3294 b
3295
3296 optional arguments:
3297 -h, --help show this help message and exit
3298 -w WWWWWWWWWWWWWWWWWWWWWWWWW
3299 -x XXXXXXXXXXXXXXXXXXXXXXXXX
3300 -y YYYYYYYYYYYYYYYYYYYYYYYYY
3301 -z ZZZZZZZZZZZZZZZZZZZZZZZZZ
3302 '''
3303 version = ''
3304
3305
3306class TestHelpUsageLongProgPositionalsWrap(HelpTestCase):
3307 """Test usage messages where the prog is long and the positionals wrap"""
3308
3309 parser_signature = Sig(prog='P' * 60, add_help=False)
3310 argument_signatures = [
3311 Sig('a' * 25),
3312 Sig('b' * 25),
3313 Sig('c' * 25),
3314 ]
3315 argument_group_signatures = []
3316 usage = '''\
3317 usage: PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
3318 aaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbb
3319 ccccccccccccccccccccccccc
3320 '''
3321 help = usage + '''\
3322
3323 positional arguments:
3324 aaaaaaaaaaaaaaaaaaaaaaaaa
3325 bbbbbbbbbbbbbbbbbbbbbbbbb
3326 ccccccccccccccccccccccccc
3327 '''
3328 version = ''
3329
3330
3331class TestHelpUsageOptionalsWrap(HelpTestCase):
3332 """Test usage messages where the optionals wrap"""
3333
3334 parser_signature = Sig(prog='PROG')
3335 argument_signatures = [
3336 Sig('-w', metavar='W' * 25),
3337 Sig('-x', metavar='X' * 25),
3338 Sig('-y', metavar='Y' * 25),
3339 Sig('-z', metavar='Z' * 25),
3340 Sig('a'),
3341 Sig('b'),
3342 Sig('c'),
3343 ]
3344 argument_group_signatures = []
3345 usage = '''\
3346 usage: PROG [-h] [-w WWWWWWWWWWWWWWWWWWWWWWWWW] \
3347[-x XXXXXXXXXXXXXXXXXXXXXXXXX]
3348 [-y YYYYYYYYYYYYYYYYYYYYYYYYY] \
3349[-z ZZZZZZZZZZZZZZZZZZZZZZZZZ]
3350 a b c
3351 '''
3352 help = usage + '''\
3353
3354 positional arguments:
3355 a
3356 b
3357 c
3358
3359 optional arguments:
3360 -h, --help show this help message and exit
3361 -w WWWWWWWWWWWWWWWWWWWWWWWWW
3362 -x XXXXXXXXXXXXXXXXXXXXXXXXX
3363 -y YYYYYYYYYYYYYYYYYYYYYYYYY
3364 -z ZZZZZZZZZZZZZZZZZZZZZZZZZ
3365 '''
3366 version = ''
3367
3368
3369class TestHelpUsagePositionalsWrap(HelpTestCase):
3370 """Test usage messages where the positionals wrap"""
3371
3372 parser_signature = Sig(prog='PROG')
3373 argument_signatures = [
3374 Sig('-x'),
3375 Sig('-y'),
3376 Sig('-z'),
3377 Sig('a' * 25),
3378 Sig('b' * 25),
3379 Sig('c' * 25),
3380 ]
3381 argument_group_signatures = []
3382 usage = '''\
3383 usage: PROG [-h] [-x X] [-y Y] [-z Z]
3384 aaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbb
3385 ccccccccccccccccccccccccc
3386 '''
3387 help = usage + '''\
3388
3389 positional arguments:
3390 aaaaaaaaaaaaaaaaaaaaaaaaa
3391 bbbbbbbbbbbbbbbbbbbbbbbbb
3392 ccccccccccccccccccccccccc
3393
3394 optional arguments:
3395 -h, --help show this help message and exit
3396 -x X
3397 -y Y
3398 -z Z
3399 '''
3400 version = ''
3401
3402
3403class TestHelpUsageOptionalsPositionalsWrap(HelpTestCase):
3404 """Test usage messages where the optionals and positionals wrap"""
3405
3406 parser_signature = Sig(prog='PROG')
3407 argument_signatures = [
3408 Sig('-x', metavar='X' * 25),
3409 Sig('-y', metavar='Y' * 25),
3410 Sig('-z', metavar='Z' * 25),
3411 Sig('a' * 25),
3412 Sig('b' * 25),
3413 Sig('c' * 25),
3414 ]
3415 argument_group_signatures = []
3416 usage = '''\
3417 usage: PROG [-h] [-x XXXXXXXXXXXXXXXXXXXXXXXXX] \
3418[-y YYYYYYYYYYYYYYYYYYYYYYYYY]
3419 [-z ZZZZZZZZZZZZZZZZZZZZZZZZZ]
3420 aaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbb
3421 ccccccccccccccccccccccccc
3422 '''
3423 help = usage + '''\
3424
3425 positional arguments:
3426 aaaaaaaaaaaaaaaaaaaaaaaaa
3427 bbbbbbbbbbbbbbbbbbbbbbbbb
3428 ccccccccccccccccccccccccc
3429
3430 optional arguments:
3431 -h, --help show this help message and exit
3432 -x XXXXXXXXXXXXXXXXXXXXXXXXX
3433 -y YYYYYYYYYYYYYYYYYYYYYYYYY
3434 -z ZZZZZZZZZZZZZZZZZZZZZZZZZ
3435 '''
3436 version = ''
3437
3438
3439class TestHelpUsageOptionalsOnlyWrap(HelpTestCase):
3440 """Test usage messages where there are only optionals and they wrap"""
3441
3442 parser_signature = Sig(prog='PROG')
3443 argument_signatures = [
3444 Sig('-x', metavar='X' * 25),
3445 Sig('-y', metavar='Y' * 25),
3446 Sig('-z', metavar='Z' * 25),
3447 ]
3448 argument_group_signatures = []
3449 usage = '''\
3450 usage: PROG [-h] [-x XXXXXXXXXXXXXXXXXXXXXXXXX] \
3451[-y YYYYYYYYYYYYYYYYYYYYYYYYY]
3452 [-z ZZZZZZZZZZZZZZZZZZZZZZZZZ]
3453 '''
3454 help = usage + '''\
3455
3456 optional arguments:
3457 -h, --help show this help message and exit
3458 -x XXXXXXXXXXXXXXXXXXXXXXXXX
3459 -y YYYYYYYYYYYYYYYYYYYYYYYYY
3460 -z ZZZZZZZZZZZZZZZZZZZZZZZZZ
3461 '''
3462 version = ''
3463
3464
3465class TestHelpUsagePositionalsOnlyWrap(HelpTestCase):
3466 """Test usage messages where there are only positionals and they wrap"""
3467
3468 parser_signature = Sig(prog='PROG', add_help=False)
3469 argument_signatures = [
3470 Sig('a' * 25),
3471 Sig('b' * 25),
3472 Sig('c' * 25),
3473 ]
3474 argument_group_signatures = []
3475 usage = '''\
3476 usage: PROG aaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbb
3477 ccccccccccccccccccccccccc
3478 '''
3479 help = usage + '''\
3480
3481 positional arguments:
3482 aaaaaaaaaaaaaaaaaaaaaaaaa
3483 bbbbbbbbbbbbbbbbbbbbbbbbb
3484 ccccccccccccccccccccccccc
3485 '''
3486 version = ''
3487
3488
3489class TestHelpVariableExpansion(HelpTestCase):
3490 """Test that variables are expanded properly in help messages"""
3491
3492 parser_signature = Sig(prog='PROG')
3493 argument_signatures = [
3494 Sig('-x', type=int,
3495 help='x %(prog)s %(default)s %(type)s %%'),
3496 Sig('-y', action='store_const', default=42, const='XXX',
3497 help='y %(prog)s %(default)s %(const)s'),
3498 Sig('--foo', choices='abc',
3499 help='foo %(prog)s %(default)s %(choices)s'),
3500 Sig('--bar', default='baz', choices=[1, 2], metavar='BBB',
3501 help='bar %(prog)s %(default)s %(dest)s'),
3502 Sig('spam', help='spam %(prog)s %(default)s'),
3503 Sig('badger', default=0.5, help='badger %(prog)s %(default)s'),
3504 ]
3505 argument_group_signatures = [
3506 (Sig('group'), [
3507 Sig('-a', help='a %(prog)s %(default)s'),
3508 Sig('-b', default=-1, help='b %(prog)s %(default)s'),
3509 ])
3510 ]
3511 usage = ('''\
3512 usage: PROG [-h] [-x X] [-y] [--foo {a,b,c}] [--bar BBB] [-a A] [-b B]
3513 spam badger
3514 ''')
3515 help = usage + '''\
3516
3517 positional arguments:
3518 spam spam PROG None
3519 badger badger PROG 0.5
3520
3521 optional arguments:
3522 -h, --help show this help message and exit
3523 -x X x PROG None int %
3524 -y y PROG 42 XXX
3525 --foo {a,b,c} foo PROG None a, b, c
3526 --bar BBB bar PROG baz bar
3527
3528 group:
3529 -a A a PROG None
3530 -b B b PROG -1
3531 '''
3532 version = ''
3533
3534
3535class TestHelpVariableExpansionUsageSupplied(HelpTestCase):
3536 """Test that variables are expanded properly when usage= is present"""
3537
3538 parser_signature = Sig(prog='PROG', usage='%(prog)s FOO')
3539 argument_signatures = []
3540 argument_group_signatures = []
3541 usage = ('''\
3542 usage: PROG FOO
3543 ''')
3544 help = usage + '''\
3545
3546 optional arguments:
3547 -h, --help show this help message and exit
3548 '''
3549 version = ''
3550
3551
3552class TestHelpVariableExpansionNoArguments(HelpTestCase):
3553 """Test that variables are expanded properly with no arguments"""
3554
3555 parser_signature = Sig(prog='PROG', add_help=False)
3556 argument_signatures = []
3557 argument_group_signatures = []
3558 usage = ('''\
3559 usage: PROG
3560 ''')
3561 help = usage
3562 version = ''
3563
3564
3565class TestHelpSuppressUsage(HelpTestCase):
3566 """Test that items can be suppressed in usage messages"""
3567
3568 parser_signature = Sig(prog='PROG', usage=argparse.SUPPRESS)
3569 argument_signatures = [
3570 Sig('--foo', help='foo help'),
3571 Sig('spam', help='spam help'),
3572 ]
3573 argument_group_signatures = []
3574 help = '''\
3575 positional arguments:
3576 spam spam help
3577
3578 optional arguments:
3579 -h, --help show this help message and exit
3580 --foo FOO foo help
3581 '''
3582 usage = ''
3583 version = ''
3584
3585
3586class TestHelpSuppressOptional(HelpTestCase):
3587 """Test that optional arguments can be suppressed in help messages"""
3588
3589 parser_signature = Sig(prog='PROG', add_help=False)
3590 argument_signatures = [
3591 Sig('--foo', help=argparse.SUPPRESS),
3592 Sig('spam', help='spam help'),
3593 ]
3594 argument_group_signatures = []
3595 usage = '''\
3596 usage: PROG spam
3597 '''
3598 help = usage + '''\
3599
3600 positional arguments:
3601 spam spam help
3602 '''
3603 version = ''
3604
3605
3606class TestHelpSuppressOptionalGroup(HelpTestCase):
3607 """Test that optional groups can be suppressed in help messages"""
3608
3609 parser_signature = Sig(prog='PROG')
3610 argument_signatures = [
3611 Sig('--foo', help='foo help'),
3612 Sig('spam', help='spam help'),
3613 ]
3614 argument_group_signatures = [
3615 (Sig('group'), [Sig('--bar', help=argparse.SUPPRESS)]),
3616 ]
3617 usage = '''\
3618 usage: PROG [-h] [--foo FOO] spam
3619 '''
3620 help = usage + '''\
3621
3622 positional arguments:
3623 spam spam help
3624
3625 optional arguments:
3626 -h, --help show this help message and exit
3627 --foo FOO foo help
3628 '''
3629 version = ''
3630
3631
3632class TestHelpSuppressPositional(HelpTestCase):
3633 """Test that positional arguments can be suppressed in help messages"""
3634
3635 parser_signature = Sig(prog='PROG')
3636 argument_signatures = [
3637 Sig('--foo', help='foo help'),
3638 Sig('spam', help=argparse.SUPPRESS),
3639 ]
3640 argument_group_signatures = []
3641 usage = '''\
3642 usage: PROG [-h] [--foo FOO]
3643 '''
3644 help = usage + '''\
3645
3646 optional arguments:
3647 -h, --help show this help message and exit
3648 --foo FOO foo help
3649 '''
3650 version = ''
3651
3652
3653class TestHelpRequiredOptional(HelpTestCase):
3654 """Test that required options don't look optional"""
3655
3656 parser_signature = Sig(prog='PROG')
3657 argument_signatures = [
3658 Sig('--foo', required=True, help='foo help'),
3659 ]
3660 argument_group_signatures = []
3661 usage = '''\
3662 usage: PROG [-h] --foo FOO
3663 '''
3664 help = usage + '''\
3665
3666 optional arguments:
3667 -h, --help show this help message and exit
3668 --foo FOO foo help
3669 '''
3670 version = ''
3671
3672
3673class TestHelpAlternatePrefixChars(HelpTestCase):
3674 """Test that options display with different prefix characters"""
3675
3676 parser_signature = Sig(prog='PROG', prefix_chars='^;', add_help=False)
3677 argument_signatures = [
3678 Sig('^^foo', action='store_true', help='foo help'),
3679 Sig(';b', ';;bar', help='bar help'),
3680 ]
3681 argument_group_signatures = []
3682 usage = '''\
3683 usage: PROG [^^foo] [;b BAR]
3684 '''
3685 help = usage + '''\
3686
3687 optional arguments:
3688 ^^foo foo help
3689 ;b BAR, ;;bar BAR bar help
3690 '''
3691 version = ''
3692
3693
3694class TestHelpNoHelpOptional(HelpTestCase):
3695 """Test that the --help argument can be suppressed help messages"""
3696
3697 parser_signature = Sig(prog='PROG', add_help=False)
3698 argument_signatures = [
3699 Sig('--foo', help='foo help'),
3700 Sig('spam', help='spam help'),
3701 ]
3702 argument_group_signatures = []
3703 usage = '''\
3704 usage: PROG [--foo FOO] spam
3705 '''
3706 help = usage + '''\
3707
3708 positional arguments:
3709 spam spam help
3710
3711 optional arguments:
3712 --foo FOO foo help
3713 '''
3714 version = ''
3715
3716
3717class TestHelpVersionOptional(HelpTestCase):
3718 """Test that the --version argument can be suppressed help messages"""
3719
3720 parser_signature = Sig(prog='PROG', version='1.0')
3721 argument_signatures = [
3722 Sig('--foo', help='foo help'),
3723 Sig('spam', help='spam help'),
3724 ]
3725 argument_group_signatures = []
3726 usage = '''\
3727 usage: PROG [-h] [-v] [--foo FOO] spam
3728 '''
3729 help = usage + '''\
3730
3731 positional arguments:
3732 spam spam help
3733
3734 optional arguments:
3735 -h, --help show this help message and exit
3736 -v, --version show program's version number and exit
3737 --foo FOO foo help
3738 '''
3739 version = '''\
3740 1.0
3741 '''
3742
3743
3744class TestHelpNone(HelpTestCase):
3745 """Test that no errors occur if no help is specified"""
3746
3747 parser_signature = Sig(prog='PROG')
3748 argument_signatures = [
3749 Sig('--foo'),
3750 Sig('spam'),
3751 ]
3752 argument_group_signatures = []
3753 usage = '''\
3754 usage: PROG [-h] [--foo FOO] spam
3755 '''
3756 help = usage + '''\
3757
3758 positional arguments:
3759 spam
3760
3761 optional arguments:
3762 -h, --help show this help message and exit
3763 --foo FOO
3764 '''
3765 version = ''
3766
3767
3768class TestHelpTupleMetavar(HelpTestCase):
3769 """Test specifying metavar as a tuple"""
3770
3771 parser_signature = Sig(prog='PROG')
3772 argument_signatures = [
3773 Sig('-w', help='w', nargs='+', metavar=('W1', 'W2')),
3774 Sig('-x', help='x', nargs='*', metavar=('X1', 'X2')),
3775 Sig('-y', help='y', nargs=3, metavar=('Y1', 'Y2', 'Y3')),
3776 Sig('-z', help='z', nargs='?', metavar=('Z1', )),
3777 ]
3778 argument_group_signatures = []
3779 usage = '''\
3780 usage: PROG [-h] [-w W1 [W2 ...]] [-x [X1 [X2 ...]]] [-y Y1 Y2 Y3] \
3781[-z [Z1]]
3782 '''
3783 help = usage + '''\
3784
3785 optional arguments:
3786 -h, --help show this help message and exit
3787 -w W1 [W2 ...] w
3788 -x [X1 [X2 ...]] x
3789 -y Y1 Y2 Y3 y
3790 -z [Z1] z
3791 '''
3792 version = ''
3793
3794
3795class TestHelpRawText(HelpTestCase):
3796 """Test the RawTextHelpFormatter"""
3797
3798 parser_signature = Sig(
3799 prog='PROG', formatter_class=argparse.RawTextHelpFormatter,
3800 description='Keep the formatting\n'
3801 ' exactly as it is written\n'
3802 '\n'
3803 'here\n')
3804
3805 argument_signatures = [
3806 Sig('--foo', help=' foo help should also\n'
3807 'appear as given here'),
3808 Sig('spam', help='spam help'),
3809 ]
3810 argument_group_signatures = [
3811 (Sig('title', description=' This text\n'
3812 ' should be indented\n'
3813 ' exactly like it is here\n'),
3814 [Sig('--bar', help='bar help')]),
3815 ]
3816 usage = '''\
3817 usage: PROG [-h] [--foo FOO] [--bar BAR] spam
3818 '''
3819 help = usage + '''\
3820
3821 Keep the formatting
3822 exactly as it is written
3823
3824 here
3825
3826 positional arguments:
3827 spam spam help
3828
3829 optional arguments:
3830 -h, --help show this help message and exit
3831 --foo FOO foo help should also
3832 appear as given here
3833
3834 title:
3835 This text
3836 should be indented
3837 exactly like it is here
3838
3839 --bar BAR bar help
3840 '''
3841 version = ''
3842
3843
3844class TestHelpRawDescription(HelpTestCase):
3845 """Test the RawTextHelpFormatter"""
3846
3847 parser_signature = Sig(
3848 prog='PROG', formatter_class=argparse.RawDescriptionHelpFormatter,
3849 description='Keep the formatting\n'
3850 ' exactly as it is written\n'
3851 '\n'
3852 'here\n')
3853
3854 argument_signatures = [
3855 Sig('--foo', help=' foo help should not\n'
3856 ' retain this odd formatting'),
3857 Sig('spam', help='spam help'),
3858 ]
3859 argument_group_signatures = [
3860 (Sig('title', description=' This text\n'
3861 ' should be indented\n'
3862 ' exactly like it is here\n'),
3863 [Sig('--bar', help='bar help')]),
3864 ]
3865 usage = '''\
3866 usage: PROG [-h] [--foo FOO] [--bar BAR] spam
3867 '''
3868 help = usage + '''\
3869
3870 Keep the formatting
3871 exactly as it is written
3872
3873 here
3874
3875 positional arguments:
3876 spam spam help
3877
3878 optional arguments:
3879 -h, --help show this help message and exit
3880 --foo FOO foo help should not retain this odd formatting
3881
3882 title:
3883 This text
3884 should be indented
3885 exactly like it is here
3886
3887 --bar BAR bar help
3888 '''
3889 version = ''
3890
3891
3892class TestHelpArgumentDefaults(HelpTestCase):
3893 """Test the ArgumentDefaultsHelpFormatter"""
3894
3895 parser_signature = Sig(
3896 prog='PROG', formatter_class=argparse.ArgumentDefaultsHelpFormatter,
3897 description='description')
3898
3899 argument_signatures = [
3900 Sig('--foo', help='foo help - oh and by the way, %(default)s'),
3901 Sig('--bar', action='store_true', help='bar help'),
3902 Sig('spam', help='spam help'),
3903 Sig('badger', nargs='?', default='wooden', help='badger help'),
3904 ]
3905 argument_group_signatures = [
3906 (Sig('title', description='description'),
3907 [Sig('--baz', type=int, default=42, help='baz help')]),
3908 ]
3909 usage = '''\
3910 usage: PROG [-h] [--foo FOO] [--bar] [--baz BAZ] spam [badger]
3911 '''
3912 help = usage + '''\
3913
3914 description
3915
3916 positional arguments:
3917 spam spam help
3918 badger badger help (default: wooden)
3919
3920 optional arguments:
3921 -h, --help show this help message and exit
3922 --foo FOO foo help - oh and by the way, None
3923 --bar bar help (default: False)
3924
3925 title:
3926 description
3927
3928 --baz BAZ baz help (default: 42)
3929 '''
3930 version = ''
3931
Steven Bethard50fe5932010-05-24 03:47:38 +00003932class TestHelpVersionAction(HelpTestCase):
3933 """Test the default help for the version action"""
3934
3935 parser_signature = Sig(prog='PROG', description='description')
3936 argument_signatures = [Sig('-V', '--version', action='version', version='3.6')]
3937 argument_group_signatures = []
3938 usage = '''\
3939 usage: PROG [-h] [-V]
3940 '''
3941 help = usage + '''\
3942
3943 description
3944
3945 optional arguments:
3946 -h, --help show this help message and exit
3947 -V, --version show program's version number and exit
3948 '''
3949 version = ''
3950
Steven Bethard8a6a1982011-03-27 13:53:53 +02003951class TestHelpSubparsersOrdering(HelpTestCase):
3952 """Test ordering of subcommands in help matches the code"""
3953 parser_signature = Sig(prog='PROG',
3954 description='display some subcommands',
3955 version='0.1')
3956
3957 subparsers_signatures = [Sig(name=name)
3958 for name in ('a', 'b', 'c', 'd', 'e')]
3959
3960 usage = '''\
3961 usage: PROG [-h] [-v] {a,b,c,d,e} ...
3962 '''
3963
3964 help = usage + '''\
3965
3966 display some subcommands
3967
3968 positional arguments:
3969 {a,b,c,d,e}
3970
3971 optional arguments:
3972 -h, --help show this help message and exit
3973 -v, --version show program's version number and exit
3974 '''
3975
3976 version = '''\
3977 0.1
3978 '''
3979
3980class TestHelpSubparsersWithHelpOrdering(HelpTestCase):
3981 """Test ordering of subcommands in help matches the code"""
3982 parser_signature = Sig(prog='PROG',
3983 description='display some subcommands',
3984 version='0.1')
3985
3986 subcommand_data = (('a', 'a subcommand help'),
3987 ('b', 'b subcommand help'),
3988 ('c', 'c subcommand help'),
3989 ('d', 'd subcommand help'),
3990 ('e', 'e subcommand help'),
3991 )
3992
3993 subparsers_signatures = [Sig(name=name, help=help)
3994 for name, help in subcommand_data]
3995
3996 usage = '''\
3997 usage: PROG [-h] [-v] {a,b,c,d,e} ...
3998 '''
3999
4000 help = usage + '''\
4001
4002 display some subcommands
4003
4004 positional arguments:
4005 {a,b,c,d,e}
4006 a a subcommand help
4007 b b subcommand help
4008 c c subcommand help
4009 d d subcommand help
4010 e e subcommand help
4011
4012 optional arguments:
4013 -h, --help show this help message and exit
4014 -v, --version show program's version number and exit
4015 '''
4016
4017 version = '''\
4018 0.1
4019 '''
4020
4021
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004022# =====================================
4023# Optional/Positional constructor tests
4024# =====================================
4025
4026class TestInvalidArgumentConstructors(TestCase):
4027 """Test a bunch of invalid Argument constructors"""
4028
4029 def assertTypeError(self, *args, **kwargs):
4030 parser = argparse.ArgumentParser()
4031 self.assertRaises(TypeError, parser.add_argument,
4032 *args, **kwargs)
4033
4034 def assertValueError(self, *args, **kwargs):
4035 parser = argparse.ArgumentParser()
4036 self.assertRaises(ValueError, parser.add_argument,
4037 *args, **kwargs)
4038
4039 def test_invalid_keyword_arguments(self):
4040 self.assertTypeError('-x', bar=None)
4041 self.assertTypeError('-y', callback='foo')
4042 self.assertTypeError('-y', callback_args=())
4043 self.assertTypeError('-y', callback_kwargs={})
4044
4045 def test_missing_destination(self):
4046 self.assertTypeError()
4047 for action in ['append', 'store']:
4048 self.assertTypeError(action=action)
4049
4050 def test_invalid_option_strings(self):
4051 self.assertValueError('--')
4052 self.assertValueError('---')
4053
4054 def test_invalid_type(self):
4055 self.assertValueError('--foo', type='int')
Steven Bethard7cb20a82011-04-04 01:53:02 +02004056 self.assertValueError('--foo', type=(int, float))
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004057
4058 def test_invalid_action(self):
4059 self.assertValueError('-x', action='foo')
4060 self.assertValueError('foo', action='baz')
Steven Bethard7cb20a82011-04-04 01:53:02 +02004061 self.assertValueError('--foo', action=('store', 'append'))
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004062 parser = argparse.ArgumentParser()
4063 try:
4064 parser.add_argument("--foo", action="store-true")
4065 except ValueError:
4066 e = sys.exc_info()[1]
4067 expected = 'unknown action'
4068 msg = 'expected %r, found %r' % (expected, e)
4069 self.assertTrue(expected in str(e), msg)
4070
4071 def test_multiple_dest(self):
4072 parser = argparse.ArgumentParser()
4073 parser.add_argument(dest='foo')
4074 try:
4075 parser.add_argument('bar', dest='baz')
4076 except ValueError:
4077 e = sys.exc_info()[1]
4078 expected = 'dest supplied twice for positional argument'
4079 msg = 'expected %r, found %r' % (expected, e)
4080 self.assertTrue(expected in str(e), msg)
4081
4082 def test_no_argument_actions(self):
4083 for action in ['store_const', 'store_true', 'store_false',
4084 'append_const', 'count']:
4085 for attrs in [dict(type=int), dict(nargs='+'),
4086 dict(choices='ab')]:
4087 self.assertTypeError('-x', action=action, **attrs)
4088
4089 def test_no_argument_no_const_actions(self):
4090 # options with zero arguments
4091 for action in ['store_true', 'store_false', 'count']:
4092
4093 # const is always disallowed
4094 self.assertTypeError('-x', const='foo', action=action)
4095
4096 # nargs is always disallowed
4097 self.assertTypeError('-x', nargs='*', action=action)
4098
4099 def test_more_than_one_argument_actions(self):
4100 for action in ['store', 'append']:
4101
4102 # nargs=0 is disallowed
4103 self.assertValueError('-x', nargs=0, action=action)
4104 self.assertValueError('spam', nargs=0, action=action)
4105
4106 # const is disallowed with non-optional arguments
4107 for nargs in [1, '*', '+']:
4108 self.assertValueError('-x', const='foo',
4109 nargs=nargs, action=action)
4110 self.assertValueError('spam', const='foo',
4111 nargs=nargs, action=action)
4112
4113 def test_required_const_actions(self):
4114 for action in ['store_const', 'append_const']:
4115
4116 # nargs is always disallowed
4117 self.assertTypeError('-x', nargs='+', action=action)
4118
4119 def test_parsers_action_missing_params(self):
4120 self.assertTypeError('command', action='parsers')
4121 self.assertTypeError('command', action='parsers', prog='PROG')
4122 self.assertTypeError('command', action='parsers',
4123 parser_class=argparse.ArgumentParser)
4124
4125 def test_required_positional(self):
4126 self.assertTypeError('foo', required=True)
4127
4128 def test_user_defined_action(self):
4129
4130 class Success(Exception):
4131 pass
4132
4133 class Action(object):
4134
4135 def __init__(self,
4136 option_strings,
4137 dest,
4138 const,
4139 default,
4140 required=False):
4141 if dest == 'spam':
4142 if const is Success:
4143 if default is Success:
4144 raise Success()
4145
4146 def __call__(self, *args, **kwargs):
4147 pass
4148
4149 parser = argparse.ArgumentParser()
4150 self.assertRaises(Success, parser.add_argument, '--spam',
4151 action=Action, default=Success, const=Success)
4152 self.assertRaises(Success, parser.add_argument, 'spam',
4153 action=Action, default=Success, const=Success)
4154
4155# ================================
4156# Actions returned by add_argument
4157# ================================
4158
4159class TestActionsReturned(TestCase):
4160
4161 def test_dest(self):
4162 parser = argparse.ArgumentParser()
4163 action = parser.add_argument('--foo')
4164 self.assertEqual(action.dest, 'foo')
4165 action = parser.add_argument('-b', '--bar')
4166 self.assertEqual(action.dest, 'bar')
4167 action = parser.add_argument('-x', '-y')
4168 self.assertEqual(action.dest, 'x')
4169
4170 def test_misc(self):
4171 parser = argparse.ArgumentParser()
4172 action = parser.add_argument('--foo', nargs='?', const=42,
4173 default=84, type=int, choices=[1, 2],
4174 help='FOO', metavar='BAR', dest='baz')
4175 self.assertEqual(action.nargs, '?')
4176 self.assertEqual(action.const, 42)
4177 self.assertEqual(action.default, 84)
4178 self.assertEqual(action.type, int)
4179 self.assertEqual(action.choices, [1, 2])
4180 self.assertEqual(action.help, 'FOO')
4181 self.assertEqual(action.metavar, 'BAR')
4182 self.assertEqual(action.dest, 'baz')
4183
4184
4185# ================================
4186# Argument conflict handling tests
4187# ================================
4188
4189class TestConflictHandling(TestCase):
4190
4191 def test_bad_type(self):
4192 self.assertRaises(ValueError, argparse.ArgumentParser,
4193 conflict_handler='foo')
4194
4195 def test_conflict_error(self):
4196 parser = argparse.ArgumentParser()
4197 parser.add_argument('-x')
4198 self.assertRaises(argparse.ArgumentError,
4199 parser.add_argument, '-x')
4200 parser.add_argument('--spam')
4201 self.assertRaises(argparse.ArgumentError,
4202 parser.add_argument, '--spam')
4203
4204 def test_resolve_error(self):
4205 get_parser = argparse.ArgumentParser
4206 parser = get_parser(prog='PROG', conflict_handler='resolve')
4207
4208 parser.add_argument('-x', help='OLD X')
4209 parser.add_argument('-x', help='NEW X')
4210 self.assertEqual(parser.format_help(), textwrap.dedent('''\
4211 usage: PROG [-h] [-x X]
4212
4213 optional arguments:
4214 -h, --help show this help message and exit
4215 -x X NEW X
4216 '''))
4217
4218 parser.add_argument('--spam', metavar='OLD_SPAM')
4219 parser.add_argument('--spam', metavar='NEW_SPAM')
4220 self.assertEqual(parser.format_help(), textwrap.dedent('''\
4221 usage: PROG [-h] [-x X] [--spam NEW_SPAM]
4222
4223 optional arguments:
4224 -h, --help show this help message and exit
4225 -x X NEW X
4226 --spam NEW_SPAM
4227 '''))
4228
4229
4230# =============================
4231# Help and Version option tests
4232# =============================
4233
4234class TestOptionalsHelpVersionActions(TestCase):
4235 """Test the help and version actions"""
4236
4237 def _get_error(self, func, *args, **kwargs):
4238 try:
4239 func(*args, **kwargs)
4240 except ArgumentParserError:
4241 return sys.exc_info()[1]
4242 else:
4243 self.assertRaises(ArgumentParserError, func, *args, **kwargs)
4244
4245 def assertPrintHelpExit(self, parser, args_str):
4246 self.assertEqual(
4247 parser.format_help(),
4248 self._get_error(parser.parse_args, args_str.split()).stdout)
4249
4250 def assertPrintVersionExit(self, parser, args_str):
4251 self.assertEqual(
4252 parser.format_version(),
4253 self._get_error(parser.parse_args, args_str.split()).stderr)
4254
4255 def assertArgumentParserError(self, parser, *args):
4256 self.assertRaises(ArgumentParserError, parser.parse_args, args)
4257
4258 def test_version(self):
4259 parser = ErrorRaisingArgumentParser(version='1.0')
4260 self.assertPrintHelpExit(parser, '-h')
4261 self.assertPrintHelpExit(parser, '--help')
4262 self.assertPrintVersionExit(parser, '-v')
4263 self.assertPrintVersionExit(parser, '--version')
4264
4265 def test_version_format(self):
4266 parser = ErrorRaisingArgumentParser(prog='PPP', version='%(prog)s 3.5')
4267 msg = self._get_error(parser.parse_args, ['-v']).stderr
4268 self.assertEqual('PPP 3.5\n', msg)
4269
4270 def test_version_no_help(self):
4271 parser = ErrorRaisingArgumentParser(add_help=False, version='1.0')
4272 self.assertArgumentParserError(parser, '-h')
4273 self.assertArgumentParserError(parser, '--help')
4274 self.assertPrintVersionExit(parser, '-v')
4275 self.assertPrintVersionExit(parser, '--version')
4276
4277 def test_version_action(self):
4278 parser = ErrorRaisingArgumentParser(prog='XXX')
4279 parser.add_argument('-V', action='version', version='%(prog)s 3.7')
4280 msg = self._get_error(parser.parse_args, ['-V']).stderr
4281 self.assertEqual('XXX 3.7\n', msg)
4282
4283 def test_no_help(self):
4284 parser = ErrorRaisingArgumentParser(add_help=False)
4285 self.assertArgumentParserError(parser, '-h')
4286 self.assertArgumentParserError(parser, '--help')
4287 self.assertArgumentParserError(parser, '-v')
4288 self.assertArgumentParserError(parser, '--version')
4289
4290 def test_alternate_help_version(self):
4291 parser = ErrorRaisingArgumentParser()
4292 parser.add_argument('-x', action='help')
4293 parser.add_argument('-y', action='version')
4294 self.assertPrintHelpExit(parser, '-x')
4295 self.assertPrintVersionExit(parser, '-y')
4296 self.assertArgumentParserError(parser, '-v')
4297 self.assertArgumentParserError(parser, '--version')
4298
4299 def test_help_version_extra_arguments(self):
4300 parser = ErrorRaisingArgumentParser(version='1.0')
4301 parser.add_argument('-x', action='store_true')
4302 parser.add_argument('y')
4303
4304 # try all combinations of valid prefixes and suffixes
4305 valid_prefixes = ['', '-x', 'foo', '-x bar', 'baz -x']
4306 valid_suffixes = valid_prefixes + ['--bad-option', 'foo bar baz']
4307 for prefix in valid_prefixes:
4308 for suffix in valid_suffixes:
4309 format = '%s %%s %s' % (prefix, suffix)
4310 self.assertPrintHelpExit(parser, format % '-h')
4311 self.assertPrintHelpExit(parser, format % '--help')
4312 self.assertPrintVersionExit(parser, format % '-v')
4313 self.assertPrintVersionExit(parser, format % '--version')
4314
4315
4316# ======================
4317# str() and repr() tests
4318# ======================
4319
4320class TestStrings(TestCase):
4321 """Test str() and repr() on Optionals and Positionals"""
4322
4323 def assertStringEqual(self, obj, result_string):
4324 for func in [str, repr]:
4325 self.assertEqual(func(obj), result_string)
4326
4327 def test_optional(self):
4328 option = argparse.Action(
4329 option_strings=['--foo', '-a', '-b'],
4330 dest='b',
4331 type='int',
4332 nargs='+',
4333 default=42,
4334 choices=[1, 2, 3],
4335 help='HELP',
4336 metavar='METAVAR')
4337 string = (
4338 "Action(option_strings=['--foo', '-a', '-b'], dest='b', "
4339 "nargs='+', const=None, default=42, type='int', "
4340 "choices=[1, 2, 3], help='HELP', metavar='METAVAR')")
4341 self.assertStringEqual(option, string)
4342
4343 def test_argument(self):
4344 argument = argparse.Action(
4345 option_strings=[],
4346 dest='x',
4347 type=float,
4348 nargs='?',
4349 default=2.5,
4350 choices=[0.5, 1.5, 2.5],
4351 help='H HH H',
4352 metavar='MV MV MV')
4353 string = (
4354 "Action(option_strings=[], dest='x', nargs='?', "
4355 "const=None, default=2.5, type=%r, choices=[0.5, 1.5, 2.5], "
4356 "help='H HH H', metavar='MV MV MV')" % float)
4357 self.assertStringEqual(argument, string)
4358
4359 def test_namespace(self):
4360 ns = argparse.Namespace(foo=42, bar='spam')
4361 string = "Namespace(bar='spam', foo=42)"
4362 self.assertStringEqual(ns, string)
4363
4364 def test_parser(self):
4365 parser = argparse.ArgumentParser(prog='PROG')
4366 string = (
4367 "ArgumentParser(prog='PROG', usage=None, description=None, "
4368 "version=None, formatter_class=%r, conflict_handler='error', "
4369 "add_help=True)" % argparse.HelpFormatter)
4370 self.assertStringEqual(parser, string)
4371
4372# ===============
4373# Namespace tests
4374# ===============
4375
4376class TestNamespace(TestCase):
4377
4378 def test_constructor(self):
4379 ns = argparse.Namespace()
4380 self.assertRaises(AttributeError, getattr, ns, 'x')
4381
4382 ns = argparse.Namespace(a=42, b='spam')
4383 self.assertEqual(ns.a, 42)
4384 self.assertEqual(ns.b, 'spam')
4385
4386 def test_equality(self):
4387 ns1 = argparse.Namespace(a=1, b=2)
4388 ns2 = argparse.Namespace(b=2, a=1)
4389 ns3 = argparse.Namespace(a=1)
4390 ns4 = argparse.Namespace(b=2)
4391
4392 self.assertEqual(ns1, ns2)
4393 self.assertNotEqual(ns1, ns3)
4394 self.assertNotEqual(ns1, ns4)
4395 self.assertNotEqual(ns2, ns3)
4396 self.assertNotEqual(ns2, ns4)
4397 self.assertTrue(ns1 != ns3)
4398 self.assertTrue(ns1 != ns4)
4399 self.assertTrue(ns2 != ns3)
4400 self.assertTrue(ns2 != ns4)
4401
4402
4403# ===================
4404# File encoding tests
4405# ===================
4406
4407class TestEncoding(TestCase):
4408
4409 def _test_module_encoding(self, path):
4410 path, _ = os.path.splitext(path)
4411 path += ".py"
Antoine Pitroub86680e2010-10-14 21:15:17 +00004412 with codecs.open(path, 'r', 'utf8') as f:
4413 f.read()
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004414
4415 def test_argparse_module_encoding(self):
4416 self._test_module_encoding(argparse.__file__)
4417
4418 def test_test_argparse_module_encoding(self):
4419 self._test_module_encoding(__file__)
4420
4421# ===================
4422# ArgumentError tests
4423# ===================
4424
4425class TestArgumentError(TestCase):
4426
4427 def test_argument_error(self):
4428 msg = "my error here"
4429 error = argparse.ArgumentError(None, msg)
4430 self.assertEqual(str(error), msg)
4431
4432# =======================
4433# ArgumentTypeError tests
4434# =======================
4435
R. David Murray722b5fd2010-11-20 03:48:58 +00004436class TestArgumentTypeError(TestCase):
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004437
4438 def test_argument_type_error(self):
4439
4440 def spam(string):
4441 raise argparse.ArgumentTypeError('spam!')
4442
4443 parser = ErrorRaisingArgumentParser(prog='PROG', add_help=False)
4444 parser.add_argument('x', type=spam)
4445 try:
4446 parser.parse_args(['XXX'])
4447 except ArgumentParserError:
4448 expected = 'usage: PROG x\nPROG: error: argument x: spam!\n'
4449 msg = sys.exc_info()[1].stderr
4450 self.assertEqual(expected, msg)
4451 else:
4452 self.fail()
4453
4454# ======================
4455# parse_known_args tests
4456# ======================
4457
4458class TestParseKnownArgs(TestCase):
4459
4460 def test_optionals(self):
4461 parser = argparse.ArgumentParser()
4462 parser.add_argument('--foo')
4463 args, extras = parser.parse_known_args('--foo F --bar --baz'.split())
4464 self.assertEqual(NS(foo='F'), args)
4465 self.assertEqual(['--bar', '--baz'], extras)
4466
4467 def test_mixed(self):
4468 parser = argparse.ArgumentParser()
4469 parser.add_argument('-v', nargs='?', const=1, type=int)
4470 parser.add_argument('--spam', action='store_false')
4471 parser.add_argument('badger')
4472
4473 argv = ["B", "C", "--foo", "-v", "3", "4"]
4474 args, extras = parser.parse_known_args(argv)
4475 self.assertEqual(NS(v=3, spam=True, badger="B"), args)
4476 self.assertEqual(["C", "--foo", "4"], extras)
4477
Steven Bethard8d9a4622011-03-26 17:33:56 +01004478# ==========================
4479# add_argument metavar tests
4480# ==========================
4481
4482class TestAddArgumentMetavar(TestCase):
4483
4484 EXPECTED_MESSAGE = "length of metavar tuple does not match nargs"
4485
4486 def do_test_no_exception(self, nargs, metavar):
4487 parser = argparse.ArgumentParser()
4488 parser.add_argument("--foo", nargs=nargs, metavar=metavar)
4489
4490 def do_test_exception(self, nargs, metavar):
4491 parser = argparse.ArgumentParser()
4492 with self.assertRaises(ValueError) as cm:
4493 parser.add_argument("--foo", nargs=nargs, metavar=metavar)
4494 self.assertEqual(cm.exception.args[0], self.EXPECTED_MESSAGE)
4495
4496 # Unit tests for different values of metavar when nargs=None
4497
4498 def test_nargs_None_metavar_string(self):
4499 self.do_test_no_exception(nargs=None, metavar="1")
4500
4501 def test_nargs_None_metavar_length0(self):
4502 self.do_test_exception(nargs=None, metavar=tuple())
4503
4504 def test_nargs_None_metavar_length1(self):
4505 self.do_test_no_exception(nargs=None, metavar=("1"))
4506
4507 def test_nargs_None_metavar_length2(self):
4508 self.do_test_exception(nargs=None, metavar=("1", "2"))
4509
4510 def test_nargs_None_metavar_length3(self):
4511 self.do_test_exception(nargs=None, metavar=("1", "2", "3"))
4512
4513 # Unit tests for different values of metavar when nargs=?
4514
4515 def test_nargs_optional_metavar_string(self):
4516 self.do_test_no_exception(nargs="?", metavar="1")
4517
4518 def test_nargs_optional_metavar_length0(self):
4519 self.do_test_exception(nargs="?", metavar=tuple())
4520
4521 def test_nargs_optional_metavar_length1(self):
4522 self.do_test_no_exception(nargs="?", metavar=("1"))
4523
4524 def test_nargs_optional_metavar_length2(self):
4525 self.do_test_exception(nargs="?", metavar=("1", "2"))
4526
4527 def test_nargs_optional_metavar_length3(self):
4528 self.do_test_exception(nargs="?", metavar=("1", "2", "3"))
4529
4530 # Unit tests for different values of metavar when nargs=*
4531
4532 def test_nargs_zeroormore_metavar_string(self):
4533 self.do_test_no_exception(nargs="*", metavar="1")
4534
4535 def test_nargs_zeroormore_metavar_length0(self):
4536 self.do_test_exception(nargs="*", metavar=tuple())
4537
4538 def test_nargs_zeroormore_metavar_length1(self):
4539 self.do_test_no_exception(nargs="*", metavar=("1"))
4540
4541 def test_nargs_zeroormore_metavar_length2(self):
4542 self.do_test_no_exception(nargs="*", metavar=("1", "2"))
4543
4544 def test_nargs_zeroormore_metavar_length3(self):
4545 self.do_test_exception(nargs="*", metavar=("1", "2", "3"))
4546
4547 # Unit tests for different values of metavar when nargs=+
4548
4549 def test_nargs_oneormore_metavar_string(self):
4550 self.do_test_no_exception(nargs="+", metavar="1")
4551
4552 def test_nargs_oneormore_metavar_length0(self):
4553 self.do_test_exception(nargs="+", metavar=tuple())
4554
4555 def test_nargs_oneormore_metavar_length1(self):
4556 self.do_test_no_exception(nargs="+", metavar=("1"))
4557
4558 def test_nargs_oneormore_metavar_length2(self):
4559 self.do_test_no_exception(nargs="+", metavar=("1", "2"))
4560
4561 def test_nargs_oneormore_metavar_length3(self):
4562 self.do_test_exception(nargs="+", metavar=("1", "2", "3"))
4563
4564 # Unit tests for different values of metavar when nargs=...
4565
4566 def test_nargs_remainder_metavar_string(self):
4567 self.do_test_no_exception(nargs="...", metavar="1")
4568
4569 def test_nargs_remainder_metavar_length0(self):
4570 self.do_test_no_exception(nargs="...", metavar=tuple())
4571
4572 def test_nargs_remainder_metavar_length1(self):
4573 self.do_test_no_exception(nargs="...", metavar=("1"))
4574
4575 def test_nargs_remainder_metavar_length2(self):
4576 self.do_test_no_exception(nargs="...", metavar=("1", "2"))
4577
4578 def test_nargs_remainder_metavar_length3(self):
4579 self.do_test_no_exception(nargs="...", metavar=("1", "2", "3"))
4580
4581 # Unit tests for different values of metavar when nargs=A...
4582
4583 def test_nargs_parser_metavar_string(self):
4584 self.do_test_no_exception(nargs="A...", metavar="1")
4585
4586 def test_nargs_parser_metavar_length0(self):
4587 self.do_test_exception(nargs="A...", metavar=tuple())
4588
4589 def test_nargs_parser_metavar_length1(self):
4590 self.do_test_no_exception(nargs="A...", metavar=("1"))
4591
4592 def test_nargs_parser_metavar_length2(self):
4593 self.do_test_exception(nargs="A...", metavar=("1", "2"))
4594
4595 def test_nargs_parser_metavar_length3(self):
4596 self.do_test_exception(nargs="A...", metavar=("1", "2", "3"))
4597
4598 # Unit tests for different values of metavar when nargs=1
4599
4600 def test_nargs_1_metavar_string(self):
4601 self.do_test_no_exception(nargs=1, metavar="1")
4602
4603 def test_nargs_1_metavar_length0(self):
4604 self.do_test_exception(nargs=1, metavar=tuple())
4605
4606 def test_nargs_1_metavar_length1(self):
4607 self.do_test_no_exception(nargs=1, metavar=("1"))
4608
4609 def test_nargs_1_metavar_length2(self):
4610 self.do_test_exception(nargs=1, metavar=("1", "2"))
4611
4612 def test_nargs_1_metavar_length3(self):
4613 self.do_test_exception(nargs=1, metavar=("1", "2", "3"))
4614
4615 # Unit tests for different values of metavar when nargs=2
4616
4617 def test_nargs_2_metavar_string(self):
4618 self.do_test_no_exception(nargs=2, metavar="1")
4619
4620 def test_nargs_2_metavar_length0(self):
4621 self.do_test_exception(nargs=2, metavar=tuple())
4622
4623 def test_nargs_2_metavar_length1(self):
4624 self.do_test_no_exception(nargs=2, metavar=("1"))
4625
4626 def test_nargs_2_metavar_length2(self):
4627 self.do_test_no_exception(nargs=2, metavar=("1", "2"))
4628
4629 def test_nargs_2_metavar_length3(self):
4630 self.do_test_exception(nargs=2, metavar=("1", "2", "3"))
4631
4632 # Unit tests for different values of metavar when nargs=3
4633
4634 def test_nargs_3_metavar_string(self):
4635 self.do_test_no_exception(nargs=3, metavar="1")
4636
4637 def test_nargs_3_metavar_length0(self):
4638 self.do_test_exception(nargs=3, metavar=tuple())
4639
4640 def test_nargs_3_metavar_length1(self):
4641 self.do_test_no_exception(nargs=3, metavar=("1"))
4642
4643 def test_nargs_3_metavar_length2(self):
4644 self.do_test_exception(nargs=3, metavar=("1", "2"))
4645
4646 def test_nargs_3_metavar_length3(self):
4647 self.do_test_no_exception(nargs=3, metavar=("1", "2", "3"))
4648
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004649# ============================
4650# from argparse import * tests
4651# ============================
4652
4653class TestImportStar(TestCase):
4654
4655 def test(self):
4656 for name in argparse.__all__:
4657 self.assertTrue(hasattr(argparse, name))
4658
Steven Bethard72c55382010-11-01 15:23:12 +00004659 def test_all_exports_everything_but_modules(self):
4660 items = [
4661 name
4662 for name, value in vars(argparse).items()
Éric Araujo12159152010-12-04 17:31:49 +00004663 if not (name.startswith("_") or name == 'ngettext')
Steven Bethard72c55382010-11-01 15:23:12 +00004664 if not inspect.ismodule(value)
4665 ]
4666 self.assertEqual(sorted(items), sorted(argparse.__all__))
4667
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004668def test_main():
Florent Xicluna41fe6152010-04-02 18:52:12 +00004669 # silence warnings about version argument - these are expected
4670 with support.check_warnings(
4671 ('The "version" argument to ArgumentParser is deprecated.',
4672 DeprecationWarning),
4673 ('The (format|print)_version method is deprecated',
4674 DeprecationWarning)):
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004675 support.run_unittest(__name__)
Benjamin Peterson4fd181c2010-03-02 23:46:42 +00004676 # Remove global references to avoid looking like we have refleaks.
4677 RFile.seen = {}
4678 WFile.seen = set()
4679
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004680
4681
4682if __name__ == '__main__':
4683 test_main()