mirror of
https://github.com/python/cpython.git
synced 2026-01-06 07:22:09 +00:00
gh-92123: Convert _elementtree types to heap types (#99221)
This commit is contained in:
parent
9109d46051
commit
3847a6c64b
4 changed files with 185 additions and 236 deletions
|
|
@ -181,6 +181,26 @@ def __hash__(self):
|
|||
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):
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
Convert :mod:`elementtree` types to heap types. Patch by Erlend E. Aasland.
|
||||
|
|
@ -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 @@ 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 |
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
14
Modules/clinic/_elementtree.c.h
generated
14
Modules/clinic/_elementtree.c.h
generated
|
|
@ -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]*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue