blob: 437fdd2be8d85ac46aa12d328bfb08fabc005a86 [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
Greg Ward48aa84b2004-10-27 02:20:04 +000027class InterceptedError(Exception):
28 def __init__(self,
29 error_message=None,
30 exit_status=None,
31 exit_message=None):
32 self.error_message = error_message
33 self.exit_status = exit_status
34 self.exit_message = exit_message
35
36 def __str__(self):
37 return self.error_message or self.exit_message or "intercepted error"
38
39class InterceptingOptionParser(OptionParser):
40 def exit(self, status=0, msg=None):
41 raise InterceptedError(exit_status=status, exit_message=msg)
42
43 def error(self, msg):
44 raise InterceptedError(error_message=msg)
45
Greg Ward55493222003-04-21 02:41:25 +000046
47class BaseTest(unittest.TestCase):
48 def assertParseOK(self, args, expected_opts, expected_positional_args):
49 """Assert the options are what we expected when parsing arguments.
50
51 Otherwise, fail with a nicely formatted message.
52
53 Keyword arguments:
54 args -- A list of arguments to parse with OptionParser.
55 expected_opts -- The options expected.
56 expected_positional_args -- The positional arguments expected.
57
58 Returns the options and positional args for further testing.
59 """
60
61 (options, positional_args) = self.parser.parse_args(args)
62 optdict = vars(options)
63
64 self.assertEqual(optdict, expected_opts,
65 """
66Options are %(optdict)s.
67Should be %(expected_opts)s.
68Args were %(args)s.""" % locals())
69
70 self.assertEqual(positional_args, expected_positional_args,
71 """
72Positional arguments are %(positional_args)s.
73Should be %(expected_positional_args)s.
74Args were %(args)s.""" % locals ())
75
76 return (options, positional_args)
77
Greg Wardeba20e62004-07-31 16:15:44 +000078 def assertRaises(self,
79 func,
80 args,
81 kwargs,
82 expected_exception,
Greg Ward48aa84b2004-10-27 02:20:04 +000083 expected_message):
84 """
85 Assert that the expected exception is raised when calling a
86 function, and that the right error message is included with
87 that exception.
Greg Ward55493222003-04-21 02:41:25 +000088
Greg Wardeba20e62004-07-31 16:15:44 +000089 Arguments:
90 func -- the function to call
91 args -- positional arguments to `func`
92 kwargs -- keyword arguments to `func`
93 expected_exception -- exception that should be raised
Thomas Wouters477c8d52006-05-27 19:21:47 +000094 expected_message -- expected exception message (or pattern
95 if a compiled regex object)
Greg Ward55493222003-04-21 02:41:25 +000096
97 Returns the exception raised for further testing.
98 """
Greg Wardeba20e62004-07-31 16:15:44 +000099 if args is None:
100 args = ()
101 if kwargs is None:
102 kwargs = {}
Greg Ward55493222003-04-21 02:41:25 +0000103
104 try:
Greg Ward48aa84b2004-10-27 02:20:04 +0000105 func(*args, **kwargs)
Guido van Rossumb940e112007-01-10 16:19:56 +0000106 except expected_exception as err:
Greg Ward48aa84b2004-10-27 02:20:04 +0000107 actual_message = str(err)
Serhiy Storchaka0b5e61d2017-10-04 20:09:49 +0300108 if isinstance(expected_message, re.Pattern):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000109 self.assertTrue(expected_message.search(actual_message),
Greg Ward48aa84b2004-10-27 02:20:04 +0000110 """\
Thomas Wouters477c8d52006-05-27 19:21:47 +0000111expected exception message pattern:
112/%s/
Greg Ward48aa84b2004-10-27 02:20:04 +0000113actual exception message:
Thomas Wouters477c8d52006-05-27 19:21:47 +0000114'''%s'''
115""" % (expected_message.pattern, actual_message))
116 else:
117 self.assertEqual(actual_message,
118 expected_message,
119 """\
120expected exception message:
121'''%s'''
122actual exception message:
123'''%s'''
124""" % (expected_message, actual_message))
Greg Ward55493222003-04-21 02:41:25 +0000125
126 return err
127 else:
Greg Wardeba20e62004-07-31 16:15:44 +0000128 self.fail("""expected exception %(expected_exception)s not raised
129called %(func)r
130with args %(args)r
131and kwargs %(kwargs)r
132""" % locals ())
Greg Ward55493222003-04-21 02:41:25 +0000133
Greg Wardeba20e62004-07-31 16:15:44 +0000134
Greg Ward55493222003-04-21 02:41:25 +0000135 # -- Assertions used in more than one class --------------------
136
137 def assertParseFail(self, cmdline_args, expected_output):
Greg Ward48aa84b2004-10-27 02:20:04 +0000138 """
139 Assert the parser fails with the expected message. Caller
140 must ensure that self.parser is an InterceptingOptionParser.
141 """
Tim Peters579f7352004-07-31 21:14:28 +0000142 try:
Greg Ward48aa84b2004-10-27 02:20:04 +0000143 self.parser.parse_args(cmdline_args)
Guido van Rossumb940e112007-01-10 16:19:56 +0000144 except InterceptedError as err:
Greg Ward48aa84b2004-10-27 02:20:04 +0000145 self.assertEqual(err.error_message, expected_output)
146 else:
147 self.assertFalse("expected parse failure")
Greg Ward55493222003-04-21 02:41:25 +0000148
Greg Ward48aa84b2004-10-27 02:20:04 +0000149 def assertOutput(self,
150 cmdline_args,
151 expected_output,
152 expected_status=0,
153 expected_error=None):
Greg Ward55493222003-04-21 02:41:25 +0000154 """Assert the parser prints the expected output on stdout."""
Tim Peters579f7352004-07-31 21:14:28 +0000155 save_stdout = sys.stdout
156 try:
Greg Ward48aa84b2004-10-27 02:20:04 +0000157 try:
158 sys.stdout = StringIO()
159 self.parser.parse_args(cmdline_args)
160 finally:
161 output = sys.stdout.getvalue()
162 sys.stdout = save_stdout
Greg Ward55493222003-04-21 02:41:25 +0000163
Guido van Rossumb940e112007-01-10 16:19:56 +0000164 except InterceptedError as err:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000165 self.assertTrue(
Guido van Rossum13257902007-06-07 23:15:56 +0000166 isinstance(output, str),
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000167 "expected output to be an ordinary string, not %r"
168 % type(output))
169
Thomas Wouters477c8d52006-05-27 19:21:47 +0000170 if output != expected_output:
171 self.fail("expected: \n'''\n" + expected_output +
172 "'''\nbut got \n'''\n" + output + "'''")
Greg Ward48aa84b2004-10-27 02:20:04 +0000173 self.assertEqual(err.exit_status, expected_status)
174 self.assertEqual(err.exit_message, expected_error)
175 else:
176 self.assertFalse("expected parser.exit()")
177
178 def assertTypeError(self, func, expected_message, *args):
179 """Assert that TypeError is raised when executing func."""
180 self.assertRaises(func, args, None, TypeError, expected_message)
Greg Wardeba20e62004-07-31 16:15:44 +0000181
182 def assertHelp(self, parser, expected_help):
183 actual_help = parser.format_help()
184 if actual_help != expected_help:
185 raise self.failureException(
186 'help text failure; expected:\n"' +
187 expected_help + '"; got:\n"' +
188 actual_help + '"\n')
Greg Ward55493222003-04-21 02:41:25 +0000189
190# -- Test make_option() aka Option -------------------------------------
191
Greg Ward48aa84b2004-10-27 02:20:04 +0000192# It's not necessary to test correct options here. All the tests in the
Greg Ward55493222003-04-21 02:41:25 +0000193# parser.parse_args() section deal with those, because they're needed
Greg Ward48aa84b2004-10-27 02:20:04 +0000194# there.
Greg Ward55493222003-04-21 02:41:25 +0000195
196class TestOptionChecks(BaseTest):
197 def setUp(self):
198 self.parser = OptionParser(usage=SUPPRESS_USAGE)
199
Greg Ward48aa84b2004-10-27 02:20:04 +0000200 def assertOptionError(self, expected_message, args=[], kwargs={}):
Greg Wardeba20e62004-07-31 16:15:44 +0000201 self.assertRaises(make_option, args, kwargs,
Greg Ward48aa84b2004-10-27 02:20:04 +0000202 OptionError, expected_message)
Greg Ward55493222003-04-21 02:41:25 +0000203
204 def test_opt_string_empty(self):
205 self.assertTypeError(make_option,
206 "at least one option string must be supplied")
207
208 def test_opt_string_too_short(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000209 self.assertOptionError(
210 "invalid option string 'b': must be at least two characters long",
211 ["b"])
Greg Ward55493222003-04-21 02:41:25 +0000212
213 def test_opt_string_short_invalid(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000214 self.assertOptionError(
215 "invalid short option string '--': must be "
216 "of the form -x, (x any non-dash char)",
217 ["--"])
Greg Ward55493222003-04-21 02:41:25 +0000218
219 def test_opt_string_long_invalid(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000220 self.assertOptionError(
221 "invalid long option string '---': "
222 "must start with --, followed by non-dash",
223 ["---"])
Greg Ward55493222003-04-21 02:41:25 +0000224
225 def test_attr_invalid(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000226 self.assertOptionError(
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000227 "option -b: invalid keyword arguments: bar, foo",
Greg Ward48aa84b2004-10-27 02:20:04 +0000228 ["-b"], {'foo': None, 'bar': None})
Greg Ward55493222003-04-21 02:41:25 +0000229
230 def test_action_invalid(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000231 self.assertOptionError(
232 "option -b: invalid action: 'foo'",
233 ["-b"], {'action': 'foo'})
Greg Ward55493222003-04-21 02:41:25 +0000234
235 def test_type_invalid(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000236 self.assertOptionError(
237 "option -b: invalid option type: 'foo'",
238 ["-b"], {'type': 'foo'})
239 self.assertOptionError(
240 "option -b: invalid option type: 'tuple'",
241 ["-b"], {'type': tuple})
Greg Ward55493222003-04-21 02:41:25 +0000242
243 def test_no_type_for_action(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000244 self.assertOptionError(
245 "option -b: must not supply a type for action 'count'",
246 ["-b"], {'action': 'count', 'type': 'int'})
Greg Ward55493222003-04-21 02:41:25 +0000247
248 def test_no_choices_list(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000249 self.assertOptionError(
250 "option -b/--bad: must supply a list of "
251 "choices for type 'choice'",
252 ["-b", "--bad"], {'type': "choice"})
Greg Ward55493222003-04-21 02:41:25 +0000253
254 def test_bad_choices_list(self):
255 typename = type('').__name__
Greg Ward48aa84b2004-10-27 02:20:04 +0000256 self.assertOptionError(
257 "option -b/--bad: choices must be a list of "
258 "strings ('%s' supplied)" % typename,
259 ["-b", "--bad"],
260 {'type': "choice", 'choices':"bad choices"})
Greg Ward55493222003-04-21 02:41:25 +0000261
262 def test_no_choices_for_type(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000263 self.assertOptionError(
264 "option -b: must not supply choices for type 'int'",
265 ["-b"], {'type': 'int', 'choices':"bad"})
Greg Ward55493222003-04-21 02:41:25 +0000266
267 def test_no_const_for_action(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000268 self.assertOptionError(
269 "option -b: 'const' must not be supplied for action 'store'",
270 ["-b"], {'action': 'store', 'const': 1})
Greg Ward55493222003-04-21 02:41:25 +0000271
272 def test_no_nargs_for_action(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000273 self.assertOptionError(
274 "option -b: 'nargs' must not be supplied for action 'count'",
275 ["-b"], {'action': 'count', 'nargs': 2})
Greg Ward55493222003-04-21 02:41:25 +0000276
277 def test_callback_not_callable(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000278 self.assertOptionError(
279 "option -b: callback not callable: 'foo'",
280 ["-b"], {'action': 'callback',
281 'callback': 'foo'})
Greg Ward55493222003-04-21 02:41:25 +0000282
283 def dummy(self):
284 pass
285
286 def test_callback_args_no_tuple(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000287 self.assertOptionError(
288 "option -b: callback_args, if supplied, "
289 "must be a tuple: not 'foo'",
290 ["-b"], {'action': 'callback',
291 'callback': self.dummy,
292 'callback_args': 'foo'})
Greg Ward55493222003-04-21 02:41:25 +0000293
294 def test_callback_kwargs_no_dict(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000295 self.assertOptionError(
296 "option -b: callback_kwargs, if supplied, "
297 "must be a dict: not 'foo'",
298 ["-b"], {'action': 'callback',
299 'callback': self.dummy,
300 'callback_kwargs': 'foo'})
Greg Ward55493222003-04-21 02:41:25 +0000301
302 def test_no_callback_for_action(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000303 self.assertOptionError(
304 "option -b: callback supplied ('foo') for non-callback option",
305 ["-b"], {'action': 'store',
306 'callback': 'foo'})
Greg Ward55493222003-04-21 02:41:25 +0000307
308 def test_no_callback_args_for_action(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000309 self.assertOptionError(
310 "option -b: callback_args supplied for non-callback option",
311 ["-b"], {'action': 'store',
312 'callback_args': 'foo'})
Greg Ward55493222003-04-21 02:41:25 +0000313
314 def test_no_callback_kwargs_for_action(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000315 self.assertOptionError(
316 "option -b: callback_kwargs supplied for non-callback option",
317 ["-b"], {'action': 'store',
318 'callback_kwargs': 'foo'})
Greg Ward55493222003-04-21 02:41:25 +0000319
R David Murray6159e092012-07-15 20:12:24 -0400320 def test_no_single_dash(self):
321 self.assertOptionError(
322 "invalid long option string '-debug': "
323 "must start with --, followed by non-dash",
324 ["-debug"])
325
326 self.assertOptionError(
327 "option -d: invalid long option string '-debug': must start with"
328 " --, followed by non-dash",
329 ["-d", "-debug"])
330
331 self.assertOptionError(
332 "invalid long option string '-debug': "
333 "must start with --, followed by non-dash",
334 ["-debug", "--debug"])
335
Greg Ward55493222003-04-21 02:41:25 +0000336class TestOptionParser(BaseTest):
337 def setUp(self):
338 self.parser = OptionParser()
339 self.parser.add_option("-v", "--verbose", "-n", "--noisy",
340 action="store_true", dest="verbose")
341 self.parser.add_option("-q", "--quiet", "--silent",
342 action="store_false", dest="verbose")
343
344 def test_add_option_no_Option(self):
345 self.assertTypeError(self.parser.add_option,
346 "not an Option instance: None", None)
347
348 def test_add_option_invalid_arguments(self):
349 self.assertTypeError(self.parser.add_option,
350 "invalid arguments", None, None)
351
352 def test_get_option(self):
353 opt1 = self.parser.get_option("-v")
Ezio Melottie9615932010-01-24 19:26:24 +0000354 self.assertIsInstance(opt1, Option)
Greg Ward55493222003-04-21 02:41:25 +0000355 self.assertEqual(opt1._short_opts, ["-v", "-n"])
356 self.assertEqual(opt1._long_opts, ["--verbose", "--noisy"])
357 self.assertEqual(opt1.action, "store_true")
358 self.assertEqual(opt1.dest, "verbose")
359
360 def test_get_option_equals(self):
361 opt1 = self.parser.get_option("-v")
362 opt2 = self.parser.get_option("--verbose")
363 opt3 = self.parser.get_option("-n")
364 opt4 = self.parser.get_option("--noisy")
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000365 self.assertTrue(opt1 is opt2 is opt3 is opt4)
Greg Ward55493222003-04-21 02:41:25 +0000366
367 def test_has_option(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000368 self.assertTrue(self.parser.has_option("-v"))
369 self.assertTrue(self.parser.has_option("--verbose"))
Greg Ward55493222003-04-21 02:41:25 +0000370
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000371 def assertTrueremoved(self):
372 self.assertTrue(self.parser.get_option("-v") is None)
373 self.assertTrue(self.parser.get_option("--verbose") is None)
374 self.assertTrue(self.parser.get_option("-n") is None)
375 self.assertTrue(self.parser.get_option("--noisy") is None)
Greg Ward55493222003-04-21 02:41:25 +0000376
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000377 self.assertFalse(self.parser.has_option("-v"))
378 self.assertFalse(self.parser.has_option("--verbose"))
379 self.assertFalse(self.parser.has_option("-n"))
380 self.assertFalse(self.parser.has_option("--noisy"))
Greg Ward55493222003-04-21 02:41:25 +0000381
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000382 self.assertTrue(self.parser.has_option("-q"))
383 self.assertTrue(self.parser.has_option("--silent"))
Greg Ward55493222003-04-21 02:41:25 +0000384
385 def test_remove_short_opt(self):
386 self.parser.remove_option("-n")
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000387 self.assertTrueremoved()
Greg Ward55493222003-04-21 02:41:25 +0000388
389 def test_remove_long_opt(self):
390 self.parser.remove_option("--verbose")
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000391 self.assertTrueremoved()
Greg Ward55493222003-04-21 02:41:25 +0000392
393 def test_remove_nonexistent(self):
Greg Wardeba20e62004-07-31 16:15:44 +0000394 self.assertRaises(self.parser.remove_option, ('foo',), None,
395 ValueError, "no such option 'foo'")
396
Andrew Kuchling45278a82014-04-15 16:44:43 -0400397 @support.impl_detail('Relies on sys.getrefcount', cpython=True)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000398 def test_refleak(self):
399 # If an OptionParser is carrying around a reference to a large
400 # object, various cycles can prevent it from being GC'd in
401 # a timely fashion. destroy() breaks the cycles to ensure stuff
402 # can be cleaned up.
403 big_thing = [42]
404 refcount = sys.getrefcount(big_thing)
405 parser = OptionParser()
406 parser.add_option("-a", "--aaarggh")
407 parser.big_thing = big_thing
408
409 parser.destroy()
410 #self.assertEqual(refcount, sys.getrefcount(big_thing))
411 del parser
412 self.assertEqual(refcount, sys.getrefcount(big_thing))
413
414
Greg Ward48aa84b2004-10-27 02:20:04 +0000415class TestOptionValues(BaseTest):
416 def setUp(self):
417 pass
418
419 def test_basics(self):
420 values = Values()
421 self.assertEqual(vars(values), {})
422 self.assertEqual(values, {})
423 self.assertNotEqual(values, {"foo": "bar"})
424 self.assertNotEqual(values, "")
425
426 dict = {"foo": "bar", "baz": 42}
427 values = Values(defaults=dict)
428 self.assertEqual(vars(values), dict)
429 self.assertEqual(values, dict)
430 self.assertNotEqual(values, {"foo": "bar"})
431 self.assertNotEqual(values, {})
432 self.assertNotEqual(values, "")
433 self.assertNotEqual(values, [])
434
435
Greg Wardeba20e62004-07-31 16:15:44 +0000436class TestTypeAliases(BaseTest):
437 def setUp(self):
438 self.parser = OptionParser()
439
Thomas Wouters477c8d52006-05-27 19:21:47 +0000440 def test_str_aliases_string(self):
441 self.parser.add_option("-s", type="str")
Ezio Melottib3aedd42010-11-20 19:04:17 +0000442 self.assertEqual(self.parser.get_option("-s").type, "string")
Thomas Wouters477c8d52006-05-27 19:21:47 +0000443
Guido van Rossum13257902007-06-07 23:15:56 +0000444 def test_type_object(self):
Thomas Wouters477c8d52006-05-27 19:21:47 +0000445 self.parser.add_option("-s", type=str)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000446 self.assertEqual(self.parser.get_option("-s").type, "string")
Thomas Wouters477c8d52006-05-27 19:21:47 +0000447 self.parser.add_option("-x", type=int)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000448 self.assertEqual(self.parser.get_option("-x").type, "int")
Thomas Wouters477c8d52006-05-27 19:21:47 +0000449
Greg Wardeba20e62004-07-31 16:15:44 +0000450
451# Custom type for testing processing of default values.
452_time_units = { 's' : 1, 'm' : 60, 'h' : 60*60, 'd' : 60*60*24 }
453
454def _check_duration(option, opt, value):
455 try:
456 if value[-1].isdigit():
457 return int(value)
458 else:
459 return int(value[:-1]) * _time_units[value[-1]]
Georg Brandl89fad142010-03-14 10:23:39 +0000460 except (ValueError, IndexError):
Greg Wardeba20e62004-07-31 16:15:44 +0000461 raise OptionValueError(
462 'option %s: invalid duration: %r' % (opt, value))
463
464class DurationOption(Option):
465 TYPES = Option.TYPES + ('duration',)
466 TYPE_CHECKER = copy.copy(Option.TYPE_CHECKER)
467 TYPE_CHECKER['duration'] = _check_duration
468
469class TestDefaultValues(BaseTest):
470 def setUp(self):
471 self.parser = OptionParser()
472 self.parser.add_option("-v", "--verbose", default=True)
473 self.parser.add_option("-q", "--quiet", dest='verbose')
474 self.parser.add_option("-n", type="int", default=37)
475 self.parser.add_option("-m", type="int")
476 self.parser.add_option("-s", default="foo")
477 self.parser.add_option("-t")
478 self.parser.add_option("-u", default=None)
479 self.expected = { 'verbose': True,
480 'n': 37,
481 'm': None,
482 's': "foo",
483 't': None,
484 'u': None }
485
486 def test_basic_defaults(self):
487 self.assertEqual(self.parser.get_default_values(), self.expected)
488
489 def test_mixed_defaults_post(self):
490 self.parser.set_defaults(n=42, m=-100)
491 self.expected.update({'n': 42, 'm': -100})
492 self.assertEqual(self.parser.get_default_values(), self.expected)
493
494 def test_mixed_defaults_pre(self):
495 self.parser.set_defaults(x="barf", y="blah")
496 self.parser.add_option("-x", default="frob")
497 self.parser.add_option("-y")
498
499 self.expected.update({'x': "frob", 'y': "blah"})
500 self.assertEqual(self.parser.get_default_values(), self.expected)
501
502 self.parser.remove_option("-y")
503 self.parser.add_option("-y", default=None)
504 self.expected.update({'y': None})
505 self.assertEqual(self.parser.get_default_values(), self.expected)
506
507 def test_process_default(self):
508 self.parser.option_class = DurationOption
509 self.parser.add_option("-d", type="duration", default=300)
510 self.parser.add_option("-e", type="duration", default="6m")
511 self.parser.set_defaults(n="42")
512 self.expected.update({'d': 300, 'e': 360, 'n': 42})
513 self.assertEqual(self.parser.get_default_values(), self.expected)
514
515 self.parser.set_process_default_values(False)
516 self.expected.update({'d': 300, 'e': "6m", 'n': "42"})
517 self.assertEqual(self.parser.get_default_values(), self.expected)
518
519
520class TestProgName(BaseTest):
521 """
522 Test that %prog expands to the right thing in usage, version,
523 and help strings.
524 """
525
526 def assertUsage(self, parser, expected_usage):
527 self.assertEqual(parser.get_usage(), expected_usage)
528
529 def assertVersion(self, parser, expected_version):
530 self.assertEqual(parser.get_version(), expected_version)
531
532
533 def test_default_progname(self):
534 # Make sure that program name taken from sys.argv[0] by default.
Tim Peters579f7352004-07-31 21:14:28 +0000535 save_argv = sys.argv[:]
536 try:
Greg Ward48aa84b2004-10-27 02:20:04 +0000537 sys.argv[0] = os.path.join("foo", "bar", "baz.py")
Thomas Wouters477c8d52006-05-27 19:21:47 +0000538 parser = OptionParser("%prog ...", version="%prog 1.2")
539 expected_usage = "Usage: baz.py ...\n"
Tim Peters579f7352004-07-31 21:14:28 +0000540 self.assertUsage(parser, expected_usage)
541 self.assertVersion(parser, "baz.py 1.2")
542 self.assertHelp(parser,
Greg Ward48aa84b2004-10-27 02:20:04 +0000543 expected_usage + "\n" +
Thomas Wouters477c8d52006-05-27 19:21:47 +0000544 "Options:\n"
Greg Ward48aa84b2004-10-27 02:20:04 +0000545 " --version show program's version number and exit\n"
546 " -h, --help show this help message and exit\n")
Tim Peters579f7352004-07-31 21:14:28 +0000547 finally:
548 sys.argv[:] = save_argv
Greg Wardeba20e62004-07-31 16:15:44 +0000549
550 def test_custom_progname(self):
551 parser = OptionParser(prog="thingy",
552 version="%prog 0.1",
553 usage="%prog arg arg")
554 parser.remove_option("-h")
555 parser.remove_option("--version")
Thomas Wouters477c8d52006-05-27 19:21:47 +0000556 expected_usage = "Usage: thingy arg arg\n"
Greg Wardeba20e62004-07-31 16:15:44 +0000557 self.assertUsage(parser, expected_usage)
558 self.assertVersion(parser, "thingy 0.1")
559 self.assertHelp(parser, expected_usage + "\n")
560
561
562class TestExpandDefaults(BaseTest):
563 def setUp(self):
564 self.parser = OptionParser(prog="test")
565 self.help_prefix = """\
Thomas Wouters477c8d52006-05-27 19:21:47 +0000566Usage: test [options]
Greg Wardeba20e62004-07-31 16:15:44 +0000567
Thomas Wouters477c8d52006-05-27 19:21:47 +0000568Options:
Greg Wardeba20e62004-07-31 16:15:44 +0000569 -h, --help show this help message and exit
570"""
571 self.file_help = "read from FILE [default: %default]"
572 self.expected_help_file = self.help_prefix + \
573 " -f FILE, --file=FILE read from FILE [default: foo.txt]\n"
574 self.expected_help_none = self.help_prefix + \
575 " -f FILE, --file=FILE read from FILE [default: none]\n"
576
577 def test_option_default(self):
578 self.parser.add_option("-f", "--file",
579 default="foo.txt",
580 help=self.file_help)
581 self.assertHelp(self.parser, self.expected_help_file)
582
583 def test_parser_default_1(self):
584 self.parser.add_option("-f", "--file",
585 help=self.file_help)
586 self.parser.set_default('file', "foo.txt")
587 self.assertHelp(self.parser, self.expected_help_file)
588
589 def test_parser_default_2(self):
590 self.parser.add_option("-f", "--file",
591 help=self.file_help)
592 self.parser.set_defaults(file="foo.txt")
593 self.assertHelp(self.parser, self.expected_help_file)
594
595 def test_no_default(self):
596 self.parser.add_option("-f", "--file",
597 help=self.file_help)
598 self.assertHelp(self.parser, self.expected_help_none)
599
600 def test_default_none_1(self):
601 self.parser.add_option("-f", "--file",
602 default=None,
603 help=self.file_help)
604 self.assertHelp(self.parser, self.expected_help_none)
Tim Peters10d59f32004-10-27 02:43:25 +0000605
Greg Wardeba20e62004-07-31 16:15:44 +0000606 def test_default_none_2(self):
607 self.parser.add_option("-f", "--file",
608 help=self.file_help)
609 self.parser.set_defaults(file=None)
610 self.assertHelp(self.parser, self.expected_help_none)
611
612 def test_float_default(self):
613 self.parser.add_option(
614 "-p", "--prob",
615 help="blow up with probability PROB [default: %default]")
616 self.parser.set_defaults(prob=0.43)
617 expected_help = self.help_prefix + \
618 " -p PROB, --prob=PROB blow up with probability PROB [default: 0.43]\n"
619 self.assertHelp(self.parser, expected_help)
620
621 def test_alt_expand(self):
622 self.parser.add_option("-f", "--file",
623 default="foo.txt",
624 help="read from FILE [default: *DEFAULT*]")
625 self.parser.formatter.default_tag = "*DEFAULT*"
626 self.assertHelp(self.parser, self.expected_help_file)
627
628 def test_no_expand(self):
629 self.parser.add_option("-f", "--file",
630 default="foo.txt",
631 help="read from %default file")
632 self.parser.formatter.default_tag = None
633 expected_help = self.help_prefix + \
634 " -f FILE, --file=FILE read from %default file\n"
635 self.assertHelp(self.parser, expected_help)
636
Greg Ward55493222003-04-21 02:41:25 +0000637
638# -- Test parser.parse_args() ------------------------------------------
639
640class TestStandard(BaseTest):
641 def setUp(self):
642 options = [make_option("-a", type="string"),
643 make_option("-b", "--boo", type="int", dest='boo'),
644 make_option("--foo", action="append")]
645
Greg Ward48aa84b2004-10-27 02:20:04 +0000646 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
647 option_list=options)
Greg Ward55493222003-04-21 02:41:25 +0000648
649 def test_required_value(self):
Éric Araujo6a1454f2011-03-20 19:59:25 +0100650 self.assertParseFail(["-a"], "-a option requires 1 argument")
Greg Ward55493222003-04-21 02:41:25 +0000651
652 def test_invalid_integer(self):
653 self.assertParseFail(["-b", "5x"],
654 "option -b: invalid integer value: '5x'")
655
656 def test_no_such_option(self):
657 self.assertParseFail(["--boo13"], "no such option: --boo13")
658
659 def test_long_invalid_integer(self):
660 self.assertParseFail(["--boo=x5"],
661 "option --boo: invalid integer value: 'x5'")
662
663 def test_empty(self):
664 self.assertParseOK([], {'a': None, 'boo': None, 'foo': None}, [])
665
666 def test_shortopt_empty_longopt_append(self):
667 self.assertParseOK(["-a", "", "--foo=blah", "--foo="],
668 {'a': "", 'boo': None, 'foo': ["blah", ""]},
669 [])
670
671 def test_long_option_append(self):
672 self.assertParseOK(["--foo", "bar", "--foo", "", "--foo=x"],
673 {'a': None,
674 'boo': None,
675 'foo': ["bar", "", "x"]},
676 [])
677
678 def test_option_argument_joined(self):
679 self.assertParseOK(["-abc"],
680 {'a': "bc", 'boo': None, 'foo': None},
681 [])
682
683 def test_option_argument_split(self):
684 self.assertParseOK(["-a", "34"],
685 {'a': "34", 'boo': None, 'foo': None},
686 [])
687
688 def test_option_argument_joined_integer(self):
689 self.assertParseOK(["-b34"],
690 {'a': None, 'boo': 34, 'foo': None},
691 [])
692
693 def test_option_argument_split_negative_integer(self):
694 self.assertParseOK(["-b", "-5"],
695 {'a': None, 'boo': -5, 'foo': None},
696 [])
697
698 def test_long_option_argument_joined(self):
699 self.assertParseOK(["--boo=13"],
700 {'a': None, 'boo': 13, 'foo': None},
701 [])
702
703 def test_long_option_argument_split(self):
704 self.assertParseOK(["--boo", "111"],
705 {'a': None, 'boo': 111, 'foo': None},
706 [])
707
708 def test_long_option_short_option(self):
709 self.assertParseOK(["--foo=bar", "-axyz"],
710 {'a': 'xyz', 'boo': None, 'foo': ["bar"]},
711 [])
712
713 def test_abbrev_long_option(self):
714 self.assertParseOK(["--f=bar", "-axyz"],
715 {'a': 'xyz', 'boo': None, 'foo': ["bar"]},
716 [])
717
718 def test_defaults(self):
719 (options, args) = self.parser.parse_args([])
720 defaults = self.parser.get_default_values()
721 self.assertEqual(vars(defaults), vars(options))
722
723 def test_ambiguous_option(self):
724 self.parser.add_option("--foz", action="store",
725 type="string", dest="foo")
Greg Ward55493222003-04-21 02:41:25 +0000726 self.assertParseFail(["--f=bar"],
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000727 "ambiguous option: --f (--foo, --foz?)")
Greg Ward55493222003-04-21 02:41:25 +0000728
729
730 def test_short_and_long_option_split(self):
731 self.assertParseOK(["-a", "xyz", "--foo", "bar"],
732 {'a': 'xyz', 'boo': None, 'foo': ["bar"]},
Victor Stinner3fa1aae2013-03-26 01:14:08 +0100733 [])
Greg Ward55493222003-04-21 02:41:25 +0000734
735 def test_short_option_split_long_option_append(self):
736 self.assertParseOK(["--foo=bar", "-b", "123", "--foo", "baz"],
737 {'a': None, 'boo': 123, 'foo': ["bar", "baz"]},
738 [])
739
740 def test_short_option_split_one_positional_arg(self):
741 self.assertParseOK(["-a", "foo", "bar"],
742 {'a': "foo", 'boo': None, 'foo': None},
Victor Stinner3fa1aae2013-03-26 01:14:08 +0100743 ["bar"])
Greg Ward55493222003-04-21 02:41:25 +0000744
745 def test_short_option_consumes_separator(self):
746 self.assertParseOK(["-a", "--", "foo", "bar"],
747 {'a': "--", 'boo': None, 'foo': None},
Victor Stinner3fa1aae2013-03-26 01:14:08 +0100748 ["foo", "bar"])
Thomas Wouters477c8d52006-05-27 19:21:47 +0000749 self.assertParseOK(["-a", "--", "--foo", "bar"],
750 {'a': "--", 'boo': None, 'foo': ["bar"]},
Victor Stinner3fa1aae2013-03-26 01:14:08 +0100751 [])
Greg Ward55493222003-04-21 02:41:25 +0000752
753 def test_short_option_joined_and_separator(self):
754 self.assertParseOK(["-ab", "--", "--foo", "bar"],
755 {'a': "b", 'boo': None, 'foo': None},
756 ["--foo", "bar"]),
757
Thomas Wouters477c8d52006-05-27 19:21:47 +0000758 def test_hyphen_becomes_positional_arg(self):
Greg Ward55493222003-04-21 02:41:25 +0000759 self.assertParseOK(["-ab", "-", "--foo", "bar"],
760 {'a': "b", 'boo': None, 'foo': ["bar"]},
761 ["-"])
762
763 def test_no_append_versus_append(self):
764 self.assertParseOK(["-b3", "-b", "5", "--foo=bar", "--foo", "baz"],
765 {'a': None, 'boo': 5, 'foo': ["bar", "baz"]},
766 [])
767
768 def test_option_consumes_optionlike_string(self):
769 self.assertParseOK(["-a", "-b3"],
770 {'a': "-b3", 'boo': None, 'foo': None},
771 [])
772
R. David Murray80972692010-06-26 00:17:12 +0000773 def test_combined_single_invalid_option(self):
774 self.parser.add_option("-t", action="store_true")
775 self.assertParseFail(["-test"],
R. David Murray76af4022010-06-26 03:34:33 +0000776 "no such option: -e")
R. David Murray80972692010-06-26 00:17:12 +0000777
Greg Ward55493222003-04-21 02:41:25 +0000778class TestBool(BaseTest):
779 def setUp(self):
780 options = [make_option("-v",
781 "--verbose",
782 action="store_true",
783 dest="verbose",
784 default=''),
785 make_option("-q",
786 "--quiet",
787 action="store_false",
788 dest="verbose")]
789 self.parser = OptionParser(option_list = options)
790
791 def test_bool_default(self):
792 self.assertParseOK([],
793 {'verbose': ''},
794 [])
795
796 def test_bool_false(self):
797 (options, args) = self.assertParseOK(["-q"],
798 {'verbose': 0},
799 [])
Georg Brandla8867b42010-07-31 21:26:40 +0000800 self.assertTrue(options.verbose is False)
Greg Ward55493222003-04-21 02:41:25 +0000801
802 def test_bool_true(self):
803 (options, args) = self.assertParseOK(["-v"],
804 {'verbose': 1},
805 [])
Georg Brandla8867b42010-07-31 21:26:40 +0000806 self.assertTrue(options.verbose is True)
Greg Ward55493222003-04-21 02:41:25 +0000807
808 def test_bool_flicker_on_and_off(self):
809 self.assertParseOK(["-qvq", "-q", "-v"],
810 {'verbose': 1},
811 [])
812
813class TestChoice(BaseTest):
814 def setUp(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000815 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
Greg Ward55493222003-04-21 02:41:25 +0000816 self.parser.add_option("-c", action="store", type="choice",
817 dest="choice", choices=["one", "two", "three"])
818
819 def test_valid_choice(self):
820 self.assertParseOK(["-c", "one", "xyz"],
821 {'choice': 'one'},
822 ["xyz"])
823
824 def test_invalid_choice(self):
825 self.assertParseFail(["-c", "four", "abc"],
826 "option -c: invalid choice: 'four' "
827 "(choose from 'one', 'two', 'three')")
828
829 def test_add_choice_option(self):
830 self.parser.add_option("-d", "--default",
831 choices=["four", "five", "six"])
832 opt = self.parser.get_option("-d")
833 self.assertEqual(opt.type, "choice")
834 self.assertEqual(opt.action, "store")
835
836class TestCount(BaseTest):
837 def setUp(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000838 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
Greg Ward55493222003-04-21 02:41:25 +0000839 self.v_opt = make_option("-v", action="count", dest="verbose")
840 self.parser.add_option(self.v_opt)
841 self.parser.add_option("--verbose", type="int", dest="verbose")
842 self.parser.add_option("-q", "--quiet",
843 action="store_const", dest="verbose", const=0)
844
845 def test_empty(self):
846 self.assertParseOK([], {'verbose': None}, [])
847
848 def test_count_one(self):
849 self.assertParseOK(["-v"], {'verbose': 1}, [])
850
851 def test_count_three(self):
852 self.assertParseOK(["-vvv"], {'verbose': 3}, [])
853
854 def test_count_three_apart(self):
855 self.assertParseOK(["-v", "-v", "-v"], {'verbose': 3}, [])
856
857 def test_count_override_amount(self):
858 self.assertParseOK(["-vvv", "--verbose=2"], {'verbose': 2}, [])
859
860 def test_count_override_quiet(self):
861 self.assertParseOK(["-vvv", "--verbose=2", "-q"], {'verbose': 0}, [])
862
863 def test_count_overriding(self):
864 self.assertParseOK(["-vvv", "--verbose=2", "-q", "-v"],
865 {'verbose': 1}, [])
866
867 def test_count_interspersed_args(self):
868 self.assertParseOK(["--quiet", "3", "-v"],
869 {'verbose': 1},
870 ["3"])
871
872 def test_count_no_interspersed_args(self):
873 self.parser.disable_interspersed_args()
874 self.assertParseOK(["--quiet", "3", "-v"],
875 {'verbose': 0},
876 ["3", "-v"])
877
878 def test_count_no_such_option(self):
879 self.assertParseFail(["-q3", "-v"], "no such option: -3")
880
881 def test_count_option_no_value(self):
882 self.assertParseFail(["--quiet=3", "-v"],
883 "--quiet option does not take a value")
884
885 def test_count_with_default(self):
886 self.parser.set_default('verbose', 0)
887 self.assertParseOK([], {'verbose':0}, [])
888
889 def test_count_overriding_default(self):
890 self.parser.set_default('verbose', 0)
891 self.assertParseOK(["-vvv", "--verbose=2", "-q", "-v"],
892 {'verbose': 1}, [])
893
Greg Ward48aa84b2004-10-27 02:20:04 +0000894class TestMultipleArgs(BaseTest):
Greg Ward55493222003-04-21 02:41:25 +0000895 def setUp(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000896 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
Greg Ward55493222003-04-21 02:41:25 +0000897 self.parser.add_option("-p", "--point",
898 action="store", nargs=3, type="float", dest="point")
899
900 def test_nargs_with_positional_args(self):
901 self.assertParseOK(["foo", "-p", "1", "2.5", "-4.3", "xyz"],
902 {'point': (1.0, 2.5, -4.3)},
903 ["foo", "xyz"])
904
905 def test_nargs_long_opt(self):
906 self.assertParseOK(["--point", "-1", "2.5", "-0", "xyz"],
907 {'point': (-1.0, 2.5, -0.0)},
908 ["xyz"])
909
910 def test_nargs_invalid_float_value(self):
911 self.assertParseFail(["-p", "1.0", "2x", "3.5"],
912 "option -p: "
913 "invalid floating-point value: '2x'")
914
915 def test_nargs_required_values(self):
916 self.assertParseFail(["--point", "1.0", "3.5"],
Greg Wardeba20e62004-07-31 16:15:44 +0000917 "--point option requires 3 arguments")
Greg Ward55493222003-04-21 02:41:25 +0000918
Greg Ward48aa84b2004-10-27 02:20:04 +0000919class TestMultipleArgsAppend(BaseTest):
Greg Ward55493222003-04-21 02:41:25 +0000920 def setUp(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000921 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
Greg Ward55493222003-04-21 02:41:25 +0000922 self.parser.add_option("-p", "--point", action="store", nargs=3,
923 type="float", dest="point")
924 self.parser.add_option("-f", "--foo", action="append", nargs=2,
925 type="int", dest="foo")
Thomas Wouters477c8d52006-05-27 19:21:47 +0000926 self.parser.add_option("-z", "--zero", action="append_const",
927 dest="foo", const=(0, 0))
Greg Ward55493222003-04-21 02:41:25 +0000928
929 def test_nargs_append(self):
930 self.assertParseOK(["-f", "4", "-3", "blah", "--foo", "1", "666"],
931 {'point': None, 'foo': [(4, -3), (1, 666)]},
932 ["blah"])
933
934 def test_nargs_append_required_values(self):
935 self.assertParseFail(["-f4,3"],
Greg Wardeba20e62004-07-31 16:15:44 +0000936 "-f option requires 2 arguments")
Greg Ward55493222003-04-21 02:41:25 +0000937
938 def test_nargs_append_simple(self):
939 self.assertParseOK(["--foo=3", "4"],
940 {'point': None, 'foo':[(3, 4)]},
941 [])
942
Thomas Wouters477c8d52006-05-27 19:21:47 +0000943 def test_nargs_append_const(self):
944 self.assertParseOK(["--zero", "--foo", "3", "4", "-z"],
945 {'point': None, 'foo':[(0, 0), (3, 4), (0, 0)]},
946 [])
947
Greg Ward55493222003-04-21 02:41:25 +0000948class TestVersion(BaseTest):
949 def test_version(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000950 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
951 version="%prog 0.1")
952 save_argv = sys.argv[:]
953 try:
954 sys.argv[0] = os.path.join(os.curdir, "foo", "bar")
955 self.assertOutput(["--version"], "bar 0.1\n")
956 finally:
957 sys.argv[:] = save_argv
Greg Ward55493222003-04-21 02:41:25 +0000958
959 def test_no_version(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000960 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
Greg Ward55493222003-04-21 02:41:25 +0000961 self.assertParseFail(["--version"],
962 "no such option: --version")
963
964# -- Test conflicting default values and parser.parse_args() -----------
965
966class TestConflictingDefaults(BaseTest):
967 """Conflicting default values: the last one should win."""
968 def setUp(self):
969 self.parser = OptionParser(option_list=[
970 make_option("-v", action="store_true", dest="verbose", default=1)])
971
972 def test_conflict_default(self):
973 self.parser.add_option("-q", action="store_false", dest="verbose",
974 default=0)
975 self.assertParseOK([], {'verbose': 0}, [])
976
977 def test_conflict_default_none(self):
978 self.parser.add_option("-q", action="store_false", dest="verbose",
979 default=None)
980 self.assertParseOK([], {'verbose': None}, [])
981
982class TestOptionGroup(BaseTest):
983 def setUp(self):
984 self.parser = OptionParser(usage=SUPPRESS_USAGE)
985
986 def test_option_group_create_instance(self):
987 group = OptionGroup(self.parser, "Spam")
988 self.parser.add_option_group(group)
989 group.add_option("--spam", action="store_true",
990 help="spam spam spam spam")
991 self.assertParseOK(["--spam"], {'spam': 1}, [])
992
993 def test_add_group_no_group(self):
994 self.assertTypeError(self.parser.add_option_group,
995 "not an OptionGroup instance: None", None)
996
997 def test_add_group_invalid_arguments(self):
998 self.assertTypeError(self.parser.add_option_group,
999 "invalid arguments", None, None)
1000
1001 def test_add_group_wrong_parser(self):
1002 group = OptionGroup(self.parser, "Spam")
1003 group.parser = OptionParser()
Greg Wardeba20e62004-07-31 16:15:44 +00001004 self.assertRaises(self.parser.add_option_group, (group,), None,
1005 ValueError, "invalid OptionGroup (wrong parser)")
Greg Ward55493222003-04-21 02:41:25 +00001006
1007 def test_group_manipulate(self):
1008 group = self.parser.add_option_group("Group 2",
1009 description="Some more options")
1010 group.set_title("Bacon")
1011 group.add_option("--bacon", type="int")
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001012 self.assertTrue(self.parser.get_option_group("--bacon"), group)
Greg Ward55493222003-04-21 02:41:25 +00001013
1014# -- Test extending and parser.parse_args() ----------------------------
1015
1016class TestExtendAddTypes(BaseTest):
1017 def setUp(self):
Greg Ward48aa84b2004-10-27 02:20:04 +00001018 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
1019 option_class=self.MyOption)
Greg Ward55493222003-04-21 02:41:25 +00001020 self.parser.add_option("-a", None, type="string", dest="a")
1021 self.parser.add_option("-f", "--file", type="file", dest="file")
1022
Thomas Wouters477c8d52006-05-27 19:21:47 +00001023 def tearDown(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001024 if os.path.isdir(support.TESTFN):
1025 os.rmdir(support.TESTFN)
1026 elif os.path.isfile(support.TESTFN):
1027 os.unlink(support.TESTFN)
Thomas Wouters477c8d52006-05-27 19:21:47 +00001028
Greg Ward55493222003-04-21 02:41:25 +00001029 class MyOption (Option):
Thomas Wouters477c8d52006-05-27 19:21:47 +00001030 def check_file(option, opt, value):
Greg Ward55493222003-04-21 02:41:25 +00001031 if not os.path.exists(value):
1032 raise OptionValueError("%s: file does not exist" % value)
1033 elif not os.path.isfile(value):
1034 raise OptionValueError("%s: not a regular file" % value)
1035 return value
1036
1037 TYPES = Option.TYPES + ("file",)
1038 TYPE_CHECKER = copy.copy(Option.TYPE_CHECKER)
1039 TYPE_CHECKER["file"] = check_file
1040
Thomas Wouters477c8d52006-05-27 19:21:47 +00001041 def test_filetype_ok(self):
Victor Stinnerbf816222011-06-30 23:25:47 +02001042 support.create_empty_file(support.TESTFN)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001043 self.assertParseOK(["--file", support.TESTFN, "-afoo"],
1044 {'file': support.TESTFN, 'a': 'foo'},
Greg Ward55493222003-04-21 02:41:25 +00001045 [])
1046
Thomas Wouters477c8d52006-05-27 19:21:47 +00001047 def test_filetype_noexist(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001048 self.assertParseFail(["--file", support.TESTFN, "-afoo"],
Greg Ward55493222003-04-21 02:41:25 +00001049 "%s: file does not exist" %
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001050 support.TESTFN)
Greg Ward55493222003-04-21 02:41:25 +00001051
Thomas Wouters477c8d52006-05-27 19:21:47 +00001052 def test_filetype_notfile(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001053 os.mkdir(support.TESTFN)
1054 self.assertParseFail(["--file", support.TESTFN, "-afoo"],
Greg Ward55493222003-04-21 02:41:25 +00001055 "%s: not a regular file" %
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001056 support.TESTFN)
Thomas Wouters477c8d52006-05-27 19:21:47 +00001057
Greg Ward55493222003-04-21 02:41:25 +00001058
1059class TestExtendAddActions(BaseTest):
1060 def setUp(self):
1061 options = [self.MyOption("-a", "--apple", action="extend",
1062 type="string", dest="apple")]
1063 self.parser = OptionParser(option_list=options)
1064
1065 class MyOption (Option):
1066 ACTIONS = Option.ACTIONS + ("extend",)
1067 STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",)
1068 TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",)
1069
Thomas Wouters477c8d52006-05-27 19:21:47 +00001070 def take_action(self, action, dest, opt, value, values, parser):
Greg Ward55493222003-04-21 02:41:25 +00001071 if action == "extend":
1072 lvalue = value.split(",")
1073 values.ensure_value(dest, []).extend(lvalue)
1074 else:
1075 Option.take_action(self, action, dest, opt, parser, value,
1076 values)
1077
1078 def test_extend_add_action(self):
1079 self.assertParseOK(["-afoo,bar", "--apple=blah"],
1080 {'apple': ["foo", "bar", "blah"]},
1081 [])
1082
1083 def test_extend_add_action_normal(self):
1084 self.assertParseOK(["-a", "foo", "-abar", "--apple=x,y"],
1085 {'apple': ["foo", "bar", "x", "y"]},
1086 [])
1087
1088# -- Test callbacks and parser.parse_args() ----------------------------
1089
1090class TestCallback(BaseTest):
1091 def setUp(self):
1092 options = [make_option("-x",
1093 None,
1094 action="callback",
1095 callback=self.process_opt),
1096 make_option("-f",
1097 "--file",
1098 action="callback",
1099 callback=self.process_opt,
1100 type="string",
1101 dest="filename")]
1102 self.parser = OptionParser(option_list=options)
1103
1104 def process_opt(self, option, opt, value, parser_):
1105 if opt == "-x":
1106 self.assertEqual(option._short_opts, ["-x"])
1107 self.assertEqual(option._long_opts, [])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001108 self.assertTrue(parser_ is self.parser)
1109 self.assertTrue(value is None)
Greg Ward55493222003-04-21 02:41:25 +00001110 self.assertEqual(vars(parser_.values), {'filename': None})
1111
1112 parser_.values.x = 42
1113 elif opt == "--file":
1114 self.assertEqual(option._short_opts, ["-f"])
1115 self.assertEqual(option._long_opts, ["--file"])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001116 self.assertTrue(parser_ is self.parser)
Greg Ward55493222003-04-21 02:41:25 +00001117 self.assertEqual(value, "foo")
1118 self.assertEqual(vars(parser_.values), {'filename': None, 'x': 42})
1119
1120 setattr(parser_.values, option.dest, value)
1121 else:
1122 self.fail("Unknown option %r in process_opt." % opt)
1123
1124 def test_callback(self):
1125 self.assertParseOK(["-x", "--file=foo"],
1126 {'filename': "foo", 'x': 42},
1127 [])
1128
Greg Wardeba20e62004-07-31 16:15:44 +00001129 def test_callback_help(self):
1130 # This test was prompted by SF bug #960515 -- the point is
1131 # not to inspect the help text, just to make sure that
1132 # format_help() doesn't crash.
1133 parser = OptionParser(usage=SUPPRESS_USAGE)
1134 parser.remove_option("-h")
1135 parser.add_option("-t", "--test", action="callback",
1136 callback=lambda: None, type="string",
1137 help="foo")
1138
Thomas Wouters477c8d52006-05-27 19:21:47 +00001139 expected_help = ("Options:\n"
Greg Wardeba20e62004-07-31 16:15:44 +00001140 " -t TEST, --test=TEST foo\n")
1141 self.assertHelp(parser, expected_help)
1142
1143
1144class TestCallbackExtraArgs(BaseTest):
Greg Ward55493222003-04-21 02:41:25 +00001145 def setUp(self):
1146 options = [make_option("-p", "--point", action="callback",
1147 callback=self.process_tuple,
1148 callback_args=(3, int), type="string",
1149 dest="points", default=[])]
1150 self.parser = OptionParser(option_list=options)
1151
Thomas Wouters477c8d52006-05-27 19:21:47 +00001152 def process_tuple(self, option, opt, value, parser_, len, type):
Greg Ward55493222003-04-21 02:41:25 +00001153 self.assertEqual(len, 3)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001154 self.assertTrue(type is int)
Greg Ward55493222003-04-21 02:41:25 +00001155
1156 if opt == "-p":
1157 self.assertEqual(value, "1,2,3")
1158 elif opt == "--point":
1159 self.assertEqual(value, "4,5,6")
1160
1161 value = tuple(map(type, value.split(",")))
1162 getattr(parser_.values, option.dest).append(value)
1163
1164 def test_callback_extra_args(self):
1165 self.assertParseOK(["-p1,2,3", "--point", "4,5,6"],
1166 {'points': [(1,2,3), (4,5,6)]},
1167 [])
1168
Greg Wardeba20e62004-07-31 16:15:44 +00001169class TestCallbackMeddleArgs(BaseTest):
Greg Ward55493222003-04-21 02:41:25 +00001170 def setUp(self):
1171 options = [make_option(str(x), action="callback",
1172 callback=self.process_n, dest='things')
1173 for x in range(-1, -6, -1)]
1174 self.parser = OptionParser(option_list=options)
1175
1176 # Callback that meddles in rargs, largs
Thomas Wouters477c8d52006-05-27 19:21:47 +00001177 def process_n(self, option, opt, value, parser_):
Greg Ward55493222003-04-21 02:41:25 +00001178 # option is -3, -5, etc.
1179 nargs = int(opt[1:])
1180 rargs = parser_.rargs
1181 if len(rargs) < nargs:
1182 self.fail("Expected %d arguments for %s option." % (nargs, opt))
1183 dest = parser_.values.ensure_value(option.dest, [])
1184 dest.append(tuple(rargs[0:nargs]))
1185 parser_.largs.append(nargs)
1186 del rargs[0:nargs]
1187
1188 def test_callback_meddle_args(self):
1189 self.assertParseOK(["-1", "foo", "-3", "bar", "baz", "qux"],
1190 {'things': [("foo",), ("bar", "baz", "qux")]},
1191 [1, 3])
1192
1193 def test_callback_meddle_args_separator(self):
1194 self.assertParseOK(["-2", "foo", "--"],
1195 {'things': [('foo', '--')]},
1196 [2])
1197
Greg Wardeba20e62004-07-31 16:15:44 +00001198class TestCallbackManyArgs(BaseTest):
Greg Ward55493222003-04-21 02:41:25 +00001199 def setUp(self):
1200 options = [make_option("-a", "--apple", action="callback", nargs=2,
1201 callback=self.process_many, type="string"),
1202 make_option("-b", "--bob", action="callback", nargs=3,
1203 callback=self.process_many, type="int")]
1204 self.parser = OptionParser(option_list=options)
1205
Thomas Wouters477c8d52006-05-27 19:21:47 +00001206 def process_many(self, option, opt, value, parser_):
Greg Ward55493222003-04-21 02:41:25 +00001207 if opt == "-a":
1208 self.assertEqual(value, ("foo", "bar"))
1209 elif opt == "--apple":
1210 self.assertEqual(value, ("ding", "dong"))
1211 elif opt == "-b":
1212 self.assertEqual(value, (1, 2, 3))
1213 elif opt == "--bob":
1214 self.assertEqual(value, (-666, 42, 0))
1215
1216 def test_many_args(self):
1217 self.assertParseOK(["-a", "foo", "bar", "--apple", "ding", "dong",
1218 "-b", "1", "2", "3", "--bob", "-666", "42",
1219 "0"],
Greg Wardeba20e62004-07-31 16:15:44 +00001220 {"apple": None, "bob": None},
Greg Ward55493222003-04-21 02:41:25 +00001221 [])
1222
Greg Wardeba20e62004-07-31 16:15:44 +00001223class TestCallbackCheckAbbrev(BaseTest):
Greg Ward55493222003-04-21 02:41:25 +00001224 def setUp(self):
1225 self.parser = OptionParser()
1226 self.parser.add_option("--foo-bar", action="callback",
1227 callback=self.check_abbrev)
1228
Thomas Wouters477c8d52006-05-27 19:21:47 +00001229 def check_abbrev(self, option, opt, value, parser):
Greg Ward55493222003-04-21 02:41:25 +00001230 self.assertEqual(opt, "--foo-bar")
1231
1232 def test_abbrev_callback_expansion(self):
1233 self.assertParseOK(["--foo"], {}, [])
1234
Greg Wardeba20e62004-07-31 16:15:44 +00001235class TestCallbackVarArgs(BaseTest):
Greg Ward55493222003-04-21 02:41:25 +00001236 def setUp(self):
1237 options = [make_option("-a", type="int", nargs=2, dest="a"),
1238 make_option("-b", action="store_true", dest="b"),
1239 make_option("-c", "--callback", action="callback",
1240 callback=self.variable_args, dest="c")]
Greg Ward48aa84b2004-10-27 02:20:04 +00001241 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
1242 option_list=options)
Greg Ward55493222003-04-21 02:41:25 +00001243
Thomas Wouters477c8d52006-05-27 19:21:47 +00001244 def variable_args(self, option, opt, value, parser):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001245 self.assertTrue(value is None)
Greg Ward55493222003-04-21 02:41:25 +00001246 value = []
1247 rargs = parser.rargs
1248 while rargs:
1249 arg = rargs[0]
1250 if ((arg[:2] == "--" and len(arg) > 2) or
1251 (arg[:1] == "-" and len(arg) > 1 and arg[1] != "-")):
1252 break
1253 else:
1254 value.append(arg)
1255 del rargs[0]
1256 setattr(parser.values, option.dest, value)
1257
1258 def test_variable_args(self):
1259 self.assertParseOK(["-a3", "-5", "--callback", "foo", "bar"],
1260 {'a': (3, -5), 'b': None, 'c': ["foo", "bar"]},
1261 [])
1262
1263 def test_consume_separator_stop_at_option(self):
1264 self.assertParseOK(["-c", "37", "--", "xxx", "-b", "hello"],
1265 {'a': None,
1266 'b': True,
1267 'c': ["37", "--", "xxx"]},
1268 ["hello"])
1269
1270 def test_positional_arg_and_variable_args(self):
1271 self.assertParseOK(["hello", "-c", "foo", "-", "bar"],
1272 {'a': None,
1273 'b': None,
1274 'c':["foo", "-", "bar"]},
1275 ["hello"])
1276
1277 def test_stop_at_option(self):
1278 self.assertParseOK(["-c", "foo", "-b"],
1279 {'a': None, 'b': True, 'c': ["foo"]},
1280 [])
1281
1282 def test_stop_at_invalid_option(self):
1283 self.assertParseFail(["-c", "3", "-5", "-a"], "no such option: -5")
1284
1285
1286# -- Test conflict handling and parser.parse_args() --------------------
1287
1288class ConflictBase(BaseTest):
1289 def setUp(self):
1290 options = [make_option("-v", "--verbose", action="count",
1291 dest="verbose", help="increment verbosity")]
Greg Ward48aa84b2004-10-27 02:20:04 +00001292 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
1293 option_list=options)
Greg Ward55493222003-04-21 02:41:25 +00001294
Thomas Wouters477c8d52006-05-27 19:21:47 +00001295 def show_version(self, option, opt, value, parser):
Greg Ward55493222003-04-21 02:41:25 +00001296 parser.values.show_version = 1
1297
1298class TestConflict(ConflictBase):
1299 """Use the default conflict resolution for Optik 1.2: error."""
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001300 def assertTrueconflict_error(self, func):
Greg Wardeba20e62004-07-31 16:15:44 +00001301 err = self.assertRaises(
1302 func, ("-v", "--version"), {'action' : "callback",
1303 'callback' : self.show_version,
1304 'help' : "show version"},
1305 OptionConflictError,
1306 "option -v/--version: conflicting option string(s): -v")
Greg Ward55493222003-04-21 02:41:25 +00001307
1308 self.assertEqual(err.msg, "conflicting option string(s): -v")
1309 self.assertEqual(err.option_id, "-v/--version")
1310
1311 def test_conflict_error(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001312 self.assertTrueconflict_error(self.parser.add_option)
Greg Ward55493222003-04-21 02:41:25 +00001313
1314 def test_conflict_error_group(self):
1315 group = OptionGroup(self.parser, "Group 1")
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001316 self.assertTrueconflict_error(group.add_option)
Greg Ward55493222003-04-21 02:41:25 +00001317
1318 def test_no_such_conflict_handler(self):
Greg Wardeba20e62004-07-31 16:15:44 +00001319 self.assertRaises(
1320 self.parser.set_conflict_handler, ('foo',), None,
1321 ValueError, "invalid conflict_resolution value 'foo'")
Greg Ward55493222003-04-21 02:41:25 +00001322
1323
Greg Ward55493222003-04-21 02:41:25 +00001324class TestConflictResolve(ConflictBase):
1325 def setUp(self):
1326 ConflictBase.setUp(self)
1327 self.parser.set_conflict_handler("resolve")
1328 self.parser.add_option("-v", "--version", action="callback",
1329 callback=self.show_version, help="show version")
1330
1331 def test_conflict_resolve(self):
1332 v_opt = self.parser.get_option("-v")
1333 verbose_opt = self.parser.get_option("--verbose")
1334 version_opt = self.parser.get_option("--version")
1335
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001336 self.assertTrue(v_opt is version_opt)
1337 self.assertTrue(v_opt is not verbose_opt)
Greg Ward55493222003-04-21 02:41:25 +00001338 self.assertEqual(v_opt._long_opts, ["--version"])
1339 self.assertEqual(version_opt._short_opts, ["-v"])
1340 self.assertEqual(version_opt._long_opts, ["--version"])
1341 self.assertEqual(verbose_opt._short_opts, [])
1342 self.assertEqual(verbose_opt._long_opts, ["--verbose"])
1343
1344 def test_conflict_resolve_help(self):
Greg Ward48aa84b2004-10-27 02:20:04 +00001345 self.assertOutput(["-h"], """\
Thomas Wouters477c8d52006-05-27 19:21:47 +00001346Options:
Greg Ward55493222003-04-21 02:41:25 +00001347 --verbose increment verbosity
1348 -h, --help show this help message and exit
1349 -v, --version show version
1350""")
1351
1352 def test_conflict_resolve_short_opt(self):
1353 self.assertParseOK(["-v"],
1354 {'verbose': None, 'show_version': 1},
1355 [])
1356
1357 def test_conflict_resolve_long_opt(self):
1358 self.assertParseOK(["--verbose"],
1359 {'verbose': 1},
1360 [])
1361
1362 def test_conflict_resolve_long_opts(self):
1363 self.assertParseOK(["--verbose", "--version"],
1364 {'verbose': 1, 'show_version': 1},
1365 [])
1366
1367class TestConflictOverride(BaseTest):
1368 def setUp(self):
Greg Ward48aa84b2004-10-27 02:20:04 +00001369 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
Greg Ward55493222003-04-21 02:41:25 +00001370 self.parser.set_conflict_handler("resolve")
1371 self.parser.add_option("-n", "--dry-run",
1372 action="store_true", dest="dry_run",
1373 help="don't do anything")
1374 self.parser.add_option("--dry-run", "-n",
1375 action="store_const", const=42, dest="dry_run",
1376 help="dry run mode")
1377
1378 def test_conflict_override_opts(self):
1379 opt = self.parser.get_option("--dry-run")
1380 self.assertEqual(opt._short_opts, ["-n"])
1381 self.assertEqual(opt._long_opts, ["--dry-run"])
1382
1383 def test_conflict_override_help(self):
Greg Ward48aa84b2004-10-27 02:20:04 +00001384 self.assertOutput(["-h"], """\
Thomas Wouters477c8d52006-05-27 19:21:47 +00001385Options:
Greg Ward55493222003-04-21 02:41:25 +00001386 -h, --help show this help message and exit
1387 -n, --dry-run dry run mode
1388""")
1389
1390 def test_conflict_override_args(self):
1391 self.assertParseOK(["-n"],
1392 {'dry_run': 42},
1393 [])
1394
1395# -- Other testing. ----------------------------------------------------
1396
Greg Wardeba20e62004-07-31 16:15:44 +00001397_expected_help_basic = """\
Thomas Wouters477c8d52006-05-27 19:21:47 +00001398Usage: bar.py [options]
Greg Wardeba20e62004-07-31 16:15:44 +00001399
Thomas Wouters477c8d52006-05-27 19:21:47 +00001400Options:
Greg Wardeba20e62004-07-31 16:15:44 +00001401 -a APPLE throw APPLEs at basket
1402 -b NUM, --boo=NUM shout "boo!" NUM times (in order to frighten away all the
1403 evil spirits that cause trouble and mayhem)
1404 --foo=FOO store FOO in the foo list for later fooing
1405 -h, --help show this help message and exit
1406"""
1407
1408_expected_help_long_opts_first = """\
Thomas Wouters477c8d52006-05-27 19:21:47 +00001409Usage: bar.py [options]
Greg Wardeba20e62004-07-31 16:15:44 +00001410
Thomas Wouters477c8d52006-05-27 19:21:47 +00001411Options:
Greg Wardeba20e62004-07-31 16:15:44 +00001412 -a APPLE throw APPLEs at basket
1413 --boo=NUM, -b NUM shout "boo!" NUM times (in order to frighten away all the
1414 evil spirits that cause trouble and mayhem)
1415 --foo=FOO store FOO in the foo list for later fooing
1416 --help, -h show this help message and exit
1417"""
1418
1419_expected_help_title_formatter = """\
1420Usage
1421=====
1422 bar.py [options]
1423
Thomas Wouters477c8d52006-05-27 19:21:47 +00001424Options
Greg Wardeba20e62004-07-31 16:15:44 +00001425=======
1426-a APPLE throw APPLEs at basket
1427--boo=NUM, -b NUM shout "boo!" NUM times (in order to frighten away all the
1428 evil spirits that cause trouble and mayhem)
1429--foo=FOO store FOO in the foo list for later fooing
1430--help, -h show this help message and exit
1431"""
1432
1433_expected_help_short_lines = """\
Thomas Wouters477c8d52006-05-27 19:21:47 +00001434Usage: bar.py [options]
Greg Wardeba20e62004-07-31 16:15:44 +00001435
Thomas Wouters477c8d52006-05-27 19:21:47 +00001436Options:
Greg Wardeba20e62004-07-31 16:15:44 +00001437 -a APPLE throw APPLEs at basket
1438 -b NUM, --boo=NUM shout "boo!" NUM times (in order to
1439 frighten away all the evil spirits
1440 that cause trouble and mayhem)
1441 --foo=FOO store FOO in the foo list for later
1442 fooing
1443 -h, --help show this help message and exit
1444"""
1445
Serhiy Storchakaf4511122014-01-09 23:14:27 +02001446_expected_very_help_short_lines = """\
1447Usage: bar.py [options]
1448
1449Options:
1450 -a APPLE
1451 throw
1452 APPLEs at
1453 basket
1454 -b NUM, --boo=NUM
1455 shout
1456 "boo!" NUM
1457 times (in
1458 order to
1459 frighten
1460 away all
1461 the evil
1462 spirits
1463 that cause
1464 trouble and
1465 mayhem)
1466 --foo=FOO
1467 store FOO
1468 in the foo
1469 list for
1470 later
1471 fooing
1472 -h, --help
1473 show this
1474 help
1475 message and
1476 exit
1477"""
1478
Greg Ward55493222003-04-21 02:41:25 +00001479class TestHelp(BaseTest):
1480 def setUp(self):
Greg Wardeba20e62004-07-31 16:15:44 +00001481 self.parser = self.make_parser(80)
1482
1483 def make_parser(self, columns):
Greg Ward55493222003-04-21 02:41:25 +00001484 options = [
1485 make_option("-a", type="string", dest='a',
1486 metavar="APPLE", help="throw APPLEs at basket"),
1487 make_option("-b", "--boo", type="int", dest='boo',
1488 metavar="NUM",
1489 help=
1490 "shout \"boo!\" NUM times (in order to frighten away "
1491 "all the evil spirits that cause trouble and mayhem)"),
1492 make_option("--foo", action="append", type="string", dest='foo',
1493 help="store FOO in the foo list for later fooing"),
1494 ]
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001495
1496 # We need to set COLUMNS for the OptionParser constructor, but
1497 # we must restore its original value -- otherwise, this test
1498 # screws things up for other tests when it's part of the Python
1499 # test suite.
Hirokazu Yamamoto71959632009-04-27 01:44:28 +00001500 with support.EnvironmentVarGuard() as env:
Walter Dörwald155374d2009-05-01 19:58:58 +00001501 env['COLUMNS'] = str(columns)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001502 return InterceptingOptionParser(option_list=options)
Greg Ward55493222003-04-21 02:41:25 +00001503
1504 def assertHelpEquals(self, expected_output):
Greg Ward48aa84b2004-10-27 02:20:04 +00001505 save_argv = sys.argv[:]
1506 try:
1507 # Make optparse believe bar.py is being executed.
1508 sys.argv[0] = os.path.join("foo", "bar.py")
1509 self.assertOutput(["-h"], expected_output)
1510 finally:
1511 sys.argv[:] = save_argv
Greg Ward55493222003-04-21 02:41:25 +00001512
1513 def test_help(self):
Greg Wardeba20e62004-07-31 16:15:44 +00001514 self.assertHelpEquals(_expected_help_basic)
Greg Ward55493222003-04-21 02:41:25 +00001515
1516 def test_help_old_usage(self):
Thomas Wouters477c8d52006-05-27 19:21:47 +00001517 self.parser.set_usage("Usage: %prog [options]")
Greg Wardeba20e62004-07-31 16:15:44 +00001518 self.assertHelpEquals(_expected_help_basic)
Greg Ward55493222003-04-21 02:41:25 +00001519
1520 def test_help_long_opts_first(self):
1521 self.parser.formatter.short_first = 0
Greg Wardeba20e62004-07-31 16:15:44 +00001522 self.assertHelpEquals(_expected_help_long_opts_first)
Greg Ward55493222003-04-21 02:41:25 +00001523
1524 def test_help_title_formatter(self):
Hirokazu Yamamoto71959632009-04-27 01:44:28 +00001525 with support.EnvironmentVarGuard() as env:
Walter Dörwald155374d2009-05-01 19:58:58 +00001526 env["COLUMNS"] = "80"
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001527 self.parser.formatter = TitledHelpFormatter()
1528 self.assertHelpEquals(_expected_help_title_formatter)
Greg Ward55493222003-04-21 02:41:25 +00001529
Greg Wardeba20e62004-07-31 16:15:44 +00001530 def test_wrap_columns(self):
1531 # Ensure that wrapping respects $COLUMNS environment variable.
1532 # Need to reconstruct the parser, since that's the only time
1533 # we look at $COLUMNS.
1534 self.parser = self.make_parser(60)
1535 self.assertHelpEquals(_expected_help_short_lines)
Serhiy Storchakaf4511122014-01-09 23:14:27 +02001536 self.parser = self.make_parser(0)
1537 self.assertHelpEquals(_expected_very_help_short_lines)
Greg Ward55493222003-04-21 02:41:25 +00001538
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001539 def test_help_unicode(self):
1540 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
Guido van Rossumef87d6e2007-05-02 19:09:54 +00001541 self.parser.add_option("-a", action="store_true", help="ol\u00E9!")
1542 expect = """\
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001543Options:
1544 -h, --help show this help message and exit
1545 -a ol\u00E9!
1546"""
1547 self.assertHelpEquals(expect)
1548
1549 def test_help_unicode_description(self):
1550 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
Guido van Rossumef87d6e2007-05-02 19:09:54 +00001551 description="ol\u00E9!")
1552 expect = """\
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001553ol\u00E9!
1554
1555Options:
1556 -h, --help show this help message and exit
1557"""
1558 self.assertHelpEquals(expect)
1559
Greg Ward55493222003-04-21 02:41:25 +00001560 def test_help_description_groups(self):
1561 self.parser.set_description(
Greg Wardeba20e62004-07-31 16:15:44 +00001562 "This is the program description for %prog. %prog has "
Greg Ward55493222003-04-21 02:41:25 +00001563 "an option group as well as single options.")
1564
1565 group = OptionGroup(
1566 self.parser, "Dangerous Options",
1567 "Caution: use of these options is at your own risk. "
1568 "It is believed that some of them bite.")
1569 group.add_option("-g", action="store_true", help="Group option.")
1570 self.parser.add_option_group(group)
1571
Thomas Wouters477c8d52006-05-27 19:21:47 +00001572 expect = """\
1573Usage: bar.py [options]
Greg Ward55493222003-04-21 02:41:25 +00001574
Greg Wardeba20e62004-07-31 16:15:44 +00001575This is the program description for bar.py. bar.py has an option group as
1576well as single options.
1577
Thomas Wouters477c8d52006-05-27 19:21:47 +00001578Options:
Greg Wardeba20e62004-07-31 16:15:44 +00001579 -a APPLE throw APPLEs at basket
1580 -b NUM, --boo=NUM shout "boo!" NUM times (in order to frighten away all the
1581 evil spirits that cause trouble and mayhem)
1582 --foo=FOO store FOO in the foo list for later fooing
1583 -h, --help show this help message and exit
Greg Ward55493222003-04-21 02:41:25 +00001584
1585 Dangerous Options:
Greg Wardeba20e62004-07-31 16:15:44 +00001586 Caution: use of these options is at your own risk. It is believed
1587 that some of them bite.
1588
1589 -g Group option.
Thomas Wouters477c8d52006-05-27 19:21:47 +00001590"""
Greg Ward55493222003-04-21 02:41:25 +00001591
Thomas Wouters477c8d52006-05-27 19:21:47 +00001592 self.assertHelpEquals(expect)
Greg Wardeba20e62004-07-31 16:15:44 +00001593
Thomas Wouters477c8d52006-05-27 19:21:47 +00001594 self.parser.epilog = "Please report bugs to /dev/null."
1595 self.assertHelpEquals(expect + "\nPlease report bugs to /dev/null.\n")
Tim Peters10d59f32004-10-27 02:43:25 +00001596
Greg Wardeba20e62004-07-31 16:15:44 +00001597
Greg Ward55493222003-04-21 02:41:25 +00001598class TestMatchAbbrev(BaseTest):
1599 def test_match_abbrev(self):
1600 self.assertEqual(_match_abbrev("--f",
1601 {"--foz": None,
1602 "--foo": None,
1603 "--fie": None,
1604 "--f": None}),
1605 "--f")
1606
1607 def test_match_abbrev_error(self):
1608 s = "--f"
1609 wordmap = {"--foz": None, "--foo": None, "--fie": None}
Greg Wardeba20e62004-07-31 16:15:44 +00001610 self.assertRaises(
1611 _match_abbrev, (s, wordmap), None,
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001612 BadOptionError, "ambiguous option: --f (--fie, --foo, --foz?)")
Greg Wardeba20e62004-07-31 16:15:44 +00001613
1614
Thomas Wouters477c8d52006-05-27 19:21:47 +00001615class TestParseNumber(BaseTest):
1616 def setUp(self):
1617 self.parser = InterceptingOptionParser()
1618 self.parser.add_option("-n", type=int)
Guido van Rossume2a383d2007-01-15 16:59:06 +00001619 self.parser.add_option("-l", type=int)
Thomas Wouters477c8d52006-05-27 19:21:47 +00001620
1621 def test_parse_num_fail(self):
1622 self.assertRaises(
1623 _parse_num, ("", int), {},
1624 ValueError,
1625 re.compile(r"invalid literal for int().*: '?'?"))
1626 self.assertRaises(
Guido van Rossume2a383d2007-01-15 16:59:06 +00001627 _parse_num, ("0xOoops", int), {},
Thomas Wouters477c8d52006-05-27 19:21:47 +00001628 ValueError,
Guido van Rossumb4e87e32007-07-09 10:08:42 +00001629 re.compile(r"invalid literal for int().*: s?'?0xOoops'?"))
Thomas Wouters477c8d52006-05-27 19:21:47 +00001630
1631 def test_parse_num_ok(self):
1632 self.assertEqual(_parse_num("0", int), 0)
1633 self.assertEqual(_parse_num("0x10", int), 16)
Guido van Rossume2a383d2007-01-15 16:59:06 +00001634 self.assertEqual(_parse_num("0XA", int), 10)
1635 self.assertEqual(_parse_num("010", int), 8)
Thomas Wouters477c8d52006-05-27 19:21:47 +00001636 self.assertEqual(_parse_num("0b11", int), 3)
Guido van Rossume2a383d2007-01-15 16:59:06 +00001637 self.assertEqual(_parse_num("0b", int), 0)
Thomas Wouters477c8d52006-05-27 19:21:47 +00001638
1639 def test_numeric_options(self):
1640 self.assertParseOK(["-n", "42", "-l", "0x20"],
1641 { "n": 42, "l": 0x20 }, [])
1642 self.assertParseOK(["-n", "0b0101", "-l010"],
1643 { "n": 5, "l": 8 }, [])
1644 self.assertParseFail(["-n008"],
1645 "option -n: invalid integer value: '008'")
1646 self.assertParseFail(["-l0b0123"],
Guido van Rossumddefaf32007-01-14 03:31:43 +00001647 "option -l: invalid integer value: '0b0123'")
Thomas Wouters477c8d52006-05-27 19:21:47 +00001648 self.assertParseFail(["-l", "0x12x"],
Guido van Rossumddefaf32007-01-14 03:31:43 +00001649 "option -l: invalid integer value: '0x12x'")
Thomas Wouters477c8d52006-05-27 19:21:47 +00001650
1651
Martin Panter19e69c52015-11-14 12:46:42 +00001652class MiscTestCase(unittest.TestCase):
1653 def test__all__(self):
1654 blacklist = {'check_builtin', 'AmbiguousOptionError', 'NO_DEFAULT'}
1655 support.check__all__(self, optparse, blacklist=blacklist)
1656
1657
Greg Ward55493222003-04-21 02:41:25 +00001658def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001659 support.run_unittest(__name__)
Greg Ward55493222003-04-21 02:41:25 +00001660
1661if __name__ == '__main__':
Guido van Rossumd8faa362007-04-27 19:54:29 +00001662 test_main()