python (3.11.7)

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