From a254921cd4c1ca22d725872601292c48b7caa20a Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sat, 19 Dec 2015 09:43:14 +0200 Subject: Issue #22227: The TarFile iterator is reimplemented using generator. This implementation is simpler that using class. --- Lib/tarfile.py | 68 ++++++++++++++++++++++------------------------------------ Misc/NEWS | 3 +++ 2 files changed, 29 insertions(+), 42 deletions(-) diff --git a/Lib/tarfile.py b/Lib/tarfile.py index 9d22c8e..80b6e35 100755 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -2372,9 +2372,32 @@ class TarFile(object): """Provide an iterator object. """ if self._loaded: - return iter(self.members) - else: - return TarIter(self) + yield from self.members + return + + # Yield items using TarFile's next() method. + # When all members have been read, set TarFile as _loaded. + index = 0 + # Fix for SF #1100429: Under rare circumstances it can + # happen that getmembers() is called during iteration, + # which will have already exhausted the next() method. + if self.firstmember is not None: + tarinfo = self.next() + index += 1 + yield tarinfo + + while True: + if index < len(self.members): + tarinfo = self.members[index] + elif not self._loaded: + tarinfo = self.next() + if not tarinfo: + self._loaded = True + return + else: + return + index += 1 + yield tarinfo def _dbg(self, level, msg): """Write debugging output to sys.stderr. @@ -2395,45 +2418,6 @@ class TarFile(object): if not self._extfileobj: self.fileobj.close() self.closed = True -# class TarFile - -class TarIter: - """Iterator Class. - - for tarinfo in TarFile(...): - suite... - """ - - def __init__(self, tarfile): - """Construct a TarIter object. - """ - self.tarfile = tarfile - self.index = 0 - def __iter__(self): - """Return iterator object. - """ - return self - def __next__(self): - """Return the next item using TarFile's next() method. - When all members have been read, set TarFile as _loaded. - """ - # Fix for SF #1100429: Under rare circumstances it can - # happen that getmembers() is called during iteration, - # which will cause TarIter to stop prematurely. - - if self.index == 0 and self.tarfile.firstmember is not None: - tarinfo = self.tarfile.next() - elif self.index < len(self.tarfile.members): - tarinfo = self.tarfile.members[self.index] - elif not self.tarfile._loaded: - tarinfo = self.tarfile.next() - if not tarinfo: - self.tarfile._loaded = True - raise StopIteration - else: - raise StopIteration - self.index += 1 - return tarinfo #-------------------- # exported functions diff --git a/Misc/NEWS b/Misc/NEWS index b57dbf1..92572fa 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -109,6 +109,9 @@ Core and Builtins Library ------- +- Issue #22227: The TarFile iterator is reimplemented using generator. + This implementation is simpler that using class. + - Issue #25638: Optimized ElementTree.iterparse(); it is now 2x faster. Optimized ElementTree parsing; it is now 10% faster. -- cgit v0.12