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