@@ -2680,10 +2680,28 @@ class Y(X, ET.Element):
26802680 e = ET .Element ('foo' )
26812681 e .extend (L )
26822682
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+
2689+ # The pure Python implementation raises a ValueError but the C
2690+ # implementation raises a RuntimeError (like OrderedDict does).
2691+ exc_type = ValueError if ET is pyET else RuntimeError
2692+
2693+ e = ET .Element ('foo' )
2694+ e .extend ([X ('bar' )])
2695+ self .assertRaises (exc_type , e .remove , ET .Element ('baz' ))
2696+
2697+ e = ET .Element ('foo' )
2698+ e .extend ([ET .Element ('bar' )])
2699+ self .assertRaises (exc_type , e .remove , X ('baz' ))
2700+
26832701 def test_remove_with_clear_children (self ):
26842702 # See: https://github.com/python/cpython/issues/126033
26852703
2686- class EvilElement (ET .Element ):
2704+ class X (ET .Element ):
26872705 def __eq__ (self , o ):
26882706 root .clear ()
26892707 return False
@@ -2692,39 +2710,36 @@ def __eq__(self, o):
26922710 # implementation raises a RuntimeError (like OrderedDict does).
26932711 exc_type = ValueError if ET is pyET else RuntimeError
26942712
2695- root = ET .Element ('.' )
2696- root .append (EvilElement ('foo' ))
2697- root .append (ET .Element ('bar' ))
2698- self .assertRaises (exc_type , root .remove , ET .Element ('pouet' ))
2713+ for foo_type , rem_type in [(X , ET .Element ), (ET .Element , X )]:
2714+ with self .subTest (foo_type = foo_type , rem_type = rem_type ):
2715+ root = ET .Element ('.' )
2716+ root .extend ([foo_type ('foo' ), rem_type ('bar' )])
2717+ self .assertRaises (exc_type , root .remove , rem_type ('baz' ))
26992718
2700- root = ET .Element ('.' )
2701- root .append (ET .Element ('foo' ))
2702- root .append (EvilElement ('bar' ))
2703- self .assertRaises (exc_type , root .remove , EvilElement ('pouet' ))
2704-
2705- def test_remove_with_mutate_children (self ):
2719+ def test_remove_with_mutate_root (self ):
27062720 # See: https://github.com/python/cpython/issues/126033
27072721
2708- class EvilElement (ET .Element ):
2722+ first_element = ET .Element ('foo' )
2723+
2724+ class X (ET .Element ):
27092725 def __eq__ (self , o ):
27102726 # Remove the first element so that the list size changes.
27112727 # This causes an infinite recursion error in the Python
27122728 # implementation, but we do not really care about it.
2713- root .remove (ET .Element ('foo' ))
2729+ #
2730+ # Depending on whether the first element is or is not
2731+ root .remove (first_element )
27142732 return False
27152733
2716- # The pure Python implementation raises a ValueError (or hits the
2717- # recursion limit) but the C implementation raises a RuntimeError
2718- # (like OrderedDict does).
2719- exc_type = (RecursionError , ValueError ) if ET is pyET else RuntimeError
2720-
2721- root = ET .Element ('.' )
2722- root .extend ([ET .Element ('foo' ), EvilElement ('bar' )])
2723- self .assertRaises (exc_type , root .remove , ET .Element ('baz' ))
2734+ # The pure Python implementation raises a ValueError but the C
2735+ # implementation raises a RuntimeError (like OrderedDict does).
2736+ exc_type = ValueError if ET is pyET else RuntimeError
27242737
2725- root = ET .Element ('.' )
2726- root .extend ([ET .Element ('foo' ), EvilElement ('bar' )])
2727- self .assertRaises (exc_type , root .remove , EvilElement ('baz' ))
2738+ for bar_type , rem_type in [(X , ET .Element ), (ET .Element , X ), (X , X )]:
2739+ with self .subTest (bar_type = bar_type , rem_type = rem_type ):
2740+ root = ET .Element ('.' )
2741+ root .extend ([first_element , bar_type ('bar' )])
2742+ self .assertRaises (exc_type , root .remove , rem_type ('baz' ))
27282743
27292744 @support .infinite_recursion (25 )
27302745 def test_recursive_repr (self ):
0 commit comments