Merge remote-tracking branch 'origin/code-cleanup'

This commit is contained in:
Daniele Varrazzo 2019-01-21 12:49:05 +00:00
commit 4246fdf809
19 changed files with 356 additions and 351 deletions

View File

@ -90,7 +90,9 @@ list_quote(listObject *self)
* array[array[]] is */ * array[array[]] is */
all_nulls = 0; all_nulls = 0;
Py_CLEAR(qs[i]); Py_CLEAR(qs[i]);
qs[i] = Bytes_FromString("ARRAY[]"); if (!(qs[i] = Bytes_FromString("ARRAY[]"))) {
goto exit;
}
} }
} }
else { else {

View File

@ -113,14 +113,14 @@ qstring_str(qstringObject *self)
static PyObject * static PyObject *
qstring_prepare(qstringObject *self, PyObject *args) qstring_prepare(qstringObject *self, PyObject *args)
{ {
connectionObject *conn; PyObject *conn;
if (!PyArg_ParseTuple(args, "O!", &connectionType, &conn)) if (!PyArg_ParseTuple(args, "O!", &connectionType, &conn))
return NULL; return NULL;
Py_CLEAR(self->conn); Py_CLEAR(self->conn);
Py_INCREF(conn); Py_INCREF(conn);
self->conn = conn; self->conn = (connectionObject *)conn;
Py_RETURN_NONE; Py_RETURN_NONE;
} }

View File

@ -79,10 +79,7 @@
#define PSYCOPG_MODULE #define PSYCOPG_MODULE
#include "psycopg/psycopg.h" #include "psycopg/psycopg.h"
#include "pyport.h"
#ifndef Py_LOCAL_INLINE
#define Py_LOCAL_INLINE(type) static type
#endif
/* Helpers for formatstring */ /* Helpers for formatstring */
@ -102,6 +99,19 @@ getnextarg(PyObject *args, Py_ssize_t arglen, Py_ssize_t *p_argidx)
return NULL; return NULL;
} }
/* wrapper around _Bytes_Resize offering normal Python call semantics */
STEALS(1)
Py_LOCAL_INLINE(PyObject *)
resize_bytes(PyObject *b, Py_ssize_t newsize) {
if (0 == _Bytes_Resize(&b, newsize)) {
return b;
}
else {
return NULL;
}
}
/* fmt%(v1,v2,...) is roughly equivalent to sprintf(fmt, v1, v2, ...) */ /* fmt%(v1,v2,...) is roughly equivalent to sprintf(fmt, v1, v2, ...) */
PyObject * PyObject *
@ -114,7 +124,7 @@ Bytes_Format(PyObject *format, PyObject *args)
PyObject *result; PyObject *result;
PyObject *dict = NULL; PyObject *dict = NULL;
if (format == NULL || !Bytes_Check(format) || args == NULL) { if (format == NULL || !Bytes_Check(format) || args == NULL) {
PyErr_BadInternalCall(); PyErr_SetString(PyExc_SystemError, "bad argument to internal function");
return NULL; return NULL;
} }
fmt = Bytes_AS_STRING(format); fmt = Bytes_AS_STRING(format);
@ -123,7 +133,7 @@ Bytes_Format(PyObject *format, PyObject *args)
result = Bytes_FromStringAndSize((char *)NULL, reslen); result = Bytes_FromStringAndSize((char *)NULL, reslen);
if (result == NULL) if (result == NULL)
return NULL; return NULL;
res = Bytes_AsString(result); res = Bytes_AS_STRING(result);
if (PyTuple_Check(args)) { if (PyTuple_Check(args)) {
arglen = PyTuple_GET_SIZE(args); arglen = PyTuple_GET_SIZE(args);
argidx = 0; argidx = 0;
@ -140,10 +150,10 @@ Bytes_Format(PyObject *format, PyObject *args)
if (--rescnt < 0) { if (--rescnt < 0) {
rescnt = fmtcnt + 100; rescnt = fmtcnt + 100;
reslen += rescnt; reslen += rescnt;
if (_Bytes_Resize(&result, reslen)) if (!(result = resize_bytes(result, reslen))) {
return NULL; return NULL;
res = Bytes_AS_STRING(result) }
+ reslen - rescnt; res = Bytes_AS_STRING(result) + reslen - rescnt;
--rescnt; --rescnt;
} }
*res++ = *fmt++; *res++ = *fmt++;
@ -210,11 +220,6 @@ Bytes_Format(PyObject *format, PyObject *args)
"incomplete format"); "incomplete format");
goto error; goto error;
} }
if (c != '%') {
v = getnextarg(args, arglen, &argidx);
if (v == NULL)
goto error;
}
switch (c) { switch (c) {
case '%': case '%':
pbuf = "%"; pbuf = "%";
@ -222,6 +227,8 @@ Bytes_Format(PyObject *format, PyObject *args)
break; break;
case 's': case 's':
/* only bytes! */ /* only bytes! */
if (!(v = getnextarg(args, arglen, &argidx)))
goto error;
if (!Bytes_CheckExact(v)) { if (!Bytes_CheckExact(v)) {
PyErr_Format(PyExc_ValueError, PyErr_Format(PyExc_ValueError,
"only bytes values expected, got %s", "only bytes values expected, got %s",
@ -238,8 +245,7 @@ Bytes_Format(PyObject *format, PyObject *args)
"unsupported format character '%c' (0x%x) " "unsupported format character '%c' (0x%x) "
"at index " FORMAT_CODE_PY_SSIZE_T, "at index " FORMAT_CODE_PY_SSIZE_T,
c, c, c, c,
(Py_ssize_t)(fmt - 1 - (Py_ssize_t)(fmt - 1 - Bytes_AS_STRING(format)));
Bytes_AsString(format)));
goto error; goto error;
} }
if (width < len) if (width < len)
@ -251,10 +257,14 @@ Bytes_Format(PyObject *format, PyObject *args)
if (reslen < 0) { if (reslen < 0) {
Py_DECREF(result); Py_DECREF(result);
Py_XDECREF(temp); Py_XDECREF(temp);
if (args_owned)
Py_DECREF(args);
return PyErr_NoMemory(); return PyErr_NoMemory();
} }
if (_Bytes_Resize(&result, reslen)) { if (!(result = resize_bytes(result, reslen))) {
Py_XDECREF(temp); Py_XDECREF(temp);
if (args_owned)
Py_DECREF(args);
return NULL; return NULL;
} }
res = Bytes_AS_STRING(result) res = Bytes_AS_STRING(result)
@ -284,8 +294,9 @@ Bytes_Format(PyObject *format, PyObject *args)
if (args_owned) { if (args_owned) {
Py_DECREF(args); Py_DECREF(args);
} }
if (_Bytes_Resize(&result, reslen - rescnt)) if (!(result = resize_bytes(result, reslen - rescnt))) {
return NULL; return NULL;
}
return result; return result;
error: error:

View File

@ -248,7 +248,7 @@ static PySequenceMethods column_sequence = {
static PyObject * static PyObject *
column_getstate(columnObject *self) column_getstate(columnObject *self, PyObject *dummy)
{ {
return PyObject_CallFunctionObjArgs( return PyObject_CallFunctionObjArgs(
(PyObject *)&PyTuple_Type, (PyObject *)self, NULL); (PyObject *)&PyTuple_Type, (PyObject *)self, NULL);

View File

@ -121,10 +121,6 @@ exit:
PyObject * PyObject *
conn_decode(connectionObject *self, const char *str, Py_ssize_t len) conn_decode(connectionObject *self, const char *str, Py_ssize_t len)
{ {
PyObject *b = NULL;
PyObject *t = NULL;
PyObject *rv = NULL;
if (len < 0) { len = strlen(str); } if (len < 0) { len = strlen(str); }
if (self) { if (self) {
@ -132,22 +128,28 @@ conn_decode(connectionObject *self, const char *str, Py_ssize_t len)
return self->cdecoder(str, len, NULL); return self->cdecoder(str, len, NULL);
} }
else if (self->pydecoder) { else if (self->pydecoder) {
if (!(b = Bytes_FromStringAndSize(str, len))) { goto exit; } PyObject *b = NULL;
PyObject *t = NULL;
PyObject *rv = NULL;
if (!(b = Bytes_FromStringAndSize(str, len))) { goto error; }
if (!(t = PyObject_CallFunctionObjArgs(self->pydecoder, b, NULL))) { if (!(t = PyObject_CallFunctionObjArgs(self->pydecoder, b, NULL))) {
goto exit; goto error;
} }
rv = PyTuple_GetItem(t, 0); if (!(rv = PyTuple_GetItem(t, 0))) { goto error; }
Py_XINCREF(rv); Py_INCREF(rv); /* PyTuple_GetItem gives a borrowes one */
error:
Py_XDECREF(t);
Py_XDECREF(b);
return rv;
}
else {
return PyUnicode_FromStringAndSize(str, len);
} }
} }
else { else {
return PyUnicode_FromStringAndSize(str, len); return PyUnicode_FromStringAndSize(str, len);
} }
exit:
Py_XDECREF(t);
Py_XDECREF(b);
return rv;
} }
/* conn_notice_callback - process notices */ /* conn_notice_callback - process notices */
@ -1079,7 +1081,16 @@ conn_poll(connectionObject *self)
/* An async query has just finished: parse the tuple in the /* An async query has just finished: parse the tuple in the
* target cursor. */ * target cursor. */
cursorObject *curs; cursorObject *curs;
PyObject *py_curs = PyWeakref_GetObject(self->async_cursor); PyObject *py_curs;
if (!(py_curs = PyWeakref_GetObject(self->async_cursor))) {
/* It shouldn't happen but consider it to avoid dereferencing
* a null pointer below. */
pq_clear_async(self);
PyErr_SetString(PyExc_SystemError,
"got null dereferencing cursor weakref");
res = PSYCO_POLL_ERROR;
break;
}
if (Py_None == py_curs) { if (Py_None == py_curs) {
pq_clear_async(self); pq_clear_async(self);
PyErr_SetString(InterfaceError, PyErr_SetString(InterfaceError,

View File

@ -112,10 +112,10 @@ psyco_conn_cursor(connectionObject *self, PyObject *args, PyObject *kwargs)
goto exit; goto exit;
} }
if (0 != psyco_curs_withhold_set((cursorObject *)obj, withhold)) { if (0 > psyco_curs_withhold_set((cursorObject *)obj, withhold)) {
goto exit; goto exit;
} }
if (0 != psyco_curs_scrollable_set((cursorObject *)obj, scrollable)) { if (0 > psyco_curs_scrollable_set((cursorObject *)obj, scrollable)) {
goto exit; goto exit;
} }
@ -138,7 +138,7 @@ exit:
#define psyco_conn_close_doc "close() -- Close the connection." #define psyco_conn_close_doc "close() -- Close the connection."
static PyObject * static PyObject *
psyco_conn_close(connectionObject *self) psyco_conn_close(connectionObject *self, PyObject *dummy)
{ {
Dprintf("psyco_conn_close: closing connection at %p", self); Dprintf("psyco_conn_close: closing connection at %p", self);
conn_close(self); conn_close(self);
@ -153,7 +153,7 @@ psyco_conn_close(connectionObject *self)
#define psyco_conn_commit_doc "commit() -- Commit all changes to database." #define psyco_conn_commit_doc "commit() -- Commit all changes to database."
static PyObject * static PyObject *
psyco_conn_commit(connectionObject *self) psyco_conn_commit(connectionObject *self, PyObject *dummy)
{ {
EXC_IF_CONN_CLOSED(self); EXC_IF_CONN_CLOSED(self);
EXC_IF_CONN_ASYNC(self, commit); EXC_IF_CONN_ASYNC(self, commit);
@ -172,7 +172,7 @@ psyco_conn_commit(connectionObject *self)
"rollback() -- Roll back all changes done to database." "rollback() -- Roll back all changes done to database."
static PyObject * static PyObject *
psyco_conn_rollback(connectionObject *self) psyco_conn_rollback(connectionObject *self, PyObject *dummy)
{ {
EXC_IF_CONN_CLOSED(self); EXC_IF_CONN_CLOSED(self);
EXC_IF_CONN_ASYNC(self, rollback); EXC_IF_CONN_ASYNC(self, rollback);
@ -245,7 +245,7 @@ exit:
"tpc_prepare() -- perform the first phase of a two-phase transaction." "tpc_prepare() -- perform the first phase of a two-phase transaction."
static PyObject * static PyObject *
psyco_conn_tpc_prepare(connectionObject *self) psyco_conn_tpc_prepare(connectionObject *self, PyObject *dummy)
{ {
EXC_IF_CONN_CLOSED(self); EXC_IF_CONN_CLOSED(self);
EXC_IF_CONN_ASYNC(self, tpc_prepare); EXC_IF_CONN_ASYNC(self, tpc_prepare);
@ -388,7 +388,7 @@ psyco_conn_tpc_rollback(connectionObject *self, PyObject *args)
"tpc_recover() -- returns a list of pending transaction IDs." "tpc_recover() -- returns a list of pending transaction IDs."
static PyObject * static PyObject *
psyco_conn_tpc_recover(connectionObject *self) psyco_conn_tpc_recover(connectionObject *self, PyObject *dummy)
{ {
EXC_IF_CONN_CLOSED(self); EXC_IF_CONN_CLOSED(self);
EXC_IF_CONN_ASYNC(self, tpc_recover); EXC_IF_CONN_ASYNC(self, tpc_recover);
@ -403,7 +403,7 @@ psyco_conn_tpc_recover(connectionObject *self)
"__enter__ -> self" "__enter__ -> self"
static PyObject * static PyObject *
psyco_conn_enter(connectionObject *self) psyco_conn_enter(connectionObject *self, PyObject *dummy)
{ {
EXC_IF_CONN_CLOSED(self); EXC_IF_CONN_CLOSED(self);
@ -828,7 +828,7 @@ psyco_conn_deferrable_set(connectionObject *self, PyObject *pyvalue)
"get_native_connection() -- Return the internal PGconn* as a Python Capsule." "get_native_connection() -- Return the internal PGconn* as a Python Capsule."
static PyObject * static PyObject *
psyco_get_native_connection(connectionObject *self) psyco_get_native_connection(connectionObject *self, PyObject *dummy)
{ {
EXC_IF_CONN_CLOSED(self); EXC_IF_CONN_CLOSED(self);
@ -866,7 +866,7 @@ psyco_conn_set_client_encoding(connectionObject *self, PyObject *args)
"get_transaction_status() -- Get backend transaction status." "get_transaction_status() -- Get backend transaction status."
static PyObject * static PyObject *
psyco_conn_get_transaction_status(connectionObject *self) psyco_conn_get_transaction_status(connectionObject *self, PyObject *dummy)
{ {
return PyInt_FromLong((long)PQtransactionStatus(self->pgconn)); return PyInt_FromLong((long)PQtransactionStatus(self->pgconn));
} }
@ -905,7 +905,7 @@ psyco_conn_get_parameter_status(connectionObject *self, PyObject *args)
"get_dsn_parameters() -- Get effective connection parameters.\n\n" "get_dsn_parameters() -- Get effective connection parameters.\n\n"
static PyObject * static PyObject *
psyco_conn_get_dsn_parameters(connectionObject *self) psyco_conn_get_dsn_parameters(connectionObject *self, PyObject *dummy)
{ {
#if PG_VERSION_NUM >= 90300 #if PG_VERSION_NUM >= 90300
PyObject *res = NULL; PyObject *res = NULL;
@ -998,7 +998,7 @@ psyco_conn_lobject(connectionObject *self, PyObject *args, PyObject *keywds)
"get_backend_pid() -- Get backend process id." "get_backend_pid() -- Get backend process id."
static PyObject * static PyObject *
psyco_conn_get_backend_pid(connectionObject *self) psyco_conn_get_backend_pid(connectionObject *self, PyObject *dummy)
{ {
EXC_IF_CONN_CLOSED(self); EXC_IF_CONN_CLOSED(self);
@ -1025,7 +1025,7 @@ psyco_conn_info_get(connectionObject *self)
"reset() -- Reset current connection to defaults." "reset() -- Reset current connection to defaults."
static PyObject * static PyObject *
psyco_conn_reset(connectionObject *self) psyco_conn_reset(connectionObject *self, PyObject *dummy)
{ {
int res; int res;
@ -1056,7 +1056,7 @@ psyco_conn_get_exception(PyObject *self, void *closure)
"poll() -> int -- Advance the connection or query process without blocking." "poll() -> int -- Advance the connection or query process without blocking."
static PyObject * static PyObject *
psyco_conn_poll(connectionObject *self) psyco_conn_poll(connectionObject *self, PyObject *dummy)
{ {
int res; int res;
@ -1076,7 +1076,7 @@ psyco_conn_poll(connectionObject *self)
"fileno() -> int -- Return file descriptor associated to database connection." "fileno() -> int -- Return file descriptor associated to database connection."
static PyObject * static PyObject *
psyco_conn_fileno(connectionObject *self) psyco_conn_fileno(connectionObject *self, PyObject *dummy)
{ {
long int socket; long int socket;
@ -1093,7 +1093,7 @@ psyco_conn_fileno(connectionObject *self)
"executing an asynchronous operation." "executing an asynchronous operation."
static PyObject * static PyObject *
psyco_conn_isexecuting(connectionObject *self) psyco_conn_isexecuting(connectionObject *self, PyObject *dummy)
{ {
/* synchronous connections will always return False */ /* synchronous connections will always return False */
if (self->async == 0) { if (self->async == 0) {
@ -1119,7 +1119,7 @@ psyco_conn_isexecuting(connectionObject *self)
"cancel() -- cancel the current operation" "cancel() -- cancel the current operation"
static PyObject * static PyObject *
psyco_conn_cancel(connectionObject *self) psyco_conn_cancel(connectionObject *self, PyObject *dummy)
{ {
char errbuf[256]; char errbuf[256];

View File

@ -93,8 +93,8 @@ struct cursorObject {
/* C-callable functions in cursor_int.c and cursor_type.c */ /* C-callable functions in cursor_int.c and cursor_type.c */
BORROWED HIDDEN PyObject *curs_get_cast(cursorObject *self, PyObject *oid); BORROWED HIDDEN PyObject *curs_get_cast(cursorObject *self, PyObject *oid);
HIDDEN void curs_reset(cursorObject *self); HIDDEN void curs_reset(cursorObject *self);
HIDDEN int psyco_curs_withhold_set(cursorObject *self, PyObject *pyvalue); RAISES_NEG HIDDEN int psyco_curs_withhold_set(cursorObject *self, PyObject *pyvalue);
HIDDEN int psyco_curs_scrollable_set(cursorObject *self, PyObject *pyvalue); RAISES_NEG HIDDEN int psyco_curs_scrollable_set(cursorObject *self, PyObject *pyvalue);
HIDDEN PyObject *psyco_curs_validate_sql_basic(cursorObject *self, PyObject *sql); HIDDEN PyObject *psyco_curs_validate_sql_basic(cursorObject *self, PyObject *sql);
/* exception-raising macros */ /* exception-raising macros */

View File

@ -47,7 +47,7 @@
"close() -- Close the cursor." "close() -- Close the cursor."
static PyObject * static PyObject *
psyco_curs_close(cursorObject *self) psyco_curs_close(cursorObject *self, PyObject *dummy)
{ {
PyObject *rv = NULL; PyObject *rv = NULL;
char *lname = NULL; char *lname = NULL;
@ -372,20 +372,17 @@ _psyco_curs_merge_query_args(cursorObject *self,
RAISES_NEG static int RAISES_NEG static int
_psyco_curs_execute(cursorObject *self, _psyco_curs_execute(cursorObject *self,
PyObject *operation, PyObject *vars, PyObject *query, PyObject *vars,
long int async, int no_result) long int async, int no_result)
{ {
int res = -1; int res = -1;
int tmp; int tmp;
PyObject *fquery, *cvt = NULL; PyObject *fquery = NULL, *cvt = NULL;
const char *scroll;
operation = psyco_curs_validate_sql_basic(self, operation); /* query becomes NULL or refcount +1, so good to XDECREF at the end */
if (!(query = psyco_curs_validate_sql_basic(self, query))) {
/* Any failure from here forward should 'goto fail' rather than 'return 0' goto exit;
directly. */ }
if (operation == NULL) { goto exit; }
CLEARPGRES(self->pgres); CLEARPGRES(self->pgres);
Py_CLEAR(self->query); Py_CLEAR(self->query);
@ -394,12 +391,24 @@ _psyco_curs_execute(cursorObject *self,
/* here we are, and we have a sequence or a dictionary filled with /* here we are, and we have a sequence or a dictionary filled with
objects to be substituted (bound variables). we try to be smart and do objects to be substituted (bound variables). we try to be smart and do
the right thing (i.e., what the user expects) */ the right thing (i.e., what the user expects) */
if (vars && vars != Py_None) if (vars && vars != Py_None)
{ {
if (0 > _mogrify(vars, operation, self, &cvt)) { goto exit; } if (0 > _mogrify(vars, query, self, &cvt)) { goto exit; }
} }
/* Merge the query to the arguments if needed */
if (cvt) {
if (!(fquery = _psyco_curs_merge_query_args(self, query, cvt))) {
goto exit;
}
}
else {
Py_INCREF(query);
fquery = query;
}
if (self->qname != NULL) {
const char *scroll;
switch (self->scrollable) { switch (self->scrollable) {
case -1: case -1:
scroll = ""; scroll = "";
@ -415,44 +424,23 @@ _psyco_curs_execute(cursorObject *self,
goto exit; goto exit;
} }
if (vars && cvt) { if (!(self->query = Bytes_FromFormat(
if (!(fquery = _psyco_curs_merge_query_args(self, operation, cvt))) { "DECLARE %s %sCURSOR %s HOLD FOR %s",
self->qname,
scroll,
self->withhold ? "WITH" : "WITHOUT",
Bytes_AS_STRING(fquery)))) {
goto exit; goto exit;
} }
if (!self->query) { goto exit; }
if (self->qname != NULL) {
self->query = Bytes_FromFormat(
"DECLARE %s %sCURSOR %s HOLD FOR %s",
self->qname,
scroll,
self->withhold ? "WITH" : "WITHOUT",
Bytes_AS_STRING(fquery));
Py_DECREF(fquery);
} }
else { else {
/* Transfer ownership */
Py_INCREF(fquery);
self->query = fquery; self->query = fquery;
} }
}
else {
if (self->qname != NULL) {
self->query = Bytes_FromFormat(
"DECLARE %s %sCURSOR %s HOLD FOR %s",
self->qname,
scroll,
self->withhold ? "WITH" : "WITHOUT",
Bytes_AS_STRING(operation));
}
else {
/* Transfer reference ownership of the str in operation to
self->query, clearing the local variable to prevent cleanup from
DECREFing it */
self->query = operation;
operation = NULL;
}
}
/* At this point, the SQL statement must be str, not unicode */ /* At this point, the SQL statement must be str, not unicode */
tmp = pq_execute(self, Bytes_AS_STRING(self->query), async, no_result, 0); tmp = pq_execute(self, Bytes_AS_STRING(self->query), async, no_result, 0);
Dprintf("psyco_curs_execute: res = %d, pgres = %p", tmp, self->pgres); Dprintf("psyco_curs_execute: res = %d, pgres = %p", tmp, self->pgres);
if (tmp < 0) { goto exit; } if (tmp < 0) { goto exit; }
@ -460,10 +448,8 @@ _psyco_curs_execute(cursorObject *self,
res = 0; /* Success */ res = 0; /* Success */
exit: exit:
/* Py_XDECREF(operation) is safe because the original reference passed Py_XDECREF(query);
by the caller was overwritten with either NULL or a new Py_XDECREF(fquery);
reference */
Py_XDECREF(operation);
Py_XDECREF(cvt); Py_XDECREF(cvt);
return res; return res;
@ -756,7 +742,7 @@ exit:
} }
static PyObject * static PyObject *
psyco_curs_fetchone(cursorObject *self) psyco_curs_fetchone(cursorObject *self, PyObject *dummy)
{ {
PyObject *res; PyObject *res;
@ -947,7 +933,7 @@ exit:
"Return `!None` when no more data is available.\n" "Return `!None` when no more data is available.\n"
static PyObject * static PyObject *
psyco_curs_fetchall(cursorObject *self) psyco_curs_fetchall(cursorObject *self, PyObject *dummy)
{ {
int i, size; int i, size;
PyObject *list = NULL; PyObject *list = NULL;
@ -1162,7 +1148,7 @@ exit:
"sets) and will raise a NotSupportedError exception." "sets) and will raise a NotSupportedError exception."
static PyObject * static PyObject *
psyco_curs_nextset(cursorObject *self) psyco_curs_nextset(cursorObject *self, PyObject *dummy)
{ {
EXC_IF_CURS_CLOSED(self); EXC_IF_CURS_CLOSED(self);
@ -1279,7 +1265,7 @@ psyco_curs_scroll(cursorObject *self, PyObject *args, PyObject *kwargs)
"__enter__ -> self" "__enter__ -> self"
static PyObject * static PyObject *
psyco_curs_enter(cursorObject *self) psyco_curs_enter(cursorObject *self, PyObject *dummy)
{ {
Py_INCREF(self); Py_INCREF(self);
return (PyObject *)self; return (PyObject *)self;
@ -1394,27 +1380,6 @@ exit:
#define psyco_curs_copy_from_doc \ #define psyco_curs_copy_from_doc \
"copy_from(file, table, sep='\\t', null='\\\\N', size=8192, columns=None) -- Copy table from file." "copy_from(file, table, sep='\\t', null='\\\\N', size=8192, columns=None) -- Copy table from file."
STEALS(1) static int
_psyco_curs_has_read_check(PyObject *o, PyObject **var)
{
if (PyObject_HasAttrString(o, "readline")
&& PyObject_HasAttrString(o, "read")) {
/* This routine stores a borrowed reference. Although it is only held
* for the duration of psyco_curs_copy_from, nested invocations of
* Py_BEGIN_ALLOW_THREADS could surrender control to another thread,
* which could invoke the garbage collector. We thus need an
* INCREF/DECREF pair if we store this pointer in a GC object, such as
* a cursorObject */
*var = o;
return 1;
}
else {
PyErr_SetString(PyExc_TypeError,
"argument 1 must have both .read() and .readline() methods");
return 0;
}
}
static PyObject * static PyObject *
psyco_curs_copy_from(cursorObject *self, PyObject *args, PyObject *kwargs) psyco_curs_copy_from(cursorObject *self, PyObject *args, PyObject *kwargs)
{ {
@ -1436,11 +1401,15 @@ psyco_curs_copy_from(cursorObject *self, PyObject *args, PyObject *kwargs)
Py_ssize_t bufsize = DEFAULT_COPYBUFF; Py_ssize_t bufsize = DEFAULT_COPYBUFF;
PyObject *file, *columns = NULL, *res = NULL; PyObject *file, *columns = NULL, *res = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, if (!PyArg_ParseTupleAndKeywords(
"O&s|ssnO", kwlist, args, kwargs, "Os|ssnO", kwlist,
_psyco_curs_has_read_check, &file, &table_name, &sep, &null, &bufsize, &file, &table_name, &sep, &null, &bufsize, &columns)) {
&columns)) return NULL;
{ }
if (!PyObject_HasAttrString(file, "read")) {
PyErr_SetString(PyExc_TypeError,
"argument 1 must have a .read() method");
return NULL; return NULL;
} }
@ -1474,6 +1443,12 @@ psyco_curs_copy_from(cursorObject *self, PyObject *args, PyObject *kwargs)
Dprintf("psyco_curs_copy_from: query = %s", query); Dprintf("psyco_curs_copy_from: query = %s", query);
/* This routine stores a borrowed reference. Although it is only held
* for the duration of psyco_curs_copy_from, nested invocations of
* Py_BEGIN_ALLOW_THREADS could surrender control to another thread,
* which could invoke the garbage collector. We thus need an
* INCREF/DECREF pair if we store this pointer in a GC object, such as
* a cursorObject */
self->copysize = bufsize; self->copysize = bufsize;
Py_INCREF(file); Py_INCREF(file);
self->copyfile = file; self->copyfile = file;
@ -1499,20 +1474,6 @@ exit:
#define psyco_curs_copy_to_doc \ #define psyco_curs_copy_to_doc \
"copy_to(file, table, sep='\\t', null='\\\\N', columns=None) -- Copy table to file." "copy_to(file, table, sep='\\t', null='\\\\N', columns=None) -- Copy table to file."
STEALS(1) static int
_psyco_curs_has_write_check(PyObject *o, PyObject **var)
{
if (PyObject_HasAttrString(o, "write")) {
*var = o;
return 1;
}
else {
PyErr_SetString(PyExc_TypeError,
"argument 1 must have a .write() method");
return 0;
}
}
static PyObject * static PyObject *
psyco_curs_copy_to(cursorObject *self, PyObject *args, PyObject *kwargs) psyco_curs_copy_to(cursorObject *self, PyObject *args, PyObject *kwargs)
{ {
@ -1530,11 +1491,17 @@ psyco_curs_copy_to(cursorObject *self, PyObject *args, PyObject *kwargs)
char *quoted_null = NULL; char *quoted_null = NULL;
const char *table_name; const char *table_name;
PyObject *file, *columns = NULL, *res = NULL; PyObject *file = NULL, *columns = NULL, *res = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&s|ssO", kwlist, if (!PyArg_ParseTupleAndKeywords(
_psyco_curs_has_write_check, &file, args, kwargs, "Os|ssO", kwlist,
&table_name, &sep, &null, &columns)) { &file, &table_name, &sep, &null, &columns)) {
return NULL;
}
if (!PyObject_HasAttrString(file, "write")) {
PyErr_SetString(PyExc_TypeError,
"argument 1 must have a .write() method");
return NULL; return NULL;
} }
@ -1681,7 +1648,7 @@ psyco_curs_withhold_get(cursorObject *self)
return PyBool_FromLong(self->withhold); return PyBool_FromLong(self->withhold);
} }
int RAISES_NEG int
psyco_curs_withhold_set(cursorObject *self, PyObject *pyvalue) psyco_curs_withhold_set(cursorObject *self, PyObject *pyvalue)
{ {
int value; int value;
@ -1726,7 +1693,7 @@ psyco_curs_scrollable_get(cursorObject *self)
return ret; return ret;
} }
int RAISES_NEG int
psyco_curs_scrollable_set(cursorObject *self, PyObject *pyvalue) psyco_curs_scrollable_set(cursorObject *self, PyObject *pyvalue)
{ {
int value; int value;
@ -1768,7 +1735,7 @@ cursor_next(PyObject *self)
if (NULL == ((cursorObject*)self)->name) { if (NULL == ((cursorObject*)self)->name) {
/* we don't parse arguments: psyco_curs_fetchone will do that for us */ /* we don't parse arguments: psyco_curs_fetchone will do that for us */
res = psyco_curs_fetchone((cursorObject*)self); res = psyco_curs_fetchone((cursorObject*)self, NULL);
/* convert a None to NULL to signal the end of iteration */ /* convert a None to NULL to signal the end of iteration */
if (res && res == Py_None) { if (res && res == Py_None) {

View File

@ -131,7 +131,7 @@ static struct PyGetSetDef error_getsets[] = {
* would require implementing __getstate__, and as of 2012 it's a little * would require implementing __getstate__, and as of 2012 it's a little
* bit too late to care. */ * bit too late to care. */
static PyObject * static PyObject *
psyco_error_reduce(errorObject *self) psyco_error_reduce(errorObject *self, PyObject *dummy)
{ {
PyObject *meth = NULL; PyObject *meth = NULL;
PyObject *tuple = NULL; PyObject *tuple = NULL;

View File

@ -36,6 +36,7 @@
#include "psycopg/config.h" #include "psycopg/config.h"
#include "psycopg/python.h" #include "psycopg/python.h"
#include "psycopg/utils.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -115,35 +116,6 @@ typedef struct {
char *pyenc; char *pyenc;
} encodingPair; } encodingPair;
/* the Decimal type, used by the DECIMAL typecaster */
HIDDEN PyObject *psyco_GetDecimalType(void);
/* forward declarations */
typedef struct cursorObject cursorObject;
typedef struct connectionObject connectionObject;
typedef struct replicationMessageObject replicationMessageObject;
/* some utility functions */
RAISES HIDDEN PyObject *psyco_set_error(PyObject *exc, cursorObject *curs, const char *msg);
HIDDEN char *psycopg_escape_string(connectionObject *conn,
const char *from, Py_ssize_t len, char *to, Py_ssize_t *tolen);
HIDDEN char *psycopg_escape_identifier(connectionObject *conn,
const char *str, Py_ssize_t len);
HIDDEN int psycopg_strdup(char **to, const char *from, Py_ssize_t len);
HIDDEN int psycopg_is_text_file(PyObject *f);
HIDDEN PyObject *psycopg_text_from_chars_safe(
const char *str, Py_ssize_t len, PyObject *decoder);
STEALS(1) HIDDEN PyObject * psycopg_ensure_bytes(PyObject *obj);
STEALS(1) HIDDEN PyObject * psycopg_ensure_text(PyObject *obj);
HIDDEN PyObject *psycopg_dict_from_conninfo_options(PQconninfoOption *options,
int include_password);
HIDDEN PyObject *psycopg_make_dsn(PyObject *dsn, PyObject *kwargs);
/* Exceptions docstrings */ /* Exceptions docstrings */
#define Error_doc \ #define Error_doc \
"Base class for error exceptions." "Base class for error exceptions."

View File

@ -39,7 +39,6 @@
#include "psycopg/typecast.h" #include "psycopg/typecast.h"
#include "psycopg/microprotocols.h" #include "psycopg/microprotocols.h"
#include "psycopg/microprotocols_proto.h" #include "psycopg/microprotocols_proto.h"
#include "psycopg/error.h"
#include "psycopg/conninfo.h" #include "psycopg/conninfo.h"
#include "psycopg/diagnostics.h" #include "psycopg/diagnostics.h"
@ -396,7 +395,7 @@ exit:
#define psyco_libpq_version_doc "Query actual libpq version loaded." #define psyco_libpq_version_doc "Query actual libpq version loaded."
static PyObject* static PyObject*
psyco_libpq_version(PyObject *self) psyco_libpq_version(PyObject *self, PyObject *dummy)
{ {
return PyInt_FromLong(PQlibVersion()); return PyInt_FromLong(PQlibVersion());
} }
@ -722,116 +721,6 @@ psyco_errors_set(PyObject *type)
} }
} }
/* psyco_set_error
Create a new error of the given type with extra attributes. */
/* TODO: may have been changed to BORROWED */
RAISES PyObject *
psyco_set_error(PyObject *exc, cursorObject *curs, const char *msg)
{
PyObject *pymsg;
PyObject *err = NULL;
connectionObject *conn = NULL;
if (curs) {
conn = ((cursorObject *)curs)->conn;
}
if ((pymsg = conn_text_from_chars(conn, msg))) {
err = PyObject_CallFunctionObjArgs(exc, pymsg, NULL);
Py_DECREF(pymsg);
}
else {
/* what's better than an error in an error handler in the morning?
* Anyway, some error was set, refcount is ok... get outta here. */
return NULL;
}
if (err && PyObject_TypeCheck(err, &errorType)) {
errorObject *perr = (errorObject *)err;
if (curs) {
Py_CLEAR(perr->cursor);
Py_INCREF(curs);
perr->cursor = curs;
}
}
if (err) {
PyErr_SetObject(exc, err);
Py_DECREF(err);
}
return err;
}
/* Return nonzero if the current one is the main interpreter */
static int
psyco_is_main_interp(void)
{
static PyInterpreterState *main_interp = NULL; /* Cached reference */
PyInterpreterState *interp;
if (main_interp) {
return (main_interp == PyThreadState_Get()->interp);
}
/* No cached value: cache the proper value and try again. */
interp = PyInterpreterState_Head();
while (interp->next)
interp = interp->next;
main_interp = interp;
assert (main_interp);
return psyco_is_main_interp();
}
/* psyco_GetDecimalType
Return a new reference to the adapter for decimal type.
If decimals should be used but the module import fails, fall back on
the float type.
If decimals are not to be used, return NULL.
*/
PyObject *
psyco_GetDecimalType(void)
{
static PyObject *cachedType = NULL;
PyObject *decimalType = NULL;
PyObject *decimal;
/* Use the cached object if running from the main interpreter. */
int can_cache = psyco_is_main_interp();
if (can_cache && cachedType) {
Py_INCREF(cachedType);
return cachedType;
}
/* Get a new reference to the Decimal type. */
decimal = PyImport_ImportModule("decimal");
if (decimal) {
decimalType = PyObject_GetAttrString(decimal, "Decimal");
Py_DECREF(decimal);
}
else {
PyErr_Clear();
decimalType = NULL;
}
/* Store the object from future uses. */
if (can_cache && !cachedType && decimalType) {
Py_INCREF(decimalType);
cachedType = decimalType;
}
return decimalType;
}
/** method table and module initialization **/ /** method table and module initialization **/
@ -1119,9 +1008,6 @@ INIT_MODULE(_psycopg)(void)
if (0 != psyco_errors_init()) { goto exit; } if (0 != psyco_errors_init()) { goto exit; }
psyco_errors_fill(dict); psyco_errors_fill(dict);
replicationPhysicalConst = PyDict_GetItemString(dict, "REPLICATION_PHYSICAL");
replicationLogicalConst = PyDict_GetItemString(dict, "REPLICATION_LOGICAL");
Dprintf("initpsycopg: module initialization complete"); Dprintf("initpsycopg: module initialization complete");
exit: exit:

View File

@ -45,9 +45,6 @@ typedef struct replicationConnectionObject {
#define REPLICATION_PHYSICAL 12345678 #define REPLICATION_PHYSICAL 12345678
#define REPLICATION_LOGICAL 87654321 #define REPLICATION_LOGICAL 87654321
extern HIDDEN PyObject *replicationPhysicalConst;
extern HIDDEN PyObject *replicationLogicalConst;
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -41,21 +41,7 @@
static PyObject * static PyObject *
psyco_repl_conn_get_type(replicationConnectionObject *self) psyco_repl_conn_get_type(replicationConnectionObject *self)
{ {
connectionObject *conn = &self->conn; return PyInt_FromLong(self->type);
PyObject *res = NULL;
EXC_IF_CONN_CLOSED(conn);
if (self->type == REPLICATION_PHYSICAL) {
res = replicationPhysicalConst;
} else if (self->type == REPLICATION_LOGICAL) {
res = replicationLogicalConst;
} else {
PyErr_Format(PyExc_TypeError, "unknown replication type constant: %ld", self->type);
}
Py_XINCREF(res);
return res;
} }
@ -63,15 +49,16 @@ static int
replicationConnection_init(replicationConnectionObject *self, replicationConnection_init(replicationConnectionObject *self,
PyObject *args, PyObject *kwargs) PyObject *args, PyObject *kwargs)
{ {
PyObject *dsn = NULL, *async = Py_False, *replication_type = NULL, PyObject *dsn = NULL, *async = Py_False,
*item = NULL, *extras = NULL, *cursor = NULL, *item = NULL, *extras = NULL, *cursor = NULL,
*newdsn = NULL, *newargs = NULL, *dsnopts = NULL; *newdsn = NULL, *newargs = NULL, *dsnopts = NULL;
int ret = -1; int ret = -1;
long int replication_type;
/* 'replication_type' is not actually optional, but there's no /* 'replication_type' is not actually optional, but there's no
good way to put it before 'async' in the list */ good way to put it before 'async' in the list */
static char *kwlist[] = {"dsn", "async", "replication_type", NULL}; static char *kwlist[] = {"dsn", "async", "replication_type", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OO", kwlist, if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Ol", kwlist,
&dsn, &async, &replication_type)) { &dsn, &async, &replication_type)) {
return ret; return ret;
} }
@ -87,9 +74,7 @@ replicationConnection_init(replicationConnectionObject *self,
if (!(extras = PyImport_ImportModule("psycopg2.extras"))) { goto exit; } if (!(extras = PyImport_ImportModule("psycopg2.extras"))) { goto exit; }
if (!(cursor = PyObject_GetAttrString(extras, "ReplicationCursor"))) { goto exit; } if (!(cursor = PyObject_GetAttrString(extras, "ReplicationCursor"))) { goto exit; }
/* checking the object reference helps to avoid recognizing if (replication_type == REPLICATION_PHYSICAL) {
unrelated integer constants as valid input values */
if (replication_type == replicationPhysicalConst) {
self->type = REPLICATION_PHYSICAL; self->type = REPLICATION_PHYSICAL;
#define SET_ITEM(k, v) \ #define SET_ITEM(k, v) \
@ -100,14 +85,15 @@ replicationConnection_init(replicationConnectionObject *self,
SET_ITEM(replication, true); SET_ITEM(replication, true);
SET_ITEM(dbname, replication); /* required for .pgpass lookup */ SET_ITEM(dbname, replication); /* required for .pgpass lookup */
} else if (replication_type == replicationLogicalConst) { } else if (replication_type == REPLICATION_LOGICAL) {
self->type = REPLICATION_LOGICAL; self->type = REPLICATION_LOGICAL;
SET_ITEM(replication, database); SET_ITEM(replication, database);
#undef SET_ITEM #undef SET_ITEM
} else { } else {
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
"replication_type must be either REPLICATION_PHYSICAL or REPLICATION_LOGICAL"); "replication_type must be either "
"REPLICATION_PHYSICAL or REPLICATION_LOGICAL");
goto exit; goto exit;
} }
@ -204,6 +190,3 @@ PyTypeObject replicationConnectionType = {
0, /*tp_alloc*/ 0, /*tp_alloc*/
0, /*tp_new*/ 0, /*tp_new*/
}; };
PyObject *replicationPhysicalConst;
PyObject *replicationLogicalConst;

View File

@ -140,7 +140,7 @@ psyco_repl_curs_consume_stream(replicationCursorObject *self,
"read_message() -- Try reading a replication message from the server (non-blocking)." "read_message() -- Try reading a replication message from the server (non-blocking)."
static PyObject * static PyObject *
psyco_repl_curs_read_message(replicationCursorObject *self) psyco_repl_curs_read_message(replicationCursorObject *self, PyObject *dummy)
{ {
cursorObject *curs = &self->cur; cursorObject *curs = &self->cur;
replicationMessageObject *msg = NULL; replicationMessageObject *msg = NULL;

View File

@ -58,12 +58,17 @@ replmsg_repr(replicationMessageObject *self)
static int static int
replmsg_init(PyObject *obj, PyObject *args, PyObject *kwargs) replmsg_init(PyObject *obj, PyObject *args, PyObject *kwargs)
{ {
replicationMessageObject *self = (replicationMessageObject*) obj; PyObject *cur = NULL;
replicationMessageObject *self = (replicationMessageObject *)obj;
if (!PyArg_ParseTuple(args, "O!O", &cursorType, &self->cursor, &self->payload)) if (!PyArg_ParseTuple(
args, "O!O", &cursorType, &cur, &self->payload)) {
return -1; return -1;
Py_XINCREF(self->cursor); }
Py_XINCREF(self->payload);
Py_INCREF(cur);
self->cursor = (cursorObject *)cur;
Py_INCREF(self->payload);
self->data_size = 0; self->data_size = 0;
self->data_start = 0; self->data_start = 0;
@ -76,7 +81,7 @@ replmsg_init(PyObject *obj, PyObject *args, PyObject *kwargs)
static int static int
replmsg_traverse(replicationMessageObject *self, visitproc visit, void *arg) replmsg_traverse(replicationMessageObject *self, visitproc visit, void *arg)
{ {
Py_VISIT((PyObject* )self->cursor); Py_VISIT((PyObject *)self->cursor);
Py_VISIT(self->payload); Py_VISIT(self->payload);
return 0; return 0;
} }

View File

@ -148,6 +148,7 @@ typecast_DECIMAL_cast(const char *s, Py_ssize_t len, PyObject *curs)
Py_DECREF(decimalType); Py_DECREF(decimalType);
} }
else { else {
PyErr_Clear();
res = PyObject_CallFunction((PyObject*)&PyFloat_Type, "s", buffer); res = PyObject_CallFunction((PyObject*)&PyFloat_Type, "s", buffer);
} }
PyMem_Free(buffer); PyMem_Free(buffer);

View File

@ -27,7 +27,9 @@
#include "psycopg/psycopg.h" #include "psycopg/psycopg.h"
#include "psycopg/connection.h" #include "psycopg/connection.h"
#include "psycopg/cursor.h"
#include "psycopg/pgtypes.h" #include "psycopg/pgtypes.h"
#include "psycopg/error.h"
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
@ -55,8 +57,8 @@ psycopg_escape_string(connectionObject *conn, const char *from, Py_ssize_t len,
if (len < 0) { if (len < 0) {
len = strlen(from); len = strlen(from);
} else if (strchr(from, '\0') != from + len) { } else if (strchr(from, '\0') != from + len) {
PyErr_Format(PyExc_ValueError, "A string literal cannot contain NUL (0x00) characters."); PyErr_Format(PyExc_ValueError,
"A string literal cannot contain NUL (0x00) characters.");
return NULL; return NULL;
} }
@ -356,3 +358,110 @@ exit:
#endif #endif
} }
/* psyco_set_error
*
* Create a new error of the given type with extra attributes.
*/
RAISES BORROWED PyObject *
psyco_set_error(PyObject *exc, cursorObject *curs, const char *msg)
{
PyObject *pymsg;
PyObject *err = NULL;
connectionObject *conn = NULL;
if (curs) {
conn = ((cursorObject *)curs)->conn;
}
if ((pymsg = conn_text_from_chars(conn, msg))) {
err = PyObject_CallFunctionObjArgs(exc, pymsg, NULL);
Py_DECREF(pymsg);
}
else {
/* what's better than an error in an error handler in the morning?
* Anyway, some error was set, refcount is ok... get outta here. */
return NULL;
}
if (err && PyObject_TypeCheck(err, &errorType)) {
errorObject *perr = (errorObject *)err;
if (curs) {
Py_CLEAR(perr->cursor);
Py_INCREF(curs);
perr->cursor = curs;
}
}
if (err) {
PyErr_SetObject(exc, err);
Py_DECREF(err);
}
return err;
}
/* Return nonzero if the current one is the main interpreter */
static int
psyco_is_main_interp(void)
{
static PyInterpreterState *main_interp = NULL; /* Cached reference */
PyInterpreterState *interp;
if (main_interp) {
return (main_interp == PyThreadState_Get()->interp);
}
/* No cached value: cache the proper value and try again. */
interp = PyInterpreterState_Head();
while (interp->next)
interp = interp->next;
main_interp = interp;
assert (main_interp);
return psyco_is_main_interp();
}
/* psyco_GetDecimalType
Return a new reference to the decimal type.
The function returns a cached version of the object, but only in the main
interpreter because subinterpreters are confusing.
*/
PyObject *
psyco_GetDecimalType(void)
{
static PyObject *cachedType = NULL;
PyObject *decimalType = NULL;
PyObject *decimal;
/* Use the cached object if running from the main interpreter. */
int can_cache = psyco_is_main_interp();
if (can_cache && cachedType) {
Py_INCREF(cachedType);
return cachedType;
}
/* Get a new reference to the Decimal type. */
decimal = PyImport_ImportModule("decimal");
if (decimal) {
decimalType = PyObject_GetAttrString(decimal, "Decimal");
Py_DECREF(decimal);
}
else {
decimalType = NULL;
}
/* Store the object from future uses. */
if (can_cache && !cachedType && decimalType) {
Py_INCREF(decimalType);
cachedType = decimalType;
}
return decimalType;
}

61
psycopg/utils.h Normal file
View File

@ -0,0 +1,61 @@
/* utils.h - function definitions for utility file
*
* Copyright (C) 2018 Daniele Varrazzo <daniele.varrazzo@gmail.com>
*
* This file is part of psycopg.
*
* psycopg2 is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* In addition, as a special exception, the copyright holders give
* permission to link this program with the OpenSSL library (or with
* modified versions of OpenSSL that use the same license as OpenSSL),
* and distribute linked combinations including the two.
*
* You must obey the GNU Lesser General Public License in all respects for
* all of the code used other than OpenSSL.
*
* psycopg2 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 Lesser General Public
* License for more details.
*/
#ifndef UTILS_H
#define UTILS_H 1
/* forward declarations */
typedef struct cursorObject cursorObject;
typedef struct connectionObject connectionObject;
typedef struct replicationMessageObject replicationMessageObject;
HIDDEN char *psycopg_escape_string(
connectionObject *conn,
const char *from, Py_ssize_t len, char *to, Py_ssize_t *tolen);
HIDDEN char *psycopg_escape_identifier(
connectionObject *conn, const char *str, Py_ssize_t len);
HIDDEN int psycopg_strdup(char **to, const char *from, Py_ssize_t len);
STEALS(1) HIDDEN PyObject * psycopg_ensure_bytes(PyObject *obj);
STEALS(1) HIDDEN PyObject * psycopg_ensure_text(PyObject *obj);
HIDDEN int psycopg_is_text_file(PyObject *f);
HIDDEN PyObject *psycopg_dict_from_conninfo_options(
PQconninfoOption *options, int include_password);
HIDDEN PyObject *psycopg_make_dsn(PyObject *dsn, PyObject *kwargs);
HIDDEN PyObject *psycopg_text_from_chars_safe(
const char *str, Py_ssize_t len, PyObject *decoder);
HIDDEN RAISES BORROWED PyObject *psyco_set_error(
PyObject *exc, cursorObject *curs, const char *msg);
HIDDEN PyObject *psyco_GetDecimalType(void);
#endif /* !defined(UTILS_H) */

View File

@ -509,7 +509,7 @@ depends = [
'replication_cursor.h', 'replication_cursor.h',
'replication_message.h', 'replication_message.h',
'notify.h', 'pqpath.h', 'xid.h', 'column.h', 'conninfo.h', 'notify.h', 'pqpath.h', 'xid.h', 'column.h', 'conninfo.h',
'libpq_support.h', 'win32_support.h', 'libpq_support.h', 'win32_support.h', 'utils.h',
'adapter_asis.h', 'adapter_binary.h', 'adapter_datetime.h', 'adapter_asis.h', 'adapter_binary.h', 'adapter_datetime.h',
'adapter_list.h', 'adapter_pboolean.h', 'adapter_pdecimal.h', 'adapter_list.h', 'adapter_pboolean.h', 'adapter_pdecimal.h',