summaryrefslogtreecommitdiffstats
path: root/ipalib
diff options
context:
space:
mode:
Diffstat (limited to 'ipalib')
-rw-r--r--ipalib/frontend.py14
-rw-r--r--ipalib/tests/test_frontend.py33
2 files changed, 44 insertions, 3 deletions
diff --git a/ipalib/frontend.py b/ipalib/frontend.py
index ce43ecea..ff0d3492 100644
--- a/ipalib/frontend.py
+++ b/ipalib/frontend.py
@@ -117,6 +117,9 @@ def parse_param_spec(spec):
class Param(plugable.ReadOnly):
+ """
+ A parameter accepted by a `Command`.
+ """
__nones = (None, '', tuple(), [])
__default = dict(
doc='',
@@ -150,9 +153,18 @@ class Param(plugable.ReadOnly):
allow_none=True
)
self.__normalize = self.__kw['normalize']
- self.rules = (type_.validate,) + self.__kw['rules']
+ self.rules = self.__check_type(tuple, 'rules')
+ self.all_rules = (type_.validate,) + self.rules
lock(self)
+ def __clone__(self, **override):
+ """
+ Return a new `Param` instance similar to this one.
+ """
+ kw = dict(self.__kw)
+ kw.update(override)
+ return self.__class__(self.name, self.type, **kw)
+
def __check_type(self, type_, name, allow_none=False):
value = self.__kw[name]
return check_type(value, type_, name, allow_none)
diff --git a/ipalib/tests/test_frontend.py b/ipalib/tests/test_frontend.py
index 43c1abf2..cc71f1c9 100644
--- a/ipalib/tests/test_frontend.py
+++ b/ipalib/tests/test_frontend.py
@@ -147,7 +147,8 @@ class test_Param(ClassChecker):
assert read_only(o, 'multivalue') is False
assert read_only(o, 'default') is None
assert read_only(o, 'default_from') is None
- assert read_only(o, 'rules') == (type_.validate,)
+ assert read_only(o, 'rules') == tuple()
+ assert read_only(o, 'all_rules') == (type_.validate,)
# Check default type_:
o = self.cls(name)
@@ -173,6 +174,33 @@ class test_Param(ClassChecker):
assert str(e) == \
'Param.__init__() takes no such kwargs: another, whatever'
+ def test_clone(self):
+ """
+ Test the `frontend.Param.__clone__` method.
+ """
+ def compare(o, kw):
+ for (k, v) in kw.iteritems():
+ assert getattr(o, k) == v, (k, v, getattr(o, k))
+ default = dict(
+ required=False,
+ multivalue=False,
+ default=None,
+ default_from=None,
+ rules=tuple(),
+ )
+ name = 'hair_color?'
+ type_ = ipa_types.Int()
+ o = self.cls(name, type_)
+ compare(o, default)
+
+ override = dict(multivalue=True, default=42)
+ d = dict(default)
+ d.update(override)
+ clone = o.__clone__(**override)
+ assert clone.name == 'hair_color'
+ assert clone.type is o.type
+ compare(clone, d)
+
def test_convert(self):
"""
Test the `frontend.Param.convert` method.
@@ -277,7 +305,8 @@ class test_Param(ClassChecker):
# Scenario 1: multivalue=False
o = self.cls(name, type_, rules=my_rules)
- assert o.rules == (type_.validate, case_rule)
+ assert o.rules == my_rules
+ assert o.all_rules == (type_.validate, case_rule)
o.validate(okay)
e = raises(errors.RuleError, o.validate, fail_case)
assert e.name is name