From fe4872f10c91f709572f04d3640b323d1eaf3633 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Fri, 30 Oct 2015 12:27:18 +0100 Subject: [PATCH] [IMP] api: add a decorator for old-API methods that take records as parameters The decorator transforms old-API calls like model.method(cr, uid, records, args) into records.method(args) --- openerp/addons/base/res/res_currency.py | 44 +++++---------------- openerp/api.py | 51 +++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 35 deletions(-) diff --git a/openerp/addons/base/res/res_currency.py b/openerp/addons/base/res/res_currency.py index 85f383f7825..5c65e4e553c 100644 --- a/openerp/addons/base/res/res_currency.py +++ b/openerp/addons/base/res/res_currency.py @@ -114,12 +114,7 @@ class res_currency(osv.osv): return super(res_currency, self).copy( cr, uid, id, default=default, context=context) - @api.v8 - def round(self, amount): - """ Return `amount` rounded according to currency `self`. """ - return float_round(amount, precision_rounding=self.rounding) - - @api.v7 + @api.cr_uid_records def round(self, cr, uid, currency, amount): """Return ``amount`` rounded according to ``currency``'s rounding rules. @@ -127,25 +122,12 @@ class res_currency(osv.osv): :param Record currency: currency for which we are rounding :param float amount: the amount to round :return: rounded float + + With the new API, call it like: ``currency.round(amount)``. """ return float_round(amount, precision_rounding=currency.rounding) - @api.v8 - def compare_amounts(self, amount1, amount2): - """ Compare `amount1` and `amount2` after rounding them according to - `self`'s precision. An amount is considered lower/greater than - another amount if their rounded value is different. This is not the - same as having a non-zero difference! - - For example 1.432 and 1.431 are equal at 2 digits precision, so this - method would return 0. However 0.006 and 0.002 are considered - different (returns 1) because they respectively round to 0.01 and - 0.0, even though 0.006-0.002 = 0.004 which would be considered zero - at 2 digits precision. - """ - return float_compare(amount1, amount2, precision_rounding=self.rounding) - - @api.v7 + @api.cr_uid_records def compare_amounts(self, cr, uid, currency, amount1, amount2): """Compare ``amount1`` and ``amount2`` after rounding them according to the given currency's precision.. @@ -164,22 +146,12 @@ class res_currency(osv.osv): :return: (resp.) -1, 0 or 1, if ``amount1`` is (resp.) lower than, equal to, or greater than ``amount2``, according to ``currency``'s rounding. + + With the new API, call it like: ``currency.compare_amounts(amount1, amount2)``. """ return float_compare(amount1, amount2, precision_rounding=currency.rounding) - @api.v8 - def is_zero(self, amount): - """ Return true if `amount` is small enough to be treated as zero - according to currency `self`'s rounding rules. - - Warning: ``is_zero(amount1-amount2)`` is not always equivalent to - ``compare_amounts(amount1,amount2) == 0``, as the former will round - after computing the difference, while the latter will round before, - giving different results, e.g., 0.006 and 0.002 at 2 digits precision. - """ - return float_is_zero(amount, precision_rounding=self.rounding) - - @api.v7 + @api.cr_uid_records def is_zero(self, cr, uid, currency, amount): """Returns true if ``amount`` is small enough to be treated as zero according to ``currency``'s rounding rules. @@ -191,6 +163,8 @@ class res_currency(osv.osv): :param Record currency: currency for which we are rounding :param float amount: amount to compare with currency's zero + + With the new API, call it like: ``currency.is_zero(amount)``. """ return float_is_zero(amount, precision_rounding=currency.rounding) diff --git a/openerp/api.py b/openerp/api.py index a2388081cd8..7492ff27410 100644 --- a/openerp/api.py +++ b/openerp/api.py @@ -550,6 +550,57 @@ def cr_uid_ids_context(method): return make_wrapper(cr_uid_ids_context, method, method, new_api) +def cr_uid_records(method): + """ Decorate a traditional-style method that takes ``cr``, ``uid``, a + recordset of model ``self`` as parameters. Such a method:: + + @api.cr_uid_records + def method(self, cr, uid, records, args): + ... + + may be called in both record and traditional styles, like:: + + # records = model.browse(cr, uid, ids, context) + records.method(args) + + model.method(cr, uid, records, args) + """ + upgrade = get_upgrade(method) + + def new_api(self, *args, **kwargs): + cr, uid, context = self.env.args + result = method(self._model, cr, uid, self, *args, **kwargs) + return upgrade(self, result) + + return make_wrapper(cr_uid_records, method, method, new_api) + + +def cr_uid_records_context(method): + """ Decorate a traditional-style method that takes ``cr``, ``uid``, a + recordset of model ``self``, ``context`` as parameters. Such a method:: + + @api.cr_uid_records_context + def method(self, cr, uid, records, args, context=None): + ... + + may be called in both record and traditional styles, like:: + + # records = model.browse(cr, uid, ids, context) + records.method(args) + + model.method(cr, uid, records, args, context=context) + """ + upgrade = get_upgrade(method) + + def new_api(self, *args, **kwargs): + cr, uid, context = self.env.args + kwargs['context'] = context + result = method(self._model, cr, uid, self, *args, **kwargs) + return upgrade(self, result) + + return make_wrapper(cr_uid_records_context, method, method, new_api) + + def v7(method_v7): """ Decorate a method that supports the old-style api only. A new-style api may be provided by redefining a method with the same name and decorated