]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
support scale argument for the C implementation of the decimal processor
authorGaëtan de Menten <gdementen@gmail.com>
Sun, 28 Feb 2010 20:39:49 +0000 (20:39 +0000)
committerGaëtan de Menten <gdementen@gmail.com>
Sun, 28 Feb 2010 20:39:49 +0000 (20:39 +0000)
lib/sqlalchemy/cextension/processors.c
lib/sqlalchemy/processors.py

index d2d39809046c559121f8f9bb545bd22160f72127..6e33027194b3edd6daa061e5c003bf6a62b0337d 100644 (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;
index 04fa5054abee27605e522da47b01bb37428c18a4..c99ca4c6f5060a3bf9ce24866e81424607a33b26 100644 (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