bpo-43292: Fix file leak in ET.iterparse() when not exhausted (GH-31696)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
This commit is contained in:
Jacob Walls 2022-03-07 04:31:46 -05:00 committed by GitHub
parent b748a36696
commit 496c428de3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 20 additions and 7 deletions

View file

@ -658,6 +658,14 @@ class ElementTreeTest(unittest.TestCase):
'junk after document element: line 1, column 12')
del cm, it
# Not exhausting the iterator still closes the resource (bpo-43292)
with warnings_helper.check_no_resource_warning(self):
it = iterparse(TESTFN)
del it
with self.assertRaises(FileNotFoundError):
iterparse("nonexistent")
def test_writefile(self):
elem = ET.Element("tag")
elem.text = "text"

View file

@ -1244,8 +1244,14 @@ def iterparse(source, events=None, parser=None):
# Use the internal, undocumented _parser argument for now; When the
# parser argument of iterparse is removed, this can be killed.
pullparser = XMLPullParser(events=events, _parser=parser)
def iterator():
def iterator(source):
close_source = False
try:
if not hasattr(source, "read"):
source = open(source, "rb")
close_source = True
yield None
while True:
yield from pullparser.read_events()
# load event buffer
@ -1261,16 +1267,12 @@ def iterparse(source, events=None, parser=None):
source.close()
class IterParseIterator(collections.abc.Iterator):
__next__ = iterator().__next__
__next__ = iterator(source).__next__
it = IterParseIterator()
it.root = None
del iterator, IterParseIterator
close_source = False
if not hasattr(source, "read"):
source = open(source, "rb")
close_source = True
next(it)
return it

View file

@ -1879,6 +1879,7 @@ Wojtek Walczak
Charles Waldman
Richard Walker
Larry Wall
Jacob Walls
Kevin Walzer
Rodrigo Steinmuller Wanderley
Dingyuan Wang

View file

@ -0,0 +1,2 @@
Fixed a file leak in :func:`xml.etree.ElementTree.iterparse` when the
iterator is not exhausted. Patch by Jacob Walls.