Merge branch 'module-init-cleanup'

This commit is contained in:
Daniele Varrazzo 2019-01-23 14:17:07 +00:00
commit 00cb2636f5
9 changed files with 283 additions and 326 deletions

View File

@ -35,7 +35,7 @@
#include <string.h> #include <string.h>
int RAISES_NEG int
psyco_adapter_datetime_init(void) psyco_adapter_datetime_init(void)
{ {
Dprintf("psyco_adapter_datetime_init: datetime init"); Dprintf("psyco_adapter_datetime_init: datetime init");

View File

@ -45,7 +45,7 @@ typedef struct {
} pydatetimeObject; } pydatetimeObject;
HIDDEN int psyco_adapter_datetime_init(void); RAISES_NEG HIDDEN int psyco_adapter_datetime_init(void);
/* functions exported to psycopgmodule.c */ /* functions exported to psycopgmodule.c */
#ifdef PSYCOPG_DEFAULT_PYDATETIME #ifdef PSYCOPG_DEFAULT_PYDATETIME

View File

@ -38,15 +38,19 @@ PyObject *psyco_adapters;
/* microprotocols_init - initialize the adapters dictionary */ /* microprotocols_init - initialize the adapters dictionary */
int RAISES_NEG int
microprotocols_init(PyObject *dict) microprotocols_init(PyObject *module)
{ {
/* create adapters dictionary and put it in module namespace */ /* create adapters dictionary and put it in module namespace */
if ((psyco_adapters = PyDict_New()) == NULL) { if (!(psyco_adapters = PyDict_New())) {
return -1; return -1;
} }
PyDict_SetItemString(dict, "adapters", psyco_adapters); Py_INCREF(psyco_adapters);
if (0 > PyModule_AddObject(module, "adapters", psyco_adapters)) {
Py_DECREF(psyco_adapters);
return -1;
}
return 0; return 0;
} }
@ -56,7 +60,7 @@ microprotocols_init(PyObject *dict)
* *
* Return 0 on success, else -1 and set an exception. * Return 0 on success, else -1 and set an exception.
*/ */
int RAISES_NEG int
microprotocols_add(PyTypeObject *type, PyObject *proto, PyObject *cast) microprotocols_add(PyTypeObject *type, PyObject *proto, PyObject *cast)
{ {
PyObject *key = NULL; PyObject *key = NULL;

View File

@ -46,8 +46,8 @@ extern HIDDEN PyObject *psyco_adapters;
/** exported functions **/ /** exported functions **/
/* used by module.c to init the microprotocols system */ /* used by module.c to init the microprotocols system */
HIDDEN int microprotocols_init(PyObject *dict); HIDDEN RAISES_NEG int microprotocols_init(PyObject *dict);
HIDDEN int microprotocols_add( HIDDEN RAISES_NEG int microprotocols_add(
PyTypeObject *type, PyObject *proto, PyObject *cast); PyTypeObject *type, PyObject *proto, PyObject *cast);
HIDDEN PyObject *microprotocols_adapt( HIDDEN PyObject *microprotocols_adapt(

View File

@ -47,75 +47,18 @@ extern "C" {
#define THREADSAFETY 2 #define THREADSAFETY 2
#define PARAMSTYLE "pyformat" #define PARAMSTYLE "pyformat"
/* C API functions */
#define psyco_errors_fill_NUM 0
#define psyco_errors_fill_RETURN void
#define psyco_errors_fill_PROTO (PyObject *dict)
#define psyco_errors_set_NUM 1
#define psyco_errors_set_RETURN void
#define psyco_errors_set_PROTO (PyObject *type)
/* Total number of C API pointers */
#define PSYCOPG_API_pointers 2
#ifdef PSYCOPG_MODULE
/** This section is used when compiling psycopgmodule.c & co. **/
HIDDEN psyco_errors_fill_RETURN psyco_errors_fill psyco_errors_fill_PROTO;
HIDDEN psyco_errors_set_RETURN psyco_errors_set psyco_errors_set_PROTO;
/* global exceptions */ /* global exceptions */
extern HIDDEN PyObject *Error, *Warning, *InterfaceError, *DatabaseError, extern HIDDEN PyObject *Error, *Warning, *InterfaceError, *DatabaseError,
*InternalError, *OperationalError, *ProgrammingError, *InternalError, *OperationalError, *ProgrammingError,
*IntegrityError, *DataError, *NotSupportedError; *IntegrityError, *DataError, *NotSupportedError;
extern HIDDEN PyObject *QueryCanceledError, *TransactionRollbackError; extern HIDDEN PyObject *QueryCanceledError, *TransactionRollbackError;
/* python versions and compatibility stuff */
#ifndef PyMODINIT_FUNC
#define PyMODINIT_FUNC void
#endif
#else
/** This section is used in modules that use psycopg's C API **/
static void **PSYCOPG_API;
#define psyco_errors_fill \
(*(psyco_errors_fill_RETURN (*)psyco_errors_fill_PROTO) \
PSYCOPG_API[psyco_errors_fill_NUM])
#define psyco_errors_set \
(*(psyco_errors_set_RETURN (*)psyco_errors_set_PROTO) \
PSYCOPG_API[psyco_errors_set_NUM])
/* Return -1 and set exception on error, 0 on success. */
static int
import_psycopg(void)
{
PyObject *module = PyImport_ImportModule("psycopg");
if (module != NULL) {
PyObject *c_api_object = PyObject_GetAttrString(module, "_C_API");
if (c_api_object == NULL) return -1;
if (PyCObject_Check(c_api_object))
PSYCOPG_API = (void **)PyCObject_AsVoidPtr(c_api_object);
Py_DECREF(c_api_object);
}
return 0;
}
#endif
/* postgresql<->python encoding map */ /* postgresql<->python encoding map */
extern HIDDEN PyObject *psycoEncodings; extern HIDDEN PyObject *psycoEncodings;
/* SQL NULL */ /* SQL NULL */
extern HIDDEN PyObject *psyco_null; extern HIDDEN PyObject *psyco_null;
typedef struct {
char *pgenc;
char *pyenc;
} encodingPair;
/* Exceptions docstrings */ /* Exceptions docstrings */
#define Error_doc \ #define Error_doc \
"Base class for error exceptions." "Base class for error exceptions."

View File

@ -60,7 +60,6 @@
/* some module-level variables, like the datetime module */ /* some module-level variables, like the datetime module */
#include <datetime.h> #include <datetime.h>
#include "psycopg/adapter_datetime.h" #include "psycopg/adapter_datetime.h"
HIDDEN PyObject *pyDateTimeModuleP = NULL;
HIDDEN PyObject *psycoEncodings = NULL; HIDDEN PyObject *psycoEncodings = NULL;
#ifdef PSYCOPG_DEBUG #ifdef PSYCOPG_DEBUG
@ -274,6 +273,8 @@ psyco_libcrypto_threads_init(void)
{ {
PyObject *m; PyObject *m;
Dprintf("psycopgmodule: configuring libpq libcrypto callbacks ");
/* importing the ssl module sets up Python's libcrypto callbacks */ /* importing the ssl module sets up Python's libcrypto callbacks */
if ((m = PyImport_ImportModule("ssl"))) { if ((m = PyImport_ImportModule("ssl"))) {
/* disable libcrypto setup in libpq, so it won't stomp on the callbacks /* disable libcrypto setup in libpq, so it won't stomp on the callbacks
@ -292,94 +293,108 @@ psyco_libcrypto_threads_init(void)
* *
* Return 0 on success, else -1 and set an exception. * Return 0 on success, else -1 and set an exception.
*/ */
static int RAISES_NEG static int
psyco_adapters_init(PyObject *mod) adapters_init(PyObject *module)
{ {
PyObject *call = NULL; PyObject *dict = NULL, *obj = NULL;
int rv = -1; int rv = -1;
if (0 != microprotocols_add(&PyFloat_Type, NULL, (PyObject*)&pfloatType)) { if (0 > microprotocols_init(module)) { goto exit; }
Dprintf("psycopgmodule: configuring adapters");
if (0 > microprotocols_add(&PyFloat_Type, NULL, (PyObject*)&pfloatType)) {
goto exit; goto exit;
} }
#if PY_MAJOR_VERSION < 3 #if PY_MAJOR_VERSION < 3
if (0 != microprotocols_add(&PyInt_Type, NULL, (PyObject*)&pintType)) { if (0 > microprotocols_add(&PyInt_Type, NULL, (PyObject*)&pintType)) {
goto exit; goto exit;
} }
#endif #endif
if (0 != microprotocols_add(&PyLong_Type, NULL, (PyObject*)&pintType)) { if (0 > microprotocols_add(&PyLong_Type, NULL, (PyObject*)&pintType)) {
goto exit; goto exit;
} }
if (0 != microprotocols_add(&PyBool_Type, NULL, (PyObject*)&pbooleanType)) { if (0 > microprotocols_add(&PyBool_Type, NULL, (PyObject*)&pbooleanType)) {
goto exit; goto exit;
} }
/* strings */ /* strings */
#if PY_MAJOR_VERSION < 3 #if PY_MAJOR_VERSION < 3
if (0 != microprotocols_add(&PyString_Type, NULL, (PyObject*)&qstringType)) { if (0 > microprotocols_add(&PyString_Type, NULL, (PyObject*)&qstringType)) {
goto exit; goto exit;
} }
#endif #endif
if (0 != microprotocols_add(&PyUnicode_Type, NULL, (PyObject*)&qstringType)) { if (0 > microprotocols_add(&PyUnicode_Type, NULL, (PyObject*)&qstringType)) {
goto exit; goto exit;
} }
/* binary */ /* binary */
#if PY_MAJOR_VERSION < 3 #if PY_MAJOR_VERSION < 3
if (0 != microprotocols_add(&PyBuffer_Type, NULL, (PyObject*)&binaryType)) { if (0 > microprotocols_add(&PyBuffer_Type, NULL, (PyObject*)&binaryType)) {
goto exit; goto exit;
} }
#else #else
if (0 != microprotocols_add(&PyBytes_Type, NULL, (PyObject*)&binaryType)) { if (0 > microprotocols_add(&PyBytes_Type, NULL, (PyObject*)&binaryType)) {
goto exit; goto exit;
} }
#endif #endif
#if PY_MAJOR_VERSION >= 3 || PY_MINOR_VERSION >= 6 #if PY_MAJOR_VERSION >= 3 || PY_MINOR_VERSION >= 6
if (0 != microprotocols_add(&PyByteArray_Type, NULL, (PyObject*)&binaryType)) { if (0 > microprotocols_add(&PyByteArray_Type, NULL, (PyObject*)&binaryType)) {
goto exit; goto exit;
} }
#endif #endif
#if PY_MAJOR_VERSION >= 3 || PY_MINOR_VERSION >= 7 #if PY_MAJOR_VERSION >= 3 || PY_MINOR_VERSION >= 7
if (0 != microprotocols_add(&PyMemoryView_Type, NULL, (PyObject*)&binaryType)) { if (0 > microprotocols_add(&PyMemoryView_Type, NULL, (PyObject*)&binaryType)) {
goto exit; goto exit;
} }
#endif #endif
if (0 != microprotocols_add(&PyList_Type, NULL, (PyObject*)&listType)) { if (0 > microprotocols_add(&PyList_Type, NULL, (PyObject*)&listType)) {
goto exit; goto exit;
} }
/* the module has already been initialized, so we can obtain the callable /* the module has already been initialized, so we can obtain the callable
objects directly from its dictionary :) */ objects directly from its dictionary :) */
if (!(call = PyMapping_GetItemString(mod, "DateFromPy"))) { goto exit; } if (!(dict = PyModule_GetDict(module))) { goto exit; }
if (0 != microprotocols_add(PyDateTimeAPI->DateType, NULL, call)) { goto exit; }
Py_CLEAR(call);
if (!(call = PyMapping_GetItemString(mod, "TimeFromPy"))) { goto exit; } if (!(obj = PyMapping_GetItemString(dict, "DateFromPy"))) { goto exit; }
if (0 != microprotocols_add(PyDateTimeAPI->TimeType, NULL, call)) { goto exit; } if (0 > microprotocols_add(PyDateTimeAPI->DateType, NULL, obj)) { goto exit; }
Py_CLEAR(call); Py_CLEAR(obj);
if (!(call = PyMapping_GetItemString(mod, "TimestampFromPy"))) { goto exit; } if (!(obj = PyMapping_GetItemString(dict, "TimeFromPy"))) { goto exit; }
if (0 != microprotocols_add(PyDateTimeAPI->DateTimeType, NULL, call)) { goto exit; } if (0 > microprotocols_add(PyDateTimeAPI->TimeType, NULL, obj)) { goto exit; }
Py_CLEAR(call); Py_CLEAR(obj);
if (!(call = PyMapping_GetItemString(mod, "IntervalFromPy"))) { goto exit; } if (!(obj = PyMapping_GetItemString(dict, "TimestampFromPy"))) { goto exit; }
if (0 != microprotocols_add(PyDateTimeAPI->DeltaType, NULL, call)) { goto exit; } if (0 > microprotocols_add(PyDateTimeAPI->DateTimeType, NULL, obj)) { goto exit; }
Py_CLEAR(call); Py_CLEAR(obj);
if (!(obj = PyMapping_GetItemString(dict, "IntervalFromPy"))) { goto exit; }
if (0 > microprotocols_add(PyDateTimeAPI->DeltaType, NULL, obj)) { goto exit; }
Py_CLEAR(obj);
#ifdef HAVE_MXDATETIME #ifdef HAVE_MXDATETIME
/* as above, we use the callable objects from the psycopg module */ /* As above, we use the callable objects from the psycopg module.
if (NULL != (call = PyMapping_GetItemString(mod, "TimestampFromMx"))) { These object are not be available at runtime if mx.DateTime import
if (0 != microprotocols_add(mxDateTime.DateTime_Type, NULL, call)) { goto exit; } failed (e.g. it was available at build time but not at runtime). */
Py_CLEAR(call); if (PyMapping_HasKeyString(dict, "TimestampFromMx")) {
if (!(obj = PyMapping_GetItemString(dict, "TimestampFromMx"))) {
goto exit;
}
if (0 > microprotocols_add(mxDateTime.DateTime_Type, NULL, obj)) {
goto exit;
}
Py_CLEAR(obj);
/* if we found the above, we have this too. */ /* if we found the above, we have this too. */
if (!(call = PyMapping_GetItemString(mod, "TimeFromMx"))) { goto exit; } if (!(obj = PyMapping_GetItemString(dict, "TimeFromMx"))) {
if (0 != microprotocols_add(mxDateTime.DateTimeDelta_Type, NULL, call)) { goto exit; } goto exit;
Py_CLEAR(call);
} }
else { if (0 > microprotocols_add(mxDateTime.DateTimeDelta_Type, NULL, obj)) {
PyErr_Clear(); goto exit;
}
Py_CLEAR(obj);
} }
#endif #endif
@ -387,7 +402,7 @@ psyco_adapters_init(PyObject *mod)
rv = 0; rv = 0;
exit: exit:
Py_XDECREF(call); Py_XDECREF(obj);
return rv; return rv;
} }
@ -499,11 +514,11 @@ exit:
} }
/* psyco_encodings_fill /* Fill the module's postgresql<->python encoding table */
static struct {
Fill the module's postgresql<->python encoding table */ char *pgenc;
char *pyenc;
static encodingPair encodings[] = { } enctable[] = {
{"ABC", "cp1258"}, {"ABC", "cp1258"},
{"ALT", "cp866"}, {"ALT", "cp866"},
{"BIG5", "big5"}, {"BIG5", "big5"},
@ -585,15 +600,28 @@ static encodingPair encodings[] = {
* *
* Return 0 on success, else -1 and set an exception. * Return 0 on success, else -1 and set an exception.
*/ */
static int psyco_encodings_fill(PyObject *dict) RAISES_NEG static int
encodings_init(PyObject *module)
{ {
PyObject *value = NULL; PyObject *value = NULL;
encodingPair *enc; int i;
int rv = -1; int rv = -1;
for (enc = encodings; enc->pgenc != NULL; enc++) { Dprintf("psycopgmodule: initializing encodings table");
if (!(value = Text_FromUTF8(enc->pyenc))) { goto exit; }
if (0 != PyDict_SetItemString(dict, enc->pgenc, value)) { goto exit; } if (!(psycoEncodings = PyDict_New())) { goto exit; }
Py_INCREF(psycoEncodings);
if (0 > PyModule_AddObject(module, "encodings", psycoEncodings)) {
Py_DECREF(psycoEncodings);
goto exit;
}
for (i = 0; enctable[i].pgenc != NULL; i++) {
if (!(value = Text_FromUTF8(enctable[i].pyenc))) { goto exit; }
if (0 > PyDict_SetItemString(
psycoEncodings, enctable[i].pgenc, value)) {
goto exit;
}
Py_CLEAR(value); Py_CLEAR(value);
} }
rv = 0; rv = 0;
@ -604,9 +632,7 @@ exit:
return rv; return rv;
} }
/* psyco_errors_init, psyco_errors_fill (callable from C) /* Initialize the module's exceptions and after that a dictionary with a full
Initialize the module's exceptions and after that a dictionary with a full
set of exceptions. */ set of exceptions. */
PyObject *Error, *Warning, *InterfaceError, *DatabaseError, PyObject *Error, *Warning, *InterfaceError, *DatabaseError,
@ -644,8 +670,8 @@ static struct {
}; };
static int RAISES_NEG static int
psyco_errors_init(void) errors_init(PyObject *module)
{ {
/* the names of the exceptions here reflect the organization of the /* the names of the exceptions here reflect the organization of the
psycopg2 module and not the fact the the original error objects psycopg2 module and not the fact the the original error objects
@ -656,6 +682,8 @@ psyco_errors_init(void)
PyObject *str = NULL; PyObject *str = NULL;
int rv = -1; int rv = -1;
Dprintf("psycopgmodule: initializing basic exceptions");
/* 'Error' has been defined elsewhere: only init the other classes */ /* 'Error' has been defined elsewhere: only init the other classes */
Error = (PyObject *)&errorType; Error = (PyObject *)&errorType;
@ -664,7 +692,7 @@ psyco_errors_init(void)
if (exctable[i].docstr) { if (exctable[i].docstr) {
if (!(str = Text_FromUTF8(exctable[i].docstr))) { goto exit; } if (!(str = Text_FromUTF8(exctable[i].docstr))) { goto exit; }
if (0 != PyDict_SetItemString(dict, "__doc__", str)) { goto exit; } if (0 > PyDict_SetItemString(dict, "__doc__", str)) { goto exit; }
Py_CLEAR(str); Py_CLEAR(str);
} }
@ -679,6 +707,21 @@ psyco_errors_init(void)
Py_CLEAR(dict); Py_CLEAR(dict);
} }
for (i = 0; exctable[i].name; i++) {
char *name;
if (NULL == exctable[i].exc) { continue; }
/* the name is the part after the last dot */
name = strrchr(exctable[i].name, '.');
name = name ? name + 1 : exctable[i].name;
Py_INCREF(*exctable[i].exc);
if (0 > PyModule_AddObject(module, name, *exctable[i].exc)) {
Py_DECREF(*exctable[i].exc);
goto exit;
}
}
rv = 0; rv = 0;
exit: exit:
@ -687,40 +730,162 @@ exit:
return rv; return rv;
} }
void
psyco_errors_fill(PyObject *dict) RAISES_NEG static int
add_module_constants(PyObject *module)
{
PyObject *tmp;
Dprintf("psycopgmodule: initializing module constants");
if (0 > PyModule_AddStringConstant(module,
"__version__", xstr(PSYCOPG_VERSION)))
{ return -1; }
if (0 > PyModule_AddStringConstant(module,
"__doc__", "psycopg2 PostgreSQL driver"))
{ return -1; }
if (0 > PyModule_AddIntConstant(module,
"__libpq_version__", PG_VERSION_NUM))
{ return -1; }
if (0 > PyModule_AddObject(module,
"apilevel", tmp = Text_FromUTF8(APILEVEL)))
{
Py_XDECREF(tmp);
return -1;
}
if (0 > PyModule_AddObject(module,
"threadsafety", tmp = PyInt_FromLong(THREADSAFETY)))
{
Py_XDECREF(tmp);
return -1;
}
if (0 > PyModule_AddObject(module,
"paramstyle", tmp = Text_FromUTF8(PARAMSTYLE)))
{
Py_XDECREF(tmp);
return -1;
}
if (0 > PyModule_AddIntMacro(module, REPLICATION_PHYSICAL)) { return -1; }
if (0 > PyModule_AddIntMacro(module, REPLICATION_LOGICAL)) { return -1; }
return 0;
}
static struct {
char *name;
PyTypeObject *type;
} typetable[] = {
{ "connection", &connectionType },
{ "cursor", &cursorType },
{ "ReplicationConnection", &replicationConnectionType },
{ "ReplicationCursor", &replicationCursorType },
{ "ReplicationMessage", &replicationMessageType },
{ "ISQLQuote", &isqlquoteType },
{ "Column", &columnType },
{ "Notify", &notifyType },
{ "Xid", &xidType },
{ "ConnectionInfo", &connInfoType },
{ "Diagnostics", &diagnosticsType },
{ "AsIs", &asisType },
{ "Binary", &binaryType },
{ "Boolean", &pbooleanType },
{ "Decimal", &pdecimalType },
{ "Int", &pintType },
{ "Float", &pfloatType },
{ "List", &listType },
{ "QuotedString", &qstringType },
{ "lobject", &lobjectType },
{NULL} /* Sentinel */
};
RAISES_NEG static int
add_module_types(PyObject *module)
{ {
int i; int i;
char *name;
for (i = 0; exctable[i].name; i++) { Dprintf("psycopgmodule: initializing module types");
if (NULL == exctable[i].exc) { continue; }
/* the name is the part after the last dot */ for (i = 0; typetable[i].name; i++) {
name = strrchr(exctable[i].name, '.'); PyObject *type = (PyObject *)typetable[i].type;
name = name ? name + 1 : exctable[i].name;
PyDict_SetItemString(dict, name, *exctable[i].exc); Py_TYPE(typetable[i].type) = &PyType_Type;
if (0 > PyType_Ready(typetable[i].type)) { return -1; }
Py_INCREF(type);
if (0 > PyModule_AddObject(module, typetable[i].name, type)) {
Py_DECREF(type);
return -1;
} }
} }
return 0;
}
void
psyco_errors_set(PyObject *type) RAISES_NEG static int
datetime_init(void)
{ {
int i; PyObject *dt = NULL;
char *name;
for (i = 0; exctable[i].name; i++) { Dprintf("psycopgmodule: datetime module");
if (NULL == exctable[i].exc) { continue; }
/* the name is the part after the last dot */ /* import python builtin datetime module, if available */
name = strrchr(exctable[i].name, '.'); if (!(dt = PyImport_ImportModule("datetime"))) {
name = name ? name + 1 : exctable[i].name; return -1;
PyObject_SetAttrString(type, name, *exctable[i].exc);
} }
Py_DECREF(dt);
/* Initialize the PyDateTimeAPI everywhere is used */
PyDateTime_IMPORT;
if (0 > psyco_adapter_datetime_init()) { return -1; }
if (0 > psyco_repl_curs_datetime_init()) { return -1; }
if (0 > psyco_replmsg_datetime_init()) { return -1; }
Py_TYPE(&pydatetimeType) = &PyType_Type;
if (0 > PyType_Ready(&pydatetimeType)) { return -1; }
return 0;
} }
RAISES_NEG static int
mxdatetime_init(PyObject *module)
{
Dprintf("psycopgmodule: initializing mx.DateTime module");
#ifdef HAVE_MXDATETIME
Py_TYPE(&mxdatetimeType) = &PyType_Type;
if (0 > PyType_Ready(&mxdatetimeType)) { return -1; }
if (mxDateTime_ImportModuleAndAPI()) {
Dprintf("psycopgmodule: mx.DateTime module import failed");
PyErr_Clear();
/* only fail if the mx typacaster should have been the default */
#ifdef PSYCOPG_DEFAULT_MXDATETIME
PyErr_SetString(PyExc_ImportError,
"can't import mx.DateTime module (requested as default adapter)");
return -1;
#endif
}
/* If we can't find mx.DateTime objects at runtime,
* remove them from the module (and, as consequence, from the adapters). */
if (0 != psyco_adapter_mxdatetime_init()) {
PyObject *dict;
if (!(dict = PyModule_GetDict(module))) { return -1; }
if (0 > PyDict_DelItemString(dict, "DateFromMx")) { return -1; }
if (0 > PyDict_DelItemString(dict, "TimeFromMx")) { return -1; }
if (0 > PyDict_DelItemString(dict, "TimestampFromMx")) { return -1; }
if (0 > PyDict_DelItemString(dict, "IntervalFromMx")) { return -1; }
}
#endif
return 0;
}
/** method table and module initialization **/ /** method table and module initialization **/
@ -801,132 +966,38 @@ static struct PyModuleDef psycopgmodule = {
}; };
#endif #endif
#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
#define PyMODINIT_FUNC void
#endif
PyMODINIT_FUNC PyMODINIT_FUNC
INIT_MODULE(_psycopg)(void) INIT_MODULE(_psycopg)(void)
{ {
#if PY_VERSION_HEX < 0x03020000 PyObject *module = NULL;
static void *PSYCOPG_API[PSYCOPG_API_pointers];
PyObject *c_api_object;
#endif
PyObject *module = NULL, *dict;
#ifdef PSYCOPG_DEBUG #ifdef PSYCOPG_DEBUG
if (getenv("PSYCOPG_DEBUG")) if (getenv("PSYCOPG_DEBUG"))
psycopg_debug_enabled = 1; psycopg_debug_enabled = 1;
#endif #endif
Dprintf("initpsycopg: initializing psycopg %s", xstr(PSYCOPG_VERSION)); Dprintf("psycopgmodule: initializing psycopg %s", xstr(PSYCOPG_VERSION));
/* initialize all the new types and then the module */
Py_TYPE(&connectionType) = &PyType_Type;
if (PyType_Ready(&connectionType) == -1) goto exit;
Py_TYPE(&cursorType) = &PyType_Type;
if (PyType_Ready(&cursorType) == -1) goto exit;
Py_TYPE(&replicationConnectionType) = &PyType_Type;
if (PyType_Ready(&replicationConnectionType) == -1) goto exit;
Py_TYPE(&replicationCursorType) = &PyType_Type;
if (PyType_Ready(&replicationCursorType) == -1) goto exit;
Py_TYPE(&replicationMessageType) = &PyType_Type;
if (PyType_Ready(&replicationMessageType) == -1) goto exit;
Py_TYPE(&typecastType) = &PyType_Type;
if (PyType_Ready(&typecastType) == -1) goto exit;
Py_TYPE(&qstringType) = &PyType_Type;
if (PyType_Ready(&qstringType) == -1) goto exit;
Py_TYPE(&binaryType) = &PyType_Type;
if (PyType_Ready(&binaryType) == -1) goto exit;
Py_TYPE(&isqlquoteType) = &PyType_Type;
if (PyType_Ready(&isqlquoteType) == -1) goto exit;
Py_TYPE(&pbooleanType) = &PyType_Type;
if (PyType_Ready(&pbooleanType) == -1) goto exit;
Py_TYPE(&pintType) = &PyType_Type;
if (PyType_Ready(&pintType) == -1) goto exit;
Py_TYPE(&pfloatType) = &PyType_Type;
if (PyType_Ready(&pfloatType) == -1) goto exit;
Py_TYPE(&pdecimalType) = &PyType_Type;
if (PyType_Ready(&pdecimalType) == -1) goto exit;
Py_TYPE(&asisType) = &PyType_Type;
if (PyType_Ready(&asisType) == -1) goto exit;
Py_TYPE(&listType) = &PyType_Type;
if (PyType_Ready(&listType) == -1) goto exit;
Py_TYPE(&chunkType) = &PyType_Type;
if (PyType_Ready(&chunkType) == -1) goto exit;
Py_TYPE(&columnType) = &PyType_Type;
if (PyType_Ready(&columnType) == -1) goto exit;
Py_TYPE(&notifyType) = &PyType_Type;
if (PyType_Ready(&notifyType) == -1) goto exit;
Py_TYPE(&xidType) = &PyType_Type;
if (PyType_Ready(&xidType) == -1) goto exit;
Py_TYPE(&errorType) = &PyType_Type;
errorType.tp_base = (PyTypeObject *)PyExc_StandardError;
if (PyType_Ready(&errorType) == -1) goto exit;
Py_TYPE(&connInfoType) = &PyType_Type;
if (PyType_Ready(&connInfoType) == -1) goto exit;
Py_TYPE(&diagnosticsType) = &PyType_Type;
if (PyType_Ready(&diagnosticsType) == -1) goto exit;
Py_TYPE(&lobjectType) = &PyType_Type;
if (PyType_Ready(&lobjectType) == -1) goto exit;
/* initialize libcrypto threading callbacks */ /* initialize libcrypto threading callbacks */
psyco_libcrypto_threads_init(); psyco_libcrypto_threads_init();
/* import mx.DateTime module, if necessary */ /* initialize types and objects not exposed to the module */
#ifdef HAVE_MXDATETIME Py_TYPE(&typecastType) = &PyType_Type;
Py_TYPE(&mxdatetimeType) = &PyType_Type; if (0 > PyType_Ready(&typecastType)) { goto exit; }
if (PyType_Ready(&mxdatetimeType) == -1) goto exit;
if (0 != mxDateTime_ImportModuleAndAPI()) { Py_TYPE(&chunkType) = &PyType_Type;
PyErr_Clear(); if (0 > PyType_Ready(&chunkType)) { goto exit; }
/* only fail if the mx typacaster should have been the default */ Py_TYPE(&errorType) = &PyType_Type;
#ifdef PSYCOPG_DEFAULT_MXDATETIME errorType.tp_base = (PyTypeObject *)PyExc_StandardError;
PyErr_SetString(PyExc_ImportError, if (0 > PyType_Ready(&errorType)) { goto exit; }
"can't import mx.DateTime module (requested as default adapter)");
goto exit;
#endif
}
#endif
/* import python builtin datetime module, if available */ if (!(psyco_null = Bytes_FromString("NULL"))) { goto exit; }
pyDateTimeModuleP = PyImport_ImportModule("datetime");
if (pyDateTimeModuleP == NULL) {
Dprintf("initpsycopg: can't import datetime module");
PyErr_SetString(PyExc_ImportError, "can't import datetime module");
goto exit;
}
/* Initialize the PyDateTimeAPI everywhere is used */ /* initialize the module */
PyDateTime_IMPORT;
if (psyco_adapter_datetime_init()) { goto exit; }
if (psyco_repl_curs_datetime_init()) { goto exit; }
if (psyco_replmsg_datetime_init()) { goto exit; }
Py_TYPE(&pydatetimeType) = &PyType_Type;
if (PyType_Ready(&pydatetimeType) == -1) goto exit;
/* initialize the module and grab module's dictionary */
#if PY_MAJOR_VERSION < 3 #if PY_MAJOR_VERSION < 3
module = Py_InitModule("_psycopg", psycopgMethods); module = Py_InitModule("_psycopg", psycopgMethods);
#else #else
@ -934,81 +1005,16 @@ INIT_MODULE(_psycopg)(void)
#endif #endif
if (!module) { goto exit; } if (!module) { goto exit; }
dict = PyModule_GetDict(module); if (0 > add_module_constants(module)) { goto exit; }
if (0 > add_module_types(module)) { goto exit; }
if (0 > datetime_init()) { goto exit; }
if (0 > mxdatetime_init(module)) { goto exit; }
if (0 > encodings_init(module)) { goto exit; }
if (0 > typecast_init(module)) { goto exit; }
if (0 > adapters_init(module)) { goto exit; }
if (0 > errors_init(module)) { goto exit; }
/* initialize all the module's exported functions */ Dprintf("psycopgmodule: module initialization complete");
/* PyBoxer_API[PyBoxer_Fake_NUM] = (void *)PyBoxer_Fake; */
/* Create a CObject containing the API pointer array's address */
/* If anybody asks for a PyCapsule we'll deal with it. */
#if PY_VERSION_HEX < 0x03020000
c_api_object = PyCObject_FromVoidPtr((void *)PSYCOPG_API, NULL);
if (c_api_object != NULL)
PyModule_AddObject(module, "_C_API", c_api_object);
#endif
/* other mixed initializations of module-level variables */
if (!(psycoEncodings = PyDict_New())) { goto exit; }
if (0 != psyco_encodings_fill(psycoEncodings)) { goto exit; }
psyco_null = Bytes_FromString("NULL");
/* set some module's parameters */
PyModule_AddStringConstant(module, "__version__", xstr(PSYCOPG_VERSION));
PyModule_AddStringConstant(module, "__doc__", "psycopg PostgreSQL driver");
PyModule_AddIntConstant(module, "__libpq_version__", PG_VERSION_NUM);
PyModule_AddIntMacro(module, REPLICATION_PHYSICAL);
PyModule_AddIntMacro(module, REPLICATION_LOGICAL);
PyModule_AddObject(module, "apilevel", Text_FromUTF8(APILEVEL));
PyModule_AddObject(module, "threadsafety", PyInt_FromLong(THREADSAFETY));
PyModule_AddObject(module, "paramstyle", Text_FromUTF8(PARAMSTYLE));
/* put new types in module dictionary */
PyModule_AddObject(module, "connection", (PyObject*)&connectionType);
PyModule_AddObject(module, "cursor", (PyObject*)&cursorType);
PyModule_AddObject(module, "ReplicationConnection", (PyObject*)&replicationConnectionType);
PyModule_AddObject(module, "ReplicationCursor", (PyObject*)&replicationCursorType);
PyModule_AddObject(module, "ReplicationMessage", (PyObject*)&replicationMessageType);
PyModule_AddObject(module, "ISQLQuote", (PyObject*)&isqlquoteType);
PyModule_AddObject(module, "Column", (PyObject*)&columnType);
PyModule_AddObject(module, "Notify", (PyObject*)&notifyType);
PyModule_AddObject(module, "Xid", (PyObject*)&xidType);
PyModule_AddObject(module, "ConnectionInfo", (PyObject*)&connInfoType);
PyModule_AddObject(module, "Diagnostics", (PyObject*)&diagnosticsType);
PyModule_AddObject(module, "AsIs", (PyObject*)&asisType);
PyModule_AddObject(module, "Binary", (PyObject*)&binaryType);
PyModule_AddObject(module, "Boolean", (PyObject*)&pbooleanType);
PyModule_AddObject(module, "Decimal", (PyObject*)&pdecimalType);
PyModule_AddObject(module, "Int", (PyObject*)&pintType);
PyModule_AddObject(module, "Float", (PyObject*)&pfloatType);
PyModule_AddObject(module, "List", (PyObject*)&listType);
PyModule_AddObject(module, "QuotedString", (PyObject*)&qstringType);
PyModule_AddObject(module, "lobject", (PyObject*)&lobjectType);
/* encodings dictionary in module dictionary */
PyModule_AddObject(module, "encodings", psycoEncodings);
#ifdef HAVE_MXDATETIME
/* If we can't find mx.DateTime objects at runtime,
* remove them from the module (and, as consequence, from the adapters). */
if (0 != psyco_adapter_mxdatetime_init()) {
PyDict_DelItemString(dict, "DateFromMx");
PyDict_DelItemString(dict, "TimeFromMx");
PyDict_DelItemString(dict, "TimestampFromMx");
PyDict_DelItemString(dict, "IntervalFromMx");
}
#endif
/* initialize default set of typecasters */
if (0 != typecast_init(dict)) { goto exit; }
/* initialize microprotocols layer */
microprotocols_init(dict);
if (0 != psyco_adapters_init(dict)) { goto exit; }
/* create a standard set of exceptions and add them to the module's dict */
if (0 != psyco_errors_init()) { goto exit; }
psyco_errors_fill(dict);
Dprintf("initpsycopg: module initialization complete");
exit: exit:
#if PY_MAJOR_VERSION > 2 #if PY_MAJOR_VERSION > 2

View File

@ -50,7 +50,7 @@ typedef struct replicationCursorObject {
} replicationCursorObject; } replicationCursorObject;
RAISES_NEG int psyco_repl_curs_datetime_init(void); RAISES_NEG HIDDEN int psyco_repl_curs_datetime_init(void);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -48,7 +48,7 @@ struct replicationMessageObject {
int64_t send_time; int64_t send_time;
}; };
RAISES_NEG int psyco_replmsg_datetime_init(void); RAISES_NEG HIDDEN int psyco_replmsg_datetime_init(void);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -252,11 +252,14 @@ PyObject *psyco_default_binary_cast;
/* typecast_init - initialize the dictionary and create default types */ /* typecast_init - initialize the dictionary and create default types */
RAISES_NEG int RAISES_NEG int
typecast_init(PyObject *dict) typecast_init(PyObject *module)
{ {
int i; int i;
int rv = -1; int rv = -1;
typecastObject *t = NULL; typecastObject *t = NULL;
PyObject *dict = NULL;
if (!(dict = PyModule_GetDict(module))) { goto exit; }
/* create type dictionary and put it in module namespace */ /* create type dictionary and put it in module namespace */
if (!(psyco_types = PyDict_New())) { goto exit; } if (!(psyco_types = PyDict_New())) { goto exit; }
@ -278,13 +281,14 @@ typecast_init(PyObject *dict)
/* export binary object */ /* export binary object */
if (typecast_builtins[i].values == typecast_BINARY_types) { if (typecast_builtins[i].values == typecast_BINARY_types) {
Py_INCREF((PyObject *)t);
psyco_default_binary_cast = (PyObject *)t; psyco_default_binary_cast = (PyObject *)t;
} }
Py_DECREF((PyObject *)t); Py_DECREF((PyObject *)t);
t = NULL; t = NULL;
} }
/* create and save a default cast object (but does not register it) */ /* create and save a default cast object (but do not register it) */
psyco_default_cast = typecast_from_c(&typecast_default, dict); psyco_default_cast = typecast_from_c(&typecast_default, dict);
/* register the date/time typecasters with their original names */ /* register the date/time typecasters with their original names */