00001 from __future__ import absolute_import, division, print_function, with_statement
00002
00003 import datetime
00004 import os
00005 import sys
00006
00007 from tornado.options import OptionParser, Error
00008 from tornado.util import basestring_type
00009 from tornado.test.util import unittest
00010
00011 try:
00012 from cStringIO import StringIO
00013 except ImportError:
00014 from io import StringIO
00015
00016 try:
00017 from unittest import mock
00018 except ImportError:
00019 try:
00020 import mock
00021 except ImportError:
00022 mock = None
00023
00024
00025 class OptionsTest(unittest.TestCase):
00026 def test_parse_command_line(self):
00027 options = OptionParser()
00028 options.define("port", default=80)
00029 options.parse_command_line(["main.py", "--port=443"])
00030 self.assertEqual(options.port, 443)
00031
00032 def test_parse_config_file(self):
00033 options = OptionParser()
00034 options.define("port", default=80)
00035 options.parse_config_file(os.path.join(os.path.dirname(__file__),
00036 "options_test.cfg"))
00037 self.assertEquals(options.port, 443)
00038
00039 def test_parse_callbacks(self):
00040 options = OptionParser()
00041 self.called = False
00042
00043 def callback():
00044 self.called = True
00045 options.add_parse_callback(callback)
00046
00047
00048 options.parse_command_line(["main.py"], final=False)
00049 self.assertFalse(self.called)
00050
00051
00052 options.parse_command_line(["main.py"])
00053 self.assertTrue(self.called)
00054
00055
00056
00057 self.called = False
00058 options.parse_command_line(["main.py"])
00059 self.assertTrue(self.called)
00060
00061 def test_help(self):
00062 options = OptionParser()
00063 try:
00064 orig_stderr = sys.stderr
00065 sys.stderr = StringIO()
00066 with self.assertRaises(SystemExit):
00067 options.parse_command_line(["main.py", "--help"])
00068 usage = sys.stderr.getvalue()
00069 finally:
00070 sys.stderr = orig_stderr
00071 self.assertIn("Usage:", usage)
00072
00073 def test_subcommand(self):
00074 base_options = OptionParser()
00075 base_options.define("verbose", default=False)
00076 sub_options = OptionParser()
00077 sub_options.define("foo", type=str)
00078 rest = base_options.parse_command_line(
00079 ["main.py", "--verbose", "subcommand", "--foo=bar"])
00080 self.assertEqual(rest, ["subcommand", "--foo=bar"])
00081 self.assertTrue(base_options.verbose)
00082 rest2 = sub_options.parse_command_line(rest)
00083 self.assertEqual(rest2, [])
00084 self.assertEqual(sub_options.foo, "bar")
00085
00086
00087 try:
00088 orig_stderr = sys.stderr
00089 sys.stderr = StringIO()
00090 with self.assertRaises(Error):
00091 sub_options.parse_command_line(["subcommand", "--verbose"])
00092 finally:
00093 sys.stderr = orig_stderr
00094
00095 def test_setattr(self):
00096 options = OptionParser()
00097 options.define('foo', default=1, type=int)
00098 options.foo = 2
00099 self.assertEqual(options.foo, 2)
00100
00101 def test_setattr_type_check(self):
00102
00103
00104 options = OptionParser()
00105 options.define('foo', default=1, type=int)
00106 with self.assertRaises(Error):
00107 options.foo = '2'
00108
00109 def test_setattr_with_callback(self):
00110 values = []
00111 options = OptionParser()
00112 options.define('foo', default=1, type=int, callback=values.append)
00113 options.foo = 2
00114 self.assertEqual(values, [2])
00115
00116 def _sample_options(self):
00117 options = OptionParser()
00118 options.define('a', default=1)
00119 options.define('b', default=2)
00120 return options
00121
00122 def test_iter(self):
00123 options = self._sample_options()
00124
00125 self.assertEqual(set(['a', 'b', 'help']), set(iter(options)))
00126
00127 def test_getitem(self):
00128 options = self._sample_options()
00129 self.assertEqual(1, options['a'])
00130
00131 def test_items(self):
00132 options = self._sample_options()
00133
00134 expected = [('a', 1), ('b', 2), ('help', options.help)]
00135 actual = sorted(options.items())
00136 self.assertEqual(expected, actual)
00137
00138 def test_as_dict(self):
00139 options = self._sample_options()
00140 expected = {'a': 1, 'b': 2, 'help': options.help}
00141 self.assertEqual(expected, options.as_dict())
00142
00143 def test_group_dict(self):
00144 options = OptionParser()
00145 options.define('a', default=1)
00146 options.define('b', group='b_group', default=2)
00147
00148 frame = sys._getframe(0)
00149 this_file = frame.f_code.co_filename
00150 self.assertEqual(set(['b_group', '', this_file]), options.groups())
00151
00152 b_group_dict = options.group_dict('b_group')
00153 self.assertEqual({'b': 2}, b_group_dict)
00154
00155 self.assertEqual({}, options.group_dict('nonexistent'))
00156
00157 @unittest.skipIf(mock is None, 'mock package not present')
00158 def test_mock_patch(self):
00159
00160 options = OptionParser()
00161 options.define('foo', default=1)
00162 options.parse_command_line(['main.py', '--foo=2'])
00163 self.assertEqual(options.foo, 2)
00164
00165 with mock.patch.object(options.mockable(), 'foo', 3):
00166 self.assertEqual(options.foo, 3)
00167 self.assertEqual(options.foo, 2)
00168
00169
00170 with mock.patch.object(options.mockable(), 'foo', 4):
00171 self.assertEqual(options.foo, 4)
00172 options.foo = 5
00173 self.assertEqual(options.foo, 5)
00174 with mock.patch.object(options.mockable(), 'foo', 6):
00175 self.assertEqual(options.foo, 6)
00176 self.assertEqual(options.foo, 5)
00177 self.assertEqual(options.foo, 2)
00178
00179 def test_types(self):
00180 options = OptionParser()
00181 options.define('str', type=str)
00182 options.define('basestring', type=basestring_type)
00183 options.define('int', type=int)
00184 options.define('float', type=float)
00185 options.define('datetime', type=datetime.datetime)
00186 options.define('timedelta', type=datetime.timedelta)
00187 options.parse_command_line(['main.py',
00188 '--str=asdf',
00189 '--basestring=qwer',
00190 '--int=42',
00191 '--float=1.5',
00192 '--datetime=2013-04-28 05:16',
00193 '--timedelta=45s'])
00194 self.assertEqual(options.str, 'asdf')
00195 self.assertEqual(options.basestring, 'qwer')
00196 self.assertEqual(options.int, 42)
00197 self.assertEqual(options.float, 1.5)
00198 self.assertEqual(options.datetime,
00199 datetime.datetime(2013, 4, 28, 5, 16))
00200 self.assertEqual(options.timedelta, datetime.timedelta(seconds=45))
00201
00202 def test_multiple_string(self):
00203 options = OptionParser()
00204 options.define('foo', type=str, multiple=True)
00205 options.parse_command_line(['main.py', '--foo=a,b,c'])
00206 self.assertEqual(options.foo, ['a', 'b', 'c'])
00207
00208 def test_multiple_int(self):
00209 options = OptionParser()
00210 options.define('foo', type=int, multiple=True)
00211 options.parse_command_line(['main.py', '--foo=1,3,5:7'])
00212 self.assertEqual(options.foo, [1, 3, 5, 6, 7])
00213
00214 def test_error_redefine(self):
00215 options = OptionParser()
00216 options.define('foo')
00217 with self.assertRaises(Error) as cm:
00218 options.define('foo')
00219 self.assertRegexpMatches(str(cm.exception),
00220 'Option.*foo.*already defined')