From 67d5d0ed442e24cc4ae4ccb1264451844ac88a0c Mon Sep 17 00:00:00 2001 From: Florent Xicluna Date: Sat, 29 Oct 2011 03:38:56 +0200 Subject: [PATCH] Closes #7334: close source files on ElementTree.parse and iterparse (partial backport of issue #10093 from 3.2). --- Lib/xml/etree/ElementTree.py | 33 ++++++++++++++++++++++----------- Misc/NEWS | 2 ++ Modules/_elementtree.c | 32 +++++++++++++++++++++----------- 3 files changed, 45 insertions(+), 22 deletions(-) diff --git a/Lib/xml/etree/ElementTree.py b/Lib/xml/etree/ElementTree.py index d89fd3be0c3..19862e2d34b 100644 --- a/Lib/xml/etree/ElementTree.py +++ b/Lib/xml/etree/ElementTree.py @@ -642,17 +642,23 @@ class ElementTree(object): # @exception ParseError If the parser fails to parse the document. def parse(self, source, parser=None): + close_source = False if not hasattr(source, "read"): source = open(source, "rb") - if not parser: - parser = XMLParser(target=TreeBuilder()) - while 1: - data = source.read(65536) - if not data: - break - parser.feed(data) - self._root = parser.close() - return self._root + close_source = True + try: + if not parser: + parser = XMLParser(target=TreeBuilder()) + while 1: + data = source.read(65536) + if not data: + break + parser.feed(data) + self._root = parser.close() + return self._root + finally: + if close_source: + source.close() ## # Creates a tree iterator for the root element. The iterator loops @@ -1189,16 +1195,19 @@ def parse(source, parser=None): # @return A (event, elem) iterator. def iterparse(source, events=None, parser=None): + close_source = False if not hasattr(source, "read"): source = open(source, "rb") + close_source = True if not parser: parser = XMLParser(target=TreeBuilder()) - return _IterParseIterator(source, events, parser) + return _IterParseIterator(source, events, parser, close_source) class _IterParseIterator(object): - def __init__(self, source, events, parser): + def __init__(self, source, events, parser, close_source=False): self._file = source + self._close_file = close_source self._events = [] self._index = 0 self.root = self._root = None @@ -1249,6 +1258,8 @@ class _IterParseIterator(object): except IndexError: if self._parser is None: self.root = self._root + if self._close_file: + self._file.close() raise StopIteration # load event buffer del self._events[:] diff --git a/Misc/NEWS b/Misc/NEWS index 922343374e7..86042f2bf48 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -71,6 +71,8 @@ Core and Builtins Library ------- +- Issue #7334: close source files on ElementTree.parse and iterparse. + - Issue #13232: logging: Improved logging of exceptions in the presence of multiple encodings. diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 4311ba2a233..c368e1456bd 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -2915,19 +2915,25 @@ init_elementtree(void) "class ElementTree(ET.ElementTree):\n" /* public */ " def parse(self, source, parser=None):\n" + " close_source = False\n" " if not hasattr(source, 'read'):\n" " source = open(source, 'rb')\n" - " if parser is not None:\n" - " while 1:\n" - " data = source.read(65536)\n" - " if not data:\n" - " break\n" - " parser.feed(data)\n" - " self._root = parser.close()\n" - " else:\n" - " parser = cElementTree.XMLParser()\n" - " self._root = parser._parse(source)\n" - " return self._root\n" + " close_source = False\n" + " try:\n" + " if parser is not None:\n" + " while 1:\n" + " data = source.read(65536)\n" + " if not data:\n" + " break\n" + " parser.feed(data)\n" + " self._root = parser.close()\n" + " else:\n" + " parser = cElementTree.XMLParser()\n" + " self._root = parser._parse(source)\n" + " return self._root\n" + " finally:\n" + " if close_source:\n" + " source.close()\n" "cElementTree.ElementTree = ElementTree\n" "def iter(node, tag=None):\n" /* helper */ @@ -2957,8 +2963,10 @@ init_elementtree(void) "class iterparse(object):\n" " root = None\n" " def __init__(self, file, events=None):\n" + " self._close_file = False\n" " if not hasattr(file, 'read'):\n" " file = open(file, 'rb')\n" + " self._close_file = True\n" " self._file = file\n" " self._events = []\n" " self._index = 0\n" @@ -2973,6 +2981,8 @@ init_elementtree(void) " except IndexError:\n" " if self._parser is None:\n" " self.root = self._root\n" + " if self._close_file:\n" + " self._file.close()\n" " raise StopIteration\n" " # load event buffer\n" " del self._events[:]\n"