Skip to content

Commit 648c3f6

Browse files
test: update test_xml_etree
1 parent c30ea14 commit 648c3f6

File tree

1 file changed

+26
-17
lines changed

1 file changed

+26
-17
lines changed

Lib/test/test_xml_etree.py

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2812,17 +2812,17 @@ class Y(X, ET.Element):
28122812
def test_remove_with_clear_assume_missing(self):
28132813
# gh-126033: Check that a concurrent clear() for an assumed-to-be
28142814
# missing element does not make the interpreter crash.
2815-
self.do_test_remove_with_clear(raises=True)
2815+
self.do_test_remove_with_clear(existing=False)
28162816

28172817
def test_remove_with_clear_assume_existing(self):
28182818
# gh-126033: Check that a concurrent clear() for an assumed-to-be
28192819
# existing element raises RuntimeError but does not crash.
2820-
self.do_test_remove_with_clear(raises=False)
2820+
self.do_test_remove_with_clear(existing=True)
28212821

2822-
def do_test_remove_with_clear(self, *, raises):
2822+
def do_test_remove_with_clear(self, *, existing):
28232823
# 'del root[:]' mutates the children list in-place, while
28242824
# 'root.clear()' replaces self._children with a new list. When
2825-
# raises=False (element "found"), the in-place mutation is detected
2825+
# existing=True (element "found"), the in-place mutation is detected
28262826
# by list.remove and raises RuntimeError, whereas root.clear() is
28272827
# invisible to list.remove (the old list is unchanged).
28282828

@@ -2832,12 +2832,12 @@ class E(ET.Element):
28322832
class X(E):
28332833
def __eq__(self, o):
28342834
del root[:]
2835-
return not raises
2835+
return existing
28362836

28372837
class Y(E):
28382838
def __eq__(self, o):
28392839
root.clear()
2840-
return not raises
2840+
return existing
28412841

28422842
self.assertIs(E.__eq__, object.__eq__)
28432843

@@ -2846,12 +2846,14 @@ def __eq__(self, o):
28462846
self.enterContext(self.subTest(side_effect=side_effect))
28472847

28482848
# X uses 'del root[:]' which mutates the list in-place; this is
2849-
# detected by list.remove when raises=False (element "found").
2849+
# detected by list.remove (pure Python implementation) when existing=False.
2850+
# The C implementation does not detect this mutation and silently
2851+
# returns None.
28502852
# Y uses 'root.clear()' which swaps out self._children; the old
28512853
# list that list.remove is iterating is untouched, so no error.
2852-
if raises:
2854+
if not existing:
28532855
get_checker_context = lambda: self.assertRaises(ValueError)
2854-
elif Z is X:
2856+
elif Z is X and is_python_implementation():
28552857
get_checker_context = lambda: self.assertRaises(RuntimeError)
28562858
else:
28572859
get_checker_context = nullcontext
@@ -2890,7 +2892,7 @@ def __eq__(self, o):
28902892
g.assert_not_called()
28912893

28922894
# Test removing root[1] (of type R) from [U(), R()].
2893-
if is_python_implementation() and raises and Z is Y:
2895+
if is_python_implementation() and not existing and Z is Y:
28942896
# In pure Python, using root.clear() sets the children
28952897
# list to [] without calling list.clear().
28962898
#
@@ -2915,25 +2917,32 @@ def __eq__(self, o):
29152917
def test_remove_with_mutate_root_assume_missing(self):
29162918
# gh-126033: Check that a concurrent mutation for an assumed-to-be
29172919
# missing element does not make the interpreter crash.
2918-
self.do_test_remove_with_mutate_root(raises=True)
2920+
self.do_test_remove_with_mutate_root(existing=False)
29192921

29202922
def test_remove_with_mutate_root_assume_existing(self):
29212923
# gh-126033: Check that a concurrent mutation for an assumed-to-be
2922-
# existing element raises RuntimeError.
2923-
self.do_test_remove_with_mutate_root(raises=False)
2924+
# existing element raises RuntimeError when using the pure Python
2925+
# implementation; the C implementation silently returns None).
2926+
self.do_test_remove_with_mutate_root(existing=True)
29242927

2925-
def do_test_remove_with_mutate_root(self, *, raises):
2928+
def do_test_remove_with_mutate_root(self, *, existing):
29262929
E = ET.Element
29272930

29282931
class Z(E):
29292932
def __eq__(self, o):
29302933
del root[0]
2931-
return not raises
2934+
return existing
29322935

2933-
if raises:
2936+
if not existing:
29342937
get_checker_context = lambda: self.assertRaises(ValueError)
2935-
else:
2938+
elif is_python_implementation():
2939+
# The Python implementation is based on list.remove, which raises
2940+
# RuntimeError if the list is mutated during the __eq__ comparison.
29362941
get_checker_context = lambda: self.assertRaises(RuntimeError)
2942+
else:
2943+
# The C implementation does not detect in-place mutations during
2944+
# remove and silently returns None.
2945+
get_checker_context = nullcontext
29372946

29382947
# test removing R() from [U(), V()]
29392948
cases = self.cases_for_remove_missing_with_mutations(E, Z)

0 commit comments

Comments
 (0)