py3k: Use "y#" code in PyArg_ParseTuple where we expect byte data

This commit also renames some functions from "fromstring" and the like to
"frombytes". I'll probably need to come back later and update any
references to "string," here or in the docs.

I also noticed that encode allocates some data for certain codecs, but
never frees them. That would be a good bug to fix. I fixed the one where it
outright stole a pointer from Python.
This commit is contained in:
Brian Crowell 2012-10-14 11:38:06 -05:00 committed by Brian Crowell
parent 4459715b6e
commit 9631d42b60
6 changed files with 62 additions and 16 deletions

View File

@ -1366,7 +1366,7 @@ _putpalette(ImagingObject* self, PyObject* args)
char* rawmode; char* rawmode;
UINT8* palette; UINT8* palette;
int palettesize; int palettesize;
if (!PyArg_ParseTuple(args, "ss#", &rawmode, &palette, &palettesize)) if (!PyArg_ParseTuple(args, "s"PY_ARG_BYTES_LENGTH, &rawmode, &palette, &palettesize))
return NULL; return NULL;
if (strcmp(self->image->mode, "L") != 0 && strcmp(self->image->mode, "P")) { if (strcmp(self->image->mode, "L") != 0 && strcmp(self->image->mode, "P")) {
@ -1861,8 +1861,9 @@ _getprojection(ImagingObject* self, PyObject* args)
ImagingGetProjection(self->image, (unsigned char *)xprofile, (unsigned char *)yprofile); ImagingGetProjection(self->image, (unsigned char *)xprofile, (unsigned char *)yprofile);
result = Py_BuildValue("s#s#", xprofile, self->image->xsize, result = Py_BuildValue(PY_ARG_BYTES_LENGTH PY_ARG_BYTES_LENGTH,
yprofile, self->image->ysize); xprofile, self->image->xsize,
yprofile, self->image->ysize);
free(xprofile); free(xprofile);
free(yprofile); free(yprofile);
@ -2089,7 +2090,7 @@ _font_new(PyObject* self_, PyObject* args)
ImagingObject* imagep; ImagingObject* imagep;
unsigned char* glyphdata; unsigned char* glyphdata;
int glyphdata_length; int glyphdata_length;
if (!PyArg_ParseTuple(args, "O!s#", if (!PyArg_ParseTuple(args, "O!"PY_ARG_BYTES_LENGTH,
&Imaging_Type, &imagep, &Imaging_Type, &imagep,
&glyphdata, &glyphdata_length)) &glyphdata, &glyphdata_length))
return NULL; return NULL;
@ -2787,7 +2788,8 @@ _crc32(PyObject* self, PyObject* args)
hi = lo = 0; hi = lo = 0;
if (!PyArg_ParseTuple(args, "s#|(ii)", &buffer, &bytes, &hi, &lo)) if (!PyArg_ParseTuple(args, PY_ARG_BYTES_LENGTH"|(ii)",
&buffer, &bytes, &hi, &lo))
return NULL; return NULL;
crc = ((UINT32) (hi & 0xFFFF) << 16) + (lo & 0xFFFF); crc = ((UINT32) (hi & 0xFFFF) << 16) + (lo & 0xFFFF);

View File

@ -129,8 +129,13 @@ cms_profile_fromstring(PyObject* self, PyObject* args)
char* pProfile; char* pProfile;
int nProfile; int nProfile;
#if PY_VERSION_HEX >= 0x03000000
if (!PyArg_ParseTuple(args, "y#:profile_frombytes", &pProfile, &nProfile))
return NULL;
#else
if (!PyArg_ParseTuple(args, "s#:profile_fromstring", &pProfile, &nProfile)) if (!PyArg_ParseTuple(args, "s#:profile_fromstring", &pProfile, &nProfile))
return NULL; return NULL;
#endif
cmsErrorAction(LCMS_ERROR_IGNORE); cmsErrorAction(LCMS_ERROR_IGNORE);
@ -496,7 +501,11 @@ cms_get_display_profile_win32(PyObject* self, PyObject* args)
static PyMethodDef pyCMSdll_methods[] = { static PyMethodDef pyCMSdll_methods[] = {
{"profile_open", cms_profile_open, 1}, {"profile_open", cms_profile_open, 1},
#if PY_VERSION_HEX >= 0x03000000
{"profile_frombytes", cms_profile_fromstring, 1},
#else
{"profile_fromstring", cms_profile_fromstring, 1}, {"profile_fromstring", cms_profile_fromstring, 1},
#endif
/* profile and transform functions */ /* profile and transform functions */
{"buildTransform", buildTransform, 1}, {"buildTransform", buildTransform, 1},

View File

@ -37,6 +37,7 @@
#endif #endif
#include "Imaging.h" #include "Imaging.h"
#include "py3.h"
#include "Gif.h" #include "Gif.h"
#include "Lzw.h" #include "Lzw.h"
@ -111,7 +112,7 @@ _decode(ImagingDecoderObject* decoder, PyObject* args)
UINT8* buffer; UINT8* buffer;
int bufsize, status; int bufsize, status;
if (!PyArg_ParseTuple(args, "s#", &buffer, &bufsize)) if (!PyArg_ParseTuple(args, PY_ARG_BYTES_LENGTH, &buffer, &bufsize))
return NULL; return NULL;
status = decoder->decode(decoder->im, &decoder->state, buffer, bufsize); status = decoder->decode(decoder->im, &decoder->state, buffer, bufsize);

View File

@ -31,6 +31,7 @@
#endif #endif
#include "Imaging.h" #include "Imaging.h"
#include "py3.h"
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* Windows DIB support */ /* Windows DIB support */
@ -183,8 +184,14 @@ _fromstring(ImagingDisplayObject* display, PyObject* args)
{ {
char* ptr; char* ptr;
int bytes; int bytes;
#if PY_VERSION_HEX >= 0x03000000
if (!PyArg_ParseTuple(args, "y#:frombytes", &ptr, &bytes))
return NULL;
#else
if (!PyArg_ParseTuple(args, "s#:fromstring", &ptr, &bytes)) if (!PyArg_ParseTuple(args, "s#:fromstring", &ptr, &bytes))
return NULL; return NULL;
#endif
if (display->dib->ysize * display->dib->linesize != bytes) { if (display->dib->ysize * display->dib->linesize != bytes) {
PyErr_SetString(PyExc_ValueError, "wrong size"); PyErr_SetString(PyExc_ValueError, "wrong size");
@ -200,10 +207,15 @@ _fromstring(ImagingDisplayObject* display, PyObject* args)
static PyObject* static PyObject*
_tostring(ImagingDisplayObject* display, PyObject* args) _tostring(ImagingDisplayObject* display, PyObject* args)
{ {
#if PY_VERSION_HEX >= 0x03000000
if (!PyArg_ParseTuple(args, ":tobytes"))
return NULL;
#else
if (!PyArg_ParseTuple(args, ":tostring")) if (!PyArg_ParseTuple(args, ":tostring"))
return NULL; return NULL;
#endif
return PyString_FromStringAndSize( return PyBytes_FromStringAndSize(
display->dib->bits, display->dib->ysize * display->dib->linesize display->dib->bits, display->dib->ysize * display->dib->linesize
); );
} }
@ -215,8 +227,13 @@ static struct PyMethodDef methods[] = {
{"query_palette", (PyCFunction)_query_palette, 1}, {"query_palette", (PyCFunction)_query_palette, 1},
{"getdc", (PyCFunction)_getdc, 1}, {"getdc", (PyCFunction)_getdc, 1},
{"releasedc", (PyCFunction)_releasedc, 1}, {"releasedc", (PyCFunction)_releasedc, 1},
#if PY_VERSION_HEX >= 0x03000000
{"frombytes", (PyCFunction)_fromstring, 1},
{"tobytes", (PyCFunction)_tostring, 1},
#else
{"fromstring", (PyCFunction)_fromstring, 1}, {"fromstring", (PyCFunction)_fromstring, 1},
{"tostring", (PyCFunction)_tostring, 1}, {"tostring", (PyCFunction)_tostring, 1},
#endif
{NULL, NULL} /* sentinel */ {NULL, NULL} /* sentinel */
}; };
@ -771,7 +788,7 @@ PyImaging_DrawWmf(PyObject* self, PyObject* args)
int datasize; int datasize;
int width, height; int width, height;
int x0, y0, x1, y1; int x0, y0, x1, y1;
if (!PyArg_ParseTuple(args, "s#(ii)(iiii):_load", &data, &datasize, if (!PyArg_ParseTuple(args, PY_ARG_BYTES_LENGTH"(ii)(iiii):_load", &data, &datasize,
&width, &height, &x0, &x1, &y0, &y1)) &width, &height, &x0, &x1, &y0, &y1))
return NULL; return NULL;

View File

@ -30,6 +30,7 @@
#endif #endif
#include "Imaging.h" #include "Imaging.h"
#include "py3.h"
#include "Gif.h" #include "Gif.h"
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
@ -451,9 +452,21 @@ PyImaging_ZipEncoderNew(PyObject* self, PyObject* args)
int optimize = 0; int optimize = 0;
char* dictionary = NULL; char* dictionary = NULL;
int dictionary_size = 0; int dictionary_size = 0;
if (!PyArg_ParseTuple(args, "ss|is#", &mode, &rawmode, &optimize, if (!PyArg_ParseTuple(args, "ss|i"PY_ARG_BYTES_LENGTH, &mode, &rawmode,
&dictionary, &dictionary_size)) &optimize, &dictionary, &dictionary_size))
return NULL; return NULL;
/* Copy to avoid referencing Python's memory, but there's no mechanism to
free this memory later, so this function (and several others here)
leaks. */
if (dictionary && dictionary_size > 0) {
char* p = malloc(dictionary_size);
if (!p)
return PyErr_NoMemory();
memcpy(p, dictionary, dictionary_size);
dictionary = p;
} else
dictionary = NULL;
encoder = PyImaging_EncoderNew(sizeof(ZIPSTATE)); encoder = PyImaging_EncoderNew(sizeof(ZIPSTATE));
if (encoder == NULL) if (encoder == NULL)
@ -513,8 +526,9 @@ PyImaging_JpegEncoderNew(PyObject* self, PyObject* args)
int xdpi = 0, ydpi = 0; int xdpi = 0, ydpi = 0;
int subsampling = -1; /* -1=default, 0=none, 1=medium, 2=high */ int subsampling = -1; /* -1=default, 0=none, 1=medium, 2=high */
char* extra = NULL; int extra_size; char* extra = NULL; int extra_size;
if (!PyArg_ParseTuple(args, "ss|iiiiiiiis#", &mode, &rawmode, &quality, if (!PyArg_ParseTuple(args, "ss|iiiiiiii"PY_ARG_BYTES_LENGTH,
&progressive, &smooth, &optimize, &streamtype, &mode, &rawmode, &quality,
&progressive, &smooth, &optimize, &streamtype,
&xdpi, &ydpi, &subsampling, &extra, &extra_size)) &xdpi, &ydpi, &subsampling, &extra, &extra_size))
return NULL; return NULL;

5
py3.h
View File

@ -11,13 +11,16 @@
*/ */
#if PY_VERSION_HEX >= 0x03000000 #if PY_VERSION_HEX >= 0x03000000
#define PY_ARG_BYTES_LENGTH "y#"
/* Map PyInt -> PyLong */ /* Map PyInt -> PyLong */
#define PyInt_AsLong PyLong_AsLong #define PyInt_AsLong PyLong_AsLong
#define PyInt_Check PyLong_Check #define PyInt_Check PyLong_Check
#define PyInt_FromLong PyLong_FromLong #define PyInt_FromLong PyLong_FromLong
#define PyInt_AS_LONG PyLong_AS_LONG #define PyInt_AS_LONG PyLong_AS_LONG
#else #else /* PY_VERSION_HEX < 0x03000000 */
#define PY_ARG_BYTES_LENGTH "s#"
#if !defined(KEEP_PY_UNICODE) #if !defined(KEEP_PY_UNICODE)
/* Map PyUnicode -> PyString */ /* Map PyUnicode -> PyString */