From b306bf0b91f6ce74f7e24a46746c92bacc53b5fe Mon Sep 17 00:00:00 2001 From: Daniel Mach Date: Mon, 22 Aug 2022 13:36:52 +0200 Subject: [PATCH] Convert defaults to their expected types Fixes problems in reading conf values before the configuration is fully initialized. --- osc/conf.py | 42 ++++++++++++++++++++++++++++++------------ tests/test_conf.py | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 12 deletions(-) create mode 100644 tests/test_conf.py diff --git a/osc/conf.py b/osc/conf.py index 11cd54e5..f7a7a126 100644 --- a/osc/conf.py +++ b/osc/conf.py @@ -196,10 +196,6 @@ if not os.path.isfile('/usr/bin/build') and os.path.isfile('/usr/bin/obs-build') if not os.path.isfile('/usr/lib/build/vc') and os.path.isfile('/usr/lib/obs-build/vc'): DEFAULTS['vc-cmd'] = '/usr/lib/obs-build/vc' -# being global to this module, this dict can be accessed from outside -# it will hold the parsed configuration -config = DEFAULTS.copy() - boolean_opts = ['debug', 'do_package_tracking', 'http_debug', 'post_mortem', 'traceback', 'check_filelist', 'plaintext_passwd', 'checkout_no_colon', 'checkout_rooted', 'check_for_request_on_action', 'linkcontrol', 'show_download_progress', 'request_show_interactive', 'request_show_source_buildstatus', 'review_inherit_group', 'use_keyring', 'gnome_keyring', 'no_verify', 'builtin_signature_check', @@ -210,6 +206,35 @@ integer_opts = ['build-jobs'] api_host_options = ['user', 'pass', 'passx', 'aliases', 'http_headers', 'realname', 'email', 'sslcertck', 'cafile', 'capath', 'trusted_prj', 'downloadurl', 'sshkey'] + +def apply_option_types(config): + """ + Return a copy of `config` dictionary with values converted to their expected types + according to the enumerated option types (boolean_opts, integer_opts). + """ + config = config.copy() + + cp = OscConfigParser.OscConfigParser(config) + cp.add_section("general") + + typed_opts = ((boolean_opts, cp.getboolean), (integer_opts, cp.getint)) + for opts, meth in typed_opts: + for opt in opts: + try: + config[opt] = meth('general', opt) + except ValueError as e: + msg = 'cannot parse \'%s\' setting: %s' % (opt, str(e)) + raise oscerr.ConfigError(msg, conffile) + + return config + + +# being global to this module, this dict can be accessed from outside +# it will hold the parsed configuration +config = DEFAULTS.copy() +config = apply_option_types(config) + + new_conf_template = """ [general] @@ -747,14 +772,7 @@ def get_config(override_conffile=None, config = dict(cp.items('general', raw=1)) config['conffile'] = conffile - typed_opts = ((boolean_opts, cp.getboolean), (integer_opts, cp.getint)) - for opts, meth in typed_opts: - for opt in opts: - try: - config[opt] = meth('general', opt) - except ValueError as e: - msg = 'cannot parse \'%s\' setting: %s' % (opt, str(e)) - raise oscerr.ConfigError(msg, conffile) + config = apply_option_types(config) config['packagecachedir'] = os.path.expanduser(config['packagecachedir']) config['exclude_glob'] = config['exclude_glob'].split() diff --git a/tests/test_conf.py b/tests/test_conf.py new file mode 100644 index 00000000..39e1f4dd --- /dev/null +++ b/tests/test_conf.py @@ -0,0 +1,44 @@ +import importlib +import unittest + +import osc.conf + + +class TestConf(unittest.TestCase): + def setUp(self): + # reset the global `config` in preparation for running the tests + importlib.reload(osc.conf) + + def tearDown(self): + # reset the global `config` to avoid impacting tests from other classes + importlib.reload(osc.conf) + + def test_bool_opts_defaults(self): + opts = osc.conf.boolean_opts + config = osc.conf.config + for opt in opts: + self.assertIsInstance(config[opt], bool, msg=f"option: '{opt}'") + + def test_int_opts_defaults(self): + opts = osc.conf.integer_opts + config = osc.conf.config + for opt in opts: + self.assertIsInstance(config[opt], int, msg=f"option: '{opt}'") + + def test_bool_opts(self): + osc.conf.get_config() + opts = osc.conf.boolean_opts + config = osc.conf.config + for opt in opts: + self.assertIsInstance(config[opt], bool, msg=f"option: '{opt}'") + + def test_int_opts(self): + osc.conf.get_config() + opts = osc.conf.integer_opts + config = osc.conf.config + for opt in opts: + self.assertIsInstance(config[opt], int, msg=f"option: '{opt}'") + + +if __name__ == "__main__": + unittest.main()