Skip to content

Commit 7c1c42b

Browse files
[3.6] bpo-34941: Fix searching Element subclasses. (GH-9766) (GH-9868)
Methods find(), findtext() and findall() of xml.etree.ElementTree.Element were not able to find chldren which are instances of Element subclasses. (cherry picked from commit b11c566)
1 parent 6829930 commit 7c1c42b

File tree

3 files changed

+31
-12
lines changed

3 files changed

+31
-12
lines changed

Lib/test/test_xml_etree.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2145,6 +2145,21 @@ def newmethod(self):
21452145
mye = MyElement('joe')
21462146
self.assertEqual(mye.newmethod(), 'joe')
21472147

2148+
def test_Element_subclass_find(self):
2149+
class MyElement(ET.Element):
2150+
pass
2151+
2152+
e = ET.Element('foo')
2153+
e.text = 'text'
2154+
sub = MyElement('bar')
2155+
sub.text = 'subtext'
2156+
e.append(sub)
2157+
self.assertEqual(e.findtext('bar'), 'subtext')
2158+
self.assertEqual(e.find('bar').tag, 'bar')
2159+
found = list(e.findall('bar'))
2160+
self.assertEqual(len(found), 1, found)
2161+
self.assertEqual(found[0].tag, 'bar')
2162+
21482163

21492164
class ElementFindTest(unittest.TestCase):
21502165
def test_find_simple(self):
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Methods ``find()``, ``findtext()`` and ``findall()`` of the ``Element``
2+
class in the :mod:`xml.etree.ElementTree` module are now able to find
3+
children which are instances of ``Element`` subclasses.

Modules/_elementtree.c

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,8 @@ typedef struct {
204204

205205

206206
#define Element_CheckExact(op) (Py_TYPE(op) == &Element_Type)
207+
#define Element_Check(op) PyObject_TypeCheck(op, &Element_Type)
208+
207209

208210
/* -------------------------------------------------------------------- */
209211
/* Element constructors and destructor */
@@ -1131,7 +1133,7 @@ _elementtree_Element_extend(ElementObject *self, PyObject *elements)
11311133
for (i = 0; i < PySequence_Fast_GET_SIZE(seq); i++) {
11321134
PyObject* element = PySequence_Fast_GET_ITEM(seq, i);
11331135
Py_INCREF(element);
1134-
if (!PyObject_TypeCheck(element, (PyTypeObject *)&Element_Type)) {
1136+
if (!Element_Check(element)) {
11351137
PyErr_Format(
11361138
PyExc_TypeError,
11371139
"expected an Element, not \"%.200s\"",
@@ -1183,7 +1185,7 @@ _elementtree_Element_find_impl(ElementObject *self, PyObject *path,
11831185
for (i = 0; i < self->extra->length; i++) {
11841186
PyObject* item = self->extra->children[i];
11851187
int rc;
1186-
if (!Element_CheckExact(item))
1188+
if (!Element_Check(item))
11871189
continue;
11881190
Py_INCREF(item);
11891191
rc = PyObject_RichCompareBool(((ElementObject*)item)->tag, path, Py_EQ);
@@ -1227,14 +1229,14 @@ _elementtree_Element_findtext_impl(ElementObject *self, PyObject *path,
12271229
}
12281230

12291231
for (i = 0; i < self->extra->length; i++) {
1230-
ElementObject* item = (ElementObject*) self->extra->children[i];
1232+
PyObject *item = self->extra->children[i];
12311233
int rc;
1232-
if (!Element_CheckExact(item))
1234+
if (!Element_Check(item))
12331235
continue;
12341236
Py_INCREF(item);
1235-
rc = PyObject_RichCompareBool(item->tag, path, Py_EQ);
1237+
rc = PyObject_RichCompareBool(((ElementObject*)item)->tag, path, Py_EQ);
12361238
if (rc > 0) {
1237-
PyObject* text = element_get_text(item);
1239+
PyObject* text = element_get_text((ElementObject*)item);
12381240
if (text == Py_None) {
12391241
Py_DECREF(item);
12401242
return PyUnicode_New(0, 0);
@@ -1267,13 +1269,12 @@ _elementtree_Element_findall_impl(ElementObject *self, PyObject *path,
12671269
{
12681270
Py_ssize_t i;
12691271
PyObject* out;
1270-
PyObject* tag = path;
12711272
elementtreestate *st = ET_STATE_GLOBAL;
12721273

1273-
if (checkpath(tag) || namespaces != Py_None) {
1274+
if (checkpath(path) || namespaces != Py_None) {
12741275
_Py_IDENTIFIER(findall);
12751276
return _PyObject_CallMethodId(
1276-
st->elementpath_obj, &PyId_findall, "OOO", self, tag, namespaces
1277+
st->elementpath_obj, &PyId_findall, "OOO", self, path, namespaces
12771278
);
12781279
}
12791280

@@ -1287,10 +1288,10 @@ _elementtree_Element_findall_impl(ElementObject *self, PyObject *path,
12871288
for (i = 0; i < self->extra->length; i++) {
12881289
PyObject* item = self->extra->children[i];
12891290
int rc;
1290-
if (!Element_CheckExact(item))
1291+
if (!Element_Check(item))
12911292
continue;
12921293
Py_INCREF(item);
1293-
rc = PyObject_RichCompareBool(((ElementObject*)item)->tag, tag, Py_EQ);
1294+
rc = PyObject_RichCompareBool(((ElementObject*)item)->tag, path, Py_EQ);
12941295
if (rc != 0 && (rc < 0 || PyList_Append(out, item) < 0)) {
12951296
Py_DECREF(item);
12961297
Py_DECREF(out);
@@ -2145,7 +2146,7 @@ elementiter_next(ElementIterObject *it)
21452146
continue;
21462147
}
21472148

2148-
if (!PyObject_TypeCheck(extra->children[child_index], &Element_Type)) {
2149+
if (!Element_Check(extra->children[child_index])) {
21492150
PyErr_Format(PyExc_AttributeError,
21502151
"'%.100s' object has no attribute 'iter'",
21512152
Py_TYPE(extra->children[child_index])->tp_name);

0 commit comments

Comments
 (0)