From d193c657441f24506f75b9ce1248c8fdebd295f3 Mon Sep 17 00:00:00 2001 From: Takashi Kajinami Date: Wed, 10 Apr 2024 15:21:29 +0900 Subject: [PATCH] Dict: Support customizing key-value separator Some projects implements their own mechanism to parse dict values from list because they use different separators between key and value. For example, nova provides the [libvirt] disk_cachemode option, and this option takes a value written in the following format. [libvirt] disk_cachemode=key1=value1,key2=value2 Introduce the new key_value_separator parameter to allow using a different separator, so that DictOpt can be used for such usage. Change-Id: Iec977e21088b1ced9ad0df05638a459af8cdda2a --- oslo_config/tests/test_types.py | 6 ++++++ oslo_config/types.py | 19 +++++++++++++++---- ...-key-value-separator-127ce36ba4d9245f.yaml | 5 +++++ 3 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 releasenotes/notes/dict-key-value-separator-127ce36ba4d9245f.yaml diff --git a/oslo_config/tests/test_types.py b/oslo_config/tests/test_types.py index dd56b98f..7ef3439f 100644 --- a/oslo_config/tests/test_types.py +++ b/oslo_config/tests/test_types.py @@ -662,6 +662,12 @@ class DictTypeTests(TypeTestHelper, unittest.TestCase): {'foo': 'bar, baz', 'bam': 'quux'}) + def test_custom_separator(self): + self.type_instance = types.Dict(key_value_separator='=') + self.assertConvertedValue(' foo=bar, baz= 123 ', + {'foo': 'bar', + 'baz': '123'}) + def test_dict_of_dicts(self): self.type_instance = types.Dict( types.Dict(types.String(), bounds=True) diff --git a/oslo_config/types.py b/oslo_config/types.py index 6176c69d..9fef13af 100644 --- a/oslo_config/types.py +++ b/oslo_config/types.py @@ -612,9 +612,14 @@ class Dict(ConfigType): .. versionchanged:: 2.7 Added *type_name* parameter. + + .. versionchanged:: 9.5 + + Added *key_value_separator* parameter. """ - def __init__(self, value_type=None, bounds=False, type_name='dict value'): + def __init__(self, value_type=None, bounds=False, type_name='dict value', + key_value_separator=':'): super(Dict, self).__init__(type_name=type_name) if value_type is None: @@ -622,8 +627,13 @@ class Dict(ConfigType): if not callable(value_type): raise TypeError('value_type must be callable') + + if key_value_separator == ',': + raise TypeError('key_value_separator should not be \',\'') + self.value_type = value_type self.bounds = bounds + self.key_value_separator = key_value_separator def __call__(self, value): if isinstance(value, dict): @@ -649,11 +659,12 @@ class Dict(ConfigType): while True: first_error = None try: - key_value = pair.split(':', 1) + key_value = pair.split(self.key_value_separator, 1) if len(key_value) < 2: - raise ValueError('Value should be NAME:VALUE pairs ' - 'separated by ","') + raise ValueError( + 'Value should be NAME%sVALUE pairs ' + 'separated by ","' % self.key_value_separator) key, value = key_value key = key.strip() diff --git a/releasenotes/notes/dict-key-value-separator-127ce36ba4d9245f.yaml b/releasenotes/notes/dict-key-value-separator-127ce36ba4d9245f.yaml new file mode 100644 index 00000000..a7caf09c --- /dev/null +++ b/releasenotes/notes/dict-key-value-separator-127ce36ba4d9245f.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + ``Dict`` type now supports the ``key_value_separator`` parameter. This + parameter allows using a customized separator between key and value.