~groldster/ubuntu/maverick/psycopg2/merge-611040

« back to all changes in this revision

Viewing changes to psycopg/psycopgmodule.c

  • Committer: Bazaar Package Importer
  • Author(s): Fabio Tranchitella
  • Date: 2006-08-09 10:28:30 UTC
  • Revision ID: james.westby@ubuntu.com-20060809102830-grac1dsp24uyqfp4
Tags: upstream-2.0.4
ImportĀ upstreamĀ versionĀ 2.0.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
}
 
122
 
 
123
static PyObject *
 
124
psyco_connect(PyObject *self, PyObject *args, PyObject *keywds)
 
125
{
 
126
    PyObject *conn, *factory = NULL;
 
127
    
 
128
    int idsn=-1, iport=-1;
 
129
    char *dsn=NULL, *database=NULL, *user=NULL, *password=NULL;
 
130
    char *host=NULL, *sslmode=NULL;
 
131
    char port[16];
 
132
    
 
133
    static char *kwlist[] = {"dsn", "database", "host", "port",
 
134
                             "user", "password", "sslmode",
 
135
                             "connection_factory", NULL};
 
136
    
 
137
    if (!PyArg_ParseTupleAndKeywords(args, keywds, "|sssisssO", kwlist,
 
138
                                     &dsn, &database, &host, &iport,
 
139
                                     &user, &password, &sslmode, &factory)) {
 
140
        return NULL;
 
141
    }
 
142
 
 
143
        if (iport > 0)
 
144
                PyOS_snprintf(port, 16, "%d", iport);
 
145
                
 
146
    if (dsn == NULL) {
 
147
        int l = 45;  /* len("dbname= user= password= host= port= sslmode=\0") */
 
148
 
 
149
        if (database) l += strlen(database);
 
150
        if (host) l += strlen(host);
 
151
        if (iport > 0) l += strlen(port);
 
152
        if (user) l += strlen(user);
 
153
        if (password) l += strlen(password);
 
154
        if (sslmode) l += strlen(sslmode);
 
155
        
 
156
        dsn = malloc(l*sizeof(char));
 
157
        if (dsn == NULL) {
 
158
            PyErr_SetString(InterfaceError, "dynamic dsn allocation failed");
 
159
            return NULL;
 
160
        }
 
161
 
 
162
        idsn = 0;
 
163
        if (database)
 
164
            idsn = _psyco_connect_fill_dsn(dsn, " dbname=", database, idsn);
 
165
        if (host)
 
166
            idsn = _psyco_connect_fill_dsn(dsn, " host=", host, idsn);
 
167
        if (iport > 0)
 
168
            idsn = _psyco_connect_fill_dsn(dsn, " port=", port, idsn);
 
169
        if (user)
 
170
            idsn = _psyco_connect_fill_dsn(dsn, " user=", user, idsn);
 
171
        if (password)
 
172
            idsn = _psyco_connect_fill_dsn(dsn, " password=", password, idsn);
 
173
        if (sslmode)
 
174
            idsn = _psyco_connect_fill_dsn(dsn, " sslmode=", sslmode, idsn);
 
175
        
 
176
        if (idsn > 0) {
 
177
            dsn[idsn] = '\0';
 
178
            memmove(dsn, &dsn[1], idsn);
 
179
        }
 
180
        else {
 
181
            free(dsn);
 
182
            PyErr_SetString(InterfaceError, "missing dsn and no parameters");
 
183
            return NULL;
 
184
        }
 
185
    }
 
186
 
 
187
    Dprintf("psyco_connect: dsn = '%s'", dsn);
 
188
 
 
189
    /* allocate connection, fill with errors and return it */
 
190
    if (factory == NULL) factory = (PyObject *)&connectionType;
 
191
    conn = PyObject_CallFunction(factory, "s", dsn);
 
192
    if (conn) _psyco_connect_fill_exc((connectionObject*)conn);
 
193
    
 
194
    return conn;
 
195
}
 
196
 
 
197
/** type registration **/
 
198
#define psyco_register_type_doc \
 
199
"register_type(obj) -> None -- register obj with psycopg type system\n\n" \
 
200
":Parameters:\n" \
 
201
"  * `obj`: A type adapter created by `new_type()`"
 
202
 
 
203
#define typecast_from_python_doc \
 
204
"new_type(oids, name, adapter) -> new type object\n\n" \
 
205
"Create a new binding object. The object can be used with the\n" \
 
206
"`register_type()` function to bind PostgreSQL objects to python objects.\n\n" \
 
207
":Parameters:\n" \
 
208
"  * `oids`: Tuple of ``oid`` of the PostgreSQL types to convert.\n" \
 
209
"  * `name`: Name for the new type\n" \
 
210
"  * `adapter`: Callable to perform type conversion.\n" \
 
211
"    It must have the signature ``fun(value, cur)`` where ``value`` is\n" \
 
212
"    the string representation returned by PostgreSQL (`None` if ``NULL``)\n" \
 
213
"    and ``cur`` is the cursor from which data are read."
 
214
 
 
215
static PyObject *
 
216
psyco_register_type(PyObject *self, PyObject *args)
 
217
{
 
218
    PyObject *type;
 
219
 
 
220
    if (!PyArg_ParseTuple(args, "O!", &typecastType, &type)) {
 
221
        return NULL;
 
222
    }
 
223
 
 
224
    typecast_add(type, 0);
 
225
    
 
226
    Py_INCREF(Py_None);
 
227
    return Py_None;
 
228
}
 
229
 
 
230
 
 
231
/* default adapters */
 
232
 
 
233
static void
 
234
psyco_adapters_init(PyObject *mod)
 
235
{
 
236
    PyObject *call;
 
237
    
 
238
    microprotocols_add(&PyFloat_Type, NULL, (PyObject*)&asisType);
 
239
    microprotocols_add(&PyInt_Type, NULL, (PyObject*)&asisType);
 
240
    microprotocols_add(&PyLong_Type, NULL, (PyObject*)&asisType);
 
241
    
 
242
    microprotocols_add(&PyString_Type, NULL, (PyObject*)&qstringType);
 
243
    microprotocols_add(&PyUnicode_Type, NULL, (PyObject*)&qstringType);
 
244
    microprotocols_add(&PyBuffer_Type, NULL, (PyObject*)&binaryType);
 
245
    microprotocols_add(&PyList_Type, NULL, (PyObject*)&listType);
 
246
                       
 
247
#ifdef HAVE_MXDATETIME
 
248
    /* the module has already been initialized, so we can obtain the callable
 
249
       objects directly from its dictionary :) */
 
250
    call = PyMapping_GetItemString(mod, "TimestampFromMx");
 
251
    microprotocols_add(mxDateTimeP->DateTime_Type, NULL, call);
 
252
    call = PyMapping_GetItemString(mod, "TimeFromMx");
 
253
    microprotocols_add(mxDateTimeP->DateTimeDelta_Type, NULL, call);
 
254
#endif
 
255
 
 
256
#ifdef HAVE_PYDATETIME
 
257
    /* as above, we use the callable objects from the psycopg module */
 
258
    call = PyMapping_GetItemString(mod, "DateFromPy");
 
259
    microprotocols_add((PyTypeObject*)pyDateTypeP, NULL, call);
 
260
    call = PyMapping_GetItemString(mod, "TimeFromPy");
 
261
    microprotocols_add((PyTypeObject*)pyTimeTypeP, NULL, call);
 
262
    call = PyMapping_GetItemString(mod, "TimestampFromPy");
 
263
    microprotocols_add((PyTypeObject*)pyDateTimeTypeP, NULL, call);
 
264
    call = PyMapping_GetItemString(mod, "IntervalFromPy");
 
265
    microprotocols_add((PyTypeObject*)pyDeltaTypeP, NULL, call);
 
266
#endif
 
267
    
 
268
#ifdef HAVE_PYBOOL
 
269
    microprotocols_add(&PyBool_Type, NULL, (PyObject*)&pbooleanType);
 
270
#endif
 
271
 
 
272
#ifdef HAVE_DECIMAL
 
273
    microprotocols_add((PyTypeObject*)decimalType, NULL, (PyObject*)&asisType);
 
274
#endif
 
275
}
 
276
 
 
277
/* psyco_encodings_fill
 
278
   
 
279
   Fill the module's postgresql<->python encoding table */
 
280
 
 
281
static encodingPair encodings[] = {
 
282
    {"SQL_ASCII",    "ascii"},
 
283
    {"LATIN1",       "latin_1"},
 
284
    {"UNICODE",      "utf_8"},
 
285
    {"UTF8",         "utf_8"},
 
286
    
 
287
    /* some compatibility stuff */
 
288
    {"LATIN-1",      "latin_1"},
 
289
    
 
290
    {NULL, NULL}
 
291
};
 
292
static void psyco_encodings_fill(PyObject *dict)
 
293
{
 
294
    encodingPair *enc;
 
295
 
 
296
    for (enc = encodings; enc->pgenc != NULL; enc++) {
 
297
        PyObject *value = PyString_FromString(enc->pyenc);
 
298
        PyDict_SetItemString(dict, enc->pgenc, value);
 
299
        Py_DECREF(value);
 
300
    }
 
301
}
 
302
 
 
303
/* psyco_errors_init, psyco_errors_fill (callable from C)
 
304
 
 
305
   Initialize the module's exceptions and after that a dictionary with a full
 
306
   set of exceptions. */
 
307
 
 
308
PyObject *Error, *Warning, *InterfaceError, *DatabaseError,
 
309
    *InternalError, *OperationalError, *ProgrammingError,
 
310
    *IntegrityError, *DataError, *NotSupportedError;
 
311
 
 
312
/* mapping between exception names and their PyObject */
 
313
static struct {
 
314
    char *name;
 
315
    PyObject **exc;
 
316
    PyObject **base;
 
317
    char *docstr;
 
318
} exctable[] = {
 
319
    { "psycopg2.Error", &Error, 0, Error_doc },
 
320
    { "psycopg2.Warning", &Warning, 0, Warning_doc },
 
321
    { "psycopg2.InterfaceError", &InterfaceError, &Error, InterfaceError_doc },
 
322
    { "psycopg2.DatabaseError", &DatabaseError, &Error, DatabaseError_doc },
 
323
    { "psycopg2.InternalError", &InternalError, &DatabaseError, InternalError_doc },
 
324
    { "psycopg2.OperationalError", &OperationalError, &DatabaseError, 
 
325
        OperationalError_doc },
 
326
    { "psycopg2.ProgrammingError", &ProgrammingError, &DatabaseError, 
 
327
        ProgrammingError_doc },
 
328
    { "psycopg2.IntegrityError", &IntegrityError, &DatabaseError, 
 
329
        IntegrityError_doc },
 
330
    { "psycopg2.DataError", &DataError, &DatabaseError, DataError_doc },
 
331
    { "psycopg2.NotSupportedError", &NotSupportedError, &DatabaseError, 
 
332
        NotSupportedError_doc },
 
333
    {NULL}  /* Sentinel */
 
334
};
 
335
 
 
336
static void
 
337
psyco_errors_init(void)
 
338
{
 
339
    /* the names of the exceptions here reflect the oranization of the
 
340
       psycopg2 module and not the fact the the original error objects
 
341
       live in _psycopg */
 
342
       
 
343
    int i;
 
344
    PyObject *dict;
 
345
    PyObject *base;
 
346
    PyObject *str;
 
347
 
 
348
    for (i=0; exctable[i].name; i++) {
 
349
        dict = PyDict_New();
 
350
 
 
351
        if (exctable[i].docstr) {
 
352
            str = PyString_FromString(exctable[i].docstr);
 
353
            PyDict_SetItemString(dict, "__doc__", str);
 
354
        }
 
355
 
 
356
        if (exctable[i].base == 0)
 
357
            base = PyExc_StandardError;
 
358
        else
 
359
            base = *exctable[i].base;
 
360
 
 
361
        *exctable[i].exc = PyErr_NewException(exctable[i].name, base, dict);
 
362
    }
 
363
}
 
364
 
 
365
void
 
366
psyco_errors_fill(PyObject *dict)
 
367
{
 
368
    PyDict_SetItemString(dict, "Error", Error);
 
369
    PyDict_SetItemString(dict, "Warning", Warning);
 
370
    PyDict_SetItemString(dict, "InterfaceError", InterfaceError);
 
371
    PyDict_SetItemString(dict, "DatabaseError", DatabaseError);
 
372
    PyDict_SetItemString(dict, "InternalError", InternalError);
 
373
    PyDict_SetItemString(dict, "OperationalError", OperationalError);
 
374
    PyDict_SetItemString(dict, "ProgrammingError", ProgrammingError);
 
375
    PyDict_SetItemString(dict, "IntegrityError", IntegrityError);
 
376
    PyDict_SetItemString(dict, "DataError", DataError);
 
377
    PyDict_SetItemString(dict, "NotSupportedError", NotSupportedError);    
 
378
}
 
379
 
 
380
void
 
381
psyco_errors_set(PyObject *type)
 
382
{
 
383
    PyObject_SetAttrString(type, "Error", Error);
 
384
    PyObject_SetAttrString(type, "Warning", Warning);
 
385
    PyObject_SetAttrString(type, "InterfaceError", InterfaceError);
 
386
    PyObject_SetAttrString(type, "DatabaseError", DatabaseError);
 
387
    PyObject_SetAttrString(type, "InternalError", InternalError);
 
388
    PyObject_SetAttrString(type, "OperationalError", OperationalError);
 
389
    PyObject_SetAttrString(type, "ProgrammingError", ProgrammingError);
 
390
    PyObject_SetAttrString(type, "IntegrityError", IntegrityError);
 
391
    PyObject_SetAttrString(type, "DataError", DataError);
 
392
    PyObject_SetAttrString(type, "NotSupportedError", NotSupportedError);
 
393
}
 
394
 
 
395
/* psyco_error_new
 
396
  
 
397
   Create a new error of the given type with extra attributes. */
 
398
   
 
399
void
 
400
psyco_set_error(PyObject *exc, PyObject *curs, char *msg, 
 
401
                 char *pgerror, char *pgcode)
 
402
{
 
403
    PyObject *t;
 
404
    
 
405
    PyObject *err = PyObject_CallFunction(exc, "s", msg);
 
406
  
 
407
    if (err) {
 
408
        if (pgerror) {
 
409
            t = PyString_FromString(pgerror);
 
410
        }
 
411
        else {
 
412
            t = Py_None ; Py_INCREF(t);
 
413
        }
 
414
        PyObject_SetAttrString(err, "pgerror", t);
 
415
        Py_DECREF(t);
 
416
 
 
417
        if (pgcode) {
 
418
            t = PyString_FromString(pgcode);
 
419
        }
 
420
        else {
 
421
            t = Py_None ; Py_INCREF(t);
 
422
        }
 
423
        PyObject_SetAttrString(err, "pgcode", t);
 
424
        Py_DECREF(t);
 
425
        
 
426
        if (curs)
 
427
            PyObject_SetAttrString(err, "cursor", curs);
 
428
        else
 
429
            PyObject_SetAttrString(err, "cursor", Py_None);
 
430
 
 
431
        PyErr_SetObject(exc, err);
 
432
        Py_DECREF(err);
 
433
    }
 
434
 
435
 
 
436
/* psyco_decimal_init
 
437
 
 
438
   Initialize the module's pointer to the decimal type. */
 
439
 
 
440
void
 
441
psyco_decimal_init(void)
 
442
{
 
443
#ifdef HAVE_DECIMAL
 
444
    PyObject *decimal = PyImport_ImportModule("decimal");
 
445
    if (decimal) {
 
446
        decimalType = PyObject_GetAttrString(decimal, "Decimal");
 
447
    }
 
448
    else {
 
449
        PyErr_Clear();
 
450
        decimalType = (PyObject *)&PyFloat_Type;
 
451
        Py_INCREF(decimalType);
 
452
    }
 
453
#endif
 
454
}
 
455
 
 
456
 
 
457
/** method table and module initialization **/
 
458
 
 
459
static PyMethodDef psycopgMethods[] = {
 
460
    {"connect",  (PyCFunction)psyco_connect,
 
461
     METH_VARARGS|METH_KEYWORDS, psyco_connect_doc},
 
462
    {"adapt",  (PyCFunction)psyco_microprotocols_adapt,
 
463
     METH_VARARGS, psyco_microprotocols_adapt_doc},
 
464
 
 
465
    {"register_type", (PyCFunction)psyco_register_type,
 
466
     METH_VARARGS, psyco_register_type_doc},
 
467
    {"new_type", (PyCFunction)typecast_from_python,
 
468
     METH_VARARGS|METH_KEYWORDS, typecast_from_python_doc},
 
469
 
 
470
    {"AsIs",  (PyCFunction)psyco_AsIs,
 
471
     METH_VARARGS, psyco_AsIs_doc},
 
472
    {"QuotedString",  (PyCFunction)psyco_QuotedString,
 
473
     METH_VARARGS, psyco_QuotedString_doc},
 
474
    {"Boolean",  (PyCFunction)psyco_Boolean,
 
475
     METH_VARARGS, psyco_Boolean_doc},
 
476
    {"Binary",  (PyCFunction)psyco_Binary,
 
477
     METH_VARARGS, psyco_Binary_doc},
 
478
    {"Date",  (PyCFunction)psyco_Date,
 
479
     METH_VARARGS, psyco_Date_doc},
 
480
    {"Time",  (PyCFunction)psyco_Time,
 
481
     METH_VARARGS, psyco_Time_doc},
 
482
    {"Timestamp",  (PyCFunction)psyco_Timestamp,
 
483
     METH_VARARGS, psyco_Timestamp_doc},
 
484
    {"DateFromTicks",  (PyCFunction)psyco_DateFromTicks,
 
485
     METH_VARARGS, psyco_DateFromTicks_doc},
 
486
    {"TimeFromTicks",  (PyCFunction)psyco_TimeFromTicks,
 
487
     METH_VARARGS, psyco_TimeFromTicks_doc},
 
488
    {"TimestampFromTicks",  (PyCFunction)psyco_TimestampFromTicks,
 
489
     METH_VARARGS, psyco_TimestampFromTicks_doc},
 
490
    {"List",  (PyCFunction)psyco_List,
 
491
     METH_VARARGS, psyco_List_doc},
 
492
    
 
493
#ifdef HAVE_MXDATETIME
 
494
    {"DateFromMx",  (PyCFunction)psyco_DateFromMx,
 
495
     METH_VARARGS, psyco_DateFromMx_doc},
 
496
    {"TimeFromMx",  (PyCFunction)psyco_TimeFromMx,
 
497
     METH_VARARGS, psyco_TimeFromMx_doc},
 
498
    {"TimestampFromMx",  (PyCFunction)psyco_TimestampFromMx,
 
499
     METH_VARARGS, psyco_TimestampFromMx_doc},
 
500
    {"IntervalFromMx",  (PyCFunction)psyco_IntervalFromMx,
 
501
     METH_VARARGS, psyco_IntervalFromMx_doc}, 
 
502
#endif
 
503
 
 
504
#ifdef HAVE_PYDATETIME
 
505
    {"DateFromPy",  (PyCFunction)psyco_DateFromPy,
 
506
     METH_VARARGS, psyco_DateFromPy_doc},
 
507
    {"TimeFromPy",  (PyCFunction)psyco_TimeFromPy,
 
508
     METH_VARARGS, psyco_TimeFromPy_doc},
 
509
    {"TimestampFromPy",  (PyCFunction)psyco_TimestampFromPy,
 
510
     METH_VARARGS, psyco_TimestampFromPy_doc},
 
511
    {"IntervalFromPy",  (PyCFunction)psyco_IntervalFromPy,
 
512
     METH_VARARGS, psyco_IntervalFromPy_doc},     
 
513
#endif
 
514
 
 
515
    {NULL, NULL, 0, NULL}        /* Sentinel */
 
516
};
 
517
 
 
518
PyMODINIT_FUNC
 
519
init_psycopg(void)
 
520
{
 
521
    static void *PSYCOPG_API[PSYCOPG_API_pointers];
 
522
    
 
523
    PyObject *module, *dict;
 
524
    PyObject *c_api_object;
 
525
 
 
526
    Dprintf("initpsycopg: initializing psycopg %s", PSYCOPG_VERSION);
 
527
 
 
528
    /* initialize all the new types and then the module */
 
529
    connectionType.ob_type = &PyType_Type;
 
530
    cursorType.ob_type     = &PyType_Type;
 
531
    typecastType.ob_type   = &PyType_Type;
 
532
    qstringType.ob_type    = &PyType_Type;
 
533
    binaryType.ob_type     = &PyType_Type;
 
534
    isqlquoteType.ob_type  = &PyType_Type;
 
535
    asisType.ob_type       = &PyType_Type;
 
536
    listType.ob_type       = &PyType_Type;
 
537
    chunkType.ob_type      = &PyType_Type;
 
538
    
 
539
    if (PyType_Ready(&connectionType) == -1) return;
 
540
    if (PyType_Ready(&cursorType) == -1) return;
 
541
    if (PyType_Ready(&typecastType) == -1) return;
 
542
    if (PyType_Ready(&qstringType) == -1) return;
 
543
    if (PyType_Ready(&binaryType) == -1) return;
 
544
    if (PyType_Ready(&isqlquoteType) == -1) return;
 
545
    if (PyType_Ready(&asisType) == -1) return;
 
546
    if (PyType_Ready(&listType) == -1) return;
 
547
    if (PyType_Ready(&chunkType) == -1) return;
 
548
    
 
549
#ifdef HAVE_PYBOOL
 
550
    pbooleanType.ob_type   = &PyType_Type;
 
551
    if (PyType_Ready(&pbooleanType) == -1) return;
 
552
#endif
 
553
    
 
554
    /* import mx.DateTime module, if necessary */
 
555
#ifdef HAVE_MXDATETIME
 
556
    mxdatetimeType.ob_type = &PyType_Type;
 
557
    if (PyType_Ready(&mxdatetimeType) == -1) return;
 
558
    if (mxDateTime_ImportModuleAndAPI() != 0) {
 
559
        Dprintf("initpsycopg: why marc hide mx.DateTime again?!"); 
 
560
        PyErr_SetString(PyExc_ImportError, "can't import mx.DateTime module");
 
561
        return;
 
562
    }
 
563
    mxDateTimeP = &mxDateTime;
 
564
#endif
 
565
 
 
566
    /* import python builtin datetime module, if available */
 
567
#ifdef HAVE_PYDATETIME
 
568
    pyDateTimeModuleP = PyImport_ImportModule("datetime");
 
569
    if (pyDateTimeModuleP == NULL) {
 
570
        Dprintf("initpsycopg: can't import datetime module"); 
 
571
        PyErr_SetString(PyExc_ImportError, "can't import datetime module");
 
572
        return;
 
573
    }
 
574
    pydatetimeType.ob_type = &PyType_Type;
 
575
    if (PyType_Ready(&pydatetimeType) == -1) return;
 
576
 
 
577
    /* now we define the datetime types, this is crazy because python should
 
578
       be doing that, not us! */
 
579
    pyDateTypeP = PyObject_GetAttrString(pyDateTimeModuleP, "date");
 
580
    pyTimeTypeP = PyObject_GetAttrString(pyDateTimeModuleP, "time");
 
581
    pyDateTimeTypeP = PyObject_GetAttrString(pyDateTimeModuleP, "datetime");
 
582
    pyDeltaTypeP = PyObject_GetAttrString(pyDateTimeModuleP, "timedelta");
 
583
#endif    
 
584
 
 
585
    /* import psycopg2.tz anyway (TODO: replace with C-level module?) */
 
586
    pyPsycopgTzModule = PyImport_ImportModule("psycopg2.tz");
 
587
    if (pyPsycopgTzModule == NULL) {
 
588
        Dprintf("initpsycopg: can't import psycopg2.tz module"); 
 
589
        PyErr_SetString(PyExc_ImportError, "can't import psycopg2.tz module");
 
590
        return;        
 
591
    }
 
592
    pyPsycopgTzLOCAL = 
 
593
        PyObject_GetAttrString(pyPsycopgTzModule, "LOCAL"); 
 
594
    pyPsycopgTzFixedOffsetTimezone = 
 
595
        PyObject_GetAttrString(pyPsycopgTzModule, "FixedOffsetTimezone");
 
596
        
 
597
    /* initialize the module and grab module's dictionary */
 
598
    module = Py_InitModule("_psycopg", psycopgMethods);
 
599
    dict = PyModule_GetDict(module);
 
600
 
 
601
    /* initialize all the module's exported functions */
 
602
    /* PyBoxer_API[PyBoxer_Fake_NUM] = (void *)PyBoxer_Fake; */
 
603
 
 
604
    /* Create a CObject containing the API pointer array's address */
 
605
    c_api_object = PyCObject_FromVoidPtr((void *)PSYCOPG_API, NULL);
 
606
    if (c_api_object != NULL)
 
607
        PyModule_AddObject(module, "_C_API", c_api_object);
 
608
 
 
609
    /* other mixed initializations of module-level variables */
 
610
    psycoEncodings = PyDict_New();
 
611
    psyco_encodings_fill(psycoEncodings);
 
612
    psyco_decimal_init();
 
613
    
 
614
    /* set some module's parameters */
 
615
    PyModule_AddStringConstant(module, "__version__", PSYCOPG_VERSION);
 
616
    PyModule_AddStringConstant(module, "__doc__", "psycopg PostgreSQL driver");
 
617
    PyModule_AddObject(module, "apilevel", PyString_FromString(APILEVEL));
 
618
    PyModule_AddObject(module, "threadsafety", PyInt_FromLong(THREADSAFETY));
 
619
    PyModule_AddObject(module, "paramstyle", PyString_FromString(PARAMSTYLE));
 
620
    
 
621
    /* put new types in module dictionary */
 
622
    PyModule_AddObject(module, "connection", (PyObject*)&connectionType);
 
623
    PyModule_AddObject(module, "cursor", (PyObject*)&cursorType);
 
624
    PyModule_AddObject(module, "ISQLQuote", (PyObject*)&isqlquoteType);
 
625
    
 
626
    /* encodings dictionary in module dictionary */
 
627
    PyModule_AddObject(module, "encodings", psycoEncodings);
 
628
    
 
629
    /* initialize default set of typecasters */
 
630
    typecast_init(dict);
 
631
 
 
632
    /* initialize microprotocols layer */
 
633
    microprotocols_init(dict);
 
634
    psyco_adapters_init(dict);
 
635
    
 
636
    /* create a standard set of exceptions and add them to the module's dict */
 
637
    psyco_errors_init();
 
638
    psyco_errors_fill(dict);
 
639
    
 
640
    /* Solve win32 build issue about non-constant initializer element */
 
641
    cursorType.tp_alloc = PyType_GenericAlloc;
 
642
    binaryType.tp_alloc = PyType_GenericAlloc;
 
643
    isqlquoteType.tp_alloc = PyType_GenericAlloc;
 
644
    pbooleanType.tp_alloc = PyType_GenericAlloc;
 
645
    connectionType.tp_alloc = PyType_GenericAlloc;
 
646
    asisType.tp_alloc = PyType_GenericAlloc;
 
647
    qstringType.tp_alloc = PyType_GenericAlloc;
 
648
    listType.tp_alloc = PyType_GenericAlloc;
 
649
    chunkType.tp_alloc = PyType_GenericAlloc;
 
650
    
 
651
#ifdef HAVE_PYDATETIME
 
652
    pydatetimeType.tp_alloc = PyType_GenericAlloc;
 
653
#endif
 
654
    
 
655
    Dprintf("initpsycopg: module initialization complete");
 
656
}