[6.1] impossible to call super in ids getter method of store from function field : wrong self type

Bug #893079 reported by Yannick Vaucher @ Camptocamp
10
This bug affects 2 people
Affects Status Importance Assigned to Milestone
Odoo Server (MOVED TO GITHUB)
Confirmed
Wishlist
OpenERP's Framework R&D

Bug Description

Hello,

I found that it is impossible to override a method used in a stored function field.

For exemple, I try to extend account.analytic.line depending on /analytic_multicurrency/account_analytic_line.py .
This for the following fields :

 _columns = {
          'aa_currency_id': fields.function(_get_account_currency, method=True, type='many2one', relation='res.currency', string='Account currency',
                  store={
                      'account.analytic.account': (_get_account_line, ['currency_id','company_id'], 50),
                      'account.analytic.line': (lambda self,cr,uid,ids,c={}: ids, ['amount','unit_amount','product_uom_id'],10),
                  },
                  help="The related analytic account currency."),
          'aa_amount_currency': fields.function(_amount_currency, method=True, digits=(16, int(config['price_accuracy'])), string='Amount currency',
                  store={
                      'account.analytic.account': (_get_account_line, ['currency_id','company_id'], 50),
                      'account.analytic.line': (lambda self,cr,uid,ids,c={}: ids, ['amount','unit_amount','product_uom_id'],10),
                  },
                  help="The amount expressed in the related analytic account currency."),
          'company_id': fields.related('general_account_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True, readonly=True),
    }

Now, here are the problems :
1) To extend the triggers on multi, by adding one new object to check, I have to rewrite the whole store dict
2) I will have to redefine _get_account_line or any trigger method as it seems out of scope for store triggering.
3) I can't use 'super' in rewritten method. -> no override is possible

No inheritance is possible because the 'self' which is given by the trigger is an instance of the triggering object calling a method of the triggered object.

I also tried to define the function that way :

from analytic_multicurrency import account_analytic_line
_get_account_line = account_analytic_line.account_analytic_line._get_account_line

Still the error on store load is

 TypeError: unbound method _get_account_line() must be called with account_analytic_line instance as first argument (got account.analytic.account instance instead)

The only way I found is to rewrite the whole getter method in my new class. That's a bit dirty.

My running python : Python 2.6.5 (r265:79063, Apr 16 2010, 13:09:56)

Yannick

Revision history for this message
Olivier Dony (Odoo) (odo-openerp) wrote :

Hi Yannick,

These are limitations of the framework, not bugs, and are closely related to the way Python functions are declared and passed as parameters. So to answer your questions:

1) Yes this is normal, the store trigger is not currently overridable, and this looks OK because you'd be breaking the OO encapsulation. There is usually no sense in doing that unless you're also redefining the implementing function, in which case you'll have to redefine the field anyway.

2 & 3) When defining a fields.function instance, the implementing function is passed as a copy of the function object, at the time it is constructed. The same is true for the store trigger functions. Therefore trying to override them will have no effect on the field, you have to redefine them completely.
Secondly, when you reference a method (as in account_analytic_line.account_analytic_line._get_account_line) and attach it to another object, you're silently unbinding/rebinding them (tricky Python methods mechanism) and you will probably never get the expected result.

Both of these use cases are not supported at the moment, and therefore I'll mark this bug as wishlist.
Feel free to suggest a clean framework API improvement to support them in the future.

As a hint, one way around these limitations would be to define the fields.function with a wrapper function that really calls the model's method, allowing to override it normally, and chain it properly with super() calls.
Even better, fields.function's constructor could play smart tricks with the function object it receives as parameters and store only their name, so that it can call the original methods on the object properly. Still, a mechanism for inheriting cleanly the store trigger rules would be needed.

Changed in openobject-server:
assignee: nobody → OpenERP's Framework R&D (openerp-dev-framework)
importance: Undecided → Wishlist
status: New → Confirmed
Revision history for this message
David Mitchell (www.novapointgroup.com) (david-novapointgroup.com) wrote :
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.