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 (["-a", "", "X", "Y"], NS(a='', x='X', y=['Y'])), 1378 ] 1379 1380 1381 class TestArgumentsFromFileConverter(TempDirMixin, ParserTestCase): 1382 """Test reading arguments from a file""" 1383 1384 def setUp(self): 1385 super(TestArgumentsFromFileConverter, self).setUp() 1386 file_texts = [ 1387 ('hello', 'hello world!\n'), 1388 ] 1389 for path, text in file_texts: 1390 file = open(path, 'w') 1391 file.write(text) 1392 file.close() 1393 1394 class FromFileConverterArgumentParser(ErrorRaisingArgumentParser): 1395 1396 def convert_arg_line_to_args(self, arg_line): 1397 for arg in arg_line.split(): 1398 if not arg.strip(): 1399 continue 1400 yield arg 1401 parser_class = FromFileConverterArgumentParser 1402 parser_signature = Sig(fromfile_prefix_chars='@') 1403 argument_signatures = [ 1404 Sig('y', nargs='+'), 1405 ] 1406 failures = [] 1407 successes = [ 1408 ('@hello X', NS(y=['hello', 'world!', 'X'])), 1409 ] 1410 1411 1412 # ===================== 1413 # Type conversion tests 1414 # ===================== 1415 1416 class TestFileTypeRepr(TestCase): 1417 1418 def test_r(self): 1419 type = argparse.FileType('r') 1420 self.assertEqual("FileType('r')", repr(type)) 1421 1422 def test_wb_1(self): 1423 type = argparse.FileType('wb', 1) 1424 self.assertEqual("FileType('wb', 1)", repr(type)) 1425 1426 1427 class RFile(object): 1428 seen = {} 1429 1430 def __init__(self, name): 1431 self.name = name 1432 1433 __hash__ = None 1434 1435 def __eq__(self, other): 1436 if other in self.seen: 1437 text = self.seen[other] 1438 else: 1439 text = self.seen[other] = other.read() 1440 other.close() 1441 if not isinstance(text, str): 1442 text = text.decode('ascii') 1443 return self.name == other.name == text 1444 1445 1446 class TestFileTypeR(TempDirMixin, ParserTestCase): 1447 """Test the FileType option/argument type for reading files""" 1448 1449 def setUp(self): 1450 super(TestFileTypeR, self).setUp() 1451 for file_name in ['foo', 'bar']: 1452 file = open(os.path.join(self.temp_dir, file_name), 'w') 1453 file.write(file_name) 1454 file.close() 1455 self.create_readonly_file('readonly') 1456 1457 argument_signatures = [ 1458 Sig('-x', type=argparse.FileType()), 1459 Sig('spam', type=argparse.FileType('r')), 1460 ] 1461 failures = ['-x', '-x bar', 'non-existent-file.txt'] 1462 successes = [ 1463 ('foo', NS(x=None, spam=RFile('foo'))), 1464 ('-x foo bar', NS(x=RFile('foo'), spam=RFile('bar'))), 1465 ('bar -x foo', NS(x=RFile('foo'), spam=RFile('bar'))), 1466 ('-x - -', NS(x=sys.stdin, spam=sys.stdin)), 1467 ('readonly', NS(x=None, spam=RFile('readonly'))), 1468 ] 1469 1470 class TestFileTypeDefaults(TempDirMixin, ParserTestCase): 1471 """Test that a file is not created unless the default is needed""" 1472 def setUp(self): 1473 super(TestFileTypeDefaults, self).setUp() 1474 file = open(os.path.join(self.temp_dir, 'good'), 'w') 1475 file.write('good') 1476 file.close() 1477 1478 argument_signatures = [ 1479 Sig('-c', type=argparse.FileType('r'), default='no-file.txt'), 1480 ] 1481 # should provoke no such file error 1482 failures = [''] 1483 # should not provoke error because default file is created 1484 successes = [('-c good', NS(c=RFile('good')))] 1485 1486 1487 class TestFileTypeRB(TempDirMixin, ParserTestCase): 1488 """Test the FileType option/argument type for reading files""" 1489 1490 def setUp(self): 1491 super(TestFileTypeRB, self).setUp() 1492 for file_name in ['foo', 'bar']: 1493 file = open(os.path.join(self.temp_dir, file_name), 'w') 1494 file.write(file_name) 1495 file.close() 1496 1497 argument_signatures = [ 1498 Sig('-x', type=argparse.FileType('rb')), 1499 Sig('spam', type=argparse.FileType('rb')), 1500 ] 1501 failures = ['-x', '-x bar'] 1502 successes = [ 1503 ('foo', NS(x=None, spam=RFile('foo'))), 1504 ('-x foo bar', NS(x=RFile('foo'), spam=RFile('bar'))), 1505 ('bar -x foo', NS(x=RFile('foo'), spam=RFile('bar'))), 1506 ('-x - -', NS(x=sys.stdin, spam=sys.stdin)), 1507 ] 1508 1509 1510 class WFile(object): 1511 seen = set() 1512 1513 def __init__(self, name): 1514 self.name = name 1515 1516 __hash__ = None 1517 1518 def __eq__(self, other): 1519 if other not in self.seen: 1520 text = 'Check that file is writable.' 1521 if 'b' in other.mode: 1522 text = text.encode('ascii') 1523 other.write(text) 1524 other.close() 1525 self.seen.add(other) 1526 return self.name == other.name 1527 1528 1529 @unittest.skipIf(hasattr(os, 'geteuid') and os.geteuid() == 0, 1530 "non-root user required") 1531 class TestFileTypeW(TempDirMixin, ParserTestCase): 1532 """Test the FileType option/argument type for writing files""" 1533 1534 def setUp(self): 1535 super(TestFileTypeW, self).setUp() 1536 self.create_readonly_file('readonly') 1537 1538 argument_signatures = [ 1539 Sig('-x', type=argparse.FileType('w')), 1540 Sig('spam', type=argparse.FileType('w')), 1541 ] 1542 failures = ['-x', '-x bar'] 1543 failures = ['-x', '-x bar', 'readonly'] 1544 successes = [ 1545 ('foo', NS(x=None, spam=WFile('foo'))), 1546 ('-x foo bar', NS(x=WFile('foo'), spam=WFile('bar'))), 1547 ('bar -x foo', NS(x=WFile('foo'), spam=WFile('bar'))), 1548 ('-x - -', NS(x=sys.stdout, spam=sys.stdout)), 1549 ] 1550 1551 1552 class TestFileTypeWB(TempDirMixin, ParserTestCase): 1553 1554 argument_signatures = [ 1555 Sig('-x', type=argparse.FileType('wb')), 1556 Sig('spam', type=argparse.FileType('wb')), 1557 ] 1558 failures = ['-x', '-x bar'] 1559 successes = [ 1560 ('foo', NS(x=None, spam=WFile('foo'))), 1561 ('-x foo bar', NS(x=WFile('foo'), spam=WFile('bar'))), 1562 ('bar -x foo', NS(x=WFile('foo'), spam=WFile('bar'))), 1563 ('-x - -', NS(x=sys.stdout, spam=sys.stdout)), 1564 ] 1565 1566 1567 class TestTypeCallable(ParserTestCase): 1568 """Test some callables as option/argument types""" 1569 1570 argument_signatures = [ 1571 Sig('--eggs', type=complex), 1572 Sig('spam', type=float), 1573 ] 1574 failures = ['a', '42j', '--eggs a', '--eggs 2i'] 1575 successes = [ 1576 ('--eggs=42 42', NS(eggs=42, spam=42.0)), 1577 ('--eggs 2j -- -1.5', NS(eggs=2j, spam=-1.5)), 1578 ('1024.675', NS(eggs=None, spam=1024.675)), 1579 ] 1580 1581 1582 class TestTypeUserDefined(ParserTestCase): 1583 """Test a user-defined option/argument type""" 1584 1585 class MyType(TestCase): 1586 1587 def __init__(self, value): 1588 self.value = value 1589 1590 __hash__ = None 1591 1592 def __eq__(self, other): 1593 return (type(self), self.value) == (type(other), other.value) 1594 1595 argument_signatures = [ 1596 Sig('-x', type=MyType), 1597 Sig('spam', type=MyType), 1598 ] 1599 failures = [] 1600 successes = [ 1601 ('a -x b', NS(x=MyType('b'), spam=MyType('a'))), 1602 ('-xf g', NS(x=MyType('f'), spam=MyType('g'))), 1603 ] 1604 1605 1606 class TestTypeClassicClass(ParserTestCase): 1607 """Test a classic class type""" 1608 1609 class C: 1610 1611 def __init__(self, value): 1612 self.value = value 1613 1614 __hash__ = None 1615 1616 def __eq__(self, other): 1617 return (type(self), self.value) == (type(other), other.value) 1618 1619 argument_signatures = [ 1620 Sig('-x', type=C), 1621 Sig('spam', type=C), 1622 ] 1623 failures = [] 1624 successes = [ 1625 ('a -x b', NS(x=C('b'), spam=C('a'))), 1626 ('-xf g', NS(x=C('f'), spam=C('g'))), 1627 ] 1628 1629 1630 class TestTypeRegistration(TestCase): 1631 """Test a user-defined type by registering it""" 1632 1633 def test(self): 1634 1635 def get_my_type(string): 1636 return 'my_type{%s}' % string 1637 1638 parser = argparse.ArgumentParser() 1639 parser.register('type', 'my_type', get_my_type) 1640 parser.add_argument('-x', type='my_type') 1641 parser.add_argument('y', type='my_type') 1642 1643 self.assertEqual(parser.parse_args('1'.split()), 1644 NS(x=None, y='my_type{1}')) 1645 self.assertEqual(parser.parse_args('-x 1 42'.split()), 1646 NS(x='my_type{1}', y='my_type{42}')) 1647 1648 1649 # ============ 1650 # Action tests 1651 # ============ 1652 1653 class TestActionUserDefined(ParserTestCase): 1654 """Test a user-defined option/argument action""" 1655 1656 class OptionalAction(argparse.Action): 1657 1658 def __call__(self, parser, namespace, value, option_string=None): 1659 try: 1660 # check destination and option string 1661 assert self.dest == 'spam', 'dest: %s' % self.dest 1662 assert option_string == '-s', 'flag: %s' % option_string 1663 # when option is before argument, badger=2, and when 1664 # option is after argument, badger=<whatever was set> 1665 expected_ns = NS(spam=0.25) 1666 if value in [0.125, 0.625]: 1667 expected_ns.badger = 2 1668 elif value in [2.0]: 1669 expected_ns.badger = 84 1670 else: 1671 raise AssertionError('value: %s' % value) 1672 assert expected_ns == namespace, ('expected %s, got %s' % 1673 (expected_ns, namespace)) 1674 except AssertionError: 1675 e = sys.exc_info()[1] 1676 raise ArgumentParserError('opt_action failed: %s' % e) 1677 setattr(namespace, 'spam', value) 1678 1679 class PositionalAction(argparse.Action): 1680 1681 def __call__(self, parser, namespace, value, option_string=None): 1682 try: 1683 assert option_string is None, ('option_string: %s' % 1684 option_string) 1685 # check destination 1686 assert self.dest == 'badger', 'dest: %s' % self.dest 1687 # when argument is before option, spam=0.25, and when 1688 # option is after argument, spam=<whatever was set> 1689 expected_ns = NS(badger=2) 1690 if value in [42, 84]: 1691 expected_ns.spam = 0.25 1692 elif value in [1]: 1693 expected_ns.spam = 0.625 1694 elif value in [2]: 1695 expected_ns.spam = 0.125 1696 else: 1697 raise AssertionError('value: %s' % value) 1698 assert expected_ns == namespace, ('expected %s, got %s' % 1699 (expected_ns, namespace)) 1700 except AssertionError: 1701 e = sys.exc_info()[1] 1702 raise ArgumentParserError('arg_action failed: %s' % e) 1703 setattr(namespace, 'badger', value) 1704 1705 argument_signatures = [ 1706 Sig('-s', dest='spam', action=OptionalAction, 1707 type=float, default=0.25), 1708 Sig('badger', action=PositionalAction, 1709 type=int, nargs='?', default=2), 1710 ] 1711 failures = [] 1712 successes = [ 1713 ('-s0.125', NS(spam=0.125, badger=2)), 1714 ('42', NS(spam=0.25, badger=42)), 1715 ('-s 0.625 1', NS(spam=0.625, badger=1)), 1716 ('84 -s2', NS(spam=2.0, badger=84)), 1717 ] 1718 1719 1720 class TestActionRegistration(TestCase): 1721 """Test a user-defined action supplied by registering it""" 1722 1723 class MyAction(argparse.Action): 1724 1725 def __call__(self, parser, namespace, values, option_string=None): 1726 setattr(namespace, self.dest, 'foo[%s]' % values) 1727 1728 def test(self): 1729 1730 parser = argparse.ArgumentParser() 1731 parser.register('action', 'my_action', self.MyAction) 1732 parser.add_argument('badger', action='my_action') 1733 1734 self.assertEqual(parser.parse_args(['1']), NS(badger='foo[1]')) 1735 self.assertEqual(parser.parse_args(['42']), NS(badger='foo[42]')) 1736 1737 1738 # ================ 1739 # Subparsers tests 1740 # ================ 1741 1742 class TestAddSubparsers(TestCase): 1743 """Test the add_subparsers method""" 1744 1745 def assertArgumentParserError(self, *args, **kwargs): 1746 self.assertRaises(ArgumentParserError, *args, **kwargs) 1747 1748 def _get_parser(self, subparser_help=False, prefix_chars=None): 1749 # create a parser with a subparsers argument 1750 if prefix_chars: 1751 parser = ErrorRaisingArgumentParser( 1752 prog='PROG', description='main description', prefix_chars=prefix_chars) 1753 parser.add_argument( 1754 prefix_chars[0] * 2 + 'foo', action='store_true', help='foo help') 1755 else: 1756 parser = ErrorRaisingArgumentParser( 1757 prog='PROG', description='main description') 1758 parser.add_argument( 1759 '--foo', action='store_true', help='foo help') 1760 parser.add_argument( 1761 'bar', type=float, help='bar help') 1762 1763 # check that only one subparsers argument can be added 1764 subparsers = parser.add_subparsers(help='command help') 1765 self.assertArgumentParserError(parser.add_subparsers) 1766 1767 # add first sub-parser 1768 parser1_kwargs = dict(description='1 description') 1769 if subparser_help: 1770 parser1_kwargs['help'] = '1 help' 1771 parser1 = subparsers.add_parser('1', **parser1_kwargs) 1772 parser1.add_argument('-w', type=int, help='w help') 1773 parser1.add_argument('x', choices='abc', help='x help') 1774 1775 # add second sub-parser 1776 parser2_kwargs = dict(description='2 description') 1777 if subparser_help: 1778 parser2_kwargs['help'] = '2 help' 1779 parser2 = subparsers.add_parser('2', **parser2_kwargs) 1780 parser2.add_argument('-y', choices='123', help='y help') 1781 parser2.add_argument('z', type=complex, nargs='*', help='z help') 1782 1783 # add third sub-parser 1784 parser3_kwargs = dict(description='3 description') 1785 if subparser_help: 1786 parser3_kwargs['help'] = '3 help' 1787 parser3 = subparsers.add_parser('3', **parser3_kwargs) 1788 parser3.add_argument('t', type=int, help='t help') 1789 parser3.add_argument('u', nargs='...', help='u help') 1790 1791 # return the main parser 1792 return parser 1793 1794 def setUp(self): 1795 super(TestAddSubparsers, self).setUp() 1796 self.parser = self._get_parser() 1797 self.command_help_parser = self._get_parser(subparser_help=True) 1798 1799 def test_parse_args_failures(self): 1800 # check some failure cases: 1801 for args_str in ['', 'a', 'a a', '0.5 a', '0.5 1', 1802 '0.5 1 -y', '0.5 2 -w']: 1803 args = args_str.split() 1804 self.assertArgumentParserError(self.parser.parse_args, args) 1805 1806 def test_parse_args(self): 1807 # check some non-failure cases: 1808 self.assertEqual( 1809 self.parser.parse_args('0.5 1 b -w 7'.split()), 1810 NS(foo=False, bar=0.5, w=7, x='b'), 1811 ) 1812 self.assertEqual( 1813 self.parser.parse_args('0.25 --foo 2 -y 2 3j -- -1j'.split()), 1814 NS(foo=True, bar=0.25, y='2', z=[3j, -1j]), 1815 ) 1816 self.assertEqual( 1817 self.parser.parse_args('--foo 0.125 1 c'.split()), 1818 NS(foo=True, bar=0.125, w=None, x='c'), 1819 ) 1820 self.assertEqual( 1821 self.parser.parse_args('-1.5 3 11 -- a --foo 7 -- b'.split()), 1822 NS(foo=False, bar=-1.5, t=11, u=['a', '--foo', '7', '--', 'b']), 1823 ) 1824 1825 def test_parse_known_args(self): 1826 self.assertEqual( 1827 self.parser.parse_known_args('0.5 1 b -w 7'.split()), 1828 (NS(foo=False, bar=0.5, w=7, x='b'), []), 1829 ) 1830 self.assertEqual( 1831 self.parser.parse_known_args('0.5 -p 1 b -w 7'.split()), 1832 (NS(foo=False, bar=0.5, w=7, x='b'), ['-p']), 1833 ) 1834 self.assertEqual( 1835 self.parser.parse_known_args('0.5 1 b -w 7 -p'.split()), 1836 (NS(foo=False, bar=0.5, w=7, x='b'), ['-p']), 1837 ) 1838 self.assertEqual( 1839 self.parser.parse_known_args('0.5 1 b -q -rs -w 7'.split()), 1840 (NS(foo=False, bar=0.5, w=7, x='b'), ['-q', '-rs']), 1841 ) 1842 self.assertEqual( 1843 self.parser.parse_known_args('0.5 -W 1 b -X Y -w 7 Z'.split()), 1844 (NS(foo=False, bar=0.5, w=7, x='b'), ['-W', '-X', 'Y', 'Z']), 1845 ) 1846 1847 def test_dest(self): 1848 parser = ErrorRaisingArgumentParser() 1849 parser.add_argument('--foo', action='store_true') 1850 subparsers = parser.add_subparsers(dest='bar') 1851 parser1 = subparsers.add_parser('1') 1852 parser1.add_argument('baz') 1853 self.assertEqual(NS(foo=False, bar='1', baz='2'), 1854 parser.parse_args('1 2'.split())) 1855 1856 def test_help(self): 1857 self.assertEqual(self.parser.format_usage(), 1858 'usage: PROG [-h] [--foo] bar {1,2,3} ...\n') 1859 self.assertEqual(self.parser.format_help(), textwrap.dedent('''\ 1860 usage: PROG [-h] [--foo] bar {1,2,3} ... 1861 1862 main description 1863 1864 positional arguments: 1865 bar bar help 1866 {1,2,3} command help 1867 1868 optional arguments: 1869 -h, --help show this help message and exit 1870 --foo foo help 1871 ''')) 1872 1873 def test_help_extra_prefix_chars(self): 1874 # Make sure - is still used for help if it is a non-first prefix char 1875 parser = self._get_parser(prefix_chars='+:-') 1876 self.assertEqual(parser.format_usage(), 1877 'usage: PROG [-h] [++foo] bar {1,2,3} ...\n') 1878 self.assertEqual(parser.format_help(), textwrap.dedent('''\ 1879 usage: PROG [-h] [++foo] bar {1,2,3} ... 1880 1881 main description 1882 1883 positional arguments: 1884 bar bar help 1885 {1,2,3} command help 1886 1887 optional arguments: 1888 -h, --help show this help message and exit 1889 ++foo foo help 1890 ''')) 1891 1892 1893 def test_help_alternate_prefix_chars(self): 1894 parser = self._get_parser(prefix_chars='+:/') 1895 self.assertEqual(parser.format_usage(), 1896 'usage: PROG [+h] [++foo] bar {1,2,3} ...\n') 1897 self.assertEqual(parser.format_help(), textwrap.dedent('''\ 1898 usage: PROG [+h] [++foo] bar {1,2,3} ... 1899 1900 main description 1901 1902 positional arguments: 1903 bar bar help 1904 {1,2,3} command help 1905 1906 optional arguments: 1907 +h, ++help show this help message and exit 1908 ++foo foo help 1909 ''')) 1910 1911 def test_parser_command_help(self): 1912 self.assertEqual(self.command_help_parser.format_usage(), 1913 'usage: PROG [-h] [--foo] bar {1,2,3} ...\n') 1914 self.assertEqual(self.command_help_parser.format_help(), 1915 textwrap.dedent('''\ 1916 usage: PROG [-h] [--foo] bar {1,2,3} ... 1917 1918 main description 1919 1920 positional arguments: 1921 bar bar help 1922 {1,2,3} command help 1923 1 1 help 1924 2 2 help 1925 3 3 help 1926 1927 optional arguments: 1928 -h, --help show this help message and exit 1929 --foo foo help 1930 ''')) 1931 1932 def test_subparser_title_help(self): 1933 parser = ErrorRaisingArgumentParser(prog='PROG', 1934 description='main description') 1935 parser.add_argument('--foo', action='store_true', help='foo help') 1936 parser.add_argument('bar', help='bar help') 1937 subparsers = parser.add_subparsers(title='subcommands', 1938 description='command help', 1939 help='additional text') 1940 parser1 = subparsers.add_parser('1') 1941 parser2 = subparsers.add_parser('2') 1942 self.assertEqual(parser.format_usage(), 1943 'usage: PROG [-h] [--foo] bar {1,2} ...\n') 1944 self.assertEqual(parser.format_help(), textwrap.dedent('''\ 1945 usage: PROG [-h] [--foo] bar {1,2} ... 1946 1947 main description 1948 1949 positional arguments: 1950 bar bar help 1951 1952 optional arguments: 1953 -h, --help show this help message and exit 1954 --foo foo help 1955 1956 subcommands: 1957 command help 1958 1959 {1,2} additional text 1960 ''')) 1961 1962 def _test_subparser_help(self, args_str, expected_help): 1963 try: 1964 self.parser.parse_args(args_str.split()) 1965 except ArgumentParserError: 1966 err = sys.exc_info()[1] 1967 if err.stdout != expected_help: 1968 print(repr(expected_help)) 1969 print(repr(err.stdout)) 1970 self.assertEqual(err.stdout, expected_help) 1971 1972 def test_subparser1_help(self): 1973 self._test_subparser_help('5.0 1 -h', textwrap.dedent('''\ 1974 usage: PROG bar 1 [-h] [-w W] {a,b,c} 1975 1976 1 description 1977 1978 positional arguments: 1979 {a,b,c} x help 1980 1981 optional arguments: 1982 -h, --help show this help message and exit 1983 -w W w help 1984 ''')) 1985 1986 def test_subparser2_help(self): 1987 self._test_subparser_help('5.0 2 -h', textwrap.dedent('''\ 1988 usage: PROG bar 2 [-h] [-y {1,2,3}] [z [z ...]] 1989 1990 2 description 1991 1992 positional arguments: 1993 z z help 1994 1995 optional arguments: 1996 -h, --help show this help message and exit 1997 -y {1,2,3} y help 1998 ''')) 1999 2000 # ============ 2001 # Groups tests 2002 # ============ 2003 2004 class TestPositionalsGroups(TestCase): 2005 """Tests that order of group positionals matches construction order""" 2006 2007 def test_nongroup_first(self): 2008 parser = ErrorRaisingArgumentParser() 2009 parser.add_argument('foo') 2010 group = parser.add_argument_group('g') 2011 group.add_argument('bar') 2012 parser.add_argument('baz') 2013 expected = NS(foo='1', bar='2', baz='3') 2014 result = parser.parse_args('1 2 3'.split()) 2015 self.assertEqual(expected, result) 2016 2017 def test_group_first(self): 2018 parser = ErrorRaisingArgumentParser() 2019 group = parser.add_argument_group('xxx') 2020 group.add_argument('foo') 2021 parser.add_argument('bar') 2022 parser.add_argument('baz') 2023 expected = NS(foo='1', bar='2', baz='3') 2024 result = parser.parse_args('1 2 3'.split()) 2025 self.assertEqual(expected, result) 2026 2027 def test_interleaved_groups(self): 2028 parser = ErrorRaisingArgumentParser() 2029 group = parser.add_argument_group('xxx') 2030 parser.add_argument('foo') 2031 group.add_argument('bar') 2032 parser.add_argument('baz') 2033 group = parser.add_argument_group('yyy') 2034 group.add_argument('frell') 2035 expected = NS(foo='1', bar='2', baz='3', frell='4') 2036 result = parser.parse_args('1 2 3 4'.split()) 2037 self.assertEqual(expected, result) 2038 2039 # =================== 2040 # Parent parser tests 2041 # =================== 2042 2043 class TestParentParsers(TestCase): 2044 """Tests that parsers can be created with parent parsers""" 2045 2046 def assertArgumentParserError(self, *args, **kwargs): 2047 self.assertRaises(ArgumentParserError, *args, **kwargs) 2048 2049 def setUp(self): 2050 super(TestParentParsers, self).setUp() 2051 self.wxyz_parent = ErrorRaisingArgumentParser(add_help=False) 2052 self.wxyz_parent.add_argument('--w') 2053 x_group = self.wxyz_parent.add_argument_group('x') 2054 x_group.add_argument('-y') 2055 self.wxyz_parent.add_argument('z') 2056 2057 self.abcd_parent = ErrorRaisingArgumentParser(add_help=False) 2058 self.abcd_parent.add_argument('a') 2059 self.abcd_parent.add_argument('-b') 2060 c_group = self.abcd_parent.add_argument_group('c') 2061 c_group.add_argument('--d') 2062 2063 self.w_parent = ErrorRaisingArgumentParser(add_help=False) 2064 self.w_parent.add_argument('--w') 2065 2066 self.z_parent = ErrorRaisingArgumentParser(add_help=False) 2067 self.z_parent.add_argument('z') 2068 2069 # parents with mutually exclusive groups 2070 self.ab_mutex_parent = ErrorRaisingArgumentParser(add_help=False) 2071 group = self.ab_mutex_parent.add_mutually_exclusive_group() 2072 group.add_argument('-a', action='store_true') 2073 group.add_argument('-b', action='store_true') 2074 2075 self.main_program = os.path.basename(sys.argv[0]) 2076 2077 def test_single_parent(self): 2078 parser = ErrorRaisingArgumentParser(parents=[self.wxyz_parent]) 2079 self.assertEqual(parser.parse_args('-y 1 2 --w 3'.split()), 2080 NS(w='3', y='1', z='2')) 2081 2082 def test_single_parent_mutex(self): 2083 self._test_mutex_ab(self.ab_mutex_parent.parse_args) 2084 parser = ErrorRaisingArgumentParser(parents=[self.ab_mutex_parent]) 2085 self._test_mutex_ab(parser.parse_args) 2086 2087 def test_single_granparent_mutex(self): 2088 parents = [self.ab_mutex_parent] 2089 parser = ErrorRaisingArgumentParser(add_help=False, parents=parents) 2090 parser = ErrorRaisingArgumentParser(parents=[parser]) 2091 self._test_mutex_ab(parser.parse_args) 2092 2093 def _test_mutex_ab(self, parse_args): 2094 self.assertEqual(parse_args([]), NS(a=False, b=False)) 2095 self.assertEqual(parse_args(['-a']), NS(a=True, b=False)) 2096 self.assertEqual(parse_args(['-b']), NS(a=False, b=True)) 2097 self.assertArgumentParserError(parse_args, ['-a', '-b']) 2098 self.assertArgumentParserError(parse_args, ['-b', '-a']) 2099 self.assertArgumentParserError(parse_args, ['-c']) 2100 self.assertArgumentParserError(parse_args, ['-a', '-c']) 2101 self.assertArgumentParserError(parse_args, ['-b', '-c']) 2102 2103 def test_multiple_parents(self): 2104 parents = [self.abcd_parent, self.wxyz_parent] 2105 parser = ErrorRaisingArgumentParser(parents=parents) 2106 self.assertEqual(parser.parse_args('--d 1 --w 2 3 4'.split()), 2107 NS(a='3', b=None, d='1', w='2', y=None, z='4')) 2108 2109 def test_multiple_parents_mutex(self): 2110 parents = [self.ab_mutex_parent, self.wxyz_parent] 2111 parser = ErrorRaisingArgumentParser(parents=parents) 2112 self.assertEqual(parser.parse_args('-a --w 2 3'.split()), 2113 NS(a=True, b=False, w='2', y=None, z='3')) 2114 self.assertArgumentParserError( 2115 parser.parse_args, '-a --w 2 3 -b'.split()) 2116 self.assertArgumentParserError( 2117 parser.parse_args, '-a -b --w 2 3'.split()) 2118 2119 def test_conflicting_parents(self): 2120 self.assertRaises( 2121 argparse.ArgumentError, 2122 argparse.ArgumentParser, 2123 parents=[self.w_parent, self.wxyz_parent]) 2124 2125 def test_conflicting_parents_mutex(self): 2126 self.assertRaises( 2127 argparse.ArgumentError, 2128 argparse.ArgumentParser, 2129 parents=[self.abcd_parent, self.ab_mutex_parent]) 2130 2131 def test_same_argument_name_parents(self): 2132 parents = [self.wxyz_parent, self.z_parent] 2133 parser = ErrorRaisingArgumentParser(parents=parents) 2134 self.assertEqual(parser.parse_args('1 2'.split()), 2135 NS(w=None, y=None, z='2')) 2136 2137 def test_subparser_parents(self): 2138 parser = ErrorRaisingArgumentParser() 2139 subparsers = parser.add_subparsers() 2140 abcde_parser = subparsers.add_parser('bar', parents=[self.abcd_parent]) 2141 abcde_parser.add_argument('e') 2142 self.assertEqual(parser.parse_args('bar -b 1 --d 2 3 4'.split()), 2143 NS(a='3', b='1', d='2', e='4')) 2144 2145 def test_subparser_parents_mutex(self): 2146 parser = ErrorRaisingArgumentParser() 2147 subparsers = parser.add_subparsers() 2148 parents = [self.ab_mutex_parent] 2149 abc_parser = subparsers.add_parser('foo', parents=parents) 2150 c_group = abc_parser.add_argument_group('c_group') 2151 c_group.add_argument('c') 2152 parents = [self.wxyz_parent, self.ab_mutex_parent] 2153 wxyzabe_parser = subparsers.add_parser('bar', parents=parents) 2154 wxyzabe_parser.add_argument('e') 2155 self.assertEqual(parser.parse_args('foo -a 4'.split()), 2156 NS(a=True, b=False, c='4')) 2157 self.assertEqual(parser.parse_args('bar -b --w 2 3 4'.split()), 2158 NS(a=False, b=True, w='2', y=None, z='3', e='4')) 2159 self.assertArgumentParserError( 2160 parser.parse_args, 'foo -a -b 4'.split()) 2161 self.assertArgumentParserError( 2162 parser.parse_args, 'bar -b -a 4'.split()) 2163 2164 def test_parent_help(self): 2165 parents = [self.abcd_parent, self.wxyz_parent] 2166 parser = ErrorRaisingArgumentParser(parents=parents) 2167 parser_help = parser.format_help() 2168 progname = self.main_program 2169 self.assertEqual(parser_help, textwrap.dedent('''\ 2170 usage: {}{}[-h] [-b B] [--d D] [--w W] [-y Y] a z 2171 2172 positional arguments: 2173 a 2174 z 2175 2176 optional arguments: 2177 -h, --help show this help message and exit 2178 -b B 2179 --w W 2180 2181 c: 2182 --d D 2183 2184 x: 2185 -y Y 2186 '''.format(progname, ' ' if progname else '' ))) 2187 2188 def test_groups_parents(self): 2189 parent = ErrorRaisingArgumentParser(add_help=False) 2190 g = parent.add_argument_group(title='g', description='gd') 2191 g.add_argument('-w') 2192 g.add_argument('-x') 2193 m = parent.add_mutually_exclusive_group() 2194 m.add_argument('-y') 2195 m.add_argument('-z') 2196 parser = ErrorRaisingArgumentParser(parents=[parent]) 2197 2198 self.assertRaises(ArgumentParserError, parser.parse_args, 2199 ['-y', 'Y', '-z', 'Z']) 2200 2201 parser_help = parser.format_help() 2202 progname = self.main_program 2203 self.assertEqual(parser_help, textwrap.dedent('''\ 2204 usage: {}{}[-h] [-w W] [-x X] [-y Y | -z Z] 2205 2206 optional arguments: 2207 -h, --help show this help message and exit 2208 -y Y 2209 -z Z 2210 2211 g: 2212 gd 2213 2214 -w W 2215 -x X 2216 '''.format(progname, ' ' if progname else '' ))) 2217 2218 # ============================== 2219 # Mutually exclusive group tests 2220 # ============================== 2221 2222 class TestMutuallyExclusiveGroupErrors(TestCase): 2223 2224 def test_invalid_add_argument_group(self): 2225 parser = ErrorRaisingArgumentParser() 2226 raises = self.assertRaises 2227 raises(TypeError, parser.add_mutually_exclusive_group, title='foo') 2228 2229 def test_invalid_add_argument(self): 2230 parser = ErrorRaisingArgumentParser() 2231 group = parser.add_mutually_exclusive_group() 2232 add_argument = group.add_argument 2233 raises = self.assertRaises 2234 raises(ValueError, add_argument, '--foo', required=True) 2235 raises(ValueError, add_argument, 'bar') 2236 raises(ValueError, add_argument, 'bar', nargs='+') 2237 raises(ValueError, add_argument, 'bar', nargs=1) 2238 raises(ValueError, add_argument, 'bar', nargs=argparse.PARSER) 2239 2240 def test_help(self): 2241 parser = ErrorRaisingArgumentParser(prog='PROG') 2242 group1 = parser.add_mutually_exclusive_group() 2243 group1.add_argument('--foo', action='store_true') 2244 group1.add_argument('--bar', action='store_false') 2245 group2 = parser.add_mutually_exclusive_group() 2246 group2.add_argument('--soup', action='store_true') 2247 group2.add_argument('--nuts', action='store_false') 2248 expected = '''\ 2249 usage: PROG [-h] [--foo | --bar] [--soup | --nuts] 2250 2251 optional arguments: 2252 -h, --help show this help message and exit 2253 --foo 2254 --bar 2255 --soup 2256 --nuts 2257 ''' 2258 self.assertEqual(parser.format_help(), textwrap.dedent(expected)) 2259 2260 class MEMixin(object): 2261 2262 def test_failures_when_not_required(self): 2263 parse_args = self.get_parser(required=False).parse_args 2264 error = ArgumentParserError 2265 for args_string in self.failures: 2266 self.assertRaises(error, parse_args, args_string.split()) 2267 2268 def test_failures_when_required(self): 2269 parse_args = self.get_parser(required=True).parse_args 2270 error = ArgumentParserError 2271 for args_string in self.failures + ['']: 2272 self.assertRaises(error, parse_args, args_string.split()) 2273 2274 def test_successes_when_not_required(self): 2275 parse_args = self.get_parser(required=False).parse_args 2276 successes = self.successes + self.successes_when_not_required 2277 for args_string, expected_ns in successes: 2278 actual_ns = parse_args(args_string.split()) 2279 self.assertEqual(actual_ns, expected_ns) 2280 2281 def test_successes_when_required(self): 2282 parse_args = self.get_parser(required=True).parse_args 2283 for args_string, expected_ns in self.successes: 2284 actual_ns = parse_args(args_string.split()) 2285 self.assertEqual(actual_ns, expected_ns) 2286 2287 def test_usage_when_not_required(self): 2288 format_usage = self.get_parser(required=False).format_usage 2289 expected_usage = self.usage_when_not_required 2290 self.assertEqual(format_usage(), textwrap.dedent(expected_usage)) 2291 2292 def test_usage_when_required(self): 2293 format_usage = self.get_parser(required=True).format_usage 2294 expected_usage = self.usage_when_required 2295 self.assertEqual(format_usage(), textwrap.dedent(expected_usage)) 2296 2297 def test_help_when_not_required(self): 2298 format_help = self.get_parser(required=False).format_help 2299 help = self.usage_when_not_required + self.help 2300 self.assertEqual(format_help(), textwrap.dedent(help)) 2301 2302 def test_help_when_required(self): 2303 format_help = self.get_parser(required=True).format_help 2304 help = self.usage_when_required + self.help 2305 self.assertEqual(format_help(), textwrap.dedent(help)) 2306 2307 2308 class TestMutuallyExclusiveSimple(MEMixin, TestCase): 2309 2310 def get_parser(self, required=None): 2311 parser = ErrorRaisingArgumentParser(prog='PROG') 2312 group = parser.add_mutually_exclusive_group(required=required) 2313 group.add_argument('--bar', help='bar help') 2314 group.add_argument('--baz', nargs='?', const='Z', help='baz help') 2315 return parser 2316 2317 failures = ['--bar X --baz Y', '--bar X --baz'] 2318 successes = [ 2319 ('--bar X', NS(bar='X', baz=None)), 2320 ('--bar X --bar Z', NS(bar='Z', baz=None)), 2321 ('--baz Y', NS(bar=None, baz='Y')), 2322 ('--baz', NS(bar=None, baz='Z')), 2323 ] 2324 successes_when_not_required = [ 2325 ('', NS(bar=None, baz=None)), 2326 ] 2327 2328 usage_when_not_required = '''\ 2329 usage: PROG [-h] [--bar BAR | --baz [BAZ]] 2330 ''' 2331 usage_when_required = '''\ 2332 usage: PROG [-h] (--bar BAR | --baz [BAZ]) 2333 ''' 2334 help = '''\ 2335 2336 optional arguments: 2337 -h, --help show this help message and exit 2338 --bar BAR bar help 2339 --baz [BAZ] baz help 2340 ''' 2341 2342 2343 class TestMutuallyExclusiveLong(MEMixin, TestCase): 2344 2345 def get_parser(self, required=None): 2346 parser = ErrorRaisingArgumentParser(prog='PROG') 2347 parser.add_argument('--abcde', help='abcde help') 2348 parser.add_argument('--fghij', help='fghij help') 2349 group = parser.add_mutually_exclusive_group(required=required) 2350 group.add_argument('--klmno', help='klmno help') 2351 group.add_argument('--pqrst', help='pqrst help') 2352 return parser 2353 2354 failures = ['--klmno X --pqrst Y'] 2355 successes = [ 2356 ('--klmno X', NS(abcde=None, fghij=None, klmno='X', pqrst=None)), 2357 ('--abcde Y --klmno X', 2358 NS(abcde='Y', fghij=None, klmno='X', pqrst=None)), 2359 ('--pqrst X', NS(abcde=None, fghij=None, klmno=None, pqrst='X')), 2360 ('--pqrst X --fghij Y', 2361 NS(abcde=None, fghij='Y', klmno=None, pqrst='X')), 2362 ] 2363 successes_when_not_required = [ 2364 ('', NS(abcde=None, fghij=None, klmno=None, pqrst=None)), 2365 ] 2366 2367 usage_when_not_required = '''\ 2368 usage: PROG [-h] [--abcde ABCDE] [--fghij FGHIJ] 2369 [--klmno KLMNO | --pqrst PQRST] 2370 ''' 2371 usage_when_required = '''\ 2372 usage: PROG [-h] [--abcde ABCDE] [--fghij FGHIJ] 2373 (--klmno KLMNO | --pqrst PQRST) 2374 ''' 2375 help = '''\ 2376 2377 optional arguments: 2378 -h, --help show this help message and exit 2379 --abcde ABCDE abcde help 2380 --fghij FGHIJ fghij help 2381 --klmno KLMNO klmno help 2382 --pqrst PQRST pqrst help 2383 ''' 2384 2385 2386 class TestMutuallyExclusiveFirstSuppressed(MEMixin, TestCase): 2387 2388 def get_parser(self, required): 2389 parser = ErrorRaisingArgumentParser(prog='PROG') 2390 group = parser.add_mutually_exclusive_group(required=required) 2391 group.add_argument('-x', help=argparse.SUPPRESS) 2392 group.add_argument('-y', action='store_false', help='y help') 2393 return parser 2394 2395 failures = ['-x X -y'] 2396 successes = [ 2397 ('-x X', NS(x='X', y=True)), 2398 ('-x X -x Y', NS(x='Y', y=True)), 2399 ('-y', NS(x=None, y=False)), 2400 ] 2401 successes_when_not_required = [ 2402 ('', NS(x=None, y=True)), 2403 ] 2404 2405 usage_when_not_required = '''\ 2406 usage: PROG [-h] [-y] 2407 ''' 2408 usage_when_required = '''\ 2409 usage: PROG [-h] -y 2410 ''' 2411 help = '''\ 2412 2413 optional arguments: 2414 -h, --help show this help message and exit 2415 -y y help 2416 ''' 2417 2418 2419 class TestMutuallyExclusiveManySuppressed(MEMixin, TestCase): 2420 2421 def get_parser(self, required): 2422 parser = ErrorRaisingArgumentParser(prog='PROG') 2423 group = parser.add_mutually_exclusive_group(required=required) 2424 add = group.add_argument 2425 add('--spam', action='store_true', help=argparse.SUPPRESS) 2426 add('--badger', action='store_false', help=argparse.SUPPRESS) 2427 add('--bladder', help=argparse.SUPPRESS) 2428 return parser 2429 2430 failures = [ 2431 '--spam --badger', 2432 '--badger --bladder B', 2433 '--bladder B --spam', 2434 ] 2435 successes = [ 2436 ('--spam', NS(spam=True, badger=True, bladder=None)), 2437 ('--badger', NS(spam=False, badger=False, bladder=None)), 2438 ('--bladder B', NS(spam=False, badger=True, bladder='B')), 2439 ('--spam --spam', NS(spam=True, badger=True, bladder=None)), 2440 ] 2441 successes_when_not_required = [ 2442 ('', NS(spam=False, badger=True, bladder=None)), 2443 ] 2444 2445 usage_when_required = usage_when_not_required = '''\ 2446 usage: PROG [-h] 2447 ''' 2448 help = '''\ 2449 2450 optional arguments: 2451 -h, --help show this help message and exit 2452 ''' 2453 2454 2455 class TestMutuallyExclusiveOptionalAndPositional(MEMixin, TestCase): 2456 2457 def get_parser(self, required): 2458 parser = ErrorRaisingArgumentParser(prog='PROG') 2459 group = parser.add_mutually_exclusive_group(required=required) 2460 group.add_argument('--foo', action='store_true', help='FOO') 2461 group.add_argument('--spam', help='SPAM') 2462 group.add_argument('badger', nargs='*', default='X', help='BADGER') 2463 return parser 2464 2465 failures = [ 2466 '--foo --spam S', 2467 '--spam S X', 2468 'X --foo', 2469 'X Y Z --spam S', 2470 '--foo X Y', 2471 ] 2472 successes = [ 2473 ('--foo', NS(foo=True, spam=None, badger='X')), 2474 ('--spam S', NS(foo=False, spam='S', badger='X')), 2475 ('X', NS(foo=False, spam=None, badger=['X'])), 2476 ('X Y Z', NS(foo=False, spam=None, badger=['X', 'Y', 'Z'])), 2477 ] 2478 successes_when_not_required = [ 2479 ('', NS(foo=False, spam=None, badger='X')), 2480 ] 2481 2482 usage_when_not_required = '''\ 2483 usage: PROG [-h] [--foo | --spam SPAM | badger [badger ...]] 2484 ''' 2485 usage_when_required = '''\ 2486 usage: PROG [-h] (--foo | --spam SPAM | badger [badger ...]) 2487 ''' 2488 help = '''\ 2489 2490 positional arguments: 2491 badger BADGER 2492 2493 optional arguments: 2494 -h, --help show this help message and exit 2495 --foo FOO 2496 --spam SPAM SPAM 2497 ''' 2498 2499 2500 class TestMutuallyExclusiveOptionalsMixed(MEMixin, TestCase): 2501 2502 def get_parser(self, required): 2503 parser = ErrorRaisingArgumentParser(prog='PROG') 2504 parser.add_argument('-x', action='store_true', help='x help') 2505 group = parser.add_mutually_exclusive_group(required=required) 2506 group.add_argument('-a', action='store_true', help='a help') 2507 group.add_argument('-b', action='store_true', help='b help') 2508 parser.add_argument('-y', action='store_true', help='y help') 2509 group.add_argument('-c', action='store_true', help='c help') 2510 return parser 2511 2512 failures = ['-a -b', '-b -c', '-a -c', '-a -b -c'] 2513 successes = [ 2514 ('-a', NS(a=True, b=False, c=False, x=False, y=False)), 2515 ('-b', NS(a=False, b=True, c=False, x=False, y=False)), 2516 ('-c', NS(a=False, b=False, c=True, x=False, y=False)), 2517 ('-a -x', NS(a=True, b=False, c=False, x=True, y=False)), 2518 ('-y -b', NS(a=False, b=True, c=False, x=False, y=True)), 2519 ('-x -y -c', NS(a=False, b=False, c=True, x=True, y=True)), 2520 ] 2521 successes_when_not_required = [ 2522 ('', NS(a=False, b=False, c=False, x=False, y=False)), 2523 ('-x', NS(a=False, b=False, c=False, x=True, y=False)), 2524 ('-y', NS(a=False, b=False, c=False, x=False, y=True)), 2525 ] 2526 2527 usage_when_required = usage_when_not_required = '''\ 2528 usage: PROG [-h] [-x] [-a] [-b] [-y] [-c] 2529 ''' 2530 help = '''\ 2531 2532 optional arguments: 2533 -h, --help show this help message and exit 2534 -x x help 2535 -a a help 2536 -b b help 2537 -y y help 2538 -c c help 2539 ''' 2540 2541 2542 class TestMutuallyExclusiveInGroup(MEMixin, TestCase): 2543 2544 def get_parser(self, required=None): 2545 parser = ErrorRaisingArgumentParser(prog='PROG') 2546 titled_group = parser.add_argument_group( 2547 title='Titled group', description='Group description') 2548 mutex_group = \ 2549 titled_group.add_mutually_exclusive_group(required=required) 2550 mutex_group.add_argument('--bar', help='bar help') 2551 mutex_group.add_argument('--baz', help='baz help') 2552 return parser 2553 2554 failures = ['--bar X --baz Y', '--baz X --bar Y'] 2555 successes = [ 2556 ('--bar X', NS(bar='X', baz=None)), 2557 ('--baz Y', NS(bar=None, baz='Y')), 2558 ] 2559 successes_when_not_required = [ 2560 ('', NS(bar=None, baz=None)), 2561 ] 2562 2563 usage_when_not_required = '''\ 2564 usage: PROG [-h] [--bar BAR | --baz BAZ] 2565 ''' 2566 usage_when_required = '''\ 2567 usage: PROG [-h] (--bar BAR | --baz BAZ) 2568 ''' 2569 help = '''\ 2570 2571 optional arguments: 2572 -h, --help show this help message and exit 2573 2574 Titled group: 2575 Group description 2576 2577 --bar BAR bar help 2578 --baz BAZ baz help 2579 ''' 2580 2581 2582 class TestMutuallyExclusiveOptionalsAndPositionalsMixed(MEMixin, TestCase): 2583 2584 def get_parser(self, required): 2585 parser = ErrorRaisingArgumentParser(prog='PROG') 2586 parser.add_argument('x', help='x help') 2587 parser.add_argument('-y', action='store_true', help='y help') 2588 group = parser.add_mutually_exclusive_group(required=required) 2589 group.add_argument('a', nargs='?', help='a help') 2590 group.add_argument('-b', action='store_true', help='b help') 2591 group.add_argument('-c', action='store_true', help='c help') 2592 return parser 2593 2594 failures = ['X A -b', '-b -c', '-c X A'] 2595 successes = [ 2596 ('X A', NS(a='A', b=False, c=False, x='X', y=False)), 2597 ('X -b', NS(a=None, b=True, c=False, x='X', y=False)), 2598 ('X -c', NS(a=None, b=False, c=True, x='X', y=False)), 2599 ('X A -y', NS(a='A', b=False, c=False, x='X', y=True)), 2600 ('X -y -b', NS(a=None, b=True, c=False, x='X', y=True)), 2601 ] 2602 successes_when_not_required = [ 2603 ('X', NS(a=None, b=False, c=False, x='X', y=False)), 2604 ('X -y', NS(a=None, b=False, c=False, x='X', y=True)), 2605 ] 2606 2607 usage_when_required = usage_when_not_required = '''\ 2608 usage: PROG [-h] [-y] [-b] [-c] x [a] 2609 ''' 2610 help = '''\ 2611 2612 positional arguments: 2613 x x help 2614 a a help 2615 2616 optional arguments: 2617 -h, --help show this help message and exit 2618 -y y help 2619 -b b help 2620 -c c help 2621 ''' 2622 2623 # ================================================= 2624 # Mutually exclusive group in parent parser tests 2625 # ================================================= 2626 2627 class MEPBase(object): 2628 2629 def get_parser(self, required=None): 2630 parent = super(MEPBase, self).get_parser(required=required) 2631 parser = ErrorRaisingArgumentParser( 2632 prog=parent.prog, add_help=False, parents=[parent]) 2633 return parser 2634 2635 2636 class TestMutuallyExclusiveGroupErrorsParent( 2637 MEPBase, TestMutuallyExclusiveGroupErrors): 2638 pass 2639 2640 2641 class TestMutuallyExclusiveSimpleParent( 2642 MEPBase, TestMutuallyExclusiveSimple): 2643 pass 2644 2645 2646 class TestMutuallyExclusiveLongParent( 2647 MEPBase, TestMutuallyExclusiveLong): 2648 pass 2649 2650 2651 class TestMutuallyExclusiveFirstSuppressedParent( 2652 MEPBase, TestMutuallyExclusiveFirstSuppressed): 2653 pass 2654 2655 2656 class TestMutuallyExclusiveManySuppressedParent( 2657 MEPBase, TestMutuallyExclusiveManySuppressed): 2658 pass 2659 2660 2661 class TestMutuallyExclusiveOptionalAndPositionalParent( 2662 MEPBase, TestMutuallyExclusiveOptionalAndPositional): 2663 pass 2664 2665 2666 class TestMutuallyExclusiveOptionalsMixedParent( 2667 MEPBase, TestMutuallyExclusiveOptionalsMixed): 2668 pass 2669 2670 2671 class TestMutuallyExclusiveOptionalsAndPositionalsMixedParent( 2672 MEPBase, TestMutuallyExclusiveOptionalsAndPositionalsMixed): 2673 pass 2674 2675 # ================= 2676 # Set default tests 2677 # ================= 2678 2679 class TestSetDefaults(TestCase): 2680 2681 def test_set_defaults_no_args(self): 2682 parser = ErrorRaisingArgumentParser() 2683 parser.set_defaults(x='foo') 2684 parser.set_defaults(y='bar', z=1) 2685 self.assertEqual(NS(x='foo', y='bar', z=1), 2686 parser.parse_args([])) 2687 self.assertEqual(NS(x='foo', y='bar', z=1), 2688 parser.parse_args([], NS())) 2689 self.assertEqual(NS(x='baz', y='bar', z=1), 2690 parser.parse_args([], NS(x='baz'))) 2691 self.assertEqual(NS(x='baz', y='bar', z=2), 2692 parser.parse_args([], NS(x='baz', z=2))) 2693 2694 def test_set_defaults_with_args(self): 2695 parser = ErrorRaisingArgumentParser() 2696 parser.set_defaults(x='foo', y='bar') 2697 parser.add_argument('-x', default='xfoox') 2698 self.assertEqual(NS(x='xfoox', y='bar'), 2699 parser.parse_args([])) 2700 self.assertEqual(NS(x='xfoox', y='bar'), 2701 parser.parse_args([], NS())) 2702 self.assertEqual(NS(x='baz', y='bar'), 2703 parser.parse_args([], NS(x='baz'))) 2704 self.assertEqual(NS(x='1', y='bar'), 2705 parser.parse_args('-x 1'.split())) 2706 self.assertEqual(NS(x='1', y='bar'), 2707 parser.parse_args('-x 1'.split(), NS())) 2708 self.assertEqual(NS(x='1', y='bar'), 2709 parser.parse_args('-x 1'.split(), NS(x='baz'))) 2710 2711 def test_set_defaults_subparsers(self): 2712 parser = ErrorRaisingArgumentParser() 2713 parser.set_defaults(x='foo') 2714 subparsers = parser.add_subparsers() 2715 parser_a = subparsers.add_parser('a') 2716 parser_a.set_defaults(y='bar') 2717 self.assertEqual(NS(x='foo', y='bar'), 2718 parser.parse_args('a'.split())) 2719 2720 def test_set_defaults_parents(self): 2721 parent = ErrorRaisingArgumentParser(add_help=False) 2722 parent.set_defaults(x='foo') 2723 parser = ErrorRaisingArgumentParser(parents=[parent]) 2724 self.assertEqual(NS(x='foo'), parser.parse_args([])) 2725 2726 def test_set_defaults_same_as_add_argument(self): 2727 parser = ErrorRaisingArgumentParser() 2728 parser.set_defaults(w='W', x='X', y='Y', z='Z') 2729 parser.add_argument('-w') 2730 parser.add_argument('-x', default='XX') 2731 parser.add_argument('y', nargs='?') 2732 parser.add_argument('z', nargs='?', default='ZZ') 2733 2734 # defaults set previously 2735 self.assertEqual(NS(w='W', x='XX', y='Y', z='ZZ'), 2736 parser.parse_args([])) 2737 2738 # reset defaults 2739 parser.set_defaults(w='WW', x='X', y='YY', z='Z') 2740 self.assertEqual(NS(w='WW', x='X', y='YY', z='Z'), 2741 parser.parse_args([])) 2742 2743 def test_set_defaults_same_as_add_argument_group(self): 2744 parser = ErrorRaisingArgumentParser() 2745 parser.set_defaults(w='W', x='X', y='Y', z='Z') 2746 group = parser.add_argument_group('foo') 2747 group.add_argument('-w') 2748 group.add_argument('-x', default='XX') 2749 group.add_argument('y', nargs='?') 2750 group.add_argument('z', nargs='?', default='ZZ') 2751 2752 2753 # defaults set previously 2754 self.assertEqual(NS(w='W', x='XX', y='Y', z='ZZ'), 2755 parser.parse_args([])) 2756 2757 # reset defaults 2758 parser.set_defaults(w='WW', x='X', y='YY', z='Z') 2759 self.assertEqual(NS(w='WW', x='X', y='YY', z='Z'), 2760 parser.parse_args([])) 2761 2762 # ================= 2763 # Get default tests 2764 # ================= 2765 2766 class TestGetDefault(TestCase): 2767 2768 def test_get_default(self): 2769 parser = ErrorRaisingArgumentParser() 2770 self.assertEqual(None, parser.get_default("foo")) 2771 self.assertEqual(None, parser.get_default("bar")) 2772 2773 parser.add_argument("--foo") 2774 self.assertEqual(None, parser.get_default("foo")) 2775 self.assertEqual(None, parser.get_default("bar")) 2776 2777 parser.add_argument("--bar", type=int, default=42) 2778 self.assertEqual(None, parser.get_default("foo")) 2779 self.assertEqual(42, parser.get_default("bar")) 2780 2781 parser.set_defaults(foo="badger") 2782 self.assertEqual("badger", parser.get_default("foo")) 2783 self.assertEqual(42, parser.get_default("bar")) 2784 2785 # ========================== 2786 # Namespace 'contains' tests 2787 # ========================== 2788 2789 class TestNamespaceContainsSimple(TestCase): 2790 2791 def test_empty(self): 2792 ns = argparse.Namespace() 2793 self.assertEqual('' in ns, False) 2794 self.assertEqual('' not in ns, True) 2795 self.assertEqual('x' in ns, False) 2796 2797 def test_non_empty(self): 2798 ns = argparse.Namespace(x=1, y=2) 2799 self.assertEqual('x' in ns, True) 2800 self.assertEqual('x' not in ns, False) 2801 self.assertEqual('y' in ns, True) 2802 self.assertEqual('' in ns, False) 2803 self.assertEqual('xx' in ns, False) 2804 self.assertEqual('z' in ns, False) 2805 2806 # ===================== 2807 # Help formatting tests 2808 # ===================== 2809 2810 class TestHelpFormattingMetaclass(type): 2811 2812 def __init__(cls, name, bases, bodydict): 2813 if name == 'HelpTestCase': 2814 return 2815 2816 class AddTests(object): 2817 2818 def __init__(self, test_class, func_suffix, std_name): 2819 self.func_suffix = func_suffix 2820 self.std_name = std_name 2821 2822 for test_func in [self.test_format, 2823 self.test_print, 2824 self.test_print_file]: 2825 test_name = '%s_%s' % (test_func.__name__, func_suffix) 2826 2827 def test_wrapper(self, test_func=test_func): 2828 test_func(self) 2829 try: 2830 test_wrapper.__name__ = test_name 2831 except TypeError: 2832 pass 2833 setattr(test_class, test_name, test_wrapper) 2834 2835 def _get_parser(self, tester): 2836 parser = argparse.ArgumentParser( 2837 *tester.parser_signature.args, 2838 **tester.parser_signature.kwargs) 2839 for argument_sig in getattr(tester, 'argument_signatures', []): 2840 parser.add_argument(*argument_sig.args, 2841 **argument_sig.kwargs) 2842 group_sigs = getattr(tester, 'argument_group_signatures', []) 2843 for group_sig, argument_sigs in group_sigs: 2844 group = parser.add_argument_group(*group_sig.args, 2845 **group_sig.kwargs) 2846 for argument_sig in argument_sigs: 2847 group.add_argument(*argument_sig.args, 2848 **argument_sig.kwargs) 2849 subparsers_sigs = getattr(tester, 'subparsers_signatures', []) 2850 if subparsers_sigs: 2851 subparsers = parser.add_subparsers() 2852 for subparser_sig in subparsers_sigs: 2853 subparsers.add_parser(*subparser_sig.args, 2854 **subparser_sig.kwargs) 2855 return parser 2856 2857 def _test(self, tester, parser_text): 2858 expected_text = getattr(tester, self.func_suffix) 2859 expected_text = textwrap.dedent(expected_text) 2860 if expected_text != parser_text: 2861 print(repr(expected_text)) 2862 print(repr(parser_text)) 2863 for char1, char2 in zip(expected_text, parser_text): 2864 if char1 != char2: 2865 print('first diff: %r %r' % (char1, char2)) 2866 break 2867 tester.assertEqual(expected_text, parser_text) 2868 2869 def test_format(self, tester): 2870 parser = self._get_parser(tester) 2871 format = getattr(parser, 'format_%s' % self.func_suffix) 2872 self._test(tester, format()) 2873 2874 def test_print(self, tester): 2875 parser = self._get_parser(tester) 2876 print_ = getattr(parser, 'print_%s' % self.func_suffix) 2877 old_stream = getattr(sys, self.std_name) 2878 setattr(sys, self.std_name, StdIOBuffer()) 2879 try: 2880 print_() 2881 parser_text = getattr(sys, self.std_name).getvalue() 2882 finally: 2883 setattr(sys, self.std_name, old_stream) 2884 self._test(tester, parser_text) 2885 2886 def test_print_file(self, tester): 2887 parser = self._get_parser(tester) 2888 print_ = getattr(parser, 'print_%s' % self.func_suffix) 2889 sfile = StdIOBuffer() 2890 print_(sfile) 2891 parser_text = sfile.getvalue() 2892 self._test(tester, parser_text) 2893 2894 # add tests for {format,print}_{usage,help,version} 2895 for func_suffix, std_name in [('usage', 'stdout'), 2896 ('help', 'stdout'), 2897 ('version', 'stderr')]: 2898 AddTests(cls, func_suffix, std_name) 2899 2900 bases = TestCase, 2901 HelpTestCase = TestHelpFormattingMetaclass('HelpTestCase', bases, {}) 2902 2903 2904 class TestHelpBiggerOptionals(HelpTestCase): 2905 """Make sure that argument help aligns when options are longer""" 2906 2907 parser_signature = Sig(prog='PROG', description='DESCRIPTION', 2908 epilog='EPILOG', version='0.1') 2909 argument_signatures = [ 2910 Sig('-x', action='store_true', help='X HELP'), 2911 Sig('--y', help='Y HELP'), 2912 Sig('foo', help='FOO HELP'), 2913 Sig('bar', help='BAR HELP'), 2914 ] 2915 argument_group_signatures = [] 2916 usage = '''\ 2917 usage: PROG [-h] [-v] [-x] [--y Y] foo bar 2918 ''' 2919 help = usage + '''\ 2920 2921 DESCRIPTION 2922 2923 positional arguments: 2924 foo FOO HELP 2925 bar BAR HELP 2926 2927 optional arguments: 2928 -h, --help show this help message and exit 2929 -v, --version show program's version number and exit 2930 -x X HELP 2931 --y Y Y HELP 2932 2933 EPILOG 2934 ''' 2935 version = '''\ 2936 0.1 2937 ''' 2938 2939 2940 class TestHelpBiggerOptionalGroups(HelpTestCase): 2941 """Make sure that argument help aligns when options are longer""" 2942 2943 parser_signature = Sig(prog='PROG', description='DESCRIPTION', 2944 epilog='EPILOG', version='0.1') 2945 argument_signatures = [ 2946 Sig('-x', action='store_true', help='X HELP'), 2947 Sig('--y', help='Y HELP'), 2948 Sig('foo', help='FOO HELP'), 2949 Sig('bar', help='BAR HELP'), 2950 ] 2951 argument_group_signatures = [ 2952 (Sig('GROUP TITLE', description='GROUP DESCRIPTION'), [ 2953 Sig('baz', help='BAZ HELP'), 2954 Sig('-z', nargs='+', help='Z HELP')]), 2955 ] 2956 usage = '''\ 2957 usage: PROG [-h] [-v] [-x] [--y Y] [-z Z [Z ...]] foo bar baz 2958 ''' 2959 help = usage + '''\ 2960 2961 DESCRIPTION 2962 2963 positional arguments: 2964 foo FOO HELP 2965 bar BAR HELP 2966 2967 optional arguments: 2968 -h, --help show this help message and exit 2969 -v, --version show program's version number and exit 2970 -x X HELP 2971 --y Y Y HELP 2972 2973 GROUP TITLE: 2974 GROUP DESCRIPTION 2975 2976 baz BAZ HELP 2977 -z Z [Z ...] Z HELP 2978 2979 EPILOG 2980 ''' 2981 version = '''\ 2982 0.1 2983 ''' 2984 2985 2986 class TestHelpBiggerPositionals(HelpTestCase): 2987 """Make sure that help aligns when arguments are longer""" 2988 2989 parser_signature = Sig(usage='USAGE', description='DESCRIPTION') 2990 argument_signatures = [ 2991 Sig('-x', action='store_true', help='X HELP'), 2992 Sig('--y', help='Y HELP'), 2993 Sig('ekiekiekifekang', help='EKI HELP'), 2994 Sig('bar', help='BAR HELP'), 2995 ] 2996 argument_group_signatures = [] 2997 usage = '''\ 2998 usage: USAGE 2999 ''' 3000 help = usage + '''\ 3001 3002 DESCRIPTION 3003 3004 positional arguments: 3005 ekiekiekifekang EKI HELP 3006 bar BAR HELP 3007 3008 optional arguments: 3009 -h, --help show this help message and exit 3010 -x X HELP 3011 --y Y Y HELP 3012 ''' 3013 3014 version = '' 3015 3016 3017 class TestHelpReformatting(HelpTestCase): 3018 """Make sure that text after short names starts on the first line""" 3019 3020 parser_signature = Sig( 3021 prog='PROG', 3022 description=' oddly formatted\n' 3023 'description\n' 3024 '\n' 3025 'that is so long that it should go onto multiple ' 3026 'lines when wrapped') 3027 argument_signatures = [ 3028 Sig('-x', metavar='XX', help='oddly\n' 3029 ' formatted -x help'), 3030 Sig('y', metavar='yyy', help='normal y help'), 3031 ] 3032 argument_group_signatures = [ 3033 (Sig('title', description='\n' 3034 ' oddly formatted group\n' 3035 '\n' 3036 'description'), 3037 [Sig('-a', action='store_true', 3038 help=' oddly \n' 3039 'formatted -a help \n' 3040 ' again, so long that it should be wrapped over ' 3041 'multiple lines')]), 3042 ] 3043 usage = '''\ 3044 usage: PROG [-h] [-x XX] [-a] yyy 3045 ''' 3046 help = usage + '''\ 3047 3048 oddly formatted description that is so long that it should go onto \ 3049 multiple 3050 lines when wrapped 3051 3052 positional arguments: 3053 yyy normal y help 3054 3055 optional arguments: 3056 -h, --help show this help message and exit 3057 -x XX oddly formatted -x help 3058 3059 title: 3060 oddly formatted group description 3061 3062 -a oddly formatted -a help again, so long that it should \ 3063 be wrapped 3064 over multiple lines 3065 ''' 3066 version = '' 3067 3068 3069 class TestHelpWrappingShortNames(HelpTestCase): 3070 """Make sure that text after short names starts on the first line""" 3071 3072 parser_signature = Sig(prog='PROG', description= 'D\nD' * 30) 3073 argument_signatures = [ 3074 Sig('-x', metavar='XX', help='XHH HX' * 20), 3075 Sig('y', metavar='yyy', help='YH YH' * 20), 3076 ] 3077 argument_group_signatures = [ 3078 (Sig('ALPHAS'), [ 3079 Sig('-a', action='store_true', help='AHHH HHA' * 10)]), 3080 ] 3081 usage = '''\ 3082 usage: PROG [-h] [-x XX] [-a] yyy 3083 ''' 3084 help = usage + '''\ 3085 3086 D DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD \ 3087 DD DD DD 3088 DD DD DD DD D 3089 3090 positional arguments: 3091 yyy YH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH \ 3092 YHYH YHYH 3093 YHYH YHYH YHYH YHYH YHYH YHYH YHYH YH 3094 3095 optional arguments: 3096 -h, --help show this help message and exit 3097 -x XX XHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH \ 3098 HXXHH HXXHH 3099 HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HX 3100 3101 ALPHAS: 3102 -a AHHH HHAAHHH HHAAHHH HHAAHHH HHAAHHH HHAAHHH HHAAHHH \ 3103 HHAAHHH 3104 HHAAHHH HHAAHHH HHA 3105 ''' 3106 version = '' 3107 3108 3109 class TestHelpWrappingLongNames(HelpTestCase): 3110 """Make sure that text after long names starts on the next line""" 3111 3112 parser_signature = Sig(usage='USAGE', description= 'D D' * 30, 3113 version='V V'*30) 3114 argument_signatures = [ 3115 Sig('-x', metavar='X' * 25, help='XH XH' * 20), 3116 Sig('y', metavar='y' * 25, help='YH YH' * 20), 3117 ] 3118 argument_group_signatures = [ 3119 (Sig('ALPHAS'), [ 3120 Sig('-a', metavar='A' * 25, help='AH AH' * 20), 3121 Sig('z', metavar='z' * 25, help='ZH ZH' * 20)]), 3122 ] 3123 usage = '''\ 3124 usage: USAGE 3125 ''' 3126 help = usage + '''\ 3127 3128 D DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD \ 3129 DD DD DD 3130 DD DD DD DD D 3131 3132 positional arguments: 3133 yyyyyyyyyyyyyyyyyyyyyyyyy 3134 YH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH \ 3135 YHYH YHYH 3136 YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YH 3137 3138 optional arguments: 3139 -h, --help show this help message and exit 3140 -v, --version show program's version number and exit 3141 -x XXXXXXXXXXXXXXXXXXXXXXXXX 3142 XH XHXH XHXH XHXH XHXH XHXH XHXH XHXH XHXH \ 3143 XHXH XHXH 3144 XHXH XHXH XHXH XHXH XHXH XHXH XHXH XHXH XHXH XH 3145 3146 ALPHAS: 3147 -a AAAAAAAAAAAAAAAAAAAAAAAAA 3148 AH AHAH AHAH AHAH AHAH AHAH AHAH AHAH AHAH \ 3149 AHAH AHAH 3150 AHAH AHAH AHAH AHAH AHAH AHAH AHAH AHAH AHAH AH 3151 zzzzzzzzzzzzzzzzzzzzzzzzz 3152 ZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH \ 3153 ZHZH ZHZH 3154 ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZH 3155 ''' 3156 version = '''\ 3157 V VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV \ 3158 VV VV VV 3159 VV VV VV VV V 3160 ''' 3161 3162 3163 class TestHelpUsage(HelpTestCase): 3164 """Test basic usage messages""" 3165 3166 parser_signature = Sig(prog='PROG') 3167 argument_signatures = [ 3168 Sig('-w', nargs='+', help='w'), 3169 Sig('-x', nargs='*', help='x'), 3170 Sig('a', help='a'), 3171 Sig('b', help='b', nargs=2), 3172 Sig('c', help='c', nargs='?'), 3173 ] 3174 argument_group_signatures = [ 3175 (Sig('group'), [ 3176 Sig('-y', nargs='?', help='y'), 3177 Sig('-z', nargs=3, help='z'), 3178 Sig('d', help='d', nargs='*'), 3179 Sig('e', help='e', nargs='+'), 3180 ]) 3181 ] 3182 usage = '''\ 3183 usage: PROG [-h] [-w W [W ...]] [-x [X [X ...]]] [-y [Y]] [-z Z Z Z] 3184 a b b [c] [d [d ...]] e [e ...] 3185 ''' 3186 help = usage + '''\ 3187 3188 positional arguments: 3189 a a 3190 b b 3191 c c 3192 3193 optional arguments: 3194 -h, --help show this help message and exit 3195 -w W [W ...] w 3196 -x [X [X ...]] x 3197 3198 group: 3199 -y [Y] y 3200 -z Z Z Z z 3201 d d 3202 e e 3203 ''' 3204 version = '' 3205 3206 3207 class TestHelpOnlyUserGroups(HelpTestCase): 3208 """Test basic usage messages""" 3209 3210 parser_signature = Sig(prog='PROG', add_help=False) 3211 argument_signatures = [] 3212 argument_group_signatures = [ 3213 (Sig('xxxx'), [ 3214 Sig('-x', help='x'), 3215 Sig('a', help='a'), 3216 ]), 3217 (Sig('yyyy'), [ 3218 Sig('b', help='b'), 3219 Sig('-y', help='y'), 3220 ]), 3221 ] 3222 usage = '''\ 3223 usage: PROG [-x X] [-y Y] a b 3224 ''' 3225 help = usage + '''\ 3226 3227 xxxx: 3228 -x X x 3229 a a 3230 3231 yyyy: 3232 b b 3233 -y Y y 3234 ''' 3235 version = '' 3236 3237 3238 class TestHelpUsageLongProg(HelpTestCase): 3239 """Test usage messages where the prog is long""" 3240 3241 parser_signature = Sig(prog='P' * 60) 3242 argument_signatures = [ 3243 Sig('-w', metavar='W'), 3244 Sig('-x', metavar='X'), 3245 Sig('a'), 3246 Sig('b'), 3247 ] 3248 argument_group_signatures = [] 3249 usage = '''\ 3250 usage: PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP 3251 [-h] [-w W] [-x X] 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 W 3262 -x X 3263 ''' 3264 version = '' 3265 3266 3267 class TestHelpUsageLongProgOptionsWrap(HelpTestCase): 3268 """Test usage messages where the prog is long and the optionals wrap""" 3269 3270 parser_signature = Sig(prog='P' * 60) 3271 argument_signatures = [ 3272 Sig('-w', metavar='W' * 25), 3273 Sig('-x', metavar='X' * 25), 3274 Sig('-y', metavar='Y' * 25), 3275 Sig('-z', metavar='Z' * 25), 3276 Sig('a'), 3277 Sig('b'), 3278 ] 3279 argument_group_signatures = [] 3280 usage = '''\ 3281 usage: PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP 3282 [-h] [-w WWWWWWWWWWWWWWWWWWWWWWWWW] \ 3283 [-x XXXXXXXXXXXXXXXXXXXXXXXXX] 3284 [-y YYYYYYYYYYYYYYYYYYYYYYYYY] [-z ZZZZZZZZZZZZZZZZZZZZZZZZZ] 3285 a b 3286 ''' 3287 help = usage + '''\ 3288 3289 positional arguments: 3290 a 3291 b 3292 3293 optional arguments: 3294 -h, --help show this help message and exit 3295 -w WWWWWWWWWWWWWWWWWWWWWWWWW 3296 -x XXXXXXXXXXXXXXXXXXXXXXXXX 3297 -y YYYYYYYYYYYYYYYYYYYYYYYYY 3298 -z ZZZZZZZZZZZZZZZZZZZZZZZZZ 3299 ''' 3300 version = '' 3301 3302 3303 class TestHelpUsageLongProgPositionalsWrap(HelpTestCase): 3304 """Test usage messages where the prog is long and the positionals wrap""" 3305 3306 parser_signature = Sig(prog='P' * 60, add_help=False) 3307 argument_signatures = [ 3308 Sig('a' * 25), 3309 Sig('b' * 25), 3310 Sig('c' * 25), 3311 ] 3312 argument_group_signatures = [] 3313 usage = '''\ 3314 usage: PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP 3315 aaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbb 3316 ccccccccccccccccccccccccc 3317 ''' 3318 help = usage + '''\ 3319 3320 positional arguments: 3321 aaaaaaaaaaaaaaaaaaaaaaaaa 3322 bbbbbbbbbbbbbbbbbbbbbbbbb 3323 ccccccccccccccccccccccccc 3324 ''' 3325 version = '' 3326 3327 3328 class TestHelpUsageOptionalsWrap(HelpTestCase): 3329 """Test usage messages where the optionals wrap""" 3330 3331 parser_signature = Sig(prog='PROG') 3332 argument_signatures = [ 3333 Sig('-w', metavar='W' * 25), 3334 Sig('-x', metavar='X' * 25), 3335 Sig('-y', metavar='Y' * 25), 3336 Sig('-z', metavar='Z' * 25), 3337 Sig('a'), 3338 Sig('b'), 3339 Sig('c'), 3340 ] 3341 argument_group_signatures = [] 3342 usage = '''\ 3343 usage: PROG [-h] [-w WWWWWWWWWWWWWWWWWWWWWWWWW] \ 3344 [-x XXXXXXXXXXXXXXXXXXXXXXXXX] 3345 [-y YYYYYYYYYYYYYYYYYYYYYYYYY] \ 3346 [-z ZZZZZZZZZZZZZZZZZZZZZZZZZ] 3347 a b c 3348 ''' 3349 help = usage + '''\ 3350 3351 positional arguments: 3352 a 3353 b 3354 c 3355 3356 optional arguments: 3357 -h, --help show this help message and exit 3358 -w WWWWWWWWWWWWWWWWWWWWWWWWW 3359 -x XXXXXXXXXXXXXXXXXXXXXXXXX 3360 -y YYYYYYYYYYYYYYYYYYYYYYYYY 3361 -z ZZZZZZZZZZZZZZZZZZZZZZZZZ 3362 ''' 3363 version = '' 3364 3365 3366 class TestHelpUsagePositionalsWrap(HelpTestCase): 3367 """Test usage messages where the positionals wrap""" 3368 3369 parser_signature = Sig(prog='PROG') 3370 argument_signatures = [ 3371 Sig('-x'), 3372 Sig('-y'), 3373 Sig('-z'), 3374 Sig('a' * 25), 3375 Sig('b' * 25), 3376 Sig('c' * 25), 3377 ] 3378 argument_group_signatures = [] 3379 usage = '''\ 3380 usage: PROG [-h] [-x X] [-y Y] [-z Z] 3381 aaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbb 3382 ccccccccccccccccccccccccc 3383 ''' 3384 help = usage + '''\ 3385 3386 positional arguments: 3387 aaaaaaaaaaaaaaaaaaaaaaaaa 3388 bbbbbbbbbbbbbbbbbbbbbbbbb 3389 ccccccccccccccccccccccccc 3390 3391 optional arguments: 3392 -h, --help show this help message and exit 3393 -x X 3394 -y Y 3395 -z Z 3396 ''' 3397 version = '' 3398 3399 3400 class TestHelpUsageOptionalsPositionalsWrap(HelpTestCase): 3401 """Test usage messages where the optionals and positionals wrap""" 3402 3403 parser_signature = Sig(prog='PROG') 3404 argument_signatures = [ 3405 Sig('-x', metavar='X' * 25), 3406 Sig('-y', metavar='Y' * 25), 3407 Sig('-z', metavar='Z' * 25), 3408 Sig('a' * 25), 3409 Sig('b' * 25), 3410 Sig('c' * 25), 3411 ] 3412 argument_group_signatures = [] 3413 usage = '''\ 3414 usage: PROG [-h] [-x XXXXXXXXXXXXXXXXXXXXXXXXX] \ 3415 [-y YYYYYYYYYYYYYYYYYYYYYYYYY] 3416 [-z ZZZZZZZZZZZZZZZZZZZZZZZZZ] 3417 aaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbb 3418 ccccccccccccccccccccccccc 3419 ''' 3420 help = usage + '''\ 3421 3422 positional arguments: 3423 aaaaaaaaaaaaaaaaaaaaaaaaa 3424 bbbbbbbbbbbbbbbbbbbbbbbbb 3425 ccccccccccccccccccccccccc 3426 3427 optional arguments: 3428 -h, --help show this help message and exit 3429 -x XXXXXXXXXXXXXXXXXXXXXXXXX 3430 -y YYYYYYYYYYYYYYYYYYYYYYYYY 3431 -z ZZZZZZZZZZZZZZZZZZZZZZZZZ 3432 ''' 3433 version = '' 3434 3435 3436 class TestHelpUsageOptionalsOnlyWrap(HelpTestCase): 3437 """Test usage messages where there are only optionals and they wrap""" 3438 3439 parser_signature = Sig(prog='PROG') 3440 argument_signatures = [ 3441 Sig('-x', metavar='X' * 25), 3442 Sig('-y', metavar='Y' * 25), 3443 Sig('-z', metavar='Z' * 25), 3444 ] 3445 argument_group_signatures = [] 3446 usage = '''\ 3447 usage: PROG [-h] [-x XXXXXXXXXXXXXXXXXXXXXXXXX] \ 3448 [-y YYYYYYYYYYYYYYYYYYYYYYYYY] 3449 [-z ZZZZZZZZZZZZZZZZZZZZZZZZZ] 3450 ''' 3451 help = usage + '''\ 3452 3453 optional arguments: 3454 -h, --help show this help message and exit 3455 -x XXXXXXXXXXXXXXXXXXXXXXXXX 3456 -y YYYYYYYYYYYYYYYYYYYYYYYYY 3457 -z ZZZZZZZZZZZZZZZZZZZZZZZZZ 3458 ''' 3459 version = '' 3460 3461 3462 class TestHelpUsagePositionalsOnlyWrap(HelpTestCase): 3463 """Test usage messages where there are only positionals and they wrap""" 3464 3465 parser_signature = Sig(prog='PROG', add_help=False) 3466 argument_signatures = [ 3467 Sig('a' * 25), 3468 Sig('b' * 25), 3469 Sig('c' * 25), 3470 ] 3471 argument_group_signatures = [] 3472 usage = '''\ 3473 usage: PROG aaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbb 3474 ccccccccccccccccccccccccc 3475 ''' 3476 help = usage + '''\ 3477 3478 positional arguments: 3479 aaaaaaaaaaaaaaaaaaaaaaaaa 3480 bbbbbbbbbbbbbbbbbbbbbbbbb 3481 ccccccccccccccccccccccccc 3482 ''' 3483 version = '' 3484 3485 3486 class TestHelpVariableExpansion(HelpTestCase): 3487 """Test that variables are expanded properly in help messages""" 3488 3489 parser_signature = Sig(prog='PROG') 3490 argument_signatures = [ 3491 Sig('-x', type=int, 3492 help='x %(prog)s %(default)s %(type)s %%'), 3493 Sig('-y', action='store_const', default=42, const='XXX', 3494 help='y %(prog)s %(default)s %(const)s'), 3495 Sig('--foo', choices='abc', 3496 help='foo %(prog)s %(default)s %(choices)s'), 3497 Sig('--bar', default='baz', choices=[1, 2], metavar='BBB', 3498 help='bar %(prog)s %(default)s %(dest)s'), 3499 Sig('spam', help='spam %(prog)s %(default)s'), 3500 Sig('badger', default=0.5, help='badger %(prog)s %(default)s'), 3501 ] 3502 argument_group_signatures = [ 3503 (Sig('group'), [ 3504 Sig('-a', help='a %(prog)s %(default)s'), 3505 Sig('-b', default=-1, help='b %(prog)s %(default)s'), 3506 ]) 3507 ] 3508 usage = ('''\ 3509 usage: PROG [-h] [-x X] [-y] [--foo {a,b,c}] [--bar BBB] [-a A] [-b B] 3510 spam badger 3511 ''') 3512 help = usage + '''\ 3513 3514 positional arguments: 3515 spam spam PROG None 3516 badger badger PROG 0.5 3517 3518 optional arguments: 3519 -h, --help show this help message and exit 3520 -x X x PROG None int % 3521 -y y PROG 42 XXX 3522 --foo {a,b,c} foo PROG None a, b, c 3523 --bar BBB bar PROG baz bar 3524 3525 group: 3526 -a A a PROG None 3527 -b B b PROG -1 3528 ''' 3529 version = '' 3530 3531 3532 class TestHelpVariableExpansionUsageSupplied(HelpTestCase): 3533 """Test that variables are expanded properly when usage= is present""" 3534 3535 parser_signature = Sig(prog='PROG', usage='%(prog)s FOO') 3536 argument_signatures = [] 3537 argument_group_signatures = [] 3538 usage = ('''\ 3539 usage: PROG FOO 3540 ''') 3541 help = usage + '''\ 3542 3543 optional arguments: 3544 -h, --help show this help message and exit 3545 ''' 3546 version = '' 3547 3548 3549 class TestHelpVariableExpansionNoArguments(HelpTestCase): 3550 """Test that variables are expanded properly with no arguments""" 3551 3552 parser_signature = Sig(prog='PROG', add_help=False) 3553 argument_signatures = [] 3554 argument_group_signatures = [] 3555 usage = ('''\ 3556 usage: PROG 3557 ''') 3558 help = usage 3559 version = '' 3560 3561 3562 class TestHelpSuppressUsage(HelpTestCase): 3563 """Test that items can be suppressed in usage messages""" 3564 3565 parser_signature = Sig(prog='PROG', usage=argparse.SUPPRESS) 3566 argument_signatures = [ 3567 Sig('--foo', help='foo help'), 3568 Sig('spam', help='spam help'), 3569 ] 3570 argument_group_signatures = [] 3571 help = '''\ 3572 positional arguments: 3573 spam spam help 3574 3575 optional arguments: 3576 -h, --help show this help message and exit 3577 --foo FOO foo help 3578 ''' 3579 usage = '' 3580 version = '' 3581 3582 3583 class TestHelpSuppressOptional(HelpTestCase): 3584 """Test that optional arguments can be suppressed in help messages""" 3585 3586 parser_signature = Sig(prog='PROG', add_help=False) 3587 argument_signatures = [ 3588 Sig('--foo', help=argparse.SUPPRESS), 3589 Sig('spam', help='spam help'), 3590 ] 3591 argument_group_signatures = [] 3592 usage = '''\ 3593 usage: PROG spam 3594 ''' 3595 help = usage + '''\ 3596 3597 positional arguments: 3598 spam spam help 3599 ''' 3600 version = '' 3601 3602 3603 class TestHelpSuppressOptionalGroup(HelpTestCase): 3604 """Test that optional groups can be suppressed in help messages""" 3605 3606 parser_signature = Sig(prog='PROG') 3607 argument_signatures = [ 3608 Sig('--foo', help='foo help'), 3609 Sig('spam', help='spam help'), 3610 ] 3611 argument_group_signatures = [ 3612 (Sig('group'), [Sig('--bar', help=argparse.SUPPRESS)]), 3613 ] 3614 usage = '''\ 3615 usage: PROG [-h] [--foo FOO] spam 3616 ''' 3617 help = usage + '''\ 3618 3619 positional arguments: 3620 spam spam help 3621 3622 optional arguments: 3623 -h, --help show this help message and exit 3624 --foo FOO foo help 3625 ''' 3626 version = '' 3627 3628 3629 class TestHelpSuppressPositional(HelpTestCase): 3630 """Test that positional arguments can be suppressed in help messages""" 3631 3632 parser_signature = Sig(prog='PROG') 3633 argument_signatures = [ 3634 Sig('--foo', help='foo help'), 3635 Sig('spam', help=argparse.SUPPRESS), 3636 ] 3637 argument_group_signatures = [] 3638 usage = '''\ 3639 usage: PROG [-h] [--foo FOO] 3640 ''' 3641 help = usage + '''\ 3642 3643 optional arguments: 3644 -h, --help show this help message and exit 3645 --foo FOO foo help 3646 ''' 3647 version = '' 3648 3649 3650 class TestHelpRequiredOptional(HelpTestCase): 3651 """Test that required options don't look optional""" 3652 3653 parser_signature = Sig(prog='PROG') 3654 argument_signatures = [ 3655 Sig('--foo', required=True, help='foo help'), 3656 ] 3657 argument_group_signatures = [] 3658 usage = '''\ 3659 usage: PROG [-h] --foo FOO 3660 ''' 3661 help = usage + '''\ 3662 3663 optional arguments: 3664 -h, --help show this help message and exit 3665 --foo FOO foo help 3666 ''' 3667 version = '' 3668 3669 3670 class TestHelpAlternatePrefixChars(HelpTestCase): 3671 """Test that options display with different prefix characters""" 3672 3673 parser_signature = Sig(prog='PROG', prefix_chars='^;', add_help=False) 3674 argument_signatures = [ 3675 Sig('^^foo', action='store_true', help='foo help'), 3676 Sig(';b', ';;bar', help='bar help'), 3677 ] 3678 argument_group_signatures = [] 3679 usage = '''\ 3680 usage: PROG [^^foo] [;b BAR] 3681 ''' 3682 help = usage + '''\ 3683 3684 optional arguments: 3685 ^^foo foo help 3686 ;b BAR, ;;bar BAR bar help 3687 ''' 3688 version = '' 3689 3690 3691 class TestHelpNoHelpOptional(HelpTestCase): 3692 """Test that the --help argument can be suppressed help messages""" 3693 3694 parser_signature = Sig(prog='PROG', add_help=False) 3695 argument_signatures = [ 3696 Sig('--foo', help='foo help'), 3697 Sig('spam', help='spam help'), 3698 ] 3699 argument_group_signatures = [] 3700 usage = '''\ 3701 usage: PROG [--foo FOO] spam 3702 ''' 3703 help = usage + '''\ 3704 3705 positional arguments: 3706 spam spam help 3707 3708 optional arguments: 3709 --foo FOO foo help 3710 ''' 3711 version = '' 3712 3713 3714 class TestHelpVersionOptional(HelpTestCase): 3715 """Test that the --version argument can be suppressed help messages""" 3716 3717 parser_signature = Sig(prog='PROG', version='1.0') 3718 argument_signatures = [ 3719 Sig('--foo', help='foo help'), 3720 Sig('spam', help='spam help'), 3721 ] 3722 argument_group_signatures = [] 3723 usage = '''\ 3724 usage: PROG [-h] [-v] [--foo FOO] spam 3725 ''' 3726 help = usage + '''\ 3727 3728 positional arguments: 3729 spam spam help 3730 3731 optional arguments: 3732 -h, --help show this help message and exit 3733 -v, --version show program's version number and exit 3734 --foo FOO foo help 3735 ''' 3736 version = '''\ 3737 1.0 3738 ''' 3739 3740 3741 class TestHelpNone(HelpTestCase): 3742 """Test that no errors occur if no help is specified""" 3743 3744 parser_signature = Sig(prog='PROG') 3745 argument_signatures = [ 3746 Sig('--foo'), 3747 Sig('spam'), 3748 ] 3749 argument_group_signatures = [] 3750 usage = '''\ 3751 usage: PROG [-h] [--foo FOO] spam 3752 ''' 3753 help = usage + '''\ 3754 3755 positional arguments: 3756 spam 3757 3758 optional arguments: 3759 -h, --help show this help message and exit 3760 --foo FOO 3761 ''' 3762 version = '' 3763 3764 3765 class TestHelpTupleMetavar(HelpTestCase): 3766 """Test specifying metavar as a tuple""" 3767 3768 parser_signature = Sig(prog='PROG') 3769 argument_signatures = [ 3770 Sig('-w', help='w', nargs='+', metavar=('W1', 'W2')), 3771 Sig('-x', help='x', nargs='*', metavar=('X1', 'X2')), 3772 Sig('-y', help='y', nargs=3, metavar=('Y1', 'Y2', 'Y3')), 3773 Sig('-z', help='z', nargs='?', metavar=('Z1', )), 3774 ] 3775 argument_group_signatures = [] 3776 usage = '''\ 3777 usage: PROG [-h] [-w W1 [W2 ...]] [-x [X1 [X2 ...]]] [-y Y1 Y2 Y3] \ 3778 [-z [Z1]] 3779 ''' 3780 help = usage + '''\ 3781 3782 optional arguments: 3783 -h, --help show this help message and exit 3784 -w W1 [W2 ...] w 3785 -x [X1 [X2 ...]] x 3786 -y Y1 Y2 Y3 y 3787 -z [Z1] z 3788 ''' 3789 version = '' 3790 3791 3792 class TestHelpRawText(HelpTestCase): 3793 """Test the RawTextHelpFormatter""" 3794 3795 parser_signature = Sig( 3796 prog='PROG', formatter_class=argparse.RawTextHelpFormatter, 3797 description='Keep the formatting\n' 3798 ' exactly as it is written\n' 3799 '\n' 3800 'here\n') 3801 3802 argument_signatures = [ 3803 Sig('--foo', help=' foo help should also\n' 3804 'appear as given here'), 3805 Sig('spam', help='spam help'), 3806 ] 3807 argument_group_signatures = [ 3808 (Sig('title', description=' This text\n' 3809 ' should be indented\n' 3810 ' exactly like it is here\n'), 3811 [Sig('--bar', help='bar help')]), 3812 ] 3813 usage = '''\ 3814 usage: PROG [-h] [--foo FOO] [--bar BAR] spam 3815 ''' 3816 help = usage + '''\ 3817 3818 Keep the formatting 3819 exactly as it is written 3820 3821 here 3822 3823 positional arguments: 3824 spam spam help 3825 3826 optional arguments: 3827 -h, --help show this help message and exit 3828 --foo FOO foo help should also 3829 appear as given here 3830 3831 title: 3832 This text 3833 should be indented 3834 exactly like it is here 3835 3836 --bar BAR bar help 3837 ''' 3838 version = '' 3839 3840 3841 class TestHelpRawDescription(HelpTestCase): 3842 """Test the RawTextHelpFormatter""" 3843 3844 parser_signature = Sig( 3845 prog='PROG', formatter_class=argparse.RawDescriptionHelpFormatter, 3846 description='Keep the formatting\n' 3847 ' exactly as it is written\n' 3848 '\n' 3849 'here\n') 3850 3851 argument_signatures = [ 3852 Sig('--foo', help=' foo help should not\n' 3853 ' retain this odd formatting'), 3854 Sig('spam', help='spam help'), 3855 ] 3856 argument_group_signatures = [ 3857 (Sig('title', description=' This text\n' 3858 ' should be indented\n' 3859 ' exactly like it is here\n'), 3860 [Sig('--bar', help='bar help')]), 3861 ] 3862 usage = '''\ 3863 usage: PROG [-h] [--foo FOO] [--bar BAR] spam 3864 ''' 3865 help = usage + '''\ 3866 3867 Keep the formatting 3868 exactly as it is written 3869 3870 here 3871 3872 positional arguments: 3873 spam spam help 3874 3875 optional arguments: 3876 -h, --help show this help message and exit 3877 --foo FOO foo help should not retain this odd formatting 3878 3879 title: 3880 This text 3881 should be indented 3882 exactly like it is here 3883 3884 --bar BAR bar help 3885 ''' 3886 version = '' 3887 3888 3889 class TestHelpArgumentDefaults(HelpTestCase): 3890 """Test the ArgumentDefaultsHelpFormatter""" 3891 3892 parser_signature = Sig( 3893 prog='PROG', formatter_class=argparse.ArgumentDefaultsHelpFormatter, 3894 description='description') 3895 3896 argument_signatures = [ 3897 Sig('--foo', help='foo help - oh and by the way, %(default)s'), 3898 Sig('--bar', action='store_true', help='bar help'), 3899 Sig('spam', help='spam help'), 3900 Sig('badger', nargs='?', default='wooden', help='badger help'), 3901 ] 3902 argument_group_signatures = [ 3903 (Sig('title', description='description'), 3904 [Sig('--baz', type=int, default=42, help='baz help')]), 3905 ] 3906 usage = '''\ 3907 usage: PROG [-h] [--foo FOO] [--bar] [--baz BAZ] spam [badger] 3908 ''' 3909 help = usage + '''\ 3910 3911 description 3912 3913 positional arguments: 3914 spam spam help 3915 badger badger help (default: wooden) 3916 3917 optional arguments: 3918 -h, --help show this help message and exit 3919 --foo FOO foo help - oh and by the way, None 3920 --bar bar help (default: False) 3921 3922 title: 3923 description 3924 3925 --baz BAZ baz help (default: 42) 3926 ''' 3927 version = '' 3928 3929 class TestHelpVersionAction(HelpTestCase): 3930 """Test the default help for the version action""" 3931 3932 parser_signature = Sig(prog='PROG', description='description') 3933 argument_signatures = [Sig('-V', '--version', action='version', version='3.6')] 3934 argument_group_signatures = [] 3935 usage = '''\ 3936 usage: PROG [-h] [-V] 3937 ''' 3938 help = usage + '''\ 3939 3940 description 3941 3942 optional arguments: 3943 -h, --help show this help message and exit 3944 -V, --version show program's version number and exit 3945 ''' 3946 version = '' 3947 3948 class TestHelpSubparsersOrdering(HelpTestCase): 3949 """Test ordering of subcommands in help matches the code""" 3950 parser_signature = Sig(prog='PROG', 3951 description='display some subcommands', 3952 version='0.1') 3953 3954 subparsers_signatures = [Sig(name=name) 3955 for name in ('a', 'b', 'c', 'd', 'e')] 3956 3957 usage = '''\ 3958 usage: PROG [-h] [-v] {a,b,c,d,e} ... 3959 ''' 3960 3961 help = usage + '''\ 3962 3963 display some subcommands 3964 3965 positional arguments: 3966 {a,b,c,d,e} 3967 3968 optional arguments: 3969 -h, --help show this help message and exit 3970 -v, --version show program's version number and exit 3971 ''' 3972 3973 version = '''\ 3974 0.1 3975 ''' 3976 3977 class TestHelpSubparsersWithHelpOrdering(HelpTestCase): 3978 """Test ordering of subcommands in help matches the code""" 3979 parser_signature = Sig(prog='PROG', 3980 description='display some subcommands', 3981 version='0.1') 3982 3983 subcommand_data = (('a', 'a subcommand help'), 3984 ('b', 'b subcommand help'), 3985 ('c', 'c subcommand help'), 3986 ('d', 'd subcommand help'), 3987 ('e', 'e subcommand help'), 3988 ) 3989 3990 subparsers_signatures = [Sig(name=name, help=help) 3991 for name, help in subcommand_data] 3992 3993 usage = '''\ 3994 usage: PROG [-h] [-v] {a,b,c,d,e} ... 3995 ''' 3996 3997 help = usage + '''\ 3998 3999 display some subcommands 4000 4001 positional arguments: 4002 {a,b,c,d,e} 4003 a a subcommand help 4004 b b subcommand help 4005 c c subcommand help 4006 d d subcommand help 4007 e e subcommand help 4008 4009 optional arguments: 4010 -h, --help show this help message and exit 4011 -v, --version show program's version number and exit 4012 ''' 4013 4014 version = '''\ 4015 0.1 4016 ''' 4017 4018 4019 # ===================================== 4020 # Optional/Positional constructor tests 4021 # ===================================== 4022 4023 class TestInvalidArgumentConstructors(TestCase): 4024 """Test a bunch of invalid Argument constructors""" 4025 4026 def assertTypeError(self, *args, **kwargs): 4027 parser = argparse.ArgumentParser() 4028 self.assertRaises(TypeError, parser.add_argument, 4029 *args, **kwargs) 4030 4031 def assertValueError(self, *args, **kwargs): 4032 parser = argparse.ArgumentParser() 4033 self.assertRaises(ValueError, parser.add_argument, 4034 *args, **kwargs) 4035 4036 def test_invalid_keyword_arguments(self): 4037 self.assertTypeError('-x', bar=None) 4038 self.assertTypeError('-y', callback='foo') 4039 self.assertTypeError('-y', callback_args=()) 4040 self.assertTypeError('-y', callback_kwargs={}) 4041 4042 def test_missing_destination(self): 4043 self.assertTypeError() 4044 for action in ['append', 'store']: 4045 self.assertTypeError(action=action) 4046 4047 def test_invalid_option_strings(self): 4048 self.assertValueError('--') 4049 self.assertValueError('---') 4050 4051 def test_invalid_type(self): 4052 self.assertValueError('--foo', type='int') 4053 self.assertValueError('--foo', type=(int, float)) 4054 4055 def test_invalid_action(self): 4056 self.assertValueError('-x', action='foo') 4057 self.assertValueError('foo', action='baz') 4058 self.assertValueError('--foo', action=('store', 'append')) 4059 parser = argparse.ArgumentParser() 4060 try: 4061 parser.add_argument("--foo", action="store-true") 4062 except ValueError: 4063 e = sys.exc_info()[1] 4064 expected = 'unknown action' 4065 msg = 'expected %r, found %r' % (expected, e) 4066 self.assertTrue(expected in str(e), msg) 4067 4068 def test_multiple_dest(self): 4069 parser = argparse.ArgumentParser() 4070 parser.add_argument(dest='foo') 4071 try: 4072 parser.add_argument('bar', dest='baz') 4073 except ValueError: 4074 e = sys.exc_info()[1] 4075 expected = 'dest supplied twice for positional argument' 4076 msg = 'expected %r, found %r' % (expected, e) 4077 self.assertTrue(expected in str(e), msg) 4078 4079 def test_no_argument_actions(self): 4080 for action in ['store_const', 'store_true', 'store_false', 4081 'append_const', 'count']: 4082 for attrs in [dict(type=int), dict(nargs='+'), 4083 dict(choices='ab')]: 4084 self.assertTypeError('-x', action=action, **attrs) 4085 4086 def test_no_argument_no_const_actions(self): 4087 # options with zero arguments 4088 for action in ['store_true', 'store_false', 'count']: 4089 4090 # const is always disallowed 4091 self.assertTypeError('-x', const='foo', action=action) 4092 4093 # nargs is always disallowed 4094 self.assertTypeError('-x', nargs='*', action=action) 4095 4096 def test_more_than_one_argument_actions(self): 4097 for action in ['store', 'append']: 4098 4099 # nargs=0 is disallowed 4100 self.assertValueError('-x', nargs=0, action=action) 4101 self.assertValueError('spam', nargs=0, action=action) 4102 4103 # const is disallowed with non-optional arguments 4104 for nargs in [1, '*', '+']: 4105 self.assertValueError('-x', const='foo', 4106 nargs=nargs, action=action) 4107 self.assertValueError('spam', const='foo', 4108 nargs=nargs, action=action) 4109 4110 def test_required_const_actions(self): 4111 for action in ['store_const', 'append_const']: 4112 4113 # nargs is always disallowed 4114 self.assertTypeError('-x', nargs='+', action=action) 4115 4116 def test_parsers_action_missing_params(self): 4117 self.assertTypeError('command', action='parsers') 4118 self.assertTypeError('command', action='parsers', prog='PROG') 4119 self.assertTypeError('command', action='parsers', 4120 parser_class=argparse.ArgumentParser) 4121 4122 def test_required_positional(self): 4123 self.assertTypeError('foo', required=True) 4124 4125 def test_user_defined_action(self): 4126 4127 class Success(Exception): 4128 pass 4129 4130 class Action(object): 4131 4132 def __init__(self, 4133 option_strings, 4134 dest, 4135 const, 4136 default, 4137 required=False): 4138 if dest == 'spam': 4139 if const is Success: 4140 if default is Success: 4141 raise Success() 4142 4143 def __call__(self, *args, **kwargs): 4144 pass 4145 4146 parser = argparse.ArgumentParser() 4147 self.assertRaises(Success, parser.add_argument, '--spam', 4148 action=Action, default=Success, const=Success) 4149 self.assertRaises(Success, parser.add_argument, 'spam', 4150 action=Action, default=Success, const=Success) 4151 4152 # ================================ 4153 # Actions returned by add_argument 4154 # ================================ 4155 4156 class TestActionsReturned(TestCase): 4157 4158 def test_dest(self): 4159 parser = argparse.ArgumentParser() 4160 action = parser.add_argument('--foo') 4161 self.assertEqual(action.dest, 'foo') 4162 action = parser.add_argument('-b', '--bar') 4163 self.assertEqual(action.dest, 'bar') 4164 action = parser.add_argument('-x', '-y') 4165 self.assertEqual(action.dest, 'x') 4166 4167 def test_misc(self): 4168 parser = argparse.ArgumentParser() 4169 action = parser.add_argument('--foo', nargs='?', const=42, 4170 default=84, type=int, choices=[1, 2], 4171 help='FOO', metavar='BAR', dest='baz') 4172 self.assertEqual(action.nargs, '?') 4173 self.assertEqual(action.const, 42) 4174 self.assertEqual(action.default, 84) 4175 self.assertEqual(action.type, int) 4176 self.assertEqual(action.choices, [1, 2]) 4177 self.assertEqual(action.help, 'FOO') 4178 self.assertEqual(action.metavar, 'BAR') 4179 self.assertEqual(action.dest, 'baz') 4180 4181 4182 # ================================ 4183 # Argument conflict handling tests 4184 # ================================ 4185 4186 class TestConflictHandling(TestCase): 4187 4188 def test_bad_type(self): 4189 self.assertRaises(ValueError, argparse.ArgumentParser, 4190 conflict_handler='foo') 4191 4192 def test_conflict_error(self): 4193 parser = argparse.ArgumentParser() 4194 parser.add_argument('-x') 4195 self.assertRaises(argparse.ArgumentError, 4196 parser.add_argument, '-x') 4197 parser.add_argument('--spam') 4198 self.assertRaises(argparse.ArgumentError, 4199 parser.add_argument, '--spam') 4200 4201 def test_resolve_error(self): 4202 get_parser = argparse.ArgumentParser 4203 parser = get_parser(prog='PROG', conflict_handler='resolve') 4204 4205 parser.add_argument('-x', help='OLD X') 4206 parser.add_argument('-x', help='NEW X') 4207 self.assertEqual(parser.format_help(), textwrap.dedent('''\ 4208 usage: PROG [-h] [-x X] 4209 4210 optional arguments: 4211 -h, --help show this help message and exit 4212 -x X NEW X 4213 ''')) 4214 4215 parser.add_argument('--spam', metavar='OLD_SPAM') 4216 parser.add_argument('--spam', metavar='NEW_SPAM') 4217 self.assertEqual(parser.format_help(), textwrap.dedent('''\ 4218 usage: PROG [-h] [-x X] [--spam NEW_SPAM] 4219 4220 optional arguments: 4221 -h, --help show this help message and exit 4222 -x X NEW X 4223 --spam NEW_SPAM 4224 ''')) 4225 4226 4227 # ============================= 4228 # Help and Version option tests 4229 # ============================= 4230 4231 class TestOptionalsHelpVersionActions(TestCase): 4232 """Test the help and version actions""" 4233 4234 def _get_error(self, func, *args, **kwargs): 4235 try: 4236 func(*args, **kwargs) 4237 except ArgumentParserError: 4238 return sys.exc_info()[1] 4239 else: 4240 self.assertRaises(ArgumentParserError, func, *args, **kwargs) 4241 4242 def assertPrintHelpExit(self, parser, args_str): 4243 self.assertEqual( 4244 parser.format_help(), 4245 self._get_error(parser.parse_args, args_str.split()).stdout) 4246 4247 def assertPrintVersionExit(self, parser, args_str): 4248 self.assertEqual( 4249 parser.format_version(), 4250 self._get_error(parser.parse_args, args_str.split()).stderr) 4251 4252 def assertArgumentParserError(self, parser, *args): 4253 self.assertRaises(ArgumentParserError, parser.parse_args, args) 4254 4255 def test_version(self): 4256 parser = ErrorRaisingArgumentParser(version='1.0') 4257 self.assertPrintHelpExit(parser, '-h') 4258 self.assertPrintHelpExit(parser, '--help') 4259 self.assertPrintVersionExit(parser, '-v') 4260 self.assertPrintVersionExit(parser, '--version') 4261 4262 def test_version_format(self): 4263 parser = ErrorRaisingArgumentParser(prog='PPP', version='%(prog)s 3.5') 4264 msg = self._get_error(parser.parse_args, ['-v']).stderr 4265 self.assertEqual('PPP 3.5\n', msg) 4266 4267 def test_version_no_help(self): 4268 parser = ErrorRaisingArgumentParser(add_help=False, version='1.0') 4269 self.assertArgumentParserError(parser, '-h') 4270 self.assertArgumentParserError(parser, '--help') 4271 self.assertPrintVersionExit(parser, '-v') 4272 self.assertPrintVersionExit(parser, '--version') 4273 4274 def test_version_action(self): 4275 parser = ErrorRaisingArgumentParser(prog='XXX') 4276 parser.add_argument('-V', action='version', version='%(prog)s 3.7') 4277 msg = self._get_error(parser.parse_args, ['-V']).stderr 4278 self.assertEqual('XXX 3.7\n', msg) 4279 4280 def test_no_help(self): 4281 parser = ErrorRaisingArgumentParser(add_help=False) 4282 self.assertArgumentParserError(parser, '-h') 4283 self.assertArgumentParserError(parser, '--help') 4284 self.assertArgumentParserError(parser, '-v') 4285 self.assertArgumentParserError(parser, '--version') 4286 4287 def test_alternate_help_version(self): 4288 parser = ErrorRaisingArgumentParser() 4289 parser.add_argument('-x', action='help') 4290 parser.add_argument('-y', action='version') 4291 self.assertPrintHelpExit(parser, '-x') 4292 self.assertPrintVersionExit(parser, '-y') 4293 self.assertArgumentParserError(parser, '-v') 4294 self.assertArgumentParserError(parser, '--version') 4295 4296 def test_help_version_extra_arguments(self): 4297 parser = ErrorRaisingArgumentParser(version='1.0') 4298 parser.add_argument('-x', action='store_true') 4299 parser.add_argument('y') 4300 4301 # try all combinations of valid prefixes and suffixes 4302 valid_prefixes = ['', '-x', 'foo', '-x bar', 'baz -x'] 4303 valid_suffixes = valid_prefixes + ['--bad-option', 'foo bar baz'] 4304 for prefix in valid_prefixes: 4305 for suffix in valid_suffixes: 4306 format = '%s %%s %s' % (prefix, suffix) 4307 self.assertPrintHelpExit(parser, format % '-h') 4308 self.assertPrintHelpExit(parser, format % '--help') 4309 self.assertPrintVersionExit(parser, format % '-v') 4310 self.assertPrintVersionExit(parser, format % '--version') 4311 4312 4313 # ====================== 4314 # str() and repr() tests 4315 # ====================== 4316 4317 class TestStrings(TestCase): 4318 """Test str() and repr() on Optionals and Positionals""" 4319 4320 def assertStringEqual(self, obj, result_string): 4321 for func in [str, repr]: 4322 self.assertEqual(func(obj), result_string) 4323 4324 def test_optional(self): 4325 option = argparse.Action( 4326 option_strings=['--foo', '-a', '-b'], 4327 dest='b', 4328 type='int', 4329 nargs='+', 4330 default=42, 4331 choices=[1, 2, 3], 4332 help='HELP', 4333 metavar='METAVAR') 4334 string = ( 4335 "Action(option_strings=['--foo', '-a', '-b'], dest='b', " 4336 "nargs='+', const=None, default=42, type='int', " 4337 "choices=[1, 2, 3], help='HELP', metavar='METAVAR')") 4338 self.assertStringEqual(option, string) 4339 4340 def test_argument(self): 4341 argument = argparse.Action( 4342 option_strings=[], 4343 dest='x', 4344 type=float, 4345 nargs='?', 4346 default=2.5, 4347 choices=[0.5, 1.5, 2.5], 4348 help='H HH H', 4349 metavar='MV MV MV') 4350 string = ( 4351 "Action(option_strings=[], dest='x', nargs='?', " 4352 "const=None, default=2.5, type=%r, choices=[0.5, 1.5, 2.5], " 4353 "help='H HH H', metavar='MV MV MV')" % float) 4354 self.assertStringEqual(argument, string) 4355 4356 def test_namespace(self): 4357 ns = argparse.Namespace(foo=42, bar='spam') 4358 string = "Namespace(bar='spam', foo=42)" 4359 self.assertStringEqual(ns, string) 4360 4361 def test_parser(self): 4362 parser = argparse.ArgumentParser(prog='PROG') 4363 string = ( 4364 "ArgumentParser(prog='PROG', usage=None, description=None, " 4365 "version=None, formatter_class=%r, conflict_handler='error', " 4366 "add_help=True)" % argparse.HelpFormatter) 4367 self.assertStringEqual(parser, string) 4368 4369 # =============== 4370 # Namespace tests 4371 # =============== 4372 4373 class TestNamespace(TestCase): 4374 4375 def test_constructor(self): 4376 ns = argparse.Namespace() 4377 self.assertRaises(AttributeError, getattr, ns, 'x') 4378 4379 ns = argparse.Namespace(a=42, b='spam') 4380 self.assertEqual(ns.a, 42) 4381 self.assertEqual(ns.b, 'spam') 4382 4383 def test_equality(self): 4384 ns1 = argparse.Namespace(a=1, b=2) 4385 ns2 = argparse.Namespace(b=2, a=1) 4386 ns3 = argparse.Namespace(a=1) 4387 ns4 = argparse.Namespace(b=2) 4388 4389 self.assertEqual(ns1, ns2) 4390 self.assertNotEqual(ns1, ns3) 4391 self.assertNotEqual(ns1, ns4) 4392 self.assertNotEqual(ns2, ns3) 4393 self.assertNotEqual(ns2, ns4) 4394 self.assertTrue(ns1 != ns3) 4395 self.assertTrue(ns1 != ns4) 4396 self.assertTrue(ns2 != ns3) 4397 self.assertTrue(ns2 != ns4) 4398 4399 4400 # =================== 4401 # File encoding tests 4402 # =================== 4403 4404 class TestEncoding(TestCase): 4405 4406 def _test_module_encoding(self, path): 4407 path, _ = os.path.splitext(path) 4408 path += ".py" 4409 with codecs.open(path, 'r', 'utf8') as f: 4410 f.read() 4411 4412 def test_argparse_module_encoding(self): 4413 self._test_module_encoding(argparse.__file__) 4414 4415 def test_test_argparse_module_encoding(self): 4416 self._test_module_encoding(__file__) 4417 4418 # =================== 4419 # ArgumentError tests 4420 # =================== 4421 4422 class TestArgumentError(TestCase): 4423 4424 def test_argument_error(self): 4425 msg = "my error here" 4426 error = argparse.ArgumentError(None, msg) 4427 self.assertEqual(str(error), msg) 4428 4429 # ======================= 4430 # ArgumentTypeError tests 4431 # ======================= 4432 4433 class TestArgumentTypeError(TestCase): 4434 4435 def test_argument_type_error(self): 4436 4437 def spam(string): 4438 raise argparse.ArgumentTypeError('spam!') 4439 4440 parser = ErrorRaisingArgumentParser(prog='PROG', add_help=False) 4441 parser.add_argument('x', type=spam) 4442 try: 4443 parser.parse_args(['XXX']) 4444 except ArgumentParserError: 4445 expected = 'usage: PROG x\nPROG: error: argument x: spam!\n' 4446 msg = sys.exc_info()[1].stderr 4447 self.assertEqual(expected, msg) 4448 else: 4449 self.fail() 4450 4451 # ================================================ 4452 # Check that the type function is called only once 4453 # ================================================ 4454 4455 class TestTypeFunctionCallOnlyOnce(TestCase): 4456 4457 def test_type_function_call_only_once(self): 4458 def spam(string_to_convert): 4459 self.assertEqual(string_to_convert, 'spam!') 4460 return 'foo_converted' 4461 4462 parser = argparse.ArgumentParser() 4463 parser.add_argument('--foo', type=spam, default='bar') 4464 args = parser.parse_args('--foo spam!'.split()) 4465 self.assertEqual(NS(foo='foo_converted'), args) 4466 4467 # ================================================================== 4468 # Check semantics regarding the default argument and type conversion 4469 # ================================================================== 4470 4471 class TestTypeFunctionCalledOnDefault(TestCase): 4472 4473 def test_type_function_call_with_non_string_default(self): 4474 def spam(int_to_convert): 4475 self.assertEqual(int_to_convert, 0) 4476 return 'foo_converted' 4477 4478 parser = argparse.ArgumentParser() 4479 parser.add_argument('--foo', type=spam, default=0) 4480 args = parser.parse_args([]) 4481 # foo should *not* be converted because its default is not a string. 4482 self.assertEqual(NS(foo=0), args) 4483 4484 def test_type_function_call_with_string_default(self): 4485 def spam(int_to_convert): 4486 return 'foo_converted' 4487 4488 parser = argparse.ArgumentParser() 4489 parser.add_argument('--foo', type=spam, default='0') 4490 args = parser.parse_args([]) 4491 # foo is converted because its default is a string. 4492 self.assertEqual(NS(foo='foo_converted'), args) 4493 4494 def test_no_double_type_conversion_of_default(self): 4495 def extend(str_to_convert): 4496 return str_to_convert + '*' 4497 4498 parser = argparse.ArgumentParser() 4499 parser.add_argument('--test', type=extend, default='*') 4500 args = parser.parse_args([]) 4501 # The test argument will be two stars, one coming from the default 4502 # value and one coming from the type conversion being called exactly 4503 # once. 4504 self.assertEqual(NS(test='**'), args) 4505 4506 def test_issue_15906(self): 4507 # Issue #15906: When action='append', type=str, default=[] are 4508 # providing, the dest value was the string representation "[]" when it 4509 # should have been an empty list. 4510 parser = argparse.ArgumentParser() 4511 parser.add_argument('--test', dest='test', type=str, 4512 default=[], action='append') 4513 args = parser.parse_args([]) 4514 self.assertEqual(args.test, []) 4515 4516 # ====================== 4517 # parse_known_args tests 4518 # ====================== 4519 4520 class TestParseKnownArgs(TestCase): 4521 4522 def test_arguments_tuple(self): 4523 parser = argparse.ArgumentParser() 4524 parser.parse_args(()) 4525 4526 def test_arguments_list(self): 4527 parser = argparse.ArgumentParser() 4528 parser.parse_args([]) 4529 4530 def test_arguments_tuple_positional(self): 4531 parser = argparse.ArgumentParser() 4532 parser.add_argument('x') 4533 parser.parse_args(('x',)) 4534 4535 def test_arguments_list_positional(self): 4536 parser = argparse.ArgumentParser() 4537 parser.add_argument('x') 4538 parser.parse_args(['x']) 4539 4540 def test_optionals(self): 4541 parser = argparse.ArgumentParser() 4542 parser.add_argument('--foo') 4543 args, extras = parser.parse_known_args('--foo F --bar --baz'.split()) 4544 self.assertEqual(NS(foo='F'), args) 4545 self.assertEqual(['--bar', '--baz'], extras) 4546 4547 def test_mixed(self): 4548 parser = argparse.ArgumentParser() 4549 parser.add_argument('-v', nargs='?', const=1, type=int) 4550 parser.add_argument('--spam', action='store_false') 4551 parser.add_argument('badger') 4552 4553 argv = ["B", "C", "--foo", "-v", "3", "4"] 4554 args, extras = parser.parse_known_args(argv) 4555 self.assertEqual(NS(v=3, spam=True, badger="B"), args) 4556 self.assertEqual(["C", "--foo", "4"], extras) 4557 4558 # ========================== 4559 # add_argument metavar tests 4560 # ========================== 4561 4562 class TestAddArgumentMetavar(TestCase): 4563 4564 EXPECTED_MESSAGE = "length of metavar tuple does not match nargs" 4565 4566 def do_test_no_exception(self, nargs, metavar): 4567 parser = argparse.ArgumentParser() 4568 parser.add_argument("--foo", nargs=nargs, metavar=metavar) 4569 4570 def do_test_exception(self, nargs, metavar): 4571 parser = argparse.ArgumentParser() 4572 with self.assertRaises(ValueError) as cm: 4573 parser.add_argument("--foo", nargs=nargs, metavar=metavar) 4574 self.assertEqual(cm.exception.args[0], self.EXPECTED_MESSAGE) 4575 4576 # Unit tests for different values of metavar when nargs=None 4577 4578 def test_nargs_None_metavar_string(self): 4579 self.do_test_no_exception(nargs=None, metavar="1") 4580 4581 def test_nargs_None_metavar_length0(self): 4582 self.do_test_exception(nargs=None, metavar=tuple()) 4583 4584 def test_nargs_None_metavar_length1(self): 4585 self.do_test_no_exception(nargs=None, metavar=("1")) 4586 4587 def test_nargs_None_metavar_length2(self): 4588 self.do_test_exception(nargs=None, metavar=("1", "2")) 4589 4590 def test_nargs_None_metavar_length3(self): 4591 self.do_test_exception(nargs=None, metavar=("1", "2", "3")) 4592 4593 # Unit tests for different values of metavar when nargs=? 4594 4595 def test_nargs_optional_metavar_string(self): 4596 self.do_test_no_exception(nargs="?", metavar="1") 4597 4598 def test_nargs_optional_metavar_length0(self): 4599 self.do_test_exception(nargs="?", metavar=tuple()) 4600 4601 def test_nargs_optional_metavar_length1(self): 4602 self.do_test_no_exception(nargs="?", metavar=("1")) 4603 4604 def test_nargs_optional_metavar_length2(self): 4605 self.do_test_exception(nargs="?", metavar=("1", "2")) 4606 4607 def test_nargs_optional_metavar_length3(self): 4608 self.do_test_exception(nargs="?", metavar=("1", "2", "3")) 4609 4610 # Unit tests for different values of metavar when nargs=* 4611 4612 def test_nargs_zeroormore_metavar_string(self): 4613 self.do_test_no_exception(nargs="*", metavar="1") 4614 4615 def test_nargs_zeroormore_metavar_length0(self): 4616 self.do_test_exception(nargs="*", metavar=tuple()) 4617 4618 def test_nargs_zeroormore_metavar_length1(self): 4619 self.do_test_no_exception(nargs="*", metavar=("1")) 4620 4621 def test_nargs_zeroormore_metavar_length2(self): 4622 self.do_test_no_exception(nargs="*", metavar=("1", "2")) 4623 4624 def test_nargs_zeroormore_metavar_length3(self): 4625 self.do_test_exception(nargs="*", metavar=("1", "2", "3")) 4626 4627 # Unit tests for different values of metavar when nargs=+ 4628 4629 def test_nargs_oneormore_metavar_string(self): 4630 self.do_test_no_exception(nargs="+", metavar="1") 4631 4632 def test_nargs_oneormore_metavar_length0(self): 4633 self.do_test_exception(nargs="+", metavar=tuple()) 4634 4635 def test_nargs_oneormore_metavar_length1(self): 4636 self.do_test_no_exception(nargs="+", metavar=("1")) 4637 4638 def test_nargs_oneormore_metavar_length2(self): 4639 self.do_test_no_exception(nargs="+", metavar=("1", "2")) 4640 4641 def test_nargs_oneormore_metavar_length3(self): 4642 self.do_test_exception(nargs="+", metavar=("1", "2", "3")) 4643 4644 # Unit tests for different values of metavar when nargs=... 4645 4646 def test_nargs_remainder_metavar_string(self): 4647 self.do_test_no_exception(nargs="...", metavar="1") 4648 4649 def test_nargs_remainder_metavar_length0(self): 4650 self.do_test_no_exception(nargs="...", metavar=tuple()) 4651 4652 def test_nargs_remainder_metavar_length1(self): 4653 self.do_test_no_exception(nargs="...", metavar=("1")) 4654 4655 def test_nargs_remainder_metavar_length2(self): 4656 self.do_test_no_exception(nargs="...", metavar=("1", "2")) 4657 4658 def test_nargs_remainder_metavar_length3(self): 4659 self.do_test_no_exception(nargs="...", metavar=("1", "2", "3")) 4660 4661 # Unit tests for different values of metavar when nargs=A... 4662 4663 def test_nargs_parser_metavar_string(self): 4664 self.do_test_no_exception(nargs="A...", metavar="1") 4665 4666 def test_nargs_parser_metavar_length0(self): 4667 self.do_test_exception(nargs="A...", metavar=tuple()) 4668 4669 def test_nargs_parser_metavar_length1(self): 4670 self.do_test_no_exception(nargs="A...", metavar=("1")) 4671 4672 def test_nargs_parser_metavar_length2(self): 4673 self.do_test_exception(nargs="A...", metavar=("1", "2")) 4674 4675 def test_nargs_parser_metavar_length3(self): 4676 self.do_test_exception(nargs="A...", metavar=("1", "2", "3")) 4677 4678 # Unit tests for different values of metavar when nargs=1 4679 4680 def test_nargs_1_metavar_string(self): 4681 self.do_test_no_exception(nargs=1, metavar="1") 4682 4683 def test_nargs_1_metavar_length0(self): 4684 self.do_test_exception(nargs=1, metavar=tuple()) 4685 4686 def test_nargs_1_metavar_length1(self): 4687 self.do_test_no_exception(nargs=1, metavar=("1")) 4688 4689 def test_nargs_1_metavar_length2(self): 4690 self.do_test_exception(nargs=1, metavar=("1", "2")) 4691 4692 def test_nargs_1_metavar_length3(self): 4693 self.do_test_exception(nargs=1, metavar=("1", "2", "3")) 4694 4695 # Unit tests for different values of metavar when nargs=2 4696 4697 def test_nargs_2_metavar_string(self): 4698 self.do_test_no_exception(nargs=2, metavar="1") 4699 4700 def test_nargs_2_metavar_length0(self): 4701 self.do_test_exception(nargs=2, metavar=tuple()) 4702 4703 def test_nargs_2_metavar_length1(self): 4704 self.do_test_no_exception(nargs=2, metavar=("1")) 4705 4706 def test_nargs_2_metavar_length2(self): 4707 self.do_test_no_exception(nargs=2, metavar=("1", "2")) 4708 4709 def test_nargs_2_metavar_length3(self): 4710 self.do_test_exception(nargs=2, metavar=("1", "2", "3")) 4711 4712 # Unit tests for different values of metavar when nargs=3 4713 4714 def test_nargs_3_metavar_string(self): 4715 self.do_test_no_exception(nargs=3, metavar="1") 4716 4717 def test_nargs_3_metavar_length0(self): 4718 self.do_test_exception(nargs=3, metavar=tuple()) 4719 4720 def test_nargs_3_metavar_length1(self): 4721 self.do_test_no_exception(nargs=3, metavar=("1")) 4722 4723 def test_nargs_3_metavar_length2(self): 4724 self.do_test_exception(nargs=3, metavar=("1", "2")) 4725 4726 def test_nargs_3_metavar_length3(self): 4727 self.do_test_no_exception(nargs=3, metavar=("1", "2", "3")) 4728 4729 # ============================ 4730 # from argparse import * tests 4731 # ============================ 4732 4733 class TestImportStar(TestCase): 4734 4735 def test(self): 4736 for name in argparse.__all__: 4737 self.assertTrue(hasattr(argparse, name)) 4738 4739 def test_all_exports_everything_but_modules(self): 4740 items = [ 4741 name 4742 for name, value in vars(argparse).items() 4743 if not name.startswith("_") 4744 if not inspect.ismodule(value) 4745 ] 4746 self.assertEqual(sorted(items), sorted(argparse.__all__)) 4747 4748 def test_main(): 4749 # silence warnings about version argument - these are expected 4750 with test_support.check_warnings( 4751 ('The "version" argument to ArgumentParser is deprecated.', 4752 DeprecationWarning), 4753 ('The (format|print)_version method is deprecated', 4754 DeprecationWarning)): 4755 test_support.run_unittest(__name__) 4756 # Remove global references to avoid looking like we have refleaks. 4757 RFile.seen = {} 4758 WFile.seen = set() 4759 4760 4761 4762 if __name__ == '__main__': 4763 test_main() 4764