Skip to content

Commit 3e3aa67

Browse files
committed
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.
1 parent 576b01f commit 3e3aa67

File tree

6 files changed

+112
-49
lines changed

6 files changed

+112
-49
lines changed

ChangeLog

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
* typecast.h: functions exported to drop warnings.
99

10+
* datetime module initialized at is supposed to be.
11+
1012
2010-11-17 Daniele Varrazzo <daniele.varrazzo@gmail.com>
1113

1214
* psycopg/connection_type.c: don't clobber exception if

psycopg/adapter_datetime.c

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,23 @@
3939
#include "psycopg/adapter_datetime.h"
4040
#include "psycopg/microprotocols_proto.h"
4141

42-
43-
/* the pointer to the datetime module API is initialized by the module init
44-
code, we just need to grab it */
45-
extern HIDDEN PyObject* pyDateTimeModuleP;
46-
extern HIDDEN PyObject *pyDateTypeP;
47-
extern HIDDEN PyObject *pyTimeTypeP;
48-
extern HIDDEN PyObject *pyDateTimeTypeP;
49-
extern HIDDEN PyObject *pyDeltaTypeP;
50-
5142
extern HIDDEN PyObject *pyPsycopgTzModule;
5243
extern HIDDEN PyObject *pyPsycopgTzLOCAL;
5344

45+
int
46+
psyco_adapter_datetime_init(void)
47+
{
48+
Dprintf("psyco_adapter_datetime_init: datetime init");
49+
50+
PyDateTime_IMPORT;
51+
52+
if (!PyDateTimeAPI) {
53+
PyErr_SetString(PyExc_ImportError, "datetime initialization failed");
54+
return -1;
55+
}
56+
return 0;
57+
}
58+
5459
/* datetime_str, datetime_getquoted - return result of quoting */
5560

5661
static PyObject *
@@ -298,7 +303,8 @@ psyco_Date(PyObject *self, PyObject *args)
298303
if (!PyArg_ParseTuple(args, "iii", &year, &month, &day))
299304
return NULL;
300305

301-
obj = PyObject_CallFunction(pyDateTypeP, "iii", year, month, day);
306+
obj = PyObject_CallFunction((PyObject*)PyDateTimeAPI->DateType,
307+
"iii", year, month, day);
302308

303309
if (obj) {
304310
res = PyObject_CallFunction((PyObject *)&pydatetimeType,
@@ -327,10 +333,10 @@ psyco_Time(PyObject *self, PyObject *args)
327333
second = floor(second);
328334

329335
if (tzinfo == NULL)
330-
obj = PyObject_CallFunction(pyTimeTypeP, "iiii",
336+
obj = PyObject_CallFunction((PyObject*)PyDateTimeAPI->TimeType, "iiii",
331337
hours, minutes, (int)second, (int)round(micro));
332338
else
333-
obj = PyObject_CallFunction(pyTimeTypeP, "iiiiO",
339+
obj = PyObject_CallFunction((PyObject*)PyDateTimeAPI->TimeType, "iiiiO",
334340
hours, minutes, (int)second, (int)round(micro), tzinfo);
335341

336342
if (obj) {
@@ -361,11 +367,13 @@ psyco_Timestamp(PyObject *self, PyObject *args)
361367
second = floor(second);
362368

363369
if (tzinfo == NULL)
364-
obj = PyObject_CallFunction(pyDateTimeTypeP, "iiiiiii",
370+
obj = PyObject_CallFunction((PyObject*)PyDateTimeAPI->DateTimeType,
371+
"iiiiiii",
365372
year, month, day, hour, minute, (int)second,
366373
(int)round(micro));
367374
else
368-
obj = PyObject_CallFunction(pyDateTimeTypeP, "iiiiiiiO",
375+
obj = PyObject_CallFunction((PyObject*)PyDateTimeAPI->DateTimeType,
376+
"iiiiiiiO",
369377
year, month, day, hour, minute, (int)second,
370378
(int)round(micro), tzinfo);
371379

@@ -462,7 +470,7 @@ psyco_DateFromPy(PyObject *self, PyObject *args)
462470
{
463471
PyObject *obj;
464472

465-
if (!PyArg_ParseTuple(args, "O!", pyDateTypeP, &obj))
473+
if (!PyArg_ParseTuple(args, "O!", PyDateTimeAPI->DateType, &obj))
466474
return NULL;
467475

468476
return PyObject_CallFunction((PyObject *)&pydatetimeType, "Oi", obj,
@@ -474,7 +482,7 @@ psyco_TimeFromPy(PyObject *self, PyObject *args)
474482
{
475483
PyObject *obj;
476484

477-
if (!PyArg_ParseTuple(args, "O!", pyTimeTypeP, &obj))
485+
if (!PyArg_ParseTuple(args, "O!", PyDateTimeAPI->TimeType, &obj))
478486
return NULL;
479487

480488
return PyObject_CallFunction((PyObject *)&pydatetimeType, "Oi", obj,
@@ -486,7 +494,7 @@ psyco_TimestampFromPy(PyObject *self, PyObject *args)
486494
{
487495
PyObject *obj;
488496

489-
if (!PyArg_ParseTuple(args, "O!", pyDateTimeTypeP, &obj))
497+
if (!PyArg_ParseTuple(args, "O!", PyDateTimeAPI->DateTimeType, &obj))
490498
return NULL;
491499

492500
return PyObject_CallFunction((PyObject *)&pydatetimeType, "Oi", obj,
@@ -498,7 +506,7 @@ psyco_IntervalFromPy(PyObject *self, PyObject *args)
498506
{
499507
PyObject *obj;
500508

501-
if (!PyArg_ParseTuple(args, "O!", pyDeltaTypeP, &obj))
509+
if (!PyArg_ParseTuple(args, "O!", PyDateTimeAPI->DeltaType, &obj))
502510
return NULL;
503511

504512
return PyObject_CallFunction((PyObject *)&pydatetimeType, "Oi", obj,

psycopg/adapter_datetime.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ typedef struct {
5353
/* functions exported to psycopgmodule.c */
5454
#ifdef PSYCOPG_DEFAULT_PYDATETIME
5555

56+
HIDDEN int psyco_adapter_datetime_init(void);
57+
5658
HIDDEN PyObject *psyco_Date(PyObject *module, PyObject *args);
5759
#define psyco_Date_doc \
5860
"Date(year, month, day) -> new date\n\n" \

psycopg/psycopgmodule.c

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
#include "psycopg/adapter_asis.h"
4949
#include "psycopg/adapter_list.h"
5050
#include "psycopg/typecast_binary.h"
51+
#include "psycopg/typecast_datetime.h"
5152

5253
#ifdef HAVE_MXDATETIME
5354
#include <mxDateTime.h>
@@ -59,10 +60,6 @@ HIDDEN mxDateTimeModule_APIObject *mxDateTimeP = NULL;
5960
#include <datetime.h>
6061
#include "psycopg/adapter_datetime.h"
6162
HIDDEN PyObject *pyDateTimeModuleP = NULL;
62-
HIDDEN PyObject *pyDateTypeP = NULL;
63-
HIDDEN PyObject *pyTimeTypeP = NULL;
64-
HIDDEN PyObject *pyDateTimeTypeP = NULL;
65-
HIDDEN PyObject *pyDeltaTypeP = NULL;
6663

6764
/* pointers to the psycopg.tz classes */
6865
HIDDEN PyObject *pyPsycopgTzModule = NULL;
@@ -312,13 +309,13 @@ psyco_adapters_init(PyObject *mod)
312309
/* the module has already been initialized, so we can obtain the callable
313310
objects directly from its dictionary :) */
314311
call = PyMapping_GetItemString(mod, "DateFromPy");
315-
microprotocols_add((PyTypeObject*)pyDateTypeP, NULL, call);
312+
microprotocols_add(PyDateTimeAPI->DateType, NULL, call);
316313
call = PyMapping_GetItemString(mod, "TimeFromPy");
317-
microprotocols_add((PyTypeObject*)pyTimeTypeP, NULL, call);
314+
microprotocols_add(PyDateTimeAPI->TimeType, NULL, call);
318315
call = PyMapping_GetItemString(mod, "TimestampFromPy");
319-
microprotocols_add((PyTypeObject*)pyDateTimeTypeP, NULL, call);
316+
microprotocols_add(PyDateTimeAPI->DateTimeType, NULL, call);
320317
call = PyMapping_GetItemString(mod, "IntervalFromPy");
321-
microprotocols_add((PyTypeObject*)pyDeltaTypeP, NULL, call);
318+
microprotocols_add(PyDateTimeAPI->DeltaType, NULL, call);
322319

323320
#ifdef HAVE_MXDATETIME
324321
/* as above, we use the callable objects from the psycopg module */
@@ -776,16 +773,15 @@ init_psycopg(void)
776773
PyErr_SetString(PyExc_ImportError, "can't import datetime module");
777774
return;
778775
}
776+
777+
/* Initialize the PyDateTimeAPI everywhere is used */
778+
PyDateTime_IMPORT;
779+
if (psyco_adapter_datetime_init()) { return; }
780+
if (psyco_typecast_datetime_init()) { return; }
781+
779782
pydatetimeType.ob_type = &PyType_Type;
780783
if (PyType_Ready(&pydatetimeType) == -1) return;
781784

782-
/* now we define the datetime types, this is crazy because python should
783-
be doing that, not us! */
784-
pyDateTypeP = PyObject_GetAttrString(pyDateTimeModuleP, "date");
785-
pyTimeTypeP = PyObject_GetAttrString(pyDateTimeModuleP, "time");
786-
pyDateTimeTypeP = PyObject_GetAttrString(pyDateTimeModuleP, "datetime");
787-
pyDeltaTypeP = PyObject_GetAttrString(pyDateTimeModuleP, "timedelta");
788-
789785
/* import psycopg2.tz anyway (TODO: replace with C-level module?) */
790786
pyPsycopgTzModule = PyImport_ImportModule("psycopg2.tz");
791787
if (pyPsycopgTzModule == NULL) {

psycopg/typecast_datetime.c

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,19 @@
2626
#include <math.h>
2727
#include "datetime.h"
2828

29+
int
30+
psyco_typecast_datetime_init(void)
31+
{
32+
Dprintf("psyco_typecast_datetime_init: datetime init");
33+
34+
PyDateTime_IMPORT;
2935

30-
/* the pointer to the datetime module API is initialized by the module init
31-
code, we just need to grab it */
32-
extern HIDDEN PyObject* pyDateTimeModuleP;
33-
extern HIDDEN PyObject *pyDateTypeP;
34-
extern HIDDEN PyObject *pyTimeTypeP;
35-
extern HIDDEN PyObject *pyDateTimeTypeP;
36-
extern HIDDEN PyObject *pyDeltaTypeP;
36+
if (!PyDateTimeAPI) {
37+
PyErr_SetString(PyExc_ImportError, "datetime initialization failed");
38+
return -1;
39+
}
40+
return 0;
41+
}
3742

3843
/** DATE - cast a date into a date python object **/
3944

@@ -47,10 +52,12 @@ typecast_PYDATE_cast(const char *str, Py_ssize_t len, PyObject *curs)
4752

4853
if (!strcmp(str, "infinity") || !strcmp(str, "-infinity")) {
4954
if (str[0] == '-') {
50-
obj = PyObject_GetAttrString(pyDateTypeP, "min");
55+
obj = PyObject_GetAttrString(
56+
(PyObject*)PyDateTimeAPI->DateType, "min");
5157
}
5258
else {
53-
obj = PyObject_GetAttrString(pyDateTypeP, "max");
59+
obj = PyObject_GetAttrString(
60+
(PyObject*)PyDateTimeAPI->DateType, "max");
5461
}
5562
}
5663

@@ -66,7 +73,8 @@ typecast_PYDATE_cast(const char *str, Py_ssize_t len, PyObject *curs)
6673
}
6774
else {
6875
if (y > 9999) y = 9999;
69-
obj = PyObject_CallFunction(pyDateTypeP, "iii", y, m, d);
76+
obj = PyObject_CallFunction(
77+
(PyObject*)PyDateTimeAPI->DateType, "iii", y, m, d);
7078
}
7179
}
7280
return obj;
@@ -89,10 +97,12 @@ typecast_PYDATETIME_cast(const char *str, Py_ssize_t len, PyObject *curs)
8997
/* check for infinity */
9098
if (!strcmp(str, "infinity") || !strcmp(str, "-infinity")) {
9199
if (str[0] == '-') {
92-
obj = PyObject_GetAttrString(pyDateTimeTypeP, "min");
100+
obj = PyObject_GetAttrString(
101+
(PyObject*)PyDateTimeAPI->DateTimeType, "min");
93102
}
94103
else {
95-
obj = PyObject_GetAttrString(pyDateTimeTypeP, "max");
104+
obj = PyObject_GetAttrString(
105+
(PyObject*)PyDateTimeAPI->DateTimeType, "max");
96106
}
97107
}
98108

@@ -144,8 +154,9 @@ typecast_PYDATETIME_cast(const char *str, Py_ssize_t len, PyObject *curs)
144154
tzinfo = Py_None;
145155
}
146156
if (tzinfo != NULL) {
147-
obj = PyObject_CallFunction(pyDateTimeTypeP, "iiiiiiiO",
148-
y, m, d, hh, mm, ss, us, tzinfo);
157+
obj = PyObject_CallFunction(
158+
(PyObject*)PyDateTimeAPI->DateTimeType, "iiiiiiiO",
159+
y, m, d, hh, mm, ss, us, tzinfo);
149160
Dprintf("typecast_PYDATETIME_cast: tzinfo: %p, refcnt = "
150161
FORMAT_CODE_PY_SSIZE_T,
151162
tzinfo, tzinfo->ob_refcnt
@@ -197,7 +208,7 @@ typecast_PYTIME_cast(const char *str, Py_ssize_t len, PyObject *curs)
197208
tzinfo = Py_None;
198209
}
199210
if (tzinfo != NULL) {
200-
obj = PyObject_CallFunction(pyTimeTypeP, "iiiiO",
211+
obj = PyObject_CallFunction((PyObject*)PyDateTimeAPI->TimeType, "iiiiO",
201212
hh, mm, ss, us, tzinfo);
202213
Py_DECREF(tzinfo);
203214
}
@@ -308,7 +319,7 @@ typecast_PYINTERVAL_cast(const char *str, Py_ssize_t len, PyObject *curs)
308319

309320
micro = (seconds - floor(seconds)) * 1000000.0;
310321
sec = (int)floor(seconds);
311-
return PyObject_CallFunction(pyDeltaTypeP, "iii",
322+
return PyObject_CallFunction((PyObject*)PyDateTimeAPI->DeltaType, "iii",
312323
days, sec, (int)round(micro));
313324
}
314325

psycopg/typecast_datetime.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/* typecast_datetime.h - definitions for datetime objects typecasters
2+
*
3+
* Copyright (C) 2010 Daniele Varrazzo <daniele.varrazzo@gmail.com>
4+
*
5+
* This file is part of psycopg.
6+
*
7+
* psycopg2 is free software: you can redistribute it and/or modify it
8+
* under the terms of the GNU Lesser General Public License as published
9+
* by the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* In addition, as a special exception, the copyright holders give
13+
* permission to link this program with the OpenSSL library (or with
14+
* modified versions of OpenSSL that use the same license as OpenSSL),
15+
* and distribute linked combinations including the two.
16+
*
17+
* You must obey the GNU Lesser General Public License in all respects for
18+
* all of the code used other than OpenSSL.
19+
*
20+
* psycopg2 is distributed in the hope that it will be useful, but WITHOUT
21+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
22+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
23+
* License for more details.
24+
*/
25+
26+
#ifndef PSYCOPG_TYPECAST_DATETIME_H
27+
#define PSYCOPG_TYPECAST_DATETIME_H 1
28+
29+
#define PY_SSIZE_T_CLEAN
30+
#include <Python.h>
31+
32+
#include "psycopg/config.h"
33+
34+
#ifdef __cplusplus
35+
extern "C" {
36+
#endif
37+
38+
HIDDEN int psyco_typecast_datetime_init(void);
39+
40+
#ifdef __cplusplus
41+
}
42+
#endif
43+
44+
#endif /* !defined(PSYCOPG_TYPECAST_DATETIME_H) */

0 commit comments

Comments
 (0)