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