summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2015-10-09 17:54:34 +0000
committerGerrit Code Review <review@openstack.org>2015-10-09 17:54:35 +0000
commitddaddba5e5f6499608836b646e6435c15756ec70 (patch)
tree5dfb133ada346d72a0a4c4f9d0de6a1e0acf29a0
parent1996532041e95f022762e025355ca9f538afaa14 (diff)
parent62ea3339acbbf79ff2012201614686a1f7fe8c9e (diff)
downloadoslo-config-ddaddba5e5f6499608836b646e6435c15756ec70.tar.gz
Merge "Case insensitiveness when comparing choices values"2.5.0
-rw-r--r--oslo_config/tests/test_types.py25
-rw-r--r--oslo_config/types.py33
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(