Don't import psycopg2.tz into the C extension

This makes possible to import _psycopg directly, after adding the
package directory to the pythonpath. This enables hacks such as:

    sys.path.insert(0, '/path/to/psycopg2')
    import _psycopg
    sys.modules['psycopg2._psycopg'] = _psycopg
    sys.path.pop(0)

which can work around e.g. the problem of #201, freeze that cannot
freeze psycopg2. Well, freeze cannot freeze it because it's just not
designed to deal with C extensions. At least now the frozen application
can hack the pythonpath and work around the limitation by importing
_psycopg as above and then doing the rest of the imports normally.

Keeping long-lived references to python objects is bad anyway: the
tz module couldn't be reloaded before.
This commit is contained in:
Daniele Varrazzo 2014-08-25 23:08:38 +01:00
parent 284677ae0a
commit b12f6a9135
3 changed files with 34 additions and 39 deletions

View File

@ -35,9 +35,6 @@
#include <string.h> #include <string.h>
extern HIDDEN PyObject *pyPsycopgTzModule;
extern HIDDEN PyObject *pyPsycopgTzLOCAL;
int int
psyco_adapter_datetime_init(void) psyco_adapter_datetime_init(void)
{ {
@ -430,6 +427,8 @@ psyco_TimeFromTicks(PyObject *self, PyObject *args)
PyObject * PyObject *
psyco_TimestampFromTicks(PyObject *self, PyObject *args) psyco_TimestampFromTicks(PyObject *self, PyObject *args)
{ {
PyObject *m = NULL;
PyObject *tz = NULL;
PyObject *res = NULL; PyObject *res = NULL;
struct tm tm; struct tm tm;
time_t t; time_t t;
@ -438,18 +437,25 @@ psyco_TimestampFromTicks(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "d", &ticks)) if (!PyArg_ParseTuple(args, "d", &ticks))
return NULL; return NULL;
/* get psycopg2.tz.LOCAL from pythonland */
if (!(m = PyImport_ImportModule("psycopg2.tz"))) { goto exit; }
if (!(tz = PyObject_GetAttrString(m, "LOCAL"))) { goto exit; }
t = (time_t)floor(ticks); t = (time_t)floor(ticks);
ticks -= (double)t; ticks -= (double)t;
if (localtime_r(&t, &tm)) { if (!localtime_r(&t, &tm)) {
PyErr_SetString(InterfaceError, "failed localtime call");
goto exit;
}
res = _psyco_Timestamp( res = _psyco_Timestamp(
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, (double)tm.tm_sec + ticks, tm.tm_hour, tm.tm_min, (double)tm.tm_sec + ticks,
pyPsycopgTzLOCAL); tz);
}
else {
PyErr_SetString(InterfaceError, "failed localtime call");
}
exit:
Py_DECREF(tz);
Py_XDECREF(m);
return res; return res;
} }

View File

@ -39,9 +39,6 @@
#include <stdlib.h> #include <stdlib.h>
extern PyObject *pyPsycopgTzFixedOffsetTimezone;
/** DBAPI methods **/ /** DBAPI methods **/
/* close method - close the cursor */ /* close method - close the cursor */
@ -1842,8 +1839,17 @@ cursor_setup(cursorObject *self, connectionObject *conn, const char *name)
self->tuple_factory = Py_None; self->tuple_factory = Py_None;
/* default tzinfo factory */ /* default tzinfo factory */
Py_INCREF(pyPsycopgTzFixedOffsetTimezone); {
self->tzinfo_factory = pyPsycopgTzFixedOffsetTimezone; PyObject *m = NULL;
if ((m = PyImport_ImportModule("psycopg2.tz"))) {
self->tzinfo_factory = PyObject_GetAttrString(
m, "FixedOffsetTimezone");
Py_DECREF(m);
}
if (!self->tzinfo_factory) {
return -1;
}
}
Dprintf("cursor_setup: good cursor object at %p, refcnt = " Dprintf("cursor_setup: good cursor object at %p, refcnt = "
FORMAT_CODE_PY_SSIZE_T, FORMAT_CODE_PY_SSIZE_T,

View File

@ -58,11 +58,6 @@
#include "psycopg/adapter_datetime.h" #include "psycopg/adapter_datetime.h"
HIDDEN PyObject *pyDateTimeModuleP = NULL; HIDDEN PyObject *pyDateTimeModuleP = NULL;
/* pointers to the psycopg.tz classes */
HIDDEN PyObject *pyPsycopgTzModule = NULL;
HIDDEN PyObject *pyPsycopgTzLOCAL = NULL;
HIDDEN PyObject *pyPsycopgTzFixedOffsetTimezone = NULL;
HIDDEN PyObject *psycoEncodings = NULL; HIDDEN PyObject *psycoEncodings = NULL;
#ifdef PSYCOPG_DEBUG #ifdef PSYCOPG_DEBUG
@ -859,18 +854,6 @@ INIT_MODULE(_psycopg)(void)
Py_TYPE(&pydatetimeType) = &PyType_Type; Py_TYPE(&pydatetimeType) = &PyType_Type;
if (PyType_Ready(&pydatetimeType) == -1) goto exit; if (PyType_Ready(&pydatetimeType) == -1) goto exit;
/* 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");
goto exit;
}
pyPsycopgTzLOCAL =
PyObject_GetAttrString(pyPsycopgTzModule, "LOCAL");
pyPsycopgTzFixedOffsetTimezone =
PyObject_GetAttrString(pyPsycopgTzModule, "FixedOffsetTimezone");
/* initialize the module and grab module's dictionary */ /* 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);