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