symbian-qemu-0.9.1-12/python-2.6.1/Lib/test/test_optparse.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 #!/usr/bin/python
       
     2 
       
     3 #
       
     4 # Test suite for Optik.  Supplied by Johannes Gijsbers
       
     5 # (taradino@softhome.net) -- translated from the original Optik
       
     6 # test suite to this PyUnit-based version.
       
     7 #
       
     8 # $Id: test_optparse.py 61000 2008-02-23 17:40:11Z christian.heimes $
       
     9 #
       
    10 
       
    11 import sys
       
    12 import os
       
    13 import re
       
    14 import copy
       
    15 import types
       
    16 import unittest
       
    17 
       
    18 from StringIO import StringIO
       
    19 from test import test_support
       
    20 
       
    21 
       
    22 from optparse import make_option, Option, IndentedHelpFormatter, \
       
    23      TitledHelpFormatter, OptionParser, OptionContainer, OptionGroup, \
       
    24      SUPPRESS_HELP, SUPPRESS_USAGE, OptionError, OptionConflictError, \
       
    25      BadOptionError, OptionValueError, Values
       
    26 from optparse import _match_abbrev
       
    27 from optparse import _parse_num
       
    28 
       
    29 # Do the right thing with boolean values for all known Python versions.
       
    30 try:
       
    31     True, False
       
    32 except NameError:
       
    33     (True, False) = (1, 0)
       
    34 
       
    35 retype = type(re.compile(''))
       
    36 
       
    37 class InterceptedError(Exception):
       
    38     def __init__(self,
       
    39                  error_message=None,
       
    40                  exit_status=None,
       
    41                  exit_message=None):
       
    42         self.error_message = error_message
       
    43         self.exit_status = exit_status
       
    44         self.exit_message = exit_message
       
    45 
       
    46     def __str__(self):
       
    47         return self.error_message or self.exit_message or "intercepted error"
       
    48 
       
    49 class InterceptingOptionParser(OptionParser):
       
    50     def exit(self, status=0, msg=None):
       
    51         raise InterceptedError(exit_status=status, exit_message=msg)
       
    52 
       
    53     def error(self, msg):
       
    54         raise InterceptedError(error_message=msg)
       
    55 
       
    56 
       
    57 class BaseTest(unittest.TestCase):
       
    58     def assertParseOK(self, args, expected_opts, expected_positional_args):
       
    59         """Assert the options are what we expected when parsing arguments.
       
    60 
       
    61         Otherwise, fail with a nicely formatted message.
       
    62 
       
    63         Keyword arguments:
       
    64         args -- A list of arguments to parse with OptionParser.
       
    65         expected_opts -- The options expected.
       
    66         expected_positional_args -- The positional arguments expected.
       
    67 
       
    68         Returns the options and positional args for further testing.
       
    69         """
       
    70 
       
    71         (options, positional_args) = self.parser.parse_args(args)
       
    72         optdict = vars(options)
       
    73 
       
    74         self.assertEqual(optdict, expected_opts,
       
    75                          """
       
    76 Options are %(optdict)s.
       
    77 Should be %(expected_opts)s.
       
    78 Args were %(args)s.""" % locals())
       
    79 
       
    80         self.assertEqual(positional_args, expected_positional_args,
       
    81                          """
       
    82 Positional arguments are %(positional_args)s.
       
    83 Should be %(expected_positional_args)s.
       
    84 Args were %(args)s.""" % locals ())
       
    85 
       
    86         return (options, positional_args)
       
    87 
       
    88     def assertRaises(self,
       
    89                      func,
       
    90                      args,
       
    91                      kwargs,
       
    92                      expected_exception,
       
    93                      expected_message):
       
    94         """
       
    95         Assert that the expected exception is raised when calling a
       
    96         function, and that the right error message is included with
       
    97         that exception.
       
    98 
       
    99         Arguments:
       
   100           func -- the function to call
       
   101           args -- positional arguments to `func`
       
   102           kwargs -- keyword arguments to `func`
       
   103           expected_exception -- exception that should be raised
       
   104           expected_message -- expected exception message (or pattern
       
   105             if a compiled regex object)
       
   106 
       
   107         Returns the exception raised for further testing.
       
   108         """
       
   109         if args is None:
       
   110             args = ()
       
   111         if kwargs is None:
       
   112             kwargs = {}
       
   113 
       
   114         try:
       
   115             func(*args, **kwargs)
       
   116         except expected_exception, err:
       
   117             actual_message = str(err)
       
   118             if isinstance(expected_message, retype):
       
   119                 self.assert_(expected_message.search(actual_message),
       
   120                              """\
       
   121 expected exception message pattern:
       
   122 /%s/
       
   123 actual exception message:
       
   124 '''%s'''
       
   125 """ % (expected_message.pattern, actual_message))
       
   126             else:
       
   127                 self.assertEqual(actual_message,
       
   128                                  expected_message,
       
   129                                  """\
       
   130 expected exception message:
       
   131 '''%s'''
       
   132 actual exception message:
       
   133 '''%s'''
       
   134 """ % (expected_message, actual_message))
       
   135 
       
   136             return err
       
   137         else:
       
   138             self.fail("""expected exception %(expected_exception)s not raised
       
   139 called %(func)r
       
   140 with args %(args)r
       
   141 and kwargs %(kwargs)r
       
   142 """ % locals ())
       
   143 
       
   144 
       
   145     # -- Assertions used in more than one class --------------------
       
   146 
       
   147     def assertParseFail(self, cmdline_args, expected_output):
       
   148         """
       
   149         Assert the parser fails with the expected message.  Caller
       
   150         must ensure that self.parser is an InterceptingOptionParser.
       
   151         """
       
   152         try:
       
   153             self.parser.parse_args(cmdline_args)
       
   154         except InterceptedError, err:
       
   155             self.assertEqual(err.error_message, expected_output)
       
   156         else:
       
   157             self.assertFalse("expected parse failure")
       
   158 
       
   159     def assertOutput(self,
       
   160                      cmdline_args,
       
   161                      expected_output,
       
   162                      expected_status=0,
       
   163                      expected_error=None):
       
   164         """Assert the parser prints the expected output on stdout."""
       
   165         save_stdout = sys.stdout
       
   166         encoding = getattr(save_stdout, 'encoding', None)
       
   167         try:
       
   168             try:
       
   169                 sys.stdout = StringIO()
       
   170                 if encoding:
       
   171                     sys.stdout.encoding = encoding
       
   172                 self.parser.parse_args(cmdline_args)
       
   173             finally:
       
   174                 output = sys.stdout.getvalue()
       
   175                 sys.stdout = save_stdout
       
   176 
       
   177         except InterceptedError, err:
       
   178             self.assert_(
       
   179                 type(output) is types.StringType,
       
   180                 "expected output to be an ordinary string, not %r"
       
   181                 % type(output))
       
   182 
       
   183             if output != expected_output:
       
   184                 self.fail("expected: \n'''\n" + expected_output +
       
   185                           "'''\nbut got \n'''\n" + output + "'''")
       
   186             self.assertEqual(err.exit_status, expected_status)
       
   187             self.assertEqual(err.exit_message, expected_error)
       
   188         else:
       
   189             self.assertFalse("expected parser.exit()")
       
   190 
       
   191     def assertTypeError(self, func, expected_message, *args):
       
   192         """Assert that TypeError is raised when executing func."""
       
   193         self.assertRaises(func, args, None, TypeError, expected_message)
       
   194 
       
   195     def assertHelp(self, parser, expected_help):
       
   196         actual_help = parser.format_help()
       
   197         if actual_help != expected_help:
       
   198             raise self.failureException(
       
   199                 'help text failure; expected:\n"' +
       
   200                 expected_help + '"; got:\n"' +
       
   201                 actual_help + '"\n')
       
   202 
       
   203 # -- Test make_option() aka Option -------------------------------------
       
   204 
       
   205 # It's not necessary to test correct options here.  All the tests in the
       
   206 # parser.parse_args() section deal with those, because they're needed
       
   207 # there.
       
   208 
       
   209 class TestOptionChecks(BaseTest):
       
   210     def setUp(self):
       
   211         self.parser = OptionParser(usage=SUPPRESS_USAGE)
       
   212 
       
   213     def assertOptionError(self, expected_message, args=[], kwargs={}):
       
   214         self.assertRaises(make_option, args, kwargs,
       
   215                           OptionError, expected_message)
       
   216 
       
   217     def test_opt_string_empty(self):
       
   218         self.assertTypeError(make_option,
       
   219                              "at least one option string must be supplied")
       
   220 
       
   221     def test_opt_string_too_short(self):
       
   222         self.assertOptionError(
       
   223             "invalid option string 'b': must be at least two characters long",
       
   224             ["b"])
       
   225 
       
   226     def test_opt_string_short_invalid(self):
       
   227         self.assertOptionError(
       
   228             "invalid short option string '--': must be "
       
   229             "of the form -x, (x any non-dash char)",
       
   230             ["--"])
       
   231 
       
   232     def test_opt_string_long_invalid(self):
       
   233         self.assertOptionError(
       
   234             "invalid long option string '---': "
       
   235             "must start with --, followed by non-dash",
       
   236             ["---"])
       
   237 
       
   238     def test_attr_invalid(self):
       
   239         self.assertOptionError(
       
   240             "option -b: invalid keyword arguments: bar, foo",
       
   241             ["-b"], {'foo': None, 'bar': None})
       
   242 
       
   243     def test_action_invalid(self):
       
   244         self.assertOptionError(
       
   245             "option -b: invalid action: 'foo'",
       
   246             ["-b"], {'action': 'foo'})
       
   247 
       
   248     def test_type_invalid(self):
       
   249         self.assertOptionError(
       
   250             "option -b: invalid option type: 'foo'",
       
   251             ["-b"], {'type': 'foo'})
       
   252         self.assertOptionError(
       
   253             "option -b: invalid option type: 'tuple'",
       
   254             ["-b"], {'type': tuple})
       
   255 
       
   256     def test_no_type_for_action(self):
       
   257         self.assertOptionError(
       
   258             "option -b: must not supply a type for action 'count'",
       
   259             ["-b"], {'action': 'count', 'type': 'int'})
       
   260 
       
   261     def test_no_choices_list(self):
       
   262         self.assertOptionError(
       
   263             "option -b/--bad: must supply a list of "
       
   264             "choices for type 'choice'",
       
   265             ["-b", "--bad"], {'type': "choice"})
       
   266 
       
   267     def test_bad_choices_list(self):
       
   268         typename = type('').__name__
       
   269         self.assertOptionError(
       
   270             "option -b/--bad: choices must be a list of "
       
   271             "strings ('%s' supplied)" % typename,
       
   272             ["-b", "--bad"],
       
   273             {'type': "choice", 'choices':"bad choices"})
       
   274 
       
   275     def test_no_choices_for_type(self):
       
   276         self.assertOptionError(
       
   277             "option -b: must not supply choices for type 'int'",
       
   278             ["-b"], {'type': 'int', 'choices':"bad"})
       
   279 
       
   280     def test_no_const_for_action(self):
       
   281         self.assertOptionError(
       
   282             "option -b: 'const' must not be supplied for action 'store'",
       
   283             ["-b"], {'action': 'store', 'const': 1})
       
   284 
       
   285     def test_no_nargs_for_action(self):
       
   286         self.assertOptionError(
       
   287             "option -b: 'nargs' must not be supplied for action 'count'",
       
   288             ["-b"], {'action': 'count', 'nargs': 2})
       
   289 
       
   290     def test_callback_not_callable(self):
       
   291         self.assertOptionError(
       
   292             "option -b: callback not callable: 'foo'",
       
   293             ["-b"], {'action': 'callback',
       
   294                      'callback': 'foo'})
       
   295 
       
   296     def dummy(self):
       
   297         pass
       
   298 
       
   299     def test_callback_args_no_tuple(self):
       
   300         self.assertOptionError(
       
   301             "option -b: callback_args, if supplied, "
       
   302             "must be a tuple: not 'foo'",
       
   303             ["-b"], {'action': 'callback',
       
   304                      'callback': self.dummy,
       
   305                      'callback_args': 'foo'})
       
   306 
       
   307     def test_callback_kwargs_no_dict(self):
       
   308         self.assertOptionError(
       
   309             "option -b: callback_kwargs, if supplied, "
       
   310             "must be a dict: not 'foo'",
       
   311             ["-b"], {'action': 'callback',
       
   312                      'callback': self.dummy,
       
   313                      'callback_kwargs': 'foo'})
       
   314 
       
   315     def test_no_callback_for_action(self):
       
   316         self.assertOptionError(
       
   317             "option -b: callback supplied ('foo') for non-callback option",
       
   318             ["-b"], {'action': 'store',
       
   319                      'callback': 'foo'})
       
   320 
       
   321     def test_no_callback_args_for_action(self):
       
   322         self.assertOptionError(
       
   323             "option -b: callback_args supplied for non-callback option",
       
   324             ["-b"], {'action': 'store',
       
   325                      'callback_args': 'foo'})
       
   326 
       
   327     def test_no_callback_kwargs_for_action(self):
       
   328         self.assertOptionError(
       
   329             "option -b: callback_kwargs supplied for non-callback option",
       
   330             ["-b"], {'action': 'store',
       
   331                      'callback_kwargs': 'foo'})
       
   332 
       
   333 class TestOptionParser(BaseTest):
       
   334     def setUp(self):
       
   335         self.parser = OptionParser()
       
   336         self.parser.add_option("-v", "--verbose", "-n", "--noisy",
       
   337                           action="store_true", dest="verbose")
       
   338         self.parser.add_option("-q", "--quiet", "--silent",
       
   339                           action="store_false", dest="verbose")
       
   340 
       
   341     def test_add_option_no_Option(self):
       
   342         self.assertTypeError(self.parser.add_option,
       
   343                              "not an Option instance: None", None)
       
   344 
       
   345     def test_add_option_invalid_arguments(self):
       
   346         self.assertTypeError(self.parser.add_option,
       
   347                              "invalid arguments", None, None)
       
   348 
       
   349     def test_get_option(self):
       
   350         opt1 = self.parser.get_option("-v")
       
   351         self.assert_(isinstance(opt1, Option))
       
   352         self.assertEqual(opt1._short_opts, ["-v", "-n"])
       
   353         self.assertEqual(opt1._long_opts, ["--verbose", "--noisy"])
       
   354         self.assertEqual(opt1.action, "store_true")
       
   355         self.assertEqual(opt1.dest, "verbose")
       
   356 
       
   357     def test_get_option_equals(self):
       
   358         opt1 = self.parser.get_option("-v")
       
   359         opt2 = self.parser.get_option("--verbose")
       
   360         opt3 = self.parser.get_option("-n")
       
   361         opt4 = self.parser.get_option("--noisy")
       
   362         self.assert_(opt1 is opt2 is opt3 is opt4)
       
   363 
       
   364     def test_has_option(self):
       
   365         self.assert_(self.parser.has_option("-v"))
       
   366         self.assert_(self.parser.has_option("--verbose"))
       
   367 
       
   368     def assert_removed(self):
       
   369         self.assert_(self.parser.get_option("-v") is None)
       
   370         self.assert_(self.parser.get_option("--verbose") is None)
       
   371         self.assert_(self.parser.get_option("-n") is None)
       
   372         self.assert_(self.parser.get_option("--noisy") is None)
       
   373 
       
   374         self.failIf(self.parser.has_option("-v"))
       
   375         self.failIf(self.parser.has_option("--verbose"))
       
   376         self.failIf(self.parser.has_option("-n"))
       
   377         self.failIf(self.parser.has_option("--noisy"))
       
   378 
       
   379         self.assert_(self.parser.has_option("-q"))
       
   380         self.assert_(self.parser.has_option("--silent"))
       
   381 
       
   382     def test_remove_short_opt(self):
       
   383         self.parser.remove_option("-n")
       
   384         self.assert_removed()
       
   385 
       
   386     def test_remove_long_opt(self):
       
   387         self.parser.remove_option("--verbose")
       
   388         self.assert_removed()
       
   389 
       
   390     def test_remove_nonexistent(self):
       
   391         self.assertRaises(self.parser.remove_option, ('foo',), None,
       
   392                           ValueError, "no such option 'foo'")
       
   393 
       
   394     def test_refleak(self):
       
   395         # If an OptionParser is carrying around a reference to a large
       
   396         # object, various cycles can prevent it from being GC'd in
       
   397         # a timely fashion.  destroy() breaks the cycles to ensure stuff
       
   398         # can be cleaned up.
       
   399         big_thing = [42]
       
   400         refcount = sys.getrefcount(big_thing)
       
   401         parser = OptionParser()
       
   402         parser.add_option("-a", "--aaarggh")
       
   403         parser.big_thing = big_thing
       
   404 
       
   405         parser.destroy()
       
   406         #self.assertEqual(refcount, sys.getrefcount(big_thing))
       
   407         del parser
       
   408         self.assertEqual(refcount, sys.getrefcount(big_thing))
       
   409 
       
   410 
       
   411 class TestOptionValues(BaseTest):
       
   412     def setUp(self):
       
   413         pass
       
   414 
       
   415     def test_basics(self):
       
   416         values = Values()
       
   417         self.assertEqual(vars(values), {})
       
   418         self.assertEqual(values, {})
       
   419         self.assertNotEqual(values, {"foo": "bar"})
       
   420         self.assertNotEqual(values, "")
       
   421 
       
   422         dict = {"foo": "bar", "baz": 42}
       
   423         values = Values(defaults=dict)
       
   424         self.assertEqual(vars(values), dict)
       
   425         self.assertEqual(values, dict)
       
   426         self.assertNotEqual(values, {"foo": "bar"})
       
   427         self.assertNotEqual(values, {})
       
   428         self.assertNotEqual(values, "")
       
   429         self.assertNotEqual(values, [])
       
   430 
       
   431 
       
   432 class TestTypeAliases(BaseTest):
       
   433     def setUp(self):
       
   434         self.parser = OptionParser()
       
   435 
       
   436     def test_str_aliases_string(self):
       
   437         self.parser.add_option("-s", type="str")
       
   438         self.assertEquals(self.parser.get_option("-s").type, "string")
       
   439 
       
   440     def test_new_type_object(self):
       
   441         self.parser.add_option("-s", type=str)
       
   442         self.assertEquals(self.parser.get_option("-s").type, "string")
       
   443         self.parser.add_option("-x", type=int)
       
   444         self.assertEquals(self.parser.get_option("-x").type, "int")
       
   445 
       
   446     def test_old_type_object(self):
       
   447         self.parser.add_option("-s", type=types.StringType)
       
   448         self.assertEquals(self.parser.get_option("-s").type, "string")
       
   449         self.parser.add_option("-x", type=types.IntType)
       
   450         self.assertEquals(self.parser.get_option("-x").type, "int")
       
   451 
       
   452 
       
   453 # Custom type for testing processing of default values.
       
   454 _time_units = { 's' : 1, 'm' : 60, 'h' : 60*60, 'd' : 60*60*24 }
       
   455 
       
   456 def _check_duration(option, opt, value):
       
   457     try:
       
   458         if value[-1].isdigit():
       
   459             return int(value)
       
   460         else:
       
   461             return int(value[:-1]) * _time_units[value[-1]]
       
   462     except ValueError, IndexError:
       
   463         raise OptionValueError(
       
   464             'option %s: invalid duration: %r' % (opt, value))
       
   465 
       
   466 class DurationOption(Option):
       
   467     TYPES = Option.TYPES + ('duration',)
       
   468     TYPE_CHECKER = copy.copy(Option.TYPE_CHECKER)
       
   469     TYPE_CHECKER['duration'] = _check_duration
       
   470 
       
   471 class TestDefaultValues(BaseTest):
       
   472     def setUp(self):
       
   473         self.parser = OptionParser()
       
   474         self.parser.add_option("-v", "--verbose", default=True)
       
   475         self.parser.add_option("-q", "--quiet", dest='verbose')
       
   476         self.parser.add_option("-n", type="int", default=37)
       
   477         self.parser.add_option("-m", type="int")
       
   478         self.parser.add_option("-s", default="foo")
       
   479         self.parser.add_option("-t")
       
   480         self.parser.add_option("-u", default=None)
       
   481         self.expected = { 'verbose': True,
       
   482                           'n': 37,
       
   483                           'm': None,
       
   484                           's': "foo",
       
   485                           't': None,
       
   486                           'u': None }
       
   487 
       
   488     def test_basic_defaults(self):
       
   489         self.assertEqual(self.parser.get_default_values(), self.expected)
       
   490 
       
   491     def test_mixed_defaults_post(self):
       
   492         self.parser.set_defaults(n=42, m=-100)
       
   493         self.expected.update({'n': 42, 'm': -100})
       
   494         self.assertEqual(self.parser.get_default_values(), self.expected)
       
   495 
       
   496     def test_mixed_defaults_pre(self):
       
   497         self.parser.set_defaults(x="barf", y="blah")
       
   498         self.parser.add_option("-x", default="frob")
       
   499         self.parser.add_option("-y")
       
   500 
       
   501         self.expected.update({'x': "frob", 'y': "blah"})
       
   502         self.assertEqual(self.parser.get_default_values(), self.expected)
       
   503 
       
   504         self.parser.remove_option("-y")
       
   505         self.parser.add_option("-y", default=None)
       
   506         self.expected.update({'y': None})
       
   507         self.assertEqual(self.parser.get_default_values(), self.expected)
       
   508 
       
   509     def test_process_default(self):
       
   510         self.parser.option_class = DurationOption
       
   511         self.parser.add_option("-d", type="duration", default=300)
       
   512         self.parser.add_option("-e", type="duration", default="6m")
       
   513         self.parser.set_defaults(n="42")
       
   514         self.expected.update({'d': 300, 'e': 360, 'n': 42})
       
   515         self.assertEqual(self.parser.get_default_values(), self.expected)
       
   516 
       
   517         self.parser.set_process_default_values(False)
       
   518         self.expected.update({'d': 300, 'e': "6m", 'n': "42"})
       
   519         self.assertEqual(self.parser.get_default_values(), self.expected)
       
   520 
       
   521 
       
   522 class TestProgName(BaseTest):
       
   523     """
       
   524     Test that %prog expands to the right thing in usage, version,
       
   525     and help strings.
       
   526     """
       
   527 
       
   528     def assertUsage(self, parser, expected_usage):
       
   529         self.assertEqual(parser.get_usage(), expected_usage)
       
   530 
       
   531     def assertVersion(self, parser, expected_version):
       
   532         self.assertEqual(parser.get_version(), expected_version)
       
   533 
       
   534 
       
   535     def test_default_progname(self):
       
   536         # Make sure that program name taken from sys.argv[0] by default.
       
   537         save_argv = sys.argv[:]
       
   538         try:
       
   539             sys.argv[0] = os.path.join("foo", "bar", "baz.py")
       
   540             parser = OptionParser("%prog ...", version="%prog 1.2")
       
   541             expected_usage = "Usage: baz.py ...\n"
       
   542             self.assertUsage(parser, expected_usage)
       
   543             self.assertVersion(parser, "baz.py 1.2")
       
   544             self.assertHelp(parser,
       
   545                             expected_usage + "\n" +
       
   546                             "Options:\n"
       
   547                             "  --version   show program's version number and exit\n"
       
   548                             "  -h, --help  show this help message and exit\n")
       
   549         finally:
       
   550             sys.argv[:] = save_argv
       
   551 
       
   552     def test_custom_progname(self):
       
   553         parser = OptionParser(prog="thingy",
       
   554                               version="%prog 0.1",
       
   555                               usage="%prog arg arg")
       
   556         parser.remove_option("-h")
       
   557         parser.remove_option("--version")
       
   558         expected_usage = "Usage: thingy arg arg\n"
       
   559         self.assertUsage(parser, expected_usage)
       
   560         self.assertVersion(parser, "thingy 0.1")
       
   561         self.assertHelp(parser, expected_usage + "\n")
       
   562 
       
   563 
       
   564 class TestExpandDefaults(BaseTest):
       
   565     def setUp(self):
       
   566         self.parser = OptionParser(prog="test")
       
   567         self.help_prefix = """\
       
   568 Usage: test [options]
       
   569 
       
   570 Options:
       
   571   -h, --help            show this help message and exit
       
   572 """
       
   573         self.file_help = "read from FILE [default: %default]"
       
   574         self.expected_help_file = self.help_prefix + \
       
   575             "  -f FILE, --file=FILE  read from FILE [default: foo.txt]\n"
       
   576         self.expected_help_none = self.help_prefix + \
       
   577             "  -f FILE, --file=FILE  read from FILE [default: none]\n"
       
   578 
       
   579     def test_option_default(self):
       
   580         self.parser.add_option("-f", "--file",
       
   581                                default="foo.txt",
       
   582                                help=self.file_help)
       
   583         self.assertHelp(self.parser, self.expected_help_file)
       
   584 
       
   585     def test_parser_default_1(self):
       
   586         self.parser.add_option("-f", "--file",
       
   587                                help=self.file_help)
       
   588         self.parser.set_default('file', "foo.txt")
       
   589         self.assertHelp(self.parser, self.expected_help_file)
       
   590 
       
   591     def test_parser_default_2(self):
       
   592         self.parser.add_option("-f", "--file",
       
   593                                help=self.file_help)
       
   594         self.parser.set_defaults(file="foo.txt")
       
   595         self.assertHelp(self.parser, self.expected_help_file)
       
   596 
       
   597     def test_no_default(self):
       
   598         self.parser.add_option("-f", "--file",
       
   599                                help=self.file_help)
       
   600         self.assertHelp(self.parser, self.expected_help_none)
       
   601 
       
   602     def test_default_none_1(self):
       
   603         self.parser.add_option("-f", "--file",
       
   604                                default=None,
       
   605                                help=self.file_help)
       
   606         self.assertHelp(self.parser, self.expected_help_none)
       
   607 
       
   608     def test_default_none_2(self):
       
   609         self.parser.add_option("-f", "--file",
       
   610                                help=self.file_help)
       
   611         self.parser.set_defaults(file=None)
       
   612         self.assertHelp(self.parser, self.expected_help_none)
       
   613 
       
   614     def test_float_default(self):
       
   615         self.parser.add_option(
       
   616             "-p", "--prob",
       
   617             help="blow up with probability PROB [default: %default]")
       
   618         self.parser.set_defaults(prob=0.43)
       
   619         expected_help = self.help_prefix + \
       
   620             "  -p PROB, --prob=PROB  blow up with probability PROB [default: 0.43]\n"
       
   621         self.assertHelp(self.parser, expected_help)
       
   622 
       
   623     def test_alt_expand(self):
       
   624         self.parser.add_option("-f", "--file",
       
   625                                default="foo.txt",
       
   626                                help="read from FILE [default: *DEFAULT*]")
       
   627         self.parser.formatter.default_tag = "*DEFAULT*"
       
   628         self.assertHelp(self.parser, self.expected_help_file)
       
   629 
       
   630     def test_no_expand(self):
       
   631         self.parser.add_option("-f", "--file",
       
   632                                default="foo.txt",
       
   633                                help="read from %default file")
       
   634         self.parser.formatter.default_tag = None
       
   635         expected_help = self.help_prefix + \
       
   636             "  -f FILE, --file=FILE  read from %default file\n"
       
   637         self.assertHelp(self.parser, expected_help)
       
   638 
       
   639 
       
   640 # -- Test parser.parse_args() ------------------------------------------
       
   641 
       
   642 class TestStandard(BaseTest):
       
   643     def setUp(self):
       
   644         options = [make_option("-a", type="string"),
       
   645                    make_option("-b", "--boo", type="int", dest='boo'),
       
   646                    make_option("--foo", action="append")]
       
   647 
       
   648         self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
       
   649                                                option_list=options)
       
   650 
       
   651     def test_required_value(self):
       
   652         self.assertParseFail(["-a"], "-a option requires an argument")
       
   653 
       
   654     def test_invalid_integer(self):
       
   655         self.assertParseFail(["-b", "5x"],
       
   656                              "option -b: invalid integer value: '5x'")
       
   657 
       
   658     def test_no_such_option(self):
       
   659         self.assertParseFail(["--boo13"], "no such option: --boo13")
       
   660 
       
   661     def test_long_invalid_integer(self):
       
   662         self.assertParseFail(["--boo=x5"],
       
   663                              "option --boo: invalid integer value: 'x5'")
       
   664 
       
   665     def test_empty(self):
       
   666         self.assertParseOK([], {'a': None, 'boo': None, 'foo': None}, [])
       
   667 
       
   668     def test_shortopt_empty_longopt_append(self):
       
   669         self.assertParseOK(["-a", "", "--foo=blah", "--foo="],
       
   670                            {'a': "", 'boo': None, 'foo': ["blah", ""]},
       
   671                            [])
       
   672 
       
   673     def test_long_option_append(self):
       
   674         self.assertParseOK(["--foo", "bar", "--foo", "", "--foo=x"],
       
   675                            {'a': None,
       
   676                             'boo': None,
       
   677                             'foo': ["bar", "", "x"]},
       
   678                            [])
       
   679 
       
   680     def test_option_argument_joined(self):
       
   681         self.assertParseOK(["-abc"],
       
   682                            {'a': "bc", 'boo': None, 'foo': None},
       
   683                            [])
       
   684 
       
   685     def test_option_argument_split(self):
       
   686         self.assertParseOK(["-a", "34"],
       
   687                            {'a': "34", 'boo': None, 'foo': None},
       
   688                            [])
       
   689 
       
   690     def test_option_argument_joined_integer(self):
       
   691         self.assertParseOK(["-b34"],
       
   692                            {'a': None, 'boo': 34, 'foo': None},
       
   693                            [])
       
   694 
       
   695     def test_option_argument_split_negative_integer(self):
       
   696         self.assertParseOK(["-b", "-5"],
       
   697                            {'a': None, 'boo': -5, 'foo': None},
       
   698                            [])
       
   699 
       
   700     def test_long_option_argument_joined(self):
       
   701         self.assertParseOK(["--boo=13"],
       
   702                            {'a': None, 'boo': 13, 'foo': None},
       
   703                            [])
       
   704 
       
   705     def test_long_option_argument_split(self):
       
   706         self.assertParseOK(["--boo", "111"],
       
   707                            {'a': None, 'boo': 111, 'foo': None},
       
   708                            [])
       
   709 
       
   710     def test_long_option_short_option(self):
       
   711         self.assertParseOK(["--foo=bar", "-axyz"],
       
   712                            {'a': 'xyz', 'boo': None, 'foo': ["bar"]},
       
   713                            [])
       
   714 
       
   715     def test_abbrev_long_option(self):
       
   716         self.assertParseOK(["--f=bar", "-axyz"],
       
   717                            {'a': 'xyz', 'boo': None, 'foo': ["bar"]},
       
   718                            [])
       
   719 
       
   720     def test_defaults(self):
       
   721         (options, args) = self.parser.parse_args([])
       
   722         defaults = self.parser.get_default_values()
       
   723         self.assertEqual(vars(defaults), vars(options))
       
   724 
       
   725     def test_ambiguous_option(self):
       
   726         self.parser.add_option("--foz", action="store",
       
   727                                type="string", dest="foo")
       
   728         self.assertParseFail(["--f=bar"],
       
   729                              "ambiguous option: --f (--foo, --foz?)")
       
   730 
       
   731 
       
   732     def test_short_and_long_option_split(self):
       
   733         self.assertParseOK(["-a", "xyz", "--foo", "bar"],
       
   734                            {'a': 'xyz', 'boo': None, 'foo': ["bar"]},
       
   735                            []),
       
   736 
       
   737     def test_short_option_split_long_option_append(self):
       
   738         self.assertParseOK(["--foo=bar", "-b", "123", "--foo", "baz"],
       
   739                            {'a': None, 'boo': 123, 'foo': ["bar", "baz"]},
       
   740                            [])
       
   741 
       
   742     def test_short_option_split_one_positional_arg(self):
       
   743         self.assertParseOK(["-a", "foo", "bar"],
       
   744                            {'a': "foo", 'boo': None, 'foo': None},
       
   745                            ["bar"]),
       
   746 
       
   747     def test_short_option_consumes_separator(self):
       
   748         self.assertParseOK(["-a", "--", "foo", "bar"],
       
   749                            {'a': "--", 'boo': None, 'foo': None},
       
   750                            ["foo", "bar"]),
       
   751         self.assertParseOK(["-a", "--", "--foo", "bar"],
       
   752                            {'a': "--", 'boo': None, 'foo': ["bar"]},
       
   753                            []),
       
   754 
       
   755     def test_short_option_joined_and_separator(self):
       
   756         self.assertParseOK(["-ab", "--", "--foo", "bar"],
       
   757                            {'a': "b", 'boo': None, 'foo': None},
       
   758                            ["--foo", "bar"]),
       
   759 
       
   760     def test_hyphen_becomes_positional_arg(self):
       
   761         self.assertParseOK(["-ab", "-", "--foo", "bar"],
       
   762                            {'a': "b", 'boo': None, 'foo': ["bar"]},
       
   763                            ["-"])
       
   764 
       
   765     def test_no_append_versus_append(self):
       
   766         self.assertParseOK(["-b3", "-b", "5", "--foo=bar", "--foo", "baz"],
       
   767                            {'a': None, 'boo': 5, 'foo': ["bar", "baz"]},
       
   768                            [])
       
   769 
       
   770     def test_option_consumes_optionlike_string(self):
       
   771         self.assertParseOK(["-a", "-b3"],
       
   772                            {'a': "-b3", 'boo': None, 'foo': None},
       
   773                            [])
       
   774 
       
   775 class TestBool(BaseTest):
       
   776     def setUp(self):
       
   777         options = [make_option("-v",
       
   778                                "--verbose",
       
   779                                action="store_true",
       
   780                                dest="verbose",
       
   781                                default=''),
       
   782                    make_option("-q",
       
   783                                "--quiet",
       
   784                                action="store_false",
       
   785                                dest="verbose")]
       
   786         self.parser = OptionParser(option_list = options)
       
   787 
       
   788     def test_bool_default(self):
       
   789         self.assertParseOK([],
       
   790                            {'verbose': ''},
       
   791                            [])
       
   792 
       
   793     def test_bool_false(self):
       
   794         (options, args) = self.assertParseOK(["-q"],
       
   795                                              {'verbose': 0},
       
   796                                              [])
       
   797         if hasattr(__builtins__, 'False'):
       
   798             self.failUnless(options.verbose is False)
       
   799 
       
   800     def test_bool_true(self):
       
   801         (options, args) = self.assertParseOK(["-v"],
       
   802                                              {'verbose': 1},
       
   803                                              [])
       
   804         if hasattr(__builtins__, 'True'):
       
   805             self.failUnless(options.verbose is True)
       
   806 
       
   807     def test_bool_flicker_on_and_off(self):
       
   808         self.assertParseOK(["-qvq", "-q", "-v"],
       
   809                            {'verbose': 1},
       
   810                            [])
       
   811 
       
   812 class TestChoice(BaseTest):
       
   813     def setUp(self):
       
   814         self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
       
   815         self.parser.add_option("-c", action="store", type="choice",
       
   816                                dest="choice", choices=["one", "two", "three"])
       
   817 
       
   818     def test_valid_choice(self):
       
   819         self.assertParseOK(["-c", "one", "xyz"],
       
   820                            {'choice': 'one'},
       
   821                            ["xyz"])
       
   822 
       
   823     def test_invalid_choice(self):
       
   824         self.assertParseFail(["-c", "four", "abc"],
       
   825                              "option -c: invalid choice: 'four' "
       
   826                              "(choose from 'one', 'two', 'three')")
       
   827 
       
   828     def test_add_choice_option(self):
       
   829         self.parser.add_option("-d", "--default",
       
   830                                choices=["four", "five", "six"])
       
   831         opt = self.parser.get_option("-d")
       
   832         self.assertEqual(opt.type, "choice")
       
   833         self.assertEqual(opt.action, "store")
       
   834 
       
   835 class TestCount(BaseTest):
       
   836     def setUp(self):
       
   837         self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
       
   838         self.v_opt = make_option("-v", action="count", dest="verbose")
       
   839         self.parser.add_option(self.v_opt)
       
   840         self.parser.add_option("--verbose", type="int", dest="verbose")
       
   841         self.parser.add_option("-q", "--quiet",
       
   842                                action="store_const", dest="verbose", const=0)
       
   843 
       
   844     def test_empty(self):
       
   845         self.assertParseOK([], {'verbose': None}, [])
       
   846 
       
   847     def test_count_one(self):
       
   848         self.assertParseOK(["-v"], {'verbose': 1}, [])
       
   849 
       
   850     def test_count_three(self):
       
   851         self.assertParseOK(["-vvv"], {'verbose': 3}, [])
       
   852 
       
   853     def test_count_three_apart(self):
       
   854         self.assertParseOK(["-v", "-v", "-v"], {'verbose': 3}, [])
       
   855 
       
   856     def test_count_override_amount(self):
       
   857         self.assertParseOK(["-vvv", "--verbose=2"], {'verbose': 2}, [])
       
   858 
       
   859     def test_count_override_quiet(self):
       
   860         self.assertParseOK(["-vvv", "--verbose=2", "-q"], {'verbose': 0}, [])
       
   861 
       
   862     def test_count_overriding(self):
       
   863         self.assertParseOK(["-vvv", "--verbose=2", "-q", "-v"],
       
   864                            {'verbose': 1}, [])
       
   865 
       
   866     def test_count_interspersed_args(self):
       
   867         self.assertParseOK(["--quiet", "3", "-v"],
       
   868                            {'verbose': 1},
       
   869                            ["3"])
       
   870 
       
   871     def test_count_no_interspersed_args(self):
       
   872         self.parser.disable_interspersed_args()
       
   873         self.assertParseOK(["--quiet", "3", "-v"],
       
   874                            {'verbose': 0},
       
   875                            ["3", "-v"])
       
   876 
       
   877     def test_count_no_such_option(self):
       
   878         self.assertParseFail(["-q3", "-v"], "no such option: -3")
       
   879 
       
   880     def test_count_option_no_value(self):
       
   881         self.assertParseFail(["--quiet=3", "-v"],
       
   882                              "--quiet option does not take a value")
       
   883 
       
   884     def test_count_with_default(self):
       
   885         self.parser.set_default('verbose', 0)
       
   886         self.assertParseOK([], {'verbose':0}, [])
       
   887 
       
   888     def test_count_overriding_default(self):
       
   889         self.parser.set_default('verbose', 0)
       
   890         self.assertParseOK(["-vvv", "--verbose=2", "-q", "-v"],
       
   891                            {'verbose': 1}, [])
       
   892 
       
   893 class TestMultipleArgs(BaseTest):
       
   894     def setUp(self):
       
   895         self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
       
   896         self.parser.add_option("-p", "--point",
       
   897                                action="store", nargs=3, type="float", dest="point")
       
   898 
       
   899     def test_nargs_with_positional_args(self):
       
   900         self.assertParseOK(["foo", "-p", "1", "2.5", "-4.3", "xyz"],
       
   901                            {'point': (1.0, 2.5, -4.3)},
       
   902                            ["foo", "xyz"])
       
   903 
       
   904     def test_nargs_long_opt(self):
       
   905         self.assertParseOK(["--point", "-1", "2.5", "-0", "xyz"],
       
   906                            {'point': (-1.0, 2.5, -0.0)},
       
   907                            ["xyz"])
       
   908 
       
   909     def test_nargs_invalid_float_value(self):
       
   910         self.assertParseFail(["-p", "1.0", "2x", "3.5"],
       
   911                              "option -p: "
       
   912                              "invalid floating-point value: '2x'")
       
   913 
       
   914     def test_nargs_required_values(self):
       
   915         self.assertParseFail(["--point", "1.0", "3.5"],
       
   916                              "--point option requires 3 arguments")
       
   917 
       
   918 class TestMultipleArgsAppend(BaseTest):
       
   919     def setUp(self):
       
   920         self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
       
   921         self.parser.add_option("-p", "--point", action="store", nargs=3,
       
   922                                type="float", dest="point")
       
   923         self.parser.add_option("-f", "--foo", action="append", nargs=2,
       
   924                                type="int", dest="foo")
       
   925         self.parser.add_option("-z", "--zero", action="append_const",
       
   926                                dest="foo", const=(0, 0))
       
   927 
       
   928     def test_nargs_append(self):
       
   929         self.assertParseOK(["-f", "4", "-3", "blah", "--foo", "1", "666"],
       
   930                            {'point': None, 'foo': [(4, -3), (1, 666)]},
       
   931                            ["blah"])
       
   932 
       
   933     def test_nargs_append_required_values(self):
       
   934         self.assertParseFail(["-f4,3"],
       
   935                              "-f option requires 2 arguments")
       
   936 
       
   937     def test_nargs_append_simple(self):
       
   938         self.assertParseOK(["--foo=3", "4"],
       
   939                            {'point': None, 'foo':[(3, 4)]},
       
   940                            [])
       
   941 
       
   942     def test_nargs_append_const(self):
       
   943         self.assertParseOK(["--zero", "--foo", "3", "4", "-z"],
       
   944                            {'point': None, 'foo':[(0, 0), (3, 4), (0, 0)]},
       
   945                            [])
       
   946 
       
   947 class TestVersion(BaseTest):
       
   948     def test_version(self):
       
   949         self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
       
   950                                                version="%prog 0.1")
       
   951         save_argv = sys.argv[:]
       
   952         try:
       
   953             sys.argv[0] = os.path.join(os.curdir, "foo", "bar")
       
   954             self.assertOutput(["--version"], "bar 0.1\n")
       
   955         finally:
       
   956             sys.argv[:] = save_argv
       
   957 
       
   958     def test_no_version(self):
       
   959         self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
       
   960         self.assertParseFail(["--version"],
       
   961                              "no such option: --version")
       
   962 
       
   963 # -- Test conflicting default values and parser.parse_args() -----------
       
   964 
       
   965 class TestConflictingDefaults(BaseTest):
       
   966     """Conflicting default values: the last one should win."""
       
   967     def setUp(self):
       
   968         self.parser = OptionParser(option_list=[
       
   969             make_option("-v", action="store_true", dest="verbose", default=1)])
       
   970 
       
   971     def test_conflict_default(self):
       
   972         self.parser.add_option("-q", action="store_false", dest="verbose",
       
   973                                default=0)
       
   974         self.assertParseOK([], {'verbose': 0}, [])
       
   975 
       
   976     def test_conflict_default_none(self):
       
   977         self.parser.add_option("-q", action="store_false", dest="verbose",
       
   978                                default=None)
       
   979         self.assertParseOK([], {'verbose': None}, [])
       
   980 
       
   981 class TestOptionGroup(BaseTest):
       
   982     def setUp(self):
       
   983         self.parser = OptionParser(usage=SUPPRESS_USAGE)
       
   984 
       
   985     def test_option_group_create_instance(self):
       
   986         group = OptionGroup(self.parser, "Spam")
       
   987         self.parser.add_option_group(group)
       
   988         group.add_option("--spam", action="store_true",
       
   989                          help="spam spam spam spam")
       
   990         self.assertParseOK(["--spam"], {'spam': 1}, [])
       
   991 
       
   992     def test_add_group_no_group(self):
       
   993         self.assertTypeError(self.parser.add_option_group,
       
   994                              "not an OptionGroup instance: None", None)
       
   995 
       
   996     def test_add_group_invalid_arguments(self):
       
   997         self.assertTypeError(self.parser.add_option_group,
       
   998                              "invalid arguments", None, None)
       
   999 
       
  1000     def test_add_group_wrong_parser(self):
       
  1001         group = OptionGroup(self.parser, "Spam")
       
  1002         group.parser = OptionParser()
       
  1003         self.assertRaises(self.parser.add_option_group, (group,), None,
       
  1004                           ValueError, "invalid OptionGroup (wrong parser)")
       
  1005 
       
  1006     def test_group_manipulate(self):
       
  1007         group = self.parser.add_option_group("Group 2",
       
  1008                                              description="Some more options")
       
  1009         group.set_title("Bacon")
       
  1010         group.add_option("--bacon", type="int")
       
  1011         self.assert_(self.parser.get_option_group("--bacon"), group)
       
  1012 
       
  1013 # -- Test extending and parser.parse_args() ----------------------------
       
  1014 
       
  1015 class TestExtendAddTypes(BaseTest):
       
  1016     def setUp(self):
       
  1017         self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
       
  1018                                                option_class=self.MyOption)
       
  1019         self.parser.add_option("-a", None, type="string", dest="a")
       
  1020         self.parser.add_option("-f", "--file", type="file", dest="file")
       
  1021 
       
  1022     def tearDown(self):
       
  1023         if os.path.isdir(test_support.TESTFN):
       
  1024             os.rmdir(test_support.TESTFN)
       
  1025         elif os.path.isfile(test_support.TESTFN):
       
  1026             os.unlink(test_support.TESTFN)
       
  1027 
       
  1028     class MyOption (Option):
       
  1029         def check_file(option, opt, value):
       
  1030             if not os.path.exists(value):
       
  1031                 raise OptionValueError("%s: file does not exist" % value)
       
  1032             elif not os.path.isfile(value):
       
  1033                 raise OptionValueError("%s: not a regular file" % value)
       
  1034             return value
       
  1035 
       
  1036         TYPES = Option.TYPES + ("file",)
       
  1037         TYPE_CHECKER = copy.copy(Option.TYPE_CHECKER)
       
  1038         TYPE_CHECKER["file"] = check_file
       
  1039 
       
  1040     def test_filetype_ok(self):
       
  1041         open(test_support.TESTFN, "w").close()
       
  1042         self.assertParseOK(["--file", test_support.TESTFN, "-afoo"],
       
  1043                            {'file': test_support.TESTFN, 'a': 'foo'},
       
  1044                            [])
       
  1045 
       
  1046     def test_filetype_noexist(self):
       
  1047         self.assertParseFail(["--file", test_support.TESTFN, "-afoo"],
       
  1048                              "%s: file does not exist" %
       
  1049                              test_support.TESTFN)
       
  1050 
       
  1051     def test_filetype_notfile(self):
       
  1052         os.mkdir(test_support.TESTFN)
       
  1053         self.assertParseFail(["--file", test_support.TESTFN, "-afoo"],
       
  1054                              "%s: not a regular file" %
       
  1055                              test_support.TESTFN)
       
  1056 
       
  1057 
       
  1058 class TestExtendAddActions(BaseTest):
       
  1059     def setUp(self):
       
  1060         options = [self.MyOption("-a", "--apple", action="extend",
       
  1061                                  type="string", dest="apple")]
       
  1062         self.parser = OptionParser(option_list=options)
       
  1063 
       
  1064     class MyOption (Option):
       
  1065         ACTIONS = Option.ACTIONS + ("extend",)
       
  1066         STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",)
       
  1067         TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",)
       
  1068 
       
  1069         def take_action(self, action, dest, opt, value, values, parser):
       
  1070             if action == "extend":
       
  1071                 lvalue = value.split(",")
       
  1072                 values.ensure_value(dest, []).extend(lvalue)
       
  1073             else:
       
  1074                 Option.take_action(self, action, dest, opt, parser, value,
       
  1075                                    values)
       
  1076 
       
  1077     def test_extend_add_action(self):
       
  1078         self.assertParseOK(["-afoo,bar", "--apple=blah"],
       
  1079                            {'apple': ["foo", "bar", "blah"]},
       
  1080                            [])
       
  1081 
       
  1082     def test_extend_add_action_normal(self):
       
  1083         self.assertParseOK(["-a", "foo", "-abar", "--apple=x,y"],
       
  1084                            {'apple': ["foo", "bar", "x", "y"]},
       
  1085                            [])
       
  1086 
       
  1087 # -- Test callbacks and parser.parse_args() ----------------------------
       
  1088 
       
  1089 class TestCallback(BaseTest):
       
  1090     def setUp(self):
       
  1091         options = [make_option("-x",
       
  1092                                None,
       
  1093                                action="callback",
       
  1094                                callback=self.process_opt),
       
  1095                    make_option("-f",
       
  1096                                "--file",
       
  1097                                action="callback",
       
  1098                                callback=self.process_opt,
       
  1099                                type="string",
       
  1100                                dest="filename")]
       
  1101         self.parser = OptionParser(option_list=options)
       
  1102 
       
  1103     def process_opt(self, option, opt, value, parser_):
       
  1104         if opt == "-x":
       
  1105             self.assertEqual(option._short_opts, ["-x"])
       
  1106             self.assertEqual(option._long_opts, [])
       
  1107             self.assert_(parser_ is self.parser)
       
  1108             self.assert_(value is None)
       
  1109             self.assertEqual(vars(parser_.values), {'filename': None})
       
  1110 
       
  1111             parser_.values.x = 42
       
  1112         elif opt == "--file":
       
  1113             self.assertEqual(option._short_opts, ["-f"])
       
  1114             self.assertEqual(option._long_opts, ["--file"])
       
  1115             self.assert_(parser_ is self.parser)
       
  1116             self.assertEqual(value, "foo")
       
  1117             self.assertEqual(vars(parser_.values), {'filename': None, 'x': 42})
       
  1118 
       
  1119             setattr(parser_.values, option.dest, value)
       
  1120         else:
       
  1121             self.fail("Unknown option %r in process_opt." % opt)
       
  1122 
       
  1123     def test_callback(self):
       
  1124         self.assertParseOK(["-x", "--file=foo"],
       
  1125                            {'filename': "foo", 'x': 42},
       
  1126                            [])
       
  1127 
       
  1128     def test_callback_help(self):
       
  1129         # This test was prompted by SF bug #960515 -- the point is
       
  1130         # not to inspect the help text, just to make sure that
       
  1131         # format_help() doesn't crash.
       
  1132         parser = OptionParser(usage=SUPPRESS_USAGE)
       
  1133         parser.remove_option("-h")
       
  1134         parser.add_option("-t", "--test", action="callback",
       
  1135                           callback=lambda: None, type="string",
       
  1136                           help="foo")
       
  1137 
       
  1138         expected_help = ("Options:\n"
       
  1139                          "  -t TEST, --test=TEST  foo\n")
       
  1140         self.assertHelp(parser, expected_help)
       
  1141 
       
  1142 
       
  1143 class TestCallbackExtraArgs(BaseTest):
       
  1144     def setUp(self):
       
  1145         options = [make_option("-p", "--point", action="callback",
       
  1146                                callback=self.process_tuple,
       
  1147                                callback_args=(3, int), type="string",
       
  1148                                dest="points", default=[])]
       
  1149         self.parser = OptionParser(option_list=options)
       
  1150 
       
  1151     def process_tuple(self, option, opt, value, parser_, len, type):
       
  1152         self.assertEqual(len, 3)
       
  1153         self.assert_(type is int)
       
  1154 
       
  1155         if opt == "-p":
       
  1156             self.assertEqual(value, "1,2,3")
       
  1157         elif opt == "--point":
       
  1158             self.assertEqual(value, "4,5,6")
       
  1159 
       
  1160         value = tuple(map(type, value.split(",")))
       
  1161         getattr(parser_.values, option.dest).append(value)
       
  1162 
       
  1163     def test_callback_extra_args(self):
       
  1164         self.assertParseOK(["-p1,2,3", "--point", "4,5,6"],
       
  1165                            {'points': [(1,2,3), (4,5,6)]},
       
  1166                            [])
       
  1167 
       
  1168 class TestCallbackMeddleArgs(BaseTest):
       
  1169     def setUp(self):
       
  1170         options = [make_option(str(x), action="callback",
       
  1171                                callback=self.process_n, dest='things')
       
  1172                    for x in range(-1, -6, -1)]
       
  1173         self.parser = OptionParser(option_list=options)
       
  1174 
       
  1175     # Callback that meddles in rargs, largs
       
  1176     def process_n(self, option, opt, value, parser_):
       
  1177         # option is -3, -5, etc.
       
  1178         nargs = int(opt[1:])
       
  1179         rargs = parser_.rargs
       
  1180         if len(rargs) < nargs:
       
  1181             self.fail("Expected %d arguments for %s option." % (nargs, opt))
       
  1182         dest = parser_.values.ensure_value(option.dest, [])
       
  1183         dest.append(tuple(rargs[0:nargs]))
       
  1184         parser_.largs.append(nargs)
       
  1185         del rargs[0:nargs]
       
  1186 
       
  1187     def test_callback_meddle_args(self):
       
  1188         self.assertParseOK(["-1", "foo", "-3", "bar", "baz", "qux"],
       
  1189                            {'things': [("foo",), ("bar", "baz", "qux")]},
       
  1190                            [1, 3])
       
  1191 
       
  1192     def test_callback_meddle_args_separator(self):
       
  1193         self.assertParseOK(["-2", "foo", "--"],
       
  1194                            {'things': [('foo', '--')]},
       
  1195                            [2])
       
  1196 
       
  1197 class TestCallbackManyArgs(BaseTest):
       
  1198     def setUp(self):
       
  1199         options = [make_option("-a", "--apple", action="callback", nargs=2,
       
  1200                                callback=self.process_many, type="string"),
       
  1201                    make_option("-b", "--bob", action="callback", nargs=3,
       
  1202                                callback=self.process_many, type="int")]
       
  1203         self.parser = OptionParser(option_list=options)
       
  1204 
       
  1205     def process_many(self, option, opt, value, parser_):
       
  1206         if opt == "-a":
       
  1207             self.assertEqual(value, ("foo", "bar"))
       
  1208         elif opt == "--apple":
       
  1209             self.assertEqual(value, ("ding", "dong"))
       
  1210         elif opt == "-b":
       
  1211             self.assertEqual(value, (1, 2, 3))
       
  1212         elif opt == "--bob":
       
  1213             self.assertEqual(value, (-666, 42, 0))
       
  1214 
       
  1215     def test_many_args(self):
       
  1216         self.assertParseOK(["-a", "foo", "bar", "--apple", "ding", "dong",
       
  1217                             "-b", "1", "2", "3", "--bob", "-666", "42",
       
  1218                             "0"],
       
  1219                            {"apple": None, "bob": None},
       
  1220                            [])
       
  1221 
       
  1222 class TestCallbackCheckAbbrev(BaseTest):
       
  1223     def setUp(self):
       
  1224         self.parser = OptionParser()
       
  1225         self.parser.add_option("--foo-bar", action="callback",
       
  1226                                callback=self.check_abbrev)
       
  1227 
       
  1228     def check_abbrev(self, option, opt, value, parser):
       
  1229         self.assertEqual(opt, "--foo-bar")
       
  1230 
       
  1231     def test_abbrev_callback_expansion(self):
       
  1232         self.assertParseOK(["--foo"], {}, [])
       
  1233 
       
  1234 class TestCallbackVarArgs(BaseTest):
       
  1235     def setUp(self):
       
  1236         options = [make_option("-a", type="int", nargs=2, dest="a"),
       
  1237                    make_option("-b", action="store_true", dest="b"),
       
  1238                    make_option("-c", "--callback", action="callback",
       
  1239                                callback=self.variable_args, dest="c")]
       
  1240         self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
       
  1241                                                option_list=options)
       
  1242 
       
  1243     def variable_args(self, option, opt, value, parser):
       
  1244         self.assert_(value is None)
       
  1245         done = 0
       
  1246         value = []
       
  1247         rargs = parser.rargs
       
  1248         while rargs:
       
  1249             arg = rargs[0]
       
  1250             if ((arg[:2] == "--" and len(arg) > 2) or
       
  1251                 (arg[:1] == "-" and len(arg) > 1 and arg[1] != "-")):
       
  1252                 break
       
  1253             else:
       
  1254                 value.append(arg)
       
  1255                 del rargs[0]
       
  1256         setattr(parser.values, option.dest, value)
       
  1257 
       
  1258     def test_variable_args(self):
       
  1259         self.assertParseOK(["-a3", "-5", "--callback", "foo", "bar"],
       
  1260                            {'a': (3, -5), 'b': None, 'c': ["foo", "bar"]},
       
  1261                            [])
       
  1262 
       
  1263     def test_consume_separator_stop_at_option(self):
       
  1264         self.assertParseOK(["-c", "37", "--", "xxx", "-b", "hello"],
       
  1265                            {'a': None,
       
  1266                             'b': True,
       
  1267                             'c': ["37", "--", "xxx"]},
       
  1268                            ["hello"])
       
  1269 
       
  1270     def test_positional_arg_and_variable_args(self):
       
  1271         self.assertParseOK(["hello", "-c", "foo", "-", "bar"],
       
  1272                            {'a': None,
       
  1273                             'b': None,
       
  1274                             'c':["foo", "-", "bar"]},
       
  1275                            ["hello"])
       
  1276 
       
  1277     def test_stop_at_option(self):
       
  1278         self.assertParseOK(["-c", "foo", "-b"],
       
  1279                            {'a': None, 'b': True, 'c': ["foo"]},
       
  1280                            [])
       
  1281 
       
  1282     def test_stop_at_invalid_option(self):
       
  1283         self.assertParseFail(["-c", "3", "-5", "-a"], "no such option: -5")
       
  1284 
       
  1285 
       
  1286 # -- Test conflict handling and parser.parse_args() --------------------
       
  1287 
       
  1288 class ConflictBase(BaseTest):
       
  1289     def setUp(self):
       
  1290         options = [make_option("-v", "--verbose", action="count",
       
  1291                                dest="verbose", help="increment verbosity")]
       
  1292         self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
       
  1293                                                option_list=options)
       
  1294 
       
  1295     def show_version(self, option, opt, value, parser):
       
  1296         parser.values.show_version = 1
       
  1297 
       
  1298 class TestConflict(ConflictBase):
       
  1299     """Use the default conflict resolution for Optik 1.2: error."""
       
  1300     def assert_conflict_error(self, func):
       
  1301         err = self.assertRaises(
       
  1302             func, ("-v", "--version"), {'action' : "callback",
       
  1303                                         'callback' : self.show_version,
       
  1304                                         'help' : "show version"},
       
  1305             OptionConflictError,
       
  1306             "option -v/--version: conflicting option string(s): -v")
       
  1307 
       
  1308         self.assertEqual(err.msg, "conflicting option string(s): -v")
       
  1309         self.assertEqual(err.option_id, "-v/--version")
       
  1310 
       
  1311     def test_conflict_error(self):
       
  1312         self.assert_conflict_error(self.parser.add_option)
       
  1313 
       
  1314     def test_conflict_error_group(self):
       
  1315         group = OptionGroup(self.parser, "Group 1")
       
  1316         self.assert_conflict_error(group.add_option)
       
  1317 
       
  1318     def test_no_such_conflict_handler(self):
       
  1319         self.assertRaises(
       
  1320             self.parser.set_conflict_handler, ('foo',), None,
       
  1321             ValueError, "invalid conflict_resolution value 'foo'")
       
  1322 
       
  1323 
       
  1324 class TestConflictResolve(ConflictBase):
       
  1325     def setUp(self):
       
  1326         ConflictBase.setUp(self)
       
  1327         self.parser.set_conflict_handler("resolve")
       
  1328         self.parser.add_option("-v", "--version", action="callback",
       
  1329                                callback=self.show_version, help="show version")
       
  1330 
       
  1331     def test_conflict_resolve(self):
       
  1332         v_opt = self.parser.get_option("-v")
       
  1333         verbose_opt = self.parser.get_option("--verbose")
       
  1334         version_opt = self.parser.get_option("--version")
       
  1335 
       
  1336         self.assert_(v_opt is version_opt)
       
  1337         self.assert_(v_opt is not verbose_opt)
       
  1338         self.assertEqual(v_opt._long_opts, ["--version"])
       
  1339         self.assertEqual(version_opt._short_opts, ["-v"])
       
  1340         self.assertEqual(version_opt._long_opts, ["--version"])
       
  1341         self.assertEqual(verbose_opt._short_opts, [])
       
  1342         self.assertEqual(verbose_opt._long_opts, ["--verbose"])
       
  1343 
       
  1344     def test_conflict_resolve_help(self):
       
  1345         self.assertOutput(["-h"], """\
       
  1346 Options:
       
  1347   --verbose      increment verbosity
       
  1348   -h, --help     show this help message and exit
       
  1349   -v, --version  show version
       
  1350 """)
       
  1351 
       
  1352     def test_conflict_resolve_short_opt(self):
       
  1353         self.assertParseOK(["-v"],
       
  1354                            {'verbose': None, 'show_version': 1},
       
  1355                            [])
       
  1356 
       
  1357     def test_conflict_resolve_long_opt(self):
       
  1358         self.assertParseOK(["--verbose"],
       
  1359                            {'verbose': 1},
       
  1360                            [])
       
  1361 
       
  1362     def test_conflict_resolve_long_opts(self):
       
  1363         self.assertParseOK(["--verbose", "--version"],
       
  1364                            {'verbose': 1, 'show_version': 1},
       
  1365                            [])
       
  1366 
       
  1367 class TestConflictOverride(BaseTest):
       
  1368     def setUp(self):
       
  1369         self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
       
  1370         self.parser.set_conflict_handler("resolve")
       
  1371         self.parser.add_option("-n", "--dry-run",
       
  1372                                action="store_true", dest="dry_run",
       
  1373                                help="don't do anything")
       
  1374         self.parser.add_option("--dry-run", "-n",
       
  1375                                action="store_const", const=42, dest="dry_run",
       
  1376                                help="dry run mode")
       
  1377 
       
  1378     def test_conflict_override_opts(self):
       
  1379         opt = self.parser.get_option("--dry-run")
       
  1380         self.assertEqual(opt._short_opts, ["-n"])
       
  1381         self.assertEqual(opt._long_opts, ["--dry-run"])
       
  1382 
       
  1383     def test_conflict_override_help(self):
       
  1384         self.assertOutput(["-h"], """\
       
  1385 Options:
       
  1386   -h, --help     show this help message and exit
       
  1387   -n, --dry-run  dry run mode
       
  1388 """)
       
  1389 
       
  1390     def test_conflict_override_args(self):
       
  1391         self.assertParseOK(["-n"],
       
  1392                            {'dry_run': 42},
       
  1393                            [])
       
  1394 
       
  1395 # -- Other testing. ----------------------------------------------------
       
  1396 
       
  1397 _expected_help_basic = """\
       
  1398 Usage: bar.py [options]
       
  1399 
       
  1400 Options:
       
  1401   -a APPLE           throw APPLEs at basket
       
  1402   -b NUM, --boo=NUM  shout "boo!" NUM times (in order to frighten away all the
       
  1403                      evil spirits that cause trouble and mayhem)
       
  1404   --foo=FOO          store FOO in the foo list for later fooing
       
  1405   -h, --help         show this help message and exit
       
  1406 """
       
  1407 
       
  1408 _expected_help_long_opts_first = """\
       
  1409 Usage: bar.py [options]
       
  1410 
       
  1411 Options:
       
  1412   -a APPLE           throw APPLEs at basket
       
  1413   --boo=NUM, -b NUM  shout "boo!" NUM times (in order to frighten away all the
       
  1414                      evil spirits that cause trouble and mayhem)
       
  1415   --foo=FOO          store FOO in the foo list for later fooing
       
  1416   --help, -h         show this help message and exit
       
  1417 """
       
  1418 
       
  1419 _expected_help_title_formatter = """\
       
  1420 Usage
       
  1421 =====
       
  1422   bar.py [options]
       
  1423 
       
  1424 Options
       
  1425 =======
       
  1426 -a APPLE           throw APPLEs at basket
       
  1427 --boo=NUM, -b NUM  shout "boo!" NUM times (in order to frighten away all the
       
  1428                    evil spirits that cause trouble and mayhem)
       
  1429 --foo=FOO          store FOO in the foo list for later fooing
       
  1430 --help, -h         show this help message and exit
       
  1431 """
       
  1432 
       
  1433 _expected_help_short_lines = """\
       
  1434 Usage: bar.py [options]
       
  1435 
       
  1436 Options:
       
  1437   -a APPLE           throw APPLEs at basket
       
  1438   -b NUM, --boo=NUM  shout "boo!" NUM times (in order to
       
  1439                      frighten away all the evil spirits
       
  1440                      that cause trouble and mayhem)
       
  1441   --foo=FOO          store FOO in the foo list for later
       
  1442                      fooing
       
  1443   -h, --help         show this help message and exit
       
  1444 """
       
  1445 
       
  1446 class TestHelp(BaseTest):
       
  1447     def setUp(self):
       
  1448         self.parser = self.make_parser(80)
       
  1449 
       
  1450     def make_parser(self, columns):
       
  1451         options = [
       
  1452             make_option("-a", type="string", dest='a',
       
  1453                         metavar="APPLE", help="throw APPLEs at basket"),
       
  1454             make_option("-b", "--boo", type="int", dest='boo',
       
  1455                         metavar="NUM",
       
  1456                         help=
       
  1457                         "shout \"boo!\" NUM times (in order to frighten away "
       
  1458                         "all the evil spirits that cause trouble and mayhem)"),
       
  1459             make_option("--foo", action="append", type="string", dest='foo',
       
  1460                         help="store FOO in the foo list for later fooing"),
       
  1461             ]
       
  1462 
       
  1463         # We need to set COLUMNS for the OptionParser constructor, but
       
  1464         # we must restore its original value -- otherwise, this test
       
  1465         # screws things up for other tests when it's part of the Python
       
  1466         # test suite.
       
  1467         orig_columns = os.environ.get('COLUMNS')
       
  1468         os.environ['COLUMNS'] = str(columns)
       
  1469         try:
       
  1470             return InterceptingOptionParser(option_list=options)
       
  1471         finally:
       
  1472             if orig_columns is None:
       
  1473                 del os.environ['COLUMNS']
       
  1474             else:
       
  1475                 os.environ['COLUMNS'] = orig_columns
       
  1476 
       
  1477     def assertHelpEquals(self, expected_output):
       
  1478         if type(expected_output) is types.UnicodeType:
       
  1479             encoding = self.parser._get_encoding(sys.stdout)
       
  1480             expected_output = expected_output.encode(encoding, "replace")
       
  1481 
       
  1482         save_argv = sys.argv[:]
       
  1483         try:
       
  1484             # Make optparse believe bar.py is being executed.
       
  1485             sys.argv[0] = os.path.join("foo", "bar.py")
       
  1486             self.assertOutput(["-h"], expected_output)
       
  1487         finally:
       
  1488             sys.argv[:] = save_argv
       
  1489 
       
  1490     def test_help(self):
       
  1491         self.assertHelpEquals(_expected_help_basic)
       
  1492 
       
  1493     def test_help_old_usage(self):
       
  1494         self.parser.set_usage("Usage: %prog [options]")
       
  1495         self.assertHelpEquals(_expected_help_basic)
       
  1496 
       
  1497     def test_help_long_opts_first(self):
       
  1498         self.parser.formatter.short_first = 0
       
  1499         self.assertHelpEquals(_expected_help_long_opts_first)
       
  1500 
       
  1501     def test_help_title_formatter(self):
       
  1502         save = os.environ.get("COLUMNS")
       
  1503         try:
       
  1504             os.environ["COLUMNS"] = "80"
       
  1505             self.parser.formatter = TitledHelpFormatter()
       
  1506             self.assertHelpEquals(_expected_help_title_formatter)
       
  1507         finally:
       
  1508             if save is not None:
       
  1509                 os.environ["COLUMNS"] = save
       
  1510             else:
       
  1511                 del os.environ["COLUMNS"]
       
  1512 
       
  1513     def test_wrap_columns(self):
       
  1514         # Ensure that wrapping respects $COLUMNS environment variable.
       
  1515         # Need to reconstruct the parser, since that's the only time
       
  1516         # we look at $COLUMNS.
       
  1517         self.parser = self.make_parser(60)
       
  1518         self.assertHelpEquals(_expected_help_short_lines)
       
  1519 
       
  1520     def test_help_unicode(self):
       
  1521         self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
       
  1522         self.parser.add_option("-a", action="store_true", help=u"ol\u00E9!")
       
  1523         expect = u"""\
       
  1524 Options:
       
  1525   -h, --help  show this help message and exit
       
  1526   -a          ol\u00E9!
       
  1527 """
       
  1528         self.assertHelpEquals(expect)
       
  1529 
       
  1530     def test_help_unicode_description(self):
       
  1531         self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
       
  1532                                                description=u"ol\u00E9!")
       
  1533         expect = u"""\
       
  1534 ol\u00E9!
       
  1535 
       
  1536 Options:
       
  1537   -h, --help  show this help message and exit
       
  1538 """
       
  1539         self.assertHelpEquals(expect)
       
  1540 
       
  1541     def test_help_description_groups(self):
       
  1542         self.parser.set_description(
       
  1543             "This is the program description for %prog.  %prog has "
       
  1544             "an option group as well as single options.")
       
  1545 
       
  1546         group = OptionGroup(
       
  1547             self.parser, "Dangerous Options",
       
  1548             "Caution: use of these options is at your own risk.  "
       
  1549             "It is believed that some of them bite.")
       
  1550         group.add_option("-g", action="store_true", help="Group option.")
       
  1551         self.parser.add_option_group(group)
       
  1552 
       
  1553         expect = """\
       
  1554 Usage: bar.py [options]
       
  1555 
       
  1556 This is the program description for bar.py.  bar.py has an option group as
       
  1557 well as single options.
       
  1558 
       
  1559 Options:
       
  1560   -a APPLE           throw APPLEs at basket
       
  1561   -b NUM, --boo=NUM  shout "boo!" NUM times (in order to frighten away all the
       
  1562                      evil spirits that cause trouble and mayhem)
       
  1563   --foo=FOO          store FOO in the foo list for later fooing
       
  1564   -h, --help         show this help message and exit
       
  1565 
       
  1566   Dangerous Options:
       
  1567     Caution: use of these options is at your own risk.  It is believed
       
  1568     that some of them bite.
       
  1569 
       
  1570     -g               Group option.
       
  1571 """
       
  1572 
       
  1573         self.assertHelpEquals(expect)
       
  1574 
       
  1575         self.parser.epilog = "Please report bugs to /dev/null."
       
  1576         self.assertHelpEquals(expect + "\nPlease report bugs to /dev/null.\n")
       
  1577 
       
  1578 
       
  1579 class TestMatchAbbrev(BaseTest):
       
  1580     def test_match_abbrev(self):
       
  1581         self.assertEqual(_match_abbrev("--f",
       
  1582                                        {"--foz": None,
       
  1583                                         "--foo": None,
       
  1584                                         "--fie": None,
       
  1585                                         "--f": None}),
       
  1586                          "--f")
       
  1587 
       
  1588     def test_match_abbrev_error(self):
       
  1589         s = "--f"
       
  1590         wordmap = {"--foz": None, "--foo": None, "--fie": None}
       
  1591         self.assertRaises(
       
  1592             _match_abbrev, (s, wordmap), None,
       
  1593             BadOptionError, "ambiguous option: --f (--fie, --foo, --foz?)")
       
  1594 
       
  1595 
       
  1596 class TestParseNumber(BaseTest):
       
  1597     def setUp(self):
       
  1598         self.parser = InterceptingOptionParser()
       
  1599         self.parser.add_option("-n", type=int)
       
  1600         self.parser.add_option("-l", type=long)
       
  1601 
       
  1602     def test_parse_num_fail(self):
       
  1603         self.assertRaises(
       
  1604             _parse_num, ("", int), {},
       
  1605             ValueError,
       
  1606             re.compile(r"invalid literal for int().*: '?'?"))
       
  1607         self.assertRaises(
       
  1608             _parse_num, ("0xOoops", long), {},
       
  1609             ValueError,
       
  1610             re.compile(r"invalid literal for long().*: '?0xOoops'?"))
       
  1611 
       
  1612     def test_parse_num_ok(self):
       
  1613         self.assertEqual(_parse_num("0", int), 0)
       
  1614         self.assertEqual(_parse_num("0x10", int), 16)
       
  1615         self.assertEqual(_parse_num("0XA", long), 10L)
       
  1616         self.assertEqual(_parse_num("010", long), 8L)
       
  1617         self.assertEqual(_parse_num("0b11", int), 3)
       
  1618         self.assertEqual(_parse_num("0b", long), 0L)
       
  1619 
       
  1620     def test_numeric_options(self):
       
  1621         self.assertParseOK(["-n", "42", "-l", "0x20"],
       
  1622                            { "n": 42, "l": 0x20 }, [])
       
  1623         self.assertParseOK(["-n", "0b0101", "-l010"],
       
  1624                            { "n": 5, "l": 8 }, [])
       
  1625         self.assertParseFail(["-n008"],
       
  1626                              "option -n: invalid integer value: '008'")
       
  1627         self.assertParseFail(["-l0b0123"],
       
  1628                              "option -l: invalid long integer value: '0b0123'")
       
  1629         self.assertParseFail(["-l", "0x12x"],
       
  1630                              "option -l: invalid long integer value: '0x12x'")
       
  1631 
       
  1632 
       
  1633 def test_main():
       
  1634     test_support.run_unittest(__name__)
       
  1635 
       
  1636 if __name__ == '__main__':
       
  1637     test_main()