Add ButtonActionException and RPCReturnException

The RPCReturnException returns the result method instead of raising an
exception.
The ButtonActionException launch an action instead of executing the button.

Closes #12009
This commit is contained in:
Cédric Krier
2023-01-17 13:26:42 +01:00
parent 8532fa3bd5
commit 3c506fe15d
8 changed files with 81 additions and 5 deletions
+1
View File
@@ -1,3 +1,4 @@
* Add ButtonActionException and RPCReturnException
* Rename ModelStorage.count into ModelStorage.estimated_count
* Add border type to images
* Lock table on transaction start
+7
View File
@@ -46,6 +46,13 @@ Exceptions
The exception raised when trying to execute a button without the rights.
.. exception:: ButtonActionException
The exception raised to launch the ``action`` instead of executing the
button method.
The ``value`` attribute is the action value returned.
.. exception:: ImportDataError
The exception raises when importing data fails.
+11
View File
@@ -61,3 +61,14 @@ Instance methods are:
.. method:: RCP.headers
Return a dictionary of the headers.
Exceptions
==========
.. exception:: RPCReturnException
The base class of exceptions to return the result of ``result`` method
instead of raising an exception.
The :class:`~trytond.transaction.Transaction` is rollbacked and tasks are
cleared.
+2 -1
View File
@@ -7,12 +7,13 @@ from .modelstorage import (
ForbiddenCharValidationError, ImportDataError, RequiredValidationError,
SelectionValidationError, SizeValidationError, TimeFormatValidationError,
ValidationError)
from .modelview import AccessButtonError
from .modelview import AccessButtonError, ButtonActionException
from .tree import RecursionError
__all__ = [
AccessButtonError,
AccessError,
ButtonActionException,
DigitsValidationError,
DomainValidationError,
ForeignKeyError,
+21 -1
View File
@@ -10,7 +10,7 @@ from trytond.exceptions import UserError
from trytond.i18n import gettext
from trytond.pool import Pool
from trytond.pyson import PYSONEncoder
from trytond.rpc import RPC
from trytond.rpc import RPC, RPCReturnException
from trytond.tools import is_instance_method
from trytond.transaction import Transaction
@@ -25,6 +25,26 @@ class AccessButtonError(UserError):
pass
class ButtonActionException(RPCReturnException):
"Exception to launch action instead of executing button."
def __init__(self, action, value=None):
super().__init__()
pool = Pool()
ModelData = pool.get('ir.model.data')
Action = pool.get('ir.action')
module, fs_id = action.split('.')
action_id = Action.get_action_id(
ModelData.get_id(module, fs_id))
self.value = Action(action_id).get_action_value()
if value:
self.value.update(value)
def result(self):
return self.value
def on_change(func):
@wraps(func)
def wrapper(self, *args, **kwargs):
+5
View File
@@ -12,6 +12,7 @@ from trytond.config import config, get_hostname
from trytond.exceptions import (
ConcurrencyException, LoginException, RateLimitException, UserError,
UserWarning)
from trytond.rpc import RPCReturnException
from trytond.tools import is_instance_method
from trytond.transaction import Transaction, TransactionError
from trytond.worker import run_task
@@ -221,6 +222,10 @@ def _dispatch(request, pool, *args, **kwargs):
continue
logger.exception(log_message, *log_args, duration())
raise
except RPCReturnException as e:
transaction.rollback()
transaction.tasks.clear()
result = e.result()
except (ConcurrencyException, UserError, UserWarning,
LoginException):
logger.info(
+8 -2
View File
@@ -3,10 +3,9 @@
import copy
import datetime as dt
from trytond.exceptions import TrytonException
from trytond.transaction import Transaction
__all__ = ['RPC']
class RPC(object):
'''Define RPC behavior
@@ -95,3 +94,10 @@ class RPCCache:
return {
'X-Tryton-Cache': int(self.duration.total_seconds()),
}
class RPCReturnException(TrytonException):
"Exception to return response instead of being raised"
def result(self):
pass
+26 -1
View File
@@ -6,7 +6,8 @@ from unittest.mock import patch
from lxml import etree
from trytond.model.exceptions import AccessButtonError, AccessError
from trytond.model.exceptions import (
AccessButtonError, AccessError, ButtonActionException)
from trytond.pool import Pool
from trytond.pyson import Eval, PYSONDecoder, PYSONEncoder
from trytond.tests.test_tryton import activate_module, with_transaction
@@ -689,3 +690,27 @@ class ModelView(unittest.TestCase):
self.assertIn('bar', writeable_fields)
self.assertIn('baz', writeable_fields)
self.assertIn('quux', writeable_fields)
@with_transaction()
def test_button_action_exception(self):
"Test value of ButtonActionException"
exception = ButtonActionException('tests.test_modelview_button_action')
self.assertEqual(exception.value, {
**exception.value,
'name': "Test Button Action",
'url': 'http://www.example.com/',
})
@with_transaction()
def test_button_action_exception_value(self):
"Test value of ButtonActionException"
exception = ButtonActionException(
'tests.test_modelview_button_action',
value={
'url': 'https://www.example.net',
})
self.assertEqual(exception.value, {
**exception.value,
'name': "Test Button Action",
'url': 'https://www.example.net',
})