diff options
Diffstat (limited to 'test/test_argparse.py')
-rw-r--r-- | test/test_argparse.py | 4206 |
1 files changed, 0 insertions, 4206 deletions
diff --git a/test/test_argparse.py b/test/test_argparse.py deleted file mode 100644 index 4392e42..0000000 --- a/test/test_argparse.py +++ /dev/null @@ -1,4206 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright © 2006-2009 Steven J. Bethard <steven.bethard@gmail.com>. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may not -# use this file except in compliance with the License. You may obtain a copy -# of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import codecs -import os -import shutil -import sys -import textwrap -import tempfile -import unittest -import argparse - -try: - from StringIO import StringIO -except ImportError: - from io import StringIO - -try: - set -except NameError: - from sets import Set as set - -try: - sorted -except NameError: - - def sorted(iterable, reverse=False): - result = list(iterable) - result.sort() - if reverse: - result.reverse() - return result - -# silence Python 2.6 buggy warnings about Exception.message -if sys.version_info[:2] == (2, 6): - import warnings - warnings.filterwarnings( - action='ignore', - message='BaseException.message has been deprecated as of Python 2.6', - category=DeprecationWarning) - -# silence warnings about version argument - these are expected -import warnings -warnings.filterwarnings( - action='ignore', - message='The "version" argument to ArgumentParser is deprecated.', - category=DeprecationWarning) -warnings.filterwarnings( - action='ignore', - message='The format_version method is deprecated', - category=DeprecationWarning) -warnings.filterwarnings( - action='ignore', - message='The print_version method is deprecated', - category=DeprecationWarning) - - -class TestCase(unittest.TestCase): - - def assertEqual(self, obj1, obj2): - if obj1 != obj2: - print('') - print(repr(obj1)) - print(repr(obj2)) - print(obj1) - print(obj2) - super(TestCase, self).assertEqual(obj1, obj2) - - -class TempDirMixin(object): - - def setUp(self): - self.temp_dir = tempfile.mkdtemp() - self.old_dir = os.getcwd() - os.chdir(self.temp_dir) - - def tearDown(self): - os.chdir(self.old_dir) - while True: - try: - shutil.rmtree(self.temp_dir) - except WindowsError: - continue - else: - break - - -class Sig(object): - - def __init__(self, *args, **kwargs): - self.args = args - self.kwargs = kwargs - - -class NS(object): - - def __init__(self, **kwargs): - self.__dict__.update(kwargs) - - def __repr__(self): - sorted_items = sorted(self.__dict__.items()) - kwarg_str = ', '.join(['%s=%r' % tup for tup in sorted_items]) - return '%s(%s)' % (type(self).__name__, kwarg_str) - - def __eq__(self, other): - return vars(self) == vars(other) - - def __ne__(self, other): - return not (self == other) - - -class ArgumentParserError(Exception): - - def __init__(self, message, stdout=None, stderr=None, error_code=None): - Exception.__init__(self, message, stdout, stderr) - self.message = message - self.stdout = stdout - self.stderr = stderr - self.error_code = error_code - - -def stderr_to_parser_error(parse_args, *args, **kwargs): - # if this is being called recursively and stderr or stdout is already being - # redirected, simply call the function and let the enclosing function - # catch the exception - if isinstance(sys.stderr, StringIO) or isinstance(sys.stdout, StringIO): - return parse_args(*args, **kwargs) - - # if this is not being called recursively, redirect stderr and - # use it as the ArgumentParserError message - old_stdout = sys.stdout - old_stderr = sys.stderr - sys.stdout = StringIO() - sys.stderr = StringIO() - try: - try: - result = parse_args(*args, **kwargs) - for key in list(vars(result)): - if getattr(result, key) is sys.stdout: - setattr(result, key, old_stdout) - if getattr(result, key) is sys.stderr: - setattr(result, key, old_stderr) - return result - except SystemExit: - code = sys.exc_info()[1].code - stdout = sys.stdout.getvalue() - stderr = sys.stderr.getvalue() - raise ArgumentParserError("SystemExit", stdout, stderr, code) - finally: - sys.stdout = old_stdout - sys.stderr = old_stderr - - -class ErrorRaisingArgumentParser(argparse.ArgumentParser): - - def parse_args(self, *args, **kwargs): - parse_args = super(ErrorRaisingArgumentParser, self).parse_args - return stderr_to_parser_error(parse_args, *args, **kwargs) - - def exit(self, *args, **kwargs): - exit = super(ErrorRaisingArgumentParser, self).exit - return stderr_to_parser_error(exit, *args, **kwargs) - - def error(self, *args, **kwargs): - error = super(ErrorRaisingArgumentParser, self).error - return stderr_to_parser_error(error, *args, **kwargs) - - -class ParserTesterMetaclass(type): - """Adds parser tests using the class attributes. - - Classes of this type should specify the following attributes: - - argument_signatures -- a list of Sig objects which specify - the signatures of Argument objects to be created - failures -- a list of args lists that should cause the parser - to fail - successes -- a list of (initial_args, options, remaining_args) tuples - where initial_args specifies the string args to be parsed, - options is a dict that should match the vars() of the options - parsed out of initial_args, and remaining_args should be any - remaining unparsed arguments - """ - - def __init__(cls, name, bases, bodydict): - if name == 'ParserTestCase': - return - - # default parser signature is empty - if not hasattr(cls, 'parser_signature'): - cls.parser_signature = Sig() - if not hasattr(cls, 'parser_class'): - cls.parser_class = ErrorRaisingArgumentParser - - # --------------------------------------- - # functions for adding optional arguments - # --------------------------------------- - def no_groups(parser, argument_signatures): - """Add all arguments directly to the parser""" - for sig in argument_signatures: - parser.add_argument(*sig.args, **sig.kwargs) - - def one_group(parser, argument_signatures): - """Add all arguments under a single group in the parser""" - group = parser.add_argument_group('foo') - for sig in argument_signatures: - group.add_argument(*sig.args, **sig.kwargs) - - def many_groups(parser, argument_signatures): - """Add each argument in its own group to the parser""" - for i, sig in enumerate(argument_signatures): - group = parser.add_argument_group('foo:%i' % i) - group.add_argument(*sig.args, **sig.kwargs) - - # -------------------------- - # functions for parsing args - # -------------------------- - def listargs(parser, args): - """Parse the args by passing in a list""" - return parser.parse_args(args) - - def sysargs(parser, args): - """Parse the args by defaulting to sys.argv""" - old_sys_argv = sys.argv - sys.argv = [old_sys_argv[0]] + args - try: - return parser.parse_args() - finally: - sys.argv = old_sys_argv - - # class that holds the combination of one optional argument - # addition method and one arg parsing method - class AddTests(object): - - def __init__(self, tester_cls, add_arguments, parse_args): - self._add_arguments = add_arguments - self._parse_args = parse_args - - add_arguments_name = self._add_arguments.__name__ - parse_args_name = self._parse_args.__name__ - for test_func in [self.test_failures, self.test_successes]: - func_name = test_func.__name__ - names = func_name, add_arguments_name, parse_args_name - test_name = '_'.join(names) - - def wrapper(self, test_func=test_func): - test_func(self) - try: - wrapper.__name__ = test_name - except TypeError: - pass - setattr(tester_cls, test_name, wrapper) - - def _get_parser(self, tester): - args = tester.parser_signature.args - kwargs = tester.parser_signature.kwargs - parser = tester.parser_class(*args, **kwargs) - self._add_arguments(parser, tester.argument_signatures) - return parser - - def test_failures(self, tester): - parser = self._get_parser(tester) - for args_str in tester.failures: - args = args_str.split() - raises = tester.assertRaises - raises(ArgumentParserError, parser.parse_args, args) - - def test_successes(self, tester): - parser = self._get_parser(tester) - for args, expected_ns in tester.successes: - if isinstance(args, str): - args = args.split() - result_ns = self._parse_args(parser, args) - tester.assertEqual(expected_ns, result_ns) - - # add tests for each combination of an optionals adding method - # and an arg parsing method - for add_arguments in [no_groups, one_group, many_groups]: - for parse_args in [listargs, sysargs]: - AddTests(cls, add_arguments, parse_args) - -bases = TestCase, -ParserTestCase = ParserTesterMetaclass('ParserTestCase', bases, {}) - -# =============== -# Optionals tests -# =============== - -class TestOptionalsSingleDash(ParserTestCase): - """Test an Optional with a single-dash option string""" - - argument_signatures = [Sig('-x')] - failures = ['-x', 'a', '--foo', '-x --foo', '-x -y'] - successes = [ - ('', NS(x=None)), - ('-x a', NS(x='a')), - ('-xa', NS(x='a')), - ('-x -1', NS(x='-1')), - ('-x-1', NS(x='-1')), - ] - - -class TestOptionalsSingleDashCombined(ParserTestCase): - """Test an Optional with a single-dash option string""" - - argument_signatures = [ - Sig('-x', action='store_true'), - Sig('-yyy', action='store_const', const=42), - Sig('-z'), - ] - failures = ['a', '--foo', '-xa', '-x --foo', '-x -z', '-z -x', - '-yx', '-yz a', '-yyyx', '-yyyza', '-xyza'] - successes = [ - ('', NS(x=False, yyy=None, z=None)), - ('-x', NS(x=True, yyy=None, z=None)), - ('-za', NS(x=False, yyy=None, z='a')), - ('-z a', NS(x=False, yyy=None, z='a')), - ('-xza', NS(x=True, yyy=None, z='a')), - ('-xz a', NS(x=True, yyy=None, z='a')), - ('-x -za', NS(x=True, yyy=None, z='a')), - ('-x -z a', NS(x=True, yyy=None, z='a')), - ('-y', NS(x=False, yyy=42, z=None)), - ('-yyy', NS(x=False, yyy=42, z=None)), - ('-x -yyy -za', NS(x=True, yyy=42, z='a')), - ('-x -yyy -z a', NS(x=True, yyy=42, z='a')), - ] - - -class TestOptionalsSingleDashLong(ParserTestCase): - """Test an Optional with a multi-character single-dash option string""" - - argument_signatures = [Sig('-foo')] - failures = ['-foo', 'a', '--foo', '-foo --foo', '-foo -y', '-fooa'] - successes = [ - ('', NS(foo=None)), - ('-foo a', NS(foo='a')), - ('-foo -1', NS(foo='-1')), - ('-fo a', NS(foo='a')), - ('-f a', NS(foo='a')), - ] - - -class TestOptionalsSingleDashSubsetAmbiguous(ParserTestCase): - """Test Optionals where option strings are subsets of each other""" - - argument_signatures = [Sig('-f'), Sig('-foobar'), Sig('-foorab')] - failures = ['-f', '-foo', '-fo', '-foo b', '-foob', '-fooba', '-foora'] - successes = [ - ('', NS(f=None, foobar=None, foorab=None)), - ('-f a', NS(f='a', foobar=None, foorab=None)), - ('-fa', NS(f='a', foobar=None, foorab=None)), - ('-foa', NS(f='oa', foobar=None, foorab=None)), - ('-fooa', NS(f='ooa', foobar=None, foorab=None)), - ('-foobar a', NS(f=None, foobar='a', foorab=None)), - ('-foorab a', NS(f=None, foobar=None, foorab='a')), - ] - - -class TestOptionalsSingleDashAmbiguous(ParserTestCase): - """Test Optionals that partially match but are not subsets""" - - argument_signatures = [Sig('-foobar'), Sig('-foorab')] - failures = ['-f', '-f a', '-fa', '-foa', '-foo', '-fo', '-foo b'] - successes = [ - ('', NS(foobar=None, foorab=None)), - ('-foob a', NS(foobar='a', foorab=None)), - ('-foor a', NS(foobar=None, foorab='a')), - ('-fooba a', NS(foobar='a', foorab=None)), - ('-foora a', NS(foobar=None, foorab='a')), - ('-foobar a', NS(foobar='a', foorab=None)), - ('-foorab a', NS(foobar=None, foorab='a')), - ] - - -class TestOptionalsNumeric(ParserTestCase): - """Test an Optional with a short opt string""" - - argument_signatures = [Sig('-1', dest='one')] - failures = ['-1', 'a', '-1 --foo', '-1 -y', '-1 -1', '-1 -2'] - successes = [ - ('', NS(one=None)), - ('-1 a', NS(one='a')), - ('-1a', NS(one='a')), - ('-1-2', NS(one='-2')), - ] - - -class TestOptionalsDoubleDash(ParserTestCase): - """Test an Optional with a double-dash option string""" - - argument_signatures = [Sig('--foo')] - failures = ['--foo', '-f', '-f a', 'a', '--foo -x', '--foo --bar'] - successes = [ - ('', NS(foo=None)), - ('--foo a', NS(foo='a')), - ('--foo=a', NS(foo='a')), - ('--foo -2.5', NS(foo='-2.5')), - ('--foo=-2.5', NS(foo='-2.5')), - ] - - -class TestOptionalsDoubleDashPartialMatch(ParserTestCase): - """Tests partial matching with a double-dash option string""" - - argument_signatures = [ - Sig('--badger', action='store_true'), - Sig('--bat'), - ] - failures = ['--bar', '--b', '--ba', '--b=2', '--ba=4', '--badge 5'] - successes = [ - ('', NS(badger=False, bat=None)), - ('--bat X', NS(badger=False, bat='X')), - ('--bad', NS(badger=True, bat=None)), - ('--badg', NS(badger=True, bat=None)), - ('--badge', NS(badger=True, bat=None)), - ('--badger', NS(badger=True, bat=None)), - ] - - -class TestOptionalsDoubleDashPrefixMatch(ParserTestCase): - """Tests when one double-dash option string is a prefix of another""" - - argument_signatures = [ - Sig('--badger', action='store_true'), - Sig('--ba'), - ] - failures = ['--bar', '--b', '--ba', '--b=2', '--badge 5'] - successes = [ - ('', NS(badger=False, ba=None)), - ('--ba X', NS(badger=False, ba='X')), - ('--ba=X', NS(badger=False, ba='X')), - ('--bad', NS(badger=True, ba=None)), - ('--badg', NS(badger=True, ba=None)), - ('--badge', NS(badger=True, ba=None)), - ('--badger', NS(badger=True, ba=None)), - ] - - -class TestOptionalsSingleDoubleDash(ParserTestCase): - """Test an Optional with single- and double-dash option strings""" - - argument_signatures = [ - Sig('-f', action='store_true'), - Sig('--bar'), - Sig('-baz', action='store_const', const=42), - ] - failures = ['--bar', '-fbar', '-fbaz', '-bazf', '-b B', 'B'] - successes = [ - ('', NS(f=False, bar=None, baz=None)), - ('-f', NS(f=True, bar=None, baz=None)), - ('--ba B', NS(f=False, bar='B', baz=None)), - ('-f --bar B', NS(f=True, bar='B', baz=None)), - ('-f -b', NS(f=True, bar=None, baz=42)), - ('-ba -f', NS(f=True, bar=None, baz=42)), - ] - - -class TestOptionalsAlternatePrefixChars(ParserTestCase): - """Test an Optional with a double-dash option string""" - - parser_signature = Sig(prefix_chars='+:/', add_help=False) - argument_signatures = [ - Sig('+f', action='store_true'), - Sig('::bar'), - Sig('/baz', action='store_const', const=42), - ] - failures = ['--bar', '-fbar', '-b B', 'B', '-f', '--bar B', '-baz'] - successes = [ - ('', NS(f=False, bar=None, baz=None)), - ('+f', NS(f=True, bar=None, baz=None)), - ('::ba B', NS(f=False, bar='B', baz=None)), - ('+f ::bar B', NS(f=True, bar='B', baz=None)), - ('+f /b', NS(f=True, bar=None, baz=42)), - ('/ba +f', NS(f=True, bar=None, baz=42)), - ] - - -class TestOptionalsShortLong(ParserTestCase): - """Test a combination of single- and double-dash option strings""" - - argument_signatures = [ - Sig('-v', '--verbose', '-n', '--noisy', action='store_true'), - ] - failures = ['--x --verbose', '-N', 'a', '-v x'] - successes = [ - ('', NS(verbose=False)), - ('-v', NS(verbose=True)), - ('--verbose', NS(verbose=True)), - ('-n', NS(verbose=True)), - ('--noisy', NS(verbose=True)), - ] - - -class TestOptionalsDest(ParserTestCase): - """Tests various means of setting destination""" - - argument_signatures = [Sig('--foo-bar'), Sig('--baz', dest='zabbaz')] - failures = ['a'] - successes = [ - ('--foo-bar f', NS(foo_bar='f', zabbaz=None)), - ('--baz g', NS(foo_bar=None, zabbaz='g')), - ('--foo-bar h --baz i', NS(foo_bar='h', zabbaz='i')), - ('--baz j --foo-bar k', NS(foo_bar='k', zabbaz='j')), - ] - - -class TestOptionalsDefault(ParserTestCase): - """Tests specifying a default for an Optional""" - - argument_signatures = [Sig('-x'), Sig('-y', default=42)] - failures = ['a'] - successes = [ - ('', NS(x=None, y=42)), - ('-xx', NS(x='x', y=42)), - ('-yy', NS(x=None, y='y')), - ] - - -class TestOptionalsNargsDefault(ParserTestCase): - """Tests not specifying the number of args for an Optional""" - - argument_signatures = [Sig('-x')] - failures = ['a', '-x'] - successes = [ - ('', NS(x=None)), - ('-x a', NS(x='a')), - ] - - -class TestOptionalsNargs1(ParserTestCase): - """Tests specifying the 1 arg for an Optional""" - - argument_signatures = [Sig('-x', nargs=1)] - failures = ['a', '-x'] - successes = [ - ('', NS(x=None)), - ('-x a', NS(x=['a'])), - ] - - -class TestOptionalsNargs3(ParserTestCase): - """Tests specifying the 3 args for an Optional""" - - argument_signatures = [Sig('-x', nargs=3)] - failures = ['a', '-x', '-x a', '-x a b', 'a -x', 'a -x b'] - successes = [ - ('', NS(x=None)), - ('-x a b c', NS(x=['a', 'b', 'c'])), - ] - - -class TestOptionalsNargsOptional(ParserTestCase): - """Tests specifying an Optional arg for an Optional""" - - argument_signatures = [ - Sig('-w', nargs='?'), - Sig('-x', nargs='?', const=42), - Sig('-y', nargs='?', default='spam'), - Sig('-z', nargs='?', type=int, const='42', default='84'), - ] - failures = ['2'] - successes = [ - ('', NS(w=None, x=None, y='spam', z=84)), - ('-w', NS(w=None, x=None, y='spam', z=84)), - ('-w 2', NS(w='2', x=None, y='spam', z=84)), - ('-x', NS(w=None, x=42, y='spam', z=84)), - ('-x 2', NS(w=None, x='2', y='spam', z=84)), - ('-y', NS(w=None, x=None, y=None, z=84)), - ('-y 2', NS(w=None, x=None, y='2', z=84)), - ('-z', NS(w=None, x=None, y='spam', z=42)), - ('-z 2', NS(w=None, x=None, y='spam', z=2)), - ] - - -class TestOptionalsNargsZeroOrMore(ParserTestCase): - """Tests specifying an args for an Optional that accepts zero or more""" - - argument_signatures = [ - Sig('-x', nargs='*'), - Sig('-y', nargs='*', default='spam'), - ] - failures = ['a'] - successes = [ - ('', NS(x=None, y='spam')), - ('-x', NS(x=[], y='spam')), - ('-x a', NS(x=['a'], y='spam')), - ('-x a b', NS(x=['a', 'b'], y='spam')), - ('-y', NS(x=None, y=[])), - ('-y a', NS(x=None, y=['a'])), - ('-y a b', NS(x=None, y=['a', 'b'])), - ] - - -class TestOptionalsNargsOneOrMore(ParserTestCase): - """Tests specifying an args for an Optional that accepts one or more""" - - argument_signatures = [ - Sig('-x', nargs='+'), - Sig('-y', nargs='+', default='spam'), - ] - failures = ['a', '-x', '-y', 'a -x', 'a -y b'] - successes = [ - ('', NS(x=None, y='spam')), - ('-x a', NS(x=['a'], y='spam')), - ('-x a b', NS(x=['a', 'b'], y='spam')), - ('-y a', NS(x=None, y=['a'])), - ('-y a b', NS(x=None, y=['a', 'b'])), - ] - - -class TestOptionalsChoices(ParserTestCase): - """Tests specifying the choices for an Optional""" - - argument_signatures = [ - Sig('-f', choices='abc'), - Sig('-g', type=int, choices=range(5))] - failures = ['a', '-f d', '-fad', '-ga', '-g 6'] - successes = [ - ('', NS(f=None, g=None)), - ('-f a', NS(f='a', g=None)), - ('-f c', NS(f='c', g=None)), - ('-g 0', NS(f=None, g=0)), - ('-g 03', NS(f=None, g=3)), - ('-fb -g4', NS(f='b', g=4)), - ] - - -class TestOptionalsRequired(ParserTestCase): - """Tests the an optional action that is required""" - - argument_signatures = [ - Sig('-x', type=int, required=True), - ] - failures = ['a', ''] - successes = [ - ('-x 1', NS(x=1)), - ('-x42', NS(x=42)), - ] - - -class TestOptionalsActionStore(ParserTestCase): - """Tests the store action for an Optional""" - - argument_signatures = [Sig('-x', action='store')] - failures = ['a', 'a -x'] - successes = [ - ('', NS(x=None)), - ('-xfoo', NS(x='foo')), - ] - - -class TestOptionalsActionStoreConst(ParserTestCase): - """Tests the store_const action for an Optional""" - - argument_signatures = [Sig('-y', action='store_const', const=object)] - failures = ['a'] - successes = [ - ('', NS(y=None)), - ('-y', NS(y=object)), - ] - - -class TestOptionalsActionStoreFalse(ParserTestCase): - """Tests the store_false action for an Optional""" - - argument_signatures = [Sig('-z', action='store_false')] - failures = ['a', '-za', '-z a'] - successes = [ - ('', NS(z=True)), - ('-z', NS(z=False)), - ] - - -class TestOptionalsActionStoreTrue(ParserTestCase): - """Tests the store_true action for an Optional""" - - argument_signatures = [Sig('--apple', action='store_true')] - failures = ['a', '--apple=b', '--apple b'] - successes = [ - ('', NS(apple=False)), - ('--apple', NS(apple=True)), - ] - - -class TestOptionalsActionAppend(ParserTestCase): - """Tests the append action for an Optional""" - - argument_signatures = [Sig('--baz', action='append')] - failures = ['a', '--baz', 'a --baz', '--baz a b'] - successes = [ - ('', NS(baz=None)), - ('--baz a', NS(baz=['a'])), - ('--baz a --baz b', NS(baz=['a', 'b'])), - ] - - -class TestOptionalsActionAppendWithDefault(ParserTestCase): - """Tests the append action for an Optional""" - - argument_signatures = [Sig('--baz', action='append', default=['X'])] - failures = ['a', '--baz', 'a --baz', '--baz a b'] - successes = [ - ('', NS(baz=['X'])), - ('--baz a', NS(baz=['X', 'a'])), - ('--baz a --baz b', NS(baz=['X', 'a', 'b'])), - ] - - -class TestOptionalsActionAppendConst(ParserTestCase): - """Tests the append_const action for an Optional""" - - argument_signatures = [ - Sig('-b', action='append_const', const=Exception), - Sig('-c', action='append', dest='b'), - ] - failures = ['a', '-c', 'a -c', '-bx', '-b x'] - successes = [ - ('', NS(b=None)), - ('-b', NS(b=[Exception])), - ('-b -cx -b -cyz', NS(b=[Exception, 'x', Exception, 'yz'])), - ] - - -class TestOptionalsActionAppendConstWithDefault(ParserTestCase): - """Tests the append_const action for an Optional""" - - argument_signatures = [ - Sig('-b', action='append_const', const=Exception, default=['X']), - Sig('-c', action='append', dest='b'), - ] - failures = ['a', '-c', 'a -c', '-bx', '-b x'] - successes = [ - ('', NS(b=['X'])), - ('-b', NS(b=['X', Exception])), - ('-b -cx -b -cyz', NS(b=['X', Exception, 'x', Exception, 'yz'])), - ] - - -class TestOptionalsActionCount(ParserTestCase): - """Tests the count action for an Optional""" - - argument_signatures = [Sig('-x', action='count')] - failures = ['a', '-x a', '-x b', '-x a -x b'] - successes = [ - ('', NS(x=None)), - ('-x', NS(x=1)), - ] - - -# ================ -# Positional tests -# ================ - -class TestPositionalsNargsNone(ParserTestCase): - """Test a Positional that doesn't specify nargs""" - - argument_signatures = [Sig('foo')] - failures = ['', '-x', 'a b'] - successes = [ - ('a', NS(foo='a')), - ] - - -class TestPositionalsNargs1(ParserTestCase): - """Test a Positional that specifies an nargs of 1""" - - argument_signatures = [Sig('foo', nargs=1)] - failures = ['', '-x', 'a b'] - successes = [ - ('a', NS(foo=['a'])), - ] - - -class TestPositionalsNargs2(ParserTestCase): - """Test a Positional that specifies an nargs of 2""" - - argument_signatures = [Sig('foo', nargs=2)] - failures = ['', 'a', '-x', 'a b c'] - successes = [ - ('a b', NS(foo=['a', 'b'])), - ] - - -class TestPositionalsNargsZeroOrMore(ParserTestCase): - """Test a Positional that specifies unlimited nargs""" - - argument_signatures = [Sig('foo', nargs='*')] - failures = ['-x'] - successes = [ - ('', NS(foo=[])), - ('a', NS(foo=['a'])), - ('a b', NS(foo=['a', 'b'])), - ] - - -class TestPositionalsNargsZeroOrMoreDefault(ParserTestCase): - """Test a Positional that specifies unlimited nargs and a default""" - - argument_signatures = [Sig('foo', nargs='*', default='bar')] - failures = ['-x'] - successes = [ - ('', NS(foo='bar')), - ('a', NS(foo=['a'])), - ('a b', NS(foo=['a', 'b'])), - ] - - -class TestPositionalsNargsOneOrMore(ParserTestCase): - """Test a Positional that specifies one or more nargs""" - - argument_signatures = [Sig('foo', nargs='+')] - failures = ['', '-x'] - successes = [ - ('a', NS(foo=['a'])), - ('a b', NS(foo=['a', 'b'])), - ] - - -class TestPositionalsNargsOptional(ParserTestCase): - """Tests an Optional Positional""" - - argument_signatures = [Sig('foo', nargs='?')] - failures = ['-x', 'a b'] - successes = [ - ('', NS(foo=None)), - ('a', NS(foo='a')), - ] - - -class TestPositionalsNargsOptionalDefault(ParserTestCase): - """Tests an Optional Positional with a default value""" - - argument_signatures = [Sig('foo', nargs='?', default=42)] - failures = ['-x', 'a b'] - successes = [ - ('', NS(foo=42)), - ('a', NS(foo='a')), - ] - - -class TestPositionalsNargsOptionalConvertedDefault(ParserTestCase): - """Tests an Optional Positional with a default value - that needs to be converted to the appropriate type. - """ - - argument_signatures = [ - Sig('foo', nargs='?', type=int, default='42'), - ] - failures = ['-x', 'a b', '1 2'] - successes = [ - ('', NS(foo=42)), - ('1', NS(foo=1)), - ] - - -class TestPositionalsNargsNoneNone(ParserTestCase): - """Test two Positionals that don't specify nargs""" - - argument_signatures = [Sig('foo'), Sig('bar')] - failures = ['', '-x', 'a', 'a b c'] - successes = [ - ('a b', NS(foo='a', bar='b')), - ] - - -class TestPositionalsNargsNone1(ParserTestCase): - """Test a Positional with no nargs followed by one with 1""" - - argument_signatures = [Sig('foo'), Sig('bar', nargs=1)] - failures = ['', '--foo', 'a', 'a b c'] - successes = [ - ('a b', NS(foo='a', bar=['b'])), - ] - - -class TestPositionalsNargs2None(ParserTestCase): - """Test a Positional with 2 nargs followed by one with none""" - - argument_signatures = [Sig('foo', nargs=2), Sig('bar')] - failures = ['', '--foo', 'a', 'a b', 'a b c d'] - successes = [ - ('a b c', NS(foo=['a', 'b'], bar='c')), - ] - - -class TestPositionalsNargsNoneZeroOrMore(ParserTestCase): - """Test a Positional with no nargs followed by one with unlimited""" - - argument_signatures = [Sig('foo'), Sig('bar', nargs='*')] - failures = ['', '--foo'] - successes = [ - ('a', NS(foo='a', bar=[])), - ('a b', NS(foo='a', bar=['b'])), - ('a b c', NS(foo='a', bar=['b', 'c'])), - ] - - -class TestPositionalsNargsNoneOneOrMore(ParserTestCase): - """Test a Positional with no nargs followed by one with one or more""" - - argument_signatures = [Sig('foo'), Sig('bar', nargs='+')] - failures = ['', '--foo', 'a'] - successes = [ - ('a b', NS(foo='a', bar=['b'])), - ('a b c', NS(foo='a', bar=['b', 'c'])), - ] - - -class TestPositionalsNargsNoneOptional(ParserTestCase): - """Test a Positional with no nargs followed by one with an Optional""" - - argument_signatures = [Sig('foo'), Sig('bar', nargs='?')] - failures = ['', '--foo', 'a b c'] - successes = [ - ('a', NS(foo='a', bar=None)), - ('a b', NS(foo='a', bar='b')), - ] - - -class TestPositionalsNargsZeroOrMoreNone(ParserTestCase): - """Test a Positional with unlimited nargs followed by one with none""" - - argument_signatures = [Sig('foo', nargs='*'), Sig('bar')] - failures = ['', '--foo'] - successes = [ - ('a', NS(foo=[], bar='a')), - ('a b', NS(foo=['a'], bar='b')), - ('a b c', NS(foo=['a', 'b'], bar='c')), - ] - - -class TestPositionalsNargsOneOrMoreNone(ParserTestCase): - """Test a Positional with one or more nargs followed by one with none""" - - argument_signatures = [Sig('foo', nargs='+'), Sig('bar')] - failures = ['', '--foo', 'a'] - successes = [ - ('a b', NS(foo=['a'], bar='b')), - ('a b c', NS(foo=['a', 'b'], bar='c')), - ] - - -class TestPositionalsNargsOptionalNone(ParserTestCase): - """Test a Positional with an Optional nargs followed by one with none""" - - argument_signatures = [Sig('foo', nargs='?', default=42), Sig('bar')] - failures = ['', '--foo', 'a b c'] - successes = [ - ('a', NS(foo=42, bar='a')), - ('a b', NS(foo='a', bar='b')), - ] - - -class TestPositionalsNargs2ZeroOrMore(ParserTestCase): - """Test a Positional with 2 nargs followed by one with unlimited""" - - argument_signatures = [Sig('foo', nargs=2), Sig('bar', nargs='*')] - failures = ['', '--foo', 'a'] - successes = [ - ('a b', NS(foo=['a', 'b'], bar=[])), - ('a b c', NS(foo=['a', 'b'], bar=['c'])), - ] - - -class TestPositionalsNargs2OneOrMore(ParserTestCase): - """Test a Positional with 2 nargs followed by one with one or more""" - - argument_signatures = [Sig('foo', nargs=2), Sig('bar', nargs='+')] - failures = ['', '--foo', 'a', 'a b'] - successes = [ - ('a b c', NS(foo=['a', 'b'], bar=['c'])), - ] - - -class TestPositionalsNargs2Optional(ParserTestCase): - """Test a Positional with 2 nargs followed by one optional""" - - argument_signatures = [Sig('foo', nargs=2), Sig('bar', nargs='?')] - failures = ['', '--foo', 'a', 'a b c d'] - successes = [ - ('a b', NS(foo=['a', 'b'], bar=None)), - ('a b c', NS(foo=['a', 'b'], bar='c')), - ] - - -class TestPositionalsNargsZeroOrMore1(ParserTestCase): - """Test a Positional with unlimited nargs followed by one with 1""" - - argument_signatures = [Sig('foo', nargs='*'), Sig('bar', nargs=1)] - failures = ['', '--foo', ] - successes = [ - ('a', NS(foo=[], bar=['a'])), - ('a b', NS(foo=['a'], bar=['b'])), - ('a b c', NS(foo=['a', 'b'], bar=['c'])), - ] - - -class TestPositionalsNargsOneOrMore1(ParserTestCase): - """Test a Positional with one or more nargs followed by one with 1""" - - argument_signatures = [Sig('foo', nargs='+'), Sig('bar', nargs=1)] - failures = ['', '--foo', 'a'] - successes = [ - ('a b', NS(foo=['a'], bar=['b'])), - ('a b c', NS(foo=['a', 'b'], bar=['c'])), - ] - - -class TestPositionalsNargsOptional1(ParserTestCase): - """Test a Positional with an Optional nargs followed by one with 1""" - - argument_signatures = [Sig('foo', nargs='?'), Sig('bar', nargs=1)] - failures = ['', '--foo', 'a b c'] - successes = [ - ('a', NS(foo=None, bar=['a'])), - ('a b', NS(foo='a', bar=['b'])), - ] - - -class TestPositionalsNargsNoneZeroOrMore1(ParserTestCase): - """Test three Positionals: no nargs, unlimited nargs and 1 nargs""" - - argument_signatures = [ - Sig('foo'), - Sig('bar', nargs='*'), - Sig('baz', nargs=1), - ] - failures = ['', '--foo', 'a'] - successes = [ - ('a b', NS(foo='a', bar=[], baz=['b'])), - ('a b c', NS(foo='a', bar=['b'], baz=['c'])), - ] - - -class TestPositionalsNargsNoneOneOrMore1(ParserTestCase): - """Test three Positionals: no nargs, one or more nargs and 1 nargs""" - - argument_signatures = [ - Sig('foo'), - Sig('bar', nargs='+'), - Sig('baz', nargs=1), - ] - failures = ['', '--foo', 'a', 'b'] - successes = [ - ('a b c', NS(foo='a', bar=['b'], baz=['c'])), - ('a b c d', NS(foo='a', bar=['b', 'c'], baz=['d'])), - ] - - -class TestPositionalsNargsNoneOptional1(ParserTestCase): - """Test three Positionals: no nargs, optional narg and 1 nargs""" - - argument_signatures = [ - Sig('foo'), - Sig('bar', nargs='?', default=0.625), - Sig('baz', nargs=1), - ] - failures = ['', '--foo', 'a'] - successes = [ - ('a b', NS(foo='a', bar=0.625, baz=['b'])), - ('a b c', NS(foo='a', bar='b', baz=['c'])), - ] - - -class TestPositionalsNargsOptionalOptional(ParserTestCase): - """Test two optional nargs""" - - argument_signatures = [ - Sig('foo', nargs='?'), - Sig('bar', nargs='?', default=42), - ] - failures = ['--foo', 'a b c'] - successes = [ - ('', NS(foo=None, bar=42)), - ('a', NS(foo='a', bar=42)), - ('a b', NS(foo='a', bar='b')), - ] - - -class TestPositionalsNargsOptionalZeroOrMore(ParserTestCase): - """Test an Optional narg followed by unlimited nargs""" - - argument_signatures = [Sig('foo', nargs='?'), Sig('bar', nargs='*')] - failures = ['--foo'] - successes = [ - ('', NS(foo=None, bar=[])), - ('a', NS(foo='a', bar=[])), - ('a b', NS(foo='a', bar=['b'])), - ('a b c', NS(foo='a', bar=['b', 'c'])), - ] - - -class TestPositionalsNargsOptionalOneOrMore(ParserTestCase): - """Test an Optional narg followed by one or more nargs""" - - argument_signatures = [Sig('foo', nargs='?'), Sig('bar', nargs='+')] - failures = ['', '--foo'] - successes = [ - ('a', NS(foo=None, bar=['a'])), - ('a b', NS(foo='a', bar=['b'])), - ('a b c', NS(foo='a', bar=['b', 'c'])), - ] - - -class TestPositionalsChoicesString(ParserTestCase): - """Test a set of single-character choices""" - - argument_signatures = [Sig('spam', choices=set('abcdefg'))] - failures = ['', '--foo', 'h', '42', 'ef'] - successes = [ - ('a', NS(spam='a')), - ('g', NS(spam='g')), - ] - - -class TestPositionalsChoicesInt(ParserTestCase): - """Test a set of integer choices""" - - argument_signatures = [Sig('spam', type=int, choices=range(20))] - failures = ['', '--foo', 'h', '42', 'ef'] - successes = [ - ('4', NS(spam=4)), - ('15', NS(spam=15)), - ] - - -class TestPositionalsActionAppend(ParserTestCase): - """Test the 'append' action""" - - argument_signatures = [ - Sig('spam', action='append'), - Sig('spam', action='append', nargs=2), - ] - failures = ['', '--foo', 'a', 'a b', 'a b c d'] - successes = [ - ('a b c', NS(spam=['a', ['b', 'c']])), - ] - -# ======================================== -# Combined optionals and positionals tests -# ======================================== - -class TestOptionalsNumericAndPositionals(ParserTestCase): - """Tests negative number args when numeric options are present""" - - argument_signatures = [ - Sig('x', nargs='?'), - Sig('-4', dest='y', action='store_true'), - ] - failures = ['-2', '-315'] - successes = [ - ('', NS(x=None, y=False)), - ('a', NS(x='a', y=False)), - ('-4', NS(x=None, y=True)), - ('-4 a', NS(x='a', y=True)), - ] - - -class TestOptionalsAlmostNumericAndPositionals(ParserTestCase): - """Tests negative number args when almost numeric options are present""" - - argument_signatures = [ - Sig('x', nargs='?'), - Sig('-k4', dest='y', action='store_true'), - ] - failures = ['-k3'] - successes = [ - ('', NS(x=None, y=False)), - ('-2', NS(x='-2', y=False)), - ('a', NS(x='a', y=False)), - ('-k4', NS(x=None, y=True)), - ('-k4 a', NS(x='a', y=True)), - ] - - -class TestEmptyAndSpaceContainingArguments(ParserTestCase): - - argument_signatures = [ - Sig('x', nargs='?'), - Sig('-y', '--yyy', dest='y'), - ] - failures = ['-y'] - successes = [ - ([''], NS(x='', y=None)), - (['a badger'], NS(x='a badger', y=None)), - (['-a badger'], NS(x='-a badger', y=None)), - (['-y', ''], NS(x=None, y='')), - (['-y', 'a badger'], NS(x=None, y='a badger')), - (['-y', '-a badger'], NS(x=None, y='-a badger')), - (['--yyy=a badger'], NS(x=None, y='a badger')), - (['--yyy=-a badger'], NS(x=None, y='-a badger')), - ] - - -class TestPrefixCharacterOnlyArguments(ParserTestCase): - - parser_signature = Sig(prefix_chars='-+') - argument_signatures = [ - Sig('-', dest='x', nargs='?', const='badger'), - Sig('+', dest='y', type=int, default=42), - Sig('-+-', dest='z', action='store_true'), - ] - failures = ['-y', '+ -'] - successes = [ - ('', NS(x=None, y=42, z=False)), - ('-', NS(x='badger', y=42, z=False)), - ('- X', NS(x='X', y=42, z=False)), - ('+ -3', NS(x=None, y=-3, z=False)), - ('-+-', NS(x=None, y=42, z=True)), - ('- ===', NS(x='===', y=42, z=False)), - ] - - -class TestNargsZeroOrMore(ParserTestCase): - """Tests specifying an args for an Optional that accepts zero or more""" - - argument_signatures = [Sig('-x', nargs='*'), Sig('y', nargs='*')] - failures = [] - successes = [ - ('', NS(x=None, y=[])), - ('-x', NS(x=[], y=[])), - ('-x a', NS(x=['a'], y=[])), - ('-x a -- b', NS(x=['a'], y=['b'])), - ('a', NS(x=None, y=['a'])), - ('a -x', NS(x=[], y=['a'])), - ('a -x b', NS(x=['b'], y=['a'])), - ] - - -class TestNargsRemainder(ParserTestCase): - """Tests specifying a positional with nargs=REMAINDER""" - - argument_signatures = [Sig('x'), Sig('y', nargs='...'), Sig('-z')] - failures = ['', '-z', '-z Z'] - successes = [ - ('X', NS(x='X', y=[], z=None)), - ('-z Z X', NS(x='X', y=[], z='Z')), - ('X A B -z Z', NS(x='X', y=['A', 'B', '-z', 'Z'], z=None)), - ('X Y --foo', NS(x='X', y=['Y', '--foo'], z=None)), - ] - - -class TestOptionLike(ParserTestCase): - """Tests options that may or may not be arguments""" - - argument_signatures = [ - Sig('-x', type=float), - Sig('-3', type=float, dest='y'), - Sig('z', nargs='*'), - ] - failures = ['-x', '-y2.5', '-xa', '-x -a', - '-x -3', '-x -3.5', '-3 -3.5', - '-x -2.5', '-x -2.5 a', '-3 -.5', - 'a x -1', '-x -1 a', '-3 -1 a'] - successes = [ - ('', NS(x=None, y=None, z=[])), - ('-x 2.5', NS(x=2.5, y=None, z=[])), - ('-x 2.5 a', NS(x=2.5, y=None, z=['a'])), - ('-3.5', NS(x=None, y=0.5, z=[])), - ('-3-.5', NS(x=None, y=-0.5, z=[])), - ('-3 .5', NS(x=None, y=0.5, z=[])), - ('a -3.5', NS(x=None, y=0.5, z=['a'])), - ('a', NS(x=None, y=None, z=['a'])), - ('a -x 1', NS(x=1.0, y=None, z=['a'])), - ('-x 1 a', NS(x=1.0, y=None, z=['a'])), - ('-3 1 a', NS(x=None, y=1.0, z=['a'])), - ] - - -class TestDefaultSuppress(ParserTestCase): - """Test actions with suppressed defaults""" - - argument_signatures = [ - Sig('foo', nargs='?', default=argparse.SUPPRESS), - Sig('bar', nargs='*', default=argparse.SUPPRESS), - Sig('--baz', action='store_true', default=argparse.SUPPRESS), - ] - failures = ['-x'] - successes = [ - ('', NS()), - ('a', NS(foo='a')), - ('a b', NS(foo='a', bar=['b'])), - ('--baz', NS(baz=True)), - ('a --baz', NS(foo='a', baz=True)), - ('--baz a b', NS(foo='a', bar=['b'], baz=True)), - ] - - -class TestParserDefaultSuppress(ParserTestCase): - """Test actions with a parser-level default of SUPPRESS""" - - parser_signature = Sig(argument_default=argparse.SUPPRESS) - argument_signatures = [ - Sig('foo', nargs='?'), - Sig('bar', nargs='*'), - Sig('--baz', action='store_true'), - ] - failures = ['-x'] - successes = [ - ('', NS()), - ('a', NS(foo='a')), - ('a b', NS(foo='a', bar=['b'])), - ('--baz', NS(baz=True)), - ('a --baz', NS(foo='a', baz=True)), - ('--baz a b', NS(foo='a', bar=['b'], baz=True)), - ] - - -class TestParserDefault42(ParserTestCase): - """Test actions with a parser-level default of 42""" - - parser_signature = Sig(argument_default=42, version='1.0') - argument_signatures = [ - Sig('foo', nargs='?'), - Sig('bar', nargs='*'), - Sig('--baz', action='store_true'), - ] - failures = ['-x'] - successes = [ - ('', NS(foo=42, bar=42, baz=42)), - ('a', NS(foo='a', bar=42, baz=42)), - ('a b', NS(foo='a', bar=['b'], baz=42)), - ('--baz', NS(foo=42, bar=42, baz=True)), - ('a --baz', NS(foo='a', bar=42, baz=True)), - ('--baz a b', NS(foo='a', bar=['b'], baz=True)), - ] - - -class TestArgumentsFromFile(TempDirMixin, ParserTestCase): - """Test reading arguments from a file""" - - def setUp(self): - super(TestArgumentsFromFile, self).setUp() - file_texts = [ - ('hello', 'hello world!\n'), - ('recursive', '-a\n' - 'A\n' - '@hello'), - ('invalid', '@no-such-path\n'), - ] - for path, text in file_texts: - file = open(path, 'w') - file.write(text) - file.close() - - parser_signature = Sig(fromfile_prefix_chars='@') - argument_signatures = [ - Sig('-a'), - Sig('x'), - Sig('y', nargs='+'), - ] - failures = ['', '-b', 'X', '@invalid', '@missing'] - successes = [ - ('X Y', NS(a=None, x='X', y=['Y'])), - ('X -a A Y Z', NS(a='A', x='X', y=['Y', 'Z'])), - ('@hello X', NS(a=None, x='hello world!', y=['X'])), - ('X @hello', NS(a=None, x='X', y=['hello world!'])), - ('-a B @recursive Y Z', NS(a='A', x='hello world!', y=['Y', 'Z'])), - ('X @recursive Z -a B', NS(a='B', x='X', y=['hello world!', 'Z'])), - ] - - -class TestArgumentsFromFileConverter(TempDirMixin, ParserTestCase): - """Test reading arguments from a file""" - - def setUp(self): - super(TestArgumentsFromFileConverter, self).setUp() - file_texts = [ - ('hello', 'hello world!\n'), - ] - for path, text in file_texts: - file = open(path, 'w') - file.write(text) - file.close() - - class FromFileConverterArgumentParser(ErrorRaisingArgumentParser): - - def convert_arg_line_to_args(self, arg_line): - for arg in arg_line.split(): - if not arg.strip(): - continue - yield arg - parser_class = FromFileConverterArgumentParser - parser_signature = Sig(fromfile_prefix_chars='@') - argument_signatures = [ - Sig('y', nargs='+'), - ] - failures = [] - successes = [ - ('@hello X', NS(y=['hello', 'world!', 'X'])), - ] - - -# ===================== -# Type conversion tests -# ===================== - -class TestFileTypeRepr(TestCase): - - def test_r(self): - type = argparse.FileType('r') - self.assertEqual("FileType('r')", repr(type)) - - def test_wb_1(self): - type = argparse.FileType('wb', 1) - self.assertEqual("FileType('wb', 1)", repr(type)) - - -class RFile(object): - seen = {} - - def __init__(self, name): - self.name = name - - def __eq__(self, other): - if other in self.seen: - text = self.seen[other] - else: - text = self.seen[other] = other.read() - other.close() - if not isinstance(text, str): - text = text.decode('ascii') - return self.name == other.name == text - - -class TestFileTypeR(TempDirMixin, ParserTestCase): - """Test the FileType option/argument type for reading files""" - - def setUp(self): - super(TestFileTypeR, self).setUp() - for file_name in ['foo', 'bar']: - file = open(os.path.join(self.temp_dir, file_name), 'w') - file.write(file_name) - file.close() - - argument_signatures = [ - Sig('-x', type=argparse.FileType()), - Sig('spam', type=argparse.FileType('r')), - ] - failures = ['-x', '-x bar'] - successes = [ - ('foo', NS(x=None, spam=RFile('foo'))), - ('-x foo bar', NS(x=RFile('foo'), spam=RFile('bar'))), - ('bar -x foo', NS(x=RFile('foo'), spam=RFile('bar'))), - ('-x - -', NS(x=sys.stdin, spam=sys.stdin)), - ] - - -class TestFileTypeRB(TempDirMixin, ParserTestCase): - """Test the FileType option/argument type for reading files""" - - def setUp(self): - super(TestFileTypeRB, self).setUp() - for file_name in ['foo', 'bar']: - file = open(os.path.join(self.temp_dir, file_name), 'w') - file.write(file_name) - file.close() - - argument_signatures = [ - Sig('-x', type=argparse.FileType('rb')), - Sig('spam', type=argparse.FileType('rb')), - ] - failures = ['-x', '-x bar'] - successes = [ - ('foo', NS(x=None, spam=RFile('foo'))), - ('-x foo bar', NS(x=RFile('foo'), spam=RFile('bar'))), - ('bar -x foo', NS(x=RFile('foo'), spam=RFile('bar'))), - ('-x - -', NS(x=sys.stdin, spam=sys.stdin)), - ] - - -class WFile(object): - seen = set() - - def __init__(self, name): - self.name = name - - def __eq__(self, other): - if other not in self.seen: - text = 'Check that file is writable.' - if 'b' in other.mode: - text = text.encode('ascii') - other.write(text) - other.close() - self.seen.add(other) - return self.name == other.name - - -class TestFileTypeW(TempDirMixin, ParserTestCase): - """Test the FileType option/argument type for writing files""" - - argument_signatures = [ - Sig('-x', type=argparse.FileType('w')), - Sig('spam', type=argparse.FileType('w')), - ] - failures = ['-x', '-x bar'] - successes = [ - ('foo', NS(x=None, spam=WFile('foo'))), - ('-x foo bar', NS(x=WFile('foo'), spam=WFile('bar'))), - ('bar -x foo', NS(x=WFile('foo'), spam=WFile('bar'))), - ('-x - -', NS(x=sys.stdout, spam=sys.stdout)), - ] - - -class TestFileTypeWB(TempDirMixin, ParserTestCase): - - argument_signatures = [ - Sig('-x', type=argparse.FileType('wb')), - Sig('spam', type=argparse.FileType('wb')), - ] - failures = ['-x', '-x bar'] - successes = [ - ('foo', NS(x=None, spam=WFile('foo'))), - ('-x foo bar', NS(x=WFile('foo'), spam=WFile('bar'))), - ('bar -x foo', NS(x=WFile('foo'), spam=WFile('bar'))), - ('-x - -', NS(x=sys.stdout, spam=sys.stdout)), - ] - - -class TestTypeCallable(ParserTestCase): - """Test some callables as option/argument types""" - - argument_signatures = [ - Sig('--eggs', type=complex), - Sig('spam', type=float), - ] - failures = ['a', '42j', '--eggs a', '--eggs 2i'] - successes = [ - ('--eggs=42 42', NS(eggs=42, spam=42.0)), - ('--eggs 2j -- -1.5', NS(eggs=2j, spam=-1.5)), - ('1024.675', NS(eggs=None, spam=1024.675)), - ] - - -class TestTypeUserDefined(ParserTestCase): - """Test a user-defined option/argument type""" - - class MyType(TestCase): - - def __init__(self, value): - self.value = value - - def __eq__(self, other): - return (type(self), self.value) == (type(other), other.value) - - argument_signatures = [ - Sig('-x', type=MyType), - Sig('spam', type=MyType), - ] - failures = [] - successes = [ - ('a -x b', NS(x=MyType('b'), spam=MyType('a'))), - ('-xf g', NS(x=MyType('f'), spam=MyType('g'))), - ] - - -class TestTypeClassicClass(ParserTestCase): - """Test a classic class type""" - - class C: - - def __init__(self, value): - self.value = value - - def __eq__(self, other): - return (type(self), self.value) == (type(other), other.value) - - argument_signatures = [ - Sig('-x', type=C), - Sig('spam', type=C), - ] - failures = [] - successes = [ - ('a -x b', NS(x=C('b'), spam=C('a'))), - ('-xf g', NS(x=C('f'), spam=C('g'))), - ] - - -class TestTypeRegistration(TestCase): - """Test a user-defined type by registering it""" - - def test(self): - - def get_my_type(string): - return 'my_type{%s}' % string - - parser = argparse.ArgumentParser() - parser.register('type', 'my_type', get_my_type) - parser.add_argument('-x', type='my_type') - parser.add_argument('y', type='my_type') - - self.assertEqual(parser.parse_args('1'.split()), - NS(x=None, y='my_type{1}')) - self.assertEqual(parser.parse_args('-x 1 42'.split()), - NS(x='my_type{1}', y='my_type{42}')) - - -# ============ -# Action tests -# ============ - -class TestActionUserDefined(ParserTestCase): - """Test a user-defined option/argument action""" - - class OptionalAction(argparse.Action): - - def __call__(self, parser, namespace, value, option_string=None): - try: - # check destination and option string - assert self.dest == 'spam', 'dest: %s' % self.dest - assert option_string == '-s', 'flag: %s' % option_string - # when option is before argument, badger=2, and when - # option is after argument, badger=<whatever was set> - expected_ns = NS(spam=0.25) - if value in [0.125, 0.625]: - expected_ns.badger = 2 - elif value in [2.0]: - expected_ns.badger = 84 - else: - raise AssertionError('value: %s' % value) - assert expected_ns == namespace, ('expected %s, got %s' % - (expected_ns, namespace)) - except AssertionError: - e = sys.exc_info()[1] - raise ArgumentParserError('opt_action failed: %s' % e) - setattr(namespace, 'spam', value) - - class PositionalAction(argparse.Action): - - def __call__(self, parser, namespace, value, option_string=None): - try: - assert option_string is None, ('option_string: %s' % - option_string) - # check destination - assert self.dest == 'badger', 'dest: %s' % self.dest - # when argument is before option, spam=0.25, and when - # option is after argument, spam=<whatever was set> - expected_ns = NS(badger=2) - if value in [42, 84]: - expected_ns.spam = 0.25 - elif value in [1]: - expected_ns.spam = 0.625 - elif value in [2]: - expected_ns.spam = 0.125 - else: - raise AssertionError('value: %s' % value) - assert expected_ns == namespace, ('expected %s, got %s' % - (expected_ns, namespace)) - except AssertionError: - e = sys.exc_info()[1] - raise ArgumentParserError('arg_action failed: %s' % e) - setattr(namespace, 'badger', value) - - argument_signatures = [ - Sig('-s', dest='spam', action=OptionalAction, - type=float, default=0.25), - Sig('badger', action=PositionalAction, - type=int, nargs='?', default=2), - ] - failures = [] - successes = [ - ('-s0.125', NS(spam=0.125, badger=2)), - ('42', NS(spam=0.25, badger=42)), - ('-s 0.625 1', NS(spam=0.625, badger=1)), - ('84 -s2', NS(spam=2.0, badger=84)), - ] - - -class TestActionRegistration(TestCase): - """Test a user-defined action supplied by registering it""" - - class MyAction(argparse.Action): - - def __call__(self, parser, namespace, values, option_string=None): - setattr(namespace, self.dest, 'foo[%s]' % values) - - def test(self): - - parser = argparse.ArgumentParser() - parser.register('action', 'my_action', self.MyAction) - parser.add_argument('badger', action='my_action') - - self.assertEqual(parser.parse_args(['1']), NS(badger='foo[1]')) - self.assertEqual(parser.parse_args(['42']), NS(badger='foo[42]')) - - -# ================ -# Subparsers tests -# ================ - -class TestAddSubparsers(TestCase): - """Test the add_subparsers method""" - - def assertArgumentParserError(self, *args, **kwargs): - self.assertRaises(ArgumentParserError, *args, **kwargs) - - def _get_parser(self, subparser_help=False): - # create a parser with a subparsers argument - parser = ErrorRaisingArgumentParser( - prog='PROG', description='main description') - parser.add_argument( - '--foo', action='store_true', help='foo help') - parser.add_argument( - 'bar', type=float, help='bar help') - - # check that only one subparsers argument can be added - subparsers = parser.add_subparsers(help='command help') - self.assertArgumentParserError(parser.add_subparsers) - - # add first sub-parser - parser1_kwargs = dict(description='1 description') - if subparser_help: - parser1_kwargs['help'] = '1 help' - parser1 = subparsers.add_parser('1', **parser1_kwargs) - parser1.add_argument('-w', type=int, help='w help') - parser1.add_argument('x', choices='abc', help='x help') - - # add second sub-parser - parser2_kwargs = dict(description='2 description') - if subparser_help: - parser2_kwargs['help'] = '2 help' - parser2 = subparsers.add_parser('2', **parser2_kwargs) - parser2.add_argument('-y', choices='123', help='y help') - parser2.add_argument('z', type=complex, nargs='*', help='z help') - - # return the main parser - return parser - - def setUp(self): - self.parser = self._get_parser() - self.command_help_parser = self._get_parser(subparser_help=True) - - def test_parse_args_failures(self): - # check some failure cases: - for args_str in ['', 'a', 'a a', '0.5 a', '0.5 1', - '0.5 1 -y', '0.5 2 -w']: - args = args_str.split() - self.assertArgumentParserError(self.parser.parse_args, args) - - def test_parse_args(self): - # check some non-failure cases: - self.assertEqual( - self.parser.parse_args('0.5 1 b -w 7'.split()), - NS(foo=False, bar=0.5, w=7, x='b'), - ) - self.assertEqual( - self.parser.parse_args('0.25 --foo 2 -y 2 3j -- -1j'.split()), - NS(foo=True, bar=0.25, y='2', z=[3j, -1j]), - ) - self.assertEqual( - self.parser.parse_args('--foo 0.125 1 c'.split()), - NS(foo=True, bar=0.125, w=None, x='c'), - ) - - def test_dest(self): - parser = ErrorRaisingArgumentParser() - parser.add_argument('--foo', action='store_true') - subparsers = parser.add_subparsers(dest='bar') - parser1 = subparsers.add_parser('1') - parser1.add_argument('baz') - self.assertEqual(NS(foo=False, bar='1', baz='2'), - parser.parse_args('1 2'.split())) - - def test_help(self): - self.assertEqual(self.parser.format_usage(), - 'usage: PROG [-h] [--foo] bar {1,2} ...\n') - self.assertEqual(self.parser.format_help(), textwrap.dedent('''\ - usage: PROG [-h] [--foo] bar {1,2} ... - - main description - - positional arguments: - bar bar help - {1,2} command help - - optional arguments: - -h, --help show this help message and exit - --foo foo help - ''')) - - def test_parser_command_help(self): - self.assertEqual(self.command_help_parser.format_usage(), - 'usage: PROG [-h] [--foo] bar {1,2} ...\n') - self.assertEqual(self.command_help_parser.format_help(), - textwrap.dedent('''\ - usage: PROG [-h] [--foo] bar {1,2} ... - - main description - - positional arguments: - bar bar help - {1,2} command help - 1 1 help - 2 2 help - - optional arguments: - -h, --help show this help message and exit - --foo foo help - ''')) - - def test_subparser_title_help(self): - parser = ErrorRaisingArgumentParser(prog='PROG', - description='main description') - parser.add_argument('--foo', action='store_true', help='foo help') - parser.add_argument('bar', help='bar help') - subparsers = parser.add_subparsers(title='subcommands', - description='command help', - help='additional text') - parser1 = subparsers.add_parser('1') - parser2 = subparsers.add_parser('2') - self.assertEqual(parser.format_usage(), - 'usage: PROG [-h] [--foo] bar {1,2} ...\n') - self.assertEqual(parser.format_help(), textwrap.dedent('''\ - usage: PROG [-h] [--foo] bar {1,2} ... - - main description - - positional arguments: - bar bar help - - optional arguments: - -h, --help show this help message and exit - --foo foo help - - subcommands: - command help - - {1,2} additional text - ''')) - - def _test_subparser_help(self, args_str, expected_help): - try: - self.parser.parse_args(args_str.split()) - except ArgumentParserError: - err = sys.exc_info()[1] - if err.stdout != expected_help: - print(repr(expected_help)) - print(repr(err.stdout)) - self.assertEqual(err.stdout, expected_help) - - def test_subparser1_help(self): - self._test_subparser_help('5.0 1 -h', textwrap.dedent('''\ - usage: PROG bar 1 [-h] [-w W] {a,b,c} - - 1 description - - positional arguments: - {a,b,c} x help - - optional arguments: - -h, --help show this help message and exit - -w W w help - ''')) - - def test_subparser2_help(self): - self._test_subparser_help('5.0 2 -h', textwrap.dedent('''\ - usage: PROG bar 2 [-h] [-y {1,2,3}] [z [z ...]] - - 2 description - - positional arguments: - z z help - - optional arguments: - -h, --help show this help message and exit - -y {1,2,3} y help - ''')) - -# ============ -# Groups tests -# ============ - -class TestPositionalsGroups(TestCase): - """Tests that order of group positionals matches construction order""" - - def test_nongroup_first(self): - parser = ErrorRaisingArgumentParser() - parser.add_argument('foo') - group = parser.add_argument_group('g') - group.add_argument('bar') - parser.add_argument('baz') - expected = NS(foo='1', bar='2', baz='3') - result = parser.parse_args('1 2 3'.split()) - self.failUnlessEqual(expected, result) - - def test_group_first(self): - parser = ErrorRaisingArgumentParser() - group = parser.add_argument_group('xxx') - group.add_argument('foo') - parser.add_argument('bar') - parser.add_argument('baz') - expected = NS(foo='1', bar='2', baz='3') - result = parser.parse_args('1 2 3'.split()) - self.failUnlessEqual(expected, result) - - def test_interleaved_groups(self): - parser = ErrorRaisingArgumentParser() - group = parser.add_argument_group('xxx') - parser.add_argument('foo') - group.add_argument('bar') - parser.add_argument('baz') - group = parser.add_argument_group('yyy') - group.add_argument('frell') - expected = NS(foo='1', bar='2', baz='3', frell='4') - result = parser.parse_args('1 2 3 4'.split()) - self.failUnlessEqual(expected, result) - -# =================== -# Parent parser tests -# =================== - -class TestParentParsers(TestCase): - """Tests that parsers can be created with parent parsers""" - - def assertArgumentParserError(self, *args, **kwargs): - self.assertRaises(ArgumentParserError, *args, **kwargs) - - def setUp(self): - self.wxyz_parent = ErrorRaisingArgumentParser(add_help=False) - self.wxyz_parent.add_argument('--w') - x_group = self.wxyz_parent.add_argument_group('x') - x_group.add_argument('-y') - self.wxyz_parent.add_argument('z') - - self.abcd_parent = ErrorRaisingArgumentParser(add_help=False) - self.abcd_parent.add_argument('a') - self.abcd_parent.add_argument('-b') - c_group = self.abcd_parent.add_argument_group('c') - c_group.add_argument('--d') - - self.w_parent = ErrorRaisingArgumentParser(add_help=False) - self.w_parent.add_argument('--w') - - self.z_parent = ErrorRaisingArgumentParser(add_help=False) - self.z_parent.add_argument('z') - - # parents with mutually exclusive groups - self.ab_mutex_parent = ErrorRaisingArgumentParser(add_help=False) - group = self.ab_mutex_parent.add_mutually_exclusive_group() - group.add_argument('-a', action='store_true') - group.add_argument('-b', action='store_true') - - def test_single_parent(self): - parser = ErrorRaisingArgumentParser(parents=[self.wxyz_parent]) - self.assertEqual(parser.parse_args('-y 1 2 --w 3'.split()), - NS(w='3', y='1', z='2')) - - def test_single_parent_mutex(self): - self._test_mutex_ab(self.ab_mutex_parent.parse_args) - parser = ErrorRaisingArgumentParser(parents=[self.ab_mutex_parent]) - self._test_mutex_ab(parser.parse_args) - - def test_single_granparent_mutex(self): - parents = [self.ab_mutex_parent] - parser = ErrorRaisingArgumentParser(add_help=False, parents=parents) - parser = ErrorRaisingArgumentParser(parents=[parser]) - self._test_mutex_ab(parser.parse_args) - - def _test_mutex_ab(self, parse_args): - self.assertEqual(parse_args([]), NS(a=False, b=False)) - self.assertEqual(parse_args(['-a']), NS(a=True, b=False)) - self.assertEqual(parse_args(['-b']), NS(a=False, b=True)) - self.assertArgumentParserError(parse_args, ['-a', '-b']) - self.assertArgumentParserError(parse_args, ['-b', '-a']) - self.assertArgumentParserError(parse_args, ['-c']) - self.assertArgumentParserError(parse_args, ['-a', '-c']) - self.assertArgumentParserError(parse_args, ['-b', '-c']) - - def test_multiple_parents(self): - parents = [self.abcd_parent, self.wxyz_parent] - parser = ErrorRaisingArgumentParser(parents=parents) - self.assertEqual(parser.parse_args('--d 1 --w 2 3 4'.split()), - NS(a='3', b=None, d='1', w='2', y=None, z='4')) - - def test_multiple_parents_mutex(self): - parents = [self.ab_mutex_parent, self.wxyz_parent] - parser = ErrorRaisingArgumentParser(parents=parents) - self.assertEqual(parser.parse_args('-a --w 2 3'.split()), - NS(a=True, b=False, w='2', y=None, z='3')) - self.assertArgumentParserError( - parser.parse_args, '-a --w 2 3 -b'.split()) - self.assertArgumentParserError( - parser.parse_args, '-a -b --w 2 3'.split()) - - def test_conflicting_parents(self): - self.assertRaises( - argparse.ArgumentError, - argparse.ArgumentParser, - parents=[self.w_parent, self.wxyz_parent]) - - def test_conflicting_parents_mutex(self): - self.assertRaises( - argparse.ArgumentError, - argparse.ArgumentParser, - parents=[self.abcd_parent, self.ab_mutex_parent]) - - def test_same_argument_name_parents(self): - parents = [self.wxyz_parent, self.z_parent] - parser = ErrorRaisingArgumentParser(parents=parents) - self.assertEqual(parser.parse_args('1 2'.split()), - NS(w=None, y=None, z='2')) - - def test_subparser_parents(self): - parser = ErrorRaisingArgumentParser() - subparsers = parser.add_subparsers() - abcde_parser = subparsers.add_parser('bar', parents=[self.abcd_parent]) - abcde_parser.add_argument('e') - self.assertEqual(parser.parse_args('bar -b 1 --d 2 3 4'.split()), - NS(a='3', b='1', d='2', e='4')) - - def test_subparser_parents_mutex(self): - parser = ErrorRaisingArgumentParser() - subparsers = parser.add_subparsers() - parents = [self.ab_mutex_parent] - abc_parser = subparsers.add_parser('foo', parents=parents) - c_group = abc_parser.add_argument_group('c_group') - c_group.add_argument('c') - parents = [self.wxyz_parent, self.ab_mutex_parent] - wxyzabe_parser = subparsers.add_parser('bar', parents=parents) - wxyzabe_parser.add_argument('e') - self.assertEqual(parser.parse_args('foo -a 4'.split()), - NS(a=True, b=False, c='4')) - self.assertEqual(parser.parse_args('bar -b --w 2 3 4'.split()), - NS(a=False, b=True, w='2', y=None, z='3', e='4')) - self.assertArgumentParserError( - parser.parse_args, 'foo -a -b 4'.split()) - self.assertArgumentParserError( - parser.parse_args, 'bar -b -a 4'.split()) - - def test_parent_help(self): - parents = [self.abcd_parent, self.wxyz_parent] - parser = ErrorRaisingArgumentParser(parents=parents) - parser_help = parser.format_help() - self.assertEqual(parser_help, textwrap.dedent('''\ - usage: test_argparse.py [-h] [-b B] [--d D] [--w W] [-y Y] a z - - positional arguments: - a - z - - optional arguments: - -h, --help show this help message and exit - -b B - --w W - - c: - --d D - - x: - -y Y - ''')) - - def test_groups_parents(self): - parent = ErrorRaisingArgumentParser(add_help=False) - g = parent.add_argument_group(title='g', description='gd') - g.add_argument('-w') - g.add_argument('-x') - m = parent.add_mutually_exclusive_group() - m.add_argument('-y') - m.add_argument('-z') - parser = ErrorRaisingArgumentParser(parents=[parent]) - - self.assertRaises(ArgumentParserError, parser.parse_args, - ['-y', 'Y', '-z', 'Z']) - - parser_help = parser.format_help() - self.assertEqual(parser_help, textwrap.dedent('''\ - usage: test_argparse.py [-h] [-w W] [-x X] [-y Y | -z Z] - - optional arguments: - -h, --help show this help message and exit - -y Y - -z Z - - g: - gd - - -w W - -x X - ''')) - -# ============================== -# Mutually exclusive group tests -# ============================== - -class TestMutuallyExclusiveGroupErrors(TestCase): - - def test_invalid_add_argument_group(self): - parser = ErrorRaisingArgumentParser() - raises = self.assertRaises - raises(TypeError, parser.add_mutually_exclusive_group, title='foo') - - def test_invalid_add_argument(self): - parser = ErrorRaisingArgumentParser() - group = parser.add_mutually_exclusive_group() - add_argument = group.add_argument - raises = self.assertRaises - raises(ValueError, add_argument, '--foo', required=True) - raises(ValueError, add_argument, 'bar') - raises(ValueError, add_argument, 'bar', nargs='+') - raises(ValueError, add_argument, 'bar', nargs=1) - raises(ValueError, add_argument, 'bar', nargs=argparse.PARSER) - - -class MEMixin(object): - - def test_failures_when_not_required(self): - parse_args = self.get_parser(required=False).parse_args - error = ArgumentParserError - for args_string in self.failures: - self.assertRaises(error, parse_args, args_string.split()) - - def test_failures_when_required(self): - parse_args = self.get_parser(required=True).parse_args - error = ArgumentParserError - for args_string in self.failures + ['']: - self.assertRaises(error, parse_args, args_string.split()) - - def test_successes_when_not_required(self): - parse_args = self.get_parser(required=False).parse_args - successes = self.successes + self.successes_when_not_required - for args_string, expected_ns in successes: - actual_ns = parse_args(args_string.split()) - self.assertEqual(actual_ns, expected_ns) - - def test_successes_when_required(self): - parse_args = self.get_parser(required=True).parse_args - for args_string, expected_ns in self.successes: - actual_ns = parse_args(args_string.split()) - self.assertEqual(actual_ns, expected_ns) - - def test_usage_when_not_required(self): - format_usage = self.get_parser(required=False).format_usage - expected_usage = self.usage_when_not_required - self.assertEqual(format_usage(), textwrap.dedent(expected_usage)) - - def test_usage_when_required(self): - format_usage = self.get_parser(required=True).format_usage - expected_usage = self.usage_when_required - self.assertEqual(format_usage(), textwrap.dedent(expected_usage)) - - def test_help_when_not_required(self): - format_help = self.get_parser(required=False).format_help - help = self.usage_when_not_required + self.help - self.assertEqual(format_help(), textwrap.dedent(help)) - - def test_help_when_required(self): - format_help = self.get_parser(required=True).format_help - help = self.usage_when_required + self.help - self.assertEqual(format_help(), textwrap.dedent(help)) - - -class TestMutuallyExclusiveSimple(MEMixin, TestCase): - - def get_parser(self, required=None): - parser = ErrorRaisingArgumentParser(prog='PROG') - group = parser.add_mutually_exclusive_group(required=required) - group.add_argument('--bar', help='bar help') - group.add_argument('--baz', nargs='?', const='Z', help='baz help') - return parser - - failures = ['--bar X --baz Y', '--bar X --baz'] - successes = [ - ('--bar X', NS(bar='X', baz=None)), - ('--bar X --bar Z', NS(bar='Z', baz=None)), - ('--baz Y', NS(bar=None, baz='Y')), - ('--baz', NS(bar=None, baz='Z')), - ] - successes_when_not_required = [ - ('', NS(bar=None, baz=None)), - ] - - usage_when_not_required = '''\ - usage: PROG [-h] [--bar BAR | --baz [BAZ]] - ''' - usage_when_required = '''\ - usage: PROG [-h] (--bar BAR | --baz [BAZ]) - ''' - help = '''\ - - optional arguments: - -h, --help show this help message and exit - --bar BAR bar help - --baz [BAZ] baz help - ''' - - -class TestMutuallyExclusiveLong(MEMixin, TestCase): - - def get_parser(self, required=None): - parser = ErrorRaisingArgumentParser(prog='PROG') - parser.add_argument('--abcde', help='abcde help') - parser.add_argument('--fghij', help='fghij help') - group = parser.add_mutually_exclusive_group(required=required) - group.add_argument('--klmno', help='klmno help') - group.add_argument('--pqrst', help='pqrst help') - return parser - - failures = ['--klmno X --pqrst Y'] - successes = [ - ('--klmno X', NS(abcde=None, fghij=None, klmno='X', pqrst=None)), - ('--abcde Y --klmno X', - NS(abcde='Y', fghij=None, klmno='X', pqrst=None)), - ('--pqrst X', NS(abcde=None, fghij=None, klmno=None, pqrst='X')), - ('--pqrst X --fghij Y', - NS(abcde=None, fghij='Y', klmno=None, pqrst='X')), - ] - successes_when_not_required = [ - ('', NS(abcde=None, fghij=None, klmno=None, pqrst=None)), - ] - - usage_when_not_required = '''\ - usage: PROG [-h] [--abcde ABCDE] [--fghij FGHIJ] - [--klmno KLMNO | --pqrst PQRST] - ''' - usage_when_required = '''\ - usage: PROG [-h] [--abcde ABCDE] [--fghij FGHIJ] - (--klmno KLMNO | --pqrst PQRST) - ''' - help = '''\ - - optional arguments: - -h, --help show this help message and exit - --abcde ABCDE abcde help - --fghij FGHIJ fghij help - --klmno KLMNO klmno help - --pqrst PQRST pqrst help - ''' - - -class TestMutuallyExclusiveFirstSuppressed(MEMixin, TestCase): - - def get_parser(self, required): - parser = ErrorRaisingArgumentParser(prog='PROG') - group = parser.add_mutually_exclusive_group(required=required) - group.add_argument('-x', help=argparse.SUPPRESS) - group.add_argument('-y', action='store_false', help='y help') - return parser - - failures = ['-x X -y'] - successes = [ - ('-x X', NS(x='X', y=True)), - ('-x X -x Y', NS(x='Y', y=True)), - ('-y', NS(x=None, y=False)), - ] - successes_when_not_required = [ - ('', NS(x=None, y=True)), - ] - - usage_when_not_required = '''\ - usage: PROG [-h] [-y] - ''' - usage_when_required = '''\ - usage: PROG [-h] -y - ''' - help = '''\ - - optional arguments: - -h, --help show this help message and exit - -y y help - ''' - - -class TestMutuallyExclusiveManySuppressed(MEMixin, TestCase): - - def get_parser(self, required): - parser = ErrorRaisingArgumentParser(prog='PROG') - group = parser.add_mutually_exclusive_group(required=required) - add = group.add_argument - add('--spam', action='store_true', help=argparse.SUPPRESS) - add('--badger', action='store_false', help=argparse.SUPPRESS) - add('--bladder', help=argparse.SUPPRESS) - return parser - - failures = [ - '--spam --badger', - '--badger --bladder B', - '--bladder B --spam', - ] - successes = [ - ('--spam', NS(spam=True, badger=True, bladder=None)), - ('--badger', NS(spam=False, badger=False, bladder=None)), - ('--bladder B', NS(spam=False, badger=True, bladder='B')), - ('--spam --spam', NS(spam=True, badger=True, bladder=None)), - ] - successes_when_not_required = [ - ('', NS(spam=False, badger=True, bladder=None)), - ] - - usage_when_required = usage_when_not_required = '''\ - usage: PROG [-h] - ''' - help = '''\ - - optional arguments: - -h, --help show this help message and exit - ''' - - -class TestMutuallyExclusiveOptionalAndPositional(MEMixin, TestCase): - - def get_parser(self, required): - parser = ErrorRaisingArgumentParser(prog='PROG') - group = parser.add_mutually_exclusive_group(required=required) - group.add_argument('--foo', action='store_true', help='FOO') - group.add_argument('--spam', help='SPAM') - group.add_argument('badger', nargs='*', default='X', help='BADGER') - return parser - - failures = [ - '--foo --spam S', - '--spam S X', - 'X --foo', - 'X Y Z --spam S', - '--foo X Y', - ] - successes = [ - ('--foo', NS(foo=True, spam=None, badger='X')), - ('--spam S', NS(foo=False, spam='S', badger='X')), - ('X', NS(foo=False, spam=None, badger=['X'])), - ('X Y Z', NS(foo=False, spam=None, badger=['X', 'Y', 'Z'])), - ] - successes_when_not_required = [ - ('', NS(foo=False, spam=None, badger='X')), - ] - - usage_when_not_required = '''\ - usage: PROG [-h] [--foo | --spam SPAM | badger [badger ...]] - ''' - usage_when_required = '''\ - usage: PROG [-h] (--foo | --spam SPAM | badger [badger ...]) - ''' - help = '''\ - - positional arguments: - badger BADGER - - optional arguments: - -h, --help show this help message and exit - --foo FOO - --spam SPAM SPAM - ''' - - -class TestMutuallyExclusiveOptionalsMixed(MEMixin, TestCase): - - def get_parser(self, required): - parser = ErrorRaisingArgumentParser(prog='PROG') - parser.add_argument('-x', action='store_true', help='x help') - group = parser.add_mutually_exclusive_group(required=required) - group.add_argument('-a', action='store_true', help='a help') - group.add_argument('-b', action='store_true', help='b help') - parser.add_argument('-y', action='store_true', help='y help') - group.add_argument('-c', action='store_true', help='c help') - return parser - - failures = ['-a -b', '-b -c', '-a -c', '-a -b -c'] - successes = [ - ('-a', NS(a=True, b=False, c=False, x=False, y=False)), - ('-b', NS(a=False, b=True, c=False, x=False, y=False)), - ('-c', NS(a=False, b=False, c=True, x=False, y=False)), - ('-a -x', NS(a=True, b=False, c=False, x=True, y=False)), - ('-y -b', NS(a=False, b=True, c=False, x=False, y=True)), - ('-x -y -c', NS(a=False, b=False, c=True, x=True, y=True)), - ] - successes_when_not_required = [ - ('', NS(a=False, b=False, c=False, x=False, y=False)), - ('-x', NS(a=False, b=False, c=False, x=True, y=False)), - ('-y', NS(a=False, b=False, c=False, x=False, y=True)), - ] - - usage_when_required = usage_when_not_required = '''\ - usage: PROG [-h] [-x] [-a] [-b] [-y] [-c] - ''' - help = '''\ - - optional arguments: - -h, --help show this help message and exit - -x x help - -a a help - -b b help - -y y help - -c c help - ''' - - -class TestMutuallyExclusiveOptionalsAndPositionalsMixed(MEMixin, TestCase): - - def get_parser(self, required): - parser = ErrorRaisingArgumentParser(prog='PROG') - parser.add_argument('x', help='x help') - parser.add_argument('-y', action='store_true', help='y help') - group = parser.add_mutually_exclusive_group(required=required) - group.add_argument('a', nargs='?', help='a help') - group.add_argument('-b', action='store_true', help='b help') - group.add_argument('-c', action='store_true', help='c help') - return parser - - failures = ['X A -b', '-b -c', '-c X A'] - successes = [ - ('X A', NS(a='A', b=False, c=False, x='X', y=False)), - ('X -b', NS(a=None, b=True, c=False, x='X', y=False)), - ('X -c', NS(a=None, b=False, c=True, x='X', y=False)), - ('X A -y', NS(a='A', b=False, c=False, x='X', y=True)), - ('X -y -b', NS(a=None, b=True, c=False, x='X', y=True)), - ] - successes_when_not_required = [ - ('X', NS(a=None, b=False, c=False, x='X', y=False)), - ('X -y', NS(a=None, b=False, c=False, x='X', y=True)), - ] - - usage_when_required = usage_when_not_required = '''\ - usage: PROG [-h] [-y] [-b] [-c] x [a] - ''' - help = '''\ - - positional arguments: - x x help - a a help - - optional arguments: - -h, --help show this help message and exit - -y y help - -b b help - -c c help - ''' - -# ================================================= -# Mutually exclusive group in parent parser tests -# ================================================= - -class MEPBase(object): - - def get_parser(self, required=None): - parent = super(MEPBase, self).get_parser(required=required) - parser = ErrorRaisingArgumentParser( - prog=parent.prog, add_help=False, parents=[parent]) - return parser - - -class TestMutuallyExclusiveGroupErrorsParent( - MEPBase, TestMutuallyExclusiveGroupErrors): - pass - - -class TestMutuallyExclusiveSimpleParent( - MEPBase, TestMutuallyExclusiveSimple): - pass - - -class TestMutuallyExclusiveLongParent( - MEPBase, TestMutuallyExclusiveLong): - pass - - -class TestMutuallyExclusiveFirstSuppressedParent( - MEPBase, TestMutuallyExclusiveFirstSuppressed): - pass - - -class TestMutuallyExclusiveManySuppressedParent( - MEPBase, TestMutuallyExclusiveManySuppressed): - pass - - -class TestMutuallyExclusiveOptionalAndPositionalParent( - MEPBase, TestMutuallyExclusiveOptionalAndPositional): - pass - - -class TestMutuallyExclusiveOptionalsMixedParent( - MEPBase, TestMutuallyExclusiveOptionalsMixed): - pass - - -class TestMutuallyExclusiveOptionalsAndPositionalsMixedParent( - MEPBase, TestMutuallyExclusiveOptionalsAndPositionalsMixed): - pass - -# ================= -# Set default tests -# ================= - -class TestSetDefaults(TestCase): - - def test_set_defaults_no_args(self): - parser = ErrorRaisingArgumentParser() - parser.set_defaults(x='foo') - parser.set_defaults(y='bar', z=1) - self.assertEqual(NS(x='foo', y='bar', z=1), - parser.parse_args([])) - self.assertEqual(NS(x='foo', y='bar', z=1), - parser.parse_args([], NS())) - self.assertEqual(NS(x='baz', y='bar', z=1), - parser.parse_args([], NS(x='baz'))) - self.assertEqual(NS(x='baz', y='bar', z=2), - parser.parse_args([], NS(x='baz', z=2))) - - def test_set_defaults_with_args(self): - parser = ErrorRaisingArgumentParser() - parser.set_defaults(x='foo', y='bar') - parser.add_argument('-x', default='xfoox') - self.assertEqual(NS(x='xfoox', y='bar'), - parser.parse_args([])) - self.assertEqual(NS(x='xfoox', y='bar'), - parser.parse_args([], NS())) - self.assertEqual(NS(x='baz', y='bar'), - parser.parse_args([], NS(x='baz'))) - self.assertEqual(NS(x='1', y='bar'), - parser.parse_args('-x 1'.split())) - self.assertEqual(NS(x='1', y='bar'), - parser.parse_args('-x 1'.split(), NS())) - self.assertEqual(NS(x='1', y='bar'), - parser.parse_args('-x 1'.split(), NS(x='baz'))) - - def test_set_defaults_subparsers(self): - parser = ErrorRaisingArgumentParser() - parser.set_defaults(x='foo') - subparsers = parser.add_subparsers() - parser_a = subparsers.add_parser('a') - parser_a.set_defaults(y='bar') - self.assertEqual(NS(x='foo', y='bar'), - parser.parse_args('a'.split())) - - def test_set_defaults_parents(self): - parent = ErrorRaisingArgumentParser(add_help=False) - parent.set_defaults(x='foo') - parser = ErrorRaisingArgumentParser(parents=[parent]) - self.assertEqual(NS(x='foo'), parser.parse_args([])) - - def test_set_defaults_same_as_add_argument(self): - parser = ErrorRaisingArgumentParser() - parser.set_defaults(w='W', x='X', y='Y', z='Z') - parser.add_argument('-w') - parser.add_argument('-x', default='XX') - parser.add_argument('y', nargs='?') - parser.add_argument('z', nargs='?', default='ZZ') - - # defaults set previously - self.assertEqual(NS(w='W', x='XX', y='Y', z='ZZ'), - parser.parse_args([])) - - # reset defaults - parser.set_defaults(w='WW', x='X', y='YY', z='Z') - self.assertEqual(NS(w='WW', x='X', y='YY', z='Z'), - parser.parse_args([])) - - def test_set_defaults_same_as_add_argument_group(self): - parser = ErrorRaisingArgumentParser() - parser.set_defaults(w='W', x='X', y='Y', z='Z') - group = parser.add_argument_group('foo') - group.add_argument('-w') - group.add_argument('-x', default='XX') - group.add_argument('y', nargs='?') - group.add_argument('z', nargs='?', default='ZZ') - - - # defaults set previously - self.assertEqual(NS(w='W', x='XX', y='Y', z='ZZ'), - parser.parse_args([])) - - # reset defaults - parser.set_defaults(w='WW', x='X', y='YY', z='Z') - self.assertEqual(NS(w='WW', x='X', y='YY', z='Z'), - parser.parse_args([])) - -# ================= -# Get default tests -# ================= - -class TestGetDefault(TestCase): - - def test_get_default(self): - parser = ErrorRaisingArgumentParser() - self.assertEqual(None, parser.get_default("foo")) - self.assertEqual(None, parser.get_default("bar")) - - parser.add_argument("--foo") - self.assertEqual(None, parser.get_default("foo")) - self.assertEqual(None, parser.get_default("bar")) - - parser.add_argument("--bar", type=int, default=42) - self.assertEqual(None, parser.get_default("foo")) - self.assertEqual(42, parser.get_default("bar")) - - parser.set_defaults(foo="badger") - self.assertEqual("badger", parser.get_default("foo")) - self.assertEqual(42, parser.get_default("bar")) - -# ========================== -# Namespace 'contains' tests -# ========================== - -class TestNamespaceContainsSimple(TestCase): - - def test_empty(self): - ns = argparse.Namespace() - self.assertEquals('' in ns, False) - self.assertEquals('' not in ns, True) - self.assertEquals('x' in ns, False) - - def test_non_empty(self): - ns = argparse.Namespace(x=1, y=2) - self.assertEquals('x' in ns, True) - self.assertEquals('x' not in ns, False) - self.assertEquals('y' in ns, True) - self.assertEquals('' in ns, False) - self.assertEquals('xx' in ns, False) - self.assertEquals('z' in ns, False) - -# ===================== -# Help formatting tests -# ===================== - -class TestHelpFormattingMetaclass(type): - - def __init__(cls, name, bases, bodydict): - if name == 'HelpTestCase': - return - - class AddTests(object): - - def __init__(self, test_class, func_suffix, std_name): - self.func_suffix = func_suffix - self.std_name = std_name - - for test_func in [self.test_format, - self.test_print, - self.test_print_file]: - test_name = '%s_%s' % (test_func.__name__, func_suffix) - - def test_wrapper(self, test_func=test_func): - test_func(self) - try: - test_wrapper.__name__ = test_name - except TypeError: - pass - setattr(test_class, test_name, test_wrapper) - - def _get_parser(self, tester): - parser = argparse.ArgumentParser( - *tester.parser_signature.args, - **tester.parser_signature.kwargs) - for argument_sig in tester.argument_signatures: - parser.add_argument(*argument_sig.args, - **argument_sig.kwargs) - group_signatures = tester.argument_group_signatures - for group_sig, argument_sigs in group_signatures: - group = parser.add_argument_group(*group_sig.args, - **group_sig.kwargs) - for argument_sig in argument_sigs: - group.add_argument(*argument_sig.args, - **argument_sig.kwargs) - return parser - - def _test(self, tester, parser_text): - expected_text = getattr(tester, self.func_suffix) - expected_text = textwrap.dedent(expected_text) - if expected_text != parser_text: - print(repr(expected_text)) - print(repr(parser_text)) - for char1, char2 in zip(expected_text, parser_text): - if char1 != char2: - print('first diff: %r %r' % (char1, char2)) - break - tester.assertEqual(expected_text, parser_text) - - def test_format(self, tester): - parser = self._get_parser(tester) - format = getattr(parser, 'format_%s' % self.func_suffix) - self._test(tester, format()) - - def test_print(self, tester): - parser = self._get_parser(tester) - print_ = getattr(parser, 'print_%s' % self.func_suffix) - old_stream = getattr(sys, self.std_name) - setattr(sys, self.std_name, StringIO()) - try: - print_() - parser_text = getattr(sys, self.std_name).getvalue() - finally: - setattr(sys, self.std_name, old_stream) - self._test(tester, parser_text) - - def test_print_file(self, tester): - parser = self._get_parser(tester) - print_ = getattr(parser, 'print_%s' % self.func_suffix) - sfile = StringIO() - print_(sfile) - parser_text = sfile.getvalue() - self._test(tester, parser_text) - - # add tests for {format,print}_{usage,help,version} - for func_suffix, std_name in [('usage', 'stdout'), - ('help', 'stdout'), - ('version', 'stderr')]: - AddTests(cls, func_suffix, std_name) - -bases = TestCase, -HelpTestCase = TestHelpFormattingMetaclass('HelpTestCase', bases, {}) - - -class TestHelpBiggerOptionals(HelpTestCase): - """Make sure that argument help aligns when options are longer""" - - parser_signature = Sig(prog='PROG', description='DESCRIPTION', - epilog='EPILOG', version='0.1') - argument_signatures = [ - Sig('-x', action='store_true', help='X HELP'), - Sig('--y', help='Y HELP'), - Sig('foo', help='FOO HELP'), - Sig('bar', help='BAR HELP'), - ] - argument_group_signatures = [] - usage = '''\ - usage: PROG [-h] [-v] [-x] [--y Y] foo bar - ''' - help = usage + '''\ - - DESCRIPTION - - positional arguments: - foo FOO HELP - bar BAR HELP - - optional arguments: - -h, --help show this help message and exit - -v, --version show program's version number and exit - -x X HELP - --y Y Y HELP - - EPILOG - ''' - version = '''\ - 0.1 - ''' - - -class TestHelpBiggerOptionalGroups(HelpTestCase): - """Make sure that argument help aligns when options are longer""" - - parser_signature = Sig(prog='PROG', description='DESCRIPTION', - epilog='EPILOG', version='0.1') - argument_signatures = [ - Sig('-x', action='store_true', help='X HELP'), - Sig('--y', help='Y HELP'), - Sig('foo', help='FOO HELP'), - Sig('bar', help='BAR HELP'), - ] - argument_group_signatures = [ - (Sig('GROUP TITLE', description='GROUP DESCRIPTION'), [ - Sig('baz', help='BAZ HELP'), - Sig('-z', nargs='+', help='Z HELP')]), - ] - usage = '''\ - usage: PROG [-h] [-v] [-x] [--y Y] [-z Z [Z ...]] foo bar baz - ''' - help = usage + '''\ - - DESCRIPTION - - positional arguments: - foo FOO HELP - bar BAR HELP - - optional arguments: - -h, --help show this help message and exit - -v, --version show program's version number and exit - -x X HELP - --y Y Y HELP - - GROUP TITLE: - GROUP DESCRIPTION - - baz BAZ HELP - -z Z [Z ...] Z HELP - - EPILOG - ''' - version = '''\ - 0.1 - ''' - - -class TestHelpBiggerPositionals(HelpTestCase): - """Make sure that help aligns when arguments are longer""" - - parser_signature = Sig(usage='USAGE', description='DESCRIPTION') - argument_signatures = [ - Sig('-x', action='store_true', help='X HELP'), - Sig('--y', help='Y HELP'), - Sig('ekiekiekifekang', help='EKI HELP'), - Sig('bar', help='BAR HELP'), - ] - argument_group_signatures = [] - usage = '''\ - usage: USAGE - ''' - help = usage + '''\ - - DESCRIPTION - - positional arguments: - ekiekiekifekang EKI HELP - bar BAR HELP - - optional arguments: - -h, --help show this help message and exit - -x X HELP - --y Y Y HELP - ''' - - version = '' - - -class TestHelpReformatting(HelpTestCase): - """Make sure that text after short names starts on the first line""" - - parser_signature = Sig( - prog='PROG', - description=' oddly formatted\n' - 'description\n' - '\n' - 'that is so long that it should go onto multiple ' - 'lines when wrapped') - argument_signatures = [ - Sig('-x', metavar='XX', help='oddly\n' - ' formatted -x help'), - Sig('y', metavar='yyy', help='normal y help'), - ] - argument_group_signatures = [ - (Sig('title', description='\n' - ' oddly formatted group\n' - '\n' - 'description'), - [Sig('-a', action='store_true', - help=' oddly \n' - 'formatted -a help \n' - ' again, so long that it should be wrapped over ' - 'multiple lines')]), - ] - usage = '''\ - usage: PROG [-h] [-x XX] [-a] yyy - ''' - help = usage + '''\ - - oddly formatted description that is so long that it should go onto \ -multiple - lines when wrapped - - positional arguments: - yyy normal y help - - optional arguments: - -h, --help show this help message and exit - -x XX oddly formatted -x help - - title: - oddly formatted group description - - -a oddly formatted -a help again, so long that it should \ -be wrapped - over multiple lines - ''' - version = '' - - -class TestHelpWrappingShortNames(HelpTestCase): - """Make sure that text after short names starts on the first line""" - - parser_signature = Sig(prog='PROG', description= 'D\nD' * 30) - argument_signatures = [ - Sig('-x', metavar='XX', help='XHH HX' * 20), - Sig('y', metavar='yyy', help='YH YH' * 20), - ] - argument_group_signatures = [ - (Sig('ALPHAS'), [ - Sig('-a', action='store_true', help='AHHH HHA' * 10)]), - ] - usage = '''\ - usage: PROG [-h] [-x XX] [-a] yyy - ''' - help = usage + '''\ - - D DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD \ -DD DD DD - DD DD DD DD D - - positional arguments: - yyy YH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH \ -YHYH YHYH - YHYH YHYH YHYH YHYH YHYH YHYH YHYH YH - - optional arguments: - -h, --help show this help message and exit - -x XX XHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH \ -HXXHH HXXHH - HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HXXHH HX - - ALPHAS: - -a AHHH HHAAHHH HHAAHHH HHAAHHH HHAAHHH HHAAHHH HHAAHHH \ -HHAAHHH - HHAAHHH HHAAHHH HHA - ''' - version = '' - - -class TestHelpWrappingLongNames(HelpTestCase): - """Make sure that text after long names starts on the next line""" - - parser_signature = Sig(usage='USAGE', description= 'D D' * 30, - version='V V'*30) - argument_signatures = [ - Sig('-x', metavar='X' * 25, help='XH XH' * 20), - Sig('y', metavar='y' * 25, help='YH YH' * 20), - ] - argument_group_signatures = [ - (Sig('ALPHAS'), [ - Sig('-a', metavar='A' * 25, help='AH AH' * 20), - Sig('z', metavar='z' * 25, help='ZH ZH' * 20)]), - ] - usage = '''\ - usage: USAGE - ''' - help = usage + '''\ - - D DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD \ -DD DD DD - DD DD DD DD D - - positional arguments: - yyyyyyyyyyyyyyyyyyyyyyyyy - YH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH \ -YHYH YHYH - YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YHYH YH - - optional arguments: - -h, --help show this help message and exit - -v, --version show program's version number and exit - -x XXXXXXXXXXXXXXXXXXXXXXXXX - XH XHXH XHXH XHXH XHXH XHXH XHXH XHXH XHXH \ -XHXH XHXH - XHXH XHXH XHXH XHXH XHXH XHXH XHXH XHXH XHXH XH - - ALPHAS: - -a AAAAAAAAAAAAAAAAAAAAAAAAA - AH AHAH AHAH AHAH AHAH AHAH AHAH AHAH AHAH \ -AHAH AHAH - AHAH AHAH AHAH AHAH AHAH AHAH AHAH AHAH AHAH AH - zzzzzzzzzzzzzzzzzzzzzzzzz - ZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH \ -ZHZH ZHZH - ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZHZH ZH - ''' - version = '''\ - V VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV VV \ -VV VV VV - VV VV VV VV V - ''' - - -class TestHelpUsage(HelpTestCase): - """Test basic usage messages""" - - parser_signature = Sig(prog='PROG') - argument_signatures = [ - Sig('-w', nargs='+', help='w'), - Sig('-x', nargs='*', help='x'), - Sig('a', help='a'), - Sig('b', help='b', nargs=2), - Sig('c', help='c', nargs='?'), - ] - argument_group_signatures = [ - (Sig('group'), [ - Sig('-y', nargs='?', help='y'), - Sig('-z', nargs=3, help='z'), - Sig('d', help='d', nargs='*'), - Sig('e', help='e', nargs='+'), - ]) - ] - usage = '''\ - usage: PROG [-h] [-w W [W ...]] [-x [X [X ...]]] [-y [Y]] [-z Z Z Z] - a b b [c] [d [d ...]] e [e ...] - ''' - help = usage + '''\ - - positional arguments: - a a - b b - c c - - optional arguments: - -h, --help show this help message and exit - -w W [W ...] w - -x [X [X ...]] x - - group: - -y [Y] y - -z Z Z Z z - d d - e e - ''' - version = '' - - -class TestHelpOnlyUserGroups(HelpTestCase): - """Test basic usage messages""" - - parser_signature = Sig(prog='PROG', add_help=False) - argument_signatures = [] - argument_group_signatures = [ - (Sig('xxxx'), [ - Sig('-x', help='x'), - Sig('a', help='a'), - ]), - (Sig('yyyy'), [ - Sig('b', help='b'), - Sig('-y', help='y'), - ]), - ] - usage = '''\ - usage: PROG [-x X] [-y Y] a b - ''' - help = usage + '''\ - - xxxx: - -x X x - a a - - yyyy: - b b - -y Y y - ''' - version = '' - - -class TestHelpUsageLongProg(HelpTestCase): - """Test usage messages where the prog is long""" - - parser_signature = Sig(prog='P' * 60) - argument_signatures = [ - Sig('-w', metavar='W'), - Sig('-x', metavar='X'), - Sig('a'), - Sig('b'), - ] - argument_group_signatures = [] - usage = '''\ - usage: PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP - [-h] [-w W] [-x X] a b - ''' - help = usage + '''\ - - positional arguments: - a - b - - optional arguments: - -h, --help show this help message and exit - -w W - -x X - ''' - version = '' - - -class TestHelpUsageLongProgOptionsWrap(HelpTestCase): - """Test usage messages where the prog is long and the optionals wrap""" - - parser_signature = Sig(prog='P' * 60) - argument_signatures = [ - Sig('-w', metavar='W' * 25), - Sig('-x', metavar='X' * 25), - Sig('-y', metavar='Y' * 25), - Sig('-z', metavar='Z' * 25), - Sig('a'), - Sig('b'), - ] - argument_group_signatures = [] - usage = '''\ - usage: PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP - [-h] [-w WWWWWWWWWWWWWWWWWWWWWWWWW] \ -[-x XXXXXXXXXXXXXXXXXXXXXXXXX] - [-y YYYYYYYYYYYYYYYYYYYYYYYYY] [-z ZZZZZZZZZZZZZZZZZZZZZZZZZ] - a b - ''' - help = usage + '''\ - - positional arguments: - a - b - - optional arguments: - -h, --help show this help message and exit - -w WWWWWWWWWWWWWWWWWWWWWWWWW - -x XXXXXXXXXXXXXXXXXXXXXXXXX - -y YYYYYYYYYYYYYYYYYYYYYYYYY - -z ZZZZZZZZZZZZZZZZZZZZZZZZZ - ''' - version = '' - - -class TestHelpUsageLongProgPositionalsWrap(HelpTestCase): - """Test usage messages where the prog is long and the positionals wrap""" - - parser_signature = Sig(prog='P' * 60, add_help=False) - argument_signatures = [ - Sig('a' * 25), - Sig('b' * 25), - Sig('c' * 25), - ] - argument_group_signatures = [] - usage = '''\ - usage: PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP - aaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbb - ccccccccccccccccccccccccc - ''' - help = usage + '''\ - - positional arguments: - aaaaaaaaaaaaaaaaaaaaaaaaa - bbbbbbbbbbbbbbbbbbbbbbbbb - ccccccccccccccccccccccccc - ''' - version = '' - - -class TestHelpUsageOptionalsWrap(HelpTestCase): - """Test usage messages where the optionals wrap""" - - parser_signature = Sig(prog='PROG') - argument_signatures = [ - Sig('-w', metavar='W' * 25), - Sig('-x', metavar='X' * 25), - Sig('-y', metavar='Y' * 25), - Sig('-z', metavar='Z' * 25), - Sig('a'), - Sig('b'), - Sig('c'), - ] - argument_group_signatures = [] - usage = '''\ - usage: PROG [-h] [-w WWWWWWWWWWWWWWWWWWWWWWWWW] \ -[-x XXXXXXXXXXXXXXXXXXXXXXXXX] - [-y YYYYYYYYYYYYYYYYYYYYYYYYY] \ -[-z ZZZZZZZZZZZZZZZZZZZZZZZZZ] - a b c - ''' - help = usage + '''\ - - positional arguments: - a - b - c - - optional arguments: - -h, --help show this help message and exit - -w WWWWWWWWWWWWWWWWWWWWWWWWW - -x XXXXXXXXXXXXXXXXXXXXXXXXX - -y YYYYYYYYYYYYYYYYYYYYYYYYY - -z ZZZZZZZZZZZZZZZZZZZZZZZZZ - ''' - version = '' - - -class TestHelpUsagePositionalsWrap(HelpTestCase): - """Test usage messages where the positionals wrap""" - - parser_signature = Sig(prog='PROG') - argument_signatures = [ - Sig('-x'), - Sig('-y'), - Sig('-z'), - Sig('a' * 25), - Sig('b' * 25), - Sig('c' * 25), - ] - argument_group_signatures = [] - usage = '''\ - usage: PROG [-h] [-x X] [-y Y] [-z Z] - aaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbb - ccccccccccccccccccccccccc - ''' - help = usage + '''\ - - positional arguments: - aaaaaaaaaaaaaaaaaaaaaaaaa - bbbbbbbbbbbbbbbbbbbbbbbbb - ccccccccccccccccccccccccc - - optional arguments: - -h, --help show this help message and exit - -x X - -y Y - -z Z - ''' - version = '' - - -class TestHelpUsageOptionalsPositionalsWrap(HelpTestCase): - """Test usage messages where the optionals and positionals wrap""" - - parser_signature = Sig(prog='PROG') - argument_signatures = [ - Sig('-x', metavar='X' * 25), - Sig('-y', metavar='Y' * 25), - Sig('-z', metavar='Z' * 25), - Sig('a' * 25), - Sig('b' * 25), - Sig('c' * 25), - ] - argument_group_signatures = [] - usage = '''\ - usage: PROG [-h] [-x XXXXXXXXXXXXXXXXXXXXXXXXX] \ -[-y YYYYYYYYYYYYYYYYYYYYYYYYY] - [-z ZZZZZZZZZZZZZZZZZZZZZZZZZ] - aaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbb - ccccccccccccccccccccccccc - ''' - help = usage + '''\ - - positional arguments: - aaaaaaaaaaaaaaaaaaaaaaaaa - bbbbbbbbbbbbbbbbbbbbbbbbb - ccccccccccccccccccccccccc - - optional arguments: - -h, --help show this help message and exit - -x XXXXXXXXXXXXXXXXXXXXXXXXX - -y YYYYYYYYYYYYYYYYYYYYYYYYY - -z ZZZZZZZZZZZZZZZZZZZZZZZZZ - ''' - version = '' - - -class TestHelpUsageOptionalsOnlyWrap(HelpTestCase): - """Test usage messages where there are only optionals and they wrap""" - - parser_signature = Sig(prog='PROG') - argument_signatures = [ - Sig('-x', metavar='X' * 25), - Sig('-y', metavar='Y' * 25), - Sig('-z', metavar='Z' * 25), - ] - argument_group_signatures = [] - usage = '''\ - usage: PROG [-h] [-x XXXXXXXXXXXXXXXXXXXXXXXXX] \ -[-y YYYYYYYYYYYYYYYYYYYYYYYYY] - [-z ZZZZZZZZZZZZZZZZZZZZZZZZZ] - ''' - help = usage + '''\ - - optional arguments: - -h, --help show this help message and exit - -x XXXXXXXXXXXXXXXXXXXXXXXXX - -y YYYYYYYYYYYYYYYYYYYYYYYYY - -z ZZZZZZZZZZZZZZZZZZZZZZZZZ - ''' - version = '' - - -class TestHelpUsagePositionalsOnlyWrap(HelpTestCase): - """Test usage messages where there are only positionals and they wrap""" - - parser_signature = Sig(prog='PROG', add_help=False) - argument_signatures = [ - Sig('a' * 25), - Sig('b' * 25), - Sig('c' * 25), - ] - argument_group_signatures = [] - usage = '''\ - usage: PROG aaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbb - ccccccccccccccccccccccccc - ''' - help = usage + '''\ - - positional arguments: - aaaaaaaaaaaaaaaaaaaaaaaaa - bbbbbbbbbbbbbbbbbbbbbbbbb - ccccccccccccccccccccccccc - ''' - version = '' - - -class TestHelpVariableExpansion(HelpTestCase): - """Test that variables are expanded properly in help messages""" - - parser_signature = Sig(prog='PROG') - argument_signatures = [ - Sig('-x', type=int, - help='x %(prog)s %(default)s %(type)s %%'), - Sig('-y', action='store_const', default=42, const='XXX', - help='y %(prog)s %(default)s %(const)s'), - Sig('--foo', choices='abc', - help='foo %(prog)s %(default)s %(choices)s'), - Sig('--bar', default='baz', choices=[1, 2], metavar='BBB', - help='bar %(prog)s %(default)s %(dest)s'), - Sig('spam', help='spam %(prog)s %(default)s'), - Sig('badger', default=0.5, help='badger %(prog)s %(default)s'), - ] - argument_group_signatures = [ - (Sig('group'), [ - Sig('-a', help='a %(prog)s %(default)s'), - Sig('-b', default=-1, help='b %(prog)s %(default)s'), - ]) - ] - usage = ('''\ - usage: PROG [-h] [-x X] [-y] [--foo {a,b,c}] [--bar BBB] [-a A] [-b B] - spam badger - ''') - help = usage + '''\ - - positional arguments: - spam spam PROG None - badger badger PROG 0.5 - - optional arguments: - -h, --help show this help message and exit - -x X x PROG None int % - -y y PROG 42 XXX - --foo {a,b,c} foo PROG None a, b, c - --bar BBB bar PROG baz bar - - group: - -a A a PROG None - -b B b PROG -1 - ''' - version = '' - - -class TestHelpVariableExpansionUsageSupplied(HelpTestCase): - """Test that variables are expanded properly when usage= is present""" - - parser_signature = Sig(prog='PROG', usage='%(prog)s FOO') - argument_signatures = [] - argument_group_signatures = [] - usage = ('''\ - usage: PROG FOO - ''') - help = usage + '''\ - - optional arguments: - -h, --help show this help message and exit - ''' - version = '' - - -class TestHelpVariableExpansionNoArguments(HelpTestCase): - """Test that variables are expanded properly with no arguments""" - - parser_signature = Sig(prog='PROG', add_help=False) - argument_signatures = [] - argument_group_signatures = [] - usage = ('''\ - usage: PROG - ''') - help = usage - version = '' - - -class TestHelpSuppressUsage(HelpTestCase): - """Test that items can be suppressed in usage messages""" - - parser_signature = Sig(prog='PROG', usage=argparse.SUPPRESS) - argument_signatures = [ - Sig('--foo', help='foo help'), - Sig('spam', help='spam help'), - ] - argument_group_signatures = [] - help = '''\ - positional arguments: - spam spam help - - optional arguments: - -h, --help show this help message and exit - --foo FOO foo help - ''' - usage = '' - version = '' - - -class TestHelpSuppressOptional(HelpTestCase): - """Test that optional arguments can be suppressed in help messages""" - - parser_signature = Sig(prog='PROG', add_help=False) - argument_signatures = [ - Sig('--foo', help=argparse.SUPPRESS), - Sig('spam', help='spam help'), - ] - argument_group_signatures = [] - usage = '''\ - usage: PROG spam - ''' - help = usage + '''\ - - positional arguments: - spam spam help - ''' - version = '' - - -class TestHelpSuppressOptionalGroup(HelpTestCase): - """Test that optional groups can be suppressed in help messages""" - - parser_signature = Sig(prog='PROG') - argument_signatures = [ - Sig('--foo', help='foo help'), - Sig('spam', help='spam help'), - ] - argument_group_signatures = [ - (Sig('group'), [Sig('--bar', help=argparse.SUPPRESS)]), - ] - usage = '''\ - usage: PROG [-h] [--foo FOO] spam - ''' - help = usage + '''\ - - positional arguments: - spam spam help - - optional arguments: - -h, --help show this help message and exit - --foo FOO foo help - ''' - version = '' - - -class TestHelpSuppressPositional(HelpTestCase): - """Test that positional arguments can be suppressed in help messages""" - - parser_signature = Sig(prog='PROG') - argument_signatures = [ - Sig('--foo', help='foo help'), - Sig('spam', help=argparse.SUPPRESS), - ] - argument_group_signatures = [] - usage = '''\ - usage: PROG [-h] [--foo FOO] - ''' - help = usage + '''\ - - optional arguments: - -h, --help show this help message and exit - --foo FOO foo help - ''' - version = '' - - -class TestHelpRequiredOptional(HelpTestCase): - """Test that required options don't look optional""" - - parser_signature = Sig(prog='PROG') - argument_signatures = [ - Sig('--foo', required=True, help='foo help'), - ] - argument_group_signatures = [] - usage = '''\ - usage: PROG [-h] --foo FOO - ''' - help = usage + '''\ - - optional arguments: - -h, --help show this help message and exit - --foo FOO foo help - ''' - version = '' - - -class TestHelpAlternatePrefixChars(HelpTestCase): - """Test that options display with different prefix characters""" - - parser_signature = Sig(prog='PROG', prefix_chars='^;', add_help=False) - argument_signatures = [ - Sig('^^foo', action='store_true', help='foo help'), - Sig(';b', ';;bar', help='bar help'), - ] - argument_group_signatures = [] - usage = '''\ - usage: PROG [^^foo] [;b BAR] - ''' - help = usage + '''\ - - optional arguments: - ^^foo foo help - ;b BAR, ;;bar BAR bar help - ''' - version = '' - - -class TestHelpNoHelpOptional(HelpTestCase): - """Test that the --help argument can be suppressed help messages""" - - parser_signature = Sig(prog='PROG', add_help=False) - argument_signatures = [ - Sig('--foo', help='foo help'), - Sig('spam', help='spam help'), - ] - argument_group_signatures = [] - usage = '''\ - usage: PROG [--foo FOO] spam - ''' - help = usage + '''\ - - positional arguments: - spam spam help - - optional arguments: - --foo FOO foo help - ''' - version = '' - - -class TestHelpVersionOptional(HelpTestCase): - """Test that the --version argument can be suppressed help messages""" - - parser_signature = Sig(prog='PROG', version='1.0') - argument_signatures = [ - Sig('--foo', help='foo help'), - Sig('spam', help='spam help'), - ] - argument_group_signatures = [] - usage = '''\ - usage: PROG [-h] [-v] [--foo FOO] spam - ''' - help = usage + '''\ - - positional arguments: - spam spam help - - optional arguments: - -h, --help show this help message and exit - -v, --version show program's version number and exit - --foo FOO foo help - ''' - version = '''\ - 1.0 - ''' - - -class TestHelpNone(HelpTestCase): - """Test that no errors occur if no help is specified""" - - parser_signature = Sig(prog='PROG') - argument_signatures = [ - Sig('--foo'), - Sig('spam'), - ] - argument_group_signatures = [] - usage = '''\ - usage: PROG [-h] [--foo FOO] spam - ''' - help = usage + '''\ - - positional arguments: - spam - - optional arguments: - -h, --help show this help message and exit - --foo FOO - ''' - version = '' - - -class TestHelpTupleMetavar(HelpTestCase): - """Test specifying metavar as a tuple""" - - parser_signature = Sig(prog='PROG') - argument_signatures = [ - Sig('-w', help='w', nargs='+', metavar=('W1', 'W2')), - Sig('-x', help='x', nargs='*', metavar=('X1', 'X2')), - Sig('-y', help='y', nargs=3, metavar=('Y1', 'Y2', 'Y3')), - Sig('-z', help='z', nargs='?', metavar=('Z1', )), - ] - argument_group_signatures = [] - usage = '''\ - usage: PROG [-h] [-w W1 [W2 ...]] [-x [X1 [X2 ...]]] [-y Y1 Y2 Y3] \ -[-z [Z1]] - ''' - help = usage + '''\ - - optional arguments: - -h, --help show this help message and exit - -w W1 [W2 ...] w - -x [X1 [X2 ...]] x - -y Y1 Y2 Y3 y - -z [Z1] z - ''' - version = '' - - -class TestHelpRawText(HelpTestCase): - """Test the RawTextHelpFormatter""" - - parser_signature = Sig( - prog='PROG', formatter_class=argparse.RawTextHelpFormatter, - description='Keep the formatting\n' - ' exactly as it is written\n' - '\n' - 'here\n') - - argument_signatures = [ - Sig('--foo', help=' foo help should also\n' - 'appear as given here'), - Sig('spam', help='spam help'), - ] - argument_group_signatures = [ - (Sig('title', description=' This text\n' - ' should be indented\n' - ' exactly like it is here\n'), - [Sig('--bar', help='bar help')]), - ] - usage = '''\ - usage: PROG [-h] [--foo FOO] [--bar BAR] spam - ''' - help = usage + '''\ - - Keep the formatting - exactly as it is written - - here - - positional arguments: - spam spam help - - optional arguments: - -h, --help show this help message and exit - --foo FOO foo help should also - appear as given here - - title: - This text - should be indented - exactly like it is here - - --bar BAR bar help - ''' - version = '' - - -class TestHelpRawDescription(HelpTestCase): - """Test the RawTextHelpFormatter""" - - parser_signature = Sig( - prog='PROG', formatter_class=argparse.RawDescriptionHelpFormatter, - description='Keep the formatting\n' - ' exactly as it is written\n' - '\n' - 'here\n') - - argument_signatures = [ - Sig('--foo', help=' foo help should not\n' - ' retain this odd formatting'), - Sig('spam', help='spam help'), - ] - argument_group_signatures = [ - (Sig('title', description=' This text\n' - ' should be indented\n' - ' exactly like it is here\n'), - [Sig('--bar', help='bar help')]), - ] - usage = '''\ - usage: PROG [-h] [--foo FOO] [--bar BAR] spam - ''' - help = usage + '''\ - - Keep the formatting - exactly as it is written - - here - - positional arguments: - spam spam help - - optional arguments: - -h, --help show this help message and exit - --foo FOO foo help should not retain this odd formatting - - title: - This text - should be indented - exactly like it is here - - --bar BAR bar help - ''' - version = '' - - -class TestHelpArgumentDefaults(HelpTestCase): - """Test the ArgumentDefaultsHelpFormatter""" - - parser_signature = Sig( - prog='PROG', formatter_class=argparse.ArgumentDefaultsHelpFormatter, - description='description') - - argument_signatures = [ - Sig('--foo', help='foo help - oh and by the way, %(default)s'), - Sig('--bar', action='store_true', help='bar help'), - Sig('spam', help='spam help'), - Sig('badger', nargs='?', default='wooden', help='badger help'), - ] - argument_group_signatures = [ - (Sig('title', description='description'), - [Sig('--baz', type=int, default=42, help='baz help')]), - ] - usage = '''\ - usage: PROG [-h] [--foo FOO] [--bar] [--baz BAZ] spam [badger] - ''' - help = usage + '''\ - - description - - positional arguments: - spam spam help - badger badger help (default: wooden) - - optional arguments: - -h, --help show this help message and exit - --foo FOO foo help - oh and by the way, None - --bar bar help (default: False) - - title: - description - - --baz BAZ baz help (default: 42) - ''' - version = '' - -# ===================================== -# Optional/Positional constructor tests -# ===================================== - -class TestInvalidArgumentConstructors(TestCase): - """Test a bunch of invalid Argument constructors""" - - def assertTypeError(self, *args, **kwargs): - parser = argparse.ArgumentParser() - self.assertRaises(TypeError, parser.add_argument, - *args, **kwargs) - - def assertValueError(self, *args, **kwargs): - parser = argparse.ArgumentParser() - self.assertRaises(ValueError, parser.add_argument, - *args, **kwargs) - - def test_invalid_keyword_arguments(self): - self.assertTypeError('-x', bar=None) - self.assertTypeError('-y', callback='foo') - self.assertTypeError('-y', callback_args=()) - self.assertTypeError('-y', callback_kwargs={}) - - def test_missing_destination(self): - self.assertTypeError() - for action in ['append', 'store']: - self.assertTypeError(action=action) - - def test_invalid_option_strings(self): - self.assertValueError('--') - self.assertValueError('---') - - def test_invalid_type(self): - self.assertValueError('--foo', type='int') - - def test_invalid_action(self): - self.assertValueError('-x', action='foo') - self.assertValueError('foo', action='baz') - parser = argparse.ArgumentParser() - try: - parser.add_argument("--foo", action="store-true") - except ValueError: - e = sys.exc_info()[1] - expected = 'unknown action' - msg = 'expected %r, found %r' % (expected, e) - self.failUnless(expected in str(e), msg) - - def test_multiple_dest(self): - parser = argparse.ArgumentParser() - parser.add_argument(dest='foo') - try: - parser.add_argument('bar', dest='baz') - except ValueError: - e = sys.exc_info()[1] - expected = 'dest supplied twice for positional argument' - msg = 'expected %r, found %r' % (expected, e) - self.failUnless(expected in str(e), msg) - - def test_no_argument_actions(self): - for action in ['store_const', 'store_true', 'store_false', - 'append_const', 'count']: - for attrs in [dict(type=int), dict(nargs='+'), - dict(choices='ab')]: - self.assertTypeError('-x', action=action, **attrs) - - def test_no_argument_no_const_actions(self): - # options with zero arguments - for action in ['store_true', 'store_false', 'count']: - - # const is always disallowed - self.assertTypeError('-x', const='foo', action=action) - - # nargs is always disallowed - self.assertTypeError('-x', nargs='*', action=action) - - def test_more_than_one_argument_actions(self): - for action in ['store', 'append']: - - # nargs=0 is disallowed - self.assertValueError('-x', nargs=0, action=action) - self.assertValueError('spam', nargs=0, action=action) - - # const is disallowed with non-optional arguments - for nargs in [1, '*', '+']: - self.assertValueError('-x', const='foo', - nargs=nargs, action=action) - self.assertValueError('spam', const='foo', - nargs=nargs, action=action) - - def test_required_const_actions(self): - for action in ['store_const', 'append_const']: - - # nargs is always disallowed - self.assertTypeError('-x', nargs='+', action=action) - - def test_parsers_action_missing_params(self): - self.assertTypeError('command', action='parsers') - self.assertTypeError('command', action='parsers', prog='PROG') - self.assertTypeError('command', action='parsers', - parser_class=argparse.ArgumentParser) - - def test_required_positional(self): - self.assertTypeError('foo', required=True) - - def test_user_defined_action(self): - - class Success(Exception): - pass - - class Action(object): - - def __init__(self, - option_strings, - dest, - const, - default, - required=False): - if dest == 'spam': - if const is Success: - if default is Success: - raise Success() - - def __call__(self, *args, **kwargs): - pass - - parser = argparse.ArgumentParser() - self.assertRaises(Success, parser.add_argument, '--spam', - action=Action, default=Success, const=Success) - self.assertRaises(Success, parser.add_argument, 'spam', - action=Action, default=Success, const=Success) - -# ================================ -# Actions returned by add_argument -# ================================ - -class TestActionsReturned(TestCase): - - def test_dest(self): - parser = argparse.ArgumentParser() - action = parser.add_argument('--foo') - self.assertEqual(action.dest, 'foo') - action = parser.add_argument('-b', '--bar') - self.assertEqual(action.dest, 'bar') - action = parser.add_argument('-x', '-y') - self.assertEqual(action.dest, 'x') - - def test_misc(self): - parser = argparse.ArgumentParser() - action = parser.add_argument('--foo', nargs='?', const=42, - default=84, type=int, choices=[1, 2], - help='FOO', metavar='BAR', dest='baz') - self.assertEqual(action.nargs, '?') - self.assertEqual(action.const, 42) - self.assertEqual(action.default, 84) - self.assertEqual(action.type, int) - self.assertEqual(action.choices, [1, 2]) - self.assertEqual(action.help, 'FOO') - self.assertEqual(action.metavar, 'BAR') - self.assertEqual(action.dest, 'baz') - - -# ================================ -# Argument conflict handling tests -# ================================ - -class TestConflictHandling(TestCase): - - def test_bad_type(self): - self.assertRaises(ValueError, argparse.ArgumentParser, - conflict_handler='foo') - - def test_conflict_error(self): - parser = argparse.ArgumentParser() - parser.add_argument('-x') - self.assertRaises(argparse.ArgumentError, - parser.add_argument, '-x') - parser.add_argument('--spam') - self.assertRaises(argparse.ArgumentError, - parser.add_argument, '--spam') - - def test_resolve_error(self): - get_parser = argparse.ArgumentParser - parser = get_parser(prog='PROG', conflict_handler='resolve') - - parser.add_argument('-x', help='OLD X') - parser.add_argument('-x', help='NEW X') - self.assertEqual(parser.format_help(), textwrap.dedent('''\ - usage: PROG [-h] [-x X] - - optional arguments: - -h, --help show this help message and exit - -x X NEW X - ''')) - - parser.add_argument('--spam', metavar='OLD_SPAM') - parser.add_argument('--spam', metavar='NEW_SPAM') - self.assertEqual(parser.format_help(), textwrap.dedent('''\ - usage: PROG [-h] [-x X] [--spam NEW_SPAM] - - optional arguments: - -h, --help show this help message and exit - -x X NEW X - --spam NEW_SPAM - ''')) - - -# ============================= -# Help and Version option tests -# ============================= - -class TestOptionalsHelpVersionActions(TestCase): - """Test the help and version actions""" - - def _get_error(self, func, *args, **kwargs): - try: - func(*args, **kwargs) - except ArgumentParserError: - return sys.exc_info()[1] - else: - self.assertRaises(ArgumentParserError, func, *args, **kwargs) - - def assertPrintHelpExit(self, parser, args_str): - self.assertEqual( - parser.format_help(), - self._get_error(parser.parse_args, args_str.split()).stdout) - - def assertPrintVersionExit(self, parser, args_str): - self.assertEqual( - parser.format_version(), - self._get_error(parser.parse_args, args_str.split()).stderr) - - def assertArgumentParserError(self, parser, *args): - self.assertRaises(ArgumentParserError, parser.parse_args, args) - - def test_version(self): - parser = ErrorRaisingArgumentParser(version='1.0') - self.assertPrintHelpExit(parser, '-h') - self.assertPrintHelpExit(parser, '--help') - self.assertPrintVersionExit(parser, '-v') - self.assertPrintVersionExit(parser, '--version') - - def test_version_format(self): - parser = ErrorRaisingArgumentParser(prog='PPP', version='%(prog)s 3.5') - msg = self._get_error(parser.parse_args, ['-v']).stderr - self.assertEqual('PPP 3.5\n', msg) - - def test_version_no_help(self): - parser = ErrorRaisingArgumentParser(add_help=False, version='1.0') - self.assertArgumentParserError(parser, '-h') - self.assertArgumentParserError(parser, '--help') - self.assertPrintVersionExit(parser, '-v') - self.assertPrintVersionExit(parser, '--version') - - def test_version_action(self): - parser = ErrorRaisingArgumentParser(prog='XXX') - parser.add_argument('-V', action='version', version='%(prog)s 3.7') - msg = self._get_error(parser.parse_args, ['-V']).stderr - self.assertEqual('XXX 3.7\n', msg) - - def test_no_help(self): - parser = ErrorRaisingArgumentParser(add_help=False) - self.assertArgumentParserError(parser, '-h') - self.assertArgumentParserError(parser, '--help') - self.assertArgumentParserError(parser, '-v') - self.assertArgumentParserError(parser, '--version') - - def test_alternate_help_version(self): - parser = ErrorRaisingArgumentParser() - parser.add_argument('-x', action='help') - parser.add_argument('-y', action='version') - self.assertPrintHelpExit(parser, '-x') - self.assertPrintVersionExit(parser, '-y') - self.assertArgumentParserError(parser, '-v') - self.assertArgumentParserError(parser, '--version') - - def test_help_version_extra_arguments(self): - parser = ErrorRaisingArgumentParser(version='1.0') - parser.add_argument('-x', action='store_true') - parser.add_argument('y') - - # try all combinations of valid prefixes and suffixes - valid_prefixes = ['', '-x', 'foo', '-x bar', 'baz -x'] - valid_suffixes = valid_prefixes + ['--bad-option', 'foo bar baz'] - for prefix in valid_prefixes: - for suffix in valid_suffixes: - format = '%s %%s %s' % (prefix, suffix) - self.assertPrintHelpExit(parser, format % '-h') - self.assertPrintHelpExit(parser, format % '--help') - self.assertPrintVersionExit(parser, format % '-v') - self.assertPrintVersionExit(parser, format % '--version') - - -# ====================== -# str() and repr() tests -# ====================== - -class TestStrings(TestCase): - """Test str() and repr() on Optionals and Positionals""" - - def assertStringEqual(self, obj, result_string): - for func in [str, repr]: - self.assertEqual(func(obj), result_string) - - def test_optional(self): - option = argparse.Action( - option_strings=['--foo', '-a', '-b'], - dest='b', - type='int', - nargs='+', - default=42, - choices=[1, 2, 3], - help='HELP', - metavar='METAVAR') - string = ( - "Action(option_strings=['--foo', '-a', '-b'], dest='b', " - "nargs='+', const=None, default=42, type='int', " - "choices=[1, 2, 3], help='HELP', metavar='METAVAR')") - self.assertStringEqual(option, string) - - def test_argument(self): - argument = argparse.Action( - option_strings=[], - dest='x', - type=float, - nargs='?', - default=2.5, - choices=[0.5, 1.5, 2.5], - help='H HH H', - metavar='MV MV MV') - string = ( - "Action(option_strings=[], dest='x', nargs='?', " - "const=None, default=2.5, type=%r, choices=[0.5, 1.5, 2.5], " - "help='H HH H', metavar='MV MV MV')" % float) - self.assertStringEqual(argument, string) - - def test_namespace(self): - ns = argparse.Namespace(foo=42, bar='spam') - string = "Namespace(bar='spam', foo=42)" - self.assertStringEqual(ns, string) - - def test_parser(self): - parser = argparse.ArgumentParser(prog='PROG') - string = ( - "ArgumentParser(prog='PROG', usage=None, description=None, " - "version=None, formatter_class=%r, conflict_handler='error', " - "add_help=True)" % argparse.HelpFormatter) - self.assertStringEqual(parser, string) - -# =============== -# Namespace tests -# =============== - -class TestNamespace(TestCase): - - def test_constructor(self): - ns = argparse.Namespace() - self.assertRaises(AttributeError, getattr, ns, 'x') - - ns = argparse.Namespace(a=42, b='spam') - self.assertEqual(ns.a, 42) - self.assertEqual(ns.b, 'spam') - - def test_equality(self): - ns1 = argparse.Namespace(a=1, b=2) - ns2 = argparse.Namespace(b=2, a=1) - ns3 = argparse.Namespace(a=1) - ns4 = argparse.Namespace(b=2) - - self.assertEqual(ns1, ns2) - self.assertNotEqual(ns1, ns3) - self.assertNotEqual(ns1, ns4) - self.assertNotEqual(ns2, ns3) - self.assertNotEqual(ns2, ns4) - self.failUnless(ns1 != ns3) - self.failUnless(ns1 != ns4) - self.failUnless(ns2 != ns3) - self.failUnless(ns2 != ns4) - - -# =================== -# File encoding tests -# =================== - -class TestEncoding(TestCase): - - def _test_module_encoding(self, path): - path, _ = os.path.splitext(path) - path += ".py" - codecs.open(path, 'r', 'utf8').read() - - def test_argparse_module_encoding(self): - self._test_module_encoding(argparse.__file__) - - def test_test_argparse_module_encoding(self): - self._test_module_encoding(__file__) - -# =================== -# ArgumentError tests -# =================== - -class TestArgumentError(TestCase): - - def test_argument_error(self): - msg = "my error here" - error = argparse.ArgumentError(None, msg) - self.failUnlessEqual(str(error), msg) - -# ======================= -# ArgumentTypeError tests -# ======================= - -class TestArgumentError(TestCase): - - def test_argument_type_error(self): - - def spam(string): - raise argparse.ArgumentTypeError('spam!') - - parser = ErrorRaisingArgumentParser(prog='PROG', add_help=False) - parser.add_argument('x', type=spam) - try: - parser.parse_args(['XXX']) - except ArgumentParserError: - expected = 'usage: PROG x\nPROG: error: argument x: spam!\n' - msg = sys.exc_info()[1].stderr - self.failUnlessEqual(expected, msg) - else: - self.fail() - -# ====================== -# parse_known_args tests -# ====================== - -class TestParseKnownArgs(TestCase): - - def test_optionals(self): - parser = argparse.ArgumentParser() - parser.add_argument('--foo') - args, extras = parser.parse_known_args('--foo F --bar --baz'.split()) - self.failUnlessEqual(NS(foo='F'), args) - self.failUnlessEqual(['--bar', '--baz'], extras) - - def test_mixed(self): - parser = argparse.ArgumentParser() - parser.add_argument('-v', nargs='?', const=1, type=int) - parser.add_argument('--spam', action='store_false') - parser.add_argument('badger') - - argv = ["B", "C", "--foo", "-v", "3", "4"] - args, extras = parser.parse_known_args(argv) - self.failUnlessEqual(NS(v=3, spam=True, badger="B"), args) - self.failUnlessEqual(["C", "--foo", "4"], extras) - -# ============================ -# from argparse import * tests -# ============================ - -class TestImportStar(TestCase): - - def test(self): - for name in argparse.__all__: - self.failUnless(hasattr(argparse, name)) - - -if __name__ == '__main__': - unittest.main() |