Don't fail import if mx.DateTime module is not found at import time

A better fix for ticket #53.
This commit is contained in:
Daniele Varrazzo 2011-06-04 14:16:24 +01:00
parent 05659c0d16
commit c8ec747903
7 changed files with 59 additions and 37 deletions

4
NEWS
View File

@ -9,8 +9,8 @@ What's new in psycopg 2.4.2
default isolation level. default isolation level.
- Fixed bug with multithread code potentially causing loss of sync - Fixed bug with multithread code potentially causing loss of sync
with the server communication or lock of the client (ticket #55). with the server communication or lock of the client (ticket #55).
- Don't build mx.DateTime support if the module can't be imported - Don't fail import if mx.DateTime module can't be found, even if its
(ticket #53). support was built (ticket #53).
- Fixed escape for negative numbers prefixed by minus operator - Fixed escape for negative numbers prefixed by minus operator
(ticket #57). (ticket #57).

View File

@ -45,11 +45,11 @@ typedef struct {
} pydatetimeObject; } pydatetimeObject;
HIDDEN int psyco_adapter_datetime_init(void);
/* functions exported to psycopgmodule.c */ /* functions exported to psycopgmodule.c */
#ifdef PSYCOPG_DEFAULT_PYDATETIME #ifdef PSYCOPG_DEFAULT_PYDATETIME
HIDDEN int psyco_adapter_datetime_init(void);
HIDDEN PyObject *psyco_Date(PyObject *module, PyObject *args); HIDDEN PyObject *psyco_Date(PyObject *module, PyObject *args);
#define psyco_Date_doc \ #define psyco_Date_doc \
"Date(year, month, day) -> new date\n\n" \ "Date(year, month, day) -> new date\n\n" \

View File

@ -26,7 +26,6 @@
#define PSYCOPG_MODULE #define PSYCOPG_MODULE
#include "psycopg/psycopg.h" #include "psycopg/psycopg.h"
/* TODO: check if still compiles ok: I have no mx on this box */
#include "psycopg/adapter_mxdatetime.h" #include "psycopg/adapter_mxdatetime.h"
#include "psycopg/microprotocols_proto.h" #include "psycopg/microprotocols_proto.h"
@ -34,13 +33,16 @@
#include <string.h> #include <string.h>
/* Return 0 on success, -1 on failure, but don't set an exception */
int int
psyco_adapter_mxdatetime_init(void) psyco_adapter_mxdatetime_init(void)
{ {
Dprintf("psyco_adapter_mxdatetime_init: mx.DateTime init"); Dprintf("psyco_adapter_mxdatetime_init: mx.DateTime init");
if (mxDateTime_ImportModuleAndAPI()) { if (mxDateTime_ImportModuleAndAPI()) {
PyErr_SetString(PyExc_ImportError, "mx.DateTime initialization failed"); Dprintf("psyco_adapter_mxdatetime_init: mx.DateTime initialization failed");
PyErr_Clear();
return -1; return -1;
} }
return 0; return 0;

View File

@ -360,10 +360,16 @@ psyco_adapters_init(PyObject *mod)
#ifdef HAVE_MXDATETIME #ifdef HAVE_MXDATETIME
/* as above, we use the callable objects from the psycopg module */ /* as above, we use the callable objects from the psycopg module */
call = PyMapping_GetItemString(mod, "TimestampFromMx"); if (NULL != (call = PyMapping_GetItemString(mod, "TimestampFromMx"))) {
microprotocols_add(mxDateTime.DateTime_Type, NULL, call); microprotocols_add(mxDateTime.DateTime_Type, NULL, call);
/* if we found the above, we have this too. */
call = PyMapping_GetItemString(mod, "TimeFromMx"); call = PyMapping_GetItemString(mod, "TimeFromMx");
microprotocols_add(mxDateTime.DateTimeDelta_Type, NULL, call); microprotocols_add(mxDateTime.DateTimeDelta_Type, NULL, call);
}
else {
PyErr_Clear();
}
#endif #endif
} }
@ -792,6 +798,7 @@ static PyMethodDef psycopgMethods[] = {
METH_VARARGS, psyco_IntervalFromPy_doc}, METH_VARARGS, psyco_IntervalFromPy_doc},
#ifdef HAVE_MXDATETIME #ifdef HAVE_MXDATETIME
/* to be deleted if not found at import time */
{"DateFromMx", (PyCFunction)psyco_DateFromMx, {"DateFromMx", (PyCFunction)psyco_DateFromMx,
METH_VARARGS, psyco_DateFromMx_doc}, METH_VARARGS, psyco_DateFromMx_doc},
{"TimeFromMx", (PyCFunction)psyco_TimeFromMx, {"TimeFromMx", (PyCFunction)psyco_TimeFromMx,
@ -885,12 +892,16 @@ INIT_MODULE(_psycopg)(void)
#ifdef HAVE_MXDATETIME #ifdef HAVE_MXDATETIME
Py_TYPE(&mxdatetimeType) = &PyType_Type; Py_TYPE(&mxdatetimeType) = &PyType_Type;
if (PyType_Ready(&mxdatetimeType) == -1) goto exit; if (PyType_Ready(&mxdatetimeType) == -1) goto exit;
if (mxDateTime_ImportModuleAndAPI() != 0) { if (0 != mxDateTime_ImportModuleAndAPI()) {
Dprintf("initpsycopg: why marc hide mx.DateTime again?!"); PyErr_Clear();
PyErr_SetString(PyExc_ImportError, "can't import mx.DateTime module");
/* only fail if the mx typacaster should have been the default */
#ifdef PSYCOPG_DEFAULT_MXDATETIME
PyErr_SetString(PyExc_ImportError,
"can't import mx.DateTime module (requested as default adapter)");
goto exit; goto exit;
#endif
} }
if (psyco_adapter_mxdatetime_init()) { goto exit; }
#endif #endif
/* import python builtin datetime module, if available */ /* import python builtin datetime module, if available */
@ -967,6 +978,16 @@ INIT_MODULE(_psycopg)(void)
/* encodings dictionary in module dictionary */ /* encodings dictionary in module dictionary */
PyModule_AddObject(module, "encodings", psycoEncodings); PyModule_AddObject(module, "encodings", psycoEncodings);
#ifdef HAVE_MXDATETIME
/* If we can't find mx.DateTime objects at runtime,
* remove them from the module (and, as consequence, from the adapters). */
if (0 != psyco_adapter_mxdatetime_init()) {
PyDict_DelItemString(dict, "DateFromMx");
PyDict_DelItemString(dict, "TimeFromMx");
PyDict_DelItemString(dict, "TimestampFromMx");
PyDict_DelItemString(dict, "IntervalFromMx");
}
#endif
/* initialize default set of typecasters */ /* initialize default set of typecasters */
typecast_init(dict); typecast_init(dict);
@ -999,7 +1020,6 @@ INIT_MODULE(_psycopg)(void)
lobjectType.tp_alloc = PyType_GenericAlloc; lobjectType.tp_alloc = PyType_GenericAlloc;
#endif #endif
#ifdef HAVE_MXDATETIME #ifdef HAVE_MXDATETIME
mxdatetimeType.tp_alloc = PyType_GenericAlloc; mxdatetimeType.tp_alloc = PyType_GenericAlloc;
#endif #endif

View File

@ -292,7 +292,7 @@ typecast_init(PyObject *dict)
/* register the date/time typecasters with their original names */ /* register the date/time typecasters with their original names */
#ifdef HAVE_MXDATETIME #ifdef HAVE_MXDATETIME
if (psyco_typecast_mxdatetime_init()) { return -1; } if (0 == psyco_typecast_mxdatetime_init()) {
for (i = 0; typecast_mxdatetime[i].name != NULL; i++) { for (i = 0; typecast_mxdatetime[i].name != NULL; i++) {
typecastObject *t; typecastObject *t;
Dprintf("typecast_init: initializing %s", typecast_mxdatetime[i].name); Dprintf("typecast_init: initializing %s", typecast_mxdatetime[i].name);
@ -300,6 +300,7 @@ typecast_init(PyObject *dict)
if (t == NULL) return -1; if (t == NULL) return -1;
PyDict_SetItem(dict, t->name, (PyObject *)t); PyDict_SetItem(dict, t->name, (PyObject *)t);
} }
}
#endif #endif
if (psyco_typecast_datetime_init()) { return -1; } if (psyco_typecast_datetime_init()) { return -1; }

View File

@ -25,13 +25,17 @@
#include "mxDateTime.h" #include "mxDateTime.h"
/* Return 0 on success, -1 on failure, but don't set an exception */
static int static int
psyco_typecast_mxdatetime_init(void) psyco_typecast_mxdatetime_init(void)
{ {
Dprintf("psyco_typecast_mxdatetime_init: mx.DateTime init"); Dprintf("psyco_typecast_mxdatetime_init: mx.DateTime init");
if (mxDateTime_ImportModuleAndAPI()) { if (mxDateTime_ImportModuleAndAPI()) {
PyErr_SetString(PyExc_ImportError, "mx.DateTime initialization failed"); Dprintf("psyco_typecast_mxdatetime_init: mx.DateTime initialization failed");
PyErr_Clear();
return -1; return -1;
} }
return 0; return 0;

View File

@ -450,12 +450,7 @@ if parser.has_option('build_ext', 'mx_include_dir'):
else: else:
mxincludedir = os.path.join(get_python_inc(plat_specific=1), "mx") mxincludedir = os.path.join(get_python_inc(plat_specific=1), "mx")
if os.path.exists(mxincludedir): if os.path.exists(mxincludedir):
# Check if mx.datetime is importable at all: see ticket #53 # Build the support for mx: we will check at runtime if it can be imported
try:
import mx.DateTime
except ImportError:
pass
else:
include_dirs.append(mxincludedir) include_dirs.append(mxincludedir)
define_macros.append(('HAVE_MXDATETIME','1')) define_macros.append(('HAVE_MXDATETIME','1'))
sources.append('adapter_mxdatetime.c') sources.append('adapter_mxdatetime.c')