[Python-checkins] cpython (3.4): Issue #25688: Fixed file leak in ElementTree.iterparse() raising an error.
serhiy.storchaka
python-checkins at python.org
Mon Nov 23 08:47:29 EST 2015
https://hg.python.org/cpython/rev/6e23777948f3
changeset: 99309:6e23777948f3
branch: 3.4
parent: 99305:bac3f63ea747
user: Serhiy Storchaka <storchaka at gmail.com>
date: Mon Nov 23 15:44:03 2015 +0200
summary:
Issue #25688: Fixed file leak in ElementTree.iterparse() raising an error.
files:
Lib/test/test_xml_etree.py | 29 +++++++++++++++-
Lib/xml/etree/ElementTree.py | 41 +++++++++++++++--------
Misc/NEWS | 2 +
3 files changed, 55 insertions(+), 17 deletions(-)
diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py
--- a/Lib/test/test_xml_etree.py
+++ b/Lib/test/test_xml_etree.py
@@ -561,11 +561,21 @@
self.assertEqual(res, ['start-ns', 'end-ns'])
events = ("start", "end", "bogus")
- with self.assertRaises(ValueError) as cm:
- with open(SIMPLE_XMLFILE, "rb") as f:
+ with open(SIMPLE_XMLFILE, "rb") as f:
+ with self.assertRaises(ValueError) as cm:
iterparse(f, events)
+ self.assertFalse(f.closed)
self.assertEqual(str(cm.exception), "unknown event 'bogus'")
+ with warnings.catch_warnings(record=True) as w:
+ warnings.filterwarnings("always", category=ResourceWarning)
+ with self.assertRaises(ValueError) as cm:
+ iterparse(SIMPLE_XMLFILE, events)
+ self.assertEqual(str(cm.exception), "unknown event 'bogus'")
+ del cm
+ support.gc_collect()
+ self.assertEqual(w, [])
+
source = io.BytesIO(
b"<?xml version='1.0' encoding='iso-8859-1'?>\n"
b"<body xmlns='http://éffbot.org/ns'\n"
@@ -586,6 +596,21 @@
self.assertEqual(str(cm.exception),
'junk after document element: line 1, column 12')
+ with open(TESTFN, "wb") as f:
+ f.write(b"<document />junk")
+ it = iterparse(TESTFN)
+ action, elem = next(it)
+ self.assertEqual((action, elem.tag), ('end', 'document'))
+ with warnings.catch_warnings(record=True) as w:
+ warnings.filterwarnings("always", category=ResourceWarning)
+ 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
+ support.gc_collect()
+ self.assertEqual(w, [])
+
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
--- a/Lib/xml/etree/ElementTree.py
+++ b/Lib/xml/etree/ElementTree.py
@@ -1206,7 +1206,12 @@
if not hasattr(source, "read"):
source = open(source, "rb")
close_source = True
- return _IterParseIterator(source, events, parser, close_source)
+ try:
+ return _IterParseIterator(source, events, parser, close_source)
+ except:
+ if close_source:
+ source.close()
+ raise
class XMLPullParser:
@@ -1289,20 +1294,26 @@
self.root = self._root = None
def __next__(self):
- while 1:
- for event in self._parser.read_events():
- return event
- if self._parser._parser is None:
- self.root = self._root
- if self._close_file:
- self._file.close()
- raise StopIteration
- # load event buffer
- data = self._file.read(16 * 1024)
- if data:
- self._parser.feed(data)
- else:
- self._root = self._parser._close_and_return_root()
+ try:
+ while 1:
+ for event in self._parser.read_events():
+ return event
+ if self._parser._parser is None:
+ break
+ # load event buffer
+ data = self._file.read(16 * 1024)
+ if data:
+ self._parser.feed(data)
+ else:
+ self._root = self._parser._close_and_return_root()
+ self.root = self._root
+ except:
+ if self._close_file:
+ self._file.close()
+ raise
+ if self._close_file:
+ self._file.close()
+ raise StopIteration
def __iter__(self):
return self
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -106,6 +106,8 @@
Library
-------
+- Issue #25688: Fixed file leak in ElementTree.iterparse() raising an error.
+
- Issue #23914: Fixed SystemError raised by unpickler on broken pickle data.
- Issue #25691: Fixed crash on deleting ElementTree.Element attributes.
--
Repository URL: https://hg.python.org/cpython
More information about the Python-checkins
mailing list