1 # Author: Steven J. Bethard <steven.bethard (at] 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() 4647