Merge "Adds new fields and field types"
This commit is contained in:
@@ -385,6 +385,15 @@ class Integer(FieldType):
|
||||
return {'type': ['integer']}
|
||||
|
||||
|
||||
class NonNegativeInteger(FieldType):
|
||||
@staticmethod
|
||||
def coerce(obj, attr, value):
|
||||
v = int(value)
|
||||
if v < 0:
|
||||
raise ValueError(_('Value must be >= 0 for field %s') % attr)
|
||||
return v
|
||||
|
||||
|
||||
class Float(FieldType):
|
||||
def coerce(self, obj, attr, value):
|
||||
return float(value)
|
||||
@@ -393,6 +402,15 @@ class Float(FieldType):
|
||||
return {'type': ['number']}
|
||||
|
||||
|
||||
class NonNegativeFloat(FieldType):
|
||||
@staticmethod
|
||||
def coerce(obj, attr, value):
|
||||
v = float(value)
|
||||
if v < 0:
|
||||
raise ValueError(_('Value must be >= 0 for field %s') % attr)
|
||||
return v
|
||||
|
||||
|
||||
class Boolean(FieldType):
|
||||
@staticmethod
|
||||
def coerce(obj, attr, value):
|
||||
@@ -482,6 +500,17 @@ class IPV6Address(IPAddress):
|
||||
return result
|
||||
|
||||
|
||||
class IPV4AndV6Address(IPAddress):
|
||||
@staticmethod
|
||||
def coerce(obj, attr, value):
|
||||
result = IPAddress.coerce(obj, attr, value)
|
||||
if result.version != 4 and result.version != 6:
|
||||
raise ValueError(_('Network "%(val)s" is not valid '
|
||||
'in field %(attr)s') %
|
||||
{'val': value, 'attr': attr})
|
||||
return result
|
||||
|
||||
|
||||
class IPNetwork(IPAddress):
|
||||
@staticmethod
|
||||
def coerce(obj, attr, value):
|
||||
@@ -898,10 +927,18 @@ class IntegerField(AutoTypedField):
|
||||
AUTO_TYPE = Integer()
|
||||
|
||||
|
||||
class NonNegativeIntegerField(AutoTypedField):
|
||||
AUTO_TYPE = NonNegativeInteger()
|
||||
|
||||
|
||||
class FloatField(AutoTypedField):
|
||||
AUTO_TYPE = Float()
|
||||
|
||||
|
||||
class NonNegativeFloatField(AutoTypedField):
|
||||
AUTO_TYPE = NonNegativeFloat()
|
||||
|
||||
|
||||
# This is a strict interpretation of boolean
|
||||
# values using Python's semantics for truth/falsehood
|
||||
class BooleanField(AutoTypedField):
|
||||
@@ -968,6 +1005,10 @@ class ListOfSetsOfIntegersField(AutoTypedField):
|
||||
AUTO_TYPE = List(Set(Integer()))
|
||||
|
||||
|
||||
class ListOfIntegersField(AutoTypedField):
|
||||
AUTO_TYPE = List(Integer())
|
||||
|
||||
|
||||
class ListOfDictOfNullableStringsField(AutoTypedField):
|
||||
AUTO_TYPE = List(Dict(String(), nullable=True))
|
||||
|
||||
@@ -998,6 +1039,10 @@ class IPV6AddressField(AutoTypedField):
|
||||
AUTO_TYPE = IPV6Address()
|
||||
|
||||
|
||||
class IPV4AndV6AddressField(AutoTypedField):
|
||||
AUTO_TYPE = IPV4AndV6Address()
|
||||
|
||||
|
||||
class IPNetworkField(AutoTypedField):
|
||||
AUTO_TYPE = IPNetwork()
|
||||
|
||||
|
||||
@@ -444,6 +444,16 @@ class TestInteger(TestField):
|
||||
self.field.get_schema())
|
||||
|
||||
|
||||
class TestNonNegativeInteger(TestField):
|
||||
def setUp(self):
|
||||
super(TestNonNegativeInteger, self).setUp()
|
||||
self.field = fields.NonNegativeIntegerField()
|
||||
self.coerce_good_values = [(1, 1), ('1', 1)]
|
||||
self.coerce_bad_values = ['-2', '4.2', 'foo', None]
|
||||
self.to_primitive_values = self.coerce_good_values[0:1]
|
||||
self.from_primitive_values = self.coerce_good_values[0:1]
|
||||
|
||||
|
||||
class TestFloat(TestField):
|
||||
def setUp(self):
|
||||
super(TestFloat, self).setUp()
|
||||
@@ -461,6 +471,16 @@ class TestFloat(TestField):
|
||||
self.field.get_schema())
|
||||
|
||||
|
||||
class TestNonNegativeFloat(TestField):
|
||||
def setUp(self):
|
||||
super(TestNonNegativeFloat, self).setUp()
|
||||
self.field = fields.NonNegativeFloatField()
|
||||
self.coerce_good_values = [(1.1, 1.1), ('1.1', 1.1)]
|
||||
self.coerce_bad_values = ['-4.2', 'foo', None]
|
||||
self.to_primitive_values = self.coerce_good_values[0:1]
|
||||
self.from_primitive_values = self.coerce_good_values[0:1]
|
||||
|
||||
|
||||
class TestBoolean(TestField):
|
||||
def setUp(self):
|
||||
super(TestField, self).setUp()
|
||||
@@ -739,6 +759,20 @@ class TestListOfSetsOfIntegers(TestField):
|
||||
self.assertEqual('[set([1,2])]', self.field.stringify([set([1, 2])]))
|
||||
|
||||
|
||||
class TestListOfIntegers(TestField):
|
||||
def setUp(self):
|
||||
super(TestListOfIntegers, self).setUp()
|
||||
self.field = fields.ListOfIntegersField()
|
||||
self.coerce_good_values = [(['1', 2], [1, 2]),
|
||||
([1, 2], [1, 2])]
|
||||
self.coerce_bad_values = [['foo']]
|
||||
self.to_primitive_values = [([1], [1])]
|
||||
self.from_primitive_values = [([1], [1])]
|
||||
|
||||
def test_stringify(self):
|
||||
self.assertEqual('[[1, 2]]', self.field.stringify([[1, 2]]))
|
||||
|
||||
|
||||
class TestLocalMethods(test.TestCase):
|
||||
@mock.patch.object(obj_base.LOG, 'exception')
|
||||
def test__make_class_properties_setter_value_error(self, mock_log):
|
||||
@@ -971,6 +1005,28 @@ class TestIPAddressV6(TestField):
|
||||
netaddr.IPAddress('::1'))]
|
||||
|
||||
|
||||
class TestIPV4AndV6Address(TestField):
|
||||
def setUp(self):
|
||||
super(TestIPV4AndV6Address, self).setUp()
|
||||
self.field = fields.IPV4AndV6Address()
|
||||
self.coerce_good_values = [('::1', netaddr.IPAddress('::1')),
|
||||
(netaddr.IPAddress('::1'),
|
||||
netaddr.IPAddress('::1')),
|
||||
('1.2.3.4',
|
||||
netaddr.IPAddress('1.2.3.4')),
|
||||
(netaddr.IPAddress('1.2.3.4'),
|
||||
netaddr.IPAddress('1.2.3.4'))]
|
||||
self.coerce_bad_values = ['1-2', 'foo']
|
||||
self.to_primitive_values = [(netaddr.IPAddress('::1'),
|
||||
'::1'),
|
||||
(netaddr.IPAddress('1.2.3.4'),
|
||||
'1.2.3.4')]
|
||||
self.from_primitive_values = [('::1',
|
||||
netaddr.IPAddress('::1')),
|
||||
('1.2.3.4',
|
||||
netaddr.IPAddress('1.2.3.4'))]
|
||||
|
||||
|
||||
class TestIPNetwork(TestField):
|
||||
def setUp(self):
|
||||
super(TestIPNetwork, self).setUp()
|
||||
|
||||
Reference in New Issue
Block a user