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.
- Fixed bug with multithread code potentially causing loss of sync
with the server communication or lock of the client (ticket #55).
- Don't build mx.DateTime support if the module can't be imported
(ticket #53).
- Don't fail import if mx.DateTime module can't be found, even if its
support was built (ticket #53).
- Fixed escape for negative numbers prefixed by minus operator
(ticket #57).

View File

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

View File

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

View File

@ -360,10 +360,16 @@ psyco_adapters_init(PyObject *mod)
#ifdef HAVE_MXDATETIME
/* as above, we use the callable objects from the psycopg module */
call = PyMapping_GetItemString(mod, "TimestampFromMx");
microprotocols_add(mxDateTime.DateTime_Type, NULL, call);
call = PyMapping_GetItemString(mod, "TimeFromMx");
microprotocols_add(mxDateTime.DateTimeDelta_Type, NULL, call);
if (NULL != (call = PyMapping_GetItemString(mod, "TimestampFromMx"))) {
microprotocols_add(mxDateTime.DateTime_Type, NULL, call);
/* if we found the above, we have this too. */
call = PyMapping_GetItemString(mod, "TimeFromMx");
microprotocols_add(mxDateTime.DateTimeDelta_Type, NULL, call);
}
else {
PyErr_Clear();
}
#endif
}
@ -792,6 +798,7 @@ static PyMethodDef psycopgMethods[] = {
METH_VARARGS, psyco_IntervalFromPy_doc},
#ifdef HAVE_MXDATETIME
/* to be deleted if not found at import time */
{"DateFromMx", (PyCFunction)psyco_DateFromMx,
METH_VARARGS, psyco_DateFromMx_doc},
{"TimeFromMx", (PyCFunction)psyco_TimeFromMx,
@ -885,12 +892,16 @@ INIT_MODULE(_psycopg)(void)
#ifdef HAVE_MXDATETIME
Py_TYPE(&mxdatetimeType) = &PyType_Type;
if (PyType_Ready(&mxdatetimeType) == -1) goto exit;
if (mxDateTime_ImportModuleAndAPI() != 0) {
Dprintf("initpsycopg: why marc hide mx.DateTime again?!");
PyErr_SetString(PyExc_ImportError, "can't import mx.DateTime module");
if (0 != mxDateTime_ImportModuleAndAPI()) {
PyErr_Clear();
/* 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;
#endif
}
if (psyco_adapter_mxdatetime_init()) { goto exit; }
#endif
/* import python builtin datetime module, if available */
@ -967,6 +978,16 @@ INIT_MODULE(_psycopg)(void)
/* encodings dictionary in module dictionary */
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 */
typecast_init(dict);
@ -999,7 +1020,6 @@ INIT_MODULE(_psycopg)(void)
lobjectType.tp_alloc = PyType_GenericAlloc;
#endif
#ifdef HAVE_MXDATETIME
mxdatetimeType.tp_alloc = PyType_GenericAlloc;
#endif

View File

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

View File

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

View File

@ -450,18 +450,13 @@ if parser.has_option('build_ext', 'mx_include_dir'):
else:
mxincludedir = os.path.join(get_python_inc(plat_specific=1), "mx")
if os.path.exists(mxincludedir):
# Check if mx.datetime is importable at all: see ticket #53
try:
import mx.DateTime
except ImportError:
pass
else:
include_dirs.append(mxincludedir)
define_macros.append(('HAVE_MXDATETIME','1'))
sources.append('adapter_mxdatetime.c')
depends.extend(['adapter_mxdatetime.h', 'typecast_mxdatetime.c'])
have_mxdatetime = True
version_flags.append('mx')
# Build the support for mx: we will check at runtime if it can be imported
include_dirs.append(mxincludedir)
define_macros.append(('HAVE_MXDATETIME','1'))
sources.append('adapter_mxdatetime.c')
depends.extend(['adapter_mxdatetime.h', 'typecast_mxdatetime.c'])
have_mxdatetime = True
version_flags.append('mx')
# now decide which package will be the default for date/time typecasts
if have_pydatetime and (use_pydatetime or not have_mxdatetime):