changeset 51719a6696d5 in trytond:default
details: https://hg.tryton.org/trytond?cmd=changeset&node=51719a6696d5
description:
        Prevent assign SQL value to record instances

        issue10413
        review379441002
diffstat:

 trytond/model/fields/field.py          |   5 ++++
 trytond/model/fields/many2one.py       |   5 ++-
 trytond/model/fields/multiselection.py |   9 +------
 trytond/model/fields/reference.py      |   5 +--
 trytond/tests/test_field_binary.py     |  10 +++++++++
 trytond/tests/test_field_boolean.py    |  10 +++++++++
 trytond/tests/test_field_char.py       |  36 +++++++++++++++++++++++++--------
 trytond/tests/test_field_date.py       |  10 +++++++++
 trytond/tests/test_field_datetime.py   |  10 +++++++++
 trytond/tests/test_field_float.py      |  10 +++++++++
 trytond/tests/test_field_integer.py    |  10 +++++++++
 trytond/tests/test_field_numeric.py    |  10 +++++++++
 trytond/tests/test_field_time.py       |  10 +++++++++
 13 files changed, 119 insertions(+), 21 deletions(-)

diffs (319 lines):

diff -r caef4ed4b9ce -r 51719a6696d5 trytond/model/fields/field.py
--- a/trytond/model/fields/field.py     Wed Oct 27 22:22:44 2021 +0200
+++ b/trytond/model/fields/field.py     Thu Oct 28 09:00:33 2021 +0200
@@ -343,8 +343,13 @@
 
     def __set__(self, inst, value):
         assert self.name is not None
+        if isinstance(value, (Query, Expression)):
+            raise ValueError("Can not assign SQL")
         if inst._values is None:
             inst._values = inst._record()
+        if (self._py_type and value is not None
+                and not isinstance(value, self._py_type)):
+            value = self._py_type(value)
         inst._values[self.name] = value
 
     def sql_format(self, value):
diff -r caef4ed4b9ce -r 51719a6696d5 trytond/model/fields/many2one.py
--- a/trytond/model/fields/many2one.py  Wed Oct 27 22:22:44 2021 +0200
+++ b/trytond/model/fields/many2one.py  Thu Oct 28 09:00:33 2021 +0200
@@ -1,6 +1,6 @@
 # This file is part of Tryton.  The COPYRIGHT file at the top level of
 # this repository contains the full copyright notices and license terms.
-from sql import Literal, Column, With
+from sql import Literal, Column, With, Query, Expression
 from sql.aggregate import Max
 from sql.conditionals import Coalesce
 from sql.operators import Or
@@ -19,7 +19,6 @@
     '''
     _type = 'many2one'
     _sql_type = 'INTEGER'
-    _py_type = int
 
     def __init__(self, model_name, string='', left=None, right=None, path=None,
             ondelete='SET NULL', datetime_field=None, target_search='join',
@@ -115,6 +114,8 @@
 
     def sql_format(self, value):
         assert value is not False
+        if value and not isinstance(value, (Query, Expression)):
+            value = int(value)
         return super().sql_format(value)
 
     def convert_domain_path(self, domain, tables):
diff -r caef4ed4b9ce -r 51719a6696d5 trytond/model/fields/multiselection.py
--- a/trytond/model/fields/multiselection.py    Wed Oct 27 22:22:44 2021 +0200
+++ b/trytond/model/fields/multiselection.py    Thu Oct 28 09:00:33 2021 +0200
@@ -18,7 +18,7 @@
     "Define a multi-selection field."
     _type = 'multiselection'
     _sql_type = 'VARCHAR'
-    _py_type = list
+    _py_type = tuple
 
     def __init__(self, selection, string='', sort=True, translate=True,
             help='', help_selection=None, required=False, readonly=False,
@@ -66,15 +66,10 @@
 
     def sql_format(self, value):
         value = super().sql_format(value)
-        if isinstance(value, list):
+        if isinstance(value, (list, tuple)):
             value = dumps(sorted(set(value)))
         return value
 
-    def __set__(self, inst, value):
-        if value:
-            value = tuple(value)
-        super().__set__(inst, value)
-
     def _domain_column(self, operator, column):
         database = Transaction().database
         return database.json_get(super()._domain_column(operator, column))
diff -r caef4ed4b9ce -r 51719a6696d5 trytond/model/fields/reference.py
--- a/trytond/model/fields/reference.py Wed Oct 27 22:22:44 2021 +0200
+++ b/trytond/model/fields/reference.py Thu Oct 28 09:00:33 2021 +0200
@@ -20,7 +20,6 @@
     '''
     _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,
@@ -159,11 +158,11 @@
         super(Reference, self).__set__(inst, value)
 
     def sql_format(self, value):
-        if not isinstance(value, (str, Query, Expression)):
+        if value and not isinstance(value, (str, Query, Expression)):
             try:
                 value = '%s,%s' % tuple(value)
             except TypeError:
-                pass
+                value = str(value)
         return super(Reference, self).sql_format(value)
 
     @with_inactive_records
diff -r caef4ed4b9ce -r 51719a6696d5 trytond/tests/test_field_binary.py
--- a/trytond/tests/test_field_binary.py        Wed Oct 27 22:22:44 2021 +0200
+++ b/trytond/tests/test_field_binary.py        Thu Oct 28 09:00:33 2021 +0200
@@ -124,6 +124,16 @@
         self.assertEqual(binary.binary, cast(b'foo'))
 
     @with_transaction()
+    def test_set_sql_value(self):
+        "Test cannot set SQL value"
+        Binary = Pool().get('test.binary')
+
+        binary = Binary()
+
+        with self.assertRaises(ValueError):
+            binary.binary = Literal('foo')
+
+    @with_transaction()
     def test_read_size(self):
         "Test read binary size"
         Binary = Pool().get('test.binary')
diff -r caef4ed4b9ce -r 51719a6696d5 trytond/tests/test_field_boolean.py
--- a/trytond/tests/test_field_boolean.py       Wed Oct 27 22:22:44 2021 +0200
+++ b/trytond/tests/test_field_boolean.py       Thu Oct 28 09:00:33 2021 +0200
@@ -60,6 +60,16 @@
         self.assertEqual(boolean.boolean, True)
 
     @with_transaction()
+    def test_set_sql_value(self):
+        "Test cannot set SQL value"
+        Boolean = Pool().get('test.boolean')
+
+        boolean = Boolean()
+
+        with self.assertRaises(ValueError):
+            boolean.boolean = Literal(True)
+
+    @with_transaction()
     def test_search_equals_true(self):
         "Test search boolean equals True"
         Boolean = Pool().get('test.boolean')
diff -r caef4ed4b9ce -r 51719a6696d5 trytond/tests/test_field_char.py
--- a/trytond/tests/test_field_char.py  Wed Oct 27 22:22:44 2021 +0200
+++ b/trytond/tests/test_field_char.py  Thu Oct 28 09:00:33 2021 +0200
@@ -42,15 +42,6 @@
         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()
@@ -344,6 +335,25 @@
         return Pool().get('test.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_set_sql_value(self):
+        "Test cannot set SQL value"
+        Char = self.Char()
+
+        char = Char()
+
+        with self.assertRaises(ValueError):
+            char.char = Literal('Foo')
+
+    @with_transaction()
     def test_create_without_default(self):
         "Test create char without default"
         Char = Pool().get('test.char')
@@ -477,6 +487,14 @@
         return Pool().get('test.char_translate')
 
     @with_transaction()
+    def test_create_with_sql_value(self):
+        "Test cannot create with SQL value"
+        Char = self.Char()
+
+        with self.assertRaises(ValueError):
+            Char.create([{'char': Literal('Foo')}])
+
+    @with_transaction()
     def test_translation_default_language_cache(self):
         """Test set translation for default language does not fill 
transactional
         cache with former value"""
diff -r caef4ed4b9ce -r 51719a6696d5 trytond/tests/test_field_date.py
--- a/trytond/tests/test_field_date.py  Wed Oct 27 22:22:44 2021 +0200
+++ b/trytond/tests/test_field_date.py  Thu Oct 28 09:00:33 2021 +0200
@@ -88,6 +88,16 @@
         self.assertTrue(date.date)
 
     @with_transaction()
+    def test_set_sql_value(self):
+        "Test cannot set SQL value"
+        Date = Pool().get('test.date')
+
+        date = Date()
+
+        with self.assertRaises(ValueError):
+            date.date = CurrentDate()
+
+    @with_transaction()
     def test_create_non_date(self):
         "Test create date with non date"
         Date = Pool().get('test.date')
diff -r caef4ed4b9ce -r 51719a6696d5 trytond/tests/test_field_datetime.py
--- a/trytond/tests/test_field_datetime.py      Wed Oct 27 22:22:44 2021 +0200
+++ b/trytond/tests/test_field_datetime.py      Thu Oct 28 09:00:33 2021 +0200
@@ -88,6 +88,16 @@
         self.assertTrue(datetime.datetime)
 
     @with_transaction()
+    def test_set_sql_value(self):
+        "Test cannot set SQL value"
+        DateTime = Pool().get('test.datetime')
+
+        datetime = DateTime()
+
+        with self.assertRaises(ValueError):
+            datetime.datetime = CurrentTimestamp()
+
+    @with_transaction()
     def test_create_non_datetime(self):
         "Test create datetime with non datetime"
         DateTime = Pool().get('test.datetime')
diff -r caef4ed4b9ce -r 51719a6696d5 trytond/tests/test_field_float.py
--- a/trytond/tests/test_field_float.py Wed Oct 27 22:22:44 2021 +0200
+++ b/trytond/tests/test_field_float.py Thu Oct 28 09:00:33 2021 +0200
@@ -70,6 +70,16 @@
         self.assertEqual(float_.float, 2.5)
 
     @with_transaction()
+    def test_set_sql_value(self):
+        "Test cannot set SQL value"
+        Float = Pool().get('test.float')
+
+        float_ = Float()
+
+        with self.assertRaises(ValueError):
+            float_.float = Literal(42)
+
+    @with_transaction()
     def test_create_non_float(self):
         "Test create float with non float"
         Float = Pool().get('test.float')
diff -r caef4ed4b9ce -r 51719a6696d5 trytond/tests/test_field_integer.py
--- a/trytond/tests/test_field_integer.py       Wed Oct 27 22:22:44 2021 +0200
+++ b/trytond/tests/test_field_integer.py       Thu Oct 28 09:00:33 2021 +0200
@@ -59,6 +59,16 @@
         self.assertEqual(integer.integer, 5)
 
     @with_transaction()
+    def test_set_sql_value(self):
+        "Test cannot set SQL value"
+        Integer = Pool().get('test.integer_default')
+
+        integer = Integer()
+
+        with self.assertRaises(ValueError):
+            integer.integer = Literal(42)
+
+    @with_transaction()
     def test_create_non_integer(self):
         "Test create integer with non integer"
         Integer = Pool().get('test.integer')
diff -r caef4ed4b9ce -r 51719a6696d5 trytond/tests/test_field_numeric.py
--- a/trytond/tests/test_field_numeric.py       Wed Oct 27 22:22:44 2021 +0200
+++ b/trytond/tests/test_field_numeric.py       Thu Oct 28 09:00:33 2021 +0200
@@ -71,6 +71,16 @@
         self.assertEqual(numeric.numeric, Decimal('2.5'))
 
     @with_transaction()
+    def test_set_sql_value(self):
+        "Test cannot set SQL value"
+        Numeric = Pool().get('test.numeric')
+
+        numeric = Numeric()
+
+        with self.assertRaises(ValueError):
+            numeric.numeric = Literal(42)
+
+    @with_transaction()
     def test_create_non_numeric(self):
         "Test create numeric with non numeric"
         Numeric = Pool().get('test.numeric')
diff -r caef4ed4b9ce -r 51719a6696d5 trytond/tests/test_field_time.py
--- a/trytond/tests/test_field_time.py  Wed Oct 27 22:22:44 2021 +0200
+++ b/trytond/tests/test_field_time.py  Thu Oct 28 09:00:33 2021 +0200
@@ -86,6 +86,16 @@
         self.assertTrue(time.time)
 
     @with_transaction()
+    def test_set_sql_value(self):
+        "Test cannot set SQL value"
+        Time = Pool().get('test.time')
+
+        time = Time()
+
+        with self.assertRaises(ValueError):
+            time.time = Time.time.sql_cast(CurrentTimestamp())
+
+    @with_transaction()
     def test_create_non_time(self):
         "Test create time with non time"
         Time = Pool().get('test.time')

Reply via email to