1 # -*- coding: utf-8 -*-
2 import openerp.modules.registry
5 from openerp.tests import common
6 from openerp.tools.misc import mute_logger
8 def message(msg, type='error', from_=0, to_=0, record=0, field='value'):
11 'rows': {'from': from_, 'to': to_},
17 def error(row, message, record=None, **kwargs):
18 """ Failed import of the record ``record`` at line ``row``, with the error
25 -1, dict(record or {}, **kwargs),
26 "Line %d : %s" % (row, message),
29 def values(seq, field='value'):
30 return [item[field] for item in seq]
32 class ImporterCase(common.TransactionCase):
35 def __init__(self, *args, **kwargs):
36 super(ImporterCase, self).__init__(*args, **kwargs)
40 super(ImporterCase, self).setUp()
41 self.model = self.registry(self.model_name)
42 self.registry('ir.model.data').clear_caches()
44 def import_(self, fields, rows, context=None):
45 return self.model.load(
46 self.cr, openerp.SUPERUSER_ID, fields, rows, context=context)
47 def read(self, fields=('value',), domain=(), context=None):
48 return self.model.read(
49 self.cr, openerp.SUPERUSER_ID,
50 self.model.search(self.cr, openerp.SUPERUSER_ID, domain, context=context),
51 fields=fields, context=context)
52 def browse(self, domain=(), context=None):
53 return self.model.browse(
54 self.cr, openerp.SUPERUSER_ID,
55 self.model.search(self.cr, openerp.SUPERUSER_ID, domain, context=context),
58 def xid(self, record):
59 ModelData = self.registry('ir.model.data')
61 ids = ModelData.search(
62 self.cr, openerp.SUPERUSER_ID,
63 [('model', '=', record._table_name), ('res_id', '=', record.id)])
66 self.cr, openerp.SUPERUSER_ID, ids, ['name', 'module'])[0]
68 return '%s.%s' % (d['module'], d['name'])
71 name = dict(record.name_get())[record.id]
72 # fix dotted name_get results, otherwise xid lookups blow up
73 name = name.replace('.', '-')
74 ModelData.create(self.cr, openerp.SUPERUSER_ID, {
76 'model': record._table_name,
80 return '__test__.' + name
82 class test_ids_stuff(ImporterCase):
83 model_name = 'export.integer'
85 def test_create_with_id(self):
86 ids, messages = self.import_(['.id', 'value'], [['42', '36']])
87 self.assertIs(ids, False)
88 self.assertEqual(messages, [{
90 'rows': {'from': 0, 'to': 0},
93 'message': u"Unknown database identifier '42'",
95 def test_create_with_xid(self):
96 ids, messages = self.import_(['id', 'value'], [['somexmlid', '42']])
97 self.assertEqual(len(ids), 1)
98 self.assertFalse(messages)
101 self.xid(self.browse()[0]))
103 def test_update_with_id(self):
104 id = self.model.create(self.cr, openerp.SUPERUSER_ID, {'value': 36})
107 self.model.browse(self.cr, openerp.SUPERUSER_ID, id).value)
109 ids, messages = self.import_(['.id', 'value'], [[str(id), '42']])
110 self.assertEqual(len(ids), 1)
111 self.assertFalse(messages)
113 [42], # updated value to imported
116 def test_update_with_xid(self):
117 self.import_(['id', 'value'], [['somexmlid', '36']])
118 self.assertEqual([36], values(self.read()))
120 self.import_(['id', 'value'], [['somexmlid', '1234567']])
121 self.assertEqual([1234567], values(self.read()))
123 class test_boolean_field(ImporterCase):
124 model_name = 'export.boolean'
126 def test_empty(self):
128 self.import_(['value'], []),
131 def test_exported(self):
132 ids, messages = self.import_(['value'], [['False'], ['True'], ])
133 self.assertEqual(len(ids), 2)
134 self.assertFalse(messages)
135 records = self.read()
141 def test_falses(self):
142 ids, messages = self.import_(
145 [u'false'], [u'FALSE'],
148 self.assertEqual(len(ids), 6)
149 self.assertFalse(messages)
160 def test_trues(self):
161 ids, messages = self.import_(
169 # Problem: OpenOffice (and probably excel) output localized booleans
172 self.assertEqual(len(ids), 7)
173 # FIXME: should warn for values which are not "true", "yes" or "1"
174 self.assertFalse(messages)
179 class test_integer_field(ImporterCase):
180 model_name = 'export.integer'
184 self.import_(['value'], []),
187 def test_empty(self):
188 ids, messages = self.import_(['value'], [['']])
189 self.assertEqual(len(ids), 1)
190 self.assertFalse(messages)
196 ids, messages = self.import_(['value'], [['0']])
197 self.assertEqual(len(ids), 1)
198 self.assertFalse(messages)
200 ids, messages = self.import_(['value'], [['-0']])
201 self.assertEqual(len(ids), 1)
202 self.assertFalse(messages)
204 self.assertEqual([False, False], values(self.read()))
206 def test_positives(self):
207 ids, messages = self.import_(['value'], [
213 self.assertEqual(len(ids), 4)
214 self.assertFalse(messages)
217 1, 42, 2**31-1, 12345678
218 ], values(self.read()))
220 def test_negatives(self):
221 ids, messages = self.import_(['value'], [
228 self.assertEqual(len(ids), 5)
229 self.assertFalse(messages)
231 -1, -42, -(2**31 - 1), -(2**31), -12345678
232 ], values(self.read()))
234 @mute_logger('openerp.sql_db')
235 def test_out_of_range(self):
236 ids, messages = self.import_(['value'], [[str(2**31)]])
237 self.assertIs(ids, False)
238 self.assertEqual(messages, [{
240 'rows': {'from': 0, 'to': 0},
242 'message': "integer out of range\n"
245 ids, messages = self.import_(['value'], [[str(-2**32)]])
246 self.assertIs(ids, False)
247 self.assertEqual(messages, [{
249 'rows': {'from': 0, 'to': 0},
251 'message': "integer out of range\n"
254 def test_nonsense(self):
255 ids, messages = self.import_(['value'], [['zorglub']])
256 self.assertIs(ids, False)
257 self.assertEqual(messages, [{
259 'rows': {'from': 0, 'to': 0},
262 'message': u"invalid literal for int() with base 10: 'zorglub'",
265 class test_float_field(ImporterCase):
266 model_name = 'export.float'
269 self.import_(['value'], []),
272 def test_empty(self):
273 ids, messages = self.import_(['value'], [['']])
274 self.assertEqual(len(ids), 1)
275 self.assertFalse(messages)
281 ids, messages = self.import_(['value'], [['0']])
282 self.assertEqual(len(ids), 1)
283 self.assertFalse(messages)
285 ids, messages = self.import_(['value'], [['-0']])
286 self.assertEqual(len(ids), 1)
287 self.assertFalse(messages)
289 self.assertEqual([False, False], values(self.read()))
291 def test_positives(self):
292 ids, messages = self.import_(['value'], [
300 self.assertEqual(len(ids), 6)
301 self.assertFalse(messages)
304 1, 42, 2**31-1, 12345678, 2.0**33, .000001
305 ], values(self.read()))
307 def test_negatives(self):
308 ids, messages = self.import_(['value'], [
317 self.assertEqual(len(ids), 7)
318 self.assertFalse(messages)
320 -1, -42, -(2**31 - 1), -(2**31), -12345678, -2.0**33, -.000001
321 ], values(self.read()))
323 def test_nonsense(self):
324 ids, messages = self.import_(['value'], [['foobar']])
325 self.assertIs(ids, False)
326 self.assertEqual(messages, [{
328 'rows': {'from': 0, 'to': 0},
331 'message': u"invalid literal for float(): foobar",
334 class test_string_field(ImporterCase):
335 model_name = 'export.string.bounded'
337 def test_empty(self):
338 ids, messages = self.import_(['value'], [['']])
339 self.assertEqual(len(ids), 1)
340 self.assertFalse(messages)
341 self.assertEqual([False], values(self.read()))
343 def test_imported(self):
344 ids, messages = self.import_(['value'], [
347 [u'Með suð à eyrum við spilum endalaust'],
348 [u"People 'get' types. They use them all the time. Telling "
349 u"someone he can't pound a nail with a banana doesn't much "
352 self.assertEqual(len(ids), 4)
353 self.assertFalse(messages)
357 u"Með suð à eyrum ",
359 ], values(self.read()))
361 class test_unbound_string_field(ImporterCase):
362 model_name = 'export.string'
364 def test_imported(self):
365 ids, messages = self.import_(['value'], [
366 [u'à dag viðrar vel til loftárása'],
368 [u"If they ask you about fun, you tell them – fun is a filthy"
371 self.assertEqual(len(ids), 2)
372 self.assertFalse(messages)
374 u"à dag viðrar vel til loftárása",
375 u"If they ask you about fun, you tell them – fun is a filthy parasite"
376 ], values(self.read()))
378 class test_text(ImporterCase):
379 model_name = 'export.text'
381 def test_empty(self):
382 ids, messages = self.import_(['value'], [['']])
383 self.assertEqual(len(ids), 1)
384 self.assertFalse(messages)
385 self.assertEqual([False], values(self.read()))
387 def test_imported(self):
388 s = (u"BreiðskÃfa er notað um útgefna hljómplötu sem inniheldur "
389 u"stúdÃóupptökur frá einum flytjanda. BreiðskÃfur eru oftast "
390 u"milli 25-80 mÃnútur og er lengd þeirra oft miðuð við 33â…“ "
391 u"snúninga 12 tommu vÃnylplötur (sem geta verið allt að 30 mÃn "
392 u"hvor hlið).\n\nBreiðskÃfur eru stundum tvöfaldar og eru þær þá"
393 u" gefnar út á tveimur geisladiskum eða tveimur vÃnylplötum.")
394 ids, messages = self.import_(['value'], [[s]])
395 self.assertEqual(len(ids), 1)
396 self.assertFalse(messages)
397 self.assertEqual([s], values(self.read()))
399 class test_selection(ImporterCase):
400 model_name = 'export.selection'
407 def test_imported(self):
408 ids, messages = self.import_(['value'], [
414 self.assertEqual(len(ids), 4)
415 self.assertFalse(messages)
416 self.assertEqual([3, 2, 1, 2], values(self.read()))
418 def test_imported_translated(self):
419 self.registry('res.lang').create(self.cr, openerp.SUPERUSER_ID, {
420 'name': u'Français',
422 'translatable': True,
423 'date_format': '%d.%m.%Y',
424 'decimal_point': ',',
427 Translations = self.registry('ir.translation')
428 for source, value in self.translations_fr:
429 Translations.create(self.cr, openerp.SUPERUSER_ID, {
430 'name': 'export.selection,value',
437 ids, messages = self.import_(['value'], [
441 ], context={'lang': 'fr_FR'})
442 self.assertEqual(len(ids), 3)
443 self.assertFalse(messages)
445 self.assertEqual([3, 1, 2], values(self.read()))
447 ids, messages = self.import_(['value'], [['Foo']], context={'lang': 'fr_FR'})
448 self.assertEqual(len(ids), 1)
449 self.assertFalse(messages)
451 def test_invalid(self):
452 ids, messages = self.import_(['value'], [['Baz']])
453 self.assertIs(ids, False)
454 self.assertEqual(messages, [{
456 'rows': {'from': 0, 'to': 0},
459 'message': "Value 'Baz' not found in selection field 'value'",
462 ids, messages = self.import_(['value'], [[42]])
463 self.assertIs(ids, False)
464 self.assertEqual(messages, [{
466 'rows': {'from': 0, 'to': 0},
469 'message': "Value '42' not found in selection field 'value'",
472 class test_selection_function(ImporterCase):
473 model_name = 'export.selection.function'
481 def test_imported(self):
482 """ import uses fields_get, so translates import label (may or may not
483 be good news) *and* serializes the selection function to reverse it:
484 import does not actually know that the selection field uses a function
486 # NOTE: conflict between a value and a label => ?
487 ids, messages = self.import_(['value'], [
491 self.assertEqual(len(ids), 2)
492 self.assertFalse(messages)
497 def test_translated(self):
498 """ Expects output of selection function returns translated labels
500 self.registry('res.lang').create(self.cr, openerp.SUPERUSER_ID, {
501 'name': u'Français',
503 'translatable': True,
504 'date_format': '%d.%m.%Y',
505 'decimal_point': ',',
508 Translations = self.registry('ir.translation')
509 for source, value in self.translations_fr:
510 Translations.create(self.cr, openerp.SUPERUSER_ID, {
511 'name': 'export.selection,value',
517 ids, messages = self.import_(['value'], [
520 ], context={'lang': 'fr_FR'})
521 self.assertIs(ids, False)
522 self.assertEqual(messages, [{
524 'rows': {'from': 1, 'to': 1},
527 'message': "Value 'tete' not found in selection field 'value'",
529 ids, messages = self.import_(['value'], [['Wheee']], context={'lang': 'fr_FR'})
530 self.assertEqual(len(ids), 1)
531 self.assertFalse(messages)
533 class test_m2o(ImporterCase):
534 model_name = 'export.many2one'
536 def test_by_name(self):
537 # create integer objects
538 integer_id1 = self.registry('export.integer').create(
539 self.cr, openerp.SUPERUSER_ID, {'value': 42})
540 integer_id2 = self.registry('export.integer').create(
541 self.cr, openerp.SUPERUSER_ID, {'value': 36})
543 name1 = dict(self.registry('export.integer').name_get(
544 self.cr, openerp.SUPERUSER_ID,[integer_id1]))[integer_id1]
545 name2 = dict(self.registry('export.integer').name_get(
546 self.cr, openerp.SUPERUSER_ID,[integer_id2]))[integer_id2]
548 ids , messages = self.import_(['value'], [
554 self.assertFalse(messages)
555 self.assertEqual(len(ids), 3)
556 # correct ids assigned to corresponding records
558 (integer_id1, name1),
559 (integer_id1, name1),
560 (integer_id2, name2),],
563 def test_by_xid(self):
564 ExportInteger = self.registry('export.integer')
565 integer_id = ExportInteger.create(
566 self.cr, openerp.SUPERUSER_ID, {'value': 42})
567 xid = self.xid(ExportInteger.browse(
568 self.cr, openerp.SUPERUSER_ID, [integer_id])[0])
570 ids, messages = self.import_(['value/id'], [[xid]])
571 self.assertFalse(messages)
572 self.assertEqual(len(ids), 1)
574 self.assertEqual(42, b[0].value.value)
576 def test_by_id(self):
577 integer_id = self.registry('export.integer').create(
578 self.cr, openerp.SUPERUSER_ID, {'value': 42})
579 ids, messages = self.import_(['value/.id'], [[integer_id]])
580 self.assertFalse(messages)
581 self.assertEqual(len(ids), 1)
583 self.assertEqual(42, b[0].value.value)
585 def test_by_names(self):
586 integer_id1 = self.registry('export.integer').create(
587 self.cr, openerp.SUPERUSER_ID, {'value': 42})
588 integer_id2 = self.registry('export.integer').create(
589 self.cr, openerp.SUPERUSER_ID, {'value': 42})
590 name1 = dict(self.registry('export.integer').name_get(
591 self.cr, openerp.SUPERUSER_ID,[integer_id1]))[integer_id1]
592 name2 = dict(self.registry('export.integer').name_get(
593 self.cr, openerp.SUPERUSER_ID,[integer_id2]))[integer_id2]
594 # names should be the same
595 self.assertEqual(name1, name2)
597 ids, messages = self.import_(['value'], [[name2]])
600 [message(u"Found multiple matches for field 'value' (2 matches)",
602 self.assertEqual(len(ids), 1)
605 ], values(self.read()))
607 def test_fail_by_implicit_id(self):
608 """ Can't implicitly import records by id
610 # create integer objects
611 integer_id1 = self.registry('export.integer').create(
612 self.cr, openerp.SUPERUSER_ID, {'value': 42})
613 integer_id2 = self.registry('export.integer').create(
614 self.cr, openerp.SUPERUSER_ID, {'value': 36})
616 # Because name_search all the things. Fallback schmallback
617 ids, messages = self.import_(['value'], [
618 # import by id, without specifying it
623 self.assertEqual(messages, [
624 message(u"No matching record found for name '%s' in field 'value'" % id,
625 from_=index, to_=index, record=index)
626 for index, id in enumerate([integer_id1, integer_id2, integer_id1])])
627 self.assertIs(ids, False)
629 def test_sub_field(self):
630 """ Does not implicitly create the record, does not warn that you can't
631 import m2o subfields (at all)...
633 ids, messages = self.import_(['value/value'], [['42']])
634 self.assertEqual(messages, [
635 message(u"Can not create Many-To-One records indirectly, import "
636 u"the field separately")])
637 self.assertIs(ids, False)
639 def test_fail_noids(self):
640 ids, messages = self.import_(['value'], [['nameisnoexist:3']])
641 self.assertEqual(messages, [message(
642 u"No matching record found for name 'nameisnoexist:3' "
643 u"in field 'value'")])
644 self.assertIs(ids, False)
646 ids, messages = self.import_(['value/id'], [['noxidhere']])
647 self.assertEqual(messages, [message(
648 u"No matching record found for external id 'noxidhere' "
649 u"in field 'value'")])
650 self.assertIs(ids, False)
652 ids, messages = self.import_(['value/.id'], [['66']])
653 self.assertEqual(messages, [message(
654 u"No matching record found for database id '66' "
655 u"in field 'value'")])
656 self.assertIs(ids, False)
658 def test_fail_multiple(self):
659 ids, messages = self.import_(
660 ['value', 'value/id'],
661 [['somename', 'somexid']])
662 self.assertEqual(messages, [message(
663 u"Ambiguous specification for field 'value', only provide one of "
664 u"name, external id or database id")])
665 self.assertIs(ids, False)
667 class test_m2m(ImporterCase):
668 model_name = 'export.many2many'
670 # apparently, one and only thing which works is a
671 # csv_internal_sep-separated list of ids, xids, or names (depending if
672 # m2m/.id, m2m/id or m2m[/anythingelse]
674 id1 = self.registry('export.many2many.other').create(
675 self.cr, openerp.SUPERUSER_ID, {'value': 3, 'str': 'record0'})
676 id2 = self.registry('export.many2many.other').create(
677 self.cr, openerp.SUPERUSER_ID, {'value': 44, 'str': 'record1'})
678 id3 = self.registry('export.many2many.other').create(
679 self.cr, openerp.SUPERUSER_ID, {'value': 84, 'str': 'record2'})
680 id4 = self.registry('export.many2many.other').create(
681 self.cr, openerp.SUPERUSER_ID, {'value': 9, 'str': 'record3'})
682 id5 = self.registry('export.many2many.other').create(
683 self.cr, openerp.SUPERUSER_ID, {'value': 99, 'str': 'record4'})
685 ids, messages = self.import_(['value/.id'], [
686 ['%d,%d' % (id1, id2)],
687 ['%d,%d,%d' % (id1, id3, id4)],
688 ['%d,%d,%d' % (id1, id2, id3)],
691 self.assertFalse(messages)
692 self.assertEqual(len(ids), 4)
694 ids = lambda records: [record.id for record in records]
697 self.assertEqual(ids(b[0].value), [id1, id2])
698 self.assertEqual(values(b[0].value), [3, 44])
700 self.assertEqual(ids(b[2].value), [id1, id2, id3])
701 self.assertEqual(values(b[2].value), [3, 44, 84])
703 def test_noids(self):
704 ids, messages = self.import_(['value/.id'], [['42']])
705 self.assertEqual(messages, [message(
706 u"No matching record found for database id '42' in field "
708 self.assertIs(ids, False)
711 M2O_o = self.registry('export.many2many.other')
712 id1 = M2O_o.create(self.cr, openerp.SUPERUSER_ID, {'value': 3, 'str': 'record0'})
713 id2 = M2O_o.create(self.cr, openerp.SUPERUSER_ID, {'value': 44, 'str': 'record1'})
714 id3 = M2O_o.create(self.cr, openerp.SUPERUSER_ID, {'value': 84, 'str': 'record2'})
715 id4 = M2O_o.create(self.cr, openerp.SUPERUSER_ID, {'value': 9, 'str': 'record3'})
716 records = M2O_o.browse(self.cr, openerp.SUPERUSER_ID, [id1, id2, id3, id4])
718 ids, messages = self.import_(['value/id'], [
719 ['%s,%s' % (self.xid(records[0]), self.xid(records[1]))],
720 ['%s' % self.xid(records[3])],
721 ['%s,%s' % (self.xid(records[2]), self.xid(records[1]))],
723 self.assertFalse(messages)
724 self.assertEqual(len(ids), 3)
727 self.assertEqual(values(b[0].value), [3, 44])
728 self.assertEqual(values(b[2].value), [44, 84])
729 def test_noxids(self):
730 ids, messages = self.import_(['value/id'], [['noxidforthat']])
731 self.assertEqual(messages, [message(
732 u"No matching record found for external id 'noxidforthat' "
733 u"in field 'value'")])
734 self.assertIs(ids, False)
736 def test_names(self):
737 M2O_o = self.registry('export.many2many.other')
738 id1 = M2O_o.create(self.cr, openerp.SUPERUSER_ID, {'value': 3, 'str': 'record0'})
739 id2 = M2O_o.create(self.cr, openerp.SUPERUSER_ID, {'value': 44, 'str': 'record1'})
740 id3 = M2O_o.create(self.cr, openerp.SUPERUSER_ID, {'value': 84, 'str': 'record2'})
741 id4 = M2O_o.create(self.cr, openerp.SUPERUSER_ID, {'value': 9, 'str': 'record3'})
742 records = M2O_o.browse(self.cr, openerp.SUPERUSER_ID, [id1, id2, id3, id4])
744 name = lambda record: dict(record.name_get())[record.id]
746 ids, messages = self.import_(['value'], [
747 ['%s,%s' % (name(records[1]), name(records[2]))],
748 ['%s,%s,%s' % (name(records[0]), name(records[1]), name(records[2]))],
749 ['%s,%s' % (name(records[0]), name(records[3]))],
751 self.assertFalse(messages)
752 self.assertEqual(len(ids), 3)
755 self.assertEqual(values(b[1].value), [3, 44, 84])
756 self.assertEqual(values(b[2].value), [3, 9])
758 def test_nonames(self):
759 ids, messages = self.import_(['value'], [['wherethem2mhavenonames']])
760 self.assertEqual(messages, [message(
761 u"No matching record found for name 'wherethem2mhavenonames' in "
763 self.assertIs(ids, False)
765 def test_import_to_existing(self):
766 M2O_o = self.registry('export.many2many.other')
767 id1 = M2O_o.create(self.cr, openerp.SUPERUSER_ID, {'value': 3, 'str': 'record0'})
768 id2 = M2O_o.create(self.cr, openerp.SUPERUSER_ID, {'value': 44, 'str': 'record1'})
769 id3 = M2O_o.create(self.cr, openerp.SUPERUSER_ID, {'value': 84, 'str': 'record2'})
770 id4 = M2O_o.create(self.cr, openerp.SUPERUSER_ID, {'value': 9, 'str': 'record3'})
773 ids, messages = self.import_(['id', 'value/.id'], [[xid, '%d,%d' % (id1, id2)]])
774 self.assertFalse(messages)
775 self.assertEqual(len(ids), 1)
776 ids, messages = self.import_(['id', 'value/.id'], [[xid, '%d,%d' % (id3, id4)]])
777 self.assertFalse(messages)
778 self.assertEqual(len(ids), 1)
781 self.assertEqual(len(b), 1)
782 # TODO: replacement of existing m2m values is correct?
783 self.assertEqual(values(b[0].value), [84, 9])
785 class test_o2m(ImporterCase):
786 model_name = 'export.one2many'
788 def test_name_get(self):
789 # FIXME: bloody hell why can't this just name_create the record?
794 [['5', u'Java is a DSL for taking large XML files'
795 u' and converting them to stack traces']])
797 def test_single(self):
798 ids, messages = self.import_(['const', 'value/value'], [
801 self.assertEqual(len(ids), 1)
802 self.assertFalse(messages)
805 self.assertEqual(b.const, 5)
806 self.assertEqual(values(b.value), [63])
808 def test_multicore(self):
809 ids, messages = self.import_(['const', 'value/value'], [
813 self.assertEqual(len(ids), 2)
814 self.assertFalse(messages)
816 b1, b2 = self.browse()
817 self.assertEqual(b1.const, 5)
818 self.assertEqual(values(b1.value), [63])
819 self.assertEqual(b2.const, 6)
820 self.assertEqual(values(b2.value), [64])
822 def test_multisub(self):
823 ids, messages = self.import_(['const', 'value/value'], [
829 self.assertEqual(len(ids), 4)
830 self.assertFalse(messages)
833 self.assertEqual(values(b.value), [63, 64, 65, 66])
835 def test_multi_subfields(self):
836 ids, messages = self.import_(['value/str', 'const', 'value/value'], [
840 ['rhythm', '', '66'],
842 self.assertEqual(len(ids), 4)
843 self.assertFalse(messages)
846 self.assertEqual(values(b.value), [63, 64, 65, 66])
848 values(b.value, 'str'),
849 'this is the rhythm'.split())
851 def test_link_inline(self):
852 id1 = self.registry('export.one2many.child').create(self.cr, openerp.SUPERUSER_ID, {
853 'str': 'Bf', 'value': 109
855 id2 = self.registry('export.one2many.child').create(self.cr, openerp.SUPERUSER_ID, {
856 'str': 'Me', 'value': 262
860 self.import_(['const', 'value/.id'], [
861 ['42', '%d,%d' % (id1, id2)]
863 self.fail("Should have raised a valueerror")
864 except ValueError, e:
865 # should be Exception(Database ID doesn't exist: export.one2many.child : $id1,$id2)
866 self.assertIs(type(e), ValueError)
869 "invalid literal for int() with base 10: '%d,%d'" % (id1, id2))
872 id1 = self.registry('export.one2many.child').create(self.cr, openerp.SUPERUSER_ID, {
873 'str': 'Bf', 'value': 109
875 id2 = self.registry('export.one2many.child').create(self.cr, openerp.SUPERUSER_ID, {
876 'str': 'Me', 'value': 262
879 ids, messages = self.import_(['const', 'value/.id'], [
883 self.assertEqual(len(ids), 2)
884 self.assertFalse(messages)
886 # No record values alongside id => o2m resolution skipped altogether,
887 # creates 2 records => remove/don't import columns sideshow columns,
888 # get completely different semantics
889 b, b1 = self.browse()
890 self.assertEqual(b.const, 42)
891 self.assertEqual(values(b.value), [])
892 self.assertEqual(b1.const, 4)
893 self.assertEqual(values(b1.value), [])
895 def test_link_2(self):
896 O2M_c = self.registry('export.one2many.child')
897 id1 = O2M_c.create(self.cr, openerp.SUPERUSER_ID, {
898 'str': 'Bf', 'value': 109
900 id2 = O2M_c.create(self.cr, openerp.SUPERUSER_ID, {
901 'str': 'Me', 'value': 262
904 ids, messages = self.import_(['const', 'value/.id', 'value/value'], [
905 ['42', str(id1), '1'],
908 self.assertEqual(len(ids), 2)
909 self.assertFalse(messages)
912 # if an id (db or xid) is provided, expectations that objects are
913 # *already* linked and emits UPDATE (1, id, {}).
914 # Noid => CREATE (0, ?, {})
915 # TODO: xid ignored aside from getting corresponding db id?
916 self.assertEqual(b.const, 42)
917 self.assertEqual(values(b.value), [])
919 # FIXME: updates somebody else's records?
921 O2M_c.read(self.cr, openerp.SUPERUSER_ID, id1),
922 {'id': id1, 'str': 'Bf', 'value': 1, 'parent_id': False})
924 O2M_c.read(self.cr, openerp.SUPERUSER_ID, id2),
925 {'id': id2, 'str': 'Me', 'value': 2, 'parent_id': False})
927 class test_o2m_multiple(ImporterCase):
928 model_name = 'export.one2many.multiple'
930 def test_multi_mixed(self):
931 ids, messages = self.import_(['const', 'child1/value', 'child2/value'], [
937 self.assertEqual(len(ids), 4)
938 self.assertFalse(messages)
939 # Oh yeah, that's the stuff
940 (b, b1, b2) = self.browse()
941 self.assertEqual(values(b.child1), [11])
942 self.assertEqual(values(b.child2), [21])
944 self.assertEqual(values(b1.child1), [12])
945 self.assertEqual(values(b1.child2), [22])
947 self.assertEqual(values(b2.child1), [13, 14])
948 self.assertEqual(values(b2.child2), [23])
950 def test_multi(self):
951 ids, messages = self.import_(['const', 'child1/value', 'child2/value'], [
959 self.assertEqual(len(ids), 6)
960 self.assertFalse(messages)
961 # What the actual fuck?
962 (b, b1) = self.browse()
963 self.assertEqual(values(b.child1), [11, 12, 13, 14])
964 self.assertEqual(values(b.child2), [21])
965 self.assertEqual(values(b1.child2), [22, 23])
967 def test_multi_fullsplit(self):
968 ids, messages = self.import_(['const', 'child1/value', 'child2/value'], [
977 self.assertEqual(len(ids), 7)
978 self.assertFalse(messages)
980 (b, b1) = self.browse()
981 self.assertEqual(b.const, 5)
982 self.assertEqual(values(b.child1), [11, 12, 13, 14])
983 self.assertEqual(b1.const, 36)
984 self.assertEqual(values(b1.child2), [21, 22, 23])
986 # function, related, reference: written to db as-is...
987 # => function uses @type for value coercion/conversion