summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ipalib/errors.py15
-rw-r--r--ipalib/errors2.py213
-rw-r--r--ipalib/parameter.py7
-rw-r--r--ipalib/request.py6
-rw-r--r--tests/test_ipalib/test_error2.py41
5 files changed, 267 insertions, 15 deletions
diff --git a/ipalib/errors.py b/ipalib/errors.py
index 7191ff405..beb6342d9 100644
--- a/ipalib/errors.py
+++ b/ipalib/errors.py
@@ -241,21 +241,6 @@ class RegistrationError(IPAError):
"""
-class NameSpaceError(RegistrationError):
- """
- Raised when name is not a valid Python identifier for use for use as
- the name of NameSpace member.
- """
- msg = 'name %r does not re.match %r'
-
- def __init__(self, name, regex):
- self.name = name
- self.regex = regex
-
- def __str__(self):
- return self.msg % (self.name, self.regex)
-
-
class SubclassError(RegistrationError):
"""
Raised when registering a plugin that is not a subclass of one of the
diff --git a/ipalib/errors2.py b/ipalib/errors2.py
new file mode 100644
index 000000000..f49c10ef9
--- /dev/null
+++ b/ipalib/errors2.py
@@ -0,0 +1,213 @@
+# Authors:
+# Jason Gerard DeRose <jderose@redhat.com>
+#
+# Copyright (C) 2008 Red Hat
+# see file 'COPYING' for use and warranty inmsgion
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; version 2 only
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+"""
+Custom exception classes.
+
+Certain errors can be returned in RPC response to relay some error condition
+to the caller.
+
+ ============= ========================================
+ Error codes Exceptions
+ ============= ========================================
+ 900 `PublicError`
+ 901 `InternalError`
+ 902 - 999 *Reserved for future use*
+ 1000 - 1999 `AuthenticationError` and its subclasses
+ 2000 - 2999 `AuthorizationError` and its subclasses
+ 3000 - 3999 `InvocationError` and its subclasses
+ 4000 - 4999 `ExecutionError` and its subclasses
+ 5000 - 5999 `GenericError` and its subclasses
+ ============= ========================================
+"""
+
+from inspect import isclass
+import request
+
+
+class PrivateError(StandardError):
+ """
+ Base class for exceptions that are *never* returned in an RPC response.
+ """
+
+
+class PublicError(StandardError):
+ """
+ **900** Base class for exceptions that can be returned in an RPC response.
+ """
+
+ code = 900
+
+ def __init__(self, message=None, **kw):
+ self.kw = kw
+ if message is None:
+ message = self.get_format(request._) % kw
+ StandardError.__init__(self, message)
+
+ def get_format(self, _):
+ return _('')
+
+
+
+
+
+class InternalError(PublicError):
+ """
+ **901** Used to conceal a non-public exception.
+ """
+
+ code = 901
+
+
+
+##############################################################################
+# 1000 - 1999: Authentication Errors
+class AuthenticationError(PublicError):
+ """
+ **1000** Base class for authentication errors (*1000 - 1999*).
+ """
+
+ code = 1000
+
+
+
+##############################################################################
+# 2000 - 2999: Authorization Errors
+class AuthorizationError(PublicError):
+ """
+ **2000** Base class for authorization errors (*2000 - 2999*).
+ """
+
+ code = 2000
+
+
+
+##############################################################################
+# 3000 - 3999: Invocation Errors
+
+class InvocationError(PublicError):
+ """
+ **3000** Base class for command invocation errors (*3000 - 3999*).
+ """
+
+ code = 3000
+
+
+class CommandError(InvocationError):
+ """
+ **3001** Raised when an unknown command is called.
+ """
+
+ code = 3001
+
+ def get_format(self, _):
+ return _('Unknown command %(name)r')
+
+
+class RemoteCommandError(InvocationError):
+ """
+ **3002** Raised when client receives a `CommandError` from server.
+ """
+
+ code = 3002
+
+
+class ArgumentError(InvocationError):
+ """
+ **3003** Raised when a command is called with wrong number of arguments.
+ """
+
+ code = 3003
+
+
+class OptionError(InvocationError):
+ """
+ **3004** Raised when a command is called with unknown options.
+ """
+
+ code = 3004
+
+
+class RequirementError(InvocationError):
+ """
+ **3005** Raised when a required parameter is not provided.
+ """
+
+ code = 3005
+
+
+class ConversionError(InvocationError):
+ """
+ **3006** Raised when a parameter value is the wrong type.
+ """
+
+ code = 3006
+
+
+class ValidationError(InvocationError):
+ """
+ **3007** Raised when a parameter value fails a validation rule.
+ """
+
+ code = 3007
+
+
+
+##############################################################################
+# 4000 - 4999: Execution Errors
+
+class ExecutionError(PublicError):
+ """
+ **4000** Base class for execution/operation errors (*4000 - 4999*).
+ """
+
+ code = 4000
+
+
+
+##############################################################################
+# 5000 - 5999: Generic Errors
+
+class GenericError(PublicError):
+ """
+ **5000** Errors inappropriate for other categories (*5000 - 5999*).
+ """
+
+ code = 5000
+
+
+
+def __errors_iter():
+ """
+ Iterate through all the `PublicError` subclasses.
+ """
+ for (key, value) in globals().items():
+ if key.startswith('_') or not isclass(value):
+ continue
+ if issubclass(value, PublicError):
+ yield value
+
+public_errors = tuple(
+ sorted(__errors_iter(), key=lambda E: E.code)
+)
+
+if __name__ == '__main__':
+ for klass in public_errors:
+ print '%d\t%s' % (klass.code, klass.__name__)
+ print '(%d public errors)' % len(public_errors)
diff --git a/ipalib/parameter.py b/ipalib/parameter.py
index 7605339d4..55a9bc6df 100644
--- a/ipalib/parameter.py
+++ b/ipalib/parameter.py
@@ -416,6 +416,13 @@ class Param(ReadOnly):
'%s.%s()' % (self.__class__.__name__, '_convert_scalar')
)
+ def validate(self, value):
+ """
+ Check validity of ``value``.
+
+ :param value: A proposed value for this parameter.
+ """
+
class Bool(Param):
"""
diff --git a/ipalib/request.py b/ipalib/request.py
index ea028239c..5a07d4dbb 100644
--- a/ipalib/request.py
+++ b/ipalib/request.py
@@ -32,6 +32,12 @@ from constants import OVERRIDE_ERROR
context = threading.local()
+def _(message):
+ if hasattr(context, 'gettext'):
+ return context.gettext(message)
+ return message.decode('UTF-8')
+
+
def set_languages(*languages):
if hasattr(context, 'languages'):
raise StandardError(OVERRIDE_ERROR %
diff --git a/tests/test_ipalib/test_error2.py b/tests/test_ipalib/test_error2.py
new file mode 100644
index 000000000..d70e49bee
--- /dev/null
+++ b/tests/test_ipalib/test_error2.py
@@ -0,0 +1,41 @@
+# Authors:
+# Jason Gerard DeRose <jderose@redhat.com>
+#
+# Copyright (C) 2008 Red Hat
+# see file 'COPYING' for use and warranty information
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; version 2 only
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+"""
+Test the `ipalib.error2` module.
+"""
+
+import re
+import inspect
+from ipalib import errors2
+
+
+def test_public_errors():
+ """
+ Test the `ipalib.errors2.public_errors` module variable.
+ """
+ for klass in errors2.public_errors:
+ assert issubclass(klass, errors2.PublicError)
+ assert not issubclass(klass, errors2.PrivateError)
+ assert type(klass.code) is int
+ assert 900 <= klass.code <= 5999
+ doc = inspect.getdoc(klass)
+ m = re.match(r'^\*{2}(\d+)\*{2} ', doc)
+ assert m is not None, doc
+ assert int(m.group(1)) == klass.code, klass.__name__