}
}
- return Py_BuildValue("O(O)(Oi)", Py_TYPE(lz),
+static PyObject *
+cycle_reduce(cycleobject *lz)
+{
+ /* Create a new cycle with the iterator tuple, then set
+ * the saved state on it.
+ */
++ return Py_BuildValue("O(O)(Oi)", Py_TYPE(lz),
+ lz->it, lz->saved, lz->firstpass);
+ }
+
+static PyObject *
+cycle_setstate(cycleobject *lz, PyObject *state)
+{
+ PyObject *saved=NULL;
+ int firstpass;
+ if (!PyArg_ParseTuple(state, "Oi", &saved, &firstpass))
+ return NULL;
+ Py_CLEAR(lz->saved);
+ lz->saved = saved;
+ Py_XINCREF(lz->saved);
+ lz->firstpass = firstpass != 0;
+ Py_RETURN_NONE;
+}
+
+static PyMethodDef cycle_methods[] = {
+ {"__reduce__", (PyCFunction)cycle_reduce, METH_NOARGS,
+ reduce_doc},
+ {"__setstate__", (PyCFunction)cycle_setstate, METH_O,
+ setstate_doc},
+ {NULL, NULL} /* sentinel */
+};
+
PyDoc_STRVAR(cycle_doc,
"cycle(iterable) --> cycle object\n\
\n\
return NULL;
}
-
+static PyObject *
+permutations_reduce(permutationsobject *po)
+{
+ if (po->result == NULL) {
+ return Py_BuildValue("O(On)", Py_TYPE(po), po->pool, po->r);
+ } else if (po->stopped) {
+ return Py_BuildValue("O(()n)", Py_TYPE(po), po->r);
+ } else {
+ PyObject *indices=NULL, *cycles=NULL;
+ Py_ssize_t n, i;
+
+ /* we must pickle the indices and cycles and use them for setstate */
+ n = PyTuple_GET_SIZE(po->pool);
+ indices = PyTuple_New(n);
+ if (indices == NULL)
+ goto err;
+ for (i=0; i<n; i++){
+ PyObject* index = PyLong_FromSsize_t(po->indices[i]);
+ if (!index)
+ goto err;
+ PyTuple_SET_ITEM(indices, i, index);
+ }
-
++
+ cycles = PyTuple_New(po->r);
+ if (cycles == NULL)
+ goto err;
+ for (i=0; i<po->r; i++)
+ {
+ PyObject* index = PyLong_FromSsize_t(po->cycles[i]);
+ if (!index)
+ goto err;
+ PyTuple_SET_ITEM(cycles, i, index);
+ }
+ return Py_BuildValue("O(On)(NN)", Py_TYPE(po),
+ po->pool, po->r,
+ indices, cycles);
+ err:
+ Py_XDECREF(indices);
+ Py_XDECREF(cycles);
+ return NULL;
+ }
+}
+
+static PyObject *
+permutations_setstate(permutationsobject *po, PyObject *state)
+{
+ PyObject *indices, *cycles, *result;
+ Py_ssize_t n, i;
++
+ if (!PyArg_ParseTuple(state, "O!O!",
+ &PyTuple_Type, &indices,
+ &PyTuple_Type, &cycles))
+ return NULL;
+
+ n = PyTuple_GET_SIZE(po->pool);
+ if (PyTuple_GET_SIZE(indices) != n ||
+ PyTuple_GET_SIZE(cycles) != po->r)
+ {
+ PyErr_SetString(PyExc_ValueError, "invalid arguments");
+ return NULL;
+ }
+
+ for (i=0; i<n; i++)
+ {
+ PyObject* indexObject = PyTuple_GET_ITEM(indices, i);
+ Py_ssize_t index = PyLong_AsSsize_t(indexObject);
+ if (index < 0 && PyErr_Occurred())
+ return NULL; /* not an integer */
+ /* clamp the index */
+ if (index < 0)
+ index = 0;
+ else if (index > n-1)
+ index = n-1;
+ po->indices[i] = index;
+ }
+
+ for (i=0; i<po->r; i++)
+ {
+ PyObject* indexObject = PyTuple_GET_ITEM(cycles, i);
+ Py_ssize_t index = PyLong_AsSsize_t(indexObject);
+ if (index < 0 && PyErr_Occurred())
+ return NULL; /* not an integer */
+ if (index < 1)
+ index = 1;
+ else if (index > n-i)
+ index = n-i;
+ po->cycles[i] = index;
+ }
+ result = PyTuple_New(po->r);
+ if (result == NULL)
+ return NULL;
+ for (i=0; i<po->r; i++) {
+ PyObject *element = PyTuple_GET_ITEM(po->pool, po->indices[i]);
+ Py_INCREF(element);
+ PyTuple_SET_ITEM(result, i, element);
+ }
+ Py_CLEAR(po->result);
+ po->result = result;
+ Py_RETURN_NONE;
+}
+
+static PyMethodDef permuations_methods[] = {
+ {"__reduce__", (PyCFunction)permutations_reduce, METH_NOARGS,
+ reduce_doc},
+ {"__setstate__", (PyCFunction)permutations_setstate, METH_O,
+ setstate_doc},
+ {NULL, NULL} /* sentinel */
+};
+
PyDoc_STRVAR(permutations_doc,
"permutations(iterable[, r]) --> permutations object\n\
\n\
return lz->total;
}
- if (lz->binop == NULL)
- newtotal = PyNumber_Add(lz->total, val);
++ if (lz->binop == NULL)
+ newtotal = PyNumber_Add(lz->total, val);
+ else
+ newtotal = PyObject_CallFunctionObjArgs(lz->binop, lz->total, val, NULL);
Py_DECREF(val);
if (newtotal == NULL)
return NULL;
return result;
}
-
+static PyObject *
+zip_longest_reduce(ziplongestobject *lz)
+{
++
+ /* Create a new tuple with empty sequences where appropriate to pickle.
+ * Then use setstate to set the fillvalue
+ */
+ int i;
+ PyObject *args = PyTuple_New(PyTuple_GET_SIZE(lz->ittuple));
+ if (args == NULL)
+ return NULL;
+ for (i=0; i<PyTuple_GET_SIZE(lz->ittuple); i++) {
+ PyObject *elem = PyTuple_GET_ITEM(lz->ittuple, i);
+ if (elem == NULL) {
+ elem = PyTuple_New(0);
+ if (elem == NULL) {
+ Py_DECREF(args);
+ return NULL;
+ }
+ } else
+ Py_INCREF(elem);
+ PyTuple_SET_ITEM(args, i, elem);
+ }
+ return Py_BuildValue("ONO", Py_TYPE(lz), args, lz->fillvalue);
+}
+
+static PyObject *
+zip_longest_setstate(ziplongestobject *lz, PyObject *state)
+{
+ Py_CLEAR(lz->fillvalue);
+ lz->fillvalue = state;
+ Py_INCREF(lz->fillvalue);
+ Py_RETURN_NONE;
+}
+
+static PyMethodDef zip_longest_methods[] = {
+ {"__reduce__", (PyCFunction)zip_longest_reduce, METH_NOARGS,
+ reduce_doc},
+ {"__setstate__", (PyCFunction)zip_longest_setstate, METH_O,
+ setstate_doc},
+ {NULL, NULL} /* sentinel */
+};
+
PyDoc_STRVAR(zip_longest_doc,
"zip_longest(iter1 [,iter2 [...]], [fillvalue=None]) --> zip_longest object\n\
\n\