From 76641a34ace5759fa7f1725451677f19475e5d13 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 20 Nov 2020 20:42:39 +0100 Subject: [PATCH 01/23] Prepare init function --- Modules/_elementtree.c | 42 +++++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 85fdfa7e5ed42c..caf535990a2f07 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -4382,11 +4382,19 @@ static struct PyModuleDef elementtreemodule = { elementtree_free }; +#define CREATE_TYPE(module, type, spec) \ +do { \ + type = (PyTypeObject *)PyType_FromModuleAndSpec(module, spec, NULL); \ + if (type == NULL) { \ + goto error; \ + } \ +} while (0) + PyMODINIT_FUNC PyInit__elementtree(void) { - PyObject *m, *temp; - elementtreestate *st; + PyObject *m = NULL, *temp; + elementtreestate *st = NULL; m = PyState_FindModule(&elementtreemodule); if (m) { @@ -4396,31 +4404,31 @@ PyInit__elementtree(void) /* Initialize object types */ if (PyType_Ready(&ElementIter_Type) < 0) - return NULL; + goto error; if (PyType_Ready(&TreeBuilder_Type) < 0) - return NULL; + goto error; if (PyType_Ready(&Element_Type) < 0) - return NULL; + goto error; if (PyType_Ready(&XMLParser_Type) < 0) - return NULL; + goto error; m = PyModule_Create(&elementtreemodule); if (!m) - return NULL; + goto error; st = get_elementtree_state(m); if (!(temp = PyImport_ImportModule("copy"))) - return NULL; + goto error; st->deepcopy_obj = PyObject_GetAttrString(temp, "deepcopy"); Py_XDECREF(temp); if (st->deepcopy_obj == NULL) { - return NULL; + goto error; } assert(!PyErr_Occurred()); if (!(st->elementpath_obj = PyImport_ImportModule("xml.etree.ElementPath"))) - return NULL; + goto error; /* link against pyexpat */ expat_capi = PyCapsule_Import(PyExpat_CAPSULE_NAME, 0); @@ -4433,10 +4441,10 @@ PyInit__elementtree(void) expat_capi->MICRO_VERSION != XML_MICRO_VERSION) { PyErr_SetString(PyExc_ImportError, "pyexpat version is incompatible"); - return NULL; + goto error; } } else { - return NULL; + goto error; } st->parseerror_obj = PyErr_NewException( @@ -4444,8 +4452,7 @@ PyInit__elementtree(void) ); Py_INCREF(st->parseerror_obj); if (PyModule_AddObject(m, "ParseError", st->parseerror_obj) < 0) { - Py_DECREF(st->parseerror_obj); - return NULL; + goto error; } PyTypeObject *types[] = { @@ -4456,9 +4463,14 @@ PyInit__elementtree(void) for (size_t i = 0; i < Py_ARRAY_LENGTH(types); i++) { if (PyModule_AddType(m, types[i]) < 0) { - return NULL; + goto error; } } return m; + +error: + Py_XDECREF(st->parseerror_obj); + Py_XDECREF(m); + return NULL; } From 5cbbe163395ac0e0e95e7165831bd175df47c236 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 20 Nov 2020 20:46:19 +0100 Subject: [PATCH 02/23] Convert element type to heap type --- Modules/_elementtree.c | 120 +++++++++++++------------------- Modules/clinic/_elementtree.c.h | 14 ++-- 2 files changed, 56 insertions(+), 78 deletions(-) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index caf535990a2f07..a6c263d4cdfec9 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -81,7 +81,7 @@ static void _clear_joined_ptr(PyObject **p) } /* Types defined by this extension */ -static PyTypeObject Element_Type; +static PyTypeObject *Element_Type; static PyTypeObject ElementIter_Type; static PyTypeObject TreeBuilder_Type; static PyTypeObject XMLParser_Type; @@ -215,8 +215,8 @@ typedef struct { } ElementObject; -#define Element_CheckExact(op) Py_IS_TYPE(op, &Element_Type) -#define Element_Check(op) PyObject_TypeCheck(op, &Element_Type) +#define Element_CheckExact(op) Py_IS_TYPE(op, Element_Type) +#define Element_Check(op) PyObject_TypeCheck(op, Element_Type) /* -------------------------------------------------------------------- */ @@ -284,7 +284,7 @@ create_new_element(PyObject* tag, PyObject* attrib) { ElementObject* self; - self = PyObject_GC_New(ElementObject, &Element_Type); + self = PyObject_GC_New(ElementObject, Element_Type); if (self == NULL) return NULL; self->extra = NULL; @@ -381,11 +381,11 @@ get_attrib_from_keywords(PyObject *kwds) /*[clinic input] module _elementtree -class _elementtree.Element "ElementObject *" "&Element_Type" +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]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=f56d497fee3f9c95]*/ static int element_init(PyObject *self, PyObject *args, PyObject *kwds) @@ -594,7 +594,7 @@ subelement(PyObject *self, PyObject *args, PyObject *kwds) PyObject* tag; PyObject* attrib = NULL; if (!PyArg_ParseTuple(args, "O!O|O!:SubElement", - &Element_Type, &parent, &tag, + Element_Type, &parent, &tag, &PyDict_Type, &attrib)) { return NULL; } @@ -676,7 +676,9 @@ element_dealloc(ElementObject* self) element_gc_clear(self); RELEASE(sizeof(ElementObject), "destroy element"); - Py_TYPE(self)->tp_free((PyObject *)self); + PyTypeObject *tp = Py_TYPE(self); + tp->tp_free(self); + Py_DECREF(tp); Py_TRASHCAN_END } @@ -685,14 +687,14 @@ element_dealloc(ElementObject* self) /*[clinic input] _elementtree.Element.append - subelement: object(subclass_of='&Element_Type') + 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]*/ +/*[clinic end generated code: output=54a884b7cf2295f4 input=59866b732e6e2891]*/ { if (element_add_subelement(self, subelement) < 0) return NULL; @@ -1475,7 +1477,7 @@ element_getitem(PyObject* self_, Py_ssize_t index) _elementtree.Element.insert index: Py_ssize_t - subelement: object(subclass_of='&Element_Type') + subelement: object(subclass_of='Element_Type') / [clinic start generated code]*/ @@ -1483,7 +1485,7 @@ _elementtree.Element.insert static PyObject * _elementtree_Element_insert_impl(ElementObject *self, Py_ssize_t index, PyObject *subelement) -/*[clinic end generated code: output=990adfef4d424c0b input=cd6fbfcdab52d7a8]*/ +/*[clinic end generated code: output=990adfef4d424c0b input=4382c42ab2659f9b]*/ { Py_ssize_t i; @@ -1583,14 +1585,14 @@ _elementtree_Element_makeelement_impl(ElementObject *self, PyObject *tag, /*[clinic input] _elementtree.Element.remove - subelement: object(subclass_of='&Element_Type') + 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]*/ +/*[clinic end generated code: output=38fe6c07d6d87d1f input=cbdf9f2ab34d93b0]*/ { Py_ssize_t i; int rc; @@ -2052,16 +2054,6 @@ element_attrib_setter(ElementObject *self, PyObject *value, void *closure) return 0; } -static PySequenceMethods element_as_sequence = { - (lenfunc) element_length, - 0, /* sq_concat */ - 0, /* sq_repeat */ - element_getitem, - 0, - element_setitem, - 0, -}; - /******************************* Element iterator ****************************/ /* ElementIterObject represents the iteration state over an XML element in @@ -4190,10 +4182,9 @@ static PyMethodDef element_methods[] = { {NULL, NULL} }; -static PyMappingMethods element_as_mapping = { - (lenfunc) element_length, - (binaryfunc) element_subscr, - (objobjargproc) element_ass_subscr, +static struct PyMemberDef element_members[] = { + {"__weaklistoffset__", T_PYSSIZET, offsetof(ElementObject, weakreflist), READONLY}, + {NULL}, }; static PyGetSetDef element_getsetlist[] = { @@ -4216,48 +4207,36 @@ static PyGetSetDef element_getsetlist[] = { {NULL}, }; -static PyTypeObject Element_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "xml.etree.ElementTree.Element", sizeof(ElementObject), 0, - /* methods */ - (destructor)element_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - (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 */ - PyObject_GenericGetAttr, /* 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)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 */ - element_getsetlist, /* 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 PyType_Slot element_slots[] = { + {Py_tp_dealloc, element_dealloc}, + {Py_tp_repr, element_repr}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_traverse, element_gc_traverse}, + {Py_tp_clear, element_gc_clear}, + {Py_tp_methods, element_methods}, + {Py_tp_members, element_members}, + {Py_tp_getset, element_getsetlist}, + {Py_tp_init, element_init}, + {Py_tp_alloc, PyType_GenericAlloc}, + {Py_tp_new, element_new}, + {Py_sq_length, element_length}, + {Py_sq_item, element_getitem}, + {Py_sq_ass_item, element_setitem}, + {Py_mp_length, element_length}, + {Py_mp_subscript, element_subscr}, + {Py_mp_ass_subscript, element_ass_subscr}, + {0, NULL}, }; +static PyType_Spec element_spec = { + .name = "xml.etree.ElementTree.Element", + .basicsize = sizeof(ElementObject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, + .slots = element_slots, +}; + +static PyTypeObject *Element_Type = NULL; + static PyMethodDef treebuilder_methods[] = { _ELEMENTTREE_TREEBUILDER_DATA_METHODDEF _ELEMENTTREE_TREEBUILDER_START_METHODDEF @@ -4407,8 +4386,7 @@ PyInit__elementtree(void) goto error; if (PyType_Ready(&TreeBuilder_Type) < 0) goto error; - if (PyType_Ready(&Element_Type) < 0) - goto error; + CREATE_TYPE(m, Element_Type, &element_spec); if (PyType_Ready(&XMLParser_Type) < 0) goto error; @@ -4456,7 +4434,7 @@ PyInit__elementtree(void) } PyTypeObject *types[] = { - &Element_Type, + Element_Type, &TreeBuilder_Type, &XMLParser_Type }; diff --git a/Modules/clinic/_elementtree.c.h b/Modules/clinic/_elementtree.c.h index 2c9ba47823bf43..28d53e33d3c0c7 100644 --- a/Modules/clinic/_elementtree.c.h +++ b/Modules/clinic/_elementtree.c.h @@ -19,8 +19,8 @@ _elementtree_Element_append(ElementObject *self, PyObject *arg) PyObject *return_value = NULL; PyObject *subelement; - if (!PyObject_TypeCheck(arg, &Element_Type)) { - _PyArg_BadArgument("append", "argument", (&Element_Type)->tp_name, arg); + if (!PyObject_TypeCheck(arg, Element_Type)) { + _PyArg_BadArgument("append", "argument", (Element_Type)->tp_name, arg); goto exit; } subelement = arg; @@ -442,8 +442,8 @@ _elementtree_Element_insert(ElementObject *self, PyObject *const *args, Py_ssize } index = ival; } - if (!PyObject_TypeCheck(args[1], &Element_Type)) { - _PyArg_BadArgument("insert", "argument 2", (&Element_Type)->tp_name, args[1]); + if (!PyObject_TypeCheck(args[1], Element_Type)) { + _PyArg_BadArgument("insert", "argument 2", (Element_Type)->tp_name, args[1]); goto exit; } subelement = args[1]; @@ -538,8 +538,8 @@ _elementtree_Element_remove(ElementObject *self, PyObject *arg) PyObject *return_value = NULL; PyObject *subelement; - if (!PyObject_TypeCheck(arg, &Element_Type)) { - _PyArg_BadArgument("remove", "argument", (&Element_Type)->tp_name, arg); + if (!PyObject_TypeCheck(arg, Element_Type)) { + _PyArg_BadArgument("remove", "argument", (Element_Type)->tp_name, arg); goto exit; } subelement = arg; @@ -915,4 +915,4 @@ _elementtree_XMLParser__setevents(XMLParserObject *self, PyObject *const *args, exit: return return_value; } -/*[clinic end generated code: output=1385b5e5688f3614 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5ea065ac45181d56 input=a9049054013a1b77]*/ From 116fa39aa2b04cf142ae883045de9d33437956f7 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 20 Nov 2020 20:51:01 +0100 Subject: [PATCH 03/23] Convert element iter type to heap type --- Modules/_elementtree.c | 63 +++++++++++++----------------------------- 1 file changed, 19 insertions(+), 44 deletions(-) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index a6c263d4cdfec9..9b0d3aa0e64bb3 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -82,7 +82,7 @@ static void _clear_joined_ptr(PyObject **p) /* Types defined by this extension */ static PyTypeObject *Element_Type; -static PyTypeObject ElementIter_Type; +static PyTypeObject *ElementIter_Type; static PyTypeObject TreeBuilder_Type; static PyTypeObject XMLParser_Type; @@ -2095,6 +2095,8 @@ elementiter_dealloc(ElementIterObject *it) Py_XDECREF(it->root_element); PyObject_GC_Del(it); + PyTypeObject *tp = Py_TYPE(it); + Py_DECREF(tp); } static int @@ -2238,51 +2240,25 @@ elementiter_next(ElementIterObject *it) return NULL; } +static PyType_Slot elementiter_slots[] = { + {Py_tp_dealloc, elementiter_dealloc}, + {Py_tp_traverse, elementiter_traverse}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, elementiter_next}, + {0, NULL}, +}; -static PyTypeObject ElementIter_Type = { - PyVarObject_HEAD_INIT(NULL, 0) +static PyType_Spec elementiter_spec = { /* 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_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 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 */ + .name = "_elementtree._element_iterator", + .basicsize = sizeof(ElementIterObject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + .slots = elementiter_slots, }; +static PyTypeObject *ElementIter_Type = NULL; + #define INIT_PARENT_STACK_SIZE 8 static PyObject * @@ -2290,7 +2266,7 @@ create_elementiter(ElementObject *self, PyObject *tag, int gettext) { ElementIterObject *it; - it = PyObject_GC_New(ElementIterObject, &ElementIter_Type); + it = PyObject_GC_New(ElementIterObject, ElementIter_Type); if (!it) return NULL; @@ -4382,8 +4358,7 @@ PyInit__elementtree(void) } /* Initialize object types */ - if (PyType_Ready(&ElementIter_Type) < 0) - goto error; + CREATE_TYPE(m, ElementIter_Type, &elementiter_spec); if (PyType_Ready(&TreeBuilder_Type) < 0) goto error; CREATE_TYPE(m, Element_Type, &element_spec); From a792fcf1db9a2db1efa5979094f21ab18a1cdada Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 20 Nov 2020 20:55:34 +0100 Subject: [PATCH 04/23] Convert tree builder type to heap type --- Modules/_elementtree.c | 76 ++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 48 deletions(-) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 9b0d3aa0e64bb3..4ddea7a25cb011 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -83,7 +83,7 @@ static void _clear_joined_ptr(PyObject **p) /* Types defined by this extension */ static PyTypeObject *Element_Type; static PyTypeObject *ElementIter_Type; -static PyTypeObject TreeBuilder_Type; +static PyTypeObject *TreeBuilder_Type; static PyTypeObject XMLParser_Type; @@ -382,7 +382,7 @@ get_attrib_from_keywords(PyObject *kwds) /*[clinic input] module _elementtree class _elementtree.Element "ElementObject *" "Element_Type" -class _elementtree.TreeBuilder "TreeBuilderObject *" "&TreeBuilder_Type" +class _elementtree.TreeBuilder "TreeBuilderObject *" "TreeBuilder_Type" class _elementtree.XMLParser "XMLParserObject *" "&XMLParser_Type" [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=f56d497fee3f9c95]*/ @@ -2325,7 +2325,7 @@ typedef struct { char insert_pis; } TreeBuilderObject; -#define TreeBuilder_CheckExact(op) Py_IS_TYPE((op), &TreeBuilder_Type) +#define TreeBuilder_CheckExact(op) Py_IS_TYPE((op), TreeBuilder_Type) /* -------------------------------------------------------------------- */ /* constructor and destructor */ @@ -2469,7 +2469,10 @@ treebuilder_dealloc(TreeBuilderObject *self) { PyObject_GC_UnTrack(self); treebuilder_gc_clear(self); - Py_TYPE(self)->tp_free((PyObject *)self); + + PyTypeObject *tp = Py_TYPE(self); + tp->tp_free(self); + Py_DECREF(tp); } /* -------------------------------------------------------------------- */ @@ -3643,7 +3646,7 @@ _elementtree_XMLParser___init___impl(XMLParserObject *self, PyObject *target, if (target) { Py_INCREF(target); } else { - target = treebuilder_new(&TreeBuilder_Type, NULL, NULL); + target = treebuilder_new(TreeBuilder_Type, NULL, NULL); if (!target) { Py_CLEAR(self->entity); Py_CLEAR(self->names); @@ -4223,48 +4226,26 @@ static PyMethodDef treebuilder_methods[] = { {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_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 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 */ - _elementtree_TreeBuilder___init__, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ - treebuilder_new, /* tp_new */ - 0, /* tp_free */ +static PyType_Slot treebuilder_slots[] = { + {Py_tp_dealloc, treebuilder_dealloc}, + {Py_tp_traverse, treebuilder_gc_traverse}, + {Py_tp_clear, treebuilder_gc_clear}, + {Py_tp_methods, treebuilder_methods}, + {Py_tp_init, _elementtree_TreeBuilder___init__}, + {Py_tp_alloc, PyType_GenericAlloc}, + {Py_tp_new, treebuilder_new}, + {0, NULL}, }; +static PyType_Spec treebuilder_spec = { + .name = "xml.etree.ElementTree.TreeBuilder", + .basicsize = sizeof(TreeBuilderObject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, + .slots = treebuilder_slots, +}; + +static PyTypeObject *TreeBuilder_Type = NULL; + static PyMethodDef xmlparser_methods[] = { _ELEMENTTREE_XMLPARSER_FEED_METHODDEF _ELEMENTTREE_XMLPARSER_CLOSE_METHODDEF @@ -4359,8 +4340,7 @@ PyInit__elementtree(void) /* Initialize object types */ CREATE_TYPE(m, ElementIter_Type, &elementiter_spec); - if (PyType_Ready(&TreeBuilder_Type) < 0) - goto error; + CREATE_TYPE(m, TreeBuilder_Type, &treebuilder_spec); CREATE_TYPE(m, Element_Type, &element_spec); if (PyType_Ready(&XMLParser_Type) < 0) goto error; @@ -4410,7 +4390,7 @@ PyInit__elementtree(void) PyTypeObject *types[] = { Element_Type, - &TreeBuilder_Type, + TreeBuilder_Type, &XMLParser_Type }; From 341a92ddaf8a065339d779a22374ce46db18ba75 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 20 Nov 2020 21:02:18 +0100 Subject: [PATCH 05/23] Convert xml parser type to heap type --- Modules/_elementtree.c | 74 ++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 46 deletions(-) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 4ddea7a25cb011..8d427d884b35a3 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -84,7 +84,7 @@ static void _clear_joined_ptr(PyObject **p) static PyTypeObject *Element_Type; static PyTypeObject *ElementIter_Type; static PyTypeObject *TreeBuilder_Type; -static PyTypeObject XMLParser_Type; +static PyTypeObject *XMLParser_Type; /* Per-module state; PEP 3121 */ @@ -383,7 +383,7 @@ get_attrib_from_keywords(PyObject *kwds) module _elementtree class _elementtree.Element "ElementObject *" "Element_Type" class _elementtree.TreeBuilder "TreeBuilderObject *" "TreeBuilder_Type" -class _elementtree.XMLParser "XMLParserObject *" "&XMLParser_Type" +class _elementtree.XMLParser "XMLParserObject *" "XMLParser_Type" [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=f56d497fee3f9c95]*/ @@ -3786,7 +3786,10 @@ xmlparser_dealloc(XMLParserObject* self) { PyObject_GC_UnTrack(self); xmlparser_gc_clear(self); - Py_TYPE(self)->tp_free((PyObject *)self); + + PyTypeObject *tp = Py_TYPE(self); + tp->tp_free(self); + Py_DECREF(tp); } Py_LOCAL_INLINE(int) @@ -4254,48 +4257,28 @@ static PyMethodDef xmlparser_methods[] = { {NULL, NULL} }; -static PyTypeObject XMLParser_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "xml.etree.ElementTree.XMLParser", sizeof(XMLParserObject), 0, - /* methods */ - (destructor)xmlparser_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 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)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 */ - xmlparser_members, /* tp_members */ - xmlparser_getsetlist, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - _elementtree_XMLParser___init__, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ - xmlparser_new, /* tp_new */ - 0, /* tp_free */ +static PyType_Slot xmlparser_slots[] = { + {Py_tp_dealloc, xmlparser_dealloc}, + {Py_tp_traverse, xmlparser_gc_traverse}, + {Py_tp_clear, xmlparser_gc_clear}, + {Py_tp_methods, xmlparser_methods}, + {Py_tp_members, xmlparser_members}, + {Py_tp_getset, xmlparser_getsetlist}, + {Py_tp_init, _elementtree_XMLParser___init__}, + {Py_tp_alloc, PyType_GenericAlloc}, + {Py_tp_new, xmlparser_new}, + {0, NULL}, }; +static PyType_Spec xmlparser_spec = { + .name = "xml.etree.ElementTree.XMLParser", + .basicsize = sizeof(XMLParserObject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, + .slots = xmlparser_slots, +}; + +static PyTypeObject *XMLParser_Type = NULL; + /* ==================================================================== */ /* python module interface */ @@ -4342,8 +4325,7 @@ PyInit__elementtree(void) CREATE_TYPE(m, ElementIter_Type, &elementiter_spec); CREATE_TYPE(m, TreeBuilder_Type, &treebuilder_spec); CREATE_TYPE(m, Element_Type, &element_spec); - if (PyType_Ready(&XMLParser_Type) < 0) - goto error; + CREATE_TYPE(m, XMLParser_Type, &xmlparser_spec); m = PyModule_Create(&elementtreemodule); if (!m) @@ -4391,7 +4373,7 @@ PyInit__elementtree(void) PyTypeObject *types[] = { Element_Type, TreeBuilder_Type, - &XMLParser_Type + XMLParser_Type }; for (size_t i = 0; i < Py_ARRAY_LENGTH(types); i++) { From f35c604d283a4cf70ec751651be1e57bcacb9be7 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 20 Nov 2020 21:05:13 +0100 Subject: [PATCH 06/23] Update clinic --- Modules/_elementtree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 8d427d884b35a3..909809f01ad1a1 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -385,7 +385,7 @@ 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=f56d497fee3f9c95]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=1ecdb32b55d9d5de]*/ static int element_init(PyObject *self, PyObject *args, PyObject *kwds) From b6573b1bd038a10b73fdd2b45cb4e0da8120e7fe Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 20 Nov 2020 21:06:53 +0100 Subject: [PATCH 07/23] Add NEWS --- .../NEWS.d/next/Library/2020-11-20-21-06-08.bpo-40077.M-iZq3.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2020-11-20-21-06-08.bpo-40077.M-iZq3.rst diff --git a/Misc/NEWS.d/next/Library/2020-11-20-21-06-08.bpo-40077.M-iZq3.rst b/Misc/NEWS.d/next/Library/2020-11-20-21-06-08.bpo-40077.M-iZq3.rst new file mode 100644 index 00000000000000..567aed55ffcbff --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-11-20-21-06-08.bpo-40077.M-iZq3.rst @@ -0,0 +1 @@ +Convert `_elementtree` type to heap types. Patch by Erlend E. Aasland From 404b398d69313a941b1dae753613f8066f00f4bd Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 20 Nov 2020 21:15:29 +0100 Subject: [PATCH 08/23] Use PyModule_AddObjectRef --- Modules/_elementtree.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 909809f01ad1a1..f1268e2ac0e1cb 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -4366,7 +4366,9 @@ PyInit__elementtree(void) "xml.etree.ElementTree.ParseError", PyExc_SyntaxError, NULL ); Py_INCREF(st->parseerror_obj); - if (PyModule_AddObject(m, "ParseError", st->parseerror_obj) < 0) { + int res = PyModule_AddObjectRef(m, "ParseError", st->parseerror_obj); + Py_DECREF(st->parseerror_obj); + if (res < 0) { goto error; } @@ -4385,7 +4387,6 @@ PyInit__elementtree(void) return m; error: - Py_XDECREF(st->parseerror_obj); Py_XDECREF(m); return NULL; } From 6e53e92da1f98c0376a8d135c1594fc20748e1e2 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 20 Nov 2020 22:44:22 +0100 Subject: [PATCH 09/23] Create module before creating types --- Modules/_elementtree.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index f1268e2ac0e1cb..327377b59e9a11 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -4321,17 +4321,17 @@ PyInit__elementtree(void) return m; } + m = PyModule_Create(&elementtreemodule); + if (!m) + goto error; + st = get_elementtree_state(m); + /* Initialize object types */ CREATE_TYPE(m, ElementIter_Type, &elementiter_spec); CREATE_TYPE(m, TreeBuilder_Type, &treebuilder_spec); CREATE_TYPE(m, Element_Type, &element_spec); CREATE_TYPE(m, XMLParser_Type, &xmlparser_spec); - m = PyModule_Create(&elementtreemodule); - if (!m) - goto error; - st = get_elementtree_state(m); - if (!(temp = PyImport_ImportModule("copy"))) goto error; st->deepcopy_obj = PyObject_GetAttrString(temp, "deepcopy"); From 525cfaff13289d39d0cd1a5fb051f1117ff5ca81 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 21 Nov 2020 11:43:18 +0100 Subject: [PATCH 10/23] Fetch type before GC --- Modules/_elementtree.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 327377b59e9a11..9cf8942eb66577 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -664,6 +664,8 @@ element_gc_clear(ElementObject *self) static void element_dealloc(ElementObject* self) { + PyTypeObject *tp = Py_TYPE(self); + /* bpo-31095: UnTrack is needed before calling any callbacks */ PyObject_GC_UnTrack(self); Py_TRASHCAN_BEGIN(self, element_dealloc) @@ -676,7 +678,6 @@ element_dealloc(ElementObject* self) element_gc_clear(self); RELEASE(sizeof(ElementObject), "destroy element"); - PyTypeObject *tp = Py_TYPE(self); tp->tp_free(self); Py_DECREF(tp); Py_TRASHCAN_END @@ -2083,6 +2084,7 @@ typedef struct { static void elementiter_dealloc(ElementIterObject *it) { + PyTypeObject *tp = Py_TYPE(it); Py_ssize_t i = it->parent_stack_used; it->parent_stack_used = 0; /* bpo-31095: UnTrack is needed before calling any callbacks */ @@ -2095,7 +2097,6 @@ elementiter_dealloc(ElementIterObject *it) Py_XDECREF(it->root_element); PyObject_GC_Del(it); - PyTypeObject *tp = Py_TYPE(it); Py_DECREF(tp); } @@ -2467,10 +2468,9 @@ treebuilder_gc_clear(TreeBuilderObject *self) static void treebuilder_dealloc(TreeBuilderObject *self) { + PyTypeObject *tp = Py_TYPE(self); PyObject_GC_UnTrack(self); treebuilder_gc_clear(self); - - PyTypeObject *tp = Py_TYPE(self); tp->tp_free(self); Py_DECREF(tp); } @@ -3784,10 +3784,9 @@ xmlparser_gc_clear(XMLParserObject *self) static void xmlparser_dealloc(XMLParserObject* self) { + PyTypeObject *tp = Py_TYPE(self); PyObject_GC_UnTrack(self); xmlparser_gc_clear(self); - - PyTypeObject *tp = Py_TYPE(self); tp->tp_free(self); Py_DECREF(tp); } From 2448e931616136441aa5bf1294ab426107b19396 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 21 Nov 2020 21:51:10 +0100 Subject: [PATCH 11/23] Add initialisation guard --- Modules/_elementtree.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 9cf8942eb66577..188342309f93eb 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -4302,6 +4302,9 @@ static struct PyModuleDef elementtreemodule = { #define CREATE_TYPE(module, type, spec) \ do { \ + if (type != NULL) { \ + break; \ + } \ type = (PyTypeObject *)PyType_FromModuleAndSpec(module, spec, NULL); \ if (type == NULL) { \ goto error; \ From 959a225aa64e6605a6cbc21df90fef60a76f3b16 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Mon, 23 Nov 2020 12:09:45 +0100 Subject: [PATCH 12/23] Address Heime's review: Don't define globals twice --- Modules/_elementtree.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 188342309f93eb..1ae14ec794e5b1 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -2258,8 +2258,6 @@ static PyType_Spec elementiter_spec = { .slots = elementiter_slots, }; -static PyTypeObject *ElementIter_Type = NULL; - #define INIT_PARENT_STACK_SIZE 8 static PyObject * @@ -4216,8 +4214,6 @@ static PyType_Spec element_spec = { .slots = element_slots, }; -static PyTypeObject *Element_Type = NULL; - static PyMethodDef treebuilder_methods[] = { _ELEMENTTREE_TREEBUILDER_DATA_METHODDEF _ELEMENTTREE_TREEBUILDER_START_METHODDEF @@ -4246,8 +4242,6 @@ static PyType_Spec treebuilder_spec = { .slots = treebuilder_slots, }; -static PyTypeObject *TreeBuilder_Type = NULL; - static PyMethodDef xmlparser_methods[] = { _ELEMENTTREE_XMLPARSER_FEED_METHODDEF _ELEMENTTREE_XMLPARSER_CLOSE_METHODDEF @@ -4276,8 +4270,6 @@ static PyType_Spec xmlparser_spec = { .slots = xmlparser_slots, }; -static PyTypeObject *XMLParser_Type = NULL; - /* ==================================================================== */ /* python module interface */ From 9210a36179fc289243819f9fcf8ad3979bb5055d Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Mon, 11 Jan 2021 09:52:06 +0100 Subject: [PATCH 13/23] Visit type in type traverse functions --- Modules/_elementtree.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 1ae14ec794e5b1..7e213368a45c5d 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -633,6 +633,7 @@ subelement(PyObject *self, PyObject *args, PyObject *kwds) static int element_gc_traverse(ElementObject *self, visitproc visit, void *arg) { + Py_VISIT(Py_TYPE(self)); Py_VISIT(self->tag); Py_VISIT(JOIN_OBJ(self->text)); Py_VISIT(JOIN_OBJ(self->tail)); @@ -2096,7 +2097,7 @@ elementiter_dealloc(ElementIterObject *it) Py_XDECREF(it->sought_tag); Py_XDECREF(it->root_element); - PyObject_GC_Del(it); + tp->tp_free(it); Py_DECREF(tp); } @@ -2109,6 +2110,7 @@ elementiter_traverse(ElementIterObject *it, visitproc visit, void *arg) Py_VISIT(it->root_element); Py_VISIT(it->sought_tag); + Py_VISIT(Py_TYPE(it)); return 0; } @@ -2422,6 +2424,7 @@ _elementtree_TreeBuilder___init___impl(TreeBuilderObject *self, static int treebuilder_gc_traverse(TreeBuilderObject *self, visitproc visit, void *arg) { + Py_VISIT(Py_TYPE(self)); Py_VISIT(self->pi_event_obj); Py_VISIT(self->comment_event_obj); Py_VISIT(self->end_ns_event_obj); @@ -3736,6 +3739,7 @@ _elementtree_XMLParser___init___impl(XMLParserObject *self, PyObject *target, static int xmlparser_gc_traverse(XMLParserObject *self, visitproc visit, void *arg) { + Py_VISIT(Py_TYPE(self)); Py_VISIT(self->handle_close); Py_VISIT(self->handle_pi); Py_VISIT(self->handle_comment); From a6c6feab42185ace5751cebef9e82f72263cd4b6 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Mon, 11 Jan 2021 10:12:17 +0100 Subject: [PATCH 14/23] Fix NEWS formatting --- .../next/Library/2020-11-20-21-06-08.bpo-40077.M-iZq3.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2020-11-20-21-06-08.bpo-40077.M-iZq3.rst b/Misc/NEWS.d/next/Library/2020-11-20-21-06-08.bpo-40077.M-iZq3.rst index 567aed55ffcbff..8a74477a4b359d 100644 --- a/Misc/NEWS.d/next/Library/2020-11-20-21-06-08.bpo-40077.M-iZq3.rst +++ b/Misc/NEWS.d/next/Library/2020-11-20-21-06-08.bpo-40077.M-iZq3.rst @@ -1 +1 @@ -Convert `_elementtree` type to heap types. Patch by Erlend E. Aasland +Convert :mod:`elementtree` types to heap types. Patch by Erlend E. Aasland. From c8a3c67df3d42aa5d12cda7ee220f714ec246b43 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 18 Jan 2023 17:28:28 +0100 Subject: [PATCH 15/23] Address review: make types immutable --- Lib/test/test_xml_etree_c.py | 14 ++++++++++++++ Modules/_elementtree.c | 11 +++++++---- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_xml_etree_c.py b/Lib/test/test_xml_etree_c.py index bec8208571902e..fbb79a7f1c8f39 100644 --- a/Lib/test/test_xml_etree_c.py +++ b/Lib/test/test_xml_etree_c.py @@ -181,6 +181,20 @@ def __hash__(self): r = e.get(X()) self.assertIsNone(r) + @support.cpython_only + def test_immutable_types(self): + root = cET.fromstring('') + dataset = ( + cET.Element, + cET.TreeBuilder, + cET.XMLParser, + type(root.iter()), + ) + for tp in dataset: + with self.subTest(tp=tp): + with self.assertRaisesRegex(TypeError, "immutable"): + tp.foo = 1 + @unittest.skipUnless(cET, 'requires _elementtree') class TestAliasWorking(unittest.TestCase): diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index f670db9def6210..05619fb2c96d52 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -2193,7 +2193,8 @@ static PyType_Spec elementiter_spec = { have such a type. */ .name = "_elementtree._element_iterator", .basicsize = sizeof(ElementIterObject), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE), .slots = elementiter_slots, }; @@ -4120,7 +4121,8 @@ static PyType_Slot element_slots[] = { static PyType_Spec element_spec = { .name = "xml.etree.ElementTree.Element", .basicsize = sizeof(ElementObject), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE), .slots = element_slots, }; @@ -4148,7 +4150,7 @@ static PyType_Slot treebuilder_slots[] = { static PyType_Spec treebuilder_spec = { .name = "xml.etree.ElementTree.TreeBuilder", .basicsize = sizeof(TreeBuilderObject), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE, .slots = treebuilder_slots, }; @@ -4176,7 +4178,8 @@ static PyType_Slot xmlparser_slots[] = { static PyType_Spec xmlparser_spec = { .name = "xml.etree.ElementTree.XMLParser", .basicsize = sizeof(XMLParserObject), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE), .slots = xmlparser_slots, }; From 2175f66465aa5d480cbf6d7887be94a27cabb548 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Thu, 19 Jan 2023 12:34:41 +0100 Subject: [PATCH 16/23] Disallow instantiation for the iter type --- Lib/test/test_xml_etree_c.py | 6 ++++++ Modules/_elementtree.c | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_xml_etree_c.py b/Lib/test/test_xml_etree_c.py index fbb79a7f1c8f39..fd27b575ec8dc9 100644 --- a/Lib/test/test_xml_etree_c.py +++ b/Lib/test/test_xml_etree_c.py @@ -195,6 +195,12 @@ def test_immutable_types(self): with self.assertRaisesRegex(TypeError, "immutable"): tp.foo = 1 + @support.cpython_only + def test_disallow_instantiation(self): + root = cET.fromstring('') + iter_type = type(root.iter()) + support.check_disallow_instantiation(self, iter_type) + @unittest.skipUnless(cET, 'requires _elementtree') class TestAliasWorking(unittest.TestCase): diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 05619fb2c96d52..c6b1f663d76b77 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -2194,7 +2194,7 @@ static PyType_Spec elementiter_spec = { .name = "_elementtree._element_iterator", .basicsize = sizeof(ElementIterObject), .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_IMMUTABLETYPE), + Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION), .slots = elementiter_slots, }; From 1ef41e123c8ece5a5d0961f0a8a39ec99bdb95ca Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 18 Jan 2023 13:41:17 +0100 Subject: [PATCH 17/23] PEP 687: Move types to state struct --- Modules/_elementtree.c | 74 +++++++++++++++++++-------------- Modules/clinic/_elementtree.c.h | 14 +++---- 2 files changed, 50 insertions(+), 38 deletions(-) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index c6b1f663d76b77..8eac8ca992ed2d 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -69,13 +69,6 @@ static void _clear_joined_ptr(PyObject **p) } } -/* Types defined by this extension */ -static PyTypeObject *Element_Type; -static PyTypeObject *ElementIter_Type; -static PyTypeObject *TreeBuilder_Type; -static PyTypeObject *XMLParser_Type; - - /* Per-module state; PEP 3121 */ typedef struct { PyObject *parseerror_obj; @@ -92,6 +85,11 @@ typedef struct { PyObject *str_findall; PyObject *str_iterfind; PyObject *str_doctype; + /* Types defined by this extension */ + PyTypeObject *Element_Type; + PyTypeObject *ElementIter_Type; + PyTypeObject *TreeBuilder_Type; + PyTypeObject *XMLParser_Type; } elementtreestate; static struct PyModuleDef elementtreemodule; @@ -122,6 +120,10 @@ elementtree_clear(PyObject *m) Py_CLEAR(st->elementpath_obj); Py_CLEAR(st->comment_factory); Py_CLEAR(st->pi_factory); + Py_CLEAR(st->Element_Type); + Py_CLEAR(st->ElementIter_Type); + Py_CLEAR(st->TreeBuilder_Type); + Py_CLEAR(st->XMLParser_Type); return 0; } @@ -134,6 +136,10 @@ elementtree_traverse(PyObject *m, visitproc visit, void *arg) Py_VISIT(st->elementpath_obj); Py_VISIT(st->comment_factory); Py_VISIT(st->pi_factory); + Py_VISIT(st->Element_Type); + Py_VISIT(st->ElementIter_Type); + Py_VISIT(st->TreeBuilder_Type); + Py_VISIT(st->XMLParser_Type); return 0; } @@ -213,8 +219,8 @@ typedef struct { } ElementObject; -#define Element_CheckExact(op) Py_IS_TYPE(op, Element_Type) -#define Element_Check(op) PyObject_TypeCheck(op, Element_Type) +#define Element_CheckExact(op) Py_IS_TYPE(op, ET_STATE_GLOBAL->Element_Type) +#define Element_Check(op) PyObject_TypeCheck(op, ET_STATE_GLOBAL->Element_Type) /* -------------------------------------------------------------------- */ @@ -281,7 +287,8 @@ create_new_element(PyObject* tag, PyObject* attrib) { ElementObject* self; - self = PyObject_GC_New(ElementObject, Element_Type); + elementtreestate *st = ET_STATE_GLOBAL; + self = PyObject_GC_New(ElementObject, st->Element_Type); if (self == NULL) return NULL; self->extra = NULL; @@ -363,11 +370,11 @@ get_attrib_from_keywords(PyObject *kwds) /*[clinic input] module _elementtree -class _elementtree.Element "ElementObject *" "Element_Type" -class _elementtree.TreeBuilder "TreeBuilderObject *" "TreeBuilder_Type" -class _elementtree.XMLParser "XMLParserObject *" "XMLParser_Type" +class _elementtree.Element "ElementObject *" "clinic_state()->Element_Type" +class _elementtree.TreeBuilder "TreeBuilderObject *" "clinic_state()->TreeBuilder_Type" +class _elementtree.XMLParser "XMLParserObject *" "clinic_state()->XMLParser_Type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=1ecdb32b55d9d5de]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=6c83ea832d2b0ef1]*/ static int element_init(PyObject *self, PyObject *args, PyObject *kwds) @@ -565,11 +572,12 @@ subelement(PyObject *self, PyObject *args, PyObject *kwds) { PyObject* elem; + elementtreestate *st = ET_STATE_GLOBAL; ElementObject* parent; PyObject* tag; PyObject* attrib = NULL; if (!PyArg_ParseTuple(args, "O!O|O!:SubElement", - Element_Type, &parent, &tag, + st->Element_Type, &parent, &tag, &PyDict_Type, &attrib)) { return NULL; } @@ -663,14 +671,14 @@ element_dealloc(ElementObject* self) /*[clinic input] _elementtree.Element.append - subelement: object(subclass_of='Element_Type') + subelement: object(subclass_of='clinic_state()->Element_Type') / [clinic start generated code]*/ static PyObject * _elementtree_Element_append_impl(ElementObject *self, PyObject *subelement) -/*[clinic end generated code: output=54a884b7cf2295f4 input=59866b732e6e2891]*/ +/*[clinic end generated code: output=54a884b7cf2295f4 input=439f2bd777288fb6]*/ { if (element_add_subelement(self, subelement) < 0) return NULL; @@ -1430,7 +1438,7 @@ element_getitem(PyObject* self_, Py_ssize_t index) _elementtree.Element.insert index: Py_ssize_t - subelement: object(subclass_of='Element_Type') + subelement: object(subclass_of='clinic_state()->Element_Type') / [clinic start generated code]*/ @@ -1438,7 +1446,7 @@ _elementtree.Element.insert static PyObject * _elementtree_Element_insert_impl(ElementObject *self, Py_ssize_t index, PyObject *subelement) -/*[clinic end generated code: output=990adfef4d424c0b input=4382c42ab2659f9b]*/ +/*[clinic end generated code: output=990adfef4d424c0b input=9530f4905aa401ca]*/ { Py_ssize_t i; @@ -1537,14 +1545,14 @@ _elementtree_Element_makeelement_impl(ElementObject *self, PyObject *tag, /*[clinic input] _elementtree.Element.remove - subelement: object(subclass_of='Element_Type') + subelement: object(subclass_of='clinic_state()->Element_Type') / [clinic start generated code]*/ static PyObject * _elementtree_Element_remove_impl(ElementObject *self, PyObject *subelement) -/*[clinic end generated code: output=38fe6c07d6d87d1f input=cbdf9f2ab34d93b0]*/ +/*[clinic end generated code: output=38fe6c07d6d87d1f input=6133e1d05597d5ee]*/ { Py_ssize_t i; int rc; @@ -2205,7 +2213,8 @@ create_elementiter(ElementObject *self, PyObject *tag, int gettext) { ElementIterObject *it; - it = PyObject_GC_New(ElementIterObject, ElementIter_Type); + elementtreestate *st = ET_STATE_GLOBAL; + it = PyObject_GC_New(ElementIterObject, st->ElementIter_Type); if (!it) return NULL; @@ -2262,7 +2271,7 @@ typedef struct { char insert_pis; } TreeBuilderObject; -#define TreeBuilder_CheckExact(op) Py_IS_TYPE((op), TreeBuilder_Type) +#define TreeBuilder_CheckExact(op) Py_IS_TYPE((op), ET_STATE_GLOBAL->TreeBuilder_Type) /* -------------------------------------------------------------------- */ /* constructor and destructor */ @@ -3556,7 +3565,8 @@ _elementtree_XMLParser___init___impl(XMLParserObject *self, PyObject *target, if (target != Py_None) { Py_INCREF(target); } else { - target = treebuilder_new(TreeBuilder_Type, NULL, NULL); + elementtreestate *st = ET_STATE_GLOBAL; + target = treebuilder_new(st->TreeBuilder_Type, NULL, NULL); if (!target) { Py_CLEAR(self->entity); Py_CLEAR(self->names); @@ -4036,7 +4046,9 @@ static PyGetSetDef xmlparser_getsetlist[] = { {NULL}, }; +#define clinic_state() (ET_STATE_GLOBAL) #include "clinic/_elementtree.c.h" +#undef clinic_state static PyMethodDef element_methods[] = { @@ -4233,10 +4245,10 @@ PyInit__elementtree(void) st = get_elementtree_state(m); /* Initialize object types */ - CREATE_TYPE(m, ElementIter_Type, &elementiter_spec); - CREATE_TYPE(m, TreeBuilder_Type, &treebuilder_spec); - CREATE_TYPE(m, Element_Type, &element_spec); - CREATE_TYPE(m, XMLParser_Type, &xmlparser_spec); + CREATE_TYPE(m, st->ElementIter_Type, &elementiter_spec); + CREATE_TYPE(m, st->TreeBuilder_Type, &treebuilder_spec); + CREATE_TYPE(m, st->Element_Type, &element_spec); + CREATE_TYPE(m, st->XMLParser_Type, &xmlparser_spec); st->deepcopy_obj = _PyImport_GetModuleAttrString("copy", "deepcopy"); if (st->deepcopy_obj == NULL) { @@ -4304,9 +4316,9 @@ PyInit__elementtree(void) } PyTypeObject *types[] = { - Element_Type, - TreeBuilder_Type, - XMLParser_Type + st->Element_Type, + st->TreeBuilder_Type, + st->XMLParser_Type }; for (size_t i = 0; i < Py_ARRAY_LENGTH(types); i++) { diff --git a/Modules/clinic/_elementtree.c.h b/Modules/clinic/_elementtree.c.h index b816e1bd8559c9..4bf342c8b60d72 100644 --- a/Modules/clinic/_elementtree.c.h +++ b/Modules/clinic/_elementtree.c.h @@ -25,8 +25,8 @@ _elementtree_Element_append(ElementObject *self, PyObject *arg) PyObject *return_value = NULL; PyObject *subelement; - if (!PyObject_TypeCheck(arg, Element_Type)) { - _PyArg_BadArgument("append", "argument", (Element_Type)->tp_name, arg); + if (!PyObject_TypeCheck(arg, clinic_state()->Element_Type)) { + _PyArg_BadArgument("append", "argument", (clinic_state()->Element_Type)->tp_name, arg); goto exit; } subelement = arg; @@ -586,8 +586,8 @@ _elementtree_Element_insert(ElementObject *self, PyObject *const *args, Py_ssize } index = ival; } - if (!PyObject_TypeCheck(args[1], Element_Type)) { - _PyArg_BadArgument("insert", "argument 2", (Element_Type)->tp_name, args[1]); + if (!PyObject_TypeCheck(args[1], clinic_state()->Element_Type)) { + _PyArg_BadArgument("insert", "argument 2", (clinic_state()->Element_Type)->tp_name, args[1]); goto exit; } subelement = args[1]; @@ -682,8 +682,8 @@ _elementtree_Element_remove(ElementObject *self, PyObject *arg) PyObject *return_value = NULL; PyObject *subelement; - if (!PyObject_TypeCheck(arg, Element_Type)) { - _PyArg_BadArgument("remove", "argument", (Element_Type)->tp_name, arg); + if (!PyObject_TypeCheck(arg, clinic_state()->Element_Type)) { + _PyArg_BadArgument("remove", "argument", (clinic_state()->Element_Type)->tp_name, arg); goto exit; } subelement = arg; @@ -1105,4 +1105,4 @@ _elementtree_XMLParser__setevents(XMLParserObject *self, PyObject *const *args, exit: return return_value; } -/*[clinic end generated code: output=db3d6654de9f8013 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d380adb43d8f4a62 input=a9049054013a1b77]*/ From 24794dda2bd4a00f139173a0d228398d49b5348d Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 20 Jan 2023 12:47:51 +0100 Subject: [PATCH 18/23] refactor: replace query with parameter Pass state as an argument to Element_CheckExact() --- Modules/_elementtree.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index f55a6bc654a5ae..4fc8223bbb5a8c 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -231,7 +231,7 @@ typedef struct { } ElementObject; -#define Element_CheckExact(op) Py_IS_TYPE(op, ET_STATE_GLOBAL->Element_Type) +#define Element_CheckExact(st, op) Py_IS_TYPE(op, (st)->Element_Type) #define Element_Check(op) PyObject_TypeCheck(op, ET_STATE_GLOBAL->Element_Type) @@ -856,7 +856,7 @@ LOCAL(PyObject *) deepcopy(PyObject *object, PyObject *memo) { /* do a deep copy of the given object */ - elementtreestate *st; + elementtreestate *st = ET_STATE_GLOBAL; PyObject *stack[2]; /* Fast paths */ @@ -879,14 +879,13 @@ deepcopy(PyObject *object, PyObject *memo) return PyDict_Copy(object); /* Fall through to general case */ } - else if (Element_CheckExact(object)) { + else if (Element_CheckExact(st, object)) { return _elementtree_Element___deepcopy___impl( (ElementObject *)object, memo); } } /* General case */ - st = ET_STATE_GLOBAL; if (!st->deepcopy_obj) { PyErr_SetString(PyExc_RuntimeError, "deepcopy helper not found"); @@ -2483,7 +2482,8 @@ treebuilder_extend_element_text_or_tail(PyObject *element, PyObject **data, PyObject **dest, PyObject *name) { /* Fast paths for the "almost always" cases. */ - if (Element_CheckExact(element)) { + elementtreestate *st = ET_STATE_GLOBAL; + if (Element_CheckExact(st, element)) { PyObject *dest_obj = JOIN_OBJ(*dest); if (dest_obj == Py_None) { *dest = JOIN_SET(*data, PyList_CheckExact(*data)); @@ -2557,7 +2557,7 @@ static int treebuilder_add_subelement(PyObject *element, PyObject *child) { elementtreestate *st = ET_STATE_GLOBAL; - if (Element_CheckExact(element)) { + if (Element_CheckExact(st, element)) { ElementObject *elem = (ElementObject *) element; return element_add_subelement(elem, child); } From 6bb6511c5b1efe05fac3df9e3b1f6ea69f4e6130 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 20 Jan 2023 12:49:59 +0100 Subject: [PATCH 19/23] refactor: replace query with parameter Pass state as an argument to Element_Check() --- Modules/_elementtree.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 4fc8223bbb5a8c..ffe215a1d4ea4d 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -232,7 +232,7 @@ typedef struct { #define Element_CheckExact(st, op) Py_IS_TYPE(op, (st)->Element_Type) -#define Element_Check(op) PyObject_TypeCheck(op, ET_STATE_GLOBAL->Element_Type) +#define Element_Check(st, op) PyObject_TypeCheck(op, (st)->Element_Type) /* -------------------------------------------------------------------- */ @@ -505,8 +505,8 @@ LOCAL(int) element_add_subelement(ElementObject* self, PyObject* element) { /* add a child element to a parent */ - - if (!Element_Check(element)) { + elementtreestate *st = ET_STATE_GLOBAL; + if (!Element_Check(st, element)) { raise_type_error(element); return -1; } @@ -816,9 +816,10 @@ _elementtree_Element___deepcopy___impl(ElementObject *self, PyObject *memo) if (element_resize(element, self->extra->length) < 0) goto error; + elementtreestate *st = ET_STATE_GLOBAL; for (i = 0; i < self->extra->length; i++) { PyObject* child = deepcopy(self->extra->children[i], memo); - if (!child || !Element_Check(child)) { + if (!child || !Element_Check(st, child)) { if (child) { raise_type_error(child); Py_DECREF(child); @@ -1029,9 +1030,10 @@ element_setstate_from_attributes(ElementObject *self, } /* Copy children */ + elementtreestate *st = ET_STATE_GLOBAL; for (i = 0; i < nchildren; i++) { PyObject *child = PyList_GET_ITEM(children, i); - if (!Element_Check(child)) { + if (!Element_Check(st, child)) { raise_type_error(child); self->extra->length = i; dealloc_extra(oldextra); @@ -1229,7 +1231,7 @@ _elementtree_Element_find_impl(ElementObject *self, PyObject *path, for (i = 0; i < self->extra->length; i++) { PyObject* item = self->extra->children[i]; int rc; - assert(Element_Check(item)); + assert(Element_Check(st, item)); Py_INCREF(item); rc = PyObject_RichCompareBool(((ElementObject*)item)->tag, path, Py_EQ); if (rc > 0) @@ -1273,7 +1275,7 @@ _elementtree_Element_findtext_impl(ElementObject *self, PyObject *path, for (i = 0; i < self->extra->length; i++) { PyObject *item = self->extra->children[i]; int rc; - assert(Element_Check(item)); + assert(Element_Check(st, item)); Py_INCREF(item); rc = PyObject_RichCompareBool(((ElementObject*)item)->tag, path, Py_EQ); if (rc > 0) { @@ -1327,7 +1329,7 @@ _elementtree_Element_findall_impl(ElementObject *self, PyObject *path, for (i = 0; i < self->extra->length; i++) { PyObject* item = self->extra->children[i]; int rc; - assert(Element_Check(item)); + assert(Element_Check(st, item)); Py_INCREF(item); rc = PyObject_RichCompareBool(((ElementObject*)item)->tag, path, Py_EQ); if (rc != 0 && (rc < 0 || PyList_Append(out, item) < 0)) { @@ -1677,7 +1679,8 @@ element_setitem(PyObject* self_, Py_ssize_t index, PyObject* item) old = self->extra->children[index]; if (item) { - if (!Element_Check(item)) { + elementtreestate *st = ET_STATE_GLOBAL; + if (!Element_Check(st, item)) { raise_type_error(item); return -1; } @@ -1874,9 +1877,10 @@ element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value) } } + elementtreestate *st = ET_STATE_GLOBAL; for (i = 0; i < newlen; i++) { PyObject *element = PySequence_Fast_GET_ITEM(seq, i); - if (!Element_Check(element)) { + if (!Element_Check(st, element)) { raise_type_error(element); Py_DECREF(seq); return -1; @@ -2149,7 +2153,8 @@ elementiter_next(ElementIterObject *it) continue; } - assert(Element_Check(extra->children[child_index])); + elementtreestate *st = ET_STATE_GLOBAL; + assert(Element_Check(st, extra->children[child_index])); elem = (ElementObject *)Py_NewRef(extra->children[child_index]); item->child_index++; } From 8dccc5ab89d6d67ef7f39f8f0f87f5e105366556 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 20 Jan 2023 12:52:07 +0100 Subject: [PATCH 20/23] refactor: replace query with parameter Pass state as an argument to TreeBuilder_CheckExact() --- Modules/_elementtree.c | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index ffe215a1d4ea4d..df4fa8edd6e103 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -2287,7 +2287,7 @@ typedef struct { char insert_pis; } TreeBuilderObject; -#define TreeBuilder_CheckExact(op) Py_IS_TYPE((op), ET_STATE_GLOBAL->TreeBuilder_Type) +#define TreeBuilder_CheckExact(st, op) Py_IS_TYPE((op), (st)->TreeBuilder_Type) /* -------------------------------------------------------------------- */ /* constructor and destructor */ @@ -3137,7 +3137,8 @@ expat_default_handler(XMLParserObject* self, const XML_Char* data_in, value = PyDict_GetItemWithError(self->entity, key); if (value) { - if (TreeBuilder_CheckExact(self->target)) + elementtreestate *st = ET_STATE_GLOBAL; + if (TreeBuilder_CheckExact(st, self->target)) res = treebuilder_handle_data( (TreeBuilderObject*) self->target, value ); @@ -3209,7 +3210,8 @@ expat_start_handler(XMLParserObject* self, const XML_Char* tag_in, attrib = NULL; } - if (TreeBuilder_CheckExact(self->target)) { + elementtreestate *st = ET_STATE_GLOBAL; + if (TreeBuilder_CheckExact(st, self->target)) { /* shortcut */ res = treebuilder_handle_start((TreeBuilderObject*) self->target, tag, attrib); @@ -3247,7 +3249,8 @@ expat_data_handler(XMLParserObject* self, const XML_Char* data_in, if (!data) return; /* parser will look for errors */ - if (TreeBuilder_CheckExact(self->target)) + elementtreestate *st = ET_STATE_GLOBAL; + if (TreeBuilder_CheckExact(st, self->target)) /* shortcut */ res = treebuilder_handle_data((TreeBuilderObject*) self->target, data); else if (self->handle_data) @@ -3269,7 +3272,8 @@ expat_end_handler(XMLParserObject* self, const XML_Char* tag_in) if (PyErr_Occurred()) return; - if (TreeBuilder_CheckExact(self->target)) + elementtreestate *st = ET_STATE_GLOBAL; + if (TreeBuilder_CheckExact(st, self->target)) /* shortcut */ /* the standard tree builder doesn't look at the end tag */ res = treebuilder_handle_end( @@ -3303,7 +3307,8 @@ expat_start_ns_handler(XMLParserObject* self, const XML_Char* prefix_in, if (!prefix_in) prefix_in = ""; - if (TreeBuilder_CheckExact(self->target)) { + elementtreestate *st = ET_STATE_GLOBAL; + if (TreeBuilder_CheckExact(st, self->target)) { /* shortcut - TreeBuilder does not actually implement .start_ns() */ TreeBuilderObject *target = (TreeBuilderObject*) self->target; @@ -3353,7 +3358,8 @@ expat_end_ns_handler(XMLParserObject* self, const XML_Char* prefix_in) if (!prefix_in) prefix_in = ""; - if (TreeBuilder_CheckExact(self->target)) { + elementtreestate *st = ET_STATE_GLOBAL; + if (TreeBuilder_CheckExact(st, self->target)) { /* shortcut - TreeBuilder does not actually implement .end_ns() */ TreeBuilderObject *target = (TreeBuilderObject*) self->target; @@ -3381,7 +3387,8 @@ expat_comment_handler(XMLParserObject* self, const XML_Char* comment_in) if (PyErr_Occurred()) return; - if (TreeBuilder_CheckExact(self->target)) { + elementtreestate *st = ET_STATE_GLOBAL; + if (TreeBuilder_CheckExact(st, self->target)) { /* shortcut */ TreeBuilderObject *target = (TreeBuilderObject*) self->target; @@ -3474,7 +3481,8 @@ expat_pi_handler(XMLParserObject* self, const XML_Char* target_in, if (PyErr_Occurred()) return; - if (TreeBuilder_CheckExact(self->target)) { + elementtreestate *st = ET_STATE_GLOBAL; + if (TreeBuilder_CheckExact(st, self->target)) { /* shortcut */ TreeBuilderObject *target = (TreeBuilderObject*) self->target; @@ -3784,7 +3792,8 @@ _elementtree_XMLParser_close_impl(XMLParserObject *self) if (!res) return NULL; - if (TreeBuilder_CheckExact(self->target)) { + elementtreestate *st = ET_STATE_GLOBAL; + if (TreeBuilder_CheckExact(st, self->target)) { Py_DECREF(res); return treebuilder_done((TreeBuilderObject*) self->target); } @@ -3923,7 +3932,8 @@ _elementtree_XMLParser__parse_whole(XMLParserObject *self, PyObject *file) res = expat_parse(self, "", 0, 1); - if (res && TreeBuilder_CheckExact(self->target)) { + elementtreestate *st = ET_STATE_GLOBAL; + if (res && TreeBuilder_CheckExact(st, self->target)) { Py_DECREF(res); return treebuilder_done((TreeBuilderObject*) self->target); } @@ -3954,7 +3964,8 @@ _elementtree_XMLParser__setevents_impl(XMLParserObject *self, if (!_check_xmlparser(self)) { return NULL; } - if (!TreeBuilder_CheckExact(self->target)) { + elementtreestate *st = ET_STATE_GLOBAL; + if (!TreeBuilder_CheckExact(st, self->target)) { PyErr_SetString( PyExc_TypeError, "event handling only supported for ElementTree.TreeBuilder " From d10ecd077afd75b1569e3f29a483af993ed13f29 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 20 Jan 2023 12:58:28 +0100 Subject: [PATCH 21/23] Readability improvement --- Modules/_elementtree.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index df4fa8edd6e103..c8aaadac248038 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -148,6 +148,8 @@ elementtree_traverse(PyObject *m, visitproc visit, void *arg) Py_VISIT(st->elementpath_obj); Py_VISIT(st->comment_factory); Py_VISIT(st->pi_factory); + + // Heap types Py_VISIT(st->Element_Type); Py_VISIT(st->ElementIter_Type); Py_VISIT(st->TreeBuilder_Type); From 78d1676336491ffc0279da0a9f6d7e91252be783 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 21 Jan 2023 10:42:23 +0100 Subject: [PATCH 22/23] Update Modules/_elementtree.c Co-authored-by: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com> --- Modules/_elementtree.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index c8aaadac248038..3be098a7dbf657 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -2155,8 +2155,10 @@ elementiter_next(ElementIterObject *it) continue; } +#ifndef NDEBUG elementtreestate *st = ET_STATE_GLOBAL; assert(Element_Check(st, extra->children[child_index])); +#endif elem = (ElementObject *)Py_NewRef(extra->children[child_index]); item->child_index++; } From 40fb57144484d45e7ca51a2d7b0a378c75e8188c Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 21 Jan 2023 11:21:42 +0100 Subject: [PATCH 23/23] Address review: remove etree types from globals-to-fix.tsv --- Tools/c-analyzer/cpython/globals-to-fix.tsv | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index cd08782edce484..761a2ab43e6cb4 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -425,10 +425,6 @@ Modules/_decimal/_decimal.c - PyDecContextManager_Type - Modules/_decimal/_decimal.c - PyDecContext_Type - Modules/_decimal/_decimal.c - PyDecSignalDictMixin_Type - Modules/_decimal/_decimal.c - PyDec_Type - -Modules/_elementtree.c - ElementIter_Type - -Modules/_elementtree.c - Element_Type - -Modules/_elementtree.c - TreeBuilder_Type - -Modules/_elementtree.c - XMLParser_Type - Modules/_pickle.c - Pdata_Type - Modules/_pickle.c - PicklerMemoProxyType - Modules/_pickle.c - Pickler_Type -