diff options
author | Jason Gerard DeRose <jderose@redhat.com> | 2009-01-03 17:27:53 -0700 |
---|---|---|
committer | Jason Gerard DeRose <jderose@redhat.com> | 2009-01-03 17:27:53 -0700 |
commit | 6b6e6b1cab7a633faf16631a565ecb6988dadb48 (patch) | |
tree | 86b5b24485955ac3186beb7e350b77c47fefa5b3 | |
parent | d1517b95ca14773773647434fb589c8224307328 (diff) | |
download | freeipa-6b6e6b1cab7a633faf16631a565ecb6988dadb48.tar.gz freeipa-6b6e6b1cab7a633faf16631a565ecb6988dadb48.tar.xz freeipa-6b6e6b1cab7a633faf16631a565ecb6988dadb48.zip |
Ported plugin registration errors into errors2.py; plugable.Registrar now raises new errors2 exceptions
-rw-r--r-- | ipalib/errors2.py | 83 | ||||
-rw-r--r-- | ipalib/plugable.py | 21 | ||||
-rw-r--r-- | tests/test_ipalib/test_error2.py | 78 | ||||
-rw-r--r-- | tests/test_ipalib/test_plugable.py | 22 |
4 files changed, 183 insertions, 21 deletions
diff --git a/ipalib/errors2.py b/ipalib/errors2.py index 676dd79f3..7793a9146 100644 --- a/ipalib/errors2.py +++ b/ipalib/errors2.py @@ -43,7 +43,7 @@ import request class PrivateError(StandardError): """ - Base class for exceptions that are *never* returned in an RPC response. + Base class for exceptions that are *never* forwarded in an RPC response. """ format = '' @@ -72,15 +72,82 @@ class SubprocessError(PrivateError): 1 >>> e.argv ('/bin/false',) + >>> e.message + "return code 1 from ('/bin/false',)" >>> str(e) "return code 1 from ('/bin/false',)" """ + format = 'return code %(returncode)d from %(argv)r' +class PluginSubclassError(PrivateError): + """ + Raised when a plugin doesn't subclass from an allowed base. + + For example: + + >>> raise PluginSubclassError(plugin='bad', bases=('base1', 'base2')) + Traceback (most recent call last): + ... + PluginSubclassError: 'bad' not subclass of any base in ('base1', 'base2') + + """ + + format = '%(plugin)r not subclass of any base in %(bases)r' + + +class PluginDuplicateError(PrivateError): + """ + Raised when the same plugin class is registered more than once. + + For example: + + >>> raise PluginDuplicateError(plugin='my_plugin') + Traceback (most recent call last): + ... + PluginDuplicateError: 'my_plugin' was already registered + """ + + format = '%(plugin)r was already registered' + + +class PluginOverrideError(PrivateError): + """ + Raised when a plugin overrides another without using ``override=True``. + + For example: + + >>> raise PluginOverrideError(base='Command', name='env', plugin='my_env') + Traceback (most recent call last): + ... + PluginOverrideError: unexpected override of Command.env with 'my_env' + """ + + format = 'unexpected override of %(base)s.%(name)s with %(plugin)r' + + +class PluginMissingOverrideError(PrivateError): + """ + Raised when a plugin overrides another that has not been registered. + + For example: + + >>> raise PluginMissingOverrideError(base='Command', name='env', plugin='my_env') + Traceback (most recent call last): + ... + PluginMissingOverrideError: Command.env not registered, cannot override with 'my_env' + """ + + format = '%(base)s.%(name)s not registered, cannot override with %(plugin)r' + + + +############################################################################## +# Public errors: class PublicError(StandardError): """ - **900** Base class for exceptions that can be returned in an RPC response. + **900** Base class for exceptions that can be forwarded in an RPC response. """ code = 900 @@ -96,8 +163,6 @@ class PublicError(StandardError): - - class InternalError(PublicError): """ **901** Used to conceal a non-public exception. @@ -108,7 +173,7 @@ class InternalError(PublicError): ############################################################################## -# 1000 - 1999: Authentication Errors +# 1000 - 1999: Authentication errors class AuthenticationError(PublicError): """ **1000** Base class for authentication errors (*1000 - 1999*). @@ -119,7 +184,7 @@ class AuthenticationError(PublicError): ############################################################################## -# 2000 - 2999: Authorization Errors +# 2000 - 2999: Authorization errors class AuthorizationError(PublicError): """ **2000** Base class for authorization errors (*2000 - 2999*). @@ -130,7 +195,7 @@ class AuthorizationError(PublicError): ############################################################################## -# 3000 - 3999: Invocation Errors +# 3000 - 3999: Invocation errors class InvocationError(PublicError): """ @@ -201,7 +266,7 @@ class ValidationError(InvocationError): ############################################################################## -# 4000 - 4999: Execution Errors +# 4000 - 4999: Execution errors class ExecutionError(PublicError): """ @@ -213,7 +278,7 @@ class ExecutionError(PublicError): ############################################################################## -# 5000 - 5999: Generic Errors +# 5000 - 5999: Generic errors class GenericError(PublicError): """ diff --git a/ipalib/plugable.py b/ipalib/plugable.py index 4ef2135b5..094634d33 100644 --- a/ipalib/plugable.py +++ b/ipalib/plugable.py @@ -34,6 +34,7 @@ import os from os import path import subprocess import errors +import errors2 from config import Env import util from base import ReadOnly, NameSpace, lock, islocked, check_name @@ -461,7 +462,9 @@ class Registrar(DictProxy): found = True yield (base, sub_d) if not found: - raise errors.SubclassError(klass, self.__allowed.keys()) + raise errors2.PluginSubclassError( + plugin=klass, bases=self.__allowed.keys() + ) def __call__(self, klass, override=False): """ @@ -471,11 +474,11 @@ class Registrar(DictProxy): :param override: If true, override an already registered plugin. """ if not inspect.isclass(klass): - raise TypeError('plugin must be a class: %r' % klass) + raise TypeError('plugin must be a class; got %r' % klass) # Raise DuplicateError if this exact class was already registered: if klass in self.__registered: - raise errors.DuplicateError(klass) + raise errors2.PluginDuplicateError(plugin=klass) # Find the base class or raise SubclassError: for (base, sub_d) in self.__findbases(klass): @@ -483,11 +486,19 @@ class Registrar(DictProxy): if klass.__name__ in sub_d: if not override: # Must use override=True to override: - raise errors.OverrideError(base, klass) + raise errors2.PluginOverrideError( + base=base.__name__, + name=klass.__name__, + plugin=klass, + ) else: if override: # There was nothing already registered to override: - raise errors.MissingOverrideError(base, klass) + raise errors2.PluginMissingOverrideError( + base=base.__name__, + name=klass.__name__, + plugin=klass, + ) # The plugin is okay, add to sub_d: sub_d[klass.__name__] = klass diff --git a/tests/test_ipalib/test_error2.py b/tests/test_ipalib/test_error2.py index f8b1a314d..9be247561 100644 --- a/tests/test_ipalib/test_error2.py +++ b/tests/test_ipalib/test_error2.py @@ -92,16 +92,92 @@ class test_SubprocessError(PrivateExceptionTester): """ Test the `ipalib.errors2.SubprocessError` exception. """ + _klass = errors2.SubprocessError def test_init(self): """ Test the `ipalib.errors2.SubprocessError.__init__` method. """ - inst = self.klass(returncode=1, argv=('/bin/false',)) + inst = self.new(returncode=1, argv=('/bin/false',)) assert inst.returncode == 1 assert inst.argv == ('/bin/false',) assert str(inst) == "return code 1 from ('/bin/false',)" + assert inst.message == str(inst) + + +class test_PluginSubclassError(PrivateExceptionTester): + """ + Test the `ipalib.errors2.PluginSubclassError` exception. + """ + + _klass = errors2.PluginSubclassError + + def test_init(self): + """ + Test the `ipalib.errors2.PluginSubclassError.__init__` method. + """ + inst = self.new(plugin='bad', bases=('base1', 'base2')) + assert inst.plugin == 'bad' + assert inst.bases == ('base1', 'base2') + assert str(inst) == \ + "'bad' not subclass of any base in ('base1', 'base2')" + assert inst.message == str(inst) + + +class test_PluginDuplicateError(PrivateExceptionTester): + """ + Test the `ipalib.errors2.PluginDuplicateError` exception. + """ + + _klass = errors2.PluginDuplicateError + + def test_init(self): + """ + Test the `ipalib.errors2.PluginDuplicateError.__init__` method. + """ + inst = self.new(plugin='my_plugin') + assert inst.plugin == 'my_plugin' + assert str(inst) == "'my_plugin' was already registered" + assert inst.message == str(inst) + + +class test_PluginOverrideError(PrivateExceptionTester): + """ + Test the `ipalib.errors2.PluginOverrideError` exception. + """ + + _klass = errors2.PluginOverrideError + + def test_init(self): + """ + Test the `ipalib.errors2.PluginOverrideError.__init__` method. + """ + inst = self.new(base='Base', name='cmd', plugin='my_cmd') + assert inst.base == 'Base' + assert inst.name == 'cmd' + assert inst.plugin == 'my_cmd' + assert str(inst) == "unexpected override of Base.cmd with 'my_cmd'" + assert inst.message == str(inst) + + +class test_PluginMissingOverrideError(PrivateExceptionTester): + """ + Test the `ipalib.errors2.PluginMissingOverrideError` exception. + """ + + _klass = errors2.PluginMissingOverrideError + + def test_init(self): + """ + Test the `ipalib.errors2.PluginMissingOverrideError.__init__` method. + """ + inst = self.new(base='Base', name='cmd', plugin='my_cmd') + assert inst.base == 'Base' + assert inst.name == 'cmd' + assert inst.plugin == 'my_cmd' + assert str(inst) == "Base.cmd not registered, cannot override with 'my_cmd'" + assert inst.message == str(inst) def test_public_errors(): diff --git a/tests/test_ipalib/test_plugable.py b/tests/test_ipalib/test_plugable.py index 9eb102ff4..dbf0cc3ff 100644 --- a/tests/test_ipalib/test_plugable.py +++ b/tests/test_ipalib/test_plugable.py @@ -25,7 +25,7 @@ import inspect from tests.util import raises, no_set, no_del, read_only from tests.util import getitem, setitem, delitem from tests.util import ClassChecker, create_test_api -from ipalib import plugable, errors +from ipalib import plugable, errors, errors2 class test_SetProxy(ClassChecker): @@ -534,11 +534,14 @@ def test_Registrar(): # Check that TypeError is raised trying to register something that isn't # a class: - raises(TypeError, r, plugin1()) + p = plugin1() + e = raises(TypeError, r, p) + assert str(e) == 'plugin must be a class; got %r' % p # Check that SubclassError is raised trying to register a class that is # not a subclass of an allowed base: - raises(errors.SubclassError, r, plugin3) + e = raises(errors2.PluginSubclassError, r, plugin3) + assert e.plugin is plugin3 # Check that registration works r(plugin1) @@ -548,7 +551,8 @@ def test_Registrar(): # Check that DuplicateError is raised trying to register exact class # again: - raises(errors.DuplicateError, r, plugin1) + e = raises(errors2.PluginDuplicateError, r, plugin1) + assert e.plugin is plugin1 # Check that OverrideError is raised trying to register class with same # name and same base: @@ -557,7 +561,10 @@ def test_Registrar(): pass class plugin1(base1_extended): pass - raises(errors.OverrideError, r, plugin1) + e = raises(errors2.PluginOverrideError, r, plugin1) + assert e.base == 'Base1' + assert e.name == 'plugin1' + assert e.plugin is plugin1 # Check that overriding works r(plugin1, override=True) @@ -567,7 +574,10 @@ def test_Registrar(): # Check that MissingOverrideError is raised trying to override a name # not yet registerd: - raises(errors.MissingOverrideError, r, plugin2, override=True) + e = raises(errors2.PluginMissingOverrideError, r, plugin2, override=True) + assert e.base == 'Base2' + assert e.name == 'plugin2' + assert e.plugin is plugin2 # Test that another plugin can be registered: assert len(r.Base2) == 0 |