Bug 1264482 - Add a string type with a limited set of possible values. r?ted
--- a/python/mozbuild/mozbuild/test/test_util.py
+++ b/python/mozbuild/mozbuild/test/test_util.py
@@ -25,16 +25,18 @@ from mozbuild.util import (
group_unified_files,
hash_file,
memoize,
memoized_property,
pair,
resolve_target_to_make,
MozbuildDeletionError,
HierarchicalStringList,
+ LimitedComparisonError,
+ LimitedString,
ListWithAction,
StrictOrderingOnAppendList,
StrictOrderingOnAppendListWithFlagsFactory,
TypedList,
TypedNamedTuple,
UnsortedError,
)
@@ -856,11 +858,35 @@ class TestMisc(unittest.TestCase):
self.assertEqual(
expand_variables('before $(string) between $(list) after', {
'string': 'abc',
'list': ['a', 'b', 'c']
}),
'before abc between a b c after'
)
+class TestLimitedString(unittest.TestCase):
+ def test_string(self):
+ class CompilerType(LimitedString):
+ POSSIBLE_VALUES = ('msvc', 'gcc', 'clang', 'clang-cl')
+
+ type = CompilerType('msvc')
+ self.assertEquals(type, 'msvc')
+ self.assertNotEquals(type, 'gcc')
+ self.assertNotEquals(type, 'clang')
+ self.assertNotEquals(type, 'clang-cl')
+ self.assertIn(type, ('msvc', 'clang-cl'))
+ self.assertNotIn(type, ('gcc', 'clang'))
+
+ with self.assertRaises(LimitedComparisonError):
+ self.assertEquals(type, 'foo')
+
+ with self.assertRaises(LimitedComparisonError):
+ self.assertNotEquals(type, 'foo')
+
+ with self.assertRaises(LimitedComparisonError):
+ self.assertIn(type, ('foo', 'gcc'))
+
+ with self.assertRaises(ValueError):
+ type = CompilerType('foo')
if __name__ == '__main__':
main()
--- a/python/mozbuild/mozbuild/util.py
+++ b/python/mozbuild/mozbuild/util.py
@@ -1116,8 +1116,36 @@ class DefinesAction(argparse.Action):
if len(values) == 1:
name, value = values[0], 1
else:
name, value = values
if value.isdigit():
value = int(value)
defines[name] = value
setattr(namespace, self.dest, defines)
+
+
+class LimitedComparisonError(Exception):
+ pass
+
+
+class LimitedString(unicode):
+ '''A string type that only can have a limited set of values, and can only
+ be compared against that set of values.
+
+ The class is meant to be subclassed, where the subclass defines
+ POSSIBLE_VALUES.
+ '''
+ POSSIBLE_VALUES = ()
+ def __init__(self, value):
+ if value not in self.POSSIBLE_VALUES:
+ raise ValueError("'%s' is not a valid value for %s"
+ % (value, self.__class__.__name__))
+
+ def __eq__(self, other):
+ if other not in self.POSSIBLE_VALUES:
+ raise LimitedComparisonError(
+ 'Can only compare with %s'
+ % ', '.join("'%s'" % v for v in self.POSSIBLE_VALUES))
+ return super(LimitedString, self).__eq__(other)
+
+ def __ne__(self, other):
+ return not (self == other)