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