diff options
| author | Goffin Simon <simon.goffin@outlook.com> | 2014-12-18 16:38:09 +0100 |
|---|---|---|
| committer | Christophe Simonis <chs@odoo.com> | 2015-01-16 17:15:18 +0100 |
| commit | 0fd773a486fbc1aeef7f00ec5eab3eaf0e4c6a9d (patch) | |
| tree | e0b6ab3c1d7c21a2539235805912ee82efd4f23a /openerp/exceptions.py | |
| parent | eeb8ed165d713f41d7cde33e46acd7accef722fb (diff) | |
[IMP] Cleanup and refactoring of exception handling
Unify and refactor exception handling in framework and addons.
The generic `except_osv` is now deprecated, and replaced by more specialized exception subtypes:
- `UserError` (renamed from Warning, as it conflicts with the built-in `Warning`) raised when a non-technical error occurs during a business operation. It could be a missing information in the data provided by the user, or a misconfiguration.
- `AccessError`: raised when any operation is denied because the user conducting it does not have the required access rights.
- `AccessDenied`: raised when an operation that requires authenticated access is attempted via an unauthenticated request.
- `MissingError`: raised when an operation is attempted on a record that does not exist.
- `ValidationError`: raised when an operation violates a SQL or Python constraint.
- All other exceptions are internal errors due to a system problem or bug, and raised untouched to the client-side, which should display a traceback.
All exceptions take a single message argument.
The `test_exceptions` module has been updated to showcase both new and old (deprecated) exceptions.
A great many old `except_osv` had a useless title with "Error!" or "Warning", those have been removed, as this is handled by the client-side widget that displays the messages.
This commit introduces a more consistent policy for logging errors and warnings:
- All messages that do not require administrator attention should be logged at INFO level or lower. This includes all errors that are notified to the user in a friendly manner, even for access right problems or validation errors during business operations.
- All messages that indicate a likely misconfiguration or malicious use by the users should be logged at WARNING level, as they typically require administrator attention.
- All other unhandled internal errors cannot typically be handled by the user and should be logged at ERROR or higher level, as they require immediate administrator attention.
Diffstat (limited to 'openerp/exceptions.py')
| -rw-r--r-- | openerp/exceptions.py | 47 |
1 files changed, 37 insertions, 10 deletions
diff --git a/openerp/exceptions.py b/openerp/exceptions.py index 7948b8a0fc1..58e57913272 100644 --- a/openerp/exceptions.py +++ b/openerp/exceptions.py @@ -28,15 +28,32 @@ treated as a 'Server error'. If you consider introducing new exceptions, check out the test_exceptions addon. """ +from inspect import currentframe +import logging +from tools.func import frame_codeinfo + +_logger = logging.getLogger(__name__) + + # kept for backward compatibility class except_orm(Exception): - def __init__(self, name, value): + def __init__(self, name, value=None): + if type(self) == except_orm: + caller = frame_codeinfo(currentframe(), 1) + _logger.warn('except_orm is deprecated. Please use specific exceptions like UserError or AccessError. Caller: %s:%s', *caller) self.name = name self.value = value self.args = (name, value) -class Warning(Exception): - pass + +class UserError(except_orm): + def __init__(self, msg): + super(UserError, self).__init__(msg) + + +# deprecated due to collision with builtins, kept for compatibility +Warning = UserError + class RedirectWarning(Exception): """ Warning with a possibility to redirect the user instead of simply @@ -48,25 +65,35 @@ class RedirectWarning(Exception): the redirection. """ + class AccessDenied(Exception): - """ Login/password error. No message, no traceback. """ + """ Login/password error. No message, no traceback. + Example: When you try to log with a wrong password.""" def __init__(self): - super(AccessDenied, self).__init__('Access denied.') + super(AccessDenied, self).__init__('Access denied') self.traceback = ('', '', '') + class AccessError(except_orm): - """ Access rights error. """ + """ Access rights error. + Example: When you try to read a record that you are not allowed to.""" def __init__(self, msg): - super(AccessError, self).__init__('AccessError', msg) + super(AccessError, self).__init__(msg) + class MissingError(except_orm): - """ Missing record(s). """ + """ Missing record(s). + Example: When you try to write on a deleted record.""" def __init__(self, msg): - super(MissingError, self).__init__('MissingError', msg) + super(MissingError, self).__init__(msg) + class ValidationError(except_orm): + """ Violation of python constraints + Example: When you try to create a new user with a login which already exist in the db.""" def __init__(self, msg): - super(ValidationError, self).__init__('ValidateError', msg) + super(ValidationError, self).__init__(msg) + class DeferredException(Exception): """ Exception object holding a traceback for asynchronous reporting. |
