From 8555aa5b0bba33c7648bb2212264b623a5a6ac3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 19 Jul 2016 07:40:50 +0700 Subject: [PATCH] Allow None in Greater/Less PYSON As all statements are evaluated even if surrounded by 'If', it is not possible to use numeric field with Greater/Less because they can be None. issue5711 review29381004 --- CHANGELOG | 1 + doc/ref/pyson.rst | 4 ++++ trytond/pyson.py | 6 ++++-- trytond/tests/test_pyson.py | 12 ++++++++++++ 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index cbdaf646a5..0b870306dc 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Allow None in Greater/Less PYSON * Add option to set admin password with trytond-admin * Remove super password * Remove database management from RPC diff --git a/doc/ref/pyson.rst b/doc/ref/pyson.rst index 0f3b3a2ca0..6b35d93d2b 100644 --- a/doc/ref/pyson.rst +++ b/doc/ref/pyson.rst @@ -126,6 +126,8 @@ true, then returns also true when both values of statements named by ``statement1`` and ``statement2`` are equal. In this case :class:`Greater` works as a *greater-than or equal* operator. +.. note:: `None` value is replaced by `0` for the comparison. + .. class:: Less(statement1, statement2[, equal]) A :class:`Less` object represents the PYSON ``Less()`` @@ -137,6 +139,8 @@ then returns also true when both values of the statements named by ``statement1`` and ``statement2`` are equal. In this case :class:`Less` works as a *less-than or equal* operator. +.. note:: `None` value is replaced by `0` for the comparison. + .. class:: If(condition, then_statement, else_statement) An :class:`If` object represents the PYSON ``If()`` diff --git a/trytond/pyson.py b/trytond/pyson.py index bc6a13b316..23137c06ca 100644 --- a/trytond/pyson.py +++ b/trytond/pyson.py @@ -313,10 +313,10 @@ class Greater(PYSON): super(Greater, self).__init__() for i in (statement1, statement2): if isinstance(i, PYSON): - assert i.types().issubset(set([int, long, float])), \ + assert i.types().issubset({int, long, float, type(None)}), \ 'statement must be an integer or a float' else: - assert isinstance(i, (int, long, float)), \ + assert isinstance(i, (int, long, float, type(None))), \ 'statement must be an integer or a float' if isinstance(equal, PYSON): assert equal.types() == set([bool]) @@ -344,6 +344,8 @@ class Greater(PYSON): @staticmethod def _convert(dct): for i in ('s1', 's2'): + if dct[i] is None: + dct[i] = 0.0 if not isinstance(dct[i], (int, long, float)): dct = dct.copy() dct[i] = float(dct[i]) diff --git a/trytond/tests/test_pyson.py b/trytond/tests/test_pyson.py index 3426125d2f..8419378552 100644 --- a/trytond/tests/test_pyson.py +++ b/trytond/tests/test_pyson.py @@ -243,6 +243,12 @@ class PYSONTestCase(unittest.TestCase): eval = pyson.PYSONEncoder().encode(pyson.Greater(1, 1, True)) self.assertTrue(pyson.PYSONDecoder().decode(eval)) + eval = pyson.PYSONEncoder().encode(pyson.Greater(None, 1)) + self.assertFalse(pyson.PYSONDecoder().decode(eval)) + + eval = pyson.PYSONEncoder().encode(pyson.Greater(1, None)) + self.assertTrue(pyson.PYSONDecoder().decode(eval)) + self.assertEqual(repr(pyson.Greater(1, 0)), 'Greater(1, 0, False)') def test_Less(self): @@ -278,6 +284,12 @@ class PYSONTestCase(unittest.TestCase): eval = pyson.PYSONEncoder().encode(pyson.Less(1, 1, True)) self.assertTrue(pyson.PYSONDecoder().decode(eval)) + eval = pyson.PYSONEncoder().encode(pyson.Less(None, 1)) + self.assertTrue(pyson.PYSONDecoder().decode(eval)) + + eval = pyson.PYSONEncoder().encode(pyson.Less(1, None)) + self.assertFalse(pyson.PYSONDecoder().decode(eval)) + self.assertEqual(repr(pyson.Less(0, 1)), 'Less(0, 1, False)') def test_If(self):