blob: 7621c2430554bd5ea652142336e38be0c01cfd0d [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
Georg Brandl1b37e872010-03-14 10:45:50 +000019from optparse import make_option, Option, \
20 TitledHelpFormatter, OptionParser, OptionGroup, \
21 SUPPRESS_USAGE, OptionError, OptionConflictError, \
Thomas Wouters477c8d52006-05-27 19:21:47 +000022 BadOptionError, OptionValueError, Values
23from optparse import _match_abbrev
24from optparse import _parse_num
Greg Ward48aa84b2004-10-27 02:20:04 +000025
Thomas Wouters477c8d52006-05-27 19:21:47 +000026retype = type(re.compile(''))
Greg Ward48aa84b2004-10-27 02:20:04 +000027
28class InterceptedError(Exception):
29 def __init__(self,
30 error_message=None,
31 exit_status=None,
32 exit_message=None):
33 self.error_message = error_message
34 self.exit_status = exit_status
35 self.exit_message = exit_message
36
37 def __str__(self):
38 return self.error_message or self.exit_message or "intercepted error"
39
40class InterceptingOptionParser(OptionParser):
41 def exit(self, status=0, msg=None):
42 raise InterceptedError(exit_status=status, exit_message=msg)
43
44 def error(self, msg):
45 raise InterceptedError(error_message=msg)
46
Greg Ward55493222003-04-21 02:41:25 +000047
48class BaseTest(unittest.TestCase):
49 def assertParseOK(self, args, expected_opts, expected_positional_args):
50 """Assert the options are what we expected when parsing arguments.
51
52 Otherwise, fail with a nicely formatted message.
53
54 Keyword arguments:
55 args -- A list of arguments to parse with OptionParser.
56 expected_opts -- The options expected.
57 expected_positional_args -- The positional arguments expected.
58
59 Returns the options and positional args for further testing.
60 """
61
62 (options, positional_args) = self.parser.parse_args(args)
63 optdict = vars(options)
64
65 self.assertEqual(optdict, expected_opts,
66 """
67Options are %(optdict)s.
68Should be %(expected_opts)s.
69Args were %(args)s.""" % locals())
70
71 self.assertEqual(positional_args, expected_positional_args,
72 """
73Positional arguments are %(positional_args)s.
74Should be %(expected_positional_args)s.
75Args were %(args)s.""" % locals ())
76
77 return (options, positional_args)
78
Greg Wardeba20e62004-07-31 16:15:44 +000079 def assertRaises(self,
80 func,
81 args,
82 kwargs,
83 expected_exception,
Greg Ward48aa84b2004-10-27 02:20:04 +000084 expected_message):
85 """
86 Assert that the expected exception is raised when calling a
87 function, and that the right error message is included with
88 that exception.
Greg Ward55493222003-04-21 02:41:25 +000089
Greg Wardeba20e62004-07-31 16:15:44 +000090 Arguments:
91 func -- the function to call
92 args -- positional arguments to `func`
93 kwargs -- keyword arguments to `func`
94 expected_exception -- exception that should be raised
Thomas Wouters477c8d52006-05-27 19:21:47 +000095 expected_message -- expected exception message (or pattern
96 if a compiled regex object)
Greg Ward55493222003-04-21 02:41:25 +000097
98 Returns the exception raised for further testing.
99 """
Greg Wardeba20e62004-07-31 16:15:44 +0000100 if args is None:
101 args = ()
102 if kwargs is None:
103 kwargs = {}
Greg Ward55493222003-04-21 02:41:25 +0000104
105 try:
Greg Ward48aa84b2004-10-27 02:20:04 +0000106 func(*args, **kwargs)
Guido van Rossumb940e112007-01-10 16:19:56 +0000107 except expected_exception as err:
Greg Ward48aa84b2004-10-27 02:20:04 +0000108 actual_message = str(err)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000109 if isinstance(expected_message, retype):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000110 self.assertTrue(expected_message.search(actual_message),
Greg Ward48aa84b2004-10-27 02:20:04 +0000111 """\
Thomas Wouters477c8d52006-05-27 19:21:47 +0000112expected exception message pattern:
113/%s/
Greg Ward48aa84b2004-10-27 02:20:04 +0000114actual exception message:
Thomas Wouters477c8d52006-05-27 19:21:47 +0000115'''%s'''
116""" % (expected_message.pattern, actual_message))
117 else:
118 self.assertEqual(actual_message,
119 expected_message,
120 """\
121expected exception message:
122'''%s'''
123actual exception message:
124'''%s'''
125""" % (expected_message, actual_message))
Greg Ward55493222003-04-21 02:41:25 +0000126
127 return err
128 else:
Greg Wardeba20e62004-07-31 16:15:44 +0000129 self.fail("""expected exception %(expected_exception)s not raised
130called %(func)r
131with args %(args)r
132and kwargs %(kwargs)r
133""" % locals ())
Greg Ward55493222003-04-21 02:41:25 +0000134
Greg Wardeba20e62004-07-31 16:15:44 +0000135
Greg Ward55493222003-04-21 02:41:25 +0000136 # -- Assertions used in more than one class --------------------
137
138 def assertParseFail(self, cmdline_args, expected_output):
Greg Ward48aa84b2004-10-27 02:20:04 +0000139 """
140 Assert the parser fails with the expected message. Caller
141 must ensure that self.parser is an InterceptingOptionParser.
142 """
Tim Peters579f7352004-07-31 21:14:28 +0000143 try:
Greg Ward48aa84b2004-10-27 02:20:04 +0000144 self.parser.parse_args(cmdline_args)
Guido van Rossumb940e112007-01-10 16:19:56 +0000145 except InterceptedError as err:
Greg Ward48aa84b2004-10-27 02:20:04 +0000146 self.assertEqual(err.error_message, expected_output)
147 else:
148 self.assertFalse("expected parse failure")
Greg Ward55493222003-04-21 02:41:25 +0000149
Greg Ward48aa84b2004-10-27 02:20:04 +0000150 def assertOutput(self,
151 cmdline_args,
152 expected_output,
153 expected_status=0,
154 expected_error=None):
Greg Ward55493222003-04-21 02:41:25 +0000155 """Assert the parser prints the expected output on stdout."""
Tim Peters579f7352004-07-31 21:14:28 +0000156 save_stdout = sys.stdout
157 try:
Greg Ward48aa84b2004-10-27 02:20:04 +0000158 try:
159 sys.stdout = StringIO()
160 self.parser.parse_args(cmdline_args)
161 finally:
162 output = sys.stdout.getvalue()
163 sys.stdout = save_stdout
Greg Ward55493222003-04-21 02:41:25 +0000164
Guido van Rossumb940e112007-01-10 16:19:56 +0000165 except InterceptedError as err:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000166 self.assertTrue(
Guido van Rossum13257902007-06-07 23:15:56 +0000167 isinstance(output, str),
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000168 "expected output to be an ordinary string, not %r"
169 % type(output))
170
Thomas Wouters477c8d52006-05-27 19:21:47 +0000171 if output != expected_output:
172 self.fail("expected: \n'''\n" + expected_output +
173 "'''\nbut got \n'''\n" + output + "'''")
Greg Ward48aa84b2004-10-27 02:20:04 +0000174 self.assertEqual(err.exit_status, expected_status)
175 self.assertEqual(err.exit_message, expected_error)
176 else:
177 self.assertFalse("expected parser.exit()")
178
179 def assertTypeError(self, func, expected_message, *args):
180 """Assert that TypeError is raised when executing func."""
181 self.assertRaises(func, args, None, TypeError, expected_message)
Greg Wardeba20e62004-07-31 16:15:44 +0000182
183 def assertHelp(self, parser, expected_help):
184 actual_help = parser.format_help()
185 if actual_help != expected_help:
186 raise self.failureException(
187 'help text failure; expected:\n"' +
188 expected_help + '"; got:\n"' +
189 actual_help + '"\n')
Greg Ward55493222003-04-21 02:41:25 +0000190
191# -- Test make_option() aka Option -------------------------------------
192
Greg Ward48aa84b2004-10-27 02:20:04 +0000193# It's not necessary to test correct options here. All the tests in the
Greg Ward55493222003-04-21 02:41:25 +0000194# parser.parse_args() section deal with those, because they're needed
Greg Ward48aa84b2004-10-27 02:20:04 +0000195# there.
Greg Ward55493222003-04-21 02:41:25 +0000196
197class TestOptionChecks(BaseTest):
198 def setUp(self):
199 self.parser = OptionParser(usage=SUPPRESS_USAGE)
200
Greg Ward48aa84b2004-10-27 02:20:04 +0000201 def assertOptionError(self, expected_message, args=[], kwargs={}):
Greg Wardeba20e62004-07-31 16:15:44 +0000202 self.assertRaises(make_option, args, kwargs,
Greg Ward48aa84b2004-10-27 02:20:04 +0000203 OptionError, expected_message)
Greg Ward55493222003-04-21 02:41:25 +0000204
205 def test_opt_string_empty(self):
206 self.assertTypeError(make_option,
207 "at least one option string must be supplied")
208
209 def test_opt_string_too_short(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000210 self.assertOptionError(
211 "invalid option string 'b': must be at least two characters long",
212 ["b"])
Greg Ward55493222003-04-21 02:41:25 +0000213
214 def test_opt_string_short_invalid(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000215 self.assertOptionError(
216 "invalid short option string '--': must be "
217 "of the form -x, (x any non-dash char)",
218 ["--"])
Greg Ward55493222003-04-21 02:41:25 +0000219
220 def test_opt_string_long_invalid(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000221 self.assertOptionError(
222 "invalid long option string '---': "
223 "must start with --, followed by non-dash",
224 ["---"])
Greg Ward55493222003-04-21 02:41:25 +0000225
226 def test_attr_invalid(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000227 self.assertOptionError(
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000228 "option -b: invalid keyword arguments: bar, foo",
Greg Ward48aa84b2004-10-27 02:20:04 +0000229 ["-b"], {'foo': None, 'bar': None})
Greg Ward55493222003-04-21 02:41:25 +0000230
231 def test_action_invalid(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000232 self.assertOptionError(
233 "option -b: invalid action: 'foo'",
234 ["-b"], {'action': 'foo'})
Greg Ward55493222003-04-21 02:41:25 +0000235
236 def test_type_invalid(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000237 self.assertOptionError(
238 "option -b: invalid option type: 'foo'",
239 ["-b"], {'type': 'foo'})
240 self.assertOptionError(
241 "option -b: invalid option type: 'tuple'",
242 ["-b"], {'type': tuple})
Greg Ward55493222003-04-21 02:41:25 +0000243
244 def test_no_type_for_action(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000245 self.assertOptionError(
246 "option -b: must not supply a type for action 'count'",
247 ["-b"], {'action': 'count', 'type': 'int'})
Greg Ward55493222003-04-21 02:41:25 +0000248
249 def test_no_choices_list(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000250 self.assertOptionError(
251 "option -b/--bad: must supply a list of "
252 "choices for type 'choice'",
253 ["-b", "--bad"], {'type': "choice"})
Greg Ward55493222003-04-21 02:41:25 +0000254
255 def test_bad_choices_list(self):
256 typename = type('').__name__
Greg Ward48aa84b2004-10-27 02:20:04 +0000257 self.assertOptionError(
258 "option -b/--bad: choices must be a list of "
259 "strings ('%s' supplied)" % typename,
260 ["-b", "--bad"],
261 {'type': "choice", 'choices':"bad choices"})
Greg Ward55493222003-04-21 02:41:25 +0000262
263 def test_no_choices_for_type(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000264 self.assertOptionError(
265 "option -b: must not supply choices for type 'int'",
266 ["-b"], {'type': 'int', 'choices':"bad"})
Greg Ward55493222003-04-21 02:41:25 +0000267
268 def test_no_const_for_action(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000269 self.assertOptionError(
270 "option -b: 'const' must not be supplied for action 'store'",
271 ["-b"], {'action': 'store', 'const': 1})
Greg Ward55493222003-04-21 02:41:25 +0000272
273 def test_no_nargs_for_action(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000274 self.assertOptionError(
275 "option -b: 'nargs' must not be supplied for action 'count'",
276 ["-b"], {'action': 'count', 'nargs': 2})
Greg Ward55493222003-04-21 02:41:25 +0000277
278 def test_callback_not_callable(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000279 self.assertOptionError(
280 "option -b: callback not callable: 'foo'",
281 ["-b"], {'action': 'callback',
282 'callback': 'foo'})
Greg Ward55493222003-04-21 02:41:25 +0000283
284 def dummy(self):
285 pass
286
287 def test_callback_args_no_tuple(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000288 self.assertOptionError(
289 "option -b: callback_args, if supplied, "
290 "must be a tuple: not 'foo'",
291 ["-b"], {'action': 'callback',
292 'callback': self.dummy,
293 'callback_args': 'foo'})
Greg Ward55493222003-04-21 02:41:25 +0000294
295 def test_callback_kwargs_no_dict(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000296 self.assertOptionError(
297 "option -b: callback_kwargs, if supplied, "
298 "must be a dict: not 'foo'",
299 ["-b"], {'action': 'callback',
300 'callback': self.dummy,
301 'callback_kwargs': 'foo'})
Greg Ward55493222003-04-21 02:41:25 +0000302
303 def test_no_callback_for_action(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000304 self.assertOptionError(
305 "option -b: callback supplied ('foo') for non-callback option",
306 ["-b"], {'action': 'store',
307 'callback': 'foo'})
Greg Ward55493222003-04-21 02:41:25 +0000308
309 def test_no_callback_args_for_action(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000310 self.assertOptionError(
311 "option -b: callback_args supplied for non-callback option",
312 ["-b"], {'action': 'store',
313 'callback_args': 'foo'})
Greg Ward55493222003-04-21 02:41:25 +0000314
315 def test_no_callback_kwargs_for_action(self):
Greg Ward48aa84b2004-10-27 02:20:04 +0000316 self.assertOptionError(
317 "option -b: callback_kwargs supplied for non-callback option",
318 ["-b"], {'action': 'store',
319 'callback_kwargs': 'foo'})
Greg Ward55493222003-04-21 02:41:25 +0000320
R David Murray6159e092012-07-15 20:12:24 -0400321 def test_no_single_dash(self):
322 self.assertOptionError(
323 "invalid long option string '-debug': "
324 "must start with --, followed by non-dash",
325 ["-debug"])
326
327 self.assertOptionError(
328 "option -d: invalid long option string '-debug': must start with"
329 " --, followed by non-dash",
330 ["-d", "-debug"])
331
332 self.assertOptionError(
333 "invalid long option string '-debug': "
334 "must start with --, followed by non-dash",
335 ["-debug", "--debug"])
336
Greg Ward55493222003-04-21 02:41:25 +0000337class TestOptionParser(BaseTest):
338 def setUp(self):
339 self.parser = OptionParser()
340 self.parser.add_option("-v", "--verbose", "-n", "--noisy",
341 action="store_true", dest="verbose")
342 self.parser.add_option("-q", "--quiet", "--silent",
343 action="store_false", dest="verbose")
344
345 def test_add_option_no_Option(self):
346 self.assertTypeError(self.parser.add_option,
347 "not an Option instance: None", None)
348
349 def test_add_option_invalid_arguments(self):
350 self.assertTypeError(self.parser.add_option,
351 "invalid arguments", None, None)
352
353 def test_get_option(self):
354 opt1 = self.parser.get_option("-v")
Ezio Melottie9615932010-01-24 19:26:24 +0000355 self.assertIsInstance(opt1, Option)
Greg Ward55493222003-04-21 02:41:25 +0000356 self.assertEqual(opt1._short_opts, ["-v", "-n"])
357 self.assertEqual(opt1._long_opts, ["--verbose", "--noisy"])
358 self.assertEqual(opt1.action, "store_true")
359 self.assertEqual(opt1.dest, "verbose")
360
361 def test_get_option_equals(self):
362 opt1 = self.parser.get_option("-v")
363 opt2 = self.parser.get_option("--verbose")
364 opt3 = self.parser.get_option("-n")
365 opt4 = self.parser.get_option("--noisy")
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000366 self.assertTrue(opt1 is opt2 is opt3 is opt4)
Greg Ward55493222003-04-21 02:41:25 +0000367
368 def test_has_option(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000369 self.assertTrue(self.parser.has_option("-v"))
370 self.assertTrue(self.parser.has_option("--verbose"))
Greg Ward55493222003-04-21 02:41:25 +0000371
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000372 def assertTrueremoved(self):
373 self.assertTrue(self.parser.get_option("-v") is None)
374 self.assertTrue(self.parser.get_option("--verbose") is None)
375 self.assertTrue(self.parser.get_option("-n") is None)
376 self.assertTrue(self.parser.get_option("--noisy") is None)
Greg Ward55493222003-04-21 02:41:25 +0000377
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000378 self.assertFalse(self.parser.has_option("-v"))
379 self.assertFalse(self.parser.has_option("--verbose"))
380 self.assertFalse(self.parser.has_option("-n"))
381 self.assertFalse(self.parser.has_option("--noisy"))
Greg Ward55493222003-04-21 02:41:25 +0000382
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000383 self.assertTrue(self.parser.has_option("-q"))
384 self.assertTrue(self.parser.has_option("--silent"))
Greg Ward55493222003-04-21 02:41:25 +0000385
386 def test_remove_short_opt(self):
387 self.parser.remove_option("-n")
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000388 self.assertTrueremoved()
Greg Ward55493222003-04-21 02:41:25 +0000389
390 def test_remove_long_opt(self):
391 self.parser.remove_option("--verbose")
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000392 self.assertTrueremoved()
Greg Ward55493222003-04-21 02:41:25 +0000393
394 def test_remove_nonexistent(self):
Greg Wardeba20e62004-07-31 16:15:44 +0000395 self.assertRaises(self.parser.remove_option, ('foo',), None,
396 ValueError, "no such option 'foo'")
397
Andrew Kuchling45278a82014-04-15 16:44:43 -0400398 @support.impl_detail('Relies on sys.getrefcount', cpython=True)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000399 def test_refleak(self):
400 # If an OptionParser is carrying around a reference to a large
401 # object, various cycles can prevent it from being GC'd in
402 # a timely fashion. destroy() breaks the cycles to ensure stuff
403 # can be cleaned up.
404 big_thing = [42]
405 refcount = sys.getrefcount(big_thing)
406 parser = OptionParser()
407 parser.add_option("-a", "--aaarggh")
408 parser.big_thing = big_thing
409
410 parser.destroy()
411 #self.assertEqual(refcount, sys.getrefcount(big_thing))
412 del parser
413 self.assertEqual(refcount, sys.getrefcount(big_thing))
414
415
Greg Ward48aa84b2004-10-27 02:20:04 +0000416class TestOptionValues(BaseTest):
417 def setUp(self):
418 pass
419
420 def test_basics(self):
421 values = Values()
422 self.assertEqual(vars(values), {})
423 self.assertEqual(values, {})
424 self.assertNotEqual(values, {"foo": "bar"})
425 self.assertNotEqual(values, "")
426
427 dict = {"foo": "bar", "baz": 42}
428 values = Values(defaults=dict)
429 self.assertEqual(vars(values), dict)
430 self.assertEqual(values, dict)
431 self.assertNotEqual(values, {"foo": "bar"})
432 self.assertNotEqual(values, {})
433 self.assertNotEqual(values, "")
434 self.assertNotEqual(values, [])
435
436
Greg Wardeba20e62004-07-31 16:15:44 +0000437class TestTypeAliases(BaseTest):
438 def setUp(self):
439 self.parser = OptionParser()
440
Thomas Wouters477c8d52006-05-27 19:21:47 +0000441 def test_str_aliases_string(self):
442 self.parser.add_option("-s", type="str")
Ezio Melottib3aedd42010-11-20 19:04:17 +0000443 self.assertEqual(self.parser.get_option("-s").type, "string")
Thomas Wouters477c8d52006-05-27 19:21:47 +0000444
Guido van Rossum13257902007-06-07 23:15:56 +0000445 def test_type_object(self):
Thomas Wouters477c8d52006-05-27 19:21:47 +0000446 self.parser.add_option("-s", type=str)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000447 self.assertEqual(self.parser.get_option("-s").type, "string")
Thomas Wouters477c8d52006-05-27 19:21:47 +0000448 self.parser.add_option("-x", type=int)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000449 self.assertEqual(self.parser.get_option("-x").type, "int")
Thomas Wouters477c8d52006-05-27 19:21:47 +0000450
Greg Wardeba20e62004-07-31 16:15:44 +0000451
452# Custom type for testing processing of default values.
453_time_units = { 's' : 1, 'm' : 60, 'h' : 60*60, 'd' : 60*60*24 }
454
455def _check_duration(option, opt, value):
456 try:
457 if value[-1].isdigit():
458 return int(value)
459 else:
460 return int(value[:-1]) * _time_units[value[-1]]
Georg Brandl89fad142010-03-14 10:23:39 +0000461 except (ValueError, IndexError):
Greg Wardeba20e62004-07-31 16:15:44 +0000462 raise OptionValueError(
463 'option %s: invalid duration: %r' % (opt, value))
464
465class DurationOption(Option):
466 TYPES = Option.TYPES + ('duration',)
467 TYPE_CHECKER = copy.copy(Option.TYPE_CHECKER)
468 TYPE_CHECKER['duration'] = _check_duration
469
470class TestDefaultValues(BaseTest):
471 def setUp(self):
472 self.parser = OptionParser()
473 self.parser.add_option("-v", "--verbose", default=True)
474 self.parser.add_option("-q", "--quiet", dest='verbose')
475 self.parser.add_option("-n", type="int", default=37)
476 self.parser.add_option("-m", type="int")
477 self.parser.add_option("-s", default="foo")
478 self.parser.add_option("-t")
479 self.parser.add_option("-u", default=None)
480 self.expected = { 'verbose': True,
481 'n': 37,
482 'm': None,
483 's': "foo",
484 't': None,
485 'u': None }
486
487 def test_basic_defaults(self):
488 self.assertEqual(self.parser.get_default_values(), self.expected)
489
490 def test_mixed_defaults_post(self):
491 self.parser.set_defaults(n=42, m=-100)
492 self.expected.update({'n': 42, 'm': -100})
493 self.assertEqual(self.parser.get_default_values(), self.expected)
494
495 def test_mixed_defaults_pre(self):
496 self.parser.set_defaults(x="barf", y="blah")
497 self.parser.add_option("-x", default="frob")
498 self.parser.add_option("-y")
499
500 self.expected.update({'x': "frob", 'y': "blah"})
501 self.assertEqual(self.parser.get_default_values(), self.expected)
502
503 self.parser.remove_option("-y")
504 self.parser.add_option("-y", default=None)
505 self.expected.update({'y': None})
506 self.assertEqual(self.parser.get_default_values(), self.expected)
507
508 def test_process_default(self):
509 self.parser.option_class = DurationOption
510 self.parser.add_option("-d", type="duration", default=300)
511 self.parser.add_option("-e", type="duration", default="6m")
512 self.parser.set_defaults(n="42")
513 self.expected.update({'d': 300, 'e': 360, 'n': 42})
514 self.assertEqual(self.parser.get_default_values(), self.expected)
515
516 self.parser.set_process_default_values(False)
517 self.expected.update({'d': 300, 'e': "6m", 'n': "42"})
518 self.assertEqual(self.parser.get_default_values(), self.expected)
519
520
521class TestProgName(BaseTest):
522 """
523 Test that %prog expands to the right thing in usage, version,
524 and help strings.
525 """
526
527 def assertUsage(self, parser, expected_usage):
528 self.assertEqual(parser.get_usage(), expected_usage)
529
530 def assertVersion(self, parser, expected_version):
531 self.assertEqual(parser.get_version(), expected_version)
532
533
534 def test_default_progname(self):
535 # Make sure that program name taken from sys.argv[0] by default.
Tim Peters579f7352004-07-31 21:14:28 +0000536 save_argv = sys.argv[:]
537 try:
Greg Ward48aa84b2004-10-27 02:20:04 +0000538 sys.argv[0] = os.path.join("foo", "bar", "baz.py")
Thomas Wouters477c8d52006-05-27 19:21:47 +0000539 parser = OptionParser("%prog ...", version="%prog 1.2")
540 expected_usage = "Usage: baz.py ...\n"
Tim Peters579f7352004-07-31 21:14:28 +0000541 self.assertUsage(parser, expected_usage)
542 self.assertVersion(parser, "baz.py 1.2")
543 self.assertHelp(parser,
Greg Ward48aa84b2004-10-27 02:20:04 +0000544 expected_usage + "\n" +
Thomas Wouters477c8d52006-05-27 19:21:47 +0000545 "Options:\n"
Greg Ward48aa84b2004-10-27 02:20:04 +0000546 " --version show program's version number and exit\n"
547 " -h, --help show this help message and exit\n")
Tim Peters579f7352004-07-31 21:14:28 +0000548 finally:
549 sys.argv[:] = save_argv
Greg Wardeba20e62004-07-31 16:15:44 +0000550
551 def test_custom_progname(self):
552 parser = OptionParser(prog="thingy",
553 version="%prog 0.1",
554 usage="%prog arg arg")
555 parser.remove_option("-h")
556 parser.remove_option("--version")
Thomas Wouters477c8d52006-05-27 19:21:47 +0000557 expected_usage = "Usage: thingy arg arg\n"
Greg Wardeba20e62004-07-31 16:15:44 +0000558 self.assertUsage(parser, expected_usage)
559 self.assertVersion(parser, "thingy 0.1")
560 self.assertHelp(parser, expected_usage + "\n")
561
562
563class TestExpandDefaults(BaseTest):
564 def setUp(self):
565 self.parser = OptionParser(prog="test")
566 self.help_prefix = """\
Thomas Wouters477c8d52006-05-27 19:21:47 +0000567Usage: test [options]
Greg Wardeba20e62004-07-31 16:15:44 +0000568
Thomas Wouters477c8d52006-05-27 19:21:47 +0000569Options:
Greg Wardeba20e62004-07-31 16:15:44 +0000570 -h, --help show this help message and exit
571"""
572 self.file_help = "read from FILE [default: %default]"
573 self.expected_help_file = self.help_prefix + \
574 " -f FILE, --file=FILE read from FILE [default: foo.txt]\n"
575 self.expected_help_none = self.help_prefix + \
576 " -f FILE, --file=FILE read from FILE [default: none]\n"
577
578 def test_option_default(self):
579 self.parser.add_option("-f", "--file",
580 default="foo.txt",
581 help=self.file_help)
582 self.assertHelp(self.parser, self.expected_help_file)
583
584 def test_parser_default_1(self):
585 self.parser.add_option("-f", "--file",
586 help=self.file_help)
587 self.parser.set_default('file', "foo.txt")
588 self.assertHelp(self.parser, self.expected_help_file)
589
590 def test_parser_default_2(self):
591 self.parser.add_option("-f", "--file",
592 help=self.file_help)
593 self.parser.set_defaults(file="foo.txt")
594 self.assertHelp(self.parser, self.expected_help_file)
595
596 def test_no_default(self):
597 self.parser.add_option("-f", "--file",
598 help=self.file_help)
599 self.assertHelp(self.parser, self.expected_help_none)
600
601 def test_default_none_1(self):
602 self.parser.add_option("-f", "--file",
603 default=None,
604 help=self.file_help)
605 self.assertHelp(self.parser, self.expected_help_none)
Tim Peters10d59f32004-10-27 02:43:25 +0000606
Greg Wardeba20e62004-07-31 16:15:44 +0000607 def test_default_none_2(self):
608 self.parser.add_option("-f", "--file",
609 help=self.file_help)
610 self.parser.set_defaults(file=None)
611 self.assertHelp(self.parser, self.expected_help_none)
612
613 def test_float_default(self):
614 self.parser.add_option(
615 "-p", "--prob",
616 help="blow up with probability PROB [default: %default]")
617 self.parser.set_defaults(prob=0.43)
618 expected_help = self.help_prefix + \
619 " -p PROB, --prob=PROB blow up with probability PROB [default: 0.43]\n"
620 self.assertHelp(self.parser, expected_help)
621
622 def test_alt_expand(self):
623 self.parser.add_option("-f", "--file",
624 default="foo.txt",
625 help="read from FILE [default: *DEFAULT*]")
626 self.parser.formatter.default_tag = "*DEFAULT*"
627 self.assertHelp(self.parser, self.expected_help_file)
628
629 def test_no_expand(self):
630 self.parser.add_option("-f", "--file",
631 default="foo.txt",
632 help="read from %default file")
633 self.parser.formatter.default_tag = None
634 expected_help = self.help_prefix + \
635 " -f FILE, --file=FILE read from %default file\n"
636 self.assertHelp(self.parser, expected_help)
637
Greg Ward55493222003-04-21 02:41:25 +0000638
639# -- Test parser.parse_args() ------------------------------------------
640
641class TestStandard(BaseTest):
642 def setUp(self):
643 options = [make_option("-a", type="string"),
644 make_option("-b", "--boo", type="int", dest='boo'),
645 make_option("--foo", action="append")]
646
Greg Ward48aa84b2004-10-27 02:20:04 +0000647 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
648 option_list=options)
Greg Ward55493222003-04-21 02:41:25 +0000649
650 def test_required_value(self):
Éric Araujo6a1454f2011-03-20 19:59:25 +0100651 self.assertParseFail(["-a"], "-a option requires 1 argument")
Greg Ward55493222003-04-21 02:41:25 +0000652
653 def test_invalid_integer(self):
654 self.assertParseFail(["-b", "5x"],
655 "option -b: invalid integer value: '5x'")
656
657 def test_no_such_option(self):
658 self.assertParseFail(["--boo13"], "no such option: --boo13")
659
660 def test_long_invalid_integer(self):
661 self.assertParseFail(["--boo=x5"],
662 "option --boo: invalid integer value: 'x5'")
663
664 def test_empty(self):
665 self.assertParseOK([], {'a': None, 'boo': None, 'foo': None}, [])
666
667 def test_shortopt_empty_longopt_append(self):
668 self.assertParseOK(["-a", "", "--foo=blah", "--foo="],
669 {'a': "", 'boo': None, 'foo': ["blah", ""]},
670 [])
671
672 def test_long_option_append(self):
673 self.assertParseOK(["--foo", "bar", "--foo", "", "--foo=x"],
674 {'a': None,
675 'boo': None,
676 'foo': ["bar", "", "x"]},
677 [])
678
679 def test_option_argument_joined(self):
680 self.assertParseOK(["-abc"],
681 {'a': "bc", 'boo': None, 'foo': None},
682 [])
683
684 def test_option_argument_split(self):
685 self.assertParseOK(["-a", "34"],
686 {'a': "34", 'boo': None, 'foo': None},
687 [])
688
689 def test_option_argument_joined_integer(self):
690 self.assertParseOK(["-b34"],
691 {'a': None, 'boo': 34, 'foo': None},
692 [])
693
694 def test_option_argument_split_negative_integer(self):
695 self.assertParseOK(["-b", "-5"],
696 {'a': None, 'boo': -5, 'foo': None},
697 [])
698
699 def test_long_option_argument_joined(self):
700 self.assertParseOK(["--boo=13"],
701 {'a': None, 'boo': 13, 'foo': None},
702 [])
703
704 def test_long_option_argument_split(self):
705 self.assertParseOK(["--boo", "111"],
706 {'a': None, 'boo': 111, 'foo': None},
707 [])
708
709 def test_long_option_short_option(self):
710 self.assertParseOK(["--foo=bar", "-axyz"],
711 {'a': 'xyz', 'boo': None, 'foo': ["bar"]},
712 [])
713
714 def test_abbrev_long_option(self):
715 self.assertParseOK(["--f=bar", "-axyz"],
716 {'a': 'xyz', 'boo': None, 'foo': ["bar"]},
717 [])
718
719 def test_defaults(self):
720 (options, args) = self.parser.parse_args([])
721 defaults = self.parser.get_default_values()
722 self.assertEqual(vars(defaults), vars(options))
723
724 def test_ambiguous_option(self):
725 self.parser.add_option("--foz", action="store",
726 type="string", dest="foo")
Greg Ward55493222003-04-21 02:41:25 +0000727 self.assertParseFail(["--f=bar"],
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000728 "ambiguous option: --f (--foo, --foz?)")
Greg Ward55493222003-04-21 02:41:25 +0000729
730
731 def test_short_and_long_option_split(self):
732 self.assertParseOK(["-a", "xyz", "--foo", "bar"],
733 {'a': 'xyz', 'boo': None, 'foo': ["bar"]},
Victor Stinner3fa1aae2013-03-26 01:14:08 +0100734 [])
Greg Ward55493222003-04-21 02:41:25 +0000735
736 def test_short_option_split_long_option_append(self):
737 self.assertParseOK(["--foo=bar", "-b", "123", "--foo", "baz"],
738 {'a': None, 'boo': 123, 'foo': ["bar", "baz"]},
739 [])
740
741 def test_short_option_split_one_positional_arg(self):
742 self.assertParseOK(["-a", "foo", "bar"],
743 {'a': "foo", 'boo': None, 'foo': None},
Victor Stinner3fa1aae2013-03-26 01:14:08 +0100744 ["bar"])
Greg Ward55493222003-04-21 02:41:25 +0000745
746 def test_short_option_consumes_separator(self):
747 self.assertParseOK(["-a", "--", "foo", "bar"],
748 {'a': "--", 'boo': None, 'foo': None},
Victor Stinner3fa1aae2013-03-26 01:14:08 +0100749 ["foo", "bar"])
Thomas Wouters477c8d52006-05-27 19:21:47 +0000750 self.assertParseOK(["-a", "--", "--foo", "bar"],
751 {'a': "--", 'boo': None, 'foo': ["bar"]},
Victor Stinner3fa1aae2013-03-26 01:14:08 +0100752 [])
Greg Ward55493222003-04-21 02:41:25 +0000753
754 def test_short_option_joined_and_separator(self):
755 self.assertParseOK(["-ab", "--", "--foo", "bar"],
756 {'a': "b", 'boo': None, 'foo': None},
757 ["--foo", "bar"]),
758
Thomas Wouters477c8d52006-05-27 19:21:47 +0000759 def test_hyphen_becomes_positional_arg(self):
Greg Ward55493222003-04-21 02:41:25 +0000760 self.assertParseOK(["-ab", "-", "--foo", "bar"],
761 {'a': "b", 'boo': None, 'foo': ["bar"]},
762 ["-"])
763
764 def test_no_append_versus_append(self):
765 self.assertParseOK(["-b3", "-b", "5", "--foo=bar", "--foo", "baz"],
766 {'a': None, 'boo': 5, 'foo': ["bar", "baz"]},
767 [])
768
769 def test_option_consumes_optionlike_string(self):
770 self.assertParseOK(["-a", "-b3"],
771 {'a': "-b3", 'boo': None, 'foo': None},
772 [])
773
R. David Murray80972692010-06-26 00:17:12 +0000774 def test_combined_single_invalid_option(self):
775 self.parser.add_option("-t", action="store_true")
776 self.assertParseFail(["-test"],
R. David Murray76af4022010-06-26 03:34:33 +0000777 "no such option: -e")
R. David Murray80972692010-06-26 00:17:12 +0000778
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 Brandla8867b42010-07-31 21:26:40 +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 Brandla8867b42010-07-31 21:26:40 +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")
Thomas Wouters477c8d52006-05-27 19:21:47 +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
Thomas Wouters477c8d52006-05-27 19:21:47 +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 Petersonc9c0f202009-06-30 23:06:06 +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
Thomas Wouters477c8d52006-05-27 19:21:47 +00001024 def tearDown(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001025 if os.path.isdir(support.TESTFN):
1026 os.rmdir(support.TESTFN)
1027 elif os.path.isfile(support.TESTFN):
1028 os.unlink(support.TESTFN)
Thomas Wouters477c8d52006-05-27 19:21:47 +00001029
Greg Ward55493222003-04-21 02:41:25 +00001030 class MyOption (Option):
Thomas Wouters477c8d52006-05-27 19:21:47 +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
Thomas Wouters477c8d52006-05-27 19:21:47 +00001042 def test_filetype_ok(self):
Victor Stinnerbf816222011-06-30 23:25:47 +02001043 support.create_empty_file(support.TESTFN)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001044 self.assertParseOK(["--file", support.TESTFN, "-afoo"],
1045 {'file': support.TESTFN, 'a': 'foo'},
Greg Ward55493222003-04-21 02:41:25 +00001046 [])
1047
Thomas Wouters477c8d52006-05-27 19:21:47 +00001048 def test_filetype_noexist(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001049 self.assertParseFail(["--file", support.TESTFN, "-afoo"],
Greg Ward55493222003-04-21 02:41:25 +00001050 "%s: file does not exist" %
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001051 support.TESTFN)
Greg Ward55493222003-04-21 02:41:25 +00001052
Thomas Wouters477c8d52006-05-27 19:21:47 +00001053 def test_filetype_notfile(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001054 os.mkdir(support.TESTFN)
1055 self.assertParseFail(["--file", support.TESTFN, "-afoo"],
Greg Ward55493222003-04-21 02:41:25 +00001056 "%s: not a regular file" %
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001057 support.TESTFN)
Thomas Wouters477c8d52006-05-27 19:21:47 +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
Thomas Wouters477c8d52006-05-27 19:21:47 +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 Petersonc9c0f202009-06-30 23:06:06 +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 Petersonc9c0f202009-06-30 23:06:06 +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
Thomas Wouters477c8d52006-05-27 19:21:47 +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
Thomas Wouters477c8d52006-05-27 19:21:47 +00001153 def process_tuple(self, option, opt, value, parser_, len, type):
Greg Ward55493222003-04-21 02:41:25 +00001154 self.assertEqual(len, 3)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +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
Thomas Wouters477c8d52006-05-27 19:21:47 +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
Thomas Wouters477c8d52006-05-27 19:21:47 +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
Thomas Wouters477c8d52006-05-27 19:21:47 +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
Thomas Wouters477c8d52006-05-27 19:21:47 +00001245 def variable_args(self, option, opt, value, parser):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +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
Thomas Wouters477c8d52006-05-27 19:21:47 +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 Petersonc9c0f202009-06-30 23:06:06 +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 Petersonc9c0f202009-06-30 23:06:06 +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 Petersonc9c0f202009-06-30 23:06:06 +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 Petersonc9c0f202009-06-30 23:06:06 +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"], """\
Thomas Wouters477c8d52006-05-27 19:21:47 +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"], """\
Thomas Wouters477c8d52006-05-27 19:21:47 +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 = """\
Thomas Wouters477c8d52006-05-27 19:21:47 +00001399Usage: bar.py [options]
Greg Wardeba20e62004-07-31 16:15:44 +00001400
Thomas Wouters477c8d52006-05-27 19:21:47 +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 = """\
Thomas Wouters477c8d52006-05-27 19:21:47 +00001410Usage: bar.py [options]
Greg Wardeba20e62004-07-31 16:15:44 +00001411
Thomas Wouters477c8d52006-05-27 19:21:47 +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
Thomas Wouters477c8d52006-05-27 19:21:47 +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 = """\
Thomas Wouters477c8d52006-05-27 19:21:47 +00001435Usage: bar.py [options]
Greg Wardeba20e62004-07-31 16:15:44 +00001436
Thomas Wouters477c8d52006-05-27 19:21:47 +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 Storchakaf4511122014-01-09 23:14:27 +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 ]
Thomas Wouters0e3f5912006-08-11 14:57:12 +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.
Hirokazu Yamamoto71959632009-04-27 01:44:28 +00001501 with support.EnvironmentVarGuard() as env:
Walter Dörwald155374d2009-05-01 19:58:58 +00001502 env['COLUMNS'] = str(columns)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001503 return InterceptingOptionParser(option_list=options)
Greg Ward55493222003-04-21 02:41:25 +00001504
1505 def assertHelpEquals(self, expected_output):
Greg Ward48aa84b2004-10-27 02:20:04 +00001506 save_argv = sys.argv[:]
1507 try:
1508 # Make optparse believe bar.py is being executed.
1509 sys.argv[0] = os.path.join("foo", "bar.py")
1510 self.assertOutput(["-h"], expected_output)
1511 finally:
1512 sys.argv[:] = save_argv
Greg Ward55493222003-04-21 02:41:25 +00001513
1514 def test_help(self):
Greg Wardeba20e62004-07-31 16:15:44 +00001515 self.assertHelpEquals(_expected_help_basic)
Greg Ward55493222003-04-21 02:41:25 +00001516
1517 def test_help_old_usage(self):
Thomas Wouters477c8d52006-05-27 19:21:47 +00001518 self.parser.set_usage("Usage: %prog [options]")
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_long_opts_first(self):
1522 self.parser.formatter.short_first = 0
Greg Wardeba20e62004-07-31 16:15:44 +00001523 self.assertHelpEquals(_expected_help_long_opts_first)
Greg Ward55493222003-04-21 02:41:25 +00001524
1525 def test_help_title_formatter(self):
Hirokazu Yamamoto71959632009-04-27 01:44:28 +00001526 with support.EnvironmentVarGuard() as env:
Walter Dörwald155374d2009-05-01 19:58:58 +00001527 env["COLUMNS"] = "80"
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001528 self.parser.formatter = TitledHelpFormatter()
1529 self.assertHelpEquals(_expected_help_title_formatter)
Greg Ward55493222003-04-21 02:41:25 +00001530
Greg Wardeba20e62004-07-31 16:15:44 +00001531 def test_wrap_columns(self):
1532 # Ensure that wrapping respects $COLUMNS environment variable.
1533 # Need to reconstruct the parser, since that's the only time
1534 # we look at $COLUMNS.
1535 self.parser = self.make_parser(60)
1536 self.assertHelpEquals(_expected_help_short_lines)
Serhiy Storchakaf4511122014-01-09 23:14:27 +02001537 self.parser = self.make_parser(0)
1538 self.assertHelpEquals(_expected_very_help_short_lines)
Greg Ward55493222003-04-21 02:41:25 +00001539
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001540 def test_help_unicode(self):
1541 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
Guido van Rossumef87d6e2007-05-02 19:09:54 +00001542 self.parser.add_option("-a", action="store_true", help="ol\u00E9!")
1543 expect = """\
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001544Options:
1545 -h, --help show this help message and exit
1546 -a ol\u00E9!
1547"""
1548 self.assertHelpEquals(expect)
1549
1550 def test_help_unicode_description(self):
1551 self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
Guido van Rossumef87d6e2007-05-02 19:09:54 +00001552 description="ol\u00E9!")
1553 expect = """\
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001554ol\u00E9!
1555
1556Options:
1557 -h, --help show this help message and exit
1558"""
1559 self.assertHelpEquals(expect)
1560
Greg Ward55493222003-04-21 02:41:25 +00001561 def test_help_description_groups(self):
1562 self.parser.set_description(
Greg Wardeba20e62004-07-31 16:15:44 +00001563 "This is the program description for %prog. %prog has "
Greg Ward55493222003-04-21 02:41:25 +00001564 "an option group as well as single options.")
1565
1566 group = OptionGroup(
1567 self.parser, "Dangerous Options",
1568 "Caution: use of these options is at your own risk. "
1569 "It is believed that some of them bite.")
1570 group.add_option("-g", action="store_true", help="Group option.")
1571 self.parser.add_option_group(group)
1572
Thomas Wouters477c8d52006-05-27 19:21:47 +00001573 expect = """\
1574Usage: bar.py [options]
Greg Ward55493222003-04-21 02:41:25 +00001575
Greg Wardeba20e62004-07-31 16:15:44 +00001576This is the program description for bar.py. bar.py has an option group as
1577well as single options.
1578
Thomas Wouters477c8d52006-05-27 19:21:47 +00001579Options:
Greg Wardeba20e62004-07-31 16:15:44 +00001580 -a APPLE throw APPLEs at basket
1581 -b NUM, --boo=NUM shout "boo!" NUM times (in order to frighten away all the
1582 evil spirits that cause trouble and mayhem)
1583 --foo=FOO store FOO in the foo list for later fooing
1584 -h, --help show this help message and exit
Greg Ward55493222003-04-21 02:41:25 +00001585
1586 Dangerous Options:
Greg Wardeba20e62004-07-31 16:15:44 +00001587 Caution: use of these options is at your own risk. It is believed
1588 that some of them bite.
1589
1590 -g Group option.
Thomas Wouters477c8d52006-05-27 19:21:47 +00001591"""
Greg Ward55493222003-04-21 02:41:25 +00001592
Thomas Wouters477c8d52006-05-27 19:21:47 +00001593 self.assertHelpEquals(expect)
Greg Wardeba20e62004-07-31 16:15:44 +00001594
Thomas Wouters477c8d52006-05-27 19:21:47 +00001595 self.parser.epilog = "Please report bugs to /dev/null."
1596 self.assertHelpEquals(expect + "\nPlease report bugs to /dev/null.\n")
Tim Peters10d59f32004-10-27 02:43:25 +00001597
Greg Wardeba20e62004-07-31 16:15:44 +00001598
Greg Ward55493222003-04-21 02:41:25 +00001599class TestMatchAbbrev(BaseTest):
1600 def test_match_abbrev(self):
1601 self.assertEqual(_match_abbrev("--f",
1602 {"--foz": None,
1603 "--foo": None,
1604 "--fie": None,
1605 "--f": None}),
1606 "--f")
1607
1608 def test_match_abbrev_error(self):
1609 s = "--f"
1610 wordmap = {"--foz": None, "--foo": None, "--fie": None}
Greg Wardeba20e62004-07-31 16:15:44 +00001611 self.assertRaises(
1612 _match_abbrev, (s, wordmap), None,
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001613 BadOptionError, "ambiguous option: --f (--fie, --foo, --foz?)")
Greg Wardeba20e62004-07-31 16:15:44 +00001614
1615
Thomas Wouters477c8d52006-05-27 19:21:47 +00001616class TestParseNumber(BaseTest):
1617 def setUp(self):
1618 self.parser = InterceptingOptionParser()
1619 self.parser.add_option("-n", type=int)
Guido van Rossume2a383d2007-01-15 16:59:06 +00001620 self.parser.add_option("-l", type=int)
Thomas Wouters477c8d52006-05-27 19:21:47 +00001621
1622 def test_parse_num_fail(self):
1623 self.assertRaises(
1624 _parse_num, ("", int), {},
1625 ValueError,
1626 re.compile(r"invalid literal for int().*: '?'?"))
1627 self.assertRaises(
Guido van Rossume2a383d2007-01-15 16:59:06 +00001628 _parse_num, ("0xOoops", int), {},
Thomas Wouters477c8d52006-05-27 19:21:47 +00001629 ValueError,
Guido van Rossumb4e87e32007-07-09 10:08:42 +00001630 re.compile(r"invalid literal for int().*: s?'?0xOoops'?"))
Thomas Wouters477c8d52006-05-27 19:21:47 +00001631
1632 def test_parse_num_ok(self):
1633 self.assertEqual(_parse_num("0", int), 0)
1634 self.assertEqual(_parse_num("0x10", int), 16)
Guido van Rossume2a383d2007-01-15 16:59:06 +00001635 self.assertEqual(_parse_num("0XA", int), 10)
1636 self.assertEqual(_parse_num("010", int), 8)
Thomas Wouters477c8d52006-05-27 19:21:47 +00001637 self.assertEqual(_parse_num("0b11", int), 3)
Guido van Rossume2a383d2007-01-15 16:59:06 +00001638 self.assertEqual(_parse_num("0b", int), 0)
Thomas Wouters477c8d52006-05-27 19:21:47 +00001639
1640 def test_numeric_options(self):
1641 self.assertParseOK(["-n", "42", "-l", "0x20"],
1642 { "n": 42, "l": 0x20 }, [])
1643 self.assertParseOK(["-n", "0b0101", "-l010"],
1644 { "n": 5, "l": 8 }, [])
1645 self.assertParseFail(["-n008"],
1646 "option -n: invalid integer value: '008'")
1647 self.assertParseFail(["-l0b0123"],
Guido van Rossumddefaf32007-01-14 03:31:43 +00001648 "option -l: invalid integer value: '0b0123'")
Thomas Wouters477c8d52006-05-27 19:21:47 +00001649 self.assertParseFail(["-l", "0x12x"],
Guido van Rossumddefaf32007-01-14 03:31:43 +00001650 "option -l: invalid integer value: '0x12x'")
Thomas Wouters477c8d52006-05-27 19:21:47 +00001651
1652
Greg Ward55493222003-04-21 02:41:25 +00001653def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001654 support.run_unittest(__name__)
Greg Ward55493222003-04-21 02:41:25 +00001655
1656if __name__ == '__main__':
Guido van Rossumd8faa362007-04-27 19:54:29 +00001657 test_main()