]> git.proxmox.com Git - mirror_edk2.git/blob - AppPkg/Applications/Python/Python-2.7.2/Lib/test/test_argparse.py
EmbeddedPkg: Extend NvVarStoreFormattedLib LIBRARY_CLASS
[mirror_edk2.git] / AppPkg / Applications / Python / Python-2.7.2 / Lib / test / test_argparse.py
1 # Author: Steven J. Bethard <steven.bethard@gmail.com>.
2
3 import codecs
4 import inspect
5 import os
6 import shutil
7 import stat
8 import sys
9 import textwrap
10 import tempfile
11 import unittest
12 import argparse
13
14 from StringIO import StringIO
15
16 class StdIOBuffer(StringIO):
17 pass
18
19 from test import test_support
20
21 class 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
32 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__)
39
40
41 class 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)
50 shutil.rmtree(self.temp_dir, True)
51
52 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)
57
58 class Sig(object):
59
60 def __init__(self, *args, **kwargs):
61 self.args = args
62 self.kwargs = kwargs
63
64
65 class NS(object):
66
67 def __init__(self, **kwargs):
68 self.__dict__.update(kwargs)
69
70 def __repr__(self):
71 sorted_items = sorted(self.__dict__.items())
72 kwarg_str = ', '.join(['%s=%r' % tup for tup in sorted_items])
73 return '%s(%s)' % (type(self).__name__, kwarg_str)
74
75 __hash__ = None
76
77 def __eq__(self, other):
78 return vars(self) == vars(other)
79
80 def __ne__(self, other):
81 return not (self == other)
82
83
84 class 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
94 def 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
98 if isinstance(sys.stderr, StdIOBuffer) or isinstance(sys.stdout, StdIOBuffer):
99 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
105 sys.stdout = StdIOBuffer()
106 sys.stderr = StdIOBuffer()
107 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
126 class 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
141 class 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
254 bases = TestCase,
255 ParserTestCase = ParserTesterMetaclass('ParserTestCase', bases, {})
256
257 # ===============
258 # Optionals tests
259 # ===============
260
261 class 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
275 class 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
301 class 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
315 class 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
331 class 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
347 class 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
360 class 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
374 class 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
392 class 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
411 class 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
430 class TestOptionalsAlternatePrefixChars(ParserTestCase):
431 """Test an Optional with option strings with custom prefixes"""
432
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 ]
439 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
450 class 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 ]
461 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)),
468 ('/ba +f', NS(f=True, bar=None, baz=42))
469 ]
470
471
472 class 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
495 class 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
511 class 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
524 class 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
536 class 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
547 class 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
558 class 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
569 class 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
592 class 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
611 class 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
628 class 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
645 class 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
658 class 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
669 class 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
680 class 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
691 class 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
702 class 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
714 class 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
726 class 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
741 class 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
756 class 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
771 class 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
781 class 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
791 class 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
801 class 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
813 class 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
825 class 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
836 class 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
847 class 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
858 class 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
873 class 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
883 class 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
893 class 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
903 class 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
915 class 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
926 class 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
937 class 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
949 class 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
960 class 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
971 class 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
982 class 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
992 class 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
1003 class 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
1015 class 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
1026 class 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
1037 class 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
1052 class 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
1067 class 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
1082 class 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
1097 class 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
1110 class 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
1122 class 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
1133 class 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
1144 class 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
1160 class 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
1176 class 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
1193 class 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
1212 class 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
1231 class 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
1247 class 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
1260 class 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
1287 class 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
1306 class 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
1326 class 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
1346 class 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
1380 class 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
1415 class 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
1426 class RFile(object):
1427 seen = {}
1428
1429 def __init__(self, name):
1430 self.name = name
1431
1432 __hash__ = None
1433
1434 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
1445 class 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()
1454 self.create_readonly_file('readonly')
1455
1456 argument_signatures = [
1457 Sig('-x', type=argparse.FileType()),
1458 Sig('spam', type=argparse.FileType('r')),
1459 ]
1460 failures = ['-x', '-x bar', 'non-existent-file.txt']
1461 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)),
1466 ('readonly', NS(x=None, spam=RFile('readonly'))),
1467 ]
1468
1469
1470 class 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
1493 class WFile(object):
1494 seen = set()
1495
1496 def __init__(self, name):
1497 self.name = name
1498
1499 __hash__ = None
1500
1501 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
1512 class TestFileTypeW(TempDirMixin, ParserTestCase):
1513 """Test the FileType option/argument type for writing files"""
1514
1515 def setUp(self):
1516 super(TestFileTypeW, self).setUp()
1517 self.create_readonly_file('readonly')
1518
1519 argument_signatures = [
1520 Sig('-x', type=argparse.FileType('w')),
1521 Sig('spam', type=argparse.FileType('w')),
1522 ]
1523 failures = ['-x', '-x bar']
1524 failures = ['-x', '-x bar', 'readonly']
1525 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
1533 class 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
1548 class 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
1563 class 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
1571 __hash__ = None
1572
1573 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
1587 class TestTypeClassicClass(ParserTestCase):
1588 """Test a classic class type"""
1589
1590 class C:
1591
1592 def __init__(self, value):
1593 self.value = value
1594
1595 __hash__ = None
1596
1597 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
1611 class 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
1634 class 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
1701 class 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
1723 class TestAddSubparsers(TestCase):
1724 """Test the add_subparsers method"""
1725
1726 def assertArgumentParserError(self, *args, **kwargs):
1727 self.assertRaises(ArgumentParserError, *args, **kwargs)
1728
1729 def _get_parser(self, subparser_help=False, prefix_chars=None):
1730 # create a parser with a subparsers argument
1731 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')
1741 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):
1768 super(TestAddSubparsers, self).setUp()
1769 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
1794 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
1816 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
1842 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
1880 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
1972 class 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())
1983 self.assertEqual(expected, result)
1984
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())
1993 self.assertEqual(expected, result)
1994
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())
2005 self.assertEqual(expected, result)
2006
2007 # ===================
2008 # Parent parser tests
2009 # ===================
2010
2011 class 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):
2018 super(TestParentParsers, self).setUp()
2019 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
2043 self.main_program = os.path.basename(sys.argv[0])
2044
2045 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('''\
2137 usage: {} [-h] [-b B] [--d D] [--w W] [-y Y] a z
2138
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
2153 '''.format(self.main_program)))
2154
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('''\
2170 usage: {} [-h] [-w W] [-x X] [-y Y | -z Z]
2171
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
2182 '''.format(self.main_program)))
2183
2184 # ==============================
2185 # Mutually exclusive group tests
2186 # ==============================
2187
2188 class 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
2206 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))
2225
2226 class 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
2274 class 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
2309 class 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
2352 class 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
2385 class 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
2421 class 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
2466 class 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
2508 class 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
2548 class 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
2593 class 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
2602 class TestMutuallyExclusiveGroupErrorsParent(
2603 MEPBase, TestMutuallyExclusiveGroupErrors):
2604 pass
2605
2606
2607 class TestMutuallyExclusiveSimpleParent(
2608 MEPBase, TestMutuallyExclusiveSimple):
2609 pass
2610
2611
2612 class TestMutuallyExclusiveLongParent(
2613 MEPBase, TestMutuallyExclusiveLong):
2614 pass
2615
2616
2617 class TestMutuallyExclusiveFirstSuppressedParent(
2618 MEPBase, TestMutuallyExclusiveFirstSuppressed):
2619 pass
2620
2621
2622 class TestMutuallyExclusiveManySuppressedParent(
2623 MEPBase, TestMutuallyExclusiveManySuppressed):
2624 pass
2625
2626
2627 class TestMutuallyExclusiveOptionalAndPositionalParent(
2628 MEPBase, TestMutuallyExclusiveOptionalAndPositional):
2629 pass
2630
2631
2632 class TestMutuallyExclusiveOptionalsMixedParent(
2633 MEPBase, TestMutuallyExclusiveOptionalsMixed):
2634 pass
2635
2636
2637 class TestMutuallyExclusiveOptionalsAndPositionalsMixedParent(
2638 MEPBase, TestMutuallyExclusiveOptionalsAndPositionalsMixed):
2639 pass
2640
2641 # =================
2642 # Set default tests
2643 # =================
2644
2645 class 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
2732 class 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
2755 class TestNamespaceContainsSimple(TestCase):
2756
2757 def test_empty(self):
2758 ns = argparse.Namespace()
2759 self.assertEqual('' in ns, False)
2760 self.assertEqual('' not in ns, True)
2761 self.assertEqual('x' in ns, False)
2762
2763 def test_non_empty(self):
2764 ns = argparse.Namespace(x=1, y=2)
2765 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)
2771
2772 # =====================
2773 # Help formatting tests
2774 # =====================
2775
2776 class 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 getattr(tester, 'argument_signatures', []):
2806 parser.add_argument(*argument_sig.args,
2807 **argument_sig.kwargs)
2808 group_sigs = getattr(tester, 'argument_group_signatures', [])
2809 for group_sig, argument_sigs in group_sigs:
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 subparsers_sigs = getattr(tester, 'subparsers_signatures', [])
2816 if subparsers_sigs:
2817 subparsers = parser.add_subparsers()
2818 for subparser_sig in subparsers_sigs:
2819 subparsers.add_parser(*subparser_sig.args,
2820 **subparser_sig.kwargs)
2821 return parser
2822
2823 def _test(self, tester, parser_text):
2824 expected_text = getattr(tester, self.func_suffix)
2825 expected_text = textwrap.dedent(expected_text)
2826 if expected_text != parser_text:
2827 print(repr(expected_text))
2828 print(repr(parser_text))
2829 for char1, char2 in zip(expected_text, parser_text):
2830 if char1 != char2:
2831 print('first diff: %r %r' % (char1, char2))
2832 break
2833 tester.assertEqual(expected_text, parser_text)
2834
2835 def test_format(self, tester):
2836 parser = self._get_parser(tester)
2837 format = getattr(parser, 'format_%s' % self.func_suffix)
2838 self._test(tester, format())
2839
2840 def test_print(self, tester):
2841 parser = self._get_parser(tester)
2842 print_ = getattr(parser, 'print_%s' % self.func_suffix)
2843 old_stream = getattr(sys, self.std_name)
2844 setattr(sys, self.std_name, StdIOBuffer())
2845 try:
2846 print_()
2847 parser_text = getattr(sys, self.std_name).getvalue()
2848 finally:
2849 setattr(sys, self.std_name, old_stream)
2850 self._test(tester, parser_text)
2851
2852 def test_print_file(self, tester):
2853 parser = self._get_parser(tester)
2854 print_ = getattr(parser, 'print_%s' % self.func_suffix)
2855 sfile = StdIOBuffer()
2856 print_(sfile)
2857 parser_text = sfile.getvalue()
2858 self._test(tester, parser_text)
2859
2860 # add tests for {format,print}_{usage,help,version}
2861 for func_suffix, std_name in [('usage', 'stdout'),
2862 ('help', 'stdout'),
2863 ('version', 'stderr')]:
2864 AddTests(cls, func_suffix, std_name)
2865
2866 bases = TestCase,
2867 HelpTestCase = TestHelpFormattingMetaclass('HelpTestCase', bases, {})
2868
2869
2870 class TestHelpBiggerOptionals(HelpTestCase):
2871 """Make sure that argument help aligns when options are longer"""
2872
2873 parser_signature = Sig(prog='PROG', description='DESCRIPTION',
2874 epilog='EPILOG', version='0.1')
2875 argument_signatures = [
2876 Sig('-x', action='store_true', help='X HELP'),
2877 Sig('--y', help='Y HELP'),
2878 Sig('foo', help='FOO HELP'),
2879 Sig('bar', help='BAR HELP'),
2880 ]
2881 argument_group_signatures = []
2882 usage = '''\
2883 usage: PROG [-h] [-v] [-x] [--y Y] foo bar
2884 '''
2885 help = usage + '''\
2886
2887 DESCRIPTION
2888
2889 positional arguments:
2890 foo FOO HELP
2891 bar BAR HELP
2892
2893 optional arguments:
2894 -h, --help show this help message and exit
2895 -v, --version show program's version number and exit
2896 -x X HELP
2897 --y Y Y HELP
2898
2899 EPILOG
2900 '''
2901 version = '''\
2902 0.1
2903 '''
2904
2905
2906 class TestHelpBiggerOptionalGroups(HelpTestCase):
2907 """Make sure that argument help aligns when options are longer"""
2908
2909 parser_signature = Sig(prog='PROG', description='DESCRIPTION',
2910 epilog='EPILOG', version='0.1')
2911 argument_signatures = [
2912 Sig('-x', action='store_true', help='X HELP'),
2913 Sig('--y', help='Y HELP'),
2914 Sig('foo', help='FOO HELP'),
2915 Sig('bar', help='BAR HELP'),
2916 ]
2917 argument_group_signatures = [
2918 (Sig('GROUP TITLE', description='GROUP DESCRIPTION'), [
2919 Sig('baz', help='BAZ HELP'),
2920 Sig('-z', nargs='+', help='Z HELP')]),
2921 ]
2922 usage = '''\
2923 usage: PROG [-h] [-v] [-x] [--y Y] [-z Z [Z ...]] foo bar baz
2924 '''
2925 help = usage + '''\
2926
2927 DESCRIPTION
2928
2929 positional arguments:
2930 foo FOO HELP
2931 bar BAR HELP
2932
2933 optional arguments:
2934 -h, --help show this help message and exit
2935 -v, --version show program's version number and exit
2936 -x X HELP
2937 --y Y Y HELP
2938
2939 GROUP TITLE:
2940 GROUP DESCRIPTION
2941
2942 baz BAZ HELP
2943 -z Z [Z ...] Z HELP
2944
2945 EPILOG
2946 '''
2947 version = '''\
2948 0.1
2949 '''
2950
2951
2952 class TestHelpBiggerPositionals(HelpTestCase):
2953 """Make sure that help aligns when arguments are longer"""
2954
2955 parser_signature = Sig(usage='USAGE', description='DESCRIPTION')
2956 argument_signatures = [
2957 Sig('-x', action='store_true', help='X HELP'),
2958 Sig('--y', help='Y HELP'),
2959 Sig('ekiekiekifekang', help='EKI HELP'),
2960 Sig('bar', help='BAR HELP'),
2961 ]
2962 argument_group_signatures = []
2963 usage = '''\
2964 usage: USAGE
2965 '''
2966 help = usage + '''\
2967
2968 DESCRIPTION
2969
2970 positional arguments:
2971 ekiekiekifekang EKI HELP
2972 bar BAR HELP
2973
2974 optional arguments:
2975 -h, --help show this help message and exit
2976 -x X HELP
2977 --y Y Y HELP
2978 '''
2979
2980 version = ''
2981
2982
2983 class TestHelpReformatting(HelpTestCase):
2984 """Make sure that text after short names starts on the first line"""
2985
2986 parser_signature = Sig(
2987 prog='PROG',
2988 description=' oddly formatted\n'
2989 'description\n'
2990 '\n'
2991 'that is so long that it should go onto multiple '
2992 'lines when wrapped')
2993 argument_signatures = [
2994 Sig('-x', metavar='XX', help='oddly\n'
2995 ' formatted -x help'),
2996 Sig('y', metavar='yyy', help='normal y help'),
2997 ]
2998 argument_group_signatures = [
2999 (Sig('title', description='\n'
3000 ' oddly formatted group\n'
3001 '\n'
3002 'description'),
3003 [Sig('-a', action='store_true',
3004 help=' oddly \n'
3005 'formatted -a help \n'
3006 ' again, so long that it should be wrapped over '
3007 'multiple lines')]),
3008 ]
3009 usage = '''\
3010 usage: PROG [-h] [-x XX] [-a] yyy
3011 '''
3012 help = usage + '''\
3013
3014 oddly formatted description that is so long that it should go onto \
3015 multiple
3016 lines when wrapped
3017
3018 positional arguments:
3019 yyy normal y help
3020
3021 optional arguments:
3022 -h, --help show this help message and exit
3023 -x XX oddly formatted -x help
3024
3025 title:
3026 oddly formatted group description
3027
3028 -a oddly formatted -a help again, so long that it should \
3029 be wrapped
3030 over multiple lines
3031 '''
3032 version = ''
3033
3034
3035 class TestHelpWrappingShortNames(HelpTestCase):
3036 """Make sure that text after short names starts on the first line"""
3037
3038 parser_signature = Sig(prog='PROG', description= 'D\nD' * 30)
3039 argument_signatures = [
3040 Sig('-x', metavar='XX', help='XHH HX' * 20),
3041 Sig('y', metavar='yyy', help='YH YH' * 20),
3042 ]
3043 argument_group_signatures = [
3044 (Sig('ALPHAS'), [
3045 Sig('-a', action='store_true', help='AHHH HHA' * 10)]),
3046 ]
3047 usage = '''\
3048 usage: PROG [-h] [-x XX] [-a] yyy
3049 '''
3050 help = usage + '''\
3051
3052 D DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD \
3053 DD DD DD
3054 DD DD DD DD D
3055
3056 positional arguments:
3057 yyy YH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH \
3058 YHYH YHYH
3059 YHYH YHYH YHYH YHYH YHYH YHYH YHYH YH
3060
3061 optional arguments:
3062 -h, --help show this help message and exit
3063 -x XX XHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH \
3064 HXXHH HXXHH
3065 HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HX
3066
3067 ALPHAS:
3068 -a AHHH HHAAHHH HHAAHHH HHAAHHH HHAAHHH HHAAHHH HHAAHHH \
3069 HHAAHHH
3070 HHAAHHH HHAAHHH HHA
3071 '''
3072 version = ''
3073
3074
3075 class TestHelpWrappingLongNames(HelpTestCase):
3076 """Make sure that text after long names starts on the next line"""
3077
3078 parser_signature = Sig(usage='USAGE', description= 'D D' * 30,
3079 version='V V'*30)
3080 argument_signatures = [
3081 Sig('-x', metavar='X' * 25, help='XH XH' * 20),
3082 Sig('y', metavar='y' * 25, help='YH YH' * 20),
3083 ]
3084 argument_group_signatures = [
3085 (Sig('ALPHAS'), [
3086 Sig('-a', metavar='A' * 25, help='AH AH' * 20),
3087 Sig('z', metavar='z' * 25, help='ZH ZH' * 20)]),
3088 ]
3089 usage = '''\
3090 usage: USAGE
3091 '''
3092 help = usage + '''\
3093
3094 D DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD \
3095 DD DD DD
3096 DD DD DD DD D
3097
3098 positional arguments:
3099 yyyyyyyyyyyyyyyyyyyyyyyyy
3100 YH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH \
3101 YHYH YHYH
3102 YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YH
3103
3104 optional arguments:
3105 -h, --help show this help message and exit
3106 -v, --version show program's version number and exit
3107 -x XXXXXXXXXXXXXXXXXXXXXXXXX
3108 XH XHXH XHXH XHXH XHXH XHXH XHXH XHXH XHXH \
3109 XHXH XHXH
3110 XHXH XHXH XHXH XHXH XHXH XHXH XHXH XHXH XHXH XH
3111
3112 ALPHAS:
3113 -a AAAAAAAAAAAAAAAAAAAAAAAAA
3114 AH AHAH AHAH AHAH AHAH AHAH AHAH AHAH AHAH \
3115 AHAH AHAH
3116 AHAH AHAH AHAH AHAH AHAH AHAH AHAH AHAH AHAH AH
3117 zzzzzzzzzzzzzzzzzzzzzzzzz
3118 ZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH \
3119 ZHZH ZHZH
3120 ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZH
3121 '''
3122 version = '''\
3123 V VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV \
3124 VV VV VV
3125 VV VV VV VV V
3126 '''
3127
3128
3129 class TestHelpUsage(HelpTestCase):
3130 """Test basic usage messages"""
3131
3132 parser_signature = Sig(prog='PROG')
3133 argument_signatures = [
3134 Sig('-w', nargs='+', help='w'),
3135 Sig('-x', nargs='*', help='x'),
3136 Sig('a', help='a'),
3137 Sig('b', help='b', nargs=2),
3138 Sig('c', help='c', nargs='?'),
3139 ]
3140 argument_group_signatures = [
3141 (Sig('group'), [
3142 Sig('-y', nargs='?', help='y'),
3143 Sig('-z', nargs=3, help='z'),
3144 Sig('d', help='d', nargs='*'),
3145 Sig('e', help='e', nargs='+'),
3146 ])
3147 ]
3148 usage = '''\
3149 usage: PROG [-h] [-w W [W ...]] [-x [X [X ...]]] [-y [Y]] [-z Z Z Z]
3150 a b b [c] [d [d ...]] e [e ...]
3151 '''
3152 help = usage + '''\
3153
3154 positional arguments:
3155 a a
3156 b b
3157 c c
3158
3159 optional arguments:
3160 -h, --help show this help message and exit
3161 -w W [W ...] w
3162 -x [X [X ...]] x
3163
3164 group:
3165 -y [Y] y
3166 -z Z Z Z z
3167 d d
3168 e e
3169 '''
3170 version = ''
3171
3172
3173 class TestHelpOnlyUserGroups(HelpTestCase):
3174 """Test basic usage messages"""
3175
3176 parser_signature = Sig(prog='PROG', add_help=False)
3177 argument_signatures = []
3178 argument_group_signatures = [
3179 (Sig('xxxx'), [
3180 Sig('-x', help='x'),
3181 Sig('a', help='a'),
3182 ]),
3183 (Sig('yyyy'), [
3184 Sig('b', help='b'),
3185 Sig('-y', help='y'),
3186 ]),
3187 ]
3188 usage = '''\
3189 usage: PROG [-x X] [-y Y] a b
3190 '''
3191 help = usage + '''\
3192
3193 xxxx:
3194 -x X x
3195 a a
3196
3197 yyyy:
3198 b b
3199 -y Y y
3200 '''
3201 version = ''
3202
3203
3204 class TestHelpUsageLongProg(HelpTestCase):
3205 """Test usage messages where the prog is long"""
3206
3207 parser_signature = Sig(prog='P' * 60)
3208 argument_signatures = [
3209 Sig('-w', metavar='W'),
3210 Sig('-x', metavar='X'),
3211 Sig('a'),
3212 Sig('b'),
3213 ]
3214 argument_group_signatures = []
3215 usage = '''\
3216 usage: PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
3217 [-h] [-w W] [-x X] a b
3218 '''
3219 help = usage + '''\
3220
3221 positional arguments:
3222 a
3223 b
3224
3225 optional arguments:
3226 -h, --help show this help message and exit
3227 -w W
3228 -x X
3229 '''
3230 version = ''
3231
3232
3233 class TestHelpUsageLongProgOptionsWrap(HelpTestCase):
3234 """Test usage messages where the prog is long and the optionals wrap"""
3235
3236 parser_signature = Sig(prog='P' * 60)
3237 argument_signatures = [
3238 Sig('-w', metavar='W' * 25),
3239 Sig('-x', metavar='X' * 25),
3240 Sig('-y', metavar='Y' * 25),
3241 Sig('-z', metavar='Z' * 25),
3242 Sig('a'),
3243 Sig('b'),
3244 ]
3245 argument_group_signatures = []
3246 usage = '''\
3247 usage: PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
3248 [-h] [-w WWWWWWWWWWWWWWWWWWWWWWWWW] \
3249 [-x XXXXXXXXXXXXXXXXXXXXXXXXX]
3250 [-y YYYYYYYYYYYYYYYYYYYYYYYYY] [-z ZZZZZZZZZZZZZZZZZZZZZZZZZ]
3251 a b
3252 '''
3253 help = usage + '''\
3254
3255 positional arguments:
3256 a
3257 b
3258
3259 optional arguments:
3260 -h, --help show this help message and exit
3261 -w WWWWWWWWWWWWWWWWWWWWWWWWW
3262 -x XXXXXXXXXXXXXXXXXXXXXXXXX
3263 -y YYYYYYYYYYYYYYYYYYYYYYYYY
3264 -z ZZZZZZZZZZZZZZZZZZZZZZZZZ
3265 '''
3266 version = ''
3267
3268
3269 class TestHelpUsageLongProgPositionalsWrap(HelpTestCase):
3270 """Test usage messages where the prog is long and the positionals wrap"""
3271
3272 parser_signature = Sig(prog='P' * 60, add_help=False)
3273 argument_signatures = [
3274 Sig('a' * 25),
3275 Sig('b' * 25),
3276 Sig('c' * 25),
3277 ]
3278 argument_group_signatures = []
3279 usage = '''\
3280 usage: PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
3281 aaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbb
3282 ccccccccccccccccccccccccc
3283 '''
3284 help = usage + '''\
3285
3286 positional arguments:
3287 aaaaaaaaaaaaaaaaaaaaaaaaa
3288 bbbbbbbbbbbbbbbbbbbbbbbbb
3289 ccccccccccccccccccccccccc
3290 '''
3291 version = ''
3292
3293
3294 class TestHelpUsageOptionalsWrap(HelpTestCase):
3295 """Test usage messages where the optionals wrap"""
3296
3297 parser_signature = Sig(prog='PROG')
3298 argument_signatures = [
3299 Sig('-w', metavar='W' * 25),
3300 Sig('-x', metavar='X' * 25),
3301 Sig('-y', metavar='Y' * 25),
3302 Sig('-z', metavar='Z' * 25),
3303 Sig('a'),
3304 Sig('b'),
3305 Sig('c'),
3306 ]
3307 argument_group_signatures = []
3308 usage = '''\
3309 usage: PROG [-h] [-w WWWWWWWWWWWWWWWWWWWWWWWWW] \
3310 [-x XXXXXXXXXXXXXXXXXXXXXXXXX]
3311 [-y YYYYYYYYYYYYYYYYYYYYYYYYY] \
3312 [-z ZZZZZZZZZZZZZZZZZZZZZZZZZ]
3313 a b c
3314 '''
3315 help = usage + '''\
3316
3317 positional arguments:
3318 a
3319 b
3320 c
3321
3322 optional arguments:
3323 -h, --help show this help message and exit
3324 -w WWWWWWWWWWWWWWWWWWWWWWWWW
3325 -x XXXXXXXXXXXXXXXXXXXXXXXXX
3326 -y YYYYYYYYYYYYYYYYYYYYYYYYY
3327 -z ZZZZZZZZZZZZZZZZZZZZZZZZZ
3328 '''
3329 version = ''
3330
3331
3332 class TestHelpUsagePositionalsWrap(HelpTestCase):
3333 """Test usage messages where the positionals wrap"""
3334
3335 parser_signature = Sig(prog='PROG')
3336 argument_signatures = [
3337 Sig('-x'),
3338 Sig('-y'),
3339 Sig('-z'),
3340 Sig('a' * 25),
3341 Sig('b' * 25),
3342 Sig('c' * 25),
3343 ]
3344 argument_group_signatures = []
3345 usage = '''\
3346 usage: PROG [-h] [-x X] [-y Y] [-z Z]
3347 aaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbb
3348 ccccccccccccccccccccccccc
3349 '''
3350 help = usage + '''\
3351
3352 positional arguments:
3353 aaaaaaaaaaaaaaaaaaaaaaaaa
3354 bbbbbbbbbbbbbbbbbbbbbbbbb
3355 ccccccccccccccccccccccccc
3356
3357 optional arguments:
3358 -h, --help show this help message and exit
3359 -x X
3360 -y Y
3361 -z Z
3362 '''
3363 version = ''
3364
3365
3366 class TestHelpUsageOptionalsPositionalsWrap(HelpTestCase):
3367 """Test usage messages where the optionals and positionals wrap"""
3368
3369 parser_signature = Sig(prog='PROG')
3370 argument_signatures = [
3371 Sig('-x', metavar='X' * 25),
3372 Sig('-y', metavar='Y' * 25),
3373 Sig('-z', metavar='Z' * 25),
3374 Sig('a' * 25),
3375 Sig('b' * 25),
3376 Sig('c' * 25),
3377 ]
3378 argument_group_signatures = []
3379 usage = '''\
3380 usage: PROG [-h] [-x XXXXXXXXXXXXXXXXXXXXXXXXX] \
3381 [-y YYYYYYYYYYYYYYYYYYYYYYYYY]
3382 [-z ZZZZZZZZZZZZZZZZZZZZZZZZZ]
3383 aaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbb
3384 ccccccccccccccccccccccccc
3385 '''
3386 help = usage + '''\
3387
3388 positional arguments:
3389 aaaaaaaaaaaaaaaaaaaaaaaaa
3390 bbbbbbbbbbbbbbbbbbbbbbbbb
3391 ccccccccccccccccccccccccc
3392
3393 optional arguments:
3394 -h, --help show this help message and exit
3395 -x XXXXXXXXXXXXXXXXXXXXXXXXX
3396 -y YYYYYYYYYYYYYYYYYYYYYYYYY
3397 -z ZZZZZZZZZZZZZZZZZZZZZZZZZ
3398 '''
3399 version = ''
3400
3401
3402 class TestHelpUsageOptionalsOnlyWrap(HelpTestCase):
3403 """Test usage messages where there are only optionals and they wrap"""
3404
3405 parser_signature = Sig(prog='PROG')
3406 argument_signatures = [
3407 Sig('-x', metavar='X' * 25),
3408 Sig('-y', metavar='Y' * 25),
3409 Sig('-z', metavar='Z' * 25),
3410 ]
3411 argument_group_signatures = []
3412 usage = '''\
3413 usage: PROG [-h] [-x XXXXXXXXXXXXXXXXXXXXXXXXX] \
3414 [-y YYYYYYYYYYYYYYYYYYYYYYYYY]
3415 [-z ZZZZZZZZZZZZZZZZZZZZZZZZZ]
3416 '''
3417 help = usage + '''\
3418
3419 optional arguments:
3420 -h, --help show this help message and exit
3421 -x XXXXXXXXXXXXXXXXXXXXXXXXX
3422 -y YYYYYYYYYYYYYYYYYYYYYYYYY
3423 -z ZZZZZZZZZZZZZZZZZZZZZZZZZ
3424 '''
3425 version = ''
3426
3427
3428 class TestHelpUsagePositionalsOnlyWrap(HelpTestCase):
3429 """Test usage messages where there are only positionals and they wrap"""
3430
3431 parser_signature = Sig(prog='PROG', add_help=False)
3432 argument_signatures = [
3433 Sig('a' * 25),
3434 Sig('b' * 25),
3435 Sig('c' * 25),
3436 ]
3437 argument_group_signatures = []
3438 usage = '''\
3439 usage: PROG aaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbb
3440 ccccccccccccccccccccccccc
3441 '''
3442 help = usage + '''\
3443
3444 positional arguments:
3445 aaaaaaaaaaaaaaaaaaaaaaaaa
3446 bbbbbbbbbbbbbbbbbbbbbbbbb
3447 ccccccccccccccccccccccccc
3448 '''
3449 version = ''
3450
3451
3452 class TestHelpVariableExpansion(HelpTestCase):
3453 """Test that variables are expanded properly in help messages"""
3454
3455 parser_signature = Sig(prog='PROG')
3456 argument_signatures = [
3457 Sig('-x', type=int,
3458 help='x %(prog)s %(default)s %(type)s %%'),
3459 Sig('-y', action='store_const', default=42, const='XXX',
3460 help='y %(prog)s %(default)s %(const)s'),
3461 Sig('--foo', choices='abc',
3462 help='foo %(prog)s %(default)s %(choices)s'),
3463 Sig('--bar', default='baz', choices=[1, 2], metavar='BBB',
3464 help='bar %(prog)s %(default)s %(dest)s'),
3465 Sig('spam', help='spam %(prog)s %(default)s'),
3466 Sig('badger', default=0.5, help='badger %(prog)s %(default)s'),
3467 ]
3468 argument_group_signatures = [
3469 (Sig('group'), [
3470 Sig('-a', help='a %(prog)s %(default)s'),
3471 Sig('-b', default=-1, help='b %(prog)s %(default)s'),
3472 ])
3473 ]
3474 usage = ('''\
3475 usage: PROG [-h] [-x X] [-y] [--foo {a,b,c}] [--bar BBB] [-a A] [-b B]
3476 spam badger
3477 ''')
3478 help = usage + '''\
3479
3480 positional arguments:
3481 spam spam PROG None
3482 badger badger PROG 0.5
3483
3484 optional arguments:
3485 -h, --help show this help message and exit
3486 -x X x PROG None int %
3487 -y y PROG 42 XXX
3488 --foo {a,b,c} foo PROG None a, b, c
3489 --bar BBB bar PROG baz bar
3490
3491 group:
3492 -a A a PROG None
3493 -b B b PROG -1
3494 '''
3495 version = ''
3496
3497
3498 class TestHelpVariableExpansionUsageSupplied(HelpTestCase):
3499 """Test that variables are expanded properly when usage= is present"""
3500
3501 parser_signature = Sig(prog='PROG', usage='%(prog)s FOO')
3502 argument_signatures = []
3503 argument_group_signatures = []
3504 usage = ('''\
3505 usage: PROG FOO
3506 ''')
3507 help = usage + '''\
3508
3509 optional arguments:
3510 -h, --help show this help message and exit
3511 '''
3512 version = ''
3513
3514
3515 class TestHelpVariableExpansionNoArguments(HelpTestCase):
3516 """Test that variables are expanded properly with no arguments"""
3517
3518 parser_signature = Sig(prog='PROG', add_help=False)
3519 argument_signatures = []
3520 argument_group_signatures = []
3521 usage = ('''\
3522 usage: PROG
3523 ''')
3524 help = usage
3525 version = ''
3526
3527
3528 class TestHelpSuppressUsage(HelpTestCase):
3529 """Test that items can be suppressed in usage messages"""
3530
3531 parser_signature = Sig(prog='PROG', usage=argparse.SUPPRESS)
3532 argument_signatures = [
3533 Sig('--foo', help='foo help'),
3534 Sig('spam', help='spam help'),
3535 ]
3536 argument_group_signatures = []
3537 help = '''\
3538 positional arguments:
3539 spam spam help
3540
3541 optional arguments:
3542 -h, --help show this help message and exit
3543 --foo FOO foo help
3544 '''
3545 usage = ''
3546 version = ''
3547
3548
3549 class TestHelpSuppressOptional(HelpTestCase):
3550 """Test that optional arguments can be suppressed in help messages"""
3551
3552 parser_signature = Sig(prog='PROG', add_help=False)
3553 argument_signatures = [
3554 Sig('--foo', help=argparse.SUPPRESS),
3555 Sig('spam', help='spam help'),
3556 ]
3557 argument_group_signatures = []
3558 usage = '''\
3559 usage: PROG spam
3560 '''
3561 help = usage + '''\
3562
3563 positional arguments:
3564 spam spam help
3565 '''
3566 version = ''
3567
3568
3569 class TestHelpSuppressOptionalGroup(HelpTestCase):
3570 """Test that optional groups can be suppressed in help messages"""
3571
3572 parser_signature = Sig(prog='PROG')
3573 argument_signatures = [
3574 Sig('--foo', help='foo help'),
3575 Sig('spam', help='spam help'),
3576 ]
3577 argument_group_signatures = [
3578 (Sig('group'), [Sig('--bar', help=argparse.SUPPRESS)]),
3579 ]
3580 usage = '''\
3581 usage: PROG [-h] [--foo FOO] spam
3582 '''
3583 help = usage + '''\
3584
3585 positional arguments:
3586 spam spam help
3587
3588 optional arguments:
3589 -h, --help show this help message and exit
3590 --foo FOO foo help
3591 '''
3592 version = ''
3593
3594
3595 class TestHelpSuppressPositional(HelpTestCase):
3596 """Test that positional arguments can be suppressed in help messages"""
3597
3598 parser_signature = Sig(prog='PROG')
3599 argument_signatures = [
3600 Sig('--foo', help='foo help'),
3601 Sig('spam', help=argparse.SUPPRESS),
3602 ]
3603 argument_group_signatures = []
3604 usage = '''\
3605 usage: PROG [-h] [--foo FOO]
3606 '''
3607 help = usage + '''\
3608
3609 optional arguments:
3610 -h, --help show this help message and exit
3611 --foo FOO foo help
3612 '''
3613 version = ''
3614
3615
3616 class TestHelpRequiredOptional(HelpTestCase):
3617 """Test that required options don't look optional"""
3618
3619 parser_signature = Sig(prog='PROG')
3620 argument_signatures = [
3621 Sig('--foo', required=True, help='foo help'),
3622 ]
3623 argument_group_signatures = []
3624 usage = '''\
3625 usage: PROG [-h] --foo FOO
3626 '''
3627 help = usage + '''\
3628
3629 optional arguments:
3630 -h, --help show this help message and exit
3631 --foo FOO foo help
3632 '''
3633 version = ''
3634
3635
3636 class TestHelpAlternatePrefixChars(HelpTestCase):
3637 """Test that options display with different prefix characters"""
3638
3639 parser_signature = Sig(prog='PROG', prefix_chars='^;', add_help=False)
3640 argument_signatures = [
3641 Sig('^^foo', action='store_true', help='foo help'),
3642 Sig(';b', ';;bar', help='bar help'),
3643 ]
3644 argument_group_signatures = []
3645 usage = '''\
3646 usage: PROG [^^foo] [;b BAR]
3647 '''
3648 help = usage + '''\
3649
3650 optional arguments:
3651 ^^foo foo help
3652 ;b BAR, ;;bar BAR bar help
3653 '''
3654 version = ''
3655
3656
3657 class TestHelpNoHelpOptional(HelpTestCase):
3658 """Test that the --help argument can be suppressed help messages"""
3659
3660 parser_signature = Sig(prog='PROG', add_help=False)
3661 argument_signatures = [
3662 Sig('--foo', help='foo help'),
3663 Sig('spam', help='spam help'),
3664 ]
3665 argument_group_signatures = []
3666 usage = '''\
3667 usage: PROG [--foo FOO] spam
3668 '''
3669 help = usage + '''\
3670
3671 positional arguments:
3672 spam spam help
3673
3674 optional arguments:
3675 --foo FOO foo help
3676 '''
3677 version = ''
3678
3679
3680 class TestHelpVersionOptional(HelpTestCase):
3681 """Test that the --version argument can be suppressed help messages"""
3682
3683 parser_signature = Sig(prog='PROG', version='1.0')
3684 argument_signatures = [
3685 Sig('--foo', help='foo help'),
3686 Sig('spam', help='spam help'),
3687 ]
3688 argument_group_signatures = []
3689 usage = '''\
3690 usage: PROG [-h] [-v] [--foo FOO] spam
3691 '''
3692 help = usage + '''\
3693
3694 positional arguments:
3695 spam spam help
3696
3697 optional arguments:
3698 -h, --help show this help message and exit
3699 -v, --version show program's version number and exit
3700 --foo FOO foo help
3701 '''
3702 version = '''\
3703 1.0
3704 '''
3705
3706
3707 class TestHelpNone(HelpTestCase):
3708 """Test that no errors occur if no help is specified"""
3709
3710 parser_signature = Sig(prog='PROG')
3711 argument_signatures = [
3712 Sig('--foo'),
3713 Sig('spam'),
3714 ]
3715 argument_group_signatures = []
3716 usage = '''\
3717 usage: PROG [-h] [--foo FOO] spam
3718 '''
3719 help = usage + '''\
3720
3721 positional arguments:
3722 spam
3723
3724 optional arguments:
3725 -h, --help show this help message and exit
3726 --foo FOO
3727 '''
3728 version = ''
3729
3730
3731 class TestHelpTupleMetavar(HelpTestCase):
3732 """Test specifying metavar as a tuple"""
3733
3734 parser_signature = Sig(prog='PROG')
3735 argument_signatures = [
3736 Sig('-w', help='w', nargs='+', metavar=('W1', 'W2')),
3737 Sig('-x', help='x', nargs='*', metavar=('X1', 'X2')),
3738 Sig('-y', help='y', nargs=3, metavar=('Y1', 'Y2', 'Y3')),
3739 Sig('-z', help='z', nargs='?', metavar=('Z1', )),
3740 ]
3741 argument_group_signatures = []
3742 usage = '''\
3743 usage: PROG [-h] [-w W1 [W2 ...]] [-x [X1 [X2 ...]]] [-y Y1 Y2 Y3] \
3744 [-z [Z1]]
3745 '''
3746 help = usage + '''\
3747
3748 optional arguments:
3749 -h, --help show this help message and exit
3750 -w W1 [W2 ...] w
3751 -x [X1 [X2 ...]] x
3752 -y Y1 Y2 Y3 y
3753 -z [Z1] z
3754 '''
3755 version = ''
3756
3757
3758 class TestHelpRawText(HelpTestCase):
3759 """Test the RawTextHelpFormatter"""
3760
3761 parser_signature = Sig(
3762 prog='PROG', formatter_class=argparse.RawTextHelpFormatter,
3763 description='Keep the formatting\n'
3764 ' exactly as it is written\n'
3765 '\n'
3766 'here\n')
3767
3768 argument_signatures = [
3769 Sig('--foo', help=' foo help should also\n'
3770 'appear as given here'),
3771 Sig('spam', help='spam help'),
3772 ]
3773 argument_group_signatures = [
3774 (Sig('title', description=' This text\n'
3775 ' should be indented\n'
3776 ' exactly like it is here\n'),
3777 [Sig('--bar', help='bar help')]),
3778 ]
3779 usage = '''\
3780 usage: PROG [-h] [--foo FOO] [--bar BAR] spam
3781 '''
3782 help = usage + '''\
3783
3784 Keep the formatting
3785 exactly as it is written
3786
3787 here
3788
3789 positional arguments:
3790 spam spam help
3791
3792 optional arguments:
3793 -h, --help show this help message and exit
3794 --foo FOO foo help should also
3795 appear as given here
3796
3797 title:
3798 This text
3799 should be indented
3800 exactly like it is here
3801
3802 --bar BAR bar help
3803 '''
3804 version = ''
3805
3806
3807 class TestHelpRawDescription(HelpTestCase):
3808 """Test the RawTextHelpFormatter"""
3809
3810 parser_signature = Sig(
3811 prog='PROG', formatter_class=argparse.RawDescriptionHelpFormatter,
3812 description='Keep the formatting\n'
3813 ' exactly as it is written\n'
3814 '\n'
3815 'here\n')
3816
3817 argument_signatures = [
3818 Sig('--foo', help=' foo help should not\n'
3819 ' retain this odd formatting'),
3820 Sig('spam', help='spam help'),
3821 ]
3822 argument_group_signatures = [
3823 (Sig('title', description=' This text\n'
3824 ' should be indented\n'
3825 ' exactly like it is here\n'),
3826 [Sig('--bar', help='bar help')]),
3827 ]
3828 usage = '''\
3829 usage: PROG [-h] [--foo FOO] [--bar BAR] spam
3830 '''
3831 help = usage + '''\
3832
3833 Keep the formatting
3834 exactly as it is written
3835
3836 here
3837
3838 positional arguments:
3839 spam spam help
3840
3841 optional arguments:
3842 -h, --help show this help message and exit
3843 --foo FOO foo help should not retain this odd formatting
3844
3845 title:
3846 This text
3847 should be indented
3848 exactly like it is here
3849
3850 --bar BAR bar help
3851 '''
3852 version = ''
3853
3854
3855 class TestHelpArgumentDefaults(HelpTestCase):
3856 """Test the ArgumentDefaultsHelpFormatter"""
3857
3858 parser_signature = Sig(
3859 prog='PROG', formatter_class=argparse.ArgumentDefaultsHelpFormatter,
3860 description='description')
3861
3862 argument_signatures = [
3863 Sig('--foo', help='foo help - oh and by the way, %(default)s'),
3864 Sig('--bar', action='store_true', help='bar help'),
3865 Sig('spam', help='spam help'),
3866 Sig('badger', nargs='?', default='wooden', help='badger help'),
3867 ]
3868 argument_group_signatures = [
3869 (Sig('title', description='description'),
3870 [Sig('--baz', type=int, default=42, help='baz help')]),
3871 ]
3872 usage = '''\
3873 usage: PROG [-h] [--foo FOO] [--bar] [--baz BAZ] spam [badger]
3874 '''
3875 help = usage + '''\
3876
3877 description
3878
3879 positional arguments:
3880 spam spam help
3881 badger badger help (default: wooden)
3882
3883 optional arguments:
3884 -h, --help show this help message and exit
3885 --foo FOO foo help - oh and by the way, None
3886 --bar bar help (default: False)
3887
3888 title:
3889 description
3890
3891 --baz BAZ baz help (default: 42)
3892 '''
3893 version = ''
3894
3895 class TestHelpVersionAction(HelpTestCase):
3896 """Test the default help for the version action"""
3897
3898 parser_signature = Sig(prog='PROG', description='description')
3899 argument_signatures = [Sig('-V', '--version', action='version', version='3.6')]
3900 argument_group_signatures = []
3901 usage = '''\
3902 usage: PROG [-h] [-V]
3903 '''
3904 help = usage + '''\
3905
3906 description
3907
3908 optional arguments:
3909 -h, --help show this help message and exit
3910 -V, --version show program's version number and exit
3911 '''
3912 version = ''
3913
3914 class TestHelpSubparsersOrdering(HelpTestCase):
3915 """Test ordering of subcommands in help matches the code"""
3916 parser_signature = Sig(prog='PROG',
3917 description='display some subcommands',
3918 version='0.1')
3919
3920 subparsers_signatures = [Sig(name=name)
3921 for name in ('a', 'b', 'c', 'd', 'e')]
3922
3923 usage = '''\
3924 usage: PROG [-h] [-v] {a,b,c,d,e} ...
3925 '''
3926
3927 help = usage + '''\
3928
3929 display some subcommands
3930
3931 positional arguments:
3932 {a,b,c,d,e}
3933
3934 optional arguments:
3935 -h, --help show this help message and exit
3936 -v, --version show program's version number and exit
3937 '''
3938
3939 version = '''\
3940 0.1
3941 '''
3942
3943 class TestHelpSubparsersWithHelpOrdering(HelpTestCase):
3944 """Test ordering of subcommands in help matches the code"""
3945 parser_signature = Sig(prog='PROG',
3946 description='display some subcommands',
3947 version='0.1')
3948
3949 subcommand_data = (('a', 'a subcommand help'),
3950 ('b', 'b subcommand help'),
3951 ('c', 'c subcommand help'),
3952 ('d', 'd subcommand help'),
3953 ('e', 'e subcommand help'),
3954 )
3955
3956 subparsers_signatures = [Sig(name=name, help=help)
3957 for name, help in subcommand_data]
3958
3959 usage = '''\
3960 usage: PROG [-h] [-v] {a,b,c,d,e} ...
3961 '''
3962
3963 help = usage + '''\
3964
3965 display some subcommands
3966
3967 positional arguments:
3968 {a,b,c,d,e}
3969 a a subcommand help
3970 b b subcommand help
3971 c c subcommand help
3972 d d subcommand help
3973 e e subcommand help
3974
3975 optional arguments:
3976 -h, --help show this help message and exit
3977 -v, --version show program's version number and exit
3978 '''
3979
3980 version = '''\
3981 0.1
3982 '''
3983
3984
3985 # =====================================
3986 # Optional/Positional constructor tests
3987 # =====================================
3988
3989 class TestInvalidArgumentConstructors(TestCase):
3990 """Test a bunch of invalid Argument constructors"""
3991
3992 def assertTypeError(self, *args, **kwargs):
3993 parser = argparse.ArgumentParser()
3994 self.assertRaises(TypeError, parser.add_argument,
3995 *args, **kwargs)
3996
3997 def assertValueError(self, *args, **kwargs):
3998 parser = argparse.ArgumentParser()
3999 self.assertRaises(ValueError, parser.add_argument,
4000 *args, **kwargs)
4001
4002 def test_invalid_keyword_arguments(self):
4003 self.assertTypeError('-x', bar=None)
4004 self.assertTypeError('-y', callback='foo')
4005 self.assertTypeError('-y', callback_args=())
4006 self.assertTypeError('-y', callback_kwargs={})
4007
4008 def test_missing_destination(self):
4009 self.assertTypeError()
4010 for action in ['append', 'store']:
4011 self.assertTypeError(action=action)
4012
4013 def test_invalid_option_strings(self):
4014 self.assertValueError('--')
4015 self.assertValueError('---')
4016
4017 def test_invalid_type(self):
4018 self.assertValueError('--foo', type='int')
4019 self.assertValueError('--foo', type=(int, float))
4020
4021 def test_invalid_action(self):
4022 self.assertValueError('-x', action='foo')
4023 self.assertValueError('foo', action='baz')
4024 self.assertValueError('--foo', action=('store', 'append'))
4025 parser = argparse.ArgumentParser()
4026 try:
4027 parser.add_argument("--foo", action="store-true")
4028 except ValueError:
4029 e = sys.exc_info()[1]
4030 expected = 'unknown action'
4031 msg = 'expected %r, found %r' % (expected, e)
4032 self.assertTrue(expected in str(e), msg)
4033
4034 def test_multiple_dest(self):
4035 parser = argparse.ArgumentParser()
4036 parser.add_argument(dest='foo')
4037 try:
4038 parser.add_argument('bar', dest='baz')
4039 except ValueError:
4040 e = sys.exc_info()[1]
4041 expected = 'dest supplied twice for positional argument'
4042 msg = 'expected %r, found %r' % (expected, e)
4043 self.assertTrue(expected in str(e), msg)
4044
4045 def test_no_argument_actions(self):
4046 for action in ['store_const', 'store_true', 'store_false',
4047 'append_const', 'count']:
4048 for attrs in [dict(type=int), dict(nargs='+'),
4049 dict(choices='ab')]:
4050 self.assertTypeError('-x', action=action, **attrs)
4051
4052 def test_no_argument_no_const_actions(self):
4053 # options with zero arguments
4054 for action in ['store_true', 'store_false', 'count']:
4055
4056 # const is always disallowed
4057 self.assertTypeError('-x', const='foo', action=action)
4058
4059 # nargs is always disallowed
4060 self.assertTypeError('-x', nargs='*', action=action)
4061
4062 def test_more_than_one_argument_actions(self):
4063 for action in ['store', 'append']:
4064
4065 # nargs=0 is disallowed
4066 self.assertValueError('-x', nargs=0, action=action)
4067 self.assertValueError('spam', nargs=0, action=action)
4068
4069 # const is disallowed with non-optional arguments
4070 for nargs in [1, '*', '+']:
4071 self.assertValueError('-x', const='foo',
4072 nargs=nargs, action=action)
4073 self.assertValueError('spam', const='foo',
4074 nargs=nargs, action=action)
4075
4076 def test_required_const_actions(self):
4077 for action in ['store_const', 'append_const']:
4078
4079 # nargs is always disallowed
4080 self.assertTypeError('-x', nargs='+', action=action)
4081
4082 def test_parsers_action_missing_params(self):
4083 self.assertTypeError('command', action='parsers')
4084 self.assertTypeError('command', action='parsers', prog='PROG')
4085 self.assertTypeError('command', action='parsers',
4086 parser_class=argparse.ArgumentParser)
4087
4088 def test_required_positional(self):
4089 self.assertTypeError('foo', required=True)
4090
4091 def test_user_defined_action(self):
4092
4093 class Success(Exception):
4094 pass
4095
4096 class Action(object):
4097
4098 def __init__(self,
4099 option_strings,
4100 dest,
4101 const,
4102 default,
4103 required=False):
4104 if dest == 'spam':
4105 if const is Success:
4106 if default is Success:
4107 raise Success()
4108
4109 def __call__(self, *args, **kwargs):
4110 pass
4111
4112 parser = argparse.ArgumentParser()
4113 self.assertRaises(Success, parser.add_argument, '--spam',
4114 action=Action, default=Success, const=Success)
4115 self.assertRaises(Success, parser.add_argument, 'spam',
4116 action=Action, default=Success, const=Success)
4117
4118 # ================================
4119 # Actions returned by add_argument
4120 # ================================
4121
4122 class TestActionsReturned(TestCase):
4123
4124 def test_dest(self):
4125 parser = argparse.ArgumentParser()
4126 action = parser.add_argument('--foo')
4127 self.assertEqual(action.dest, 'foo')
4128 action = parser.add_argument('-b', '--bar')
4129 self.assertEqual(action.dest, 'bar')
4130 action = parser.add_argument('-x', '-y')
4131 self.assertEqual(action.dest, 'x')
4132
4133 def test_misc(self):
4134 parser = argparse.ArgumentParser()
4135 action = parser.add_argument('--foo', nargs='?', const=42,
4136 default=84, type=int, choices=[1, 2],
4137 help='FOO', metavar='BAR', dest='baz')
4138 self.assertEqual(action.nargs, '?')
4139 self.assertEqual(action.const, 42)
4140 self.assertEqual(action.default, 84)
4141 self.assertEqual(action.type, int)
4142 self.assertEqual(action.choices, [1, 2])
4143 self.assertEqual(action.help, 'FOO')
4144 self.assertEqual(action.metavar, 'BAR')
4145 self.assertEqual(action.dest, 'baz')
4146
4147
4148 # ================================
4149 # Argument conflict handling tests
4150 # ================================
4151
4152 class TestConflictHandling(TestCase):
4153
4154 def test_bad_type(self):
4155 self.assertRaises(ValueError, argparse.ArgumentParser,
4156 conflict_handler='foo')
4157
4158 def test_conflict_error(self):
4159 parser = argparse.ArgumentParser()
4160 parser.add_argument('-x')
4161 self.assertRaises(argparse.ArgumentError,
4162 parser.add_argument, '-x')
4163 parser.add_argument('--spam')
4164 self.assertRaises(argparse.ArgumentError,
4165 parser.add_argument, '--spam')
4166
4167 def test_resolve_error(self):
4168 get_parser = argparse.ArgumentParser
4169 parser = get_parser(prog='PROG', conflict_handler='resolve')
4170
4171 parser.add_argument('-x', help='OLD X')
4172 parser.add_argument('-x', help='NEW X')
4173 self.assertEqual(parser.format_help(), textwrap.dedent('''\
4174 usage: PROG [-h] [-x X]
4175
4176 optional arguments:
4177 -h, --help show this help message and exit
4178 -x X NEW X
4179 '''))
4180
4181 parser.add_argument('--spam', metavar='OLD_SPAM')
4182 parser.add_argument('--spam', metavar='NEW_SPAM')
4183 self.assertEqual(parser.format_help(), textwrap.dedent('''\
4184 usage: PROG [-h] [-x X] [--spam NEW_SPAM]
4185
4186 optional arguments:
4187 -h, --help show this help message and exit
4188 -x X NEW X
4189 --spam NEW_SPAM
4190 '''))
4191
4192
4193 # =============================
4194 # Help and Version option tests
4195 # =============================
4196
4197 class TestOptionalsHelpVersionActions(TestCase):
4198 """Test the help and version actions"""
4199
4200 def _get_error(self, func, *args, **kwargs):
4201 try:
4202 func(*args, **kwargs)
4203 except ArgumentParserError:
4204 return sys.exc_info()[1]
4205 else:
4206 self.assertRaises(ArgumentParserError, func, *args, **kwargs)
4207
4208 def assertPrintHelpExit(self, parser, args_str):
4209 self.assertEqual(
4210 parser.format_help(),
4211 self._get_error(parser.parse_args, args_str.split()).stdout)
4212
4213 def assertPrintVersionExit(self, parser, args_str):
4214 self.assertEqual(
4215 parser.format_version(),
4216 self._get_error(parser.parse_args, args_str.split()).stderr)
4217
4218 def assertArgumentParserError(self, parser, *args):
4219 self.assertRaises(ArgumentParserError, parser.parse_args, args)
4220
4221 def test_version(self):
4222 parser = ErrorRaisingArgumentParser(version='1.0')
4223 self.assertPrintHelpExit(parser, '-h')
4224 self.assertPrintHelpExit(parser, '--help')
4225 self.assertPrintVersionExit(parser, '-v')
4226 self.assertPrintVersionExit(parser, '--version')
4227
4228 def test_version_format(self):
4229 parser = ErrorRaisingArgumentParser(prog='PPP', version='%(prog)s 3.5')
4230 msg = self._get_error(parser.parse_args, ['-v']).stderr
4231 self.assertEqual('PPP 3.5\n', msg)
4232
4233 def test_version_no_help(self):
4234 parser = ErrorRaisingArgumentParser(add_help=False, version='1.0')
4235 self.assertArgumentParserError(parser, '-h')
4236 self.assertArgumentParserError(parser, '--help')
4237 self.assertPrintVersionExit(parser, '-v')
4238 self.assertPrintVersionExit(parser, '--version')
4239
4240 def test_version_action(self):
4241 parser = ErrorRaisingArgumentParser(prog='XXX')
4242 parser.add_argument('-V', action='version', version='%(prog)s 3.7')
4243 msg = self._get_error(parser.parse_args, ['-V']).stderr
4244 self.assertEqual('XXX 3.7\n', msg)
4245
4246 def test_no_help(self):
4247 parser = ErrorRaisingArgumentParser(add_help=False)
4248 self.assertArgumentParserError(parser, '-h')
4249 self.assertArgumentParserError(parser, '--help')
4250 self.assertArgumentParserError(parser, '-v')
4251 self.assertArgumentParserError(parser, '--version')
4252
4253 def test_alternate_help_version(self):
4254 parser = ErrorRaisingArgumentParser()
4255 parser.add_argument('-x', action='help')
4256 parser.add_argument('-y', action='version')
4257 self.assertPrintHelpExit(parser, '-x')
4258 self.assertPrintVersionExit(parser, '-y')
4259 self.assertArgumentParserError(parser, '-v')
4260 self.assertArgumentParserError(parser, '--version')
4261
4262 def test_help_version_extra_arguments(self):
4263 parser = ErrorRaisingArgumentParser(version='1.0')
4264 parser.add_argument('-x', action='store_true')
4265 parser.add_argument('y')
4266
4267 # try all combinations of valid prefixes and suffixes
4268 valid_prefixes = ['', '-x', 'foo', '-x bar', 'baz -x']
4269 valid_suffixes = valid_prefixes + ['--bad-option', 'foo bar baz']
4270 for prefix in valid_prefixes:
4271 for suffix in valid_suffixes:
4272 format = '%s %%s %s' % (prefix, suffix)
4273 self.assertPrintHelpExit(parser, format % '-h')
4274 self.assertPrintHelpExit(parser, format % '--help')
4275 self.assertPrintVersionExit(parser, format % '-v')
4276 self.assertPrintVersionExit(parser, format % '--version')
4277
4278
4279 # ======================
4280 # str() and repr() tests
4281 # ======================
4282
4283 class TestStrings(TestCase):
4284 """Test str() and repr() on Optionals and Positionals"""
4285
4286 def assertStringEqual(self, obj, result_string):
4287 for func in [str, repr]:
4288 self.assertEqual(func(obj), result_string)
4289
4290 def test_optional(self):
4291 option = argparse.Action(
4292 option_strings=['--foo', '-a', '-b'],
4293 dest='b',
4294 type='int',
4295 nargs='+',
4296 default=42,
4297 choices=[1, 2, 3],
4298 help='HELP',
4299 metavar='METAVAR')
4300 string = (
4301 "Action(option_strings=['--foo', '-a', '-b'], dest='b', "
4302 "nargs='+', const=None, default=42, type='int', "
4303 "choices=[1, 2, 3], help='HELP', metavar='METAVAR')")
4304 self.assertStringEqual(option, string)
4305
4306 def test_argument(self):
4307 argument = argparse.Action(
4308 option_strings=[],
4309 dest='x',
4310 type=float,
4311 nargs='?',
4312 default=2.5,
4313 choices=[0.5, 1.5, 2.5],
4314 help='H HH H',
4315 metavar='MV MV MV')
4316 string = (
4317 "Action(option_strings=[], dest='x', nargs='?', "
4318 "const=None, default=2.5, type=%r, choices=[0.5, 1.5, 2.5], "
4319 "help='H HH H', metavar='MV MV MV')" % float)
4320 self.assertStringEqual(argument, string)
4321
4322 def test_namespace(self):
4323 ns = argparse.Namespace(foo=42, bar='spam')
4324 string = "Namespace(bar='spam', foo=42)"
4325 self.assertStringEqual(ns, string)
4326
4327 def test_parser(self):
4328 parser = argparse.ArgumentParser(prog='PROG')
4329 string = (
4330 "ArgumentParser(prog='PROG', usage=None, description=None, "
4331 "version=None, formatter_class=%r, conflict_handler='error', "
4332 "add_help=True)" % argparse.HelpFormatter)
4333 self.assertStringEqual(parser, string)
4334
4335 # ===============
4336 # Namespace tests
4337 # ===============
4338
4339 class TestNamespace(TestCase):
4340
4341 def test_constructor(self):
4342 ns = argparse.Namespace()
4343 self.assertRaises(AttributeError, getattr, ns, 'x')
4344
4345 ns = argparse.Namespace(a=42, b='spam')
4346 self.assertEqual(ns.a, 42)
4347 self.assertEqual(ns.b, 'spam')
4348
4349 def test_equality(self):
4350 ns1 = argparse.Namespace(a=1, b=2)
4351 ns2 = argparse.Namespace(b=2, a=1)
4352 ns3 = argparse.Namespace(a=1)
4353 ns4 = argparse.Namespace(b=2)
4354
4355 self.assertEqual(ns1, ns2)
4356 self.assertNotEqual(ns1, ns3)
4357 self.assertNotEqual(ns1, ns4)
4358 self.assertNotEqual(ns2, ns3)
4359 self.assertNotEqual(ns2, ns4)
4360 self.assertTrue(ns1 != ns3)
4361 self.assertTrue(ns1 != ns4)
4362 self.assertTrue(ns2 != ns3)
4363 self.assertTrue(ns2 != ns4)
4364
4365
4366 # ===================
4367 # File encoding tests
4368 # ===================
4369
4370 class TestEncoding(TestCase):
4371
4372 def _test_module_encoding(self, path):
4373 path, _ = os.path.splitext(path)
4374 path += ".py"
4375 with codecs.open(path, 'r', 'utf8') as f:
4376 f.read()
4377
4378 def test_argparse_module_encoding(self):
4379 self._test_module_encoding(argparse.__file__)
4380
4381 def test_test_argparse_module_encoding(self):
4382 self._test_module_encoding(__file__)
4383
4384 # ===================
4385 # ArgumentError tests
4386 # ===================
4387
4388 class TestArgumentError(TestCase):
4389
4390 def test_argument_error(self):
4391 msg = "my error here"
4392 error = argparse.ArgumentError(None, msg)
4393 self.assertEqual(str(error), msg)
4394
4395 # =======================
4396 # ArgumentTypeError tests
4397 # =======================
4398
4399 class TestArgumentTypeError(TestCase):
4400
4401 def test_argument_type_error(self):
4402
4403 def spam(string):
4404 raise argparse.ArgumentTypeError('spam!')
4405
4406 parser = ErrorRaisingArgumentParser(prog='PROG', add_help=False)
4407 parser.add_argument('x', type=spam)
4408 try:
4409 parser.parse_args(['XXX'])
4410 except ArgumentParserError:
4411 expected = 'usage: PROG x\nPROG: error: argument x: spam!\n'
4412 msg = sys.exc_info()[1].stderr
4413 self.assertEqual(expected, msg)
4414 else:
4415 self.fail()
4416
4417 # ======================
4418 # parse_known_args tests
4419 # ======================
4420
4421 class TestParseKnownArgs(TestCase):
4422
4423 def test_optionals(self):
4424 parser = argparse.ArgumentParser()
4425 parser.add_argument('--foo')
4426 args, extras = parser.parse_known_args('--foo F --bar --baz'.split())
4427 self.assertEqual(NS(foo='F'), args)
4428 self.assertEqual(['--bar', '--baz'], extras)
4429
4430 def test_mixed(self):
4431 parser = argparse.ArgumentParser()
4432 parser.add_argument('-v', nargs='?', const=1, type=int)
4433 parser.add_argument('--spam', action='store_false')
4434 parser.add_argument('badger')
4435
4436 argv = ["B", "C", "--foo", "-v", "3", "4"]
4437 args, extras = parser.parse_known_args(argv)
4438 self.assertEqual(NS(v=3, spam=True, badger="B"), args)
4439 self.assertEqual(["C", "--foo", "4"], extras)
4440
4441 # ==========================
4442 # add_argument metavar tests
4443 # ==========================
4444
4445 class TestAddArgumentMetavar(TestCase):
4446
4447 EXPECTED_MESSAGE = "length of metavar tuple does not match nargs"
4448
4449 def do_test_no_exception(self, nargs, metavar):
4450 parser = argparse.ArgumentParser()
4451 parser.add_argument("--foo", nargs=nargs, metavar=metavar)
4452
4453 def do_test_exception(self, nargs, metavar):
4454 parser = argparse.ArgumentParser()
4455 with self.assertRaises(ValueError) as cm:
4456 parser.add_argument("--foo", nargs=nargs, metavar=metavar)
4457 self.assertEqual(cm.exception.args[0], self.EXPECTED_MESSAGE)
4458
4459 # Unit tests for different values of metavar when nargs=None
4460
4461 def test_nargs_None_metavar_string(self):
4462 self.do_test_no_exception(nargs=None, metavar="1")
4463
4464 def test_nargs_None_metavar_length0(self):
4465 self.do_test_exception(nargs=None, metavar=tuple())
4466
4467 def test_nargs_None_metavar_length1(self):
4468 self.do_test_no_exception(nargs=None, metavar=("1"))
4469
4470 def test_nargs_None_metavar_length2(self):
4471 self.do_test_exception(nargs=None, metavar=("1", "2"))
4472
4473 def test_nargs_None_metavar_length3(self):
4474 self.do_test_exception(nargs=None, metavar=("1", "2", "3"))
4475
4476 # Unit tests for different values of metavar when nargs=?
4477
4478 def test_nargs_optional_metavar_string(self):
4479 self.do_test_no_exception(nargs="?", metavar="1")
4480
4481 def test_nargs_optional_metavar_length0(self):
4482 self.do_test_exception(nargs="?", metavar=tuple())
4483
4484 def test_nargs_optional_metavar_length1(self):
4485 self.do_test_no_exception(nargs="?", metavar=("1"))
4486
4487 def test_nargs_optional_metavar_length2(self):
4488 self.do_test_exception(nargs="?", metavar=("1", "2"))
4489
4490 def test_nargs_optional_metavar_length3(self):
4491 self.do_test_exception(nargs="?", metavar=("1", "2", "3"))
4492
4493 # Unit tests for different values of metavar when nargs=*
4494
4495 def test_nargs_zeroormore_metavar_string(self):
4496 self.do_test_no_exception(nargs="*", metavar="1")
4497
4498 def test_nargs_zeroormore_metavar_length0(self):
4499 self.do_test_exception(nargs="*", metavar=tuple())
4500
4501 def test_nargs_zeroormore_metavar_length1(self):
4502 self.do_test_no_exception(nargs="*", metavar=("1"))
4503
4504 def test_nargs_zeroormore_metavar_length2(self):
4505 self.do_test_no_exception(nargs="*", metavar=("1", "2"))
4506
4507 def test_nargs_zeroormore_metavar_length3(self):
4508 self.do_test_exception(nargs="*", metavar=("1", "2", "3"))
4509
4510 # Unit tests for different values of metavar when nargs=+
4511
4512 def test_nargs_oneormore_metavar_string(self):
4513 self.do_test_no_exception(nargs="+", metavar="1")
4514
4515 def test_nargs_oneormore_metavar_length0(self):
4516 self.do_test_exception(nargs="+", metavar=tuple())
4517
4518 def test_nargs_oneormore_metavar_length1(self):
4519 self.do_test_no_exception(nargs="+", metavar=("1"))
4520
4521 def test_nargs_oneormore_metavar_length2(self):
4522 self.do_test_no_exception(nargs="+", metavar=("1", "2"))
4523
4524 def test_nargs_oneormore_metavar_length3(self):
4525 self.do_test_exception(nargs="+", metavar=("1", "2", "3"))
4526
4527 # Unit tests for different values of metavar when nargs=...
4528
4529 def test_nargs_remainder_metavar_string(self):
4530 self.do_test_no_exception(nargs="...", metavar="1")
4531
4532 def test_nargs_remainder_metavar_length0(self):
4533 self.do_test_no_exception(nargs="...", metavar=tuple())
4534
4535 def test_nargs_remainder_metavar_length1(self):
4536 self.do_test_no_exception(nargs="...", metavar=("1"))
4537
4538 def test_nargs_remainder_metavar_length2(self):
4539 self.do_test_no_exception(nargs="...", metavar=("1", "2"))
4540
4541 def test_nargs_remainder_metavar_length3(self):
4542 self.do_test_no_exception(nargs="...", metavar=("1", "2", "3"))
4543
4544 # Unit tests for different values of metavar when nargs=A...
4545
4546 def test_nargs_parser_metavar_string(self):
4547 self.do_test_no_exception(nargs="A...", metavar="1")
4548
4549 def test_nargs_parser_metavar_length0(self):
4550 self.do_test_exception(nargs="A...", metavar=tuple())
4551
4552 def test_nargs_parser_metavar_length1(self):
4553 self.do_test_no_exception(nargs="A...", metavar=("1"))
4554
4555 def test_nargs_parser_metavar_length2(self):
4556 self.do_test_exception(nargs="A...", metavar=("1", "2"))
4557
4558 def test_nargs_parser_metavar_length3(self):
4559 self.do_test_exception(nargs="A...", metavar=("1", "2", "3"))
4560
4561 # Unit tests for different values of metavar when nargs=1
4562
4563 def test_nargs_1_metavar_string(self):
4564 self.do_test_no_exception(nargs=1, metavar="1")
4565
4566 def test_nargs_1_metavar_length0(self):
4567 self.do_test_exception(nargs=1, metavar=tuple())
4568
4569 def test_nargs_1_metavar_length1(self):
4570 self.do_test_no_exception(nargs=1, metavar=("1"))
4571
4572 def test_nargs_1_metavar_length2(self):
4573 self.do_test_exception(nargs=1, metavar=("1", "2"))
4574
4575 def test_nargs_1_metavar_length3(self):
4576 self.do_test_exception(nargs=1, metavar=("1", "2", "3"))
4577
4578 # Unit tests for different values of metavar when nargs=2
4579
4580 def test_nargs_2_metavar_string(self):
4581 self.do_test_no_exception(nargs=2, metavar="1")
4582
4583 def test_nargs_2_metavar_length0(self):
4584 self.do_test_exception(nargs=2, metavar=tuple())
4585
4586 def test_nargs_2_metavar_length1(self):
4587 self.do_test_no_exception(nargs=2, metavar=("1"))
4588
4589 def test_nargs_2_metavar_length2(self):
4590 self.do_test_no_exception(nargs=2, metavar=("1", "2"))
4591
4592 def test_nargs_2_metavar_length3(self):
4593 self.do_test_exception(nargs=2, metavar=("1", "2", "3"))
4594
4595 # Unit tests for different values of metavar when nargs=3
4596
4597 def test_nargs_3_metavar_string(self):
4598 self.do_test_no_exception(nargs=3, metavar="1")
4599
4600 def test_nargs_3_metavar_length0(self):
4601 self.do_test_exception(nargs=3, metavar=tuple())
4602
4603 def test_nargs_3_metavar_length1(self):
4604 self.do_test_no_exception(nargs=3, metavar=("1"))
4605
4606 def test_nargs_3_metavar_length2(self):
4607 self.do_test_exception(nargs=3, metavar=("1", "2"))
4608
4609 def test_nargs_3_metavar_length3(self):
4610 self.do_test_no_exception(nargs=3, metavar=("1", "2", "3"))
4611
4612 # ============================
4613 # from argparse import * tests
4614 # ============================
4615
4616 class TestImportStar(TestCase):
4617
4618 def test(self):
4619 for name in argparse.__all__:
4620 self.assertTrue(hasattr(argparse, name))
4621
4622 def test_all_exports_everything_but_modules(self):
4623 items = [
4624 name
4625 for name, value in vars(argparse).items()
4626 if not name.startswith("_")
4627 if not inspect.ismodule(value)
4628 ]
4629 self.assertEqual(sorted(items), sorted(argparse.__all__))
4630
4631 def test_main():
4632 # silence warnings about version argument - these are expected
4633 with test_support.check_warnings(
4634 ('The "version" argument to ArgumentParser is deprecated.',
4635 DeprecationWarning),
4636 ('The (format|print)_version method is deprecated',
4637 DeprecationWarning)):
4638 test_support.run_unittest(__name__)
4639 # Remove global references to avoid looking like we have refleaks.
4640 RFile.seen = {}
4641 WFile.seen = set()
4642
4643
4644
4645 if __name__ == '__main__':
4646 test_main()