From 2542224ce564a31ec81c3d512c61dfdb93fd9635 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sat, 18 Aug 2018 17:19:33 +0200 Subject: [PATCH] Add pyson TimeDelta issue7351 review47651002 --- CHANGELOG | 1 + trytond/pyson.py | 40 ++++++++++++++++++++++++++++++++++++- trytond/tests/test_pyson.py | 31 ++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 204d0e2b09..a74c1392a2 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Add pyson TimeDelta * Remove button if it is not allowed to access some of its dependant fields * Add support for Python 3.7 * Add transactional queue and workers diff --git a/trytond/pyson.py b/trytond/pyson.py index ac83bc2a71..821349fe9d 100644 --- a/trytond/pyson.py +++ b/trytond/pyson.py @@ -628,6 +628,44 @@ class DateTime(Date): ) +class TimeDelta(PYSON): + + def __init__(self, days=0, seconds=0, microseconds=0): + for i in [days, seconds, microseconds]: + if isinstance(i, PYSON): + assert i.types().issubset({int, float}), \ + '%s must be an integer' % (i,) + else: + assert isinstance(i, (int, float)), \ + '%s must be an integer' % (i,) + self._days = days + self._seconds = seconds + self._microseconds = microseconds + + @property + def __repr_params__(self): + return self._days, self._seconds, self._microseconds + + def pyson(self): + return { + '__class__': 'TimeDelta', + 'd': self._days, + 's': self._seconds, + 'm': self._microseconds, + } + + def types(self): + return {datetime.timedelta} + + @staticmethod + def eval(dct, context): + return datetime.timedelta( + days=dct['d'], + seconds=dct['s'], + microseconds=dct['m'], + ) + + class Len(PYSON): def __init__(self, v): @@ -679,7 +717,6 @@ class Id(PYSON): return {int} - CONTEXT = { 'Eval': Eval, 'Not': Not, @@ -694,6 +731,7 @@ CONTEXT = { 'In': In, 'Date': Date, 'DateTime': DateTime, + 'TimeDelta': TimeDelta, 'Len': Len, 'Id': Id, } diff --git a/trytond/tests/test_pyson.py b/trytond/tests/test_pyson.py index 7a8775d306..9b04febb64 100644 --- a/trytond/tests/test_pyson.py +++ b/trytond/tests/test_pyson.py @@ -567,6 +567,37 @@ class PYSONTestCase(unittest.TestCase): self.assertEqual(repr(pyson.Len([1, 2, 3])), 'Len([1, 2, 3])') + def test_TimeDelta_pyson(self): + "Test pyson.TimeDelta.pyson" + self.assertEqual(pyson.TimeDelta(1, 2, 3).pyson(), { + '__class__': 'TimeDelta', + 'd': 1, + 's': 2, + 'm': 3, + }) + + def test_TimeDelta_types(self): + "Test pyson.TimeDelta.types" + self.assertEqual( + pyson.TimeDelta(seconds=10).types(), {datetime.timedelta}) + + def test_TimeDelta_invalid_type(self): + "Test pyson.TimeDelta invalid type" + with self.assertRaises(AssertionError): + pyson.TimeDelta('foo') + + def test_TimeDelta_eval(self): + "Test pyson.TimeDelta.eval" + eval = pyson.PYSONEncoder().encode(pyson.TimeDelta(1, 2, 3)) + + self.assertEqual( + pyson.PYSONDecoder().decode(eval), datetime.timedelta(1, 2, 3)) + + def test_TimeDelta_repr(self): + "Test pyson.TimeDelta.repr" + self.assertEqual( + repr(pyson.TimeDelta(1, 2, 3)), 'TimeDelta(1, 2, 3)') + def test_Composite(self): 'Test Composite' expr = pyson.If(pyson.Not(