diff --git a/Doc/library/zipfile.rst b/Doc/library/zipfile.rst index a0de10cae3dbeb5..24d13a57ff86678 100644 --- a/Doc/library/zipfile.rst +++ b/Doc/library/zipfile.rst @@ -132,8 +132,9 @@ ZipFile Objects .. class:: ZipFile(file, mode='r', compression=ZIP_STORED, allowZip64=True) - Open a ZIP file, where *file* can be either a path to a file (a string) or a - file-like object. The *mode* parameter should be ``'r'`` to read an existing + Open a ZIP file, where *file* can be a path to a file (a string), a + file-like object or a :term:`path-like object`. + The *mode* parameter should be ``'r'`` to read an existing file, ``'w'`` to truncate and write a new file, ``'a'`` to append to an existing file, or ``'x'`` to exclusively create and write a new file. If *mode* is ``'x'`` and *file* refers to an existing file, @@ -183,6 +184,9 @@ ZipFile Objects Previously, a plain :exc:`RuntimeError` was raised for unrecognized compression values. + .. versionchanged:: 3.6.1 + The *file* parameter accepts a :term:`path-like object`. + .. method:: ZipFile.close() @@ -403,6 +407,9 @@ ZipFile Objects The following data attributes are also available: +.. attribute:: ZipFile.filename + + Name of the ZIP file. .. attribute:: ZipFile.debug diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py index 0a19d76f429b399..70a3c85b04adbc3 100644 --- a/Lib/test/test_zipfile.py +++ b/Lib/test/test_zipfile.py @@ -2,6 +2,7 @@ import io import os import importlib.util +import pathlib import posixpath import time import struct @@ -148,6 +149,12 @@ def test_open(self): for f in get_files(self): self.zip_open_test(f, self.compression) + def test_open_with_pathlike(self): + path = pathlib.Path(TESTFN2) + self.zip_open_test(path, self.compression) + with zipfile.ZipFile(path, "r", self.compression) as zipfp: + self.assertIsInstance(zipfp.filename, str) + def zip_random_open_test(self, f, compression): self.make_test_archive(f, compression) diff --git a/Lib/zipfile.py b/Lib/zipfile.py index 93171358e41167b..7a93de57af3baac 100644 --- a/Lib/zipfile.py +++ b/Lib/zipfile.py @@ -1069,10 +1069,10 @@ def __init__(self, file, mode="r", compression=ZIP_STORED, allowZip64=True): self._comment = b'' # Check if we were passed a file-like object - if isinstance(file, str): + if isinstance(file, (str, os.PathLike)): # No, it's a filename self._filePassed = 0 - self.filename = file + self.filename = os.fspath(file) modeDict = {'r' : 'rb', 'w': 'w+b', 'x': 'x+b', 'a' : 'r+b', 'r+b': 'w+b', 'w+b': 'wb', 'x+b': 'xb'} filemode = modeDict[mode] diff --git a/Misc/NEWS b/Misc/NEWS index 8949ab4c75e7f62..8af11ed1da42529 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -249,6 +249,9 @@ Extension Modules Library ------- +- bpo-28231: Make file parameter of ZipFile accept PathLike objects. + Initial patch by Ethan Furman. + - bpo-28518: Start a transaction implicitly before a DML statement. Patch by Aviv Palivoda.