Changeset 623


Ignore:
Timestamp:
Nov 25, 2015, 7:59:03 AM (4 years ago)
Author:
cito
Message:

Backport decimal_point handling from trunk to 4.x

This fixes some issues with the old implementation and also introduces
the new feature to return money values formatted as string by setting
decimal_point(None), which was not possible before. Everything is still
totally backward compatible as decimal_point('.') is still the default.

Location:
branches/4.x/module
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • branches/4.x/module/TEST_PyGreSQL_classic_connection.py

    r587 r623  
    935935        # for the current lc_monetary setting
    936936        query("set lc_monetary='en_US.UTF-8'")
     937        pg.set_decimal_point(None)
     938        try:
     939            r = query("select '34.25'::money").getresult()[0][0]
     940        finally:
     941            pg.set_decimal_point(point)
     942        self.assertIsInstance(r, str)
     943        self.assertIn(r, (
     944            '$34.25', '$ 34.25', '34.25$', '34.25 $', '34.25 Dollar'))
    937945        pg.set_decimal_point('.')
    938         r = query("select '34.25'::money").getresult()[0][0]
     946        try:
     947            r = query("select '34.25'::money").getresult()[0][0]
     948        finally:
     949            pg.set_decimal_point(point)
    939950        self.assertIsInstance(r, d)
    940951        self.assertEqual(r, d('34.25'))
    941952        pg.set_decimal_point(',')
    942         r = query("select '34.25'::money").getresult()[0][0]
     953        try:
     954            r = query("select '34.25'::money").getresult()[0][0]
     955        finally:
     956            pg.set_decimal_point(point)
    943957        self.assertNotEqual(r, d('34.25'))
    944958        query("set lc_monetary='de_DE.UTF-8'")
     959        pg.set_decimal_point(None)
     960        try:
     961            r = query("select '34,25'::money").getresult()[0][0]
     962        finally:
     963            pg.set_decimal_point(point)
     964        self.assertIsInstance(r, str)
     965        self.assertIn(r, ('34,25€', '34,25 €', '€34,25' '€ 34,25',
     966            '34,25 EUR', '34,25 Euro', '34,25 DM'))
    945967        pg.set_decimal_point(',')
    946         r = query("select '34,25'::money").getresult()[0][0]
     968        try:
     969            r = query("select '34,25'::money").getresult()[0][0]
     970        finally:
     971            pg.set_decimal_point(point)
    947972        self.assertIsInstance(r, d)
    948973        self.assertEqual(r, d('34.25'))
    949         pg.set_decimal_point('.')
     974        try:
     975            pg.set_decimal_point('.')
     976        finally:
     977            pg.set_decimal_point(point)
    950978        r = query("select '34,25'::money").getresult()[0][0]
    951979        self.assertNotEqual(r, d('34.25'))
    952         pg.set_decimal_point(point)
    953980
    954981    def testSetDecimal(self):
     
    959986        self.assertEqual(r, d('3425'))
    960987        pg.set_decimal(long)
    961         r = query("select 3425::numeric").getresult()[0][0]
     988        try:
     989            r = query("select 3425::numeric").getresult()[0][0]
     990        finally:
     991            pg.set_decimal(d)
    962992        self.assertNotIsInstance(r, d)
    963993        self.assertIsInstance(r, long)
    964994        self.assertEqual(r, 3425L)
    965         pg.set_decimal(d)
    966995
    967996    @unittest.skipUnless(namedtuple, 'Named tuples not available')
  • branches/4.x/module/TEST_PyGreSQL_classic_dbwrapper.py

    r552 r623  
    284284    def setUp(self):
    285285        self.db = DB()
    286         self.db.query("set lc_monetary='C'")
    287         self.db.query('set bytea_output=hex')
    288         self.db.query('set standard_conforming_strings=on')
     286        query = self.db.query
     287        query('set client_encoding=utf8')
     288        query('set standard_conforming_strings=on')
     289        query('set bytea_output=hex')
     290        query("set lc_monetary='C'")
    289291
    290292    def tearDown(self):
  • branches/4.x/module/pgmodule.c

    r549 r623  
    120120static PyObject *decimal = NULL, /* decimal type */
    121121                                *namedresult = NULL; /* function for getting named results */
    122 static char *decimal_point = "."; /* decimal point used in money values */
     122static char decimal_point = '.'; /* decimal point used in money values */
    123123
    124124
     
    21712171
    21722172                                        case 5:  /* money */
     2173                                                /* convert to decimal only if decimal point is set */
     2174                                                if (!decimal_point) goto default_case;
    21732175                                                for (k = 0;
    21742176                                                         *s && k < sizeof(cashbuf) / sizeof(cashbuf[0]) - 1;
    21752177                                                         s++)
    21762178                                                {
    2177                                                         if (isdigit(*s))
     2179                                                        if (*s >= '0' && *s <= '9')
    21782180                                                                cashbuf[k++] = *s;
    2179                                                         else if (*s == *decimal_point)
     2181                                                        else if (*s == decimal_point)
    21802182                                                                cashbuf[k++] = '.';
    21812183                                                        else if (*s == '(' || *s == '-')
     
    22012203
    22022204                                        default:
     2205                                        default_case:
    22032206                                                val = PyString_FromString(s);
    22042207                                                break;
     
    22982301
    22992302                                        case 5:  /* money */
     2303                                                /* convert to decimal only if decimal point is set */
     2304                                                if (!decimal_point) goto default_case;
     2305
    23002306                                                for (k = 0;
    23012307                                                         *s && k < sizeof(cashbuf) / sizeof(cashbuf[0]) - 1;
    23022308                                                         s++)
    23032309                                                {
    2304                                                         if (isdigit(*s))
     2310                                                        if (*s >= '0' && *s <= '9')
    23052311                                                                cashbuf[k++] = *s;
    2306                                                         else if (*s == *decimal_point)
     2312                                                        else if (*s == decimal_point)
    23072313                                                                cashbuf[k++] = '.';
    23082314                                                        else if (*s == '(' || *s == '-')
     
    23282334
    23292335                                        default:
     2336                                        default_case:
    23302337                                                val = PyString_FromString(s);
    23312338                                                break;
     
    37023709{
    37033710        PyObject *ret = NULL;
    3704         char *s;
    3705 
    3706         if (PyArg_ParseTuple(args, "s", &s))
    3707         {
    3708                 decimal_point = s;
     3711        char *s = NULL;
     3712
     3713        /* gets arguments */
     3714        if (PyArg_ParseTuple(args, "z", &s)) {
     3715                if (!s)
     3716                        s = "\0";
     3717                else if (*s && (*(s+1) || !strchr(".,;: '*/_`|", *s)))
     3718                        s = NULL;
     3719        }
     3720
     3721        if (s) {
     3722                decimal_point = *s;
    37093723                Py_INCREF(Py_None); ret = Py_None;
    3710         }
     3724        } else {
     3725                PyErr_SetString(PyExc_TypeError,
     3726                        "set_decimal_point() expects a decimal mark character");
     3727        }
     3728
    37113729        return ret;
    37123730}
     
    37203738{
    37213739        PyObject *ret = NULL;
     3740        char s[2];
    37223741
    37233742        if (PyArg_ParseTuple(args, ""))
    37243743        {
    3725                 ret = PyString_FromString(decimal_point);
     3744                if (decimal_point) {
     3745                        s[0] = decimal_point; s[1] = '\0';
     3746                        ret = PyString_FromString(s);
     3747                } else {
     3748                        Py_INCREF(Py_None); ret = Py_None;
     3749                }
    37263750        }
    37273751        else
    37283752        {
    37293753                PyErr_SetString(PyExc_TypeError,
    3730                         " get_decimal_point() takes no parameter");
    3731         }
    3732 
     3754                        "get_decimal_point() takes no parameter");
     3755        }
    37333756
    37343757        return ret;
  • branches/4.x/module/setup.py

    r555 r623  
    8888define_macros = [('PYGRESQL_VERSION', version)]
    8989undef_macros = []
    90 extra_compile_args = ['-O2', '-Wall', '-Werror']
     90extra_compile_args = ['-O2', '-Wall', '-Werror', '-funsigned-char']
    9191
    9292
Note: See TracChangeset for help on using the changeset viewer.