diff -r 657caf5d3eb1 Modules/_elementtree.c --- a/Modules/_elementtree.c Mon Dec 03 16:13:48 2012 +0200 +++ b/Modules/_elementtree.c Mon Dec 03 16:33:57 2012 +0000 @@ -814,6 +814,84 @@ return PyLong_FromSsize_t(result); } +static PyObject * +element_reduce(ElementObject *self) +{ + PyObject *children; + + if (self->extra && self->extra->length) { + /* Build a tuple of children. */ + int i; + children = PyTuple_New(self->extra->length); + for (i = 0; i < self->extra->length; i++) { + PyObject *child = self->extra->children[i]; + Py_INCREF(child); + PyTuple_SET_ITEM(children, i, child); + } + } + else { + /* No children. */ + Py_INCREF(Py_None); + children = Py_None; + } + + if (self->extra && self->extra->attrib && self->extra->attrib != Py_None) { + return Py_BuildValue("O(OO)(OOO)", Py_TYPE(self), self->tag, + self->extra->attrib, + self->text, self->tail, children); + } + else { + return Py_BuildValue("O(O)(OOO)", Py_TYPE(self), self->tag, + self->text, self->tail, children); + } +} +PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); + +static PyObject * +element_setstate(ElementObject *self, PyObject *state) +{ + PyObject *text, *tail, *children; + if (!PyArg_ParseTuple(state, "OOO", &text, &tail, &children)) + return NULL; + + Py_CLEAR(self->text); + self->text = text; + Py_INCREF(self->text); + + Py_CLEAR(self->tail); + self->tail = tail; + Py_INCREF(self->tail); + + if (children == Py_None) { + /* No children. */ + } + else if (!PyTuple_Check(children)) { + /* Internal error? */ + PyErr_SetString(PyExc_SystemError, + "Expected _elementtree.__setstate__() " + "to be passed a tuple"); + return NULL; + } + else { + /* Have children. */ + Py_ssize_t n = PyTuple_Size(children); + int i; + + /* ### TODO: verify this block doesn't interfere with attrib */ + /* attrib, if any, will have been set by now. */ + assert(! self->extra || ! self->extra->length); + if (element_resize(self, n) < 0) + return NULL; + + for (i = 0; i < n; i++) { + if (element_add_subelement(self, PyTuple_GET_ITEM(children, i)) < 0) + return NULL; + } + } + + Py_RETURN_NONE; +} + LOCAL(int) checkpath(PyObject* tag) { @@ -1582,6 +1660,8 @@ {"__copy__", (PyCFunction) element_copy, METH_VARARGS}, {"__deepcopy__", (PyCFunction) element_deepcopy, METH_VARARGS}, {"__sizeof__", element_sizeof, METH_NOARGS}, + {"__reduce__", (PyCFunction)element_reduce, METH_NOARGS, reduce_doc}, + {"__setstate__", (PyCFunction)element_setstate, METH_O}, {NULL, NULL} }; @@ -1686,6 +1766,10 @@ static PyTypeObject Element_Type = { PyVarObject_HEAD_INIT(NULL, 0) +#if 1 + /* ### TODO: other type objects need the same treatment? */ + "_elementtree" "." +#endif "Element", sizeof(ElementObject), 0, /* methods */ (destructor)element_dealloc, /* tp_dealloc */