From 7cfe6171a120b9d53d3743a5fca787d503325a0c Mon Sep 17 00:00:00 2001 From: noname Date: Tue, 4 Jun 2019 19:40:24 +0300 Subject: [PATCH 1/8] Convert path-like object to regular path --- Lib/tarfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/tarfile.py b/Lib/tarfile.py index 2c06f9160c658a..c2bdbb8a6551c0 100755 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -349,7 +349,7 @@ def __init__(self, name, mode, comptype, fileobj, bufsize): fileobj = _StreamProxy(fileobj) comptype = fileobj.getcomptype() - self.name = name or "" + self.name = os.path.abspath(name) if name else "" self.mode = mode self.comptype = comptype self.fileobj = fileobj From a30716481312bb1b2457906ed47905696c696168 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" Date: Tue, 4 Jun 2019 16:50:57 +0000 Subject: [PATCH 2/8] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NEWS.d/next/Library/2019-06-04-16-50-56.bpo-37144.Yu8j2L.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2019-06-04-16-50-56.bpo-37144.Yu8j2L.rst diff --git a/Misc/NEWS.d/next/Library/2019-06-04-16-50-56.bpo-37144.Yu8j2L.rst b/Misc/NEWS.d/next/Library/2019-06-04-16-50-56.bpo-37144.Yu8j2L.rst new file mode 100644 index 00000000000000..c716f92b97297f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-06-04-16-50-56.bpo-37144.Yu8j2L.rst @@ -0,0 +1 @@ +Now `tarfile.open(path, 'w|gz')` works for path-like objects \ No newline at end of file From 9d34011f699c158c005d8aa752c0b1a4c8254cc7 Mon Sep 17 00:00:00 2001 From: noname Date: Tue, 4 Jun 2019 21:12:26 +0300 Subject: [PATCH 3/8] Replace os.path.abspath with os.fspath and add test --- Lib/tarfile.py | 2 +- Lib/test/test_tarfile.py | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Lib/tarfile.py b/Lib/tarfile.py index c2bdbb8a6551c0..b9959e013f1857 100755 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -349,7 +349,7 @@ def __init__(self, name, mode, comptype, fileobj, bufsize): fileobj = _StreamProxy(fileobj) comptype = fileobj.getcomptype() - self.name = os.path.abspath(name) if name else "" + self.name = os.fspath(name) if name else "" self.mode = mode self.comptype = comptype self.fileobj = fileobj diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py index 7e32cbccd6c56d..33c2c5941c77d6 100644 --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -1422,7 +1422,10 @@ def test_file_mode(self): os.umask(original_umask) class GzipStreamWriteTest(GzipTest, StreamWriteTest): - pass + def test_open_by_path_object(self): + # Test for issue #37144: open gzip for stream write by path-like object + tar = tarfile.open(pathlib.Path(self.tarname), self.mode) + tar.close() class Bz2StreamWriteTest(Bz2Test, StreamWriteTest): decompressor = bz2.BZ2Decompressor if bz2 else None From cd73f1e9782a0b594e769ef12dfc7ad546a35329 Mon Sep 17 00:00:00 2001 From: noname Date: Wed, 5 Jun 2019 03:23:40 +0300 Subject: [PATCH 4/8] Change os.path.abspath on os.fspath --- Lib/tarfile.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/tarfile.py b/Lib/tarfile.py index b9959e013f1857..e3cbf9745e78ab 100755 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -1468,7 +1468,7 @@ def __init__(self, name=None, mode="r", fileobj=None, format=None, if hasattr(fileobj, "mode"): self._mode = fileobj.mode self._extfileobj = True - self.name = os.path.abspath(name) if name else None + self.name = os.fspath(name) if name else None self.fileobj = fileobj # Init attributes. @@ -1943,7 +1943,7 @@ def add(self, name, arcname=None, recursive=True, *, filter=None): arcname = name # Skip if somebody tries to archive the archive... - if self.name is not None and os.path.abspath(name) == self.name: + if self.name is not None and os.fspath(name) == self.name: self._dbg(2, "tarfile: Skipped %r" % name) return From cb854029eb35cee9676f48240594726c976ad0d2 Mon Sep 17 00:00:00 2001 From: noname Date: Wed, 5 Jun 2019 04:36:29 +0300 Subject: [PATCH 5/8] Perform open check against temp tar file --- Lib/test/test_tarfile.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py index 33c2c5941c77d6..c4af49470df540 100644 --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -1421,12 +1421,14 @@ def test_file_mode(self): finally: os.umask(original_umask) -class GzipStreamWriteTest(GzipTest, StreamWriteTest): def test_open_by_path_object(self): - # Test for issue #37144: open gzip for stream write by path-like object - tar = tarfile.open(pathlib.Path(self.tarname), self.mode) + # Test for issue #37144: broken open for stream write by path-like object + tar = tarfile.open(pathlib.Path(tmpname), self.mode) tar.close() +class GzipStreamWriteTest(GzipTest, StreamWriteTest): + pass + class Bz2StreamWriteTest(Bz2Test, StreamWriteTest): decompressor = bz2.BZ2Decompressor if bz2 else None From dd30c0de4681ae5ec9ad9a6272d33ac2dce1ab6b Mon Sep 17 00:00:00 2001 From: noname Date: Wed, 5 Jun 2019 04:46:33 +0300 Subject: [PATCH 6/8] Remove unused variable --- Lib/test/test_tarfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py index c4af49470df540..7c27ab8d7b93fb 100644 --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -1368,7 +1368,7 @@ def write(self, data): f = BadFile() with self.assertRaises(exctype): - tar = tarfile.open(tmpname, self.mode, fileobj=f, + tarfile.open(tmpname, self.mode, fileobj=f, format=tarfile.PAX_FORMAT, pax_headers={'non': 'empty'}) self.assertFalse(f.closed) From 82882ddb700691df408f298f22cf27174e14de8a Mon Sep 17 00:00:00 2001 From: noname Date: Wed, 5 Jun 2019 23:55:26 +0300 Subject: [PATCH 7/8] Perform os.path.abspath to result of os.fspath, use context manager --- Lib/tarfile.py | 7 +++++-- Lib/test/test_tarfile.py | 7 ++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Lib/tarfile.py b/Lib/tarfile.py index e3cbf9745e78ab..521991c2f7143d 100755 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -1468,7 +1468,9 @@ def __init__(self, name=None, mode="r", fileobj=None, format=None, if hasattr(fileobj, "mode"): self._mode = fileobj.mode self._extfileobj = True - self.name = os.fspath(name) if name else None + + name = os.fspath(name) if name else None + self.name = os.path.abspath(name) if name else None self.fileobj = fileobj # Init attributes. @@ -1938,12 +1940,13 @@ def add(self, name, arcname=None, recursive=True, *, filter=None): excluded from the archive. """ self._check("awx") + name = os.fspath(name) if arcname is None: arcname = name # Skip if somebody tries to archive the archive... - if self.name is not None and os.fspath(name) == self.name: + if self.name is not None and os.path.abspath(name) == self.name: self._dbg(2, "tarfile: Skipped %r" % name) return diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py index 7c27ab8d7b93fb..c4a51be8c86306 100644 --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -1422,9 +1422,10 @@ def test_file_mode(self): os.umask(original_umask) def test_open_by_path_object(self): - # Test for issue #37144: broken open for stream write by path-like object - tar = tarfile.open(pathlib.Path(tmpname), self.mode) - tar.close() + # Test for issue #37144: + # broken open for stream write by path-like object + with tarfile.open(pathlib.Path(tmpname), self.mode): + pass class GzipStreamWriteTest(GzipTest, StreamWriteTest): pass From 14ae1490c5a78a58f41f53ad738157b9f472c774 Mon Sep 17 00:00:00 2001 From: noname Date: Fri, 7 Jun 2019 14:58:32 +0300 Subject: [PATCH 8/8] Convert path object to raw path for all usages --- Lib/tarfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/tarfile.py b/Lib/tarfile.py index 521991c2f7143d..f9579e4c846a32 100755 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -1454,6 +1454,7 @@ def __init__(self, name=None, mode="r", fileobj=None, format=None, self.mode = mode self._mode = modes[mode] + name = os.fspath(name) if name else None if not fileobj: if self.mode == "a" and not os.path.exists(name): # Create nonexistent files in append mode. @@ -1469,7 +1470,6 @@ def __init__(self, name=None, mode="r", fileobj=None, format=None, self._mode = fileobj.mode self._extfileobj = True - name = os.fspath(name) if name else None self.name = os.path.abspath(name) if name else None self.fileobj = fileobj