Merge remote-tracking branch 'origin/pycurl' into planetlab-4_0-branch
[plcapi.git] / trunk / psycopg2 / psycopg / psycopgmodule.c
1 /* psycopgmodule.c - psycopg module (will import other C classes)
2  *
3  * Copyright (C) 2003 Federico Di Gregorio <fog@debian.org>
4  *
5  * This file is part of psycopg.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2,
10  * or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */
21
22 #include <Python.h>
23
24 #define PSYCOPG_MODULE
25 #include "psycopg/config.h"
26 #include "psycopg/python.h"
27 #include "psycopg/psycopg.h"
28 #include "psycopg/connection.h"
29 #include "psycopg/cursor.h"
30 #include "psycopg/typecast.h"
31 #include "psycopg/microprotocols.h"
32 #include "psycopg/microprotocols_proto.h"
33
34 #include "psycopg/adapter_qstring.h"
35 #include "psycopg/adapter_binary.h"
36 #include "psycopg/adapter_pboolean.h"
37 #include "psycopg/adapter_asis.h"
38 #include "psycopg/adapter_list.h"
39 #include "psycopg/typecast_binary.h"
40
41 #ifdef HAVE_MXDATETIME
42 #include <mxDateTime.h>
43 #include "psycopg/adapter_mxdatetime.h"
44 mxDateTimeModule_APIObject *mxDateTimeP = NULL;
45 #endif
46
47 /* some module-level variables, like the datetime module */
48 #ifdef HAVE_PYDATETIME
49 #include <datetime.h>
50 #include "psycopg/adapter_datetime.h"
51 PyObject *pyDateTimeModuleP = NULL;
52 PyObject *pyDateTypeP = NULL;
53 PyObject *pyTimeTypeP = NULL;
54 PyObject *pyDateTimeTypeP = NULL;
55 PyObject *pyDeltaTypeP = NULL;
56 #endif
57
58 /* pointers to the psycopg.tz classes */
59 PyObject *pyPsycopgTzModule = NULL;
60 PyObject *pyPsycopgTzLOCAL = NULL;
61 PyObject *pyPsycopgTzFixedOffsetTimezone = NULL;
62
63 PyObject *psycoEncodings = NULL;
64 PyObject *decimalType = NULL;
65
66 /** connect module-level function **/
67 #define psyco_connect_doc \
68 "connect(dsn, ...) -- Create a new database connection.\n\n"               \
69 "This function supports two different but equivalent sets of arguments.\n" \
70 "A single data source name or ``dsn`` string can be used to specify the\n" \
71 "connection parameters, as follows::\n\n"                                  \
72 "    psycopg2.connect(\"dbname=xxx user=xxx ...\")\n\n"   \
73 "If ``dsn`` is not provided it is possible to pass the parameters as\n"    \
74 "keyword arguments; e.g.::\n\n"                                            \
75 "    psycopg2.connect(database='xxx', user='xxx', ...)\n\n"                \
76 "The full list of available parameters is:\n\n"                            \
77 "- ``dbname`` -- database name (only in 'dsn')\n"                          \
78 "- ``database`` -- database name (only as keyword argument)\n"             \
79 "- ``host`` -- host address (defaults to UNIX socket if not provided)\n"   \
80 "- ``port`` -- port number (defaults to 5432 if not provided)\n"           \
81 "- ``user`` -- user name used to authenticate\n"                           \
82 "- ``password`` -- password used to authenticate\n"                        \
83 "- ``sslmode`` -- SSL mode (see PostgreSQL documentation)\n\n"             \
84 "If the ``connection_factory`` keyword argument is not provided this\n"    \
85 "function always return an instance of the `connection` class.\n"          \
86 "Else the given sub-class of `extensions.connection` will be used to\n"    \
87 "instantiate the connection object.\n\n"                                   \
88 ":return: New database connection\n"                                         \
89 ":rtype: `extensions.connection`"
90
91 static int
92 _psyco_connect_fill_dsn(char *dsn, char *kw, char *v, int i)
93 {
94     strcpy(&dsn[i], kw); i += strlen(kw);
95     strcpy(&dsn[i], v); i += strlen(v);
96     return i;
97 }
98
99 static void
100 _psyco_connect_fill_exc(connectionObject *conn)
101 {
102     /* fill the connection object with the exceptions */
103     conn->exc_Error = Error;
104     Py_INCREF(Error);
105     conn->exc_Warning = Warning;
106     Py_INCREF(Warning);
107     conn->exc_InterfaceError = InterfaceError;
108     Py_INCREF(InterfaceError);
109     conn->exc_DatabaseError = DatabaseError;
110     Py_INCREF(DatabaseError);
111     conn->exc_InternalError = InternalError;
112     Py_INCREF(InternalError);
113     conn->exc_ProgrammingError = ProgrammingError;
114     Py_INCREF(ProgrammingError);
115     conn->exc_IntegrityError = IntegrityError;
116     Py_INCREF(IntegrityError);
117     conn->exc_DataError = DataError;
118     Py_INCREF(DataError);
119     conn->exc_NotSupportedError = NotSupportedError;
120     Py_INCREF(NotSupportedError);
121     conn->exc_OperationalError = OperationalError;
122     Py_INCREF(OperationalError);
123 }
124
125 static PyObject *
126 psyco_connect(PyObject *self, PyObject *args, PyObject *keywds)
127 {
128     PyObject *conn, *factory = NULL;
129     PyObject *pyport = NULL;
130     
131     int idsn=-1, iport=-1;
132     char *dsn=NULL, *database=NULL, *user=NULL, *password=NULL;
133     char *host=NULL, *sslmode=NULL;
134     char port[16];
135     
136     static char *kwlist[] = {"dsn", "database", "host", "port",
137                              "user", "password", "sslmode",
138                              "connection_factory", NULL};
139     
140     if (!PyArg_ParseTupleAndKeywords(args, keywds, "|sssOsssO", kwlist,
141                                      &dsn, &database, &host, &pyport,
142                                      &user, &password, &sslmode, &factory)) {
143         return NULL;
144     }
145
146     if (pyport && PyString_Check(pyport)) {
147         PyObject *pyint = PyInt_FromString(PyString_AsString(pyport), NULL, 10);
148         if (!pyint) return NULL;
149         iport = PyInt_AsLong(pyint);
150     }
151     else if (pyport && PyInt_Check(pyport)) {
152         iport = PyInt_AsLong(pyport);
153     }
154     else if (pyport != NULL) {
155         PyErr_SetString(PyExc_TypeError, "port must be a string or int");
156         return NULL;
157     }
158
159     if (iport > 0)
160       PyOS_snprintf(port, 16, "%d", iport);
161
162     if (dsn == NULL) {
163         int l = 45;  /* len("dbname= user= password= host= port= sslmode=\0") */
164
165         if (database) l += strlen(database);
166         if (host) l += strlen(host);
167         if (iport > 0) l += strlen(port);
168         if (user) l += strlen(user);
169         if (password) l += strlen(password);
170         if (sslmode) l += strlen(sslmode);
171         
172         dsn = malloc(l*sizeof(char));
173         if (dsn == NULL) {
174             PyErr_SetString(InterfaceError, "dynamic dsn allocation failed");
175             return NULL;
176         }
177
178         idsn = 0;
179         if (database)
180             idsn = _psyco_connect_fill_dsn(dsn, " dbname=", database, idsn);
181         if (host)
182             idsn = _psyco_connect_fill_dsn(dsn, " host=", host, idsn);
183         if (iport > 0)
184             idsn = _psyco_connect_fill_dsn(dsn, " port=", port, idsn);
185         if (user)
186             idsn = _psyco_connect_fill_dsn(dsn, " user=", user, idsn);
187         if (password)
188             idsn = _psyco_connect_fill_dsn(dsn, " password=", password, idsn);
189         if (sslmode)
190             idsn = _psyco_connect_fill_dsn(dsn, " sslmode=", sslmode, idsn);
191         
192         if (idsn > 0) {
193             dsn[idsn] = '\0';
194             memmove(dsn, &dsn[1], idsn);
195         }
196         else {
197             free(dsn);
198             PyErr_SetString(InterfaceError, "missing dsn and no parameters");
199             return NULL;
200         }
201     }
202
203     Dprintf("psyco_connect: dsn = '%s'", dsn);
204
205     /* allocate connection, fill with errors and return it */
206     if (factory == NULL) factory = (PyObject *)&connectionType;
207     conn = PyObject_CallFunction(factory, "s", dsn);
208     if (conn) _psyco_connect_fill_exc((connectionObject*)conn);
209     
210     return conn;
211 }
212
213 /** type registration **/
214 #define psyco_register_type_doc \
215 "register_type(obj) -> None -- register obj with psycopg type system\n\n" \
216 ":Parameters:\n" \
217 "  * `obj`: A type adapter created by `new_type()`"
218
219 #define typecast_from_python_doc \
220 "new_type(oids, name, adapter) -> new type object\n\n" \
221 "Create a new binding object. The object can be used with the\n" \
222 "`register_type()` function to bind PostgreSQL objects to python objects.\n\n" \
223 ":Parameters:\n" \
224 "  * `oids`: Tuple of ``oid`` of the PostgreSQL types to convert.\n" \
225 "  * `name`: Name for the new type\n" \
226 "  * `adapter`: Callable to perform type conversion.\n" \
227 "    It must have the signature ``fun(value, cur)`` where ``value`` is\n" \
228 "    the string representation returned by PostgreSQL (`None` if ``NULL``)\n" \
229 "    and ``cur`` is the cursor from which data are read."
230
231 static PyObject *
232 psyco_register_type(PyObject *self, PyObject *args)
233 {
234     PyObject *type;
235
236     if (!PyArg_ParseTuple(args, "O!", &typecastType, &type)) {
237         return NULL;
238     }
239
240     typecast_add(type, 0);
241     
242     Py_INCREF(Py_None);
243     return Py_None;
244 }
245
246
247 /* default adapters */
248
249 static void
250 psyco_adapters_init(PyObject *mod)
251 {
252     PyObject *call;
253     
254     microprotocols_add(&PyFloat_Type, NULL, (PyObject*)&asisType);
255     microprotocols_add(&PyInt_Type, NULL, (PyObject*)&asisType);
256     microprotocols_add(&PyLong_Type, NULL, (PyObject*)&asisType);
257     
258     microprotocols_add(&PyString_Type, NULL, (PyObject*)&qstringType);
259     microprotocols_add(&PyUnicode_Type, NULL, (PyObject*)&qstringType);
260     microprotocols_add(&PyBuffer_Type, NULL, (PyObject*)&binaryType);
261     microprotocols_add(&PyList_Type, NULL, (PyObject*)&listType);
262                        
263 #ifdef HAVE_MXDATETIME
264     /* the module has already been initialized, so we can obtain the callable
265        objects directly from its dictionary :) */
266     call = PyMapping_GetItemString(mod, "TimestampFromMx");
267     microprotocols_add(mxDateTimeP->DateTime_Type, NULL, call);
268     call = PyMapping_GetItemString(mod, "TimeFromMx");
269     microprotocols_add(mxDateTimeP->DateTimeDelta_Type, NULL, call);
270 #endif
271
272 #ifdef HAVE_PYDATETIME
273     /* as above, we use the callable objects from the psycopg module */
274     call = PyMapping_GetItemString(mod, "DateFromPy");
275     microprotocols_add((PyTypeObject*)pyDateTypeP, NULL, call);
276     call = PyMapping_GetItemString(mod, "TimeFromPy");
277     microprotocols_add((PyTypeObject*)pyTimeTypeP, NULL, call);
278     call = PyMapping_GetItemString(mod, "TimestampFromPy");
279     microprotocols_add((PyTypeObject*)pyDateTimeTypeP, NULL, call);
280     call = PyMapping_GetItemString(mod, "IntervalFromPy");
281     microprotocols_add((PyTypeObject*)pyDeltaTypeP, NULL, call);
282 #endif
283     
284 #ifdef HAVE_PYBOOL
285     microprotocols_add(&PyBool_Type, NULL, (PyObject*)&pbooleanType);
286 #endif
287
288 #ifdef HAVE_DECIMAL
289     microprotocols_add((PyTypeObject*)decimalType, NULL, (PyObject*)&asisType);
290 #endif
291 }
292
293 /* psyco_encodings_fill
294    
295    Fill the module's postgresql<->python encoding table */
296
297 static encodingPair encodings[] = {
298     {"SQL_ASCII",    "ascii"},
299     {"LATIN1",       "latin_1"},
300     {"UNICODE",      "utf_8"},
301     {"UTF8",         "utf_8"},
302     
303     /* some compatibility stuff */
304     {"LATIN-1",      "latin_1"},
305     
306     {NULL, NULL}
307 };
308 static void psyco_encodings_fill(PyObject *dict)
309 {
310     encodingPair *enc;
311
312     for (enc = encodings; enc->pgenc != NULL; enc++) {
313         PyObject *value = PyString_FromString(enc->pyenc);
314         PyDict_SetItemString(dict, enc->pgenc, value);
315         Py_DECREF(value);
316     }
317 }
318
319 /* psyco_errors_init, psyco_errors_fill (callable from C)
320
321    Initialize the module's exceptions and after that a dictionary with a full
322    set of exceptions. */
323
324 PyObject *Error, *Warning, *InterfaceError, *DatabaseError,
325     *InternalError, *OperationalError, *ProgrammingError,
326     *IntegrityError, *DataError, *NotSupportedError;
327
328 /* mapping between exception names and their PyObject */
329 static struct {
330     char *name;
331     PyObject **exc;
332     PyObject **base;
333     char *docstr;
334 } exctable[] = {
335     { "psycopg2.Error", &Error, 0, Error_doc },
336     { "psycopg2.Warning", &Warning, 0, Warning_doc },
337     { "psycopg2.InterfaceError", &InterfaceError, &Error, InterfaceError_doc },
338     { "psycopg2.DatabaseError", &DatabaseError, &Error, DatabaseError_doc },
339     { "psycopg2.InternalError", &InternalError, &DatabaseError, InternalError_doc },
340     { "psycopg2.OperationalError", &OperationalError, &DatabaseError, 
341         OperationalError_doc },
342     { "psycopg2.ProgrammingError", &ProgrammingError, &DatabaseError, 
343         ProgrammingError_doc },
344     { "psycopg2.IntegrityError", &IntegrityError, &DatabaseError, 
345         IntegrityError_doc },
346     { "psycopg2.DataError", &DataError, &DatabaseError, DataError_doc },
347     { "psycopg2.NotSupportedError", &NotSupportedError, &DatabaseError, 
348         NotSupportedError_doc },
349     {NULL}  /* Sentinel */
350 };
351
352 static void
353 psyco_errors_init(void)
354 {
355     /* the names of the exceptions here reflect the oranization of the
356        psycopg2 module and not the fact the the original error objects
357        live in _psycopg */
358        
359     int i;
360     PyObject *dict;
361     PyObject *base;
362     PyObject *str;
363
364     for (i=0; exctable[i].name; i++) {
365         dict = PyDict_New();
366
367         if (exctable[i].docstr) {
368             str = PyString_FromString(exctable[i].docstr);
369             PyDict_SetItemString(dict, "__doc__", str);
370         }
371
372         if (exctable[i].base == 0)
373             base = PyExc_StandardError;
374         else
375             base = *exctable[i].base;
376
377         *exctable[i].exc = PyErr_NewException(exctable[i].name, base, dict);
378     }
379 }
380
381 void
382 psyco_errors_fill(PyObject *dict)
383 {
384     PyDict_SetItemString(dict, "Error", Error);
385     PyDict_SetItemString(dict, "Warning", Warning);
386     PyDict_SetItemString(dict, "InterfaceError", InterfaceError);
387     PyDict_SetItemString(dict, "DatabaseError", DatabaseError);
388     PyDict_SetItemString(dict, "InternalError", InternalError);
389     PyDict_SetItemString(dict, "OperationalError", OperationalError);
390     PyDict_SetItemString(dict, "ProgrammingError", ProgrammingError);
391     PyDict_SetItemString(dict, "IntegrityError", IntegrityError);
392     PyDict_SetItemString(dict, "DataError", DataError);
393     PyDict_SetItemString(dict, "NotSupportedError", NotSupportedError);    
394 }
395
396 void
397 psyco_errors_set(PyObject *type)
398 {
399     PyObject_SetAttrString(type, "Error", Error);
400     PyObject_SetAttrString(type, "Warning", Warning);
401     PyObject_SetAttrString(type, "InterfaceError", InterfaceError);
402     PyObject_SetAttrString(type, "DatabaseError", DatabaseError);
403     PyObject_SetAttrString(type, "InternalError", InternalError);
404     PyObject_SetAttrString(type, "OperationalError", OperationalError);
405     PyObject_SetAttrString(type, "ProgrammingError", ProgrammingError);
406     PyObject_SetAttrString(type, "IntegrityError", IntegrityError);
407     PyObject_SetAttrString(type, "DataError", DataError);
408     PyObject_SetAttrString(type, "NotSupportedError", NotSupportedError);
409 }
410
411 /* psyco_error_new
412   
413    Create a new error of the given type with extra attributes. */
414    
415 void
416 psyco_set_error(PyObject *exc, PyObject *curs, char *msg, 
417                  char *pgerror, char *pgcode)
418 {
419     PyObject *t;
420     
421     PyObject *err = PyObject_CallFunction(exc, "s", msg);
422   
423     if (err) {
424         if (pgerror) {
425             t = PyString_FromString(pgerror);
426         }
427         else {
428             t = Py_None ; Py_INCREF(t);
429         }
430         PyObject_SetAttrString(err, "pgerror", t);
431         Py_DECREF(t);
432
433         if (pgcode) {
434             t = PyString_FromString(pgcode);
435         }
436         else {
437             t = Py_None ; Py_INCREF(t);
438         }
439         PyObject_SetAttrString(err, "pgcode", t);
440         Py_DECREF(t);
441         
442         if (curs)
443             PyObject_SetAttrString(err, "cursor", curs);
444         else
445             PyObject_SetAttrString(err, "cursor", Py_None);
446
447         PyErr_SetObject(exc, err);
448         Py_DECREF(err);
449     }
450
451
452 /* psyco_decimal_init
453
454    Initialize the module's pointer to the decimal type. */
455
456 void
457 psyco_decimal_init(void)
458 {
459 #ifdef HAVE_DECIMAL
460     PyObject *decimal = PyImport_ImportModule("decimal");
461     if (decimal) {
462         decimalType = PyObject_GetAttrString(decimal, "Decimal");
463     }
464     else {
465         PyErr_Clear();
466         decimalType = (PyObject *)&PyFloat_Type;
467         Py_INCREF(decimalType);
468     }
469 #endif
470 }
471
472
473 /** method table and module initialization **/
474
475 static PyMethodDef psycopgMethods[] = {
476     {"connect",  (PyCFunction)psyco_connect,
477      METH_VARARGS|METH_KEYWORDS, psyco_connect_doc},
478     {"adapt",  (PyCFunction)psyco_microprotocols_adapt,
479      METH_VARARGS, psyco_microprotocols_adapt_doc},
480
481     {"register_type", (PyCFunction)psyco_register_type,
482      METH_VARARGS, psyco_register_type_doc},
483     {"new_type", (PyCFunction)typecast_from_python,
484      METH_VARARGS|METH_KEYWORDS, typecast_from_python_doc},
485
486     {"AsIs",  (PyCFunction)psyco_AsIs,
487      METH_VARARGS, psyco_AsIs_doc},
488     {"QuotedString",  (PyCFunction)psyco_QuotedString,
489      METH_VARARGS, psyco_QuotedString_doc},
490     {"Boolean",  (PyCFunction)psyco_Boolean,
491      METH_VARARGS, psyco_Boolean_doc},
492     {"Binary",  (PyCFunction)psyco_Binary,
493      METH_VARARGS, psyco_Binary_doc},
494     {"Date",  (PyCFunction)psyco_Date,
495      METH_VARARGS, psyco_Date_doc},
496     {"Time",  (PyCFunction)psyco_Time,
497      METH_VARARGS, psyco_Time_doc},
498     {"Timestamp",  (PyCFunction)psyco_Timestamp,
499      METH_VARARGS, psyco_Timestamp_doc},
500     {"DateFromTicks",  (PyCFunction)psyco_DateFromTicks,
501      METH_VARARGS, psyco_DateFromTicks_doc},
502     {"TimeFromTicks",  (PyCFunction)psyco_TimeFromTicks,
503      METH_VARARGS, psyco_TimeFromTicks_doc},
504     {"TimestampFromTicks",  (PyCFunction)psyco_TimestampFromTicks,
505      METH_VARARGS, psyco_TimestampFromTicks_doc},
506     {"List",  (PyCFunction)psyco_List,
507      METH_VARARGS, psyco_List_doc},
508     
509 #ifdef HAVE_MXDATETIME
510     {"DateFromMx",  (PyCFunction)psyco_DateFromMx,
511      METH_VARARGS, psyco_DateFromMx_doc},
512     {"TimeFromMx",  (PyCFunction)psyco_TimeFromMx,
513      METH_VARARGS, psyco_TimeFromMx_doc},
514     {"TimestampFromMx",  (PyCFunction)psyco_TimestampFromMx,
515      METH_VARARGS, psyco_TimestampFromMx_doc},
516     {"IntervalFromMx",  (PyCFunction)psyco_IntervalFromMx,
517      METH_VARARGS, psyco_IntervalFromMx_doc}, 
518 #endif
519
520 #ifdef HAVE_PYDATETIME
521     {"DateFromPy",  (PyCFunction)psyco_DateFromPy,
522      METH_VARARGS, psyco_DateFromPy_doc},
523     {"TimeFromPy",  (PyCFunction)psyco_TimeFromPy,
524      METH_VARARGS, psyco_TimeFromPy_doc},
525     {"TimestampFromPy",  (PyCFunction)psyco_TimestampFromPy,
526      METH_VARARGS, psyco_TimestampFromPy_doc},
527     {"IntervalFromPy",  (PyCFunction)psyco_IntervalFromPy,
528      METH_VARARGS, psyco_IntervalFromPy_doc},     
529 #endif
530
531     {NULL, NULL, 0, NULL}        /* Sentinel */
532 };
533
534 PyMODINIT_FUNC
535 init_psycopg(void)
536 {
537     static void *PSYCOPG_API[PSYCOPG_API_pointers];
538     
539     PyObject *module, *dict;
540     PyObject *c_api_object;
541
542     Dprintf("initpsycopg: initializing psycopg %s", PSYCOPG_VERSION);
543
544     /* initialize all the new types and then the module */
545     connectionType.ob_type = &PyType_Type;
546     cursorType.ob_type     = &PyType_Type;
547     typecastType.ob_type   = &PyType_Type;
548     qstringType.ob_type    = &PyType_Type;
549     binaryType.ob_type     = &PyType_Type;
550     isqlquoteType.ob_type  = &PyType_Type;
551     asisType.ob_type       = &PyType_Type;
552     listType.ob_type       = &PyType_Type;
553     chunkType.ob_type      = &PyType_Type;
554     
555     if (PyType_Ready(&connectionType) == -1) return;
556     if (PyType_Ready(&cursorType) == -1) return;
557     if (PyType_Ready(&typecastType) == -1) return;
558     if (PyType_Ready(&qstringType) == -1) return;
559     if (PyType_Ready(&binaryType) == -1) return;
560     if (PyType_Ready(&isqlquoteType) == -1) return;
561     if (PyType_Ready(&asisType) == -1) return;
562     if (PyType_Ready(&listType) == -1) return;
563     if (PyType_Ready(&chunkType) == -1) return;
564     
565 #ifdef HAVE_PYBOOL
566     pbooleanType.ob_type   = &PyType_Type;
567     if (PyType_Ready(&pbooleanType) == -1) return;
568 #endif
569     
570     /* import mx.DateTime module, if necessary */
571 #ifdef HAVE_MXDATETIME
572     mxdatetimeType.ob_type = &PyType_Type;
573     if (PyType_Ready(&mxdatetimeType) == -1) return;
574     if (mxDateTime_ImportModuleAndAPI() != 0) {
575         Dprintf("initpsycopg: why marc hide mx.DateTime again?!"); 
576         PyErr_SetString(PyExc_ImportError, "can't import mx.DateTime module");
577         return;
578     }
579     mxDateTimeP = &mxDateTime;
580 #endif
581
582     /* import python builtin datetime module, if available */
583 #ifdef HAVE_PYDATETIME
584     pyDateTimeModuleP = PyImport_ImportModule("datetime");
585     if (pyDateTimeModuleP == NULL) {
586         Dprintf("initpsycopg: can't import datetime module"); 
587         PyErr_SetString(PyExc_ImportError, "can't import datetime module");
588         return;
589     }
590     pydatetimeType.ob_type = &PyType_Type;
591     if (PyType_Ready(&pydatetimeType) == -1) return;
592
593     /* now we define the datetime types, this is crazy because python should
594        be doing that, not us! */
595     pyDateTypeP = PyObject_GetAttrString(pyDateTimeModuleP, "date");
596     pyTimeTypeP = PyObject_GetAttrString(pyDateTimeModuleP, "time");
597     pyDateTimeTypeP = PyObject_GetAttrString(pyDateTimeModuleP, "datetime");
598     pyDeltaTypeP = PyObject_GetAttrString(pyDateTimeModuleP, "timedelta");
599 #endif    
600
601     /* import psycopg2.tz anyway (TODO: replace with C-level module?) */
602     pyPsycopgTzModule = PyImport_ImportModule("psycopg2.tz");
603     if (pyPsycopgTzModule == NULL) {
604         Dprintf("initpsycopg: can't import psycopg2.tz module"); 
605         PyErr_SetString(PyExc_ImportError, "can't import psycopg2.tz module");
606         return;        
607     }
608     pyPsycopgTzLOCAL = 
609         PyObject_GetAttrString(pyPsycopgTzModule, "LOCAL"); 
610     pyPsycopgTzFixedOffsetTimezone = 
611         PyObject_GetAttrString(pyPsycopgTzModule, "FixedOffsetTimezone");
612         
613     /* initialize the module and grab module's dictionary */
614     module = Py_InitModule("_psycopg", psycopgMethods);
615     dict = PyModule_GetDict(module);
616
617     /* initialize all the module's exported functions */
618     /* PyBoxer_API[PyBoxer_Fake_NUM] = (void *)PyBoxer_Fake; */
619
620     /* Create a CObject containing the API pointer array's address */
621     c_api_object = PyCObject_FromVoidPtr((void *)PSYCOPG_API, NULL);
622     if (c_api_object != NULL)
623         PyModule_AddObject(module, "_C_API", c_api_object);
624
625     /* other mixed initializations of module-level variables */
626     psycoEncodings = PyDict_New();
627     psyco_encodings_fill(psycoEncodings);
628     psyco_decimal_init();
629     
630     /* set some module's parameters */
631     PyModule_AddStringConstant(module, "__version__", PSYCOPG_VERSION);
632     PyModule_AddStringConstant(module, "__doc__", "psycopg PostgreSQL driver");
633     PyModule_AddObject(module, "apilevel", PyString_FromString(APILEVEL));
634     PyModule_AddObject(module, "threadsafety", PyInt_FromLong(THREADSAFETY));
635     PyModule_AddObject(module, "paramstyle", PyString_FromString(PARAMSTYLE));
636     
637     /* put new types in module dictionary */
638     PyModule_AddObject(module, "connection", (PyObject*)&connectionType);
639     PyModule_AddObject(module, "cursor", (PyObject*)&cursorType);
640     PyModule_AddObject(module, "ISQLQuote", (PyObject*)&isqlquoteType);
641     
642     /* encodings dictionary in module dictionary */
643     PyModule_AddObject(module, "encodings", psycoEncodings);
644     
645     /* initialize default set of typecasters */
646     typecast_init(dict);
647
648     /* initialize microprotocols layer */
649     microprotocols_init(dict);
650     psyco_adapters_init(dict);
651     
652     /* create a standard set of exceptions and add them to the module's dict */
653     psyco_errors_init();
654     psyco_errors_fill(dict);
655     
656     /* Solve win32 build issue about non-constant initializer element */
657     cursorType.tp_alloc = PyType_GenericAlloc;
658     binaryType.tp_alloc = PyType_GenericAlloc;
659     isqlquoteType.tp_alloc = PyType_GenericAlloc;
660     pbooleanType.tp_alloc = PyType_GenericAlloc;
661     connectionType.tp_alloc = PyType_GenericAlloc;
662     asisType.tp_alloc = PyType_GenericAlloc;
663     qstringType.tp_alloc = PyType_GenericAlloc;
664     listType.tp_alloc = PyType_GenericAlloc;
665     chunkType.tp_alloc = PyType_GenericAlloc;
666     
667 #ifdef HAVE_PYDATETIME
668     pydatetimeType.tp_alloc = PyType_GenericAlloc;
669 #endif
670     
671     Dprintf("initpsycopg: module initialization complete");
672 }