This commit is contained in:
Cédric Krier
2010-03-17 11:51:34 +01:00
8 changed files with 521 additions and 39 deletions
+1
View File
@@ -1,4 +1,5 @@
* Improve search on translatable fields
* export_data return empty value for invisible fields
* Don't allow to use float in Numeric fields
* set/get function on Fields take a list of ids
* New interface for Function/Property fields
+1 -1
View File
@@ -11,7 +11,7 @@ class Integer(Field):
_type = 'integer'
class BigInteger(Field):
class BigInteger(Integer):
'''
Define an integer field (``long``).
'''
+11 -7
View File
@@ -355,9 +355,11 @@ class ModelSQL(ModelStorage):
for field_name in self._columns:
field = self._columns[field_name]
# Check required fields
if field.required \
and not hasattr(field, 'set') \
and field_name not in ('create_uid', 'create_date'):
if field.required and \
not hasattr(field, 'set') and \
not isinstance(field, (fields.Interger,
fields.Float)) and \
field_name not in ('create_uid', 'create_date'):
if not values.get(field_name):
self.raise_user_error(cursor2, 'required_field',
error_args=self._get_error_args(
@@ -876,10 +878,12 @@ class ModelSQL(ModelStorage):
continue
field = self._columns[field_name]
# Check required fields
if field.required \
and not hasattr(field, 'set') \
and field_name not in \
('create_uid', 'create_date'):
if field.required and \
not hasattr(field, 'set') and \
not isinstance(field, (fields.Interger,
fields.Float)) and \
field_name not in ('create_uid',
'create_date'):
if not values[field_name]:
self.raise_user_error(cursor2,
'required_field',
+51 -31
View File
@@ -496,41 +496,61 @@ class ModelStorage(Model):
local_cache=local_cache, context=context) for x in ids),
context=context)
def __export_row(self, cursor, user, row, fields_names, context=None):
def __export_row(self, cursor, user, record, fields_names, context=None):
lines = []
data = ['' for x in range(len(fields_names))]
done = []
for fpos in range(len(fields_names)):
field = fields_names[fpos]
if field:
row2 = row
i = 0
while i < len(field):
row2 = row2[field[i]]
if not row2:
fields_tree = fields_names[fpos]
if not fields_tree:
continue
value = record
i = 0
while i < len(fields_tree):
if not isinstance(value, BrowseRecord):
break
field_name = fields_tree[i]
model_obj = self.pool.get(value._model_name)
field = model_obj._columns[field_name]
if field.states and 'invisible' in field.states:
pyson_invisible = PYSONEncoder().encode(
field.states['invisible'])
env = EvalEnvironment(value, model_obj)
env.update(context)
env['current_date'] = datetime.datetime.today()
env['time'] = time
env['context'] = context
env['active_id'] = value.id
invisible = PYSONDecoder(env).decode(pyson_invisible)
if invisible:
value = ''
break
if isinstance(row2, (BrowseRecordList, list)):
first = True
fields2 = [(x[:i+1]==field[:i+1] and x[i+1:]) \
or [] for x in fields_names]
if fields2 in done:
break
done.append(fields2)
for row2 in row2:
lines2 = self.__export_row(cursor, user, row2,
fields2, context)
if first:
for fpos2 in range(len(fields_names)):
if lines2 and lines2[0][fpos2]:
data[fpos2] = lines2[0][fpos2]
lines += lines2[1:]
first = False
else:
lines += lines2
value = value[field_name]
if isinstance(value, (BrowseRecordList, list)):
first = True
child_fields_names = [(x[:i + 1] == fields_tree[:i + 1] and
x[i + 1:]) or [] for x in fields_names]
if child_fields_names in done:
break
i += 1
if i == len(field):
data[fpos] = row2 or ''
done.append(child_fields_names)
for child_record in value:
child_lines = self.__export_row(cursor, user,
child_record, child_fields_names, context)
if first:
for child_fpos in xrange(len(fields_names)):
if child_lines and child_lines[0][child_fpos]:
data[child_fpos] = \
child_lines[0][child_fpos]
lines += child_lines[1:]
first = False
else:
lines += child_lines
break
i += 1
if i == len(fields_tree):
if value is None:
value = ''
data[fpos] = value
return [data] + lines
def export_data(self, cursor, user, ids, fields_names, context=None):
@@ -547,8 +567,8 @@ class ModelStorage(Model):
'''
fields_names = [x.split('/') for x in fields_names]
datas = []
for row in self.browse(cursor, user, ids, context):
datas += self.__export_row(cursor, user, row, fields_names, context)
for record in self.browse(cursor, user, ids, context):
datas += self.__export_row(cursor, user, record, fields_names, context)
return datas
def import_data(self, cursor, user, fields_names, datas, context=None):
+1
View File
@@ -5,3 +5,4 @@ from test import *
from model import *
from mptt import *
from import_data import *
from export_data import *
+58
View File
@@ -0,0 +1,58 @@
#This file is part of Tryton. The COPYRIGHT file at the top level of
#this repository contains the full copyright notices and license terms.
"Test for export_data"
from trytond.model import ModelSQL, fields
class ExportDataTarget(ModelSQL):
"Export Data Target"
_name = 'test.export_data.target'
_description = __doc__
name = fields.Char('Name')
ExportDataTarget()
class ExportData(ModelSQL):
"Export Data"
_name = 'test.export_data'
_description = __doc__
boolean = fields.Boolean('Boolean')
integer = fields.Integer('Integer')
float = fields.Float('Float')
numeric = fields.Numeric('Numeric')
char = fields.Char('Char')
text = fields.Text('Text')
sha = fields.Sha('Sha')
date = fields.Date('Date')
datetime = fields.DateTime('DateTime')
selection = fields.Selection([
('select1', 'Select 1'),
('select2', 'Select 2'),
], 'Selection')
many2one = fields.Many2One('test.export_data.target',
'Many2One')
many2many = fields.Many2Many('test.export_data.relation',
'many2many', 'target', 'Many2Many')
one2many = fields.One2Many('test.export_data.target', 'one2many',
'One2Many')
reference = fields.Reference('Reference', [
('test.export_data.target', 'Target'),
])
ExportData()
class ExportDataTarget(ExportDataTarget):
one2many = fields.Many2One('test.export_data', 'Export Data')
ExportDataTarget()
class ExportDataRelation(ModelSQL):
"Export Data Many2Many"
_name = 'test.export_data.relation'
_description = __doc__
many2many = fields.Many2One('test.export_data', 'Export Data')
target = fields.Many2One('test.export_data.target', 'Target')
ExportDataRelation()
+396
View File
@@ -0,0 +1,396 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#This file is part of Tryton. The COPYRIGHT file at the top level of
#this repository contains the full copyright notices and license terms.
import unittest
from decimal import Decimal
import datetime
from trytond.tests.test_tryton import POOL, DB, USER, CONTEXT, install_module
class ExportDataTestCase(unittest.TestCase):
'''
Test export_data.
'''
def setUp(self):
install_module('test')
self.export_data = POOL.get('test.export_data')
self.export_data_target = POOL.get('test.export_data.target')
self.export_data_relation = POOL.get('test.export_data.relation')
def test0010boolean(self):
'''
Test boolean.
'''
cursor = DB.cursor()
export1_id = self.export_data.create(cursor, USER, {
'boolean': True,
}, context=CONTEXT)
self.assert_(self.export_data.export_data(cursor, USER, [export1_id],
['boolean'], context=CONTEXT) == [[True]])
export2_id = self.export_data.create(cursor, USER, {
'boolean': False,
}, context=CONTEXT)
self.assert_(self.export_data.export_data(cursor, USER, [export2_id],
['boolean'], context=CONTEXT) == [[False]])
self.assert_(self.export_data.export_data(cursor, USER,
[export1_id, export2_id], ['boolean'], context=CONTEXT) ==
[[True], [False]])
cursor.rollback()
cursor.close()
def test0020integer(self):
'''
Test integer.
'''
cursor = DB.cursor()
export1_id = self.export_data.create(cursor, USER, {
'integer': 2,
}, context=CONTEXT)
self.assert_(self.export_data.export_data(cursor, USER, [export1_id],
['integer'], context=CONTEXT) == [[2]])
export2_id = self.export_data.create(cursor, USER, {
'integer': 0,
}, context=CONTEXT)
self.assert_(self.export_data.export_data(cursor, USER, [export2_id],
['integer'], context=CONTEXT) == [[0]])
self.assert_(self.export_data.export_data(cursor, USER,
[export1_id, export2_id], ['integer'], context=CONTEXT) ==
[[2], [0]])
cursor.rollback()
cursor.close()
def test0030float(self):
'''
Test float.
'''
cursor = DB.cursor()
export1_id = self.export_data.create(cursor, USER, {
'float': 1.1,
}, context=CONTEXT)
self.assert_(self.export_data.export_data(cursor, USER, [export1_id],
['float'], context=CONTEXT) == [[1.1]])
export2_id = self.export_data.create(cursor, USER, {
'float': 0,
}, context=CONTEXT)
self.assert_(self.export_data.export_data(cursor, USER, [export2_id],
['float'], context=CONTEXT) == [[0]])
self.assert_(self.export_data.export_data(cursor, USER,
[export1_id, export2_id], ['float'], context=CONTEXT) ==
[[1.1], [0]])
cursor.rollback()
cursor.close()
def test0040numeric(self):
'''
Test numeric.
'''
cursor = DB.cursor()
export1_id = self.export_data.create(cursor, USER, {
'numeric': Decimal('1.1'),
}, context=CONTEXT)
self.assert_(self.export_data.export_data(cursor, USER, [export1_id],
['numeric'], context=CONTEXT) == [[Decimal('1.1')]])
export2_id = self.export_data.create(cursor, USER, {
'numeric': Decimal('0'),
}, context=CONTEXT)
self.assert_(self.export_data.export_data(cursor, USER, [export2_id],
['numeric'], context=CONTEXT) == [[Decimal('0')]])
self.assert_(self.export_data.export_data(cursor, USER,
[export1_id, export2_id], ['numeric'], context=CONTEXT) ==
[[Decimal('1.1')], [Decimal('0')]])
cursor.rollback()
cursor.close()
def test0050char(self):
'''
Test char.
'''
cursor = DB.cursor()
export1_id = self.export_data.create(cursor, USER, {
'char': 'test',
}, context=CONTEXT)
self.assert_(self.export_data.export_data(cursor, USER, [export1_id],
['char'], context=CONTEXT) == [['test']])
export2_id = self.export_data.create(cursor, USER, {
'char': False,
}, context=CONTEXT)
self.assert_(self.export_data.export_data(cursor, USER, [export2_id],
['char'], context=CONTEXT) == [['']])
self.assert_(self.export_data.export_data(cursor, USER,
[export1_id, export2_id], ['char'], context=CONTEXT) ==
[['test'], ['']])
cursor.rollback()
cursor.close()
def test0060text(self):
'''
Test text.
'''
cursor = DB.cursor()
export1_id = self.export_data.create(cursor, USER, {
'text': 'test',
}, context=CONTEXT)
self.assert_(self.export_data.export_data(cursor, USER, [export1_id],
['text'], context=CONTEXT) == [['test']])
export2_id = self.export_data.create(cursor, USER, {
'text': False,
}, context=CONTEXT)
self.assert_(self.export_data.export_data(cursor, USER, [export2_id],
['text'], context=CONTEXT) == [['']])
self.assert_(self.export_data.export_data(cursor, USER,
[export1_id, export2_id], ['text'], context=CONTEXT) ==
[['test'], ['']])
cursor.rollback()
cursor.close()
def test0070sha(self):
'''
Test sha.
'''
cursor = DB.cursor()
export1_id = self.export_data.create(cursor, USER, {
'sha': 'Test',
}, context=CONTEXT)
self.assert_(self.export_data.export_data(cursor, USER, [export1_id],
['sha'], context=CONTEXT) == [['640ab2bae07bedc4c163f679a746f7ab7fb5d1fa']])
cursor.rollback()
cursor.close()
def test0080date(self):
'''
Test date.
'''
cursor = DB.cursor()
export1_id = self.export_data.create(cursor, USER, {
'date': datetime.date(2010, 1, 1),
}, context=CONTEXT)
self.assert_(self.export_data.export_data(cursor, USER, [export1_id],
['date'], context=CONTEXT) == [[datetime.date(2010, 1, 1)]])
export2_id = self.export_data.create(cursor, USER, {
'date': False,
}, context=CONTEXT)
self.assert_(self.export_data.export_data(cursor, USER, [export2_id],
['date'], context=CONTEXT) == [['']])
self.assert_(self.export_data.export_data(cursor, USER,
[export1_id, export2_id], ['date'], context=CONTEXT) ==
[[datetime.date(2010, 1, 1)], ['']])
cursor.rollback()
cursor.close()
def test0090datetime(self):
'''
Test datetime.
'''
cursor = DB.cursor()
export1_id = self.export_data.create(cursor, USER, {
'datetime': datetime.datetime(2010, 1, 1, 12, 0, 0),
}, context=CONTEXT)
self.assert_(self.export_data.export_data(cursor, USER, [export1_id],
['datetime'], context=CONTEXT) == [[datetime.datetime(2010, 1,
1, 12, 0, 0)]])
export2_id = self.export_data.create(cursor, USER, {
'datetime': False,
}, context=CONTEXT)
self.assert_(self.export_data.export_data(cursor, USER, [export2_id],
['datetime'], context=CONTEXT) == [['']])
self.assert_(self.export_data.export_data(cursor, USER,
[export1_id, export2_id], ['datetime'], context=CONTEXT) ==
[[datetime.datetime(2010, 1, 1, 12, 0, 0)], ['']])
cursor.rollback()
cursor.close()
def test0100selection(self):
'''
Test selection.
'''
cursor = DB.cursor()
export1_id = self.export_data.create(cursor, USER, {
'selection': 'select1',
}, context=CONTEXT)
self.assert_(self.export_data.export_data(cursor, USER, [export1_id],
['selection'], context=CONTEXT) == [['select1']])
export2_id = self.export_data.create(cursor, USER, {
'selection': False,
}, context=CONTEXT)
self.assert_(self.export_data.export_data(cursor, USER, [export2_id],
['selection'], context=CONTEXT) == [['']])
self.assert_(self.export_data.export_data(cursor, USER,
[export1_id, export2_id], ['selection'], context=CONTEXT) ==
[['select1'], ['']])
cursor.rollback()
cursor.close()
def test0110many2one(self):
'''
Test many2one.
'''
cursor = DB.cursor()
target_id = self.export_data_target.create(cursor, USER, {
'name': 'Target Test',
}, context=CONTEXT)
export1_id = self.export_data.create(cursor, USER, {
'many2one': target_id,
}, context=CONTEXT)
self.assert_(self.export_data.export_data(cursor, USER, [export1_id],
['many2one/name'], context=CONTEXT) == [['Target Test']])
export2_id = self.export_data.create(cursor, USER, {
'many2one': False,
}, context=CONTEXT)
self.assert_(self.export_data.export_data(cursor, USER, [export2_id],
['many2one/name'], context=CONTEXT) == [['']])
self.assert_(self.export_data.export_data(cursor, USER,
[export1_id, export2_id], ['many2one/name'], context=CONTEXT) ==
[['Target Test'], ['']])
cursor.rollback()
cursor.close()
def test0120many2many(self):
'''
Test many2many.
'''
cursor = DB.cursor()
target1_id = self.export_data_target.create(cursor, USER, {
'name': 'Target 1',
}, context=CONTEXT)
export1_id = self.export_data.create(cursor, USER, {
'many2many': [('set', [target1_id])],
}, context=CONTEXT)
self.assert_(self.export_data.export_data(cursor, USER, [export1_id],
['many2many/name'], context=CONTEXT) == [['Target 1']])
target2_id = self.export_data_target.create(cursor, USER, {
'name': 'Target 2',
}, context=CONTEXT)
self.export_data.write(cursor, USER, export1_id, {
'many2many': [('set', [target1_id, target2_id])],
}, context=CONTEXT)
self.assert_(self.export_data.export_data(cursor, USER, [export1_id],
['id', 'many2many/name'], context=CONTEXT) ==
[[export1_id, 'Target 1'], ['', 'Target 2']])
export2_id = self.export_data.create(cursor, USER, {
'many2many': False,
}, context=CONTEXT)
self.assert_(self.export_data.export_data(cursor, USER, [export2_id],
['many2many/name'], context=CONTEXT) == [['']])
self.assert_(self.export_data.export_data(cursor, USER,
[export1_id, export2_id], ['id', 'many2many/name'], context=CONTEXT)
== [[export1_id, 'Target 1'], ['', 'Target 2'], [export2_id, '']])
cursor.rollback()
cursor.close()
def test0130one2many(self):
'''
Test one2many.
'''
cursor = DB.cursor()
export1_id = self.export_data.create(cursor, USER, {}, context=CONTEXT)
target1_id = self.export_data_target.create(cursor, USER, {
'name': 'Target 1',
'one2many': export1_id,
}, context=CONTEXT)
self.assert_(self.export_data.export_data(cursor, USER, [export1_id],
['one2many/name'], context=CONTEXT) == [['Target 1']])
target2_id = self.export_data_target.create(cursor, USER, {
'name': 'Target 2',
'one2many': export1_id,
}, context=CONTEXT)
self.assert_(self.export_data.export_data(cursor, USER, [export1_id],
['id', 'one2many/name'], context=CONTEXT) ==
[[export1_id, 'Target 1'], ['', 'Target 2']])
export2_id = self.export_data.create(cursor, USER, {}, context=CONTEXT)
self.assert_(self.export_data.export_data(cursor, USER, [export2_id],
['one2many/name'], context=CONTEXT) == [['']])
self.assert_(self.export_data.export_data(cursor, USER,
[export1_id, export2_id], ['id', 'one2many/name'], context=CONTEXT)
== [[export1_id, 'Target 1'], ['', 'Target 2'], [export2_id, '']])
cursor.rollback()
cursor.close()
def test0140reference(self):
'''
Test reference.
'''
cursor = DB.cursor()
target1_id = self.export_data_target.create(cursor, USER, {},
context=CONTEXT)
export1_id = self.export_data.create(cursor, USER, {
'reference': 'test.export_data.target,%s' % target1_id,
}, context=CONTEXT)
self.assert_(self.export_data.export_data(cursor, USER, [export1_id],
['reference'], context=CONTEXT) ==
[['test.export_data.target,%s' % target1_id]])
export2_id = self.export_data.create(cursor, USER, {
'reference': False,
}, context=CONTEXT)
self.assert_(self.export_data.export_data(cursor, USER, [export2_id],
['reference'], context=CONTEXT) == [['']])
self.assert_(self.export_data.export_data(cursor, USER,
[export1_id, export2_id], ['reference'], context=CONTEXT) ==
[['test.export_data.target,%s' % target1_id], ['']])
cursor.rollback()
cursor.close()
def suite():
return unittest.TestLoader().loadTestsFromTestCase(ExportDataTestCase)
if __name__ == '__main__':
suite = suite()
unittest.TextTestRunner(verbosity=2).run(suite)
+2
View File
@@ -168,6 +168,8 @@ def all_suite():
suite_.addTests(test_mptt.suite())
import trytond.tests.test_importdata as test_importdata
suite_.addTests(test_importdata.suite())
import trytond.tests.test_exportdata as test_exportdata
suite_.addTests(test_exportdata.suite())
return suite_
def modules_suite():