From 8b3342140336d4e81868390052087f3993457de3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 22 Dec 2011 22:17:08 +0100 Subject: [PATCH] Use XML-RPC struct for Decimal and Date review191006 --- CHANGELOG | 1 + trytond/backend/fields.py | 2 - trytond/backend/postgresql/database.py | 2 - trytond/protocols/datatype.py | 176 ----------- trytond/protocols/xmlrpc.py | 40 ++- trytond/tests/test_fields.py | 15 - trytond/tests/test_protocols_datatype.py | 384 ----------------------- trytond/tests/test_tryton.py | 2 - 8 files changed, 29 insertions(+), 593 deletions(-) delete mode 100644 trytond/protocols/datatype.py delete mode 100644 trytond/tests/test_protocols_datatype.py diff --git a/CHANGELOG b/CHANGELOG index 48d2e4a2c4..80e4e42470 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Use XML-RPC struct for Decimal and Date * Remove change_default on fields Version 2.2.0 - 2011-10-24 diff --git a/trytond/backend/fields.py b/trytond/backend/fields.py index 0919c26ef1..24cd28d48b 100644 --- a/trytond/backend/fields.py +++ b/trytond/backend/fields.py @@ -81,8 +81,6 @@ class Numeric(Float): value = Decimal('0.0') if isinstance(value, (int, long)): value = Decimal(str(value)) - if isinstance(value, float) and hasattr(value, 'decimal'): - value = value.decimal assert isinstance(value, Decimal) return value diff --git a/trytond/backend/postgresql/database.py b/trytond/backend/postgresql/database.py index 3950a84bb6..b0064926ff 100644 --- a/trytond/backend/postgresql/database.py +++ b/trytond/backend/postgresql/database.py @@ -22,7 +22,6 @@ import os if os.name == 'posix': import pwd from decimal import Decimal -from trytond.protocols.datatype import Float RE_FROM = re.compile('.* from "?([a-zA-Z_0-9]+)"?.*$') RE_INTO = re.compile('.* into "?([a-zA-Z_0-9]+)"?.*$') @@ -435,5 +434,4 @@ if PYTIME: register_type(PYTIME) register_adapter(Session, AsIs) register_adapter(float, lambda value: AsIs(repr(value))) -register_adapter(Float, lambda value: AsIs(repr(value))) register_adapter(Decimal, lambda value: AsIs(str(value))) diff --git a/trytond/protocols/datatype.py b/trytond/protocols/datatype.py deleted file mode 100644 index 85d68481bd..0000000000 --- a/trytond/protocols/datatype.py +++ /dev/null @@ -1,176 +0,0 @@ -#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 decimal -from decimal import Decimal - -_convert_other = decimal._convert_other - -def _convert_Float(other, *args, **kwargs): - if isinstance(other, Float): - return other.decimal - return _convert_other(other, *args, **kwargs) -decimal._convert_other = _convert_Float - - -class Float(float): - def __init__(self, value): - super(Float, self).__init__() - self.__decimal = Decimal(value) - - @property - def decimal(self): - return self.__decimal - - def __repr__(self): - return str(self.decimal) - - def __str__(self): - return str(self.decimal) - - def __abs__(self, round=True, context=None): - return Float(str(abs(self.decimal))) - - def __add__(self, other, context=None): - if isinstance(other, Decimal): - return self.decimal.__add__(other, context=context) - return super(Float, self).__add__(other) - - def __radd__(self, other, context=None): - if isinstance(other, Decimal): - return self.decimal.__radd__(other, context=context) - return super(Float, self).__radd__(other) - - def __div__(self, other, context=None): - if isinstance(other, Decimal): - return self.decimal.__div__(other, context=context) - return super(Float, self).__div__(other) - - def __rdiv__(self, other, context=None): - if isinstance(other, Decimal): - return self.decimal.__rdiv__(other, context=context) - return super(Float, self).__rdiv__(other) - - def __divmod__(self, other, context=None): - if isinstance(other, Decimal): - return self.decimal.__divmod__(other, context=context) - return super(Float, self).__divmod__(other) - - def __rdivmod__(self, other, context=None): - if isinstance(other, Decimal): - return self.decimal.__rdivmod__(other, context=context) - return super(Float, self).__rdivmod__(other) - - def __eq__(self, other): - if isinstance(other, Decimal): - return self.decimal.__eq__(other) - return super(Float, self).__eq__(other) - - def __hash__(self): - return super(Float, self).__hash__() - - def __floordiv__(self, other, context=None): - if isinstance(other, Decimal): - return self.decimal.__floordiv__(other, context=context) - return super(Float, self).__floordiv__(other) - - def __rfloordiv__(self, other, context=None): - if isinstance(other, Decimal): - return self.decimal.__rfloordiv__(other, context=context) - return super(Float, self).__rfloordiv__(other) - - def __format__(self, specifier, context=None): - return self.decimal.__format__(specifier, context=context) - - def __ge__(self, other, context=None): - if isinstance(other, Decimal): - if hasattr(self.decimal, '__ge__'): - return self.decimal.__ge__(other, context=context) - # For Python < 2.6 - return self.decimal >= other - return super(Float, self).__ge__(other) - - def __gt__(self, other, context=None): - if isinstance(other, Decimal): - if hasattr(self.decimal, '__gt__'): - return self.decimal.__gt__(other, context=context) - # For Python < 2.6 - return self.decimal > other - return super(Float, self).__gt__(other) - - def __le__(self, other, context=None): - if isinstance(other, Decimal): - if hasattr(self.decimal, '__le__'): - return self.decimal.__le__(other, context=context) - # For Python < 2.6 - return self.decimal <= other - return super(Float, self).__le__(other) - - def __lt__(self, other, context=None): - if isinstance(other, Decimal): - if hasattr(self.decimal, '__lt__'): - return self.decimal.__lt__(other, context=context) - # For Python < 2.6 - return self.decimal < other - return super(Float, self).__lt__(other) - - def __mod__(self, other, context=None): - if isinstance(other, Decimal): - return self.decimal.__mod__(other, context=context) - return super(Float, self).__mod__(other) - - def __rmod__(self, other, context=None): - if isinstance(other, Decimal): - return self.decimal.__rmod__(other, context=context) - return super(Float, self).__rmod__(other) - - def __mul__(self, other, context=None): - if isinstance(other, Decimal): - return self.decimal.__mul__(other, context=context) - return super(Float, self).__mul__(other) - - def __rmul__(self, other, context=None): - if isinstance(other, Decimal): - return self.decimal.__rmul__(other, context=context) - return super(Float, self).__rmul__(other) - - def __ne__(self, other): - if isinstance(other, Decimal): - return self.decimal.__ne__(other) - return super(Float, self).__ne__(other) - - def __neg__(self, context=None): - return Float(str(-self.decimal)) - - def __nonzero__(self): - return self.decimal.__nonzero__() - - def __pos__(self): - return Float(str(self.decimal)) - - def __pow__(self, other, modulo=None, context=None): - if isinstance(other, Decimal): - return self.decimal.__pow__(other, modulo, context) - return super(Float, self).__pow__(other, modulo) - - def __rpow__(self, other, context=None): - if isinstance(other, Decimal): - return self.decimal.__rpow__(other, context=context) - return super(Float, self).__rpow__(other) - - def __sub__(self, other, context=None): - if isinstance(other, Decimal): - return self.decimal.__sub__(other, context=context) - return super(Float, self).__sub__(other) - - def __rsub__(self, other, context=None): - if isinstance(other, Decimal): - return self.decimal.__rsub__(other, context=context) - return super(Float, self).__rsub__(other) - - def __truediv__(self, other, context=None): - if isinstance(other, Decimal): - return self.decimal.__truediv__(other, context=context) - return super(Float, self).__truediv__(other) - - def __getattr__(self, name): - return getattr(self.decimal, name) diff --git a/trytond/protocols/xmlrpc.py b/trytond/protocols/xmlrpc.py index a9cc2a44d9..f3e913ce70 100644 --- a/trytond/protocols/xmlrpc.py +++ b/trytond/protocols/xmlrpc.py @@ -3,7 +3,6 @@ from trytond.protocols.sslsocket import SSLSocket from trytond.protocols.dispatcher import dispatch from trytond.config import CONFIG -from trytond.protocols.datatype import Float from trytond.protocols.common import daemon, GZipRequestHandlerMixin from trytond.exceptions import UserError, UserWarning, NotLogged, \ ConcurrencyException @@ -22,9 +21,10 @@ from types import DictType from decimal import Decimal def dump_decimal(self, value, write): - write("") - write(str(value)) - write("\n") + value = {'__class__': 'Decimal', + 'decimal': str(value), + } + self.dump_struct(value, write) def dump_buffer(self, value, write): self.write = write @@ -32,13 +32,18 @@ def dump_buffer(self, value, write): value.encode(self) del self.write +def dump_date(self, value, write): + value = {'__class__': 'date', + 'year': value.year, + 'month': value.month, + 'day': value.day, + } + self.dump_struct(value, write) + xmlrpclib.Marshaller.dispatch[Decimal] = dump_decimal -xmlrpclib.Marshaller.dispatch[Float] = dump_decimal xmlrpclib.Marshaller.dispatch[type(None)] = \ lambda self, value, write: self.dump_bool(bool(value), write) -xmlrpclib.Marshaller.dispatch[datetime.date] = \ - lambda self, value, write: self.dump_datetime( - datetime.datetime.combine(value, datetime.time()), write) +xmlrpclib.Marshaller.dispatch[datetime.date] = dump_date xmlrpclib.Marshaller.dispatch[buffer] = dump_buffer def dump_struct(self, value, write, escape=xmlrpclib.escape): @@ -53,11 +58,22 @@ def dump_struct(self, value, write, escape=xmlrpclib.escape): xmlrpclib.Marshaller.dispatch[DictType] = dump_struct - -def _end_double(self, data): - self.append(Float(data)) +def end_struct(self, data): + mark = self._marks.pop() + # map structs to Python dictionaries + dct = {} + items = self._stack[mark:] + for i in range(0, len(items), 2): + dct[xmlrpclib._stringify(items[i])] = items[i+1] + if '__class__' in dct: + if dct['__class__'] == 'date': + dct = datetime.date(dct['year'], dct['month'], dct['day']) + elif dct['__class__'] == 'Decimal': + dct = Decimal(dct['decimal']) + self._stack[mark:] = [dct] self._value = 0 -xmlrpclib.Unmarshaller.dispatch["double"] = _end_double + +xmlrpclib.Unmarshaller.dispatch['struct'] = end_struct def _end_dateTime(self, data): value = xmlrpclib.DateTime() value.decode(data) diff --git a/trytond/tests/test_fields.py b/trytond/tests/test_fields.py index e618f78411..cf1705e39e 100644 --- a/trytond/tests/test_fields.py +++ b/trytond/tests/test_fields.py @@ -8,7 +8,6 @@ from decimal import Decimal from trytond.tests.test_tryton import POOL, DB_NAME, USER, CONTEXT, \ install_module from trytond.transaction import Transaction -from trytond.protocols.datatype import Float class FieldsTestCase(unittest.TestCase): @@ -554,13 +553,6 @@ class FieldsTestCase(unittest.TestCase): float7 = self.float.read(float7_id, ['float']) self.assert_(float7['float'] == 0.123456789012345) - float8_id = self.float.create({ - 'float': Float('1.1'), - }) - - float8 = self.float.read(float8_id, ['float']) - self.assertEqual(float8['float'], 1.1) - transaction.cursor.rollback() def test0040numeric(self): @@ -782,13 +774,6 @@ class FieldsTestCase(unittest.TestCase): self.assert_(numeric7['numeric'] == Decimal('0.1234567890123456789')) - numeric8_id = self.numeric.create({ - 'numeric': Float('1.1'), - }) - - numeric8 = self.numeric.read(numeric8_id, ['numeric']) - self.assertEqual(numeric8['numeric'], Decimal('1.1')) - transaction.cursor.rollback() def test0050char(self): diff --git a/trytond/tests/test_protocols_datatype.py b/trytond/tests/test_protocols_datatype.py deleted file mode 100644 index ff5552155b..0000000000 --- a/trytond/tests/test_protocols_datatype.py +++ /dev/null @@ -1,384 +0,0 @@ -#!/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 sys, os -DIR = os.path.abspath(os.path.normpath(os.path.join(__file__, - '..', '..', '..', 'trytond'))) -if os.path.isdir(DIR): - sys.path.insert(0, os.path.dirname(DIR)) - -import unittest -from decimal import Decimal -from trytond.protocols.datatype import Float - -class ProtocolsDatatypeFloatTestCase(unittest.TestCase): - ''' - Test Float. - ''' - def test_abs(self): - ''' - Test absolute Float - ''' - self.assertEqual(abs(Float('-1.0')), Float('1.0')) - self.assert_(isinstance(abs(Float('-1.0')), Float)) - - def test_Float_add_Decimal(self): - ''' - Test addition between Float and Decimal - ''' - self.assertEqual(Float('1.0') + Decimal('1.0'), Decimal('2.0')) - - def test_Float_add_float(self): - ''' - Test addition between Float and float - ''' - self.assertEqual(Float('1.0') + 1.0, 2.0) - - def test_Decimal_radd__Float(self): - ''' - Test right addition between Float and Decimal - ''' - self.assertEqual(Decimal('1.0') + Float('1.0'), Decimal('2.0')) - - def test_float_radd__Float(self): - ''' - Test right addition between Float and float - ''' - self.assertEqual(1.0 + Float('1.0'), 2.0) - - def test_Float_div_Decimal(self): - ''' - Test division between Float and Decimal - ''' - self.assertEqual(Float('1.0') / Decimal('1.0'), Decimal('1.0')) - - def test_Float_div_float(self): - ''' - Test division between Float and float - ''' - self.assertEqual(Float('1.0') / 1.0, 1.0) - - def test_Decimal_rdiv_Float(self): - ''' - Test right division between Float and Decimal - ''' - self.assertEqual(Decimal('1.0') / Float('1.0'), Decimal('1.0')) - - def test_float_rdiv_Float(self): - ''' - Test right division between Float and float - ''' - self.assertEqual(1.0 / Float('1.0'), 1.0) - - def test_Float_divmod_Decimal(self): - ''' - Test divmod between Float and Decimal - ''' - self.assertEqual(divmod(Float('2.1'), Decimal('20.5')), - divmod(Decimal('2.1'), Decimal('20.5'))) - - def test_Float_divmod_float(self): - ''' - Test divmod between Float and float - ''' - self.assertEqual(divmod(Float('2.1'), 20.5), divmod(2.1, 20.5)) - - def test_Decimal_rdivmod_float(self): - ''' - Test right divmod between Float and Decimal - ''' - self.assertEqual(divmod(Decimal('2.1'), Float('20.5')), - divmod(Decimal('2.1'), Decimal('20.5'))) - - def test_float_rdivmod_Float(self): - ''' - Test right divmod between Float and float - ''' - self.assertEqual(divmod(2.1, Float('20.5')), divmod(2.1, 20.5)) - - def test_Float_eq_Decimal(self): - ''' - Test equal between Float and Decimal - ''' - self.assert_(Float('1.1') == Decimal('1.1')) - self.assertFalse(Float('1.1') == Decimal('1.0')) - - def test_Float_eq_float(self): - ''' - Test equal between Float and float - ''' - self.assert_(Float('1.1') == 1.1) - self.assertFalse(Float('1.1') == 1.0) - - def test_Decimal_eq_Float(self): - ''' - Test equal between Decimal and Float - ''' - self.assert_(Decimal('1.1') == Float('1.1')) - self.assertFalse(Decimal('1.1') == Float('1.0')) - - def test_float_eq_Float(self): - ''' - Test equal between float and Decimal - ''' - self.assert_(1.1 == Float('1.1')) - self.assertFalse(1.1 == Float('1.0')) - - def test_Float_floordiv_Decimal(self): - ''' - Test floordiv between Float and Decimal - ''' - self.assertEqual(Float('2.5') // Decimal('2.1'), Decimal('1')) - - def test_Float_floordiv_float(self): - ''' - Test floordiv between Float and float - ''' - self.assertEqual(Float('2.5') // 2.1, 1.0) - - def test_Decimal_rfloordiv_Float(self): - ''' - Test rfloordiv between Decimal and Float - ''' - self.assertEqual(Decimal('2.5') // Float('2.1'), Decimal('1')) - - def test_float_rfloordiv_Float(self): - ''' - Test rfloordiv between float and Float - ''' - self.assertEqual(2.5 // Float('2.1'), 1.0) - - def test_Float_format(self): - ''' - Test format Float - ''' - # For Python < 2.6 - if hasattr(__builtins__, 'format'): - self.assertEqual(format(Float('1.1'), '.32f'), - '1.10000000000000000000000000000000') - - def test_Float_ge_Decimal(self): - ''' - Test ge between Float and Decimal - ''' - self.assert_(Float('1.5') >= Decimal('1.1')) - self.assertFalse(Float('1.1') >= Decimal('1.5')) - - def test_Float_ge_float(self): - ''' - Test ge between Float and float - ''' - self.assert_(Float('1.5') >= 1.1) - self.assertFalse(Float('1.1') >= 1.5) - - def test_Float_gt_Decimal(self): - ''' - Test gt between Float and Decimal - ''' - self.assert_(Float('1.5') > Decimal('1.1')) - self.assertFalse(Float('1.1') > Decimal('1.5')) - - def test_Float_gt_float(self): - ''' - Test gt between Float and float - ''' - self.assert_(Float('1.5') > 1.1) - self.assertFalse(Float('1.1') > 1.5) - - def test_Float_le_Decimal(self): - ''' - Test le between Float and Decimal - ''' - self.assert_(Float('1.1') <= Decimal('1.5')) - self.assertFalse(Float('1.5') <= Decimal('1.1')) - - def test_Float_le_float(self): - ''' - Test le between Float and float - ''' - self.assert_(Float('1.1') <= 1.5) - self.assertFalse(Float('1.5') <= 1.1) - - def test_Float_lt_Decimal(self): - ''' - Test lt between Float and Decimal - ''' - self.assert_(Float('1.1') < Decimal('1.5')) - self.assertFalse(Float('1.5') < Decimal('1.1')) - - def test_Float_lt_float(self): - ''' - Test lt between Float and float - ''' - self.assert_(Float('1.1') < 1.5) - self.assertFalse(Float('1.5') < 1.1) - - def test_Float_mod_Decimal(self): - ''' - Test modulo between Float and Decimal - ''' - self.assertEqual(Float('2.1') % Decimal('20.5'), - Decimal('2.1') % Decimal('20.5')) - - def test_Float_mod_float(self): - ''' - Test modulo between Float and float - ''' - self.assertEqual(Float('2.1') % 20.5, 2.1 % 20.5) - - def test_Decimal_rmod_Float(self): - ''' - Test right modulo between Decimal and Float - ''' - self.assertEqual(Decimal('2.1') % Float('20.5'), - Decimal('2.1') % Decimal('20.5')) - - def test_float_rmod_Float(self): - ''' - Test right modulo between float and Float - ''' - self.assertEqual(2.1 % Float('20.5'), 2.1 % 20.5) - - def test_Float_mul_Decimal(self): - ''' - Test multiplication between Float and Decimal - ''' - self.assertEqual(Float('1.5') * Decimal('1.2'), Decimal('1.8')) - - def test_Float_mul_float(self): - ''' - Test multiplication between Float and float - ''' - self.assertEqual(Float('1.5') * 1.2, 1.5 * 1.2) - - def test_Decimal_rmul_Float(self): - ''' - Test right multiplication between Decimal and Float - ''' - self.assertEqual(Decimal('1.5') * Float('1.2'), Decimal('1.8')) - - def test_float_rmul_Float(self): - ''' - Test right multiplication between float and Float - ''' - self.assertEqual(1.5 * Float('1.2'), 1.5 * 1.2) - - def test_Float_ne_Decimal(self): - ''' - Test not equal between Float and Decimal - ''' - self.assert_(Float('1.1') != Decimal('1.2')) - self.assertFalse(Float('1.1') != Decimal('1.1')) - - def test_Float_ne_float(self): - ''' - Test not equal between Float and float - ''' - self.assert_(Float('1.1') != 1.2) - self.assertFalse(Float('1.1') != 1.1) - - def test_Decimal_ne_Float(self): - ''' - Test not equal between Decimal and Float - ''' - self.assert_(Decimal('1.1') != Float('1.2')) - self.assertFalse(Decimal('1.1') != Float('1.1')) - - def test_float_ne_Float(self): - ''' - Test not equal between float and Decimal - ''' - self.assert_(1.1 != Float('1.2')) - self.assertFalse(1.1 != Float('1.1')) - - def test_neg(self): - ''' - Test negative Float - ''' - self.assertEqual(-Float('1.0'), Float('-1.0')) - self.assert_(isinstance(-Float('1.0'), Float)) - - def test_nonzero(self): - ''' - Test non zero Float - ''' - self.assert_(Float('1.0') != 0) - self.assertFalse(Float('0.0') != 0) - - def test_pos(self): - ''' - Test positive Float - ''' - self.assertEqual(+Float('1.0'), Float('1.0')) - self.assert_(isinstance(+Float('1.0'), Float)) - - def test_Float_pow_Decimal(self): - ''' - Test pow between Float and Decimal - ''' - self.assertEqual(Float('2.5') ** Decimal('2.0'), Decimal('6.25')) - - def test_Float_pow_float(self): - ''' - Test pow between Float and float - ''' - self.assertEqual(Float('2.5') ** 2.0, 6.25) - - def test_Decimal_rpow_float(self): - ''' - Test right pow between Decimal and Float - ''' - self.assertEqual(Decimal('2.5') ** Float('2.0'), Decimal('6.25')) - - def test_float_rpow_Float(self): - ''' - Test right pow between Float and float - ''' - self.assert_(2.5 ** Float('2.0'), 6.25) - - def test_Float_sub_Decimal(self): - ''' - Test substration between Float and Decimal - ''' - self.assertEqual(Float('2.5') - Decimal('1.2'), Decimal('1.3')) - - def test_Float_sub_float(self): - ''' - Test substraction between Float and float - ''' - self.assertEqual(Float('2.5') - 1.2, 1.3) - - def test_Decimal_rsub_Float(self): - ''' - Test right substraction between Decimal and Float - ''' - self.assertEqual(Decimal('2.5') - Float('1.2'), Decimal('1.3')) - - def test_float_rsub_Float(self): - ''' - Test right substraction between float and Float - ''' - self.assertEqual(2.5 - Float('1.2'), 1.3) - - def test_Decimal_only_Method(self): - ''' - Test Decimal only method - ''' - self.assertEqual(Float('1.5').quantize(Decimal('1')), Decimal('2')) - - def test_float_only_Method(self): - ''' - Test float only method - ''' - # For Python < 2.6 - if hasattr(float, 'hex'): - self.assertEqual(Float('1.5').hex(), '0x1.8000000000000p+0') - -def suite(): - return unittest.TestLoader().loadTestsFromTestCase(ProtocolsDatatypeFloatTestCase) - -if __name__ == '__main__': - suite = suite() - unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/trytond/tests/test_tryton.py b/trytond/tests/test_tryton.py index 55d3c7db81..30d924fc54 100644 --- a/trytond/tests/test_tryton.py +++ b/trytond/tests/test_tryton.py @@ -251,8 +251,6 @@ def all_suite(): suite_.addTests(test_exportdata.suite()) import trytond.tests.test_trigger as test_trigger suite_.addTests(test_trigger.suite()) - import trytond.tests.test_protocols_datatype as test_protocols_datatype - suite_.addTests(test_protocols_datatype.suite()) import trytond.tests.test_sequence as test_sequence suite_.addTests(test_sequence.suite()) import trytond.tests.test_access as test_access