blob: 852991c77f2466894b172416095ac15473cc884a [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()
Terry Jan Reedyee91e092012-01-09 18:20:09 -05002173 progname = self.main_program
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002174 self.assertEqual(parser_help, textwrap.dedent('''\
Terry Jan Reedyee91e092012-01-09 18:20:09 -05002175 usage: {}{}[-h] [-b B] [--d D] [--w W] [-y Y] a z
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002176
2177 positional arguments:
2178 a
2179 z
2180
2181 optional arguments:
2182 -h, --help show this help message and exit
2183 -b B
2184 --w W
2185
2186 c:
2187 --d D
2188
2189 x:
2190 -y Y
Terry Jan Reedyee91e092012-01-09 18:20:09 -05002191 '''.format(progname, ' ' if progname else '' )))
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002192
2193 def test_groups_parents(self):
2194 parent = ErrorRaisingArgumentParser(add_help=False)
2195 g = parent.add_argument_group(title='g', description='gd')
2196 g.add_argument('-w')
2197 g.add_argument('-x')
2198 m = parent.add_mutually_exclusive_group()
2199 m.add_argument('-y')
2200 m.add_argument('-z')
2201 parser = ErrorRaisingArgumentParser(parents=[parent])
2202
2203 self.assertRaises(ArgumentParserError, parser.parse_args,
2204 ['-y', 'Y', '-z', 'Z'])
2205
2206 parser_help = parser.format_help()
Terry Jan Reedyee91e092012-01-09 18:20:09 -05002207 progname = self.main_program
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002208 self.assertEqual(parser_help, textwrap.dedent('''\
Terry Jan Reedyee91e092012-01-09 18:20:09 -05002209 usage: {}{}[-h] [-w W] [-x X] [-y Y | -z Z]
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002210
2211 optional arguments:
2212 -h, --help show this help message and exit
2213 -y Y
2214 -z Z
2215
2216 g:
2217 gd
2218
2219 -w W
2220 -x X
Terry Jan Reedyee91e092012-01-09 18:20:09 -05002221 '''.format(progname, ' ' if progname else '' )))
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002222
2223# ==============================
2224# Mutually exclusive group tests
2225# ==============================
2226
2227class TestMutuallyExclusiveGroupErrors(TestCase):
2228
2229 def test_invalid_add_argument_group(self):
2230 parser = ErrorRaisingArgumentParser()
2231 raises = self.assertRaises
2232 raises(TypeError, parser.add_mutually_exclusive_group, title='foo')
2233
2234 def test_invalid_add_argument(self):
2235 parser = ErrorRaisingArgumentParser()
2236 group = parser.add_mutually_exclusive_group()
2237 add_argument = group.add_argument
2238 raises = self.assertRaises
2239 raises(ValueError, add_argument, '--foo', required=True)
2240 raises(ValueError, add_argument, 'bar')
2241 raises(ValueError, add_argument, 'bar', nargs='+')
2242 raises(ValueError, add_argument, 'bar', nargs=1)
2243 raises(ValueError, add_argument, 'bar', nargs=argparse.PARSER)
2244
Steven Bethard49998ee2010-11-01 16:29:26 +00002245 def test_help(self):
2246 parser = ErrorRaisingArgumentParser(prog='PROG')
2247 group1 = parser.add_mutually_exclusive_group()
2248 group1.add_argument('--foo', action='store_true')
2249 group1.add_argument('--bar', action='store_false')
2250 group2 = parser.add_mutually_exclusive_group()
2251 group2.add_argument('--soup', action='store_true')
2252 group2.add_argument('--nuts', action='store_false')
2253 expected = '''\
2254 usage: PROG [-h] [--foo | --bar] [--soup | --nuts]
2255
2256 optional arguments:
2257 -h, --help show this help message and exit
2258 --foo
2259 --bar
2260 --soup
2261 --nuts
2262 '''
2263 self.assertEqual(parser.format_help(), textwrap.dedent(expected))
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002264
2265class MEMixin(object):
2266
2267 def test_failures_when_not_required(self):
2268 parse_args = self.get_parser(required=False).parse_args
2269 error = ArgumentParserError
2270 for args_string in self.failures:
2271 self.assertRaises(error, parse_args, args_string.split())
2272
2273 def test_failures_when_required(self):
2274 parse_args = self.get_parser(required=True).parse_args
2275 error = ArgumentParserError
2276 for args_string in self.failures + ['']:
2277 self.assertRaises(error, parse_args, args_string.split())
2278
2279 def test_successes_when_not_required(self):
2280 parse_args = self.get_parser(required=False).parse_args
2281 successes = self.successes + self.successes_when_not_required
2282 for args_string, expected_ns in successes:
2283 actual_ns = parse_args(args_string.split())
2284 self.assertEqual(actual_ns, expected_ns)
2285
2286 def test_successes_when_required(self):
2287 parse_args = self.get_parser(required=True).parse_args
2288 for args_string, expected_ns in self.successes:
2289 actual_ns = parse_args(args_string.split())
2290 self.assertEqual(actual_ns, expected_ns)
2291
2292 def test_usage_when_not_required(self):
2293 format_usage = self.get_parser(required=False).format_usage
2294 expected_usage = self.usage_when_not_required
2295 self.assertEqual(format_usage(), textwrap.dedent(expected_usage))
2296
2297 def test_usage_when_required(self):
2298 format_usage = self.get_parser(required=True).format_usage
2299 expected_usage = self.usage_when_required
2300 self.assertEqual(format_usage(), textwrap.dedent(expected_usage))
2301
2302 def test_help_when_not_required(self):
2303 format_help = self.get_parser(required=False).format_help
2304 help = self.usage_when_not_required + self.help
2305 self.assertEqual(format_help(), textwrap.dedent(help))
2306
2307 def test_help_when_required(self):
2308 format_help = self.get_parser(required=True).format_help
2309 help = self.usage_when_required + self.help
2310 self.assertEqual(format_help(), textwrap.dedent(help))
2311
2312
2313class TestMutuallyExclusiveSimple(MEMixin, TestCase):
2314
2315 def get_parser(self, required=None):
2316 parser = ErrorRaisingArgumentParser(prog='PROG')
2317 group = parser.add_mutually_exclusive_group(required=required)
2318 group.add_argument('--bar', help='bar help')
2319 group.add_argument('--baz', nargs='?', const='Z', help='baz help')
2320 return parser
2321
2322 failures = ['--bar X --baz Y', '--bar X --baz']
2323 successes = [
2324 ('--bar X', NS(bar='X', baz=None)),
2325 ('--bar X --bar Z', NS(bar='Z', baz=None)),
2326 ('--baz Y', NS(bar=None, baz='Y')),
2327 ('--baz', NS(bar=None, baz='Z')),
2328 ]
2329 successes_when_not_required = [
2330 ('', NS(bar=None, baz=None)),
2331 ]
2332
2333 usage_when_not_required = '''\
2334 usage: PROG [-h] [--bar BAR | --baz [BAZ]]
2335 '''
2336 usage_when_required = '''\
2337 usage: PROG [-h] (--bar BAR | --baz [BAZ])
2338 '''
2339 help = '''\
2340
2341 optional arguments:
2342 -h, --help show this help message and exit
2343 --bar BAR bar help
2344 --baz [BAZ] baz help
2345 '''
2346
2347
2348class TestMutuallyExclusiveLong(MEMixin, TestCase):
2349
2350 def get_parser(self, required=None):
2351 parser = ErrorRaisingArgumentParser(prog='PROG')
2352 parser.add_argument('--abcde', help='abcde help')
2353 parser.add_argument('--fghij', help='fghij help')
2354 group = parser.add_mutually_exclusive_group(required=required)
2355 group.add_argument('--klmno', help='klmno help')
2356 group.add_argument('--pqrst', help='pqrst help')
2357 return parser
2358
2359 failures = ['--klmno X --pqrst Y']
2360 successes = [
2361 ('--klmno X', NS(abcde=None, fghij=None, klmno='X', pqrst=None)),
2362 ('--abcde Y --klmno X',
2363 NS(abcde='Y', fghij=None, klmno='X', pqrst=None)),
2364 ('--pqrst X', NS(abcde=None, fghij=None, klmno=None, pqrst='X')),
2365 ('--pqrst X --fghij Y',
2366 NS(abcde=None, fghij='Y', klmno=None, pqrst='X')),
2367 ]
2368 successes_when_not_required = [
2369 ('', NS(abcde=None, fghij=None, klmno=None, pqrst=None)),
2370 ]
2371
2372 usage_when_not_required = '''\
2373 usage: PROG [-h] [--abcde ABCDE] [--fghij FGHIJ]
2374 [--klmno KLMNO | --pqrst PQRST]
2375 '''
2376 usage_when_required = '''\
2377 usage: PROG [-h] [--abcde ABCDE] [--fghij FGHIJ]
2378 (--klmno KLMNO | --pqrst PQRST)
2379 '''
2380 help = '''\
2381
2382 optional arguments:
2383 -h, --help show this help message and exit
2384 --abcde ABCDE abcde help
2385 --fghij FGHIJ fghij help
2386 --klmno KLMNO klmno help
2387 --pqrst PQRST pqrst help
2388 '''
2389
2390
2391class TestMutuallyExclusiveFirstSuppressed(MEMixin, TestCase):
2392
2393 def get_parser(self, required):
2394 parser = ErrorRaisingArgumentParser(prog='PROG')
2395 group = parser.add_mutually_exclusive_group(required=required)
2396 group.add_argument('-x', help=argparse.SUPPRESS)
2397 group.add_argument('-y', action='store_false', help='y help')
2398 return parser
2399
2400 failures = ['-x X -y']
2401 successes = [
2402 ('-x X', NS(x='X', y=True)),
2403 ('-x X -x Y', NS(x='Y', y=True)),
2404 ('-y', NS(x=None, y=False)),
2405 ]
2406 successes_when_not_required = [
2407 ('', NS(x=None, y=True)),
2408 ]
2409
2410 usage_when_not_required = '''\
2411 usage: PROG [-h] [-y]
2412 '''
2413 usage_when_required = '''\
2414 usage: PROG [-h] -y
2415 '''
2416 help = '''\
2417
2418 optional arguments:
2419 -h, --help show this help message and exit
2420 -y y help
2421 '''
2422
2423
2424class TestMutuallyExclusiveManySuppressed(MEMixin, TestCase):
2425
2426 def get_parser(self, required):
2427 parser = ErrorRaisingArgumentParser(prog='PROG')
2428 group = parser.add_mutually_exclusive_group(required=required)
2429 add = group.add_argument
2430 add('--spam', action='store_true', help=argparse.SUPPRESS)
2431 add('--badger', action='store_false', help=argparse.SUPPRESS)
2432 add('--bladder', help=argparse.SUPPRESS)
2433 return parser
2434
2435 failures = [
2436 '--spam --badger',
2437 '--badger --bladder B',
2438 '--bladder B --spam',
2439 ]
2440 successes = [
2441 ('--spam', NS(spam=True, badger=True, bladder=None)),
2442 ('--badger', NS(spam=False, badger=False, bladder=None)),
2443 ('--bladder B', NS(spam=False, badger=True, bladder='B')),
2444 ('--spam --spam', NS(spam=True, badger=True, bladder=None)),
2445 ]
2446 successes_when_not_required = [
2447 ('', NS(spam=False, badger=True, bladder=None)),
2448 ]
2449
2450 usage_when_required = usage_when_not_required = '''\
2451 usage: PROG [-h]
2452 '''
2453 help = '''\
2454
2455 optional arguments:
2456 -h, --help show this help message and exit
2457 '''
2458
2459
2460class TestMutuallyExclusiveOptionalAndPositional(MEMixin, TestCase):
2461
2462 def get_parser(self, required):
2463 parser = ErrorRaisingArgumentParser(prog='PROG')
2464 group = parser.add_mutually_exclusive_group(required=required)
2465 group.add_argument('--foo', action='store_true', help='FOO')
2466 group.add_argument('--spam', help='SPAM')
2467 group.add_argument('badger', nargs='*', default='X', help='BADGER')
2468 return parser
2469
2470 failures = [
2471 '--foo --spam S',
2472 '--spam S X',
2473 'X --foo',
2474 'X Y Z --spam S',
2475 '--foo X Y',
2476 ]
2477 successes = [
2478 ('--foo', NS(foo=True, spam=None, badger='X')),
2479 ('--spam S', NS(foo=False, spam='S', badger='X')),
2480 ('X', NS(foo=False, spam=None, badger=['X'])),
2481 ('X Y Z', NS(foo=False, spam=None, badger=['X', 'Y', 'Z'])),
2482 ]
2483 successes_when_not_required = [
2484 ('', NS(foo=False, spam=None, badger='X')),
2485 ]
2486
2487 usage_when_not_required = '''\
2488 usage: PROG [-h] [--foo | --spam SPAM | badger [badger ...]]
2489 '''
2490 usage_when_required = '''\
2491 usage: PROG [-h] (--foo | --spam SPAM | badger [badger ...])
2492 '''
2493 help = '''\
2494
2495 positional arguments:
2496 badger BADGER
2497
2498 optional arguments:
2499 -h, --help show this help message and exit
2500 --foo FOO
2501 --spam SPAM SPAM
2502 '''
2503
2504
2505class TestMutuallyExclusiveOptionalsMixed(MEMixin, TestCase):
2506
2507 def get_parser(self, required):
2508 parser = ErrorRaisingArgumentParser(prog='PROG')
2509 parser.add_argument('-x', action='store_true', help='x help')
2510 group = parser.add_mutually_exclusive_group(required=required)
2511 group.add_argument('-a', action='store_true', help='a help')
2512 group.add_argument('-b', action='store_true', help='b help')
2513 parser.add_argument('-y', action='store_true', help='y help')
2514 group.add_argument('-c', action='store_true', help='c help')
2515 return parser
2516
2517 failures = ['-a -b', '-b -c', '-a -c', '-a -b -c']
2518 successes = [
2519 ('-a', NS(a=True, b=False, c=False, x=False, y=False)),
2520 ('-b', NS(a=False, b=True, c=False, x=False, y=False)),
2521 ('-c', NS(a=False, b=False, c=True, x=False, y=False)),
2522 ('-a -x', NS(a=True, b=False, c=False, x=True, y=False)),
2523 ('-y -b', NS(a=False, b=True, c=False, x=False, y=True)),
2524 ('-x -y -c', NS(a=False, b=False, c=True, x=True, y=True)),
2525 ]
2526 successes_when_not_required = [
2527 ('', NS(a=False, b=False, c=False, x=False, y=False)),
2528 ('-x', NS(a=False, b=False, c=False, x=True, y=False)),
2529 ('-y', NS(a=False, b=False, c=False, x=False, y=True)),
2530 ]
2531
2532 usage_when_required = usage_when_not_required = '''\
2533 usage: PROG [-h] [-x] [-a] [-b] [-y] [-c]
2534 '''
2535 help = '''\
2536
2537 optional arguments:
2538 -h, --help show this help message and exit
2539 -x x help
2540 -a a help
2541 -b b help
2542 -y y help
2543 -c c help
2544 '''
2545
2546
Georg Brandl0f6b47a2011-01-30 12:19:35 +00002547class TestMutuallyExclusiveInGroup(MEMixin, TestCase):
2548
2549 def get_parser(self, required=None):
2550 parser = ErrorRaisingArgumentParser(prog='PROG')
2551 titled_group = parser.add_argument_group(
2552 title='Titled group', description='Group description')
2553 mutex_group = \
2554 titled_group.add_mutually_exclusive_group(required=required)
2555 mutex_group.add_argument('--bar', help='bar help')
2556 mutex_group.add_argument('--baz', help='baz help')
2557 return parser
2558
2559 failures = ['--bar X --baz Y', '--baz X --bar Y']
2560 successes = [
2561 ('--bar X', NS(bar='X', baz=None)),
2562 ('--baz Y', NS(bar=None, baz='Y')),
2563 ]
2564 successes_when_not_required = [
2565 ('', NS(bar=None, baz=None)),
2566 ]
2567
2568 usage_when_not_required = '''\
2569 usage: PROG [-h] [--bar BAR | --baz BAZ]
2570 '''
2571 usage_when_required = '''\
2572 usage: PROG [-h] (--bar BAR | --baz BAZ)
2573 '''
2574 help = '''\
2575
2576 optional arguments:
2577 -h, --help show this help message and exit
2578
2579 Titled group:
2580 Group description
2581
2582 --bar BAR bar help
2583 --baz BAZ baz help
2584 '''
2585
2586
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002587class TestMutuallyExclusiveOptionalsAndPositionalsMixed(MEMixin, TestCase):
2588
2589 def get_parser(self, required):
2590 parser = ErrorRaisingArgumentParser(prog='PROG')
2591 parser.add_argument('x', help='x help')
2592 parser.add_argument('-y', action='store_true', help='y help')
2593 group = parser.add_mutually_exclusive_group(required=required)
2594 group.add_argument('a', nargs='?', help='a help')
2595 group.add_argument('-b', action='store_true', help='b help')
2596 group.add_argument('-c', action='store_true', help='c help')
2597 return parser
2598
2599 failures = ['X A -b', '-b -c', '-c X A']
2600 successes = [
2601 ('X A', NS(a='A', b=False, c=False, x='X', y=False)),
2602 ('X -b', NS(a=None, b=True, c=False, x='X', y=False)),
2603 ('X -c', NS(a=None, b=False, c=True, x='X', y=False)),
2604 ('X A -y', NS(a='A', b=False, c=False, x='X', y=True)),
2605 ('X -y -b', NS(a=None, b=True, c=False, x='X', y=True)),
2606 ]
2607 successes_when_not_required = [
2608 ('X', NS(a=None, b=False, c=False, x='X', y=False)),
2609 ('X -y', NS(a=None, b=False, c=False, x='X', y=True)),
2610 ]
2611
2612 usage_when_required = usage_when_not_required = '''\
2613 usage: PROG [-h] [-y] [-b] [-c] x [a]
2614 '''
2615 help = '''\
2616
2617 positional arguments:
2618 x x help
2619 a a help
2620
2621 optional arguments:
2622 -h, --help show this help message and exit
2623 -y y help
2624 -b b help
2625 -c c help
2626 '''
2627
2628# =================================================
2629# Mutually exclusive group in parent parser tests
2630# =================================================
2631
2632class MEPBase(object):
2633
2634 def get_parser(self, required=None):
2635 parent = super(MEPBase, self).get_parser(required=required)
2636 parser = ErrorRaisingArgumentParser(
2637 prog=parent.prog, add_help=False, parents=[parent])
2638 return parser
2639
2640
2641class TestMutuallyExclusiveGroupErrorsParent(
2642 MEPBase, TestMutuallyExclusiveGroupErrors):
2643 pass
2644
2645
2646class TestMutuallyExclusiveSimpleParent(
2647 MEPBase, TestMutuallyExclusiveSimple):
2648 pass
2649
2650
2651class TestMutuallyExclusiveLongParent(
2652 MEPBase, TestMutuallyExclusiveLong):
2653 pass
2654
2655
2656class TestMutuallyExclusiveFirstSuppressedParent(
2657 MEPBase, TestMutuallyExclusiveFirstSuppressed):
2658 pass
2659
2660
2661class TestMutuallyExclusiveManySuppressedParent(
2662 MEPBase, TestMutuallyExclusiveManySuppressed):
2663 pass
2664
2665
2666class TestMutuallyExclusiveOptionalAndPositionalParent(
2667 MEPBase, TestMutuallyExclusiveOptionalAndPositional):
2668 pass
2669
2670
2671class TestMutuallyExclusiveOptionalsMixedParent(
2672 MEPBase, TestMutuallyExclusiveOptionalsMixed):
2673 pass
2674
2675
2676class TestMutuallyExclusiveOptionalsAndPositionalsMixedParent(
2677 MEPBase, TestMutuallyExclusiveOptionalsAndPositionalsMixed):
2678 pass
2679
2680# =================
2681# Set default tests
2682# =================
2683
2684class TestSetDefaults(TestCase):
2685
2686 def test_set_defaults_no_args(self):
2687 parser = ErrorRaisingArgumentParser()
2688 parser.set_defaults(x='foo')
2689 parser.set_defaults(y='bar', z=1)
2690 self.assertEqual(NS(x='foo', y='bar', z=1),
2691 parser.parse_args([]))
2692 self.assertEqual(NS(x='foo', y='bar', z=1),
2693 parser.parse_args([], NS()))
2694 self.assertEqual(NS(x='baz', y='bar', z=1),
2695 parser.parse_args([], NS(x='baz')))
2696 self.assertEqual(NS(x='baz', y='bar', z=2),
2697 parser.parse_args([], NS(x='baz', z=2)))
2698
2699 def test_set_defaults_with_args(self):
2700 parser = ErrorRaisingArgumentParser()
2701 parser.set_defaults(x='foo', y='bar')
2702 parser.add_argument('-x', default='xfoox')
2703 self.assertEqual(NS(x='xfoox', y='bar'),
2704 parser.parse_args([]))
2705 self.assertEqual(NS(x='xfoox', y='bar'),
2706 parser.parse_args([], NS()))
2707 self.assertEqual(NS(x='baz', y='bar'),
2708 parser.parse_args([], NS(x='baz')))
2709 self.assertEqual(NS(x='1', y='bar'),
2710 parser.parse_args('-x 1'.split()))
2711 self.assertEqual(NS(x='1', y='bar'),
2712 parser.parse_args('-x 1'.split(), NS()))
2713 self.assertEqual(NS(x='1', y='bar'),
2714 parser.parse_args('-x 1'.split(), NS(x='baz')))
2715
2716 def test_set_defaults_subparsers(self):
2717 parser = ErrorRaisingArgumentParser()
2718 parser.set_defaults(x='foo')
2719 subparsers = parser.add_subparsers()
2720 parser_a = subparsers.add_parser('a')
2721 parser_a.set_defaults(y='bar')
2722 self.assertEqual(NS(x='foo', y='bar'),
2723 parser.parse_args('a'.split()))
2724
2725 def test_set_defaults_parents(self):
2726 parent = ErrorRaisingArgumentParser(add_help=False)
2727 parent.set_defaults(x='foo')
2728 parser = ErrorRaisingArgumentParser(parents=[parent])
2729 self.assertEqual(NS(x='foo'), parser.parse_args([]))
2730
2731 def test_set_defaults_same_as_add_argument(self):
2732 parser = ErrorRaisingArgumentParser()
2733 parser.set_defaults(w='W', x='X', y='Y', z='Z')
2734 parser.add_argument('-w')
2735 parser.add_argument('-x', default='XX')
2736 parser.add_argument('y', nargs='?')
2737 parser.add_argument('z', nargs='?', default='ZZ')
2738
2739 # defaults set previously
2740 self.assertEqual(NS(w='W', x='XX', y='Y', z='ZZ'),
2741 parser.parse_args([]))
2742
2743 # reset defaults
2744 parser.set_defaults(w='WW', x='X', y='YY', z='Z')
2745 self.assertEqual(NS(w='WW', x='X', y='YY', z='Z'),
2746 parser.parse_args([]))
2747
2748 def test_set_defaults_same_as_add_argument_group(self):
2749 parser = ErrorRaisingArgumentParser()
2750 parser.set_defaults(w='W', x='X', y='Y', z='Z')
2751 group = parser.add_argument_group('foo')
2752 group.add_argument('-w')
2753 group.add_argument('-x', default='XX')
2754 group.add_argument('y', nargs='?')
2755 group.add_argument('z', nargs='?', default='ZZ')
2756
2757
2758 # defaults set previously
2759 self.assertEqual(NS(w='W', x='XX', y='Y', z='ZZ'),
2760 parser.parse_args([]))
2761
2762 # reset defaults
2763 parser.set_defaults(w='WW', x='X', y='YY', z='Z')
2764 self.assertEqual(NS(w='WW', x='X', y='YY', z='Z'),
2765 parser.parse_args([]))
2766
2767# =================
2768# Get default tests
2769# =================
2770
2771class TestGetDefault(TestCase):
2772
2773 def test_get_default(self):
2774 parser = ErrorRaisingArgumentParser()
2775 self.assertEqual(None, parser.get_default("foo"))
2776 self.assertEqual(None, parser.get_default("bar"))
2777
2778 parser.add_argument("--foo")
2779 self.assertEqual(None, parser.get_default("foo"))
2780 self.assertEqual(None, parser.get_default("bar"))
2781
2782 parser.add_argument("--bar", type=int, default=42)
2783 self.assertEqual(None, parser.get_default("foo"))
2784 self.assertEqual(42, parser.get_default("bar"))
2785
2786 parser.set_defaults(foo="badger")
2787 self.assertEqual("badger", parser.get_default("foo"))
2788 self.assertEqual(42, parser.get_default("bar"))
2789
2790# ==========================
2791# Namespace 'contains' tests
2792# ==========================
2793
2794class TestNamespaceContainsSimple(TestCase):
2795
2796 def test_empty(self):
2797 ns = argparse.Namespace()
Ezio Melottib3aedd42010-11-20 19:04:17 +00002798 self.assertEqual('' in ns, False)
2799 self.assertEqual('' not in ns, True)
2800 self.assertEqual('x' in ns, False)
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002801
2802 def test_non_empty(self):
2803 ns = argparse.Namespace(x=1, y=2)
Ezio Melottib3aedd42010-11-20 19:04:17 +00002804 self.assertEqual('x' in ns, True)
2805 self.assertEqual('x' not in ns, False)
2806 self.assertEqual('y' in ns, True)
2807 self.assertEqual('' in ns, False)
2808 self.assertEqual('xx' in ns, False)
2809 self.assertEqual('z' in ns, False)
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002810
2811# =====================
2812# Help formatting tests
2813# =====================
2814
2815class TestHelpFormattingMetaclass(type):
2816
2817 def __init__(cls, name, bases, bodydict):
2818 if name == 'HelpTestCase':
2819 return
2820
2821 class AddTests(object):
2822
2823 def __init__(self, test_class, func_suffix, std_name):
2824 self.func_suffix = func_suffix
2825 self.std_name = std_name
2826
2827 for test_func in [self.test_format,
2828 self.test_print,
2829 self.test_print_file]:
2830 test_name = '%s_%s' % (test_func.__name__, func_suffix)
2831
2832 def test_wrapper(self, test_func=test_func):
2833 test_func(self)
2834 try:
2835 test_wrapper.__name__ = test_name
2836 except TypeError:
2837 pass
2838 setattr(test_class, test_name, test_wrapper)
2839
2840 def _get_parser(self, tester):
2841 parser = argparse.ArgumentParser(
2842 *tester.parser_signature.args,
2843 **tester.parser_signature.kwargs)
Steven Bethard8a6a1982011-03-27 13:53:53 +02002844 for argument_sig in getattr(tester, 'argument_signatures', []):
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002845 parser.add_argument(*argument_sig.args,
2846 **argument_sig.kwargs)
Steven Bethard8a6a1982011-03-27 13:53:53 +02002847 group_sigs = getattr(tester, 'argument_group_signatures', [])
2848 for group_sig, argument_sigs in group_sigs:
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002849 group = parser.add_argument_group(*group_sig.args,
2850 **group_sig.kwargs)
2851 for argument_sig in argument_sigs:
2852 group.add_argument(*argument_sig.args,
2853 **argument_sig.kwargs)
Steven Bethard8a6a1982011-03-27 13:53:53 +02002854 subparsers_sigs = getattr(tester, 'subparsers_signatures', [])
2855 if subparsers_sigs:
2856 subparsers = parser.add_subparsers()
2857 for subparser_sig in subparsers_sigs:
2858 subparsers.add_parser(*subparser_sig.args,
2859 **subparser_sig.kwargs)
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002860 return parser
2861
2862 def _test(self, tester, parser_text):
2863 expected_text = getattr(tester, self.func_suffix)
2864 expected_text = textwrap.dedent(expected_text)
2865 if expected_text != parser_text:
2866 print(repr(expected_text))
2867 print(repr(parser_text))
2868 for char1, char2 in zip(expected_text, parser_text):
2869 if char1 != char2:
2870 print('first diff: %r %r' % (char1, char2))
2871 break
2872 tester.assertEqual(expected_text, parser_text)
2873
2874 def test_format(self, tester):
2875 parser = self._get_parser(tester)
2876 format = getattr(parser, 'format_%s' % self.func_suffix)
2877 self._test(tester, format())
2878
2879 def test_print(self, tester):
2880 parser = self._get_parser(tester)
2881 print_ = getattr(parser, 'print_%s' % self.func_suffix)
2882 old_stream = getattr(sys, self.std_name)
Benjamin Petersonb48af542010-04-11 20:43:16 +00002883 setattr(sys, self.std_name, StdIOBuffer())
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002884 try:
2885 print_()
2886 parser_text = getattr(sys, self.std_name).getvalue()
2887 finally:
2888 setattr(sys, self.std_name, old_stream)
2889 self._test(tester, parser_text)
2890
2891 def test_print_file(self, tester):
2892 parser = self._get_parser(tester)
2893 print_ = getattr(parser, 'print_%s' % self.func_suffix)
Benjamin Petersonb48af542010-04-11 20:43:16 +00002894 sfile = StdIOBuffer()
Benjamin Peterson698a18a2010-03-02 22:34:37 +00002895 print_(sfile)
2896 parser_text = sfile.getvalue()
2897 self._test(tester, parser_text)
2898
2899 # add tests for {format,print}_{usage,help,version}
2900 for func_suffix, std_name in [('usage', 'stdout'),
2901 ('help', 'stdout'),
2902 ('version', 'stderr')]:
2903 AddTests(cls, func_suffix, std_name)
2904
2905bases = TestCase,
2906HelpTestCase = TestHelpFormattingMetaclass('HelpTestCase', bases, {})
2907
2908
2909class TestHelpBiggerOptionals(HelpTestCase):
2910 """Make sure that argument help aligns when options are longer"""
2911
2912 parser_signature = Sig(prog='PROG', description='DESCRIPTION',
2913 epilog='EPILOG', version='0.1')
2914 argument_signatures = [
2915 Sig('-x', action='store_true', help='X HELP'),
2916 Sig('--y', help='Y HELP'),
2917 Sig('foo', help='FOO HELP'),
2918 Sig('bar', help='BAR HELP'),
2919 ]
2920 argument_group_signatures = []
2921 usage = '''\
2922 usage: PROG [-h] [-v] [-x] [--y Y] foo bar
2923 '''
2924 help = usage + '''\
2925
2926 DESCRIPTION
2927
2928 positional arguments:
2929 foo FOO HELP
2930 bar BAR HELP
2931
2932 optional arguments:
2933 -h, --help show this help message and exit
2934 -v, --version show program's version number and exit
2935 -x X HELP
2936 --y Y Y HELP
2937
2938 EPILOG
2939 '''
2940 version = '''\
2941 0.1
2942 '''
2943
2944
2945class TestHelpBiggerOptionalGroups(HelpTestCase):
2946 """Make sure that argument help aligns when options are longer"""
2947
2948 parser_signature = Sig(prog='PROG', description='DESCRIPTION',
2949 epilog='EPILOG', version='0.1')
2950 argument_signatures = [
2951 Sig('-x', action='store_true', help='X HELP'),
2952 Sig('--y', help='Y HELP'),
2953 Sig('foo', help='FOO HELP'),
2954 Sig('bar', help='BAR HELP'),
2955 ]
2956 argument_group_signatures = [
2957 (Sig('GROUP TITLE', description='GROUP DESCRIPTION'), [
2958 Sig('baz', help='BAZ HELP'),
2959 Sig('-z', nargs='+', help='Z HELP')]),
2960 ]
2961 usage = '''\
2962 usage: PROG [-h] [-v] [-x] [--y Y] [-z Z [Z ...]] foo bar baz
2963 '''
2964 help = usage + '''\
2965
2966 DESCRIPTION
2967
2968 positional arguments:
2969 foo FOO HELP
2970 bar BAR HELP
2971
2972 optional arguments:
2973 -h, --help show this help message and exit
2974 -v, --version show program's version number and exit
2975 -x X HELP
2976 --y Y Y HELP
2977
2978 GROUP TITLE:
2979 GROUP DESCRIPTION
2980
2981 baz BAZ HELP
2982 -z Z [Z ...] Z HELP
2983
2984 EPILOG
2985 '''
2986 version = '''\
2987 0.1
2988 '''
2989
2990
2991class TestHelpBiggerPositionals(HelpTestCase):
2992 """Make sure that help aligns when arguments are longer"""
2993
2994 parser_signature = Sig(usage='USAGE', description='DESCRIPTION')
2995 argument_signatures = [
2996 Sig('-x', action='store_true', help='X HELP'),
2997 Sig('--y', help='Y HELP'),
2998 Sig('ekiekiekifekang', help='EKI HELP'),
2999 Sig('bar', help='BAR HELP'),
3000 ]
3001 argument_group_signatures = []
3002 usage = '''\
3003 usage: USAGE
3004 '''
3005 help = usage + '''\
3006
3007 DESCRIPTION
3008
3009 positional arguments:
3010 ekiekiekifekang EKI HELP
3011 bar BAR HELP
3012
3013 optional arguments:
3014 -h, --help show this help message and exit
3015 -x X HELP
3016 --y Y Y HELP
3017 '''
3018
3019 version = ''
3020
3021
3022class TestHelpReformatting(HelpTestCase):
3023 """Make sure that text after short names starts on the first line"""
3024
3025 parser_signature = Sig(
3026 prog='PROG',
3027 description=' oddly formatted\n'
3028 'description\n'
3029 '\n'
3030 'that is so long that it should go onto multiple '
3031 'lines when wrapped')
3032 argument_signatures = [
3033 Sig('-x', metavar='XX', help='oddly\n'
3034 ' formatted -x help'),
3035 Sig('y', metavar='yyy', help='normal y help'),
3036 ]
3037 argument_group_signatures = [
3038 (Sig('title', description='\n'
3039 ' oddly formatted group\n'
3040 '\n'
3041 'description'),
3042 [Sig('-a', action='store_true',
3043 help=' oddly \n'
3044 'formatted -a help \n'
3045 ' again, so long that it should be wrapped over '
3046 'multiple lines')]),
3047 ]
3048 usage = '''\
3049 usage: PROG [-h] [-x XX] [-a] yyy
3050 '''
3051 help = usage + '''\
3052
3053 oddly formatted description that is so long that it should go onto \
3054multiple
3055 lines when wrapped
3056
3057 positional arguments:
3058 yyy normal y help
3059
3060 optional arguments:
3061 -h, --help show this help message and exit
3062 -x XX oddly formatted -x help
3063
3064 title:
3065 oddly formatted group description
3066
3067 -a oddly formatted -a help again, so long that it should \
3068be wrapped
3069 over multiple lines
3070 '''
3071 version = ''
3072
3073
3074class TestHelpWrappingShortNames(HelpTestCase):
3075 """Make sure that text after short names starts on the first line"""
3076
3077 parser_signature = Sig(prog='PROG', description= 'D\nD' * 30)
3078 argument_signatures = [
3079 Sig('-x', metavar='XX', help='XHH HX' * 20),
3080 Sig('y', metavar='yyy', help='YH YH' * 20),
3081 ]
3082 argument_group_signatures = [
3083 (Sig('ALPHAS'), [
3084 Sig('-a', action='store_true', help='AHHH HHA' * 10)]),
3085 ]
3086 usage = '''\
3087 usage: PROG [-h] [-x XX] [-a] yyy
3088 '''
3089 help = usage + '''\
3090
3091 D DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD \
3092DD DD DD
3093 DD DD DD DD D
3094
3095 positional arguments:
3096 yyy YH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH \
3097YHYH YHYH
3098 YHYH YHYH YHYH YHYH YHYH YHYH YHYH YH
3099
3100 optional arguments:
3101 -h, --help show this help message and exit
3102 -x XX XHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH \
3103HXXHH HXXHH
3104 HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HX
3105
3106 ALPHAS:
3107 -a AHHH HHAAHHH HHAAHHH HHAAHHH HHAAHHH HHAAHHH HHAAHHH \
3108HHAAHHH
3109 HHAAHHH HHAAHHH HHA
3110 '''
3111 version = ''
3112
3113
3114class TestHelpWrappingLongNames(HelpTestCase):
3115 """Make sure that text after long names starts on the next line"""
3116
3117 parser_signature = Sig(usage='USAGE', description= 'D D' * 30,
3118 version='V V'*30)
3119 argument_signatures = [
3120 Sig('-x', metavar='X' * 25, help='XH XH' * 20),
3121 Sig('y', metavar='y' * 25, help='YH YH' * 20),
3122 ]
3123 argument_group_signatures = [
3124 (Sig('ALPHAS'), [
3125 Sig('-a', metavar='A' * 25, help='AH AH' * 20),
3126 Sig('z', metavar='z' * 25, help='ZH ZH' * 20)]),
3127 ]
3128 usage = '''\
3129 usage: USAGE
3130 '''
3131 help = usage + '''\
3132
3133 D DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD \
3134DD DD DD
3135 DD DD DD DD D
3136
3137 positional arguments:
3138 yyyyyyyyyyyyyyyyyyyyyyyyy
3139 YH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH \
3140YHYH YHYH
3141 YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YH
3142
3143 optional arguments:
3144 -h, --help show this help message and exit
3145 -v, --version show program's version number and exit
3146 -x XXXXXXXXXXXXXXXXXXXXXXXXX
3147 XH XHXH XHXH XHXH XHXH XHXH XHXH XHXH XHXH \
3148XHXH XHXH
3149 XHXH XHXH XHXH XHXH XHXH XHXH XHXH XHXH XHXH XH
3150
3151 ALPHAS:
3152 -a AAAAAAAAAAAAAAAAAAAAAAAAA
3153 AH AHAH AHAH AHAH AHAH AHAH AHAH AHAH AHAH \
3154AHAH AHAH
3155 AHAH AHAH AHAH AHAH AHAH AHAH AHAH AHAH AHAH AH
3156 zzzzzzzzzzzzzzzzzzzzzzzzz
3157 ZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH \
3158ZHZH ZHZH
3159 ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZH
3160 '''
3161 version = '''\
3162 V VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV \
3163VV VV VV
3164 VV VV VV VV V
3165 '''
3166
3167
3168class TestHelpUsage(HelpTestCase):
3169 """Test basic usage messages"""
3170
3171 parser_signature = Sig(prog='PROG')
3172 argument_signatures = [
3173 Sig('-w', nargs='+', help='w'),
3174 Sig('-x', nargs='*', help='x'),
3175 Sig('a', help='a'),
3176 Sig('b', help='b', nargs=2),
3177 Sig('c', help='c', nargs='?'),
3178 ]
3179 argument_group_signatures = [
3180 (Sig('group'), [
3181 Sig('-y', nargs='?', help='y'),
3182 Sig('-z', nargs=3, help='z'),
3183 Sig('d', help='d', nargs='*'),
3184 Sig('e', help='e', nargs='+'),
3185 ])
3186 ]
3187 usage = '''\
3188 usage: PROG [-h] [-w W [W ...]] [-x [X [X ...]]] [-y [Y]] [-z Z Z Z]
3189 a b b [c] [d [d ...]] e [e ...]
3190 '''
3191 help = usage + '''\
3192
3193 positional arguments:
3194 a a
3195 b b
3196 c c
3197
3198 optional arguments:
3199 -h, --help show this help message and exit
3200 -w W [W ...] w
3201 -x [X [X ...]] x
3202
3203 group:
3204 -y [Y] y
3205 -z Z Z Z z
3206 d d
3207 e e
3208 '''
3209 version = ''
3210
3211
3212class TestHelpOnlyUserGroups(HelpTestCase):
3213 """Test basic usage messages"""
3214
3215 parser_signature = Sig(prog='PROG', add_help=False)
3216 argument_signatures = []
3217 argument_group_signatures = [
3218 (Sig('xxxx'), [
3219 Sig('-x', help='x'),
3220 Sig('a', help='a'),
3221 ]),
3222 (Sig('yyyy'), [
3223 Sig('b', help='b'),
3224 Sig('-y', help='y'),
3225 ]),
3226 ]
3227 usage = '''\
3228 usage: PROG [-x X] [-y Y] a b
3229 '''
3230 help = usage + '''\
3231
3232 xxxx:
3233 -x X x
3234 a a
3235
3236 yyyy:
3237 b b
3238 -y Y y
3239 '''
3240 version = ''
3241
3242
3243class TestHelpUsageLongProg(HelpTestCase):
3244 """Test usage messages where the prog is long"""
3245
3246 parser_signature = Sig(prog='P' * 60)
3247 argument_signatures = [
3248 Sig('-w', metavar='W'),
3249 Sig('-x', metavar='X'),
3250 Sig('a'),
3251 Sig('b'),
3252 ]
3253 argument_group_signatures = []
3254 usage = '''\
3255 usage: PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
3256 [-h] [-w W] [-x X] a b
3257 '''
3258 help = usage + '''\
3259
3260 positional arguments:
3261 a
3262 b
3263
3264 optional arguments:
3265 -h, --help show this help message and exit
3266 -w W
3267 -x X
3268 '''
3269 version = ''
3270
3271
3272class TestHelpUsageLongProgOptionsWrap(HelpTestCase):
3273 """Test usage messages where the prog is long and the optionals wrap"""
3274
3275 parser_signature = Sig(prog='P' * 60)
3276 argument_signatures = [
3277 Sig('-w', metavar='W' * 25),
3278 Sig('-x', metavar='X' * 25),
3279 Sig('-y', metavar='Y' * 25),
3280 Sig('-z', metavar='Z' * 25),
3281 Sig('a'),
3282 Sig('b'),
3283 ]
3284 argument_group_signatures = []
3285 usage = '''\
3286 usage: PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
3287 [-h] [-w WWWWWWWWWWWWWWWWWWWWWWWWW] \
3288[-x XXXXXXXXXXXXXXXXXXXXXXXXX]
3289 [-y YYYYYYYYYYYYYYYYYYYYYYYYY] [-z ZZZZZZZZZZZZZZZZZZZZZZZZZ]
3290 a b
3291 '''
3292 help = usage + '''\
3293
3294 positional arguments:
3295 a
3296 b
3297
3298 optional arguments:
3299 -h, --help show this help message and exit
3300 -w WWWWWWWWWWWWWWWWWWWWWWWWW
3301 -x XXXXXXXXXXXXXXXXXXXXXXXXX
3302 -y YYYYYYYYYYYYYYYYYYYYYYYYY
3303 -z ZZZZZZZZZZZZZZZZZZZZZZZZZ
3304 '''
3305 version = ''
3306
3307
3308class TestHelpUsageLongProgPositionalsWrap(HelpTestCase):
3309 """Test usage messages where the prog is long and the positionals wrap"""
3310
3311 parser_signature = Sig(prog='P' * 60, add_help=False)
3312 argument_signatures = [
3313 Sig('a' * 25),
3314 Sig('b' * 25),
3315 Sig('c' * 25),
3316 ]
3317 argument_group_signatures = []
3318 usage = '''\
3319 usage: PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
3320 aaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbb
3321 ccccccccccccccccccccccccc
3322 '''
3323 help = usage + '''\
3324
3325 positional arguments:
3326 aaaaaaaaaaaaaaaaaaaaaaaaa
3327 bbbbbbbbbbbbbbbbbbbbbbbbb
3328 ccccccccccccccccccccccccc
3329 '''
3330 version = ''
3331
3332
3333class TestHelpUsageOptionalsWrap(HelpTestCase):
3334 """Test usage messages where the optionals wrap"""
3335
3336 parser_signature = Sig(prog='PROG')
3337 argument_signatures = [
3338 Sig('-w', metavar='W' * 25),
3339 Sig('-x', metavar='X' * 25),
3340 Sig('-y', metavar='Y' * 25),
3341 Sig('-z', metavar='Z' * 25),
3342 Sig('a'),
3343 Sig('b'),
3344 Sig('c'),
3345 ]
3346 argument_group_signatures = []
3347 usage = '''\
3348 usage: PROG [-h] [-w WWWWWWWWWWWWWWWWWWWWWWWWW] \
3349[-x XXXXXXXXXXXXXXXXXXXXXXXXX]
3350 [-y YYYYYYYYYYYYYYYYYYYYYYYYY] \
3351[-z ZZZZZZZZZZZZZZZZZZZZZZZZZ]
3352 a b c
3353 '''
3354 help = usage + '''\
3355
3356 positional arguments:
3357 a
3358 b
3359 c
3360
3361 optional arguments:
3362 -h, --help show this help message and exit
3363 -w WWWWWWWWWWWWWWWWWWWWWWWWW
3364 -x XXXXXXXXXXXXXXXXXXXXXXXXX
3365 -y YYYYYYYYYYYYYYYYYYYYYYYYY
3366 -z ZZZZZZZZZZZZZZZZZZZZZZZZZ
3367 '''
3368 version = ''
3369
3370
3371class TestHelpUsagePositionalsWrap(HelpTestCase):
3372 """Test usage messages where the positionals wrap"""
3373
3374 parser_signature = Sig(prog='PROG')
3375 argument_signatures = [
3376 Sig('-x'),
3377 Sig('-y'),
3378 Sig('-z'),
3379 Sig('a' * 25),
3380 Sig('b' * 25),
3381 Sig('c' * 25),
3382 ]
3383 argument_group_signatures = []
3384 usage = '''\
3385 usage: PROG [-h] [-x X] [-y Y] [-z Z]
3386 aaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbb
3387 ccccccccccccccccccccccccc
3388 '''
3389 help = usage + '''\
3390
3391 positional arguments:
3392 aaaaaaaaaaaaaaaaaaaaaaaaa
3393 bbbbbbbbbbbbbbbbbbbbbbbbb
3394 ccccccccccccccccccccccccc
3395
3396 optional arguments:
3397 -h, --help show this help message and exit
3398 -x X
3399 -y Y
3400 -z Z
3401 '''
3402 version = ''
3403
3404
3405class TestHelpUsageOptionalsPositionalsWrap(HelpTestCase):
3406 """Test usage messages where the optionals and positionals wrap"""
3407
3408 parser_signature = Sig(prog='PROG')
3409 argument_signatures = [
3410 Sig('-x', metavar='X' * 25),
3411 Sig('-y', metavar='Y' * 25),
3412 Sig('-z', metavar='Z' * 25),
3413 Sig('a' * 25),
3414 Sig('b' * 25),
3415 Sig('c' * 25),
3416 ]
3417 argument_group_signatures = []
3418 usage = '''\
3419 usage: PROG [-h] [-x XXXXXXXXXXXXXXXXXXXXXXXXX] \
3420[-y YYYYYYYYYYYYYYYYYYYYYYYYY]
3421 [-z ZZZZZZZZZZZZZZZZZZZZZZZZZ]
3422 aaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbb
3423 ccccccccccccccccccccccccc
3424 '''
3425 help = usage + '''\
3426
3427 positional arguments:
3428 aaaaaaaaaaaaaaaaaaaaaaaaa
3429 bbbbbbbbbbbbbbbbbbbbbbbbb
3430 ccccccccccccccccccccccccc
3431
3432 optional arguments:
3433 -h, --help show this help message and exit
3434 -x XXXXXXXXXXXXXXXXXXXXXXXXX
3435 -y YYYYYYYYYYYYYYYYYYYYYYYYY
3436 -z ZZZZZZZZZZZZZZZZZZZZZZZZZ
3437 '''
3438 version = ''
3439
3440
3441class TestHelpUsageOptionalsOnlyWrap(HelpTestCase):
3442 """Test usage messages where there are only optionals and they wrap"""
3443
3444 parser_signature = Sig(prog='PROG')
3445 argument_signatures = [
3446 Sig('-x', metavar='X' * 25),
3447 Sig('-y', metavar='Y' * 25),
3448 Sig('-z', metavar='Z' * 25),
3449 ]
3450 argument_group_signatures = []
3451 usage = '''\
3452 usage: PROG [-h] [-x XXXXXXXXXXXXXXXXXXXXXXXXX] \
3453[-y YYYYYYYYYYYYYYYYYYYYYYYYY]
3454 [-z ZZZZZZZZZZZZZZZZZZZZZZZZZ]
3455 '''
3456 help = usage + '''\
3457
3458 optional arguments:
3459 -h, --help show this help message and exit
3460 -x XXXXXXXXXXXXXXXXXXXXXXXXX
3461 -y YYYYYYYYYYYYYYYYYYYYYYYYY
3462 -z ZZZZZZZZZZZZZZZZZZZZZZZZZ
3463 '''
3464 version = ''
3465
3466
3467class TestHelpUsagePositionalsOnlyWrap(HelpTestCase):
3468 """Test usage messages where there are only positionals and they wrap"""
3469
3470 parser_signature = Sig(prog='PROG', add_help=False)
3471 argument_signatures = [
3472 Sig('a' * 25),
3473 Sig('b' * 25),
3474 Sig('c' * 25),
3475 ]
3476 argument_group_signatures = []
3477 usage = '''\
3478 usage: PROG aaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbb
3479 ccccccccccccccccccccccccc
3480 '''
3481 help = usage + '''\
3482
3483 positional arguments:
3484 aaaaaaaaaaaaaaaaaaaaaaaaa
3485 bbbbbbbbbbbbbbbbbbbbbbbbb
3486 ccccccccccccccccccccccccc
3487 '''
3488 version = ''
3489
3490
3491class TestHelpVariableExpansion(HelpTestCase):
3492 """Test that variables are expanded properly in help messages"""
3493
3494 parser_signature = Sig(prog='PROG')
3495 argument_signatures = [
3496 Sig('-x', type=int,
3497 help='x %(prog)s %(default)s %(type)s %%'),
3498 Sig('-y', action='store_const', default=42, const='XXX',
3499 help='y %(prog)s %(default)s %(const)s'),
3500 Sig('--foo', choices='abc',
3501 help='foo %(prog)s %(default)s %(choices)s'),
3502 Sig('--bar', default='baz', choices=[1, 2], metavar='BBB',
3503 help='bar %(prog)s %(default)s %(dest)s'),
3504 Sig('spam', help='spam %(prog)s %(default)s'),
3505 Sig('badger', default=0.5, help='badger %(prog)s %(default)s'),
3506 ]
3507 argument_group_signatures = [
3508 (Sig('group'), [
3509 Sig('-a', help='a %(prog)s %(default)s'),
3510 Sig('-b', default=-1, help='b %(prog)s %(default)s'),
3511 ])
3512 ]
3513 usage = ('''\
3514 usage: PROG [-h] [-x X] [-y] [--foo {a,b,c}] [--bar BBB] [-a A] [-b B]
3515 spam badger
3516 ''')
3517 help = usage + '''\
3518
3519 positional arguments:
3520 spam spam PROG None
3521 badger badger PROG 0.5
3522
3523 optional arguments:
3524 -h, --help show this help message and exit
3525 -x X x PROG None int %
3526 -y y PROG 42 XXX
3527 --foo {a,b,c} foo PROG None a, b, c
3528 --bar BBB bar PROG baz bar
3529
3530 group:
3531 -a A a PROG None
3532 -b B b PROG -1
3533 '''
3534 version = ''
3535
3536
3537class TestHelpVariableExpansionUsageSupplied(HelpTestCase):
3538 """Test that variables are expanded properly when usage= is present"""
3539
3540 parser_signature = Sig(prog='PROG', usage='%(prog)s FOO')
3541 argument_signatures = []
3542 argument_group_signatures = []
3543 usage = ('''\
3544 usage: PROG FOO
3545 ''')
3546 help = usage + '''\
3547
3548 optional arguments:
3549 -h, --help show this help message and exit
3550 '''
3551 version = ''
3552
3553
3554class TestHelpVariableExpansionNoArguments(HelpTestCase):
3555 """Test that variables are expanded properly with no arguments"""
3556
3557 parser_signature = Sig(prog='PROG', add_help=False)
3558 argument_signatures = []
3559 argument_group_signatures = []
3560 usage = ('''\
3561 usage: PROG
3562 ''')
3563 help = usage
3564 version = ''
3565
3566
3567class TestHelpSuppressUsage(HelpTestCase):
3568 """Test that items can be suppressed in usage messages"""
3569
3570 parser_signature = Sig(prog='PROG', usage=argparse.SUPPRESS)
3571 argument_signatures = [
3572 Sig('--foo', help='foo help'),
3573 Sig('spam', help='spam help'),
3574 ]
3575 argument_group_signatures = []
3576 help = '''\
3577 positional arguments:
3578 spam spam help
3579
3580 optional arguments:
3581 -h, --help show this help message and exit
3582 --foo FOO foo help
3583 '''
3584 usage = ''
3585 version = ''
3586
3587
3588class TestHelpSuppressOptional(HelpTestCase):
3589 """Test that optional arguments can be suppressed in help messages"""
3590
3591 parser_signature = Sig(prog='PROG', add_help=False)
3592 argument_signatures = [
3593 Sig('--foo', help=argparse.SUPPRESS),
3594 Sig('spam', help='spam help'),
3595 ]
3596 argument_group_signatures = []
3597 usage = '''\
3598 usage: PROG spam
3599 '''
3600 help = usage + '''\
3601
3602 positional arguments:
3603 spam spam help
3604 '''
3605 version = ''
3606
3607
3608class TestHelpSuppressOptionalGroup(HelpTestCase):
3609 """Test that optional groups can be suppressed in help messages"""
3610
3611 parser_signature = Sig(prog='PROG')
3612 argument_signatures = [
3613 Sig('--foo', help='foo help'),
3614 Sig('spam', help='spam help'),
3615 ]
3616 argument_group_signatures = [
3617 (Sig('group'), [Sig('--bar', help=argparse.SUPPRESS)]),
3618 ]
3619 usage = '''\
3620 usage: PROG [-h] [--foo FOO] spam
3621 '''
3622 help = usage + '''\
3623
3624 positional arguments:
3625 spam spam help
3626
3627 optional arguments:
3628 -h, --help show this help message and exit
3629 --foo FOO foo help
3630 '''
3631 version = ''
3632
3633
3634class TestHelpSuppressPositional(HelpTestCase):
3635 """Test that positional arguments can be suppressed in help messages"""
3636
3637 parser_signature = Sig(prog='PROG')
3638 argument_signatures = [
3639 Sig('--foo', help='foo help'),
3640 Sig('spam', help=argparse.SUPPRESS),
3641 ]
3642 argument_group_signatures = []
3643 usage = '''\
3644 usage: PROG [-h] [--foo FOO]
3645 '''
3646 help = usage + '''\
3647
3648 optional arguments:
3649 -h, --help show this help message and exit
3650 --foo FOO foo help
3651 '''
3652 version = ''
3653
3654
3655class TestHelpRequiredOptional(HelpTestCase):
3656 """Test that required options don't look optional"""
3657
3658 parser_signature = Sig(prog='PROG')
3659 argument_signatures = [
3660 Sig('--foo', required=True, help='foo help'),
3661 ]
3662 argument_group_signatures = []
3663 usage = '''\
3664 usage: PROG [-h] --foo FOO
3665 '''
3666 help = usage + '''\
3667
3668 optional arguments:
3669 -h, --help show this help message and exit
3670 --foo FOO foo help
3671 '''
3672 version = ''
3673
3674
3675class TestHelpAlternatePrefixChars(HelpTestCase):
3676 """Test that options display with different prefix characters"""
3677
3678 parser_signature = Sig(prog='PROG', prefix_chars='^;', add_help=False)
3679 argument_signatures = [
3680 Sig('^^foo', action='store_true', help='foo help'),
3681 Sig(';b', ';;bar', help='bar help'),
3682 ]
3683 argument_group_signatures = []
3684 usage = '''\
3685 usage: PROG [^^foo] [;b BAR]
3686 '''
3687 help = usage + '''\
3688
3689 optional arguments:
3690 ^^foo foo help
3691 ;b BAR, ;;bar BAR bar help
3692 '''
3693 version = ''
3694
3695
3696class TestHelpNoHelpOptional(HelpTestCase):
3697 """Test that the --help argument can be suppressed help messages"""
3698
3699 parser_signature = Sig(prog='PROG', add_help=False)
3700 argument_signatures = [
3701 Sig('--foo', help='foo help'),
3702 Sig('spam', help='spam help'),
3703 ]
3704 argument_group_signatures = []
3705 usage = '''\
3706 usage: PROG [--foo FOO] spam
3707 '''
3708 help = usage + '''\
3709
3710 positional arguments:
3711 spam spam help
3712
3713 optional arguments:
3714 --foo FOO foo help
3715 '''
3716 version = ''
3717
3718
3719class TestHelpVersionOptional(HelpTestCase):
3720 """Test that the --version argument can be suppressed help messages"""
3721
3722 parser_signature = Sig(prog='PROG', version='1.0')
3723 argument_signatures = [
3724 Sig('--foo', help='foo help'),
3725 Sig('spam', help='spam help'),
3726 ]
3727 argument_group_signatures = []
3728 usage = '''\
3729 usage: PROG [-h] [-v] [--foo FOO] spam
3730 '''
3731 help = usage + '''\
3732
3733 positional arguments:
3734 spam spam help
3735
3736 optional arguments:
3737 -h, --help show this help message and exit
3738 -v, --version show program's version number and exit
3739 --foo FOO foo help
3740 '''
3741 version = '''\
3742 1.0
3743 '''
3744
3745
3746class TestHelpNone(HelpTestCase):
3747 """Test that no errors occur if no help is specified"""
3748
3749 parser_signature = Sig(prog='PROG')
3750 argument_signatures = [
3751 Sig('--foo'),
3752 Sig('spam'),
3753 ]
3754 argument_group_signatures = []
3755 usage = '''\
3756 usage: PROG [-h] [--foo FOO] spam
3757 '''
3758 help = usage + '''\
3759
3760 positional arguments:
3761 spam
3762
3763 optional arguments:
3764 -h, --help show this help message and exit
3765 --foo FOO
3766 '''
3767 version = ''
3768
3769
3770class TestHelpTupleMetavar(HelpTestCase):
3771 """Test specifying metavar as a tuple"""
3772
3773 parser_signature = Sig(prog='PROG')
3774 argument_signatures = [
3775 Sig('-w', help='w', nargs='+', metavar=('W1', 'W2')),
3776 Sig('-x', help='x', nargs='*', metavar=('X1', 'X2')),
3777 Sig('-y', help='y', nargs=3, metavar=('Y1', 'Y2', 'Y3')),
3778 Sig('-z', help='z', nargs='?', metavar=('Z1', )),
3779 ]
3780 argument_group_signatures = []
3781 usage = '''\
3782 usage: PROG [-h] [-w W1 [W2 ...]] [-x [X1 [X2 ...]]] [-y Y1 Y2 Y3] \
3783[-z [Z1]]
3784 '''
3785 help = usage + '''\
3786
3787 optional arguments:
3788 -h, --help show this help message and exit
3789 -w W1 [W2 ...] w
3790 -x [X1 [X2 ...]] x
3791 -y Y1 Y2 Y3 y
3792 -z [Z1] z
3793 '''
3794 version = ''
3795
3796
3797class TestHelpRawText(HelpTestCase):
3798 """Test the RawTextHelpFormatter"""
3799
3800 parser_signature = Sig(
3801 prog='PROG', formatter_class=argparse.RawTextHelpFormatter,
3802 description='Keep the formatting\n'
3803 ' exactly as it is written\n'
3804 '\n'
3805 'here\n')
3806
3807 argument_signatures = [
3808 Sig('--foo', help=' foo help should also\n'
3809 'appear as given here'),
3810 Sig('spam', help='spam help'),
3811 ]
3812 argument_group_signatures = [
3813 (Sig('title', description=' This text\n'
3814 ' should be indented\n'
3815 ' exactly like it is here\n'),
3816 [Sig('--bar', help='bar help')]),
3817 ]
3818 usage = '''\
3819 usage: PROG [-h] [--foo FOO] [--bar BAR] spam
3820 '''
3821 help = usage + '''\
3822
3823 Keep the formatting
3824 exactly as it is written
3825
3826 here
3827
3828 positional arguments:
3829 spam spam help
3830
3831 optional arguments:
3832 -h, --help show this help message and exit
3833 --foo FOO foo help should also
3834 appear as given here
3835
3836 title:
3837 This text
3838 should be indented
3839 exactly like it is here
3840
3841 --bar BAR bar help
3842 '''
3843 version = ''
3844
3845
3846class TestHelpRawDescription(HelpTestCase):
3847 """Test the RawTextHelpFormatter"""
3848
3849 parser_signature = Sig(
3850 prog='PROG', formatter_class=argparse.RawDescriptionHelpFormatter,
3851 description='Keep the formatting\n'
3852 ' exactly as it is written\n'
3853 '\n'
3854 'here\n')
3855
3856 argument_signatures = [
3857 Sig('--foo', help=' foo help should not\n'
3858 ' retain this odd formatting'),
3859 Sig('spam', help='spam help'),
3860 ]
3861 argument_group_signatures = [
3862 (Sig('title', description=' This text\n'
3863 ' should be indented\n'
3864 ' exactly like it is here\n'),
3865 [Sig('--bar', help='bar help')]),
3866 ]
3867 usage = '''\
3868 usage: PROG [-h] [--foo FOO] [--bar BAR] spam
3869 '''
3870 help = usage + '''\
3871
3872 Keep the formatting
3873 exactly as it is written
3874
3875 here
3876
3877 positional arguments:
3878 spam spam help
3879
3880 optional arguments:
3881 -h, --help show this help message and exit
3882 --foo FOO foo help should not retain this odd formatting
3883
3884 title:
3885 This text
3886 should be indented
3887 exactly like it is here
3888
3889 --bar BAR bar help
3890 '''
3891 version = ''
3892
3893
3894class TestHelpArgumentDefaults(HelpTestCase):
3895 """Test the ArgumentDefaultsHelpFormatter"""
3896
3897 parser_signature = Sig(
3898 prog='PROG', formatter_class=argparse.ArgumentDefaultsHelpFormatter,
3899 description='description')
3900
3901 argument_signatures = [
3902 Sig('--foo', help='foo help - oh and by the way, %(default)s'),
3903 Sig('--bar', action='store_true', help='bar help'),
3904 Sig('spam', help='spam help'),
3905 Sig('badger', nargs='?', default='wooden', help='badger help'),
3906 ]
3907 argument_group_signatures = [
3908 (Sig('title', description='description'),
3909 [Sig('--baz', type=int, default=42, help='baz help')]),
3910 ]
3911 usage = '''\
3912 usage: PROG [-h] [--foo FOO] [--bar] [--baz BAZ] spam [badger]
3913 '''
3914 help = usage + '''\
3915
3916 description
3917
3918 positional arguments:
3919 spam spam help
3920 badger badger help (default: wooden)
3921
3922 optional arguments:
3923 -h, --help show this help message and exit
3924 --foo FOO foo help - oh and by the way, None
3925 --bar bar help (default: False)
3926
3927 title:
3928 description
3929
3930 --baz BAZ baz help (default: 42)
3931 '''
3932 version = ''
3933
Steven Bethard50fe5932010-05-24 03:47:38 +00003934class TestHelpVersionAction(HelpTestCase):
3935 """Test the default help for the version action"""
3936
3937 parser_signature = Sig(prog='PROG', description='description')
3938 argument_signatures = [Sig('-V', '--version', action='version', version='3.6')]
3939 argument_group_signatures = []
3940 usage = '''\
3941 usage: PROG [-h] [-V]
3942 '''
3943 help = usage + '''\
3944
3945 description
3946
3947 optional arguments:
3948 -h, --help show this help message and exit
3949 -V, --version show program's version number and exit
3950 '''
3951 version = ''
3952
Steven Bethard8a6a1982011-03-27 13:53:53 +02003953class TestHelpSubparsersOrdering(HelpTestCase):
3954 """Test ordering of subcommands in help matches the code"""
3955 parser_signature = Sig(prog='PROG',
3956 description='display some subcommands',
3957 version='0.1')
3958
3959 subparsers_signatures = [Sig(name=name)
3960 for name in ('a', 'b', 'c', 'd', 'e')]
3961
3962 usage = '''\
3963 usage: PROG [-h] [-v] {a,b,c,d,e} ...
3964 '''
3965
3966 help = usage + '''\
3967
3968 display some subcommands
3969
3970 positional arguments:
3971 {a,b,c,d,e}
3972
3973 optional arguments:
3974 -h, --help show this help message and exit
3975 -v, --version show program's version number and exit
3976 '''
3977
3978 version = '''\
3979 0.1
3980 '''
3981
3982class TestHelpSubparsersWithHelpOrdering(HelpTestCase):
3983 """Test ordering of subcommands in help matches the code"""
3984 parser_signature = Sig(prog='PROG',
3985 description='display some subcommands',
3986 version='0.1')
3987
3988 subcommand_data = (('a', 'a subcommand help'),
3989 ('b', 'b subcommand help'),
3990 ('c', 'c subcommand help'),
3991 ('d', 'd subcommand help'),
3992 ('e', 'e subcommand help'),
3993 )
3994
3995 subparsers_signatures = [Sig(name=name, help=help)
3996 for name, help in subcommand_data]
3997
3998 usage = '''\
3999 usage: PROG [-h] [-v] {a,b,c,d,e} ...
4000 '''
4001
4002 help = usage + '''\
4003
4004 display some subcommands
4005
4006 positional arguments:
4007 {a,b,c,d,e}
4008 a a subcommand help
4009 b b subcommand help
4010 c c subcommand help
4011 d d subcommand help
4012 e e subcommand help
4013
4014 optional arguments:
4015 -h, --help show this help message and exit
4016 -v, --version show program's version number and exit
4017 '''
4018
4019 version = '''\
4020 0.1
4021 '''
4022
4023
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004024# =====================================
4025# Optional/Positional constructor tests
4026# =====================================
4027
4028class TestInvalidArgumentConstructors(TestCase):
4029 """Test a bunch of invalid Argument constructors"""
4030
4031 def assertTypeError(self, *args, **kwargs):
4032 parser = argparse.ArgumentParser()
4033 self.assertRaises(TypeError, parser.add_argument,
4034 *args, **kwargs)
4035
4036 def assertValueError(self, *args, **kwargs):
4037 parser = argparse.ArgumentParser()
4038 self.assertRaises(ValueError, parser.add_argument,
4039 *args, **kwargs)
4040
4041 def test_invalid_keyword_arguments(self):
4042 self.assertTypeError('-x', bar=None)
4043 self.assertTypeError('-y', callback='foo')
4044 self.assertTypeError('-y', callback_args=())
4045 self.assertTypeError('-y', callback_kwargs={})
4046
4047 def test_missing_destination(self):
4048 self.assertTypeError()
4049 for action in ['append', 'store']:
4050 self.assertTypeError(action=action)
4051
4052 def test_invalid_option_strings(self):
4053 self.assertValueError('--')
4054 self.assertValueError('---')
4055
4056 def test_invalid_type(self):
4057 self.assertValueError('--foo', type='int')
Steven Bethard7cb20a82011-04-04 01:53:02 +02004058 self.assertValueError('--foo', type=(int, float))
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004059
4060 def test_invalid_action(self):
4061 self.assertValueError('-x', action='foo')
4062 self.assertValueError('foo', action='baz')
Steven Bethard7cb20a82011-04-04 01:53:02 +02004063 self.assertValueError('--foo', action=('store', 'append'))
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004064 parser = argparse.ArgumentParser()
4065 try:
4066 parser.add_argument("--foo", action="store-true")
4067 except ValueError:
4068 e = sys.exc_info()[1]
4069 expected = 'unknown action'
4070 msg = 'expected %r, found %r' % (expected, e)
4071 self.assertTrue(expected in str(e), msg)
4072
4073 def test_multiple_dest(self):
4074 parser = argparse.ArgumentParser()
4075 parser.add_argument(dest='foo')
4076 try:
4077 parser.add_argument('bar', dest='baz')
4078 except ValueError:
4079 e = sys.exc_info()[1]
4080 expected = 'dest supplied twice for positional argument'
4081 msg = 'expected %r, found %r' % (expected, e)
4082 self.assertTrue(expected in str(e), msg)
4083
4084 def test_no_argument_actions(self):
4085 for action in ['store_const', 'store_true', 'store_false',
4086 'append_const', 'count']:
4087 for attrs in [dict(type=int), dict(nargs='+'),
4088 dict(choices='ab')]:
4089 self.assertTypeError('-x', action=action, **attrs)
4090
4091 def test_no_argument_no_const_actions(self):
4092 # options with zero arguments
4093 for action in ['store_true', 'store_false', 'count']:
4094
4095 # const is always disallowed
4096 self.assertTypeError('-x', const='foo', action=action)
4097
4098 # nargs is always disallowed
4099 self.assertTypeError('-x', nargs='*', action=action)
4100
4101 def test_more_than_one_argument_actions(self):
4102 for action in ['store', 'append']:
4103
4104 # nargs=0 is disallowed
4105 self.assertValueError('-x', nargs=0, action=action)
4106 self.assertValueError('spam', nargs=0, action=action)
4107
4108 # const is disallowed with non-optional arguments
4109 for nargs in [1, '*', '+']:
4110 self.assertValueError('-x', const='foo',
4111 nargs=nargs, action=action)
4112 self.assertValueError('spam', const='foo',
4113 nargs=nargs, action=action)
4114
4115 def test_required_const_actions(self):
4116 for action in ['store_const', 'append_const']:
4117
4118 # nargs is always disallowed
4119 self.assertTypeError('-x', nargs='+', action=action)
4120
4121 def test_parsers_action_missing_params(self):
4122 self.assertTypeError('command', action='parsers')
4123 self.assertTypeError('command', action='parsers', prog='PROG')
4124 self.assertTypeError('command', action='parsers',
4125 parser_class=argparse.ArgumentParser)
4126
4127 def test_required_positional(self):
4128 self.assertTypeError('foo', required=True)
4129
4130 def test_user_defined_action(self):
4131
4132 class Success(Exception):
4133 pass
4134
4135 class Action(object):
4136
4137 def __init__(self,
4138 option_strings,
4139 dest,
4140 const,
4141 default,
4142 required=False):
4143 if dest == 'spam':
4144 if const is Success:
4145 if default is Success:
4146 raise Success()
4147
4148 def __call__(self, *args, **kwargs):
4149 pass
4150
4151 parser = argparse.ArgumentParser()
4152 self.assertRaises(Success, parser.add_argument, '--spam',
4153 action=Action, default=Success, const=Success)
4154 self.assertRaises(Success, parser.add_argument, 'spam',
4155 action=Action, default=Success, const=Success)
4156
4157# ================================
4158# Actions returned by add_argument
4159# ================================
4160
4161class TestActionsReturned(TestCase):
4162
4163 def test_dest(self):
4164 parser = argparse.ArgumentParser()
4165 action = parser.add_argument('--foo')
4166 self.assertEqual(action.dest, 'foo')
4167 action = parser.add_argument('-b', '--bar')
4168 self.assertEqual(action.dest, 'bar')
4169 action = parser.add_argument('-x', '-y')
4170 self.assertEqual(action.dest, 'x')
4171
4172 def test_misc(self):
4173 parser = argparse.ArgumentParser()
4174 action = parser.add_argument('--foo', nargs='?', const=42,
4175 default=84, type=int, choices=[1, 2],
4176 help='FOO', metavar='BAR', dest='baz')
4177 self.assertEqual(action.nargs, '?')
4178 self.assertEqual(action.const, 42)
4179 self.assertEqual(action.default, 84)
4180 self.assertEqual(action.type, int)
4181 self.assertEqual(action.choices, [1, 2])
4182 self.assertEqual(action.help, 'FOO')
4183 self.assertEqual(action.metavar, 'BAR')
4184 self.assertEqual(action.dest, 'baz')
4185
4186
4187# ================================
4188# Argument conflict handling tests
4189# ================================
4190
4191class TestConflictHandling(TestCase):
4192
4193 def test_bad_type(self):
4194 self.assertRaises(ValueError, argparse.ArgumentParser,
4195 conflict_handler='foo')
4196
4197 def test_conflict_error(self):
4198 parser = argparse.ArgumentParser()
4199 parser.add_argument('-x')
4200 self.assertRaises(argparse.ArgumentError,
4201 parser.add_argument, '-x')
4202 parser.add_argument('--spam')
4203 self.assertRaises(argparse.ArgumentError,
4204 parser.add_argument, '--spam')
4205
4206 def test_resolve_error(self):
4207 get_parser = argparse.ArgumentParser
4208 parser = get_parser(prog='PROG', conflict_handler='resolve')
4209
4210 parser.add_argument('-x', help='OLD X')
4211 parser.add_argument('-x', help='NEW X')
4212 self.assertEqual(parser.format_help(), textwrap.dedent('''\
4213 usage: PROG [-h] [-x X]
4214
4215 optional arguments:
4216 -h, --help show this help message and exit
4217 -x X NEW X
4218 '''))
4219
4220 parser.add_argument('--spam', metavar='OLD_SPAM')
4221 parser.add_argument('--spam', metavar='NEW_SPAM')
4222 self.assertEqual(parser.format_help(), textwrap.dedent('''\
4223 usage: PROG [-h] [-x X] [--spam NEW_SPAM]
4224
4225 optional arguments:
4226 -h, --help show this help message and exit
4227 -x X NEW X
4228 --spam NEW_SPAM
4229 '''))
4230
4231
4232# =============================
4233# Help and Version option tests
4234# =============================
4235
4236class TestOptionalsHelpVersionActions(TestCase):
4237 """Test the help and version actions"""
4238
4239 def _get_error(self, func, *args, **kwargs):
4240 try:
4241 func(*args, **kwargs)
4242 except ArgumentParserError:
4243 return sys.exc_info()[1]
4244 else:
4245 self.assertRaises(ArgumentParserError, func, *args, **kwargs)
4246
4247 def assertPrintHelpExit(self, parser, args_str):
4248 self.assertEqual(
4249 parser.format_help(),
4250 self._get_error(parser.parse_args, args_str.split()).stdout)
4251
4252 def assertPrintVersionExit(self, parser, args_str):
4253 self.assertEqual(
4254 parser.format_version(),
4255 self._get_error(parser.parse_args, args_str.split()).stderr)
4256
4257 def assertArgumentParserError(self, parser, *args):
4258 self.assertRaises(ArgumentParserError, parser.parse_args, args)
4259
4260 def test_version(self):
4261 parser = ErrorRaisingArgumentParser(version='1.0')
4262 self.assertPrintHelpExit(parser, '-h')
4263 self.assertPrintHelpExit(parser, '--help')
4264 self.assertPrintVersionExit(parser, '-v')
4265 self.assertPrintVersionExit(parser, '--version')
4266
4267 def test_version_format(self):
4268 parser = ErrorRaisingArgumentParser(prog='PPP', version='%(prog)s 3.5')
4269 msg = self._get_error(parser.parse_args, ['-v']).stderr
4270 self.assertEqual('PPP 3.5\n', msg)
4271
4272 def test_version_no_help(self):
4273 parser = ErrorRaisingArgumentParser(add_help=False, version='1.0')
4274 self.assertArgumentParserError(parser, '-h')
4275 self.assertArgumentParserError(parser, '--help')
4276 self.assertPrintVersionExit(parser, '-v')
4277 self.assertPrintVersionExit(parser, '--version')
4278
4279 def test_version_action(self):
4280 parser = ErrorRaisingArgumentParser(prog='XXX')
4281 parser.add_argument('-V', action='version', version='%(prog)s 3.7')
4282 msg = self._get_error(parser.parse_args, ['-V']).stderr
4283 self.assertEqual('XXX 3.7\n', msg)
4284
4285 def test_no_help(self):
4286 parser = ErrorRaisingArgumentParser(add_help=False)
4287 self.assertArgumentParserError(parser, '-h')
4288 self.assertArgumentParserError(parser, '--help')
4289 self.assertArgumentParserError(parser, '-v')
4290 self.assertArgumentParserError(parser, '--version')
4291
4292 def test_alternate_help_version(self):
4293 parser = ErrorRaisingArgumentParser()
4294 parser.add_argument('-x', action='help')
4295 parser.add_argument('-y', action='version')
4296 self.assertPrintHelpExit(parser, '-x')
4297 self.assertPrintVersionExit(parser, '-y')
4298 self.assertArgumentParserError(parser, '-v')
4299 self.assertArgumentParserError(parser, '--version')
4300
4301 def test_help_version_extra_arguments(self):
4302 parser = ErrorRaisingArgumentParser(version='1.0')
4303 parser.add_argument('-x', action='store_true')
4304 parser.add_argument('y')
4305
4306 # try all combinations of valid prefixes and suffixes
4307 valid_prefixes = ['', '-x', 'foo', '-x bar', 'baz -x']
4308 valid_suffixes = valid_prefixes + ['--bad-option', 'foo bar baz']
4309 for prefix in valid_prefixes:
4310 for suffix in valid_suffixes:
4311 format = '%s %%s %s' % (prefix, suffix)
4312 self.assertPrintHelpExit(parser, format % '-h')
4313 self.assertPrintHelpExit(parser, format % '--help')
4314 self.assertPrintVersionExit(parser, format % '-v')
4315 self.assertPrintVersionExit(parser, format % '--version')
4316
4317
4318# ======================
4319# str() and repr() tests
4320# ======================
4321
4322class TestStrings(TestCase):
4323 """Test str() and repr() on Optionals and Positionals"""
4324
4325 def assertStringEqual(self, obj, result_string):
4326 for func in [str, repr]:
4327 self.assertEqual(func(obj), result_string)
4328
4329 def test_optional(self):
4330 option = argparse.Action(
4331 option_strings=['--foo', '-a', '-b'],
4332 dest='b',
4333 type='int',
4334 nargs='+',
4335 default=42,
4336 choices=[1, 2, 3],
4337 help='HELP',
4338 metavar='METAVAR')
4339 string = (
4340 "Action(option_strings=['--foo', '-a', '-b'], dest='b', "
4341 "nargs='+', const=None, default=42, type='int', "
4342 "choices=[1, 2, 3], help='HELP', metavar='METAVAR')")
4343 self.assertStringEqual(option, string)
4344
4345 def test_argument(self):
4346 argument = argparse.Action(
4347 option_strings=[],
4348 dest='x',
4349 type=float,
4350 nargs='?',
4351 default=2.5,
4352 choices=[0.5, 1.5, 2.5],
4353 help='H HH H',
4354 metavar='MV MV MV')
4355 string = (
4356 "Action(option_strings=[], dest='x', nargs='?', "
4357 "const=None, default=2.5, type=%r, choices=[0.5, 1.5, 2.5], "
4358 "help='H HH H', metavar='MV MV MV')" % float)
4359 self.assertStringEqual(argument, string)
4360
4361 def test_namespace(self):
4362 ns = argparse.Namespace(foo=42, bar='spam')
4363 string = "Namespace(bar='spam', foo=42)"
4364 self.assertStringEqual(ns, string)
4365
4366 def test_parser(self):
4367 parser = argparse.ArgumentParser(prog='PROG')
4368 string = (
4369 "ArgumentParser(prog='PROG', usage=None, description=None, "
4370 "version=None, formatter_class=%r, conflict_handler='error', "
4371 "add_help=True)" % argparse.HelpFormatter)
4372 self.assertStringEqual(parser, string)
4373
4374# ===============
4375# Namespace tests
4376# ===============
4377
4378class TestNamespace(TestCase):
4379
4380 def test_constructor(self):
4381 ns = argparse.Namespace()
4382 self.assertRaises(AttributeError, getattr, ns, 'x')
4383
4384 ns = argparse.Namespace(a=42, b='spam')
4385 self.assertEqual(ns.a, 42)
4386 self.assertEqual(ns.b, 'spam')
4387
4388 def test_equality(self):
4389 ns1 = argparse.Namespace(a=1, b=2)
4390 ns2 = argparse.Namespace(b=2, a=1)
4391 ns3 = argparse.Namespace(a=1)
4392 ns4 = argparse.Namespace(b=2)
4393
4394 self.assertEqual(ns1, ns2)
4395 self.assertNotEqual(ns1, ns3)
4396 self.assertNotEqual(ns1, ns4)
4397 self.assertNotEqual(ns2, ns3)
4398 self.assertNotEqual(ns2, ns4)
4399 self.assertTrue(ns1 != ns3)
4400 self.assertTrue(ns1 != ns4)
4401 self.assertTrue(ns2 != ns3)
4402 self.assertTrue(ns2 != ns4)
4403
4404
4405# ===================
4406# File encoding tests
4407# ===================
4408
4409class TestEncoding(TestCase):
4410
4411 def _test_module_encoding(self, path):
4412 path, _ = os.path.splitext(path)
4413 path += ".py"
Antoine Pitroub86680e2010-10-14 21:15:17 +00004414 with codecs.open(path, 'r', 'utf8') as f:
4415 f.read()
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004416
4417 def test_argparse_module_encoding(self):
4418 self._test_module_encoding(argparse.__file__)
4419
4420 def test_test_argparse_module_encoding(self):
4421 self._test_module_encoding(__file__)
4422
4423# ===================
4424# ArgumentError tests
4425# ===================
4426
4427class TestArgumentError(TestCase):
4428
4429 def test_argument_error(self):
4430 msg = "my error here"
4431 error = argparse.ArgumentError(None, msg)
4432 self.assertEqual(str(error), msg)
4433
4434# =======================
4435# ArgumentTypeError tests
4436# =======================
4437
R. David Murray722b5fd2010-11-20 03:48:58 +00004438class TestArgumentTypeError(TestCase):
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004439
4440 def test_argument_type_error(self):
4441
4442 def spam(string):
4443 raise argparse.ArgumentTypeError('spam!')
4444
4445 parser = ErrorRaisingArgumentParser(prog='PROG', add_help=False)
4446 parser.add_argument('x', type=spam)
4447 try:
4448 parser.parse_args(['XXX'])
4449 except ArgumentParserError:
4450 expected = 'usage: PROG x\nPROG: error: argument x: spam!\n'
4451 msg = sys.exc_info()[1].stderr
4452 self.assertEqual(expected, msg)
4453 else:
4454 self.fail()
4455
4456# ======================
4457# parse_known_args tests
4458# ======================
4459
4460class TestParseKnownArgs(TestCase):
4461
4462 def test_optionals(self):
4463 parser = argparse.ArgumentParser()
4464 parser.add_argument('--foo')
4465 args, extras = parser.parse_known_args('--foo F --bar --baz'.split())
4466 self.assertEqual(NS(foo='F'), args)
4467 self.assertEqual(['--bar', '--baz'], extras)
4468
4469 def test_mixed(self):
4470 parser = argparse.ArgumentParser()
4471 parser.add_argument('-v', nargs='?', const=1, type=int)
4472 parser.add_argument('--spam', action='store_false')
4473 parser.add_argument('badger')
4474
4475 argv = ["B", "C", "--foo", "-v", "3", "4"]
4476 args, extras = parser.parse_known_args(argv)
4477 self.assertEqual(NS(v=3, spam=True, badger="B"), args)
4478 self.assertEqual(["C", "--foo", "4"], extras)
4479
Steven Bethard8d9a4622011-03-26 17:33:56 +01004480# ==========================
4481# add_argument metavar tests
4482# ==========================
4483
4484class TestAddArgumentMetavar(TestCase):
4485
4486 EXPECTED_MESSAGE = "length of metavar tuple does not match nargs"
4487
4488 def do_test_no_exception(self, nargs, metavar):
4489 parser = argparse.ArgumentParser()
4490 parser.add_argument("--foo", nargs=nargs, metavar=metavar)
4491
4492 def do_test_exception(self, nargs, metavar):
4493 parser = argparse.ArgumentParser()
4494 with self.assertRaises(ValueError) as cm:
4495 parser.add_argument("--foo", nargs=nargs, metavar=metavar)
4496 self.assertEqual(cm.exception.args[0], self.EXPECTED_MESSAGE)
4497
4498 # Unit tests for different values of metavar when nargs=None
4499
4500 def test_nargs_None_metavar_string(self):
4501 self.do_test_no_exception(nargs=None, metavar="1")
4502
4503 def test_nargs_None_metavar_length0(self):
4504 self.do_test_exception(nargs=None, metavar=tuple())
4505
4506 def test_nargs_None_metavar_length1(self):
4507 self.do_test_no_exception(nargs=None, metavar=("1"))
4508
4509 def test_nargs_None_metavar_length2(self):
4510 self.do_test_exception(nargs=None, metavar=("1", "2"))
4511
4512 def test_nargs_None_metavar_length3(self):
4513 self.do_test_exception(nargs=None, metavar=("1", "2", "3"))
4514
4515 # Unit tests for different values of metavar when nargs=?
4516
4517 def test_nargs_optional_metavar_string(self):
4518 self.do_test_no_exception(nargs="?", metavar="1")
4519
4520 def test_nargs_optional_metavar_length0(self):
4521 self.do_test_exception(nargs="?", metavar=tuple())
4522
4523 def test_nargs_optional_metavar_length1(self):
4524 self.do_test_no_exception(nargs="?", metavar=("1"))
4525
4526 def test_nargs_optional_metavar_length2(self):
4527 self.do_test_exception(nargs="?", metavar=("1", "2"))
4528
4529 def test_nargs_optional_metavar_length3(self):
4530 self.do_test_exception(nargs="?", metavar=("1", "2", "3"))
4531
4532 # Unit tests for different values of metavar when nargs=*
4533
4534 def test_nargs_zeroormore_metavar_string(self):
4535 self.do_test_no_exception(nargs="*", metavar="1")
4536
4537 def test_nargs_zeroormore_metavar_length0(self):
4538 self.do_test_exception(nargs="*", metavar=tuple())
4539
4540 def test_nargs_zeroormore_metavar_length1(self):
4541 self.do_test_no_exception(nargs="*", metavar=("1"))
4542
4543 def test_nargs_zeroormore_metavar_length2(self):
4544 self.do_test_no_exception(nargs="*", metavar=("1", "2"))
4545
4546 def test_nargs_zeroormore_metavar_length3(self):
4547 self.do_test_exception(nargs="*", metavar=("1", "2", "3"))
4548
4549 # Unit tests for different values of metavar when nargs=+
4550
4551 def test_nargs_oneormore_metavar_string(self):
4552 self.do_test_no_exception(nargs="+", metavar="1")
4553
4554 def test_nargs_oneormore_metavar_length0(self):
4555 self.do_test_exception(nargs="+", metavar=tuple())
4556
4557 def test_nargs_oneormore_metavar_length1(self):
4558 self.do_test_no_exception(nargs="+", metavar=("1"))
4559
4560 def test_nargs_oneormore_metavar_length2(self):
4561 self.do_test_no_exception(nargs="+", metavar=("1", "2"))
4562
4563 def test_nargs_oneormore_metavar_length3(self):
4564 self.do_test_exception(nargs="+", metavar=("1", "2", "3"))
4565
4566 # Unit tests for different values of metavar when nargs=...
4567
4568 def test_nargs_remainder_metavar_string(self):
4569 self.do_test_no_exception(nargs="...", metavar="1")
4570
4571 def test_nargs_remainder_metavar_length0(self):
4572 self.do_test_no_exception(nargs="...", metavar=tuple())
4573
4574 def test_nargs_remainder_metavar_length1(self):
4575 self.do_test_no_exception(nargs="...", metavar=("1"))
4576
4577 def test_nargs_remainder_metavar_length2(self):
4578 self.do_test_no_exception(nargs="...", metavar=("1", "2"))
4579
4580 def test_nargs_remainder_metavar_length3(self):
4581 self.do_test_no_exception(nargs="...", metavar=("1", "2", "3"))
4582
4583 # Unit tests for different values of metavar when nargs=A...
4584
4585 def test_nargs_parser_metavar_string(self):
4586 self.do_test_no_exception(nargs="A...", metavar="1")
4587
4588 def test_nargs_parser_metavar_length0(self):
4589 self.do_test_exception(nargs="A...", metavar=tuple())
4590
4591 def test_nargs_parser_metavar_length1(self):
4592 self.do_test_no_exception(nargs="A...", metavar=("1"))
4593
4594 def test_nargs_parser_metavar_length2(self):
4595 self.do_test_exception(nargs="A...", metavar=("1", "2"))
4596
4597 def test_nargs_parser_metavar_length3(self):
4598 self.do_test_exception(nargs="A...", metavar=("1", "2", "3"))
4599
4600 # Unit tests for different values of metavar when nargs=1
4601
4602 def test_nargs_1_metavar_string(self):
4603 self.do_test_no_exception(nargs=1, metavar="1")
4604
4605 def test_nargs_1_metavar_length0(self):
4606 self.do_test_exception(nargs=1, metavar=tuple())
4607
4608 def test_nargs_1_metavar_length1(self):
4609 self.do_test_no_exception(nargs=1, metavar=("1"))
4610
4611 def test_nargs_1_metavar_length2(self):
4612 self.do_test_exception(nargs=1, metavar=("1", "2"))
4613
4614 def test_nargs_1_metavar_length3(self):
4615 self.do_test_exception(nargs=1, metavar=("1", "2", "3"))
4616
4617 # Unit tests for different values of metavar when nargs=2
4618
4619 def test_nargs_2_metavar_string(self):
4620 self.do_test_no_exception(nargs=2, metavar="1")
4621
4622 def test_nargs_2_metavar_length0(self):
4623 self.do_test_exception(nargs=2, metavar=tuple())
4624
4625 def test_nargs_2_metavar_length1(self):
4626 self.do_test_no_exception(nargs=2, metavar=("1"))
4627
4628 def test_nargs_2_metavar_length2(self):
4629 self.do_test_no_exception(nargs=2, metavar=("1", "2"))
4630
4631 def test_nargs_2_metavar_length3(self):
4632 self.do_test_exception(nargs=2, metavar=("1", "2", "3"))
4633
4634 # Unit tests for different values of metavar when nargs=3
4635
4636 def test_nargs_3_metavar_string(self):
4637 self.do_test_no_exception(nargs=3, metavar="1")
4638
4639 def test_nargs_3_metavar_length0(self):
4640 self.do_test_exception(nargs=3, metavar=tuple())
4641
4642 def test_nargs_3_metavar_length1(self):
4643 self.do_test_no_exception(nargs=3, metavar=("1"))
4644
4645 def test_nargs_3_metavar_length2(self):
4646 self.do_test_exception(nargs=3, metavar=("1", "2"))
4647
4648 def test_nargs_3_metavar_length3(self):
4649 self.do_test_no_exception(nargs=3, metavar=("1", "2", "3"))
4650
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004651# ============================
4652# from argparse import * tests
4653# ============================
4654
4655class TestImportStar(TestCase):
4656
4657 def test(self):
4658 for name in argparse.__all__:
4659 self.assertTrue(hasattr(argparse, name))
4660
Steven Bethard72c55382010-11-01 15:23:12 +00004661 def test_all_exports_everything_but_modules(self):
4662 items = [
4663 name
4664 for name, value in vars(argparse).items()
Éric Araujo12159152010-12-04 17:31:49 +00004665 if not (name.startswith("_") or name == 'ngettext')
Steven Bethard72c55382010-11-01 15:23:12 +00004666 if not inspect.ismodule(value)
4667 ]
4668 self.assertEqual(sorted(items), sorted(argparse.__all__))
4669
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004670def test_main():
Florent Xicluna41fe6152010-04-02 18:52:12 +00004671 # silence warnings about version argument - these are expected
4672 with support.check_warnings(
4673 ('The "version" argument to ArgumentParser is deprecated.',
4674 DeprecationWarning),
4675 ('The (format|print)_version method is deprecated',
4676 DeprecationWarning)):
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004677 support.run_unittest(__name__)
Benjamin Peterson4fd181c2010-03-02 23:46:42 +00004678 # Remove global references to avoid looking like we have refleaks.
4679 RFile.seen = {}
4680 WFile.seen = set()
4681
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004682
4683
4684if __name__ == '__main__':
4685 test_main()