diff --git a/oslo_config/cfg.py b/oslo_config/cfg.py index bc572003..9fc13d8a 100644 --- a/oslo_config/cfg.py +++ b/oslo_config/cfg.py @@ -409,6 +409,7 @@ import os import string import sys +import debtcollector from debtcollector import removals import six from six import moves @@ -2479,11 +2480,8 @@ class ConfigOpts(collections.Mapping): :raises: NoSuchOptError, NoSuchGroupError """ opt_info = self._get_opt_info(name, group) - if enforce_type and override is not None: - opt_info['override'] = self._convert_value(override, - opt_info['opt']) - else: - opt_info['override'] = override + opt_info['override'] = self._get_enforced_type_value( + opt_info['opt'], override, enforce_type) @__clear_cache def set_default(self, name, default, group=None, enforce_type=False): @@ -2501,11 +2499,28 @@ class ConfigOpts(collections.Mapping): :raises: NoSuchOptError, NoSuchGroupError """ opt_info = self._get_opt_info(name, group) - if enforce_type and default is not None: - opt_info['default'] = self._convert_value(default, - opt_info['opt']) + opt_info['default'] = self._get_enforced_type_value( + opt_info['opt'], default, enforce_type) + + def _get_enforced_type_value(self, opt, value, enforce_type): + if value is None: + return None + try: + converted = self._convert_value(value, opt) + except (ValueError, TypeError): + if enforce_type: + raise + debtcollector.deprecate( + "The argument enforce_type is changing its " + "default value to True and then will be removed completely, " + "please fix the invalid %s value '%s' for option '%s'." + % (repr(opt.type), value, opt.name), + version=4.0 + ) + if enforce_type: + return converted else: - opt_info['default'] = default + return value @__clear_cache def clear_override(self, name, group=None): diff --git a/oslo_config/tests/test_cfg.py b/oslo_config/tests/test_cfg.py index 188d69e0..4c2f48bf 100644 --- a/oslo_config/tests/test_cfg.py +++ b/oslo_config/tests/test_cfg.py @@ -2993,6 +2993,21 @@ class OverridesTestCase(BaseTestCase): self.conf.clear_default('foo') self.assertEqual('foo', self.conf.foo) + @mock.patch('debtcollector.deprecate') + def test_deprecation_wrong_type_default(self, deprecate): + self.conf.register_opt(cfg.IntOpt('foo', default=1)) + self.conf([]) + self.assertEqual(1, self.conf.foo) + self.conf.set_default('foo', "not_really_a_int") + self.assertEqual('not_really_a_int', self.conf.foo) + self.conf.clear_default('foo') + self.assertEqual(1, self.conf.foo) + deprecate.assert_called_once_with( + "The argument enforce_type is changing its default value to True " + "and then will be removed completely, please fix the invalid " + "Integer value 'not_really_a_int' for option 'foo'.", + version=4.0) + def test_override(self): self.conf.register_opt(cfg.StrOpt('foo')) self.conf.set_override('foo', 'bar') @@ -3070,6 +3085,20 @@ class OverridesTestCase(BaseTestCase): self.conf.clear_override('foo') self.assertIsNone(self.conf.foo) + @mock.patch('debtcollector.deprecate') + def test_deprecation_wrong_type_override(self, deprecate): + self.conf.register_opt(cfg.IntOpt('foo')) + self.conf.set_override('foo', "not_really_a_int") + self.conf([]) + self.assertEqual('not_really_a_int', self.conf.foo) + self.conf.clear_override('foo') + self.assertIsNone(self.conf.foo) + deprecate.assert_called_once_with( + "The argument enforce_type is changing its default value to True " + "and then will be removed completely, please fix the invalid " + "Integer value 'not_really_a_int' for option 'foo'.", + version=4.0) + def test_set_override_in_choices(self): self.conf.register_group(cfg.OptGroup('f')) self.conf.register_cli_opt(cfg.StrOpt('oo', choices=('a', 'b')),