Merge lp:~openerp-community/openobject-server/stefan-therp_lp727727-6.1 into lp:openobject-server

Proposed by Stefan Rijnhart (Opener)
Status: Merged
Approved by: Olivier Dony (Odoo)
Approved revision: 3782
Merged at revision: 3808
Proposed branch: lp:~openerp-community/openobject-server/stefan-therp_lp727727-6.1
Merge into: lp:openobject-server
Diff against target: 91 lines (+13/-4)
4 files modified
openerp/addons/base/base_data.xml (+1/-2)
openerp/addons/base/module/module_view.xml (+0/-1)
openerp/addons/base/res/res_partner_view.xml (+0/-1)
openerp/osv/orm.py (+12/-0)
To merge this branch: bzr merge lp:~openerp-community/openobject-server/stefan-therp_lp727727-6.1
Reviewer Review Type Date Requested Status
Olivier Dony (Odoo) Approve
Stefan Rijnhart (Opener) (community) Needs Resubmitting
Review via email: mp+80904@code.launchpad.net

Description of the change

This branch issues a warning when a value is passed to the ORM for a non existing field during create() or write(). These values are simply dropped, which can lead to data loss. Additionaly, this branch corrects non existing fields in the base module's XML files.

To post a comment you must log in.
Revision history for this message
Olivier Dony (Odoo) (odo-openerp) wrote :

Hi Stefan,

I agree that silently ignoring unknown fields in create() and write() can be a source of errors, especially while creating new module and debugging, so it would be a good practice to enforce that.

However, I can also imagine many cases where this situation is abused at the moment, because it makes the code simpler (e.g. when working with "virtual" columns), or just because it was overlooked. Indeed it would be better to fix 100% of these cases (and raising an exception would help that), but that would also mean a possibly great number of fixes will be needed in many modules, both community and core. While useful, those fixes are mostly nice-to-have, and are not likely to fix real bugs in existing modules.
So in the current case, I think logging a WARNING message would be better as a first step. That would still help for developing/debugging, and allow a progressive cleanup of existing abuse cases without breaking too much stuff. Maybe you could even use warnings.DeprecationWarning to indicate that in a future version this may indeed be completely forbidden.

Some other minor remarks:
- for consistency, read()/_read_flat() should do the same w.r.t. to unknown fields
- in error messages, why not mention directly all unknown fields, rather than just the first one? Log messages must not be translated so using different messages will not be a concern anymore, if it's easier.

The cleanup of XML files is very welcome, too!

Many thanks for the clean merge proposal, as always.

PS: I'll change the merge prop status to "Work in Progress", do not forget to change it back when you request another review - this is to help us sort out the numerous merge props, as review comments do not directly allow this.

review: Needs Fixing
Revision history for this message
Stefan Rijnhart (Opener) (stefan-opener) wrote :

Hi Olivier,

thanks again for the valuable review.

On your suggestion, I have replaced the exception with a warning. I used a logging.warn instead of a warnings.DeprecationWarning as these cannot easily be redirected to the application log unless one requires Python 2.7 (with logging.captureWarnings()).

Also, it does indeed make sense to mention all unknown fields at once.

However, I cannot think of a situation that warrants the overhead of performing a similar check in every read operation. Usually, the absense of fields will become immediately clear when trying to read their values from the resulting data structure. For completeness, note that a check on non-existing fields in domain expressions does already exist in expression.py.

Regards,
Stefan.

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

I can live with logging.warn and not having an explicit check in read() :-)
It's less consistent, but it's true that data loss is not as much a concern as with create/write.

Thanks for the update, great job!

review: Approve
Revision history for this message
Stefan Rijnhart (Opener) (stefan-opener) wrote :

Hi Olivier,

Thanks for all your work on this review and other community branches!

Cheers,
Stefan.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'openerp/addons/base/base_data.xml'
2--- openerp/addons/base/base_data.xml 2011-10-24 12:02:19 +0000
3+++ openerp/addons/base/base_data.xml 2011-11-02 20:27:24 +0000
4@@ -1580,7 +1580,6 @@
5
6 <record id="res_bank_1" model="res.bank">
7 <field name="name">Reserve</field>
8- <field name="code">RSV</field>
9 </record>
10
11 <record id="CRC" model="res.currency">
12@@ -1600,7 +1599,7 @@
13 <field name="name">localhost</field>
14 <field name="smtp_host">localhost</field>
15 <field eval="25" name="smtp_port"/>
16- <field eval="10" name="priority"/>
17+ <field eval="10" name="sequence"/>
18 </record>
19
20 <record id="MUR" model="res.currency">
21
22=== modified file 'openerp/addons/base/module/module_view.xml'
23--- openerp/addons/base/module/module_view.xml 2011-07-27 12:34:44 +0000
24+++ openerp/addons/base/module/module_view.xml 2011-11-02 20:27:24 +0000
25@@ -75,7 +75,6 @@
26 <field eval="'ir.module.category'" name="model"/>
27 <field name="name">Categorized Modules</field>
28 <field eval="'ir.actions.act_window,%d'%action_module_open_categ" name="value"/>
29- <field eval="True" name="object"/>
30 </record>
31
32
33
34=== modified file 'openerp/addons/base/res/res_partner_view.xml'
35--- openerp/addons/base/res/res_partner_view.xml 2011-10-25 20:48:47 +0000
36+++ openerp/addons/base/res/res_partner_view.xml 2011-11-02 20:27:24 +0000
37@@ -651,7 +651,6 @@
38 <field eval="'res.partner.category'" name="model"/>
39 <field name="name">Open partners</field>
40 <field eval="'ir.actions.act_window,%d'%action_partner_by_category" name="value"/>
41- <field eval="True" name="object"/>
42 </record>
43
44 <record id="action_partner_category_form" model="ir.actions.act_window">
45
46=== modified file 'openerp/osv/orm.py'
47--- openerp/osv/orm.py 2011-10-19 11:46:18 +0000
48+++ openerp/osv/orm.py 2011-11-02 20:27:24 +0000
49@@ -3808,6 +3808,7 @@
50 for id in ids:
51 result += self._columns[field].set(cr, self, id, field, vals[field], user, context=rel_context) or []
52
53+ unknown_fields = updend[:]
54 for table in self._inherits:
55 col = self._inherits[table]
56 nids = []
57@@ -3820,9 +3821,14 @@
58 for val in updend:
59 if self._inherit_fields[val][0] == table:
60 v[val] = vals[val]
61+ unknown_fields.remove(val)
62 if v:
63 self.pool.get(table).write(cr, user, nids, v, context)
64
65+ if unknown_fields:
66+ self.__logger.warn(
67+ 'No such field(s) in model %s: %s.',
68+ self._name, ', '.join(unknown_fields))
69 self._validate(cr, user, ids, context)
70
71 # TODO: use _order to set dest at the right position and not first node of parent
72@@ -3945,6 +3951,7 @@
73 tocreate[v] = {'id': vals[self._inherits[v]]}
74 (upd0, upd1, upd2) = ('', '', [])
75 upd_todo = []
76+ unknown_fields = []
77 for v in vals.keys():
78 if v in self._inherit_fields:
79 (table, col, col_detail, original_parent) = self._inherit_fields[v]
80@@ -3953,6 +3960,11 @@
81 else:
82 if (v not in self._inherit_fields) and (v not in self._columns):
83 del vals[v]
84+ unknown_fields.append(v)
85+ if unknown_fields:
86+ self.__logger.warn(
87+ 'No such field(s) in model %s: %s.',
88+ self._name, ', '.join(unknown_fields))
89
90 # Try-except added to filter the creation of those records whose filds are readonly.
91 # Example : any dashboard which has all the fields readonly.(due to Views(database views))