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:
Lin Tan
2015-12-01 15:52:28 +08:00
parent 9dd719f83a
commit 0416d73e56
2 changed files with 60 additions and 6 deletions

View File

@@ -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()

View File

@@ -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)
)