summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>2011-06-04 14:16:24 +0100
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>2011-06-04 14:16:24 +0100
commitc8ec747903a4d0063d88fdd38cb18b50303daaa7 (patch)
tree36cb343bff2247eaac42338bf5f26c8467ceae28
parent05659c0d16767f0cba55d0e6acfbe3748aacc719 (diff)
downloadpsycopg2-c8ec747903a4d0063d88fdd38cb18b50303daaa7.tar.gz
Don't fail import if mx.DateTime module is not found at import time
A better fix for ticket #53.
-rw-r--r--NEWS4
-rw-r--r--psycopg/adapter_datetime.h4
-rw-r--r--psycopg/adapter_mxdatetime.c8
-rw-r--r--psycopg/psycopgmodule.c38
-rw-r--r--psycopg/typecast.c15
-rw-r--r--psycopg/typecast_mxdatetime.c8
-rw-r--r--setup.py19
7 files changed, 59 insertions, 37 deletions
diff --git a/NEWS b/NEWS
index a14cbf3..2d0d076 100644
--- a/NEWS
+++ b/NEWS
@@ -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).
diff --git a/psycopg/adapter_datetime.h b/psycopg/adapter_datetime.h
index dd59e9b..09abd88 100644
--- a/psycopg/adapter_datetime.h
+++ b/psycopg/adapter_datetime.h
@@ -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" \
diff --git a/psycopg/adapter_mxdatetime.c b/psycopg/adapter_mxdatetime.c
index 793dfba..abe73f8 100644
--- a/psycopg/adapter_mxdatetime.c
+++ b/psycopg/adapter_mxdatetime.c
@@ -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;
diff --git a/psycopg/psycopgmodule.c b/psycopg/psycopgmodule.c
index c5daefd..f37a98e 100644
--- a/psycopg/psycopgmodule.c
+++ b/psycopg/psycopgmodule.c
@@ -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
diff --git a/psycopg/typecast.c b/psycopg/typecast.c
index ba3871e..56a203d 100644
--- a/psycopg/typecast.c
+++ b/psycopg/typecast.c
@@ -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
diff --git a/psycopg/typecast_mxdatetime.c b/psycopg/typecast_mxdatetime.c
index a3a95fa..e61224d 100644
--- a/psycopg/typecast_mxdatetime.c
+++ b/psycopg/typecast_mxdatetime.c
@@ -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;
diff --git a/setup.py b/setup.py
index 45b1a90..6f06ad1 100644
--- a/setup.py
+++ b/setup.py
@@ -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):