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