On 9/19/07, Landlord Bulfleet <[EMAIL PROTECTED]> wrote: ... > > sum is property of a model object in our database > (models.DecimalField(max_digits=7, decimal_places=2)) & f_c.rate is a > Decimal constructed using Decimal(string) construction (Decimal is imported > with "from decimal import Decimal") > > We have some doubts that this may be a result of the django's python 2.3 > _decimal compatibility.
You're using PsycoPG with multiple interpreters. :) http://www.initd.org/tracker/psycopg/ticket/192 http://groups.google.com/group/django-developers/browse_thread/thread/63046b2fca27673c/898dbf8da327ce71 Anyway, I did run into this using psycopg1, but switched to psycopg2 and patched it since 1) it's being maintained and 2) it was easier to fix that way. I emailed the psycopg list a couple weeks ago with a patch but never heard back from them. I don't have rights to add the patch to their ticket tracker, or I'd do that, too. I'm attaching a patch against psycopg2's source code here. This is for r896 on the 2.0.x branch. Alternatively, you could run separate apache processes for each needed interpreter or switch to mod_wsgi. I wasn't prepared to swtich to mod_wsgi in a hurry, so patched psycopg2 instead. Apparently not that many people are using multiple interpreters and decimal fields with psycopg... --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-users@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~----------~----~----~----~------~----~------~--~---
Index: psycopg/psycopg.h =================================================================== --- psycopg/psycopg.h (revision 896) +++ psycopg/psycopg.h (working copy) @@ -129,8 +129,7 @@ char *pyenc; } encodingPair; -/* the Decimal type, used by the DECIMAL typecaster */ -extern PyObject *decimalType; +extern PyObject *psyco_decimal_type(void); /* some utility functions */ extern void psyco_set_error(PyObject *exc, PyObject *curs, char *msg, Index: psycopg/psycopgmodule.c =================================================================== --- psycopg/psycopgmodule.c (revision 896) +++ psycopg/psycopgmodule.c (working copy) @@ -62,7 +62,6 @@ PyObject *pyPsycopgTzFixedOffsetTimezone = NULL; PyObject *psycoEncodings = NULL; -PyObject *decimalType = NULL; /** connect module-level function **/ #define psyco_connect_doc \ @@ -330,7 +329,7 @@ #endif #ifdef HAVE_DECIMAL - microprotocols_add((PyTypeObject*)decimalType, NULL, (PyObject*)&asisType); + microprotocols_add((PyTypeObject*)psyco_decimal_type(), NULL, (PyObject*)&asisType); #endif } @@ -554,27 +553,7 @@ } } -/* psyco_decimal_init - Initialize the module's pointer to the decimal type. */ - -void -psyco_decimal_init(void) -{ -#ifdef HAVE_DECIMAL - PyObject *decimal = PyImport_ImportModule("decimal"); - if (decimal) { - decimalType = PyObject_GetAttrString(decimal, "Decimal"); - } - else { - PyErr_Clear(); - decimalType = (PyObject *)&PyFloat_Type; - Py_INCREF(decimalType); - } -#endif -} - - /** method table and module initialization **/ static PyMethodDef psycopgMethods[] = { @@ -730,7 +709,6 @@ /* other mixed initializations of module-level variables */ psycoEncodings = PyDict_New(); psyco_encodings_fill(psycoEncodings); - psyco_decimal_init(); /* set some module's parameters */ PyModule_AddStringConstant(module, "__version__", PSYCOPG_VERSION); Index: psycopg/typecast_basic.c =================================================================== --- psycopg/typecast_basic.c (revision 896) +++ psycopg/typecast_basic.c (working copy) @@ -113,6 +113,40 @@ return res; } +/* psyco_decimal_type + + Retrieve the decimal type from the current interpreter. + Can't cache due to each interpreter having separate sys.modules, + which causes isinstance(Decimal(), Decimal) to fail between interpreters. + + //FIXME: dropping refs every time it's called; dangerous if + // there are no other references in interp. + //We should have a pre-compiler + // WITH_MULTI_INTERPRETER to store typecasters per interpreter. +*/ + +PyObject *psyco_decimal_type(void) +{ +#ifdef HAVE_DECIMAL + + PyObject *decimal = PyImport_ImportModule("decimal"); + PyObject *decimalClass; + + if (decimal) { + Py_DECREF(decimal); + decimalClass = PyObject_GetAttrString(decimal, "Decimal"); + Py_DECREF(decimalClass); + } + else { + PyErr_Clear(); + decimalClass = (PyObject *)&PyFloat_Type; + } + return decimalClass; +#endif +} + + + /** DECIMAL - cast any kind of number into a Python Decimal object **/ #ifdef HAVE_DECIMAL @@ -127,7 +161,7 @@ if ((buffer = PyMem_Malloc(len+1)) == NULL) PyErr_NoMemory(); strncpy(buffer, s, (size_t) len); buffer[len] = '\0'; - res = PyObject_CallFunction(decimalType, "s", buffer); + res = PyObject_CallFunction(psyco_decimal_type(), "s", buffer); PyMem_Free(buffer); return res; Index: setup.py =================================================================== --- setup.py (revision 896) +++ setup.py (working copy) @@ -55,7 +55,7 @@ from distutils.ccompiler import get_default_compiler PSYCOPG_VERSION = '2.0.6' -version_flags = [] +version_flags = ['895+pegasus'] PLATFORM_IS_WINDOWS = sys.platform.lower().startswith('win') Index: ChangeLog =================================================================== --- ChangeLog (revision 896) +++ ChangeLog (working copy) @@ -1,7 +1,3 @@ -2007-09-01 Federico Di Gregorio <[EMAIL PROTECTED]> - - * Added "name" parameter to all .cursor() calls in extras.py. - 2007-05-29 Federico Di Gregorio <[EMAIL PROTECTED]> * Release 2.0.6. Index: lib/extras.py =================================================================== --- lib/extras.py (revision 896) +++ lib/extras.py (working copy) @@ -69,11 +69,8 @@ class DictConnection(_connection): """A connection that uses DictCursor automatically.""" - def cursor(self, name=None): - if name is None: - return _connection.cursor(self, cursor_factory=DictCursor) - else: - return _connection.cursor(self, name, cursor_factory=DictCursor) + def cursor(self): + return _connection.cursor(self, cursor_factory=DictCursor) class DictCursor(DictCursorBase): """A cursor that keeps a list of column name -> index mappings.""" @@ -138,11 +135,8 @@ class RealDictConnection(_connection): """A connection that uses RealDictCursor automatically.""" - def cursor(self, name=None): - if name is None: - return _connection.cursor(self, cursor_factory=RealDictCursor) - else: - return _connection.cursor(self, name, cursor_factory=RealDictCursor) + def cursor(self): + return _connection.cursor(self, cursor_factory=RealDictCursor) class RealDictCursor(DictCursorBase): """A cursor that uses a real dict as the base type for rows. @@ -221,13 +215,10 @@ raise self.ProgrammingError( "LoggingConnection object has not been initialize()d") - def cursor(self, name=None): + def cursor(self): self._check() - if name is None: - return _connection.cursor(self, cursor_factory=LoggingCursor) - else: - return _connection.cursor(self, name, cursor_factory=LoggingCursor) - + return _connection.cursor(self, cursor_factory=LoggingCursor) + class LoggingCursor(_cursor): """A cursor that logs queries using its connection logging facilities.""" @@ -263,12 +254,9 @@ if t > self._mintime: return msg + os.linesep + " (execution time: %d ms)" % t - def cursor(self, name=None): + def cursor(self): self._check() - if name is None: - return _connection.cursor(self, cursor_factory=MinTimeLoggingCursor) - else: - return _connection.cursor(self, name, cursor_factory=MinTimeLoggingCursor) + return _connection.cursor(self, cursor_factory=MinTimeLoggingCursor) class MinTimeLoggingCursor(LoggingCursor): """The cursor sub-class companion to MinTimeLoggingConnection."""