blob: 44927d60467df804fbd3b48c477d694c878f5371 [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
Greg Wardab05edc2006-04-23 03:47:58 +000011import re
Greg Ward55493222003-04-21 02:41:25 +000012import copy
Greg Wardab05edc2006-04-23 03:47:58 +000013import types
Greg Ward55493222003-04-21 02:41:25 +000014import unittest
15
Greg Ward0e0c9f42006-06-11 16:24:11 +000016from StringIO import StringIO
Greg Ward55493222003-04-21 02:41:25 +000017from test import test_support
18
Greg Wardab05edc2006-04-23 03:47:58 +000019
Georg Brandla4f46e12010-02-07 17:03:15 +000020from optparse import make_option, Option, \
21 TitledHelpFormatter, OptionParser, OptionGroup, \
22 SUPPRESS_USAGE, OptionError, OptionConflictError, \
Greg Wardab05edc2006-04-23 03:47:58 +000023 BadOptionError, OptionValueError, Values
24from optparse import _match_abbrev
25from optparse import _parse_num
Greg Ward48aa84b2004-10-27 02:20:04 +000026
Greg Wardab05edc2006-04-23 03:47:58 +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
Greg Wardab05edc2006-04-23 03:47:58 +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)
Greg Ward55493222003-04-21 02:41:25 +0000108 except expected_exception, err:
Greg Ward48aa84b2004-10-27 02:20:04 +0000109 actual_message = str(err)
Greg Wardab05edc2006-04-23 03:47:58 +0000110 if isinstance(expected_message, retype):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000111 self.assertTrue(expected_message.search(actual_message),
Greg Ward48aa84b2004-10-27 02:20:04 +0000112 """\
Greg Wardab05edc2006-04-23 03:47:58 +0000113expected exception message pattern:
114/%s/
Greg Ward48aa84b2004-10-27 02:20:04 +0000115actual exception message:
Greg Wardab05edc2006-04-23 03:47:58 +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)
146 except InterceptedError, err:
147 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
Greg Ward0e0c9f42006-06-11 16:24:11 +0000158 encoding = getattr(save_stdout, 'encoding', None)
Tim Peters579f7352004-07-31 21:14:28 +0000159 try:
Greg Ward48aa84b2004-10-27 02:20:04 +0000160 try:
161 sys.stdout = StringIO()
Greg Ward0e0c9f42006-06-11 16:24:11 +0000162 if encoding:
163 sys.stdout.encoding = encoding
Greg Ward48aa84b2004-10-27 02:20:04 +0000164 self.parser.parse_args(cmdline_args)
165 finally:
166 output = sys.stdout.getvalue()
167 sys.stdout = save_stdout
Greg Ward55493222003-04-21 02:41:25 +0000168
Greg Ward48aa84b2004-10-27 02:20:04 +0000169 except InterceptedError, err:
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000170 self.assertTrue(
Greg Ward0e0c9f42006-06-11 16:24:11 +0000171 type(output) is types.StringType,
172 "expected output to be an ordinary string, not %r"
173 % type(output))
174
Greg Wardab05edc2006-04-23 03:47:58 +0000175 if output != expected_output:
176 self.fail("expected: \n'''\n" + expected_output +
177 "'''\nbut got \n'''\n" + output + "'''")
Greg Ward48aa84b2004-10-27 02:20:04 +0000178 self.assertEqual(err.exit_status, expected_status)
179 self.assertEqual(err.exit_message, expected_error)
180 else:
181 self.assertFalse("expected parser.exit()")
182
183 def assertTypeError(self, func, expected_message, *args):
184 """Assert that TypeError is raised when executing func."""
185 self.assertRaises(func, args, None, TypeError, expected_message)
Greg Wardeba20e62004-07-31 16:15:44 +0000186
187 def assertHelp(self, parser, expected_help):
188 actual_help = parser.format_help()
189 if actual_help != expected_help:
190 raise self.failureException(
191 'help text failure; expected:\n"' +
192 expected_help + '"; got:\n"' +
193 actual_help + '"\n')
Greg Ward55493222003-04-21 02:41:25 +0000194
195# -- Test make_option() aka Option -------------------------------------
196
Greg Ward48aa84b2004-10-27 02:20:04 +0000197# It's not necessary to test correct options here. All the tests in the
Greg Ward55493222003-04-21 02:41:25 +0000198# parser.parse_args() section deal with those, because they're needed
Greg Ward48aa84b2004-10-27 02:20:04 +0000199# there.
Greg Ward55493222003-04-21 02:41:25 +0000200
201class TestOptionChecks(BaseTest):
202 def setUp(self):
203 self.parser = OptionParser(usage=SUPPRESS_USAGE)
204
Greg Ward48aa84b2004-10-27 02:20:04 +0000205 def assertOptionError(self, expected_message, args=[], kwargs={}):
Greg Wardeba20e62004-07-31 16:15:44 +0000206 self.assertRaises(make_option, args, kwargs,
Greg Ward48aa84b2004-10-27 02:20:04 +0000207 OptionError, expected_message)
Greg Ward55493222003-04-21 02:41:25 +0000208
209 def test_opt_string_empty(self):
210 self.assertTypeError(make_option,
211 "at least one option string must be supplied")
212
213 def test_opt_string_too_short(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000214 self.assertOptionError(
215 "invalid option string 'b': must be at least two characters long",
216 ["b"])
Greg Ward55493222003-04-21 02:41:25 +0000217
218 def test_opt_string_short_invalid(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000219 self.assertOptionError(
220 "invalid short option string '--': must be "
221 "of the form -x, (x any non-dash char)",
222 ["--"])
Greg Ward55493222003-04-21 02:41:25 +0000223
224 def test_opt_string_long_invalid(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000225 self.assertOptionError(
226 "invalid long option string '---': "
227 "must start with --, followed by non-dash",
228 ["---"])
Greg Ward55493222003-04-21 02:41:25 +0000229
230 def test_attr_invalid(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000231 self.assertOptionError(
Armin Rigoa3f09272006-05-28 19:13:17 +0000232 "option -b: invalid keyword arguments: bar, foo",
Greg Ward48aa84b2004-10-27 02:20:04 +0000233 ["-b"], {'foo': None, 'bar': None})
Greg Ward55493222003-04-21 02:41:25 +0000234
235 def test_action_invalid(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000236 self.assertOptionError(
237 "option -b: invalid action: 'foo'",
238 ["-b"], {'action': 'foo'})
Greg Ward55493222003-04-21 02:41:25 +0000239
240 def test_type_invalid(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000241 self.assertOptionError(
242 "option -b: invalid option type: 'foo'",
243 ["-b"], {'type': 'foo'})
244 self.assertOptionError(
245 "option -b: invalid option type: 'tuple'",
246 ["-b"], {'type': tuple})
Greg Ward55493222003-04-21 02:41:25 +0000247
248 def test_no_type_for_action(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000249 self.assertOptionError(
250 "option -b: must not supply a type for action 'count'",
251 ["-b"], {'action': 'count', 'type': 'int'})
Greg Ward55493222003-04-21 02:41:25 +0000252
253 def test_no_choices_list(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000254 self.assertOptionError(
255 "option -b/--bad: must supply a list of "
256 "choices for type 'choice'",
257 ["-b", "--bad"], {'type': "choice"})
Greg Ward55493222003-04-21 02:41:25 +0000258
259 def test_bad_choices_list(self):
260 typename = type('').__name__
Greg Ward48aa84b2004-10-27 02:20:04 +0000261 self.assertOptionError(
262 "option -b/--bad: choices must be a list of "
263 "strings ('%s' supplied)" % typename,
264 ["-b", "--bad"],
265 {'type': "choice", 'choices':"bad choices"})
Greg Ward55493222003-04-21 02:41:25 +0000266
267 def test_no_choices_for_type(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000268 self.assertOptionError(
269 "option -b: must not supply choices for type 'int'",
270 ["-b"], {'type': 'int', 'choices':"bad"})
Greg Ward55493222003-04-21 02:41:25 +0000271
272 def test_no_const_for_action(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000273 self.assertOptionError(
274 "option -b: 'const' must not be supplied for action 'store'",
275 ["-b"], {'action': 'store', 'const': 1})
Greg Ward55493222003-04-21 02:41:25 +0000276
277 def test_no_nargs_for_action(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000278 self.assertOptionError(
279 "option -b: 'nargs' must not be supplied for action 'count'",
280 ["-b"], {'action': 'count', 'nargs': 2})
Greg Ward55493222003-04-21 02:41:25 +0000281
282 def test_callback_not_callable(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000283 self.assertOptionError(
284 "option -b: callback not callable: 'foo'",
285 ["-b"], {'action': 'callback',
286 'callback': 'foo'})
Greg Ward55493222003-04-21 02:41:25 +0000287
288 def dummy(self):
289 pass
290
291 def test_callback_args_no_tuple(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000292 self.assertOptionError(
293 "option -b: callback_args, if supplied, "
294 "must be a tuple: not 'foo'",
295 ["-b"], {'action': 'callback',
296 'callback': self.dummy,
297 'callback_args': 'foo'})
Greg Ward55493222003-04-21 02:41:25 +0000298
299 def test_callback_kwargs_no_dict(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000300 self.assertOptionError(
301 "option -b: callback_kwargs, if supplied, "
302 "must be a dict: not 'foo'",
303 ["-b"], {'action': 'callback',
304 'callback': self.dummy,
305 'callback_kwargs': 'foo'})
Greg Ward55493222003-04-21 02:41:25 +0000306
307 def test_no_callback_for_action(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000308 self.assertOptionError(
309 "option -b: callback supplied ('foo') for non-callback option",
310 ["-b"], {'action': 'store',
311 'callback': 'foo'})
Greg Ward55493222003-04-21 02:41:25 +0000312
313 def test_no_callback_args_for_action(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000314 self.assertOptionError(
315 "option -b: callback_args supplied for non-callback option",
316 ["-b"], {'action': 'store',
317 'callback_args': 'foo'})
Greg Ward55493222003-04-21 02:41:25 +0000318
319 def test_no_callback_kwargs_for_action(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000320 self.assertOptionError(
321 "option -b: callback_kwargs supplied for non-callback option",
322 ["-b"], {'action': 'store',
323 'callback_kwargs': 'foo'})
Greg Ward55493222003-04-21 02:41:25 +0000324
325class TestOptionParser(BaseTest):
326 def setUp(self):
327 self.parser = OptionParser()
328 self.parser.add_option("-v", "--verbose", "-n", "--noisy",
329 action="store_true", dest="verbose")
330 self.parser.add_option("-q", "--quiet", "--silent",
331 action="store_false", dest="verbose")
332
333 def test_add_option_no_Option(self):
334 self.assertTypeError(self.parser.add_option,
335 "not an Option instance: None", None)
336
337 def test_add_option_invalid_arguments(self):
338 self.assertTypeError(self.parser.add_option,
339 "invalid arguments", None, None)
340
341 def test_get_option(self):
342 opt1 = self.parser.get_option("-v")
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000343 self.assertIsInstance(opt1, Option)
Greg Ward55493222003-04-21 02:41:25 +0000344 self.assertEqual(opt1._short_opts, ["-v", "-n"])
345 self.assertEqual(opt1._long_opts, ["--verbose", "--noisy"])
346 self.assertEqual(opt1.action, "store_true")
347 self.assertEqual(opt1.dest, "verbose")
348
349 def test_get_option_equals(self):
350 opt1 = self.parser.get_option("-v")
351 opt2 = self.parser.get_option("--verbose")
352 opt3 = self.parser.get_option("-n")
353 opt4 = self.parser.get_option("--noisy")
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000354 self.assertTrue(opt1 is opt2 is opt3 is opt4)
Greg Ward55493222003-04-21 02:41:25 +0000355
356 def test_has_option(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000357 self.assertTrue(self.parser.has_option("-v"))
358 self.assertTrue(self.parser.has_option("--verbose"))
Greg Ward55493222003-04-21 02:41:25 +0000359
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000360 def assertTrueremoved(self):
361 self.assertTrue(self.parser.get_option("-v") is None)
362 self.assertTrue(self.parser.get_option("--verbose") is None)
363 self.assertTrue(self.parser.get_option("-n") is None)
364 self.assertTrue(self.parser.get_option("--noisy") is None)
Greg Ward55493222003-04-21 02:41:25 +0000365
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000366 self.assertFalse(self.parser.has_option("-v"))
367 self.assertFalse(self.parser.has_option("--verbose"))
368 self.assertFalse(self.parser.has_option("-n"))
369 self.assertFalse(self.parser.has_option("--noisy"))
Greg Ward55493222003-04-21 02:41:25 +0000370
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000371 self.assertTrue(self.parser.has_option("-q"))
372 self.assertTrue(self.parser.has_option("--silent"))
Greg Ward55493222003-04-21 02:41:25 +0000373
374 def test_remove_short_opt(self):
375 self.parser.remove_option("-n")
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000376 self.assertTrueremoved()
Greg Ward55493222003-04-21 02:41:25 +0000377
378 def test_remove_long_opt(self):
379 self.parser.remove_option("--verbose")
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000380 self.assertTrueremoved()
Greg Ward55493222003-04-21 02:41:25 +0000381
382 def test_remove_nonexistent(self):
Greg Wardeba20e62004-07-31 16:15:44 +0000383 self.assertRaises(self.parser.remove_option, ('foo',), None,
384 ValueError, "no such option 'foo'")
385
Greg Wardab05edc2006-04-23 03:47:58 +0000386 def test_refleak(self):
387 # If an OptionParser is carrying around a reference to a large
388 # object, various cycles can prevent it from being GC'd in
389 # a timely fashion. destroy() breaks the cycles to ensure stuff
390 # can be cleaned up.
391 big_thing = [42]
392 refcount = sys.getrefcount(big_thing)
393 parser = OptionParser()
394 parser.add_option("-a", "--aaarggh")
395 parser.big_thing = big_thing
396
397 parser.destroy()
398 #self.assertEqual(refcount, sys.getrefcount(big_thing))
399 del parser
400 self.assertEqual(refcount, sys.getrefcount(big_thing))
401
402
Greg Ward48aa84b2004-10-27 02:20:04 +0000403class TestOptionValues(BaseTest):
404 def setUp(self):
405 pass
406
407 def test_basics(self):
408 values = Values()
409 self.assertEqual(vars(values), {})
410 self.assertEqual(values, {})
411 self.assertNotEqual(values, {"foo": "bar"})
412 self.assertNotEqual(values, "")
413
414 dict = {"foo": "bar", "baz": 42}
415 values = Values(defaults=dict)
416 self.assertEqual(vars(values), dict)
417 self.assertEqual(values, dict)
418 self.assertNotEqual(values, {"foo": "bar"})
419 self.assertNotEqual(values, {})
420 self.assertNotEqual(values, "")
421 self.assertNotEqual(values, [])
422
423
Greg Wardeba20e62004-07-31 16:15:44 +0000424class TestTypeAliases(BaseTest):
425 def setUp(self):
426 self.parser = OptionParser()
427
Greg Wardab05edc2006-04-23 03:47:58 +0000428 def test_str_aliases_string(self):
429 self.parser.add_option("-s", type="str")
Ezio Melotti2623a372010-11-21 13:34:58 +0000430 self.assertEqual(self.parser.get_option("-s").type, "string")
Greg Wardab05edc2006-04-23 03:47:58 +0000431
432 def test_new_type_object(self):
433 self.parser.add_option("-s", type=str)
Ezio Melotti2623a372010-11-21 13:34:58 +0000434 self.assertEqual(self.parser.get_option("-s").type, "string")
Greg Wardab05edc2006-04-23 03:47:58 +0000435 self.parser.add_option("-x", type=int)
Ezio Melotti2623a372010-11-21 13:34:58 +0000436 self.assertEqual(self.parser.get_option("-x").type, "int")
Greg Wardab05edc2006-04-23 03:47:58 +0000437
438 def test_old_type_object(self):
439 self.parser.add_option("-s", type=types.StringType)
Ezio Melotti2623a372010-11-21 13:34:58 +0000440 self.assertEqual(self.parser.get_option("-s").type, "string")
Greg Wardab05edc2006-04-23 03:47:58 +0000441 self.parser.add_option("-x", type=types.IntType)
Ezio Melotti2623a372010-11-21 13:34:58 +0000442 self.assertEqual(self.parser.get_option("-x").type, "int")
Tim Peters10d59f32004-10-27 02:43:25 +0000443
Greg Wardeba20e62004-07-31 16:15:44 +0000444
445# Custom type for testing processing of default values.
446_time_units = { 's' : 1, 'm' : 60, 'h' : 60*60, 'd' : 60*60*24 }
447
448def _check_duration(option, opt, value):
449 try:
450 if value[-1].isdigit():
451 return int(value)
452 else:
453 return int(value[:-1]) * _time_units[value[-1]]
Georg Brandlb3cda982010-02-07 12:19:43 +0000454 except (ValueError, IndexError):
Greg Wardeba20e62004-07-31 16:15:44 +0000455 raise OptionValueError(
456 'option %s: invalid duration: %r' % (opt, value))
457
458class DurationOption(Option):
459 TYPES = Option.TYPES + ('duration',)
460 TYPE_CHECKER = copy.copy(Option.TYPE_CHECKER)
461 TYPE_CHECKER['duration'] = _check_duration
462
463class TestDefaultValues(BaseTest):
464 def setUp(self):
465 self.parser = OptionParser()
466 self.parser.add_option("-v", "--verbose", default=True)
467 self.parser.add_option("-q", "--quiet", dest='verbose')
468 self.parser.add_option("-n", type="int", default=37)
469 self.parser.add_option("-m", type="int")
470 self.parser.add_option("-s", default="foo")
471 self.parser.add_option("-t")
472 self.parser.add_option("-u", default=None)
473 self.expected = { 'verbose': True,
474 'n': 37,
475 'm': None,
476 's': "foo",
477 't': None,
478 'u': None }
479
480 def test_basic_defaults(self):
481 self.assertEqual(self.parser.get_default_values(), self.expected)
482
483 def test_mixed_defaults_post(self):
484 self.parser.set_defaults(n=42, m=-100)
485 self.expected.update({'n': 42, 'm': -100})
486 self.assertEqual(self.parser.get_default_values(), self.expected)
487
488 def test_mixed_defaults_pre(self):
489 self.parser.set_defaults(x="barf", y="blah")
490 self.parser.add_option("-x", default="frob")
491 self.parser.add_option("-y")
492
493 self.expected.update({'x': "frob", 'y': "blah"})
494 self.assertEqual(self.parser.get_default_values(), self.expected)
495
496 self.parser.remove_option("-y")
497 self.parser.add_option("-y", default=None)
498 self.expected.update({'y': None})
499 self.assertEqual(self.parser.get_default_values(), self.expected)
500
501 def test_process_default(self):
502 self.parser.option_class = DurationOption
503 self.parser.add_option("-d", type="duration", default=300)
504 self.parser.add_option("-e", type="duration", default="6m")
505 self.parser.set_defaults(n="42")
506 self.expected.update({'d': 300, 'e': 360, 'n': 42})
507 self.assertEqual(self.parser.get_default_values(), self.expected)
508
509 self.parser.set_process_default_values(False)
510 self.expected.update({'d': 300, 'e': "6m", 'n': "42"})
511 self.assertEqual(self.parser.get_default_values(), self.expected)
512
513
514class TestProgName(BaseTest):
515 """
516 Test that %prog expands to the right thing in usage, version,
517 and help strings.
518 """
519
520 def assertUsage(self, parser, expected_usage):
521 self.assertEqual(parser.get_usage(), expected_usage)
522
523 def assertVersion(self, parser, expected_version):
524 self.assertEqual(parser.get_version(), expected_version)
525
526
527 def test_default_progname(self):
528 # Make sure that program name taken from sys.argv[0] by default.
Tim Peters579f7352004-07-31 21:14:28 +0000529 save_argv = sys.argv[:]
530 try:
Greg Ward48aa84b2004-10-27 02:20:04 +0000531 sys.argv[0] = os.path.join("foo", "bar", "baz.py")
Greg Wardab05edc2006-04-23 03:47:58 +0000532 parser = OptionParser("%prog ...", version="%prog 1.2")
533 expected_usage = "Usage: baz.py ...\n"
Tim Peters579f7352004-07-31 21:14:28 +0000534 self.assertUsage(parser, expected_usage)
535 self.assertVersion(parser, "baz.py 1.2")
536 self.assertHelp(parser,
Greg Ward48aa84b2004-10-27 02:20:04 +0000537 expected_usage + "\n" +
Greg Wardab05edc2006-04-23 03:47:58 +0000538 "Options:\n"
Greg Ward48aa84b2004-10-27 02:20:04 +0000539 " --version show program's version number and exit\n"
540 " -h, --help show this help message and exit\n")
Tim Peters579f7352004-07-31 21:14:28 +0000541 finally:
542 sys.argv[:] = save_argv
Greg Wardeba20e62004-07-31 16:15:44 +0000543
544 def test_custom_progname(self):
545 parser = OptionParser(prog="thingy",
546 version="%prog 0.1",
547 usage="%prog arg arg")
548 parser.remove_option("-h")
549 parser.remove_option("--version")
Greg Wardab05edc2006-04-23 03:47:58 +0000550 expected_usage = "Usage: thingy arg arg\n"
Greg Wardeba20e62004-07-31 16:15:44 +0000551 self.assertUsage(parser, expected_usage)
552 self.assertVersion(parser, "thingy 0.1")
553 self.assertHelp(parser, expected_usage + "\n")
554
555
556class TestExpandDefaults(BaseTest):
557 def setUp(self):
558 self.parser = OptionParser(prog="test")
559 self.help_prefix = """\
Greg Wardab05edc2006-04-23 03:47:58 +0000560Usage: test [options]
Greg Wardeba20e62004-07-31 16:15:44 +0000561
Greg Wardab05edc2006-04-23 03:47:58 +0000562Options:
Greg Wardeba20e62004-07-31 16:15:44 +0000563 -h, --help show this help message and exit
564"""
565 self.file_help = "read from FILE [default: %default]"
566 self.expected_help_file = self.help_prefix + \
567 " -f FILE, --file=FILE read from FILE [default: foo.txt]\n"
568 self.expected_help_none = self.help_prefix + \
569 " -f FILE, --file=FILE read from FILE [default: none]\n"
570
571 def test_option_default(self):
572 self.parser.add_option("-f", "--file",
573 default="foo.txt",
574 help=self.file_help)
575 self.assertHelp(self.parser, self.expected_help_file)
576
577 def test_parser_default_1(self):
578 self.parser.add_option("-f", "--file",
579 help=self.file_help)
580 self.parser.set_default('file', "foo.txt")
581 self.assertHelp(self.parser, self.expected_help_file)
582
583 def test_parser_default_2(self):
584 self.parser.add_option("-f", "--file",
585 help=self.file_help)
586 self.parser.set_defaults(file="foo.txt")
587 self.assertHelp(self.parser, self.expected_help_file)
588
589 def test_no_default(self):
590 self.parser.add_option("-f", "--file",
591 help=self.file_help)
592 self.assertHelp(self.parser, self.expected_help_none)
593
594 def test_default_none_1(self):
595 self.parser.add_option("-f", "--file",
596 default=None,
597 help=self.file_help)
598 self.assertHelp(self.parser, self.expected_help_none)
Tim Peters10d59f32004-10-27 02:43:25 +0000599
Greg Wardeba20e62004-07-31 16:15:44 +0000600 def test_default_none_2(self):
601 self.parser.add_option("-f", "--file",
602 help=self.file_help)
603 self.parser.set_defaults(file=None)
604 self.assertHelp(self.parser, self.expected_help_none)
605
606 def test_float_default(self):
607 self.parser.add_option(
608 "-p", "--prob",
609 help="blow up with probability PROB [default: %default]")
610 self.parser.set_defaults(prob=0.43)
611 expected_help = self.help_prefix + \
612 " -p PROB, --prob=PROB blow up with probability PROB [default: 0.43]\n"
613 self.assertHelp(self.parser, expected_help)
614
615 def test_alt_expand(self):
616 self.parser.add_option("-f", "--file",
617 default="foo.txt",
618 help="read from FILE [default: *DEFAULT*]")
619 self.parser.formatter.default_tag = "*DEFAULT*"
620 self.assertHelp(self.parser, self.expected_help_file)
621
622 def test_no_expand(self):
623 self.parser.add_option("-f", "--file",
624 default="foo.txt",
625 help="read from %default file")
626 self.parser.formatter.default_tag = None
627 expected_help = self.help_prefix + \
628 " -f FILE, --file=FILE read from %default file\n"
629 self.assertHelp(self.parser, expected_help)
630
Greg Ward55493222003-04-21 02:41:25 +0000631
632# -- Test parser.parse_args() ------------------------------------------
633
634class TestStandard(BaseTest):
635 def setUp(self):
636 options = [make_option("-a", type="string"),
637 make_option("-b", "--boo", type="int", dest='boo'),
638 make_option("--foo", action="append")]
639
Greg Ward48aa84b2004-10-27 02:20:04 +0000640 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
641 option_list=options)
Greg Ward55493222003-04-21 02:41:25 +0000642
643 def test_required_value(self):
Greg Wardeba20e62004-07-31 16:15:44 +0000644 self.assertParseFail(["-a"], "-a option requires an argument")
Greg Ward55493222003-04-21 02:41:25 +0000645
646 def test_invalid_integer(self):
647 self.assertParseFail(["-b", "5x"],
648 "option -b: invalid integer value: '5x'")
649
650 def test_no_such_option(self):
651 self.assertParseFail(["--boo13"], "no such option: --boo13")
652
653 def test_long_invalid_integer(self):
654 self.assertParseFail(["--boo=x5"],
655 "option --boo: invalid integer value: 'x5'")
656
657 def test_empty(self):
658 self.assertParseOK([], {'a': None, 'boo': None, 'foo': None}, [])
659
660 def test_shortopt_empty_longopt_append(self):
661 self.assertParseOK(["-a", "", "--foo=blah", "--foo="],
662 {'a': "", 'boo': None, 'foo': ["blah", ""]},
663 [])
664
665 def test_long_option_append(self):
666 self.assertParseOK(["--foo", "bar", "--foo", "", "--foo=x"],
667 {'a': None,
668 'boo': None,
669 'foo': ["bar", "", "x"]},
670 [])
671
672 def test_option_argument_joined(self):
673 self.assertParseOK(["-abc"],
674 {'a': "bc", 'boo': None, 'foo': None},
675 [])
676
677 def test_option_argument_split(self):
678 self.assertParseOK(["-a", "34"],
679 {'a': "34", 'boo': None, 'foo': None},
680 [])
681
682 def test_option_argument_joined_integer(self):
683 self.assertParseOK(["-b34"],
684 {'a': None, 'boo': 34, 'foo': None},
685 [])
686
687 def test_option_argument_split_negative_integer(self):
688 self.assertParseOK(["-b", "-5"],
689 {'a': None, 'boo': -5, 'foo': None},
690 [])
691
692 def test_long_option_argument_joined(self):
693 self.assertParseOK(["--boo=13"],
694 {'a': None, 'boo': 13, 'foo': None},
695 [])
696
697 def test_long_option_argument_split(self):
698 self.assertParseOK(["--boo", "111"],
699 {'a': None, 'boo': 111, 'foo': None},
700 [])
701
702 def test_long_option_short_option(self):
703 self.assertParseOK(["--foo=bar", "-axyz"],
704 {'a': 'xyz', 'boo': None, 'foo': ["bar"]},
705 [])
706
707 def test_abbrev_long_option(self):
708 self.assertParseOK(["--f=bar", "-axyz"],
709 {'a': 'xyz', 'boo': None, 'foo': ["bar"]},
710 [])
711
712 def test_defaults(self):
713 (options, args) = self.parser.parse_args([])
714 defaults = self.parser.get_default_values()
715 self.assertEqual(vars(defaults), vars(options))
716
717 def test_ambiguous_option(self):
718 self.parser.add_option("--foz", action="store",
719 type="string", dest="foo")
Greg Ward55493222003-04-21 02:41:25 +0000720 self.assertParseFail(["--f=bar"],
Armin Rigoa3f09272006-05-28 19:13:17 +0000721 "ambiguous option: --f (--foo, --foz?)")
Greg Ward55493222003-04-21 02:41:25 +0000722
723
724 def test_short_and_long_option_split(self):
725 self.assertParseOK(["-a", "xyz", "--foo", "bar"],
726 {'a': 'xyz', 'boo': None, 'foo': ["bar"]},
727 []),
728
729 def test_short_option_split_long_option_append(self):
730 self.assertParseOK(["--foo=bar", "-b", "123", "--foo", "baz"],
731 {'a': None, 'boo': 123, 'foo': ["bar", "baz"]},
732 [])
733
734 def test_short_option_split_one_positional_arg(self):
735 self.assertParseOK(["-a", "foo", "bar"],
736 {'a': "foo", 'boo': None, 'foo': None},
737 ["bar"]),
738
739 def test_short_option_consumes_separator(self):
740 self.assertParseOK(["-a", "--", "foo", "bar"],
741 {'a': "--", 'boo': None, 'foo': None},
742 ["foo", "bar"]),
Greg Wardab05edc2006-04-23 03:47:58 +0000743 self.assertParseOK(["-a", "--", "--foo", "bar"],
744 {'a': "--", 'boo': None, 'foo': ["bar"]},
745 []),
Greg Ward55493222003-04-21 02:41:25 +0000746
747 def test_short_option_joined_and_separator(self):
748 self.assertParseOK(["-ab", "--", "--foo", "bar"],
749 {'a': "b", 'boo': None, 'foo': None},
750 ["--foo", "bar"]),
751
Greg Wardab05edc2006-04-23 03:47:58 +0000752 def test_hyphen_becomes_positional_arg(self):
Greg Ward55493222003-04-21 02:41:25 +0000753 self.assertParseOK(["-ab", "-", "--foo", "bar"],
754 {'a': "b", 'boo': None, 'foo': ["bar"]},
755 ["-"])
756
757 def test_no_append_versus_append(self):
758 self.assertParseOK(["-b3", "-b", "5", "--foo=bar", "--foo", "baz"],
759 {'a': None, 'boo': 5, 'foo': ["bar", "baz"]},
760 [])
761
762 def test_option_consumes_optionlike_string(self):
763 self.assertParseOK(["-a", "-b3"],
764 {'a': "-b3", 'boo': None, 'foo': None},
765 [])
766
R. David Murray32e06812010-06-26 00:06:44 +0000767 def test_combined_single_invalid_option(self):
768 self.parser.add_option("-t", action="store_true")
769 self.assertParseFail(["-test"],
R. David Murray04a34392010-06-26 03:27:32 +0000770 "no such option: -e")
R. David Murray32e06812010-06-26 00:06:44 +0000771
R David Murray7cd8b422012-08-14 09:14:37 -0400772 def test_add_option_accepts_unicode(self):
773 self.parser.add_option(u"-u", u"--unicode", action="store_true")
774 self.assertParseOK(["-u"],
775 {'a': None, 'boo': None, 'foo': None, 'unicode': True},
776 [])
777
R David Murrayfe9efc52012-08-13 22:04:30 -0400778
Greg Ward55493222003-04-21 02:41:25 +0000779class TestBool(BaseTest):
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 [])
Georg Brandle2773252010-08-01 19:14:56 +0000801 self.assertTrue(options.verbose is False)
Greg Ward55493222003-04-21 02:41:25 +0000802
803 def test_bool_true(self):
804 (options, args) = self.assertParseOK(["-v"],
805 {'verbose': 1},
806 [])
Georg Brandle2773252010-08-01 19:14:56 +0000807 self.assertTrue(options.verbose is True)
Greg Ward55493222003-04-21 02:41:25 +0000808
809 def test_bool_flicker_on_and_off(self):
810 self.assertParseOK(["-qvq", "-q", "-v"],
811 {'verbose': 1},
812 [])
813
814class TestChoice(BaseTest):
815 def setUp(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000816 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
Greg Ward55493222003-04-21 02:41:25 +0000817 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
837class TestCount(BaseTest):
838 def setUp(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000839 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
Greg Ward55493222003-04-21 02:41:25 +0000840 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
Greg Ward48aa84b2004-10-27 02:20:04 +0000895class TestMultipleArgs(BaseTest):
Greg Ward55493222003-04-21 02:41:25 +0000896 def setUp(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000897 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
Greg Ward55493222003-04-21 02:41:25 +0000898 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"],
Greg Wardeba20e62004-07-31 16:15:44 +0000918 "--point option requires 3 arguments")
Greg Ward55493222003-04-21 02:41:25 +0000919
Greg Ward48aa84b2004-10-27 02:20:04 +0000920class TestMultipleArgsAppend(BaseTest):
Greg Ward55493222003-04-21 02:41:25 +0000921 def setUp(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000922 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
Greg Ward55493222003-04-21 02:41:25 +0000923 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")
Greg Wardab05edc2006-04-23 03:47:58 +0000927 self.parser.add_option("-z", "--zero", action="append_const",
928 dest="foo", const=(0, 0))
Greg Ward55493222003-04-21 02:41:25 +0000929
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"],
Greg Wardeba20e62004-07-31 16:15:44 +0000937 "-f option requires 2 arguments")
Greg Ward55493222003-04-21 02:41:25 +0000938
939 def test_nargs_append_simple(self):
940 self.assertParseOK(["--foo=3", "4"],
941 {'point': None, 'foo':[(3, 4)]},
942 [])
943
Greg Wardab05edc2006-04-23 03:47:58 +0000944 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
Greg Ward55493222003-04-21 02:41:25 +0000949class TestVersion(BaseTest):
950 def test_version(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000951 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
Greg Ward55493222003-04-21 02:41:25 +0000959
960 def test_no_version(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000961 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
Greg Ward55493222003-04-21 02:41:25 +0000962 self.assertParseFail(["--version"],
963 "no such option: --version")
964
965# -- Test conflicting default values and parser.parse_args() -----------
966
967class TestConflictingDefaults(BaseTest):
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
983class TestOptionGroup(BaseTest):
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()
Greg Wardeba20e62004-07-31 16:15:44 +00001005 self.assertRaises(self.parser.add_option_group, (group,), None,
1006 ValueError, "invalid OptionGroup (wrong parser)")
Greg Ward55493222003-04-21 02:41:25 +00001007
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")
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001013 self.assertTrue(self.parser.get_option_group("--bacon"), group)
Greg Ward55493222003-04-21 02:41:25 +00001014
1015# -- Test extending and parser.parse_args() ----------------------------
1016
1017class TestExtendAddTypes(BaseTest):
1018 def setUp(self):
Greg Ward48aa84b2004-10-27 02:20:04 +00001019 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
1020 option_class=self.MyOption)
Greg Ward55493222003-04-21 02:41:25 +00001021 self.parser.add_option("-a", None, type="string", dest="a")
1022 self.parser.add_option("-f", "--file", type="file", dest="file")
1023
Greg Wardab05edc2006-04-23 03:47:58 +00001024 def tearDown(self):
1025 if os.path.isdir(test_support.TESTFN):
1026 os.rmdir(test_support.TESTFN)
1027 elif os.path.isfile(test_support.TESTFN):
1028 os.unlink(test_support.TESTFN)
1029
Greg Ward55493222003-04-21 02:41:25 +00001030 class MyOption (Option):
Greg Wardab05edc2006-04-23 03:47:58 +00001031 def check_file(option, opt, value):
Greg Ward55493222003-04-21 02:41:25 +00001032 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
Greg Wardab05edc2006-04-23 03:47:58 +00001042 def test_filetype_ok(self):
Greg Ward55493222003-04-21 02:41:25 +00001043 open(test_support.TESTFN, "w").close()
1044 self.assertParseOK(["--file", test_support.TESTFN, "-afoo"],
1045 {'file': test_support.TESTFN, 'a': 'foo'},
1046 [])
1047
Greg Wardab05edc2006-04-23 03:47:58 +00001048 def test_filetype_noexist(self):
Greg Ward55493222003-04-21 02:41:25 +00001049 self.assertParseFail(["--file", test_support.TESTFN, "-afoo"],
1050 "%s: file does not exist" %
1051 test_support.TESTFN)
1052
Greg Wardab05edc2006-04-23 03:47:58 +00001053 def test_filetype_notfile(self):
Greg Ward55493222003-04-21 02:41:25 +00001054 os.mkdir(test_support.TESTFN)
1055 self.assertParseFail(["--file", test_support.TESTFN, "-afoo"],
1056 "%s: not a regular file" %
1057 test_support.TESTFN)
Greg Wardab05edc2006-04-23 03:47:58 +00001058
Greg Ward55493222003-04-21 02:41:25 +00001059
1060class TestExtendAddActions(BaseTest):
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 MyOption (Option):
1067 ACTIONS = Option.ACTIONS + ("extend",)
1068 STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",)
1069 TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",)
1070
Greg Wardab05edc2006-04-23 03:47:58 +00001071 def take_action(self, action, dest, opt, value, values, parser):
Greg Ward55493222003-04-21 02:41:25 +00001072 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
1091class TestCallback(BaseTest):
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, [])
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001109 self.assertTrue(parser_ is self.parser)
1110 self.assertTrue(value is None)
Greg Ward55493222003-04-21 02:41:25 +00001111 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"])
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001117 self.assertTrue(parser_ is self.parser)
Greg Ward55493222003-04-21 02:41:25 +00001118 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
Greg Wardeba20e62004-07-31 16:15:44 +00001130 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
Greg Wardab05edc2006-04-23 03:47:58 +00001140 expected_help = ("Options:\n"
Greg Wardeba20e62004-07-31 16:15:44 +00001141 " -t TEST, --test=TEST foo\n")
1142 self.assertHelp(parser, expected_help)
1143
1144
1145class TestCallbackExtraArgs(BaseTest):
Greg Ward55493222003-04-21 02:41:25 +00001146 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
Greg Wardab05edc2006-04-23 03:47:58 +00001153 def process_tuple(self, option, opt, value, parser_, len, type):
Greg Ward55493222003-04-21 02:41:25 +00001154 self.assertEqual(len, 3)
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001155 self.assertTrue(type is int)
Greg Ward55493222003-04-21 02:41:25 +00001156
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
Greg Wardeba20e62004-07-31 16:15:44 +00001170class TestCallbackMeddleArgs(BaseTest):
Greg Ward55493222003-04-21 02:41:25 +00001171 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
Greg Wardab05edc2006-04-23 03:47:58 +00001178 def process_n(self, option, opt, value, parser_):
Greg Ward55493222003-04-21 02:41:25 +00001179 # 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
Greg Wardeba20e62004-07-31 16:15:44 +00001199class TestCallbackManyArgs(BaseTest):
Greg Ward55493222003-04-21 02:41:25 +00001200 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
Greg Wardab05edc2006-04-23 03:47:58 +00001207 def process_many(self, option, opt, value, parser_):
Greg Ward55493222003-04-21 02:41:25 +00001208 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"],
Greg Wardeba20e62004-07-31 16:15:44 +00001221 {"apple": None, "bob": None},
Greg Ward55493222003-04-21 02:41:25 +00001222 [])
1223
Greg Wardeba20e62004-07-31 16:15:44 +00001224class TestCallbackCheckAbbrev(BaseTest):
Greg Ward55493222003-04-21 02:41:25 +00001225 def setUp(self):
1226 self.parser = OptionParser()
1227 self.parser.add_option("--foo-bar", action="callback",
1228 callback=self.check_abbrev)
1229
Greg Wardab05edc2006-04-23 03:47:58 +00001230 def check_abbrev(self, option, opt, value, parser):
Greg Ward55493222003-04-21 02:41:25 +00001231 self.assertEqual(opt, "--foo-bar")
1232
1233 def test_abbrev_callback_expansion(self):
1234 self.assertParseOK(["--foo"], {}, [])
1235
Greg Wardeba20e62004-07-31 16:15:44 +00001236class TestCallbackVarArgs(BaseTest):
Greg Ward55493222003-04-21 02:41:25 +00001237 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")]
Greg Ward48aa84b2004-10-27 02:20:04 +00001242 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
1243 option_list=options)
Greg Ward55493222003-04-21 02:41:25 +00001244
Greg Wardab05edc2006-04-23 03:47:58 +00001245 def variable_args(self, option, opt, value, parser):
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001246 self.assertTrue(value is None)
Greg Ward55493222003-04-21 02:41:25 +00001247 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
1289class ConflictBase(BaseTest):
1290 def setUp(self):
1291 options = [make_option("-v", "--verbose", action="count",
1292 dest="verbose", help="increment verbosity")]
Greg Ward48aa84b2004-10-27 02:20:04 +00001293 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
1294 option_list=options)
Greg Ward55493222003-04-21 02:41:25 +00001295
Greg Wardab05edc2006-04-23 03:47:58 +00001296 def show_version(self, option, opt, value, parser):
Greg Ward55493222003-04-21 02:41:25 +00001297 parser.values.show_version = 1
1298
1299class TestConflict(ConflictBase):
1300 """Use the default conflict resolution for Optik 1.2: error."""
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001301 def assertTrueconflict_error(self, func):
Greg Wardeba20e62004-07-31 16:15:44 +00001302 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")
Greg Ward55493222003-04-21 02:41:25 +00001308
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):
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001313 self.assertTrueconflict_error(self.parser.add_option)
Greg Ward55493222003-04-21 02:41:25 +00001314
1315 def test_conflict_error_group(self):
1316 group = OptionGroup(self.parser, "Group 1")
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001317 self.assertTrueconflict_error(group.add_option)
Greg Ward55493222003-04-21 02:41:25 +00001318
1319 def test_no_such_conflict_handler(self):
Greg Wardeba20e62004-07-31 16:15:44 +00001320 self.assertRaises(
1321 self.parser.set_conflict_handler, ('foo',), None,
1322 ValueError, "invalid conflict_resolution value 'foo'")
Greg Ward55493222003-04-21 02:41:25 +00001323
1324
Greg Ward55493222003-04-21 02:41:25 +00001325class TestConflictResolve(ConflictBase):
1326 def setUp(self):
1327 ConflictBase.setUp(self)
1328 self.parser.set_conflict_handler("resolve")
1329 self.parser.add_option("-v", "--version", action="callback",
1330 callback=self.show_version, help="show version")
1331
1332 def test_conflict_resolve(self):
1333 v_opt = self.parser.get_option("-v")
1334 verbose_opt = self.parser.get_option("--verbose")
1335 version_opt = self.parser.get_option("--version")
1336
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001337 self.assertTrue(v_opt is version_opt)
1338 self.assertTrue(v_opt is not verbose_opt)
Greg Ward55493222003-04-21 02:41:25 +00001339 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):
Greg Ward48aa84b2004-10-27 02:20:04 +00001346 self.assertOutput(["-h"], """\
Greg Wardab05edc2006-04-23 03:47:58 +00001347Options:
Greg Ward55493222003-04-21 02:41:25 +00001348 --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
1368class TestConflictOverride(BaseTest):
1369 def setUp(self):
Greg Ward48aa84b2004-10-27 02:20:04 +00001370 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
Greg Ward55493222003-04-21 02:41:25 +00001371 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):
Greg Ward48aa84b2004-10-27 02:20:04 +00001385 self.assertOutput(["-h"], """\
Greg Wardab05edc2006-04-23 03:47:58 +00001386Options:
Greg Ward55493222003-04-21 02:41:25 +00001387 -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
Greg Wardeba20e62004-07-31 16:15:44 +00001398_expected_help_basic = """\
Greg Wardab05edc2006-04-23 03:47:58 +00001399Usage: bar.py [options]
Greg Wardeba20e62004-07-31 16:15:44 +00001400
Greg Wardab05edc2006-04-23 03:47:58 +00001401Options:
Greg Wardeba20e62004-07-31 16:15:44 +00001402 -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 = """\
Greg Wardab05edc2006-04-23 03:47:58 +00001410Usage: bar.py [options]
Greg Wardeba20e62004-07-31 16:15:44 +00001411
Greg Wardab05edc2006-04-23 03:47:58 +00001412Options:
Greg Wardeba20e62004-07-31 16:15:44 +00001413 -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 = """\
1421Usage
1422=====
1423 bar.py [options]
1424
Greg Wardab05edc2006-04-23 03:47:58 +00001425Options
Greg Wardeba20e62004-07-31 16:15:44 +00001426=======
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 = """\
Greg Wardab05edc2006-04-23 03:47:58 +00001435Usage: bar.py [options]
Greg Wardeba20e62004-07-31 16:15:44 +00001436
Greg Wardab05edc2006-04-23 03:47:58 +00001437Options:
Greg Wardeba20e62004-07-31 16:15:44 +00001438 -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
Serhiy Storchaka9f8621f2014-01-09 23:13:48 +02001447_expected_very_help_short_lines = """\
1448Usage: bar.py [options]
1449
1450Options:
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
Greg Ward55493222003-04-21 02:41:25 +00001480class TestHelp(BaseTest):
1481 def setUp(self):
Greg Wardeba20e62004-07-31 16:15:44 +00001482 self.parser = self.make_parser(80)
1483
1484 def make_parser(self, columns):
Greg Ward55493222003-04-21 02:41:25 +00001485 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 ]
Greg Ward48fae7a2006-07-23 16:05:51 +00001496
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.
Walter Dörwald4b965f62009-04-26 20:51:44 +00001501 with test_support.EnvironmentVarGuard() as env:
Walter Dörwald6733bed2009-05-01 17:35:37 +00001502 env['COLUMNS'] = str(columns)
Tim Peterse7d7caa2006-06-19 09:09:44 +00001503 return InterceptingOptionParser(option_list=options)
Greg Ward55493222003-04-21 02:41:25 +00001504
1505 def assertHelpEquals(self, expected_output):
Greg Ward0e0c9f42006-06-11 16:24:11 +00001506 if type(expected_output) is types.UnicodeType:
1507 encoding = self.parser._get_encoding(sys.stdout)
1508 expected_output = expected_output.encode(encoding, "replace")
1509
Greg Ward48aa84b2004-10-27 02:20:04 +00001510 save_argv = sys.argv[:]
1511 try:
1512 # Make optparse believe bar.py is being executed.
1513 sys.argv[0] = os.path.join("foo", "bar.py")
1514 self.assertOutput(["-h"], expected_output)
1515 finally:
1516 sys.argv[:] = save_argv
Greg Ward55493222003-04-21 02:41:25 +00001517
1518 def test_help(self):
Greg Wardeba20e62004-07-31 16:15:44 +00001519 self.assertHelpEquals(_expected_help_basic)
Greg Ward55493222003-04-21 02:41:25 +00001520
1521 def test_help_old_usage(self):
Greg Wardab05edc2006-04-23 03:47:58 +00001522 self.parser.set_usage("Usage: %prog [options]")
Greg Wardeba20e62004-07-31 16:15:44 +00001523 self.assertHelpEquals(_expected_help_basic)
Greg Ward55493222003-04-21 02:41:25 +00001524
1525 def test_help_long_opts_first(self):
1526 self.parser.formatter.short_first = 0
Greg Wardeba20e62004-07-31 16:15:44 +00001527 self.assertHelpEquals(_expected_help_long_opts_first)
Greg Ward55493222003-04-21 02:41:25 +00001528
1529 def test_help_title_formatter(self):
Walter Dörwald4b965f62009-04-26 20:51:44 +00001530 with test_support.EnvironmentVarGuard() as env:
Walter Dörwald6733bed2009-05-01 17:35:37 +00001531 env["COLUMNS"] = "80"
Guido van Rossum0567ba22007-01-14 03:46:33 +00001532 self.parser.formatter = TitledHelpFormatter()
1533 self.assertHelpEquals(_expected_help_title_formatter)
Greg Ward55493222003-04-21 02:41:25 +00001534
Greg Wardeba20e62004-07-31 16:15:44 +00001535 def test_wrap_columns(self):
1536 # Ensure that wrapping respects $COLUMNS environment variable.
1537 # Need to reconstruct the parser, since that's the only time
1538 # we look at $COLUMNS.
1539 self.parser = self.make_parser(60)
1540 self.assertHelpEquals(_expected_help_short_lines)
Serhiy Storchaka9f8621f2014-01-09 23:13:48 +02001541 self.parser = self.make_parser(0)
1542 self.assertHelpEquals(_expected_very_help_short_lines)
Greg Ward55493222003-04-21 02:41:25 +00001543
Greg Ward0e0c9f42006-06-11 16:24:11 +00001544 def test_help_unicode(self):
1545 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
1546 self.parser.add_option("-a", action="store_true", help=u"ol\u00E9!")
1547 expect = u"""\
1548Options:
1549 -h, --help show this help message and exit
1550 -a ol\u00E9!
1551"""
1552 self.assertHelpEquals(expect)
1553
1554 def test_help_unicode_description(self):
1555 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
1556 description=u"ol\u00E9!")
1557 expect = u"""\
1558ol\u00E9!
1559
1560Options:
1561 -h, --help show this help message and exit
1562"""
1563 self.assertHelpEquals(expect)
1564
Greg Ward55493222003-04-21 02:41:25 +00001565 def test_help_description_groups(self):
1566 self.parser.set_description(
Greg Wardeba20e62004-07-31 16:15:44 +00001567 "This is the program description for %prog. %prog has "
Greg Ward55493222003-04-21 02:41:25 +00001568 "an option group as well as single options.")
1569
1570 group = OptionGroup(
1571 self.parser, "Dangerous Options",
1572 "Caution: use of these options is at your own risk. "
1573 "It is believed that some of them bite.")
1574 group.add_option("-g", action="store_true", help="Group option.")
1575 self.parser.add_option_group(group)
1576
Greg Wardab05edc2006-04-23 03:47:58 +00001577 expect = """\
1578Usage: bar.py [options]
Greg Ward55493222003-04-21 02:41:25 +00001579
Greg Wardeba20e62004-07-31 16:15:44 +00001580This is the program description for bar.py. bar.py has an option group as
1581well as single options.
1582
Greg Wardab05edc2006-04-23 03:47:58 +00001583Options:
Greg Wardeba20e62004-07-31 16:15:44 +00001584 -a APPLE throw APPLEs at basket
1585 -b NUM, --boo=NUM shout "boo!" NUM times (in order to frighten away all the
1586 evil spirits that cause trouble and mayhem)
1587 --foo=FOO store FOO in the foo list for later fooing
1588 -h, --help show this help message and exit
Greg Ward55493222003-04-21 02:41:25 +00001589
1590 Dangerous Options:
Greg Wardeba20e62004-07-31 16:15:44 +00001591 Caution: use of these options is at your own risk. It is believed
1592 that some of them bite.
1593
1594 -g Group option.
Greg Wardab05edc2006-04-23 03:47:58 +00001595"""
Greg Ward55493222003-04-21 02:41:25 +00001596
Greg Wardab05edc2006-04-23 03:47:58 +00001597 self.assertHelpEquals(expect)
Greg Wardeba20e62004-07-31 16:15:44 +00001598
Greg Wardab05edc2006-04-23 03:47:58 +00001599 self.parser.epilog = "Please report bugs to /dev/null."
1600 self.assertHelpEquals(expect + "\nPlease report bugs to /dev/null.\n")
Tim Peters10d59f32004-10-27 02:43:25 +00001601
Greg Wardeba20e62004-07-31 16:15:44 +00001602
Greg Ward55493222003-04-21 02:41:25 +00001603class TestMatchAbbrev(BaseTest):
1604 def test_match_abbrev(self):
1605 self.assertEqual(_match_abbrev("--f",
1606 {"--foz": None,
1607 "--foo": None,
1608 "--fie": None,
1609 "--f": None}),
1610 "--f")
1611
1612 def test_match_abbrev_error(self):
1613 s = "--f"
1614 wordmap = {"--foz": None, "--foo": None, "--fie": None}
Greg Wardeba20e62004-07-31 16:15:44 +00001615 self.assertRaises(
1616 _match_abbrev, (s, wordmap), None,
Armin Rigoa3f09272006-05-28 19:13:17 +00001617 BadOptionError, "ambiguous option: --f (--fie, --foo, --foz?)")
Greg Wardeba20e62004-07-31 16:15:44 +00001618
1619
Greg Wardab05edc2006-04-23 03:47:58 +00001620class TestParseNumber(BaseTest):
1621 def setUp(self):
1622 self.parser = InterceptingOptionParser()
1623 self.parser.add_option("-n", type=int)
1624 self.parser.add_option("-l", type=long)
1625
1626 def test_parse_num_fail(self):
1627 self.assertRaises(
1628 _parse_num, ("", int), {},
1629 ValueError,
1630 re.compile(r"invalid literal for int().*: '?'?"))
1631 self.assertRaises(
1632 _parse_num, ("0xOoops", long), {},
1633 ValueError,
1634 re.compile(r"invalid literal for long().*: '?0xOoops'?"))
1635
1636 def test_parse_num_ok(self):
1637 self.assertEqual(_parse_num("0", int), 0)
1638 self.assertEqual(_parse_num("0x10", int), 16)
1639 self.assertEqual(_parse_num("0XA", long), 10L)
1640 self.assertEqual(_parse_num("010", long), 8L)
1641 self.assertEqual(_parse_num("0b11", int), 3)
1642 self.assertEqual(_parse_num("0b", long), 0L)
1643
1644 def test_numeric_options(self):
1645 self.assertParseOK(["-n", "42", "-l", "0x20"],
1646 { "n": 42, "l": 0x20 }, [])
1647 self.assertParseOK(["-n", "0b0101", "-l010"],
1648 { "n": 5, "l": 8 }, [])
1649 self.assertParseFail(["-n008"],
1650 "option -n: invalid integer value: '008'")
1651 self.assertParseFail(["-l0b0123"],
1652 "option -l: invalid long integer value: '0b0123'")
1653 self.assertParseFail(["-l", "0x12x"],
1654 "option -l: invalid long integer value: '0x12x'")
1655
1656
Greg Ward55493222003-04-21 02:41:25 +00001657def test_main():
Collin Winterc2898c52007-04-25 17:29:52 +00001658 test_support.run_unittest(__name__)
Greg Ward55493222003-04-21 02:41:25 +00001659
1660if __name__ == '__main__':
Collin Winterc2898c52007-04-25 17:29:52 +00001661 test_main()