summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog2
-rw-r--r--psycopg/adapter_datetime.c44
-rw-r--r--psycopg/adapter_datetime.h2
-rw-r--r--psycopg/psycopgmodule.c26
-rw-r--r--psycopg/typecast_datetime.c43
-rw-r--r--psycopg/typecast_datetime.h44
6 files changed, 112 insertions, 49 deletions
diff --git a/ChangeLog b/ChangeLog
index 9411302..2305813 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -7,6 +7,8 @@
* typecast.h: functions exported to drop warnings.
+ * datetime module initialized at is supposed to be.
+
2010-11-17 Daniele Varrazzo <daniele.varrazzo@gmail.com>
* psycopg/connection_type.c: don't clobber exception if
diff --git a/psycopg/adapter_datetime.c b/psycopg/adapter_datetime.c
index 7ba98f2..08b0cd6 100644
--- a/psycopg/adapter_datetime.c
+++ b/psycopg/adapter_datetime.c
@@ -39,18 +39,23 @@
#include "psycopg/adapter_datetime.h"
#include "psycopg/microprotocols_proto.h"
-
-/* the pointer to the datetime module API is initialized by the module init
- code, we just need to grab it */
-extern HIDDEN PyObject* pyDateTimeModuleP;
-extern HIDDEN PyObject *pyDateTypeP;
-extern HIDDEN PyObject *pyTimeTypeP;
-extern HIDDEN PyObject *pyDateTimeTypeP;
-extern HIDDEN PyObject *pyDeltaTypeP;
-
extern HIDDEN PyObject *pyPsycopgTzModule;
extern HIDDEN PyObject *pyPsycopgTzLOCAL;
+int
+psyco_adapter_datetime_init(void)
+{
+ Dprintf("psyco_adapter_datetime_init: datetime init");
+
+ PyDateTime_IMPORT;
+
+ if (!PyDateTimeAPI) {
+ PyErr_SetString(PyExc_ImportError, "datetime initialization failed");
+ return -1;
+ }
+ return 0;
+}
+
/* datetime_str, datetime_getquoted - return result of quoting */
static PyObject *
@@ -298,7 +303,8 @@ psyco_Date(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "iii", &year, &month, &day))
return NULL;
- obj = PyObject_CallFunction(pyDateTypeP, "iii", year, month, day);
+ obj = PyObject_CallFunction((PyObject*)PyDateTimeAPI->DateType,
+ "iii", year, month, day);
if (obj) {
res = PyObject_CallFunction((PyObject *)&pydatetimeType,
@@ -327,10 +333,10 @@ psyco_Time(PyObject *self, PyObject *args)
second = floor(second);
if (tzinfo == NULL)
- obj = PyObject_CallFunction(pyTimeTypeP, "iiii",
+ obj = PyObject_CallFunction((PyObject*)PyDateTimeAPI->TimeType, "iiii",
hours, minutes, (int)second, (int)round(micro));
else
- obj = PyObject_CallFunction(pyTimeTypeP, "iiiiO",
+ obj = PyObject_CallFunction((PyObject*)PyDateTimeAPI->TimeType, "iiiiO",
hours, minutes, (int)second, (int)round(micro), tzinfo);
if (obj) {
@@ -361,11 +367,13 @@ psyco_Timestamp(PyObject *self, PyObject *args)
second = floor(second);
if (tzinfo == NULL)
- obj = PyObject_CallFunction(pyDateTimeTypeP, "iiiiiii",
+ obj = PyObject_CallFunction((PyObject*)PyDateTimeAPI->DateTimeType,
+ "iiiiiii",
year, month, day, hour, minute, (int)second,
(int)round(micro));
else
- obj = PyObject_CallFunction(pyDateTimeTypeP, "iiiiiiiO",
+ obj = PyObject_CallFunction((PyObject*)PyDateTimeAPI->DateTimeType,
+ "iiiiiiiO",
year, month, day, hour, minute, (int)second,
(int)round(micro), tzinfo);
@@ -462,7 +470,7 @@ psyco_DateFromPy(PyObject *self, PyObject *args)
{
PyObject *obj;
- if (!PyArg_ParseTuple(args, "O!", pyDateTypeP, &obj))
+ if (!PyArg_ParseTuple(args, "O!", PyDateTimeAPI->DateType, &obj))
return NULL;
return PyObject_CallFunction((PyObject *)&pydatetimeType, "Oi", obj,
@@ -474,7 +482,7 @@ psyco_TimeFromPy(PyObject *self, PyObject *args)
{
PyObject *obj;
- if (!PyArg_ParseTuple(args, "O!", pyTimeTypeP, &obj))
+ if (!PyArg_ParseTuple(args, "O!", PyDateTimeAPI->TimeType, &obj))
return NULL;
return PyObject_CallFunction((PyObject *)&pydatetimeType, "Oi", obj,
@@ -486,7 +494,7 @@ psyco_TimestampFromPy(PyObject *self, PyObject *args)
{
PyObject *obj;
- if (!PyArg_ParseTuple(args, "O!", pyDateTimeTypeP, &obj))
+ if (!PyArg_ParseTuple(args, "O!", PyDateTimeAPI->DateTimeType, &obj))
return NULL;
return PyObject_CallFunction((PyObject *)&pydatetimeType, "Oi", obj,
@@ -498,7 +506,7 @@ psyco_IntervalFromPy(PyObject *self, PyObject *args)
{
PyObject *obj;
- if (!PyArg_ParseTuple(args, "O!", pyDeltaTypeP, &obj))
+ if (!PyArg_ParseTuple(args, "O!", PyDateTimeAPI->DeltaType, &obj))
return NULL;
return PyObject_CallFunction((PyObject *)&pydatetimeType, "Oi", obj,
diff --git a/psycopg/adapter_datetime.h b/psycopg/adapter_datetime.h
index a0df12e..a2c36fb 100644
--- a/psycopg/adapter_datetime.h
+++ b/psycopg/adapter_datetime.h
@@ -53,6 +53,8 @@ typedef struct {
/* 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/psycopgmodule.c b/psycopg/psycopgmodule.c
index 4764b8e..26e17e0 100644
--- a/psycopg/psycopgmodule.c
+++ b/psycopg/psycopgmodule.c
@@ -48,6 +48,7 @@
#include "psycopg/adapter_asis.h"
#include "psycopg/adapter_list.h"
#include "psycopg/typecast_binary.h"
+#include "psycopg/typecast_datetime.h"
#ifdef HAVE_MXDATETIME
#include <mxDateTime.h>
@@ -59,10 +60,6 @@ HIDDEN mxDateTimeModule_APIObject *mxDateTimeP = NULL;
#include <datetime.h>
#include "psycopg/adapter_datetime.h"
HIDDEN PyObject *pyDateTimeModuleP = NULL;
-HIDDEN PyObject *pyDateTypeP = NULL;
-HIDDEN PyObject *pyTimeTypeP = NULL;
-HIDDEN PyObject *pyDateTimeTypeP = NULL;
-HIDDEN PyObject *pyDeltaTypeP = NULL;
/* pointers to the psycopg.tz classes */
HIDDEN PyObject *pyPsycopgTzModule = NULL;
@@ -312,13 +309,13 @@ psyco_adapters_init(PyObject *mod)
/* the module has already been initialized, so we can obtain the callable
objects directly from its dictionary :) */
call = PyMapping_GetItemString(mod, "DateFromPy");
- microprotocols_add((PyTypeObject*)pyDateTypeP, NULL, call);
+ microprotocols_add(PyDateTimeAPI->DateType, NULL, call);
call = PyMapping_GetItemString(mod, "TimeFromPy");
- microprotocols_add((PyTypeObject*)pyTimeTypeP, NULL, call);
+ microprotocols_add(PyDateTimeAPI->TimeType, NULL, call);
call = PyMapping_GetItemString(mod, "TimestampFromPy");
- microprotocols_add((PyTypeObject*)pyDateTimeTypeP, NULL, call);
+ microprotocols_add(PyDateTimeAPI->DateTimeType, NULL, call);
call = PyMapping_GetItemString(mod, "IntervalFromPy");
- microprotocols_add((PyTypeObject*)pyDeltaTypeP, NULL, call);
+ microprotocols_add(PyDateTimeAPI->DeltaType, NULL, call);
#ifdef HAVE_MXDATETIME
/* as above, we use the callable objects from the psycopg module */
@@ -776,16 +773,15 @@ init_psycopg(void)
PyErr_SetString(PyExc_ImportError, "can't import datetime module");
return;
}
+
+ /* Initialize the PyDateTimeAPI everywhere is used */
+ PyDateTime_IMPORT;
+ if (psyco_adapter_datetime_init()) { return; }
+ if (psyco_typecast_datetime_init()) { return; }
+
pydatetimeType.ob_type = &PyType_Type;
if (PyType_Ready(&pydatetimeType) == -1) return;
- /* now we define the datetime types, this is crazy because python should
- be doing that, not us! */
- pyDateTypeP = PyObject_GetAttrString(pyDateTimeModuleP, "date");
- pyTimeTypeP = PyObject_GetAttrString(pyDateTimeModuleP, "time");
- pyDateTimeTypeP = PyObject_GetAttrString(pyDateTimeModuleP, "datetime");
- pyDeltaTypeP = PyObject_GetAttrString(pyDateTimeModuleP, "timedelta");
-
/* import psycopg2.tz anyway (TODO: replace with C-level module?) */
pyPsycopgTzModule = PyImport_ImportModule("psycopg2.tz");
if (pyPsycopgTzModule == NULL) {
diff --git a/psycopg/typecast_datetime.c b/psycopg/typecast_datetime.c
index 759633b..871965b 100644
--- a/psycopg/typecast_datetime.c
+++ b/psycopg/typecast_datetime.c
@@ -26,14 +26,19 @@
#include <math.h>
#include "datetime.h"
+int
+psyco_typecast_datetime_init(void)
+{
+ Dprintf("psyco_typecast_datetime_init: datetime init");
+
+ PyDateTime_IMPORT;
-/* the pointer to the datetime module API is initialized by the module init
- code, we just need to grab it */
-extern HIDDEN PyObject* pyDateTimeModuleP;
-extern HIDDEN PyObject *pyDateTypeP;
-extern HIDDEN PyObject *pyTimeTypeP;
-extern HIDDEN PyObject *pyDateTimeTypeP;
-extern HIDDEN PyObject *pyDeltaTypeP;
+ if (!PyDateTimeAPI) {
+ PyErr_SetString(PyExc_ImportError, "datetime initialization failed");
+ return -1;
+ }
+ return 0;
+}
/** DATE - cast a date into a date python object **/
@@ -47,10 +52,12 @@ typecast_PYDATE_cast(const char *str, Py_ssize_t len, PyObject *curs)
if (!strcmp(str, "infinity") || !strcmp(str, "-infinity")) {
if (str[0] == '-') {
- obj = PyObject_GetAttrString(pyDateTypeP, "min");
+ obj = PyObject_GetAttrString(
+ (PyObject*)PyDateTimeAPI->DateType, "min");
}
else {
- obj = PyObject_GetAttrString(pyDateTypeP, "max");
+ obj = PyObject_GetAttrString(
+ (PyObject*)PyDateTimeAPI->DateType, "max");
}
}
@@ -66,7 +73,8 @@ typecast_PYDATE_cast(const char *str, Py_ssize_t len, PyObject *curs)
}
else {
if (y > 9999) y = 9999;
- obj = PyObject_CallFunction(pyDateTypeP, "iii", y, m, d);
+ obj = PyObject_CallFunction(
+ (PyObject*)PyDateTimeAPI->DateType, "iii", y, m, d);
}
}
return obj;
@@ -89,10 +97,12 @@ typecast_PYDATETIME_cast(const char *str, Py_ssize_t len, PyObject *curs)
/* check for infinity */
if (!strcmp(str, "infinity") || !strcmp(str, "-infinity")) {
if (str[0] == '-') {
- obj = PyObject_GetAttrString(pyDateTimeTypeP, "min");
+ obj = PyObject_GetAttrString(
+ (PyObject*)PyDateTimeAPI->DateTimeType, "min");
}
else {
- obj = PyObject_GetAttrString(pyDateTimeTypeP, "max");
+ obj = PyObject_GetAttrString(
+ (PyObject*)PyDateTimeAPI->DateTimeType, "max");
}
}
@@ -144,8 +154,9 @@ typecast_PYDATETIME_cast(const char *str, Py_ssize_t len, PyObject *curs)
tzinfo = Py_None;
}
if (tzinfo != NULL) {
- obj = PyObject_CallFunction(pyDateTimeTypeP, "iiiiiiiO",
- y, m, d, hh, mm, ss, us, tzinfo);
+ obj = PyObject_CallFunction(
+ (PyObject*)PyDateTimeAPI->DateTimeType, "iiiiiiiO",
+ y, m, d, hh, mm, ss, us, tzinfo);
Dprintf("typecast_PYDATETIME_cast: tzinfo: %p, refcnt = "
FORMAT_CODE_PY_SSIZE_T,
tzinfo, tzinfo->ob_refcnt
@@ -197,7 +208,7 @@ typecast_PYTIME_cast(const char *str, Py_ssize_t len, PyObject *curs)
tzinfo = Py_None;
}
if (tzinfo != NULL) {
- obj = PyObject_CallFunction(pyTimeTypeP, "iiiiO",
+ obj = PyObject_CallFunction((PyObject*)PyDateTimeAPI->TimeType, "iiiiO",
hh, mm, ss, us, tzinfo);
Py_DECREF(tzinfo);
}
@@ -308,7 +319,7 @@ typecast_PYINTERVAL_cast(const char *str, Py_ssize_t len, PyObject *curs)
micro = (seconds - floor(seconds)) * 1000000.0;
sec = (int)floor(seconds);
- return PyObject_CallFunction(pyDeltaTypeP, "iii",
+ return PyObject_CallFunction((PyObject*)PyDateTimeAPI->DeltaType, "iii",
days, sec, (int)round(micro));
}
diff --git a/psycopg/typecast_datetime.h b/psycopg/typecast_datetime.h
new file mode 100644
index 0000000..cb01c6f
--- /dev/null
+++ b/psycopg/typecast_datetime.h
@@ -0,0 +1,44 @@
+/* typecast_datetime.h - definitions for datetime objects typecasters
+ *
+ * Copyright (C) 2010 Daniele Varrazzo <daniele.varrazzo@gmail.com>
+ *
+ * This file is part of psycopg.
+ *
+ * psycopg2 is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link this program with the OpenSSL library (or with
+ * modified versions of OpenSSL that use the same license as OpenSSL),
+ * and distribute linked combinations including the two.
+ *
+ * You must obey the GNU Lesser General Public License in all respects for
+ * all of the code used other than OpenSSL.
+ *
+ * psycopg2 is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ */
+
+#ifndef PSYCOPG_TYPECAST_DATETIME_H
+#define PSYCOPG_TYPECAST_DATETIME_H 1
+
+#define PY_SSIZE_T_CLEAN
+#include <Python.h>
+
+#include "psycopg/config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+HIDDEN int psyco_typecast_datetime_init(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !defined(PSYCOPG_TYPECAST_DATETIME_H) */