diff options
author | Jason Gerard DeRose <jderose@redhat.com> | 2008-12-12 03:13:58 -0700 |
---|---|---|
committer | Jason Gerard DeRose <jderose@redhat.com> | 2008-12-12 03:13:58 -0700 |
commit | 5272949bfd01b9648902fd9dea77762d06d52832 (patch) | |
tree | 33107b83a31f0e069eeeb4dc706acbe623033d0a | |
parent | 079721da2cfdd9bc040f7fe6e2842a4775e0e964 (diff) | |
download | freeipa-5272949bfd01b9648902fd9dea77762d06d52832.tar.gz freeipa-5272949bfd01b9648902fd9dea77762d06d52832.tar.xz freeipa-5272949bfd01b9648902fd9dea77762d06d52832.zip |
New Param: added all logic for minlength, maxlength, and length in Bytes class (which Str inherits)
-rw-r--r-- | ipalib/parameter.py | 70 | ||||
-rw-r--r-- | tests/test_ipalib/test_parameter.py | 57 |
2 files changed, 112 insertions, 15 deletions
diff --git a/ipalib/parameter.py b/ipalib/parameter.py index 6acf04830..82be8feec 100644 --- a/ipalib/parameter.py +++ b/ipalib/parameter.py @@ -203,19 +203,27 @@ class Param(ReadOnly): def __init__(self, name, **kw): assert type(self.type) is type + self.kwargs += (('default', self.type, None),) self.param_spec = name self.__kw = dict(kw) if not ('required' in kw or 'multivalue' in kw): (name, kw_from_spec) = parse_param_spec(name) kw.update(kw_from_spec) self.name = check_name(name) + self.nice = '%s(%r)' % (self.__class__.__name__, self.name) + if not set(t[0] for t in self.kwargs).issuperset(self.__kw): + extra = set(kw) - set(t[0] for t in self.kwargs) + raise TypeError( + '%s: no such kwargs: %s' % (self.nice, + ', '.join(repr(k) for k in sorted(extra)) + ) + ) if kw.get('cli_name', None) is None: kw['cli_name'] = self.name df = kw.get('default_from', None) if callable(df) and not isinstance(df, DefaultFrom): kw['default_from'] = DefaultFrom(df) self.__clonekw = kw - self.kwargs += (('default', self.type, None),) for (key, kind, default) in self.kwargs: value = kw.get(key, default) if value is not None: @@ -245,14 +253,12 @@ class Param(ReadOnly): For example: - >>> param = Str('telephone', + >>> param = Param('telephone', ... normalizer=lambda value: value.replace('.', '-') ... ) >>> param.normalize(u'800.123.4567') u'800-123-4567' - (Note that `Str` is a subclass of `Param`.) - If this `Param` instance was created with a normalizer callback and ``value`` is a unicode instance, the normalizer callback is called and *its* return value is returned. @@ -293,8 +299,8 @@ class Param(ReadOnly): if self.multivalue: if type(value) in (tuple, list): values = filter( - lambda val: val not in NULLS, - (self._convert_scalar(v, i) for (i, v) in enumerate(value)) + lambda val: val not in NULLS, + (self._convert_scalar(v, i) for (i, v) in enumerate(value)) ) if len(values) == 0: return @@ -336,23 +342,59 @@ class Bytes(Param): type = str - def __init__(self, name, **kw): - kwargs = dict( - minlength=(int, None), - maxlength=(int, None), - length=(int, None), - pattern=(str, None), - ) + kwargs = Param.kwargs + ( + ('minlength', int, None), + ('maxlength', int, None), + ('length', int, None), + ('pattern', str, None), + ) + def __init__(self, name, **kw): + super(Bytes, self).__init__(name, **kw) + + if not ( + self.length is None or + (self.minlength is None and self.maxlength is None) + ): + raise ValueError( + '%s: cannot mix length with minlength or maxlength' % self.nice + ) + + if self.minlength is not None and self.minlength < 1: + raise ValueError( + '%s: minlength must be >= 1; got %r' % (self.nice, self.minlength) + ) + + if self.maxlength is not None and self.maxlength < 1: + raise ValueError( + '%s: maxlength must be >= 1; got %r' % (self.nice, self.maxlength) + ) + + if None not in (self.minlength, self.maxlength): + if self.minlength > self.maxlength: + raise ValueError( + '%s: minlength > maxlength (minlength=%r, maxlength=%r)' % ( + self.nice, self.minlength, self.maxlength) + ) + elif self.minlength == self.maxlength: + raise ValueError( + '%s: minlength == maxlength; use length=%d instead' % ( + self.nice, self.minlength) + ) -class Str(Param): + +class Str(Bytes): """ """ type = unicode + kwargs = Bytes.kwargs[:-1] + ( + ('pattern', unicode, None), + ) + def __init__(self, name, **kw): super(Str, self).__init__(name, **kw) diff --git a/tests/test_ipalib/test_parameter.py b/tests/test_ipalib/test_parameter.py index f72c4e627..ddc938d47 100644 --- a/tests/test_ipalib/test_parameter.py +++ b/tests/test_ipalib/test_parameter.py @@ -149,11 +149,12 @@ class test_Param(ClassChecker): assert str(e) == CALLABLE_ERROR % (key, value, type(value)) else: assert str(e) == TYPE_ERROR % (key, kind, value, type(value)) - # Test with None: kw = {key: None} Subclass('my_param', **kw) + # Test when using unknown kwargs: + def test_convert_scalar(self): """ Test the `ipalib.parameter.Param._convert_scalar` method. @@ -168,6 +169,56 @@ class test_Param(ClassChecker): assert str(e) == 'Subclass._convert_scalar()' +class test_Bytes(ClassChecker): + """ + Test the `ipalib.parameter.Bytes` class. + """ + _cls = parameter.Bytes + + def test_init(self): + """ + Test the `ipalib.parameter.Bytes.__init__` method. + """ + o = self.cls('my_bytes') + assert o.type is str + assert o.minlength is None + assert o.maxlength is None + assert o.length is None + assert o.pattern is None + + # Test mixing length with minlength or maxlength: + o = self.cls('my_bytes', length=5) + assert o.length == 5 + permutations = [ + dict(minlength=3), + dict(maxlength=7), + dict(minlength=3, maxlength=7), + ] + for kw in permutations: + o = self.cls('my_bytes', **kw) + for (key, value) in kw.iteritems(): + assert getattr(o, key) == value + e = raises(ValueError, self.cls, 'my_bytes', length=5, **kw) + assert str(e) == \ + "Bytes('my_bytes'): cannot mix length with minlength or maxlength" + + # Test when minlength or maxlength are less than 1: + e = raises(ValueError, self.cls, 'my_bytes', minlength=0) + assert str(e) == "Bytes('my_bytes'): minlength must be >= 1; got 0" + e = raises(ValueError, self.cls, 'my_bytes', maxlength=0) + assert str(e) == "Bytes('my_bytes'): maxlength must be >= 1; got 0" + + # Test when minlength > maxlength: + e = raises(ValueError, self.cls, 'my_bytes', minlength=22, maxlength=15) + assert str(e) == \ + "Bytes('my_bytes'): minlength > maxlength (minlength=22, maxlength=15)" + + # Test when minlength == maxlength + e = raises(ValueError, self.cls, 'my_bytes', minlength=7, maxlength=7) + assert str(e) == \ + "Bytes('my_bytes'): minlength == maxlength; use length=7 instead" + + class test_Str(ClassChecker): """ Test the `ipalib.parameter.Str` class. @@ -180,6 +231,10 @@ class test_Str(ClassChecker): """ o = self.cls('my_str') assert o.type is unicode + assert o.minlength is None + assert o.maxlength is None + assert o.length is None + assert o.pattern is None def test_convert_scalar(self): """ |