[IMP] fields: improve _determine_default() and add test for inherited fields
authorRaphael Collet <rco@openerp.com>
Thu, 6 Nov 2014 08:59:41 +0000 (09:59 +0100)
committerRaphael Collet <rco@openerp.com>
Thu, 6 Nov 2014 11:20:39 +0000 (12:20 +0100)
openerp/addons/test_inherit/models.py
openerp/addons/test_inherit/tests/test_inherit.py
openerp/fields.py

index 1a386a2..422d59f 100644 (file)
@@ -69,4 +69,7 @@ class daughter(models.Model):
     # simply redeclare the field without adding any option
     template_id = fields.Many2one()
 
+    # change the default value of an inherited field
+    name = fields.Char(default='Baz')
+
 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
index e9be815..6909882 100644 (file)
@@ -17,19 +17,25 @@ class test_inherits(common.TransactionCase):
 
     def test_field_extension(self):
         """ check the extension of a field in an inherited model """
-        # the field mother.name should inherit required=True, and have "Bar" as
-        # a default value
         mother = self.env['test.inherit.mother']
+        daughter = self.env['test.inherit.daughter']
+
+        # the field mother.name must have required=True and "Bar" as default
         field = mother._fields['name']
         self.assertTrue(field.required)
-
         self.assertEqual(field.default(mother), "Bar")
-        self.assertEqual(mother.default_get(['name']), {'name': "Bar"})
         self.assertEqual(mother._defaults.get('name'), "Bar")
+        self.assertEqual(mother.default_get(['name']), {'name': "Bar"})
 
-        # the field daughter.template_id should inherit
-        # model_name='test.inherit.mother', string='Template', required=True
-        daughter = self.env['test.inherit.daughter']
+        # the field daughter.name must have required=False and "Baz" as default
+        field = daughter._fields['name']
+        self.assertFalse(field.required)
+        self.assertEqual(field.default(mother), "Baz")
+        self.assertEqual(daughter._defaults.get('name'), "Baz")
+        self.assertEqual(daughter.default_get(['name']), {'name': "Baz"})
+
+        # the field daughter.template_id should have
+        # comodel_name='test.inherit.mother', string='Template', required=True
         field = daughter._fields['template_id']
         self.assertEqual(field.comodel_name, 'test.inherit.mother')
         self.assertEqual(field.string, "Template")
index 2d5e0c2..417591c 100644 (file)
@@ -347,30 +347,36 @@ class Field(object):
         # traverse the class hierarchy upwards, and take the first field
         # definition with a default or _defaults for self
         for klass in cls.__mro__:
-            field = klass.__dict__.get(name, self)
-            if not isinstance(field, type(self)):
-                return      # klass contains another value overridden by self
+            if name in klass.__dict__:
+                field = klass.__dict__[name]
+                if not isinstance(field, type(self)):
+                    # klass contains another value overridden by self
+                    return
 
-            if 'default' in field._attrs:
-                # take the default in field, and adapt it for cls._defaults
-                value = field._attrs['default']
-                if callable(value):
-                    self.default = value
-                    cls._defaults[name] = lambda model, cr, uid, context: \
-                        self.convert_to_write(value(model.browse(cr, uid, [], context)))
-                else:
-                    self.default = lambda recs: value
-                    cls._defaults[name] = value
-                return
+                if 'default' in field._attrs:
+                    # take the default in field, and adapt it for cls._defaults
+                    value = field._attrs['default']
+                    if callable(value):
+                        from openerp import api
+                        self.default = value
+                        cls._defaults[name] = api.model(
+                            lambda recs: self.convert_to_write(value(recs))
+                        )
+                    else:
+                        self.default = lambda recs: value
+                        cls._defaults[name] = value
+                    return
 
             defaults = klass.__dict__.get('_defaults') or {}
             if name in defaults:
                 # take the value from _defaults, and adapt it for self.default
                 value = defaults[name]
-                value_func = value if callable(value) else lambda *args: value
+                if callable(value):
+                    func = lambda recs: value(recs._model, recs._cr, recs._uid, recs._context)
+                else:
+                    func = lambda recs: value
                 self.default = lambda recs: self.convert_to_cache(
-                    value_func(recs._model, recs._cr, recs._uid, recs._context),
-                    recs, validate=False,
+                    func(recs), recs, validate=False,
                 )
                 cls._defaults[name] = value
                 return