From ac258169622ca758757e51338443a4cbed1e605d Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Fri, 31 Dec 2010 02:49:46 +0100 Subject: [PATCH] Use the same Bytes_Format function for both Python 2 and 3. This makes the behaviour between the two versions similar. It also have the effect of a more specific error message in case an user specifies a placeholder different from 's'. --- psycopg/bytes_format.c | 38 ++++++++++++++++++++------------------ psycopg/python.h | 13 ++++++------- setup.py | 5 +---- 3 files changed, 27 insertions(+), 29 deletions(-) diff --git a/psycopg/bytes_format.c b/psycopg/bytes_format.c index 3702a684..3c64f4ae 100644 --- a/psycopg/bytes_format.c +++ b/psycopg/bytes_format.c @@ -24,7 +24,9 @@ */ /* This implementation is based on the PyString_Format function available in - * Python 2.7.1. Original license follows. + * Python 2.7.1. The function is altered to be used with both Python 2 strings + * and Python 3 bytes and is stripped of the support of formats different than + * 's'. Original license follows. * * PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 * -------------------------------------------- @@ -99,7 +101,7 @@ getnextarg(PyObject *args, Py_ssize_t arglen, Py_ssize_t *p_argidx) /* fmt%(v1,v2,...) is roughly equivalent to sprintf(fmt, v1, v2, ...) */ PyObject * -PyBytes_Format(PyObject *format, PyObject *args) +Bytes_Format(PyObject *format, PyObject *args) { char *fmt, *res; Py_ssize_t arglen, argidx; @@ -107,18 +109,18 @@ PyBytes_Format(PyObject *format, PyObject *args) int args_owned = 0; PyObject *result, *orig_args; PyObject *dict = NULL; - if (format == NULL || !PyBytes_Check(format) || args == NULL) { + if (format == NULL || !Bytes_Check(format) || args == NULL) { PyErr_BadInternalCall(); return NULL; } orig_args = args; - fmt = PyBytes_AS_STRING(format); - fmtcnt = PyBytes_GET_SIZE(format); + fmt = Bytes_AS_STRING(format); + fmtcnt = Bytes_GET_SIZE(format); reslen = rescnt = fmtcnt + 100; - result = PyBytes_FromStringAndSize((char *)NULL, reslen); + result = Bytes_FromStringAndSize((char *)NULL, reslen); if (result == NULL) return NULL; - res = PyBytes_AsString(result); + res = Bytes_AsString(result); if (PyTuple_Check(args)) { arglen = PyTuple_GET_SIZE(args); argidx = 0; @@ -128,16 +130,16 @@ PyBytes_Format(PyObject *format, PyObject *args) argidx = -2; } if (Py_TYPE(args)->tp_as_mapping && !PyTuple_Check(args) && - !PyObject_TypeCheck(args, &PyBytes_Type)) + !PyObject_TypeCheck(args, &Bytes_Type)) dict = args; while (--fmtcnt >= 0) { if (*fmt != '%') { if (--rescnt < 0) { rescnt = fmtcnt + 100; reslen += rescnt; - if (_PyBytes_Resize(&result, reslen)) + if (_Bytes_Resize(&result, reslen)) return NULL; - res = PyBytes_AS_STRING(result) + res = Bytes_AS_STRING(result) + reslen - rescnt; --rescnt; } @@ -180,7 +182,7 @@ PyBytes_Format(PyObject *format, PyObject *args) "incomplete format key"); goto error; } - key = PyUnicode_FromStringAndSize(keystart, keylen); + key = Text_FromUTF8AndSize(keystart, keylen); if (key == NULL) goto error; if (args_owned) { @@ -217,7 +219,7 @@ PyBytes_Format(PyObject *format, PyObject *args) break; case 's': /* only bytes! */ - if (!PyBytes_CheckExact(v)) { + if (!Bytes_CheckExact(v)) { PyErr_Format(PyExc_ValueError, "only bytes values expected, got %s", Py_TYPE(v)->tp_name); @@ -225,8 +227,8 @@ PyBytes_Format(PyObject *format, PyObject *args) } temp = v; Py_INCREF(v); - pbuf = PyBytes_AS_STRING(temp); - len = PyBytes_GET_SIZE(temp); + pbuf = Bytes_AS_STRING(temp); + len = Bytes_GET_SIZE(temp); break; default: PyErr_Format(PyExc_ValueError, @@ -234,7 +236,7 @@ PyBytes_Format(PyObject *format, PyObject *args) "at index %zd", c, c, (Py_ssize_t)(fmt - 1 - - PyBytes_AsString(format))); + Bytes_AsString(format))); goto error; } if (width < len) @@ -248,11 +250,11 @@ PyBytes_Format(PyObject *format, PyObject *args) Py_XDECREF(temp); return PyErr_NoMemory(); } - if (_PyBytes_Resize(&result, reslen)) { + if (_Bytes_Resize(&result, reslen)) { Py_XDECREF(temp); return NULL; } - res = PyBytes_AS_STRING(result) + res = Bytes_AS_STRING(result) + reslen - rescnt; } Py_MEMCPY(res, pbuf, len); @@ -279,7 +281,7 @@ PyBytes_Format(PyObject *format, PyObject *args) if (args_owned) { Py_DECREF(args); } - if (_PyBytes_Resize(&result, reslen - rescnt)) + if (_Bytes_Resize(&result, reslen - rescnt)) return NULL; return result; diff --git a/psycopg/python.h b/psycopg/python.h index ee2dee76..1e46cc51 100644 --- a/psycopg/python.h +++ b/psycopg/python.h @@ -103,8 +103,7 @@ #endif /* PY_MAJOR_VERSION > 2 */ #if PY_MAJOR_VERSION < 3 -/* XXX BytesType -> Bytes_Type */ -#define BytesType PyString_Type +#define Bytes_Type PyString_Type #define Bytes_Check PyString_Check #define Bytes_CheckExact PyString_CheckExact #define Bytes_AS_STRING PyString_AS_STRING @@ -115,11 +114,11 @@ #define Bytes_FromString PyString_FromString #define Bytes_FromStringAndSize PyString_FromStringAndSize #define Bytes_FromFormat PyString_FromFormat -#define Bytes_Format PyString_Format +#define _Bytes_Resize _PyString_Resize #else -#define BytesType PyBytes_Type +#define Bytes_Type PyBytes_Type #define Bytes_Check PyBytes_Check #define Bytes_CheckExact PyBytes_CheckExact #define Bytes_AS_STRING PyBytes_AS_STRING @@ -130,12 +129,12 @@ #define Bytes_FromString PyBytes_FromString #define Bytes_FromStringAndSize PyBytes_FromStringAndSize #define Bytes_FromFormat PyBytes_FromFormat -#define Bytes_Format PyBytes_Format - -HIDDEN PyObject *PyBytes_Format(PyObject *format, PyObject *args); +#define _Bytes_Resize _PyBytes_Resize #endif +HIDDEN PyObject *Bytes_Format(PyObject *format, PyObject *args); + /* Mangle the module name into the name of the module init function */ #if PY_MAJOR_VERSION > 2 #define INIT_MODULE(m) PyInit_ ## m diff --git a/setup.py b/setup.py index b05bf9a7..701ad5bf 100644 --- a/setup.py +++ b/setup.py @@ -362,7 +362,7 @@ ext = [] ; data_files = [] sources = [ 'psycopgmodule.c', - 'green.c', 'pqpath.c', 'utils.c', + 'green.c', 'pqpath.c', 'utils.c', 'bytes_format.c', 'connection_int.c', 'connection_type.c', 'cursor_int.c', 'cursor_type.c', @@ -376,9 +376,6 @@ sources = [ 'typecast.c', ] -if sys.version_info[0] >= 3: - sources.append('bytes_format.c') - depends = [ # headers 'config.h', 'pgtypes.h', 'psycopg.h', 'python.h',