diff --git a/trytond/model/modelsql.py b/trytond/model/modelsql.py index 8c6a048428..5c0fd67eb9 100644 --- a/trytond/model/modelsql.py +++ b/trytond/model/modelsql.py @@ -576,8 +576,14 @@ class ModelSQL(ModelStorage): translation_values.setdefault( '%s,%s' % (cls.__name__, fname), {})[new_id] = value if hasattr(field, 'set'): - fields_to_set.setdefault(fname, []).extend( - ([new_id], value)) + args = fields_to_set.setdefault(fname, []) + actions = iter(args) + for ids, val in zip(actions, actions): + if val == value: + ids.append(new_id) + break + else: + args.extend(([new_id], value)) if translation_values: for name, translations in translation_values.iteritems(): diff --git a/trytond/tests/__init__.py b/trytond/tests/__init__.py index 3c8cab60b8..a16f4c25f3 100644 --- a/trytond/tests/__init__.py +++ b/trytond/tests/__init__.py @@ -106,6 +106,7 @@ def register(): ModelStorage, ModelSQLRequiredField, ModelSQLTimestamp, + ModelSQLFieldSet, Model4Union1, Model4Union2, Model4Union3, diff --git a/trytond/tests/model.py b/trytond/tests/model.py index 835eb99d1c..c0d17307b6 100644 --- a/trytond/tests/model.py +++ b/trytond/tests/model.py @@ -5,7 +5,7 @@ from trytond.model import ModelSingleton, ModelSQL, UnionMixin, fields __all__ = [ 'Singleton', 'URLObject', 'ModelStorage', - 'ModelSQLRequiredField', 'ModelSQLTimestamp', + 'ModelSQLRequiredField', 'ModelSQLTimestamp', 'ModelSQLFieldSet', 'Model4Union1', 'Model4Union2', 'Model4Union3', 'Model4Union4', 'Union', 'UnionUnion', 'Model4UnionTree1', 'Model4UnionTree2', 'UnionTree', @@ -47,6 +47,21 @@ class ModelSQLTimestamp(ModelSQL): __name__ = 'test.modelsql.timestamp' +class ModelSQLFieldSet(ModelSQL): + 'Model to test field set' + __name__ = 'test.modelsql.field_set' + + field = fields.Function(fields.Integer('Field'), + 'get_field', setter='set_field') + + def get_field(self, name=None): + return + + @classmethod + def set_field(cls, records, name, value): + pass + + class Model4Union1(ModelSQL): 'Model for union 1' __name__ = 'test.model.union1' diff --git a/trytond/tests/test_modelsql.py b/trytond/tests/test_modelsql.py index bf42a01c5d..7c47414009 100644 --- a/trytond/tests/test_modelsql.py +++ b/trytond/tests/test_modelsql.py @@ -5,6 +5,8 @@ import unittest import time +from mock import patch, call + from trytond import backend from trytond.exceptions import UserError, ConcurrencyException from trytond.transaction import Transaction @@ -81,6 +83,37 @@ class ModelSQLTestCase(unittest.TestCase): ModelsqlTimestamp.delete([record]) transaction.commit() + @with_transaction() + def test_create_field_set(self): + 'Test field.set in create' + pool = Pool() + Model = pool.get('test.modelsql.field_set') + + with patch.object(Model, 'set_field') as setter: + records = Model.create([{'field': 1}]) + setter.assert_called_with(records, 'field', 1) + + # Different values are not grouped + with patch.object(Model, 'set_field') as setter: + records = Model.create([{'field': 1}, {'field': 2}]) + setter.assert_has_calls([ + call([records[0]], 'field', 1), + call([records[1]], 'field', 2), + ]) + + # Same values are grouped in one call + with patch.object(Model, 'set_field') as setter: + records = Model.create([{'field': 1}, {'field': 1}]) + setter.assert_called_with(records, 'field', 1) + + # Mixed values are grouped per value + with patch.object(Model, 'set_field') as setter: + records = Model.create([{'field': 1}, {'field': 2}, {'field': 1}]) + setter.assert_has_calls([ + call([records[0], records[2]], 'field', 1), + call([records[1]], 'field', 2), + ]) + def suite(): return unittest.TestLoader().loadTestsFromTestCase(ModelSQLTestCase)