gh-140601: Add ResourceWarning to iterparse when not closed (GH-140603)

When iterparse() opens a file by filename and is not explicitly closed,
emit a ResourceWarning to alert developers of the resource leak.

Signed-off-by: Osama Abdelkader <osama.abdelkader@gmail.com>
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
This commit is contained in:
Osama Abdelkader 2025-11-13 20:05:28 +01:00 committed by GitHub
parent 209eaff68c
commit a486d452c7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 69 additions and 4 deletions

View file

@ -1436,17 +1436,39 @@ def test_nonexistent_file(self):
def test_resource_warnings_not_exhausted(self):
# Not exhausting the iterator still closes the underlying file (bpo-43292)
# Not closing before del should emit ResourceWarning
it = ET.iterparse(SIMPLE_XMLFILE)
with warnings_helper.check_no_resource_warning(self):
it.close()
del it
gc_collect()
it = ET.iterparse(SIMPLE_XMLFILE)
with self.assertWarns(ResourceWarning) as wm:
del it
gc_collect()
# Not 'unclosed file'.
self.assertIn('unclosed iterparse iterator', str(wm.warning))
self.assertIn(repr(SIMPLE_XMLFILE), str(wm.warning))
self.assertEqual(wm.filename, __file__)
it = ET.iterparse(SIMPLE_XMLFILE)
with warnings_helper.check_no_resource_warning(self):
action, elem = next(it)
it.close()
self.assertEqual((action, elem.tag), ('end', 'element'))
del it, elem
gc_collect()
it = ET.iterparse(SIMPLE_XMLFILE)
with self.assertWarns(ResourceWarning) as wm:
action, elem = next(it)
self.assertEqual((action, elem.tag), ('end', 'element'))
del it, elem
gc_collect()
self.assertIn('unclosed iterparse iterator', str(wm.warning))
self.assertIn(repr(SIMPLE_XMLFILE), str(wm.warning))
self.assertEqual(wm.filename, __file__)
def test_resource_warnings_failed_iteration(self):
self.addCleanup(os_helper.unlink, TESTFN)
@ -1461,16 +1483,41 @@ def test_resource_warnings_failed_iteration(self):
next(it)
self.assertEqual(str(cm.exception),
'junk after document element: line 1, column 12')
it.close()
del cm, it
gc_collect()
it = ET.iterparse(TESTFN)
action, elem = next(it)
self.assertEqual((action, elem.tag), ('end', 'document'))
with self.assertWarns(ResourceWarning) as wm:
with self.assertRaises(ET.ParseError) as cm:
next(it)
self.assertEqual(str(cm.exception),
'junk after document element: line 1, column 12')
del cm, it
gc_collect()
self.assertIn('unclosed iterparse iterator', str(wm.warning))
self.assertIn(repr(TESTFN), str(wm.warning))
self.assertEqual(wm.filename, __file__)
def test_resource_warnings_exhausted(self):
it = ET.iterparse(SIMPLE_XMLFILE)
with warnings_helper.check_no_resource_warning(self):
list(it)
it.close()
del it
gc_collect()
it = ET.iterparse(SIMPLE_XMLFILE)
with self.assertWarns(ResourceWarning) as wm:
list(it)
del it
gc_collect()
self.assertIn('unclosed iterparse iterator', str(wm.warning))
self.assertIn(repr(SIMPLE_XMLFILE), str(wm.warning))
self.assertEqual(wm.filename, __file__)
def test_close_not_exhausted(self):
iterparse = ET.iterparse