From 66dea8bb7bd6db2557515dc21b8f3e96b072aca0 Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Fri, 31 Aug 2018 14:42:03 +0000 Subject: [PATCH] [REF] web: remove raw_mode flag on export The export is now always in raw_mode Adapt the tests Fixes odoo/odoo#18798 closes odoo/odoo#26724 Signed-off-by: Martin Trigaux (mat) --- addons/calendar/models/calendar.py | 4 +- addons/web/controllers/main.py | 5 +- odoo/addons/test_impex/tests/test_export.py | 193 ++++++++++---------- odoo/fields.py | 16 +- odoo/models.py | 4 +- 5 files changed, 110 insertions(+), 112 deletions(-) diff --git a/addons/calendar/models/calendar.py b/addons/calendar/models/calendar.py index 5498759f550..3870e028d7e 100644 --- a/addons/calendar/models/calendar.py +++ b/addons/calendar/models/calendar.py @@ -1604,10 +1604,10 @@ class Meeting(models.Model): self.env['calendar.alarm_manager']._notify_next_alarm(meeting.partner_ids.ids) return meeting - def export_data(self, fields_to_export, raw_data=False): + def export_data(self, fields_to_export): """ Override to convert virtual ids to ids """ records = self.browse(set(get_real_ids(self.ids))) - return super(Meeting, records).export_data(fields_to_export, raw_data) + return super(Meeting, records).export_data(fields_to_export) @api.model def read_group(self, domain, fields, groupby, offset=0, limit=None, orderby=False, lazy=True): diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index befdc0a2c8b..85f01e3c83d 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -1576,7 +1576,6 @@ class Export(http.Controller): for k, v in self.fields_info(model, export_fields).items()) class ExportFormat(object): - raw_data = False @property def content_type(self): @@ -1612,7 +1611,7 @@ class ExportFormat(object): fields = [field for field in fields if field['name'] != 'id'] field_names = [f['name'] for f in fields] - import_data = records.export_data(field_names, self.raw_data).get('datas',[]) + import_data = records.export_data(field_names).get('datas',[]) if import_compat: columns_headers = field_names @@ -1658,8 +1657,6 @@ class CSVExport(ExportFormat, http.Controller): return fp.getvalue() class ExcelExport(ExportFormat, http.Controller): - # Excel needs raw data to correctly handle numbers and date values - raw_data = True @http.route('/web/export/xls', type='http', auth="user") @serialize_exception diff --git a/odoo/addons/test_impex/tests/test_export.py b/odoo/addons/test_impex/tests/test_export.py index 3fc071e7454..4995f8a7e82 100644 --- a/odoo/addons/test_impex/tests/test_export.py +++ b/odoo/addons/test_impex/tests/test_export.py @@ -5,6 +5,7 @@ import itertools import pstats from cProfile import Profile +from odoo import fields from odoo.tests import common @@ -42,7 +43,7 @@ class test_xids(CreatorCase): record.invalidate_cache() self.assertEqual( record._export_rows([['id'], ['value']]), - [[u'x', u'True']] + [[u'x', True]] ) class test_boolean_field(CreatorCase): @@ -51,7 +52,7 @@ class test_boolean_field(CreatorCase): def test_true(self): self.assertEqual( self.export(True), - [[u'True']]) + [[True]]) def test_false(self): """ ``False`` value to boolean fields is unique in being exported as a @@ -59,7 +60,7 @@ class test_boolean_field(CreatorCase): """ self.assertEqual( self.export(False), - [[u'False']]) + [[False]]) class test_integer_field(CreatorCase): @@ -72,22 +73,22 @@ class test_integer_field(CreatorCase): def test_0(self): self.assertEqual( self.export(0), - [[u'0']]) + [[0]]) def test_basic_value(self): self.assertEqual( self.export(42), - [[u'42']]) + [[42]]) def test_negative(self): self.assertEqual( self.export(-32), - [[u'-32']]) + [[-32]]) def test_huge(self): self.assertEqual( self.export(2**31-1), - [[str(2**31-1)]]) + [[2147483647]]) class test_float_field(CreatorCase): @@ -96,27 +97,27 @@ class test_float_field(CreatorCase): def test_0(self): self.assertEqual( self.export(0.0), - [[u'0.0']]) + [[0.0]]) def test_epsilon(self): self.assertEqual( self.export(0.000000000027), - [[u'2.7e-11']]) + [[0.000000000027]]) def test_negative(self): self.assertEqual( self.export(-2.42), - [[u'-2.42']]) + [[-2.42]]) def test_positive(self): self.assertEqual( self.export(47.36), - [[u'47.36']]) + [[47.36]]) def test_big(self): self.assertEqual( self.export(87654321.4678), - [[u'87654321.4678']]) + [[87654321.4678]]) class test_decimal_field(CreatorCase): @@ -125,28 +126,28 @@ class test_decimal_field(CreatorCase): def test_0(self): self.assertEqual( self.export(0.0), - [[u'0.0']]) + [[0.0]]) def test_epsilon(self): """ epsilon gets sliced to 0 due to precision """ self.assertEqual( self.export(0.000000000027), - [[u'0.0']]) + [[0.0]]) def test_negative(self): self.assertEqual( self.export(-2.42), - [[u'-2.42']]) + [[-2.42]]) def test_positive(self): self.assertEqual( self.export(47.36), - [[u'47.36']]) + [[47.36]]) def test_big(self): self.assertEqual( - self.export(87654321.4678), [[u'87654321.468']]) + self.export(87654321.4678), [[87654321.468]]) class test_string_field(CreatorCase): @@ -218,6 +219,10 @@ class test_text(CreatorCase): u" programming in the A-normal form. That is indeed all there" u" is to monads"]]) + def test_numeric(self): + self.assertEqual( + self.export(42), + [["42"]]) class test_date(CreatorCase): model_name = 'export.date' @@ -230,7 +235,7 @@ class test_date(CreatorCase): def test_basic(self): self.assertEqual( self.export('2011-11-07'), - [[u'2011-11-07']]) + [[fields.Date.from_string('2011-11-07')]]) class test_datetime(CreatorCase): @@ -247,7 +252,7 @@ class test_datetime(CreatorCase): self.env.user.write({'tz': False}) self.assertEqual( self.export('2011-11-07 21:05:48'), - [[u'2011-11-07 21:05:48']]) + [[fields.Datetime.from_string('2011-11-07 21:05:48')]]) def test_tz(self): """ Export converts the value in the user's TZ @@ -256,7 +261,7 @@ class test_datetime(CreatorCase): """ self.assertEqual( self.export('2011-11-07 21:05:48', context={'tz': 'Pacific/Norfolk'}), - [[u'2011-11-08 08:35:48']]) + [[fields.Datetime.from_string('2011-11-08 08:35:48')]]) class test_selection(CreatorCase): @@ -270,7 +275,7 @@ class test_selection(CreatorCase): def test_empty(self): self.assertEqual( self.export(False), - [[False]]) + [['']]) def test_value(self): """ selections export the *label* for their value @@ -339,7 +344,7 @@ class test_m2o(CreatorCase): record = self.env['export.integer'].create({'value': 42}) self.assertEqual( self.export(record.id, fields=['value/.id', 'value/value']), - [[str(record.id), '42']]) + [[str(record.id), 42]]) def test_external_id(self): record = self.env['export.integer'].create({'value': 42}) @@ -395,30 +400,30 @@ class test_o2m(CreatorCase): self.assertEqual( self.export([(0, False, {'value': 42})], fields=['value', 'value/value']), - [[u'export.one2many.child:42', u'42']]) + [[u'export.one2many.child:42', 42]]) def test_integrate_one_in_parent(self): self.assertEqual( self.export([(0, False, {'value': 42})], fields=['const', 'value/value']), - [[u'4', u'42']]) + [[4, 42]]) def test_multiple_records(self): self.assertEqual( self.export(self.commands, fields=['const', 'value/value']), [ - [u'4', u'4'], - [u'', u'42'], - [u'', u'36'], - [u'', u'4'], - [u'', u'13'], + [4, 4], + [u'', 42], + [u'', 36], + [u'', 4], + [u'', 13], ]) def test_multiple_records_name(self): self.assertEqual( self.export(self.commands, fields=['const', 'value']), [ - [u'4', u'export.one2many.child:4'], + [4, u'export.one2many.child:4'], [u'', u'export.one2many.child:42'], [u'', u'export.one2many.child:36'], [u'', u'export.one2many.child:4'], @@ -431,7 +436,7 @@ class test_o2m(CreatorCase): self.assertEqual( export, [ - ['4', str(records[0].id)], + [4, str(records[0].id)], ['', str(records[1].id)], ['', str(records[2].id)], ['', str(records[3].id)], @@ -442,44 +447,44 @@ class test_o2m(CreatorCase): self.assertEqual( self.export(self.commands, fields=['const', 'value', 'value/value']), [ - [u'4', u'export.one2many.child:4', u'4'], - ['', u'export.one2many.child:42', u'42'], - ['', u'export.one2many.child:36', u'36'], - ['', u'export.one2many.child:4', u'4'], - ['', u'export.one2many.child:13', u'13'], + [4, u'export.one2many.child:4', 4], + ['', u'export.one2many.child:42', 42], + ['', u'export.one2many.child:36', 36], + ['', u'export.one2many.child:4', 4], + ['', u'export.one2many.child:13', 13], ]) def test_multiple_records_with_name_after(self): self.assertEqual( self.export(self.commands, fields=['const', 'value/value', 'value']), [ - [u'4', u'4', u'export.one2many.child:4'], - ['', u'42', u'export.one2many.child:42'], - ['', u'36', u'export.one2many.child:36'], - ['', u'4', u'export.one2many.child:4'], - ['', u'13', u'export.one2many.child:13'], + [4, 4, u'export.one2many.child:4'], + ['', 42, u'export.one2many.child:42'], + ['', 36, u'export.one2many.child:36'], + ['', 4, u'export.one2many.child:4'], + ['', 13, u'export.one2many.child:13'], ]) def test_multiple_subfields_neighbour(self): self.assertEqual( self.export(self.commands, fields=['const', 'value/str','value/value']), [ - [u'4', u'record1', u'4'], - ['', u'record2', u'42'], - ['', u'record3', u'36'], - ['', u'record4', u'4'], - ['', u'record5', u'13'], + [4, u'record1', 4], + ['', u'record2', 42], + ['', u'record3', 36], + ['', u'record4', 4], + ['', u'record5', 13], ]) def test_multiple_subfields_separated(self): self.assertEqual( self.export(self.commands, fields=['value/str', 'const', 'value/value']), [ - [u'record1', u'4', u'4'], - [u'record2', '', u'42'], - [u'record3', '', u'36'], - [u'record4', '', u'4'], - [u'record5', '', u'13'], + [u'record1', 4, 4], + [u'record2', '', 42], + [u'record3', '', 36], + [u'record4', '', 4], + [u'record5', '', 13], ]) @@ -519,18 +524,18 @@ class test_o2m_multiple(CreatorCase): self.assertEqual( self.export(child1=False, child2=[(0, False, {'value': 42})], fields=fields), - [[u'36', False, u'42']]) + [[36, False, 42]]) self.assertEqual( self.export(child1=[(0, False, {'value': 43})], child2=False, fields=fields), - [[u'36', u'43', False]]) + [[36, 43, False]]) self.assertEqual( self.export(child1=[(0, False, {'value': 43})], child2=[(0, False, {'value': 42})], fields=fields), - [[u'36', u'43', u'42']]) + [[36, 43, 42]]) def test_multiple(self): """ With two "concurrent" o2ms, exports the first line combined, then @@ -545,35 +550,35 @@ class test_o2m_multiple(CreatorCase): self.assertEqual( self.export(child1=child1, child2=False, fields=fields), [ - [u'36', u'4', False], - ['', u'42', ''], - ['', u'36', ''], - ['', u'4', ''], - ['', u'13', ''], + [36, 4, False], + ['', 42, ''], + ['', 36, ''], + ['', 4, ''], + ['', 13, ''], ]) self.assertEqual( self.export(child1=False, child2=child2, fields=fields), [ - [u'36', False, u'8'], - ['', '', u'12'], - ['', '', u'8'], - ['', '', u'55'], - ['', '', u'33'], - ['', '', u'13'], + [36, False, 8], + ['', '', 12], + ['', '', 8], + ['', '', 55], + ['', '', 33], + ['', '', 13], ]) self.assertEqual( self.export(child1=child1, child2=child2, fields=fields), [ - [u'36', u'4', u'8'], - ['', u'42', ''], - ['', u'36', ''], - ['', u'4', ''], - ['', u'13', ''], - ['', '', u'12'], - ['', '', u'8'], - ['', '', u'55'], - ['', '', u'33'], - ['', '', u'13'], + [36, 4, 8], + ['', 42, ''], + ['', 36, ''], + ['', 4, ''], + ['', 13, ''], + ['', '', 12], + ['', '', 8], + ['', '', 55], + ['', '', 33], + ['', '', 13], ]) @@ -606,30 +611,30 @@ class test_m2m(CreatorCase): self.assertEqual( self.export([(0, False, {'value': 42})], fields=['value', 'value/value']), - [[u'export.many2many.other:42', u'42']]) + [[u'export.many2many.other:42', 42]]) def test_integrate_one_in_parent(self): self.assertEqual( self.export([(0, False, {'value': 42})], fields=['const', 'value/value']), - [[u'4', u'42']]) + [[4, 42]]) def test_multiple_records(self): self.assertEqual( self.export(self.commands, fields=['const', 'value/value']), [ - [u'4', u'4'], - [u'', u'42'], - [u'', u'36'], - [u'', u'4'], - [u'', u'13'], + [4, 4], + [u'', 42], + [u'', 36], + [u'', 4], + [u'', 13], ]) def test_multiple_records_name(self): self.assertEqual( self.export(self.commands, fields=['const', 'value']), [ - [u'4', u'export.many2many.other:4'], + [4, u'export.many2many.other:4'], ['', u'export.many2many.other:42'], ['', u'export.many2many.other:36'], ['', u'export.many2many.other:4'], @@ -667,21 +672,21 @@ class test_m2m(CreatorCase): self.assertEqual( r.with_context(import_compat=False)._export_rows([['id'], ['value', 'id'], ['value', 'value']]), [ - [xid, u'__t__.record000', u'4'], - [u'', u'__t__.record001', u'42'], - [u'', u'__t__.record010', u'36'], - [u'', u'__t__.record011', u'4'], - [u'', u'__t__.record100', u'13'] + [xid, u'__t__.record000', 4], + [u'', u'__t__.record001', 42], + [u'', u'__t__.record010', 36], + [u'', u'__t__.record011', 4], + [u'', u'__t__.record100', 13] ] ) self.assertEqual( r.with_context(import_compat=False)._export_rows([['id'], ['value', 'value'], ['value', 'id']]), [ - [xid, u'4', u'__t__.record000'], - [u'', u'42', u'__t__.record001'], - [u'', u'36', u'__t__.record010'], - [u'', u'4', u'__t__.record011'], - [u'', u'13', u'__t__.record100'] + [xid, 4, u'__t__.record000'], + [u'', 42, u'__t__.record001'], + [u'', 36, u'__t__.record010'], + [u'', 4, u'__t__.record011'], + [u'', 13, u'__t__.record100'] ] ) @@ -694,7 +699,7 @@ class test_function(CreatorCase): """ self.assertEqual( self.export(42), - [[u'3']]) + [[3]]) @common.tagged('-standard', 'bench') diff --git a/odoo/fields.py b/odoo/fields.py index 3e529c8f26f..41779826d6e 100644 --- a/odoo/fields.py +++ b/odoo/fields.py @@ -858,7 +858,7 @@ class Field(MetaField('DummyField', (object,), {})): """ Convert ``value`` from the record format to the export format. """ if not value: return '' - return value if record._context.get('export_raw_data') else ustr(value) + return value def convert_to_display_name(self, value, record): """ Convert ``value`` from the record format to a suitable display name. """ @@ -1214,9 +1214,7 @@ class Boolean(Field): return bool(value) def convert_to_export(self, value, record): - if record._context.get('export_raw_data'): - return value - return ustr(value) + return value class Integer(Field): @@ -1250,7 +1248,7 @@ class Integer(Field): def convert_to_export(self, value, record): if value or value == 0: - return value if record._context.get('export_raw_data') else ustr(value) + return value return '' @@ -1310,7 +1308,7 @@ class Float(Field): def convert_to_export(self, value, record): if value or value == 0.0: - return value if record._context.get('export_raw_data') else ustr(value) + return value return '' @@ -1671,7 +1669,7 @@ class Date(Field): def convert_to_export(self, value, record): if not value: return '' - return self.from_string(value) if record._context.get('export_raw_data') else ustr(value) + return self.from_string(value) class Datetime(Field): @@ -1782,7 +1780,7 @@ class Datetime(Field): if not value: return '' value = self.convert_to_display_name(value, record) - return self.from_string(value) if record._context.get('export_raw_data') else ustr(value) + return self.from_string(value) def convert_to_display_name(self, value, record): assert record, 'Record expected' @@ -2007,7 +2005,7 @@ class Selection(Field): for item in self._description_selection(record.env): if item[0] == value: return item[1] - return False + return '' class Reference(Selection): diff --git a/odoo/models.py b/odoo/models.py index 5ffde4cd104..08e3a6f23c7 100644 --- a/odoo/models.py +++ b/odoo/models.py @@ -825,7 +825,7 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})): # backward compatibility __export_rows = _export_rows - def export_data(self, fields_to_export, raw_data=False): + def export_data(self, fields_to_export): """ Export fields for selected objects :param fields_to_export: list of fields @@ -835,8 +835,6 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})): This method is used when exporting data via client menu """ fields_to_export = [fix_import_export_id_paths(f) for f in fields_to_export] - if raw_data: - self = self.with_context(export_raw_data=True) return {'datas': self._export_rows(fields_to_export)} @api.model