changeset e4f619ba9c25 in trytond:default
details: https://hg.tryton.org/trytond?cmd=changeset;node=e4f619ba9c25
description:
        Allow SQL expression as value of fields

        issue6460
        review279431002
diffstat:

 CHANGELOG                             |   1 +
 trytond/model/fields/boolean.py       |   1 +
 trytond/model/fields/char.py          |   7 +--
 trytond/model/fields/date.py          |  72 +++++++++++++++++-----------------
 trytond/model/fields/dict.py          |  10 ++--
 trytond/model/fields/field.py         |   4 +
 trytond/model/fields/float.py         |   6 +--
 trytond/model/fields/integer.py       |   6 +--
 trytond/model/fields/many2one.py      |   5 +-
 trytond/model/fields/numeric.py       |   9 +---
 trytond/model/fields/reference.py     |   1 +
 trytond/model/fields/selection.py     |   1 +
 trytond/tests/field_time.py           |   7 +++
 trytond/tests/test_field_binary.py    |  13 ++++++
 trytond/tests/test_field_boolean.py   |  11 +++++
 trytond/tests/test_field_char.py      |  11 +++++
 trytond/tests/test_field_date.py      |  15 ++++++-
 trytond/tests/test_field_datetime.py  |  21 ++++++++-
 trytond/tests/test_field_float.py     |  11 +++++
 trytond/tests/test_field_integer.py   |  11 +++++
 trytond/tests/test_field_numeric.py   |  11 +++++
 trytond/tests/test_field_time.py      |  15 ++++++-
 trytond/tests/test_field_timedelta.py |   8 +-
 23 files changed, 177 insertions(+), 80 deletions(-)

diffs (726 lines):

diff -r f95be0d3807d -r e4f619ba9c25 CHANGELOG
--- a/CHANGELOG Sun Jun 16 19:24:15 2019 +0200
+++ b/CHANGELOG Wed Jun 26 21:56:16 2019 +0200
@@ -1,3 +1,4 @@
+* Allow SQL expression as value of fields
 * Allow customizing Dict keys order with a sequence field
 * Add invalid domain in DomainValidationError
 * Add domain inversion tools
diff -r f95be0d3807d -r e4f619ba9c25 trytond/model/fields/boolean.py
--- a/trytond/model/fields/boolean.py   Sun Jun 16 19:24:15 2019 +0200
+++ b/trytond/model/fields/boolean.py   Wed Jun 26 21:56:16 2019 +0200
@@ -10,6 +10,7 @@
     '''
     _type = 'boolean'
     _sql_type = 'BOOL'
+    _py_type = bool
 
     def __init__(self, string='', help='', readonly=False, domain=None,
             states=None, select=False, on_change=None, on_change_with=None,
diff -r f95be0d3807d -r e4f619ba9c25 trytond/model/fields/char.py
--- a/trytond/model/fields/char.py      Sun Jun 16 19:24:15 2019 +0200
+++ b/trytond/model/fields/char.py      Wed Jun 26 21:56:16 2019 +0200
@@ -12,6 +12,7 @@
     Define a char field (``unicode``).
     '''
     _type = 'char'
+    _py_type = str
 
     def __init__(self, string='', size=None, help='', required=False,
             readonly=False, domain=None, states=None, translate=False,
@@ -47,12 +48,6 @@
 
     size = property(_get_size, _set_size)
 
-    def sql_format(self, value):
-        if value is None:
-            return None
-        assert isinstance(value, str)
-        return value
-
     @property
     def _sql_type(self):
         return 'VARCHAR(%s)' % self.size if self.size else 'VARCHAR'
diff -r f95be0d3807d -r e4f619ba9c25 trytond/model/fields/date.py
--- a/trytond/model/fields/date.py      Sun Jun 16 19:24:15 2019 +0200
+++ b/trytond/model/fields/date.py      Wed Jun 26 21:56:16 2019 +0200
@@ -1,6 +1,7 @@
 # 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 datetime
+
 from sql.functions import Function
 
 from trytond.pyson import PYSONEncoder
@@ -29,23 +30,16 @@
     '''
     _type = 'date'
     _sql_type = 'DATE'
+    _py_type = datetime.date
 
     def sql_format(self, value):
-        if value is None:
-            return None
         if isinstance(value, str):
             year, month, day = list(map(int, value.split("-", 2)))
-            return datetime.date(year, month, day)
-
-        if (not isinstance(value, datetime.date)
-                # Allow datetime with min time for XML-RPC
-                # datetime must be tested separately because datetime is a
-                # subclass of date
-                or (isinstance(value, datetime.datetime)
-                    and value.time() != datetime.time())):
-            raise ValueError("invalid type '%s' for %s"
-                % (type(value), type(self)))
-        return value
+            value = datetime.date(year, month, day)
+        elif isinstance(value, datetime.datetime):
+            if value.time() != datetime.time():
+                raise ValueError("Date field can not have time")
+        return super().sql_format(value)
 
     def sql_cast(self, expression):
         if backend.name() == 'sqlite':
@@ -68,11 +62,10 @@
     '''
     _type = 'timestamp'
     _sql_type = 'TIMESTAMP'
+    _py_type = datetime.datetime
     format = '%H:%M:%S.%f'
 
     def sql_format(self, value):
-        if value is None:
-            return None
         if isinstance(value, str):
             datepart, timepart = value.split(" ")
             year, month, day = map(int, datepart.split("-", 2))
@@ -82,12 +75,9 @@
                 microseconds = int(timepart_full[1])
             else:
                 microseconds = 0
-            return datetime.datetime(year, month, day, hours, minutes, seconds,
-                    microseconds)
-        if not isinstance(value, datetime.datetime):
-            raise ValueError("invalid type '%s' for %s"
-                % (type(value), type(self)))
-        return value
+            value = datetime.datetime(
+                year, month, day, hours, minutes, seconds, microseconds)
+        return super().sql_format(value)
 
     def sql_cast(self, expression):
         if backend.name() == 'sqlite':
@@ -119,28 +109,40 @@
 
     def sql_format(self, value):
         value = super().sql_format(value)
-        if value:
+        if isinstance(value, datetime.datetime):
             value = value.replace(microsecond=0)
         return value
 
 
-class Time(DateTime):
+class Time(FormatMixin, Field):
     '''
     Define a time field (``time``).
     '''
     _type = 'time'
     _sql_type = 'TIME'
+    _py_type = datetime.time
+
+    def __init__(self, string='', format='%H:%M:%S', help='', required=False,
+            readonly=False, domain=None, states=None, select=False,
+            on_change=None, on_change_with=None, depends=None,
+            context=None, loading='eager'):
+        '''
+        :param format: The validation format as used by strftime.
+        '''
+        super().__init__(string=string, help=help,
+            required=required, readonly=readonly, domain=domain, states=states,
+            select=select, on_change=on_change, on_change_with=on_change_with,
+            depends=depends, context=context, loading=loading)
+        self.format = format
 
     def sql_format(self, value):
-        if value is None:
-            return None
         if isinstance(value, str):
             hours, minutes, seconds = map(int, value.split(":"))
-            return datetime.time(hours, minutes, seconds)
-        if not isinstance(value, datetime.time):
-            raise ValueError("invalid type '%s' for %s"
-                % (type(value), type(self)))
-        return value.replace(microsecond=0)
+            value = datetime.time(hours, minutes, seconds)
+        value = super().sql_format(value)
+        if isinstance(value, datetime.time):
+            value = value.replace(microsecond=0)
+        return value
 
     def sql_cast(self, expression):
         if backend.name() == 'sqlite':
@@ -154,6 +156,7 @@
     '''
     _type = 'timedelta'
     _sql_type = 'INTERVAL'
+    _py_type = datetime.timedelta
 
     def __init__(self, string='', converter=None, help='', required=False,
             readonly=False, domain=None, states=None, select=False,
@@ -170,12 +173,9 @@
         self.converter = converter
 
     def sql_format(self, value):
-        if value is None:
-            return None
-        if not isinstance(value, datetime.timedelta):
-            raise ValueError("invalid type '%s' for %s"
-                % (type(value), type(self)))
-        return super(TimeDelta, self).sql_format(value)
+        if isinstance(value, (int, float)):
+            raise TypeError("TimeDelta requires a timedelta")
+        return super().sql_format(value)
 
     @classmethod
     def get(cls, ids, model, name, values=None):
diff -r f95be0d3807d -r e4f619ba9c25 trytond/model/fields/dict.py
--- a/trytond/model/fields/dict.py      Sun Jun 16 19:24:15 2019 +0200
+++ b/trytond/model/fields/dict.py      Wed Jun 26 21:56:16 2019 +0200
@@ -21,6 +21,7 @@
     'Define dict field.'
     _type = 'dict'
     _sql_type = 'TEXT'
+    _py_type = dict
 
     def __init__(self, schema_model, string='', help='', required=False,
             readonly=False, domain=None, states=None, select=False,
@@ -44,11 +45,10 @@
         return dicts
 
     def sql_format(self, value):
-        if value is None:
-            return None
-        assert isinstance(value, dict)
-        value = {k: v for k, v in value.items() if v is not None}
-        return dumps(value)
+        value = super().sql_format(value)
+        if isinstance(value, dict):
+            value = dumps({k: v for k, v in value.items() if v is not None})
+        return value
 
     def translated(self, name=None, type_='values'):
         "Return a descriptor for the translated value of the field"
diff -r f95be0d3807d -r e4f619ba9c25 trytond/model/fields/field.py
--- a/trytond/model/fields/field.py     Sun Jun 16 19:24:15 2019 +0200
+++ b/trytond/model/fields/field.py     Wed Jun 26 21:56:16 2019 +0200
@@ -210,6 +210,7 @@
 class Field(object):
     _type = None
     _sql_type = None
+    _py_type = None
 
     def __init__(self, string='', help='', required=False, readonly=False,
             domain=None, states=None, select=False, on_change=None,
@@ -343,6 +344,9 @@
 
         assert self._sql_type is not None
         database = Transaction().database
+        if (self._py_type and value is not None
+                and not isinstance(value, self._py_type)):
+            value = self._py_type(value)
         return database.sql_format(self._sql_type, value)
 
     def sql_type(self):
diff -r f95be0d3807d -r e4f619ba9c25 trytond/model/fields/float.py
--- a/trytond/model/fields/float.py     Sun Jun 16 19:24:15 2019 +0200
+++ b/trytond/model/fields/float.py     Wed Jun 26 21:56:16 2019 +0200
@@ -22,6 +22,7 @@
     '''
     _type = 'float'
     _sql_type = 'FLOAT'
+    _py_type = float
 
     def __init__(self, string='', digits=None, help='', required=False,
             readonly=False, domain=None, states=None, select=False,
@@ -49,11 +50,6 @@
 
     digits = property(_get_digits, _set_digits)
 
-    def sql_format(self, value):
-        if value is None:
-            return None
-        return float(value)
-
     def definition(self, model, language):
         encoder = PYSONEncoder()
         definition = super().definition(model, language)
diff -r f95be0d3807d -r e4f619ba9c25 trytond/model/fields/integer.py
--- a/trytond/model/fields/integer.py   Sun Jun 16 19:24:15 2019 +0200
+++ b/trytond/model/fields/integer.py   Wed Jun 26 21:56:16 2019 +0200
@@ -9,11 +9,7 @@
     '''
     _type = 'integer'
     _sql_type = 'INTEGER'
-
-    def sql_format(self, value):
-        if value is None:
-            return None
-        return int(str(value))
+    _py_type = int
 
 
 class BigInteger(Integer):
diff -r f95be0d3807d -r e4f619ba9c25 trytond/model/fields/many2one.py
--- a/trytond/model/fields/many2one.py  Sun Jun 16 19:24:15 2019 +0200
+++ b/trytond/model/fields/many2one.py  Wed Jun 26 21:56:16 2019 +0200
@@ -19,6 +19,7 @@
     '''
     _type = 'many2one'
     _sql_type = 'INTEGER'
+    _py_type = int
 
     def __init__(self, model_name, string='', left=None, right=None,
             ondelete='SET NULL', datetime_field=None, target_search='join',
@@ -111,10 +112,8 @@
         super(Many2One, self).__set__(inst, value)
 
     def sql_format(self, value):
-        if value is None:
-            return None
         assert value is not False
-        return int(value)
+        return super().sql_format(value)
 
     def convert_domain_mptt(self, domain, tables):
         cursor = Transaction().connection.cursor()
diff -r f95be0d3807d -r e4f619ba9c25 trytond/model/fields/numeric.py
--- a/trytond/model/fields/numeric.py   Sun Jun 16 19:24:15 2019 +0200
+++ b/trytond/model/fields/numeric.py   Wed Jun 26 21:56:16 2019 +0200
@@ -20,14 +20,7 @@
     '''
     _type = 'numeric'
     _sql_type = 'NUMERIC'
-
-    def sql_format(self, value):
-        if value is None:
-            return None
-        if isinstance(value, int):
-            value = Decimal(str(value))
-        value = Decimal(value)
-        return value
+    _py_type = Decimal
 
     def sql_column(self, table):
         column = super(Numeric, self).sql_column(table)
diff -r f95be0d3807d -r e4f619ba9c25 trytond/model/fields/reference.py
--- a/trytond/model/fields/reference.py Sun Jun 16 19:24:15 2019 +0200
+++ b/trytond/model/fields/reference.py Wed Jun 26 21:56:16 2019 +0200
@@ -20,6 +20,7 @@
     '''
     _type = 'reference'
     _sql_type = 'VARCHAR'
+    _py_type = str
 
     def __init__(self, string='', selection=None, sort=True,
             selection_change_with=None, translate=True, search_order=None,
diff -r f95be0d3807d -r e4f619ba9c25 trytond/model/fields/selection.py
--- a/trytond/model/fields/selection.py Sun Jun 16 19:24:15 2019 +0200
+++ b/trytond/model/fields/selection.py Wed Jun 26 21:56:16 2019 +0200
@@ -59,6 +59,7 @@
     '''
     _type = 'selection'
     _sql_type = 'VARCHAR'
+    _py_type = str
 
     def __init__(self, selection, string='', sort=True,
             selection_change_with=None, translate=True, help='',
diff -r f95be0d3807d -r e4f619ba9c25 trytond/tests/field_time.py
--- a/trytond/tests/field_time.py       Sun Jun 16 19:24:15 2019 +0200
+++ b/trytond/tests/field_time.py       Wed Jun 26 21:56:16 2019 +0200
@@ -35,10 +35,17 @@
     time = fields.Time(string='Time', format='%H:%M')
 
 
+class TimePrecision(ModelSQL):
+    "Time precision"
+    __name__ = 'test.time_precision'
+    time = fields.Time(string="Time", format="%H:%M:%S.%f")
+
+
 def register(module):
     Pool.register(
         Time,
         TimeDefault,
         TimeRequired,
         TimeFormat,
+        TimePrecision,
         module=module, type_='model')
diff -r f95be0d3807d -r e4f619ba9c25 trytond/tests/test_field_binary.py
--- a/trytond/tests/test_field_binary.py        Sun Jun 16 19:24:15 2019 +0200
+++ b/trytond/tests/test_field_binary.py        Wed Jun 26 21:56:16 2019 +0200
@@ -4,6 +4,8 @@
 import tempfile
 import unittest
 
+from sql import Literal
+
 from trytond.config import config
 from trytond.model.exceptions import RequiredValidationError
 from trytond.model import fields
@@ -111,6 +113,17 @@
         self.assertEqual(binary.binary_id, None)
 
     @with_transaction()
+    def test_create_with_sql_value(self):
+        "Test create binary with SQL value"
+        Binary = Pool().get('test.binary')
+
+        binary, = Binary.create([{
+                    'binary': Literal('foo'),
+                    }])
+
+        self.assertEqual(binary.binary, cast(b'foo'))
+
+    @with_transaction()
     def test_read_size(self):
         "Test read binary size"
         Binary = Pool().get('test.binary')
diff -r f95be0d3807d -r e4f619ba9c25 trytond/tests/test_field_boolean.py
--- a/trytond/tests/test_field_boolean.py       Sun Jun 16 19:24:15 2019 +0200
+++ b/trytond/tests/test_field_boolean.py       Wed Jun 26 21:56:16 2019 +0200
@@ -2,6 +2,8 @@
 # this repository contains the full copyright notices and license terms.
 import unittest
 
+from sql import Literal
+
 from trytond.pool import Pool
 from trytond.tests.test_tryton import activate_module, with_transaction
 
@@ -49,6 +51,15 @@
         self.assertEqual(boolean.boolean, True)
 
     @with_transaction()
+    def test_create_with_sql_value(self):
+        "Test create boolean with SQL value"
+        Boolean = Pool().get('test.boolean')
+
+        boolean, = Boolean.create([{'boolean': Literal(True)}])
+
+        self.assertEqual(boolean.boolean, True)
+
+    @with_transaction()
     def test_search_equals_true(self):
         "Test search boolean equals True"
         Boolean = Pool().get('test.boolean')
diff -r f95be0d3807d -r e4f619ba9c25 trytond/tests/test_field_char.py
--- a/trytond/tests/test_field_char.py  Sun Jun 16 19:24:15 2019 +0200
+++ b/trytond/tests/test_field_char.py  Wed Jun 26 21:56:16 2019 +0200
@@ -3,6 +3,8 @@
 # this repository contains the full copyright notices and license terms.
 import unittest
 
+from sql import Literal
+
 from trytond import backend
 from trytond.model.exceptions import RequiredValidationError
 from trytond.pool import Pool
@@ -38,6 +40,15 @@
         self.assertEqual(char.char, "é")
 
     @with_transaction()
+    def test_create_with_sql_value(self):
+        "Test create with SQL value"
+        Char = self.Char()
+
+        char, = Char.create([{'char': Literal('Foo')}])
+
+        self.assertEqual(char.char, "Foo")
+
+    @with_transaction()
     def test_search_equals(self):
         "Test search char equals"
         Char = self.Char()
diff -r f95be0d3807d -r e4f619ba9c25 trytond/tests/test_field_date.py
--- a/trytond/tests/test_field_date.py  Sun Jun 16 19:24:15 2019 +0200
+++ b/trytond/tests/test_field_date.py  Wed Jun 26 21:56:16 2019 +0200
@@ -3,6 +3,8 @@
 import datetime
 import unittest
 
+from sql.functions import CurrentDate
+
 from trytond.model.exceptions import RequiredValidationError
 from trytond.pool import Pool
 from trytond.tests.test_tryton import activate_module, with_transaction
@@ -74,6 +76,15 @@
         self.assertEqual(date.date, default_date)
 
     @with_transaction()
+    def test_create_with_sql_value(self):
+        "Test create date with SQL value"
+        Date = Pool().get('test.date')
+
+        date, = Date.create([{'date': CurrentDate()}])
+
+        self.assert_(date.date)
+
+    @with_transaction()
     def test_create_non_date(self):
         "Test create date with non date"
         Date = Pool().get('test.date')
@@ -88,7 +99,7 @@
         "Test create date with integer"
         Date = Pool().get('test.date')
 
-        with self.assertRaises(ValueError):
+        with self.assertRaises(TypeError):
             Date.create([{
                         'date': 42,
                         }])
@@ -413,7 +424,7 @@
                     'date': today,
                     }])
 
-        with self.assertRaises(ValueError):
+        with self.assertRaises(TypeError):
             Date.write([date], {
                     'date': 42,
                     })
diff -r f95be0d3807d -r e4f619ba9c25 trytond/tests/test_field_datetime.py
--- a/trytond/tests/test_field_datetime.py      Sun Jun 16 19:24:15 2019 +0200
+++ b/trytond/tests/test_field_datetime.py      Wed Jun 26 21:56:16 2019 +0200
@@ -3,6 +3,8 @@
 import datetime
 import unittest
 
+from sql.functions import CurrentTimestamp
+
 from trytond.model.exceptions import (
     RequiredValidationError, TimeFormatValidationError)
 from trytond.pool import Pool
@@ -75,6 +77,17 @@
         self.assertEqual(datetime.datetime, default_datetime)
 
     @with_transaction()
+    def test_create_with_sql_value(self):
+        "Test create datetime with SQL value"
+        DateTime = Pool().get('test.datetime')
+
+        datetime, = DateTime.create([{
+                    'datetime': DateTime.datetime.sql_cast(CurrentTimestamp()),
+                    }])
+
+        self.assert_(datetime.datetime)
+
+    @with_transaction()
     def test_create_non_datetime(self):
         "Test create datetime with non datetime"
         DateTime = Pool().get('test.datetime')
@@ -89,7 +102,7 @@
         "Test create datetime with integer"
         DateTime = Pool().get('test.datetime')
 
-        with self.assertRaises(ValueError):
+        with self.assertRaises(TypeError):
             DateTime.create([{
                         'datetime': 42,
                         }])
@@ -99,7 +112,7 @@
         "Test create datetime with date"
         DateTime = Pool().get('test.datetime')
 
-        with self.assertRaises(ValueError):
+        with self.assertRaises(TypeError):
             DateTime.create([{
                         'datetime': datetime.date(2009, 1, 1),
                         }])
@@ -447,7 +460,7 @@
                     'datetime': today,
                     }])
 
-        with self.assertRaises(ValueError):
+        with self.assertRaises(TypeError):
             DateTime.write([datetime], {
                     'datetime': 42,
                     })
@@ -460,7 +473,7 @@
                     'datetime': today,
                     }])
 
-        with self.assertRaises(ValueError):
+        with self.assertRaises(TypeError):
             DateTime.write([datetime_], {
                     'datetime': datetime.date(2009, 1, 1),
                     })
diff -r f95be0d3807d -r e4f619ba9c25 trytond/tests/test_field_float.py
--- a/trytond/tests/test_field_float.py Sun Jun 16 19:24:15 2019 +0200
+++ b/trytond/tests/test_field_float.py Wed Jun 26 21:56:16 2019 +0200
@@ -2,6 +2,8 @@
 # this repository contains the full copyright notices and license terms.
 import unittest
 
+from sql import Literal
+
 from trytond.model.exceptions import (
     RequiredValidationError, DigitsValidationError)
 from trytond.pool import Pool
@@ -59,6 +61,15 @@
         self.assertEqual(float_.float, 5.5)
 
     @with_transaction()
+    def test_create_with_sql_value(self):
+        "Test create float with SQL value"
+        Float = Pool().get('test.float')
+
+        float_, = Float.create([{'float': Literal(5.) / Literal(2.)}])
+
+        self.assertEqual(float_.float, 2.5)
+
+    @with_transaction()
     def test_create_non_float(self):
         "Test create float with non float"
         Float = Pool().get('test.float')
diff -r f95be0d3807d -r e4f619ba9c25 trytond/tests/test_field_integer.py
--- a/trytond/tests/test_field_integer.py       Sun Jun 16 19:24:15 2019 +0200
+++ b/trytond/tests/test_field_integer.py       Wed Jun 26 21:56:16 2019 +0200
@@ -2,6 +2,8 @@
 # this repository contains the full copyright notices and license terms.
 import unittest
 
+from sql import Literal
+
 from trytond.model.exceptions import (
     RequiredValidationError, DomainValidationError)
 from trytond.pool import Pool
@@ -48,6 +50,15 @@
         self.assertEqual(integer.integer, 5)
 
     @with_transaction()
+    def test_create_with_sql_value(self):
+        "Test create integer with SQL value"
+        Integer = Pool().get('test.integer_default')
+
+        integer, = Integer.create([{'integer': Literal(5)}])
+
+        self.assertEqual(integer.integer, 5)
+
+    @with_transaction()
     def test_create_non_integer(self):
         "Test create integer with non integer"
         Integer = Pool().get('test.integer')
diff -r f95be0d3807d -r e4f619ba9c25 trytond/tests/test_field_numeric.py
--- a/trytond/tests/test_field_numeric.py       Sun Jun 16 19:24:15 2019 +0200
+++ b/trytond/tests/test_field_numeric.py       Wed Jun 26 21:56:16 2019 +0200
@@ -3,6 +3,8 @@
 import unittest
 from decimal import Decimal, InvalidOperation
 
+from sql import Literal
+
 from trytond.model.exceptions import (
     RequiredValidationError, DigitsValidationError)
 from trytond.pool import Pool
@@ -60,6 +62,15 @@
         self.assertEqual(numeric.numeric, Decimal('5.5'))
 
     @with_transaction()
+    def test_create_with_sql_value(self):
+        "Test create numeric with SQL value"
+        Numeric = Pool().get('test.numeric')
+
+        numeric, = Numeric.create([{'numeric': Literal(5.) / Literal(2.)}])
+
+        self.assertEqual(numeric.numeric, Decimal('2.5'))
+
+    @with_transaction()
     def test_create_non_numeric(self):
         "Test create numeric with non numeric"
         Numeric = Pool().get('test.numeric')
diff -r f95be0d3807d -r e4f619ba9c25 trytond/tests/test_field_time.py
--- a/trytond/tests/test_field_time.py  Sun Jun 16 19:24:15 2019 +0200
+++ b/trytond/tests/test_field_time.py  Wed Jun 26 21:56:16 2019 +0200
@@ -3,6 +3,8 @@
 import datetime
 import unittest
 
+from sql.functions import CurrentTimestamp
+
 from trytond.model.exceptions import (
     RequiredValidationError, TimeFormatValidationError)
 from trytond.pool import Pool
@@ -75,6 +77,15 @@
         self.assertEqual(time.time, default_time)
 
     @with_transaction()
+    def test_create_with_sql_value(self):
+        "Test create time with SQL value"
+        Time = Pool().get('test.time_precision')
+
+        time, = Time.create([{'time': Time.time.sql_cast(CurrentTimestamp())}])
+
+        self.assert_(time.time)
+
+    @with_transaction()
     def test_create_non_time(self):
         "Test create time with non time"
         Time = Pool().get('test.time')
@@ -99,7 +110,7 @@
         "Test create time with date"
         Time = Pool().get('test.time')
 
-        with self.assertRaises(ValueError):
+        with self.assertRaises(TypeError):
             Time.create([{
                         'time': datetime.date(2009, 1, 1),
                         }])
@@ -460,7 +471,7 @@
                     'time': evening,
                     }])
 
-        with self.assertRaises(ValueError):
+        with self.assertRaises(TypeError):
             Time.write([time], {
                     'time': datetime.date(2009, 1, 1),
                     })
diff -r f95be0d3807d -r e4f619ba9c25 trytond/tests/test_field_timedelta.py
--- a/trytond/tests/test_field_timedelta.py     Sun Jun 16 19:24:15 2019 +0200
+++ b/trytond/tests/test_field_timedelta.py     Wed Jun 26 21:56:16 2019 +0200
@@ -57,7 +57,7 @@
         "Test create timedelta with non timedelta"
         TimeDelta = Pool().get('test.timedelta')
 
-        with self.assertRaises(ValueError):
+        with self.assertRaises(TypeError):
             TimeDelta.create([{
                         'timedelta': 'non timedelta',
                         }])
@@ -67,7 +67,7 @@
         "Test create timedelta with integer"
         TimeDelta = Pool().get('test.timedelta')
 
-        with self.assertRaises(ValueError):
+        with self.assertRaises(TypeError):
             TimeDelta.create([{
                         'timedelta': 42,
                         }])
@@ -369,7 +369,7 @@
                     'timedelta': hour,
                     }])
 
-        with self.assertRaises(ValueError):
+        with self.assertRaises(TypeError):
             TimeDelta.write([timedelta], {
                     'timedelta': 'non timedelta',
                     })
@@ -382,7 +382,7 @@
                     'timedelta': hour,
                     }])
 
-        with self.assertRaises(ValueError):
+        with self.assertRaises(TypeError):
             TimeDelta.write([timedelta], {
                     'timedelta': 42,
                     })

Reply via email to