Antony Lesuisse (OpenERP) has proposed merging
lp:~openerp-dev/openobject-server/trunk-fix-o2m-in-contexts-xmo-simple into
lp:openobject-server.
Requested reviews:
OpenERP Core Team (openerp)
For more details, see:
https://code.launchpad.net/~openerp-dev/openobject-server/trunk-fix-o2m-in-contexts-xmo-simple/+merge/78893
Alternative to
https://code.launchpad.net/~openerp-dev/openobject-server/trunk-fix-o2m-in-contexts-xmo/+merge/78845
--
https://code.launchpad.net/~openerp-dev/openobject-server/trunk-fix-o2m-in-contexts-xmo-simple/+merge/78893
Your team OpenERP R&D Team is subscribed to branch
lp:~openerp-dev/openobject-server/trunk-fix-o2m-in-contexts-xmo-simple.
=== modified file 'openerp/addons/base/res/res_bank.py'
--- openerp/addons/base/res/res_bank.py 2011-10-10 08:10:21 +0000
+++ openerp/addons/base/res/res_bank.py 2011-10-10 22:40:23 +0000
@@ -108,14 +108,8 @@
if not context.get('address'):
return value
- for _, id, address_data in context['address']:
- if not (id or address): continue
- address = {}
- if id:
- address.update(self.pool['res.partner.address']
- .read(cursor, user, [id], ['type', field], context=context)[0])
- if address_data:
- address.update(address_data)
+ for address in self.pool.get('res.partner').serialize_o2m_commands(
+ cursor, user, 'address', context['address'], ['type', field], context=context):
if address.get('type') == 'default':
return address.get(field, value)
=== modified file 'openerp/osv/orm.py'
--- openerp/osv/orm.py 2011-10-07 14:49:44 +0000
+++ openerp/osv/orm.py 2011-10-10 22:40:23 +0000
@@ -4762,6 +4762,45 @@
return True
+ def serialize_o2m_commands(self, cr, uid, field_name, o2m_commands, fields=None, context=None):
+ """ Serializes o2m commands into record dictionaries (as if
+ all the o2m records came from the database via a read()), and
+ returns an iterator over these dictionaries.
+
+ Because o2m commands might be creation commands, not all
+ record ids will contain an ``id`` field. Commands matching an
+ existing record (UPDATE and LINK_TO) will have an id.
+
+ :param field_name: name of the o2m field matching the commands
+ :type field_name: str
+ :param o2m_commands: one2many commands to execute on ``field_name``
+ :type o2m_commands: list((int|False, int|False, dict|False))
+ :param fields: list of fields to read from the database, when applicable
+ :type fields: list(str)
+ :param context: request context
+ :returns: o2m records in a shape similar to that returned by
+ ``read()`` (except records may be missing the ``id``
+ field if they don't exist in db)
+ :rtype: iter(dict)
+ """
+ o2m_model = self._all_columns[field_name].column._obj
+ result = []
+ for c in o2m_commands:
+ # Convert ids to 4:LINK_TO commands
+ if not isinstance(c, (list, tuple)):
+ c = (4, c, None)
+ # Process command 0:create 1:update 4:link_to
+ mode, id, arg = c
+ if mode == 0:
+ v = arg
+ elif mode == 1:
+ v = self.pool.get(o2m_model).read(cr, uid, [id], fields=fields, context=context)[0]
+ v.update(arg)
+ elif mode == 4:
+ v = self.pool.get(o2m_model).read(cr, uid, [id], fields=fields, context=context)[0]
+ result.append(v)
+ return result
+
# keep this import here, at top it will cause dependency cycle errors
import expression
=== added file 'tests/test_orm.py'
--- tests/test_orm.py 1970-01-01 00:00:00 +0000
+++ tests/test_orm.py 2011-10-10 22:40:23 +0000
@@ -0,0 +1,121 @@
+import os
+import unittest2
+import openerp
+
+UID = 1
+DB = os.environ['OPENERP_DATABASE']
+
+CREATE = lambda values: (0, False, values)
+UPDATE = lambda id, values: (1, id, values)
+LINK_TO = lambda id: (4, id, False)
+
+
+def setUpModule():
+ openerp.tools.config['addons_path'] = os.environ['OPENERP_ADDONS_PATH']
+
+class TestO2MSerialization(unittest2.TestCase):
+ def setUp(self):
+ self.cr = openerp.modules.registry.RegistryManager.get(DB).db.cursor()
+ self.partner = openerp.modules.registry.RegistryManager.get(DB)['res.partner']
+ self.address = openerp.modules.registry.RegistryManager.get(DB)['res.partner.address']
+ def tearDown(self):
+ self.cr.rollback()
+ self.cr.close()
+
+ def test_no_command(self):
+ " empty list of commands yields an empty list of records "
+ results = list(self.partner.serialize_o2m_commands(self.cr, UID, 'address', []))
+
+ self.assertEqual(results, [])
+
+ def test_CREATE_commands(self):
+ " returns the VALUES dict as-is "
+ results = list(self.partner.serialize_o2m_commands(
+ self.cr, UID, 'address',
+ map(CREATE, [{'foo': 'bar'}, {'foo': 'baz'}, {'foo': 'baq'}])))
+ self.assertEqual(results, [
+ {'foo': 'bar'},
+ {'foo': 'baz'},
+ {'foo': 'baq'}
+ ])
+
+ def test_LINK_TO_command(self):
+ " reads the records from the database, records are returned with their ids. "
+ ids = [
+ self.address.create(self.cr, UID, {'name': 'foo'}),
+ self.address.create(self.cr, UID, {'name': 'bar'}),
+ self.address.create(self.cr, UID, {'name': 'baz'})
+ ]
+ commands = map(LINK_TO, ids)
+
+ results = list(self.partner.serialize_o2m_commands(self.cr, UID, 'address', commands, ['name']))
+
+ self.assertEqual(results, [
+ {'id': ids[0], 'name': 'foo'},
+ {'id': ids[1], 'name': 'bar'},
+ {'id': ids[2], 'name': 'baz'}
+ ])
+
+ def test_bare_ids_command(self):
+ " same as the equivalent LINK_TO commands "
+ ids = [
+ self.address.create(self.cr, UID, {'name': 'foo'}),
+ self.address.create(self.cr, UID, {'name': 'bar'}),
+ self.address.create(self.cr, UID, {'name': 'baz'})
+ ]
+
+ results = list(self.partner.serialize_o2m_commands(self.cr, UID, 'address', ids, ['name']))
+
+ self.assertEqual(results, [
+ {'id': ids[0], 'name': 'foo'},
+ {'id': ids[1], 'name': 'bar'},
+ {'id': ids[2], 'name': 'baz'}
+ ])
+
+ def test_UPDATE_command(self):
+ " take the in-db records and merge the provided information in "
+ id_foo = self.address.create(self.cr, UID, {'name': 'foo'})
+ id_bar = self.address.create(self.cr, UID, {'name': 'bar'})
+ id_baz = self.address.create(self.cr, UID, {'name': 'baz', 'city': 'tag'})
+
+ results = list(self.partner.serialize_o2m_commands(
+ self.cr, UID, 'address', [
+ LINK_TO(id_foo),
+ UPDATE(id_bar, {'name': 'qux', 'city': 'tagtag'}),
+ UPDATE(id_baz, {'name': 'quux'})
+ ], ['name', 'city']))
+
+ self.assertEqual(results, [
+ {'id': id_foo, 'name': 'foo', 'city': False},
+ {'id': id_bar, 'name': 'qux', 'city': 'tagtag'},
+ {'id': id_baz, 'name': 'quux', 'city': 'tag'}
+ ])
+
+ def test_mixed_commands(self):
+ ids = [
+ self.address.create(self.cr, UID, {'name': name})
+ for name in ['NObar', 'baz', 'qux', 'NOquux', 'NOcorge', 'garply']
+ ]
+
+ results = list(self.partner.serialize_o2m_commands(
+ self.cr, UID, 'address', [
+ CREATE({'name': 'foo'}),
+ UPDATE(ids[0], {'name': 'bar'}),
+ LINK_TO(ids[1]),
+ LINK_TO(ids[2]),
+ UPDATE(ids[3], {'name': 'quux',}),
+ UPDATE(ids[4], {'name': 'corge'}),
+ CREATE({'name': 'grault'}),
+ LINK_TO(ids[5])
+ ], ['name']))
+
+ self.assertEqual(results, [
+ {'name': 'foo'},
+ {'id': ids[0], 'name': 'bar'},
+ {'id': ids[1], 'name': 'baz'},
+ {'id': ids[2], 'name': 'qux'},
+ {'id': ids[3], 'name': 'quux'},
+ {'id': ids[4], 'name': 'corge'},
+ {'name': 'grault'},
+ {'id': ids[5], 'name': 'garply'}
+ ])
_______________________________________________
Mailing list: https://launchpad.net/~openerp-dev-gtk
Post to : [email protected]
Unsubscribe : https://launchpad.net/~openerp-dev-gtk
More help : https://help.launchpad.net/ListHelp