From c2d01423e02d9721f897812cf6a93e64c7d75c15 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sat, 18 Jan 2014 16:14:10 +0200 Subject: [PATCH] Issue #20243: TarFile no longer raise ReadError when opened in write mode. --- Lib/tarfile.py | 29 ++++++++++++++++++----------- Lib/test/test_tarfile.py | 16 ++++++++++++++++ Misc/NEWS | 2 ++ 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/Lib/tarfile.py b/Lib/tarfile.py index 8a69988c086..6c40cb95964 100755 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -1628,19 +1628,22 @@ class TarFile(object): except (ImportError, AttributeError): raise CompressionError("gzip module is not available") - extfileobj = fileobj is not None try: fileobj = gzip.GzipFile(name, mode + "b", compresslevel, fileobj) + except OSError: + if fileobj is not None and mode == 'r': + raise ReadError("not a gzip file") + raise + + try: t = cls.taropen(name, mode, fileobj, **kwargs) - except IOError: - if not extfileobj and fileobj is not None: - fileobj.close() - if fileobj is None: - raise - raise ReadError("not a gzip file") + except OSError: + fileobj.close() + if mode == 'r': + raise ReadError("not a gzip file") + raise except: - if not extfileobj and fileobj is not None: - fileobj.close() + fileobj.close() raise t._extfileobj = False return t @@ -1665,7 +1668,9 @@ class TarFile(object): t = cls.taropen(name, mode, fileobj, **kwargs) except (IOError, EOFError): fileobj.close() - raise ReadError("not a bzip2 file") + if mode == 'r': + raise ReadError("not a bzip2 file") + raise t._extfileobj = False return t @@ -1688,7 +1693,9 @@ class TarFile(object): t = cls.taropen(name, mode, fileobj, **kwargs) except (lzma.LZMAError, EOFError): fileobj.close() - raise ReadError("not an lzma file") + if mode == 'r': + raise ReadError("not an lzma file") + raise t._extfileobj = False return t diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py index ceaa3aa4949..f22b908797d 100644 --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -1155,6 +1155,22 @@ class WriteTest(WriteTestBase, unittest.TestCase): finally: os.chdir(cwd) + def test_open_nonwritable_fileobj(self): + for exctype in OSError, EOFError, RuntimeError: + class BadFile(io.BytesIO): + first = True + def write(self, data): + if self.first: + self.first = False + raise exctype + + f = BadFile() + with self.assertRaises(exctype): + tar = tarfile.open(tmpname, self.mode, fileobj=f, + format=tarfile.PAX_FORMAT, + pax_headers={'non': 'empty'}) + self.assertFalse(f.closed) + class GzipWriteTest(GzipTest, WriteTest): pass diff --git a/Misc/NEWS b/Misc/NEWS index 839e8fe4d85..533d5c59492 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -43,6 +43,8 @@ Core and Builtins Library ------- +- Issue #20243: TarFile no longer raise ReadError when opened in write mode. + - Issue #20238: TarFile opened with external fileobj and "w:gz" mode didn't write complete output on close.