Skip to content

Commit 4b74caf

Browse files
committed
improve test coverage
1 parent 756b1eb commit 4b74caf

File tree

1 file changed

+72
-31
lines changed

1 file changed

+72
-31
lines changed

Lib/test/test_xml_etree.py

Lines changed: 72 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2642,6 +2642,11 @@ def test_pickle_issue18997(self):
26422642

26432643

26442644
class BadElementTest(ElementTestCase, unittest.TestCase):
2645+
2646+
@classmethod
2647+
def setUpClass(cls):
2648+
cls.is_c = ET is not pyET
2649+
26452650
def test_extend_mutable_list(self):
26462651
class X:
26472652
@property
@@ -2680,54 +2685,90 @@ class Y(X, ET.Element):
26802685
e = ET.Element('foo')
26812686
e.extend(L)
26822687

2683-
def test_remove_with_clear_child(self):
2684-
class X(ET.Element):
2685-
def __eq__(self, o):
2686-
del e[:]
2687-
return False
2688+
def test_remove_with_clear(self):
2689+
# See: https://github.com/python/cpython/issues/126033
26882690

2689-
e = ET.Element('foo')
2690-
e.extend([X('bar')])
2691-
self.assertRaises(ValueError, e.remove, ET.Element('baz'))
2691+
# Until the discrepency between "del root[:]" and "root.clear()" is
2692+
# resolved, we need to keep two tests. Previously, using "del root[:]"
2693+
# did not crash with the reproducer of gh-126033 while "root.clear()"
2694+
# did.
26922695

2693-
e = ET.Element('foo')
2694-
e.extend([ET.Element('bar')])
2695-
self.assertRaises(ValueError, e.remove, X('baz'))
2696+
E = ET.Element
26962697

2697-
def test_remove_with_clear_children(self):
2698-
# See: https://github.com/python/cpython/issues/126033
2698+
class X1(E):
2699+
def __eq__(self, o):
2700+
del root[:]
2701+
return False
26992702

2700-
class X(ET.Element):
2703+
class X2(E):
27012704
def __eq__(self, o):
27022705
root.clear()
27032706
return False
27042707

2705-
for foo_type, rem_type in [(X, ET.Element), (ET.Element, X)]:
2706-
with self.subTest(foo_type=foo_type, rem_type=rem_type):
2707-
root = ET.Element('.')
2708-
root.extend([foo_type('foo'), rem_type('bar')])
2709-
self.assertRaises(ValueError, root.remove, rem_type('baz'))
2708+
class Y1(E):
2709+
def __eq__(self, o):
2710+
del root[:]
2711+
return True
2712+
2713+
class Y2(E):
2714+
def __eq__(self, o):
2715+
root.clear()
2716+
return True
2717+
2718+
def test_remove(root, target, raises):
2719+
if raises:
2720+
self.assertRaises(ValueError, root.remove, target)
2721+
else:
2722+
root.remove(target)
2723+
self.assertNotIn(target, root)
2724+
2725+
for etype, rem_type, raises in [
2726+
(E, X1, True), (E, X2, True),
2727+
(X1, E, True), (X2, E, True),
2728+
(Y1, E, self.is_c), (Y2, E, self.is_c),
2729+
(E, Y1, self.is_c), (E, Y2, self.is_c),
2730+
]:
2731+
with self.subTest(etype=etype, rem_type=rem_type, raises=raises):
2732+
with self.subTest("single child"):
2733+
root = E('.')
2734+
root.append(etype('one'))
2735+
test_remove(root, rem_type('baz'), raises)
2736+
2737+
with self.subTest("with children"):
2738+
root = E('.')
2739+
root.extend([etype('one'), rem_type('two')])
2740+
test_remove(root, rem_type('baz'), raises)
27102741

27112742
def test_remove_with_mutate_root(self):
27122743
# See: https://github.com/python/cpython/issues/126033
27132744

2714-
first_element = ET.Element('foo')
2745+
E = ET.Element
27152746

27162747
class X(ET.Element):
27172748
def __eq__(self, o):
2718-
# Remove the first element so that the list size changes.
2719-
# This causes an infinite recursion error in the Python
2720-
# implementation, but we do not really care about it.
2721-
#
2722-
# Depending on whether the first element is or is not
2723-
root.remove(first_element)
2749+
del root[0]
27242750
return False
27252751

2726-
for bar_type, rem_type in [(X, ET.Element), (ET.Element, X), (X, X)]:
2727-
with self.subTest(bar_type=bar_type, rem_type=rem_type):
2728-
root = ET.Element('.')
2729-
root.extend([first_element, bar_type('bar')])
2730-
self.assertRaises(ValueError, root.remove, rem_type('baz'))
2752+
class Y(ET.Element):
2753+
def __eq__(self, o):
2754+
del root[0]
2755+
return True
2756+
2757+
for bar_type, rem_type, raises in [
2758+
(E, X, True),
2759+
(X, E, True),
2760+
(Y, E, True),
2761+
(E, Y, False),
2762+
]:
2763+
with self.subTest(bar_type=bar_type, rem_type=rem_type, raises=raises):
2764+
root = E('.')
2765+
root.extend([E('first'), rem_type('bar')])
2766+
to_remove = rem_type('baz')
2767+
if raises:
2768+
self.assertRaises(ValueError, root.remove, to_remove)
2769+
else:
2770+
root.remove(to_remove)
2771+
self.assertNotIn(to_remove, root)
27312772

27322773
@support.infinite_recursion(25)
27332774
def test_recursive_repr(self):

0 commit comments

Comments
 (0)