diff options
author | Jenkins <jenkins@review.openstack.org> | 2015-10-09 17:54:34 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2015-10-09 17:54:35 +0000 |
commit | ddaddba5e5f6499608836b646e6435c15756ec70 (patch) | |
tree | 5dfb133ada346d72a0a4c4f9d0de6a1e0acf29a0 | |
parent | 1996532041e95f022762e025355ca9f538afaa14 (diff) | |
parent | 62ea3339acbbf79ff2012201614686a1f7fe8c9e (diff) | |
download | oslo-config-ddaddba5e5f6499608836b646e6435c15756ec70.tar.gz |
Merge "Case insensitiveness when comparing choices values"2.5.0
-rw-r--r-- | oslo_config/tests/test_types.py | 25 | ||||
-rw-r--r-- | oslo_config/types.py | 33 |
2 files changed, 54 insertions, 4 deletions
diff --git a/oslo_config/tests/test_types.py b/oslo_config/tests/test_types.py index 8546d7d..49d63e1 100644 --- a/oslo_config/tests/test_types.py +++ b/oslo_config/tests/test_types.py @@ -126,6 +126,31 @@ class StringTypeTests(TypeTestHelper, unittest.TestCase): t2 = types.String(regex=re.compile("^[a-z]")) self.assertFalse(t1 == t2) + def test_ignore_case(self): + self.type_instance = types.String(choices=['foo', 'bar'], + ignore_case=True) + self.assertConvertedValue('Foo', 'Foo') + self.assertConvertedValue('bAr', 'bAr') + + def test_ignore_case_raises(self): + self.type_instance = types.String(choices=['foo', 'bar'], + ignore_case=False) + self.assertRaises(ValueError, self.assertConvertedValue, 'Foo', 'Foo') + + def test_regex_and_ignore_case(self): + self.type_instance = types.String(regex=re.compile("^[A-Z]"), + ignore_case=True) + self.assertConvertedValue("foo", "foo") + + def test_regex_and_ignore_case_str(self): + self.type_instance = types.String(regex="^[A-Z]", ignore_case=True) + self.assertConvertedValue("foo", "foo") + + def test_regex_preserve_flags(self): + self.type_instance = types.String(regex=re.compile("^[A-Z]", re.I), + ignore_case=False) + self.assertConvertedValue("foo", "foo") + class BooleanTypeTests(TypeTestHelper, unittest.TestCase): type = types.Boolean() diff --git a/oslo_config/types.py b/oslo_config/types.py index 6245eec..99f42f3 100644 --- a/oslo_config/types.py +++ b/oslo_config/types.py @@ -48,18 +48,36 @@ class String(ConfigType): :param regex: Optional regular expression (string or compiled regex) that the value must match on an unanchored search. Mutually exclusive with 'choices'. + :param ignore_case: If True case differences (uppercase vs. lowercase) + between 'choices' or 'regex' will be ignored; + defaults to False. """ BASE_TYPES = six.string_types - def __init__(self, choices=None, quotes=False, regex=None): + def __init__(self, choices=None, quotes=False, regex=None, + ignore_case=False): super(String, self).__init__() if choices and regex: raise ValueError("'choices' and 'regex' cannot both be specified") - self.choices = choices + self.ignore_case = ignore_case self.quotes = quotes - self.regex = re.compile(regex) if regex is not None else None + + self.choices = choices + self.lower_case_choices = None + if self.choices is not None and self.ignore_case: + self.lower_case_choices = [c.lower() for c in choices] + + self.regex = regex + if self.regex is not None: + re_flags = re.IGNORECASE if self.ignore_case else 0 + + # Check if regex is a string or an already compiled regex + if isinstance(regex, six.string_types): + self.regex = re.compile(regex, re_flags) + else: + self.regex = re.compile(regex.pattern, re_flags | regex.flags) def __call__(self, value): value = str(value) @@ -73,7 +91,14 @@ class String(ConfigType): raise ValueError("Value %r doesn't match regex %r" % (value, self.regex.pattern)) - if self.choices is None or value in self.choices: + if self.choices is None: + return value + + # Check for case insensitive + processed_value, choices = ((value.lower(), self.lower_case_choices) + if self.ignore_case else + (value, self.choices)) + if processed_value in choices: return value raise ValueError( |