blob: d7f90cdaa98869a1a33d69e0d32afdca5f69a5b0 [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
3855class TestHelpVersionOptional(HelpTestCase):
3856 """Test that the --version argument can be suppressed help messages"""
3857
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02003858 parser_signature = Sig(prog='PROG')
Benjamin Peterson698a18a2010-03-02 22:34:37 +00003859 argument_signatures = [
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02003860 Sig('-v', '--version', action='version', version='1.0'),
Benjamin Peterson698a18a2010-03-02 22:34:37 +00003861 Sig('--foo', help='foo help'),
3862 Sig('spam', help='spam help'),
3863 ]
3864 argument_group_signatures = []
3865 usage = '''\
3866 usage: PROG [-h] [-v] [--foo FOO] spam
3867 '''
3868 help = usage + '''\
3869
3870 positional arguments:
3871 spam spam help
3872
3873 optional arguments:
3874 -h, --help show this help message and exit
3875 -v, --version show program's version number and exit
3876 --foo FOO foo help
3877 '''
3878 version = '''\
3879 1.0
3880 '''
3881
3882
3883class TestHelpNone(HelpTestCase):
3884 """Test that no errors occur if no help is specified"""
3885
3886 parser_signature = Sig(prog='PROG')
3887 argument_signatures = [
3888 Sig('--foo'),
3889 Sig('spam'),
3890 ]
3891 argument_group_signatures = []
3892 usage = '''\
3893 usage: PROG [-h] [--foo FOO] spam
3894 '''
3895 help = usage + '''\
3896
3897 positional arguments:
3898 spam
3899
3900 optional arguments:
3901 -h, --help show this help message and exit
3902 --foo FOO
3903 '''
3904 version = ''
3905
3906
3907class TestHelpTupleMetavar(HelpTestCase):
3908 """Test specifying metavar as a tuple"""
3909
3910 parser_signature = Sig(prog='PROG')
3911 argument_signatures = [
3912 Sig('-w', help='w', nargs='+', metavar=('W1', 'W2')),
3913 Sig('-x', help='x', nargs='*', metavar=('X1', 'X2')),
3914 Sig('-y', help='y', nargs=3, metavar=('Y1', 'Y2', 'Y3')),
3915 Sig('-z', help='z', nargs='?', metavar=('Z1', )),
3916 ]
3917 argument_group_signatures = []
3918 usage = '''\
3919 usage: PROG [-h] [-w W1 [W2 ...]] [-x [X1 [X2 ...]]] [-y Y1 Y2 Y3] \
3920[-z [Z1]]
3921 '''
3922 help = usage + '''\
3923
3924 optional arguments:
3925 -h, --help show this help message and exit
3926 -w W1 [W2 ...] w
3927 -x [X1 [X2 ...]] x
3928 -y Y1 Y2 Y3 y
3929 -z [Z1] z
3930 '''
3931 version = ''
3932
3933
3934class TestHelpRawText(HelpTestCase):
3935 """Test the RawTextHelpFormatter"""
3936
3937 parser_signature = Sig(
3938 prog='PROG', formatter_class=argparse.RawTextHelpFormatter,
3939 description='Keep the formatting\n'
3940 ' exactly as it is written\n'
3941 '\n'
3942 'here\n')
3943
3944 argument_signatures = [
3945 Sig('--foo', help=' foo help should also\n'
3946 'appear as given here'),
3947 Sig('spam', help='spam help'),
3948 ]
3949 argument_group_signatures = [
3950 (Sig('title', description=' This text\n'
3951 ' should be indented\n'
3952 ' exactly like it is here\n'),
3953 [Sig('--bar', help='bar help')]),
3954 ]
3955 usage = '''\
3956 usage: PROG [-h] [--foo FOO] [--bar BAR] spam
3957 '''
3958 help = usage + '''\
3959
3960 Keep the formatting
3961 exactly as it is written
3962
3963 here
3964
3965 positional arguments:
3966 spam spam help
3967
3968 optional arguments:
3969 -h, --help show this help message and exit
3970 --foo FOO foo help should also
3971 appear as given here
3972
3973 title:
3974 This text
3975 should be indented
3976 exactly like it is here
3977
3978 --bar BAR bar help
3979 '''
3980 version = ''
3981
3982
3983class TestHelpRawDescription(HelpTestCase):
3984 """Test the RawTextHelpFormatter"""
3985
3986 parser_signature = Sig(
3987 prog='PROG', formatter_class=argparse.RawDescriptionHelpFormatter,
3988 description='Keep the formatting\n'
3989 ' exactly as it is written\n'
3990 '\n'
3991 'here\n')
3992
3993 argument_signatures = [
3994 Sig('--foo', help=' foo help should not\n'
3995 ' retain this odd formatting'),
3996 Sig('spam', help='spam help'),
3997 ]
3998 argument_group_signatures = [
3999 (Sig('title', description=' This text\n'
4000 ' should be indented\n'
4001 ' exactly like it is here\n'),
4002 [Sig('--bar', help='bar help')]),
4003 ]
4004 usage = '''\
4005 usage: PROG [-h] [--foo FOO] [--bar BAR] spam
4006 '''
4007 help = usage + '''\
4008
4009 Keep the formatting
4010 exactly as it is written
4011
4012 here
4013
4014 positional arguments:
4015 spam spam help
4016
4017 optional arguments:
4018 -h, --help show this help message and exit
4019 --foo FOO foo help should not retain this odd formatting
4020
4021 title:
4022 This text
4023 should be indented
4024 exactly like it is here
4025
4026 --bar BAR bar help
4027 '''
4028 version = ''
4029
4030
4031class TestHelpArgumentDefaults(HelpTestCase):
4032 """Test the ArgumentDefaultsHelpFormatter"""
4033
4034 parser_signature = Sig(
4035 prog='PROG', formatter_class=argparse.ArgumentDefaultsHelpFormatter,
4036 description='description')
4037
4038 argument_signatures = [
4039 Sig('--foo', help='foo help - oh and by the way, %(default)s'),
4040 Sig('--bar', action='store_true', help='bar help'),
4041 Sig('spam', help='spam help'),
4042 Sig('badger', nargs='?', default='wooden', help='badger help'),
4043 ]
4044 argument_group_signatures = [
4045 (Sig('title', description='description'),
4046 [Sig('--baz', type=int, default=42, help='baz help')]),
4047 ]
4048 usage = '''\
4049 usage: PROG [-h] [--foo FOO] [--bar] [--baz BAZ] spam [badger]
4050 '''
4051 help = usage + '''\
4052
4053 description
4054
4055 positional arguments:
4056 spam spam help
4057 badger badger help (default: wooden)
4058
4059 optional arguments:
4060 -h, --help show this help message and exit
4061 --foo FOO foo help - oh and by the way, None
4062 --bar bar help (default: False)
4063
4064 title:
4065 description
4066
4067 --baz BAZ baz help (default: 42)
4068 '''
4069 version = ''
4070
Steven Bethard50fe5932010-05-24 03:47:38 +00004071class TestHelpVersionAction(HelpTestCase):
4072 """Test the default help for the version action"""
4073
4074 parser_signature = Sig(prog='PROG', description='description')
4075 argument_signatures = [Sig('-V', '--version', action='version', version='3.6')]
4076 argument_group_signatures = []
4077 usage = '''\
4078 usage: PROG [-h] [-V]
4079 '''
4080 help = usage + '''\
4081
4082 description
4083
4084 optional arguments:
4085 -h, --help show this help message and exit
4086 -V, --version show program's version number and exit
4087 '''
4088 version = ''
4089
Steven Bethard8a6a1982011-03-27 13:53:53 +02004090class TestHelpSubparsersOrdering(HelpTestCase):
4091 """Test ordering of subcommands in help matches the code"""
4092 parser_signature = Sig(prog='PROG',
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02004093 description='display some subcommands')
4094 argument_signatures = [Sig('-v', '--version', action='version', version='0.1')]
Steven Bethard8a6a1982011-03-27 13:53:53 +02004095
4096 subparsers_signatures = [Sig(name=name)
4097 for name in ('a', 'b', 'c', 'd', 'e')]
4098
4099 usage = '''\
4100 usage: PROG [-h] [-v] {a,b,c,d,e} ...
4101 '''
4102
4103 help = usage + '''\
4104
4105 display some subcommands
4106
4107 positional arguments:
4108 {a,b,c,d,e}
4109
4110 optional arguments:
4111 -h, --help show this help message and exit
4112 -v, --version show program's version number and exit
4113 '''
4114
4115 version = '''\
4116 0.1
4117 '''
4118
4119class TestHelpSubparsersWithHelpOrdering(HelpTestCase):
4120 """Test ordering of subcommands in help matches the code"""
4121 parser_signature = Sig(prog='PROG',
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02004122 description='display some subcommands')
4123 argument_signatures = [Sig('-v', '--version', action='version', version='0.1')]
Steven Bethard8a6a1982011-03-27 13:53:53 +02004124
4125 subcommand_data = (('a', 'a subcommand help'),
4126 ('b', 'b subcommand help'),
4127 ('c', 'c subcommand help'),
4128 ('d', 'd subcommand help'),
4129 ('e', 'e subcommand help'),
4130 )
4131
4132 subparsers_signatures = [Sig(name=name, help=help)
4133 for name, help in subcommand_data]
4134
4135 usage = '''\
4136 usage: PROG [-h] [-v] {a,b,c,d,e} ...
4137 '''
4138
4139 help = usage + '''\
4140
4141 display some subcommands
4142
4143 positional arguments:
4144 {a,b,c,d,e}
4145 a a subcommand help
4146 b b subcommand help
4147 c c subcommand help
4148 d d subcommand help
4149 e e subcommand help
4150
4151 optional arguments:
4152 -h, --help show this help message and exit
4153 -v, --version show program's version number and exit
4154 '''
4155
4156 version = '''\
4157 0.1
4158 '''
4159
4160
Steven Bethard0331e902011-03-26 14:48:04 +01004161
4162class TestHelpMetavarTypeFormatter(HelpTestCase):
4163 """"""
4164
4165 def custom_type(string):
4166 return string
4167
4168 parser_signature = Sig(prog='PROG', description='description',
4169 formatter_class=argparse.MetavarTypeHelpFormatter)
4170 argument_signatures = [Sig('a', type=int),
4171 Sig('-b', type=custom_type),
4172 Sig('-c', type=float, metavar='SOME FLOAT')]
4173 argument_group_signatures = []
4174 usage = '''\
4175 usage: PROG [-h] [-b custom_type] [-c SOME FLOAT] int
4176 '''
4177 help = usage + '''\
4178
4179 description
4180
4181 positional arguments:
4182 int
4183
4184 optional arguments:
4185 -h, --help show this help message and exit
4186 -b custom_type
4187 -c SOME FLOAT
4188 '''
4189 version = ''
4190
4191
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004192# =====================================
4193# Optional/Positional constructor tests
4194# =====================================
4195
4196class TestInvalidArgumentConstructors(TestCase):
4197 """Test a bunch of invalid Argument constructors"""
4198
4199 def assertTypeError(self, *args, **kwargs):
4200 parser = argparse.ArgumentParser()
4201 self.assertRaises(TypeError, parser.add_argument,
4202 *args, **kwargs)
4203
4204 def assertValueError(self, *args, **kwargs):
4205 parser = argparse.ArgumentParser()
4206 self.assertRaises(ValueError, parser.add_argument,
4207 *args, **kwargs)
4208
4209 def test_invalid_keyword_arguments(self):
4210 self.assertTypeError('-x', bar=None)
4211 self.assertTypeError('-y', callback='foo')
4212 self.assertTypeError('-y', callback_args=())
4213 self.assertTypeError('-y', callback_kwargs={})
4214
4215 def test_missing_destination(self):
4216 self.assertTypeError()
4217 for action in ['append', 'store']:
4218 self.assertTypeError(action=action)
4219
4220 def test_invalid_option_strings(self):
4221 self.assertValueError('--')
4222 self.assertValueError('---')
4223
4224 def test_invalid_type(self):
4225 self.assertValueError('--foo', type='int')
Steven Bethard7cb20a82011-04-04 01:53:02 +02004226 self.assertValueError('--foo', type=(int, float))
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004227
4228 def test_invalid_action(self):
4229 self.assertValueError('-x', action='foo')
4230 self.assertValueError('foo', action='baz')
Steven Bethard7cb20a82011-04-04 01:53:02 +02004231 self.assertValueError('--foo', action=('store', 'append'))
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004232 parser = argparse.ArgumentParser()
Berker Peksag1c5f56a2014-07-06 09:33:20 +03004233 with self.assertRaises(ValueError) as cm:
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004234 parser.add_argument("--foo", action="store-true")
Berker Peksag1c5f56a2014-07-06 09:33:20 +03004235 self.assertIn('unknown action', str(cm.exception))
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004236
4237 def test_multiple_dest(self):
4238 parser = argparse.ArgumentParser()
4239 parser.add_argument(dest='foo')
Berker Peksag1c5f56a2014-07-06 09:33:20 +03004240 with self.assertRaises(ValueError) as cm:
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004241 parser.add_argument('bar', dest='baz')
Berker Peksag1c5f56a2014-07-06 09:33:20 +03004242 self.assertIn('dest supplied twice for positional argument',
4243 str(cm.exception))
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004244
4245 def test_no_argument_actions(self):
4246 for action in ['store_const', 'store_true', 'store_false',
4247 'append_const', 'count']:
4248 for attrs in [dict(type=int), dict(nargs='+'),
4249 dict(choices='ab')]:
4250 self.assertTypeError('-x', action=action, **attrs)
4251
4252 def test_no_argument_no_const_actions(self):
4253 # options with zero arguments
4254 for action in ['store_true', 'store_false', 'count']:
4255
4256 # const is always disallowed
4257 self.assertTypeError('-x', const='foo', action=action)
4258
4259 # nargs is always disallowed
4260 self.assertTypeError('-x', nargs='*', action=action)
4261
4262 def test_more_than_one_argument_actions(self):
4263 for action in ['store', 'append']:
4264
4265 # nargs=0 is disallowed
4266 self.assertValueError('-x', nargs=0, action=action)
4267 self.assertValueError('spam', nargs=0, action=action)
4268
4269 # const is disallowed with non-optional arguments
4270 for nargs in [1, '*', '+']:
4271 self.assertValueError('-x', const='foo',
4272 nargs=nargs, action=action)
4273 self.assertValueError('spam', const='foo',
4274 nargs=nargs, action=action)
4275
4276 def test_required_const_actions(self):
4277 for action in ['store_const', 'append_const']:
4278
4279 # nargs is always disallowed
4280 self.assertTypeError('-x', nargs='+', action=action)
4281
4282 def test_parsers_action_missing_params(self):
4283 self.assertTypeError('command', action='parsers')
4284 self.assertTypeError('command', action='parsers', prog='PROG')
4285 self.assertTypeError('command', action='parsers',
4286 parser_class=argparse.ArgumentParser)
4287
4288 def test_required_positional(self):
4289 self.assertTypeError('foo', required=True)
4290
4291 def test_user_defined_action(self):
4292
4293 class Success(Exception):
4294 pass
4295
4296 class Action(object):
4297
4298 def __init__(self,
4299 option_strings,
4300 dest,
4301 const,
4302 default,
4303 required=False):
4304 if dest == 'spam':
4305 if const is Success:
4306 if default is Success:
4307 raise Success()
4308
4309 def __call__(self, *args, **kwargs):
4310 pass
4311
4312 parser = argparse.ArgumentParser()
4313 self.assertRaises(Success, parser.add_argument, '--spam',
4314 action=Action, default=Success, const=Success)
4315 self.assertRaises(Success, parser.add_argument, 'spam',
4316 action=Action, default=Success, const=Success)
4317
4318# ================================
4319# Actions returned by add_argument
4320# ================================
4321
4322class TestActionsReturned(TestCase):
4323
4324 def test_dest(self):
4325 parser = argparse.ArgumentParser()
4326 action = parser.add_argument('--foo')
4327 self.assertEqual(action.dest, 'foo')
4328 action = parser.add_argument('-b', '--bar')
4329 self.assertEqual(action.dest, 'bar')
4330 action = parser.add_argument('-x', '-y')
4331 self.assertEqual(action.dest, 'x')
4332
4333 def test_misc(self):
4334 parser = argparse.ArgumentParser()
4335 action = parser.add_argument('--foo', nargs='?', const=42,
4336 default=84, type=int, choices=[1, 2],
4337 help='FOO', metavar='BAR', dest='baz')
4338 self.assertEqual(action.nargs, '?')
4339 self.assertEqual(action.const, 42)
4340 self.assertEqual(action.default, 84)
4341 self.assertEqual(action.type, int)
4342 self.assertEqual(action.choices, [1, 2])
4343 self.assertEqual(action.help, 'FOO')
4344 self.assertEqual(action.metavar, 'BAR')
4345 self.assertEqual(action.dest, 'baz')
4346
4347
4348# ================================
4349# Argument conflict handling tests
4350# ================================
4351
4352class TestConflictHandling(TestCase):
4353
4354 def test_bad_type(self):
4355 self.assertRaises(ValueError, argparse.ArgumentParser,
4356 conflict_handler='foo')
4357
4358 def test_conflict_error(self):
4359 parser = argparse.ArgumentParser()
4360 parser.add_argument('-x')
4361 self.assertRaises(argparse.ArgumentError,
4362 parser.add_argument, '-x')
4363 parser.add_argument('--spam')
4364 self.assertRaises(argparse.ArgumentError,
4365 parser.add_argument, '--spam')
4366
4367 def test_resolve_error(self):
4368 get_parser = argparse.ArgumentParser
4369 parser = get_parser(prog='PROG', conflict_handler='resolve')
4370
4371 parser.add_argument('-x', help='OLD X')
4372 parser.add_argument('-x', help='NEW X')
4373 self.assertEqual(parser.format_help(), textwrap.dedent('''\
4374 usage: PROG [-h] [-x X]
4375
4376 optional arguments:
4377 -h, --help show this help message and exit
4378 -x X NEW X
4379 '''))
4380
4381 parser.add_argument('--spam', metavar='OLD_SPAM')
4382 parser.add_argument('--spam', metavar='NEW_SPAM')
4383 self.assertEqual(parser.format_help(), textwrap.dedent('''\
4384 usage: PROG [-h] [-x X] [--spam NEW_SPAM]
4385
4386 optional arguments:
4387 -h, --help show this help message and exit
4388 -x X NEW X
4389 --spam NEW_SPAM
4390 '''))
4391
4392
4393# =============================
4394# Help and Version option tests
4395# =============================
4396
4397class TestOptionalsHelpVersionActions(TestCase):
4398 """Test the help and version actions"""
4399
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004400 def assertPrintHelpExit(self, parser, args_str):
Berker Peksag1c5f56a2014-07-06 09:33:20 +03004401 with self.assertRaises(ArgumentParserError) as cm:
4402 parser.parse_args(args_str.split())
4403 self.assertEqual(parser.format_help(), cm.exception.stdout)
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004404
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004405 def assertArgumentParserError(self, parser, *args):
4406 self.assertRaises(ArgumentParserError, parser.parse_args, args)
4407
4408 def test_version(self):
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02004409 parser = ErrorRaisingArgumentParser()
4410 parser.add_argument('-v', '--version', action='version', version='1.0')
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004411 self.assertPrintHelpExit(parser, '-h')
4412 self.assertPrintHelpExit(parser, '--help')
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02004413 self.assertRaises(AttributeError, getattr, parser, 'format_version')
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004414
4415 def test_version_format(self):
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02004416 parser = ErrorRaisingArgumentParser(prog='PPP')
4417 parser.add_argument('-v', '--version', action='version', version='%(prog)s 3.5')
Berker Peksag1c5f56a2014-07-06 09:33:20 +03004418 with self.assertRaises(ArgumentParserError) as cm:
4419 parser.parse_args(['-v'])
4420 self.assertEqual('PPP 3.5\n', cm.exception.stdout)
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004421
4422 def test_version_no_help(self):
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02004423 parser = ErrorRaisingArgumentParser(add_help=False)
4424 parser.add_argument('-v', '--version', action='version', version='1.0')
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004425 self.assertArgumentParserError(parser, '-h')
4426 self.assertArgumentParserError(parser, '--help')
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02004427 self.assertRaises(AttributeError, getattr, parser, 'format_version')
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004428
4429 def test_version_action(self):
4430 parser = ErrorRaisingArgumentParser(prog='XXX')
4431 parser.add_argument('-V', action='version', version='%(prog)s 3.7')
Berker Peksag1c5f56a2014-07-06 09:33:20 +03004432 with self.assertRaises(ArgumentParserError) as cm:
4433 parser.parse_args(['-V'])
4434 self.assertEqual('XXX 3.7\n', cm.exception.stdout)
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004435
4436 def test_no_help(self):
4437 parser = ErrorRaisingArgumentParser(add_help=False)
4438 self.assertArgumentParserError(parser, '-h')
4439 self.assertArgumentParserError(parser, '--help')
4440 self.assertArgumentParserError(parser, '-v')
4441 self.assertArgumentParserError(parser, '--version')
4442
4443 def test_alternate_help_version(self):
4444 parser = ErrorRaisingArgumentParser()
4445 parser.add_argument('-x', action='help')
4446 parser.add_argument('-y', action='version')
4447 self.assertPrintHelpExit(parser, '-x')
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004448 self.assertArgumentParserError(parser, '-v')
4449 self.assertArgumentParserError(parser, '--version')
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02004450 self.assertRaises(AttributeError, getattr, parser, 'format_version')
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004451
4452 def test_help_version_extra_arguments(self):
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02004453 parser = ErrorRaisingArgumentParser()
4454 parser.add_argument('--version', action='version', version='1.0')
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004455 parser.add_argument('-x', action='store_true')
4456 parser.add_argument('y')
4457
4458 # try all combinations of valid prefixes and suffixes
4459 valid_prefixes = ['', '-x', 'foo', '-x bar', 'baz -x']
4460 valid_suffixes = valid_prefixes + ['--bad-option', 'foo bar baz']
4461 for prefix in valid_prefixes:
4462 for suffix in valid_suffixes:
4463 format = '%s %%s %s' % (prefix, suffix)
4464 self.assertPrintHelpExit(parser, format % '-h')
4465 self.assertPrintHelpExit(parser, format % '--help')
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02004466 self.assertRaises(AttributeError, getattr, parser, 'format_version')
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004467
4468
4469# ======================
4470# str() and repr() tests
4471# ======================
4472
4473class TestStrings(TestCase):
4474 """Test str() and repr() on Optionals and Positionals"""
4475
4476 def assertStringEqual(self, obj, result_string):
4477 for func in [str, repr]:
4478 self.assertEqual(func(obj), result_string)
4479
4480 def test_optional(self):
4481 option = argparse.Action(
4482 option_strings=['--foo', '-a', '-b'],
4483 dest='b',
4484 type='int',
4485 nargs='+',
4486 default=42,
4487 choices=[1, 2, 3],
4488 help='HELP',
4489 metavar='METAVAR')
4490 string = (
4491 "Action(option_strings=['--foo', '-a', '-b'], dest='b', "
4492 "nargs='+', const=None, default=42, type='int', "
4493 "choices=[1, 2, 3], help='HELP', metavar='METAVAR')")
4494 self.assertStringEqual(option, string)
4495
4496 def test_argument(self):
4497 argument = argparse.Action(
4498 option_strings=[],
4499 dest='x',
4500 type=float,
4501 nargs='?',
4502 default=2.5,
4503 choices=[0.5, 1.5, 2.5],
4504 help='H HH H',
4505 metavar='MV MV MV')
4506 string = (
4507 "Action(option_strings=[], dest='x', nargs='?', "
4508 "const=None, default=2.5, type=%r, choices=[0.5, 1.5, 2.5], "
4509 "help='H HH H', metavar='MV MV MV')" % float)
4510 self.assertStringEqual(argument, string)
4511
4512 def test_namespace(self):
4513 ns = argparse.Namespace(foo=42, bar='spam')
4514 string = "Namespace(bar='spam', foo=42)"
4515 self.assertStringEqual(ns, string)
4516
4517 def test_parser(self):
4518 parser = argparse.ArgumentParser(prog='PROG')
4519 string = (
4520 "ArgumentParser(prog='PROG', usage=None, description=None, "
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02004521 "formatter_class=%r, conflict_handler='error', "
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004522 "add_help=True)" % argparse.HelpFormatter)
4523 self.assertStringEqual(parser, string)
4524
4525# ===============
4526# Namespace tests
4527# ===============
4528
4529class TestNamespace(TestCase):
4530
4531 def test_constructor(self):
4532 ns = argparse.Namespace()
4533 self.assertRaises(AttributeError, getattr, ns, 'x')
4534
4535 ns = argparse.Namespace(a=42, b='spam')
4536 self.assertEqual(ns.a, 42)
4537 self.assertEqual(ns.b, 'spam')
4538
4539 def test_equality(self):
4540 ns1 = argparse.Namespace(a=1, b=2)
4541 ns2 = argparse.Namespace(b=2, a=1)
4542 ns3 = argparse.Namespace(a=1)
4543 ns4 = argparse.Namespace(b=2)
4544
4545 self.assertEqual(ns1, ns2)
4546 self.assertNotEqual(ns1, ns3)
4547 self.assertNotEqual(ns1, ns4)
4548 self.assertNotEqual(ns2, ns3)
4549 self.assertNotEqual(ns2, ns4)
4550 self.assertTrue(ns1 != ns3)
4551 self.assertTrue(ns1 != ns4)
4552 self.assertTrue(ns2 != ns3)
4553 self.assertTrue(ns2 != ns4)
4554
Raymond Hettingerdea46ec2014-05-26 00:43:27 -07004555 def test_equality_returns_notimplemeted(self):
4556 # See issue 21481
4557 ns = argparse.Namespace(a=1, b=2)
4558 self.assertIs(ns.__eq__(None), NotImplemented)
4559 self.assertIs(ns.__ne__(None), NotImplemented)
4560
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004561
4562# ===================
4563# File encoding tests
4564# ===================
4565
4566class TestEncoding(TestCase):
4567
4568 def _test_module_encoding(self, path):
4569 path, _ = os.path.splitext(path)
4570 path += ".py"
Marc-André Lemburg8f36af72011-02-25 15:42:01 +00004571 with codecs.open(path, 'r', 'utf-8') as f:
Antoine Pitroub86680e2010-10-14 21:15:17 +00004572 f.read()
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004573
4574 def test_argparse_module_encoding(self):
4575 self._test_module_encoding(argparse.__file__)
4576
4577 def test_test_argparse_module_encoding(self):
4578 self._test_module_encoding(__file__)
4579
4580# ===================
4581# ArgumentError tests
4582# ===================
4583
4584class TestArgumentError(TestCase):
4585
4586 def test_argument_error(self):
4587 msg = "my error here"
4588 error = argparse.ArgumentError(None, msg)
4589 self.assertEqual(str(error), msg)
4590
4591# =======================
4592# ArgumentTypeError tests
4593# =======================
4594
R. David Murray722b5fd2010-11-20 03:48:58 +00004595class TestArgumentTypeError(TestCase):
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004596
4597 def test_argument_type_error(self):
4598
4599 def spam(string):
4600 raise argparse.ArgumentTypeError('spam!')
4601
4602 parser = ErrorRaisingArgumentParser(prog='PROG', add_help=False)
4603 parser.add_argument('x', type=spam)
Berker Peksag1c5f56a2014-07-06 09:33:20 +03004604 with self.assertRaises(ArgumentParserError) as cm:
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004605 parser.parse_args(['XXX'])
Berker Peksag1c5f56a2014-07-06 09:33:20 +03004606 self.assertEqual('usage: PROG x\nPROG: error: argument x: spam!\n',
4607 cm.exception.stderr)
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004608
R David Murrayf97c59a2011-06-09 12:34:07 -04004609# =========================
4610# MessageContentError tests
4611# =========================
4612
4613class TestMessageContentError(TestCase):
4614
4615 def test_missing_argument_name_in_message(self):
4616 parser = ErrorRaisingArgumentParser(prog='PROG', usage='')
4617 parser.add_argument('req_pos', type=str)
4618 parser.add_argument('-req_opt', type=int, required=True)
4619 parser.add_argument('need_one', type=str, nargs='+')
4620
4621 with self.assertRaises(ArgumentParserError) as cm:
4622 parser.parse_args([])
4623 msg = str(cm.exception)
4624 self.assertRegex(msg, 'req_pos')
4625 self.assertRegex(msg, 'req_opt')
4626 self.assertRegex(msg, 'need_one')
4627 with self.assertRaises(ArgumentParserError) as cm:
4628 parser.parse_args(['myXargument'])
4629 msg = str(cm.exception)
4630 self.assertNotIn(msg, 'req_pos')
4631 self.assertRegex(msg, 'req_opt')
4632 self.assertRegex(msg, 'need_one')
4633 with self.assertRaises(ArgumentParserError) as cm:
4634 parser.parse_args(['myXargument', '-req_opt=1'])
4635 msg = str(cm.exception)
4636 self.assertNotIn(msg, 'req_pos')
4637 self.assertNotIn(msg, 'req_opt')
4638 self.assertRegex(msg, 'need_one')
4639
4640 def test_optional_optional_not_in_message(self):
4641 parser = ErrorRaisingArgumentParser(prog='PROG', usage='')
4642 parser.add_argument('req_pos', type=str)
4643 parser.add_argument('--req_opt', type=int, required=True)
4644 parser.add_argument('--opt_opt', type=bool, nargs='?',
4645 default=True)
4646 with self.assertRaises(ArgumentParserError) as cm:
4647 parser.parse_args([])
4648 msg = str(cm.exception)
4649 self.assertRegex(msg, 'req_pos')
4650 self.assertRegex(msg, 'req_opt')
4651 self.assertNotIn(msg, 'opt_opt')
4652 with self.assertRaises(ArgumentParserError) as cm:
4653 parser.parse_args(['--req_opt=1'])
4654 msg = str(cm.exception)
4655 self.assertRegex(msg, 'req_pos')
4656 self.assertNotIn(msg, 'req_opt')
4657 self.assertNotIn(msg, 'opt_opt')
4658
4659 def test_optional_positional_not_in_message(self):
4660 parser = ErrorRaisingArgumentParser(prog='PROG', usage='')
4661 parser.add_argument('req_pos')
4662 parser.add_argument('optional_positional', nargs='?', default='eggs')
4663 with self.assertRaises(ArgumentParserError) as cm:
4664 parser.parse_args([])
4665 msg = str(cm.exception)
4666 self.assertRegex(msg, 'req_pos')
4667 self.assertNotIn(msg, 'optional_positional')
4668
4669
R David Murray6fb8fb12012-08-31 22:45:20 -04004670# ================================================
4671# Check that the type function is called only once
4672# ================================================
4673
4674class TestTypeFunctionCallOnlyOnce(TestCase):
4675
4676 def test_type_function_call_only_once(self):
4677 def spam(string_to_convert):
4678 self.assertEqual(string_to_convert, 'spam!')
4679 return 'foo_converted'
4680
4681 parser = argparse.ArgumentParser()
4682 parser.add_argument('--foo', type=spam, default='bar')
4683 args = parser.parse_args('--foo spam!'.split())
4684 self.assertEqual(NS(foo='foo_converted'), args)
4685
Barry Warsaweaae1b72012-09-12 14:34:50 -04004686# ==================================================================
4687# Check semantics regarding the default argument and type conversion
4688# ==================================================================
R David Murray6fb8fb12012-08-31 22:45:20 -04004689
Barry Warsaweaae1b72012-09-12 14:34:50 -04004690class TestTypeFunctionCalledOnDefault(TestCase):
R David Murray6fb8fb12012-08-31 22:45:20 -04004691
4692 def test_type_function_call_with_non_string_default(self):
4693 def spam(int_to_convert):
4694 self.assertEqual(int_to_convert, 0)
4695 return 'foo_converted'
4696
4697 parser = argparse.ArgumentParser()
4698 parser.add_argument('--foo', type=spam, default=0)
4699 args = parser.parse_args([])
Barry Warsaweaae1b72012-09-12 14:34:50 -04004700 # foo should *not* be converted because its default is not a string.
4701 self.assertEqual(NS(foo=0), args)
4702
4703 def test_type_function_call_with_string_default(self):
4704 def spam(int_to_convert):
4705 return 'foo_converted'
4706
4707 parser = argparse.ArgumentParser()
4708 parser.add_argument('--foo', type=spam, default='0')
4709 args = parser.parse_args([])
4710 # foo is converted because its default is a string.
R David Murray6fb8fb12012-08-31 22:45:20 -04004711 self.assertEqual(NS(foo='foo_converted'), args)
4712
Barry Warsaweaae1b72012-09-12 14:34:50 -04004713 def test_no_double_type_conversion_of_default(self):
4714 def extend(str_to_convert):
4715 return str_to_convert + '*'
4716
4717 parser = argparse.ArgumentParser()
4718 parser.add_argument('--test', type=extend, default='*')
4719 args = parser.parse_args([])
4720 # The test argument will be two stars, one coming from the default
4721 # value and one coming from the type conversion being called exactly
4722 # once.
4723 self.assertEqual(NS(test='**'), args)
4724
Barry Warsaw4b2f9e92012-09-11 22:38:47 -04004725 def test_issue_15906(self):
4726 # Issue #15906: When action='append', type=str, default=[] are
4727 # providing, the dest value was the string representation "[]" when it
4728 # should have been an empty list.
4729 parser = argparse.ArgumentParser()
4730 parser.add_argument('--test', dest='test', type=str,
4731 default=[], action='append')
4732 args = parser.parse_args([])
4733 self.assertEqual(args.test, [])
4734
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004735# ======================
4736# parse_known_args tests
4737# ======================
4738
4739class TestParseKnownArgs(TestCase):
4740
R David Murrayb5228282012-09-08 12:08:01 -04004741 def test_arguments_tuple(self):
4742 parser = argparse.ArgumentParser()
4743 parser.parse_args(())
4744
4745 def test_arguments_list(self):
4746 parser = argparse.ArgumentParser()
4747 parser.parse_args([])
4748
4749 def test_arguments_tuple_positional(self):
4750 parser = argparse.ArgumentParser()
4751 parser.add_argument('x')
4752 parser.parse_args(('x',))
4753
4754 def test_arguments_list_positional(self):
4755 parser = argparse.ArgumentParser()
4756 parser.add_argument('x')
4757 parser.parse_args(['x'])
4758
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004759 def test_optionals(self):
4760 parser = argparse.ArgumentParser()
4761 parser.add_argument('--foo')
4762 args, extras = parser.parse_known_args('--foo F --bar --baz'.split())
4763 self.assertEqual(NS(foo='F'), args)
4764 self.assertEqual(['--bar', '--baz'], extras)
4765
4766 def test_mixed(self):
4767 parser = argparse.ArgumentParser()
4768 parser.add_argument('-v', nargs='?', const=1, type=int)
4769 parser.add_argument('--spam', action='store_false')
4770 parser.add_argument('badger')
4771
4772 argv = ["B", "C", "--foo", "-v", "3", "4"]
4773 args, extras = parser.parse_known_args(argv)
4774 self.assertEqual(NS(v=3, spam=True, badger="B"), args)
4775 self.assertEqual(["C", "--foo", "4"], extras)
4776
Steven Bethard8d9a4622011-03-26 17:33:56 +01004777# ==========================
4778# add_argument metavar tests
4779# ==========================
4780
4781class TestAddArgumentMetavar(TestCase):
4782
4783 EXPECTED_MESSAGE = "length of metavar tuple does not match nargs"
4784
4785 def do_test_no_exception(self, nargs, metavar):
4786 parser = argparse.ArgumentParser()
4787 parser.add_argument("--foo", nargs=nargs, metavar=metavar)
4788
4789 def do_test_exception(self, nargs, metavar):
4790 parser = argparse.ArgumentParser()
4791 with self.assertRaises(ValueError) as cm:
4792 parser.add_argument("--foo", nargs=nargs, metavar=metavar)
4793 self.assertEqual(cm.exception.args[0], self.EXPECTED_MESSAGE)
4794
4795 # Unit tests for different values of metavar when nargs=None
4796
4797 def test_nargs_None_metavar_string(self):
4798 self.do_test_no_exception(nargs=None, metavar="1")
4799
4800 def test_nargs_None_metavar_length0(self):
4801 self.do_test_exception(nargs=None, metavar=tuple())
4802
4803 def test_nargs_None_metavar_length1(self):
4804 self.do_test_no_exception(nargs=None, metavar=("1"))
4805
4806 def test_nargs_None_metavar_length2(self):
4807 self.do_test_exception(nargs=None, metavar=("1", "2"))
4808
4809 def test_nargs_None_metavar_length3(self):
4810 self.do_test_exception(nargs=None, metavar=("1", "2", "3"))
4811
4812 # Unit tests for different values of metavar when nargs=?
4813
4814 def test_nargs_optional_metavar_string(self):
4815 self.do_test_no_exception(nargs="?", metavar="1")
4816
4817 def test_nargs_optional_metavar_length0(self):
4818 self.do_test_exception(nargs="?", metavar=tuple())
4819
4820 def test_nargs_optional_metavar_length1(self):
4821 self.do_test_no_exception(nargs="?", metavar=("1"))
4822
4823 def test_nargs_optional_metavar_length2(self):
4824 self.do_test_exception(nargs="?", metavar=("1", "2"))
4825
4826 def test_nargs_optional_metavar_length3(self):
4827 self.do_test_exception(nargs="?", metavar=("1", "2", "3"))
4828
4829 # Unit tests for different values of metavar when nargs=*
4830
4831 def test_nargs_zeroormore_metavar_string(self):
4832 self.do_test_no_exception(nargs="*", metavar="1")
4833
4834 def test_nargs_zeroormore_metavar_length0(self):
4835 self.do_test_exception(nargs="*", metavar=tuple())
4836
4837 def test_nargs_zeroormore_metavar_length1(self):
4838 self.do_test_no_exception(nargs="*", metavar=("1"))
4839
4840 def test_nargs_zeroormore_metavar_length2(self):
4841 self.do_test_no_exception(nargs="*", metavar=("1", "2"))
4842
4843 def test_nargs_zeroormore_metavar_length3(self):
4844 self.do_test_exception(nargs="*", metavar=("1", "2", "3"))
4845
4846 # Unit tests for different values of metavar when nargs=+
4847
4848 def test_nargs_oneormore_metavar_string(self):
4849 self.do_test_no_exception(nargs="+", metavar="1")
4850
4851 def test_nargs_oneormore_metavar_length0(self):
4852 self.do_test_exception(nargs="+", metavar=tuple())
4853
4854 def test_nargs_oneormore_metavar_length1(self):
4855 self.do_test_no_exception(nargs="+", metavar=("1"))
4856
4857 def test_nargs_oneormore_metavar_length2(self):
4858 self.do_test_no_exception(nargs="+", metavar=("1", "2"))
4859
4860 def test_nargs_oneormore_metavar_length3(self):
4861 self.do_test_exception(nargs="+", metavar=("1", "2", "3"))
4862
4863 # Unit tests for different values of metavar when nargs=...
4864
4865 def test_nargs_remainder_metavar_string(self):
4866 self.do_test_no_exception(nargs="...", metavar="1")
4867
4868 def test_nargs_remainder_metavar_length0(self):
4869 self.do_test_no_exception(nargs="...", metavar=tuple())
4870
4871 def test_nargs_remainder_metavar_length1(self):
4872 self.do_test_no_exception(nargs="...", metavar=("1"))
4873
4874 def test_nargs_remainder_metavar_length2(self):
4875 self.do_test_no_exception(nargs="...", metavar=("1", "2"))
4876
4877 def test_nargs_remainder_metavar_length3(self):
4878 self.do_test_no_exception(nargs="...", metavar=("1", "2", "3"))
4879
4880 # Unit tests for different values of metavar when nargs=A...
4881
4882 def test_nargs_parser_metavar_string(self):
4883 self.do_test_no_exception(nargs="A...", metavar="1")
4884
4885 def test_nargs_parser_metavar_length0(self):
4886 self.do_test_exception(nargs="A...", metavar=tuple())
4887
4888 def test_nargs_parser_metavar_length1(self):
4889 self.do_test_no_exception(nargs="A...", metavar=("1"))
4890
4891 def test_nargs_parser_metavar_length2(self):
4892 self.do_test_exception(nargs="A...", metavar=("1", "2"))
4893
4894 def test_nargs_parser_metavar_length3(self):
4895 self.do_test_exception(nargs="A...", metavar=("1", "2", "3"))
4896
4897 # Unit tests for different values of metavar when nargs=1
4898
4899 def test_nargs_1_metavar_string(self):
4900 self.do_test_no_exception(nargs=1, metavar="1")
4901
4902 def test_nargs_1_metavar_length0(self):
4903 self.do_test_exception(nargs=1, metavar=tuple())
4904
4905 def test_nargs_1_metavar_length1(self):
4906 self.do_test_no_exception(nargs=1, metavar=("1"))
4907
4908 def test_nargs_1_metavar_length2(self):
4909 self.do_test_exception(nargs=1, metavar=("1", "2"))
4910
4911 def test_nargs_1_metavar_length3(self):
4912 self.do_test_exception(nargs=1, metavar=("1", "2", "3"))
4913
4914 # Unit tests for different values of metavar when nargs=2
4915
4916 def test_nargs_2_metavar_string(self):
4917 self.do_test_no_exception(nargs=2, metavar="1")
4918
4919 def test_nargs_2_metavar_length0(self):
4920 self.do_test_exception(nargs=2, metavar=tuple())
4921
4922 def test_nargs_2_metavar_length1(self):
4923 self.do_test_no_exception(nargs=2, metavar=("1"))
4924
4925 def test_nargs_2_metavar_length2(self):
4926 self.do_test_no_exception(nargs=2, metavar=("1", "2"))
4927
4928 def test_nargs_2_metavar_length3(self):
4929 self.do_test_exception(nargs=2, metavar=("1", "2", "3"))
4930
4931 # Unit tests for different values of metavar when nargs=3
4932
4933 def test_nargs_3_metavar_string(self):
4934 self.do_test_no_exception(nargs=3, metavar="1")
4935
4936 def test_nargs_3_metavar_length0(self):
4937 self.do_test_exception(nargs=3, metavar=tuple())
4938
4939 def test_nargs_3_metavar_length1(self):
4940 self.do_test_no_exception(nargs=3, metavar=("1"))
4941
4942 def test_nargs_3_metavar_length2(self):
4943 self.do_test_exception(nargs=3, metavar=("1", "2"))
4944
4945 def test_nargs_3_metavar_length3(self):
4946 self.do_test_no_exception(nargs=3, metavar=("1", "2", "3"))
4947
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004948# ============================
4949# from argparse import * tests
4950# ============================
4951
4952class TestImportStar(TestCase):
4953
4954 def test(self):
4955 for name in argparse.__all__:
4956 self.assertTrue(hasattr(argparse, name))
4957
Steven Bethard72c55382010-11-01 15:23:12 +00004958 def test_all_exports_everything_but_modules(self):
4959 items = [
4960 name
4961 for name, value in vars(argparse).items()
Éric Araujo12159152010-12-04 17:31:49 +00004962 if not (name.startswith("_") or name == 'ngettext')
Steven Bethard72c55382010-11-01 15:23:12 +00004963 if not inspect.ismodule(value)
4964 ]
4965 self.assertEqual(sorted(items), sorted(argparse.__all__))
4966
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004967def test_main():
Florent Xiclunaaf1adbe2012-07-07 17:02:22 +02004968 support.run_unittest(__name__)
Benjamin Peterson4fd181c2010-03-02 23:46:42 +00004969 # Remove global references to avoid looking like we have refleaks.
4970 RFile.seen = {}
4971 WFile.seen = set()
4972
Benjamin Peterson698a18a2010-03-02 22:34:37 +00004973
4974
4975if __name__ == '__main__':
4976 test_main()