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