Issue #28227: gzip now supports pathlib

Patch by Ethan Furman.
This commit is contained in:
Berker Peksag 2016-10-02 13:47:58 +03:00
parent 8e9045d0d8
commit 03020cfa97
4 changed files with 32 additions and 1 deletions

View File

@ -56,6 +56,8 @@ The module defines the following items:
.. versionchanged:: 3.4
Added support for the ``'x'``, ``'xb'`` and ``'xt'`` modes.
.. versionchanged:: 3.6
Accepts a :term:`path-like object`.
.. class:: GzipFile(filename=None, mode=None, compresslevel=9, fileobj=None, mtime=None)
@ -151,6 +153,9 @@ The module defines the following items:
The :meth:`~io.BufferedIOBase.read` method now accepts an argument of
``None``.
.. versionchanged:: 3.6
Accepts a :term:`path-like object`.
.. function:: compress(data, compresslevel=9)

View File

@ -49,7 +49,7 @@ def open(filename, mode="rb", compresslevel=9,
raise ValueError("Argument 'newline' not supported in binary mode")
gz_mode = mode.replace("t", "")
if isinstance(filename, (str, bytes)):
if isinstance(filename, (str, bytes, os.PathLike)):
binary_file = GzipFile(filename, gz_mode, compresslevel)
elif hasattr(filename, "read") or hasattr(filename, "write"):
binary_file = GzipFile(None, gz_mode, compresslevel, filename)
@ -165,6 +165,8 @@ class GzipFile(_compression.BaseStream):
filename = getattr(fileobj, 'name', '')
if not isinstance(filename, (str, bytes)):
filename = ''
else:
filename = os.fspath(filename)
if mode is None:
mode = getattr(fileobj, 'mode', 'rb')

View File

@ -5,6 +5,7 @@ import unittest
from test import support
from test.support import bigmemtest, _4G
import os
import pathlib
import io
import struct
import array
@ -67,6 +68,18 @@ class TestGzip(BaseTest):
# Test multiple close() calls.
f.close()
def test_write_read_with_pathlike_file(self):
filename = pathlib.Path(self.filename)
with gzip.GzipFile(filename, 'w') as f:
f.write(data1 * 50)
self.assertIsInstance(f.name, str)
with gzip.GzipFile(filename, 'a') as f:
f.write(data1)
with gzip.GzipFile(filename) as f:
d = f.read()
self.assertEqual(d, data1 * 51)
self.assertIsInstance(f.name, str)
# The following test_write_xy methods test that write accepts
# the corresponding bytes-like object type as input
# and that the data written equals bytes(xy) in all cases.
@ -521,6 +534,15 @@ class TestOpen(BaseTest):
file_data = gzip.decompress(f.read())
self.assertEqual(file_data, uncompressed)
def test_pathlike_file(self):
filename = pathlib.Path(self.filename)
with gzip.open(filename, "wb") as f:
f.write(data1 * 50)
with gzip.open(filename, "ab") as f:
f.write(data1)
with gzip.open(filename) as f:
self.assertEqual(f.read(), data1 * 51)
def test_implicit_binary_modes(self):
# Test implicit binary modes (no "b" or "t" in mode string).
uncompressed = data1 * 50

View File

@ -46,6 +46,8 @@ Core and Builtins
Library
-------
- Issue #28227: gzip now supports pathlib. Patch by Ethan Furman.
- Issue #27358: Optimized merging var-keyword arguments and improved error
message when pass a non-mapping as a var-keyword argument.