[Python-checkins] cpython: Issue #20159. Converted the _elementtree module to Argument Clinic.

serhiy.storchaka python-checkins at python.org
Mon May 4 14:33:27 CEST 2015


https://hg.python.org/cpython/rev/fea94f9cb5a0
changeset:   95878:fea94f9cb5a0
user:        Serhiy Storchaka <storchaka at gmail.com>
date:        Mon May 04 15:32:48 2015 +0300
summary:
  Issue #20159. Converted the _elementtree module to Argument Clinic.

files:
  Modules/_elementtree.c |  2578 ++++++++-------
  Modules/_elementtree.c |  4337 +++------------------------
  2 files changed, 1978 insertions(+), 4937 deletions(-)


diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c
--- a/Modules/_elementtree.c
+++ b/Modules/_elementtree.c
@@ -370,6 +370,14 @@
     return attrib;
 }
 
+/*[clinic input]
+module _elementtree
+class _elementtree.Element "ElementObject *" "&Element_Type"
+class _elementtree.TreeBuilder "TreeBuilderObject *" "&TreeBuilder_Type"
+class _elementtree.XMLParser "XMLParserObject *" "&XMLParser_Type"
+[clinic start generated code]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=159aa50a54061c22]*/
+
 static int
 element_init(PyObject *self, PyObject *args, PyObject *kwds)
 {
@@ -658,25 +666,33 @@
 
 /* -------------------------------------------------------------------- */
 
-static PyObject*
-element_append(ElementObject* self, PyObject* args)
+/*[clinic input]
+_elementtree.Element.append
+
+    subelement: object(subclass_of='&Element_Type')
+    /
+
+[clinic start generated code]*/
+
+static PyObject *
+_elementtree_Element_append_impl(ElementObject *self, PyObject *subelement)
+/*[clinic end generated code: output=54a884b7cf2295f4 input=3ed648beb5bfa22a]*/
 {
-    PyObject* element;
-    if (!PyArg_ParseTuple(args, "O!:append", &Element_Type, &element))
-        return NULL;
-
-    if (element_add_subelement(self, element) < 0)
+    if (element_add_subelement(self, subelement) < 0)
         return NULL;
 
     Py_RETURN_NONE;
 }
 
-static PyObject*
-element_clearmethod(ElementObject* self, PyObject* args)
+/*[clinic input]
+_elementtree.Element.clear
+
+[clinic start generated code]*/
+
+static PyObject *
+_elementtree_Element_clear_impl(ElementObject *self)
+/*[clinic end generated code: output=8bcd7a51f94cfff6 input=3c719ff94bf45dd6]*/
 {
-    if (!PyArg_ParseTuple(args, ":clear"))
-        return NULL;
-
     dealloc_extra(self);
 
     Py_INCREF(Py_None);
@@ -690,15 +706,18 @@
     Py_RETURN_NONE;
 }
 
-static PyObject*
-element_copy(ElementObject* self, PyObject* args)
+/*[clinic input]
+_elementtree.Element.__copy__
+
+[clinic start generated code]*/
+
+static PyObject *
+_elementtree_Element___copy___impl(ElementObject *self)
+/*[clinic end generated code: output=2c701ebff7247781 input=ad87aaebe95675bf]*/
 {
     Py_ssize_t i;
     ElementObject* element;
 
-    if (!PyArg_ParseTuple(args, ":__copy__"))
-        return NULL;
-
     element = (ElementObject*) create_new_element(
         self->tag, (self->extra) ? self->extra->attrib : Py_None);
     if (!element)
@@ -729,8 +748,17 @@
     return (PyObject*) element;
 }
 
-static PyObject*
-element_deepcopy(ElementObject* self, PyObject* args)
+/*[clinic input]
+_elementtree.Element.__deepcopy__
+
+    memo: object
+    /
+
+[clinic start generated code]*/
+
+static PyObject *
+_elementtree_Element___deepcopy__(ElementObject *self, PyObject *memo)
+/*[clinic end generated code: output=d1f19851d17bf239 input=df24c2b602430b77]*/
 {
     Py_ssize_t i;
     ElementObject* element;
@@ -740,10 +768,6 @@
     PyObject* tail;
     PyObject* id;
 
-    PyObject* memo;
-    if (!PyArg_ParseTuple(args, "O:__deepcopy__", &memo))
-        return NULL;
-
     tag = deepcopy(self->tag, memo);
     if (!tag)
         return NULL;
@@ -814,17 +838,22 @@
     return NULL;
 }
 
-static PyObject*
-element_sizeof(PyObject* myself, PyObject* args)
+/*[clinic input]
+_elementtree.Element.__sizeof__ -> Py_ssize_t
+
+[clinic start generated code]*/
+
+static Py_ssize_t
+_elementtree_Element___sizeof___impl(ElementObject *self)
+/*[clinic end generated code: output=bf73867721008000 input=70f4b323d55a17c1]*/
 {
-    ElementObject *self = (ElementObject*)myself;
     Py_ssize_t result = sizeof(ElementObject);
     if (self->extra) {
         result += sizeof(ElementObjectExtra);
         if (self->extra->children != self->extra->_children)
             result += sizeof(PyObject*) * self->extra->allocated;
     }
-    return PyLong_FromSsize_t(result);
+    return result;
 }
 
 /* dict keys for getstate/setstate. */
@@ -840,8 +869,14 @@
  * any unnecessary structures there; and (b) it buys compatibility with 3.2
  * pickles.  See issue #16076.
  */
+/*[clinic input]
+_elementtree.Element.__getstate__
+
+[clinic start generated code]*/
+
 static PyObject *
-element_getstate(ElementObject *self)
+_elementtree_Element___getstate___impl(ElementObject *self)
+/*[clinic end generated code: output=37279aeeb6bb5b04 input=f0d16d7ec2f7adc1]*/
 {
     Py_ssize_t i, noattrib;
     PyObject *instancedict = NULL, *children;
@@ -956,6 +991,7 @@
 /* __setstate__ for Element instance from the Python implementation.
  * 'state' should be the instance dict.
  */
+
 static PyObject *
 element_setstate_from_Python(ElementObject *self, PyObject *state)
 {
@@ -981,8 +1017,17 @@
     return retval;
 }
 
+/*[clinic input]
+_elementtree.Element.__setstate__
+
+    state: object
+    /
+
+[clinic start generated code]*/
+
 static PyObject *
-element_setstate(ElementObject *self, PyObject *state)
+_elementtree_Element___setstate__(ElementObject *self, PyObject *state)
+/*[clinic end generated code: output=ea28bf3491b1f75e input=aaf80abea7c1e3b9]*/
 {
     if (!PyDict_CheckExact(state)) {
         PyErr_Format(PyExc_TypeError,
@@ -1036,21 +1081,26 @@
     return 1; /* unknown type; might be path expression */
 }
 
-static PyObject*
-element_extend(ElementObject* self, PyObject* args)
+/*[clinic input]
+_elementtree.Element.extend
+
+    elements: object
+    /
+
+[clinic start generated code]*/
+
+static PyObject *
+_elementtree_Element_extend(ElementObject *self, PyObject *elements)
+/*[clinic end generated code: output=f6e67fc2ff529191 input=807bc4f31c69f7c0]*/
 {
     PyObject* seq;
     Py_ssize_t i, seqlen = 0;
 
-    PyObject* seq_in;
-    if (!PyArg_ParseTuple(args, "O:extend", &seq_in))
-        return NULL;
-
-    seq = PySequence_Fast(seq_in, "");
+    seq = PySequence_Fast(elements, "");
     if (!seq) {
         PyErr_Format(
             PyExc_TypeError,
-            "expected sequence, not \"%.200s\"", Py_TYPE(seq_in)->tp_name
+            "expected sequence, not \"%.200s\"", Py_TYPE(elements)->tp_name
             );
         return NULL;
     }
@@ -1078,23 +1128,26 @@
     Py_RETURN_NONE;
 }
 
-static PyObject*
-element_find(ElementObject *self, PyObject *args, PyObject *kwds)
+/*[clinic input]
+_elementtree.Element.find
+
+    path: object
+    namespaces: object = None
+
+[clinic start generated code]*/
+
+static PyObject *
+_elementtree_Element_find_impl(ElementObject *self, PyObject *path,
+                               PyObject *namespaces)
+/*[clinic end generated code: output=41b43f0f0becafae input=359b6985f6489d2e]*/
 {
     Py_ssize_t i;
-    PyObject* tag;
-    PyObject* namespaces = Py_None;
-    static char *kwlist[] = {"path", "namespaces", 0};
     elementtreestate *st = ET_STATE_GLOBAL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:find", kwlist,
-                                     &tag, &namespaces))
-        return NULL;
-
-    if (checkpath(tag) || namespaces != Py_None) {
+    if (checkpath(path) || namespaces != Py_None) {
         _Py_IDENTIFIER(find);
         return _PyObject_CallMethodId(
-            st->elementpath_obj, &PyId_find, "OOO", self, tag, namespaces
+            st->elementpath_obj, &PyId_find, "OOO", self, path, namespaces
             );
     }
 
@@ -1104,7 +1157,7 @@
     for (i = 0; i < self->extra->length; i++) {
         PyObject* item = self->extra->children[i];
         if (Element_CheckExact(item) &&
-            PyObject_RichCompareBool(((ElementObject*)item)->tag, tag, Py_EQ) == 1) {
+            PyObject_RichCompareBool(((ElementObject*)item)->tag, path, Py_EQ) == 1) {
             Py_INCREF(item);
             return item;
         }
@@ -1113,24 +1166,28 @@
     Py_RETURN_NONE;
 }
 
-static PyObject*
-element_findtext(ElementObject *self, PyObject *args, PyObject *kwds)
+/*[clinic input]
+_elementtree.Element.findtext
+
+    path: object
+    default: object = None
+    namespaces: object = None
+
+[clinic start generated code]*/
+
+static PyObject *
+_elementtree_Element_findtext_impl(ElementObject *self, PyObject *path,
+                                   PyObject *default_value,
+                                   PyObject *namespaces)
+/*[clinic end generated code: output=83b3ba4535d308d2 input=b53a85aa5aa2a916]*/
 {
     Py_ssize_t i;
-    PyObject* tag;
-    PyObject* default_value = Py_None;
-    PyObject* namespaces = Py_None;
     _Py_IDENTIFIER(findtext);
-    static char *kwlist[] = {"path", "default", "namespaces", 0};
     elementtreestate *st = ET_STATE_GLOBAL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OO:findtext", kwlist,
-                                     &tag, &default_value, &namespaces))
-        return NULL;
-
-    if (checkpath(tag) || namespaces != Py_None)
+    if (checkpath(path) || namespaces != Py_None)
         return _PyObject_CallMethodId(
-            st->elementpath_obj, &PyId_findtext, "OOOO", self, tag, default_value, namespaces
+            st->elementpath_obj, &PyId_findtext, "OOOO", self, path, default_value, namespaces
             );
 
     if (!self->extra) {
@@ -1141,7 +1198,7 @@
     for (i = 0; i < self->extra->length; i++) {
         ElementObject* item = (ElementObject*) self->extra->children[i];
         if (Element_CheckExact(item) &&
-            (PyObject_RichCompareBool(item->tag, tag, Py_EQ) == 1)) {
+            (PyObject_RichCompareBool(item->tag, path, Py_EQ) == 1)) {
             PyObject* text = element_get_text(item);
             if (text == Py_None)
                 return PyUnicode_New(0, 0);
@@ -1154,20 +1211,24 @@
     return default_value;
 }
 
-static PyObject*
-element_findall(ElementObject *self, PyObject *args, PyObject *kwds)
+/*[clinic input]
+_elementtree.Element.findall
+
+    path: object
+    namespaces: object = None
+
+[clinic start generated code]*/
+
+static PyObject *
+_elementtree_Element_findall_impl(ElementObject *self, PyObject *path,
+                                  PyObject *namespaces)
+/*[clinic end generated code: output=1a0bd9f5541b711d input=4d9e6505a638550c]*/
 {
     Py_ssize_t i;
     PyObject* out;
-    PyObject* tag;
-    PyObject* namespaces = Py_None;
-    static char *kwlist[] = {"path", "namespaces", 0};
+    PyObject* tag = path;
     elementtreestate *st = ET_STATE_GLOBAL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:findall", kwlist,
-                                     &tag, &namespaces))
-        return NULL;
-
     if (checkpath(tag) || namespaces != Py_None) {
         _Py_IDENTIFIER(findall);
         return _PyObject_CallMethodId(
@@ -1196,36 +1257,41 @@
     return out;
 }
 
-static PyObject*
-element_iterfind(ElementObject *self, PyObject *args, PyObject *kwds)
+/*[clinic input]
+_elementtree.Element.iterfind
+
+    path: object
+    namespaces: object = None
+
+[clinic start generated code]*/
+
+static PyObject *
+_elementtree_Element_iterfind_impl(ElementObject *self, PyObject *path,
+                                   PyObject *namespaces)
+/*[clinic end generated code: output=ecdd56d63b19d40f input=abb974e350fb65c7]*/
 {
-    PyObject* tag;
-    PyObject* namespaces = Py_None;
+    PyObject* tag = path;
     _Py_IDENTIFIER(iterfind);
-    static char *kwlist[] = {"path", "namespaces", 0};
     elementtreestate *st = ET_STATE_GLOBAL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:iterfind", kwlist,
-                                     &tag, &namespaces)) {
-        return NULL;
-    }
-
     return _PyObject_CallMethodId(
         st->elementpath_obj, &PyId_iterfind, "OOO", self, tag, namespaces);
 }
 
-static PyObject*
-element_get(ElementObject* self, PyObject* args, PyObject* kwds)
+/*[clinic input]
+_elementtree.Element.get
+
+    key: object
+    default: object = None
+
+[clinic start generated code]*/
+
+static PyObject *
+_elementtree_Element_get_impl(ElementObject *self, PyObject *key,
+                              PyObject *default_value)
+/*[clinic end generated code: output=523c614142595d75 input=ee153bbf8cdb246e]*/
 {
     PyObject* value;
-    static char* kwlist[] = {"key", "default", 0};
-
-    PyObject* key;
-    PyObject* default_value = Py_None;
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:get", kwlist, &key,
-                                     &default_value))
-        return NULL;
 
     if (!self->extra || self->extra->attrib == Py_None)
         value = default_value;
@@ -1239,17 +1305,20 @@
     return value;
 }
 
-static PyObject*
-element_getchildren(ElementObject* self, PyObject* args)
+/*[clinic input]
+_elementtree.Element.getchildren
+
+[clinic start generated code]*/
+
+static PyObject *
+_elementtree_Element_getchildren_impl(ElementObject *self)
+/*[clinic end generated code: output=e50ffe118637b14f input=0f754dfded150d5f]*/
 {
     Py_ssize_t i;
     PyObject* list;
 
     /* FIXME: report as deprecated? */
 
-    if (!PyArg_ParseTuple(args, ":getchildren"))
-        return NULL;
-
     if (!self->extra)
         return PyList_New(0);
 
@@ -1271,25 +1340,30 @@
 create_elementiter(ElementObject *self, PyObject *tag, int gettext);
 
 
+/*[clinic input]
+_elementtree.Element.iter
+
+    tag: object = None
+
+[clinic start generated code]*/
+
 static PyObject *
-element_iter(ElementObject *self, PyObject *args, PyObject *kwds)
+_elementtree_Element_iter_impl(ElementObject *self, PyObject *tag)
+/*[clinic end generated code: output=3f49f9a862941cc5 input=774d5b12e573aedd]*/
 {
-    PyObject* tag = Py_None;
-    static char* kwlist[] = {"tag", 0};
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:iter", kwlist, &tag))
-        return NULL;
-
     return create_elementiter(self, tag, 0);
 }
 
 
-static PyObject*
-element_itertext(ElementObject* self, PyObject* args)
+/*[clinic input]
+_elementtree.Element.itertext
+
+[clinic start generated code]*/
+
+static PyObject *
+_elementtree_Element_itertext_impl(ElementObject *self)
+/*[clinic end generated code: output=5fa34b2fbcb65df6 input=af8f0e42cb239c89]*/
 {
-    if (!PyArg_ParseTuple(args, ":itertext"))
-        return NULL;
-
     return create_elementiter(self, Py_None, 1);
 }
 
@@ -1311,14 +1385,21 @@
     return self->extra->children[index];
 }
 
-static PyObject*
-element_insert(ElementObject* self, PyObject* args)
+/*[clinic input]
+_elementtree.Element.insert
+
+    index: Py_ssize_t
+    subelement: object(subclass_of='&Element_Type')
+    /
+
+[clinic start generated code]*/
+
+static PyObject *
+_elementtree_Element_insert_impl(ElementObject *self, Py_ssize_t index,
+                                 PyObject *subelement)
+/*[clinic end generated code: output=990adfef4d424c0b input=cd6fbfcdab52d7a8]*/
 {
-    Py_ssize_t index, i;
-    PyObject* element;
-    if (!PyArg_ParseTuple(args, "nO!:insert", &index,
-                          &Element_Type, &element))
-        return NULL;
+    Py_ssize_t i;
 
     if (!self->extra) {
         if (create_extra(self, NULL) < 0)
@@ -1339,32 +1420,38 @@
     for (i = self->extra->length; i > index; i--)
         self->extra->children[i] = self->extra->children[i-1];
 
-    Py_INCREF(element);
-    self->extra->children[index] = element;
+    Py_INCREF(subelement);
+    self->extra->children[index] = subelement;
 
     self->extra->length++;
 
     Py_RETURN_NONE;
 }
 
-static PyObject*
-element_items(ElementObject* self, PyObject* args)
+/*[clinic input]
+_elementtree.Element.items
+
+[clinic start generated code]*/
+
+static PyObject *
+_elementtree_Element_items_impl(ElementObject *self)
+/*[clinic end generated code: output=6db2c778ce3f5a4d input=adbe09aaea474447]*/
 {
-    if (!PyArg_ParseTuple(args, ":items"))
-        return NULL;
-
     if (!self->extra || self->extra->attrib == Py_None)
         return PyList_New(0);
 
     return PyDict_Items(self->extra->attrib);
 }
 
-static PyObject*
-element_keys(ElementObject* self, PyObject* args)
+/*[clinic input]
+_elementtree.Element.keys
+
+[clinic start generated code]*/
+
+static PyObject *
+_elementtree_Element_keys_impl(ElementObject *self)
+/*[clinic end generated code: output=bc5bfabbf20eeb3c input=f02caf5b496b5b0b]*/
 {
-    if (!PyArg_ParseTuple(args, ":keys"))
-        return NULL;
-
     if (!self->extra || self->extra->attrib == Py_None)
         return PyList_New(0);
 
@@ -1380,16 +1467,22 @@
     return self->extra->length;
 }
 
-static PyObject*
-element_makeelement(PyObject* self, PyObject* args, PyObject* kw)
+/*[clinic input]
+_elementtree.Element.makeelement
+
+    tag: object
+    attrib: object
+    /
+
+[clinic start generated code]*/
+
+static PyObject *
+_elementtree_Element_makeelement_impl(ElementObject *self, PyObject *tag,
+                                      PyObject *attrib)
+/*[clinic end generated code: output=4109832d5bb789ef input=9480d1d2e3e68235]*/
 {
     PyObject* elem;
 
-    PyObject* tag;
-    PyObject* attrib;
-    if (!PyArg_ParseTuple(args, "OO:makeelement", &tag, &attrib))
-        return NULL;
-
     attrib = PyDict_Copy(attrib);
     if (!attrib)
         return NULL;
@@ -1401,15 +1494,20 @@
     return elem;
 }
 
-static PyObject*
-element_remove(ElementObject* self, PyObject* args)
+/*[clinic input]
+_elementtree.Element.remove
+
+    subelement: object(subclass_of='&Element_Type')
+    /
+
+[clinic start generated code]*/
+
+static PyObject *
+_elementtree_Element_remove_impl(ElementObject *self, PyObject *subelement)
+/*[clinic end generated code: output=38fe6c07d6d87d1f input=d52fc28ededc0bd8]*/
 {
     Py_ssize_t i;
 
-    PyObject* element;
-    if (!PyArg_ParseTuple(args, "O!:remove", &Element_Type, &element))
-        return NULL;
-
     if (!self->extra) {
         /* element has no children, so raise exception */
         PyErr_SetString(
@@ -1420,14 +1518,14 @@
     }
 
     for (i = 0; i < self->extra->length; i++) {
-        if (self->extra->children[i] == element)
+        if (self->extra->children[i] == subelement)
             break;
-        if (PyObject_RichCompareBool(self->extra->children[i], element, Py_EQ) == 1)
+        if (PyObject_RichCompareBool(self->extra->children[i], subelement, Py_EQ) == 1)
             break;
     }
 
     if (i == self->extra->length) {
-        /* element is not in children, so raise exception */
+        /* subelement is not in children, so raise exception */
         PyErr_SetString(
             PyExc_ValueError,
             "list.remove(x): x not in list"
@@ -1454,16 +1552,22 @@
         return PyUnicode_FromFormat("<Element at %p>", self);
 }
 
-static PyObject*
-element_set(ElementObject* self, PyObject* args)
+/*[clinic input]
+_elementtree.Element.set
+
+    key: object
+    value: object
+    /
+
+[clinic start generated code]*/
+
+static PyObject *
+_elementtree_Element_set_impl(ElementObject *self, PyObject *key,
+                              PyObject *value)
+/*[clinic end generated code: output=fb938806be3c5656 input=1efe90f7d82b3fe9]*/
 {
     PyObject* attrib;
 
-    PyObject* key;
-    PyObject* value;
-    if (!PyArg_ParseTuple(args, "OO:set", &key, &value))
-        return NULL;
-
     if (!self->extra) {
         if (create_extra(self, NULL) < 0)
             return NULL;
@@ -1744,43 +1848,6 @@
     }
 }
 
-static PyMethodDef element_methods[] = {
-
-    {"clear", (PyCFunction) element_clearmethod, METH_VARARGS},
-
-    {"get", (PyCFunction) element_get, METH_VARARGS | METH_KEYWORDS},
-    {"set", (PyCFunction) element_set, METH_VARARGS},
-
-    {"find", (PyCFunction) element_find, METH_VARARGS | METH_KEYWORDS},
-    {"findtext", (PyCFunction) element_findtext, METH_VARARGS | METH_KEYWORDS},
-    {"findall", (PyCFunction) element_findall, METH_VARARGS | METH_KEYWORDS},
-
-    {"append", (PyCFunction) element_append, METH_VARARGS},
-    {"extend", (PyCFunction) element_extend, METH_VARARGS},
-    {"insert", (PyCFunction) element_insert, METH_VARARGS},
-    {"remove", (PyCFunction) element_remove, METH_VARARGS},
-
-    {"iter", (PyCFunction) element_iter, METH_VARARGS | METH_KEYWORDS},
-    {"itertext", (PyCFunction) element_itertext, METH_VARARGS},
-    {"iterfind", (PyCFunction) element_iterfind, METH_VARARGS | METH_KEYWORDS},
-
-    {"getiterator", (PyCFunction) element_iter, METH_VARARGS | METH_KEYWORDS},
-    {"getchildren", (PyCFunction) element_getchildren, METH_VARARGS},
-
-    {"items", (PyCFunction) element_items, METH_VARARGS},
-    {"keys", (PyCFunction) element_keys, METH_VARARGS},
-
-    {"makeelement", (PyCFunction) element_makeelement, METH_VARARGS},
-
-    {"__copy__", (PyCFunction) element_copy, METH_VARARGS},
-    {"__deepcopy__", (PyCFunction) element_deepcopy, METH_VARARGS},
-    {"__sizeof__", element_sizeof, METH_NOARGS},
-    {"__getstate__", (PyCFunction)element_getstate, METH_NOARGS},
-    {"__setstate__", (PyCFunction)element_setstate, METH_O},
-
-    {NULL, NULL}
-};
-
 static PyObject*
 element_getattro(ElementObject* self, PyObject* nameobj)
 {
@@ -1877,54 +1944,6 @@
     0,
 };
 
-static PyMappingMethods element_as_mapping = {
-    (lenfunc) element_length,
-    (binaryfunc) element_subscr,
-    (objobjargproc) element_ass_subscr,
-};
-
-static PyTypeObject Element_Type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "xml.etree.ElementTree.Element", sizeof(ElementObject), 0,
-    /* methods */
-    (destructor)element_dealloc,                    /* tp_dealloc */
-    0,                                              /* tp_print */
-    0,                                              /* tp_getattr */
-    0,                                              /* tp_setattr */
-    0,                                              /* tp_reserved */
-    (reprfunc)element_repr,                         /* tp_repr */
-    0,                                              /* tp_as_number */
-    &element_as_sequence,                           /* tp_as_sequence */
-    &element_as_mapping,                            /* tp_as_mapping */
-    0,                                              /* tp_hash */
-    0,                                              /* tp_call */
-    0,                                              /* tp_str */
-    (getattrofunc)element_getattro,                 /* tp_getattro */
-    (setattrofunc)element_setattro,                 /* tp_setattro */
-    0,                                              /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
-                                                    /* tp_flags */
-    0,                                              /* tp_doc */
-    (traverseproc)element_gc_traverse,              /* tp_traverse */
-    (inquiry)element_gc_clear,                      /* tp_clear */
-    0,                                              /* tp_richcompare */
-    offsetof(ElementObject, weakreflist),           /* tp_weaklistoffset */
-    0,                                              /* tp_iter */
-    0,                                              /* tp_iternext */
-    element_methods,                                /* tp_methods */
-    0,                                              /* tp_members */
-    0,                                              /* tp_getset */
-    0,                                              /* tp_base */
-    0,                                              /* tp_dict */
-    0,                                              /* tp_descr_get */
-    0,                                              /* tp_descr_set */
-    0,                                              /* tp_dictoffset */
-    (initproc)element_init,                         /* tp_init */
-    PyType_GenericAlloc,                            /* tp_alloc */
-    element_new,                                    /* tp_new */
-    0,                                              /* tp_free */
-};
-
 /******************************* Element iterator ****************************/
 
 /* ElementIterObject represents the iteration state over an XML element in
@@ -2264,23 +2283,24 @@
     return (PyObject *)t;
 }
 
+/*[clinic input]
+_elementtree.TreeBuilder.__init__
+
+    element_factory: object = NULL
+
+[clinic start generated code]*/
+
 static int
-treebuilder_init(PyObject *self, PyObject *args, PyObject *kwds)
+_elementtree_TreeBuilder___init___impl(TreeBuilderObject *self,
+                                       PyObject *element_factory)
+/*[clinic end generated code: output=91cfa7558970ee96 input=1b424eeefc35249c]*/
 {
-    static char *kwlist[] = {"element_factory", 0};
-    PyObject *element_factory = NULL;
-    TreeBuilderObject *self_tb = (TreeBuilderObject *)self;
     PyObject *tmp;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:TreeBuilder", kwlist,
-                                     &element_factory)) {
-        return -1;
-    }
-
     if (element_factory) {
         Py_INCREF(element_factory);
-        tmp = self_tb->element_factory;
-        self_tb->element_factory = element_factory;
+        tmp = self->element_factory;
+        self->element_factory = element_factory;
         Py_XDECREF(tmp);
     }
 
@@ -2600,23 +2620,33 @@
 /* -------------------------------------------------------------------- */
 /* methods (in alphabetical order) */
 
-static PyObject*
-treebuilder_data(TreeBuilderObject* self, PyObject* args)
+/*[clinic input]
+_elementtree.TreeBuilder.data
+
+    data: object
+    /
+
+[clinic start generated code]*/
+
+static PyObject *
+_elementtree_TreeBuilder_data(TreeBuilderObject *self, PyObject *data)
+/*[clinic end generated code: output=69144c7100795bb2 input=a0540c532b284d29]*/
 {
-    PyObject* data;
-    if (!PyArg_ParseTuple(args, "O:data", &data))
-        return NULL;
-
     return treebuilder_handle_data(self, data);
 }
 
-static PyObject*
-treebuilder_end(TreeBuilderObject* self, PyObject* args)
+/*[clinic input]
+_elementtree.TreeBuilder.end
+
+    tag: object
+    /
+
+[clinic start generated code]*/
+
+static PyObject *
+_elementtree_TreeBuilder_end(TreeBuilderObject *self, PyObject *tag)
+/*[clinic end generated code: output=9a98727cc691cd9d input=22dc3674236f5745]*/
 {
-    PyObject* tag;
-    if (!PyArg_ParseTuple(args, "O:end", &tag))
-        return NULL;
-
     return treebuilder_handle_end(self, tag);
 }
 
@@ -2636,31 +2666,1089 @@
     return res;
 }
 
-static PyObject*
-treebuilder_close(TreeBuilderObject* self, PyObject* args)
+/*[clinic input]
+_elementtree.TreeBuilder.close
+
+[clinic start generated code]*/
+
+static PyObject *
+_elementtree_TreeBuilder_close_impl(TreeBuilderObject *self)
+/*[clinic end generated code: output=b441fee3202f61ee input=f7c9c65dc718de14]*/
 {
-    if (!PyArg_ParseTuple(args, ":close"))
-        return NULL;
-
     return treebuilder_done(self);
 }
 
-static PyObject*
-treebuilder_start(TreeBuilderObject* self, PyObject* args)
+/*[clinic input]
+_elementtree.TreeBuilder.start
+
+    tag: object
+    attrs: object = None
+    /
+
+[clinic start generated code]*/
+
+static PyObject *
+_elementtree_TreeBuilder_start_impl(TreeBuilderObject *self, PyObject *tag,
+                                    PyObject *attrs)
+/*[clinic end generated code: output=e7e9dc2861349411 input=95fc1758dd042c65]*/
+{
+    return treebuilder_handle_start(self, tag, attrs);
+}
+
+/* ==================================================================== */
+/* the expat interface */
+
+#include "expat.h"
+#include "pyexpat.h"
+
+/* The PyExpat_CAPI structure is an immutable dispatch table, so it can be
+ * cached globally without being in per-module state.
+ */
+static struct PyExpat_CAPI *expat_capi;
+#define EXPAT(func) (expat_capi->func)
+
+static XML_Memory_Handling_Suite ExpatMemoryHandler = {
+    PyObject_Malloc, PyObject_Realloc, PyObject_Free};
+
+typedef struct {
+    PyObject_HEAD
+
+    XML_Parser parser;
+
+    PyObject *target;
+    PyObject *entity;
+
+    PyObject *names;
+
+    PyObject *handle_start;
+    PyObject *handle_data;
+    PyObject *handle_end;
+
+    PyObject *handle_comment;
+    PyObject *handle_pi;
+    PyObject *handle_doctype;
+
+    PyObject *handle_close;
+
+} XMLParserObject;
+
+#define XMLParser_CheckExact(op) (Py_TYPE(op) == &XMLParser_Type)
+
+/* helpers */
+
+LOCAL(PyObject*)
+makeuniversal(XMLParserObject* self, const char* string)
+{
+    /* convert a UTF-8 tag/attribute name from the expat parser
+       to a universal name string */
+
+    Py_ssize_t size = (Py_ssize_t) strlen(string);
+    PyObject* key;
+    PyObject* value;
+
+    /* look the 'raw' name up in the names dictionary */
+    key = PyBytes_FromStringAndSize(string, size);
+    if (!key)
+        return NULL;
+
+    value = PyDict_GetItem(self->names, key);
+
+    if (value) {
+        Py_INCREF(value);
+    } else {
+        /* new name.  convert to universal name, and decode as
+           necessary */
+
+        PyObject* tag;
+        char* p;
+        Py_ssize_t i;
+
+        /* look for namespace separator */
+        for (i = 0; i < size; i++)
+            if (string[i] == '}')
+                break;
+        if (i != size) {
+            /* convert to universal name */
+            tag = PyBytes_FromStringAndSize(NULL, size+1);
+            if (tag == NULL) {
+                Py_DECREF(key);
+                return NULL;
+            }
+            p = PyBytes_AS_STRING(tag);
+            p[0] = '{';
+            memcpy(p+1, string, size);
+            size++;
+        } else {
+            /* plain name; use key as tag */
+            Py_INCREF(key);
+            tag = key;
+        }
+
+        /* decode universal name */
+        p = PyBytes_AS_STRING(tag);
+        value = PyUnicode_DecodeUTF8(p, size, "strict");
+        Py_DECREF(tag);
+        if (!value) {
+            Py_DECREF(key);
+            return NULL;
+        }
+
+        /* add to names dictionary */
+        if (PyDict_SetItem(self->names, key, value) < 0) {
+            Py_DECREF(key);
+            Py_DECREF(value);
+            return NULL;
+        }
+    }
+
+    Py_DECREF(key);
+    return value;
+}
+
+/* Set the ParseError exception with the given parameters.
+ * If message is not NULL, it's used as the error string. Otherwise, the
+ * message string is the default for the given error_code.
+*/
+static void
+expat_set_error(enum XML_Error error_code, Py_ssize_t line, Py_ssize_t column,
+                const char *message)
+{
+    PyObject *errmsg, *error, *position, *code;
+    elementtreestate *st = ET_STATE_GLOBAL;
+
+    errmsg = PyUnicode_FromFormat("%s: line %zd, column %zd",
+                message ? message : EXPAT(ErrorString)(error_code),
+                line, column);
+    if (errmsg == NULL)
+        return;
+
+    error = PyObject_CallFunction(st->parseerror_obj, "O", errmsg);
+    Py_DECREF(errmsg);
+    if (!error)
+        return;
+
+    /* Add code and position attributes */
+    code = PyLong_FromLong((long)error_code);
+    if (!code) {
+        Py_DECREF(error);
+        return;
+    }
+    if (PyObject_SetAttrString(error, "code", code) == -1) {
+        Py_DECREF(error);
+        Py_DECREF(code);
+        return;
+    }
+    Py_DECREF(code);
+
+    position = Py_BuildValue("(nn)", line, column);
+    if (!position) {
+        Py_DECREF(error);
+        return;
+    }
+    if (PyObject_SetAttrString(error, "position", position) == -1) {
+        Py_DECREF(error);
+        Py_DECREF(position);
+        return;
+    }
+    Py_DECREF(position);
+
+    PyErr_SetObject(st->parseerror_obj, error);
+    Py_DECREF(error);
+}
+
+/* -------------------------------------------------------------------- */
+/* handlers */
+
+static void
+expat_default_handler(XMLParserObject* self, const XML_Char* data_in,
+                      int data_len)
+{
+    PyObject* key;
+    PyObject* value;
+    PyObject* res;
+
+    if (data_len < 2 || data_in[0] != '&')
+        return;
+
+    if (PyErr_Occurred())
+        return;
+
+    key = PyUnicode_DecodeUTF8(data_in + 1, data_len - 2, "strict");
+    if (!key)
+        return;
+
+    value = PyDict_GetItem(self->entity, key);
+
+    if (value) {
+        if (TreeBuilder_CheckExact(self->target))
+            res = treebuilder_handle_data(
+                (TreeBuilderObject*) self->target, value
+                );
+        else if (self->handle_data)
+            res = PyObject_CallFunction(self->handle_data, "O", value);
+        else
+            res = NULL;
+        Py_XDECREF(res);
+    } else if (!PyErr_Occurred()) {
+        /* Report the first error, not the last */
+        char message[128] = "undefined entity ";
+        strncat(message, data_in, data_len < 100?data_len:100);
+        expat_set_error(
+            XML_ERROR_UNDEFINED_ENTITY,
+            EXPAT(GetErrorLineNumber)(self->parser),
+            EXPAT(GetErrorColumnNumber)(self->parser),
+            message
+            );
+    }
+
+    Py_DECREF(key);
+}
+
+static void
+expat_start_handler(XMLParserObject* self, const XML_Char* tag_in,
+                    const XML_Char **attrib_in)
+{
+    PyObject* res;
+    PyObject* tag;
+    PyObject* attrib;
+    int ok;
+
+    if (PyErr_Occurred())
+        return;
+
+    /* tag name */
+    tag = makeuniversal(self, tag_in);
+    if (!tag)
+        return; /* parser will look for errors */
+
+    /* attributes */
+    if (attrib_in[0]) {
+        attrib = PyDict_New();
+        if (!attrib)
+            return;
+        while (attrib_in[0] && attrib_in[1]) {
+            PyObject* key = makeuniversal(self, attrib_in[0]);
+            PyObject* value = PyUnicode_DecodeUTF8(attrib_in[1], strlen(attrib_in[1]), "strict");
+            if (!key || !value) {
+                Py_XDECREF(value);
+                Py_XDECREF(key);
+                Py_DECREF(attrib);
+                return;
+            }
+            ok = PyDict_SetItem(attrib, key, value);
+            Py_DECREF(value);
+            Py_DECREF(key);
+            if (ok < 0) {
+                Py_DECREF(attrib);
+                return;
+            }
+            attrib_in += 2;
+        }
+    } else {
+        /* Pass an empty dictionary on */
+        attrib = PyDict_New();
+        if (!attrib)
+            return;
+    }
+
+    if (TreeBuilder_CheckExact(self->target)) {
+        /* shortcut */
+        res = treebuilder_handle_start((TreeBuilderObject*) self->target,
+                                       tag, attrib);
+    }
+    else if (self->handle_start) {
+        res = PyObject_CallFunction(self->handle_start, "OO", tag, attrib);
+    } else
+        res = NULL;
+
+    Py_DECREF(tag);
+    Py_DECREF(attrib);
+
+    Py_XDECREF(res);
+}
+
+static void
+expat_data_handler(XMLParserObject* self, const XML_Char* data_in,
+                   int data_len)
+{
+    PyObject* data;
+    PyObject* res;
+
+    if (PyErr_Occurred())
+        return;
+
+    data = PyUnicode_DecodeUTF8(data_in, data_len, "strict");
+    if (!data)
+        return; /* parser will look for errors */
+
+    if (TreeBuilder_CheckExact(self->target))
+        /* shortcut */
+        res = treebuilder_handle_data((TreeBuilderObject*) self->target, data);
+    else if (self->handle_data)
+        res = PyObject_CallFunction(self->handle_data, "O", data);
+    else
+        res = NULL;
+
+    Py_DECREF(data);
+
+    Py_XDECREF(res);
+}
+
+static void
+expat_end_handler(XMLParserObject* self, const XML_Char* tag_in)
 {
     PyObject* tag;
-    PyObject* attrib = Py_None;
-    if (!PyArg_ParseTuple(args, "O|O:start", &tag, &attrib))
+    PyObject* res = NULL;
+
+    if (PyErr_Occurred())
+        return;
+
+    if (TreeBuilder_CheckExact(self->target))
+        /* shortcut */
+        /* the standard tree builder doesn't look at the end tag */
+        res = treebuilder_handle_end(
+            (TreeBuilderObject*) self->target, Py_None
+            );
+    else if (self->handle_end) {
+        tag = makeuniversal(self, tag_in);
+        if (tag) {
+            res = PyObject_CallFunction(self->handle_end, "O", tag);
+            Py_DECREF(tag);
+        }
+    }
+
+    Py_XDECREF(res);
+}
+
+static void
+expat_start_ns_handler(XMLParserObject* self, const XML_Char* prefix,
+                       const XML_Char *uri)
+{
+    PyObject* sprefix = NULL;
+    PyObject* suri = NULL;
+
+    if (PyErr_Occurred())
+        return;
+
+    if (uri)
+        suri = PyUnicode_DecodeUTF8(uri, strlen(uri), "strict");
+    else
+        suri = PyUnicode_FromString("");
+    if (!suri)
+        return;
+
+    if (prefix)
+        sprefix = PyUnicode_DecodeUTF8(prefix, strlen(prefix), "strict");
+    else
+        sprefix = PyUnicode_FromString("");
+    if (!sprefix) {
+        Py_DECREF(suri);
+        return;
+    }
+
+    treebuilder_handle_namespace(
+        (TreeBuilderObject*) self->target, 1, sprefix, suri
+        );
+
+    Py_DECREF(sprefix);
+    Py_DECREF(suri);
+}
+
+static void
+expat_end_ns_handler(XMLParserObject* self, const XML_Char* prefix_in)
+{
+    if (PyErr_Occurred())
+        return;
+
+    treebuilder_handle_namespace(
+        (TreeBuilderObject*) self->target, 0, NULL, NULL
+        );
+}
+
+static void
+expat_comment_handler(XMLParserObject* self, const XML_Char* comment_in)
+{
+    PyObject* comment;
+    PyObject* res;
+
+    if (PyErr_Occurred())
+        return;
+
+    if (self->handle_comment) {
+        comment = PyUnicode_DecodeUTF8(comment_in, strlen(comment_in), "strict");
+        if (comment) {
+            res = PyObject_CallFunction(self->handle_comment, "O", comment);
+            Py_XDECREF(res);
+            Py_DECREF(comment);
+        }
+    }
+}
+
+static void
+expat_start_doctype_handler(XMLParserObject *self,
+                            const XML_Char *doctype_name,
+                            const XML_Char *sysid,
+                            const XML_Char *pubid,
+                            int has_internal_subset)
+{
+    PyObject *self_pyobj = (PyObject *)self;
+    PyObject *doctype_name_obj, *sysid_obj, *pubid_obj;
+    PyObject *parser_doctype = NULL;
+    PyObject *res = NULL;
+
+    if (PyErr_Occurred())
+        return;
+
+    doctype_name_obj = makeuniversal(self, doctype_name);
+    if (!doctype_name_obj)
+        return;
+
+    if (sysid) {
+        sysid_obj = makeuniversal(self, sysid);
+        if (!sysid_obj) {
+            Py_DECREF(doctype_name_obj);
+            return;
+        }
+    } else {
+        Py_INCREF(Py_None);
+        sysid_obj = Py_None;
+    }
+
+    if (pubid) {
+        pubid_obj = makeuniversal(self, pubid);
+        if (!pubid_obj) {
+            Py_DECREF(doctype_name_obj);
+            Py_DECREF(sysid_obj);
+            return;
+        }
+    } else {
+        Py_INCREF(Py_None);
+        pubid_obj = Py_None;
+    }
+
+    /* If the target has a handler for doctype, call it. */
+    if (self->handle_doctype) {
+        res = PyObject_CallFunction(self->handle_doctype, "OOO",
+                                    doctype_name_obj, pubid_obj, sysid_obj);
+        Py_CLEAR(res);
+    }
+
+    /* Now see if the parser itself has a doctype method. If yes and it's
+     * a subclass, call it but warn about deprecation. If it's not a subclass
+     * (i.e. vanilla XMLParser), do nothing.
+     */
+    parser_doctype = PyObject_GetAttrString(self_pyobj, "doctype");
+    if (parser_doctype) {
+        if (!XMLParser_CheckExact(self_pyobj)) {
+            if (PyErr_WarnEx(PyExc_DeprecationWarning,
+                            "This method of XMLParser is deprecated.  Define"
+                            " doctype() method on the TreeBuilder target.",
+                            1) < 0) {
+                goto clear;
+            }
+            res = PyObject_CallFunction(parser_doctype, "OOO",
+                                        doctype_name_obj, pubid_obj, sysid_obj);
+            Py_CLEAR(res);
+        }
+    }
+
+clear:
+    Py_XDECREF(parser_doctype);
+    Py_DECREF(doctype_name_obj);
+    Py_DECREF(pubid_obj);
+    Py_DECREF(sysid_obj);
+}
+
+static void
+expat_pi_handler(XMLParserObject* self, const XML_Char* target_in,
+                 const XML_Char* data_in)
+{
+    PyObject* target;
+    PyObject* data;
+    PyObject* res;
+
+    if (PyErr_Occurred())
+        return;
+
+    if (self->handle_pi) {
+        target = PyUnicode_DecodeUTF8(target_in, strlen(target_in), "strict");
+        data = PyUnicode_DecodeUTF8(data_in, strlen(data_in), "strict");
+        if (target && data) {
+            res = PyObject_CallFunction(self->handle_pi, "OO", target, data);
+            Py_XDECREF(res);
+            Py_DECREF(data);
+            Py_DECREF(target);
+        } else {
+            Py_XDECREF(data);
+            Py_XDECREF(target);
+        }
+    }
+}
+
+/* -------------------------------------------------------------------- */
+
+static PyObject *
+xmlparser_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    XMLParserObject *self = (XMLParserObject *)type->tp_alloc(type, 0);
+    if (self) {
+        self->parser = NULL;
+        self->target = self->entity = self->names = NULL;
+        self->handle_start = self->handle_data = self->handle_end = NULL;
+        self->handle_comment = self->handle_pi = self->handle_close = NULL;
+        self->handle_doctype = NULL;
+    }
+    return (PyObject *)self;
+}
+
+/*[clinic input]
+_elementtree.XMLParser.__init__
+
+    html: object = NULL
+    target: object = NULL
+    encoding: str(nullable=True) = NULL
+
+[clinic start generated code]*/
+
+static int
+_elementtree_XMLParser___init___impl(XMLParserObject *self, PyObject *html,
+                                     PyObject *target, const char *encoding)
+/*[clinic end generated code: output=d6a16c63dda54441 input=a870da39c80d7d68]*/
+{
+    self->entity = PyDict_New();
+    if (!self->entity)
+        return -1;
+
+    self->names = PyDict_New();
+    if (!self->names) {
+        Py_CLEAR(self->entity);
+        return -1;
+    }
+
+    self->parser = EXPAT(ParserCreate_MM)(encoding, &ExpatMemoryHandler, "}");
+    if (!self->parser) {
+        Py_CLEAR(self->entity);
+        Py_CLEAR(self->names);
+        PyErr_NoMemory();
+        return -1;
+    }
+
+    if (target) {
+        Py_INCREF(target);
+    } else {
+        target = treebuilder_new(&TreeBuilder_Type, NULL, NULL);
+        if (!target) {
+            Py_CLEAR(self->entity);
+            Py_CLEAR(self->names);
+            EXPAT(ParserFree)(self->parser);
+            return -1;
+        }
+    }
+    self->target = target;
+
+    self->handle_start = PyObject_GetAttrString(target, "start");
+    self->handle_data = PyObject_GetAttrString(target, "data");
+    self->handle_end = PyObject_GetAttrString(target, "end");
+    self->handle_comment = PyObject_GetAttrString(target, "comment");
+    self->handle_pi = PyObject_GetAttrString(target, "pi");
+    self->handle_close = PyObject_GetAttrString(target, "close");
+    self->handle_doctype = PyObject_GetAttrString(target, "doctype");
+
+    PyErr_Clear();
+
+    /* configure parser */
+    EXPAT(SetUserData)(self->parser, self);
+    EXPAT(SetElementHandler)(
+        self->parser,
+        (XML_StartElementHandler) expat_start_handler,
+        (XML_EndElementHandler) expat_end_handler
+        );
+    EXPAT(SetDefaultHandlerExpand)(
+        self->parser,
+        (XML_DefaultHandler) expat_default_handler
+        );
+    EXPAT(SetCharacterDataHandler)(
+        self->parser,
+        (XML_CharacterDataHandler) expat_data_handler
+        );
+    if (self->handle_comment)
+        EXPAT(SetCommentHandler)(
+            self->parser,
+            (XML_CommentHandler) expat_comment_handler
+            );
+    if (self->handle_pi)
+        EXPAT(SetProcessingInstructionHandler)(
+            self->parser,
+            (XML_ProcessingInstructionHandler) expat_pi_handler
+            );
+    EXPAT(SetStartDoctypeDeclHandler)(
+        self->parser,
+        (XML_StartDoctypeDeclHandler) expat_start_doctype_handler
+        );
+    EXPAT(SetUnknownEncodingHandler)(
+        self->parser,
+        EXPAT(DefaultUnknownEncodingHandler), NULL
+        );
+
+    return 0;
+}
+
+static int
+xmlparser_gc_traverse(XMLParserObject *self, visitproc visit, void *arg)
+{
+    Py_VISIT(self->handle_close);
+    Py_VISIT(self->handle_pi);
+    Py_VISIT(self->handle_comment);
+    Py_VISIT(self->handle_end);
+    Py_VISIT(self->handle_data);
+    Py_VISIT(self->handle_start);
+
+    Py_VISIT(self->target);
+    Py_VISIT(self->entity);
+    Py_VISIT(self->names);
+
+    return 0;
+}
+
+static int
+xmlparser_gc_clear(XMLParserObject *self)
+{
+    EXPAT(ParserFree)(self->parser);
+
+    Py_CLEAR(self->handle_close);
+    Py_CLEAR(self->handle_pi);
+    Py_CLEAR(self->handle_comment);
+    Py_CLEAR(self->handle_end);
+    Py_CLEAR(self->handle_data);
+    Py_CLEAR(self->handle_start);
+    Py_CLEAR(self->handle_doctype);
+
+    Py_CLEAR(self->target);
+    Py_CLEAR(self->entity);
+    Py_CLEAR(self->names);
+
+    return 0;
+}
+
+static void
+xmlparser_dealloc(XMLParserObject* self)
+{
+    PyObject_GC_UnTrack(self);
+    xmlparser_gc_clear(self);
+    Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+LOCAL(PyObject*)
+expat_parse(XMLParserObject* self, const char* data, int data_len, int final)
+{
+    int ok;
+
+    assert(!PyErr_Occurred());
+    ok = EXPAT(Parse)(self->parser, data, data_len, final);
+
+    if (PyErr_Occurred())
         return NULL;
 
-    return treebuilder_handle_start(self, tag, attrib);
+    if (!ok) {
+        expat_set_error(
+            EXPAT(GetErrorCode)(self->parser),
+            EXPAT(GetErrorLineNumber)(self->parser),
+            EXPAT(GetErrorColumnNumber)(self->parser),
+            NULL
+            );
+        return NULL;
+    }
+
+    Py_RETURN_NONE;
 }
 
+/*[clinic input]
+_elementtree.XMLParser.close
+
+[clinic start generated code]*/
+
+static PyObject *
+_elementtree_XMLParser_close_impl(XMLParserObject *self)
+/*[clinic end generated code: output=d68d375dd23bc7fb input=ca7909ca78c3abfe]*/
+{
+    /* end feeding data to parser */
+
+    PyObject* res;
+    res = expat_parse(self, "", 0, 1);
+    if (!res)
+        return NULL;
+
+    if (TreeBuilder_CheckExact(self->target)) {
+        Py_DECREF(res);
+        return treebuilder_done((TreeBuilderObject*) self->target);
+    }
+    else if (self->handle_close) {
+        Py_DECREF(res);
+        return PyObject_CallFunction(self->handle_close, "");
+    }
+    else {
+        return res;
+    }
+}
+
+/*[clinic input]
+_elementtree.XMLParser.feed
+
+    data: object
+    /
+
+[clinic start generated code]*/
+
+static PyObject *
+_elementtree_XMLParser_feed(XMLParserObject *self, PyObject *data)
+/*[clinic end generated code: output=e42b6a78eec7446d input=fe231b6b8de3ce1f]*/
+{
+    /* feed data to parser */
+
+    if (PyUnicode_Check(data)) {
+        Py_ssize_t data_len;
+        const char *data_ptr = PyUnicode_AsUTF8AndSize(data, &data_len);
+        if (data_ptr == NULL)
+            return NULL;
+        if (data_len > INT_MAX) {
+            PyErr_SetString(PyExc_OverflowError, "size does not fit in an int");
+            return NULL;
+        }
+        /* Explicitly set UTF-8 encoding. Return code ignored. */
+        (void)EXPAT(SetEncoding)(self->parser, "utf-8");
+        return expat_parse(self, data_ptr, (int)data_len, 0);
+    }
+    else {
+        Py_buffer view;
+        PyObject *res;
+        if (PyObject_GetBuffer(data, &view, PyBUF_SIMPLE) < 0)
+            return NULL;
+        if (view.len > INT_MAX) {
+            PyBuffer_Release(&view);
+            PyErr_SetString(PyExc_OverflowError, "size does not fit in an int");
+            return NULL;
+        }
+        res = expat_parse(self, view.buf, (int)view.len, 0);
+        PyBuffer_Release(&view);
+        return res;
+    }
+}
+
+/*[clinic input]
+_elementtree.XMLParser._parse_whole
+
+    file: object
+    /
+
+[clinic start generated code]*/
+
+static PyObject *
+_elementtree_XMLParser__parse_whole(XMLParserObject *self, PyObject *file)
+/*[clinic end generated code: output=f797197bb818dda3 input=19ecc893b6f3e752]*/
+{
+    /* (internal) parse the whole input, until end of stream */
+    PyObject* reader;
+    PyObject* buffer;
+    PyObject* temp;
+    PyObject* res;
+
+    reader = PyObject_GetAttrString(file, "read");
+    if (!reader)
+        return NULL;
+
+    /* read from open file object */
+    for (;;) {
+
+        buffer = PyObject_CallFunction(reader, "i", 64*1024);
+
+        if (!buffer) {
+            /* read failed (e.g. due to KeyboardInterrupt) */
+            Py_DECREF(reader);
+            return NULL;
+        }
+
+        if (PyUnicode_CheckExact(buffer)) {
+            /* A unicode object is encoded into bytes using UTF-8 */
+            if (PyUnicode_GET_LENGTH(buffer) == 0) {
+                Py_DECREF(buffer);
+                break;
+            }
+            temp = PyUnicode_AsEncodedString(buffer, "utf-8", "surrogatepass");
+            Py_DECREF(buffer);
+            if (!temp) {
+                /* Propagate exception from PyUnicode_AsEncodedString */
+                Py_DECREF(reader);
+                return NULL;
+            }
+            buffer = temp;
+        }
+        else if (!PyBytes_CheckExact(buffer) || PyBytes_GET_SIZE(buffer) == 0) {
+            Py_DECREF(buffer);
+            break;
+        }
+
+        if (PyBytes_GET_SIZE(buffer) > INT_MAX) {
+            Py_DECREF(buffer);
+            Py_DECREF(reader);
+            PyErr_SetString(PyExc_OverflowError, "size does not fit in an int");
+            return NULL;
+        }
+        res = expat_parse(
+            self, PyBytes_AS_STRING(buffer), (int)PyBytes_GET_SIZE(buffer), 0
+            );
+
+        Py_DECREF(buffer);
+
+        if (!res) {
+            Py_DECREF(reader);
+            return NULL;
+        }
+        Py_DECREF(res);
+
+    }
+
+    Py_DECREF(reader);
+
+    res = expat_parse(self, "", 0, 1);
+
+    if (res && TreeBuilder_CheckExact(self->target)) {
+        Py_DECREF(res);
+        return treebuilder_done((TreeBuilderObject*) self->target);
+    }
+
+    return res;
+}
+
+/*[clinic input]
+_elementtree.XMLParser.doctype
+
+[clinic start generated code]*/
+
+static PyObject *
+_elementtree_XMLParser_doctype_impl(XMLParserObject *self)
+/*[clinic end generated code: output=d09fdb9c45f3a602 input=20d5e0febf902a2f]*/
+{
+    Py_RETURN_NONE;
+}
+
+/*[clinic input]
+_elementtree.XMLParser._setevents
+
+    events_queue: object(subclass_of='&PyList_Type')
+    events_to_report: object = None
+    /
+
+[clinic start generated code]*/
+
+static PyObject *
+_elementtree_XMLParser__setevents_impl(XMLParserObject *self,
+                                       PyObject *events_queue,
+                                       PyObject *events_to_report)
+/*[clinic end generated code: output=1440092922b13ed1 input=59db9742910c6174]*/
+{
+    /* activate element event reporting */
+    Py_ssize_t i, seqlen;
+    TreeBuilderObject *target;
+    PyObject *events_seq;
+
+    if (!TreeBuilder_CheckExact(self->target)) {
+        PyErr_SetString(
+            PyExc_TypeError,
+            "event handling only supported for ElementTree.TreeBuilder "
+            "targets"
+            );
+        return NULL;
+    }
+
+    target = (TreeBuilderObject*) self->target;
+
+    Py_INCREF(events_queue);
+    Py_XDECREF(target->events);
+    target->events = events_queue;
+
+    /* clear out existing events */
+    Py_CLEAR(target->start_event_obj);
+    Py_CLEAR(target->end_event_obj);
+    Py_CLEAR(target->start_ns_event_obj);
+    Py_CLEAR(target->end_ns_event_obj);
+
+    if (events_to_report == Py_None) {
+        /* default is "end" only */
+        target->end_event_obj = PyUnicode_FromString("end");
+        Py_RETURN_NONE;
+    }
+
+    if (!(events_seq = PySequence_Fast(events_to_report,
+                                       "events must be a sequence"))) {
+        return NULL;
+    }
+
+    seqlen = PySequence_Size(events_seq);
+    for (i = 0; i < seqlen; ++i) {
+        PyObject *event_name_obj = PySequence_Fast_GET_ITEM(events_seq, i);
+        char *event_name = NULL;
+        if (PyUnicode_Check(event_name_obj)) {
+            event_name = _PyUnicode_AsString(event_name_obj);
+        } else if (PyBytes_Check(event_name_obj)) {
+            event_name = PyBytes_AS_STRING(event_name_obj);
+        }
+
+        if (event_name == NULL) {
+            Py_DECREF(events_seq);
+            PyErr_Format(PyExc_ValueError, "invalid events sequence");
+            return NULL;
+        } else if (strcmp(event_name, "start") == 0) {
+            Py_INCREF(event_name_obj);
+            target->start_event_obj = event_name_obj;
+        } else if (strcmp(event_name, "end") == 0) {
+            Py_INCREF(event_name_obj);
+            Py_XDECREF(target->end_event_obj);
+            target->end_event_obj = event_name_obj;
+        } else if (strcmp(event_name, "start-ns") == 0) {
+            Py_INCREF(event_name_obj);
+            Py_XDECREF(target->start_ns_event_obj);
+            target->start_ns_event_obj = event_name_obj;
+            EXPAT(SetNamespaceDeclHandler)(
+                self->parser,
+                (XML_StartNamespaceDeclHandler) expat_start_ns_handler,
+                (XML_EndNamespaceDeclHandler) expat_end_ns_handler
+                );
+        } else if (strcmp(event_name, "end-ns") == 0) {
+            Py_INCREF(event_name_obj);
+            Py_XDECREF(target->end_ns_event_obj);
+            target->end_ns_event_obj = event_name_obj;
+            EXPAT(SetNamespaceDeclHandler)(
+                self->parser,
+                (XML_StartNamespaceDeclHandler) expat_start_ns_handler,
+                (XML_EndNamespaceDeclHandler) expat_end_ns_handler
+                );
+        } else {
+            Py_DECREF(events_seq);
+            PyErr_Format(PyExc_ValueError, "unknown event '%s'", event_name);
+            return NULL;
+        }
+    }
+
+    Py_DECREF(events_seq);
+    Py_RETURN_NONE;
+}
+
+static PyObject*
+xmlparser_getattro(XMLParserObject* self, PyObject* nameobj)
+{
+    if (PyUnicode_Check(nameobj)) {
+        PyObject* res;
+        if (PyUnicode_CompareWithASCIIString(nameobj, "entity") == 0)
+            res = self->entity;
+        else if (PyUnicode_CompareWithASCIIString(nameobj, "target") == 0)
+            res = self->target;
+        else if (PyUnicode_CompareWithASCIIString(nameobj, "version") == 0) {
+            return PyUnicode_FromFormat(
+                "Expat %d.%d.%d", XML_MAJOR_VERSION,
+                XML_MINOR_VERSION, XML_MICRO_VERSION);
+        }
+        else
+            goto generic;
+
+        Py_INCREF(res);
+        return res;
+    }
+  generic:
+    return PyObject_GenericGetAttr((PyObject*) self, nameobj);
+}
+
+#include "clinic/_elementtree.c.h"
+
+static PyMethodDef element_methods[] = {
+
+    _ELEMENTTREE_ELEMENT_CLEAR_METHODDEF
+
+    _ELEMENTTREE_ELEMENT_GET_METHODDEF
+    _ELEMENTTREE_ELEMENT_SET_METHODDEF
+
+    _ELEMENTTREE_ELEMENT_FIND_METHODDEF
+    _ELEMENTTREE_ELEMENT_FINDTEXT_METHODDEF
+    _ELEMENTTREE_ELEMENT_FINDALL_METHODDEF
+
+    _ELEMENTTREE_ELEMENT_APPEND_METHODDEF
+    _ELEMENTTREE_ELEMENT_EXTEND_METHODDEF
+    _ELEMENTTREE_ELEMENT_INSERT_METHODDEF
+    _ELEMENTTREE_ELEMENT_REMOVE_METHODDEF
+
+    _ELEMENTTREE_ELEMENT_ITER_METHODDEF
+    _ELEMENTTREE_ELEMENT_ITERTEXT_METHODDEF
+    _ELEMENTTREE_ELEMENT_ITERFIND_METHODDEF
+
+    {"getiterator", (PyCFunction)_elementtree_Element_iter, METH_VARARGS|METH_KEYWORDS, _elementtree_Element_iter__doc__},
+    _ELEMENTTREE_ELEMENT_GETCHILDREN_METHODDEF
+
+    _ELEMENTTREE_ELEMENT_ITEMS_METHODDEF
+    _ELEMENTTREE_ELEMENT_KEYS_METHODDEF
+
+    _ELEMENTTREE_ELEMENT_MAKEELEMENT_METHODDEF
+
+    _ELEMENTTREE_ELEMENT___COPY___METHODDEF
+    _ELEMENTTREE_ELEMENT___DEEPCOPY___METHODDEF
+    _ELEMENTTREE_ELEMENT___SIZEOF___METHODDEF
+    _ELEMENTTREE_ELEMENT___GETSTATE___METHODDEF
+    _ELEMENTTREE_ELEMENT___SETSTATE___METHODDEF
+
+    {NULL, NULL}
+};
+
+static PyMappingMethods element_as_mapping = {
+    (lenfunc) element_length,
+    (binaryfunc) element_subscr,
+    (objobjargproc) element_ass_subscr,
+};
+
+static PyTypeObject Element_Type = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "xml.etree.ElementTree.Element", sizeof(ElementObject), 0,
+    /* methods */
+    (destructor)element_dealloc,                    /* tp_dealloc */
+    0,                                              /* tp_print */
+    0,                                              /* tp_getattr */
+    0,                                              /* tp_setattr */
+    0,                                              /* tp_reserved */
+    (reprfunc)element_repr,                         /* tp_repr */
+    0,                                              /* tp_as_number */
+    &element_as_sequence,                           /* tp_as_sequence */
+    &element_as_mapping,                            /* tp_as_mapping */
+    0,                                              /* tp_hash */
+    0,                                              /* tp_call */
+    0,                                              /* tp_str */
+    (getattrofunc)element_getattro,                 /* tp_getattro */
+    (setattrofunc)element_setattro,                 /* tp_setattro */
+    0,                                              /* tp_as_buffer */
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
+                                                    /* tp_flags */
+    0,                                              /* tp_doc */
+    (traverseproc)element_gc_traverse,              /* tp_traverse */
+    (inquiry)element_gc_clear,                      /* tp_clear */
+    0,                                              /* tp_richcompare */
+    offsetof(ElementObject, weakreflist),           /* tp_weaklistoffset */
+    0,                                              /* tp_iter */
+    0,                                              /* tp_iternext */
+    element_methods,                                /* tp_methods */
+    0,                                              /* tp_members */
+    0,                                              /* tp_getset */
+    0,                                              /* tp_base */
+    0,                                              /* tp_dict */
+    0,                                              /* tp_descr_get */
+    0,                                              /* tp_descr_set */
+    0,                                              /* tp_dictoffset */
+    (initproc)element_init,                         /* tp_init */
+    PyType_GenericAlloc,                            /* tp_alloc */
+    element_new,                                    /* tp_new */
+    0,                                              /* tp_free */
+};
+
 static PyMethodDef treebuilder_methods[] = {
-    {"data", (PyCFunction) treebuilder_data, METH_VARARGS},
-    {"start", (PyCFunction) treebuilder_start, METH_VARARGS},
-    {"end", (PyCFunction) treebuilder_end, METH_VARARGS},
-    {"close", (PyCFunction) treebuilder_close, METH_VARARGS},
+    _ELEMENTTREE_TREEBUILDER_DATA_METHODDEF
+    _ELEMENTTREE_TREEBUILDER_START_METHODDEF
+    _ELEMENTTREE_TREEBUILDER_END_METHODDEF
+    _ELEMENTTREE_TREEBUILDER_CLOSE_METHODDEF
     {NULL, NULL}
 };
 
@@ -2700,953 +3788,21 @@
     0,                                              /* tp_descr_get */
     0,                                              /* tp_descr_set */
     0,                                              /* tp_dictoffset */
-    (initproc)treebuilder_init,                     /* tp_init */
+    _elementtree_TreeBuilder___init__,              /* tp_init */
     PyType_GenericAlloc,                            /* tp_alloc */
     treebuilder_new,                                /* tp_new */
     0,                                              /* tp_free */
 };
 
-/* ==================================================================== */
-/* the expat interface */
-
-#include "expat.h"
-#include "pyexpat.h"
-
-/* The PyExpat_CAPI structure is an immutable dispatch table, so it can be
- * cached globally without being in per-module state.
- */
-static struct PyExpat_CAPI *expat_capi;
-#define EXPAT(func) (expat_capi->func)
-
-static XML_Memory_Handling_Suite ExpatMemoryHandler = {
-    PyObject_Malloc, PyObject_Realloc, PyObject_Free};
-
-typedef struct {
-    PyObject_HEAD
-
-    XML_Parser parser;
-
-    PyObject *target;
-    PyObject *entity;
-
-    PyObject *names;
-
-    PyObject *handle_start;
-    PyObject *handle_data;
-    PyObject *handle_end;
-
-    PyObject *handle_comment;
-    PyObject *handle_pi;
-    PyObject *handle_doctype;
-
-    PyObject *handle_close;
-
-} XMLParserObject;
-
-#define XMLParser_CheckExact(op) (Py_TYPE(op) == &XMLParser_Type)
-
-/* helpers */
-
-LOCAL(PyObject*)
-makeuniversal(XMLParserObject* self, const char* string)
-{
-    /* convert a UTF-8 tag/attribute name from the expat parser
-       to a universal name string */
-
-    Py_ssize_t size = (Py_ssize_t) strlen(string);
-    PyObject* key;
-    PyObject* value;
-
-    /* look the 'raw' name up in the names dictionary */
-    key = PyBytes_FromStringAndSize(string, size);
-    if (!key)
-        return NULL;
-
-    value = PyDict_GetItem(self->names, key);
-
-    if (value) {
-        Py_INCREF(value);
-    } else {
-        /* new name.  convert to universal name, and decode as
-           necessary */
-
-        PyObject* tag;
-        char* p;
-        Py_ssize_t i;
-
-        /* look for namespace separator */
-        for (i = 0; i < size; i++)
-            if (string[i] == '}')
-                break;
-        if (i != size) {
-            /* convert to universal name */
-            tag = PyBytes_FromStringAndSize(NULL, size+1);
-            if (tag == NULL) {
-                Py_DECREF(key);
-                return NULL;
-            }
-            p = PyBytes_AS_STRING(tag);
-            p[0] = '{';
-            memcpy(p+1, string, size);
-            size++;
-        } else {
-            /* plain name; use key as tag */
-            Py_INCREF(key);
-            tag = key;
-        }
-
-        /* decode universal name */
-        p = PyBytes_AS_STRING(tag);
-        value = PyUnicode_DecodeUTF8(p, size, "strict");
-        Py_DECREF(tag);
-        if (!value) {
-            Py_DECREF(key);
-            return NULL;
-        }
-
-        /* add to names dictionary */
-        if (PyDict_SetItem(self->names, key, value) < 0) {
-            Py_DECREF(key);
-            Py_DECREF(value);
-            return NULL;
-        }
-    }
-
-    Py_DECREF(key);
-    return value;
-}
-
-/* Set the ParseError exception with the given parameters.
- * If message is not NULL, it's used as the error string. Otherwise, the
- * message string is the default for the given error_code.
-*/
-static void
-expat_set_error(enum XML_Error error_code, Py_ssize_t line, Py_ssize_t column,
-                const char *message)
-{
-    PyObject *errmsg, *error, *position, *code;
-    elementtreestate *st = ET_STATE_GLOBAL;
-
-    errmsg = PyUnicode_FromFormat("%s: line %zd, column %zd",
-                message ? message : EXPAT(ErrorString)(error_code),
-                line, column);
-    if (errmsg == NULL)
-        return;
-
-    error = PyObject_CallFunction(st->parseerror_obj, "O", errmsg);
-    Py_DECREF(errmsg);
-    if (!error)
-        return;
-
-    /* Add code and position attributes */
-    code = PyLong_FromLong((long)error_code);
-    if (!code) {
-        Py_DECREF(error);
-        return;
-    }
-    if (PyObject_SetAttrString(error, "code", code) == -1) {
-        Py_DECREF(error);
-        Py_DECREF(code);
-        return;
-    }
-    Py_DECREF(code);
-
-    position = Py_BuildValue("(nn)", line, column);
-    if (!position) {
-        Py_DECREF(error);
-        return;
-    }
-    if (PyObject_SetAttrString(error, "position", position) == -1) {
-        Py_DECREF(error);
-        Py_DECREF(position);
-        return;
-    }
-    Py_DECREF(position);
-
-    PyErr_SetObject(st->parseerror_obj, error);
-    Py_DECREF(error);
-}
-
-/* -------------------------------------------------------------------- */
-/* handlers */
-
-static void
-expat_default_handler(XMLParserObject* self, const XML_Char* data_in,
-                      int data_len)
-{
-    PyObject* key;
-    PyObject* value;
-    PyObject* res;
-
-    if (data_len < 2 || data_in[0] != '&')
-        return;
-
-    if (PyErr_Occurred())
-        return;
-
-    key = PyUnicode_DecodeUTF8(data_in + 1, data_len - 2, "strict");
-    if (!key)
-        return;
-
-    value = PyDict_GetItem(self->entity, key);
-
-    if (value) {
-        if (TreeBuilder_CheckExact(self->target))
-            res = treebuilder_handle_data(
-                (TreeBuilderObject*) self->target, value
-                );
-        else if (self->handle_data)
-            res = PyObject_CallFunction(self->handle_data, "O", value);
-        else
-            res = NULL;
-        Py_XDECREF(res);
-    } else if (!PyErr_Occurred()) {
-        /* Report the first error, not the last */
-        char message[128] = "undefined entity ";
-        strncat(message, data_in, data_len < 100?data_len:100);
-        expat_set_error(
-            XML_ERROR_UNDEFINED_ENTITY,
-            EXPAT(GetErrorLineNumber)(self->parser),
-            EXPAT(GetErrorColumnNumber)(self->parser),
-            message
-            );
-    }
-
-    Py_DECREF(key);
-}
-
-static void
-expat_start_handler(XMLParserObject* self, const XML_Char* tag_in,
-                    const XML_Char **attrib_in)
-{
-    PyObject* res;
-    PyObject* tag;
-    PyObject* attrib;
-    int ok;
-
-    if (PyErr_Occurred())
-        return;
-
-    /* tag name */
-    tag = makeuniversal(self, tag_in);
-    if (!tag)
-        return; /* parser will look for errors */
-
-    /* attributes */
-    if (attrib_in[0]) {
-        attrib = PyDict_New();
-        if (!attrib)
-            return;
-        while (attrib_in[0] && attrib_in[1]) {
-            PyObject* key = makeuniversal(self, attrib_in[0]);
-            PyObject* value = PyUnicode_DecodeUTF8(attrib_in[1], strlen(attrib_in[1]), "strict");
-            if (!key || !value) {
-                Py_XDECREF(value);
-                Py_XDECREF(key);
-                Py_DECREF(attrib);
-                return;
-            }
-            ok = PyDict_SetItem(attrib, key, value);
-            Py_DECREF(value);
-            Py_DECREF(key);
-            if (ok < 0) {
-                Py_DECREF(attrib);
-                return;
-            }
-            attrib_in += 2;
-        }
-    } else {
-        /* Pass an empty dictionary on */
-        attrib = PyDict_New();
-        if (!attrib)
-            return;
-    }
-
-    if (TreeBuilder_CheckExact(self->target)) {
-        /* shortcut */
-        res = treebuilder_handle_start((TreeBuilderObject*) self->target,
-                                       tag, attrib);
-    }
-    else if (self->handle_start) {
-        res = PyObject_CallFunction(self->handle_start, "OO", tag, attrib);
-    } else
-        res = NULL;
-
-    Py_DECREF(tag);
-    Py_DECREF(attrib);
-
-    Py_XDECREF(res);
-}
-
-static void
-expat_data_handler(XMLParserObject* self, const XML_Char* data_in,
-                   int data_len)
-{
-    PyObject* data;
-    PyObject* res;
-
-    if (PyErr_Occurred())
-        return;
-
-    data = PyUnicode_DecodeUTF8(data_in, data_len, "strict");
-    if (!data)
-        return; /* parser will look for errors */
-
-    if (TreeBuilder_CheckExact(self->target))
-        /* shortcut */
-        res = treebuilder_handle_data((TreeBuilderObject*) self->target, data);
-    else if (self->handle_data)
-        res = PyObject_CallFunction(self->handle_data, "O", data);
-    else
-        res = NULL;
-
-    Py_DECREF(data);
-
-    Py_XDECREF(res);
-}
-
-static void
-expat_end_handler(XMLParserObject* self, const XML_Char* tag_in)
-{
-    PyObject* tag;
-    PyObject* res = NULL;
-
-    if (PyErr_Occurred())
-        return;
-
-    if (TreeBuilder_CheckExact(self->target))
-        /* shortcut */
-        /* the standard tree builder doesn't look at the end tag */
-        res = treebuilder_handle_end(
-            (TreeBuilderObject*) self->target, Py_None
-            );
-    else if (self->handle_end) {
-        tag = makeuniversal(self, tag_in);
-        if (tag) {
-            res = PyObject_CallFunction(self->handle_end, "O", tag);
-            Py_DECREF(tag);
-        }
-    }
-
-    Py_XDECREF(res);
-}
-
-static void
-expat_start_ns_handler(XMLParserObject* self, const XML_Char* prefix,
-                       const XML_Char *uri)
-{
-    PyObject* sprefix = NULL;
-    PyObject* suri = NULL;
-
-    if (PyErr_Occurred())
-        return;
-
-    if (uri)
-        suri = PyUnicode_DecodeUTF8(uri, strlen(uri), "strict");
-    else
-        suri = PyUnicode_FromString("");
-    if (!suri)
-        return;
-
-    if (prefix)
-        sprefix = PyUnicode_DecodeUTF8(prefix, strlen(prefix), "strict");
-    else
-        sprefix = PyUnicode_FromString("");
-    if (!sprefix) {
-        Py_DECREF(suri);
-        return;
-    }
-
-    treebuilder_handle_namespace(
-        (TreeBuilderObject*) self->target, 1, sprefix, suri
-        );
-
-    Py_DECREF(sprefix);
-    Py_DECREF(suri);
-}
-
-static void
-expat_end_ns_handler(XMLParserObject* self, const XML_Char* prefix_in)
-{
-    if (PyErr_Occurred())
-        return;
-
-    treebuilder_handle_namespace(
-        (TreeBuilderObject*) self->target, 0, NULL, NULL
-        );
-}
-
-static void
-expat_comment_handler(XMLParserObject* self, const XML_Char* comment_in)
-{
-    PyObject* comment;
-    PyObject* res;
-
-    if (PyErr_Occurred())
-        return;
-
-    if (self->handle_comment) {
-        comment = PyUnicode_DecodeUTF8(comment_in, strlen(comment_in), "strict");
-        if (comment) {
-            res = PyObject_CallFunction(self->handle_comment, "O", comment);
-            Py_XDECREF(res);
-            Py_DECREF(comment);
-        }
-    }
-}
-
-static void
-expat_start_doctype_handler(XMLParserObject *self,
-                            const XML_Char *doctype_name,
-                            const XML_Char *sysid,
-                            const XML_Char *pubid,
-                            int has_internal_subset)
-{
-    PyObject *self_pyobj = (PyObject *)self;
-    PyObject *doctype_name_obj, *sysid_obj, *pubid_obj;
-    PyObject *parser_doctype = NULL;
-    PyObject *res = NULL;
-
-    if (PyErr_Occurred())
-        return;
-
-    doctype_name_obj = makeuniversal(self, doctype_name);
-    if (!doctype_name_obj)
-        return;
-
-    if (sysid) {
-        sysid_obj = makeuniversal(self, sysid);
-        if (!sysid_obj) {
-            Py_DECREF(doctype_name_obj);
-            return;
-        }
-    } else {
-        Py_INCREF(Py_None);
-        sysid_obj = Py_None;
-    }
-
-    if (pubid) {
-        pubid_obj = makeuniversal(self, pubid);
-        if (!pubid_obj) {
-            Py_DECREF(doctype_name_obj);
-            Py_DECREF(sysid_obj);
-            return;
-        }
-    } else {
-        Py_INCREF(Py_None);
-        pubid_obj = Py_None;
-    }
-
-    /* If the target has a handler for doctype, call it. */
-    if (self->handle_doctype) {
-        res = PyObject_CallFunction(self->handle_doctype, "OOO",
-                                    doctype_name_obj, pubid_obj, sysid_obj);
-        Py_CLEAR(res);
-    }
-
-    /* Now see if the parser itself has a doctype method. If yes and it's
-     * a subclass, call it but warn about deprecation. If it's not a subclass
-     * (i.e. vanilla XMLParser), do nothing.
-     */
-    parser_doctype = PyObject_GetAttrString(self_pyobj, "doctype");
-    if (parser_doctype) {
-        if (!XMLParser_CheckExact(self_pyobj)) {
-            if (PyErr_WarnEx(PyExc_DeprecationWarning,
-                            "This method of XMLParser is deprecated.  Define"
-                            " doctype() method on the TreeBuilder target.",
-                            1) < 0) {
-                goto clear;
-            }
-            res = PyObject_CallFunction(parser_doctype, "OOO",
-                                        doctype_name_obj, pubid_obj, sysid_obj);
-            Py_CLEAR(res);
-        }
-    }
-
-clear:
-    Py_XDECREF(parser_doctype);
-    Py_DECREF(doctype_name_obj);
-    Py_DECREF(pubid_obj);
-    Py_DECREF(sysid_obj);
-}
-
-static void
-expat_pi_handler(XMLParserObject* self, const XML_Char* target_in,
-                 const XML_Char* data_in)
-{
-    PyObject* target;
-    PyObject* data;
-    PyObject* res;
-
-    if (PyErr_Occurred())
-        return;
-
-    if (self->handle_pi) {
-        target = PyUnicode_DecodeUTF8(target_in, strlen(target_in), "strict");
-        data = PyUnicode_DecodeUTF8(data_in, strlen(data_in), "strict");
-        if (target && data) {
-            res = PyObject_CallFunction(self->handle_pi, "OO", target, data);
-            Py_XDECREF(res);
-            Py_DECREF(data);
-            Py_DECREF(target);
-        } else {
-            Py_XDECREF(data);
-            Py_XDECREF(target);
-        }
-    }
-}
-
-/* -------------------------------------------------------------------- */
-
-static PyObject *
-xmlparser_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
-    XMLParserObject *self = (XMLParserObject *)type->tp_alloc(type, 0);
-    if (self) {
-        self->parser = NULL;
-        self->target = self->entity = self->names = NULL;
-        self->handle_start = self->handle_data = self->handle_end = NULL;
-        self->handle_comment = self->handle_pi = self->handle_close = NULL;
-        self->handle_doctype = NULL;
-    }
-    return (PyObject *)self;
-}
-
-static int
-xmlparser_init(PyObject *self, PyObject *args, PyObject *kwds)
-{
-    XMLParserObject *self_xp = (XMLParserObject *)self;
-    PyObject *target = NULL, *html = NULL;
-    char *encoding = NULL;
-    static char *kwlist[] = {"html", "target", "encoding", 0};
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOz:XMLParser", kwlist,
-                                     &html, &target, &encoding)) {
-        return -1;
-    }
-
-    self_xp->entity = PyDict_New();
-    if (!self_xp->entity)
-        return -1;
-
-    self_xp->names = PyDict_New();
-    if (!self_xp->names) {
-        Py_CLEAR(self_xp->entity);
-        return -1;
-    }
-
-    self_xp->parser = EXPAT(ParserCreate_MM)(encoding, &ExpatMemoryHandler, "}");
-    if (!self_xp->parser) {
-        Py_CLEAR(self_xp->entity);
-        Py_CLEAR(self_xp->names);
-        PyErr_NoMemory();
-        return -1;
-    }
-
-    if (target) {
-        Py_INCREF(target);
-    } else {
-        target = treebuilder_new(&TreeBuilder_Type, NULL, NULL);
-        if (!target) {
-            Py_CLEAR(self_xp->entity);
-            Py_CLEAR(self_xp->names);
-            EXPAT(ParserFree)(self_xp->parser);
-            return -1;
-        }
-    }
-    self_xp->target = target;
-
-    self_xp->handle_start = PyObject_GetAttrString(target, "start");
-    self_xp->handle_data = PyObject_GetAttrString(target, "data");
-    self_xp->handle_end = PyObject_GetAttrString(target, "end");
-    self_xp->handle_comment = PyObject_GetAttrString(target, "comment");
-    self_xp->handle_pi = PyObject_GetAttrString(target, "pi");
-    self_xp->handle_close = PyObject_GetAttrString(target, "close");
-    self_xp->handle_doctype = PyObject_GetAttrString(target, "doctype");
-
-    PyErr_Clear();
-
-    /* configure parser */
-    EXPAT(SetUserData)(self_xp->parser, self_xp);
-    EXPAT(SetElementHandler)(
-        self_xp->parser,
-        (XML_StartElementHandler) expat_start_handler,
-        (XML_EndElementHandler) expat_end_handler
-        );
-    EXPAT(SetDefaultHandlerExpand)(
-        self_xp->parser,
-        (XML_DefaultHandler) expat_default_handler
-        );
-    EXPAT(SetCharacterDataHandler)(
-        self_xp->parser,
-        (XML_CharacterDataHandler) expat_data_handler
-        );
-    if (self_xp->handle_comment)
-        EXPAT(SetCommentHandler)(
-            self_xp->parser,
-            (XML_CommentHandler) expat_comment_handler
-            );
-    if (self_xp->handle_pi)
-        EXPAT(SetProcessingInstructionHandler)(
-            self_xp->parser,
-            (XML_ProcessingInstructionHandler) expat_pi_handler
-            );
-    EXPAT(SetStartDoctypeDeclHandler)(
-        self_xp->parser,
-        (XML_StartDoctypeDeclHandler) expat_start_doctype_handler
-        );
-    EXPAT(SetUnknownEncodingHandler)(
-        self_xp->parser,
-        EXPAT(DefaultUnknownEncodingHandler), NULL
-        );
-
-    return 0;
-}
-
-static int
-xmlparser_gc_traverse(XMLParserObject *self, visitproc visit, void *arg)
-{
-    Py_VISIT(self->handle_close);
-    Py_VISIT(self->handle_pi);
-    Py_VISIT(self->handle_comment);
-    Py_VISIT(self->handle_end);
-    Py_VISIT(self->handle_data);
-    Py_VISIT(self->handle_start);
-
-    Py_VISIT(self->target);
-    Py_VISIT(self->entity);
-    Py_VISIT(self->names);
-
-    return 0;
-}
-
-static int
-xmlparser_gc_clear(XMLParserObject *self)
-{
-    EXPAT(ParserFree)(self->parser);
-
-    Py_CLEAR(self->handle_close);
-    Py_CLEAR(self->handle_pi);
-    Py_CLEAR(self->handle_comment);
-    Py_CLEAR(self->handle_end);
-    Py_CLEAR(self->handle_data);
-    Py_CLEAR(self->handle_start);
-    Py_CLEAR(self->handle_doctype);
-
-    Py_CLEAR(self->target);
-    Py_CLEAR(self->entity);
-    Py_CLEAR(self->names);
-
-    return 0;
-}
-
-static void
-xmlparser_dealloc(XMLParserObject* self)
-{
-    PyObject_GC_UnTrack(self);
-    xmlparser_gc_clear(self);
-    Py_TYPE(self)->tp_free((PyObject *)self);
-}
-
-LOCAL(PyObject*)
-expat_parse(XMLParserObject* self, const char* data, int data_len, int final)
-{
-    int ok;
-
-    assert(!PyErr_Occurred());
-    ok = EXPAT(Parse)(self->parser, data, data_len, final);
-
-    if (PyErr_Occurred())
-        return NULL;
-
-    if (!ok) {
-        expat_set_error(
-            EXPAT(GetErrorCode)(self->parser),
-            EXPAT(GetErrorLineNumber)(self->parser),
-            EXPAT(GetErrorColumnNumber)(self->parser),
-            NULL
-            );
-        return NULL;
-    }
-
-    Py_RETURN_NONE;
-}
-
-static PyObject*
-xmlparser_close(XMLParserObject* self, PyObject* args)
-{
-    /* end feeding data to parser */
-
-    PyObject* res;
-    if (!PyArg_ParseTuple(args, ":close"))
-        return NULL;
-
-    res = expat_parse(self, "", 0, 1);
-    if (!res)
-        return NULL;
-
-    if (TreeBuilder_CheckExact(self->target)) {
-        Py_DECREF(res);
-        return treebuilder_done((TreeBuilderObject*) self->target);
-    }
-    else if (self->handle_close) {
-        Py_DECREF(res);
-        return PyObject_CallFunction(self->handle_close, "");
-    }
-    else {
-        return res;
-    }
-}
-
-static PyObject*
-xmlparser_feed(XMLParserObject* self, PyObject* arg)
-{
-    /* feed data to parser */
-
-    if (PyUnicode_Check(arg)) {
-        Py_ssize_t data_len;
-        const char *data = PyUnicode_AsUTF8AndSize(arg, &data_len);
-        if (data == NULL)
-            return NULL;
-        if (data_len > INT_MAX) {
-            PyErr_SetString(PyExc_OverflowError, "size does not fit in an int");
-            return NULL;
-        }
-        /* Explicitly set UTF-8 encoding. Return code ignored. */
-        (void)EXPAT(SetEncoding)(self->parser, "utf-8");
-        return expat_parse(self, data, (int)data_len, 0);
-    }
-    else {
-        Py_buffer view;
-        PyObject *res;
-        if (PyObject_GetBuffer(arg, &view, PyBUF_SIMPLE) < 0)
-            return NULL;
-        if (view.len > INT_MAX) {
-            PyBuffer_Release(&view);
-            PyErr_SetString(PyExc_OverflowError, "size does not fit in an int");
-            return NULL;
-        }
-        res = expat_parse(self, view.buf, (int)view.len, 0);
-        PyBuffer_Release(&view);
-        return res;
-    }
-}
-
-static PyObject*
-xmlparser_parse_whole(XMLParserObject* self, PyObject* args)
-{
-    /* (internal) parse the whole input, until end of stream */
-    PyObject* reader;
-    PyObject* buffer;
-    PyObject* temp;
-    PyObject* res;
-
-    PyObject* fileobj;
-    if (!PyArg_ParseTuple(args, "O:_parse", &fileobj))
-        return NULL;
-
-    reader = PyObject_GetAttrString(fileobj, "read");
-    if (!reader)
-        return NULL;
-
-    /* read from open file object */
-    for (;;) {
-
-        buffer = PyObject_CallFunction(reader, "i", 64*1024);
-
-        if (!buffer) {
-            /* read failed (e.g. due to KeyboardInterrupt) */
-            Py_DECREF(reader);
-            return NULL;
-        }
-
-        if (PyUnicode_CheckExact(buffer)) {
-            /* A unicode object is encoded into bytes using UTF-8 */
-            if (PyUnicode_GET_LENGTH(buffer) == 0) {
-                Py_DECREF(buffer);
-                break;
-            }
-            temp = PyUnicode_AsEncodedString(buffer, "utf-8", "surrogatepass");
-            Py_DECREF(buffer);
-            if (!temp) {
-                /* Propagate exception from PyUnicode_AsEncodedString */
-                Py_DECREF(reader);
-                return NULL;
-            }
-            buffer = temp;
-        }
-        else if (!PyBytes_CheckExact(buffer) || PyBytes_GET_SIZE(buffer) == 0) {
-            Py_DECREF(buffer);
-            break;
-        }
-
-        if (PyBytes_GET_SIZE(buffer) > INT_MAX) {
-            Py_DECREF(buffer);
-            Py_DECREF(reader);
-            PyErr_SetString(PyExc_OverflowError, "size does not fit in an int");
-            return NULL;
-        }
-        res = expat_parse(
-            self, PyBytes_AS_STRING(buffer), (int)PyBytes_GET_SIZE(buffer), 0
-            );
-
-        Py_DECREF(buffer);
-
-        if (!res) {
-            Py_DECREF(reader);
-            return NULL;
-        }
-        Py_DECREF(res);
-
-    }
-
-    Py_DECREF(reader);
-
-    res = expat_parse(self, "", 0, 1);
-
-    if (res && TreeBuilder_CheckExact(self->target)) {
-        Py_DECREF(res);
-        return treebuilder_done((TreeBuilderObject*) self->target);
-    }
-
-    return res;
-}
-
-static PyObject*
-xmlparser_doctype(XMLParserObject *self, PyObject *args)
-{
-    Py_RETURN_NONE;
-}
-
-static PyObject*
-xmlparser_setevents(XMLParserObject *self, PyObject* args)
-{
-    /* activate element event reporting */
-    Py_ssize_t i, seqlen;
-    TreeBuilderObject *target;
-
-    PyObject *events_queue;
-    PyObject *events_to_report = Py_None;
-    PyObject *events_seq;
-    if (!PyArg_ParseTuple(args, "O!|O:_setevents",  &PyList_Type, &events_queue,
-                          &events_to_report))
-        return NULL;
-
-    if (!TreeBuilder_CheckExact(self->target)) {
-        PyErr_SetString(
-            PyExc_TypeError,
-            "event handling only supported for ElementTree.TreeBuilder "
-            "targets"
-            );
-        return NULL;
-    }
-
-    target = (TreeBuilderObject*) self->target;
-
-    Py_INCREF(events_queue);
-    Py_XDECREF(target->events);
-    target->events = events_queue;
-
-    /* clear out existing events */
-    Py_CLEAR(target->start_event_obj);
-    Py_CLEAR(target->end_event_obj);
-    Py_CLEAR(target->start_ns_event_obj);
-    Py_CLEAR(target->end_ns_event_obj);
-
-    if (events_to_report == Py_None) {
-        /* default is "end" only */
-        target->end_event_obj = PyUnicode_FromString("end");
-        Py_RETURN_NONE;
-    }
-
-    if (!(events_seq = PySequence_Fast(events_to_report,
-                                       "events must be a sequence"))) {
-        return NULL;
-    }
-
-    seqlen = PySequence_Size(events_seq);
-    for (i = 0; i < seqlen; ++i) {
-        PyObject *event_name_obj = PySequence_Fast_GET_ITEM(events_seq, i);
-        char *event_name = NULL;
-        if (PyUnicode_Check(event_name_obj)) {
-            event_name = _PyUnicode_AsString(event_name_obj);
-        } else if (PyBytes_Check(event_name_obj)) {
-            event_name = PyBytes_AS_STRING(event_name_obj);
-        }
-
-        if (event_name == NULL) {
-            Py_DECREF(events_seq);
-            PyErr_Format(PyExc_ValueError, "invalid events sequence");
-            return NULL;
-        } else if (strcmp(event_name, "start") == 0) {
-            Py_INCREF(event_name_obj);
-            target->start_event_obj = event_name_obj;
-        } else if (strcmp(event_name, "end") == 0) {
-            Py_INCREF(event_name_obj);
-            Py_XDECREF(target->end_event_obj);
-            target->end_event_obj = event_name_obj;
-        } else if (strcmp(event_name, "start-ns") == 0) {
-            Py_INCREF(event_name_obj);
-            Py_XDECREF(target->start_ns_event_obj);
-            target->start_ns_event_obj = event_name_obj;
-            EXPAT(SetNamespaceDeclHandler)(
-                self->parser,
-                (XML_StartNamespaceDeclHandler) expat_start_ns_handler,
-                (XML_EndNamespaceDeclHandler) expat_end_ns_handler
-                );
-        } else if (strcmp(event_name, "end-ns") == 0) {
-            Py_INCREF(event_name_obj);
-            Py_XDECREF(target->end_ns_event_obj);
-            target->end_ns_event_obj = event_name_obj;
-            EXPAT(SetNamespaceDeclHandler)(
-                self->parser,
-                (XML_StartNamespaceDeclHandler) expat_start_ns_handler,
-                (XML_EndNamespaceDeclHandler) expat_end_ns_handler
-                );
-        } else {
-            Py_DECREF(events_seq);
-            PyErr_Format(PyExc_ValueError, "unknown event '%s'", event_name);
-            return NULL;
-        }
-    }
-
-    Py_DECREF(events_seq);
-    Py_RETURN_NONE;
-}
-
 static PyMethodDef xmlparser_methods[] = {
-    {"feed", (PyCFunction) xmlparser_feed, METH_O},
-    {"close", (PyCFunction) xmlparser_close, METH_VARARGS},
-    {"_parse_whole", (PyCFunction) xmlparser_parse_whole, METH_VARARGS},
-    {"_setevents", (PyCFunction) xmlparser_setevents, METH_VARARGS},
-    {"doctype", (PyCFunction) xmlparser_doctype, METH_VARARGS},
+    _ELEMENTTREE_XMLPARSER_FEED_METHODDEF
+    _ELEMENTTREE_XMLPARSER_CLOSE_METHODDEF
+    _ELEMENTTREE_XMLPARSER__PARSE_WHOLE_METHODDEF
+    _ELEMENTTREE_XMLPARSER__SETEVENTS_METHODDEF
+    _ELEMENTTREE_XMLPARSER_DOCTYPE_METHODDEF
     {NULL, NULL}
 };
 
-static PyObject*
-xmlparser_getattro(XMLParserObject* self, PyObject* nameobj)
-{
-    if (PyUnicode_Check(nameobj)) {
-        PyObject* res;
-        if (PyUnicode_CompareWithASCIIString(nameobj, "entity") == 0)
-            res = self->entity;
-        else if (PyUnicode_CompareWithASCIIString(nameobj, "target") == 0)
-            res = self->target;
-        else if (PyUnicode_CompareWithASCIIString(nameobj, "version") == 0) {
-            return PyUnicode_FromFormat(
-                "Expat %d.%d.%d", XML_MAJOR_VERSION,
-                XML_MINOR_VERSION, XML_MICRO_VERSION);
-        }
-        else
-            goto generic;
-
-        Py_INCREF(res);
-        return res;
-    }
-  generic:
-    return PyObject_GenericGetAttr((PyObject*) self, nameobj);
-}
-
 static PyTypeObject XMLParser_Type = {
     PyVarObject_HEAD_INIT(NULL, 0)
     "xml.etree.ElementTree.XMLParser", sizeof(XMLParserObject), 0,
@@ -3683,7 +3839,7 @@
     0,                                              /* tp_descr_get */
     0,                                              /* tp_descr_set */
     0,                                              /* tp_dictoffset */
-    (initproc)xmlparser_init,                       /* tp_init */
+    _elementtree_XMLParser___init__,                /* tp_init */
     PyType_GenericAlloc,                            /* tp_alloc */
     xmlparser_new,                                  /* tp_new */
     0,                                              /* tp_free */
diff --git a/Modules/_elementtree.c b/Modules/clinic/_elementtree.c.h
copy from Modules/_elementtree.c
copy to Modules/clinic/_elementtree.c.h
--- a/Modules/_elementtree.c
+++ b/Modules/clinic/_elementtree.c.h
@@ -1,3781 +1,666 @@
-/*--------------------------------------------------------------------
- * Licensed to PSF under a Contributor Agreement.
- * See http://www.python.org/psf/license for licensing details.
- *
- * _elementtree - C accelerator for xml.etree.ElementTree
- * Copyright (c) 1999-2009 by Secret Labs AB.  All rights reserved.
- * Copyright (c) 1999-2009 by Fredrik Lundh.
- *
- * info at pythonware.com
- * http://www.pythonware.com
- *--------------------------------------------------------------------
- */
+/*[clinic input]
+preserve
+[clinic start generated code]*/
 
-#define PY_SSIZE_T_CLEAN
+PyDoc_STRVAR(_elementtree_Element_append__doc__,
+"append($self, subelement, /)\n"
+"--\n"
+"\n");
 
-#include "Python.h"
-#include "structmember.h"
+#define _ELEMENTTREE_ELEMENT_APPEND_METHODDEF    \
+    {"append", (PyCFunction)_elementtree_Element_append, METH_O, _elementtree_Element_append__doc__},
 
-/* -------------------------------------------------------------------- */
-/* configuration */
+static PyObject *
+_elementtree_Element_append_impl(ElementObject *self, PyObject *subelement);
 
-/* An element can hold this many children without extra memory
-   allocations. */
-#define STATIC_CHILDREN 4
+static PyObject *
+_elementtree_Element_append(ElementObject *self, PyObject *arg)
+{
+    PyObject *return_value = NULL;
+    PyObject *subelement;
 
-/* For best performance, chose a value so that 80-90% of all nodes
-   have no more than the given number of children.  Set this to zero
-   to minimize the size of the element structure itself (this only
-   helps if you have lots of leaf nodes with attributes). */
+    if (!PyArg_Parse(arg, "O!:append", &Element_Type, &subelement))
+        goto exit;
+    return_value = _elementtree_Element_append_impl(self, subelement);
 
-/* Also note that pymalloc always allocates blocks in multiples of
-   eight bytes.  For the current C version of ElementTree, this means
-   that the number of children should be an even number, at least on
-   32-bit platforms. */
-
-/* -------------------------------------------------------------------- */
-
-#if 0
-static int memory = 0;
-#define ALLOC(size, comment)\
-do { memory += size; printf("%8d - %s\n", memory, comment); } while (0)
-#define RELEASE(size, comment)\
-do { memory -= size; printf("%8d - %s\n", memory, comment); } while (0)
-#else
-#define ALLOC(size, comment)
-#define RELEASE(size, comment)
-#endif
-
-/* compiler tweaks */
-#if defined(_MSC_VER)
-#define LOCAL(type) static __inline type __fastcall
-#else
-#define LOCAL(type) static type
-#endif
-
-/* macros used to store 'join' flags in string object pointers.  note
-   that all use of text and tail as object pointers must be wrapped in
-   JOIN_OBJ.  see comments in the ElementObject definition for more
-   info. */
-#define JOIN_GET(p) ((Py_uintptr_t) (p) & 1)
-#define JOIN_SET(p, flag) ((void*) ((Py_uintptr_t) (JOIN_OBJ(p)) | (flag)))
-#define JOIN_OBJ(p) ((PyObject*) ((Py_uintptr_t) (p) & ~(Py_uintptr_t)1))
-
-/* Py_CLEAR for a PyObject* that uses a join flag. Pass the pointer by
- * reference since this function sets it to NULL.
-*/
-static void _clear_joined_ptr(PyObject **p)
-{
-    if (*p) {
-        PyObject *tmp = JOIN_OBJ(*p);
-        *p = NULL;
-        Py_DECREF(tmp);
-    }
+exit:
+    return return_value;
 }
 
-/* Types defined by this extension */
-static PyTypeObject Element_Type;
-static PyTypeObject ElementIter_Type;
-static PyTypeObject TreeBuilder_Type;
-static PyTypeObject XMLParser_Type;
+PyDoc_STRVAR(_elementtree_Element_clear__doc__,
+"clear($self, /)\n"
+"--\n"
+"\n");
 
+#define _ELEMENTTREE_ELEMENT_CLEAR_METHODDEF    \
+    {"clear", (PyCFunction)_elementtree_Element_clear, METH_NOARGS, _elementtree_Element_clear__doc__},
 
-/* Per-module state; PEP 3121 */
-typedef struct {
-    PyObject *parseerror_obj;
-    PyObject *deepcopy_obj;
-    PyObject *elementpath_obj;
-} elementtreestate;
+static PyObject *
+_elementtree_Element_clear_impl(ElementObject *self);
 
-static struct PyModuleDef elementtreemodule;
+static PyObject *
+_elementtree_Element_clear(ElementObject *self, PyObject *Py_UNUSED(ignored))
+{
+    return _elementtree_Element_clear_impl(self);
+}
 
-/* Given a module object (assumed to be _elementtree), get its per-module
- * state.
- */
-#define ET_STATE(mod) ((elementtreestate *) PyModule_GetState(mod))
+PyDoc_STRVAR(_elementtree_Element___copy____doc__,
+"__copy__($self, /)\n"
+"--\n"
+"\n");
 
-/* Find the module instance imported in the currently running sub-interpreter
- * and get its state.
- */
-#define ET_STATE_GLOBAL \
-    ((elementtreestate *) PyModule_GetState(PyState_FindModule(&elementtreemodule)))
+#define _ELEMENTTREE_ELEMENT___COPY___METHODDEF    \
+    {"__copy__", (PyCFunction)_elementtree_Element___copy__, METH_NOARGS, _elementtree_Element___copy____doc__},
 
-static int
-elementtree_clear(PyObject *m)
+static PyObject *
+_elementtree_Element___copy___impl(ElementObject *self);
+
+static PyObject *
+_elementtree_Element___copy__(ElementObject *self, PyObject *Py_UNUSED(ignored))
 {
-    elementtreestate *st = ET_STATE(m);
-    Py_CLEAR(st->parseerror_obj);
-    Py_CLEAR(st->deepcopy_obj);
-    Py_CLEAR(st->elementpath_obj);
-    return 0;
+    return _elementtree_Element___copy___impl(self);
+}
+
+PyDoc_STRVAR(_elementtree_Element___deepcopy____doc__,
+"__deepcopy__($self, memo, /)\n"
+"--\n"
+"\n");
+
+#define _ELEMENTTREE_ELEMENT___DEEPCOPY___METHODDEF    \
+    {"__deepcopy__", (PyCFunction)_elementtree_Element___deepcopy__, METH_O, _elementtree_Element___deepcopy____doc__},
+
+PyDoc_STRVAR(_elementtree_Element___sizeof____doc__,
+"__sizeof__($self, /)\n"
+"--\n"
+"\n");
+
+#define _ELEMENTTREE_ELEMENT___SIZEOF___METHODDEF    \
+    {"__sizeof__", (PyCFunction)_elementtree_Element___sizeof__, METH_NOARGS, _elementtree_Element___sizeof____doc__},
+
+static Py_ssize_t
+_elementtree_Element___sizeof___impl(ElementObject *self);
+
+static PyObject *
+_elementtree_Element___sizeof__(ElementObject *self, PyObject *Py_UNUSED(ignored))
+{
+    PyObject *return_value = NULL;
+    Py_ssize_t _return_value;
+
+    _return_value = _elementtree_Element___sizeof___impl(self);
+    if ((_return_value == -1) && PyErr_Occurred())
+        goto exit;
+    return_value = PyLong_FromSsize_t(_return_value);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(_elementtree_Element___getstate____doc__,
+"__getstate__($self, /)\n"
+"--\n"
+"\n");
+
+#define _ELEMENTTREE_ELEMENT___GETSTATE___METHODDEF    \
+    {"__getstate__", (PyCFunction)_elementtree_Element___getstate__, METH_NOARGS, _elementtree_Element___getstate____doc__},
+
+static PyObject *
+_elementtree_Element___getstate___impl(ElementObject *self);
+
+static PyObject *
+_elementtree_Element___getstate__(ElementObject *self, PyObject *Py_UNUSED(ignored))
+{
+    return _elementtree_Element___getstate___impl(self);
+}
+
+PyDoc_STRVAR(_elementtree_Element___setstate____doc__,
+"__setstate__($self, state, /)\n"
+"--\n"
+"\n");
+
+#define _ELEMENTTREE_ELEMENT___SETSTATE___METHODDEF    \
+    {"__setstate__", (PyCFunction)_elementtree_Element___setstate__, METH_O, _elementtree_Element___setstate____doc__},
+
+PyDoc_STRVAR(_elementtree_Element_extend__doc__,
+"extend($self, elements, /)\n"
+"--\n"
+"\n");
+
+#define _ELEMENTTREE_ELEMENT_EXTEND_METHODDEF    \
+    {"extend", (PyCFunction)_elementtree_Element_extend, METH_O, _elementtree_Element_extend__doc__},
+
+PyDoc_STRVAR(_elementtree_Element_find__doc__,
+"find($self, /, path, namespaces=None)\n"
+"--\n"
+"\n");
+
+#define _ELEMENTTREE_ELEMENT_FIND_METHODDEF    \
+    {"find", (PyCFunction)_elementtree_Element_find, METH_VARARGS|METH_KEYWORDS, _elementtree_Element_find__doc__},
+
+static PyObject *
+_elementtree_Element_find_impl(ElementObject *self, PyObject *path,
+                               PyObject *namespaces);
+
+static PyObject *
+_elementtree_Element_find(ElementObject *self, PyObject *args, PyObject *kwargs)
+{
+    PyObject *return_value = NULL;
+    static char *_keywords[] = {"path", "namespaces", NULL};
+    PyObject *path;
+    PyObject *namespaces = Py_None;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:find", _keywords,
+        &path, &namespaces))
+        goto exit;
+    return_value = _elementtree_Element_find_impl(self, path, namespaces);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(_elementtree_Element_findtext__doc__,
+"findtext($self, /, path, default=None, namespaces=None)\n"
+"--\n"
+"\n");
+
+#define _ELEMENTTREE_ELEMENT_FINDTEXT_METHODDEF    \
+    {"findtext", (PyCFunction)_elementtree_Element_findtext, METH_VARARGS|METH_KEYWORDS, _elementtree_Element_findtext__doc__},
+
+static PyObject *
+_elementtree_Element_findtext_impl(ElementObject *self, PyObject *path,
+                                   PyObject *default_value,
+                                   PyObject *namespaces);
+
+static PyObject *
+_elementtree_Element_findtext(ElementObject *self, PyObject *args, PyObject *kwargs)
+{
+    PyObject *return_value = NULL;
+    static char *_keywords[] = {"path", "default", "namespaces", NULL};
+    PyObject *path;
+    PyObject *default_value = Py_None;
+    PyObject *namespaces = Py_None;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OO:findtext", _keywords,
+        &path, &default_value, &namespaces))
+        goto exit;
+    return_value = _elementtree_Element_findtext_impl(self, path, default_value, namespaces);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(_elementtree_Element_findall__doc__,
+"findall($self, /, path, namespaces=None)\n"
+"--\n"
+"\n");
+
+#define _ELEMENTTREE_ELEMENT_FINDALL_METHODDEF    \
+    {"findall", (PyCFunction)_elementtree_Element_findall, METH_VARARGS|METH_KEYWORDS, _elementtree_Element_findall__doc__},
+
+static PyObject *
+_elementtree_Element_findall_impl(ElementObject *self, PyObject *path,
+                                  PyObject *namespaces);
+
+static PyObject *
+_elementtree_Element_findall(ElementObject *self, PyObject *args, PyObject *kwargs)
+{
+    PyObject *return_value = NULL;
+    static char *_keywords[] = {"path", "namespaces", NULL};
+    PyObject *path;
+    PyObject *namespaces = Py_None;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:findall", _keywords,
+        &path, &namespaces))
+        goto exit;
+    return_value = _elementtree_Element_findall_impl(self, path, namespaces);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(_elementtree_Element_iterfind__doc__,
+"iterfind($self, /, path, namespaces=None)\n"
+"--\n"
+"\n");
+
+#define _ELEMENTTREE_ELEMENT_ITERFIND_METHODDEF    \
+    {"iterfind", (PyCFunction)_elementtree_Element_iterfind, METH_VARARGS|METH_KEYWORDS, _elementtree_Element_iterfind__doc__},
+
+static PyObject *
+_elementtree_Element_iterfind_impl(ElementObject *self, PyObject *path,
+                                   PyObject *namespaces);
+
+static PyObject *
+_elementtree_Element_iterfind(ElementObject *self, PyObject *args, PyObject *kwargs)
+{
+    PyObject *return_value = NULL;
+    static char *_keywords[] = {"path", "namespaces", NULL};
+    PyObject *path;
+    PyObject *namespaces = Py_None;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:iterfind", _keywords,
+        &path, &namespaces))
+        goto exit;
+    return_value = _elementtree_Element_iterfind_impl(self, path, namespaces);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(_elementtree_Element_get__doc__,
+"get($self, /, key, default=None)\n"
+"--\n"
+"\n");
+
+#define _ELEMENTTREE_ELEMENT_GET_METHODDEF    \
+    {"get", (PyCFunction)_elementtree_Element_get, METH_VARARGS|METH_KEYWORDS, _elementtree_Element_get__doc__},
+
+static PyObject *
+_elementtree_Element_get_impl(ElementObject *self, PyObject *key,
+                              PyObject *default_value);
+
+static PyObject *
+_elementtree_Element_get(ElementObject *self, PyObject *args, PyObject *kwargs)
+{
+    PyObject *return_value = NULL;
+    static char *_keywords[] = {"key", "default", NULL};
+    PyObject *key;
+    PyObject *default_value = Py_None;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get", _keywords,
+        &key, &default_value))
+        goto exit;
+    return_value = _elementtree_Element_get_impl(self, key, default_value);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(_elementtree_Element_getchildren__doc__,
+"getchildren($self, /)\n"
+"--\n"
+"\n");
+
+#define _ELEMENTTREE_ELEMENT_GETCHILDREN_METHODDEF    \
+    {"getchildren", (PyCFunction)_elementtree_Element_getchildren, METH_NOARGS, _elementtree_Element_getchildren__doc__},
+
+static PyObject *
+_elementtree_Element_getchildren_impl(ElementObject *self);
+
+static PyObject *
+_elementtree_Element_getchildren(ElementObject *self, PyObject *Py_UNUSED(ignored))
+{
+    return _elementtree_Element_getchildren_impl(self);
+}
+
+PyDoc_STRVAR(_elementtree_Element_iter__doc__,
+"iter($self, /, tag=None)\n"
+"--\n"
+"\n");
+
+#define _ELEMENTTREE_ELEMENT_ITER_METHODDEF    \
+    {"iter", (PyCFunction)_elementtree_Element_iter, METH_VARARGS|METH_KEYWORDS, _elementtree_Element_iter__doc__},
+
+static PyObject *
+_elementtree_Element_iter_impl(ElementObject *self, PyObject *tag);
+
+static PyObject *
+_elementtree_Element_iter(ElementObject *self, PyObject *args, PyObject *kwargs)
+{
+    PyObject *return_value = NULL;
+    static char *_keywords[] = {"tag", NULL};
+    PyObject *tag = Py_None;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:iter", _keywords,
+        &tag))
+        goto exit;
+    return_value = _elementtree_Element_iter_impl(self, tag);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(_elementtree_Element_itertext__doc__,
+"itertext($self, /)\n"
+"--\n"
+"\n");
+
+#define _ELEMENTTREE_ELEMENT_ITERTEXT_METHODDEF    \
+    {"itertext", (PyCFunction)_elementtree_Element_itertext, METH_NOARGS, _elementtree_Element_itertext__doc__},
+
+static PyObject *
+_elementtree_Element_itertext_impl(ElementObject *self);
+
+static PyObject *
+_elementtree_Element_itertext(ElementObject *self, PyObject *Py_UNUSED(ignored))
+{
+    return _elementtree_Element_itertext_impl(self);
+}
+
+PyDoc_STRVAR(_elementtree_Element_insert__doc__,
+"insert($self, index, subelement, /)\n"
+"--\n"
+"\n");
+
+#define _ELEMENTTREE_ELEMENT_INSERT_METHODDEF    \
+    {"insert", (PyCFunction)_elementtree_Element_insert, METH_VARARGS, _elementtree_Element_insert__doc__},
+
+static PyObject *
+_elementtree_Element_insert_impl(ElementObject *self, Py_ssize_t index,
+                                 PyObject *subelement);
+
+static PyObject *
+_elementtree_Element_insert(ElementObject *self, PyObject *args)
+{
+    PyObject *return_value = NULL;
+    Py_ssize_t index;
+    PyObject *subelement;
+
+    if (!PyArg_ParseTuple(args, "nO!:insert",
+        &index, &Element_Type, &subelement))
+        goto exit;
+    return_value = _elementtree_Element_insert_impl(self, index, subelement);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(_elementtree_Element_items__doc__,
+"items($self, /)\n"
+"--\n"
+"\n");
+
+#define _ELEMENTTREE_ELEMENT_ITEMS_METHODDEF    \
+    {"items", (PyCFunction)_elementtree_Element_items, METH_NOARGS, _elementtree_Element_items__doc__},
+
+static PyObject *
+_elementtree_Element_items_impl(ElementObject *self);
+
+static PyObject *
+_elementtree_Element_items(ElementObject *self, PyObject *Py_UNUSED(ignored))
+{
+    return _elementtree_Element_items_impl(self);
+}
+
+PyDoc_STRVAR(_elementtree_Element_keys__doc__,
+"keys($self, /)\n"
+"--\n"
+"\n");
+
+#define _ELEMENTTREE_ELEMENT_KEYS_METHODDEF    \
+    {"keys", (PyCFunction)_elementtree_Element_keys, METH_NOARGS, _elementtree_Element_keys__doc__},
+
+static PyObject *
+_elementtree_Element_keys_impl(ElementObject *self);
+
+static PyObject *
+_elementtree_Element_keys(ElementObject *self, PyObject *Py_UNUSED(ignored))
+{
+    return _elementtree_Element_keys_impl(self);
+}
+
+PyDoc_STRVAR(_elementtree_Element_makeelement__doc__,
+"makeelement($self, tag, attrib, /)\n"
+"--\n"
+"\n");
+
+#define _ELEMENTTREE_ELEMENT_MAKEELEMENT_METHODDEF    \
+    {"makeelement", (PyCFunction)_elementtree_Element_makeelement, METH_VARARGS, _elementtree_Element_makeelement__doc__},
+
+static PyObject *
+_elementtree_Element_makeelement_impl(ElementObject *self, PyObject *tag,
+                                      PyObject *attrib);
+
+static PyObject *
+_elementtree_Element_makeelement(ElementObject *self, PyObject *args)
+{
+    PyObject *return_value = NULL;
+    PyObject *tag;
+    PyObject *attrib;
+
+    if (!PyArg_UnpackTuple(args, "makeelement",
+        2, 2,
+        &tag, &attrib))
+        goto exit;
+    return_value = _elementtree_Element_makeelement_impl(self, tag, attrib);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(_elementtree_Element_remove__doc__,
+"remove($self, subelement, /)\n"
+"--\n"
+"\n");
+
+#define _ELEMENTTREE_ELEMENT_REMOVE_METHODDEF    \
+    {"remove", (PyCFunction)_elementtree_Element_remove, METH_O, _elementtree_Element_remove__doc__},
+
+static PyObject *
+_elementtree_Element_remove_impl(ElementObject *self, PyObject *subelement);
+
+static PyObject *
+_elementtree_Element_remove(ElementObject *self, PyObject *arg)
+{
+    PyObject *return_value = NULL;
+    PyObject *subelement;
+
+    if (!PyArg_Parse(arg, "O!:remove", &Element_Type, &subelement))
+        goto exit;
+    return_value = _elementtree_Element_remove_impl(self, subelement);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(_elementtree_Element_set__doc__,
+"set($self, key, value, /)\n"
+"--\n"
+"\n");
+
+#define _ELEMENTTREE_ELEMENT_SET_METHODDEF    \
+    {"set", (PyCFunction)_elementtree_Element_set, METH_VARARGS, _elementtree_Element_set__doc__},
+
+static PyObject *
+_elementtree_Element_set_impl(ElementObject *self, PyObject *key,
+                              PyObject *value);
+
+static PyObject *
+_elementtree_Element_set(ElementObject *self, PyObject *args)
+{
+    PyObject *return_value = NULL;
+    PyObject *key;
+    PyObject *value;
+
+    if (!PyArg_UnpackTuple(args, "set",
+        2, 2,
+        &key, &value))
+        goto exit;
+    return_value = _elementtree_Element_set_impl(self, key, value);
+
+exit:
+    return return_value;
 }
 
 static int
-elementtree_traverse(PyObject *m, visitproc visit, void *arg)
+_elementtree_TreeBuilder___init___impl(TreeBuilderObject *self,
+                                       PyObject *element_factory);
+
+static int
+_elementtree_TreeBuilder___init__(PyObject *self, PyObject *args, PyObject *kwargs)
 {
-    elementtreestate *st = ET_STATE(m);
-    Py_VISIT(st->parseerror_obj);
-    Py_VISIT(st->deepcopy_obj);
-    Py_VISIT(st->elementpath_obj);
-    return 0;
+    int return_value = -1;
+    static char *_keywords[] = {"element_factory", NULL};
+    PyObject *element_factory = NULL;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:TreeBuilder", _keywords,
+        &element_factory))
+        goto exit;
+    return_value = _elementtree_TreeBuilder___init___impl((TreeBuilderObject *)self, element_factory);
+
+exit:
+    return return_value;
 }
 
-static void
-elementtree_free(void *m)
+PyDoc_STRVAR(_elementtree_TreeBuilder_data__doc__,
+"data($self, data, /)\n"
+"--\n"
+"\n");
+
+#define _ELEMENTTREE_TREEBUILDER_DATA_METHODDEF    \
+    {"data", (PyCFunction)_elementtree_TreeBuilder_data, METH_O, _elementtree_TreeBuilder_data__doc__},
+
+PyDoc_STRVAR(_elementtree_TreeBuilder_end__doc__,
+"end($self, tag, /)\n"
+"--\n"
+"\n");
+
+#define _ELEMENTTREE_TREEBUILDER_END_METHODDEF    \
+    {"end", (PyCFunction)_elementtree_TreeBuilder_end, METH_O, _elementtree_TreeBuilder_end__doc__},
+
+PyDoc_STRVAR(_elementtree_TreeBuilder_close__doc__,
+"close($self, /)\n"
+"--\n"
+"\n");
+
+#define _ELEMENTTREE_TREEBUILDER_CLOSE_METHODDEF    \
+    {"close", (PyCFunction)_elementtree_TreeBuilder_close, METH_NOARGS, _elementtree_TreeBuilder_close__doc__},
+
+static PyObject *
+_elementtree_TreeBuilder_close_impl(TreeBuilderObject *self);
+
+static PyObject *
+_elementtree_TreeBuilder_close(TreeBuilderObject *self, PyObject *Py_UNUSED(ignored))
 {
-    elementtree_clear((PyObject *)m);
+    return _elementtree_TreeBuilder_close_impl(self);
 }
 
-/* helpers */
+PyDoc_STRVAR(_elementtree_TreeBuilder_start__doc__,
+"start($self, tag, attrs=None, /)\n"
+"--\n"
+"\n");
 
-LOCAL(PyObject*)
-deepcopy(PyObject* object, PyObject* memo)
-{
-    /* do a deep copy of the given object */
-    PyObject* args;
-    PyObject* result;
-    elementtreestate *st = ET_STATE_GLOBAL;
-
-    if (!st->deepcopy_obj) {
-        PyErr_SetString(
-            PyExc_RuntimeError,
-            "deepcopy helper not found"
-            );
-        return NULL;
-    }
-
-    args = PyTuple_Pack(2, object, memo);
-    if (!args)
-        return NULL;
-    result = PyObject_CallObject(st->deepcopy_obj, args);
-    Py_DECREF(args);
-    return result;
-}
-
-LOCAL(PyObject*)
-list_join(PyObject* list)
-{
-    /* join list elements (destroying the list in the process) */
-    PyObject* joiner;
-    PyObject* result;
-
-    joiner = PyUnicode_FromStringAndSize("", 0);
-    if (!joiner)
-        return NULL;
-    result = PyUnicode_Join(joiner, list);
-    Py_DECREF(joiner);
-    if (result)
-        Py_DECREF(list);
-    return result;
-}
-
-/* Is the given object an empty dictionary?
-*/
-static int
-is_empty_dict(PyObject *obj)
-{
-    return PyDict_CheckExact(obj) && PyDict_Size(obj) == 0;
-}
-
-
-/* -------------------------------------------------------------------- */
-/* the Element type */
-
-typedef struct {
-
-    /* attributes (a dictionary object), or None if no attributes */
-    PyObject* attrib;
-
-    /* child elements */
-    Py_ssize_t length; /* actual number of items */
-    Py_ssize_t allocated; /* allocated items */
-
-    /* this either points to _children or to a malloced buffer */
-    PyObject* *children;
-
-    PyObject* _children[STATIC_CHILDREN];
-
-} ElementObjectExtra;
-
-typedef struct {
-    PyObject_HEAD
-
-    /* element tag (a string). */
-    PyObject* tag;
-
-    /* text before first child.  note that this is a tagged pointer;
-       use JOIN_OBJ to get the object pointer.  the join flag is used
-       to distinguish lists created by the tree builder from lists
-       assigned to the attribute by application code; the former
-       should be joined before being returned to the user, the latter
-       should be left intact. */
-    PyObject* text;
-
-    /* text after this element, in parent.  note that this is a tagged
-       pointer; use JOIN_OBJ to get the object pointer. */
-    PyObject* tail;
-
-    ElementObjectExtra* extra;
-
-    PyObject *weakreflist; /* For tp_weaklistoffset */
-
-} ElementObject;
-
-
-#define Element_CheckExact(op) (Py_TYPE(op) == &Element_Type)
-
-/* -------------------------------------------------------------------- */
-/* Element constructors and destructor */
-
-LOCAL(int)
-create_extra(ElementObject* self, PyObject* attrib)
-{
-    self->extra = PyObject_Malloc(sizeof(ElementObjectExtra));
-    if (!self->extra) {
-        PyErr_NoMemory();
-        return -1;
-    }
-
-    if (!attrib)
-        attrib = Py_None;
-
-    Py_INCREF(attrib);
-    self->extra->attrib = attrib;
-
-    self->extra->length = 0;
-    self->extra->allocated = STATIC_CHILDREN;
-    self->extra->children = self->extra->_children;
-
-    return 0;
-}
-
-LOCAL(void)
-dealloc_extra(ElementObject* self)
-{
-    ElementObjectExtra *myextra;
-    Py_ssize_t i;
-
-    if (!self->extra)
-        return;
-
-    /* Avoid DECREFs calling into this code again (cycles, etc.)
-    */
-    myextra = self->extra;
-    self->extra = NULL;
-
-    Py_DECREF(myextra->attrib);
-
-    for (i = 0; i < myextra->length; i++)
-        Py_DECREF(myextra->children[i]);
-
-    if (myextra->children != myextra->_children)
-        PyObject_Free(myextra->children);
-
-    PyObject_Free(myextra);
-}
-
-/* Convenience internal function to create new Element objects with the given
- * tag and attributes.
-*/
-LOCAL(PyObject*)
-create_new_element(PyObject* tag, PyObject* attrib)
-{
-    ElementObject* self;
-
-    self = PyObject_GC_New(ElementObject, &Element_Type);
-    if (self == NULL)
-        return NULL;
-    self->extra = NULL;
-
-    Py_INCREF(tag);
-    self->tag = tag;
-
-    Py_INCREF(Py_None);
-    self->text = Py_None;
-
-    Py_INCREF(Py_None);
-    self->tail = Py_None;
-
-    self->weakreflist = NULL;
-
-    ALLOC(sizeof(ElementObject), "create element");
-    PyObject_GC_Track(self);
-
-    if (attrib != Py_None && !is_empty_dict(attrib)) {
-        if (create_extra(self, attrib) < 0) {
-            Py_DECREF(self);
-            return NULL;
-        }
-    }
-
-    return (PyObject*) self;
-}
+#define _ELEMENTTREE_TREEBUILDER_START_METHODDEF    \
+    {"start", (PyCFunction)_elementtree_TreeBuilder_start, METH_VARARGS, _elementtree_TreeBuilder_start__doc__},
 
 static PyObject *
-element_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+_elementtree_TreeBuilder_start_impl(TreeBuilderObject *self, PyObject *tag,
+                                    PyObject *attrs);
+
+static PyObject *
+_elementtree_TreeBuilder_start(TreeBuilderObject *self, PyObject *args)
 {
-    ElementObject *e = (ElementObject *)type->tp_alloc(type, 0);
-    if (e != NULL) {
-        Py_INCREF(Py_None);
-        e->tag = Py_None;
+    PyObject *return_value = NULL;
+    PyObject *tag;
+    PyObject *attrs = Py_None;
 
-        Py_INCREF(Py_None);
-        e->text = Py_None;
+    if (!PyArg_UnpackTuple(args, "start",
+        1, 2,
+        &tag, &attrs))
+        goto exit;
+    return_value = _elementtree_TreeBuilder_start_impl(self, tag, attrs);
 
-        Py_INCREF(Py_None);
-        e->tail = Py_None;
-
-        e->extra = NULL;
-        e->weakreflist = NULL;
-    }
-    return (PyObject *)e;
-}
-
-/* Helper function for extracting the attrib dictionary from a keywords dict.
- * This is required by some constructors/functions in this module that can
- * either accept attrib as a keyword argument or all attributes splashed
- * directly into *kwds.
- *
- * Return a dictionary with the content of kwds merged into the content of
- * attrib. If there is no attrib keyword, return a copy of kwds.
- */
-static PyObject*
-get_attrib_from_keywords(PyObject *kwds)
-{
-    PyObject *attrib_str = PyUnicode_FromString("attrib");
-    PyObject *attrib = PyDict_GetItem(kwds, attrib_str);
-
-    if (attrib) {
-        /* If attrib was found in kwds, copy its value and remove it from
-         * kwds
-         */
-        if (!PyDict_Check(attrib)) {
-            Py_DECREF(attrib_str);
-            PyErr_Format(PyExc_TypeError, "attrib must be dict, not %.100s",
-                         Py_TYPE(attrib)->tp_name);
-            return NULL;
-        }
-        attrib = PyDict_Copy(attrib);
-        PyDict_DelItem(kwds, attrib_str);
-    } else {
-        attrib = PyDict_New();
-    }
-
-    Py_DECREF(attrib_str);
-
-    /* attrib can be NULL if PyDict_New failed */
-    if (attrib)
-        if (PyDict_Update(attrib, kwds) < 0)
-            return NULL;
-    return attrib;
+exit:
+    return return_value;
 }
 
 static int
-element_init(PyObject *self, PyObject *args, PyObject *kwds)
+_elementtree_XMLParser___init___impl(XMLParserObject *self, PyObject *html,
+                                     PyObject *target, const char *encoding);
+
+static int
+_elementtree_XMLParser___init__(PyObject *self, PyObject *args, PyObject *kwargs)
 {
-    PyObject *tag;
-    PyObject *tmp;
-    PyObject *attrib = NULL;
-    ElementObject *self_elem;
+    int return_value = -1;
+    static char *_keywords[] = {"html", "target", "encoding", NULL};
+    PyObject *html = NULL;
+    PyObject *target = NULL;
+    const char *encoding = NULL;
 
-    if (!PyArg_ParseTuple(args, "O|O!:Element", &tag, &PyDict_Type, &attrib))
-        return -1;
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOz:XMLParser", _keywords,
+        &html, &target, &encoding))
+        goto exit;
+    return_value = _elementtree_XMLParser___init___impl((XMLParserObject *)self, html, target, encoding);
 
-    if (attrib) {
-        /* attrib passed as positional arg */
-        attrib = PyDict_Copy(attrib);
-        if (!attrib)
-            return -1;
-        if (kwds) {
-            if (PyDict_Update(attrib, kwds) < 0) {
-                Py_DECREF(attrib);
-                return -1;
-            }
-        }
-    } else if (kwds) {
-        /* have keywords args */
-        attrib = get_attrib_from_keywords(kwds);
-        if (!attrib)
-            return -1;
-    }
-
-    self_elem = (ElementObject *)self;
-
-    if (attrib != NULL && !is_empty_dict(attrib)) {
-        if (create_extra(self_elem, attrib) < 0) {
-            Py_DECREF(attrib);
-            return -1;
-        }
-    }
-
-    /* We own a reference to attrib here and it's no longer needed. */
-    Py_XDECREF(attrib);
-
-    /* Replace the objects already pointed to by tag, text and tail. */
-    tmp = self_elem->tag;
-    Py_INCREF(tag);
-    self_elem->tag = tag;
-    Py_DECREF(tmp);
-
-    tmp = self_elem->text;
-    Py_INCREF(Py_None);
-    self_elem->text = Py_None;
-    Py_DECREF(JOIN_OBJ(tmp));
-
-    tmp = self_elem->tail;
-    Py_INCREF(Py_None);
-    self_elem->tail = Py_None;
-    Py_DECREF(JOIN_OBJ(tmp));
-
-    return 0;
+exit:
+    return return_value;
 }
 
-LOCAL(int)
-element_resize(ElementObject* self, Py_ssize_t extra)
+PyDoc_STRVAR(_elementtree_XMLParser_close__doc__,
+"close($self, /)\n"
+"--\n"
+"\n");
+
+#define _ELEMENTTREE_XMLPARSER_CLOSE_METHODDEF    \
+    {"close", (PyCFunction)_elementtree_XMLParser_close, METH_NOARGS, _elementtree_XMLParser_close__doc__},
+
+static PyObject *
+_elementtree_XMLParser_close_impl(XMLParserObject *self);
+
+static PyObject *
+_elementtree_XMLParser_close(XMLParserObject *self, PyObject *Py_UNUSED(ignored))
 {
-    Py_ssize_t size;
-    PyObject* *children;
-
-    /* make sure self->children can hold the given number of extra
-       elements.  set an exception and return -1 if allocation failed */
-
-    if (!self->extra) {
-        if (create_extra(self, NULL) < 0)
-            return -1;
-    }
-
-    size = self->extra->length + extra;  /* never overflows */
-
-    if (size > self->extra->allocated) {
-        /* use Python 2.4's list growth strategy */
-        size = (size >> 3) + (size < 9 ? 3 : 6) + size;
-        /* Coverity CID #182 size_error: Allocating 1 bytes to pointer "children"
-         * which needs at least 4 bytes.
-         * Although it's a false alarm always assume at least one child to
-         * be safe.
-         */
-        size = size ? size : 1;
-        if ((size_t)size > PY_SSIZE_T_MAX/sizeof(PyObject*))
-            goto nomemory;
-        if (self->extra->children != self->extra->_children) {
-            /* Coverity CID #182 size_error: Allocating 1 bytes to pointer
-             * "children", which needs at least 4 bytes. Although it's a
-             * false alarm always assume at least one child to be safe.
-             */
-            children = PyObject_Realloc(self->extra->children,
-                                        size * sizeof(PyObject*));
-            if (!children)
-                goto nomemory;
-        } else {
-            children = PyObject_Malloc(size * sizeof(PyObject*));
-            if (!children)
-                goto nomemory;
-            /* copy existing children from static area to malloc buffer */
-            memcpy(children, self->extra->children,
-                   self->extra->length * sizeof(PyObject*));
-        }
-        self->extra->children = children;
-        self->extra->allocated = size;
-    }
-
-    return 0;
-
-  nomemory:
-    PyErr_NoMemory();
-    return -1;
+    return _elementtree_XMLParser_close_impl(self);
 }
 
-LOCAL(int)
-element_add_subelement(ElementObject* self, PyObject* element)
+PyDoc_STRVAR(_elementtree_XMLParser_feed__doc__,
+"feed($self, data, /)\n"
+"--\n"
+"\n");
+
+#define _ELEMENTTREE_XMLPARSER_FEED_METHODDEF    \
+    {"feed", (PyCFunction)_elementtree_XMLParser_feed, METH_O, _elementtree_XMLParser_feed__doc__},
+
+PyDoc_STRVAR(_elementtree_XMLParser__parse_whole__doc__,
+"_parse_whole($self, file, /)\n"
+"--\n"
+"\n");
+
+#define _ELEMENTTREE_XMLPARSER__PARSE_WHOLE_METHODDEF    \
+    {"_parse_whole", (PyCFunction)_elementtree_XMLParser__parse_whole, METH_O, _elementtree_XMLParser__parse_whole__doc__},
+
+PyDoc_STRVAR(_elementtree_XMLParser_doctype__doc__,
+"doctype($self, /)\n"
+"--\n"
+"\n");
+
+#define _ELEMENTTREE_XMLPARSER_DOCTYPE_METHODDEF    \
+    {"doctype", (PyCFunction)_elementtree_XMLParser_doctype, METH_NOARGS, _elementtree_XMLParser_doctype__doc__},
+
+static PyObject *
+_elementtree_XMLParser_doctype_impl(XMLParserObject *self);
+
+static PyObject *
+_elementtree_XMLParser_doctype(XMLParserObject *self, PyObject *Py_UNUSED(ignored))
 {
-    /* add a child element to a parent */
-
-    if (element_resize(self, 1) < 0)
-        return -1;
-
-    Py_INCREF(element);
-    self->extra->children[self->extra->length] = element;
-
-    self->extra->length++;
-
-    return 0;
+    return _elementtree_XMLParser_doctype_impl(self);
 }
 
-LOCAL(PyObject*)
-element_get_attrib(ElementObject* self)
-{
-    /* return borrowed reference to attrib dictionary */
-    /* note: this function assumes that the extra section exists */
+PyDoc_STRVAR(_elementtree_XMLParser__setevents__doc__,
+"_setevents($self, events_queue, events_to_report=None, /)\n"
+"--\n"
+"\n");
 
-    PyObject* res = self->extra->attrib;
-
-    if (res == Py_None) {
-        /* create missing dictionary */
-        res = PyDict_New();
-        if (!res)
-            return NULL;
-        Py_DECREF(Py_None);
-        self->extra->attrib = res;
-    }
-
-    return res;
-}
-
-LOCAL(PyObject*)
-element_get_text(ElementObject* self)
-{
-    /* return borrowed reference to text attribute */
-
-    PyObject* res = self->text;
-
-    if (JOIN_GET(res)) {
-        res = JOIN_OBJ(res);
-        if (PyList_CheckExact(res)) {
-            res = list_join(res);
-            if (!res)
-                return NULL;
-            self->text = res;
-        }
-    }
-
-    return res;
-}
-
-LOCAL(PyObject*)
-element_get_tail(ElementObject* self)
-{
-    /* return borrowed reference to text attribute */
-
-    PyObject* res = self->tail;
-
-    if (JOIN_GET(res)) {
-        res = JOIN_OBJ(res);
-        if (PyList_CheckExact(res)) {
-            res = list_join(res);
-            if (!res)
-                return NULL;
-            self->tail = res;
-        }
-    }
-
-    return res;
-}
-
-static PyObject*
-subelement(PyObject *self, PyObject *args, PyObject *kwds)
-{
-    PyObject* elem;
-
-    ElementObject* parent;
-    PyObject* tag;
-    PyObject* attrib = NULL;
-    if (!PyArg_ParseTuple(args, "O!O|O!:SubElement",
-                          &Element_Type, &parent, &tag,
-                          &PyDict_Type, &attrib)) {
-        return NULL;
-    }
-
-    if (attrib) {
-        /* attrib passed as positional arg */
-        attrib = PyDict_Copy(attrib);
-        if (!attrib)
-            return NULL;
-        if (kwds) {
-            if (PyDict_Update(attrib, kwds) < 0) {
-                return NULL;
-            }
-        }
-    } else if (kwds) {
-        /* have keyword args */
-        attrib = get_attrib_from_keywords(kwds);
-        if (!attrib)
-            return NULL;
-    } else {
-        /* no attrib arg, no kwds, so no attribute */
-        Py_INCREF(Py_None);
-        attrib = Py_None;
-    }
-
-    elem = create_new_element(tag, attrib);
-    Py_DECREF(attrib);
-    if (elem == NULL)
-        return NULL;
-
-    if (element_add_subelement(parent, elem) < 0) {
-        Py_DECREF(elem);
-        return NULL;
-    }
-
-    return elem;
-}
-
-static int
-element_gc_traverse(ElementObject *self, visitproc visit, void *arg)
-{
-    Py_VISIT(self->tag);
-    Py_VISIT(JOIN_OBJ(self->text));
-    Py_VISIT(JOIN_OBJ(self->tail));
-
-    if (self->extra) {
-        Py_ssize_t i;
-        Py_VISIT(self->extra->attrib);
-
-        for (i = 0; i < self->extra->length; ++i)
-            Py_VISIT(self->extra->children[i]);
-    }
-    return 0;
-}
-
-static int
-element_gc_clear(ElementObject *self)
-{
-    Py_CLEAR(self->tag);
-    _clear_joined_ptr(&self->text);
-    _clear_joined_ptr(&self->tail);
-
-    /* After dropping all references from extra, it's no longer valid anyway,
-     * so fully deallocate it.
-    */
-    dealloc_extra(self);
-    return 0;
-}
-
-static void
-element_dealloc(ElementObject* self)
-{
-    PyObject_GC_UnTrack(self);
-
-    if (self->weakreflist != NULL)
-        PyObject_ClearWeakRefs((PyObject *) self);
-
-    /* element_gc_clear clears all references and deallocates extra
-    */
-    element_gc_clear(self);
-
-    RELEASE(sizeof(ElementObject), "destroy element");
-    Py_TYPE(self)->tp_free((PyObject *)self);
-}
-
-/* -------------------------------------------------------------------- */
-
-static PyObject*
-element_append(ElementObject* self, PyObject* args)
-{
-    PyObject* element;
-    if (!PyArg_ParseTuple(args, "O!:append", &Element_Type, &element))
-        return NULL;
-
-    if (element_add_subelement(self, element) < 0)
-        return NULL;
-
-    Py_RETURN_NONE;
-}
-
-static PyObject*
-element_clearmethod(ElementObject* self, PyObject* args)
-{
-    if (!PyArg_ParseTuple(args, ":clear"))
-        return NULL;
-
-    dealloc_extra(self);
-
-    Py_INCREF(Py_None);
-    Py_DECREF(JOIN_OBJ(self->text));
-    self->text = Py_None;
-
-    Py_INCREF(Py_None);
-    Py_DECREF(JOIN_OBJ(self->tail));
-    self->tail = Py_None;
-
-    Py_RETURN_NONE;
-}
-
-static PyObject*
-element_copy(ElementObject* self, PyObject* args)
-{
-    Py_ssize_t i;
-    ElementObject* element;
-
-    if (!PyArg_ParseTuple(args, ":__copy__"))
-        return NULL;
-
-    element = (ElementObject*) create_new_element(
-        self->tag, (self->extra) ? self->extra->attrib : Py_None);
-    if (!element)
-        return NULL;
-
-    Py_DECREF(JOIN_OBJ(element->text));
-    element->text = self->text;
-    Py_INCREF(JOIN_OBJ(element->text));
-
-    Py_DECREF(JOIN_OBJ(element->tail));
-    element->tail = self->tail;
-    Py_INCREF(JOIN_OBJ(element->tail));
-
-    if (self->extra) {
-        if (element_resize(element, self->extra->length) < 0) {
-            Py_DECREF(element);
-            return NULL;
-        }
-
-        for (i = 0; i < self->extra->length; i++) {
-            Py_INCREF(self->extra->children[i]);
-            element->extra->children[i] = self->extra->children[i];
-        }
-
-        element->extra->length = self->extra->length;
-    }
-
-    return (PyObject*) element;
-}
-
-static PyObject*
-element_deepcopy(ElementObject* self, PyObject* args)
-{
-    Py_ssize_t i;
-    ElementObject* element;
-    PyObject* tag;
-    PyObject* attrib;
-    PyObject* text;
-    PyObject* tail;
-    PyObject* id;
-
-    PyObject* memo;
-    if (!PyArg_ParseTuple(args, "O:__deepcopy__", &memo))
-        return NULL;
-
-    tag = deepcopy(self->tag, memo);
-    if (!tag)
-        return NULL;
-
-    if (self->extra) {
-        attrib = deepcopy(self->extra->attrib, memo);
-        if (!attrib) {
-            Py_DECREF(tag);
-            return NULL;
-        }
-    } else {
-        Py_INCREF(Py_None);
-        attrib = Py_None;
-    }
-
-    element = (ElementObject*) create_new_element(tag, attrib);
-
-    Py_DECREF(tag);
-    Py_DECREF(attrib);
-
-    if (!element)
-        return NULL;
-
-    text = deepcopy(JOIN_OBJ(self->text), memo);
-    if (!text)
-        goto error;
-    Py_DECREF(element->text);
-    element->text = JOIN_SET(text, JOIN_GET(self->text));
-
-    tail = deepcopy(JOIN_OBJ(self->tail), memo);
-    if (!tail)
-        goto error;
-    Py_DECREF(element->tail);
-    element->tail = JOIN_SET(tail, JOIN_GET(self->tail));
-
-    if (self->extra) {
-        if (element_resize(element, self->extra->length) < 0)
-            goto error;
-
-        for (i = 0; i < self->extra->length; i++) {
-            PyObject* child = deepcopy(self->extra->children[i], memo);
-            if (!child) {
-                element->extra->length = i;
-                goto error;
-            }
-            element->extra->children[i] = child;
-        }
-
-        element->extra->length = self->extra->length;
-    }
-
-    /* add object to memo dictionary (so deepcopy won't visit it again) */
-    id = PyLong_FromSsize_t((Py_uintptr_t) self);
-    if (!id)
-        goto error;
-
-    i = PyDict_SetItem(memo, id, (PyObject*) element);
-
-    Py_DECREF(id);
-
-    if (i < 0)
-        goto error;
-
-    return (PyObject*) element;
-
-  error:
-    Py_DECREF(element);
-    return NULL;
-}
-
-static PyObject*
-element_sizeof(PyObject* myself, PyObject* args)
-{
-    ElementObject *self = (ElementObject*)myself;
-    Py_ssize_t result = sizeof(ElementObject);
-    if (self->extra) {
-        result += sizeof(ElementObjectExtra);
-        if (self->extra->children != self->extra->_children)
-            result += sizeof(PyObject*) * self->extra->allocated;
-    }
-    return PyLong_FromSsize_t(result);
-}
-
-/* dict keys for getstate/setstate. */
-#define PICKLED_TAG "tag"
-#define PICKLED_CHILDREN "_children"
-#define PICKLED_ATTRIB "attrib"
-#define PICKLED_TAIL "tail"
-#define PICKLED_TEXT "text"
-
-/* __getstate__ returns a fabricated instance dict as in the pure-Python
- * Element implementation, for interoperability/interchangeability.  This
- * makes the pure-Python implementation details an API, but (a) there aren't
- * any unnecessary structures there; and (b) it buys compatibility with 3.2
- * pickles.  See issue #16076.
- */
-static PyObject *
-element_getstate(ElementObject *self)
-{
-    Py_ssize_t i, noattrib;
-    PyObject *instancedict = NULL, *children;
-
-    /* Build a list of children. */
-    children = PyList_New(self->extra ? self->extra->length : 0);
-    if (!children)
-        return NULL;
-    for (i = 0; i < PyList_GET_SIZE(children); i++) {
-        PyObject *child = self->extra->children[i];
-        Py_INCREF(child);
-        PyList_SET_ITEM(children, i, child);
-    }
-
-    /* Construct the state object. */
-    noattrib = (self->extra == NULL || self->extra->attrib == Py_None);
-    if (noattrib)
-        instancedict = Py_BuildValue("{sOsOs{}sOsO}",
-                                     PICKLED_TAG, self->tag,
-                                     PICKLED_CHILDREN, children,
-                                     PICKLED_ATTRIB,
-                                     PICKLED_TEXT, JOIN_OBJ(self->text),
-                                     PICKLED_TAIL, JOIN_OBJ(self->tail));
-    else
-        instancedict = Py_BuildValue("{sOsOsOsOsO}",
-                                     PICKLED_TAG, self->tag,
-                                     PICKLED_CHILDREN, children,
-                                     PICKLED_ATTRIB, self->extra->attrib,
-                                     PICKLED_TEXT, JOIN_OBJ(self->text),
-                                     PICKLED_TAIL, JOIN_OBJ(self->tail));
-    if (instancedict) {
-        Py_DECREF(children);
-        return instancedict;
-    }
-    else {
-        for (i = 0; i < PyList_GET_SIZE(children); i++)
-            Py_DECREF(PyList_GET_ITEM(children, i));
-        Py_DECREF(children);
-
-        return NULL;
-    }
-}
+#define _ELEMENTTREE_XMLPARSER__SETEVENTS_METHODDEF    \
+    {"_setevents", (PyCFunction)_elementtree_XMLParser__setevents, METH_VARARGS, _elementtree_XMLParser__setevents__doc__},
 
 static PyObject *
-element_setstate_from_attributes(ElementObject *self,
-                                 PyObject *tag,
-                                 PyObject *attrib,
-                                 PyObject *text,
-                                 PyObject *tail,
-                                 PyObject *children)
-{
-    Py_ssize_t i, nchildren;
-
-    if (!tag) {
-        PyErr_SetString(PyExc_TypeError, "tag may not be NULL");
-        return NULL;
-    }
-
-    Py_CLEAR(self->tag);
-    self->tag = tag;
-    Py_INCREF(self->tag);
-
-    _clear_joined_ptr(&self->text);
-    self->text = text ? JOIN_SET(text, PyList_CheckExact(text)) : Py_None;
-    Py_INCREF(JOIN_OBJ(self->text));
-
-    _clear_joined_ptr(&self->tail);
-    self->tail = tail ? JOIN_SET(tail, PyList_CheckExact(tail)) : Py_None;
-    Py_INCREF(JOIN_OBJ(self->tail));
-
-    /* Handle ATTRIB and CHILDREN. */
-    if (!children && !attrib)
-        Py_RETURN_NONE;
-
-    /* Compute 'nchildren'. */
-    if (children) {
-        if (!PyList_Check(children)) {
-            PyErr_SetString(PyExc_TypeError, "'_children' is not a list");
-            return NULL;
-        }
-        nchildren = PyList_Size(children);
-    }
-    else {
-        nchildren = 0;
-    }
-
-    /* Allocate 'extra'. */
-    if (element_resize(self, nchildren)) {
-        return NULL;
-    }
-    assert(self->extra && self->extra->allocated >= nchildren);
-
-    /* Copy children */
-    for (i = 0; i < nchildren; i++) {
-        self->extra->children[i] = PyList_GET_ITEM(children, i);
-        Py_INCREF(self->extra->children[i]);
-    }
-
-    self->extra->length = nchildren;
-    self->extra->allocated = nchildren;
-
-    /* Stash attrib. */
-    if (attrib) {
-        Py_CLEAR(self->extra->attrib);
-        self->extra->attrib = attrib;
-        Py_INCREF(attrib);
-    }
-
-    Py_RETURN_NONE;
-}
-
-/* __setstate__ for Element instance from the Python implementation.
- * 'state' should be the instance dict.
- */
-static PyObject *
-element_setstate_from_Python(ElementObject *self, PyObject *state)
-{
-    static char *kwlist[] = {PICKLED_TAG, PICKLED_ATTRIB, PICKLED_TEXT,
-                             PICKLED_TAIL, PICKLED_CHILDREN, 0};
-    PyObject *args;
-    PyObject *tag, *attrib, *text, *tail, *children;
-    PyObject *retval;
-
-    tag = attrib = text = tail = children = NULL;
-    args = PyTuple_New(0);
-    if (!args)
-        return NULL;
-
-    if (PyArg_ParseTupleAndKeywords(args, state, "|$OOOOO", kwlist, &tag,
-                                    &attrib, &text, &tail, &children))
-        retval = element_setstate_from_attributes(self, tag, attrib, text,
-                                                  tail, children);
-    else
-        retval = NULL;
-
-    Py_DECREF(args);
-    return retval;
-}
+_elementtree_XMLParser__setevents_impl(XMLParserObject *self,
+                                       PyObject *events_queue,
+                                       PyObject *events_to_report);
 
 static PyObject *
-element_setstate(ElementObject *self, PyObject *state)
+_elementtree_XMLParser__setevents(XMLParserObject *self, PyObject *args)
 {
-    if (!PyDict_CheckExact(state)) {
-        PyErr_Format(PyExc_TypeError,
-                     "Don't know how to unpickle \"%.200R\" as an Element",
-                     state);
-        return NULL;
-    }
-    else
-        return element_setstate_from_Python(self, state);
-}
-
-LOCAL(int)
-checkpath(PyObject* tag)
-{
-    Py_ssize_t i;
-    int check = 1;
-
-    /* check if a tag contains an xpath character */
-
-#define PATHCHAR(ch) \
-    (ch == '/' || ch == '*' || ch == '[' || ch == '@' || ch == '.')
-
-    if (PyUnicode_Check(tag)) {
-        const Py_ssize_t len = PyUnicode_GET_LENGTH(tag);
-        void *data = PyUnicode_DATA(tag);
-        unsigned int kind = PyUnicode_KIND(tag);
-        for (i = 0; i < len; i++) {
-            Py_UCS4 ch = PyUnicode_READ(kind, data, i);
-            if (ch == '{')
-                check = 0;
-            else if (ch == '}')
-                check = 1;
-            else if (check && PATHCHAR(ch))
-                return 1;
-        }
-        return 0;
-    }
-    if (PyBytes_Check(tag)) {
-        char *p = PyBytes_AS_STRING(tag);
-        for (i = 0; i < PyBytes_GET_SIZE(tag); i++) {
-            if (p[i] == '{')
-                check = 0;
-            else if (p[i] == '}')
-                check = 1;
-            else if (check && PATHCHAR(p[i]))
-                return 1;
-        }
-        return 0;
-    }
-
-    return 1; /* unknown type; might be path expression */
-}
-
-static PyObject*
-element_extend(ElementObject* self, PyObject* args)
-{
-    PyObject* seq;
-    Py_ssize_t i, seqlen = 0;
-
-    PyObject* seq_in;
-    if (!PyArg_ParseTuple(args, "O:extend", &seq_in))
-        return NULL;
-
-    seq = PySequence_Fast(seq_in, "");
-    if (!seq) {
-        PyErr_Format(
-            PyExc_TypeError,
-            "expected sequence, not \"%.200s\"", Py_TYPE(seq_in)->tp_name
-            );
-        return NULL;
-    }
-
-    seqlen = PySequence_Size(seq);
-    for (i = 0; i < seqlen; i++) {
-        PyObject* element = PySequence_Fast_GET_ITEM(seq, i);
-        if (!PyObject_IsInstance(element, (PyObject *)&Element_Type)) {
-            Py_DECREF(seq);
-            PyErr_Format(
-                PyExc_TypeError,
-                "expected an Element, not \"%.200s\"",
-                Py_TYPE(element)->tp_name);
-            return NULL;
-        }
-
-        if (element_add_subelement(self, element) < 0) {
-            Py_DECREF(seq);
-            return NULL;
-        }
-    }
-
-    Py_DECREF(seq);
-
-    Py_RETURN_NONE;
-}
-
-static PyObject*
-element_find(ElementObject *self, PyObject *args, PyObject *kwds)
-{
-    Py_ssize_t i;
-    PyObject* tag;
-    PyObject* namespaces = Py_None;
-    static char *kwlist[] = {"path", "namespaces", 0};
-    elementtreestate *st = ET_STATE_GLOBAL;
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:find", kwlist,
-                                     &tag, &namespaces))
-        return NULL;
-
-    if (checkpath(tag) || namespaces != Py_None) {
-        _Py_IDENTIFIER(find);
-        return _PyObject_CallMethodId(
-            st->elementpath_obj, &PyId_find, "OOO", self, tag, namespaces
-            );
-    }
-
-    if (!self->extra)
-        Py_RETURN_NONE;
-
-    for (i = 0; i < self->extra->length; i++) {
-        PyObject* item = self->extra->children[i];
-        if (Element_CheckExact(item) &&
-            PyObject_RichCompareBool(((ElementObject*)item)->tag, tag, Py_EQ) == 1) {
-            Py_INCREF(item);
-            return item;
-        }
-    }
-
-    Py_RETURN_NONE;
-}
-
-static PyObject*
-element_findtext(ElementObject *self, PyObject *args, PyObject *kwds)
-{
-    Py_ssize_t i;
-    PyObject* tag;
-    PyObject* default_value = Py_None;
-    PyObject* namespaces = Py_None;
-    _Py_IDENTIFIER(findtext);
-    static char *kwlist[] = {"path", "default", "namespaces", 0};
-    elementtreestate *st = ET_STATE_GLOBAL;
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OO:findtext", kwlist,
-                                     &tag, &default_value, &namespaces))
-        return NULL;
-
-    if (checkpath(tag) || namespaces != Py_None)
-        return _PyObject_CallMethodId(
-            st->elementpath_obj, &PyId_findtext, "OOOO", self, tag, default_value, namespaces
-            );
-
-    if (!self->extra) {
-        Py_INCREF(default_value);
-        return default_value;
-    }
-
-    for (i = 0; i < self->extra->length; i++) {
-        ElementObject* item = (ElementObject*) self->extra->children[i];
-        if (Element_CheckExact(item) &&
-            (PyObject_RichCompareBool(item->tag, tag, Py_EQ) == 1)) {
-            PyObject* text = element_get_text(item);
-            if (text == Py_None)
-                return PyUnicode_New(0, 0);
-            Py_XINCREF(text);
-            return text;
-        }
-    }
-
-    Py_INCREF(default_value);
-    return default_value;
-}
-
-static PyObject*
-element_findall(ElementObject *self, PyObject *args, PyObject *kwds)
-{
-    Py_ssize_t i;
-    PyObject* out;
-    PyObject* tag;
-    PyObject* namespaces = Py_None;
-    static char *kwlist[] = {"path", "namespaces", 0};
-    elementtreestate *st = ET_STATE_GLOBAL;
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:findall", kwlist,
-                                     &tag, &namespaces))
-        return NULL;
-
-    if (checkpath(tag) || namespaces != Py_None) {
-        _Py_IDENTIFIER(findall);
-        return _PyObject_CallMethodId(
-            st->elementpath_obj, &PyId_findall, "OOO", self, tag, namespaces
-            );
-    }
-
-    out = PyList_New(0);
-    if (!out)
-        return NULL;
-
-    if (!self->extra)
-        return out;
-
-    for (i = 0; i < self->extra->length; i++) {
-        PyObject* item = self->extra->children[i];
-        if (Element_CheckExact(item) &&
-            PyObject_RichCompareBool(((ElementObject*)item)->tag, tag, Py_EQ) == 1) {
-            if (PyList_Append(out, item) < 0) {
-                Py_DECREF(out);
-                return NULL;
-            }
-        }
-    }
-
-    return out;
-}
-
-static PyObject*
-element_iterfind(ElementObject *self, PyObject *args, PyObject *kwds)
-{
-    PyObject* tag;
-    PyObject* namespaces = Py_None;
-    _Py_IDENTIFIER(iterfind);
-    static char *kwlist[] = {"path", "namespaces", 0};
-    elementtreestate *st = ET_STATE_GLOBAL;
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:iterfind", kwlist,
-                                     &tag, &namespaces)) {
-        return NULL;
-    }
-
-    return _PyObject_CallMethodId(
-        st->elementpath_obj, &PyId_iterfind, "OOO", self, tag, namespaces);
-}
-
-static PyObject*
-element_get(ElementObject* self, PyObject* args, PyObject* kwds)
-{
-    PyObject* value;
-    static char* kwlist[] = {"key", "default", 0};
-
-    PyObject* key;
-    PyObject* default_value = Py_None;
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:get", kwlist, &key,
-                                     &default_value))
-        return NULL;
-
-    if (!self->extra || self->extra->attrib == Py_None)
-        value = default_value;
-    else {
-        value = PyDict_GetItem(self->extra->attrib, key);
-        if (!value)
-            value = default_value;
-    }
-
-    Py_INCREF(value);
-    return value;
-}
-
-static PyObject*
-element_getchildren(ElementObject* self, PyObject* args)
-{
-    Py_ssize_t i;
-    PyObject* list;
-
-    /* FIXME: report as deprecated? */
-
-    if (!PyArg_ParseTuple(args, ":getchildren"))
-        return NULL;
-
-    if (!self->extra)
-        return PyList_New(0);
-
-    list = PyList_New(self->extra->length);
-    if (!list)
-        return NULL;
-
-    for (i = 0; i < self->extra->length; i++) {
-        PyObject* item = self->extra->children[i];
-        Py_INCREF(item);
-        PyList_SET_ITEM(list, i, item);
-    }
-
-    return list;
-}
-
-
-static PyObject *
-create_elementiter(ElementObject *self, PyObject *tag, int gettext);
-
-
-static PyObject *
-element_iter(ElementObject *self, PyObject *args, PyObject *kwds)
-{
-    PyObject* tag = Py_None;
-    static char* kwlist[] = {"tag", 0};
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:iter", kwlist, &tag))
-        return NULL;
-
-    return create_elementiter(self, tag, 0);
-}
-
-
-static PyObject*
-element_itertext(ElementObject* self, PyObject* args)
-{
-    if (!PyArg_ParseTuple(args, ":itertext"))
-        return NULL;
-
-    return create_elementiter(self, Py_None, 1);
-}
-
-
-static PyObject*
-element_getitem(PyObject* self_, Py_ssize_t index)
-{
-    ElementObject* self = (ElementObject*) self_;
-
-    if (!self->extra || index < 0 || index >= self->extra->length) {
-        PyErr_SetString(
-            PyExc_IndexError,
-            "child index out of range"
-            );
-        return NULL;
-    }
-
-    Py_INCREF(self->extra->children[index]);
-    return self->extra->children[index];
-}
-
-static PyObject*
-element_insert(ElementObject* self, PyObject* args)
-{
-    Py_ssize_t index, i;
-    PyObject* element;
-    if (!PyArg_ParseTuple(args, "nO!:insert", &index,
-                          &Element_Type, &element))
-        return NULL;
-
-    if (!self->extra) {
-        if (create_extra(self, NULL) < 0)
-            return NULL;
-    }
-
-    if (index < 0) {
-        index += self->extra->length;
-        if (index < 0)
-            index = 0;
-    }
-    if (index > self->extra->length)
-        index = self->extra->length;
-
-    if (element_resize(self, 1) < 0)
-        return NULL;
-
-    for (i = self->extra->length; i > index; i--)
-        self->extra->children[i] = self->extra->children[i-1];
-
-    Py_INCREF(element);
-    self->extra->children[index] = element;
-
-    self->extra->length++;
-
-    Py_RETURN_NONE;
-}
-
-static PyObject*
-element_items(ElementObject* self, PyObject* args)
-{
-    if (!PyArg_ParseTuple(args, ":items"))
-        return NULL;
-
-    if (!self->extra || self->extra->attrib == Py_None)
-        return PyList_New(0);
-
-    return PyDict_Items(self->extra->attrib);
-}
-
-static PyObject*
-element_keys(ElementObject* self, PyObject* args)
-{
-    if (!PyArg_ParseTuple(args, ":keys"))
-        return NULL;
-
-    if (!self->extra || self->extra->attrib == Py_None)
-        return PyList_New(0);
-
-    return PyDict_Keys(self->extra->attrib);
-}
-
-static Py_ssize_t
-element_length(ElementObject* self)
-{
-    if (!self->extra)
-        return 0;
-
-    return self->extra->length;
-}
-
-static PyObject*
-element_makeelement(PyObject* self, PyObject* args, PyObject* kw)
-{
-    PyObject* elem;
-
-    PyObject* tag;
-    PyObject* attrib;
-    if (!PyArg_ParseTuple(args, "OO:makeelement", &tag, &attrib))
-        return NULL;
-
-    attrib = PyDict_Copy(attrib);
-    if (!attrib)
-        return NULL;
-
-    elem = create_new_element(tag, attrib);
-
-    Py_DECREF(attrib);
-
-    return elem;
-}
-
-static PyObject*
-element_remove(ElementObject* self, PyObject* args)
-{
-    Py_ssize_t i;
-
-    PyObject* element;
-    if (!PyArg_ParseTuple(args, "O!:remove", &Element_Type, &element))
-        return NULL;
-
-    if (!self->extra) {
-        /* element has no children, so raise exception */
-        PyErr_SetString(
-            PyExc_ValueError,
-            "list.remove(x): x not in list"
-            );
-        return NULL;
-    }
-
-    for (i = 0; i < self->extra->length; i++) {
-        if (self->extra->children[i] == element)
-            break;
-        if (PyObject_RichCompareBool(self->extra->children[i], element, Py_EQ) == 1)
-            break;
-    }
-
-    if (i == self->extra->length) {
-        /* element is not in children, so raise exception */
-        PyErr_SetString(
-            PyExc_ValueError,
-            "list.remove(x): x not in list"
-            );
-        return NULL;
-    }
-
-    Py_DECREF(self->extra->children[i]);
-
-    self->extra->length--;
-
-    for (; i < self->extra->length; i++)
-        self->extra->children[i] = self->extra->children[i+1];
-
-    Py_RETURN_NONE;
-}
-
-static PyObject*
-element_repr(ElementObject* self)
-{
-    if (self->tag)
-        return PyUnicode_FromFormat("<Element %R at %p>", self->tag, self);
-    else
-        return PyUnicode_FromFormat("<Element at %p>", self);
-}
-
-static PyObject*
-element_set(ElementObject* self, PyObject* args)
-{
-    PyObject* attrib;
-
-    PyObject* key;
-    PyObject* value;
-    if (!PyArg_ParseTuple(args, "OO:set", &key, &value))
-        return NULL;
-
-    if (!self->extra) {
-        if (create_extra(self, NULL) < 0)
-            return NULL;
-    }
-
-    attrib = element_get_attrib(self);
-    if (!attrib)
-        return NULL;
-
-    if (PyDict_SetItem(attrib, key, value) < 0)
-        return NULL;
-
-    Py_RETURN_NONE;
-}
-
-static int
-element_setitem(PyObject* self_, Py_ssize_t index, PyObject* item)
-{
-    ElementObject* self = (ElementObject*) self_;
-    Py_ssize_t i;
-    PyObject* old;
-
-    if (!self->extra || index < 0 || index >= self->extra->length) {
-        PyErr_SetString(
-            PyExc_IndexError,
-            "child assignment index out of range");
-        return -1;
-    }
-
-    old = self->extra->children[index];
-
-    if (item) {
-        Py_INCREF(item);
-        self->extra->children[index] = item;
-    } else {
-        self->extra->length--;
-        for (i = index; i < self->extra->length; i++)
-            self->extra->children[i] = self->extra->children[i+1];
-    }
-
-    Py_DECREF(old);
-
-    return 0;
-}
-
-static PyObject*
-element_subscr(PyObject* self_, PyObject* item)
-{
-    ElementObject* self = (ElementObject*) self_;
-
-    if (PyIndex_Check(item)) {
-        Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
-
-        if (i == -1 && PyErr_Occurred()) {
-            return NULL;
-        }
-        if (i < 0 && self->extra)
-            i += self->extra->length;
-        return element_getitem(self_, i);
-    }
-    else if (PySlice_Check(item)) {
-        Py_ssize_t start, stop, step, slicelen, cur, i;
-        PyObject* list;
-
-        if (!self->extra)
-            return PyList_New(0);
-
-        if (PySlice_GetIndicesEx(item,
-                self->extra->length,
-                &start, &stop, &step, &slicelen) < 0) {
-            return NULL;
-        }
-
-        if (slicelen <= 0)
-            return PyList_New(0);
-        else {
-            list = PyList_New(slicelen);
-            if (!list)
-                return NULL;
-
-            for (cur = start, i = 0; i < slicelen;
-                 cur += step, i++) {
-                PyObject* item = self->extra->children[cur];
-                Py_INCREF(item);
-                PyList_SET_ITEM(list, i, item);
-            }
-
-            return list;
-        }
-    }
-    else {
-        PyErr_SetString(PyExc_TypeError,
-                "element indices must be integers");
-        return NULL;
-    }
-}
-
-static int
-element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value)
-{
-    ElementObject* self = (ElementObject*) self_;
-
-    if (PyIndex_Check(item)) {
-        Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
-
-        if (i == -1 && PyErr_Occurred()) {
-            return -1;
-        }
-        if (i < 0 && self->extra)
-            i += self->extra->length;
-        return element_setitem(self_, i, value);
-    }
-    else if (PySlice_Check(item)) {
-        Py_ssize_t start, stop, step, slicelen, newlen, cur, i;
-
-        PyObject* recycle = NULL;
-        PyObject* seq = NULL;
-
-        if (!self->extra) {
-            if (create_extra(self, NULL) < 0)
-                return -1;
-        }
-
-        if (PySlice_GetIndicesEx(item,
-                self->extra->length,
-                &start, &stop, &step, &slicelen) < 0) {
-            return -1;
-        }
-
-        if (value == NULL) {
-            /* Delete slice */
-            size_t cur;
-            Py_ssize_t i;
-
-            if (slicelen <= 0)
-                return 0;
-
-            /* Since we're deleting, the direction of the range doesn't matter,
-             * so for simplicity make it always ascending.
-            */
-            if (step < 0) {
-                stop = start + 1;
-                start = stop + step * (slicelen - 1) - 1;
-                step = -step;
-            }
-
-            assert((size_t)slicelen <= PY_SIZE_MAX / sizeof(PyObject *));
-
-            /* recycle is a list that will contain all the children
-             * scheduled for removal.
-            */
-            if (!(recycle = PyList_New(slicelen))) {
-                PyErr_NoMemory();
-                return -1;
-            }
-
-            /* This loop walks over all the children that have to be deleted,
-             * with cur pointing at them. num_moved is the amount of children
-             * until the next deleted child that have to be "shifted down" to
-             * occupy the deleted's places.
-             * Note that in the ith iteration, shifting is done i+i places down
-             * because i children were already removed.
-            */
-            for (cur = start, i = 0; cur < (size_t)stop; cur += step, ++i) {
-                /* Compute how many children have to be moved, clipping at the
-                 * list end.
-                */
-                Py_ssize_t num_moved = step - 1;
-                if (cur + step >= (size_t)self->extra->length) {
-                    num_moved = self->extra->length - cur - 1;
-                }
-
-                PyList_SET_ITEM(recycle, i, self->extra->children[cur]);
-
-                memmove(
-                    self->extra->children + cur - i,
-                    self->extra->children + cur + 1,
-                    num_moved * sizeof(PyObject *));
-            }
-
-            /* Leftover "tail" after the last removed child */
-            cur = start + (size_t)slicelen * step;
-            if (cur < (size_t)self->extra->length) {
-                memmove(
-                    self->extra->children + cur - slicelen,
-                    self->extra->children + cur,
-                    (self->extra->length - cur) * sizeof(PyObject *));
-            }
-
-            self->extra->length -= slicelen;
-
-            /* Discard the recycle list with all the deleted sub-elements */
-            Py_XDECREF(recycle);
-            return 0;
-        }
-        else {
-            /* A new slice is actually being assigned */
-            seq = PySequence_Fast(value, "");
-            if (!seq) {
-                PyErr_Format(
-                    PyExc_TypeError,
-                    "expected sequence, not \"%.200s\"", Py_TYPE(value)->tp_name
-                    );
-                return -1;
-            }
-            newlen = PySequence_Size(seq);
-        }
-
-        if (step !=  1 && newlen != slicelen)
-        {
-            PyErr_Format(PyExc_ValueError,
-                "attempt to assign sequence of size %zd "
-                "to extended slice of size %zd",
-                newlen, slicelen
-                );
-            return -1;
-        }
-
-        /* Resize before creating the recycle bin, to prevent refleaks. */
-        if (newlen > slicelen) {
-            if (element_resize(self, newlen - slicelen) < 0) {
-                if (seq) {
-                    Py_DECREF(seq);
-                }
-                return -1;
-            }
-        }
-
-        if (slicelen > 0) {
-            /* to avoid recursive calls to this method (via decref), move
-               old items to the recycle bin here, and get rid of them when
-               we're done modifying the element */
-            recycle = PyList_New(slicelen);
-            if (!recycle) {
-                if (seq) {
-                    Py_DECREF(seq);
-                }
-                return -1;
-            }
-            for (cur = start, i = 0; i < slicelen;
-                 cur += step, i++)
-                PyList_SET_ITEM(recycle, i, self->extra->children[cur]);
-        }
-
-        if (newlen < slicelen) {
-            /* delete slice */
-            for (i = stop; i < self->extra->length; i++)
-                self->extra->children[i + newlen - slicelen] = self->extra->children[i];
-        } else if (newlen > slicelen) {
-            /* insert slice */
-            for (i = self->extra->length-1; i >= stop; i--)
-                self->extra->children[i + newlen - slicelen] = self->extra->children[i];
-        }
-
-        /* replace the slice */
-        for (cur = start, i = 0; i < newlen;
-             cur += step, i++) {
-            PyObject* element = PySequence_Fast_GET_ITEM(seq, i);
-            Py_INCREF(element);
-            self->extra->children[cur] = element;
-        }
-
-        self->extra->length += newlen - slicelen;
-
-        if (seq) {
-            Py_DECREF(seq);
-        }
-
-        /* discard the recycle bin, and everything in it */
-        Py_XDECREF(recycle);
-
-        return 0;
-    }
-    else {
-        PyErr_SetString(PyExc_TypeError,
-                "element indices must be integers");
-        return -1;
-    }
-}
-
-static PyMethodDef element_methods[] = {
-
-    {"clear", (PyCFunction) element_clearmethod, METH_VARARGS},
-
-    {"get", (PyCFunction) element_get, METH_VARARGS | METH_KEYWORDS},
-    {"set", (PyCFunction) element_set, METH_VARARGS},
-
-    {"find", (PyCFunction) element_find, METH_VARARGS | METH_KEYWORDS},
-    {"findtext", (PyCFunction) element_findtext, METH_VARARGS | METH_KEYWORDS},
-    {"findall", (PyCFunction) element_findall, METH_VARARGS | METH_KEYWORDS},
-
-    {"append", (PyCFunction) element_append, METH_VARARGS},
-    {"extend", (PyCFunction) element_extend, METH_VARARGS},
-    {"insert", (PyCFunction) element_insert, METH_VARARGS},
-    {"remove", (PyCFunction) element_remove, METH_VARARGS},
-
-    {"iter", (PyCFunction) element_iter, METH_VARARGS | METH_KEYWORDS},
-    {"itertext", (PyCFunction) element_itertext, METH_VARARGS},
-    {"iterfind", (PyCFunction) element_iterfind, METH_VARARGS | METH_KEYWORDS},
-
-    {"getiterator", (PyCFunction) element_iter, METH_VARARGS | METH_KEYWORDS},
-    {"getchildren", (PyCFunction) element_getchildren, METH_VARARGS},
-
-    {"items", (PyCFunction) element_items, METH_VARARGS},
-    {"keys", (PyCFunction) element_keys, METH_VARARGS},
-
-    {"makeelement", (PyCFunction) element_makeelement, METH_VARARGS},
-
-    {"__copy__", (PyCFunction) element_copy, METH_VARARGS},
-    {"__deepcopy__", (PyCFunction) element_deepcopy, METH_VARARGS},
-    {"__sizeof__", element_sizeof, METH_NOARGS},
-    {"__getstate__", (PyCFunction)element_getstate, METH_NOARGS},
-    {"__setstate__", (PyCFunction)element_setstate, METH_O},
-
-    {NULL, NULL}
-};
-
-static PyObject*
-element_getattro(ElementObject* self, PyObject* nameobj)
-{
-    PyObject* res;
-    char *name = "";
-
-    if (PyUnicode_Check(nameobj))
-        name = _PyUnicode_AsString(nameobj);
-
-    if (name == NULL)
-        return NULL;
-
-    /* handle common attributes first */
-    if (strcmp(name, "tag") == 0) {
-        res = self->tag;
-        Py_INCREF(res);
-        return res;
-    } else if (strcmp(name, "text") == 0) {
-        res = element_get_text(self);
-        Py_XINCREF(res);
-        return res;
-    }
-
-    /* methods */
-    res = PyObject_GenericGetAttr((PyObject*) self, nameobj);
-    if (res)
-        return res;
-
-    /* less common attributes */
-    if (strcmp(name, "tail") == 0) {
-        PyErr_Clear();
-        res = element_get_tail(self);
-    } else if (strcmp(name, "attrib") == 0) {
-        PyErr_Clear();
-        if (!self->extra) {
-            if (create_extra(self, NULL) < 0)
-                return NULL;
-        }
-        res = element_get_attrib(self);
-    }
-
-    if (!res)
-        return NULL;
-
-    Py_INCREF(res);
-    return res;
-}
-
-static int
-element_setattro(ElementObject* self, PyObject* nameobj, PyObject* value)
-{
-    char *name = "";
-    if (PyUnicode_Check(nameobj))
-        name = _PyUnicode_AsString(nameobj);
-    if (name == NULL)
-        return -1;
-
-    if (strcmp(name, "tag") == 0) {
-        Py_DECREF(self->tag);
-        self->tag = value;
-        Py_INCREF(self->tag);
-    } else if (strcmp(name, "text") == 0) {
-        Py_DECREF(JOIN_OBJ(self->text));
-        self->text = value;
-        Py_INCREF(self->text);
-    } else if (strcmp(name, "tail") == 0) {
-        Py_DECREF(JOIN_OBJ(self->tail));
-        self->tail = value;
-        Py_INCREF(self->tail);
-    } else if (strcmp(name, "attrib") == 0) {
-        if (!self->extra) {
-            if (create_extra(self, NULL) < 0)
-                return -1;
-        }
-        Py_DECREF(self->extra->attrib);
-        self->extra->attrib = value;
-        Py_INCREF(self->extra->attrib);
-    } else {
-        PyErr_SetString(PyExc_AttributeError,
-            "Can't set arbitrary attributes on Element");
-        return -1;
-    }
-
-    return 0;
-}
-
-static PySequenceMethods element_as_sequence = {
-    (lenfunc) element_length,
-    0, /* sq_concat */
-    0, /* sq_repeat */
-    element_getitem,
-    0,
-    element_setitem,
-    0,
-};
-
-static PyMappingMethods element_as_mapping = {
-    (lenfunc) element_length,
-    (binaryfunc) element_subscr,
-    (objobjargproc) element_ass_subscr,
-};
-
-static PyTypeObject Element_Type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "xml.etree.ElementTree.Element", sizeof(ElementObject), 0,
-    /* methods */
-    (destructor)element_dealloc,                    /* tp_dealloc */
-    0,                                              /* tp_print */
-    0,                                              /* tp_getattr */
-    0,                                              /* tp_setattr */
-    0,                                              /* tp_reserved */
-    (reprfunc)element_repr,                         /* tp_repr */
-    0,                                              /* tp_as_number */
-    &element_as_sequence,                           /* tp_as_sequence */
-    &element_as_mapping,                            /* tp_as_mapping */
-    0,                                              /* tp_hash */
-    0,                                              /* tp_call */
-    0,                                              /* tp_str */
-    (getattrofunc)element_getattro,                 /* tp_getattro */
-    (setattrofunc)element_setattro,                 /* tp_setattro */
-    0,                                              /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
-                                                    /* tp_flags */
-    0,                                              /* tp_doc */
-    (traverseproc)element_gc_traverse,              /* tp_traverse */
-    (inquiry)element_gc_clear,                      /* tp_clear */
-    0,                                              /* tp_richcompare */
-    offsetof(ElementObject, weakreflist),           /* tp_weaklistoffset */
-    0,                                              /* tp_iter */
-    0,                                              /* tp_iternext */
-    element_methods,                                /* tp_methods */
-    0,                                              /* tp_members */
-    0,                                              /* tp_getset */
-    0,                                              /* tp_base */
-    0,                                              /* tp_dict */
-    0,                                              /* tp_descr_get */
-    0,                                              /* tp_descr_set */
-    0,                                              /* tp_dictoffset */
-    (initproc)element_init,                         /* tp_init */
-    PyType_GenericAlloc,                            /* tp_alloc */
-    element_new,                                    /* tp_new */
-    0,                                              /* tp_free */
-};
-
-/******************************* Element iterator ****************************/
-
-/* ElementIterObject represents the iteration state over an XML element in
- * pre-order traversal. To keep track of which sub-element should be returned
- * next, a stack of parents is maintained. This is a standard stack-based
- * iterative pre-order traversal of a tree.
- * The stack is managed using a single-linked list starting at parent_stack.
- * Each stack node contains the saved parent to which we should return after
- * the current one is exhausted, and the next child to examine in that parent.
- */
-typedef struct ParentLocator_t {
-    ElementObject *parent;
-    Py_ssize_t child_index;
-    struct ParentLocator_t *next;
-} ParentLocator;
-
-typedef struct {
-    PyObject_HEAD
-    ParentLocator *parent_stack;
-    ElementObject *root_element;
-    PyObject *sought_tag;
-    int root_done;
-    int gettext;
-} ElementIterObject;
-
-
-static void
-elementiter_dealloc(ElementIterObject *it)
-{
-    ParentLocator *p = it->parent_stack;
-    while (p) {
-        ParentLocator *temp = p;
-        Py_XDECREF(p->parent);
-        p = p->next;
-        PyObject_Free(temp);
-    }
-
-    Py_XDECREF(it->sought_tag);
-    Py_XDECREF(it->root_element);
-
-    PyObject_GC_UnTrack(it);
-    PyObject_GC_Del(it);
-}
-
-static int
-elementiter_traverse(ElementIterObject *it, visitproc visit, void *arg)
-{
-    ParentLocator *p = it->parent_stack;
-    while (p) {
-        Py_VISIT(p->parent);
-        p = p->next;
-    }
-
-    Py_VISIT(it->root_element);
-    Py_VISIT(it->sought_tag);
-    return 0;
-}
-
-/* Helper function for elementiter_next. Add a new parent to the parent stack.
- */
-static ParentLocator *
-parent_stack_push_new(ParentLocator *stack, ElementObject *parent)
-{
-    ParentLocator *new_node = PyObject_Malloc(sizeof(ParentLocator));
-    if (new_node) {
-        new_node->parent = parent;
-        Py_INCREF(parent);
-        new_node->child_index = 0;
-        new_node->next = stack;
-    }
-    return new_node;
-}
-
-static PyObject *
-elementiter_next(ElementIterObject *it)
-{
-    /* Sub-element iterator.
-     *
-     * A short note on gettext: this function serves both the iter() and
-     * itertext() methods to avoid code duplication. However, there are a few
-     * small differences in the way these iterations work. Namely:
-     *   - itertext() only yields text from nodes that have it, and continues
-     *     iterating when a node doesn't have text (so it doesn't return any
-     *     node like iter())
-     *   - itertext() also has to handle tail, after finishing with all the
-     *     children of a node.
-     */
-    ElementObject *cur_parent;
-    Py_ssize_t child_index;
-
-    while (1) {
-        /* Handle the case reached in the beginning and end of iteration, where
-         * the parent stack is empty. The root_done flag gives us indication
-         * whether we've just started iterating (so root_done is 0), in which
-         * case the root is returned. If root_done is 1 and we're here, the
-         * iterator is exhausted.
-         */
-        if (!it->parent_stack->parent) {
-            if (it->root_done) {
-                PyErr_SetNone(PyExc_StopIteration);
-                return NULL;
-            } else {
-                it->parent_stack = parent_stack_push_new(it->parent_stack,
-                                                         it->root_element);
-                if (!it->parent_stack) {
-                    PyErr_NoMemory();
-                    return NULL;
-                }
-
-                it->root_done = 1;
-                if (it->sought_tag == Py_None ||
-                    PyObject_RichCompareBool(it->root_element->tag,
-                                             it->sought_tag, Py_EQ) == 1) {
-                    if (it->gettext) {
-                        PyObject *text = element_get_text(it->root_element);
-                        if (!text)
-                            return NULL;
-                        if (PyObject_IsTrue(text)) {
-                            Py_INCREF(text);
-                            return text;
-                        }
-                    } else {
-                        Py_INCREF(it->root_element);
-                        return (PyObject *)it->root_element;
-                    }
-                }
-            }
-        }
-
-        /* See if there are children left to traverse in the current parent. If
-         * yes, visit the next child. If not, pop the stack and try again.
-         */
-        cur_parent = it->parent_stack->parent;
-        child_index = it->parent_stack->child_index;
-        if (cur_parent->extra && child_index < cur_parent->extra->length) {
-            ElementObject *child = (ElementObject *)
-                cur_parent->extra->children[child_index];
-            it->parent_stack->child_index++;
-            it->parent_stack = parent_stack_push_new(it->parent_stack,
-                                                     child);
-            if (!it->parent_stack) {
-                PyErr_NoMemory();
-                return NULL;
-            }
-
-            if (it->gettext) {
-                PyObject *text = element_get_text(child);
-                if (!text)
-                    return NULL;
-                if (PyObject_IsTrue(text)) {
-                    Py_INCREF(text);
-                    return text;
-                }
-            } else if (it->sought_tag == Py_None ||
-                PyObject_RichCompareBool(child->tag,
-                                         it->sought_tag, Py_EQ) == 1) {
-                Py_INCREF(child);
-                return (PyObject *)child;
-            }
-            else
-                continue;
-        }
-        else {
-            PyObject *tail;
-            ParentLocator *next = it->parent_stack->next;
-            if (it->gettext) {
-                tail = element_get_tail(cur_parent);
-                if (!tail)
-                    return NULL;
-            }
-            else
-                tail = Py_None;
-            Py_XDECREF(it->parent_stack->parent);
-            PyObject_Free(it->parent_stack);
-            it->parent_stack = next;
-
-            /* Note that extra condition on it->parent_stack->parent here;
-             * this is because itertext() is supposed to only return *inner*
-             * text, not text following the element it began iteration with.
-             */
-            if (it->parent_stack->parent && PyObject_IsTrue(tail)) {
-                Py_INCREF(tail);
-                return tail;
-            }
-        }
-    }
-
-    return NULL;
-}
-
-
-static PyTypeObject ElementIter_Type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    /* Using the module's name since the pure-Python implementation does not
-       have such a type. */
-    "_elementtree._element_iterator",           /* tp_name */
-    sizeof(ElementIterObject),                  /* tp_basicsize */
-    0,                                          /* tp_itemsize */
-    /* methods */
-    (destructor)elementiter_dealloc,            /* tp_dealloc */
-    0,                                          /* tp_print */
-    0,                                          /* tp_getattr */
-    0,                                          /* tp_setattr */
-    0,                                          /* tp_reserved */
-    0,                                          /* tp_repr */
-    0,                                          /* tp_as_number */
-    0,                                          /* tp_as_sequence */
-    0,                                          /* tp_as_mapping */
-    0,                                          /* tp_hash */
-    0,                                          /* tp_call */
-    0,                                          /* tp_str */
-    0,                                          /* tp_getattro */
-    0,                                          /* tp_setattro */
-    0,                                          /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,    /* tp_flags */
-    0,                                          /* tp_doc */
-    (traverseproc)elementiter_traverse,         /* tp_traverse */
-    0,                                          /* tp_clear */
-    0,                                          /* tp_richcompare */
-    0,                                          /* tp_weaklistoffset */
-    PyObject_SelfIter,                          /* tp_iter */
-    (iternextfunc)elementiter_next,             /* tp_iternext */
-    0,                                          /* tp_methods */
-    0,                                          /* tp_members */
-    0,                                          /* tp_getset */
-    0,                                          /* tp_base */
-    0,                                          /* tp_dict */
-    0,                                          /* tp_descr_get */
-    0,                                          /* tp_descr_set */
-    0,                                          /* tp_dictoffset */
-    0,                                          /* tp_init */
-    0,                                          /* tp_alloc */
-    0,                                          /* tp_new */
-};
-
-
-static PyObject *
-create_elementiter(ElementObject *self, PyObject *tag, int gettext)
-{
-    ElementIterObject *it;
-    PyObject *star = NULL;
-
-    it = PyObject_GC_New(ElementIterObject, &ElementIter_Type);
-    if (!it)
-        return NULL;
-
-    if (PyUnicode_Check(tag))
-        star = PyUnicode_FromString("*");
-    else if (PyBytes_Check(tag))
-        star = PyBytes_FromString("*");
-
-    if (star && PyObject_RichCompareBool(tag, star, Py_EQ) == 1)
-        tag = Py_None;
-    Py_XDECREF(star);
-
-    Py_INCREF(tag);
-    it->sought_tag = tag;
-    it->root_done = 0;
-    it->gettext = gettext;
-    Py_INCREF(self);
-    it->root_element = self;
-
-    PyObject_GC_Track(it);
-
-    it->parent_stack = PyObject_Malloc(sizeof(ParentLocator));
-    if (it->parent_stack == NULL) {
-        Py_DECREF(it);
-        PyErr_NoMemory();
-        return NULL;
-    }
-    it->parent_stack->parent = NULL;
-    it->parent_stack->child_index = 0;
-    it->parent_stack->next = NULL;
-
-    return (PyObject *)it;
-}
-
-
-/* ==================================================================== */
-/* the tree builder type */
-
-typedef struct {
-    PyObject_HEAD
-
-    PyObject *root; /* root node (first created node) */
-
-    PyObject *this; /* current node */
-    PyObject *last; /* most recently created node */
-
-    PyObject *data; /* data collector (string or list), or NULL */
-
-    PyObject *stack; /* element stack */
-    Py_ssize_t index; /* current stack size (0 means empty) */
-
-    PyObject *element_factory;
-
-    /* element tracing */
-    PyObject *events; /* list of events, or NULL if not collecting */
-    PyObject *start_event_obj; /* event objects (NULL to ignore) */
-    PyObject *end_event_obj;
-    PyObject *start_ns_event_obj;
-    PyObject *end_ns_event_obj;
-} TreeBuilderObject;
-
-#define TreeBuilder_CheckExact(op) (Py_TYPE(op) == &TreeBuilder_Type)
-
-/* -------------------------------------------------------------------- */
-/* constructor and destructor */
-
-static PyObject *
-treebuilder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
-    TreeBuilderObject *t = (TreeBuilderObject *)type->tp_alloc(type, 0);
-    if (t != NULL) {
-        t->root = NULL;
-
-        Py_INCREF(Py_None);
-        t->this = Py_None;
-        Py_INCREF(Py_None);
-        t->last = Py_None;
-
-        t->data = NULL;
-        t->element_factory = NULL;
-        t->stack = PyList_New(20);
-        if (!t->stack) {
-            Py_DECREF(t->this);
-            Py_DECREF(t->last);
-            Py_DECREF((PyObject *) t);
-            return NULL;
-        }
-        t->index = 0;
-
-        t->events = NULL;
-        t->start_event_obj = t->end_event_obj = NULL;
-        t->start_ns_event_obj = t->end_ns_event_obj = NULL;
-    }
-    return (PyObject *)t;
-}
-
-static int
-treebuilder_init(PyObject *self, PyObject *args, PyObject *kwds)
-{
-    static char *kwlist[] = {"element_factory", 0};
-    PyObject *element_factory = NULL;
-    TreeBuilderObject *self_tb = (TreeBuilderObject *)self;
-    PyObject *tmp;
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:TreeBuilder", kwlist,
-                                     &element_factory)) {
-        return -1;
-    }
-
-    if (element_factory) {
-        Py_INCREF(element_factory);
-        tmp = self_tb->element_factory;
-        self_tb->element_factory = element_factory;
-        Py_XDECREF(tmp);
-    }
-
-    return 0;
-}
-
-static int
-treebuilder_gc_traverse(TreeBuilderObject *self, visitproc visit, void *arg)
-{
-    Py_VISIT(self->root);
-    Py_VISIT(self->this);
-    Py_VISIT(self->last);
-    Py_VISIT(self->data);
-    Py_VISIT(self->stack);
-    Py_VISIT(self->element_factory);
-    return 0;
-}
-
-static int
-treebuilder_gc_clear(TreeBuilderObject *self)
-{
-    Py_CLEAR(self->end_ns_event_obj);
-    Py_CLEAR(self->start_ns_event_obj);
-    Py_CLEAR(self->end_event_obj);
-    Py_CLEAR(self->start_event_obj);
-    Py_CLEAR(self->events);
-    Py_CLEAR(self->stack);
-    Py_CLEAR(self->data);
-    Py_CLEAR(self->last);
-    Py_CLEAR(self->this);
-    Py_CLEAR(self->element_factory);
-    Py_CLEAR(self->root);
-    return 0;
-}
-
-static void
-treebuilder_dealloc(TreeBuilderObject *self)
-{
-    PyObject_GC_UnTrack(self);
-    treebuilder_gc_clear(self);
-    Py_TYPE(self)->tp_free((PyObject *)self);
-}
-
-/* -------------------------------------------------------------------- */
-/* helpers for handling of arbitrary element-like objects */
-
-static int
-treebuilder_set_element_text_or_tail(PyObject *element, PyObject *data,
-                                     PyObject **dest, _Py_Identifier *name)
-{
-    if (Element_CheckExact(element)) {
-        Py_DECREF(JOIN_OBJ(*dest));
-        *dest = JOIN_SET(data, PyList_CheckExact(data));
-        return 0;
-    }
-    else {
-        PyObject *joined = list_join(data);
-        int r;
-        if (joined == NULL)
-            return -1;
-        r = _PyObject_SetAttrId(element, name, joined);
-        Py_DECREF(joined);
-        return r;
-    }
-}
-
-/* These two functions steal a reference to data */
-static int
-treebuilder_set_element_text(PyObject *element, PyObject *data)
-{
-    _Py_IDENTIFIER(text);
-    return treebuilder_set_element_text_or_tail(
-        element, data, &((ElementObject *) element)->text, &PyId_text);
-}
-
-static int
-treebuilder_set_element_tail(PyObject *element, PyObject *data)
-{
-    _Py_IDENTIFIER(tail);
-    return treebuilder_set_element_text_or_tail(
-        element, data, &((ElementObject *) element)->tail, &PyId_tail);
-}
-
-static int
-treebuilder_add_subelement(PyObject *element, PyObject *child)
-{
-    _Py_IDENTIFIER(append);
-    if (Element_CheckExact(element)) {
-        ElementObject *elem = (ElementObject *) element;
-        return element_add_subelement(elem, child);
-    }
-    else {
-        PyObject *res;
-        res = _PyObject_CallMethodId(element, &PyId_append, "O", child);
-        if (res == NULL)
-            return -1;
-        Py_DECREF(res);
-        return 0;
-    }
-}
-
-/* -------------------------------------------------------------------- */
-/* handlers */
-
-LOCAL(PyObject*)
-treebuilder_handle_start(TreeBuilderObject* self, PyObject* tag,
-                         PyObject* attrib)
-{
-    PyObject* node;
-    PyObject* this;
-    elementtreestate *st = ET_STATE_GLOBAL;
-
-    if (self->data) {
-        if (self->this == self->last) {
-            if (treebuilder_set_element_text(self->last, self->data))
-                return NULL;
-        }
-        else {
-            if (treebuilder_set_element_tail(self->last, self->data))
-                return NULL;
-        }
-        self->data = NULL;
-    }
-
-    if (self->element_factory && self->element_factory != Py_None) {
-        node = PyObject_CallFunction(self->element_factory, "OO", tag, attrib);
-    } else {
-        node = create_new_element(tag, attrib);
-    }
-    if (!node) {
-        return NULL;
-    }
-
-    this = self->this;
-
-    if (this != Py_None) {
-        if (treebuilder_add_subelement(this, node) < 0)
-            goto error;
-    } else {
-        if (self->root) {
-            PyErr_SetString(
-                st->parseerror_obj,
-                "multiple elements on top level"
-                );
-            goto error;
-        }
-        Py_INCREF(node);
-        self->root = node;
-    }
-
-    if (self->index < PyList_GET_SIZE(self->stack)) {
-        if (PyList_SetItem(self->stack, self->index, this) < 0)
-            goto error;
-        Py_INCREF(this);
-    } else {
-        if (PyList_Append(self->stack, this) < 0)
-            goto error;
-    }
-    self->index++;
-
-    Py_DECREF(this);
-    Py_INCREF(node);
-    self->this = node;
-
-    Py_DECREF(self->last);
-    Py_INCREF(node);
-    self->last = node;
-
-    if (self->start_event_obj) {
-        PyObject* res;
-        PyObject* action = self->start_event_obj;
-        res = PyTuple_Pack(2, action, node);
-        if (res) {
-            PyList_Append(self->events, res);
-            Py_DECREF(res);
-        } else
-            PyErr_Clear(); /* FIXME: propagate error */
-    }
-
-    return node;
-
-  error:
-    Py_DECREF(node);
-    return NULL;
-}
-
-LOCAL(PyObject*)
-treebuilder_handle_data(TreeBuilderObject* self, PyObject* data)
-{
-    if (!self->data) {
-        if (self->last == Py_None) {
-            /* ignore calls to data before the first call to start */
-            Py_RETURN_NONE;
-        }
-        /* store the first item as is */
-        Py_INCREF(data); self->data = data;
-    } else {
-        /* more than one item; use a list to collect items */
-        if (PyBytes_CheckExact(self->data) && Py_REFCNT(self->data) == 1 &&
-            PyBytes_CheckExact(data) && PyBytes_GET_SIZE(data) == 1) {
-            /* XXX this code path unused in Python 3? */
-            /* expat often generates single character data sections; handle
-               the most common case by resizing the existing string... */
-            Py_ssize_t size = PyBytes_GET_SIZE(self->data);
-            if (_PyBytes_Resize(&self->data, size + 1) < 0)
-                return NULL;
-            PyBytes_AS_STRING(self->data)[size] = PyBytes_AS_STRING(data)[0];
-        } else if (PyList_CheckExact(self->data)) {
-            if (PyList_Append(self->data, data) < 0)
-                return NULL;
-        } else {
-            PyObject* list = PyList_New(2);
-            if (!list)
-                return NULL;
-            PyList_SET_ITEM(list, 0, self->data);
-            Py_INCREF(data); PyList_SET_ITEM(list, 1, data);
-            self->data = list;
-        }
-    }
-
-    Py_RETURN_NONE;
-}
-
-LOCAL(PyObject*)
-treebuilder_handle_end(TreeBuilderObject* self, PyObject* tag)
-{
-    PyObject* item;
-
-    if (self->data) {
-        if (self->this == self->last) {
-            if (treebuilder_set_element_text(self->last, self->data))
-                return NULL;
-        } else {
-            if (treebuilder_set_element_tail(self->last, self->data))
-                return NULL;
-        }
-        self->data = NULL;
-    }
-
-    if (self->index == 0) {
-        PyErr_SetString(
-            PyExc_IndexError,
-            "pop from empty stack"
-            );
-        return NULL;
-    }
-
-    self->index--;
-
-    item = PyList_GET_ITEM(self->stack, self->index);
-    Py_INCREF(item);
-
-    Py_DECREF(self->last);
-
-    self->last = self->this;
-    self->this = item;
-
-    if (self->end_event_obj) {
-        PyObject* res;
-        PyObject* action = self->end_event_obj;
-        PyObject* node = (PyObject*) self->last;
-        res = PyTuple_Pack(2, action, node);
-        if (res) {
-            PyList_Append(self->events, res);
-            Py_DECREF(res);
-        } else
-            PyErr_Clear(); /* FIXME: propagate error */
-    }
-
-    Py_INCREF(self->last);
-    return (PyObject*) self->last;
-}
-
-LOCAL(void)
-treebuilder_handle_namespace(TreeBuilderObject* self, int start,
-                             PyObject *prefix, PyObject *uri)
-{
-    PyObject* res;
-    PyObject* action;
-    PyObject* parcel;
-
-    if (!self->events)
-        return;
-
-    if (start) {
-        if (!self->start_ns_event_obj)
-            return;
-        action = self->start_ns_event_obj;
-        parcel = Py_BuildValue("OO", prefix, uri);
-        if (!parcel)
-            return;
-        Py_INCREF(action);
-    } else {
-        if (!self->end_ns_event_obj)
-            return;
-        action = self->end_ns_event_obj;
-        Py_INCREF(action);
-        parcel = Py_None;
-        Py_INCREF(parcel);
-    }
-
-    res = PyTuple_New(2);
-
-    if (res) {
-        PyTuple_SET_ITEM(res, 0, action);
-        PyTuple_SET_ITEM(res, 1, parcel);
-        PyList_Append(self->events, res);
-        Py_DECREF(res);
-    }
-    else {
-        Py_DECREF(action);
-        Py_DECREF(parcel);
-        PyErr_Clear(); /* FIXME: propagate error */
-    }
-}
-
-/* -------------------------------------------------------------------- */
-/* methods (in alphabetical order) */
-
-static PyObject*
-treebuilder_data(TreeBuilderObject* self, PyObject* args)
-{
-    PyObject* data;
-    if (!PyArg_ParseTuple(args, "O:data", &data))
-        return NULL;
-
-    return treebuilder_handle_data(self, data);
-}
-
-static PyObject*
-treebuilder_end(TreeBuilderObject* self, PyObject* args)
-{
-    PyObject* tag;
-    if (!PyArg_ParseTuple(args, "O:end", &tag))
-        return NULL;
-
-    return treebuilder_handle_end(self, tag);
-}
-
-LOCAL(PyObject*)
-treebuilder_done(TreeBuilderObject* self)
-{
-    PyObject* res;
-
-    /* FIXME: check stack size? */
-
-    if (self->root)
-        res = self->root;
-    else
-        res = Py_None;
-
-    Py_INCREF(res);
-    return res;
-}
-
-static PyObject*
-treebuilder_close(TreeBuilderObject* self, PyObject* args)
-{
-    if (!PyArg_ParseTuple(args, ":close"))
-        return NULL;
-
-    return treebuilder_done(self);
-}
-
-static PyObject*
-treebuilder_start(TreeBuilderObject* self, PyObject* args)
-{
-    PyObject* tag;
-    PyObject* attrib = Py_None;
-    if (!PyArg_ParseTuple(args, "O|O:start", &tag, &attrib))
-        return NULL;
-
-    return treebuilder_handle_start(self, tag, attrib);
-}
-
-static PyMethodDef treebuilder_methods[] = {
-    {"data", (PyCFunction) treebuilder_data, METH_VARARGS},
-    {"start", (PyCFunction) treebuilder_start, METH_VARARGS},
-    {"end", (PyCFunction) treebuilder_end, METH_VARARGS},
-    {"close", (PyCFunction) treebuilder_close, METH_VARARGS},
-    {NULL, NULL}
-};
-
-static PyTypeObject TreeBuilder_Type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "xml.etree.ElementTree.TreeBuilder", sizeof(TreeBuilderObject), 0,
-    /* methods */
-    (destructor)treebuilder_dealloc,                /* tp_dealloc */
-    0,                                              /* tp_print */
-    0,                                              /* tp_getattr */
-    0,                                              /* tp_setattr */
-    0,                                              /* tp_reserved */
-    0,                                              /* tp_repr */
-    0,                                              /* tp_as_number */
-    0,                                              /* tp_as_sequence */
-    0,                                              /* tp_as_mapping */
-    0,                                              /* tp_hash */
-    0,                                              /* tp_call */
-    0,                                              /* tp_str */
-    0,                                              /* tp_getattro */
-    0,                                              /* tp_setattro */
-    0,                                              /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
-                                                    /* tp_flags */
-    0,                                              /* tp_doc */
-    (traverseproc)treebuilder_gc_traverse,          /* tp_traverse */
-    (inquiry)treebuilder_gc_clear,                  /* tp_clear */
-    0,                                              /* tp_richcompare */
-    0,                                              /* tp_weaklistoffset */
-    0,                                              /* tp_iter */
-    0,                                              /* tp_iternext */
-    treebuilder_methods,                            /* tp_methods */
-    0,                                              /* tp_members */
-    0,                                              /* tp_getset */
-    0,                                              /* tp_base */
-    0,                                              /* tp_dict */
-    0,                                              /* tp_descr_get */
-    0,                                              /* tp_descr_set */
-    0,                                              /* tp_dictoffset */
-    (initproc)treebuilder_init,                     /* tp_init */
-    PyType_GenericAlloc,                            /* tp_alloc */
-    treebuilder_new,                                /* tp_new */
-    0,                                              /* tp_free */
-};
-
-/* ==================================================================== */
-/* the expat interface */
-
-#include "expat.h"
-#include "pyexpat.h"
-
-/* The PyExpat_CAPI structure is an immutable dispatch table, so it can be
- * cached globally without being in per-module state.
- */
-static struct PyExpat_CAPI *expat_capi;
-#define EXPAT(func) (expat_capi->func)
-
-static XML_Memory_Handling_Suite ExpatMemoryHandler = {
-    PyObject_Malloc, PyObject_Realloc, PyObject_Free};
-
-typedef struct {
-    PyObject_HEAD
-
-    XML_Parser parser;
-
-    PyObject *target;
-    PyObject *entity;
-
-    PyObject *names;
-
-    PyObject *handle_start;
-    PyObject *handle_data;
-    PyObject *handle_end;
-
-    PyObject *handle_comment;
-    PyObject *handle_pi;
-    PyObject *handle_doctype;
-
-    PyObject *handle_close;
-
-} XMLParserObject;
-
-#define XMLParser_CheckExact(op) (Py_TYPE(op) == &XMLParser_Type)
-
-/* helpers */
-
-LOCAL(PyObject*)
-makeuniversal(XMLParserObject* self, const char* string)
-{
-    /* convert a UTF-8 tag/attribute name from the expat parser
-       to a universal name string */
-
-    Py_ssize_t size = (Py_ssize_t) strlen(string);
-    PyObject* key;
-    PyObject* value;
-
-    /* look the 'raw' name up in the names dictionary */
-    key = PyBytes_FromStringAndSize(string, size);
-    if (!key)
-        return NULL;
-
-    value = PyDict_GetItem(self->names, key);
-
-    if (value) {
-        Py_INCREF(value);
-    } else {
-        /* new name.  convert to universal name, and decode as
-           necessary */
-
-        PyObject* tag;
-        char* p;
-        Py_ssize_t i;
-
-        /* look for namespace separator */
-        for (i = 0; i < size; i++)
-            if (string[i] == '}')
-                break;
-        if (i != size) {
-            /* convert to universal name */
-            tag = PyBytes_FromStringAndSize(NULL, size+1);
-            if (tag == NULL) {
-                Py_DECREF(key);
-                return NULL;
-            }
-            p = PyBytes_AS_STRING(tag);
-            p[0] = '{';
-            memcpy(p+1, string, size);
-            size++;
-        } else {
-            /* plain name; use key as tag */
-            Py_INCREF(key);
-            tag = key;
-        }
-
-        /* decode universal name */
-        p = PyBytes_AS_STRING(tag);
-        value = PyUnicode_DecodeUTF8(p, size, "strict");
-        Py_DECREF(tag);
-        if (!value) {
-            Py_DECREF(key);
-            return NULL;
-        }
-
-        /* add to names dictionary */
-        if (PyDict_SetItem(self->names, key, value) < 0) {
-            Py_DECREF(key);
-            Py_DECREF(value);
-            return NULL;
-        }
-    }
-
-    Py_DECREF(key);
-    return value;
-}
-
-/* Set the ParseError exception with the given parameters.
- * If message is not NULL, it's used as the error string. Otherwise, the
- * message string is the default for the given error_code.
-*/
-static void
-expat_set_error(enum XML_Error error_code, Py_ssize_t line, Py_ssize_t column,
-                const char *message)
-{
-    PyObject *errmsg, *error, *position, *code;
-    elementtreestate *st = ET_STATE_GLOBAL;
-
-    errmsg = PyUnicode_FromFormat("%s: line %zd, column %zd",
-                message ? message : EXPAT(ErrorString)(error_code),
-                line, column);
-    if (errmsg == NULL)
-        return;
-
-    error = PyObject_CallFunction(st->parseerror_obj, "O", errmsg);
-    Py_DECREF(errmsg);
-    if (!error)
-        return;
-
-    /* Add code and position attributes */
-    code = PyLong_FromLong((long)error_code);
-    if (!code) {
-        Py_DECREF(error);
-        return;
-    }
-    if (PyObject_SetAttrString(error, "code", code) == -1) {
-        Py_DECREF(error);
-        Py_DECREF(code);
-        return;
-    }
-    Py_DECREF(code);
-
-    position = Py_BuildValue("(nn)", line, column);
-    if (!position) {
-        Py_DECREF(error);
-        return;
-    }
-    if (PyObject_SetAttrString(error, "position", position) == -1) {
-        Py_DECREF(error);
-        Py_DECREF(position);
-        return;
-    }
-    Py_DECREF(position);
-
-    PyErr_SetObject(st->parseerror_obj, error);
-    Py_DECREF(error);
-}
-
-/* -------------------------------------------------------------------- */
-/* handlers */
-
-static void
-expat_default_handler(XMLParserObject* self, const XML_Char* data_in,
-                      int data_len)
-{
-    PyObject* key;
-    PyObject* value;
-    PyObject* res;
-
-    if (data_len < 2 || data_in[0] != '&')
-        return;
-
-    if (PyErr_Occurred())
-        return;
-
-    key = PyUnicode_DecodeUTF8(data_in + 1, data_len - 2, "strict");
-    if (!key)
-        return;
-
-    value = PyDict_GetItem(self->entity, key);
-
-    if (value) {
-        if (TreeBuilder_CheckExact(self->target))
-            res = treebuilder_handle_data(
-                (TreeBuilderObject*) self->target, value
-                );
-        else if (self->handle_data)
-            res = PyObject_CallFunction(self->handle_data, "O", value);
-        else
-            res = NULL;
-        Py_XDECREF(res);
-    } else if (!PyErr_Occurred()) {
-        /* Report the first error, not the last */
-        char message[128] = "undefined entity ";
-        strncat(message, data_in, data_len < 100?data_len:100);
-        expat_set_error(
-            XML_ERROR_UNDEFINED_ENTITY,
-            EXPAT(GetErrorLineNumber)(self->parser),
-            EXPAT(GetErrorColumnNumber)(self->parser),
-            message
-            );
-    }
-
-    Py_DECREF(key);
-}
-
-static void
-expat_start_handler(XMLParserObject* self, const XML_Char* tag_in,
-                    const XML_Char **attrib_in)
-{
-    PyObject* res;
-    PyObject* tag;
-    PyObject* attrib;
-    int ok;
-
-    if (PyErr_Occurred())
-        return;
-
-    /* tag name */
-    tag = makeuniversal(self, tag_in);
-    if (!tag)
-        return; /* parser will look for errors */
-
-    /* attributes */
-    if (attrib_in[0]) {
-        attrib = PyDict_New();
-        if (!attrib)
-            return;
-        while (attrib_in[0] && attrib_in[1]) {
-            PyObject* key = makeuniversal(self, attrib_in[0]);
-            PyObject* value = PyUnicode_DecodeUTF8(attrib_in[1], strlen(attrib_in[1]), "strict");
-            if (!key || !value) {
-                Py_XDECREF(value);
-                Py_XDECREF(key);
-                Py_DECREF(attrib);
-                return;
-            }
-            ok = PyDict_SetItem(attrib, key, value);
-            Py_DECREF(value);
-            Py_DECREF(key);
-            if (ok < 0) {
-                Py_DECREF(attrib);
-                return;
-            }
-            attrib_in += 2;
-        }
-    } else {
-        /* Pass an empty dictionary on */
-        attrib = PyDict_New();
-        if (!attrib)
-            return;
-    }
-
-    if (TreeBuilder_CheckExact(self->target)) {
-        /* shortcut */
-        res = treebuilder_handle_start((TreeBuilderObject*) self->target,
-                                       tag, attrib);
-    }
-    else if (self->handle_start) {
-        res = PyObject_CallFunction(self->handle_start, "OO", tag, attrib);
-    } else
-        res = NULL;
-
-    Py_DECREF(tag);
-    Py_DECREF(attrib);
-
-    Py_XDECREF(res);
-}
-
-static void
-expat_data_handler(XMLParserObject* self, const XML_Char* data_in,
-                   int data_len)
-{
-    PyObject* data;
-    PyObject* res;
-
-    if (PyErr_Occurred())
-        return;
-
-    data = PyUnicode_DecodeUTF8(data_in, data_len, "strict");
-    if (!data)
-        return; /* parser will look for errors */
-
-    if (TreeBuilder_CheckExact(self->target))
-        /* shortcut */
-        res = treebuilder_handle_data((TreeBuilderObject*) self->target, data);
-    else if (self->handle_data)
-        res = PyObject_CallFunction(self->handle_data, "O", data);
-    else
-        res = NULL;
-
-    Py_DECREF(data);
-
-    Py_XDECREF(res);
-}
-
-static void
-expat_end_handler(XMLParserObject* self, const XML_Char* tag_in)
-{
-    PyObject* tag;
-    PyObject* res = NULL;
-
-    if (PyErr_Occurred())
-        return;
-
-    if (TreeBuilder_CheckExact(self->target))
-        /* shortcut */
-        /* the standard tree builder doesn't look at the end tag */
-        res = treebuilder_handle_end(
-            (TreeBuilderObject*) self->target, Py_None
-            );
-    else if (self->handle_end) {
-        tag = makeuniversal(self, tag_in);
-        if (tag) {
-            res = PyObject_CallFunction(self->handle_end, "O", tag);
-            Py_DECREF(tag);
-        }
-    }
-
-    Py_XDECREF(res);
-}
-
-static void
-expat_start_ns_handler(XMLParserObject* self, const XML_Char* prefix,
-                       const XML_Char *uri)
-{
-    PyObject* sprefix = NULL;
-    PyObject* suri = NULL;
-
-    if (PyErr_Occurred())
-        return;
-
-    if (uri)
-        suri = PyUnicode_DecodeUTF8(uri, strlen(uri), "strict");
-    else
-        suri = PyUnicode_FromString("");
-    if (!suri)
-        return;
-
-    if (prefix)
-        sprefix = PyUnicode_DecodeUTF8(prefix, strlen(prefix), "strict");
-    else
-        sprefix = PyUnicode_FromString("");
-    if (!sprefix) {
-        Py_DECREF(suri);
-        return;
-    }
-
-    treebuilder_handle_namespace(
-        (TreeBuilderObject*) self->target, 1, sprefix, suri
-        );
-
-    Py_DECREF(sprefix);
-    Py_DECREF(suri);
-}
-
-static void
-expat_end_ns_handler(XMLParserObject* self, const XML_Char* prefix_in)
-{
-    if (PyErr_Occurred())
-        return;
-
-    treebuilder_handle_namespace(
-        (TreeBuilderObject*) self->target, 0, NULL, NULL
-        );
-}
-
-static void
-expat_comment_handler(XMLParserObject* self, const XML_Char* comment_in)
-{
-    PyObject* comment;
-    PyObject* res;
-
-    if (PyErr_Occurred())
-        return;
-
-    if (self->handle_comment) {
-        comment = PyUnicode_DecodeUTF8(comment_in, strlen(comment_in), "strict");
-        if (comment) {
-            res = PyObject_CallFunction(self->handle_comment, "O", comment);
-            Py_XDECREF(res);
-            Py_DECREF(comment);
-        }
-    }
-}
-
-static void
-expat_start_doctype_handler(XMLParserObject *self,
-                            const XML_Char *doctype_name,
-                            const XML_Char *sysid,
-                            const XML_Char *pubid,
-                            int has_internal_subset)
-{
-    PyObject *self_pyobj = (PyObject *)self;
-    PyObject *doctype_name_obj, *sysid_obj, *pubid_obj;
-    PyObject *parser_doctype = NULL;
-    PyObject *res = NULL;
-
-    if (PyErr_Occurred())
-        return;
-
-    doctype_name_obj = makeuniversal(self, doctype_name);
-    if (!doctype_name_obj)
-        return;
-
-    if (sysid) {
-        sysid_obj = makeuniversal(self, sysid);
-        if (!sysid_obj) {
-            Py_DECREF(doctype_name_obj);
-            return;
-        }
-    } else {
-        Py_INCREF(Py_None);
-        sysid_obj = Py_None;
-    }
-
-    if (pubid) {
-        pubid_obj = makeuniversal(self, pubid);
-        if (!pubid_obj) {
-            Py_DECREF(doctype_name_obj);
-            Py_DECREF(sysid_obj);
-            return;
-        }
-    } else {
-        Py_INCREF(Py_None);
-        pubid_obj = Py_None;
-    }
-
-    /* If the target has a handler for doctype, call it. */
-    if (self->handle_doctype) {
-        res = PyObject_CallFunction(self->handle_doctype, "OOO",
-                                    doctype_name_obj, pubid_obj, sysid_obj);
-        Py_CLEAR(res);
-    }
-
-    /* Now see if the parser itself has a doctype method. If yes and it's
-     * a subclass, call it but warn about deprecation. If it's not a subclass
-     * (i.e. vanilla XMLParser), do nothing.
-     */
-    parser_doctype = PyObject_GetAttrString(self_pyobj, "doctype");
-    if (parser_doctype) {
-        if (!XMLParser_CheckExact(self_pyobj)) {
-            if (PyErr_WarnEx(PyExc_DeprecationWarning,
-                            "This method of XMLParser is deprecated.  Define"
-                            " doctype() method on the TreeBuilder target.",
-                            1) < 0) {
-                goto clear;
-            }
-            res = PyObject_CallFunction(parser_doctype, "OOO",
-                                        doctype_name_obj, pubid_obj, sysid_obj);
-            Py_CLEAR(res);
-        }
-    }
-
-clear:
-    Py_XDECREF(parser_doctype);
-    Py_DECREF(doctype_name_obj);
-    Py_DECREF(pubid_obj);
-    Py_DECREF(sysid_obj);
-}
-
-static void
-expat_pi_handler(XMLParserObject* self, const XML_Char* target_in,
-                 const XML_Char* data_in)
-{
-    PyObject* target;
-    PyObject* data;
-    PyObject* res;
-
-    if (PyErr_Occurred())
-        return;
-
-    if (self->handle_pi) {
-        target = PyUnicode_DecodeUTF8(target_in, strlen(target_in), "strict");
-        data = PyUnicode_DecodeUTF8(data_in, strlen(data_in), "strict");
-        if (target && data) {
-            res = PyObject_CallFunction(self->handle_pi, "OO", target, data);
-            Py_XDECREF(res);
-            Py_DECREF(data);
-            Py_DECREF(target);
-        } else {
-            Py_XDECREF(data);
-            Py_XDECREF(target);
-        }
-    }
-}
-
-/* -------------------------------------------------------------------- */
-
-static PyObject *
-xmlparser_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
-    XMLParserObject *self = (XMLParserObject *)type->tp_alloc(type, 0);
-    if (self) {
-        self->parser = NULL;
-        self->target = self->entity = self->names = NULL;
-        self->handle_start = self->handle_data = self->handle_end = NULL;
-        self->handle_comment = self->handle_pi = self->handle_close = NULL;
-        self->handle_doctype = NULL;
-    }
-    return (PyObject *)self;
-}
-
-static int
-xmlparser_init(PyObject *self, PyObject *args, PyObject *kwds)
-{
-    XMLParserObject *self_xp = (XMLParserObject *)self;
-    PyObject *target = NULL, *html = NULL;
-    char *encoding = NULL;
-    static char *kwlist[] = {"html", "target", "encoding", 0};
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOz:XMLParser", kwlist,
-                                     &html, &target, &encoding)) {
-        return -1;
-    }
-
-    self_xp->entity = PyDict_New();
-    if (!self_xp->entity)
-        return -1;
-
-    self_xp->names = PyDict_New();
-    if (!self_xp->names) {
-        Py_CLEAR(self_xp->entity);
-        return -1;
-    }
-
-    self_xp->parser = EXPAT(ParserCreate_MM)(encoding, &ExpatMemoryHandler, "}");
-    if (!self_xp->parser) {
-        Py_CLEAR(self_xp->entity);
-        Py_CLEAR(self_xp->names);
-        PyErr_NoMemory();
-        return -1;
-    }
-
-    if (target) {
-        Py_INCREF(target);
-    } else {
-        target = treebuilder_new(&TreeBuilder_Type, NULL, NULL);
-        if (!target) {
-            Py_CLEAR(self_xp->entity);
-            Py_CLEAR(self_xp->names);
-            EXPAT(ParserFree)(self_xp->parser);
-            return -1;
-        }
-    }
-    self_xp->target = target;
-
-    self_xp->handle_start = PyObject_GetAttrString(target, "start");
-    self_xp->handle_data = PyObject_GetAttrString(target, "data");
-    self_xp->handle_end = PyObject_GetAttrString(target, "end");
-    self_xp->handle_comment = PyObject_GetAttrString(target, "comment");
-    self_xp->handle_pi = PyObject_GetAttrString(target, "pi");
-    self_xp->handle_close = PyObject_GetAttrString(target, "close");
-    self_xp->handle_doctype = PyObject_GetAttrString(target, "doctype");
-
-    PyErr_Clear();
-
-    /* configure parser */
-    EXPAT(SetUserData)(self_xp->parser, self_xp);
-    EXPAT(SetElementHandler)(
-        self_xp->parser,
-        (XML_StartElementHandler) expat_start_handler,
-        (XML_EndElementHandler) expat_end_handler
-        );
-    EXPAT(SetDefaultHandlerExpand)(
-        self_xp->parser,
-        (XML_DefaultHandler) expat_default_handler
-        );
-    EXPAT(SetCharacterDataHandler)(
-        self_xp->parser,
-        (XML_CharacterDataHandler) expat_data_handler
-        );
-    if (self_xp->handle_comment)
-        EXPAT(SetCommentHandler)(
-            self_xp->parser,
-            (XML_CommentHandler) expat_comment_handler
-            );
-    if (self_xp->handle_pi)
-        EXPAT(SetProcessingInstructionHandler)(
-            self_xp->parser,
-            (XML_ProcessingInstructionHandler) expat_pi_handler
-            );
-    EXPAT(SetStartDoctypeDeclHandler)(
-        self_xp->parser,
-        (XML_StartDoctypeDeclHandler) expat_start_doctype_handler
-        );
-    EXPAT(SetUnknownEncodingHandler)(
-        self_xp->parser,
-        EXPAT(DefaultUnknownEncodingHandler), NULL
-        );
-
-    return 0;
-}
-
-static int
-xmlparser_gc_traverse(XMLParserObject *self, visitproc visit, void *arg)
-{
-    Py_VISIT(self->handle_close);
-    Py_VISIT(self->handle_pi);
-    Py_VISIT(self->handle_comment);
-    Py_VISIT(self->handle_end);
-    Py_VISIT(self->handle_data);
-    Py_VISIT(self->handle_start);
-
-    Py_VISIT(self->target);
-    Py_VISIT(self->entity);
-    Py_VISIT(self->names);
-
-    return 0;
-}
-
-static int
-xmlparser_gc_clear(XMLParserObject *self)
-{
-    EXPAT(ParserFree)(self->parser);
-
-    Py_CLEAR(self->handle_close);
-    Py_CLEAR(self->handle_pi);
-    Py_CLEAR(self->handle_comment);
-    Py_CLEAR(self->handle_end);
-    Py_CLEAR(self->handle_data);
-    Py_CLEAR(self->handle_start);
-    Py_CLEAR(self->handle_doctype);
-
-    Py_CLEAR(self->target);
-    Py_CLEAR(self->entity);
-    Py_CLEAR(self->names);
-
-    return 0;
-}
-
-static void
-xmlparser_dealloc(XMLParserObject* self)
-{
-    PyObject_GC_UnTrack(self);
-    xmlparser_gc_clear(self);
-    Py_TYPE(self)->tp_free((PyObject *)self);
-}
-
-LOCAL(PyObject*)
-expat_parse(XMLParserObject* self, const char* data, int data_len, int final)
-{
-    int ok;
-
-    assert(!PyErr_Occurred());
-    ok = EXPAT(Parse)(self->parser, data, data_len, final);
-
-    if (PyErr_Occurred())
-        return NULL;
-
-    if (!ok) {
-        expat_set_error(
-            EXPAT(GetErrorCode)(self->parser),
-            EXPAT(GetErrorLineNumber)(self->parser),
-            EXPAT(GetErrorColumnNumber)(self->parser),
-            NULL
-            );
-        return NULL;
-    }
-
-    Py_RETURN_NONE;
-}
-
-static PyObject*
-xmlparser_close(XMLParserObject* self, PyObject* args)
-{
-    /* end feeding data to parser */
-
-    PyObject* res;
-    if (!PyArg_ParseTuple(args, ":close"))
-        return NULL;
-
-    res = expat_parse(self, "", 0, 1);
-    if (!res)
-        return NULL;
-
-    if (TreeBuilder_CheckExact(self->target)) {
-        Py_DECREF(res);
-        return treebuilder_done((TreeBuilderObject*) self->target);
-    }
-    else if (self->handle_close) {
-        Py_DECREF(res);
-        return PyObject_CallFunction(self->handle_close, "");
-    }
-    else {
-        return res;
-    }
-}
-
-static PyObject*
-xmlparser_feed(XMLParserObject* self, PyObject* arg)
-{
-    /* feed data to parser */
-
-    if (PyUnicode_Check(arg)) {
-        Py_ssize_t data_len;
-        const char *data = PyUnicode_AsUTF8AndSize(arg, &data_len);
-        if (data == NULL)
-            return NULL;
-        if (data_len > INT_MAX) {
-            PyErr_SetString(PyExc_OverflowError, "size does not fit in an int");
-            return NULL;
-        }
-        /* Explicitly set UTF-8 encoding. Return code ignored. */
-        (void)EXPAT(SetEncoding)(self->parser, "utf-8");
-        return expat_parse(self, data, (int)data_len, 0);
-    }
-    else {
-        Py_buffer view;
-        PyObject *res;
-        if (PyObject_GetBuffer(arg, &view, PyBUF_SIMPLE) < 0)
-            return NULL;
-        if (view.len > INT_MAX) {
-            PyBuffer_Release(&view);
-            PyErr_SetString(PyExc_OverflowError, "size does not fit in an int");
-            return NULL;
-        }
-        res = expat_parse(self, view.buf, (int)view.len, 0);
-        PyBuffer_Release(&view);
-        return res;
-    }
-}
-
-static PyObject*
-xmlparser_parse_whole(XMLParserObject* self, PyObject* args)
-{
-    /* (internal) parse the whole input, until end of stream */
-    PyObject* reader;
-    PyObject* buffer;
-    PyObject* temp;
-    PyObject* res;
-
-    PyObject* fileobj;
-    if (!PyArg_ParseTuple(args, "O:_parse", &fileobj))
-        return NULL;
-
-    reader = PyObject_GetAttrString(fileobj, "read");
-    if (!reader)
-        return NULL;
-
-    /* read from open file object */
-    for (;;) {
-
-        buffer = PyObject_CallFunction(reader, "i", 64*1024);
-
-        if (!buffer) {
-            /* read failed (e.g. due to KeyboardInterrupt) */
-            Py_DECREF(reader);
-            return NULL;
-        }
-
-        if (PyUnicode_CheckExact(buffer)) {
-            /* A unicode object is encoded into bytes using UTF-8 */
-            if (PyUnicode_GET_LENGTH(buffer) == 0) {
-                Py_DECREF(buffer);
-                break;
-            }
-            temp = PyUnicode_AsEncodedString(buffer, "utf-8", "surrogatepass");
-            Py_DECREF(buffer);
-            if (!temp) {
-                /* Propagate exception from PyUnicode_AsEncodedString */
-                Py_DECREF(reader);
-                return NULL;
-            }
-            buffer = temp;
-        }
-        else if (!PyBytes_CheckExact(buffer) || PyBytes_GET_SIZE(buffer) == 0) {
-            Py_DECREF(buffer);
-            break;
-        }
-
-        if (PyBytes_GET_SIZE(buffer) > INT_MAX) {
-            Py_DECREF(buffer);
-            Py_DECREF(reader);
-            PyErr_SetString(PyExc_OverflowError, "size does not fit in an int");
-            return NULL;
-        }
-        res = expat_parse(
-            self, PyBytes_AS_STRING(buffer), (int)PyBytes_GET_SIZE(buffer), 0
-            );
-
-        Py_DECREF(buffer);
-
-        if (!res) {
-            Py_DECREF(reader);
-            return NULL;
-        }
-        Py_DECREF(res);
-
-    }
-
-    Py_DECREF(reader);
-
-    res = expat_parse(self, "", 0, 1);
-
-    if (res && TreeBuilder_CheckExact(self->target)) {
-        Py_DECREF(res);
-        return treebuilder_done((TreeBuilderObject*) self->target);
-    }
-
-    return res;
-}
-
-static PyObject*
-xmlparser_doctype(XMLParserObject *self, PyObject *args)
-{
-    Py_RETURN_NONE;
-}
-
-static PyObject*
-xmlparser_setevents(XMLParserObject *self, PyObject* args)
-{
-    /* activate element event reporting */
-    Py_ssize_t i, seqlen;
-    TreeBuilderObject *target;
-
+    PyObject *return_value = NULL;
     PyObject *events_queue;
     PyObject *events_to_report = Py_None;
-    PyObject *events_seq;
-    if (!PyArg_ParseTuple(args, "O!|O:_setevents",  &PyList_Type, &events_queue,
-                          &events_to_report))
-        return NULL;
 
-    if (!TreeBuilder_CheckExact(self->target)) {
-        PyErr_SetString(
-            PyExc_TypeError,
-            "event handling only supported for ElementTree.TreeBuilder "
-            "targets"
-            );
-        return NULL;
-    }
+    if (!PyArg_ParseTuple(args, "O!|O:_setevents",
+        &PyList_Type, &events_queue, &events_to_report))
+        goto exit;
+    return_value = _elementtree_XMLParser__setevents_impl(self, events_queue, events_to_report);
 
-    target = (TreeBuilderObject*) self->target;
-
-    Py_INCREF(events_queue);
-    Py_XDECREF(target->events);
-    target->events = events_queue;
-
-    /* clear out existing events */
-    Py_CLEAR(target->start_event_obj);
-    Py_CLEAR(target->end_event_obj);
-    Py_CLEAR(target->start_ns_event_obj);
-    Py_CLEAR(target->end_ns_event_obj);
-
-    if (events_to_report == Py_None) {
-        /* default is "end" only */
-        target->end_event_obj = PyUnicode_FromString("end");
-        Py_RETURN_NONE;
-    }
-
-    if (!(events_seq = PySequence_Fast(events_to_report,
-                                       "events must be a sequence"))) {
-        return NULL;
-    }
-
-    seqlen = PySequence_Size(events_seq);
-    for (i = 0; i < seqlen; ++i) {
-        PyObject *event_name_obj = PySequence_Fast_GET_ITEM(events_seq, i);
-        char *event_name = NULL;
-        if (PyUnicode_Check(event_name_obj)) {
-            event_name = _PyUnicode_AsString(event_name_obj);
-        } else if (PyBytes_Check(event_name_obj)) {
-            event_name = PyBytes_AS_STRING(event_name_obj);
-        }
-
-        if (event_name == NULL) {
-            Py_DECREF(events_seq);
-            PyErr_Format(PyExc_ValueError, "invalid events sequence");
-            return NULL;
-        } else if (strcmp(event_name, "start") == 0) {
-            Py_INCREF(event_name_obj);
-            target->start_event_obj = event_name_obj;
-        } else if (strcmp(event_name, "end") == 0) {
-            Py_INCREF(event_name_obj);
-            Py_XDECREF(target->end_event_obj);
-            target->end_event_obj = event_name_obj;
-        } else if (strcmp(event_name, "start-ns") == 0) {
-            Py_INCREF(event_name_obj);
-            Py_XDECREF(target->start_ns_event_obj);
-            target->start_ns_event_obj = event_name_obj;
-            EXPAT(SetNamespaceDeclHandler)(
-                self->parser,
-                (XML_StartNamespaceDeclHandler) expat_start_ns_handler,
-                (XML_EndNamespaceDeclHandler) expat_end_ns_handler
-                );
-        } else if (strcmp(event_name, "end-ns") == 0) {
-            Py_INCREF(event_name_obj);
-            Py_XDECREF(target->end_ns_event_obj);
-            target->end_ns_event_obj = event_name_obj;
-            EXPAT(SetNamespaceDeclHandler)(
-                self->parser,
-                (XML_StartNamespaceDeclHandler) expat_start_ns_handler,
-                (XML_EndNamespaceDeclHandler) expat_end_ns_handler
-                );
-        } else {
-            Py_DECREF(events_seq);
-            PyErr_Format(PyExc_ValueError, "unknown event '%s'", event_name);
-            return NULL;
-        }
-    }
-
-    Py_DECREF(events_seq);
-    Py_RETURN_NONE;
+exit:
+    return return_value;
 }
-
-static PyMethodDef xmlparser_methods[] = {
-    {"feed", (PyCFunction) xmlparser_feed, METH_O},
-    {"close", (PyCFunction) xmlparser_close, METH_VARARGS},
-    {"_parse_whole", (PyCFunction) xmlparser_parse_whole, METH_VARARGS},
-    {"_setevents", (PyCFunction) xmlparser_setevents, METH_VARARGS},
-    {"doctype", (PyCFunction) xmlparser_doctype, METH_VARARGS},
-    {NULL, NULL}
-};
-
-static PyObject*
-xmlparser_getattro(XMLParserObject* self, PyObject* nameobj)
-{
-    if (PyUnicode_Check(nameobj)) {
-        PyObject* res;
-        if (PyUnicode_CompareWithASCIIString(nameobj, "entity") == 0)
-            res = self->entity;
-        else if (PyUnicode_CompareWithASCIIString(nameobj, "target") == 0)
-            res = self->target;
-        else if (PyUnicode_CompareWithASCIIString(nameobj, "version") == 0) {
-            return PyUnicode_FromFormat(
-                "Expat %d.%d.%d", XML_MAJOR_VERSION,
-                XML_MINOR_VERSION, XML_MICRO_VERSION);
-        }
-        else
-            goto generic;
-
-        Py_INCREF(res);
-        return res;
-    }
-  generic:
-    return PyObject_GenericGetAttr((PyObject*) self, nameobj);
-}
-
-static PyTypeObject XMLParser_Type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "xml.etree.ElementTree.XMLParser", sizeof(XMLParserObject), 0,
-    /* methods */
-    (destructor)xmlparser_dealloc,                  /* tp_dealloc */
-    0,                                              /* tp_print */
-    0,                                              /* tp_getattr */
-    0,                                              /* tp_setattr */
-    0,                                              /* tp_reserved */
-    0,                                              /* tp_repr */
-    0,                                              /* tp_as_number */
-    0,                                              /* tp_as_sequence */
-    0,                                              /* tp_as_mapping */
-    0,                                              /* tp_hash */
-    0,                                              /* tp_call */
-    0,                                              /* tp_str */
-    (getattrofunc)xmlparser_getattro,               /* tp_getattro */
-    0,                                              /* tp_setattro */
-    0,                                              /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
-                                                    /* tp_flags */
-    0,                                              /* tp_doc */
-    (traverseproc)xmlparser_gc_traverse,            /* tp_traverse */
-    (inquiry)xmlparser_gc_clear,                    /* tp_clear */
-    0,                                              /* tp_richcompare */
-    0,                                              /* tp_weaklistoffset */
-    0,                                              /* tp_iter */
-    0,                                              /* tp_iternext */
-    xmlparser_methods,                              /* tp_methods */
-    0,                                              /* tp_members */
-    0,                                              /* tp_getset */
-    0,                                              /* tp_base */
-    0,                                              /* tp_dict */
-    0,                                              /* tp_descr_get */
-    0,                                              /* tp_descr_set */
-    0,                                              /* tp_dictoffset */
-    (initproc)xmlparser_init,                       /* tp_init */
-    PyType_GenericAlloc,                            /* tp_alloc */
-    xmlparser_new,                                  /* tp_new */
-    0,                                              /* tp_free */
-};
-
-/* ==================================================================== */
-/* python module interface */
-
-static PyMethodDef _functions[] = {
-    {"SubElement", (PyCFunction) subelement, METH_VARARGS | METH_KEYWORDS},
-    {NULL, NULL}
-};
-
-
-static struct PyModuleDef elementtreemodule = {
-    PyModuleDef_HEAD_INIT,
-    "_elementtree",
-    NULL,
-    sizeof(elementtreestate),
-    _functions,
-    NULL,
-    elementtree_traverse,
-    elementtree_clear,
-    elementtree_free
-};
-
-PyMODINIT_FUNC
-PyInit__elementtree(void)
-{
-    PyObject *m, *temp;
-    elementtreestate *st;
-
-    m = PyState_FindModule(&elementtreemodule);
-    if (m) {
-        Py_INCREF(m);
-        return m;
-    }
-
-    /* Initialize object types */
-    if (PyType_Ready(&ElementIter_Type) < 0)
-        return NULL;
-    if (PyType_Ready(&TreeBuilder_Type) < 0)
-        return NULL;
-    if (PyType_Ready(&Element_Type) < 0)
-        return NULL;
-    if (PyType_Ready(&XMLParser_Type) < 0)
-        return NULL;
-
-    m = PyModule_Create(&elementtreemodule);
-    if (!m)
-        return NULL;
-    st = ET_STATE(m);
-
-    if (!(temp = PyImport_ImportModule("copy")))
-        return NULL;
-    st->deepcopy_obj = PyObject_GetAttrString(temp, "deepcopy");
-    Py_XDECREF(temp);
-
-    if (!(st->elementpath_obj = PyImport_ImportModule("xml.etree.ElementPath")))
-        return NULL;
-
-    /* link against pyexpat */
-    expat_capi = PyCapsule_Import(PyExpat_CAPSULE_NAME, 0);
-    if (expat_capi) {
-        /* check that it's usable */
-        if (strcmp(expat_capi->magic, PyExpat_CAPI_MAGIC) != 0 ||
-            (size_t)expat_capi->size < sizeof(struct PyExpat_CAPI) ||
-            expat_capi->MAJOR_VERSION != XML_MAJOR_VERSION ||
-            expat_capi->MINOR_VERSION != XML_MINOR_VERSION ||
-            expat_capi->MICRO_VERSION != XML_MICRO_VERSION) {
-            PyErr_SetString(PyExc_ImportError,
-                            "pyexpat version is incompatible");
-            return NULL;
-        }
-    } else {
-        return NULL;
-    }
-
-    st->parseerror_obj = PyErr_NewException(
-        "xml.etree.ElementTree.ParseError", PyExc_SyntaxError, NULL
-        );
-    Py_INCREF(st->parseerror_obj);
-    PyModule_AddObject(m, "ParseError", st->parseerror_obj);
-
-    Py_INCREF((PyObject *)&Element_Type);
-    PyModule_AddObject(m, "Element", (PyObject *)&Element_Type);
-
-    Py_INCREF((PyObject *)&TreeBuilder_Type);
-    PyModule_AddObject(m, "TreeBuilder", (PyObject *)&TreeBuilder_Type);
-
-    Py_INCREF((PyObject *)&XMLParser_Type);
-    PyModule_AddObject(m, "XMLParser", (PyObject *)&XMLParser_Type);
-
-    return m;
-}
+/*[clinic end generated code: output=119aed84c1545187 input=a9049054013a1b77]*/

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list