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