@@ -692,28 +692,28 @@ def test_iterparse(self):
692692 it = iterparse (TESTFN )
693693 action , elem = next (it )
694694 self .assertEqual ((action , elem .tag ), ('end' , 'document' ))
695- with warnings_helper . check_no_resource_warning ( self ) :
696- with self . assertRaises ( ET . ParseError ) as cm :
697- next ( it )
698- self . assertEqual ( str ( cm . exception ),
699- 'junk after document element: line 1, column 12' )
700- del cm , it
695+ with self . assertRaises ( ET . ParseError ) as cm :
696+ next ( it )
697+ self . assertEqual ( str ( cm . exception ),
698+ 'junk after document element: line 1, column 12' )
699+ it . close () # Close to avoid ResourceWarning
700+ del cm , it
701701
702- # Not exhausting the iterator still closes the resource (bpo-43292)
703- with warnings_helper .check_no_resource_warning (self ):
704- it = iterparse (SIMPLE_XMLFILE )
705- del it
702+ # Deleting iterator without close() should emit ResourceWarning (bpo-43292)
703+ it = iterparse (SIMPLE_XMLFILE )
704+ del it
706705
706+ # Explicitly calling close() should not emit warning
707707 with warnings_helper .check_no_resource_warning (self ):
708708 it = iterparse (SIMPLE_XMLFILE )
709709 it .close ()
710710 del it
711711
712- with warnings_helper . check_no_resource_warning ( self ):
713- it = iterparse (SIMPLE_XMLFILE )
714- action , elem = next (it )
715- self .assertEqual ((action , elem .tag ), ('end' , 'element' ))
716- del it , elem
712+ # Not closing before del should emit ResourceWarning
713+ it = iterparse (SIMPLE_XMLFILE )
714+ action , elem = next (it )
715+ self .assertEqual ((action , elem .tag ), ('end' , 'element' ))
716+ del it , elem
717717
718718 with warnings_helper .check_no_resource_warning (self ):
719719 it = iterparse (SIMPLE_XMLFILE )
@@ -725,6 +725,63 @@ def test_iterparse(self):
725725 with self .assertRaises (FileNotFoundError ):
726726 iterparse ("nonexistent" )
727727
728+ def test_iterparse_resource_warning (self ):
729+ # Test ResourceWarning when iterparse with filename is not closed
730+ import gc
731+ import warnings
732+
733+ # Should emit warning when not closed
734+ with warnings .catch_warnings (record = True ) as w :
735+ warnings .simplefilter ("always" , ResourceWarning )
736+
737+ def create_unclosed ():
738+ context = ET .iterparse (SIMPLE_XMLFILE )
739+ next (context )
740+ # Don't close - should warn
741+
742+ create_unclosed ()
743+ gc .collect ()
744+
745+ resource_warnings = [x for x in w
746+ if issubclass (x .category , ResourceWarning )]
747+ self .assertGreater (len (resource_warnings ), 0 ,
748+ "Expected ResourceWarning when iterparse is not closed" )
749+
750+ # Should NOT warn when explicitly closed
751+ with warnings .catch_warnings (record = True ) as w :
752+ warnings .simplefilter ("always" , ResourceWarning )
753+
754+ def create_closed ():
755+ context = ET .iterparse (SIMPLE_XMLFILE )
756+ next (context )
757+ context .close ()
758+
759+ create_closed ()
760+ gc .collect ()
761+
762+ resource_warnings = [x for x in w
763+ if issubclass (x .category , ResourceWarning )]
764+ self .assertEqual (len (resource_warnings ), 0 ,
765+ "No warning expected when iterparse is properly closed" )
766+
767+ # Should NOT warn for file objects (externally managed)
768+ with open (SIMPLE_XMLFILE , 'rb' ) as source :
769+ with warnings .catch_warnings (record = True ) as w :
770+ warnings .simplefilter ("always" , ResourceWarning )
771+
772+ def create_with_fileobj ():
773+ context = ET .iterparse (source )
774+ next (context )
775+ # Don't close - file object managed externally
776+
777+ create_with_fileobj ()
778+ gc .collect ()
779+
780+ resource_warnings = [x for x in w
781+ if issubclass (x .category , ResourceWarning )]
782+ self .assertEqual (len (resource_warnings ), 0 ,
783+ "No warning for file objects managed externally" )
784+
728785 def test_iterparse_close (self ):
729786 iterparse = ET .iterparse
730787
0 commit comments