PyXR

c:\python24\lib \ test \ test_optparse.py



0001 #!/usr/bin/python
0002 
0003 #
0004 # Test suite for Optik.  Supplied by Johannes Gijsbers
0005 # (taradino@softhome.net) -- translated from the original Optik
0006 # test suite to this PyUnit-based version.
0007 #
0008 # $Id: test_optparse.py,v 1.10 2004/10/27 02:43:25 tim_one Exp $
0009 #
0010 
0011 import sys
0012 import os
0013 import copy
0014 import unittest
0015 
0016 from cStringIO import StringIO
0017 from pprint import pprint
0018 from test import test_support
0019 
0020 from optparse import make_option, Option, IndentedHelpFormatter, \
0021      TitledHelpFormatter, OptionParser, OptionContainer, OptionGroup, \
0022      SUPPRESS_HELP, SUPPRESS_USAGE, OptionError, OptionConflictError, \
0023      BadOptionError, OptionValueError, Values, _match_abbrev
0024 
0025 # Do the right thing with boolean values for all known Python versions.
0026 try:
0027     True, False
0028 except NameError:
0029     (True, False) = (1, 0)
0030 
0031 
0032 class InterceptedError(Exception):
0033     def __init__(self,
0034                  error_message=None,
0035                  exit_status=None,
0036                  exit_message=None):
0037         self.error_message = error_message
0038         self.exit_status = exit_status
0039         self.exit_message = exit_message
0040 
0041     def __str__(self):
0042         return self.error_message or self.exit_message or "intercepted error"
0043 
0044 class InterceptingOptionParser(OptionParser):
0045     def exit(self, status=0, msg=None):
0046         raise InterceptedError(exit_status=status, exit_message=msg)
0047 
0048     def error(self, msg):
0049         raise InterceptedError(error_message=msg)
0050 
0051 
0052 class BaseTest(unittest.TestCase):
0053     def assertParseOK(self, args, expected_opts, expected_positional_args):
0054         """Assert the options are what we expected when parsing arguments.
0055 
0056         Otherwise, fail with a nicely formatted message.
0057 
0058         Keyword arguments:
0059         args -- A list of arguments to parse with OptionParser.
0060         expected_opts -- The options expected.
0061         expected_positional_args -- The positional arguments expected.
0062 
0063         Returns the options and positional args for further testing.
0064         """
0065 
0066         (options, positional_args) = self.parser.parse_args(args)
0067         optdict = vars(options)
0068 
0069         self.assertEqual(optdict, expected_opts,
0070                          """
0071 Options are %(optdict)s.
0072 Should be %(expected_opts)s.
0073 Args were %(args)s.""" % locals())
0074 
0075         self.assertEqual(positional_args, expected_positional_args,
0076                          """
0077 Positional arguments are %(positional_args)s.
0078 Should be %(expected_positional_args)s.
0079 Args were %(args)s.""" % locals ())
0080 
0081         return (options, positional_args)
0082 
0083     def assertRaises(self,
0084                      func,
0085                      args,
0086                      kwargs,
0087                      expected_exception,
0088                      expected_message):
0089         """
0090         Assert that the expected exception is raised when calling a
0091         function, and that the right error message is included with
0092         that exception.
0093 
0094         Arguments:
0095           func -- the function to call
0096           args -- positional arguments to `func`
0097           kwargs -- keyword arguments to `func`
0098           expected_exception -- exception that should be raised
0099           expected_output -- output we expect to see
0100 
0101         Returns the exception raised for further testing.
0102         """
0103         if args is None:
0104             args = ()
0105         if kwargs is None:
0106             kwargs = {}
0107 
0108         try:
0109             func(*args, **kwargs)
0110         except expected_exception, err:
0111             actual_message = str(err)
0112             self.assertEqual(actual_message,
0113                              expected_message,
0114                              """\
0115 expected exception message:
0116 '''%(expected_message)s'''
0117 actual exception message:
0118 '''%(actual_message)s'''
0119 """ % locals())
0120 
0121             return err
0122         else:
0123             self.fail("""expected exception %(expected_exception)s not raised
0124 called %(func)r
0125 with args %(args)r
0126 and kwargs %(kwargs)r
0127 """ % locals ())
0128 
0129 
0130     # -- Assertions used in more than one class --------------------
0131 
0132     def assertParseFail(self, cmdline_args, expected_output):
0133         """
0134         Assert the parser fails with the expected message.  Caller
0135         must ensure that self.parser is an InterceptingOptionParser.
0136         """
0137         try:
0138             self.parser.parse_args(cmdline_args)
0139         except InterceptedError, err:
0140             self.assertEqual(err.error_message, expected_output)
0141         else:
0142             self.assertFalse("expected parse failure")
0143 
0144     def assertOutput(self,
0145                      cmdline_args,
0146                      expected_output,
0147                      expected_status=0,
0148                      expected_error=None):
0149         """Assert the parser prints the expected output on stdout."""
0150         save_stdout = sys.stdout
0151         try:
0152             try:
0153                 sys.stdout = StringIO()
0154                 self.parser.parse_args(cmdline_args)
0155             finally:
0156                 output = sys.stdout.getvalue()
0157                 sys.stdout = save_stdout
0158 
0159         except InterceptedError, err:
0160             self.assertEqual(output, expected_output)
0161             self.assertEqual(err.exit_status, expected_status)
0162             self.assertEqual(err.exit_message, expected_error)
0163         else:
0164             self.assertFalse("expected parser.exit()")
0165 
0166     def assertTypeError(self, func, expected_message, *args):
0167         """Assert that TypeError is raised when executing func."""
0168         self.assertRaises(func, args, None, TypeError, expected_message)
0169 
0170     def assertHelp(self, parser, expected_help):
0171         actual_help = parser.format_help()
0172         if actual_help != expected_help:
0173             raise self.failureException(
0174                 'help text failure; expected:\n"' +
0175                 expected_help + '"; got:\n"' +
0176                 actual_help + '"\n')
0177 
0178 # -- Test make_option() aka Option -------------------------------------
0179 
0180 # It's not necessary to test correct options here.  All the tests in the
0181 # parser.parse_args() section deal with those, because they're needed
0182 # there.
0183 
0184 class TestOptionChecks(BaseTest):
0185     def setUp(self):
0186         self.parser = OptionParser(usage=SUPPRESS_USAGE)
0187 
0188     def assertOptionError(self, expected_message, args=[], kwargs={}):
0189         self.assertRaises(make_option, args, kwargs,
0190                           OptionError, expected_message)
0191 
0192     def test_opt_string_empty(self):
0193         self.assertTypeError(make_option,
0194                              "at least one option string must be supplied")
0195 
0196     def test_opt_string_too_short(self):
0197         self.assertOptionError(
0198             "invalid option string 'b': must be at least two characters long",
0199             ["b"])
0200 
0201     def test_opt_string_short_invalid(self):
0202         self.assertOptionError(
0203             "invalid short option string '--': must be "
0204             "of the form -x, (x any non-dash char)",
0205             ["--"])
0206 
0207     def test_opt_string_long_invalid(self):
0208         self.assertOptionError(
0209             "invalid long option string '---': "
0210             "must start with --, followed by non-dash",
0211             ["---"])
0212 
0213     def test_attr_invalid(self):
0214         self.assertOptionError(
0215             "option -b: invalid keyword arguments: foo, bar",
0216             ["-b"], {'foo': None, 'bar': None})
0217 
0218     def test_action_invalid(self):
0219         self.assertOptionError(
0220             "option -b: invalid action: 'foo'",
0221             ["-b"], {'action': 'foo'})
0222 
0223     def test_type_invalid(self):
0224         self.assertOptionError(
0225             "option -b: invalid option type: 'foo'",
0226             ["-b"], {'type': 'foo'})
0227         self.assertOptionError(
0228             "option -b: invalid option type: 'tuple'",
0229             ["-b"], {'type': tuple})
0230 
0231     def test_no_type_for_action(self):
0232         self.assertOptionError(
0233             "option -b: must not supply a type for action 'count'",
0234             ["-b"], {'action': 'count', 'type': 'int'})
0235 
0236     def test_no_choices_list(self):
0237         self.assertOptionError(
0238             "option -b/--bad: must supply a list of "
0239             "choices for type 'choice'",
0240             ["-b", "--bad"], {'type': "choice"})
0241 
0242     def test_bad_choices_list(self):
0243         typename = type('').__name__
0244         self.assertOptionError(
0245             "option -b/--bad: choices must be a list of "
0246             "strings ('%s' supplied)" % typename,
0247             ["-b", "--bad"],
0248             {'type': "choice", 'choices':"bad choices"})
0249 
0250     def test_no_choices_for_type(self):
0251         self.assertOptionError(
0252             "option -b: must not supply choices for type 'int'",
0253             ["-b"], {'type': 'int', 'choices':"bad"})
0254 
0255     def test_no_const_for_action(self):
0256         self.assertOptionError(
0257             "option -b: 'const' must not be supplied for action 'store'",
0258             ["-b"], {'action': 'store', 'const': 1})
0259 
0260     def test_no_nargs_for_action(self):
0261         self.assertOptionError(
0262             "option -b: 'nargs' must not be supplied for action 'count'",
0263             ["-b"], {'action': 'count', 'nargs': 2})
0264 
0265     def test_callback_not_callable(self):
0266         self.assertOptionError(
0267             "option -b: callback not callable: 'foo'",
0268             ["-b"], {'action': 'callback',
0269                      'callback': 'foo'})
0270 
0271     def dummy(self):
0272         pass
0273 
0274     def test_callback_args_no_tuple(self):
0275         self.assertOptionError(
0276             "option -b: callback_args, if supplied, "
0277             "must be a tuple: not 'foo'",
0278             ["-b"], {'action': 'callback',
0279                      'callback': self.dummy,
0280                      'callback_args': 'foo'})
0281 
0282     def test_callback_kwargs_no_dict(self):
0283         self.assertOptionError(
0284             "option -b: callback_kwargs, if supplied, "
0285             "must be a dict: not 'foo'",
0286             ["-b"], {'action': 'callback',
0287                      'callback': self.dummy,
0288                      'callback_kwargs': 'foo'})
0289 
0290     def test_no_callback_for_action(self):
0291         self.assertOptionError(
0292             "option -b: callback supplied ('foo') for non-callback option",
0293             ["-b"], {'action': 'store',
0294                      'callback': 'foo'})
0295 
0296     def test_no_callback_args_for_action(self):
0297         self.assertOptionError(
0298             "option -b: callback_args supplied for non-callback option",
0299             ["-b"], {'action': 'store',
0300                      'callback_args': 'foo'})
0301 
0302     def test_no_callback_kwargs_for_action(self):
0303         self.assertOptionError(
0304             "option -b: callback_kwargs supplied for non-callback option",
0305             ["-b"], {'action': 'store',
0306                      'callback_kwargs': 'foo'})
0307 
0308 class TestOptionParser(BaseTest):
0309     def setUp(self):
0310         self.parser = OptionParser()
0311         self.parser.add_option("-v", "--verbose", "-n", "--noisy",
0312                           action="store_true", dest="verbose")
0313         self.parser.add_option("-q", "--quiet", "--silent",
0314                           action="store_false", dest="verbose")
0315 
0316     def test_add_option_no_Option(self):
0317         self.assertTypeError(self.parser.add_option,
0318                              "not an Option instance: None", None)
0319 
0320     def test_add_option_invalid_arguments(self):
0321         self.assertTypeError(self.parser.add_option,
0322                              "invalid arguments", None, None)
0323 
0324     def test_get_option(self):
0325         opt1 = self.parser.get_option("-v")
0326         self.assert_(isinstance(opt1, Option))
0327         self.assertEqual(opt1._short_opts, ["-v", "-n"])
0328         self.assertEqual(opt1._long_opts, ["--verbose", "--noisy"])
0329         self.assertEqual(opt1.action, "store_true")
0330         self.assertEqual(opt1.dest, "verbose")
0331 
0332     def test_get_option_equals(self):
0333         opt1 = self.parser.get_option("-v")
0334         opt2 = self.parser.get_option("--verbose")
0335         opt3 = self.parser.get_option("-n")
0336         opt4 = self.parser.get_option("--noisy")
0337         self.assert_(opt1 is opt2 is opt3 is opt4)
0338 
0339     def test_has_option(self):
0340         self.assert_(self.parser.has_option("-v"))
0341         self.assert_(self.parser.has_option("--verbose"))
0342 
0343     def assert_removed(self):
0344         self.assert_(self.parser.get_option("-v") is None)
0345         self.assert_(self.parser.get_option("--verbose") is None)
0346         self.assert_(self.parser.get_option("-n") is None)
0347         self.assert_(self.parser.get_option("--noisy") is None)
0348 
0349         self.failIf(self.parser.has_option("-v"))
0350         self.failIf(self.parser.has_option("--verbose"))
0351         self.failIf(self.parser.has_option("-n"))
0352         self.failIf(self.parser.has_option("--noisy"))
0353 
0354         self.assert_(self.parser.has_option("-q"))
0355         self.assert_(self.parser.has_option("--silent"))
0356 
0357     def test_remove_short_opt(self):
0358         self.parser.remove_option("-n")
0359         self.assert_removed()
0360 
0361     def test_remove_long_opt(self):
0362         self.parser.remove_option("--verbose")
0363         self.assert_removed()
0364 
0365     def test_remove_nonexistent(self):
0366         self.assertRaises(self.parser.remove_option, ('foo',), None,
0367                           ValueError, "no such option 'foo'")
0368 
0369 class TestOptionValues(BaseTest):
0370     def setUp(self):
0371         pass
0372 
0373     def test_basics(self):
0374         values = Values()
0375         self.assertEqual(vars(values), {})
0376         self.assertEqual(values, {})
0377         self.assertNotEqual(values, {"foo": "bar"})
0378         self.assertNotEqual(values, "")
0379 
0380         dict = {"foo": "bar", "baz": 42}
0381         values = Values(defaults=dict)
0382         self.assertEqual(vars(values), dict)
0383         self.assertEqual(values, dict)
0384         self.assertNotEqual(values, {"foo": "bar"})
0385         self.assertNotEqual(values, {})
0386         self.assertNotEqual(values, "")
0387         self.assertNotEqual(values, [])
0388 
0389 
0390 class TestTypeAliases(BaseTest):
0391     def setUp(self):
0392         self.parser = OptionParser()
0393 
0394     def test_type_aliases(self):
0395         self.parser.add_option("-x", type=int)
0396         self.parser.add_option("-s", type=str)
0397         self.parser.add_option("-t", type="str")
0398         self.assertEquals(self.parser.get_option("-x").type, "int")
0399         self.assertEquals(self.parser.get_option("-s").type, "string")
0400         self.assertEquals(self.parser.get_option("-t").type, "string")
0401 
0402 
0403 # Custom type for testing processing of default values.
0404 _time_units = { 's' : 1, 'm' : 60, 'h' : 60*60, 'd' : 60*60*24 }
0405 
0406 def _check_duration(option, opt, value):
0407     try:
0408         if value[-1].isdigit():
0409             return int(value)
0410         else:
0411             return int(value[:-1]) * _time_units[value[-1]]
0412     except ValueError, IndexError:
0413         raise OptionValueError(
0414             'option %s: invalid duration: %r' % (opt, value))
0415 
0416 class DurationOption(Option):
0417     TYPES = Option.TYPES + ('duration',)
0418     TYPE_CHECKER = copy.copy(Option.TYPE_CHECKER)
0419     TYPE_CHECKER['duration'] = _check_duration
0420 
0421 class TestDefaultValues(BaseTest):
0422     def setUp(self):
0423         self.parser = OptionParser()
0424         self.parser.add_option("-v", "--verbose", default=True)
0425         self.parser.add_option("-q", "--quiet", dest='verbose')
0426         self.parser.add_option("-n", type="int", default=37)
0427         self.parser.add_option("-m", type="int")
0428         self.parser.add_option("-s", default="foo")
0429         self.parser.add_option("-t")
0430         self.parser.add_option("-u", default=None)
0431         self.expected = { 'verbose': True,
0432                           'n': 37,
0433                           'm': None,
0434                           's': "foo",
0435                           't': None,
0436                           'u': None }
0437 
0438     def test_basic_defaults(self):
0439         self.assertEqual(self.parser.get_default_values(), self.expected)
0440 
0441     def test_mixed_defaults_post(self):
0442         self.parser.set_defaults(n=42, m=-100)
0443         self.expected.update({'n': 42, 'm': -100})
0444         self.assertEqual(self.parser.get_default_values(), self.expected)
0445 
0446     def test_mixed_defaults_pre(self):
0447         self.parser.set_defaults(x="barf", y="blah")
0448         self.parser.add_option("-x", default="frob")
0449         self.parser.add_option("-y")
0450 
0451         self.expected.update({'x': "frob", 'y': "blah"})
0452         self.assertEqual(self.parser.get_default_values(), self.expected)
0453 
0454         self.parser.remove_option("-y")
0455         self.parser.add_option("-y", default=None)
0456         self.expected.update({'y': None})
0457         self.assertEqual(self.parser.get_default_values(), self.expected)
0458 
0459     def test_process_default(self):
0460         self.parser.option_class = DurationOption
0461         self.parser.add_option("-d", type="duration", default=300)
0462         self.parser.add_option("-e", type="duration", default="6m")
0463         self.parser.set_defaults(n="42")
0464         self.expected.update({'d': 300, 'e': 360, 'n': 42})
0465         self.assertEqual(self.parser.get_default_values(), self.expected)
0466 
0467         self.parser.set_process_default_values(False)
0468         self.expected.update({'d': 300, 'e': "6m", 'n': "42"})
0469         self.assertEqual(self.parser.get_default_values(), self.expected)
0470 
0471 
0472 class TestProgName(BaseTest):
0473     """
0474     Test that %prog expands to the right thing in usage, version,
0475     and help strings.
0476     """
0477 
0478     def assertUsage(self, parser, expected_usage):
0479         self.assertEqual(parser.get_usage(), expected_usage)
0480 
0481     def assertVersion(self, parser, expected_version):
0482         self.assertEqual(parser.get_version(), expected_version)
0483 
0484 
0485     def test_default_progname(self):
0486         # Make sure that program name taken from sys.argv[0] by default.
0487         save_argv = sys.argv[:]
0488         try:
0489             sys.argv[0] = os.path.join("foo", "bar", "baz.py")
0490             parser = OptionParser("usage: %prog ...", version="%prog 1.2")
0491             expected_usage = "usage: baz.py ...\n"
0492             self.assertUsage(parser, expected_usage)
0493             self.assertVersion(parser, "baz.py 1.2")
0494             self.assertHelp(parser,
0495                             expected_usage + "\n" +
0496                             "options:\n"
0497                             "  --version   show program's version number and exit\n"
0498                             "  -h, --help  show this help message and exit\n")
0499         finally:
0500             sys.argv[:] = save_argv
0501 
0502     def test_custom_progname(self):
0503         parser = OptionParser(prog="thingy",
0504                               version="%prog 0.1",
0505                               usage="%prog arg arg")
0506         parser.remove_option("-h")
0507         parser.remove_option("--version")
0508         expected_usage = "usage: thingy arg arg\n"
0509         self.assertUsage(parser, expected_usage)
0510         self.assertVersion(parser, "thingy 0.1")
0511         self.assertHelp(parser, expected_usage + "\n")
0512 
0513 
0514 class TestExpandDefaults(BaseTest):
0515     def setUp(self):
0516         self.parser = OptionParser(prog="test")
0517         self.help_prefix = """\
0518 usage: test [options]
0519 
0520 options:
0521   -h, --help            show this help message and exit
0522 """
0523         self.file_help = "read from FILE [default: %default]"
0524         self.expected_help_file = self.help_prefix + \
0525             "  -f FILE, --file=FILE  read from FILE [default: foo.txt]\n"
0526         self.expected_help_none = self.help_prefix + \
0527             "  -f FILE, --file=FILE  read from FILE [default: none]\n"
0528 
0529     def test_option_default(self):
0530         self.parser.add_option("-f", "--file",
0531                                default="foo.txt",
0532                                help=self.file_help)
0533         self.assertHelp(self.parser, self.expected_help_file)
0534 
0535     def test_parser_default_1(self):
0536         self.parser.add_option("-f", "--file",
0537                                help=self.file_help)
0538         self.parser.set_default('file', "foo.txt")
0539         self.assertHelp(self.parser, self.expected_help_file)
0540 
0541     def test_parser_default_2(self):
0542         self.parser.add_option("-f", "--file",
0543                                help=self.file_help)
0544         self.parser.set_defaults(file="foo.txt")
0545         self.assertHelp(self.parser, self.expected_help_file)
0546 
0547     def test_no_default(self):
0548         self.parser.add_option("-f", "--file",
0549                                help=self.file_help)
0550         self.assertHelp(self.parser, self.expected_help_none)
0551 
0552     def test_default_none_1(self):
0553         self.parser.add_option("-f", "--file",
0554                                default=None,
0555                                help=self.file_help)
0556         self.assertHelp(self.parser, self.expected_help_none)
0557 
0558     def test_default_none_2(self):
0559         self.parser.add_option("-f", "--file",
0560                                help=self.file_help)
0561         self.parser.set_defaults(file=None)
0562         self.assertHelp(self.parser, self.expected_help_none)
0563 
0564     def test_float_default(self):
0565         self.parser.add_option(
0566             "-p", "--prob",
0567             help="blow up with probability PROB [default: %default]")
0568         self.parser.set_defaults(prob=0.43)
0569         expected_help = self.help_prefix + \
0570             "  -p PROB, --prob=PROB  blow up with probability PROB [default: 0.43]\n"
0571         self.assertHelp(self.parser, expected_help)
0572 
0573     def test_alt_expand(self):
0574         self.parser.add_option("-f", "--file",
0575                                default="foo.txt",
0576                                help="read from FILE [default: *DEFAULT*]")
0577         self.parser.formatter.default_tag = "*DEFAULT*"
0578         self.assertHelp(self.parser, self.expected_help_file)
0579 
0580     def test_no_expand(self):
0581         self.parser.add_option("-f", "--file",
0582                                default="foo.txt",
0583                                help="read from %default file")
0584         self.parser.formatter.default_tag = None
0585         expected_help = self.help_prefix + \
0586             "  -f FILE, --file=FILE  read from %default file\n"
0587         self.assertHelp(self.parser, expected_help)
0588 
0589 
0590 # -- Test parser.parse_args() ------------------------------------------
0591 
0592 class TestStandard(BaseTest):
0593     def setUp(self):
0594         options = [make_option("-a", type="string"),
0595                    make_option("-b", "--boo", type="int", dest='boo'),
0596                    make_option("--foo", action="append")]
0597 
0598         self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
0599                                                option_list=options)
0600 
0601     def test_required_value(self):
0602         self.assertParseFail(["-a"], "-a option requires an argument")
0603 
0604     def test_invalid_integer(self):
0605         self.assertParseFail(["-b", "5x"],
0606                              "option -b: invalid integer value: '5x'")
0607 
0608     def test_no_such_option(self):
0609         self.assertParseFail(["--boo13"], "no such option: --boo13")
0610 
0611     def test_long_invalid_integer(self):
0612         self.assertParseFail(["--boo=x5"],
0613                              "option --boo: invalid integer value: 'x5'")
0614 
0615     def test_empty(self):
0616         self.assertParseOK([], {'a': None, 'boo': None, 'foo': None}, [])
0617 
0618     def test_shortopt_empty_longopt_append(self):
0619         self.assertParseOK(["-a", "", "--foo=blah", "--foo="],
0620                            {'a': "", 'boo': None, 'foo': ["blah", ""]},
0621                            [])
0622 
0623     def test_long_option_append(self):
0624         self.assertParseOK(["--foo", "bar", "--foo", "", "--foo=x"],
0625                            {'a': None,
0626                             'boo': None,
0627                             'foo': ["bar", "", "x"]},
0628                            [])
0629 
0630     def test_option_argument_joined(self):
0631         self.assertParseOK(["-abc"],
0632                            {'a': "bc", 'boo': None, 'foo': None},
0633                            [])
0634 
0635     def test_option_argument_split(self):
0636         self.assertParseOK(["-a", "34"],
0637                            {'a': "34", 'boo': None, 'foo': None},
0638                            [])
0639 
0640     def test_option_argument_joined_integer(self):
0641         self.assertParseOK(["-b34"],
0642                            {'a': None, 'boo': 34, 'foo': None},
0643                            [])
0644 
0645     def test_option_argument_split_negative_integer(self):
0646         self.assertParseOK(["-b", "-5"],
0647                            {'a': None, 'boo': -5, 'foo': None},
0648                            [])
0649 
0650     def test_long_option_argument_joined(self):
0651         self.assertParseOK(["--boo=13"],
0652                            {'a': None, 'boo': 13, 'foo': None},
0653                            [])
0654 
0655     def test_long_option_argument_split(self):
0656         self.assertParseOK(["--boo", "111"],
0657                            {'a': None, 'boo': 111, 'foo': None},
0658                            [])
0659 
0660     def test_long_option_short_option(self):
0661         self.assertParseOK(["--foo=bar", "-axyz"],
0662                            {'a': 'xyz', 'boo': None, 'foo': ["bar"]},
0663                            [])
0664 
0665     def test_abbrev_long_option(self):
0666         self.assertParseOK(["--f=bar", "-axyz"],
0667                            {'a': 'xyz', 'boo': None, 'foo': ["bar"]},
0668                            [])
0669 
0670     def test_defaults(self):
0671         (options, args) = self.parser.parse_args([])
0672         defaults = self.parser.get_default_values()
0673         self.assertEqual(vars(defaults), vars(options))
0674 
0675     def test_ambiguous_option(self):
0676         self.parser.add_option("--foz", action="store",
0677                                type="string", dest="foo")
0678         possibilities = ", ".join({"--foz": None, "--foo": None}.keys())
0679         self.assertParseFail(["--f=bar"],
0680                              "ambiguous option: --f (%s?)" % possibilities)
0681 
0682 
0683     def test_short_and_long_option_split(self):
0684         self.assertParseOK(["-a", "xyz", "--foo", "bar"],
0685                            {'a': 'xyz', 'boo': None, 'foo': ["bar"]},
0686                            []),
0687 
0688     def test_short_option_split_long_option_append(self):
0689         self.assertParseOK(["--foo=bar", "-b", "123", "--foo", "baz"],
0690                            {'a': None, 'boo': 123, 'foo': ["bar", "baz"]},
0691                            [])
0692 
0693     def test_short_option_split_one_positional_arg(self):
0694         self.assertParseOK(["-a", "foo", "bar"],
0695                            {'a': "foo", 'boo': None, 'foo': None},
0696                            ["bar"]),
0697 
0698     def test_short_option_consumes_separator(self):
0699         self.assertParseOK(["-a", "--", "foo", "bar"],
0700                            {'a': "--", 'boo': None, 'foo': None},
0701                            ["foo", "bar"]),
0702 
0703     def test_short_option_joined_and_separator(self):
0704         self.assertParseOK(["-ab", "--", "--foo", "bar"],
0705                            {'a': "b", 'boo': None, 'foo': None},
0706                            ["--foo", "bar"]),
0707 
0708     def test_invalid_option_becomes_positional_arg(self):
0709         self.assertParseOK(["-ab", "-", "--foo", "bar"],
0710                            {'a': "b", 'boo': None, 'foo': ["bar"]},
0711                            ["-"])
0712 
0713     def test_no_append_versus_append(self):
0714         self.assertParseOK(["-b3", "-b", "5", "--foo=bar", "--foo", "baz"],
0715                            {'a': None, 'boo': 5, 'foo': ["bar", "baz"]},
0716                            [])
0717 
0718     def test_option_consumes_optionlike_string(self):
0719         self.assertParseOK(["-a", "-b3"],
0720                            {'a': "-b3", 'boo': None, 'foo': None},
0721                            [])
0722 
0723 class TestBool(BaseTest):
0724     def setUp(self):
0725         options = [make_option("-v",
0726                                "--verbose",
0727                                action="store_true",
0728                                dest="verbose",
0729                                default=''),
0730                    make_option("-q",
0731                                "--quiet",
0732                                action="store_false",
0733                                dest="verbose")]
0734         self.parser = OptionParser(option_list = options)
0735 
0736     def test_bool_default(self):
0737         self.assertParseOK([],
0738                            {'verbose': ''},
0739                            [])
0740 
0741     def test_bool_false(self):
0742         (options, args) = self.assertParseOK(["-q"],
0743                                              {'verbose': 0},
0744                                              [])
0745         if hasattr(__builtins__, 'False'):
0746             self.failUnless(options.verbose is False)
0747 
0748     def test_bool_true(self):
0749         (options, args) = self.assertParseOK(["-v"],
0750                                              {'verbose': 1},
0751                                              [])
0752         if hasattr(__builtins__, 'True'):
0753             self.failUnless(options.verbose is True)
0754 
0755     def test_bool_flicker_on_and_off(self):
0756         self.assertParseOK(["-qvq", "-q", "-v"],
0757                            {'verbose': 1},
0758                            [])
0759 
0760 class TestChoice(BaseTest):
0761     def setUp(self):
0762         self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
0763         self.parser.add_option("-c", action="store", type="choice",
0764                                dest="choice", choices=["one", "two", "three"])
0765 
0766     def test_valid_choice(self):
0767         self.assertParseOK(["-c", "one", "xyz"],
0768                            {'choice': 'one'},
0769                            ["xyz"])
0770 
0771     def test_invalid_choice(self):
0772         self.assertParseFail(["-c", "four", "abc"],
0773                              "option -c: invalid choice: 'four' "
0774                              "(choose from 'one', 'two', 'three')")
0775 
0776     def test_add_choice_option(self):
0777         self.parser.add_option("-d", "--default",
0778                                choices=["four", "five", "six"])
0779         opt = self.parser.get_option("-d")
0780         self.assertEqual(opt.type, "choice")
0781         self.assertEqual(opt.action, "store")
0782 
0783 class TestCount(BaseTest):
0784     def setUp(self):
0785         self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
0786         self.v_opt = make_option("-v", action="count", dest="verbose")
0787         self.parser.add_option(self.v_opt)
0788         self.parser.add_option("--verbose", type="int", dest="verbose")
0789         self.parser.add_option("-q", "--quiet",
0790                                action="store_const", dest="verbose", const=0)
0791 
0792     def test_empty(self):
0793         self.assertParseOK([], {'verbose': None}, [])
0794 
0795     def test_count_one(self):
0796         self.assertParseOK(["-v"], {'verbose': 1}, [])
0797 
0798     def test_count_three(self):
0799         self.assertParseOK(["-vvv"], {'verbose': 3}, [])
0800 
0801     def test_count_three_apart(self):
0802         self.assertParseOK(["-v", "-v", "-v"], {'verbose': 3}, [])
0803 
0804     def test_count_override_amount(self):
0805         self.assertParseOK(["-vvv", "--verbose=2"], {'verbose': 2}, [])
0806 
0807     def test_count_override_quiet(self):
0808         self.assertParseOK(["-vvv", "--verbose=2", "-q"], {'verbose': 0}, [])
0809 
0810     def test_count_overriding(self):
0811         self.assertParseOK(["-vvv", "--verbose=2", "-q", "-v"],
0812                            {'verbose': 1}, [])
0813 
0814     def test_count_interspersed_args(self):
0815         self.assertParseOK(["--quiet", "3", "-v"],
0816                            {'verbose': 1},
0817                            ["3"])
0818 
0819     def test_count_no_interspersed_args(self):
0820         self.parser.disable_interspersed_args()
0821         self.assertParseOK(["--quiet", "3", "-v"],
0822                            {'verbose': 0},
0823                            ["3", "-v"])
0824 
0825     def test_count_no_such_option(self):
0826         self.assertParseFail(["-q3", "-v"], "no such option: -3")
0827 
0828     def test_count_option_no_value(self):
0829         self.assertParseFail(["--quiet=3", "-v"],
0830                              "--quiet option does not take a value")
0831 
0832     def test_count_with_default(self):
0833         self.parser.set_default('verbose', 0)
0834         self.assertParseOK([], {'verbose':0}, [])
0835 
0836     def test_count_overriding_default(self):
0837         self.parser.set_default('verbose', 0)
0838         self.assertParseOK(["-vvv", "--verbose=2", "-q", "-v"],
0839                            {'verbose': 1}, [])
0840 
0841 class TestMultipleArgs(BaseTest):
0842     def setUp(self):
0843         self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
0844         self.parser.add_option("-p", "--point",
0845                                action="store", nargs=3, type="float", dest="point")
0846 
0847     def test_nargs_with_positional_args(self):
0848         self.assertParseOK(["foo", "-p", "1", "2.5", "-4.3", "xyz"],
0849                            {'point': (1.0, 2.5, -4.3)},
0850                            ["foo", "xyz"])
0851 
0852     def test_nargs_long_opt(self):
0853         self.assertParseOK(["--point", "-1", "2.5", "-0", "xyz"],
0854                            {'point': (-1.0, 2.5, -0.0)},
0855                            ["xyz"])
0856 
0857     def test_nargs_invalid_float_value(self):
0858         self.assertParseFail(["-p", "1.0", "2x", "3.5"],
0859                              "option -p: "
0860                              "invalid floating-point value: '2x'")
0861 
0862     def test_nargs_required_values(self):
0863         self.assertParseFail(["--point", "1.0", "3.5"],
0864                              "--point option requires 3 arguments")
0865 
0866 class TestMultipleArgsAppend(BaseTest):
0867     def setUp(self):
0868         self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
0869         self.parser.add_option("-p", "--point", action="store", nargs=3,
0870                                type="float", dest="point")
0871         self.parser.add_option("-f", "--foo", action="append", nargs=2,
0872                                type="int", dest="foo")
0873 
0874     def test_nargs_append(self):
0875         self.assertParseOK(["-f", "4", "-3", "blah", "--foo", "1", "666"],
0876                            {'point': None, 'foo': [(4, -3), (1, 666)]},
0877                            ["blah"])
0878 
0879     def test_nargs_append_required_values(self):
0880         self.assertParseFail(["-f4,3"],
0881                              "-f option requires 2 arguments")
0882 
0883     def test_nargs_append_simple(self):
0884         self.assertParseOK(["--foo=3", "4"],
0885                            {'point': None, 'foo':[(3, 4)]},
0886                            [])
0887 
0888 class TestVersion(BaseTest):
0889     def test_version(self):
0890         self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
0891                                                version="%prog 0.1")
0892         save_argv = sys.argv[:]
0893         try:
0894             sys.argv[0] = os.path.join(os.curdir, "foo", "bar")
0895             self.assertOutput(["--version"], "bar 0.1\n")
0896         finally:
0897             sys.argv[:] = save_argv
0898 
0899     def test_no_version(self):
0900         self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
0901         self.assertParseFail(["--version"],
0902                              "no such option: --version")
0903 
0904 # -- Test conflicting default values and parser.parse_args() -----------
0905 
0906 class TestConflictingDefaults(BaseTest):
0907     """Conflicting default values: the last one should win."""
0908     def setUp(self):
0909         self.parser = OptionParser(option_list=[
0910             make_option("-v", action="store_true", dest="verbose", default=1)])
0911 
0912     def test_conflict_default(self):
0913         self.parser.add_option("-q", action="store_false", dest="verbose",
0914                                default=0)
0915         self.assertParseOK([], {'verbose': 0}, [])
0916 
0917     def test_conflict_default_none(self):
0918         self.parser.add_option("-q", action="store_false", dest="verbose",
0919                                default=None)
0920         self.assertParseOK([], {'verbose': None}, [])
0921 
0922 class TestOptionGroup(BaseTest):
0923     def setUp(self):
0924         self.parser = OptionParser(usage=SUPPRESS_USAGE)
0925 
0926     def test_option_group_create_instance(self):
0927         group = OptionGroup(self.parser, "Spam")
0928         self.parser.add_option_group(group)
0929         group.add_option("--spam", action="store_true",
0930                          help="spam spam spam spam")
0931         self.assertParseOK(["--spam"], {'spam': 1}, [])
0932 
0933     def test_add_group_no_group(self):
0934         self.assertTypeError(self.parser.add_option_group,
0935                              "not an OptionGroup instance: None", None)
0936 
0937     def test_add_group_invalid_arguments(self):
0938         self.assertTypeError(self.parser.add_option_group,
0939                              "invalid arguments", None, None)
0940 
0941     def test_add_group_wrong_parser(self):
0942         group = OptionGroup(self.parser, "Spam")
0943         group.parser = OptionParser()
0944         self.assertRaises(self.parser.add_option_group, (group,), None,
0945                           ValueError, "invalid OptionGroup (wrong parser)")
0946 
0947     def test_group_manipulate(self):
0948         group = self.parser.add_option_group("Group 2",
0949                                              description="Some more options")
0950         group.set_title("Bacon")
0951         group.add_option("--bacon", type="int")
0952         self.assert_(self.parser.get_option_group("--bacon"), group)
0953 
0954 # -- Test extending and parser.parse_args() ----------------------------
0955 
0956 class TestExtendAddTypes(BaseTest):
0957     def setUp(self):
0958         self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
0959                                                option_class=self.MyOption)
0960         self.parser.add_option("-a", None, type="string", dest="a")
0961         self.parser.add_option("-f", "--file", type="file", dest="file")
0962 
0963     class MyOption (Option):
0964         def check_file (option, opt, value):
0965             if not os.path.exists(value):
0966                 raise OptionValueError("%s: file does not exist" % value)
0967             elif not os.path.isfile(value):
0968                 raise OptionValueError("%s: not a regular file" % value)
0969             return value
0970 
0971         TYPES = Option.TYPES + ("file",)
0972         TYPE_CHECKER = copy.copy(Option.TYPE_CHECKER)
0973         TYPE_CHECKER["file"] = check_file
0974 
0975     def test_extend_file(self):
0976         open(test_support.TESTFN, "w").close()
0977         self.assertParseOK(["--file", test_support.TESTFN, "-afoo"],
0978                            {'file': test_support.TESTFN, 'a': 'foo'},
0979                            [])
0980 
0981         os.unlink(test_support.TESTFN)
0982 
0983     def test_extend_file_nonexistent(self):
0984         self.assertParseFail(["--file", test_support.TESTFN, "-afoo"],
0985                              "%s: file does not exist" %
0986                              test_support.TESTFN)
0987 
0988     def test_file_irregular(self):
0989         os.mkdir(test_support.TESTFN)
0990         self.assertParseFail(["--file", test_support.TESTFN, "-afoo"],
0991                              "%s: not a regular file" %
0992                              test_support.TESTFN)
0993         os.rmdir(test_support.TESTFN)
0994 
0995 class TestExtendAddActions(BaseTest):
0996     def setUp(self):
0997         options = [self.MyOption("-a", "--apple", action="extend",
0998                                  type="string", dest="apple")]
0999         self.parser = OptionParser(option_list=options)
1000 
1001     class MyOption (Option):
1002         ACTIONS = Option.ACTIONS + ("extend",)
1003         STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",)
1004         TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",)
1005 
1006         def take_action (self, action, dest, opt, value, values, parser):
1007             if action == "extend":
1008                 lvalue = value.split(",")
1009                 values.ensure_value(dest, []).extend(lvalue)
1010             else:
1011                 Option.take_action(self, action, dest, opt, parser, value,
1012                                    values)
1013 
1014     def test_extend_add_action(self):
1015         self.assertParseOK(["-afoo,bar", "--apple=blah"],
1016                            {'apple': ["foo", "bar", "blah"]},
1017                            [])
1018 
1019     def test_extend_add_action_normal(self):
1020         self.assertParseOK(["-a", "foo", "-abar", "--apple=x,y"],
1021                            {'apple': ["foo", "bar", "x", "y"]},
1022                            [])
1023 
1024 # -- Test callbacks and parser.parse_args() ----------------------------
1025 
1026 class TestCallback(BaseTest):
1027     def setUp(self):
1028         options = [make_option("-x",
1029                                None,
1030                                action="callback",
1031                                callback=self.process_opt),
1032                    make_option("-f",
1033                                "--file",
1034                                action="callback",
1035                                callback=self.process_opt,
1036                                type="string",
1037                                dest="filename")]
1038         self.parser = OptionParser(option_list=options)
1039 
1040     def process_opt(self, option, opt, value, parser_):
1041         if opt == "-x":
1042             self.assertEqual(option._short_opts, ["-x"])
1043             self.assertEqual(option._long_opts, [])
1044             self.assert_(parser_ is self.parser)
1045             self.assert_(value is None)
1046             self.assertEqual(vars(parser_.values), {'filename': None})
1047 
1048             parser_.values.x = 42
1049         elif opt == "--file":
1050             self.assertEqual(option._short_opts, ["-f"])
1051             self.assertEqual(option._long_opts, ["--file"])
1052             self.assert_(parser_ is self.parser)
1053             self.assertEqual(value, "foo")
1054             self.assertEqual(vars(parser_.values), {'filename': None, 'x': 42})
1055 
1056             setattr(parser_.values, option.dest, value)
1057         else:
1058             self.fail("Unknown option %r in process_opt." % opt)
1059 
1060     def test_callback(self):
1061         self.assertParseOK(["-x", "--file=foo"],
1062                            {'filename': "foo", 'x': 42},
1063                            [])
1064 
1065     def test_callback_help(self):
1066         # This test was prompted by SF bug #960515 -- the point is
1067         # not to inspect the help text, just to make sure that
1068         # format_help() doesn't crash.
1069         parser = OptionParser(usage=SUPPRESS_USAGE)
1070         parser.remove_option("-h")
1071         parser.add_option("-t", "--test", action="callback",
1072                           callback=lambda: None, type="string",
1073                           help="foo")
1074 
1075         expected_help = ("options:\n"
1076                          "  -t TEST, --test=TEST  foo\n")
1077         self.assertHelp(parser, expected_help)
1078 
1079 
1080 class TestCallbackExtraArgs(BaseTest):
1081     def setUp(self):
1082         options = [make_option("-p", "--point", action="callback",
1083                                callback=self.process_tuple,
1084                                callback_args=(3, int), type="string",
1085                                dest="points", default=[])]
1086         self.parser = OptionParser(option_list=options)
1087 
1088     def process_tuple (self, option, opt, value, parser_, len, type):
1089         self.assertEqual(len, 3)
1090         self.assert_(type is int)
1091 
1092         if opt == "-p":
1093             self.assertEqual(value, "1,2,3")
1094         elif opt == "--point":
1095             self.assertEqual(value, "4,5,6")
1096 
1097         value = tuple(map(type, value.split(",")))
1098         getattr(parser_.values, option.dest).append(value)
1099 
1100     def test_callback_extra_args(self):
1101         self.assertParseOK(["-p1,2,3", "--point", "4,5,6"],
1102                            {'points': [(1,2,3), (4,5,6)]},
1103                            [])
1104 
1105 class TestCallbackMeddleArgs(BaseTest):
1106     def setUp(self):
1107         options = [make_option(str(x), action="callback",
1108                                callback=self.process_n, dest='things')
1109                    for x in range(-1, -6, -1)]
1110         self.parser = OptionParser(option_list=options)
1111 
1112     # Callback that meddles in rargs, largs
1113     def process_n (self, option, opt, value, parser_):
1114         # option is -3, -5, etc.
1115         nargs = int(opt[1:])
1116         rargs = parser_.rargs
1117         if len(rargs) < nargs:
1118             self.fail("Expected %d arguments for %s option." % (nargs, opt))
1119         dest = parser_.values.ensure_value(option.dest, [])
1120         dest.append(tuple(rargs[0:nargs]))
1121         parser_.largs.append(nargs)
1122         del rargs[0:nargs]
1123 
1124     def test_callback_meddle_args(self):
1125         self.assertParseOK(["-1", "foo", "-3", "bar", "baz", "qux"],
1126                            {'things': [("foo",), ("bar", "baz", "qux")]},
1127                            [1, 3])
1128 
1129     def test_callback_meddle_args_separator(self):
1130         self.assertParseOK(["-2", "foo", "--"],
1131                            {'things': [('foo', '--')]},
1132                            [2])
1133 
1134 class TestCallbackManyArgs(BaseTest):
1135     def setUp(self):
1136         options = [make_option("-a", "--apple", action="callback", nargs=2,
1137                                callback=self.process_many, type="string"),
1138                    make_option("-b", "--bob", action="callback", nargs=3,
1139                                callback=self.process_many, type="int")]
1140         self.parser = OptionParser(option_list=options)
1141 
1142     def process_many (self, option, opt, value, parser_):
1143         if opt == "-a":
1144             self.assertEqual(value, ("foo", "bar"))
1145         elif opt == "--apple":
1146             self.assertEqual(value, ("ding", "dong"))
1147         elif opt == "-b":
1148             self.assertEqual(value, (1, 2, 3))
1149         elif opt == "--bob":
1150             self.assertEqual(value, (-666, 42, 0))
1151 
1152     def test_many_args(self):
1153         self.assertParseOK(["-a", "foo", "bar", "--apple", "ding", "dong",
1154                             "-b", "1", "2", "3", "--bob", "-666", "42",
1155                             "0"],
1156                            {"apple": None, "bob": None},
1157                            [])
1158 
1159 class TestCallbackCheckAbbrev(BaseTest):
1160     def setUp(self):
1161         self.parser = OptionParser()
1162         self.parser.add_option("--foo-bar", action="callback",
1163                                callback=self.check_abbrev)
1164 
1165     def check_abbrev (self, option, opt, value, parser):
1166         self.assertEqual(opt, "--foo-bar")
1167 
1168     def test_abbrev_callback_expansion(self):
1169         self.assertParseOK(["--foo"], {}, [])
1170 
1171 class TestCallbackVarArgs(BaseTest):
1172     def setUp(self):
1173         options = [make_option("-a", type="int", nargs=2, dest="a"),
1174                    make_option("-b", action="store_true", dest="b"),
1175                    make_option("-c", "--callback", action="callback",
1176                                callback=self.variable_args, dest="c")]
1177         self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
1178                                                option_list=options)
1179 
1180     def variable_args (self, option, opt, value, parser):
1181         self.assert_(value is None)
1182         done = 0
1183         value = []
1184         rargs = parser.rargs
1185         while rargs:
1186             arg = rargs[0]
1187             if ((arg[:2] == "--" and len(arg) > 2) or
1188                 (arg[:1] == "-" and len(arg) > 1 and arg[1] != "-")):
1189                 break
1190             else:
1191                 value.append(arg)
1192                 del rargs[0]
1193         setattr(parser.values, option.dest, value)
1194 
1195     def test_variable_args(self):
1196         self.assertParseOK(["-a3", "-5", "--callback", "foo", "bar"],
1197                            {'a': (3, -5), 'b': None, 'c': ["foo", "bar"]},
1198                            [])
1199 
1200     def test_consume_separator_stop_at_option(self):
1201         self.assertParseOK(["-c", "37", "--", "xxx", "-b", "hello"],
1202                            {'a': None,
1203                             'b': True,
1204                             'c': ["37", "--", "xxx"]},
1205                            ["hello"])
1206 
1207     def test_positional_arg_and_variable_args(self):
1208         self.assertParseOK(["hello", "-c", "foo", "-", "bar"],
1209                            {'a': None,
1210                             'b': None,
1211                             'c':["foo", "-", "bar"]},
1212                            ["hello"])
1213 
1214     def test_stop_at_option(self):
1215         self.assertParseOK(["-c", "foo", "-b"],
1216                            {'a': None, 'b': True, 'c': ["foo"]},
1217                            [])
1218 
1219     def test_stop_at_invalid_option(self):
1220         self.assertParseFail(["-c", "3", "-5", "-a"], "no such option: -5")
1221 
1222 
1223 # -- Test conflict handling and parser.parse_args() --------------------
1224 
1225 class ConflictBase(BaseTest):
1226     def setUp(self):
1227         options = [make_option("-v", "--verbose", action="count",
1228                                dest="verbose", help="increment verbosity")]
1229         self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
1230                                                option_list=options)
1231 
1232     def show_version (self, option, opt, value, parser):
1233         parser.values.show_version = 1
1234 
1235 class TestConflict(ConflictBase):
1236     """Use the default conflict resolution for Optik 1.2: error."""
1237     def assert_conflict_error(self, func):
1238         err = self.assertRaises(
1239             func, ("-v", "--version"), {'action' : "callback",
1240                                         'callback' : self.show_version,
1241                                         'help' : "show version"},
1242             OptionConflictError,
1243             "option -v/--version: conflicting option string(s): -v")
1244 
1245         self.assertEqual(err.msg, "conflicting option string(s): -v")
1246         self.assertEqual(err.option_id, "-v/--version")
1247 
1248     def test_conflict_error(self):
1249         self.assert_conflict_error(self.parser.add_option)
1250 
1251     def test_conflict_error_group(self):
1252         group = OptionGroup(self.parser, "Group 1")
1253         self.assert_conflict_error(group.add_option)
1254 
1255     def test_no_such_conflict_handler(self):
1256         self.assertRaises(
1257             self.parser.set_conflict_handler, ('foo',), None,
1258             ValueError, "invalid conflict_resolution value 'foo'")
1259 
1260 
1261 class TestConflictResolve(ConflictBase):
1262     def setUp(self):
1263         ConflictBase.setUp(self)
1264         self.parser.set_conflict_handler("resolve")
1265         self.parser.add_option("-v", "--version", action="callback",
1266                                callback=self.show_version, help="show version")
1267 
1268     def test_conflict_resolve(self):
1269         v_opt = self.parser.get_option("-v")
1270         verbose_opt = self.parser.get_option("--verbose")
1271         version_opt = self.parser.get_option("--version")
1272 
1273         self.assert_(v_opt is version_opt)
1274         self.assert_(v_opt is not verbose_opt)
1275         self.assertEqual(v_opt._long_opts, ["--version"])
1276         self.assertEqual(version_opt._short_opts, ["-v"])
1277         self.assertEqual(version_opt._long_opts, ["--version"])
1278         self.assertEqual(verbose_opt._short_opts, [])
1279         self.assertEqual(verbose_opt._long_opts, ["--verbose"])
1280 
1281     def test_conflict_resolve_help(self):
1282         self.assertOutput(["-h"], """\
1283 options:
1284   --verbose      increment verbosity
1285   -h, --help     show this help message and exit
1286   -v, --version  show version
1287 """)
1288 
1289     def test_conflict_resolve_short_opt(self):
1290         self.assertParseOK(["-v"],
1291                            {'verbose': None, 'show_version': 1},
1292                            [])
1293 
1294     def test_conflict_resolve_long_opt(self):
1295         self.assertParseOK(["--verbose"],
1296                            {'verbose': 1},
1297                            [])
1298 
1299     def test_conflict_resolve_long_opts(self):
1300         self.assertParseOK(["--verbose", "--version"],
1301                            {'verbose': 1, 'show_version': 1},
1302                            [])
1303 
1304 class TestConflictOverride(BaseTest):
1305     def setUp(self):
1306         self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
1307         self.parser.set_conflict_handler("resolve")
1308         self.parser.add_option("-n", "--dry-run",
1309                                action="store_true", dest="dry_run",
1310                                help="don't do anything")
1311         self.parser.add_option("--dry-run", "-n",
1312                                action="store_const", const=42, dest="dry_run",
1313                                help="dry run mode")
1314 
1315     def test_conflict_override_opts(self):
1316         opt = self.parser.get_option("--dry-run")
1317         self.assertEqual(opt._short_opts, ["-n"])
1318         self.assertEqual(opt._long_opts, ["--dry-run"])
1319 
1320     def test_conflict_override_help(self):
1321         self.assertOutput(["-h"], """\
1322 options:
1323   -h, --help     show this help message and exit
1324   -n, --dry-run  dry run mode
1325 """)
1326 
1327     def test_conflict_override_args(self):
1328         self.assertParseOK(["-n"],
1329                            {'dry_run': 42},
1330                            [])
1331 
1332 # -- Other testing. ----------------------------------------------------
1333 
1334 _expected_help_basic = """\
1335 usage: bar.py [options]
1336 
1337 options:
1338   -a APPLE           throw APPLEs at basket
1339   -b NUM, --boo=NUM  shout "boo!" NUM times (in order to frighten away all the
1340                      evil spirits that cause trouble and mayhem)
1341   --foo=FOO          store FOO in the foo list for later fooing
1342   -h, --help         show this help message and exit
1343 """
1344 
1345 _expected_help_long_opts_first = """\
1346 usage: bar.py [options]
1347 
1348 options:
1349   -a APPLE           throw APPLEs at basket
1350   --boo=NUM, -b NUM  shout "boo!" NUM times (in order to frighten away all the
1351                      evil spirits that cause trouble and mayhem)
1352   --foo=FOO          store FOO in the foo list for later fooing
1353   --help, -h         show this help message and exit
1354 """
1355 
1356 _expected_help_title_formatter = """\
1357 Usage
1358 =====
1359   bar.py [options]
1360 
1361 options
1362 =======
1363 -a APPLE           throw APPLEs at basket
1364 --boo=NUM, -b NUM  shout "boo!" NUM times (in order to frighten away all the
1365                    evil spirits that cause trouble and mayhem)
1366 --foo=FOO          store FOO in the foo list for later fooing
1367 --help, -h         show this help message and exit
1368 """
1369 
1370 _expected_help_short_lines = """\
1371 usage: bar.py [options]
1372 
1373 options:
1374   -a APPLE           throw APPLEs at basket
1375   -b NUM, --boo=NUM  shout "boo!" NUM times (in order to
1376                      frighten away all the evil spirits
1377                      that cause trouble and mayhem)
1378   --foo=FOO          store FOO in the foo list for later
1379                      fooing
1380   -h, --help         show this help message and exit
1381 """
1382 
1383 class TestHelp(BaseTest):
1384     def setUp(self):
1385         self.parser = self.make_parser(80)
1386 
1387     def make_parser(self, columns):
1388         options = [
1389             make_option("-a", type="string", dest='a',
1390                         metavar="APPLE", help="throw APPLEs at basket"),
1391             make_option("-b", "--boo", type="int", dest='boo',
1392                         metavar="NUM",
1393                         help=
1394                         "shout \"boo!\" NUM times (in order to frighten away "
1395                         "all the evil spirits that cause trouble and mayhem)"),
1396             make_option("--foo", action="append", type="string", dest='foo',
1397                         help="store FOO in the foo list for later fooing"),
1398             ]
1399         os.environ['COLUMNS'] = str(columns)
1400         return InterceptingOptionParser(option_list=options)
1401 
1402     def assertHelpEquals(self, expected_output):
1403         save_argv = sys.argv[:]
1404         try:
1405             # Make optparse believe bar.py is being executed.
1406             sys.argv[0] = os.path.join("foo", "bar.py")
1407             self.assertOutput(["-h"], expected_output)
1408         finally:
1409             sys.argv[:] = save_argv
1410 
1411     def test_help(self):
1412         self.assertHelpEquals(_expected_help_basic)
1413 
1414     def test_help_old_usage(self):
1415         self.parser.set_usage("usage: %prog [options]")
1416         self.assertHelpEquals(_expected_help_basic)
1417 
1418     def test_help_long_opts_first(self):
1419         self.parser.formatter.short_first = 0
1420         self.assertHelpEquals(_expected_help_long_opts_first)
1421 
1422     def test_help_title_formatter(self):
1423         self.parser.formatter = TitledHelpFormatter()
1424         self.assertHelpEquals(_expected_help_title_formatter)
1425 
1426     def test_wrap_columns(self):
1427         # Ensure that wrapping respects $COLUMNS environment variable.
1428         # Need to reconstruct the parser, since that's the only time
1429         # we look at $COLUMNS.
1430         self.parser = self.make_parser(60)
1431         self.assertHelpEquals(_expected_help_short_lines)
1432 
1433     def test_help_description_groups(self):
1434         self.parser.set_description(
1435             "This is the program description for %prog.  %prog has "
1436             "an option group as well as single options.")
1437 
1438         group = OptionGroup(
1439             self.parser, "Dangerous Options",
1440             "Caution: use of these options is at your own risk.  "
1441             "It is believed that some of them bite.")
1442         group.add_option("-g", action="store_true", help="Group option.")
1443         self.parser.add_option_group(group)
1444 
1445         self.assertHelpEquals("""\
1446 usage: bar.py [options]
1447 
1448 This is the program description for bar.py.  bar.py has an option group as
1449 well as single options.
1450 
1451 options:
1452   -a APPLE           throw APPLEs at basket
1453   -b NUM, --boo=NUM  shout "boo!" NUM times (in order to frighten away all the
1454                      evil spirits that cause trouble and mayhem)
1455   --foo=FOO          store FOO in the foo list for later fooing
1456   -h, --help         show this help message and exit
1457 
1458   Dangerous Options:
1459     Caution: use of these options is at your own risk.  It is believed
1460     that some of them bite.
1461 
1462     -g               Group option.
1463 """)
1464 
1465 
1466 
1467 
1468 class TestMatchAbbrev(BaseTest):
1469     def test_match_abbrev(self):
1470         self.assertEqual(_match_abbrev("--f",
1471                                        {"--foz": None,
1472                                         "--foo": None,
1473                                         "--fie": None,
1474                                         "--f": None}),
1475                          "--f")
1476 
1477     def test_match_abbrev_error(self):
1478         s = "--f"
1479         wordmap = {"--foz": None, "--foo": None, "--fie": None}
1480         possibilities = ", ".join(wordmap.keys())
1481         self.assertRaises(
1482             _match_abbrev, (s, wordmap), None,
1483             BadOptionError, "ambiguous option: --f (%s?)" % possibilities)
1484 
1485 
1486 def _testclasses():
1487     mod = sys.modules[__name__]
1488     return [getattr(mod, name) for name in dir(mod) if name.startswith('Test')]
1489 
1490 def suite():
1491     suite = unittest.TestSuite()
1492     for testclass in _testclasses():
1493         suite.addTest(unittest.makeSuite(testclass))
1494     return suite
1495 
1496 def test_main():
1497     test_support.run_suite(suite())
1498 
1499 if __name__ == '__main__':
1500     unittest.main()
1501 

Generated by PyXR 0.9.4
SourceForge.net Logo