Skip to content

Commit d9e4c4b

Browse files
[3.13] gh-123213: Fixed xml.etree.ElementTree.Element.extend and assignment to no longer hide exceptions (GH-123214) (#123257)
gh-123213: Fixed xml.etree.ElementTree.Element.extend and assignment to no longer hide exceptions (GH-123214) (cherry picked from commit 90b6d0e) Co-authored-by: Bar Harel <[email protected]>
1 parent 4ea9c5b commit d9e4c4b

File tree

4 files changed

+38
-11
lines changed

4 files changed

+38
-11
lines changed

Doc/library/xml.etree.elementtree.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -971,7 +971,7 @@ Element Objects
971971

972972
.. method:: extend(subelements)
973973

974-
Appends *subelements* from a sequence object with zero or more elements.
974+
Appends *subelements* from an iterable of elements.
975975
Raises :exc:`TypeError` if a subelement is not an :class:`Element`.
976976

977977
.. versionadded:: 3.2

Lib/test/test_xml_etree.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2423,6 +2423,22 @@ def test_39495_treebuilder_start(self):
24232423
self.assertRaises(TypeError, ET.TreeBuilder().start, "tag")
24242424
self.assertRaises(TypeError, ET.TreeBuilder().start, "tag", None)
24252425

2426+
def test_issue123213_correct_extend_exception(self):
2427+
# Does not hide the internal exception when extending the element
2428+
self.assertRaises(ZeroDivisionError, ET.Element('tag').extend,
2429+
(1/0 for i in range(2)))
2430+
2431+
# Still raises the TypeError when extending with a non-iterable
2432+
self.assertRaises(TypeError, ET.Element('tag').extend, None)
2433+
2434+
# Preserves the TypeError message when extending with a generator
2435+
def f():
2436+
raise TypeError("mymessage")
2437+
2438+
self.assertRaisesRegex(
2439+
TypeError, 'mymessage',
2440+
ET.Element('tag').extend, (f() for i in range(2)))
2441+
24262442

24272443

24282444
# --------------------------------------------------------------------
@@ -3748,6 +3764,22 @@ def test_setslice_negative_steps(self):
37483764
e[1::-sys.maxsize<<64] = [ET.Element('d')]
37493765
self.assertEqual(self._subelem_tags(e), ['a0', 'd', 'a2', 'a3'])
37503766

3767+
def test_issue123213_setslice_exception(self):
3768+
e = ET.Element('tag')
3769+
# Does not hide the internal exception when assigning to the element
3770+
with self.assertRaises(ZeroDivisionError):
3771+
e[:1] = (1/0 for i in range(2))
3772+
3773+
# Still raises the TypeError when assigning with a non-iterable
3774+
with self.assertRaises(TypeError):
3775+
e[:1] = None
3776+
3777+
# Preserve the original TypeError message when assigning.
3778+
def f():
3779+
raise TypeError("mymessage")
3780+
3781+
with self.assertRaisesRegex(TypeError, 'mymessage'):
3782+
e[:1] = (f() for i in range(2))
37513783

37523784
class IOTest(unittest.TestCase):
37533785
def test_encoding(self):
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
:meth:`xml.etree.ElementTree.Element.extend` and
2+
:class:`~xml.etree.ElementTree.Element` assignment no longer hide the internal
3+
exception if an erronous generator is passed. Patch by Bar Harel.

Modules/_elementtree.c

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,12 +1213,8 @@ _elementtree_Element_extend_impl(ElementObject *self, PyTypeObject *cls,
12131213
PyObject* seq;
12141214
Py_ssize_t i;
12151215

1216-
seq = PySequence_Fast(elements, "");
1216+
seq = PySequence_Fast(elements, "'elements' must be an iterable");
12171217
if (!seq) {
1218-
PyErr_Format(
1219-
PyExc_TypeError,
1220-
"expected sequence, not \"%.200s\"", Py_TYPE(elements)->tp_name
1221-
);
12221218
return NULL;
12231219
}
12241220

@@ -1918,12 +1914,8 @@ element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value)
19181914
}
19191915

19201916
/* A new slice is actually being assigned */
1921-
seq = PySequence_Fast(value, "");
1917+
seq = PySequence_Fast(value, "assignment expects an iterable");
19221918
if (!seq) {
1923-
PyErr_Format(
1924-
PyExc_TypeError,
1925-
"expected sequence, not \"%.200s\"", Py_TYPE(value)->tp_name
1926-
);
19271919
return -1;
19281920
}
19291921
newlen = PySequence_Fast_GET_SIZE(seq);

0 commit comments

Comments
 (0)