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'.
This commit is contained in:
Daniele Varrazzo 2010-12-31 02:49:46 +01:00
parent 2930ed3d59
commit ac25816962
3 changed files with 27 additions and 29 deletions

View File

@ -24,7 +24,9 @@
*/ */
/* This implementation is based on the PyString_Format function available in /* 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 * 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, ...) */ /* fmt%(v1,v2,...) is roughly equivalent to sprintf(fmt, v1, v2, ...) */
PyObject * PyObject *
PyBytes_Format(PyObject *format, PyObject *args) Bytes_Format(PyObject *format, PyObject *args)
{ {
char *fmt, *res; char *fmt, *res;
Py_ssize_t arglen, argidx; Py_ssize_t arglen, argidx;
@ -107,18 +109,18 @@ PyBytes_Format(PyObject *format, PyObject *args)
int args_owned = 0; int args_owned = 0;
PyObject *result, *orig_args; PyObject *result, *orig_args;
PyObject *dict = NULL; PyObject *dict = NULL;
if (format == NULL || !PyBytes_Check(format) || args == NULL) { if (format == NULL || !Bytes_Check(format) || args == NULL) {
PyErr_BadInternalCall(); PyErr_BadInternalCall();
return NULL; return NULL;
} }
orig_args = args; orig_args = args;
fmt = PyBytes_AS_STRING(format); fmt = Bytes_AS_STRING(format);
fmtcnt = PyBytes_GET_SIZE(format); fmtcnt = Bytes_GET_SIZE(format);
reslen = rescnt = fmtcnt + 100; reslen = rescnt = fmtcnt + 100;
result = PyBytes_FromStringAndSize((char *)NULL, reslen); result = Bytes_FromStringAndSize((char *)NULL, reslen);
if (result == NULL) if (result == NULL)
return NULL; return NULL;
res = PyBytes_AsString(result); res = Bytes_AsString(result);
if (PyTuple_Check(args)) { if (PyTuple_Check(args)) {
arglen = PyTuple_GET_SIZE(args); arglen = PyTuple_GET_SIZE(args);
argidx = 0; argidx = 0;
@ -128,16 +130,16 @@ PyBytes_Format(PyObject *format, PyObject *args)
argidx = -2; argidx = -2;
} }
if (Py_TYPE(args)->tp_as_mapping && !PyTuple_Check(args) && if (Py_TYPE(args)->tp_as_mapping && !PyTuple_Check(args) &&
!PyObject_TypeCheck(args, &PyBytes_Type)) !PyObject_TypeCheck(args, &Bytes_Type))
dict = args; dict = args;
while (--fmtcnt >= 0) { while (--fmtcnt >= 0) {
if (*fmt != '%') { if (*fmt != '%') {
if (--rescnt < 0) { if (--rescnt < 0) {
rescnt = fmtcnt + 100; rescnt = fmtcnt + 100;
reslen += rescnt; reslen += rescnt;
if (_PyBytes_Resize(&result, reslen)) if (_Bytes_Resize(&result, reslen))
return NULL; return NULL;
res = PyBytes_AS_STRING(result) res = Bytes_AS_STRING(result)
+ reslen - rescnt; + reslen - rescnt;
--rescnt; --rescnt;
} }
@ -180,7 +182,7 @@ PyBytes_Format(PyObject *format, PyObject *args)
"incomplete format key"); "incomplete format key");
goto error; goto error;
} }
key = PyUnicode_FromStringAndSize(keystart, keylen); key = Text_FromUTF8AndSize(keystart, keylen);
if (key == NULL) if (key == NULL)
goto error; goto error;
if (args_owned) { if (args_owned) {
@ -217,7 +219,7 @@ PyBytes_Format(PyObject *format, PyObject *args)
break; break;
case 's': case 's':
/* only bytes! */ /* only bytes! */
if (!PyBytes_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",
Py_TYPE(v)->tp_name); Py_TYPE(v)->tp_name);
@ -225,8 +227,8 @@ PyBytes_Format(PyObject *format, PyObject *args)
} }
temp = v; temp = v;
Py_INCREF(v); Py_INCREF(v);
pbuf = PyBytes_AS_STRING(temp); pbuf = Bytes_AS_STRING(temp);
len = PyBytes_GET_SIZE(temp); len = Bytes_GET_SIZE(temp);
break; break;
default: default:
PyErr_Format(PyExc_ValueError, PyErr_Format(PyExc_ValueError,
@ -234,7 +236,7 @@ PyBytes_Format(PyObject *format, PyObject *args)
"at index %zd", "at index %zd",
c, c, c, c,
(Py_ssize_t)(fmt - 1 - (Py_ssize_t)(fmt - 1 -
PyBytes_AsString(format))); Bytes_AsString(format)));
goto error; goto error;
} }
if (width < len) if (width < len)
@ -248,11 +250,11 @@ PyBytes_Format(PyObject *format, PyObject *args)
Py_XDECREF(temp); Py_XDECREF(temp);
return PyErr_NoMemory(); return PyErr_NoMemory();
} }
if (_PyBytes_Resize(&result, reslen)) { if (_Bytes_Resize(&result, reslen)) {
Py_XDECREF(temp); Py_XDECREF(temp);
return NULL; return NULL;
} }
res = PyBytes_AS_STRING(result) res = Bytes_AS_STRING(result)
+ reslen - rescnt; + reslen - rescnt;
} }
Py_MEMCPY(res, pbuf, len); Py_MEMCPY(res, pbuf, len);
@ -279,7 +281,7 @@ PyBytes_Format(PyObject *format, PyObject *args)
if (args_owned) { if (args_owned) {
Py_DECREF(args); Py_DECREF(args);
} }
if (_PyBytes_Resize(&result, reslen - rescnt)) if (_Bytes_Resize(&result, reslen - rescnt))
return NULL; return NULL;
return result; return result;

View File

@ -103,8 +103,7 @@
#endif /* PY_MAJOR_VERSION > 2 */ #endif /* PY_MAJOR_VERSION > 2 */
#if PY_MAJOR_VERSION < 3 #if PY_MAJOR_VERSION < 3
/* XXX BytesType -> Bytes_Type */ #define Bytes_Type PyString_Type
#define BytesType PyString_Type
#define Bytes_Check PyString_Check #define Bytes_Check PyString_Check
#define Bytes_CheckExact PyString_CheckExact #define Bytes_CheckExact PyString_CheckExact
#define Bytes_AS_STRING PyString_AS_STRING #define Bytes_AS_STRING PyString_AS_STRING
@ -115,11 +114,11 @@
#define Bytes_FromString PyString_FromString #define Bytes_FromString PyString_FromString
#define Bytes_FromStringAndSize PyString_FromStringAndSize #define Bytes_FromStringAndSize PyString_FromStringAndSize
#define Bytes_FromFormat PyString_FromFormat #define Bytes_FromFormat PyString_FromFormat
#define Bytes_Format PyString_Format #define _Bytes_Resize _PyString_Resize
#else #else
#define BytesType PyBytes_Type #define Bytes_Type PyBytes_Type
#define Bytes_Check PyBytes_Check #define Bytes_Check PyBytes_Check
#define Bytes_CheckExact PyBytes_CheckExact #define Bytes_CheckExact PyBytes_CheckExact
#define Bytes_AS_STRING PyBytes_AS_STRING #define Bytes_AS_STRING PyBytes_AS_STRING
@ -130,12 +129,12 @@
#define Bytes_FromString PyBytes_FromString #define Bytes_FromString PyBytes_FromString
#define Bytes_FromStringAndSize PyBytes_FromStringAndSize #define Bytes_FromStringAndSize PyBytes_FromStringAndSize
#define Bytes_FromFormat PyBytes_FromFormat #define Bytes_FromFormat PyBytes_FromFormat
#define Bytes_Format PyBytes_Format #define _Bytes_Resize _PyBytes_Resize
HIDDEN PyObject *PyBytes_Format(PyObject *format, PyObject *args);
#endif #endif
HIDDEN PyObject *Bytes_Format(PyObject *format, PyObject *args);
/* Mangle the module name into the name of the module init function */ /* Mangle the module name into the name of the module init function */
#if PY_MAJOR_VERSION > 2 #if PY_MAJOR_VERSION > 2
#define INIT_MODULE(m) PyInit_ ## m #define INIT_MODULE(m) PyInit_ ## m

View File

@ -362,7 +362,7 @@ ext = [] ; data_files = []
sources = [ sources = [
'psycopgmodule.c', 'psycopgmodule.c',
'green.c', 'pqpath.c', 'utils.c', 'green.c', 'pqpath.c', 'utils.c', 'bytes_format.c',
'connection_int.c', 'connection_type.c', 'connection_int.c', 'connection_type.c',
'cursor_int.c', 'cursor_type.c', 'cursor_int.c', 'cursor_type.c',
@ -376,9 +376,6 @@ sources = [
'typecast.c', 'typecast.c',
] ]
if sys.version_info[0] >= 3:
sources.append('bytes_format.c')
depends = [ depends = [
# headers # headers
'config.h', 'pgtypes.h', 'psycopg.h', 'python.h', 'config.h', 'pgtypes.h', 'psycopg.h', 'python.h',