Back to index

python-cliapp  1.20120630
settings_tests.py
Go to the documentation of this file.
00001 # Copyright (C) 2009-2012  Lars Wirzenius
00002 # 
00003 # This program is free software; you can redistribute it and/or modify
00004 # it under the terms of the GNU General Public License as published by
00005 # the Free Software Foundation; either version 2 of the License, or
00006 # (at your option) any later version.
00007 # 
00008 # This program is distributed in the hope that it will be useful,
00009 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 # GNU General Public License for more details.
00012 # 
00013 # You should have received a copy of the GNU General Public License along
00014 # with this program; if not, write to the Free Software Foundation, Inc.,
00015 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00016 
00017 
00018 import optparse
00019 import StringIO
00020 import sys
00021 import unittest
00022 
00023 import cliapp
00024 
00025 
00026 class SettingsTests(unittest.TestCase):
00027 
00028     def setUp(self):
00029         self.settings = cliapp.Settings('appname', '1.0')
00030         
00031     def test_has_progname(self):
00032         self.assertEqual(self.settings.progname, 'appname')
00033         
00034     def test_sets_progname(self):
00035         self.settings.progname = 'foo'
00036         self.assertEqual(self.settings.progname, 'foo')
00037         
00038     def test_has_version(self):
00039         self.assertEqual(self.settings.version, '1.0')
00040 
00041     def test_sets_usage_from_func(self):
00042         s = cliapp.Settings('appname', '1.0', usage=lambda: 'xyzzy')
00043         p = s.build_parser()
00044         self.assert_('xyzzy' in p.usage)
00045 
00046     def test_adds_default_options_and_settings(self):
00047         self.assert_('output' in self.settings)
00048         self.assert_('log' in self.settings)
00049         self.assert_('log-level' in self.settings)
00050 
00051     def test_iterates_over_canonical_settings_names(self):
00052         known = ['output', 'log', 'log-level']
00053         self.assertEqual(sorted(x for x in self.settings if x in known),
00054                          sorted(known))
00055 
00056     def test_keys_returns_canonical_names(self):
00057         known = ['output', 'log', 'log-level']
00058         self.assertEqual(sorted(x for x in self.settings.keys() if x in known),
00059                          sorted(known))
00060 
00061     def test_parses_options(self):
00062         self.settings.string(['foo'], 'foo help', group='foo')
00063         self.settings.boolean(['bar'], 'bar help')
00064         self.settings.parse_args(['--foo=foovalue', '--bar'])
00065         self.assertEqual(self.settings['foo'], 'foovalue')
00066         self.assertEqual(self.settings['bar'], True)
00067 
00068     def test_does_not_have_foo_setting_by_default(self):
00069         self.assertFalse('foo' in self.settings)
00070 
00071     def test_raises_keyerror_for_getting_unknown_setting(self):
00072         self.assertRaises(KeyError, self.settings.__getitem__, 'foo')
00073 
00074     def test_raises_keyerror_for_setting_unknown_setting(self):
00075         self.assertRaises(KeyError, self.settings.__setitem__, 'foo', 'bar')
00076 
00077     def test_adds_string_setting(self):
00078         self.settings.string(['foo'], 'foo help')
00079         self.assert_('foo' in self.settings)
00080 
00081     def test_adds_string_list_setting(self):
00082         self.settings.string_list(['foo'], 'foo help')
00083         self.assert_('foo' in self.settings)
00084 
00085     def test_string_list_is_empty_list_by_default(self):
00086         self.settings.string_list(['foo'], '')
00087         self.settings.parse_args([])
00088         self.assertEqual(self.settings['foo'], [])
00089 
00090     def test_string_list_parses_one_item(self):
00091         self.settings.string_list(['foo'], '')
00092         self.settings.parse_args(['--foo=foo'])
00093         self.assertEqual(self.settings['foo'], ['foo'])
00094 
00095     def test_string_list_parses_two_items(self):
00096         self.settings.string_list(['foo'], '')
00097         self.settings.parse_args(['--foo=foo', '--foo', 'bar'])
00098         self.assertEqual(self.settings['foo'], ['foo', 'bar'])
00099 
00100     def test_string_list_uses_nonempty_default_if_given(self):
00101         self.settings.string_list(['foo'], '', default=['bar'])
00102         self.settings.parse_args([])
00103         self.assertEqual(self.settings['foo'], ['bar'])
00104 
00105     def test_string_list_uses_ignores_default_if_user_provides_values(self):
00106         self.settings.string_list(['foo'], '', default=['bar'])
00107         self.settings.parse_args(['--foo=pink', '--foo=punk'])
00108         self.assertEqual(self.settings['foo'], ['pink', 'punk'])
00109 
00110     def test_adds_choice_setting(self):
00111         self.settings.choice(['foo'], ['foo', 'bar'], 'foo help')
00112         self.assert_('foo' in self.settings)
00113 
00114     def test_choice_defaults_to_first_one(self):
00115         self.settings.choice(['foo'], ['foo', 'bar'], 'foo help')
00116         self.settings.parse_args([])
00117         self.assertEqual(self.settings['foo'], 'foo')
00118 
00119     def test_choice_accepts_any_valid_value(self):
00120         self.settings.choice(['foo'], ['foo', 'bar'], 'foo help')
00121         self.settings.parse_args(['--foo=foo'])
00122         self.assertEqual(self.settings['foo'], 'foo')
00123         self.settings.parse_args(['--foo=bar'])
00124         self.assertEqual(self.settings['foo'], 'bar')
00125 
00126     def test_choice_raises_error_for_unacceptable_value(self):
00127         self.settings.choice(['foo'], ['foo', 'bar'], 'foo help')
00128         self.assertRaises(SystemExit,
00129                           self.settings.parse_args, ['--foo=xyzzy'],
00130                           suppress_errors=True)
00131 
00132     def test_adds_boolean_setting(self):
00133         self.settings.boolean(['foo'], 'foo help')
00134         self.assert_('foo' in self.settings)
00135         
00136     def test_boolean_setting_is_false_by_default(self):
00137         self.settings.boolean(['foo'], 'foo help')
00138         self.assertFalse(self.settings['foo'])
00139         
00140     def test_sets_boolean_setting_to_true_for_many_true_values(self):
00141         self.settings.boolean(['foo'], 'foo help')
00142         self.settings['foo'] = True
00143         self.assert_(self.settings['foo'])
00144         self.settings['foo'] = 1
00145         self.assert_(self.settings['foo'])
00146         
00147     def test_sets_boolean_setting_to_false_for_many_false_values(self):
00148         self.settings.boolean(['foo'], 'foo help')
00149         self.settings['foo'] = False
00150         self.assertFalse(self.settings['foo'])
00151         self.settings['foo'] = 0
00152         self.assertFalse(self.settings['foo'])
00153         self.settings['foo'] = ()
00154         self.assertFalse(self.settings['foo'])
00155         self.settings['foo'] = []
00156         self.assertFalse(self.settings['foo'])
00157         self.settings['foo'] = ''
00158         self.assertFalse(self.settings['foo'])
00159 
00160     def test_sets_boolean_to_true_from_config_file(self):
00161         def fake_open(filename):
00162             return StringIO.StringIO('[config]\nfoo = yes\n')
00163         self.settings.boolean(['foo'], 'foo help')
00164         self.settings.load_configs(open=fake_open)
00165         self.assertEqual(self.settings['foo'], True)
00166         
00167     def test_sets_boolean_to_false_from_config_file(self):
00168         def fake_open(filename):
00169             return StringIO.StringIO('[config]\nfoo = False\n')
00170         self.settings.boolean(['foo'], 'foo help')
00171         self.settings.load_configs(open=fake_open)
00172         self.assertEqual(self.settings['foo'], False)
00173         
00174     def test_adds_bytesize_setting(self):
00175         self.settings.bytesize(['foo'], 'foo help')
00176         self.assert_('foo' in self.settings)
00177 
00178     def test_parses_bytesize_option(self):
00179         self.settings.bytesize(['foo'], 'foo help')
00180 
00181         self.settings.parse_args(args=['--foo=xyzzy'])
00182         self.assertEqual(self.settings['foo'], 0)
00183 
00184         self.settings.parse_args(args=['--foo=123'])
00185         self.assertEqual(self.settings['foo'], 123)
00186 
00187         self.settings.parse_args(args=['--foo=123k'])
00188         self.assertEqual(self.settings['foo'], 123 * 1000)
00189 
00190         self.settings.parse_args(args=['--foo=123m'])
00191         self.assertEqual(self.settings['foo'], 123 * 1000**2)
00192 
00193         self.settings.parse_args(args=['--foo=123g'])
00194         self.assertEqual(self.settings['foo'], 123 * 1000**3)
00195 
00196         self.settings.parse_args(args=['--foo=123t'])
00197         self.assertEqual(self.settings['foo'], 123 * 1000**4)
00198 
00199         self.settings.parse_args(args=['--foo=123kib'])
00200         self.assertEqual(self.settings['foo'], 123 * 1024)
00201 
00202         self.settings.parse_args(args=['--foo=123mib'])
00203         self.assertEqual(self.settings['foo'], 123 * 1024**2)
00204 
00205         self.settings.parse_args(args=['--foo=123gib'])
00206         self.assertEqual(self.settings['foo'], 123 * 1024**3)
00207 
00208         self.settings.parse_args(args=['--foo=123tib'])
00209         self.assertEqual(self.settings['foo'], 123 * 1024**4)
00210         
00211     def test_adds_integer_setting(self):
00212         self.settings.integer(['foo'], 'foo help')
00213         self.assert_('foo' in self.settings)
00214 
00215     def test_parses_integer_option(self):
00216         self.settings.integer(['foo'], 'foo help', default=123)
00217 
00218         self.settings.parse_args(args=[])
00219         self.assertEqual(self.settings['foo'], 123)
00220 
00221         self.settings.parse_args(args=['--foo=123'])
00222         self.assertEqual(self.settings['foo'], 123)
00223 
00224     def test_has_list_of_default_config_files(self):
00225         defaults = self.settings._default_config_files
00226         self.assert_(isinstance(defaults, list))
00227         self.assert_(len(defaults) > 0)
00228 
00229     def test_listconfs_returns_empty_list_for_nonexistent_directory(self):
00230         self.assertEqual(self.settings._listconfs('notexist'), [])
00231 
00232     def test_listconfs_lists_config_files_only(self):
00233         def mock_listdir(dirname):
00234             return ['foo.conf', 'foo.notconf']
00235         names = self.settings._listconfs('.', listdir=mock_listdir)
00236         self.assertEqual(names, ['./foo.conf'])
00237 
00238     def test_listconfs_sorts_names_in_C_locale(self):
00239         def mock_listdir(dirname):
00240             return ['foo.conf', 'bar.conf']
00241         names = self.settings._listconfs('.', listdir=mock_listdir)
00242         self.assertEqual(names, ['./bar.conf', './foo.conf'])
00243 
00244     def test_has_config_files_attribute(self):
00245         self.assertEqual(self.settings.config_files,
00246                          self.settings._default_config_files)
00247 
00248     def test_has_config_files_list_can_be_changed(self):
00249         self.settings.config_files += ['./foo']
00250         self.assertEqual(self.settings.config_files,
00251                          self.settings._default_config_files + ['./foo'])
00252 
00253     def test_loads_config_files(self):
00254     
00255         def mock_open(filename, mode=None):
00256             return StringIO.StringIO('''\
00257 [config]
00258 foo = yeehaa
00259 ''')
00260     
00261         self.settings.string(['foo'], 'foo help')
00262         self.settings.config_files = ['whatever.conf']
00263         self.settings.load_configs(open=mock_open)
00264         self.assertEqual(self.settings['foo'], 'yeehaa')
00265 
00266     def test_loads_string_list_from_config_files(self):
00267     
00268         def mock_open(filename, mode=None):
00269             return StringIO.StringIO('''\
00270 [config]
00271 foo = yeehaa
00272 bar = ping, pong
00273 ''')
00274     
00275         self.settings.string_list(['foo'], 'foo help')
00276         self.settings.string_list(['bar'], 'bar help')
00277         self.settings.config_files = ['whatever.conf']
00278         self.settings.load_configs(open=mock_open)
00279         self.assertEqual(self.settings['foo'], ['yeehaa'])
00280         self.assertEqual(self.settings['bar'], ['ping', 'pong'])
00281 
00282     def test_handles_defaults_with_config_files(self):
00283     
00284         def mock_open(filename, mode=None):
00285             return StringIO.StringIO('''\
00286 [config]
00287 ''')
00288     
00289         self.settings.string(['foo'], 'foo help', default='foo')
00290         self.settings.string_list(['bar'], 'bar help', default=['bar'])
00291         self.settings.config_files = ['whatever.conf']
00292         self.settings.load_configs(open=mock_open)
00293         self.assertEqual(self.settings['foo'], 'foo')
00294         self.assertEqual(self.settings['bar'], ['bar'])
00295 
00296     def test_handles_overridden_defaults_with_config_files(self):
00297     
00298         def mock_open(filename, mode=None):
00299             return StringIO.StringIO('''\
00300 [config]
00301 foo = yeehaa
00302 bar = ping, pong
00303 ''')
00304     
00305         self.settings.string(['foo'], 'foo help', default='foo')
00306         self.settings.string_list(['bar'], 'bar help', default=['bar'])
00307         self.settings.config_files = ['whatever.conf']
00308         self.settings.load_configs(open=mock_open)
00309         self.assertEqual(self.settings['foo'], 'yeehaa')
00310         self.assertEqual(self.settings['bar'], ['ping', 'pong'])
00311 
00312     def test_handles_values_from_config_files_overridden_on_command_line(self):
00313     
00314         def mock_open(filename, mode=None):
00315             return StringIO.StringIO('''\
00316 [config]
00317 foo = yeehaa
00318 bar = ping, pong
00319 ''')
00320     
00321         self.settings.string(['foo'], 'foo help', default='foo')
00322         self.settings.string_list(['bar'], 'bar help', default=['bar'])
00323         self.settings.config_files = ['whatever.conf']
00324         self.settings.load_configs(open=mock_open)
00325         self.settings.parse_args(['--foo=red', '--bar=blue', '--bar=white'])
00326         self.assertEqual(self.settings['foo'], 'red')
00327         self.assertEqual(self.settings['bar'], ['blue', 'white'])
00328 
00329     def test_load_configs_ignore_errors_opening_a_file(self):
00330         
00331         def mock_open(filename, mode=None):
00332             raise IOError()
00333             
00334         self.assertEqual(self.settings.load_configs(open=mock_open), None)
00335 
00336     def test_adds_config_file_with_dash_dash_config(self):
00337         self.settings.parse_args(['--config=foo.conf'])
00338         self.assertEqual(self.settings.config_files,
00339                          self.settings._default_config_files + ['foo.conf'])
00340 
00341     def test_ignores_default_configs(self):
00342         self.settings.parse_args(['--no-default-configs'])
00343         self.assertEqual(self.settings.config_files, [])
00344 
00345     def test_ignores_then_adds_configs_works(self):
00346         self.settings.parse_args(['--no-default-configs', '--config=foo.conf'])
00347         self.assertEqual(self.settings.config_files, ['foo.conf'])
00348 
00349     def test_require_raises_error_if_string_unset(self):
00350         self.settings.string(['foo'], 'foo help', default=None)
00351         self.assertRaises(cliapp.AppException, self.settings.require, 
00352                           'foo')
00353 
00354     def test_require_is_ok_with_set_string(self):
00355         self.settings.string(['foo'], 'foo help', default=None)
00356         self.settings['foo'] = 'bar'
00357         self.assertEqual(self.settings.require('foo'), None)
00358 
00359     def test_require_is_ok_with_default_string(self):
00360         self.settings.string(['foo'], 'foo help', default='foo default')
00361         self.assertEqual(self.settings.require('foo'), None)
00362 
00363     def test_require_raises_error_if_string_list_unset(self):
00364         self.settings.string_list(['foo'], 'foo help')
00365         self.assertRaises(cliapp.AppException, self.settings.require, 'foo')
00366 
00367     def test_require_is_ok_with_set_string_list(self):
00368         self.settings.string(['foo'], 'foo help')
00369         self.settings['foo'] = ['foo', 'bar']
00370         self.assertEqual(self.settings.require('foo'), None)
00371 
00372     def test_require_is_ok_with_default_string_list(self):
00373         self.settings.string(['foo'], 'foo help', default=['foo'])
00374         self.assertEqual(self.settings.require('foo'), None)
00375 
00376     def test_require_is_ok_with_unset_choice(self):
00377         self.settings.choice(['foo'], ['foo', 'bar'], 'foo help')
00378         self.assertEqual(self.settings.require('foo'), None)
00379 
00380     def test_require_is_ok_with_unset_boolean(self):
00381         self.settings.boolean(['foo'], 'foo help')
00382         self.assertEqual(self.settings.require('foo'), None)
00383 
00384     def test_require_is_ok_with_unset_bytesize(self):
00385         self.settings.bytesize(['foo'], 'foo help')
00386         self.assertEqual(self.settings.require('foo'), None)
00387 
00388     def test_require_is_ok_with_unset_integer(self):
00389         self.settings.integer(['foo'], 'foo help')
00390         self.assertEqual(self.settings.require('foo'), None)
00391 
00392     def test_exports_configparser_with_settings(self):
00393         self.settings.integer(['foo'], 'foo help', default=1)
00394         self.settings.string(['bar'], 'bar help', default='yo')
00395         cp = self.settings.as_cp()
00396         self.assertEqual(cp.get('config', 'foo'), '1')
00397         self.assertEqual(cp.get('config', 'bar'), 'yo')
00398 
00399     def test_exports_all_config_sections_via_as_cp(self):
00400     
00401         def mock_open(filename, mode=None):
00402             return StringIO.StringIO('''\
00403 [config]
00404 foo = yeehaa
00405 
00406 [other]
00407 bar = dodo
00408 ''')
00409     
00410         self.settings.string(['foo'], 'foo help', default='foo')
00411         self.settings.config_files = ['whatever.conf']
00412         self.settings.load_configs(open=mock_open)
00413         cp = self.settings.as_cp()
00414 
00415         self.assertEqual(sorted(cp.sections()), ['config', 'other'])
00416         self.assertEqual(cp.get('config', 'foo'), 'yeehaa')
00417         self.assertEqual(cp.options('other'), ['bar'])
00418         self.assertEqual(cp.get('other', 'bar'), 'dodo')
00419