summaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/src/Modules/_elementtree.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/tools/python3/src/Modules/_elementtree.c')
-rw-r--r--contrib/tools/python3/src/Modules/_elementtree.c1203
1 files changed, 604 insertions, 599 deletions
diff --git a/contrib/tools/python3/src/Modules/_elementtree.c b/contrib/tools/python3/src/Modules/_elementtree.c
index 12d22337d82..620de8bb4c6 100644
--- a/contrib/tools/python3/src/Modules/_elementtree.c
+++ b/contrib/tools/python3/src/Modules/_elementtree.c
@@ -12,10 +12,11 @@
*/
#define PY_SSIZE_T_CLEAN
-#define NEEDS_PY_IDENTIFIER
#include "Python.h"
#include "structmember.h" // PyMemberDef
+#include "expat.h"
+#include "pyexpat.h"
/* -------------------------------------------------------------------- */
/* configuration */
@@ -70,13 +71,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;
@@ -84,6 +78,23 @@ typedef struct {
PyObject *elementpath_obj;
PyObject *comment_factory;
PyObject *pi_factory;
+ /* Interned strings */
+ PyObject *str_text;
+ PyObject *str_tail;
+ PyObject *str_append;
+ PyObject *str_find;
+ PyObject *str_findtext;
+ 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;
+
+ PyObject *expat_capsule;
+ struct PyExpat_CAPI *expat_capi;
} elementtreestate;
static struct PyModuleDef elementtreemodule;
@@ -99,11 +110,21 @@ get_elementtree_state(PyObject *module)
return (elementtreestate *)state;
}
-/* Find the module instance imported in the currently running sub-interpreter
- * and get its state.
- */
-#define ET_STATE_GLOBAL \
- ((elementtreestate *) PyModule_GetState(PyState_FindModule(&elementtreemodule)))
+static inline elementtreestate *
+get_elementtree_state_by_cls(PyTypeObject *cls)
+{
+ void *state = PyType_GetModuleState(cls);
+ assert(state != NULL);
+ return (elementtreestate *)state;
+}
+
+static inline elementtreestate *
+get_elementtree_state_by_type(PyTypeObject *tp)
+{
+ PyObject *mod = PyType_GetModuleByDef(tp, &elementtreemodule);
+ assert(mod != NULL);
+ return get_elementtree_state(mod);
+}
static int
elementtree_clear(PyObject *m)
@@ -114,6 +135,25 @@ elementtree_clear(PyObject *m)
Py_CLEAR(st->elementpath_obj);
Py_CLEAR(st->comment_factory);
Py_CLEAR(st->pi_factory);
+
+ // Interned strings
+ Py_CLEAR(st->str_append);
+ Py_CLEAR(st->str_find);
+ Py_CLEAR(st->str_findall);
+ Py_CLEAR(st->str_findtext);
+ Py_CLEAR(st->str_iterfind);
+ Py_CLEAR(st->str_tail);
+ Py_CLEAR(st->str_text);
+ Py_CLEAR(st->str_doctype);
+
+ // Heap types
+ Py_CLEAR(st->Element_Type);
+ Py_CLEAR(st->ElementIter_Type);
+ Py_CLEAR(st->TreeBuilder_Type);
+ Py_CLEAR(st->XMLParser_Type);
+ Py_CLEAR(st->expat_capsule);
+
+ st->expat_capi = NULL;
return 0;
}
@@ -126,6 +166,13 @@ 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);
+ Py_VISIT(st->XMLParser_Type);
+ Py_VISIT(st->expat_capsule);
return 0;
}
@@ -205,8 +252,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(st, op) Py_IS_TYPE(op, (st)->Element_Type)
+#define Element_Check(st, op) PyObject_TypeCheck(op, (st)->Element_Type)
/* -------------------------------------------------------------------- */
@@ -221,8 +268,7 @@ create_extra(ElementObject* self, PyObject* attrib)
return -1;
}
- Py_XINCREF(attrib);
- self->extra->attrib = attrib;
+ self->extra->attrib = Py_XNewRef(attrib);
self->extra->length = 0;
self->extra->allocated = STATIC_CHILDREN;
@@ -270,24 +316,17 @@ clear_extra(ElementObject* self)
* tag and attributes.
*/
LOCAL(PyObject*)
-create_new_element(PyObject* tag, PyObject* attrib)
+create_new_element(elementtreestate *st, PyObject *tag, PyObject *attrib)
{
ElementObject* self;
- self = PyObject_GC_New(ElementObject, &Element_Type);
+ self = PyObject_GC_New(ElementObject, st->Element_Type);
if (self == NULL)
return NULL;
self->extra = NULL;
-
- Py_INCREF(tag);
- self->tag = tag;
-
- Py_INCREF(Py_None);
- self->text = Py_None;
-
- Py_INCREF(Py_None);
- self->tail = Py_None;
-
+ self->tag = Py_NewRef(tag);
+ self->text = Py_NewRef(Py_None);
+ self->tail = Py_NewRef(Py_None);
self->weakreflist = NULL;
PyObject_GC_Track(self);
@@ -307,15 +346,9 @@ element_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
ElementObject *e = (ElementObject *)type->tp_alloc(type, 0);
if (e != NULL) {
- Py_INCREF(Py_None);
- e->tag = Py_None;
-
- Py_INCREF(Py_None);
- e->text = Py_None;
-
- Py_INCREF(Py_None);
- e->tail = Py_None;
-
+ e->tag = Py_NewRef(Py_None);
+ e->text = Py_NewRef(Py_None);
+ e->tail = Py_NewRef(Py_None);
e->extra = NULL;
e->weakreflist = NULL;
}
@@ -351,8 +384,7 @@ get_attrib_from_keywords(PyObject *kwds)
}
attrib = PyDict_Copy(attrib);
if (attrib && PyDict_DelItem(kwds, attrib_str) < 0) {
- Py_DECREF(attrib);
- attrib = NULL;
+ Py_SETREF(attrib, NULL);
}
}
else if (!PyErr_Occurred()) {
@@ -370,11 +402,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=159aa50a54061c22]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=6c83ea832d2b0ef1]*/
static int
element_init(PyObject *self, PyObject *args, PyObject *kwds)
@@ -417,14 +449,10 @@ element_init(PyObject *self, PyObject *args, PyObject *kwds)
Py_XDECREF(attrib);
/* Replace the objects already pointed to by tag, text and tail. */
- Py_INCREF(tag);
- Py_XSETREF(self_elem->tag, tag);
-
- Py_INCREF(Py_None);
- _set_joined_ptr(&self_elem->text, Py_None);
+ Py_XSETREF(self_elem->tag, Py_NewRef(tag));
- Py_INCREF(Py_None);
- _set_joined_ptr(&self_elem->tail, Py_None);
+ _set_joined_ptr(&self_elem->text, Py_NewRef(Py_None));
+ _set_joined_ptr(&self_elem->tail, Py_NewRef(Py_None));
return 0;
}
@@ -494,11 +522,11 @@ raise_type_error(PyObject *element)
}
LOCAL(int)
-element_add_subelement(ElementObject* self, PyObject* element)
+element_add_subelement(elementtreestate *st, ElementObject *self,
+ PyObject *element)
{
/* add a child element to a parent */
-
- if (!Element_Check(element)) {
+ if (!Element_Check(st, element)) {
raise_type_error(element);
return -1;
}
@@ -506,8 +534,7 @@ element_add_subelement(ElementObject* self, PyObject* element)
if (element_resize(self, 1) < 0)
return -1;
- Py_INCREF(element);
- self->extra->children[self->extra->length] = element;
+ self->extra->children[self->extra->length] = Py_NewRef(element);
self->extra->length++;
@@ -544,8 +571,7 @@ element_get_text(ElementObject* self)
if (!tmp)
return NULL;
self->text = tmp;
- Py_DECREF(res);
- res = tmp;
+ Py_SETREF(res, tmp);
}
}
@@ -566,8 +592,7 @@ element_get_tail(ElementObject* self)
if (!tmp)
return NULL;
self->tail = tmp;
- Py_DECREF(res);
- res = tmp;
+ Py_SETREF(res, tmp);
}
}
@@ -579,11 +604,12 @@ subelement(PyObject *self, PyObject *args, PyObject *kwds)
{
PyObject* elem;
+ elementtreestate *st = get_elementtree_state(self);
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;
}
@@ -606,12 +632,12 @@ subelement(PyObject *self, PyObject *args, PyObject *kwds)
/* no attrib arg, no kwds, so no attribute */
}
- elem = create_new_element(tag, attrib);
+ elem = create_new_element(st, tag, attrib);
Py_XDECREF(attrib);
if (elem == NULL)
return NULL;
- if (element_add_subelement(parent, elem) < 0) {
+ if (element_add_subelement(st, parent, elem) < 0) {
Py_DECREF(elem);
return NULL;
}
@@ -622,6 +648,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));
@@ -653,6 +680,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)
@@ -664,7 +693,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
}
@@ -673,16 +703,19 @@ element_dealloc(ElementObject* self)
/*[clinic input]
_elementtree.Element.append
- subelement: object(subclass_of='&Element_Type')
+ cls: defining_class
+ 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=3ed648beb5bfa22a]*/
+_elementtree_Element_append_impl(ElementObject *self, PyTypeObject *cls,
+ PyObject *subelement)
+/*[clinic end generated code: output=d00923711ea317fc input=8baf92679f9717b8]*/
{
- if (element_add_subelement(self, subelement) < 0)
+ elementtreestate *st = get_elementtree_state_by_cls(cls);
+ if (element_add_subelement(st, self, subelement) < 0)
return NULL;
Py_RETURN_NONE;
@@ -699,11 +732,8 @@ _elementtree_Element_clear_impl(ElementObject *self)
{
clear_extra(self);
- Py_INCREF(Py_None);
- _set_joined_ptr(&self->text, Py_None);
-
- Py_INCREF(Py_None);
- _set_joined_ptr(&self->tail, Py_None);
+ _set_joined_ptr(&self->text, Py_NewRef(Py_None));
+ _set_joined_ptr(&self->tail, Py_NewRef(Py_None));
Py_RETURN_NONE;
}
@@ -711,17 +741,21 @@ _elementtree_Element_clear_impl(ElementObject *self)
/*[clinic input]
_elementtree.Element.__copy__
+ cls: defining_class
+ /
+
[clinic start generated code]*/
static PyObject *
-_elementtree_Element___copy___impl(ElementObject *self)
-/*[clinic end generated code: output=2c701ebff7247781 input=ad87aaebe95675bf]*/
+_elementtree_Element___copy___impl(ElementObject *self, PyTypeObject *cls)
+/*[clinic end generated code: output=da22894421ff2b36 input=91edb92d9f441213]*/
{
Py_ssize_t i;
ElementObject* element;
+ elementtreestate *st = get_elementtree_state_by_cls(cls);
element = (ElementObject*) create_new_element(
- self->tag, self->extra ? self->extra->attrib : NULL);
+ st, self->tag, self->extra ? self->extra->attrib : NULL);
if (!element)
return NULL;
@@ -739,8 +773,7 @@ _elementtree_Element___copy___impl(ElementObject *self)
}
for (i = 0; i < self->extra->length; i++) {
- Py_INCREF(self->extra->children[i]);
- element->extra->children[i] = self->extra->children[i];
+ element->extra->children[i] = Py_NewRef(self->extra->children[i]);
}
assert(!element->extra->length);
@@ -751,7 +784,7 @@ _elementtree_Element___copy___impl(ElementObject *self)
}
/* Helper for a deep copy. */
-LOCAL(PyObject *) deepcopy(PyObject *, PyObject *);
+LOCAL(PyObject *) deepcopy(elementtreestate *, PyObject *, PyObject *);
/*[clinic input]
_elementtree.Element.__deepcopy__
@@ -773,12 +806,14 @@ _elementtree_Element___deepcopy___impl(ElementObject *self, PyObject *memo)
PyObject* tail;
PyObject* id;
- tag = deepcopy(self->tag, memo);
+ PyTypeObject *tp = Py_TYPE(self);
+ elementtreestate *st = get_elementtree_state_by_type(tp);
+ tag = deepcopy(st, self->tag, memo);
if (!tag)
return NULL;
if (self->extra && self->extra->attrib) {
- attrib = deepcopy(self->extra->attrib, memo);
+ attrib = deepcopy(st, self->extra->attrib, memo);
if (!attrib) {
Py_DECREF(tag);
return NULL;
@@ -787,7 +822,7 @@ _elementtree_Element___deepcopy___impl(ElementObject *self, PyObject *memo)
attrib = NULL;
}
- element = (ElementObject*) create_new_element(tag, attrib);
+ element = (ElementObject*) create_new_element(st, tag, attrib);
Py_DECREF(tag);
Py_XDECREF(attrib);
@@ -795,12 +830,12 @@ _elementtree_Element___deepcopy___impl(ElementObject *self, PyObject *memo)
if (!element)
return NULL;
- text = deepcopy(JOIN_OBJ(self->text), memo);
+ text = deepcopy(st, JOIN_OBJ(self->text), memo);
if (!text)
goto error;
_set_joined_ptr(&element->text, JOIN_SET(text, JOIN_GET(self->text)));
- tail = deepcopy(JOIN_OBJ(self->tail), memo);
+ tail = deepcopy(st, JOIN_OBJ(self->tail), memo);
if (!tail)
goto error;
_set_joined_ptr(&element->tail, JOIN_SET(tail, JOIN_GET(self->tail)));
@@ -811,8 +846,8 @@ _elementtree_Element___deepcopy___impl(ElementObject *self, PyObject *memo)
goto error;
for (i = 0; i < self->extra->length; i++) {
- PyObject* child = deepcopy(self->extra->children[i], memo);
- if (!child || !Element_Check(child)) {
+ PyObject* child = deepcopy(st, self->extra->children[i], memo);
+ if (!child || !Element_Check(st, child)) {
if (child) {
raise_type_error(child);
Py_DECREF(child);
@@ -847,16 +882,14 @@ _elementtree_Element___deepcopy___impl(ElementObject *self, PyObject *memo)
}
LOCAL(PyObject *)
-deepcopy(PyObject *object, PyObject *memo)
+deepcopy(elementtreestate *st, PyObject *object, PyObject *memo)
{
/* do a deep copy of the given object */
- elementtreestate *st;
PyObject *stack[2];
/* Fast paths */
if (object == Py_None || PyUnicode_CheckExact(object)) {
- Py_INCREF(object);
- return object;
+ return Py_NewRef(object);
}
if (Py_REFCNT(object) == 1) {
@@ -874,14 +907,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");
@@ -895,19 +927,20 @@ deepcopy(PyObject *object, PyObject *memo)
/*[clinic input]
-_elementtree.Element.__sizeof__ -> Py_ssize_t
+_elementtree.Element.__sizeof__ -> size_t
[clinic start generated code]*/
-static Py_ssize_t
+static size_t
_elementtree_Element___sizeof___impl(ElementObject *self)
-/*[clinic end generated code: output=bf73867721008000 input=70f4b323d55a17c1]*/
+/*[clinic end generated code: output=baae4e7ae9fe04ec input=54e298c501f3e0d0]*/
{
- Py_ssize_t result = _PyObject_SIZE(Py_TYPE(self));
+ size_t result = _PyObject_SIZE(Py_TYPE(self));
if (self->extra) {
result += sizeof(ElementObjectExtra);
- if (self->extra->children != self->extra->_children)
- result += sizeof(PyObject*) * self->extra->allocated;
+ if (self->extra->children != self->extra->_children) {
+ result += (size_t)self->extra->allocated * sizeof(PyObject*);
+ }
}
return result;
}
@@ -942,14 +975,12 @@ _elementtree_Element___getstate___impl(ElementObject *self)
if (!children)
return NULL;
for (i = 0; i < PyList_GET_SIZE(children); i++) {
- PyObject *child = self->extra->children[i];
- Py_INCREF(child);
+ PyObject *child = Py_NewRef(self->extra->children[i]);
PyList_SET_ITEM(children, i, child);
}
if (self->extra && self->extra->attrib) {
- attrib = self->extra->attrib;
- Py_INCREF(attrib);
+ attrib = Py_NewRef(self->extra->attrib);
}
else {
attrib = PyDict_New();
@@ -968,7 +999,8 @@ _elementtree_Element___getstate___impl(ElementObject *self)
}
static PyObject *
-element_setstate_from_attributes(ElementObject *self,
+element_setstate_from_attributes(elementtreestate *st,
+ ElementObject *self,
PyObject *tag,
PyObject *attrib,
PyObject *text,
@@ -983,8 +1015,7 @@ element_setstate_from_attributes(ElementObject *self,
return NULL;
}
- Py_INCREF(tag);
- Py_XSETREF(self->tag, tag);
+ Py_XSETREF(self->tag, Py_NewRef(tag));
text = text ? JOIN_SET(text, PyList_CheckExact(text)) : Py_None;
Py_INCREF(JOIN_OBJ(text));
@@ -1029,14 +1060,13 @@ element_setstate_from_attributes(ElementObject *self,
/* Copy children */
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);
return NULL;
}
- Py_INCREF(child);
- self->extra->children[i] = child;
+ self->extra->children[i] = Py_NewRef(child);
}
assert(!self->extra->length);
@@ -1049,8 +1079,7 @@ element_setstate_from_attributes(ElementObject *self,
}
/* Stash attrib. */
- Py_XINCREF(attrib);
- Py_XSETREF(self->extra->attrib, attrib);
+ Py_XSETREF(self->extra->attrib, Py_XNewRef(attrib));
dealloc_extra(oldextra);
Py_RETURN_NONE;
@@ -1061,7 +1090,8 @@ element_setstate_from_attributes(ElementObject *self,
*/
static PyObject *
-element_setstate_from_Python(ElementObject *self, PyObject *state)
+element_setstate_from_Python(elementtreestate *st, ElementObject *self,
+ PyObject *state)
{
static char *kwlist[] = {PICKLED_TAG, PICKLED_ATTRIB, PICKLED_TEXT,
PICKLED_TAIL, PICKLED_CHILDREN, 0};
@@ -1076,7 +1106,7 @@ element_setstate_from_Python(ElementObject *self, PyObject *state)
if (PyArg_ParseTupleAndKeywords(args, state, "|$OOOOO", kwlist, &tag,
&attrib, &text, &tail, &children))
- retval = element_setstate_from_attributes(self, tag, attrib, text,
+ retval = element_setstate_from_attributes(st, self, tag, attrib, text,
tail, children);
else
retval = NULL;
@@ -1088,14 +1118,16 @@ element_setstate_from_Python(ElementObject *self, PyObject *state)
/*[clinic input]
_elementtree.Element.__setstate__
+ cls: defining_class
state: object
/
[clinic start generated code]*/
static PyObject *
-_elementtree_Element___setstate__(ElementObject *self, PyObject *state)
-/*[clinic end generated code: output=ea28bf3491b1f75e input=aaf80abea7c1e3b9]*/
+_elementtree_Element___setstate___impl(ElementObject *self,
+ PyTypeObject *cls, PyObject *state)
+/*[clinic end generated code: output=598bfb5730f71509 input=13830488d35d51f7]*/
{
if (!PyDict_CheckExact(state)) {
PyErr_Format(PyExc_TypeError,
@@ -1103,8 +1135,10 @@ _elementtree_Element___setstate__(ElementObject *self, PyObject *state)
state);
return NULL;
}
- else
- return element_setstate_from_Python(self, state);
+ else {
+ elementtreestate *st = get_elementtree_state_by_cls(cls);
+ return element_setstate_from_Python(st, self, state);
+ }
}
LOCAL(int)
@@ -1121,7 +1155,7 @@ checkpath(PyObject* tag)
if (PyUnicode_Check(tag)) {
const Py_ssize_t len = PyUnicode_GET_LENGTH(tag);
const void *data = PyUnicode_DATA(tag);
- unsigned int kind = PyUnicode_KIND(tag);
+ int kind = PyUnicode_KIND(tag);
if (len >= 3 && PyUnicode_READ(kind, data, 0) == '{' && (
PyUnicode_READ(kind, data, 1) == '}' || (
PyUnicode_READ(kind, data, 1) == '*' &&
@@ -1165,14 +1199,16 @@ checkpath(PyObject* tag)
/*[clinic input]
_elementtree.Element.extend
+ cls: defining_class
elements: object
/
[clinic start generated code]*/
static PyObject *
-_elementtree_Element_extend(ElementObject *self, PyObject *elements)
-/*[clinic end generated code: output=f6e67fc2ff529191 input=807bc4f31c69f7c0]*/
+_elementtree_Element_extend_impl(ElementObject *self, PyTypeObject *cls,
+ PyObject *elements)
+/*[clinic end generated code: output=3e86d37fac542216 input=6479b1b5379d09ae]*/
{
PyObject* seq;
Py_ssize_t i;
@@ -1186,10 +1222,10 @@ _elementtree_Element_extend(ElementObject *self, PyObject *elements)
return NULL;
}
+ elementtreestate *st = get_elementtree_state_by_cls(cls);
for (i = 0; i < PySequence_Fast_GET_SIZE(seq); i++) {
- PyObject* element = PySequence_Fast_GET_ITEM(seq, i);
- Py_INCREF(element);
- if (element_add_subelement(self, element) < 0) {
+ PyObject* element = Py_NewRef(PySequence_Fast_GET_ITEM(seq, i));
+ if (element_add_subelement(st, self, element) < 0) {
Py_DECREF(seq);
Py_DECREF(element);
return NULL;
@@ -1205,23 +1241,24 @@ _elementtree_Element_extend(ElementObject *self, PyObject *elements)
/*[clinic input]
_elementtree.Element.find
+ cls: defining_class
+ /
path: object
namespaces: object = None
[clinic start generated code]*/
static PyObject *
-_elementtree_Element_find_impl(ElementObject *self, PyObject *path,
- PyObject *namespaces)
-/*[clinic end generated code: output=41b43f0f0becafae input=359b6985f6489d2e]*/
+_elementtree_Element_find_impl(ElementObject *self, PyTypeObject *cls,
+ PyObject *path, PyObject *namespaces)
+/*[clinic end generated code: output=18f77d393c9fef1b input=94df8a83f956acc6]*/
{
Py_ssize_t i;
- elementtreestate *st = ET_STATE_GLOBAL;
+ elementtreestate *st = get_elementtree_state_by_cls(cls);
if (checkpath(path) || namespaces != Py_None) {
- _Py_IDENTIFIER(find);
- return _PyObject_CallMethodIdObjArgs(
- st->elementpath_obj, &PyId_find, self, path, namespaces, NULL
+ return PyObject_CallMethodObjArgs(
+ st->elementpath_obj, st->str_find, self, path, namespaces, NULL
);
}
@@ -1231,7 +1268,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)
@@ -1247,6 +1284,8 @@ _elementtree_Element_find_impl(ElementObject *self, PyObject *path,
/*[clinic input]
_elementtree.Element.findtext
+ cls: defining_class
+ /
path: object
default: object = None
namespaces: object = None
@@ -1254,30 +1293,28 @@ _elementtree.Element.findtext
[clinic start generated code]*/
static PyObject *
-_elementtree_Element_findtext_impl(ElementObject *self, PyObject *path,
- PyObject *default_value,
+_elementtree_Element_findtext_impl(ElementObject *self, PyTypeObject *cls,
+ PyObject *path, PyObject *default_value,
PyObject *namespaces)
-/*[clinic end generated code: output=83b3ba4535d308d2 input=b53a85aa5aa2a916]*/
+/*[clinic end generated code: output=6af7a2d96aac32cb input=32f252099f62a3d2]*/
{
Py_ssize_t i;
- _Py_IDENTIFIER(findtext);
- elementtreestate *st = ET_STATE_GLOBAL;
+ elementtreestate *st = get_elementtree_state_by_cls(cls);
if (checkpath(path) || namespaces != Py_None)
- return _PyObject_CallMethodIdObjArgs(
- st->elementpath_obj, &PyId_findtext,
+ return PyObject_CallMethodObjArgs(
+ st->elementpath_obj, st->str_findtext,
self, path, default_value, namespaces, NULL
);
if (!self->extra) {
- Py_INCREF(default_value);
- return default_value;
+ return Py_NewRef(default_value);
}
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) {
@@ -1295,31 +1332,31 @@ _elementtree_Element_findtext_impl(ElementObject *self, PyObject *path,
return NULL;
}
- Py_INCREF(default_value);
- return default_value;
+ return Py_NewRef(default_value);
}
/*[clinic input]
_elementtree.Element.findall
+ cls: defining_class
+ /
path: object
namespaces: object = None
[clinic start generated code]*/
static PyObject *
-_elementtree_Element_findall_impl(ElementObject *self, PyObject *path,
- PyObject *namespaces)
-/*[clinic end generated code: output=1a0bd9f5541b711d input=4d9e6505a638550c]*/
+_elementtree_Element_findall_impl(ElementObject *self, PyTypeObject *cls,
+ PyObject *path, PyObject *namespaces)
+/*[clinic end generated code: output=65e39a1208f3b59e input=7aa0db45673fc9a5]*/
{
Py_ssize_t i;
PyObject* out;
- elementtreestate *st = ET_STATE_GLOBAL;
+ elementtreestate *st = get_elementtree_state_by_cls(cls);
if (checkpath(path) || namespaces != Py_None) {
- _Py_IDENTIFIER(findall);
- return _PyObject_CallMethodIdObjArgs(
- st->elementpath_obj, &PyId_findall, self, path, namespaces, NULL
+ return PyObject_CallMethodObjArgs(
+ st->elementpath_obj, st->str_findall, self, path, namespaces, NULL
);
}
@@ -1333,7 +1370,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)) {
@@ -1350,22 +1387,23 @@ _elementtree_Element_findall_impl(ElementObject *self, PyObject *path,
/*[clinic input]
_elementtree.Element.iterfind
+ cls: defining_class
+ /
path: object
namespaces: object = None
[clinic start generated code]*/
static PyObject *
-_elementtree_Element_iterfind_impl(ElementObject *self, PyObject *path,
- PyObject *namespaces)
-/*[clinic end generated code: output=ecdd56d63b19d40f input=abb974e350fb65c7]*/
+_elementtree_Element_iterfind_impl(ElementObject *self, PyTypeObject *cls,
+ PyObject *path, PyObject *namespaces)
+/*[clinic end generated code: output=be5c3f697a14e676 input=88766875a5c9a88b]*/
{
PyObject* tag = path;
- _Py_IDENTIFIER(iterfind);
- elementtreestate *st = ET_STATE_GLOBAL;
+ elementtreestate *st = get_elementtree_state_by_cls(cls);
- return _PyObject_CallMethodIdObjArgs(
- st->elementpath_obj, &PyId_iterfind, self, tag, namespaces, NULL);
+ return PyObject_CallMethodObjArgs(
+ st->elementpath_obj, st->str_iterfind, self, tag, namespaces, NULL);
}
/*[clinic input]
@@ -1382,34 +1420,35 @@ _elementtree_Element_get_impl(ElementObject *self, PyObject *key,
/*[clinic end generated code: output=523c614142595d75 input=ee153bbf8cdb246e]*/
{
if (self->extra && self->extra->attrib) {
- PyObject *attrib = self->extra->attrib;
- Py_INCREF(attrib);
- PyObject *value = PyDict_GetItemWithError(attrib, key);
- Py_XINCREF(value);
+ PyObject *attrib = Py_NewRef(self->extra->attrib);
+ PyObject *value = Py_XNewRef(PyDict_GetItemWithError(attrib, key));
Py_DECREF(attrib);
if (value != NULL || PyErr_Occurred()) {
return value;
}
}
- Py_INCREF(default_value);
- return default_value;
+ return Py_NewRef(default_value);
}
static PyObject *
-create_elementiter(ElementObject *self, PyObject *tag, int gettext);
+create_elementiter(elementtreestate *st, ElementObject *self, PyObject *tag,
+ int gettext);
/*[clinic input]
_elementtree.Element.iter
+ cls: defining_class
+ /
tag: object = None
[clinic start generated code]*/
static PyObject *
-_elementtree_Element_iter_impl(ElementObject *self, PyObject *tag)
-/*[clinic end generated code: output=3f49f9a862941cc5 input=774d5b12e573aedd]*/
+_elementtree_Element_iter_impl(ElementObject *self, PyTypeObject *cls,
+ PyObject *tag)
+/*[clinic end generated code: output=bff29dc5d4566c68 input=f6944c48d3f84c58]*/
{
if (PyUnicode_Check(tag)) {
if (PyUnicode_READY(tag) < 0)
@@ -1422,20 +1461,25 @@ _elementtree_Element_iter_impl(ElementObject *self, PyObject *tag)
tag = Py_None;
}
- return create_elementiter(self, tag, 0);
+ elementtreestate *st = get_elementtree_state_by_cls(cls);
+ return create_elementiter(st, self, tag, 0);
}
/*[clinic input]
_elementtree.Element.itertext
+ cls: defining_class
+ /
+
[clinic start generated code]*/
static PyObject *
-_elementtree_Element_itertext_impl(ElementObject *self)
-/*[clinic end generated code: output=5fa34b2fbcb65df6 input=af8f0e42cb239c89]*/
+_elementtree_Element_itertext_impl(ElementObject *self, PyTypeObject *cls)
+/*[clinic end generated code: output=fdeb2a3bca0ae063 input=a1ef1f0fc872a586]*/
{
- return create_elementiter(self, Py_None, 1);
+ elementtreestate *st = get_elementtree_state_by_cls(cls);
+ return create_elementiter(st, self, Py_None, 1);
}
@@ -1452,15 +1496,31 @@ element_getitem(PyObject* self_, Py_ssize_t index)
return NULL;
}
- Py_INCREF(self->extra->children[index]);
- return self->extra->children[index];
+ return Py_NewRef(self->extra->children[index]);
+}
+
+static int
+element_bool(PyObject* self_)
+{
+ ElementObject* self = (ElementObject*) self_;
+ if (PyErr_WarnEx(PyExc_DeprecationWarning,
+ "Testing an element's truth value will raise an exception "
+ "in future versions. Use specific 'len(elem)' or "
+ "'elem is not None' test instead.",
+ 1) < 0) {
+ return -1;
+ };
+ if (self->extra ? self->extra->length : 0) {
+ return 1;
+ }
+ return 0;
}
/*[clinic input]
_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]*/
@@ -1468,7 +1528,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=9530f4905aa401ca]*/
{
Py_ssize_t i;
@@ -1491,8 +1551,7 @@ _elementtree_Element_insert_impl(ElementObject *self, Py_ssize_t index,
for (i = self->extra->length; i > index; i--)
self->extra->children[i] = self->extra->children[i-1];
- Py_INCREF(subelement);
- self->extra->children[index] = subelement;
+ self->extra->children[index] = Py_NewRef(subelement);
self->extra->length++;
@@ -1541,6 +1600,7 @@ element_length(ElementObject* self)
/*[clinic input]
_elementtree.Element.makeelement
+ cls: defining_class
tag: object
attrib: object(subclass_of='&PyDict_Type')
/
@@ -1548,9 +1608,9 @@ _elementtree.Element.makeelement
[clinic start generated code]*/
static PyObject *
-_elementtree_Element_makeelement_impl(ElementObject *self, PyObject *tag,
- PyObject *attrib)
-/*[clinic end generated code: output=4109832d5bb789ef input=2279d974529c3861]*/
+_elementtree_Element_makeelement_impl(ElementObject *self, PyTypeObject *cls,
+ PyObject *tag, PyObject *attrib)
+/*[clinic end generated code: output=d50bb17a47077d47 input=589829dab92f26e8]*/
{
PyObject* elem;
@@ -1558,7 +1618,8 @@ _elementtree_Element_makeelement_impl(ElementObject *self, PyObject *tag,
if (!attrib)
return NULL;
- elem = create_new_element(tag, attrib);
+ elementtreestate *st = get_elementtree_state_by_cls(cls);
+ elem = create_new_element(st, tag, attrib);
Py_DECREF(attrib);
@@ -1568,14 +1629,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=d52fc28ededc0bd8]*/
+/*[clinic end generated code: output=38fe6c07d6d87d1f input=6133e1d05597d5ee]*/
{
Py_ssize_t i;
int rc;
@@ -1689,12 +1750,13 @@ element_setitem(PyObject* self_, Py_ssize_t index, PyObject* item)
old = self->extra->children[index];
if (item) {
- if (!Element_Check(item)) {
+ PyTypeObject *tp = Py_TYPE(self);
+ elementtreestate *st = get_elementtree_state_by_type(tp);
+ if (!Element_Check(st, item)) {
raise_type_error(item);
return -1;
}
- Py_INCREF(item);
- self->extra->children[index] = item;
+ self->extra->children[index] = Py_NewRef(item);
} else {
self->extra->length--;
for (i = index; i < self->extra->length; i++)
@@ -1744,8 +1806,7 @@ element_subscr(PyObject* self_, PyObject* item)
for (cur = start, i = 0; i < slicelen;
cur += step, i++) {
- PyObject* item = self->extra->children[cur];
- Py_INCREF(item);
+ PyObject* item = Py_NewRef(self->extra->children[cur]);
PyList_SET_ITEM(list, i, item);
}
@@ -1888,9 +1949,11 @@ element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value)
}
}
+ PyTypeObject *tp = Py_TYPE(self);
+ elementtreestate *st = get_elementtree_state_by_type(tp);
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;
@@ -1925,8 +1988,7 @@ element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value)
for (cur = start, i = 0; i < newlen;
cur += step, i++) {
PyObject* element = PySequence_Fast_GET_ITEM(seq, i);
- Py_INCREF(element);
- self->extra->children[cur] = element;
+ self->extra->children[cur] = Py_NewRef(element);
}
self->extra->length += newlen - slicelen;
@@ -1949,24 +2011,21 @@ static PyObject*
element_tag_getter(ElementObject *self, void *closure)
{
PyObject *res = self->tag;
- Py_INCREF(res);
- return res;
+ return Py_NewRef(res);
}
static PyObject*
element_text_getter(ElementObject *self, void *closure)
{
PyObject *res = element_get_text(self);
- Py_XINCREF(res);
- return res;
+ return Py_XNewRef(res);
}
static PyObject*
element_tail_getter(ElementObject *self, void *closure)
{
PyObject *res = element_get_tail(self);
- Py_XINCREF(res);
- return res;
+ return Py_XNewRef(res);
}
static PyObject*
@@ -1978,8 +2037,7 @@ element_attrib_getter(ElementObject *self, void *closure)
return NULL;
}
res = element_get_attrib(self);
- Py_XINCREF(res);
- return res;
+ return Py_XNewRef(res);
}
/* macro for setter validation */
@@ -1995,8 +2053,7 @@ static int
element_tag_setter(ElementObject *self, PyObject *value, void *closure)
{
_VALIDATE_ATTR_VALUE(value);
- Py_INCREF(value);
- Py_SETREF(self->tag, value);
+ Py_SETREF(self->tag, Py_NewRef(value));
return 0;
}
@@ -2004,8 +2061,7 @@ static int
element_text_setter(ElementObject *self, PyObject *value, void *closure)
{
_VALIDATE_ATTR_VALUE(value);
- Py_INCREF(value);
- _set_joined_ptr(&self->text, value);
+ _set_joined_ptr(&self->text, Py_NewRef(value));
return 0;
}
@@ -2013,8 +2069,7 @@ static int
element_tail_setter(ElementObject *self, PyObject *value, void *closure)
{
_VALIDATE_ATTR_VALUE(value);
- Py_INCREF(value);
- _set_joined_ptr(&self->tail, value);
+ _set_joined_ptr(&self->tail, Py_NewRef(value));
return 0;
}
@@ -2032,21 +2087,10 @@ element_attrib_setter(ElementObject *self, PyObject *value, void *closure)
if (create_extra(self, NULL) < 0)
return -1;
}
- Py_INCREF(value);
- Py_XSETREF(self->extra->attrib, value);
+ Py_XSETREF(self->extra->attrib, Py_NewRef(value));
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
@@ -2076,6 +2120,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 */
@@ -2087,7 +2132,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
@@ -2099,6 +2145,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;
}
@@ -2119,8 +2166,7 @@ parent_stack_push_new(ElementIterObject *it, ElementObject *parent)
it->parent_stack_size = new_size;
}
item = it->parent_stack + it->parent_stack_used++;
- Py_INCREF(parent);
- item->parent = parent;
+ item->parent = (ElementObject*)Py_NewRef(parent);
item->child_index = 0;
return 0;
}
@@ -2180,10 +2226,13 @@ elementiter_next(ElementIterObject *it)
continue;
}
- assert(Element_Check(extra->children[child_index]));
- elem = (ElementObject *)extra->children[child_index];
+#ifndef NDEBUG
+ PyTypeObject *tp = Py_TYPE(it);
+ elementtreestate *st = get_elementtree_state_by_type(tp);
+ assert(Element_Check(st, extra->children[child_index]));
+#endif
+ elem = (ElementObject *)Py_NewRef(extra->children[child_index]);
item->child_index++;
- Py_INCREF(elem);
}
if (parent_stack_push_new(it, elem) < 0) {
@@ -2231,67 +2280,39 @@ 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
static PyObject *
-create_elementiter(ElementObject *self, PyObject *tag, int gettext)
+create_elementiter(elementtreestate *st, ElementObject *self, PyObject *tag,
+ int gettext)
{
ElementIterObject *it;
- it = PyObject_GC_New(ElementIterObject, &ElementIter_Type);
+ it = PyObject_GC_New(ElementIterObject, st->ElementIter_Type);
if (!it)
return NULL;
- Py_INCREF(tag);
- it->sought_tag = tag;
+ it->sought_tag = Py_NewRef(tag);
it->gettext = gettext;
- Py_INCREF(self);
- it->root_element = self;
+ it->root_element = (ElementObject*)Py_NewRef(self);
it->parent_stack = PyMem_New(ParentLocator, INIT_PARENT_STACK_SIZE);
if (it->parent_stack == NULL) {
@@ -2340,9 +2361,10 @@ typedef struct {
char insert_comments;
char insert_pis;
+ elementtreestate *state;
} TreeBuilderObject;
-#define TreeBuilder_CheckExact(op) Py_IS_TYPE((op), &TreeBuilder_Type)
+#define TreeBuilder_CheckExact(st, op) Py_IS_TYPE((op), (st)->TreeBuilder_Type)
/* -------------------------------------------------------------------- */
/* constructor and destructor */
@@ -2353,12 +2375,8 @@ treebuilder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
TreeBuilderObject *t = (TreeBuilderObject *)type->tp_alloc(type, 0);
if (t != NULL) {
t->root = NULL;
-
- Py_INCREF(Py_None);
- t->this = Py_None;
- Py_INCREF(Py_None);
- t->last = Py_None;
-
+ t->this = Py_NewRef(Py_None);
+ t->last = Py_NewRef(Py_None);
t->data = NULL;
t->element_factory = NULL;
t->comment_factory = NULL;
@@ -2377,6 +2395,7 @@ treebuilder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
t->start_ns_event_obj = t->end_ns_event_obj = NULL;
t->comment_event_obj = t->pi_event_obj = NULL;
t->insert_comments = t->insert_pis = 0;
+ t->state = get_elementtree_state_by_type(type);
}
return (PyObject *)t;
}
@@ -2402,19 +2421,17 @@ _elementtree_TreeBuilder___init___impl(TreeBuilderObject *self,
/*[clinic end generated code: output=8571d4dcadfdf952 input=ae98a94df20b5cc3]*/
{
if (element_factory != Py_None) {
- Py_INCREF(element_factory);
- Py_XSETREF(self->element_factory, element_factory);
+ Py_XSETREF(self->element_factory, Py_NewRef(element_factory));
} else {
Py_CLEAR(self->element_factory);
}
if (comment_factory == Py_None) {
- elementtreestate *st = ET_STATE_GLOBAL;
+ elementtreestate *st = self->state;
comment_factory = st->comment_factory;
}
if (comment_factory) {
- Py_INCREF(comment_factory);
- Py_XSETREF(self->comment_factory, comment_factory);
+ Py_XSETREF(self->comment_factory, Py_NewRef(comment_factory));
self->insert_comments = insert_comments;
} else {
Py_CLEAR(self->comment_factory);
@@ -2422,12 +2439,11 @@ _elementtree_TreeBuilder___init___impl(TreeBuilderObject *self,
}
if (pi_factory == Py_None) {
- elementtreestate *st = ET_STATE_GLOBAL;
+ elementtreestate *st = self->state;
pi_factory = st->pi_factory;
}
if (pi_factory) {
- Py_INCREF(pi_factory);
- Py_XSETREF(self->pi_factory, pi_factory);
+ Py_XSETREF(self->pi_factory, Py_NewRef(pi_factory));
self->insert_pis = insert_pis;
} else {
Py_CLEAR(self->pi_factory);
@@ -2440,6 +2456,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);
@@ -2484,9 +2501,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);
}
/* -------------------------------------------------------------------- */
@@ -2509,7 +2528,7 @@ _elementtree__set_factories_impl(PyObject *module, PyObject *comment_factory,
PyObject *pi_factory)
/*[clinic end generated code: output=813b408adee26535 input=99d17627aea7fb3b]*/
{
- elementtreestate *st = ET_STATE_GLOBAL;
+ elementtreestate *st = get_elementtree_state(module);
PyObject *old;
if (!PyCallable_Check(comment_factory) && comment_factory != Py_None) {
@@ -2530,25 +2549,24 @@ _elementtree__set_factories_impl(PyObject *module, PyObject *comment_factory,
if (comment_factory == Py_None) {
Py_CLEAR(st->comment_factory);
} else {
- Py_INCREF(comment_factory);
- Py_XSETREF(st->comment_factory, comment_factory);
+ Py_XSETREF(st->comment_factory, Py_NewRef(comment_factory));
}
if (pi_factory == Py_None) {
Py_CLEAR(st->pi_factory);
} else {
- Py_INCREF(pi_factory);
- Py_XSETREF(st->pi_factory, pi_factory);
+ Py_XSETREF(st->pi_factory, Py_NewRef(pi_factory));
}
return old;
}
static int
-treebuilder_extend_element_text_or_tail(PyObject *element, PyObject **data,
- PyObject **dest, _Py_Identifier *name)
+treebuilder_extend_element_text_or_tail(elementtreestate *st, PyObject *element,
+ PyObject **data, PyObject **dest,
+ PyObject *name)
{
/* Fast paths for the "almost always" cases. */
- if (Element_CheckExact(element)) {
+ if (Element_CheckExact(st, element)) {
PyObject *dest_obj = JOIN_OBJ(*dest);
if (dest_obj == Py_None) {
*dest = JOIN_SET(*data, PyList_CheckExact(*data));
@@ -2569,7 +2587,7 @@ treebuilder_extend_element_text_or_tail(PyObject *element, PyObject **data,
{
int r;
PyObject* joined;
- PyObject* previous = _PyObject_GetAttrId(element, name);
+ PyObject* previous = PyObject_GetAttr(element, name);
if (!previous)
return -1;
joined = list_join(*data);
@@ -2588,7 +2606,7 @@ treebuilder_extend_element_text_or_tail(PyObject *element, PyObject **data,
Py_DECREF(previous);
}
- r = _PyObject_SetAttrId(element, name, joined);
+ r = PyObject_SetAttr(element, name, joined);
Py_DECREF(joined);
if (r < 0)
return -1;
@@ -2603,34 +2621,32 @@ treebuilder_flush_data(TreeBuilderObject* self)
if (!self->data) {
return 0;
}
-
+ elementtreestate *st = self->state;
if (!self->last_for_tail) {
PyObject *element = self->last;
- _Py_IDENTIFIER(text);
return treebuilder_extend_element_text_or_tail(
- element, &self->data,
- &((ElementObject *) element)->text, &PyId_text);
+ st, element, &self->data,
+ &((ElementObject *) element)->text, st->str_text);
}
else {
PyObject *element = self->last_for_tail;
- _Py_IDENTIFIER(tail);
return treebuilder_extend_element_text_or_tail(
- element, &self->data,
- &((ElementObject *) element)->tail, &PyId_tail);
+ st, element, &self->data,
+ &((ElementObject *) element)->tail, st->str_tail);
}
}
static int
-treebuilder_add_subelement(PyObject *element, PyObject *child)
+treebuilder_add_subelement(elementtreestate *st, PyObject *element,
+ PyObject *child)
{
- _Py_IDENTIFIER(append);
- if (Element_CheckExact(element)) {
+ if (Element_CheckExact(st, element)) {
ElementObject *elem = (ElementObject *) element;
- return element_add_subelement(elem, child);
+ return element_add_subelement(st, elem, child);
}
else {
PyObject *res;
- res = _PyObject_CallMethodIdOneArg(element, &PyId_append, child);
+ res = PyObject_CallMethodOneArg(element, st->str_append, child);
if (res == NULL)
return -1;
Py_DECREF(res);
@@ -2665,15 +2681,16 @@ treebuilder_handle_start(TreeBuilderObject* self, PyObject* tag,
{
PyObject* node;
PyObject* this;
- elementtreestate *st = ET_STATE_GLOBAL;
+ elementtreestate *st = self->state;
if (treebuilder_flush_data(self) < 0) {
return NULL;
}
if (!self->element_factory) {
- node = create_new_element(tag, attrib);
- } else if (attrib == NULL) {
+ node = create_new_element(st, tag, attrib);
+ }
+ else if (attrib == NULL) {
attrib = PyDict_New();
if (!attrib)
return NULL;
@@ -2693,8 +2710,9 @@ treebuilder_handle_start(TreeBuilderObject* self, PyObject* tag,
Py_CLEAR(self->last_for_tail);
if (this != Py_None) {
- if (treebuilder_add_subelement(this, node) < 0)
+ if (treebuilder_add_subelement(st, this, node) < 0) {
goto error;
+ }
} else {
if (self->root) {
PyErr_SetString(
@@ -2703,8 +2721,7 @@ treebuilder_handle_start(TreeBuilderObject* self, PyObject* tag,
);
goto error;
}
- Py_INCREF(node);
- self->root = node;
+ self->root = Py_NewRef(node);
}
if (self->index < PyList_GET_SIZE(self->stack)) {
@@ -2717,10 +2734,8 @@ treebuilder_handle_start(TreeBuilderObject* self, PyObject* tag,
}
self->index++;
- Py_INCREF(node);
- Py_SETREF(self->this, node);
- Py_INCREF(node);
- Py_SETREF(self->last, node);
+ Py_SETREF(self->this, Py_NewRef(node));
+ Py_SETREF(self->last, Py_NewRef(node));
if (treebuilder_append_event(self, self->start_event_obj, node) < 0)
goto error;
@@ -2741,7 +2756,7 @@ treebuilder_handle_data(TreeBuilderObject* self, PyObject* data)
Py_RETURN_NONE;
}
/* store the first item as is */
- Py_INCREF(data); self->data = data;
+ self->data = Py_NewRef(data);
} else {
/* more than one item; use a list to collect items */
if (PyBytes_CheckExact(self->data) && Py_REFCNT(self->data) == 1 &&
@@ -2760,9 +2775,9 @@ treebuilder_handle_data(TreeBuilderObject* self, PyObject* data)
PyObject* list = PyList_New(2);
if (!list)
return NULL;
- PyList_SET_ITEM(list, 0, self->data);
- Py_INCREF(data); PyList_SET_ITEM(list, 1, data);
- self->data = list;
+ PyList_SET_ITEM(list, 0, Py_NewRef(self->data));
+ PyList_SET_ITEM(list, 1, Py_NewRef(data));
+ Py_SETREF(self->data, list);
}
}
@@ -2787,19 +2802,16 @@ treebuilder_handle_end(TreeBuilderObject* self, PyObject* tag)
}
item = self->last;
- self->last = self->this;
- Py_INCREF(self->last);
+ self->last = Py_NewRef(self->this);
Py_XSETREF(self->last_for_tail, self->last);
self->index--;
- self->this = PyList_GET_ITEM(self->stack, self->index);
- Py_INCREF(self->this);
+ self->this = Py_NewRef(PyList_GET_ITEM(self->stack, self->index));
Py_DECREF(item);
if (treebuilder_append_event(self, self->end_event_obj, self->last) < 0)
return NULL;
- Py_INCREF(self->last);
- return (PyObject*) self->last;
+ return Py_NewRef(self->last);
}
LOCAL(PyObject*)
@@ -2819,14 +2831,13 @@ treebuilder_handle_comment(TreeBuilderObject* self, PyObject* text)
this = self->this;
if (self->insert_comments && this != Py_None) {
- if (treebuilder_add_subelement(this, comment) < 0)
+ if (treebuilder_add_subelement(self->state, this, comment) < 0) {
goto error;
- Py_INCREF(comment);
- Py_XSETREF(self->last_for_tail, comment);
+ }
+ Py_XSETREF(self->last_for_tail, Py_NewRef(comment));
}
} else {
- Py_INCREF(text);
- comment = text;
+ comment = Py_NewRef(text);
}
if (self->events_append && self->comment_event_obj) {
@@ -2860,10 +2871,10 @@ treebuilder_handle_pi(TreeBuilderObject* self, PyObject* target, PyObject* text)
this = self->this;
if (self->insert_pis && this != Py_None) {
- if (treebuilder_add_subelement(this, pi) < 0)
+ if (treebuilder_add_subelement(self->state, this, pi) < 0) {
goto error;
- Py_INCREF(pi);
- Py_XSETREF(self->last_for_tail, pi);
+ }
+ Py_XSETREF(self->last_for_tail, Py_NewRef(pi));
}
} else {
pi = PyTuple_Pack(2, target, text);
@@ -2994,8 +3005,7 @@ treebuilder_done(TreeBuilderObject* self)
else
res = Py_None;
- Py_INCREF(res);
- return res;
+ return Py_NewRef(res);
}
/*[clinic input]
@@ -3030,14 +3040,7 @@ _elementtree_TreeBuilder_start_impl(TreeBuilderObject *self, PyObject *tag,
/* ==================================================================== */
/* the expat interface */
-#include "expat.h"
-#include "pyexpat.h"
-
-/* The PyExpat_CAPI structure is an immutable dispatch table, so it can be
- * cached globally without being in per-module state.
- */
-static struct PyExpat_CAPI *expat_capi;
-#define EXPAT(func) (expat_capi->func)
+#define EXPAT(st, func) ((st)->expat_capi->func)
static XML_Memory_Handling_Suite ExpatMemoryHandler = {
PyObject_Malloc, PyObject_Realloc, PyObject_Free};
@@ -3064,6 +3067,8 @@ typedef struct {
PyObject *handle_close;
+ elementtreestate *state;
+ PyObject *elementtree_module;
} XMLParserObject;
/* helpers */
@@ -3083,12 +3088,9 @@ makeuniversal(XMLParserObject* self, const char* string)
if (!key)
return NULL;
- value = PyDict_GetItemWithError(self->names, key);
+ value = Py_XNewRef(PyDict_GetItemWithError(self->names, key));
- if (value) {
- Py_INCREF(value);
- }
- else if (!PyErr_Occurred()) {
+ if (value == NULL && !PyErr_Occurred()) {
/* new name. convert to universal name, and decode as
necessary */
@@ -3113,8 +3115,7 @@ makeuniversal(XMLParserObject* self, const char* string)
size++;
} else {
/* plain name; use key as tag */
- Py_INCREF(key);
- tag = key;
+ tag = Py_NewRef(key);
}
/* decode universal name */
@@ -3143,14 +3144,13 @@ makeuniversal(XMLParserObject* self, const char* string)
* message string is the default for the given error_code.
*/
static void
-expat_set_error(enum XML_Error error_code, Py_ssize_t line, Py_ssize_t column,
- const char *message)
+expat_set_error(elementtreestate *st, enum XML_Error error_code,
+ Py_ssize_t line, Py_ssize_t column, const char *message)
{
PyObject *errmsg, *error, *position, *code;
- elementtreestate *st = ET_STATE_GLOBAL;
errmsg = PyUnicode_FromFormat("%s: line %zd, column %zd",
- message ? message : EXPAT(ErrorString)(error_code),
+ message ? message : EXPAT(st, ErrorString)(error_code),
line, column);
if (errmsg == NULL)
return;
@@ -3212,8 +3212,9 @@ expat_default_handler(XMLParserObject* self, const XML_Char* data_in,
value = PyDict_GetItemWithError(self->entity, key);
+ elementtreestate *st = self->state;
if (value) {
- if (TreeBuilder_CheckExact(self->target))
+ if (TreeBuilder_CheckExact(st, self->target))
res = treebuilder_handle_data(
(TreeBuilderObject*) self->target, value
);
@@ -3227,9 +3228,10 @@ expat_default_handler(XMLParserObject* self, const XML_Char* data_in,
char message[128] = "undefined entity ";
strncat(message, data_in, data_len < 100?data_len:100);
expat_set_error(
+ st,
XML_ERROR_UNDEFINED_ENTITY,
- EXPAT(GetErrorLineNumber)(self->parser),
- EXPAT(GetErrorColumnNumber)(self->parser),
+ EXPAT(st, GetErrorLineNumber)(self->parser),
+ EXPAT(st, GetErrorColumnNumber)(self->parser),
message
);
}
@@ -3289,7 +3291,8 @@ expat_start_handler(XMLParserObject* self, const XML_Char* tag_in,
attrib = NULL;
}
- if (TreeBuilder_CheckExact(self->target)) {
+ elementtreestate *st = self->state;
+ if (TreeBuilder_CheckExact(st, self->target)) {
/* shortcut */
res = treebuilder_handle_start((TreeBuilderObject*) self->target,
tag, attrib);
@@ -3327,7 +3330,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 = self->state;
+ if (TreeBuilder_CheckExact(st, self->target))
/* shortcut */
res = treebuilder_handle_data((TreeBuilderObject*) self->target, data);
else if (self->handle_data)
@@ -3349,7 +3353,8 @@ expat_end_handler(XMLParserObject* self, const XML_Char* tag_in)
if (PyErr_Occurred())
return;
- if (TreeBuilder_CheckExact(self->target))
+ elementtreestate *st = self->state;
+ if (TreeBuilder_CheckExact(st, self->target))
/* shortcut */
/* the standard tree builder doesn't look at the end tag */
res = treebuilder_handle_end(
@@ -3383,7 +3388,8 @@ expat_start_ns_handler(XMLParserObject* self, const XML_Char* prefix_in,
if (!prefix_in)
prefix_in = "";
- if (TreeBuilder_CheckExact(self->target)) {
+ elementtreestate *st = self->state;
+ if (TreeBuilder_CheckExact(st, self->target)) {
/* shortcut - TreeBuilder does not actually implement .start_ns() */
TreeBuilderObject *target = (TreeBuilderObject*) self->target;
@@ -3433,7 +3439,8 @@ expat_end_ns_handler(XMLParserObject* self, const XML_Char* prefix_in)
if (!prefix_in)
prefix_in = "";
- if (TreeBuilder_CheckExact(self->target)) {
+ elementtreestate *st = self->state;
+ if (TreeBuilder_CheckExact(st, self->target)) {
/* shortcut - TreeBuilder does not actually implement .end_ns() */
TreeBuilderObject *target = (TreeBuilderObject*) self->target;
@@ -3461,7 +3468,8 @@ expat_comment_handler(XMLParserObject* self, const XML_Char* comment_in)
if (PyErr_Occurred())
return;
- if (TreeBuilder_CheckExact(self->target)) {
+ elementtreestate *st = self->state;
+ if (TreeBuilder_CheckExact(st, self->target)) {
/* shortcut */
TreeBuilderObject *target = (TreeBuilderObject*) self->target;
@@ -3490,7 +3498,6 @@ expat_start_doctype_handler(XMLParserObject *self,
const XML_Char *pubid,
int has_internal_subset)
{
- _Py_IDENTIFIER(doctype);
PyObject *doctype_name_obj, *sysid_obj, *pubid_obj;
PyObject *res;
@@ -3508,8 +3515,7 @@ expat_start_doctype_handler(XMLParserObject *self,
return;
}
} else {
- Py_INCREF(Py_None);
- sysid_obj = Py_None;
+ sysid_obj = Py_NewRef(Py_None);
}
if (pubid) {
@@ -3520,10 +3526,10 @@ expat_start_doctype_handler(XMLParserObject *self,
return;
}
} else {
- Py_INCREF(Py_None);
- pubid_obj = Py_None;
+ pubid_obj = Py_NewRef(Py_None);
}
+ elementtreestate *st = self->state;
/* If the target has a handler for doctype, call it. */
if (self->handle_doctype) {
res = PyObject_CallFunctionObjArgs(self->handle_doctype,
@@ -3531,7 +3537,7 @@ expat_start_doctype_handler(XMLParserObject *self,
sysid_obj, NULL);
Py_XDECREF(res);
}
- else if (_PyObject_LookupAttrId((PyObject *)self, &PyId_doctype, &res) > 0) {
+ else if (_PyObject_LookupAttr((PyObject *)self, st->str_doctype, &res) > 0) {
(void)PyErr_WarnEx(PyExc_RuntimeWarning,
"The doctype() method of XMLParser is ignored. "
"Define doctype() method on the TreeBuilder target.",
@@ -3556,7 +3562,8 @@ expat_pi_handler(XMLParserObject* self, const XML_Char* target_in,
if (PyErr_Occurred())
return;
- if (TreeBuilder_CheckExact(self->target)) {
+ elementtreestate *st = self->state;
+ if (TreeBuilder_CheckExact(st, self->target)) {
/* shortcut */
TreeBuilderObject *target = (TreeBuilderObject*) self->target;
@@ -3608,6 +3615,11 @@ xmlparser_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
self->handle_start = self->handle_data = self->handle_end = NULL;
self->handle_comment = self->handle_pi = self->handle_close = NULL;
self->handle_doctype = NULL;
+ self->elementtree_module = PyType_GetModuleByDef(type, &elementtreemodule);
+ assert(self->elementtree_module != NULL);
+ Py_INCREF(self->elementtree_module);
+ // See gh-111784 for explanation why is reference to module needed here.
+ self->state = get_elementtree_state(self->elementtree_module);
}
return (PyObject *)self;
}
@@ -3647,8 +3659,8 @@ _elementtree_XMLParser___init___impl(XMLParserObject *self, PyObject *target,
Py_CLEAR(self->entity);
return -1;
}
-
- self->parser = EXPAT(ParserCreate_MM)(encoding, &ExpatMemoryHandler, "}");
+ elementtreestate *st = self->state;
+ self->parser = EXPAT(st, ParserCreate_MM)(encoding, &ExpatMemoryHandler, "}");
if (!self->parser) {
Py_CLEAR(self->entity);
Py_CLEAR(self->names);
@@ -3656,15 +3668,15 @@ _elementtree_XMLParser___init___impl(XMLParserObject *self, PyObject *target,
return -1;
}
/* expat < 2.1.0 has no XML_SetHashSalt() */
- if (EXPAT(SetHashSalt) != NULL) {
- EXPAT(SetHashSalt)(self->parser,
+ if (EXPAT(st, SetHashSalt) != NULL) {
+ EXPAT(st, SetHashSalt)(self->parser,
(unsigned long)_Py_HashSecret.expat.hashsalt);
}
if (target != Py_None) {
Py_INCREF(target);
} else {
- target = treebuilder_new(&TreeBuilder_Type, NULL, NULL);
+ target = treebuilder_new(st->TreeBuilder_Type, NULL, NULL);
if (!target) {
Py_CLEAR(self->entity);
Py_CLEAR(self->names);
@@ -3711,43 +3723,43 @@ _elementtree_XMLParser___init___impl(XMLParserObject *self, PyObject *target,
}
/* configure parser */
- EXPAT(SetUserData)(self->parser, self);
+ EXPAT(st, SetUserData)(self->parser, self);
if (self->handle_start_ns || self->handle_end_ns)
- EXPAT(SetNamespaceDeclHandler)(
+ EXPAT(st, SetNamespaceDeclHandler)(
self->parser,
(XML_StartNamespaceDeclHandler) expat_start_ns_handler,
(XML_EndNamespaceDeclHandler) expat_end_ns_handler
);
- EXPAT(SetElementHandler)(
+ EXPAT(st, SetElementHandler)(
self->parser,
(XML_StartElementHandler) expat_start_handler,
(XML_EndElementHandler) expat_end_handler
);
- EXPAT(SetDefaultHandlerExpand)(
+ EXPAT(st, SetDefaultHandlerExpand)(
self->parser,
(XML_DefaultHandler) expat_default_handler
);
- EXPAT(SetCharacterDataHandler)(
+ EXPAT(st, SetCharacterDataHandler)(
self->parser,
(XML_CharacterDataHandler) expat_data_handler
);
if (self->handle_comment)
- EXPAT(SetCommentHandler)(
+ EXPAT(st, SetCommentHandler)(
self->parser,
(XML_CommentHandler) expat_comment_handler
);
if (self->handle_pi)
- EXPAT(SetProcessingInstructionHandler)(
+ EXPAT(st, SetProcessingInstructionHandler)(
self->parser,
(XML_ProcessingInstructionHandler) expat_pi_handler
);
- EXPAT(SetStartDoctypeDeclHandler)(
+ EXPAT(st, SetStartDoctypeDeclHandler)(
self->parser,
(XML_StartDoctypeDeclHandler) expat_start_doctype_handler
);
- EXPAT(SetUnknownEncodingHandler)(
+ EXPAT(st, SetUnknownEncodingHandler)(
self->parser,
- EXPAT(DefaultUnknownEncodingHandler), NULL
+ EXPAT(st, DefaultUnknownEncodingHandler), NULL
);
return 0;
@@ -3756,6 +3768,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);
@@ -3776,12 +3789,14 @@ xmlparser_gc_traverse(XMLParserObject *self, visitproc visit, void *arg)
static int
xmlparser_gc_clear(XMLParserObject *self)
{
+ elementtreestate *st = self->state;
if (self->parser != NULL) {
XML_Parser parser = self->parser;
self->parser = NULL;
- EXPAT(ParserFree)(parser);
+ EXPAT(st, ParserFree)(parser);
}
+ Py_CLEAR(self->elementtree_module);
Py_CLEAR(self->handle_close);
Py_CLEAR(self->handle_pi);
Py_CLEAR(self->handle_comment);
@@ -3802,9 +3817,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)
@@ -3819,21 +3836,23 @@ _check_xmlparser(XMLParserObject* self)
}
LOCAL(PyObject*)
-expat_parse(XMLParserObject* self, const char* data, int data_len, int final)
+expat_parse(elementtreestate *st, XMLParserObject *self, const char *data,
+ int data_len, int final)
{
int ok;
assert(!PyErr_Occurred());
- ok = EXPAT(Parse)(self->parser, data, data_len, final);
+ ok = EXPAT(st, Parse)(self->parser, data, data_len, final);
if (PyErr_Occurred())
return NULL;
if (!ok) {
expat_set_error(
- EXPAT(GetErrorCode)(self->parser),
- EXPAT(GetErrorLineNumber)(self->parser),
- EXPAT(GetErrorColumnNumber)(self->parser),
+ st,
+ EXPAT(st, GetErrorCode)(self->parser),
+ EXPAT(st, GetErrorLineNumber)(self->parser),
+ EXPAT(st, GetErrorColumnNumber)(self->parser),
NULL
);
return NULL;
@@ -3858,11 +3877,12 @@ _elementtree_XMLParser_close_impl(XMLParserObject *self)
if (!_check_xmlparser(self)) {
return NULL;
}
- res = expat_parse(self, "", 0, 1);
+ elementtreestate *st = self->state;
+ res = expat_parse(st, self, "", 0, 1);
if (!res)
return NULL;
- if (TreeBuilder_CheckExact(self->target)) {
+ if (TreeBuilder_CheckExact(st, self->target)) {
Py_DECREF(res);
return treebuilder_done((TreeBuilderObject*) self->target);
}
@@ -3892,6 +3912,7 @@ _elementtree_XMLParser_feed(XMLParserObject *self, PyObject *data)
if (!_check_xmlparser(self)) {
return NULL;
}
+ elementtreestate *st = self->state;
if (PyUnicode_Check(data)) {
Py_ssize_t data_len;
const char *data_ptr = PyUnicode_AsUTF8AndSize(data, &data_len);
@@ -3902,8 +3923,9 @@ _elementtree_XMLParser_feed(XMLParserObject *self, PyObject *data)
return NULL;
}
/* Explicitly set UTF-8 encoding. Return code ignored. */
- (void)EXPAT(SetEncoding)(self->parser, "utf-8");
- return expat_parse(self, data_ptr, (int)data_len, 0);
+ (void)EXPAT(st, SetEncoding)(self->parser, "utf-8");
+
+ return expat_parse(st, self, data_ptr, (int)data_len, 0);
}
else {
Py_buffer view;
@@ -3915,7 +3937,7 @@ _elementtree_XMLParser_feed(XMLParserObject *self, PyObject *data)
PyErr_SetString(PyExc_OverflowError, "size does not fit in an int");
return NULL;
}
- res = expat_parse(self, view.buf, (int)view.len, 0);
+ res = expat_parse(st, self, view.buf, (int)view.len, 0);
PyBuffer_Release(&view);
return res;
}
@@ -3947,6 +3969,7 @@ _elementtree_XMLParser__parse_whole(XMLParserObject *self, PyObject *file)
return NULL;
/* read from open file object */
+ elementtreestate *st = self->state;
for (;;) {
buffer = PyObject_CallFunction(reader, "i", 64*1024);
@@ -3984,8 +4007,8 @@ _elementtree_XMLParser__parse_whole(XMLParserObject *self, PyObject *file)
return NULL;
}
res = expat_parse(
- self, PyBytes_AS_STRING(buffer), (int)PyBytes_GET_SIZE(buffer), 0
- );
+ st, self, PyBytes_AS_STRING(buffer), (int)PyBytes_GET_SIZE(buffer),
+ 0);
Py_DECREF(buffer);
@@ -3999,9 +4022,9 @@ _elementtree_XMLParser__parse_whole(XMLParserObject *self, PyObject *file)
Py_DECREF(reader);
- res = expat_parse(self, "", 0, 1);
+ res = expat_parse(st, self, "", 0, 1);
- if (res && TreeBuilder_CheckExact(self->target)) {
+ if (res && TreeBuilder_CheckExact(st, self->target)) {
Py_DECREF(res);
return treebuilder_done((TreeBuilderObject*) self->target);
}
@@ -4032,7 +4055,8 @@ _elementtree_XMLParser__setevents_impl(XMLParserObject *self,
if (!_check_xmlparser(self)) {
return NULL;
}
- if (!TreeBuilder_CheckExact(self->target)) {
+ elementtreestate *st = self->state;
+ if (!TreeBuilder_CheckExact(st, self->target)) {
PyErr_SetString(
PyExc_TypeError,
"event handling only supported for ElementTree.TreeBuilder "
@@ -4081,39 +4105,37 @@ _elementtree_XMLParser__setevents_impl(XMLParserObject *self,
return NULL;
}
- Py_INCREF(event_name_obj);
if (strcmp(event_name, "start") == 0) {
- Py_XSETREF(target->start_event_obj, event_name_obj);
+ Py_XSETREF(target->start_event_obj, Py_NewRef(event_name_obj));
} else if (strcmp(event_name, "end") == 0) {
- Py_XSETREF(target->end_event_obj, event_name_obj);
+ Py_XSETREF(target->end_event_obj, Py_NewRef(event_name_obj));
} else if (strcmp(event_name, "start-ns") == 0) {
- Py_XSETREF(target->start_ns_event_obj, event_name_obj);
- EXPAT(SetNamespaceDeclHandler)(
+ Py_XSETREF(target->start_ns_event_obj, Py_NewRef(event_name_obj));
+ EXPAT(st, SetNamespaceDeclHandler)(
self->parser,
(XML_StartNamespaceDeclHandler) expat_start_ns_handler,
(XML_EndNamespaceDeclHandler) expat_end_ns_handler
);
} else if (strcmp(event_name, "end-ns") == 0) {
- Py_XSETREF(target->end_ns_event_obj, event_name_obj);
- EXPAT(SetNamespaceDeclHandler)(
+ Py_XSETREF(target->end_ns_event_obj, Py_NewRef(event_name_obj));
+ EXPAT(st, SetNamespaceDeclHandler)(
self->parser,
(XML_StartNamespaceDeclHandler) expat_start_ns_handler,
(XML_EndNamespaceDeclHandler) expat_end_ns_handler
);
} else if (strcmp(event_name, "comment") == 0) {
- Py_XSETREF(target->comment_event_obj, event_name_obj);
- EXPAT(SetCommentHandler)(
+ Py_XSETREF(target->comment_event_obj, Py_NewRef(event_name_obj));
+ EXPAT(st, SetCommentHandler)(
self->parser,
(XML_CommentHandler) expat_comment_handler
);
} else if (strcmp(event_name, "pi") == 0) {
- Py_XSETREF(target->pi_event_obj, event_name_obj);
- EXPAT(SetProcessingInstructionHandler)(
+ Py_XSETREF(target->pi_event_obj, Py_NewRef(event_name_obj));
+ EXPAT(st, SetProcessingInstructionHandler)(
self->parser,
(XML_ProcessingInstructionHandler) expat_pi_handler
);
} else {
- Py_DECREF(event_name_obj);
Py_DECREF(events_seq);
PyErr_Format(PyExc_ValueError, "unknown event '%s'", event_name);
return NULL;
@@ -4143,7 +4165,9 @@ static PyGetSetDef xmlparser_getsetlist[] = {
{NULL},
};
+#define clinic_state() (get_elementtree_state_by_type(Py_TYPE(self)))
#include "clinic/_elementtree.c.h"
+#undef clinic_state
static PyMethodDef element_methods[] = {
@@ -4179,10 +4203,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[] = {
@@ -4205,46 +4228,34 @@ 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_nb_bool, element_bool},
+ {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[] = {
@@ -4257,46 +4268,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[] = {
@@ -4307,46 +4294,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,
};
/* ==================================================================== */
@@ -4358,96 +4324,135 @@ static PyMethodDef _functions[] = {
{NULL, NULL}
};
+#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)
-static struct PyModuleDef elementtreemodule = {
- PyModuleDef_HEAD_INIT,
- "_elementtree",
- NULL,
- sizeof(elementtreestate),
- _functions,
- NULL,
- elementtree_traverse,
- elementtree_clear,
- elementtree_free
-};
-
-PyMODINIT_FUNC
-PyInit__elementtree(void)
+static int
+module_exec(PyObject *m)
{
- PyObject *m, *temp;
- elementtreestate *st;
-
- m = PyState_FindModule(&elementtreemodule);
- if (m) {
- Py_INCREF(m);
- return m;
- }
+ elementtreestate *st = get_elementtree_state(m);
/* Initialize object types */
- if (PyType_Ready(&ElementIter_Type) < 0)
- return NULL;
- if (PyType_Ready(&TreeBuilder_Type) < 0)
- return NULL;
- if (PyType_Ready(&Element_Type) < 0)
- return NULL;
- if (PyType_Ready(&XMLParser_Type) < 0)
- return NULL;
-
- m = PyModule_Create(&elementtreemodule);
- if (!m)
- return NULL;
- st = get_elementtree_state(m);
-
- if (!(temp = PyImport_ImportModule("copy")))
- return NULL;
- st->deepcopy_obj = PyObject_GetAttrString(temp, "deepcopy");
- Py_XDECREF(temp);
+ 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) {
- 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);
- if (expat_capi) {
+ if (!(st->expat_capsule = _PyImport_GetModuleAttrString("pyexpat", "expat_CAPI")))
+ goto error;
+ if (!(st->expat_capi = PyCapsule_GetPointer(st->expat_capsule, PyExpat_CAPSULE_NAME)))
+ goto error;
+ if (st->expat_capi) {
/* check that it's usable */
- if (strcmp(expat_capi->magic, PyExpat_CAPI_MAGIC) != 0 ||
- (size_t)expat_capi->size < sizeof(struct PyExpat_CAPI) ||
- expat_capi->MAJOR_VERSION != XML_MAJOR_VERSION ||
- expat_capi->MINOR_VERSION != XML_MINOR_VERSION ||
- expat_capi->MICRO_VERSION != XML_MICRO_VERSION) {
+ if (strcmp(st->expat_capi->magic, PyExpat_CAPI_MAGIC) != 0 ||
+ (size_t)st->expat_capi->size < sizeof(struct PyExpat_CAPI) ||
+ st->expat_capi->MAJOR_VERSION != XML_MAJOR_VERSION ||
+ st->expat_capi->MINOR_VERSION != XML_MINOR_VERSION ||
+ st->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) {
+ goto error;
+ }
+ st->str_find = PyUnicode_InternFromString("find");
+ if (st->str_find == NULL) {
+ goto error;
+ }
+ st->str_findall = PyUnicode_InternFromString("findall");
+ if (st->str_findall == NULL) {
+ goto error;
+ }
+ st->str_findtext = PyUnicode_InternFromString("findtext");
+ if (st->str_findtext == NULL) {
+ goto error;
+ }
+ st->str_iterfind = PyUnicode_InternFromString("iterfind");
+ if (st->str_iterfind == NULL) {
+ goto error;
+ }
+ st->str_tail = PyUnicode_InternFromString("tail");
+ if (st->str_tail == NULL) {
+ goto error;
+ }
+ st->str_text = PyUnicode_InternFromString("text");
+ if (st->str_text == NULL) {
+ goto error;
+ }
+ st->str_doctype = PyUnicode_InternFromString("doctype");
+ if (st->str_doctype == NULL) {
+ goto error;
+ }
st->parseerror_obj = PyErr_NewException(
"xml.etree.ElementTree.ParseError", PyExc_SyntaxError, NULL
);
- Py_INCREF(st->parseerror_obj);
- if (PyModule_AddObject(m, "ParseError", st->parseerror_obj) < 0) {
- Py_DECREF(st->parseerror_obj);
- return NULL;
+ if (PyModule_AddObjectRef(m, "ParseError", st->parseerror_obj) < 0) {
+ goto error;
}
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++) {
if (PyModule_AddType(m, types[i]) < 0) {
- return NULL;
+ goto error;
}
}
- return m;
+ return 0;
+
+error:
+ return -1;
+}
+
+static struct PyModuleDef_Slot elementtree_slots[] = {
+ {Py_mod_exec, module_exec},
+ // XXX gh-103092: fix isolation.
+ {Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED},
+ //{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
+ {0, NULL},
+};
+
+static struct PyModuleDef elementtreemodule = {
+ .m_base = PyModuleDef_HEAD_INIT,
+ .m_name = "_elementtree",
+ .m_size = sizeof(elementtreestate),
+ .m_methods = _functions,
+ .m_slots = elementtree_slots,
+ .m_traverse = elementtree_traverse,
+ .m_clear = elementtree_clear,
+ .m_free = elementtree_free,
+};
+
+PyMODINIT_FUNC
+PyInit__elementtree(void)
+{
+ return PyModuleDef_Init(&elementtreemodule);
}