mirror of
https://github.com/python/cpython.git
synced 2025-10-01 04:42:10 +00:00
Issue #25688: Fixed file leak in ElementTree.iterparse() raising an error.
This commit is contained in:
commit
698068b013
3 changed files with 55 additions and 17 deletions
|
@ -561,11 +561,21 @@ class ElementTreeTest(unittest.TestCase):
|
||||||
self.assertEqual(res, ['start-ns', 'end-ns'])
|
self.assertEqual(res, ['start-ns', 'end-ns'])
|
||||||
|
|
||||||
events = ("start", "end", "bogus")
|
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)
|
iterparse(f, events)
|
||||||
|
self.assertFalse(f.closed)
|
||||||
self.assertEqual(str(cm.exception), "unknown event 'bogus'")
|
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(
|
source = io.BytesIO(
|
||||||
b"<?xml version='1.0' encoding='iso-8859-1'?>\n"
|
b"<?xml version='1.0' encoding='iso-8859-1'?>\n"
|
||||||
b"<body xmlns='http://éffbot.org/ns'\n"
|
b"<body xmlns='http://éffbot.org/ns'\n"
|
||||||
|
@ -586,6 +596,21 @@ class ElementTreeTest(unittest.TestCase):
|
||||||
self.assertEqual(str(cm.exception),
|
self.assertEqual(str(cm.exception),
|
||||||
'junk after document element: line 1, column 12')
|
'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):
|
def test_writefile(self):
|
||||||
elem = ET.Element("tag")
|
elem = ET.Element("tag")
|
||||||
elem.text = "text"
|
elem.text = "text"
|
||||||
|
|
|
@ -1202,7 +1202,12 @@ def iterparse(source, events=None, parser=None):
|
||||||
if not hasattr(source, "read"):
|
if not hasattr(source, "read"):
|
||||||
source = open(source, "rb")
|
source = open(source, "rb")
|
||||||
close_source = True
|
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:
|
class XMLPullParser:
|
||||||
|
@ -1285,20 +1290,26 @@ class _IterParseIterator:
|
||||||
self.root = self._root = None
|
self.root = self._root = None
|
||||||
|
|
||||||
def __next__(self):
|
def __next__(self):
|
||||||
while 1:
|
try:
|
||||||
for event in self._parser.read_events():
|
while 1:
|
||||||
return event
|
for event in self._parser.read_events():
|
||||||
if self._parser._parser is None:
|
return event
|
||||||
self.root = self._root
|
if self._parser._parser is None:
|
||||||
if self._close_file:
|
break
|
||||||
self._file.close()
|
# load event buffer
|
||||||
raise StopIteration
|
data = self._file.read(16 * 1024)
|
||||||
# load event buffer
|
if data:
|
||||||
data = self._file.read(16 * 1024)
|
self._parser.feed(data)
|
||||||
if data:
|
else:
|
||||||
self._parser.feed(data)
|
self._root = self._parser._close_and_return_root()
|
||||||
else:
|
self.root = self._root
|
||||||
self._root = self._parser._close_and_return_root()
|
except:
|
||||||
|
if self._close_file:
|
||||||
|
self._file.close()
|
||||||
|
raise
|
||||||
|
if self._close_file:
|
||||||
|
self._file.close()
|
||||||
|
raise StopIteration
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return self
|
return self
|
||||||
|
|
|
@ -95,6 +95,8 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #25688: Fixed file leak in ElementTree.iterparse() raising an error.
|
||||||
|
|
||||||
- Issue #23914: Fixed SystemError raised by unpickler on broken pickle data.
|
- Issue #23914: Fixed SystemError raised by unpickler on broken pickle data.
|
||||||
|
|
||||||
- Issue #25691: Fixed crash on deleting ElementTree.Element attributes.
|
- Issue #25691: Fixed crash on deleting ElementTree.Element attributes.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue