Reputation: 93
I'm trying to translate a, b, c, d = iterable
to Python's C/API.
I'm looking for a function similar to PyArg_ParseTuple
, just for iterables.
In other words, something in the area of PyIter_Parse
or PyObject_ParseIterable
, if such functions would have existed.
Any tips how to implement it?
Upvotes: 1
Views: 331
Reputation: 1124238
No, there is no helper function that can do this for you.
You'd have to use PyIter_Next()
up to max
times to retrieve values, raise an exception when you can't get at least min
values, and then just build a tuple from that.
Something like (untested, largely pilfered from PySequence_Tuple()
):
int
PyIter_LimitedTuple(PyObject *v, Py_ssize_t min, Py_ssize_t max)
{
PyObject *it; /* iter(v) */
PyObject *result = NULL;
Py_ssize_t j;
it = PyObject_GetIter(v);
if (it == NULL)
return NULL;
/* allocate space. */
result = PyTuple_New(max);
if (result == NULL)
goto Fail;
/* Fill the tuple. */
for (j = 0; ; ++j) {
PyObject *item = PyIter_Next(it);
if (item == NULL) {
if (PyErr_Occurred())
goto Fail;
break;
}
if (j > max) {
PyErr_Format(PyExc_ValueError,
"too many values to unpack");
goto Fail;
}
PyTuple_SET_ITEM(result, j, item);
}
if (j < min) {
PyErr_Format(PyExc_ValueError,
"need more than %d value to unpack",
j);
goto Fail;
}
/* Cut tuple back if fewer than max items were available. */
if (j < max &&
_PyTuple_Resize(&result, j) != 0)
goto Fail;
Py_DECREF(it);
return result;
Fail:
Py_XDECREF(result);
Py_DECREF(it);
return NULL;
}
then pass the resulting tuple to PyArg_UnpackTuple()
.
Upvotes: 2