blob: 91a0319a7352b04f5ddc56ad17473be0081e7dfa [file] [log] [blame]
Greg Ward55493222003-04-21 02:41:25 +00001#
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
9import sys
10import os
Thomas Wouters477c8d52006-05-27 19:21:47 +000011import re
Greg Ward55493222003-04-21 02:41:25 +000012import copy
13import unittest
14
Guido van Rossum34d19282007-08-09 01:03:29 +000015from io import StringIO
Benjamin Petersonee8712c2008-05-20 21:35:26 +000016from test import support
Greg Ward55493222003-04-21 02:41:25 +000017
Thomas Wouters477c8d52006-05-27 19:21:47 +000018
Martin Panter19e69c52015-11-14 12:46:42 +000019import optparse
Georg Brandl1b37e872010-03-14 10:45:50 +000020from optparse import make_option, Option, \
21 TitledHelpFormatter, OptionParser, OptionGroup, \
22 SUPPRESS_USAGE, OptionError, OptionConflictError, \
Thomas Wouters477c8d52006-05-27 19:21:47 +000023 BadOptionError, OptionValueError, Values
24from optparse import _match_abbrev
25from optparse import _parse_num
Greg Ward48aa84b2004-10-27 02:20:04 +000026
Thomas Wouters477c8d52006-05-27 19:21:47 +000027retype = type(re.compile(''))
Greg Ward48aa84b2004-10-27 02:20:04 +000028
29class InterceptedError(Exception):
30 def __init__(self,
31 error_message=None,
32 exit_status=None,
33 exit_message=None):
34 self.error_message = error_message
35 self.exit_status = exit_status
36 self.exit_message = exit_message
37
38 def __str__(self):
39 return self.error_message or self.exit_message or "intercepted error"
40
41class InterceptingOptionParser(OptionParser):
42 def exit(self, status=0, msg=None):
43 raise InterceptedError(exit_status=status, exit_message=msg)
44
45 def error(self, msg):
46 raise InterceptedError(error_message=msg)
47
Greg Ward55493222003-04-21 02:41:25 +000048
49class BaseTest(unittest.TestCase):
50 def assertParseOK(self, args, expected_opts, expected_positional_args):
51 """Assert the options are what we expected when parsing arguments.
52
53 Otherwise, fail with a nicely formatted message.
54
55 Keyword arguments:
56 args -- A list of arguments to parse with OptionParser.
57 expected_opts -- The options expected.
58 expected_positional_args -- The positional arguments expected.
59
60 Returns the options and positional args for further testing.
61 """
62
63 (options, positional_args) = self.parser.parse_args(args)
64 optdict = vars(options)
65
66 self.assertEqual(optdict, expected_opts,
67 """
68Options are %(optdict)s.
69Should be %(expected_opts)s.
70Args were %(args)s.""" % locals())
71
72 self.assertEqual(positional_args, expected_positional_args,
73 """
74Positional arguments are %(positional_args)s.
75Should be %(expected_positional_args)s.
76Args were %(args)s.""" % locals ())
77
78 return (options, positional_args)
79
Greg Wardeba20e62004-07-31 16:15:44 +000080 def assertRaises(self,
81 func,
82 args,
83 kwargs,
84 expected_exception,
Greg Ward48aa84b2004-10-27 02:20:04 +000085 expected_message):
86 """
87 Assert that the expected exception is raised when calling a
88 function, and that the right error message is included with
89 that exception.
Greg Ward55493222003-04-21 02:41:25 +000090
Greg Wardeba20e62004-07-31 16:15:44 +000091 Arguments:
92 func -- the function to call
93 args -- positional arguments to `func`
94 kwargs -- keyword arguments to `func`
95 expected_exception -- exception that should be raised
Thomas Wouters477c8d52006-05-27 19:21:47 +000096 expected_message -- expected exception message (or pattern
97 if a compiled regex object)
Greg Ward55493222003-04-21 02:41:25 +000098
99 Returns the exception raised for further testing.
100 """
Greg Wardeba20e62004-07-31 16:15:44 +0000101 if args is None:
102 args = ()
103 if kwargs is None:
104 kwargs = {}
Greg Ward55493222003-04-21 02:41:25 +0000105
106 try:
Greg Ward48aa84b2004-10-27 02:20:04 +0000107 func(*args, **kwargs)
Guido van Rossumb940e112007-01-10 16:19:56 +0000108 except expected_exception as err:
Greg Ward48aa84b2004-10-27 02:20:04 +0000109 actual_message = str(err)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000110 if isinstance(expected_message, retype):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000111 self.assertTrue(expected_message.search(actual_message),
Greg Ward48aa84b2004-10-27 02:20:04 +0000112 """\
Thomas Wouters477c8d52006-05-27 19:21:47 +0000113expected exception message pattern:
114/%s/
Greg Ward48aa84b2004-10-27 02:20:04 +0000115actual exception message:
Thomas Wouters477c8d52006-05-27 19:21:47 +0000116'''%s'''
117""" % (expected_message.pattern, actual_message))
118 else:
119 self.assertEqual(actual_message,
120 expected_message,
121 """\
122expected exception message:
123'''%s'''
124actual exception message:
125'''%s'''
126""" % (expected_message, actual_message))
Greg Ward55493222003-04-21 02:41:25 +0000127
128 return err
129 else:
Greg Wardeba20e62004-07-31 16:15:44 +0000130 self.fail("""expected exception %(expected_exception)s not raised
131called %(func)r
132with args %(args)r
133and kwargs %(kwargs)r
134""" % locals ())
Greg Ward55493222003-04-21 02:41:25 +0000135
Greg Wardeba20e62004-07-31 16:15:44 +0000136
Greg Ward55493222003-04-21 02:41:25 +0000137 # -- Assertions used in more than one class --------------------
138
139 def assertParseFail(self, cmdline_args, expected_output):
Greg Ward48aa84b2004-10-27 02:20:04 +0000140 """
141 Assert the parser fails with the expected message. Caller
142 must ensure that self.parser is an InterceptingOptionParser.
143 """
Tim Peters579f7352004-07-31 21:14:28 +0000144 try:
Greg Ward48aa84b2004-10-27 02:20:04 +0000145 self.parser.parse_args(cmdline_args)
Guido van Rossumb940e112007-01-10 16:19:56 +0000146 except InterceptedError as err:
Greg Ward48aa84b2004-10-27 02:20:04 +0000147 self.assertEqual(err.error_message, expected_output)
148 else:
149 self.assertFalse("expected parse failure")
Greg Ward55493222003-04-21 02:41:25 +0000150
Greg Ward48aa84b2004-10-27 02:20:04 +0000151 def assertOutput(self,
152 cmdline_args,
153 expected_output,
154 expected_status=0,
155 expected_error=None):
Greg Ward55493222003-04-21 02:41:25 +0000156 """Assert the parser prints the expected output on stdout."""
Tim Peters579f7352004-07-31 21:14:28 +0000157 save_stdout = sys.stdout
158 try:
Greg Ward48aa84b2004-10-27 02:20:04 +0000159 try:
160 sys.stdout = StringIO()
161 self.parser.parse_args(cmdline_args)
162 finally:
163 output = sys.stdout.getvalue()
164 sys.stdout = save_stdout
Greg Ward55493222003-04-21 02:41:25 +0000165
Guido van Rossumb940e112007-01-10 16:19:56 +0000166 except InterceptedError as err:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000167 self.assertTrue(
Guido van Rossum13257902007-06-07 23:15:56 +0000168 isinstance(output, str),
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000169 "expected output to be an ordinary string, not %r"
170 % type(output))
171
Thomas Wouters477c8d52006-05-27 19:21:47 +0000172 if output != expected_output:
173 self.fail("expected: \n'''\n" + expected_output +
174 "'''\nbut got \n'''\n" + output + "'''")
Greg Ward48aa84b2004-10-27 02:20:04 +0000175 self.assertEqual(err.exit_status, expected_status)
176 self.assertEqual(err.exit_message, expected_error)
177 else:
178 self.assertFalse("expected parser.exit()")
179
180 def assertTypeError(self, func, expected_message, *args):
181 """Assert that TypeError is raised when executing func."""
182 self.assertRaises(func, args, None, TypeError, expected_message)
Greg Wardeba20e62004-07-31 16:15:44 +0000183
184 def assertHelp(self, parser, expected_help):
185 actual_help = parser.format_help()
186 if actual_help != expected_help:
187 raise self.failureException(
188 'help text failure; expected:\n"' +
189 expected_help + '"; got:\n"' +
190 actual_help + '"\n')
Greg Ward55493222003-04-21 02:41:25 +0000191
192# -- Test make_option() aka Option -------------------------------------
193
Greg Ward48aa84b2004-10-27 02:20:04 +0000194# It's not necessary to test correct options here. All the tests in the
Greg Ward55493222003-04-21 02:41:25 +0000195# parser.parse_args() section deal with those, because they're needed
Greg Ward48aa84b2004-10-27 02:20:04 +0000196# there.
Greg Ward55493222003-04-21 02:41:25 +0000197
198class TestOptionChecks(BaseTest):
199 def setUp(self):
200 self.parser = OptionParser(usage=SUPPRESS_USAGE)
201
Greg Ward48aa84b2004-10-27 02:20:04 +0000202 def assertOptionError(self, expected_message, args=[], kwargs={}):
Greg Wardeba20e62004-07-31 16:15:44 +0000203 self.assertRaises(make_option, args, kwargs,
Greg Ward48aa84b2004-10-27 02:20:04 +0000204 OptionError, expected_message)
Greg Ward55493222003-04-21 02:41:25 +0000205
206 def test_opt_string_empty(self):
207 self.assertTypeError(make_option,
208 "at least one option string must be supplied")
209
210 def test_opt_string_too_short(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000211 self.assertOptionError(
212 "invalid option string 'b': must be at least two characters long",
213 ["b"])
Greg Ward55493222003-04-21 02:41:25 +0000214
215 def test_opt_string_short_invalid(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000216 self.assertOptionError(
217 "invalid short option string '--': must be "
218 "of the form -x, (x any non-dash char)",
219 ["--"])
Greg Ward55493222003-04-21 02:41:25 +0000220
221 def test_opt_string_long_invalid(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000222 self.assertOptionError(
223 "invalid long option string '---': "
224 "must start with --, followed by non-dash",
225 ["---"])
Greg Ward55493222003-04-21 02:41:25 +0000226
227 def test_attr_invalid(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000228 self.assertOptionError(
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000229 "option -b: invalid keyword arguments: bar, foo",
Greg Ward48aa84b2004-10-27 02:20:04 +0000230 ["-b"], {'foo': None, 'bar': None})
Greg Ward55493222003-04-21 02:41:25 +0000231
232 def test_action_invalid(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000233 self.assertOptionError(
234 "option -b: invalid action: 'foo'",
235 ["-b"], {'action': 'foo'})
Greg Ward55493222003-04-21 02:41:25 +0000236
237 def test_type_invalid(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000238 self.assertOptionError(
239 "option -b: invalid option type: 'foo'",
240 ["-b"], {'type': 'foo'})
241 self.assertOptionError(
242 "option -b: invalid option type: 'tuple'",
243 ["-b"], {'type': tuple})
Greg Ward55493222003-04-21 02:41:25 +0000244
245 def test_no_type_for_action(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000246 self.assertOptionError(
247 "option -b: must not supply a type for action 'count'",
248 ["-b"], {'action': 'count', 'type': 'int'})
Greg Ward55493222003-04-21 02:41:25 +0000249
250 def test_no_choices_list(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000251 self.assertOptionError(
252 "option -b/--bad: must supply a list of "
253 "choices for type 'choice'",
254 ["-b", "--bad"], {'type': "choice"})
Greg Ward55493222003-04-21 02:41:25 +0000255
256 def test_bad_choices_list(self):
257 typename = type('').__name__
Greg Ward48aa84b2004-10-27 02:20:04 +0000258 self.assertOptionError(
259 "option -b/--bad: choices must be a list of "
260 "strings ('%s' supplied)" % typename,
261 ["-b", "--bad"],
262 {'type': "choice", 'choices':"bad choices"})
Greg Ward55493222003-04-21 02:41:25 +0000263
264 def test_no_choices_for_type(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000265 self.assertOptionError(
266 "option -b: must not supply choices for type 'int'",
267 ["-b"], {'type': 'int', 'choices':"bad"})
Greg Ward55493222003-04-21 02:41:25 +0000268
269 def test_no_const_for_action(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000270 self.assertOptionError(
271 "option -b: 'const' must not be supplied for action 'store'",
272 ["-b"], {'action': 'store', 'const': 1})
Greg Ward55493222003-04-21 02:41:25 +0000273
274 def test_no_nargs_for_action(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000275 self.assertOptionError(
276 "option -b: 'nargs' must not be supplied for action 'count'",
277 ["-b"], {'action': 'count', 'nargs': 2})
Greg Ward55493222003-04-21 02:41:25 +0000278
279 def test_callback_not_callable(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000280 self.assertOptionError(
281 "option -b: callback not callable: 'foo'",
282 ["-b"], {'action': 'callback',
283 'callback': 'foo'})
Greg Ward55493222003-04-21 02:41:25 +0000284
285 def dummy(self):
286 pass
287
288 def test_callback_args_no_tuple(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000289 self.assertOptionError(
290 "option -b: callback_args, if supplied, "
291 "must be a tuple: not 'foo'",
292 ["-b"], {'action': 'callback',
293 'callback': self.dummy,
294 'callback_args': 'foo'})
Greg Ward55493222003-04-21 02:41:25 +0000295
296 def test_callback_kwargs_no_dict(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000297 self.assertOptionError(
298 "option -b: callback_kwargs, if supplied, "
299 "must be a dict: not 'foo'",
300 ["-b"], {'action': 'callback',
301 'callback': self.dummy,
302 'callback_kwargs': 'foo'})
Greg Ward55493222003-04-21 02:41:25 +0000303
304 def test_no_callback_for_action(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000305 self.assertOptionError(
306 "option -b: callback supplied ('foo') for non-callback option",
307 ["-b"], {'action': 'store',
308 'callback': 'foo'})
Greg Ward55493222003-04-21 02:41:25 +0000309
310 def test_no_callback_args_for_action(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000311 self.assertOptionError(
312 "option -b: callback_args supplied for non-callback option",
313 ["-b"], {'action': 'store',
314 'callback_args': 'foo'})
Greg Ward55493222003-04-21 02:41:25 +0000315
316 def test_no_callback_kwargs_for_action(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000317 self.assertOptionError(
318 "option -b: callback_kwargs supplied for non-callback option",
319 ["-b"], {'action': 'store',
320 'callback_kwargs': 'foo'})
Greg Ward55493222003-04-21 02:41:25 +0000321
R David Murray6159e092012-07-15 20:12:24 -0400322 def test_no_single_dash(self):
323 self.assertOptionError(
324 "invalid long option string '-debug': "
325 "must start with --, followed by non-dash",
326 ["-debug"])
327
328 self.assertOptionError(
329 "option -d: invalid long option string '-debug': must start with"
330 " --, followed by non-dash",
331 ["-d", "-debug"])
332
333 self.assertOptionError(
334 "invalid long option string '-debug': "
335 "must start with --, followed by non-dash",
336 ["-debug", "--debug"])
337
Greg Ward55493222003-04-21 02:41:25 +0000338class TestOptionParser(BaseTest):
339 def setUp(self):
340 self.parser = OptionParser()
341 self.parser.add_option("-v", "--verbose", "-n", "--noisy",
342 action="store_true", dest="verbose")
343 self.parser.add_option("-q", "--quiet", "--silent",
344 action="store_false", dest="verbose")
345
346 def test_add_option_no_Option(self):
347 self.assertTypeError(self.parser.add_option,
348 "not an Option instance: None", None)
349
350 def test_add_option_invalid_arguments(self):
351 self.assertTypeError(self.parser.add_option,
352 "invalid arguments", None, None)
353
354 def test_get_option(self):
355 opt1 = self.parser.get_option("-v")
Ezio Melottie9615932010-01-24 19:26:24 +0000356 self.assertIsInstance(opt1, Option)
Greg Ward55493222003-04-21 02:41:25 +0000357 self.assertEqual(opt1._short_opts, ["-v", "-n"])
358 self.assertEqual(opt1._long_opts, ["--verbose", "--noisy"])
359 self.assertEqual(opt1.action, "store_true")
360 self.assertEqual(opt1.dest, "verbose")
361
362 def test_get_option_equals(self):
363 opt1 = self.parser.get_option("-v")
364 opt2 = self.parser.get_option("--verbose")
365 opt3 = self.parser.get_option("-n")
366 opt4 = self.parser.get_option("--noisy")
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000367 self.assertTrue(opt1 is opt2 is opt3 is opt4)
Greg Ward55493222003-04-21 02:41:25 +0000368
369 def test_has_option(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000370 self.assertTrue(self.parser.has_option("-v"))
371 self.assertTrue(self.parser.has_option("--verbose"))
Greg Ward55493222003-04-21 02:41:25 +0000372
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000373 def assertTrueremoved(self):
374 self.assertTrue(self.parser.get_option("-v") is None)
375 self.assertTrue(self.parser.get_option("--verbose") is None)
376 self.assertTrue(self.parser.get_option("-n") is None)
377 self.assertTrue(self.parser.get_option("--noisy") is None)
Greg Ward55493222003-04-21 02:41:25 +0000378
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000379 self.assertFalse(self.parser.has_option("-v"))
380 self.assertFalse(self.parser.has_option("--verbose"))
381 self.assertFalse(self.parser.has_option("-n"))
382 self.assertFalse(self.parser.has_option("--noisy"))
Greg Ward55493222003-04-21 02:41:25 +0000383
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000384 self.assertTrue(self.parser.has_option("-q"))
385 self.assertTrue(self.parser.has_option("--silent"))
Greg Ward55493222003-04-21 02:41:25 +0000386
387 def test_remove_short_opt(self):
388 self.parser.remove_option("-n")
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000389 self.assertTrueremoved()
Greg Ward55493222003-04-21 02:41:25 +0000390
391 def test_remove_long_opt(self):
392 self.parser.remove_option("--verbose")
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000393 self.assertTrueremoved()
Greg Ward55493222003-04-21 02:41:25 +0000394
395 def test_remove_nonexistent(self):
Greg Wardeba20e62004-07-31 16:15:44 +0000396 self.assertRaises(self.parser.remove_option, ('foo',), None,
397 ValueError, "no such option 'foo'")
398
Andrew Kuchling45278a82014-04-15 16:44:43 -0400399 @support.impl_detail('Relies on sys.getrefcount', cpython=True)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000400 def test_refleak(self):
401 # If an OptionParser is carrying around a reference to a large
402 # object, various cycles can prevent it from being GC'd in
403 # a timely fashion. destroy() breaks the cycles to ensure stuff
404 # can be cleaned up.
405 big_thing = [42]
406 refcount = sys.getrefcount(big_thing)
407 parser = OptionParser()
408 parser.add_option("-a", "--aaarggh")
409 parser.big_thing = big_thing
410
411 parser.destroy()
412 #self.assertEqual(refcount, sys.getrefcount(big_thing))
413 del parser
414 self.assertEqual(refcount, sys.getrefcount(big_thing))
415
416
Greg Ward48aa84b2004-10-27 02:20:04 +0000417class TestOptionValues(BaseTest):
418 def setUp(self):
419 pass
420
421 def test_basics(self):
422 values = Values()
423 self.assertEqual(vars(values), {})
424 self.assertEqual(values, {})
425 self.assertNotEqual(values, {"foo": "bar"})
426 self.assertNotEqual(values, "")
427
428 dict = {"foo": "bar", "baz": 42}
429 values = Values(defaults=dict)
430 self.assertEqual(vars(values), dict)
431 self.assertEqual(values, dict)
432 self.assertNotEqual(values, {"foo": "bar"})
433 self.assertNotEqual(values, {})
434 self.assertNotEqual(values, "")
435 self.assertNotEqual(values, [])
436
437
Greg Wardeba20e62004-07-31 16:15:44 +0000438class TestTypeAliases(BaseTest):
439 def setUp(self):
440 self.parser = OptionParser()
441
Thomas Wouters477c8d52006-05-27 19:21:47 +0000442 def test_str_aliases_string(self):
443 self.parser.add_option("-s", type="str")
Ezio Melottib3aedd42010-11-20 19:04:17 +0000444 self.assertEqual(self.parser.get_option("-s").type, "string")
Thomas Wouters477c8d52006-05-27 19:21:47 +0000445
Guido van Rossum13257902007-06-07 23:15:56 +0000446 def test_type_object(self):
Thomas Wouters477c8d52006-05-27 19:21:47 +0000447 self.parser.add_option("-s", type=str)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000448 self.assertEqual(self.parser.get_option("-s").type, "string")
Thomas Wouters477c8d52006-05-27 19:21:47 +0000449 self.parser.add_option("-x", type=int)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000450 self.assertEqual(self.parser.get_option("-x").type, "int")
Thomas Wouters477c8d52006-05-27 19:21:47 +0000451
Greg Wardeba20e62004-07-31 16:15:44 +0000452
453# Custom type for testing processing of default values.
454_time_units = { 's' : 1, 'm' : 60, 'h' : 60*60, 'd' : 60*60*24 }
455
456def _check_duration(option, opt, value):
457 try:
458 if value[-1].isdigit():
459 return int(value)
460 else:
461 return int(value[:-1]) * _time_units[value[-1]]
Georg Brandl89fad142010-03-14 10:23:39 +0000462 except (ValueError, IndexError):
Greg Wardeba20e62004-07-31 16:15:44 +0000463 raise OptionValueError(
464 'option %s: invalid duration: %r' % (opt, value))
465
466class DurationOption(Option):
467 TYPES = Option.TYPES + ('duration',)
468 TYPE_CHECKER = copy.copy(Option.TYPE_CHECKER)
469 TYPE_CHECKER['duration'] = _check_duration
470
471class TestDefaultValues(BaseTest):
472 def setUp(self):
473 self.parser = OptionParser()
474 self.parser.add_option("-v", "--verbose", default=True)
475 self.parser.add_option("-q", "--quiet", dest='verbose')
476 self.parser.add_option("-n", type="int", default=37)
477 self.parser.add_option("-m", type="int")
478 self.parser.add_option("-s", default="foo")
479 self.parser.add_option("-t")
480 self.parser.add_option("-u", default=None)
481 self.expected = { 'verbose': True,
482 'n': 37,
483 'm': None,
484 's': "foo",
485 't': None,
486 'u': None }
487
488 def test_basic_defaults(self):
489 self.assertEqual(self.parser.get_default_values(), self.expected)
490
491 def test_mixed_defaults_post(self):
492 self.parser.set_defaults(n=42, m=-100)
493 self.expected.update({'n': 42, 'm': -100})
494 self.assertEqual(self.parser.get_default_values(), self.expected)
495
496 def test_mixed_defaults_pre(self):
497 self.parser.set_defaults(x="barf", y="blah")
498 self.parser.add_option("-x", default="frob")
499 self.parser.add_option("-y")
500
501 self.expected.update({'x': "frob", 'y': "blah"})
502 self.assertEqual(self.parser.get_default_values(), self.expected)
503
504 self.parser.remove_option("-y")
505 self.parser.add_option("-y", default=None)
506 self.expected.update({'y': None})
507 self.assertEqual(self.parser.get_default_values(), self.expected)
508
509 def test_process_default(self):
510 self.parser.option_class = DurationOption
511 self.parser.add_option("-d", type="duration", default=300)
512 self.parser.add_option("-e", type="duration", default="6m")
513 self.parser.set_defaults(n="42")
514 self.expected.update({'d': 300, 'e': 360, 'n': 42})
515 self.assertEqual(self.parser.get_default_values(), self.expected)
516
517 self.parser.set_process_default_values(False)
518 self.expected.update({'d': 300, 'e': "6m", 'n': "42"})
519 self.assertEqual(self.parser.get_default_values(), self.expected)
520
521
522class TestProgName(BaseTest):
523 """
524 Test that %prog expands to the right thing in usage, version,
525 and help strings.
526 """
527
528 def assertUsage(self, parser, expected_usage):
529 self.assertEqual(parser.get_usage(), expected_usage)
530
531 def assertVersion(self, parser, expected_version):
532 self.assertEqual(parser.get_version(), expected_version)
533
534
535 def test_default_progname(self):
536 # Make sure that program name taken from sys.argv[0] by default.
Tim Peters579f7352004-07-31 21:14:28 +0000537 save_argv = sys.argv[:]
538 try:
Greg Ward48aa84b2004-10-27 02:20:04 +0000539 sys.argv[0] = os.path.join("foo", "bar", "baz.py")
Thomas Wouters477c8d52006-05-27 19:21:47 +0000540 parser = OptionParser("%prog ...", version="%prog 1.2")
541 expected_usage = "Usage: baz.py ...\n"
Tim Peters579f7352004-07-31 21:14:28 +0000542 self.assertUsage(parser, expected_usage)
543 self.assertVersion(parser, "baz.py 1.2")
544 self.assertHelp(parser,
Greg Ward48aa84b2004-10-27 02:20:04 +0000545 expected_usage + "\n" +
Thomas Wouters477c8d52006-05-27 19:21:47 +0000546 "Options:\n"
Greg Ward48aa84b2004-10-27 02:20:04 +0000547 " --version show program's version number and exit\n"
548 " -h, --help show this help message and exit\n")
Tim Peters579f7352004-07-31 21:14:28 +0000549 finally:
550 sys.argv[:] = save_argv
Greg Wardeba20e62004-07-31 16:15:44 +0000551
552 def test_custom_progname(self):
553 parser = OptionParser(prog="thingy",
554 version="%prog 0.1",
555 usage="%prog arg arg")
556 parser.remove_option("-h")
557 parser.remove_option("--version")
Thomas Wouters477c8d52006-05-27 19:21:47 +0000558 expected_usage = "Usage: thingy arg arg\n"
Greg Wardeba20e62004-07-31 16:15:44 +0000559 self.assertUsage(parser, expected_usage)
560 self.assertVersion(parser, "thingy 0.1")
561 self.assertHelp(parser, expected_usage + "\n")
562
563
564class TestExpandDefaults(BaseTest):
565 def setUp(self):
566 self.parser = OptionParser(prog="test")
567 self.help_prefix = """\
Thomas Wouters477c8d52006-05-27 19:21:47 +0000568Usage: test [options]
Greg Wardeba20e62004-07-31 16:15:44 +0000569
Thomas Wouters477c8d52006-05-27 19:21:47 +0000570Options:
Greg Wardeba20e62004-07-31 16:15:44 +0000571 -h, --help show this help message and exit
572"""
573 self.file_help = "read from FILE [default: %default]"
574 self.expected_help_file = self.help_prefix + \
575 " -f FILE, --file=FILE read from FILE [default: foo.txt]\n"
576 self.expected_help_none = self.help_prefix + \
577 " -f FILE, --file=FILE read from FILE [default: none]\n"
578
579 def test_option_default(self):
580 self.parser.add_option("-f", "--file",
581 default="foo.txt",
582 help=self.file_help)
583 self.assertHelp(self.parser, self.expected_help_file)
584
585 def test_parser_default_1(self):
586 self.parser.add_option("-f", "--file",
587 help=self.file_help)
588 self.parser.set_default('file', "foo.txt")
589 self.assertHelp(self.parser, self.expected_help_file)
590
591 def test_parser_default_2(self):
592 self.parser.add_option("-f", "--file",
593 help=self.file_help)
594 self.parser.set_defaults(file="foo.txt")
595 self.assertHelp(self.parser, self.expected_help_file)
596
597 def test_no_default(self):
598 self.parser.add_option("-f", "--file",
599 help=self.file_help)
600 self.assertHelp(self.parser, self.expected_help_none)
601
602 def test_default_none_1(self):
603 self.parser.add_option("-f", "--file",
604 default=None,
605 help=self.file_help)
606 self.assertHelp(self.parser, self.expected_help_none)
Tim Peters10d59f32004-10-27 02:43:25 +0000607
Greg Wardeba20e62004-07-31 16:15:44 +0000608 def test_default_none_2(self):
609 self.parser.add_option("-f", "--file",
610 help=self.file_help)
611 self.parser.set_defaults(file=None)
612 self.assertHelp(self.parser, self.expected_help_none)
613
614 def test_float_default(self):
615 self.parser.add_option(
616 "-p", "--prob",
617 help="blow up with probability PROB [default: %default]")
618 self.parser.set_defaults(prob=0.43)
619 expected_help = self.help_prefix + \
620 " -p PROB, --prob=PROB blow up with probability PROB [default: 0.43]\n"
621 self.assertHelp(self.parser, expected_help)
622
623 def test_alt_expand(self):
624 self.parser.add_option("-f", "--file",
625 default="foo.txt",
626 help="read from FILE [default: *DEFAULT*]")
627 self.parser.formatter.default_tag = "*DEFAULT*"
628 self.assertHelp(self.parser, self.expected_help_file)
629
630 def test_no_expand(self):
631 self.parser.add_option("-f", "--file",
632 default="foo.txt",
633 help="read from %default file")
634 self.parser.formatter.default_tag = None
635 expected_help = self.help_prefix + \
636 " -f FILE, --file=FILE read from %default file\n"
637 self.assertHelp(self.parser, expected_help)
638
Greg Ward55493222003-04-21 02:41:25 +0000639
640# -- Test parser.parse_args() ------------------------------------------
641
642class TestStandard(BaseTest):
643 def setUp(self):
644 options = [make_option("-a", type="string"),
645 make_option("-b", "--boo", type="int", dest='boo'),
646 make_option("--foo", action="append")]
647
Greg Ward48aa84b2004-10-27 02:20:04 +0000648 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
649 option_list=options)
Greg Ward55493222003-04-21 02:41:25 +0000650
651 def test_required_value(self):
Éric Araujo6a1454f2011-03-20 19:59:25 +0100652 self.assertParseFail(["-a"], "-a option requires 1 argument")
Greg Ward55493222003-04-21 02:41:25 +0000653
654 def test_invalid_integer(self):
655 self.assertParseFail(["-b", "5x"],
656 "option -b: invalid integer value: '5x'")
657
658 def test_no_such_option(self):
659 self.assertParseFail(["--boo13"], "no such option: --boo13")
660
661 def test_long_invalid_integer(self):
662 self.assertParseFail(["--boo=x5"],
663 "option --boo: invalid integer value: 'x5'")
664
665 def test_empty(self):
666 self.assertParseOK([], {'a': None, 'boo': None, 'foo': None}, [])
667
668 def test_shortopt_empty_longopt_append(self):
669 self.assertParseOK(["-a", "", "--foo=blah", "--foo="],
670 {'a': "", 'boo': None, 'foo': ["blah", ""]},
671 [])
672
673 def test_long_option_append(self):
674 self.assertParseOK(["--foo", "bar", "--foo", "", "--foo=x"],
675 {'a': None,
676 'boo': None,
677 'foo': ["bar", "", "x"]},
678 [])
679
680 def test_option_argument_joined(self):
681 self.assertParseOK(["-abc"],
682 {'a': "bc", 'boo': None, 'foo': None},
683 [])
684
685 def test_option_argument_split(self):
686 self.assertParseOK(["-a", "34"],
687 {'a': "34", 'boo': None, 'foo': None},
688 [])
689
690 def test_option_argument_joined_integer(self):
691 self.assertParseOK(["-b34"],
692 {'a': None, 'boo': 34, 'foo': None},
693 [])
694
695 def test_option_argument_split_negative_integer(self):
696 self.assertParseOK(["-b", "-5"],
697 {'a': None, 'boo': -5, 'foo': None},
698 [])
699
700 def test_long_option_argument_joined(self):
701 self.assertParseOK(["--boo=13"],
702 {'a': None, 'boo': 13, 'foo': None},
703 [])
704
705 def test_long_option_argument_split(self):
706 self.assertParseOK(["--boo", "111"],
707 {'a': None, 'boo': 111, 'foo': None},
708 [])
709
710 def test_long_option_short_option(self):
711 self.assertParseOK(["--foo=bar", "-axyz"],
712 {'a': 'xyz', 'boo': None, 'foo': ["bar"]},
713 [])
714
715 def test_abbrev_long_option(self):
716 self.assertParseOK(["--f=bar", "-axyz"],
717 {'a': 'xyz', 'boo': None, 'foo': ["bar"]},
718 [])
719
720 def test_defaults(self):
721 (options, args) = self.parser.parse_args([])
722 defaults = self.parser.get_default_values()
723 self.assertEqual(vars(defaults), vars(options))
724
725 def test_ambiguous_option(self):
726 self.parser.add_option("--foz", action="store",
727 type="string", dest="foo")
Greg Ward55493222003-04-21 02:41:25 +0000728 self.assertParseFail(["--f=bar"],
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000729 "ambiguous option: --f (--foo, --foz?)")
Greg Ward55493222003-04-21 02:41:25 +0000730
731
732 def test_short_and_long_option_split(self):
733 self.assertParseOK(["-a", "xyz", "--foo", "bar"],
734 {'a': 'xyz', 'boo': None, 'foo': ["bar"]},
Victor Stinner3fa1aae2013-03-26 01:14:08 +0100735 [])
Greg Ward55493222003-04-21 02:41:25 +0000736
737 def test_short_option_split_long_option_append(self):
738 self.assertParseOK(["--foo=bar", "-b", "123", "--foo", "baz"],
739 {'a': None, 'boo': 123, 'foo': ["bar", "baz"]},
740 [])
741
742 def test_short_option_split_one_positional_arg(self):
743 self.assertParseOK(["-a", "foo", "bar"],
744 {'a': "foo", 'boo': None, 'foo': None},
Victor Stinner3fa1aae2013-03-26 01:14:08 +0100745 ["bar"])
Greg Ward55493222003-04-21 02:41:25 +0000746
747 def test_short_option_consumes_separator(self):
748 self.assertParseOK(["-a", "--", "foo", "bar"],
749 {'a': "--", 'boo': None, 'foo': None},
Victor Stinner3fa1aae2013-03-26 01:14:08 +0100750 ["foo", "bar"])
Thomas Wouters477c8d52006-05-27 19:21:47 +0000751 self.assertParseOK(["-a", "--", "--foo", "bar"],
752 {'a': "--", 'boo': None, 'foo': ["bar"]},
Victor Stinner3fa1aae2013-03-26 01:14:08 +0100753 [])
Greg Ward55493222003-04-21 02:41:25 +0000754
755 def test_short_option_joined_and_separator(self):
756 self.assertParseOK(["-ab", "--", "--foo", "bar"],
757 {'a': "b", 'boo': None, 'foo': None},
758 ["--foo", "bar"]),
759
Thomas Wouters477c8d52006-05-27 19:21:47 +0000760 def test_hyphen_becomes_positional_arg(self):
Greg Ward55493222003-04-21 02:41:25 +0000761 self.assertParseOK(["-ab", "-", "--foo", "bar"],
762 {'a': "b", 'boo': None, 'foo': ["bar"]},
763 ["-"])
764
765 def test_no_append_versus_append(self):
766 self.assertParseOK(["-b3", "-b", "5", "--foo=bar", "--foo", "baz"],
767 {'a': None, 'boo': 5, 'foo': ["bar", "baz"]},
768 [])
769
770 def test_option_consumes_optionlike_string(self):
771 self.assertParseOK(["-a", "-b3"],
772 {'a': "-b3", 'boo': None, 'foo': None},
773 [])
774
R. David Murray80972692010-06-26 00:17:12 +0000775 def test_combined_single_invalid_option(self):
776 self.parser.add_option("-t", action="store_true")
777 self.assertParseFail(["-test"],
R. David Murray76af4022010-06-26 03:34:33 +0000778 "no such option: -e")
R. David Murray80972692010-06-26 00:17:12 +0000779
Greg Ward55493222003-04-21 02:41:25 +0000780class TestBool(BaseTest):
781 def setUp(self):
782 options = [make_option("-v",
783 "--verbose",
784 action="store_true",
785 dest="verbose",
786 default=''),
787 make_option("-q",
788 "--quiet",
789 action="store_false",
790 dest="verbose")]
791 self.parser = OptionParser(option_list = options)
792
793 def test_bool_default(self):
794 self.assertParseOK([],
795 {'verbose': ''},
796 [])
797
798 def test_bool_false(self):
799 (options, args) = self.assertParseOK(["-q"],
800 {'verbose': 0},
801 [])
Georg Brandla8867b42010-07-31 21:26:40 +0000802 self.assertTrue(options.verbose is False)
Greg Ward55493222003-04-21 02:41:25 +0000803
804 def test_bool_true(self):
805 (options, args) = self.assertParseOK(["-v"],
806 {'verbose': 1},
807 [])
Georg Brandla8867b42010-07-31 21:26:40 +0000808 self.assertTrue(options.verbose is True)
Greg Ward55493222003-04-21 02:41:25 +0000809
810 def test_bool_flicker_on_and_off(self):
811 self.assertParseOK(["-qvq", "-q", "-v"],
812 {'verbose': 1},
813 [])
814
815class TestChoice(BaseTest):
816 def setUp(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000817 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
Greg Ward55493222003-04-21 02:41:25 +0000818 self.parser.add_option("-c", action="store", type="choice",
819 dest="choice", choices=["one", "two", "three"])
820
821 def test_valid_choice(self):
822 self.assertParseOK(["-c", "one", "xyz"],
823 {'choice': 'one'},
824 ["xyz"])
825
826 def test_invalid_choice(self):
827 self.assertParseFail(["-c", "four", "abc"],
828 "option -c: invalid choice: 'four' "
829 "(choose from 'one', 'two', 'three')")
830
831 def test_add_choice_option(self):
832 self.parser.add_option("-d", "--default",
833 choices=["four", "five", "six"])
834 opt = self.parser.get_option("-d")
835 self.assertEqual(opt.type, "choice")
836 self.assertEqual(opt.action, "store")
837
838class TestCount(BaseTest):
839 def setUp(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000840 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
Greg Ward55493222003-04-21 02:41:25 +0000841 self.v_opt = make_option("-v", action="count", dest="verbose")
842 self.parser.add_option(self.v_opt)
843 self.parser.add_option("--verbose", type="int", dest="verbose")
844 self.parser.add_option("-q", "--quiet",
845 action="store_const", dest="verbose", const=0)
846
847 def test_empty(self):
848 self.assertParseOK([], {'verbose': None}, [])
849
850 def test_count_one(self):
851 self.assertParseOK(["-v"], {'verbose': 1}, [])
852
853 def test_count_three(self):
854 self.assertParseOK(["-vvv"], {'verbose': 3}, [])
855
856 def test_count_three_apart(self):
857 self.assertParseOK(["-v", "-v", "-v"], {'verbose': 3}, [])
858
859 def test_count_override_amount(self):
860 self.assertParseOK(["-vvv", "--verbose=2"], {'verbose': 2}, [])
861
862 def test_count_override_quiet(self):
863 self.assertParseOK(["-vvv", "--verbose=2", "-q"], {'verbose': 0}, [])
864
865 def test_count_overriding(self):
866 self.assertParseOK(["-vvv", "--verbose=2", "-q", "-v"],
867 {'verbose': 1}, [])
868
869 def test_count_interspersed_args(self):
870 self.assertParseOK(["--quiet", "3", "-v"],
871 {'verbose': 1},
872 ["3"])
873
874 def test_count_no_interspersed_args(self):
875 self.parser.disable_interspersed_args()
876 self.assertParseOK(["--quiet", "3", "-v"],
877 {'verbose': 0},
878 ["3", "-v"])
879
880 def test_count_no_such_option(self):
881 self.assertParseFail(["-q3", "-v"], "no such option: -3")
882
883 def test_count_option_no_value(self):
884 self.assertParseFail(["--quiet=3", "-v"],
885 "--quiet option does not take a value")
886
887 def test_count_with_default(self):
888 self.parser.set_default('verbose', 0)
889 self.assertParseOK([], {'verbose':0}, [])
890
891 def test_count_overriding_default(self):
892 self.parser.set_default('verbose', 0)
893 self.assertParseOK(["-vvv", "--verbose=2", "-q", "-v"],
894 {'verbose': 1}, [])
895
Greg Ward48aa84b2004-10-27 02:20:04 +0000896class TestMultipleArgs(BaseTest):
Greg Ward55493222003-04-21 02:41:25 +0000897 def setUp(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000898 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
Greg Ward55493222003-04-21 02:41:25 +0000899 self.parser.add_option("-p", "--point",
900 action="store", nargs=3, type="float", dest="point")
901
902 def test_nargs_with_positional_args(self):
903 self.assertParseOK(["foo", "-p", "1", "2.5", "-4.3", "xyz"],
904 {'point': (1.0, 2.5, -4.3)},
905 ["foo", "xyz"])
906
907 def test_nargs_long_opt(self):
908 self.assertParseOK(["--point", "-1", "2.5", "-0", "xyz"],
909 {'point': (-1.0, 2.5, -0.0)},
910 ["xyz"])
911
912 def test_nargs_invalid_float_value(self):
913 self.assertParseFail(["-p", "1.0", "2x", "3.5"],
914 "option -p: "
915 "invalid floating-point value: '2x'")
916
917 def test_nargs_required_values(self):
918 self.assertParseFail(["--point", "1.0", "3.5"],
Greg Wardeba20e62004-07-31 16:15:44 +0000919 "--point option requires 3 arguments")
Greg Ward55493222003-04-21 02:41:25 +0000920
Greg Ward48aa84b2004-10-27 02:20:04 +0000921class TestMultipleArgsAppend(BaseTest):
Greg Ward55493222003-04-21 02:41:25 +0000922 def setUp(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000923 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
Greg Ward55493222003-04-21 02:41:25 +0000924 self.parser.add_option("-p", "--point", action="store", nargs=3,
925 type="float", dest="point")
926 self.parser.add_option("-f", "--foo", action="append", nargs=2,
927 type="int", dest="foo")
Thomas Wouters477c8d52006-05-27 19:21:47 +0000928 self.parser.add_option("-z", "--zero", action="append_const",
929 dest="foo", const=(0, 0))
Greg Ward55493222003-04-21 02:41:25 +0000930
931 def test_nargs_append(self):
932 self.assertParseOK(["-f", "4", "-3", "blah", "--foo", "1", "666"],
933 {'point': None, 'foo': [(4, -3), (1, 666)]},
934 ["blah"])
935
936 def test_nargs_append_required_values(self):
937 self.assertParseFail(["-f4,3"],
Greg Wardeba20e62004-07-31 16:15:44 +0000938 "-f option requires 2 arguments")
Greg Ward55493222003-04-21 02:41:25 +0000939
940 def test_nargs_append_simple(self):
941 self.assertParseOK(["--foo=3", "4"],
942 {'point': None, 'foo':[(3, 4)]},
943 [])
944
Thomas Wouters477c8d52006-05-27 19:21:47 +0000945 def test_nargs_append_const(self):
946 self.assertParseOK(["--zero", "--foo", "3", "4", "-z"],
947 {'point': None, 'foo':[(0, 0), (3, 4), (0, 0)]},
948 [])
949
Greg Ward55493222003-04-21 02:41:25 +0000950class TestVersion(BaseTest):
951 def test_version(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000952 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
953 version="%prog 0.1")
954 save_argv = sys.argv[:]
955 try:
956 sys.argv[0] = os.path.join(os.curdir, "foo", "bar")
957 self.assertOutput(["--version"], "bar 0.1\n")
958 finally:
959 sys.argv[:] = save_argv
Greg Ward55493222003-04-21 02:41:25 +0000960
961 def test_no_version(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000962 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
Greg Ward55493222003-04-21 02:41:25 +0000963 self.assertParseFail(["--version"],
964 "no such option: --version")
965
966# -- Test conflicting default values and parser.parse_args() -----------
967
968class TestConflictingDefaults(BaseTest):
969 """Conflicting default values: the last one should win."""
970 def setUp(self):
971 self.parser = OptionParser(option_list=[
972 make_option("-v", action="store_true", dest="verbose", default=1)])
973
974 def test_conflict_default(self):
975 self.parser.add_option("-q", action="store_false", dest="verbose",
976 default=0)
977 self.assertParseOK([], {'verbose': 0}, [])
978
979 def test_conflict_default_none(self):
980 self.parser.add_option("-q", action="store_false", dest="verbose",
981 default=None)
982 self.assertParseOK([], {'verbose': None}, [])
983
984class TestOptionGroup(BaseTest):
985 def setUp(self):
986 self.parser = OptionParser(usage=SUPPRESS_USAGE)
987
988 def test_option_group_create_instance(self):
989 group = OptionGroup(self.parser, "Spam")
990 self.parser.add_option_group(group)
991 group.add_option("--spam", action="store_true",
992 help="spam spam spam spam")
993 self.assertParseOK(["--spam"], {'spam': 1}, [])
994
995 def test_add_group_no_group(self):
996 self.assertTypeError(self.parser.add_option_group,
997 "not an OptionGroup instance: None", None)
998
999 def test_add_group_invalid_arguments(self):
1000 self.assertTypeError(self.parser.add_option_group,
1001 "invalid arguments", None, None)
1002
1003 def test_add_group_wrong_parser(self):
1004 group = OptionGroup(self.parser, "Spam")
1005 group.parser = OptionParser()
Greg Wardeba20e62004-07-31 16:15:44 +00001006 self.assertRaises(self.parser.add_option_group, (group,), None,
1007 ValueError, "invalid OptionGroup (wrong parser)")
Greg Ward55493222003-04-21 02:41:25 +00001008
1009 def test_group_manipulate(self):
1010 group = self.parser.add_option_group("Group 2",
1011 description="Some more options")
1012 group.set_title("Bacon")
1013 group.add_option("--bacon", type="int")
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001014 self.assertTrue(self.parser.get_option_group("--bacon"), group)
Greg Ward55493222003-04-21 02:41:25 +00001015
1016# -- Test extending and parser.parse_args() ----------------------------
1017
1018class TestExtendAddTypes(BaseTest):
1019 def setUp(self):
Greg Ward48aa84b2004-10-27 02:20:04 +00001020 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
1021 option_class=self.MyOption)
Greg Ward55493222003-04-21 02:41:25 +00001022 self.parser.add_option("-a", None, type="string", dest="a")
1023 self.parser.add_option("-f", "--file", type="file", dest="file")
1024
Thomas Wouters477c8d52006-05-27 19:21:47 +00001025 def tearDown(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001026 if os.path.isdir(support.TESTFN):
1027 os.rmdir(support.TESTFN)
1028 elif os.path.isfile(support.TESTFN):
1029 os.unlink(support.TESTFN)
Thomas Wouters477c8d52006-05-27 19:21:47 +00001030
Greg Ward55493222003-04-21 02:41:25 +00001031 class MyOption (Option):
Thomas Wouters477c8d52006-05-27 19:21:47 +00001032 def check_file(option, opt, value):
Greg Ward55493222003-04-21 02:41:25 +00001033 if not os.path.exists(value):
1034 raise OptionValueError("%s: file does not exist" % value)
1035 elif not os.path.isfile(value):
1036 raise OptionValueError("%s: not a regular file" % value)
1037 return value
1038
1039 TYPES = Option.TYPES + ("file",)
1040 TYPE_CHECKER = copy.copy(Option.TYPE_CHECKER)
1041 TYPE_CHECKER["file"] = check_file
1042
Thomas Wouters477c8d52006-05-27 19:21:47 +00001043 def test_filetype_ok(self):
Victor Stinnerbf816222011-06-30 23:25:47 +02001044 support.create_empty_file(support.TESTFN)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001045 self.assertParseOK(["--file", support.TESTFN, "-afoo"],
1046 {'file': support.TESTFN, 'a': 'foo'},
Greg Ward55493222003-04-21 02:41:25 +00001047 [])
1048
Thomas Wouters477c8d52006-05-27 19:21:47 +00001049 def test_filetype_noexist(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001050 self.assertParseFail(["--file", support.TESTFN, "-afoo"],
Greg Ward55493222003-04-21 02:41:25 +00001051 "%s: file does not exist" %
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001052 support.TESTFN)
Greg Ward55493222003-04-21 02:41:25 +00001053
Thomas Wouters477c8d52006-05-27 19:21:47 +00001054 def test_filetype_notfile(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001055 os.mkdir(support.TESTFN)
1056 self.assertParseFail(["--file", support.TESTFN, "-afoo"],
Greg Ward55493222003-04-21 02:41:25 +00001057 "%s: not a regular file" %
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001058 support.TESTFN)
Thomas Wouters477c8d52006-05-27 19:21:47 +00001059
Greg Ward55493222003-04-21 02:41:25 +00001060
1061class TestExtendAddActions(BaseTest):
1062 def setUp(self):
1063 options = [self.MyOption("-a", "--apple", action="extend",
1064 type="string", dest="apple")]
1065 self.parser = OptionParser(option_list=options)
1066
1067 class MyOption (Option):
1068 ACTIONS = Option.ACTIONS + ("extend",)
1069 STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",)
1070 TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",)
1071
Thomas Wouters477c8d52006-05-27 19:21:47 +00001072 def take_action(self, action, dest, opt, value, values, parser):
Greg Ward55493222003-04-21 02:41:25 +00001073 if action == "extend":
1074 lvalue = value.split(",")
1075 values.ensure_value(dest, []).extend(lvalue)
1076 else:
1077 Option.take_action(self, action, dest, opt, parser, value,
1078 values)
1079
1080 def test_extend_add_action(self):
1081 self.assertParseOK(["-afoo,bar", "--apple=blah"],
1082 {'apple': ["foo", "bar", "blah"]},
1083 [])
1084
1085 def test_extend_add_action_normal(self):
1086 self.assertParseOK(["-a", "foo", "-abar", "--apple=x,y"],
1087 {'apple': ["foo", "bar", "x", "y"]},
1088 [])
1089
1090# -- Test callbacks and parser.parse_args() ----------------------------
1091
1092class TestCallback(BaseTest):
1093 def setUp(self):
1094 options = [make_option("-x",
1095 None,
1096 action="callback",
1097 callback=self.process_opt),
1098 make_option("-f",
1099 "--file",
1100 action="callback",
1101 callback=self.process_opt,
1102 type="string",
1103 dest="filename")]
1104 self.parser = OptionParser(option_list=options)
1105
1106 def process_opt(self, option, opt, value, parser_):
1107 if opt == "-x":
1108 self.assertEqual(option._short_opts, ["-x"])
1109 self.assertEqual(option._long_opts, [])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001110 self.assertTrue(parser_ is self.parser)
1111 self.assertTrue(value is None)
Greg Ward55493222003-04-21 02:41:25 +00001112 self.assertEqual(vars(parser_.values), {'filename': None})
1113
1114 parser_.values.x = 42
1115 elif opt == "--file":
1116 self.assertEqual(option._short_opts, ["-f"])
1117 self.assertEqual(option._long_opts, ["--file"])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001118 self.assertTrue(parser_ is self.parser)
Greg Ward55493222003-04-21 02:41:25 +00001119 self.assertEqual(value, "foo")
1120 self.assertEqual(vars(parser_.values), {'filename': None, 'x': 42})
1121
1122 setattr(parser_.values, option.dest, value)
1123 else:
1124 self.fail("Unknown option %r in process_opt." % opt)
1125
1126 def test_callback(self):
1127 self.assertParseOK(["-x", "--file=foo"],
1128 {'filename': "foo", 'x': 42},
1129 [])
1130
Greg Wardeba20e62004-07-31 16:15:44 +00001131 def test_callback_help(self):
1132 # This test was prompted by SF bug #960515 -- the point is
1133 # not to inspect the help text, just to make sure that
1134 # format_help() doesn't crash.
1135 parser = OptionParser(usage=SUPPRESS_USAGE)
1136 parser.remove_option("-h")
1137 parser.add_option("-t", "--test", action="callback",
1138 callback=lambda: None, type="string",
1139 help="foo")
1140
Thomas Wouters477c8d52006-05-27 19:21:47 +00001141 expected_help = ("Options:\n"
Greg Wardeba20e62004-07-31 16:15:44 +00001142 " -t TEST, --test=TEST foo\n")
1143 self.assertHelp(parser, expected_help)
1144
1145
1146class TestCallbackExtraArgs(BaseTest):
Greg Ward55493222003-04-21 02:41:25 +00001147 def setUp(self):
1148 options = [make_option("-p", "--point", action="callback",
1149 callback=self.process_tuple,
1150 callback_args=(3, int), type="string",
1151 dest="points", default=[])]
1152 self.parser = OptionParser(option_list=options)
1153
Thomas Wouters477c8d52006-05-27 19:21:47 +00001154 def process_tuple(self, option, opt, value, parser_, len, type):
Greg Ward55493222003-04-21 02:41:25 +00001155 self.assertEqual(len, 3)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001156 self.assertTrue(type is int)
Greg Ward55493222003-04-21 02:41:25 +00001157
1158 if opt == "-p":
1159 self.assertEqual(value, "1,2,3")
1160 elif opt == "--point":
1161 self.assertEqual(value, "4,5,6")
1162
1163 value = tuple(map(type, value.split(",")))
1164 getattr(parser_.values, option.dest).append(value)
1165
1166 def test_callback_extra_args(self):
1167 self.assertParseOK(["-p1,2,3", "--point", "4,5,6"],
1168 {'points': [(1,2,3), (4,5,6)]},
1169 [])
1170
Greg Wardeba20e62004-07-31 16:15:44 +00001171class TestCallbackMeddleArgs(BaseTest):
Greg Ward55493222003-04-21 02:41:25 +00001172 def setUp(self):
1173 options = [make_option(str(x), action="callback",
1174 callback=self.process_n, dest='things')
1175 for x in range(-1, -6, -1)]
1176 self.parser = OptionParser(option_list=options)
1177
1178 # Callback that meddles in rargs, largs
Thomas Wouters477c8d52006-05-27 19:21:47 +00001179 def process_n(self, option, opt, value, parser_):
Greg Ward55493222003-04-21 02:41:25 +00001180 # option is -3, -5, etc.
1181 nargs = int(opt[1:])
1182 rargs = parser_.rargs
1183 if len(rargs) < nargs:
1184 self.fail("Expected %d arguments for %s option." % (nargs, opt))
1185 dest = parser_.values.ensure_value(option.dest, [])
1186 dest.append(tuple(rargs[0:nargs]))
1187 parser_.largs.append(nargs)
1188 del rargs[0:nargs]
1189
1190 def test_callback_meddle_args(self):
1191 self.assertParseOK(["-1", "foo", "-3", "bar", "baz", "qux"],
1192 {'things': [("foo",), ("bar", "baz", "qux")]},
1193 [1, 3])
1194
1195 def test_callback_meddle_args_separator(self):
1196 self.assertParseOK(["-2", "foo", "--"],
1197 {'things': [('foo', '--')]},
1198 [2])
1199
Greg Wardeba20e62004-07-31 16:15:44 +00001200class TestCallbackManyArgs(BaseTest):
Greg Ward55493222003-04-21 02:41:25 +00001201 def setUp(self):
1202 options = [make_option("-a", "--apple", action="callback", nargs=2,
1203 callback=self.process_many, type="string"),
1204 make_option("-b", "--bob", action="callback", nargs=3,
1205 callback=self.process_many, type="int")]
1206 self.parser = OptionParser(option_list=options)
1207
Thomas Wouters477c8d52006-05-27 19:21:47 +00001208 def process_many(self, option, opt, value, parser_):
Greg Ward55493222003-04-21 02:41:25 +00001209 if opt == "-a":
1210 self.assertEqual(value, ("foo", "bar"))
1211 elif opt == "--apple":
1212 self.assertEqual(value, ("ding", "dong"))
1213 elif opt == "-b":
1214 self.assertEqual(value, (1, 2, 3))
1215 elif opt == "--bob":
1216 self.assertEqual(value, (-666, 42, 0))
1217
1218 def test_many_args(self):
1219 self.assertParseOK(["-a", "foo", "bar", "--apple", "ding", "dong",
1220 "-b", "1", "2", "3", "--bob", "-666", "42",
1221 "0"],
Greg Wardeba20e62004-07-31 16:15:44 +00001222 {"apple": None, "bob": None},
Greg Ward55493222003-04-21 02:41:25 +00001223 [])
1224
Greg Wardeba20e62004-07-31 16:15:44 +00001225class TestCallbackCheckAbbrev(BaseTest):
Greg Ward55493222003-04-21 02:41:25 +00001226 def setUp(self):
1227 self.parser = OptionParser()
1228 self.parser.add_option("--foo-bar", action="callback",
1229 callback=self.check_abbrev)
1230
Thomas Wouters477c8d52006-05-27 19:21:47 +00001231 def check_abbrev(self, option, opt, value, parser):
Greg Ward55493222003-04-21 02:41:25 +00001232 self.assertEqual(opt, "--foo-bar")
1233
1234 def test_abbrev_callback_expansion(self):
1235 self.assertParseOK(["--foo"], {}, [])
1236
Greg Wardeba20e62004-07-31 16:15:44 +00001237class TestCallbackVarArgs(BaseTest):
Greg Ward55493222003-04-21 02:41:25 +00001238 def setUp(self):
1239 options = [make_option("-a", type="int", nargs=2, dest="a"),
1240 make_option("-b", action="store_true", dest="b"),
1241 make_option("-c", "--callback", action="callback",
1242 callback=self.variable_args, dest="c")]
Greg Ward48aa84b2004-10-27 02:20:04 +00001243 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
1244 option_list=options)
Greg Ward55493222003-04-21 02:41:25 +00001245
Thomas Wouters477c8d52006-05-27 19:21:47 +00001246 def variable_args(self, option, opt, value, parser):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001247 self.assertTrue(value is None)
Greg Ward55493222003-04-21 02:41:25 +00001248 value = []
1249 rargs = parser.rargs
1250 while rargs:
1251 arg = rargs[0]
1252 if ((arg[:2] == "--" and len(arg) > 2) or
1253 (arg[:1] == "-" and len(arg) > 1 and arg[1] != "-")):
1254 break
1255 else:
1256 value.append(arg)
1257 del rargs[0]
1258 setattr(parser.values, option.dest, value)
1259
1260 def test_variable_args(self):
1261 self.assertParseOK(["-a3", "-5", "--callback", "foo", "bar"],
1262 {'a': (3, -5), 'b': None, 'c': ["foo", "bar"]},
1263 [])
1264
1265 def test_consume_separator_stop_at_option(self):
1266 self.assertParseOK(["-c", "37", "--", "xxx", "-b", "hello"],
1267 {'a': None,
1268 'b': True,
1269 'c': ["37", "--", "xxx"]},
1270 ["hello"])
1271
1272 def test_positional_arg_and_variable_args(self):
1273 self.assertParseOK(["hello", "-c", "foo", "-", "bar"],
1274 {'a': None,
1275 'b': None,
1276 'c':["foo", "-", "bar"]},
1277 ["hello"])
1278
1279 def test_stop_at_option(self):
1280 self.assertParseOK(["-c", "foo", "-b"],
1281 {'a': None, 'b': True, 'c': ["foo"]},
1282 [])
1283
1284 def test_stop_at_invalid_option(self):
1285 self.assertParseFail(["-c", "3", "-5", "-a"], "no such option: -5")
1286
1287
1288# -- Test conflict handling and parser.parse_args() --------------------
1289
1290class ConflictBase(BaseTest):
1291 def setUp(self):
1292 options = [make_option("-v", "--verbose", action="count",
1293 dest="verbose", help="increment verbosity")]
Greg Ward48aa84b2004-10-27 02:20:04 +00001294 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
1295 option_list=options)
Greg Ward55493222003-04-21 02:41:25 +00001296
Thomas Wouters477c8d52006-05-27 19:21:47 +00001297 def show_version(self, option, opt, value, parser):
Greg Ward55493222003-04-21 02:41:25 +00001298 parser.values.show_version = 1
1299
1300class TestConflict(ConflictBase):
1301 """Use the default conflict resolution for Optik 1.2: error."""
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001302 def assertTrueconflict_error(self, func):
Greg Wardeba20e62004-07-31 16:15:44 +00001303 err = self.assertRaises(
1304 func, ("-v", "--version"), {'action' : "callback",
1305 'callback' : self.show_version,
1306 'help' : "show version"},
1307 OptionConflictError,
1308 "option -v/--version: conflicting option string(s): -v")
Greg Ward55493222003-04-21 02:41:25 +00001309
1310 self.assertEqual(err.msg, "conflicting option string(s): -v")
1311 self.assertEqual(err.option_id, "-v/--version")
1312
1313 def test_conflict_error(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001314 self.assertTrueconflict_error(self.parser.add_option)
Greg Ward55493222003-04-21 02:41:25 +00001315
1316 def test_conflict_error_group(self):
1317 group = OptionGroup(self.parser, "Group 1")
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001318 self.assertTrueconflict_error(group.add_option)
Greg Ward55493222003-04-21 02:41:25 +00001319
1320 def test_no_such_conflict_handler(self):
Greg Wardeba20e62004-07-31 16:15:44 +00001321 self.assertRaises(
1322 self.parser.set_conflict_handler, ('foo',), None,
1323 ValueError, "invalid conflict_resolution value 'foo'")
Greg Ward55493222003-04-21 02:41:25 +00001324
1325
Greg Ward55493222003-04-21 02:41:25 +00001326class TestConflictResolve(ConflictBase):
1327 def setUp(self):
1328 ConflictBase.setUp(self)
1329 self.parser.set_conflict_handler("resolve")
1330 self.parser.add_option("-v", "--version", action="callback",
1331 callback=self.show_version, help="show version")
1332
1333 def test_conflict_resolve(self):
1334 v_opt = self.parser.get_option("-v")
1335 verbose_opt = self.parser.get_option("--verbose")
1336 version_opt = self.parser.get_option("--version")
1337
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001338 self.assertTrue(v_opt is version_opt)
1339 self.assertTrue(v_opt is not verbose_opt)
Greg Ward55493222003-04-21 02:41:25 +00001340 self.assertEqual(v_opt._long_opts, ["--version"])
1341 self.assertEqual(version_opt._short_opts, ["-v"])
1342 self.assertEqual(version_opt._long_opts, ["--version"])
1343 self.assertEqual(verbose_opt._short_opts, [])
1344 self.assertEqual(verbose_opt._long_opts, ["--verbose"])
1345
1346 def test_conflict_resolve_help(self):
Greg Ward48aa84b2004-10-27 02:20:04 +00001347 self.assertOutput(["-h"], """\
Thomas Wouters477c8d52006-05-27 19:21:47 +00001348Options:
Greg Ward55493222003-04-21 02:41:25 +00001349 --verbose increment verbosity
1350 -h, --help show this help message and exit
1351 -v, --version show version
1352""")
1353
1354 def test_conflict_resolve_short_opt(self):
1355 self.assertParseOK(["-v"],
1356 {'verbose': None, 'show_version': 1},
1357 [])
1358
1359 def test_conflict_resolve_long_opt(self):
1360 self.assertParseOK(["--verbose"],
1361 {'verbose': 1},
1362 [])
1363
1364 def test_conflict_resolve_long_opts(self):
1365 self.assertParseOK(["--verbose", "--version"],
1366 {'verbose': 1, 'show_version': 1},
1367 [])
1368
1369class TestConflictOverride(BaseTest):
1370 def setUp(self):
Greg Ward48aa84b2004-10-27 02:20:04 +00001371 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
Greg Ward55493222003-04-21 02:41:25 +00001372 self.parser.set_conflict_handler("resolve")
1373 self.parser.add_option("-n", "--dry-run",
1374 action="store_true", dest="dry_run",
1375 help="don't do anything")
1376 self.parser.add_option("--dry-run", "-n",
1377 action="store_const", const=42, dest="dry_run",
1378 help="dry run mode")
1379
1380 def test_conflict_override_opts(self):
1381 opt = self.parser.get_option("--dry-run")
1382 self.assertEqual(opt._short_opts, ["-n"])
1383 self.assertEqual(opt._long_opts, ["--dry-run"])
1384
1385 def test_conflict_override_help(self):
Greg Ward48aa84b2004-10-27 02:20:04 +00001386 self.assertOutput(["-h"], """\
Thomas Wouters477c8d52006-05-27 19:21:47 +00001387Options:
Greg Ward55493222003-04-21 02:41:25 +00001388 -h, --help show this help message and exit
1389 -n, --dry-run dry run mode
1390""")
1391
1392 def test_conflict_override_args(self):
1393 self.assertParseOK(["-n"],
1394 {'dry_run': 42},
1395 [])
1396
1397# -- Other testing. ----------------------------------------------------
1398
Greg Wardeba20e62004-07-31 16:15:44 +00001399_expected_help_basic = """\
Thomas Wouters477c8d52006-05-27 19:21:47 +00001400Usage: bar.py [options]
Greg Wardeba20e62004-07-31 16:15:44 +00001401
Thomas Wouters477c8d52006-05-27 19:21:47 +00001402Options:
Greg Wardeba20e62004-07-31 16:15:44 +00001403 -a APPLE throw APPLEs at basket
1404 -b NUM, --boo=NUM shout "boo!" NUM times (in order to frighten away all the
1405 evil spirits that cause trouble and mayhem)
1406 --foo=FOO store FOO in the foo list for later fooing
1407 -h, --help show this help message and exit
1408"""
1409
1410_expected_help_long_opts_first = """\
Thomas Wouters477c8d52006-05-27 19:21:47 +00001411Usage: bar.py [options]
Greg Wardeba20e62004-07-31 16:15:44 +00001412
Thomas Wouters477c8d52006-05-27 19:21:47 +00001413Options:
Greg Wardeba20e62004-07-31 16:15:44 +00001414 -a APPLE throw APPLEs at basket
1415 --boo=NUM, -b NUM shout "boo!" NUM times (in order to frighten away all the
1416 evil spirits that cause trouble and mayhem)
1417 --foo=FOO store FOO in the foo list for later fooing
1418 --help, -h show this help message and exit
1419"""
1420
1421_expected_help_title_formatter = """\
1422Usage
1423=====
1424 bar.py [options]
1425
Thomas Wouters477c8d52006-05-27 19:21:47 +00001426Options
Greg Wardeba20e62004-07-31 16:15:44 +00001427=======
1428-a APPLE throw APPLEs at basket
1429--boo=NUM, -b NUM shout "boo!" NUM times (in order to frighten away all the
1430 evil spirits that cause trouble and mayhem)
1431--foo=FOO store FOO in the foo list for later fooing
1432--help, -h show this help message and exit
1433"""
1434
1435_expected_help_short_lines = """\
Thomas Wouters477c8d52006-05-27 19:21:47 +00001436Usage: bar.py [options]
Greg Wardeba20e62004-07-31 16:15:44 +00001437
Thomas Wouters477c8d52006-05-27 19:21:47 +00001438Options:
Greg Wardeba20e62004-07-31 16:15:44 +00001439 -a APPLE throw APPLEs at basket
1440 -b NUM, --boo=NUM shout "boo!" NUM times (in order to
1441 frighten away all the evil spirits
1442 that cause trouble and mayhem)
1443 --foo=FOO store FOO in the foo list for later
1444 fooing
1445 -h, --help show this help message and exit
1446"""
1447
Serhiy Storchakaf4511122014-01-09 23:14:27 +02001448_expected_very_help_short_lines = """\
1449Usage: bar.py [options]
1450
1451Options:
1452 -a APPLE
1453 throw
1454 APPLEs at
1455 basket
1456 -b NUM, --boo=NUM
1457 shout
1458 "boo!" NUM
1459 times (in
1460 order to
1461 frighten
1462 away all
1463 the evil
1464 spirits
1465 that cause
1466 trouble and
1467 mayhem)
1468 --foo=FOO
1469 store FOO
1470 in the foo
1471 list for
1472 later
1473 fooing
1474 -h, --help
1475 show this
1476 help
1477 message and
1478 exit
1479"""
1480
Greg Ward55493222003-04-21 02:41:25 +00001481class TestHelp(BaseTest):
1482 def setUp(self):
Greg Wardeba20e62004-07-31 16:15:44 +00001483 self.parser = self.make_parser(80)
1484
1485 def make_parser(self, columns):
Greg Ward55493222003-04-21 02:41:25 +00001486 options = [
1487 make_option("-a", type="string", dest='a',
1488 metavar="APPLE", help="throw APPLEs at basket"),
1489 make_option("-b", "--boo", type="int", dest='boo',
1490 metavar="NUM",
1491 help=
1492 "shout \"boo!\" NUM times (in order to frighten away "
1493 "all the evil spirits that cause trouble and mayhem)"),
1494 make_option("--foo", action="append", type="string", dest='foo',
1495 help="store FOO in the foo list for later fooing"),
1496 ]
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001497
1498 # We need to set COLUMNS for the OptionParser constructor, but
1499 # we must restore its original value -- otherwise, this test
1500 # screws things up for other tests when it's part of the Python
1501 # test suite.
Hirokazu Yamamoto71959632009-04-27 01:44:28 +00001502 with support.EnvironmentVarGuard() as env:
Walter Dörwald155374d2009-05-01 19:58:58 +00001503 env['COLUMNS'] = str(columns)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001504 return InterceptingOptionParser(option_list=options)
Greg Ward55493222003-04-21 02:41:25 +00001505
1506 def assertHelpEquals(self, expected_output):
Greg Ward48aa84b2004-10-27 02:20:04 +00001507 save_argv = sys.argv[:]
1508 try:
1509 # Make optparse believe bar.py is being executed.
1510 sys.argv[0] = os.path.join("foo", "bar.py")
1511 self.assertOutput(["-h"], expected_output)
1512 finally:
1513 sys.argv[:] = save_argv
Greg Ward55493222003-04-21 02:41:25 +00001514
1515 def test_help(self):
Greg Wardeba20e62004-07-31 16:15:44 +00001516 self.assertHelpEquals(_expected_help_basic)
Greg Ward55493222003-04-21 02:41:25 +00001517
1518 def test_help_old_usage(self):
Thomas Wouters477c8d52006-05-27 19:21:47 +00001519 self.parser.set_usage("Usage: %prog [options]")
Greg Wardeba20e62004-07-31 16:15:44 +00001520 self.assertHelpEquals(_expected_help_basic)
Greg Ward55493222003-04-21 02:41:25 +00001521
1522 def test_help_long_opts_first(self):
1523 self.parser.formatter.short_first = 0
Greg Wardeba20e62004-07-31 16:15:44 +00001524 self.assertHelpEquals(_expected_help_long_opts_first)
Greg Ward55493222003-04-21 02:41:25 +00001525
1526 def test_help_title_formatter(self):
Hirokazu Yamamoto71959632009-04-27 01:44:28 +00001527 with support.EnvironmentVarGuard() as env:
Walter Dörwald155374d2009-05-01 19:58:58 +00001528 env["COLUMNS"] = "80"
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001529 self.parser.formatter = TitledHelpFormatter()
1530 self.assertHelpEquals(_expected_help_title_formatter)
Greg Ward55493222003-04-21 02:41:25 +00001531
Greg Wardeba20e62004-07-31 16:15:44 +00001532 def test_wrap_columns(self):
1533 # Ensure that wrapping respects $COLUMNS environment variable.
1534 # Need to reconstruct the parser, since that's the only time
1535 # we look at $COLUMNS.
1536 self.parser = self.make_parser(60)
1537 self.assertHelpEquals(_expected_help_short_lines)
Serhiy Storchakaf4511122014-01-09 23:14:27 +02001538 self.parser = self.make_parser(0)
1539 self.assertHelpEquals(_expected_very_help_short_lines)
Greg Ward55493222003-04-21 02:41:25 +00001540
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001541 def test_help_unicode(self):
1542 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
Guido van Rossumef87d6e2007-05-02 19:09:54 +00001543 self.parser.add_option("-a", action="store_true", help="ol\u00E9!")
1544 expect = """\
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001545Options:
1546 -h, --help show this help message and exit
1547 -a ol\u00E9!
1548"""
1549 self.assertHelpEquals(expect)
1550
1551 def test_help_unicode_description(self):
1552 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
Guido van Rossumef87d6e2007-05-02 19:09:54 +00001553 description="ol\u00E9!")
1554 expect = """\
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001555ol\u00E9!
1556
1557Options:
1558 -h, --help show this help message and exit
1559"""
1560 self.assertHelpEquals(expect)
1561
Greg Ward55493222003-04-21 02:41:25 +00001562 def test_help_description_groups(self):
1563 self.parser.set_description(
Greg Wardeba20e62004-07-31 16:15:44 +00001564 "This is the program description for %prog. %prog has "
Greg Ward55493222003-04-21 02:41:25 +00001565 "an option group as well as single options.")
1566
1567 group = OptionGroup(
1568 self.parser, "Dangerous Options",
1569 "Caution: use of these options is at your own risk. "
1570 "It is believed that some of them bite.")
1571 group.add_option("-g", action="store_true", help="Group option.")
1572 self.parser.add_option_group(group)
1573
Thomas Wouters477c8d52006-05-27 19:21:47 +00001574 expect = """\
1575Usage: bar.py [options]
Greg Ward55493222003-04-21 02:41:25 +00001576
Greg Wardeba20e62004-07-31 16:15:44 +00001577This is the program description for bar.py. bar.py has an option group as
1578well as single options.
1579
Thomas Wouters477c8d52006-05-27 19:21:47 +00001580Options:
Greg Wardeba20e62004-07-31 16:15:44 +00001581 -a APPLE throw APPLEs at basket
1582 -b NUM, --boo=NUM shout "boo!" NUM times (in order to frighten away all the
1583 evil spirits that cause trouble and mayhem)
1584 --foo=FOO store FOO in the foo list for later fooing
1585 -h, --help show this help message and exit
Greg Ward55493222003-04-21 02:41:25 +00001586
1587 Dangerous Options:
Greg Wardeba20e62004-07-31 16:15:44 +00001588 Caution: use of these options is at your own risk. It is believed
1589 that some of them bite.
1590
1591 -g Group option.
Thomas Wouters477c8d52006-05-27 19:21:47 +00001592"""
Greg Ward55493222003-04-21 02:41:25 +00001593
Thomas Wouters477c8d52006-05-27 19:21:47 +00001594 self.assertHelpEquals(expect)
Greg Wardeba20e62004-07-31 16:15:44 +00001595
Thomas Wouters477c8d52006-05-27 19:21:47 +00001596 self.parser.epilog = "Please report bugs to /dev/null."
1597 self.assertHelpEquals(expect + "\nPlease report bugs to /dev/null.\n")
Tim Peters10d59f32004-10-27 02:43:25 +00001598
Greg Wardeba20e62004-07-31 16:15:44 +00001599
Greg Ward55493222003-04-21 02:41:25 +00001600class TestMatchAbbrev(BaseTest):
1601 def test_match_abbrev(self):
1602 self.assertEqual(_match_abbrev("--f",
1603 {"--foz": None,
1604 "--foo": None,
1605 "--fie": None,
1606 "--f": None}),
1607 "--f")
1608
1609 def test_match_abbrev_error(self):
1610 s = "--f"
1611 wordmap = {"--foz": None, "--foo": None, "--fie": None}
Greg Wardeba20e62004-07-31 16:15:44 +00001612 self.assertRaises(
1613 _match_abbrev, (s, wordmap), None,
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001614 BadOptionError, "ambiguous option: --f (--fie, --foo, --foz?)")
Greg Wardeba20e62004-07-31 16:15:44 +00001615
1616
Thomas Wouters477c8d52006-05-27 19:21:47 +00001617class TestParseNumber(BaseTest):
1618 def setUp(self):
1619 self.parser = InterceptingOptionParser()
1620 self.parser.add_option("-n", type=int)
Guido van Rossume2a383d2007-01-15 16:59:06 +00001621 self.parser.add_option("-l", type=int)
Thomas Wouters477c8d52006-05-27 19:21:47 +00001622
1623 def test_parse_num_fail(self):
1624 self.assertRaises(
1625 _parse_num, ("", int), {},
1626 ValueError,
1627 re.compile(r"invalid literal for int().*: '?'?"))
1628 self.assertRaises(
Guido van Rossume2a383d2007-01-15 16:59:06 +00001629 _parse_num, ("0xOoops", int), {},
Thomas Wouters477c8d52006-05-27 19:21:47 +00001630 ValueError,
Guido van Rossumb4e87e32007-07-09 10:08:42 +00001631 re.compile(r"invalid literal for int().*: s?'?0xOoops'?"))
Thomas Wouters477c8d52006-05-27 19:21:47 +00001632
1633 def test_parse_num_ok(self):
1634 self.assertEqual(_parse_num("0", int), 0)
1635 self.assertEqual(_parse_num("0x10", int), 16)
Guido van Rossume2a383d2007-01-15 16:59:06 +00001636 self.assertEqual(_parse_num("0XA", int), 10)
1637 self.assertEqual(_parse_num("010", int), 8)
Thomas Wouters477c8d52006-05-27 19:21:47 +00001638 self.assertEqual(_parse_num("0b11", int), 3)
Guido van Rossume2a383d2007-01-15 16:59:06 +00001639 self.assertEqual(_parse_num("0b", int), 0)
Thomas Wouters477c8d52006-05-27 19:21:47 +00001640
1641 def test_numeric_options(self):
1642 self.assertParseOK(["-n", "42", "-l", "0x20"],
1643 { "n": 42, "l": 0x20 }, [])
1644 self.assertParseOK(["-n", "0b0101", "-l010"],
1645 { "n": 5, "l": 8 }, [])
1646 self.assertParseFail(["-n008"],
1647 "option -n: invalid integer value: '008'")
1648 self.assertParseFail(["-l0b0123"],
Guido van Rossumddefaf32007-01-14 03:31:43 +00001649 "option -l: invalid integer value: '0b0123'")
Thomas Wouters477c8d52006-05-27 19:21:47 +00001650 self.assertParseFail(["-l", "0x12x"],
Guido van Rossumddefaf32007-01-14 03:31:43 +00001651 "option -l: invalid integer value: '0x12x'")
Thomas Wouters477c8d52006-05-27 19:21:47 +00001652
1653
Martin Panter19e69c52015-11-14 12:46:42 +00001654class MiscTestCase(unittest.TestCase):
1655 def test__all__(self):
1656 blacklist = {'check_builtin', 'AmbiguousOptionError', 'NO_DEFAULT'}
1657 support.check__all__(self, optparse, blacklist=blacklist)
1658
1659
Greg Ward55493222003-04-21 02:41:25 +00001660def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001661 support.run_unittest(__name__)
Greg Ward55493222003-04-21 02:41:25 +00001662
1663if __name__ == '__main__':
Guido van Rossumd8faa362007-04-27 19:54:29 +00001664 test_main()