summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorErlend E. Aasland <erlend.aasland@protonmail.com>2023-01-20 11:40:06 (GMT)
committerGitHub <noreply@github.com>2023-01-20 11:40:06 (GMT)
commit3847a6c64b96bb2cb93be394a590d4df2c35e876 (patch)
tree690f476a3bbd8f850e524b9a46ecd626f39f5ec8
parent9109d460511a317f5598a26658ba495e77ea8686 (diff)
downloadcpython-3847a6c64b96bb2cb93be394a590d4df2c35e876.zip
cpython-3847a6c64b96bb2cb93be394a590d4df2c35e876.tar.gz
cpython-3847a6c64b96bb2cb93be394a590d4df2c35e876.tar.bz2
gh-92123: Convert `_elementtree` types to heap types (#99221)
-rw-r--r--Lib/test/test_xml_etree_c.py20
-rw-r--r--Misc/NEWS.d/next/Library/2020-11-20-21-06-08.bpo-40077.M-iZq3.rst1
-rw-r--r--Modules/_elementtree.c386
-rw-r--r--Modules/clinic/_elementtree.c.h14
4 files changed, 185 insertions, 236 deletions
diff --git a/Lib/test/test_xml_etree_c.py b/Lib/test/test_xml_etree_c.py
index bec8208..fd27b57 100644
--- a/Lib/test/test_xml_etree_c.py
+++ b/Lib/test/test_xml_etree_c.py
@@ -181,6 +181,26 @@ class MiscTests(unittest.TestCase):
r = e.get(X())
self.assertIsNone(r)
+ @support.cpython_only
+ def test_immutable_types(self):
+ root = cET.fromstring('<a></a>')
+ 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
+
+ @support.cpython_only
+ def test_disallow_instantiation(self):
+ root = cET.fromstring('<a></a>')
+ iter_type = type(root.iter())
+ support.check_disallow_instantiation(self, iter_type)
+
@unittest.skipUnless(cET, 'requires _elementtree')
class TestAliasWorking(unittest.TestCase):
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 0000000..8a74477
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2020-11-20-21-06-08.bpo-40077.M-iZq3.rst
@@ -0,0 +1 @@
+Convert :mod:`elementtree` types to heap types. Patch by Erlend E. Aasland.
diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c
index e0ab791..93a9d60 100644
--- a/Modules/_elementtree.c
+++ b/Modules/_elementtree.c
@@ -70,10 +70,10 @@ 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;
+static PyTypeObject *Element_Type;
+static PyTypeObject *ElementIter_Type;
+static PyTypeObject *TreeBuilder_Type;
+static PyTypeObject *XMLParser_Type;
/* Per-module state; PEP 3121 */
@@ -223,8 +223,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)
/* -------------------------------------------------------------------- */
@@ -291,7 +291,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;
@@ -373,11 +373,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 *" "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=1ecdb32b55d9d5de]*/
static int
element_init(PyObject *self, PyObject *args, PyObject *kwds)
@@ -579,7 +579,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;
}
@@ -618,6 +618,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));
@@ -649,6 +650,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)
@@ -660,7 +663,8 @@ element_dealloc(ElementObject* self)
*/
element_gc_clear(self);
- Py_TYPE(self)->tp_free((PyObject *)self);
+ tp->tp_free((PyObject *)self);
+ Py_DECREF(tp);
Py_TRASHCAN_END
}
@@ -669,14 +673,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;
@@ -1436,7 +1440,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]*/
@@ -1444,7 +1448,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;
@@ -1543,14 +1547,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;
@@ -2001,16 +2005,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
@@ -2040,6 +2034,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 */
@@ -2051,7 +2046,8 @@ 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);
}
static int
@@ -2063,6 +2059,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;
}
@@ -2193,49 +2190,22 @@ gettext:
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 |
+ Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION),
+ .slots = elementiter_slots,
};
#define INIT_PARENT_STACK_SIZE 8
@@ -2245,7 +2215,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;
@@ -2302,7 +2272,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 */
@@ -2393,6 +2363,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);
@@ -2437,9 +2408,11 @@ treebuilder_gc_clear(TreeBuilderObject *self)
static void
treebuilder_dealloc(TreeBuilderObject *self)
{
+ PyTypeObject *tp = Py_TYPE(self);
PyObject_GC_UnTrack(self);
treebuilder_gc_clear(self);
- Py_TYPE(self)->tp_free((PyObject *)self);
+ tp->tp_free(self);
+ Py_DECREF(tp);
}
/* -------------------------------------------------------------------- */
@@ -3593,7 +3566,7 @@ _elementtree_XMLParser___init___impl(XMLParserObject *self, PyObject *target,
if (target != Py_None) {
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);
@@ -3685,6 +3658,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);
@@ -3731,9 +3705,11 @@ xmlparser_gc_clear(XMLParserObject *self)
static void
xmlparser_dealloc(XMLParserObject* self)
{
+ PyTypeObject *tp = Py_TYPE(self);
PyObject_GC_UnTrack(self);
xmlparser_gc_clear(self);
- Py_TYPE(self)->tp_free((PyObject *)self);
+ tp->tp_free(self);
+ Py_DECREF(tp);
}
Py_LOCAL_INLINE(int)
@@ -4106,10 +4082,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[] = {
@@ -4132,46 +4107,33 @@ 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 |
+ Py_TPFLAGS_IMMUTABLETYPE),
+ .slots = element_slots,
};
static PyMethodDef treebuilder_methods[] = {
@@ -4184,46 +4146,22 @@ 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 | Py_TPFLAGS_IMMUTABLETYPE,
+ .slots = treebuilder_slots,
};
static PyMethodDef xmlparser_methods[] = {
@@ -4234,46 +4172,25 @@ 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 |
+ Py_TPFLAGS_IMMUTABLETYPE),
+ .slots = xmlparser_slots,
};
/* ==================================================================== */
@@ -4298,40 +4215,47 @@ static struct PyModuleDef elementtreemodule = {
elementtree_free
};
+#define CREATE_TYPE(module, type, spec) \
+do { \
+ if (type != NULL) { \
+ break; \
+ } \
+ type = (PyTypeObject *)PyType_FromModuleAndSpec(module, spec, NULL); \
+ if (type == NULL) { \
+ goto error; \
+ } \
+} while (0)
+
PyMODINIT_FUNC
PyInit__elementtree(void)
{
- PyObject *m;
- elementtreestate *st;
+ PyObject *m = NULL;
+ elementtreestate *st = NULL;
m = PyState_FindModule(&elementtreemodule);
if (m) {
return Py_NewRef(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;
+ 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);
+
st->deepcopy_obj = _PyImport_GetModuleAttrString("copy", "deepcopy");
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);
@@ -4344,62 +4268,66 @@ 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->str_append = PyUnicode_InternFromString("append");
if (st->str_append == NULL) {
- return NULL;
+ goto error;
}
st->str_find = PyUnicode_InternFromString("find");
if (st->str_find == NULL) {
- return NULL;
+ goto error;
}
st->str_findall = PyUnicode_InternFromString("findall");
if (st->str_findall == NULL) {
- return NULL;
+ goto error;
}
st->str_findtext = PyUnicode_InternFromString("findtext");
if (st->str_findtext == NULL) {
- return NULL;
+ goto error;
}
st->str_iterfind = PyUnicode_InternFromString("iterfind");
if (st->str_iterfind == NULL) {
- return NULL;
+ goto error;
}
st->str_tail = PyUnicode_InternFromString("tail");
if (st->str_tail == NULL) {
- return NULL;
+ goto error;
}
st->str_text = PyUnicode_InternFromString("text");
if (st->str_text == NULL) {
- return NULL;
+ goto error;
}
st->str_doctype = PyUnicode_InternFromString("doctype");
if (st->str_doctype == NULL) {
- return NULL;
+ goto error;
}
st->parseerror_obj = PyErr_NewException(
"xml.etree.ElementTree.ParseError", PyExc_SyntaxError, NULL
);
if (PyModule_AddObjectRef(m, "ParseError", st->parseerror_obj) < 0) {
- return NULL;
+ goto error;
}
PyTypeObject *types[] = {
- &Element_Type,
- &TreeBuilder_Type,
- &XMLParser_Type
+ Element_Type,
+ TreeBuilder_Type,
+ XMLParser_Type
};
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(m);
+ return NULL;
}
diff --git a/Modules/clinic/_elementtree.c.h b/Modules/clinic/_elementtree.c.h
index 33ccaf7..b816e1b 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, Element_Type)) {
+ _PyArg_BadArgument("append", "argument", (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], Element_Type)) {
+ _PyArg_BadArgument("insert", "argument 2", (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, Element_Type)) {
+ _PyArg_BadArgument("remove", "argument", (Element_Type)->tp_name, arg);
goto exit;
}
subelement = arg;
@@ -1105,4 +1105,4 @@ skip_optional:
exit:
return return_value;
}
-/*[clinic end generated code: output=4ad006cadce01571 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=db3d6654de9f8013 input=a9049054013a1b77]*/