diff options
| author | AlexSm <[email protected]> | 2024-02-16 11:51:30 +0100 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-02-16 11:51:30 +0100 |
| commit | 506ecaee93b52cc12c2e2f97c3d42e3ca2a7f59e (patch) | |
| tree | d096fb9eb988fbb0ca1ba970041773207ce3aa70 /contrib/tools/python3/src/Modules/_elementtree.c | |
| parent | 4749b9e5d260714490997e6f5ee1ee8c1c8fc46c (diff) | |
| parent | f200f72c9d7a89c1018e3dc6b46c49fe2ecf84fb (diff) | |
Merge pull request #1940 from dcherednik/importlib
Library import 14
Diffstat (limited to 'contrib/tools/python3/src/Modules/_elementtree.c')
| -rw-r--r-- | contrib/tools/python3/src/Modules/_elementtree.c | 1203 |
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); } |
