support scale argument for the C implementation of the decimal processor

This commit is contained in:
Gaëtan de Menten
2010-02-28 20:39:49 +00:00
parent 9fd094edbb
commit 08f2c2c19a
2 changed files with 32 additions and 28 deletions
+14 -5
View File
@@ -143,6 +143,7 @@ typedef struct {
typedef struct {
PyObject_HEAD
PyObject *type;
PyObject *format;
} DecimalResultProcessor;
@@ -158,7 +159,7 @@ UnicodeResultProcessor_init(UnicodeResultProcessor *self, PyObject *args,
PyObject *encoding, *errors = NULL;
static char *kwlist[] = {"encoding", "errors", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "S|S:init", kwlist,
if (!PyArg_ParseTupleAndKeywords(args, kwds, "S|S:__init__", kwlist,
&encoding, &errors))
return -1;
@@ -252,30 +253,38 @@ static int
DecimalResultProcessor_init(DecimalResultProcessor *self, PyObject *args,
PyObject *kwds)
{
PyObject *type;
PyObject *type, *format;
if (!PyArg_ParseTuple(args, "O", &type))
if (!PyArg_ParseTuple(args, "OS", &type, &format))
return -1;
Py_INCREF(type);
self->type = type;
Py_INCREF(format);
self->format = format;
return 0;
}
static PyObject *
DecimalResultProcessor_process(DecimalResultProcessor *self, PyObject *value)
{
PyObject *str, *result;
PyObject *str, *result, *args;
if (value == Py_None)
Py_RETURN_NONE;
if (PyFloat_CheckExact(value)) {
/* Decimal does not accept float values directly */
str = PyObject_Str(value);
args = PyTuple_Pack(1, value);
if (args == NULL)
return NULL;
str = PyString_Format(self->format, args);
if (str == NULL)
return NULL;
result = PyObject_CallFunctionObjArgs(self->type, str, NULL);
Py_DECREF(str);
return result;
+18 -23
View File
@@ -4,7 +4,8 @@
# This module is part of SQLAlchemy and is released under
# the MIT License: http://www.opensource.org/licenses/mit-license.php
"""defines generic type conversion functions, as used in result processors.
"""defines generic type conversion functions, as used in bind and result
processors.
They all share one common characteristic: None is passed through unchanged.
@@ -39,9 +40,13 @@ try:
else:
return UnicodeResultProcessor(encoding).process
# TODO: add scale argument
#def to_decimal_processor_factory(target_class):
# return DecimalResultProcessor(target_class).process
def to_decimal_processor_factory(target_class, scale=10):
# Note that the scale argument is not taken into account for integer
# values in the C implementation while it is in the Python one.
# For example, the Python implementation might return
# Decimal('5.00000') whereas the C implementation will
# return Decimal('5'). These are equivalent of course.
return DecimalResultProcessor(target_class, "%%.%df" % scale).process
except ImportError:
def to_unicode_processor_factory(encoding, errors=None):
@@ -54,18 +59,18 @@ except ImportError:
# decoder returns a tuple: (value, len). Simply dropping the
# len part is safe: it is done that way in the normal
# 'xx'.decode(encoding) code path.
# cfr python-source/Python/codecs.c:PyCodec_Decode
return decoder(value, errors)[0]
return process
# TODO: add scale argument
#def to_decimal_processor_factory(target_class):
# def process(value):
# if value is None:
# return None
# else:
# return target_class(str(value))
# return process
def to_decimal_processor_factory(target_class, scale=10):
fstring = "%%.%df" % scale
def process(value):
if value is None:
return None
else:
return target_class(fstring % value)
return process
def to_float(value):
if value is None:
@@ -94,13 +99,3 @@ except ImportError:
str_to_time = str_to_datetime_processor_factory(TIME_RE, datetime.time)
str_to_date = str_to_datetime_processor_factory(DATE_RE, datetime.date)
def to_decimal_processor_factory(target_class, scale=10):
fstring = "%%.%df" % scale
def process(value):
if value is None:
return None
else:
return target_class(fstring % value)
return process