mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
New Param: split common Bytes/Str functionality into new Data base class; Str no longer subclasses from Bytes
This commit is contained in:
parent
3a6f716aac
commit
3e201dfff6
@ -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),
|
||||
)
|
||||
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user