Add enum fieldtype field

In some case, one field should be limited to some value, like the
cpu architect field.

Make sure that when the value limitation is changed,
the fingerprint will be changed, so that a version bump should happen.

Change-Id: I7848f8b934c169a76b1cfd875f7905273f9f914b
Implements: blueprint resource-objects
This commit is contained in:
yunhong jiang
2015-01-15 14:17:41 -08:00
committed by Michael Still
parent 45e4d3a574
commit 1a5dff21da
2 changed files with 105 additions and 3 deletions

View File

@@ -252,6 +252,24 @@ class String(FieldType):
return '\'%s\'' % value
class Enum(String):
def __init__(self, valid_values=None, **kwargs):
self._valid_values = valid_values
super(Enum, self).__init__(**kwargs)
def coerce(self, obj, attr, value):
if self._valid_values and value not in self._valid_values:
msg = _("Field value %s is invalid") % value
raise ValueError(msg)
return super(Enum, self).coerce(obj, attr, value)
def stringify(self, value):
if self._valid_values and value not in self._valid_values:
msg = _("Field value %s is invalid") % value
raise ValueError(msg)
return super(Enum, self).stringify(value)
class UUID(FieldType):
@staticmethod
def coerce(obj, attr, value):
@@ -572,6 +590,24 @@ class StringField(AutoTypedField):
AUTO_TYPE = String()
class EnumField(AutoTypedField):
def __init__(self, valid_values=None, **kwargs):
self.AUTO_TYPE = Enum(valid_values=valid_values)
super(EnumField, self).__init__(**kwargs)
def __repr__(self):
valid_values = self._type._valid_values
args = {
'nullable': self._nullable,
'default': self._default,
}
if valid_values:
args.update({'valid_values': valid_values})
return '%s(%s)' % (self._type.__class__.__name__,
','.join(['%s=%s' % (k, v)
for k, v in args.items()]))
class UUIDField(AutoTypedField):
AUTO_TYPE = UUID()
@@ -636,6 +672,24 @@ class ListOfStringsField(AutoTypedField):
AUTO_TYPE = List(String())
class ListOfEnumField(AutoTypedField):
def __init__(self, valid_values=None, **kwargs):
self.AUTO_TYPE = List(Enum(valid_values=valid_values))
super(ListOfEnumField, self).__init__(**kwargs)
def __repr__(self):
valid_values = self._type._element_type._type._valid_values
args = {
'nullable': self._nullable,
'default': self._default,
}
if valid_values:
args.update({'valid_values': valid_values})
return '%s(%s)' % (self._type.__class__.__name__,
','.join(['%s=%s' % (k, v)
for k, v in args.items()]))
class SetOfIntegersField(AutoTypedField):
AUTO_TYPE = Set(Integer())

View File

@@ -72,7 +72,7 @@ class TestField(test.NoDBTestCase):
class TestString(TestField):
def setUp(self):
super(TestField, self).setUp()
super(TestString, self).setUp()
self.field = fields.StringField()
self.coerce_good_values = [('foo', 'foo'), (1, '1'), (1L, '1'),
(True, 'True')]
@@ -84,9 +84,34 @@ class TestString(TestField):
self.assertEqual("'123'", self.field.stringify(123))
class TestEnum(TestField):
def setUp(self):
super(TestEnum, self).setUp()
self.field = fields.EnumField(
valid_values=['foo', 'bar', 1, 1L, True])
self.coerce_good_values = [('foo', 'foo'), (1, '1'), (1L, '1'),
(True, 'True')]
self.coerce_bad_values = ['boo', 2, False]
self.to_primitive_values = self.coerce_good_values[0:1]
self.from_primitive_values = self.coerce_good_values[0:1]
def test_stringify(self):
self.assertEqual("'foo'", self.field.stringify('foo'))
def test_stringify_invalid(self):
self.assertRaises(ValueError, self.field.stringify, '123')
def test_fingerprint(self):
# Notes(yjiang5): make sure changing valid_value will be detected
# in test_objects.test_versions
field1 = fields.EnumField(valid_values=['foo', 'bar'])
field2 = fields.EnumField(valid_values=['foo', 'bar1'])
self.assertNotEqual(str(field1), str(field2))
class TestInteger(TestField):
def setUp(self):
super(TestField, self).setUp()
super(TestInteger, self).setUp()
self.field = fields.IntegerField()
self.coerce_good_values = [(1, 1), ('1', 1)]
self.coerce_bad_values = ['foo', None]
@@ -106,7 +131,7 @@ class TestFloat(TestField):
class TestBoolean(TestField):
def setUp(self):
super(TestField, self).setUp()
super(TestBoolean, self).setUp()
self.field = fields.BooleanField()
self.coerce_good_values = [(True, True), (False, False), (1, True),
('foo', True), (0, False), ('', False)]
@@ -286,6 +311,29 @@ class TestListOfStrings(TestField):
self.assertEqual("['abc']", self.field.stringify(['abc']))
class TestListOfEnum(TestField):
def setUp(self):
super(TestListOfEnum, self).setUp()
self.field = fields.ListOfEnumField(valid_values=['foo', 'bar'])
self.coerce_good_values = [(['foo', 'bar'], ['foo', 'bar'])]
self.coerce_bad_values = ['foo', ['foo', 'bar1']]
self.to_primitive_values = [(['foo'], ['foo'])]
self.from_primitive_values = [(['foo'], ['foo'])]
def test_stringify(self):
self.assertEqual("['foo']", self.field.stringify(['foo']))
def test_stringify_invalid(self):
self.assertRaises(ValueError, self.field.stringify, '[abc]')
def test_fingerprint(self):
# Notes(yjiang5): make sure changing valid_value will be detected
# in test_objects.test_versions
field1 = fields.ListOfEnumField(valid_values=['foo', 'bar'])
field2 = fields.ListOfEnumField(valid_values=['foo', 'bar1'])
self.assertNotEqual(str(field1), str(field2))
class TestSet(TestField):
def setUp(self):
super(TestSet, self).setUp()