Thursday, July 09, 2009

python3 C API - simple slicing (sq_slice) gone.

Python3.x silently removed simple slicing support from the C API.

The problem is, python3 doesn't give you a warning it won't be used... it compiles fine... just your slicing tests will fail.

Since it's not documented anywhere, I will briefly mention a solution. Thanks to Campbell Barton for the idea.


You can reuse your old sq_slice function and create a new function in a PyMappingMethods. You can also reuse your sq_length in the MappingMethods directly with no changes.

http://docs.python.org/dev/py3k/c-api/typeobj.html#mapping-object-structures

mp_subscript is it's name.

Here is an example function from pygame.Color where it reuses _color_slice from the old simple slice function.
static PyObject * _color_subscript(PyColor* self, PyObject* item) {


#if PY_VERSION_HEX < 0x02050000
if (PyInt_Check(item)) {
Py_ssize_t i;
i = 0;
#else
if (PyIndex_Check(item)) {
Py_ssize_t i;
i = PyNumber_AsSsize_t(item, PyExc_IndexError);
#endif

if (i == -1 && PyErr_Occurred())
return NULL;
/*
if (i < 0)
i += PyList_GET_SIZE(self);
*/
return _color_item(self, i);
}
if (PySlice_Check(item)) {
int len= 4;
Py_ssize_t start, stop, step, slicelength;

if (PySlice_GetIndicesEx((PySliceObject*)item,
len, &start, &stop,
&step, &slicelength) < 0)
return NULL;

if (slicelength <= 0) {
return PyTuple_New(0);
}
else if (step == 1) {
/*NOTE: reuse your sq_slice method here. */
return _color_slice(self, start, stop);
}
else {
PyErr_SetString(PyExc_TypeError,
"slice steps not supported");
return NULL;
}
}
else {
PyErr_Format(PyExc_TypeError,
"Color indices must be integers, not %.200s",
item->ob_type->tp_name);
return NULL;
}
}


pygame 1.9.0 has support for python2.4 through to python3.1 now. It still mostly works with 2.2 and 2.3 too, but we stopped caring about those versions with this release. So it seems possible to make complex packages which contain both C extensions, and python parts that support many different versions of python. Not everything is ported to python3.x yet, hopefully that will come in a future pygame release.

More python3.x c porting tips are being collected in the wiki at http://wiki.python.org/moin/cporting. Searching on google is becoming more useful as people discover the C API differences themselves. If you've got any other C API porting tips, or links to peoples experiences please leave them on the wiki too! :)

No comments: