summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2022-03-07 02:31:52 -0800
committerGitHub <noreply@github.com>2022-03-07 02:31:52 -0800
commit8acbb93c0763fa53b5959fe05d86ba275c9e8a5b (patch)
tree8090672c0d9f70c2a9c3193b3fe8f547e5ac86fc
parentee18df425209cfa4f394b57220177c168fc3a1da (diff)
downloadcpython-git-8acbb93c0763fa53b5959fe05d86ba275c9e8a5b.tar.gz
bpo-43292: Fix file leak in `ET.iterparse()` when not exhausted (GH-31696)
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com> (cherry picked from commit 496c428de3318c9c5770937491b71dc3d3f18a6a) Co-authored-by: Jacob Walls <jacobtylerwalls@gmail.com>
-rw-r--r--Lib/test/test_xml_etree.py8
-rw-r--r--Lib/xml/etree/ElementTree.py16
-rw-r--r--Misc/ACKS1
-rw-r--r--Misc/NEWS.d/next/Library/2022-03-05-09-43-53.bpo-25707.gTlclP.rst2
4 files changed, 20 insertions, 7 deletions
diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py
index c5292b5e9e..5a34d848b3 100644
--- a/Lib/test/test_xml_etree.py
+++ b/Lib/test/test_xml_etree.py
@@ -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"
diff --git a/Lib/xml/etree/ElementTree.py b/Lib/xml/etree/ElementTree.py
index e9409fd29a..07be8609b8 100644
--- a/Lib/xml/etree/ElementTree.py
+++ b/Lib/xml/etree/ElementTree.py
@@ -1248,8 +1248,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
@@ -1265,16 +1271,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
diff --git a/Misc/ACKS b/Misc/ACKS
index e107945600..c9bf79d035 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -1870,6 +1870,7 @@ Wojtek Walczak
Charles Waldman
Richard Walker
Larry Wall
+Jacob Walls
Kevin Walzer
Rodrigo Steinmuller Wanderley
Dingyuan Wang
diff --git a/Misc/NEWS.d/next/Library/2022-03-05-09-43-53.bpo-25707.gTlclP.rst b/Misc/NEWS.d/next/Library/2022-03-05-09-43-53.bpo-25707.gTlclP.rst
new file mode 100644
index 0000000000..a59f0a7657
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-03-05-09-43-53.bpo-25707.gTlclP.rst
@@ -0,0 +1,2 @@
+Fixed a file leak in :func:`xml.etree.ElementTree.iterparse` when the
+iterator is not exhausted. Patch by Jacob Walls.