Author: cito
Date: Wed Nov 25 07:59:03 2015
New Revision: 623
Log:
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.
Modified:
branches/4.x/module/TEST_PyGreSQL_classic_connection.py
branches/4.x/module/TEST_PyGreSQL_classic_dbwrapper.py
branches/4.x/module/pgmodule.c
branches/4.x/module/setup.py
Modified: branches/4.x/module/TEST_PyGreSQL_classic_connection.py
==============================================================================
--- branches/4.x/module/TEST_PyGreSQL_classic_connection.py Wed Nov 25
07:25:24 2015 (r622)
+++ branches/4.x/module/TEST_PyGreSQL_classic_connection.py Wed Nov 25
07:59:03 2015 (r623)
@@ -934,22 +934,49 @@
# if and only if the decimal point is set appropriately
# for the current lc_monetary setting
query("set lc_monetary='en_US.UTF-8'")
+ pg.set_decimal_point(None)
+ try:
+ r = query("select '34.25'::money").getresult()[0][0]
+ finally:
+ pg.set_decimal_point(point)
+ self.assertIsInstance(r, str)
+ self.assertIn(r, (
+ '$34.25', '$ 34.25', '34.25$', '34.25 $', '34.25 Dollar'))
pg.set_decimal_point('.')
- r = query("select '34.25'::money").getresult()[0][0]
+ try:
+ r = query("select '34.25'::money").getresult()[0][0]
+ finally:
+ pg.set_decimal_point(point)
self.assertIsInstance(r, d)
self.assertEqual(r, d('34.25'))
pg.set_decimal_point(',')
- r = query("select '34.25'::money").getresult()[0][0]
+ try:
+ r = query("select '34.25'::money").getresult()[0][0]
+ finally:
+ pg.set_decimal_point(point)
self.assertNotEqual(r, d('34.25'))
query("set lc_monetary='de_DE.UTF-8'")
+ pg.set_decimal_point(None)
+ try:
+ r = query("select '34,25'::money").getresult()[0][0]
+ finally:
+ pg.set_decimal_point(point)
+ self.assertIsInstance(r, str)
+ self.assertIn(r, ('34,25€', '34,25 €', '€34,25' '€ 34,25',
+ '34,25 EUR', '34,25 Euro', '34,25 DM'))
pg.set_decimal_point(',')
- r = query("select '34,25'::money").getresult()[0][0]
+ try:
+ r = query("select '34,25'::money").getresult()[0][0]
+ finally:
+ pg.set_decimal_point(point)
self.assertIsInstance(r, d)
self.assertEqual(r, d('34.25'))
- pg.set_decimal_point('.')
+ try:
+ pg.set_decimal_point('.')
+ finally:
+ pg.set_decimal_point(point)
r = query("select '34,25'::money").getresult()[0][0]
self.assertNotEqual(r, d('34.25'))
- pg.set_decimal_point(point)
def testSetDecimal(self):
d = pg.Decimal
@@ -958,11 +985,13 @@
self.assertIsInstance(r, d)
self.assertEqual(r, d('3425'))
pg.set_decimal(long)
- r = query("select 3425::numeric").getresult()[0][0]
+ try:
+ r = query("select 3425::numeric").getresult()[0][0]
+ finally:
+ pg.set_decimal(d)
self.assertNotIsInstance(r, d)
self.assertIsInstance(r, long)
self.assertEqual(r, 3425L)
- pg.set_decimal(d)
@unittest.skipUnless(namedtuple, 'Named tuples not available')
def testSetNamedresult(self):
Modified: branches/4.x/module/TEST_PyGreSQL_classic_dbwrapper.py
==============================================================================
--- branches/4.x/module/TEST_PyGreSQL_classic_dbwrapper.py Wed Nov 25
07:25:24 2015 (r622)
+++ branches/4.x/module/TEST_PyGreSQL_classic_dbwrapper.py Wed Nov 25
07:59:03 2015 (r623)
@@ -283,9 +283,11 @@
def setUp(self):
self.db = DB()
- self.db.query("set lc_monetary='C'")
- self.db.query('set bytea_output=hex')
- self.db.query('set standard_conforming_strings=on')
+ query = self.db.query
+ query('set client_encoding=utf8')
+ query('set standard_conforming_strings=on')
+ query('set bytea_output=hex')
+ query("set lc_monetary='C'")
def tearDown(self):
self.db.close()
Modified: branches/4.x/module/pgmodule.c
==============================================================================
--- branches/4.x/module/pgmodule.c Wed Nov 25 07:25:24 2015 (r622)
+++ branches/4.x/module/pgmodule.c Wed Nov 25 07:59:03 2015 (r623)
@@ -119,7 +119,7 @@
static PyObject *decimal = NULL, /* decimal type */
*namedresult = NULL; /* function for getting
named results */
-static char *decimal_point = "."; /* decimal point used in money values */
+static char decimal_point = '.'; /* decimal point used in money values */
/* --------------------------------------------------------------------- */
@@ -2170,13 +2170,15 @@
break;
case 5: /* money */
+ /* convert to decimal only if
decimal point is set */
+ if (!decimal_point) goto
default_case;
for (k = 0;
*s && k <
sizeof(cashbuf) / sizeof(cashbuf[0]) - 1;
s++)
{
- if (isdigit(*s))
+ if (*s >= '0' && *s <=
'9')
cashbuf[k++] =
*s;
- else if (*s ==
*decimal_point)
+ else if (*s ==
decimal_point)
cashbuf[k++] =
'.';
else if (*s == '(' ||
*s == '-')
cashbuf[k++] =
'-';
@@ -2200,6 +2202,7 @@
break;
default:
+ default_case:
val = PyString_FromString(s);
break;
}
@@ -2297,13 +2300,16 @@
break;
case 5: /* money */
+ /* convert to decimal only if
decimal point is set */
+ if (!decimal_point) goto
default_case;
+
for (k = 0;
*s && k <
sizeof(cashbuf) / sizeof(cashbuf[0]) - 1;
s++)
{
- if (isdigit(*s))
+ if (*s >= '0' && *s <=
'9')
cashbuf[k++] =
*s;
- else if (*s ==
*decimal_point)
+ else if (*s ==
decimal_point)
cashbuf[k++] =
'.';
else if (*s == '(' ||
*s == '-')
cashbuf[k++] =
'-';
@@ -2327,6 +2333,7 @@
break;
default:
+ default_case:
val = PyString_FromString(s);
break;
}
@@ -3701,13 +3708,24 @@
set_decimal_point(PyObject *self, PyObject * args)
{
PyObject *ret = NULL;
- char *s;
+ char *s = NULL;
- if (PyArg_ParseTuple(args, "s", &s))
- {
- decimal_point = s;
+ /* gets arguments */
+ if (PyArg_ParseTuple(args, "z", &s)) {
+ if (!s)
+ s = "\0";
+ else if (*s && (*(s+1) || !strchr(".,;: '*/_`|", *s)))
+ s = NULL;
+ }
+
+ if (s) {
+ decimal_point = *s;
Py_INCREF(Py_None); ret = Py_None;
+ } else {
+ PyErr_SetString(PyExc_TypeError,
+ "set_decimal_point() expects a decimal mark character");
}
+
return ret;
}
@@ -3719,18 +3737,23 @@
get_decimal_point(PyObject *self, PyObject * args)
{
PyObject *ret = NULL;
+ char s[2];
if (PyArg_ParseTuple(args, ""))
{
- ret = PyString_FromString(decimal_point);
+ if (decimal_point) {
+ s[0] = decimal_point; s[1] = '\0';
+ ret = PyString_FromString(s);
+ } else {
+ Py_INCREF(Py_None); ret = Py_None;
+ }
}
else
{
PyErr_SetString(PyExc_TypeError,
- " get_decimal_point() takes no parameter");
+ "get_decimal_point() takes no parameter");
}
-
return ret;
}
Modified: branches/4.x/module/setup.py
==============================================================================
--- branches/4.x/module/setup.py Wed Nov 25 07:25:24 2015 (r622)
+++ branches/4.x/module/setup.py Wed Nov 25 07:59:03 2015 (r623)
@@ -87,7 +87,7 @@
library_dirs = [get_python_lib(), pg_config('libdir')]
define_macros = [('PYGRESQL_VERSION', version)]
undef_macros = []
-extra_compile_args = ['-O2', '-Wall', '-Werror']
+extra_compile_args = ['-O2', '-Wall', '-Werror', '-funsigned-char']
class build_pg_ext(build_ext):
_______________________________________________
PyGreSQL mailing list
[email protected]
https://mail.vex.net/mailman/listinfo.cgi/pygresql