New Param: split common Bytes/Str functionality into new Data base class; Str no longer subclasses from Bytes

This commit is contained in:
Jason Gerard DeRose 2009-01-14 10:58:05 -07:00
parent 3a6f716aac
commit 3e201dfff6
2 changed files with 89 additions and 15 deletions

View File

@ -19,6 +19,16 @@
"""
Parameter system for command plugins.
TODO:
* Change rule call signature to rule(_, value, **kw) so that rules can also
validate relative to other parameter values (e.g., login name as it relates
to first name and last name)
* Add the _rule_pattern() methods to `Bytes` and `Str`
* Add maxvalue, minvalue kwargs and rules to `Int` and `Float`
"""
from types import NoneType
@ -28,7 +38,6 @@ from plugable import ReadOnly, lock, check_name
from errors2 import ConversionError, RequirementError, ValidationError
from constants import NULLS, TYPE_ERROR, CALLABLE_ERROR
class DefaultFrom(ReadOnly):
"""
Derive a default value from other supplied values.
@ -695,29 +704,23 @@ class Float(Param):
type_error = _('must be a decimal number')
class Bytes(Param):
class Data(Param):
"""
A parameter for binary data (stored in the ``str`` type).
Base class for the `Bytes` and `Str` parameters.
This class is named *Bytes* instead of *Str* so it's aligned with the
Python v3 ``(str, unicode) => (bytes, str)`` clean-up. See:
http://docs.python.org/3.0/whatsnew/3.0.html
Previously `Str` was as subclass of `Bytes`. Now the common functionality
has been split into this base class so that ``isinstance(foo, Bytes)`` wont
be ``True`` when ``foo`` is actually an `Str` instance (which is confusing).
"""
type = str
type_error = _('must be binary data')
kwargs = Param.kwargs + (
('minlength', int, None),
('maxlength', int, None),
('length', int, None),
('pattern', str, None),
)
def __init__(self, name, *rules, **kw):
super(Bytes, self).__init__(name, *rules, **kw)
super(Data, self).__init__(name, *rules, **kw)
if not (
self.length is None or
@ -749,6 +752,24 @@ class Bytes(Param):
self.nice, self.minlength)
)
class Bytes(Data):
"""
A parameter for binary data (stored in the ``str`` type).
This class is named *Bytes* instead of *Str* so it's aligned with the
Python v3 ``(str, unicode) => (bytes, str)`` clean-up. See:
http://docs.python.org/3.0/whatsnew/3.0.html
"""
type = str
type_error = _('must be binary data')
kwargs = Data.kwargs + (
('pattern', str, None),
)
def _rule_minlength(self, _, value):
"""
Check minlength constraint.
@ -780,7 +801,7 @@ class Bytes(Param):
)
class Str(Bytes):
class Str(Data):
"""
A parameter for Unicode text (stored in the ``unicode`` type).
@ -793,7 +814,7 @@ class Str(Bytes):
type = unicode
type_error = _('must be Unicode text')
kwargs = Bytes.kwargs[:-1] + (
kwargs = Data.kwargs + (
('pattern', unicode, None),
)

View File

@ -587,6 +587,59 @@ class test_Flag(ClassChecker):
assert orig.clone(default=False).default is False
class test_Data(ClassChecker):
"""
Test the `ipalib.parameters.Data` class.
"""
_cls = parameters.Data
def test_init(self):
"""
Test the `ipalib.parameters.Data.__init__` method.
"""
o = self.cls('my_data')
assert o.type is NoneType
assert o.rules == tuple()
assert o.class_rules == tuple()
assert o.all_rules == tuple()
assert o.minlength is None
assert o.maxlength is None
assert o.length is None
assert not hasattr(o, 'pattern')
# Test mixing length with minlength or maxlength:
o = self.cls('my_data', 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_data', **kw)
for (key, value) in kw.iteritems():
assert getattr(o, key) == value
e = raises(ValueError, self.cls, 'my_data', length=5, **kw)
assert str(e) == \
"Data('my_data'): cannot mix length with minlength or maxlength"
# Test when minlength or maxlength are less than 1:
e = raises(ValueError, self.cls, 'my_data', minlength=0)
assert str(e) == "Data('my_data'): minlength must be >= 1; got 0"
e = raises(ValueError, self.cls, 'my_data', maxlength=0)
assert str(e) == "Data('my_data'): maxlength must be >= 1; got 0"
# Test when minlength > maxlength:
e = raises(ValueError, self.cls, 'my_data', minlength=22, maxlength=15)
assert str(e) == \
"Data('my_data'): minlength > maxlength (minlength=22, maxlength=15)"
# Test when minlength == maxlength
e = raises(ValueError, self.cls, 'my_data', minlength=7, maxlength=7)
assert str(e) == \
"Data('my_data'): minlength == maxlength; use length=7 instead"
class test_Bytes(ClassChecker):
"""
Test the `ipalib.parameters.Bytes` class.