Commit a12df7b7 authored by Jelle Zijlstra's avatar Jelle Zijlstra Committed by Brett Cannon

bpo-30218: support path-like objects in shutil.unpack_archive() (GH-1367)

Thanks to Jelle Zijlstra for the patch.
parent a1054c3b
...@@ -550,6 +550,9 @@ provided. They rely on the :mod:`zipfile` and :mod:`tarfile` modules. ...@@ -550,6 +550,9 @@ provided. They rely on the :mod:`zipfile` and :mod:`tarfile` modules.
registered for that extension. In case none is found, registered for that extension. In case none is found,
a :exc:`ValueError` is raised. a :exc:`ValueError` is raised.
.. versionchanged:: 3.7
Accepts a :term:`path-like object` for *filename* and *extract_dir*.
.. function:: register_unpack_format(name, extensions, function[, extra_args[, description]]) .. function:: register_unpack_format(name, extensions, function[, extra_args[, description]])
......
...@@ -958,6 +958,9 @@ def unpack_archive(filename, extract_dir=None, format=None): ...@@ -958,6 +958,9 @@ def unpack_archive(filename, extract_dir=None, format=None):
if extract_dir is None: if extract_dir is None:
extract_dir = os.getcwd() extract_dir = os.getcwd()
extract_dir = os.fspath(extract_dir)
filename = os.fspath(filename)
if format is not None: if format is not None:
try: try:
format_info = _UNPACK_FORMATS[format] format_info = _UNPACK_FORMATS[format]
......
...@@ -10,6 +10,7 @@ import os ...@@ -10,6 +10,7 @@ import os
import os.path import os.path
import errno import errno
import functools import functools
import pathlib
import subprocess import subprocess
from shutil import (make_archive, from shutil import (make_archive,
register_archive_format, unregister_archive_format, register_archive_format, unregister_archive_format,
...@@ -1223,6 +1224,18 @@ class TestShutil(unittest.TestCase): ...@@ -1223,6 +1224,18 @@ class TestShutil(unittest.TestCase):
self.assertNotIn('xxx', formats) self.assertNotIn('xxx', formats)
def check_unpack_archive(self, format): def check_unpack_archive(self, format):
self.check_unpack_archive_with_converter(format, lambda path: path)
self.check_unpack_archive_with_converter(format, pathlib.Path)
class MyPath:
def __init__(self, path):
self.path = path
def __fspath__(self):
return self.path
self.check_unpack_archive_with_converter(format, MyPath)
def check_unpack_archive_with_converter(self, format, converter):
root_dir, base_dir = self._create_files() root_dir, base_dir = self._create_files()
expected = rlistdir(root_dir) expected = rlistdir(root_dir)
expected.remove('outer') expected.remove('outer')
...@@ -1232,16 +1245,16 @@ class TestShutil(unittest.TestCase): ...@@ -1232,16 +1245,16 @@ class TestShutil(unittest.TestCase):
# let's try to unpack it now # let's try to unpack it now
tmpdir2 = self.mkdtemp() tmpdir2 = self.mkdtemp()
unpack_archive(filename, tmpdir2) unpack_archive(converter(filename), converter(tmpdir2))
self.assertEqual(rlistdir(tmpdir2), expected) self.assertEqual(rlistdir(tmpdir2), expected)
# and again, this time with the format specified # and again, this time with the format specified
tmpdir3 = self.mkdtemp() tmpdir3 = self.mkdtemp()
unpack_archive(filename, tmpdir3, format=format) unpack_archive(converter(filename), converter(tmpdir3), format=format)
self.assertEqual(rlistdir(tmpdir3), expected) self.assertEqual(rlistdir(tmpdir3), expected)
self.assertRaises(shutil.ReadError, unpack_archive, TESTFN) self.assertRaises(shutil.ReadError, unpack_archive, converter(TESTFN))
self.assertRaises(ValueError, unpack_archive, TESTFN, format='xxx') self.assertRaises(ValueError, unpack_archive, converter(TESTFN), format='xxx')
def test_unpack_archive_tar(self): def test_unpack_archive_tar(self):
self.check_unpack_archive('tar') self.check_unpack_archive('tar')
......
...@@ -362,6 +362,9 @@ Library ...@@ -362,6 +362,9 @@ Library
Fixed possible other errors caused by not checking results of PyObject_Size(), Fixed possible other errors caused by not checking results of PyObject_Size(),
PySequence_Size(), or PyMapping_Size(). PySequence_Size(), or PyMapping_Size().
- bpo-30218: Fix PathLike support for shutil.unpack_archive. Patch by Jelle
Zijlstra.
- bpo-10076: Compiled regular expression and match objects in the re module - bpo-10076: Compiled regular expression and match objects in the re module
now support copy.copy() and copy.deepcopy() (they are considered atomic). now support copy.copy() and copy.deepcopy() (they are considered atomic).
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment