Merge lp:~openerp-dev/openobject-server/trunk-improve-export-ref-mat into lp:openobject-server

Proposed by Martin Trigaux (OpenERP)
Status: Work in progress
Proposed branch: lp:~openerp-dev/openobject-server/trunk-improve-export-ref-mat
Merge into: lp:openobject-server
Diff against target: 354 lines (+83/-73)
2 files modified
openerp/addons/test_impex/tests/test_export.py (+22/-22)
openerp/osv/orm.py (+61/-51)
To merge this branch: bzr merge lp:~openerp-dev/openobject-server/trunk-improve-export-ref-mat
Reviewer Review Type Date Requested Status
OpenERP Core Team Pending
Review via email: mp+216035@code.launchpad.net

Description of the change

refactoring export for better excel

To post a comment you must log in.
5164. By Martin Trigaux (OpenERP)

improving tests and export

5165. By Martin Trigaux (OpenERP)

[FIX] initialise value

Unmerged revisions

5165. By Martin Trigaux (OpenERP)

[FIX] initialise value

5164. By Martin Trigaux (OpenERP)

improving tests and export

5163. By Martin Trigaux (OpenERP)

sync with trunk

5162. By Martin Trigaux (OpenERP)

[FIX] export: when exporting make sure use correct model, improve raw data export, clean code

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'openerp/addons/test_impex/tests/test_export.py'
--- openerp/addons/test_impex/tests/test_export.py 2013-10-24 21:47:35 +0000
+++ openerp/addons/test_impex/tests/test_export.py 2014-04-16 13:23:35 +0000
@@ -50,7 +50,7 @@
50 def test_0(self):50 def test_0(self):
51 self.assertEqual(51 self.assertEqual(
52 self.export(0),52 self.export(0),
53 [[False]])53 [['0']])
5454
55 def test_basic_value(self):55 def test_basic_value(self):
56 self.assertEqual(56 self.assertEqual(
@@ -73,7 +73,7 @@
73 def test_0(self):73 def test_0(self):
74 self.assertEqual(74 self.assertEqual(
75 self.export(0.0),75 self.export(0.0),
76 [[False]])76 [['0.0']])
7777
78 def test_epsilon(self):78 def test_epsilon(self):
79 self.assertEqual(79 self.assertEqual(
@@ -101,14 +101,14 @@
101 def test_0(self):101 def test_0(self):
102 self.assertEqual(102 self.assertEqual(
103 self.export(0.0),103 self.export(0.0),
104 [[False]])104 [['0.0']])
105105
106 def test_epsilon(self):106 def test_epsilon(self):
107 """ epsilon gets sliced to 0 due to precision107 """ epsilon gets sliced to 0 due to precision
108 """108 """
109 self.assertEqual(109 self.assertEqual(
110 self.export(0.000000000027),110 self.export(0.000000000027),
111 [[False]])111 [['0.0']])
112112
113 def test_negative(self):113 def test_negative(self):
114 self.assertEqual(114 self.assertEqual(
@@ -130,7 +130,7 @@
130 def test_empty(self):130 def test_empty(self):
131 self.assertEqual(131 self.assertEqual(
132 self.export(""),132 self.export(""),
133 [[False]])133 [[""]])
134 def test_within_bounds(self):134 def test_within_bounds(self):
135 self.assertEqual(135 self.assertEqual(
136 self.export("foobar"),136 self.export("foobar"),
@@ -149,7 +149,7 @@
149 def test_empty(self):149 def test_empty(self):
150 self.assertEqual(150 self.assertEqual(
151 self.export(""),151 self.export(""),
152 [[False]])152 [[""]])
153 def test_small(self):153 def test_small(self):
154 self.assertEqual(154 self.assertEqual(
155 self.export("foobar"),155 self.export("foobar"),
@@ -171,7 +171,7 @@
171 def test_empty(self):171 def test_empty(self):
172 self.assertEqual(172 self.assertEqual(
173 self.export(""),173 self.export(""),
174 [[False]])174 [[""]])
175 def test_small(self):175 def test_small(self):
176 self.assertEqual(176 self.assertEqual(
177 self.export("foobar"),177 self.export("foobar"),
@@ -191,7 +191,7 @@
191 def test_empty(self):191 def test_empty(self):
192 self.assertEqual(192 self.assertEqual(
193 self.export(False),193 self.export(False),
194 [[False]])194 [['']])
195 def test_basic(self):195 def test_basic(self):
196 self.assertEqual(196 self.assertEqual(
197 self.export('2011-11-07'),197 self.export('2011-11-07'),
@@ -203,7 +203,7 @@
203 def test_empty(self):203 def test_empty(self):
204 self.assertEqual(204 self.assertEqual(
205 self.export(False),205 self.export(False),
206 [[False]])206 [['']])
207 def test_basic(self):207 def test_basic(self):
208 self.assertEqual(208 self.assertEqual(
209 self.export('2011-11-07 21:05:48'),209 self.export('2011-11-07 21:05:48'),
@@ -229,7 +229,7 @@
229 def test_empty(self):229 def test_empty(self):
230 self.assertEqual(230 self.assertEqual(
231 self.export(False),231 self.export(False),
232 [[False]])232 [['']])
233233
234 def test_value(self):234 def test_value(self):
235 """ selections export the *label* for their value235 """ selections export the *label* for their value
@@ -266,7 +266,7 @@
266 def test_empty(self):266 def test_empty(self):
267 self.assertEqual(267 self.assertEqual(
268 self.export(False),268 self.export(False),
269 [[False]])269 [['']])
270270
271 def test_value(self):271 def test_value(self):
272 # FIXME: selection functions export the *value* itself272 # FIXME: selection functions export the *value* itself
@@ -279,7 +279,7 @@
279 # fucking hell279 # fucking hell
280 self.assertEqual(280 self.assertEqual(
281 self.export(0),281 self.export(0),
282 [[False]])282 [['']])
283283
284class test_m2o(CreatorCase):284class test_m2o(CreatorCase):
285 model_name = 'export.many2one'285 model_name = 'export.many2one'
@@ -287,7 +287,7 @@
287 def test_empty(self):287 def test_empty(self):
288 self.assertEqual(288 self.assertEqual(
289 self.export(False),289 self.export(False),
290 [[False]])290 [['']])
291 def test_basic(self):291 def test_basic(self):
292 """ Exported value is the name_get of the related object292 """ Exported value is the name_get of the related object
293 """293 """
@@ -333,7 +333,7 @@
333 def test_empty(self):333 def test_empty(self):
334 self.assertEqual(334 self.assertEqual(
335 self.export(False),335 self.export(False),
336 [[False]])336 [['']])
337337
338 def test_single(self):338 def test_single(self):
339 self.assertEqual(339 self.assertEqual(
@@ -443,16 +443,16 @@
443 def test_empty(self):443 def test_empty(self):
444 self.assertEqual(444 self.assertEqual(
445 self.export(child1=False, child2=False),445 self.export(child1=False, child2=False),
446 [[False, False]])446 [['', '']])
447447
448 def test_single_per_side(self):448 def test_single_per_side(self):
449 self.assertEqual(449 self.assertEqual(
450 self.export(child1=False, child2=[(0, False, {'value': 42})]),450 self.export(child1=False, child2=[(0, False, {'value': 42})]),
451 [[False, u'export.one2many.child.2:42']])451 [['', u'export.one2many.child.2:42']])
452452
453 self.assertEqual(453 self.assertEqual(
454 self.export(child1=[(0, False, {'value': 43})], child2=False),454 self.export(child1=[(0, False, {'value': 43})], child2=False),
455 [[u'export.one2many.child.1:43', False]])455 [[u'export.one2many.child.1:43', '']])
456456
457 self.assertEqual(457 self.assertEqual(
458 self.export(child1=[(0, False, {'value': 43})],458 self.export(child1=[(0, False, {'value': 43})],
@@ -464,12 +464,12 @@
464 self.assertEqual(464 self.assertEqual(
465 self.export(child1=False, child2=[(0, False, {'value': 42})],465 self.export(child1=False, child2=[(0, False, {'value': 42})],
466 fields=fields),466 fields=fields),
467 [[u'36', False, u'42']])467 [[u'36', '', u'42']])
468468
469 self.assertEqual(469 self.assertEqual(
470 self.export(child1=[(0, False, {'value': 43})], child2=False,470 self.export(child1=[(0, False, {'value': 43})], child2=False,
471 fields=fields),471 fields=fields),
472 [[u'36', u'43', False]])472 [[u'36', u'43', '']])
473473
474 self.assertEqual(474 self.assertEqual(
475 self.export(child1=[(0, False, {'value': 43})],475 self.export(child1=[(0, False, {'value': 43})],
@@ -490,7 +490,7 @@
490 self.assertEqual(490 self.assertEqual(
491 self.export(child1=child1, child2=False, fields=fields),491 self.export(child1=child1, child2=False, fields=fields),
492 [492 [
493 [u'36', u'4', False],493 [u'36', u'4', ''],
494 ['', u'42', ''],494 ['', u'42', ''],
495 ['', u'36', ''],495 ['', u'36', ''],
496 ['', u'4', ''],496 ['', u'4', ''],
@@ -499,7 +499,7 @@
499 self.assertEqual(499 self.assertEqual(
500 self.export(child1=False, child2=child2, fields=fields),500 self.export(child1=False, child2=child2, fields=fields),
501 [501 [
502 [u'36', False, u'8'],502 [u'36', '', u'8'],
503 ['', '', u'12'],503 ['', '', u'12'],
504 ['', '', u'8'],504 ['', '', u'8'],
505 ['', '', u'55'],505 ['', '', u'55'],
@@ -538,7 +538,7 @@
538 def test_empty(self):538 def test_empty(self):
539 self.assertEqual(539 self.assertEqual(
540 self.export(False),540 self.export(False),
541 [[False]])541 [['']])
542542
543 def test_single(self):543 def test_single(self):
544 self.assertEqual(544 self.assertEqual(
545545
=== modified file 'openerp/osv/orm.py'
--- openerp/osv/orm.py 2014-04-11 07:55:56 +0000
+++ openerp/osv/orm.py 2014-04-16 13:23:35 +0000
@@ -1115,18 +1115,9 @@
1115 elif field_type == 'integer':1115 elif field_type == 'integer':
1116 return 01116 return 0
1117 elif field_type == 'boolean':1117 elif field_type == 'boolean':
1118 return 'False'1118 return False
1119 return ''1119 return ''
11201120
1121 def selection_field(in_field):
1122 col_obj = self.pool[in_field.keys()[0]]
1123 if f[i] in col_obj._columns.keys():
1124 return col_obj._columns[f[i]]
1125 elif f[i] in col_obj._inherits.keys():
1126 selection_field(col_obj._inherits)
1127 else:
1128 return False
1129
1130 def _get_xml_id(self, cr, uid, r):1121 def _get_xml_id(self, cr, uid, r):
1131 model_data = self.pool.get('ir.model.data')1122 model_data = self.pool.get('ir.model.data')
1132 data_ids = model_data.search(cr, uid, [('model', '=', r._model._name), ('res_id', '=', r['id'])])1123 data_ids = model_data.search(cr, uid, [('model', '=', r._model._name), ('res_id', '=', r['id'])])
@@ -1155,57 +1146,64 @@
1155 lines = []1146 lines = []
1156 data = map(lambda x: '', range(len(fields)))1147 data = map(lambda x: '', range(len(fields)))
1157 done = []1148 done = []
1149 init_row = row
1158 for fpos in range(len(fields)):1150 for fpos in range(len(fields)):
1159 f = fields[fpos]1151 # list of fields to get through
1160 if f:1152 fpath = fields[fpos]
1161 r = row1153 if fpath:
1154 result = False
1162 i = 01155 i = 0
1163 while i < len(f):1156 row = init_row
1157 while i < len(fpath):
1164 cols = False1158 cols = False
1165 if f[i] == '.id':1159 col_type = False
1166 r = r['id']1160 row_model = row._model
1167 elif f[i] == 'id':1161 row_columns = row_model._all_columns
1168 r = _get_xml_id(self, cr, uid, r)1162
1163 if fpath[i] == '.id':
1164 result = row['id']
1165 col_type = 'integer'
1166 elif fpath[i] == 'id':
1167 result = _get_xml_id(self, cr, uid, row)
1168 col_type = 'char'
1169 else:1169 else:
1170 r = r[f[i]]1170 result = row[fpath[i]]
1171 # To display external name of selection field when its exported1171 # To display external name of selection field when its exported
1172 if f[i] in self._columns.keys():1172 if fpath[i] in row_columns.keys():
1173 cols = self._columns[f[i]]1173 cols = row_columns[fpath[i]].column
1174 elif f[i] in self._inherit_fields.keys():
1175 cols = selection_field(self._inherits)
1176 if cols and cols._type == 'selection':1174 if cols and cols._type == 'selection':
1177 sel_list = cols.selection1175 sel_list = cols.selection
1178 if r and type(sel_list) == type([]):1176 if result and type(sel_list) == list:
1179 r = [x[1] for x in sel_list if r==x[0]]1177 result = [x[1] for x in sel_list if result==x[0]]
1180 r = r and r[0] or False1178 result = result and result[0] or False
1181 if not r:1179 col_type = cols and cols._type or False
1182 if f[i] in self._columns:1180
1183 r = check_type(self._columns[f[i]]._type)1181 if col_type == 'many2one':
1184 elif f[i] in self._inherit_fields:1182 # next iteration should use field model
1185 r = check_type(self._inherit_fields[f[i]][2]._type)1183 row = result
1186 data[fpos] = r or False1184
1187 break1185 elif col_type in ['many2many', 'one2many']:
1188 if isinstance(r, (browse_record_list, list)):1186 # list of browse records
1189 first = True1187 first = True
1190 fields2 = map(lambda x: (x[:i+1]==f[:i+1] and x[i+1:]) \1188 fields2 = map(lambda x: (x[:i+1]==fpath[:i+1] and x[i+1:]) \
1191 or [], fields)1189 or [], fields)
1192 if fields2 in done:1190 if fields2 in done:
1193 if [x for x in fields2 if x]:1191 if [x for x in fields2 if x]:
1194 break1192 break
1195 done.append(fields2)1193 done.append(fields2)
1196 if cols and cols._type=='many2many' and len(fields[fpos])>(i+1) and (fields[fpos][i+1]=='id'):1194 if col_type == 'many2many' and len(fields[fpos])>(i+1) and (fields[fpos][i+1]=='id'):
1197 data[fpos] = ','.join([_get_xml_id(self, cr, uid, x) for x in r])1195 data[fpos] = ','.join([_get_xml_id(self, cr, uid, x) for x in result])
1198 break1196 break
11991197
1200 for row2 in r:1198 for row2 in result:
1201 lines2 = row2._model.__export_row(cr, uid, row2, fields2, context=context)1199 lines2 = row2._model.__export_row(cr, uid, row2, fields2, raw_data=raw_data, context=context)
1202 if first:1200 if first:
1203 for fpos2 in range(len(fields)):1201 for fpos2 in range(len(fields)):
1204 if lines2 and lines2[0][fpos2]:1202 if lines2 and lines2[0][fpos2]:
1205 data[fpos2] = lines2[0][fpos2]1203 data[fpos2] = lines2[0][fpos2]
1206 if not data[fpos]:1204 if not data[fpos]:
1207 dt = ''1205 dt = ''
1208 for rr in r:1206 for rr in result:
1209 name_relation = self.pool[rr._table_name]._rec_name1207 name_relation = self.pool[rr._table_name]._rec_name
1210 if isinstance(rr[name_relation], browse_record):1208 if isinstance(rr[name_relation], browse_record):
1211 rr = rr[name_relation]1209 rr = rr[name_relation]
@@ -1218,21 +1216,33 @@
1218 first = False1216 first = False
1219 else:1217 else:
1220 lines += lines21218 lines += lines2
1219 # data already in
1221 break1220 break
1222 i += 11221 i += 1
12231222
1224 if i == len(f):1223 # skip in case of *2m where data is already set
1225 if isinstance(r, browse_record):1224 if i == len(fpath):
1226 r = self.pool[r._table_name].name_get(cr, uid, [r.id], context=context)1225 if isinstance(result, browse_record):
1227 r = r and r[0] and r[0][1] or ''1226 result = self.pool[result._table_name].name_get(cr, uid, [result.id], context=context)
1228 if raw_data and cols and cols._type in ('integer', 'boolean', 'float'):1227 result = result and result[0] and result[0][1] or ''
1229 data[fpos] = r1228 if raw_data and col_type in ('integer', 'boolean', 'float'):
1230 elif raw_data and cols and cols._type == 'date':1229 data[fpos] = result
1231 data[fpos] = datetime.datetime.strptime(r, tools.DEFAULT_SERVER_DATE_FORMAT).date()1230 elif raw_data and col_type == 'date':
1232 elif raw_data and cols and cols._type == 'datetime':1231 data[fpos] = datetime.datetime.strptime(result, tools.DEFAULT_SERVER_DATE_FORMAT).date()
1233 data[fpos] = datetime.datetime.strptime(r, tools.DEFAULT_SERVER_DATETIME_FORMAT)1232 elif raw_data and col_type == 'datetime':
1233 data[fpos] = datetime.datetime.strptime(result, tools.DEFAULT_SERVER_DATETIME_FORMAT)
1234 elif not result:
1235 if col_type == 'float':
1236 data[fpos] = '0.0'
1237 elif col_type == 'integer':
1238 data[fpos] = '0'
1239 elif col_type == 'boolean':
1240 data[fpos] = 'False'
1241 else:
1242 data[fpos] = ''
1234 else:1243 else:
1235 data[fpos] = tools.ustr(r or '')1244 data[fpos] = tools.ustr(result)
1245
1236 return [data] + lines1246 return [data] + lines
12371247
1238 def export_data(self, cr, uid, ids, fields_to_export, raw_data=False, context=None):1248 def export_data(self, cr, uid, ids, fields_to_export, raw_data=False, context=None):