X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=trunk%2Fpsycopg2%2Fpsycopg%2Fpsycopgmodule.c;fp=trunk%2Fpsycopg2%2Fpsycopg%2Fpsycopgmodule.c;h=426fb27a693ad8aba08c4c4fedf072281603b5de;hb=5a4c1b1278ffa01e630fde47f7c54888ed20a576;hp=0000000000000000000000000000000000000000;hpb=cee5ab52df1c9f38b6eaff2dd354cb22f59028c7;p=plcapi.git diff --git a/trunk/psycopg2/psycopg/psycopgmodule.c b/trunk/psycopg2/psycopg/psycopgmodule.c new file mode 100644 index 0000000..426fb27 --- /dev/null +++ b/trunk/psycopg2/psycopg/psycopgmodule.c @@ -0,0 +1,672 @@ +/* psycopgmodule.c - psycopg module (will import other C classes) + * + * Copyright (C) 2003 Federico Di Gregorio + * + * This file is part of psycopg. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include + +#define PSYCOPG_MODULE +#include "psycopg/config.h" +#include "psycopg/python.h" +#include "psycopg/psycopg.h" +#include "psycopg/connection.h" +#include "psycopg/cursor.h" +#include "psycopg/typecast.h" +#include "psycopg/microprotocols.h" +#include "psycopg/microprotocols_proto.h" + +#include "psycopg/adapter_qstring.h" +#include "psycopg/adapter_binary.h" +#include "psycopg/adapter_pboolean.h" +#include "psycopg/adapter_asis.h" +#include "psycopg/adapter_list.h" +#include "psycopg/typecast_binary.h" + +#ifdef HAVE_MXDATETIME +#include +#include "psycopg/adapter_mxdatetime.h" +mxDateTimeModule_APIObject *mxDateTimeP = NULL; +#endif + +/* some module-level variables, like the datetime module */ +#ifdef HAVE_PYDATETIME +#include +#include "psycopg/adapter_datetime.h" +PyObject *pyDateTimeModuleP = NULL; +PyObject *pyDateTypeP = NULL; +PyObject *pyTimeTypeP = NULL; +PyObject *pyDateTimeTypeP = NULL; +PyObject *pyDeltaTypeP = NULL; +#endif + +/* pointers to the psycopg.tz classes */ +PyObject *pyPsycopgTzModule = NULL; +PyObject *pyPsycopgTzLOCAL = NULL; +PyObject *pyPsycopgTzFixedOffsetTimezone = NULL; + +PyObject *psycoEncodings = NULL; +PyObject *decimalType = NULL; + +/** connect module-level function **/ +#define psyco_connect_doc \ +"connect(dsn, ...) -- Create a new database connection.\n\n" \ +"This function supports two different but equivalent sets of arguments.\n" \ +"A single data source name or ``dsn`` string can be used to specify the\n" \ +"connection parameters, as follows::\n\n" \ +" psycopg2.connect(\"dbname=xxx user=xxx ...\")\n\n" \ +"If ``dsn`` is not provided it is possible to pass the parameters as\n" \ +"keyword arguments; e.g.::\n\n" \ +" psycopg2.connect(database='xxx', user='xxx', ...)\n\n" \ +"The full list of available parameters is:\n\n" \ +"- ``dbname`` -- database name (only in 'dsn')\n" \ +"- ``database`` -- database name (only as keyword argument)\n" \ +"- ``host`` -- host address (defaults to UNIX socket if not provided)\n" \ +"- ``port`` -- port number (defaults to 5432 if not provided)\n" \ +"- ``user`` -- user name used to authenticate\n" \ +"- ``password`` -- password used to authenticate\n" \ +"- ``sslmode`` -- SSL mode (see PostgreSQL documentation)\n\n" \ +"If the ``connection_factory`` keyword argument is not provided this\n" \ +"function always return an instance of the `connection` class.\n" \ +"Else the given sub-class of `extensions.connection` will be used to\n" \ +"instantiate the connection object.\n\n" \ +":return: New database connection\n" \ +":rtype: `extensions.connection`" + +static int +_psyco_connect_fill_dsn(char *dsn, char *kw, char *v, int i) +{ + strcpy(&dsn[i], kw); i += strlen(kw); + strcpy(&dsn[i], v); i += strlen(v); + return i; +} + +static void +_psyco_connect_fill_exc(connectionObject *conn) +{ + /* fill the connection object with the exceptions */ + conn->exc_Error = Error; + Py_INCREF(Error); + conn->exc_Warning = Warning; + Py_INCREF(Warning); + conn->exc_InterfaceError = InterfaceError; + Py_INCREF(InterfaceError); + conn->exc_DatabaseError = DatabaseError; + Py_INCREF(DatabaseError); + conn->exc_InternalError = InternalError; + Py_INCREF(InternalError); + conn->exc_ProgrammingError = ProgrammingError; + Py_INCREF(ProgrammingError); + conn->exc_IntegrityError = IntegrityError; + Py_INCREF(IntegrityError); + conn->exc_DataError = DataError; + Py_INCREF(DataError); + conn->exc_NotSupportedError = NotSupportedError; + Py_INCREF(NotSupportedError); + conn->exc_OperationalError = OperationalError; + Py_INCREF(OperationalError); +} + +static PyObject * +psyco_connect(PyObject *self, PyObject *args, PyObject *keywds) +{ + PyObject *conn, *factory = NULL; + PyObject *pyport = NULL; + + int idsn=-1, iport=-1; + char *dsn=NULL, *database=NULL, *user=NULL, *password=NULL; + char *host=NULL, *sslmode=NULL; + char port[16]; + + static char *kwlist[] = {"dsn", "database", "host", "port", + "user", "password", "sslmode", + "connection_factory", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, keywds, "|sssOsssO", kwlist, + &dsn, &database, &host, &pyport, + &user, &password, &sslmode, &factory)) { + return NULL; + } + + if (pyport && PyString_Check(pyport)) { + PyObject *pyint = PyInt_FromString(PyString_AsString(pyport), NULL, 10); + if (!pyint) return NULL; + iport = PyInt_AsLong(pyint); + } + else if (pyport && PyInt_Check(pyport)) { + iport = PyInt_AsLong(pyport); + } + else if (pyport != NULL) { + PyErr_SetString(PyExc_TypeError, "port must be a string or int"); + return NULL; + } + + if (iport > 0) + PyOS_snprintf(port, 16, "%d", iport); + + if (dsn == NULL) { + int l = 45; /* len("dbname= user= password= host= port= sslmode=\0") */ + + if (database) l += strlen(database); + if (host) l += strlen(host); + if (iport > 0) l += strlen(port); + if (user) l += strlen(user); + if (password) l += strlen(password); + if (sslmode) l += strlen(sslmode); + + dsn = malloc(l*sizeof(char)); + if (dsn == NULL) { + PyErr_SetString(InterfaceError, "dynamic dsn allocation failed"); + return NULL; + } + + idsn = 0; + if (database) + idsn = _psyco_connect_fill_dsn(dsn, " dbname=", database, idsn); + if (host) + idsn = _psyco_connect_fill_dsn(dsn, " host=", host, idsn); + if (iport > 0) + idsn = _psyco_connect_fill_dsn(dsn, " port=", port, idsn); + if (user) + idsn = _psyco_connect_fill_dsn(dsn, " user=", user, idsn); + if (password) + idsn = _psyco_connect_fill_dsn(dsn, " password=", password, idsn); + if (sslmode) + idsn = _psyco_connect_fill_dsn(dsn, " sslmode=", sslmode, idsn); + + if (idsn > 0) { + dsn[idsn] = '\0'; + memmove(dsn, &dsn[1], idsn); + } + else { + free(dsn); + PyErr_SetString(InterfaceError, "missing dsn and no parameters"); + return NULL; + } + } + + Dprintf("psyco_connect: dsn = '%s'", dsn); + + /* allocate connection, fill with errors and return it */ + if (factory == NULL) factory = (PyObject *)&connectionType; + conn = PyObject_CallFunction(factory, "s", dsn); + if (conn) _psyco_connect_fill_exc((connectionObject*)conn); + + return conn; +} + +/** type registration **/ +#define psyco_register_type_doc \ +"register_type(obj) -> None -- register obj with psycopg type system\n\n" \ +":Parameters:\n" \ +" * `obj`: A type adapter created by `new_type()`" + +#define typecast_from_python_doc \ +"new_type(oids, name, adapter) -> new type object\n\n" \ +"Create a new binding object. The object can be used with the\n" \ +"`register_type()` function to bind PostgreSQL objects to python objects.\n\n" \ +":Parameters:\n" \ +" * `oids`: Tuple of ``oid`` of the PostgreSQL types to convert.\n" \ +" * `name`: Name for the new type\n" \ +" * `adapter`: Callable to perform type conversion.\n" \ +" It must have the signature ``fun(value, cur)`` where ``value`` is\n" \ +" the string representation returned by PostgreSQL (`None` if ``NULL``)\n" \ +" and ``cur`` is the cursor from which data are read." + +static PyObject * +psyco_register_type(PyObject *self, PyObject *args) +{ + PyObject *type; + + if (!PyArg_ParseTuple(args, "O!", &typecastType, &type)) { + return NULL; + } + + typecast_add(type, 0); + + Py_INCREF(Py_None); + return Py_None; +} + + +/* default adapters */ + +static void +psyco_adapters_init(PyObject *mod) +{ + PyObject *call; + + microprotocols_add(&PyFloat_Type, NULL, (PyObject*)&asisType); + microprotocols_add(&PyInt_Type, NULL, (PyObject*)&asisType); + microprotocols_add(&PyLong_Type, NULL, (PyObject*)&asisType); + + microprotocols_add(&PyString_Type, NULL, (PyObject*)&qstringType); + microprotocols_add(&PyUnicode_Type, NULL, (PyObject*)&qstringType); + microprotocols_add(&PyBuffer_Type, NULL, (PyObject*)&binaryType); + microprotocols_add(&PyList_Type, NULL, (PyObject*)&listType); + +#ifdef HAVE_MXDATETIME + /* the module has already been initialized, so we can obtain the callable + objects directly from its dictionary :) */ + call = PyMapping_GetItemString(mod, "TimestampFromMx"); + microprotocols_add(mxDateTimeP->DateTime_Type, NULL, call); + call = PyMapping_GetItemString(mod, "TimeFromMx"); + microprotocols_add(mxDateTimeP->DateTimeDelta_Type, NULL, call); +#endif + +#ifdef HAVE_PYDATETIME + /* as above, we use the callable objects from the psycopg module */ + call = PyMapping_GetItemString(mod, "DateFromPy"); + microprotocols_add((PyTypeObject*)pyDateTypeP, NULL, call); + call = PyMapping_GetItemString(mod, "TimeFromPy"); + microprotocols_add((PyTypeObject*)pyTimeTypeP, NULL, call); + call = PyMapping_GetItemString(mod, "TimestampFromPy"); + microprotocols_add((PyTypeObject*)pyDateTimeTypeP, NULL, call); + call = PyMapping_GetItemString(mod, "IntervalFromPy"); + microprotocols_add((PyTypeObject*)pyDeltaTypeP, NULL, call); +#endif + +#ifdef HAVE_PYBOOL + microprotocols_add(&PyBool_Type, NULL, (PyObject*)&pbooleanType); +#endif + +#ifdef HAVE_DECIMAL + microprotocols_add((PyTypeObject*)decimalType, NULL, (PyObject*)&asisType); +#endif +} + +/* psyco_encodings_fill + + Fill the module's postgresql<->python encoding table */ + +static encodingPair encodings[] = { + {"SQL_ASCII", "ascii"}, + {"LATIN1", "latin_1"}, + {"UNICODE", "utf_8"}, + {"UTF8", "utf_8"}, + + /* some compatibility stuff */ + {"LATIN-1", "latin_1"}, + + {NULL, NULL} +}; +static void psyco_encodings_fill(PyObject *dict) +{ + encodingPair *enc; + + for (enc = encodings; enc->pgenc != NULL; enc++) { + PyObject *value = PyString_FromString(enc->pyenc); + PyDict_SetItemString(dict, enc->pgenc, value); + Py_DECREF(value); + } +} + +/* psyco_errors_init, psyco_errors_fill (callable from C) + + Initialize the module's exceptions and after that a dictionary with a full + set of exceptions. */ + +PyObject *Error, *Warning, *InterfaceError, *DatabaseError, + *InternalError, *OperationalError, *ProgrammingError, + *IntegrityError, *DataError, *NotSupportedError; + +/* mapping between exception names and their PyObject */ +static struct { + char *name; + PyObject **exc; + PyObject **base; + char *docstr; +} exctable[] = { + { "psycopg2.Error", &Error, 0, Error_doc }, + { "psycopg2.Warning", &Warning, 0, Warning_doc }, + { "psycopg2.InterfaceError", &InterfaceError, &Error, InterfaceError_doc }, + { "psycopg2.DatabaseError", &DatabaseError, &Error, DatabaseError_doc }, + { "psycopg2.InternalError", &InternalError, &DatabaseError, InternalError_doc }, + { "psycopg2.OperationalError", &OperationalError, &DatabaseError, + OperationalError_doc }, + { "psycopg2.ProgrammingError", &ProgrammingError, &DatabaseError, + ProgrammingError_doc }, + { "psycopg2.IntegrityError", &IntegrityError, &DatabaseError, + IntegrityError_doc }, + { "psycopg2.DataError", &DataError, &DatabaseError, DataError_doc }, + { "psycopg2.NotSupportedError", &NotSupportedError, &DatabaseError, + NotSupportedError_doc }, + {NULL} /* Sentinel */ +}; + +static void +psyco_errors_init(void) +{ + /* the names of the exceptions here reflect the oranization of the + psycopg2 module and not the fact the the original error objects + live in _psycopg */ + + int i; + PyObject *dict; + PyObject *base; + PyObject *str; + + for (i=0; exctable[i].name; i++) { + dict = PyDict_New(); + + if (exctable[i].docstr) { + str = PyString_FromString(exctable[i].docstr); + PyDict_SetItemString(dict, "__doc__", str); + } + + if (exctable[i].base == 0) + base = PyExc_StandardError; + else + base = *exctable[i].base; + + *exctable[i].exc = PyErr_NewException(exctable[i].name, base, dict); + } +} + +void +psyco_errors_fill(PyObject *dict) +{ + PyDict_SetItemString(dict, "Error", Error); + PyDict_SetItemString(dict, "Warning", Warning); + PyDict_SetItemString(dict, "InterfaceError", InterfaceError); + PyDict_SetItemString(dict, "DatabaseError", DatabaseError); + PyDict_SetItemString(dict, "InternalError", InternalError); + PyDict_SetItemString(dict, "OperationalError", OperationalError); + PyDict_SetItemString(dict, "ProgrammingError", ProgrammingError); + PyDict_SetItemString(dict, "IntegrityError", IntegrityError); + PyDict_SetItemString(dict, "DataError", DataError); + PyDict_SetItemString(dict, "NotSupportedError", NotSupportedError); +} + +void +psyco_errors_set(PyObject *type) +{ + PyObject_SetAttrString(type, "Error", Error); + PyObject_SetAttrString(type, "Warning", Warning); + PyObject_SetAttrString(type, "InterfaceError", InterfaceError); + PyObject_SetAttrString(type, "DatabaseError", DatabaseError); + PyObject_SetAttrString(type, "InternalError", InternalError); + PyObject_SetAttrString(type, "OperationalError", OperationalError); + PyObject_SetAttrString(type, "ProgrammingError", ProgrammingError); + PyObject_SetAttrString(type, "IntegrityError", IntegrityError); + PyObject_SetAttrString(type, "DataError", DataError); + PyObject_SetAttrString(type, "NotSupportedError", NotSupportedError); +} + +/* psyco_error_new + + Create a new error of the given type with extra attributes. */ + +void +psyco_set_error(PyObject *exc, PyObject *curs, char *msg, + char *pgerror, char *pgcode) +{ + PyObject *t; + + PyObject *err = PyObject_CallFunction(exc, "s", msg); + + if (err) { + if (pgerror) { + t = PyString_FromString(pgerror); + } + else { + t = Py_None ; Py_INCREF(t); + } + PyObject_SetAttrString(err, "pgerror", t); + Py_DECREF(t); + + if (pgcode) { + t = PyString_FromString(pgcode); + } + else { + t = Py_None ; Py_INCREF(t); + } + PyObject_SetAttrString(err, "pgcode", t); + Py_DECREF(t); + + if (curs) + PyObject_SetAttrString(err, "cursor", curs); + else + PyObject_SetAttrString(err, "cursor", Py_None); + + PyErr_SetObject(exc, err); + Py_DECREF(err); + } +} + +/* psyco_decimal_init + + Initialize the module's pointer to the decimal type. */ + +void +psyco_decimal_init(void) +{ +#ifdef HAVE_DECIMAL + PyObject *decimal = PyImport_ImportModule("decimal"); + if (decimal) { + decimalType = PyObject_GetAttrString(decimal, "Decimal"); + } + else { + PyErr_Clear(); + decimalType = (PyObject *)&PyFloat_Type; + Py_INCREF(decimalType); + } +#endif +} + + +/** method table and module initialization **/ + +static PyMethodDef psycopgMethods[] = { + {"connect", (PyCFunction)psyco_connect, + METH_VARARGS|METH_KEYWORDS, psyco_connect_doc}, + {"adapt", (PyCFunction)psyco_microprotocols_adapt, + METH_VARARGS, psyco_microprotocols_adapt_doc}, + + {"register_type", (PyCFunction)psyco_register_type, + METH_VARARGS, psyco_register_type_doc}, + {"new_type", (PyCFunction)typecast_from_python, + METH_VARARGS|METH_KEYWORDS, typecast_from_python_doc}, + + {"AsIs", (PyCFunction)psyco_AsIs, + METH_VARARGS, psyco_AsIs_doc}, + {"QuotedString", (PyCFunction)psyco_QuotedString, + METH_VARARGS, psyco_QuotedString_doc}, + {"Boolean", (PyCFunction)psyco_Boolean, + METH_VARARGS, psyco_Boolean_doc}, + {"Binary", (PyCFunction)psyco_Binary, + METH_VARARGS, psyco_Binary_doc}, + {"Date", (PyCFunction)psyco_Date, + METH_VARARGS, psyco_Date_doc}, + {"Time", (PyCFunction)psyco_Time, + METH_VARARGS, psyco_Time_doc}, + {"Timestamp", (PyCFunction)psyco_Timestamp, + METH_VARARGS, psyco_Timestamp_doc}, + {"DateFromTicks", (PyCFunction)psyco_DateFromTicks, + METH_VARARGS, psyco_DateFromTicks_doc}, + {"TimeFromTicks", (PyCFunction)psyco_TimeFromTicks, + METH_VARARGS, psyco_TimeFromTicks_doc}, + {"TimestampFromTicks", (PyCFunction)psyco_TimestampFromTicks, + METH_VARARGS, psyco_TimestampFromTicks_doc}, + {"List", (PyCFunction)psyco_List, + METH_VARARGS, psyco_List_doc}, + +#ifdef HAVE_MXDATETIME + {"DateFromMx", (PyCFunction)psyco_DateFromMx, + METH_VARARGS, psyco_DateFromMx_doc}, + {"TimeFromMx", (PyCFunction)psyco_TimeFromMx, + METH_VARARGS, psyco_TimeFromMx_doc}, + {"TimestampFromMx", (PyCFunction)psyco_TimestampFromMx, + METH_VARARGS, psyco_TimestampFromMx_doc}, + {"IntervalFromMx", (PyCFunction)psyco_IntervalFromMx, + METH_VARARGS, psyco_IntervalFromMx_doc}, +#endif + +#ifdef HAVE_PYDATETIME + {"DateFromPy", (PyCFunction)psyco_DateFromPy, + METH_VARARGS, psyco_DateFromPy_doc}, + {"TimeFromPy", (PyCFunction)psyco_TimeFromPy, + METH_VARARGS, psyco_TimeFromPy_doc}, + {"TimestampFromPy", (PyCFunction)psyco_TimestampFromPy, + METH_VARARGS, psyco_TimestampFromPy_doc}, + {"IntervalFromPy", (PyCFunction)psyco_IntervalFromPy, + METH_VARARGS, psyco_IntervalFromPy_doc}, +#endif + + {NULL, NULL, 0, NULL} /* Sentinel */ +}; + +PyMODINIT_FUNC +init_psycopg(void) +{ + static void *PSYCOPG_API[PSYCOPG_API_pointers]; + + PyObject *module, *dict; + PyObject *c_api_object; + + Dprintf("initpsycopg: initializing psycopg %s", PSYCOPG_VERSION); + + /* initialize all the new types and then the module */ + connectionType.ob_type = &PyType_Type; + cursorType.ob_type = &PyType_Type; + typecastType.ob_type = &PyType_Type; + qstringType.ob_type = &PyType_Type; + binaryType.ob_type = &PyType_Type; + isqlquoteType.ob_type = &PyType_Type; + asisType.ob_type = &PyType_Type; + listType.ob_type = &PyType_Type; + chunkType.ob_type = &PyType_Type; + + if (PyType_Ready(&connectionType) == -1) return; + if (PyType_Ready(&cursorType) == -1) return; + if (PyType_Ready(&typecastType) == -1) return; + if (PyType_Ready(&qstringType) == -1) return; + if (PyType_Ready(&binaryType) == -1) return; + if (PyType_Ready(&isqlquoteType) == -1) return; + if (PyType_Ready(&asisType) == -1) return; + if (PyType_Ready(&listType) == -1) return; + if (PyType_Ready(&chunkType) == -1) return; + +#ifdef HAVE_PYBOOL + pbooleanType.ob_type = &PyType_Type; + if (PyType_Ready(&pbooleanType) == -1) return; +#endif + + /* import mx.DateTime module, if necessary */ +#ifdef HAVE_MXDATETIME + mxdatetimeType.ob_type = &PyType_Type; + if (PyType_Ready(&mxdatetimeType) == -1) return; + if (mxDateTime_ImportModuleAndAPI() != 0) { + Dprintf("initpsycopg: why marc hide mx.DateTime again?!"); + PyErr_SetString(PyExc_ImportError, "can't import mx.DateTime module"); + return; + } + mxDateTimeP = &mxDateTime; +#endif + + /* import python builtin datetime module, if available */ +#ifdef HAVE_PYDATETIME + pyDateTimeModuleP = PyImport_ImportModule("datetime"); + if (pyDateTimeModuleP == NULL) { + Dprintf("initpsycopg: can't import datetime module"); + PyErr_SetString(PyExc_ImportError, "can't import datetime module"); + 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"); +#endif + + /* import psycopg2.tz anyway (TODO: replace with C-level module?) */ + pyPsycopgTzModule = PyImport_ImportModule("psycopg2.tz"); + if (pyPsycopgTzModule == NULL) { + Dprintf("initpsycopg: can't import psycopg2.tz module"); + PyErr_SetString(PyExc_ImportError, "can't import psycopg2.tz module"); + return; + } + pyPsycopgTzLOCAL = + PyObject_GetAttrString(pyPsycopgTzModule, "LOCAL"); + pyPsycopgTzFixedOffsetTimezone = + PyObject_GetAttrString(pyPsycopgTzModule, "FixedOffsetTimezone"); + + /* initialize the module and grab module's dictionary */ + module = Py_InitModule("_psycopg", psycopgMethods); + dict = PyModule_GetDict(module); + + /* initialize all the module's exported functions */ + /* PyBoxer_API[PyBoxer_Fake_NUM] = (void *)PyBoxer_Fake; */ + + /* Create a CObject containing the API pointer array's address */ + c_api_object = PyCObject_FromVoidPtr((void *)PSYCOPG_API, NULL); + if (c_api_object != NULL) + PyModule_AddObject(module, "_C_API", c_api_object); + + /* other mixed initializations of module-level variables */ + psycoEncodings = PyDict_New(); + psyco_encodings_fill(psycoEncodings); + psyco_decimal_init(); + + /* set some module's parameters */ + PyModule_AddStringConstant(module, "__version__", PSYCOPG_VERSION); + PyModule_AddStringConstant(module, "__doc__", "psycopg PostgreSQL driver"); + PyModule_AddObject(module, "apilevel", PyString_FromString(APILEVEL)); + PyModule_AddObject(module, "threadsafety", PyInt_FromLong(THREADSAFETY)); + PyModule_AddObject(module, "paramstyle", PyString_FromString(PARAMSTYLE)); + + /* put new types in module dictionary */ + PyModule_AddObject(module, "connection", (PyObject*)&connectionType); + PyModule_AddObject(module, "cursor", (PyObject*)&cursorType); + PyModule_AddObject(module, "ISQLQuote", (PyObject*)&isqlquoteType); + + /* encodings dictionary in module dictionary */ + PyModule_AddObject(module, "encodings", psycoEncodings); + + /* initialize default set of typecasters */ + typecast_init(dict); + + /* initialize microprotocols layer */ + microprotocols_init(dict); + psyco_adapters_init(dict); + + /* create a standard set of exceptions and add them to the module's dict */ + psyco_errors_init(); + psyco_errors_fill(dict); + + /* Solve win32 build issue about non-constant initializer element */ + cursorType.tp_alloc = PyType_GenericAlloc; + binaryType.tp_alloc = PyType_GenericAlloc; + isqlquoteType.tp_alloc = PyType_GenericAlloc; + pbooleanType.tp_alloc = PyType_GenericAlloc; + connectionType.tp_alloc = PyType_GenericAlloc; + asisType.tp_alloc = PyType_GenericAlloc; + qstringType.tp_alloc = PyType_GenericAlloc; + listType.tp_alloc = PyType_GenericAlloc; + chunkType.tp_alloc = PyType_GenericAlloc; + +#ifdef HAVE_PYDATETIME + pydatetimeType.tp_alloc = PyType_GenericAlloc; +#endif + + Dprintf("initpsycopg: module initialization complete"); +}