diff --git a/ipalib/ipa_types.py b/ipalib/ipa_types.py index 9a34a6b63..a03b88227 100644 --- a/ipalib/ipa_types.py +++ b/ipalib/ipa_types.py @@ -25,6 +25,26 @@ from plugable import ReadOnly, lock import errors +def check_min_max(min_value, max_value, min_name, max_name): + assert type(min_name) is str, 'min_name must be an str' + assert type(max_name) is str, 'max_name must be an str' + for (name, value) in [(min_name, min_value), (max_name, max_value)]: + if not (value is None or type(value) is int): + raise TypeError( + '`%s` must be an int or None, got: %r' % (name, value) + ) + if None not in (min_value, max_value) and min_value >= max_value: + d = dict( + k0=min_name, + v0=min_value, + k1=max_name, + v1=max_value, + ) + raise ValueError( + '%(k1)s > %(k0)s: %(k0)s=%(v0)r, %(k1)s=%(v1)r' % d + ) + + class Type(ReadOnly): """ Base class for all IPA types. @@ -47,16 +67,7 @@ class Int(Type): type = int def __init__(self, min_value=None, max_value=None): - args = (min_value, max_value) - for arg in args: - if not (arg is None or type(arg) is int): - raise TypeError('Must be an int or None: %r' % arg) - if None not in args and min_value >= max_value: - raise ValueError( - 'min_value not less than max_value: %r, %r' % ( - min_value, max_value - ) - ) + check_min_max(min_value, max_value, 'min_value', 'max_value') self.min_value = min_value self.max_value = max_value lock(self) @@ -70,22 +81,6 @@ class Int(Type): return 'Cannot be larger than %d' % self.max_value -def check_min_max(min_name, min_value, max_name, max_value): - assert type(min_name) is str, 'min_name must be an str' - assert type(max_name) is str, 'max_name must be an str' - for (name, value) in [(min_name, min_value), (max_name, max_value)]: - if not (value is None or type(value) is int): - raise TypeError( - '%s must be an int or None, got: %r' % (name, value) - ) -# if None not in (min_value, max_value) and min_value >= max_value: -# raise ValueError( -# 'min_value not less than max_value: %r, %r' % ( -# min_value, max_value -# ) -# ) - - class Unicode(Type): def __init__(self, min_length=None, max_length=None, pattern=None): integers = (min_length, max_length) diff --git a/ipalib/tests/test_ipa_types.py b/ipalib/tests/test_ipa_types.py index 6ecef2a54..87063ef69 100644 --- a/ipalib/tests/test_ipa_types.py +++ b/ipalib/tests/test_ipa_types.py @@ -30,6 +30,13 @@ def test_check_min_max(): Tests the `ipa_types.check_min_max` function. """ f = ipa_types.check_min_max + okay = [ + (None, -5), + (-20, None), + (-20, -5), + ] + for (l, h) in okay: + assert f(l, h, 'low', 'high') is None fail_type = [ '10', 10.0, @@ -39,11 +46,18 @@ def test_check_min_max(): object, ] for value in fail_type: - e = raises(TypeError, f, 'low', value, 'high', None) - assert str(e) == 'low must be an int or None, got: %r' % value - e = raises(TypeError, f, 'low', None, 'high', value) - assert str(e) == 'high must be an int or None, got: %r' % value - + e = raises(TypeError, f, value, None, 'low', 'high') + assert str(e) == '`low` must be an int or None, got: %r' % value + e = raises(TypeError, f, None, value, 'low', 'high') + assert str(e) == '`high` must be an int or None, got: %r' % value + fail_value = [ + (10, 5), + (-5, -10), + (5, -10), + ] + for (l, h) in fail_value: + e = raises(ValueError, f, l, h, 'low', 'high') + assert str(e) == 'high > low: low=%r, high=%r' % (l, h) class test_Type(ClassChecker): @@ -56,36 +70,52 @@ class test_Type(ClassChecker): assert self.cls.__bases__ == (plugable.ReadOnly,) - class test_Int(ClassChecker): _cls = ipa_types.Int + def test_class(self): + assert self.cls.__bases__ == (ipa_types.Type,) + assert self.cls.type is int + def test_init(self): o = self.cls() + assert o.name == 'Int' assert o.min_value is None assert o.max_value is None + okay = [ (None, -5), (-20, None), (-20, -5), ] + for (l, h) in okay: + o = self.cls(min_value=l, max_value=h) + assert o.min_value is l + assert o.max_value is h + fail_type = [ - (None, 10L), - (5L, None), - (None, '10'), - ('5', None), + '10', + 10.0, + 10L, + True, + False, + object, ] + for value in fail_type: + e = raises(TypeError, self.cls, min_value=value) + assert str(e) == ( + '`min_value` must be an int or None, got: %r' % value + ) + e = raises(TypeError, self.cls, max_value=value) + assert str(e) == ( + '`max_value` must be an int or None, got: %r' % value + ) + fail_value = [ (10, 5), (5, -5), (-5, -10), ] - for (l, h) in okay: - o = self.cls(min_value=l, max_value=h) - assert o.min_value is l - assert o.max_value is h - for (l, h) in fail_type: - raises(TypeError, self.cls, min_value=l, max_value=h) for (l, h) in fail_value: raises(ValueError, self.cls, min_value=l, max_value=h)