Add new parameter choices to Integer type
This is also useful to provide a list of valid values for Integer type Choices option will overlay the options of 'min' and 'max' in repr. Change-Id: I0906b6e2309d751d7c31589fc3da8e5f3026bf64
This commit is contained in:
@@ -242,6 +242,10 @@ class IntegerTypeTests(TypeTestHelper, unittest.TestCase):
|
||||
t = types.Integer(min=0, max=0)
|
||||
self.assertEqual('Integer(min=0, max=0)', repr(t))
|
||||
|
||||
def test_repr_with_choices(self):
|
||||
t = types.Integer(choices=[80, 457], min=0)
|
||||
self.assertEqual('Integer(choices=[80, 457])', repr(t))
|
||||
|
||||
def test_equal(self):
|
||||
self.assertTrue(types.Integer() == types.Integer())
|
||||
|
||||
@@ -256,8 +260,15 @@ class IntegerTypeTests(TypeTestHelper, unittest.TestCase):
|
||||
t2 = types.Integer(min=1, max=123)
|
||||
self.assertTrue(t1 == t2)
|
||||
|
||||
def test_equal_with_same_choices(self):
|
||||
t1 = types.Integer(choices=[80, 457])
|
||||
t2 = types.Integer(choices=[80, 457])
|
||||
self.assertTrue(t1 == t2)
|
||||
|
||||
def test_not_equal(self):
|
||||
self.assertFalse(types.Integer(min=123) == types.Integer(min=456))
|
||||
self.assertFalse(types.Integer(choices=[80, 457]) ==
|
||||
types.Integer(choices=[80, 40]))
|
||||
|
||||
def test_not_equal_to_other_class(self):
|
||||
self.assertFalse(types.Integer() == types.String())
|
||||
@@ -276,6 +287,16 @@ class IntegerTypeTests(TypeTestHelper, unittest.TestCase):
|
||||
types.Integer,
|
||||
min=50, max=0)
|
||||
|
||||
def test_choices_outside_min_and_max(self):
|
||||
self.assertRaises(ValueError,
|
||||
types.Integer,
|
||||
min=0, max=100,
|
||||
choices=[50, -1])
|
||||
self.assertRaises(ValueError,
|
||||
types.Integer,
|
||||
min=0, max=100,
|
||||
choices=[101,50])
|
||||
|
||||
def test_with_max_and_min(self):
|
||||
t = types.Integer(min=123, max=456)
|
||||
self.assertRaises(ValueError, t, 122)
|
||||
@@ -305,6 +326,14 @@ class IntegerTypeTests(TypeTestHelper, unittest.TestCase):
|
||||
self.assertRaises(ValueError, t, 201)
|
||||
self.assertRaises(ValueError, t, -457)
|
||||
|
||||
def test_with_choices(self):
|
||||
t = types.Integer(choices=[80, 457])
|
||||
self.assertRaises(ValueError, t, 1)
|
||||
self.assertRaises(ValueError, t, 200)
|
||||
self.assertRaises(ValueError, t, -457)
|
||||
t(80)
|
||||
t(457)
|
||||
|
||||
|
||||
class FloatTypeTests(TypeTestHelper, unittest.TestCase):
|
||||
type = types.Float()
|
||||
|
||||
@@ -195,20 +195,35 @@ class Integer(ConfigType):
|
||||
:param min: Optional check that value is greater than or equal to min
|
||||
:param max: Optional check that value is less than or equal to max
|
||||
:param type_name: Type name to be used in the sample config file.
|
||||
:param choices: Optional sequence of valid values. This will overlay the
|
||||
'min' and 'max' in repr.
|
||||
|
||||
.. versionchanged:: 2.4
|
||||
The class now honors zero for *min* and *max* parameters.
|
||||
|
||||
.. versionchanged:: 2.7
|
||||
Added *type_name* parameter.
|
||||
|
||||
.. versionchanged:: 3.1
|
||||
Added *choices* parameter.
|
||||
"""
|
||||
|
||||
def __init__(self, min=None, max=None, type_name='integer value'):
|
||||
def __init__(self, min=None, max=None, type_name='integer value',
|
||||
choices=None):
|
||||
super(Integer, self).__init__(type_name=type_name)
|
||||
self.min = min
|
||||
self.max = max
|
||||
self.choices = choices
|
||||
if min is not None and max is not None and max < min:
|
||||
raise ValueError('Max value is less than min value')
|
||||
if choices is not None:
|
||||
choices.sort()
|
||||
if min is not None and choices[0]< min:
|
||||
raise ValueError('minimal of choices is less than '
|
||||
'min value')
|
||||
if max is not None and choices[-1] > max:
|
||||
raise ValueError('maximum of choices is greater than '
|
||||
'max value')
|
||||
|
||||
def __call__(self, value):
|
||||
if not isinstance(value, int):
|
||||
@@ -224,6 +239,12 @@ class Integer(ConfigType):
|
||||
return value
|
||||
|
||||
def _check_range(self, value):
|
||||
if self.choices is not None:
|
||||
if value in self.choices:
|
||||
return
|
||||
else:
|
||||
raise ValueError('Valid values are %r, but found %d' % (
|
||||
self.choices, value))
|
||||
if self.min is not None and value < self.min:
|
||||
raise ValueError('Should be greater than or equal to %d' %
|
||||
self.min)
|
||||
@@ -232,10 +253,13 @@ class Integer(ConfigType):
|
||||
|
||||
def __repr__(self):
|
||||
props = []
|
||||
if self.min is not None:
|
||||
props.append('min=%d' % self.min)
|
||||
if self.max is not None:
|
||||
props.append('max=%d' % self.max)
|
||||
if self.choices is not None:
|
||||
props.append("choices=%r" % self.choices)
|
||||
else:
|
||||
if self.min is not None:
|
||||
props.append('min=%d' % self.min)
|
||||
if self.max is not None:
|
||||
props.append('max=%d' % self.max)
|
||||
|
||||
if props:
|
||||
return 'Integer(%s)' % ', '.join(props)
|
||||
@@ -245,7 +269,8 @@ class Integer(ConfigType):
|
||||
return (
|
||||
(self.__class__ == other.__class__) and
|
||||
(self.min == other.min) and
|
||||
(self.max == other.max)
|
||||
(self.max == other.max) and
|
||||
(self.choices == other.choices)
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user