@@ -2642,6 +2642,11 @@ def test_pickle_issue18997(self):
26422642
26432643
26442644class 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