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:
committed by
Michael Still
parent
45e4d3a574
commit
1a5dff21da
@@ -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())
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user