typedef struct {
PyObject_HEAD
PyObject *type;
+ PyObject *format;
} DecimalResultProcessor;
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;
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;
# 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.
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):
# 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:
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