datetime module initialized as it is supposed to be.

Dropped compiler warnings. It wouldn't blow up if any api was called.
No need to pass type pointers around.
This commit is contained in:
Daniele Varrazzo 2010-11-18 23:16:40 +00:00
parent 576b01f6a3
commit 3e3aa676a9
6 changed files with 112 additions and 49 deletions

View File

@ -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

View File

@ -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,

View File

@ -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" \

View File

@ -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) {

View File

@ -26,14 +26,19 @@
#include <math.h>
#include "datetime.h"
int
psyco_typecast_datetime_init(void)
{
Dprintf("psyco_typecast_datetime_init: datetime init");
/* 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;
PyDateTime_IMPORT;
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));
}

View File

@ -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) */