diff options
-rw-r--r-- | ipalib/errors.py | 12 | ||||
-rw-r--r-- | ipalib/public.py | 10 | ||||
-rw-r--r-- | ipalib/tests/test_public.py | 37 |
3 files changed, 43 insertions, 16 deletions
diff --git a/ipalib/errors.py b/ipalib/errors.py index 47e0a3ed..afc61dd8 100644 --- a/ipalib/errors.py +++ b/ipalib/errors.py @@ -64,11 +64,23 @@ class NormalizationError(ValidationError): class RuleError(ValidationError): + """ + Raised when a required option was not provided. + """ def __init__(self, name, value, rule, error): self.rule = rule ValidationError.__init__(self, name, value, error) +class RequirementError(ValidationError): + """ + Raised when a required option was not provided. + """ + def __init__(self, name): + ValidationError.__init__(self, name, None, + 'missing required value' + ) + class SetError(IPAError): msg = 'setting %r, but NameSpace does not allow attribute setting' diff --git a/ipalib/public.py b/ipalib/public.py index 9677358f..4c085ba3 100644 --- a/ipalib/public.py +++ b/ipalib/public.py @@ -199,9 +199,13 @@ class cmd(plugable.Plugin): def validate(self, **kw): self.print_call('validate', kw, 1) - for (key, value) in kw.items(): - if key in self.options: - self.options[key].validate(value) + for opt in self.options: + value = kw.get(opt.name, None) + if value is None: + if opt.required: + raise errors.RequirementError(opt.name) + continue + opt.validate(value) def execute(self, **kw): self.print_call('execute', kw, 1) diff --git a/ipalib/tests/test_public.py b/ipalib/tests/test_public.py index eb19f28a..a331316d 100644 --- a/ipalib/tests/test_public.py +++ b/ipalib/tests/test_public.py @@ -177,7 +177,7 @@ class test_cmd(ClassChecker): class option0(my_option): pass class option1(my_option): - pass + required = True class example(self.cls): option_classes = (option0, option1) return example @@ -254,18 +254,30 @@ class test_cmd(ClassChecker): Tests the `validate` method. """ assert 'validate' in self.cls.__public__ # Public + sub = self.subcls() - for name in ('option0', 'option1'): - okay = { - name: name, - 'another_option': 'some value', - } - fail = { - name: 'whatever', - 'another_option': 'some value', - } - sub.validate(**okay) - raises(errors.RuleError, sub.validate, **fail) + + # Check with valid args + okay = dict( + option0='option0', + option1='option1', + another_option='some value', + ) + sub.validate(**okay) + + # Check with an invalid arg + fail = dict(okay) + fail['option0'] = 'whatever' + raises(errors.RuleError, sub.validate, **fail) + + # Check with a missing required arg + fail = dict(okay) + fail.pop('option1') + raises(errors.RequirementError, sub.validate, **fail) + + # Check with missing *not* required arg + okay.pop('option0') + sub.validate(**okay) def test_execute(self): """ @@ -274,7 +286,6 @@ class test_cmd(ClassChecker): assert 'execute' in self.cls.__public__ # Public - def test_obj(): cls = public.obj assert issubclass(cls, plugable.Plugin) |