mirror of
https://github.com/python/cpython.git
synced 2025-08-04 17:08:35 +00:00
bpo-28230: Document the pathlib support in tarfile and add tests. (#512)
This commit is contained in:
parent
21a74312f2
commit
c45cd167d4
2 changed files with 100 additions and 4 deletions
|
@ -146,6 +146,10 @@ Some facts and figures:
|
|||
.. versionchanged:: 3.5
|
||||
The ``'x'`` (exclusive creation) mode was added.
|
||||
|
||||
.. versionchanged:: 3.6
|
||||
The *name* parameter accepts a :term:`path-like object`.
|
||||
|
||||
|
||||
.. class:: TarFile
|
||||
|
||||
Class for reading and writing tar archives. Do not use this class directly:
|
||||
|
@ -266,7 +270,8 @@ be finalized; only the internally used file object will be closed. See the
|
|||
All following arguments are optional and can be accessed as instance attributes
|
||||
as well.
|
||||
|
||||
*name* is the pathname of the archive. It can be omitted if *fileobj* is given.
|
||||
*name* is the pathname of the archive. *name* may be a :term:`path-like object`.
|
||||
It can be omitted if *fileobj* is given.
|
||||
In this case, the file object's :attr:`name` attribute is used if it exists.
|
||||
|
||||
*mode* is either ``'r'`` to read from an existing archive, ``'a'`` to append
|
||||
|
@ -319,6 +324,10 @@ be finalized; only the internally used file object will be closed. See the
|
|||
.. versionchanged:: 3.5
|
||||
The ``'x'`` (exclusive creation) mode was added.
|
||||
|
||||
.. versionchanged:: 3.6
|
||||
The *name* parameter accepts a :term:`path-like object`.
|
||||
|
||||
|
||||
.. classmethod:: TarFile.open(...)
|
||||
|
||||
Alternative constructor. The :func:`tarfile.open` function is actually a
|
||||
|
@ -390,14 +399,17 @@ be finalized; only the internally used file object will be closed. See the
|
|||
.. versionchanged:: 3.5
|
||||
Added the *numeric_owner* parameter.
|
||||
|
||||
.. versionchanged:: 3.6
|
||||
The *path* parameter accepts a :term:`path-like object`.
|
||||
|
||||
|
||||
.. method:: TarFile.extract(member, path="", set_attrs=True, *, numeric_owner=False)
|
||||
|
||||
Extract a member from the archive to the current working directory, using its
|
||||
full name. Its file information is extracted as accurately as possible. *member*
|
||||
may be a filename or a :class:`TarInfo` object. You can specify a different
|
||||
directory using *path*. File attributes (owner, mtime, mode) are set unless
|
||||
*set_attrs* is false.
|
||||
directory using *path*. *path* may be a :term:`path-like object`.
|
||||
File attributes (owner, mtime, mode) are set unless *set_attrs* is false.
|
||||
|
||||
If *numeric_owner* is :const:`True`, the uid and gid numbers from the tarfile
|
||||
are used to set the owner/group for the extracted files. Otherwise, the named
|
||||
|
@ -418,6 +430,10 @@ be finalized; only the internally used file object will be closed. See the
|
|||
.. versionchanged:: 3.5
|
||||
Added the *numeric_owner* parameter.
|
||||
|
||||
.. versionchanged:: 3.6
|
||||
The *path* parameter accepts a :term:`path-like object`.
|
||||
|
||||
|
||||
.. method:: TarFile.extractfile(member)
|
||||
|
||||
Extract a member from the archive as a file object. *member* may be a filename
|
||||
|
@ -457,7 +473,8 @@ be finalized; only the internally used file object will be closed. See the
|
|||
|
||||
Create a :class:`TarInfo` object from the result of :func:`os.stat` or
|
||||
equivalent on an existing file. The file is either named by *name*, or
|
||||
specified as a :term:`file object` *fileobj* with a file descriptor. If
|
||||
specified as a :term:`file object` *fileobj* with a file descriptor.
|
||||
*name* may be a :term:`path-like object`. If
|
||||
given, *arcname* specifies an alternative name for the file in the
|
||||
archive, otherwise, the name is taken from *fileobj*’s
|
||||
:attr:`~io.FileIO.name` attribute, or the *name* argument. The name
|
||||
|
@ -471,6 +488,9 @@ be finalized; only the internally used file object will be closed. See the
|
|||
The :attr:`~TarInfo.name` may also be modified, in which case *arcname*
|
||||
could be a dummy string.
|
||||
|
||||
.. versionchanged:: 3.6
|
||||
The *name* parameter accepts a :term:`path-like object`.
|
||||
|
||||
|
||||
.. method:: TarFile.close()
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import io
|
|||
from hashlib import md5
|
||||
from contextlib import contextmanager
|
||||
from random import Random
|
||||
import pathlib
|
||||
|
||||
import unittest
|
||||
import unittest.mock
|
||||
|
@ -440,6 +441,22 @@ class MiscReadTestBase(CommonReadTest):
|
|||
self.assertIsInstance(tar.name, bytes)
|
||||
self.assertEqual(tar.name, os.path.abspath(fobj.name))
|
||||
|
||||
def test_pathlike_name(self):
|
||||
tarname = pathlib.Path(self.tarname)
|
||||
with tarfile.open(tarname, mode=self.mode) as tar:
|
||||
self.assertIsInstance(tar.name, str)
|
||||
self.assertEqual(tar.name, os.path.abspath(os.fspath(tarname)))
|
||||
with self.taropen(tarname) as tar:
|
||||
self.assertIsInstance(tar.name, str)
|
||||
self.assertEqual(tar.name, os.path.abspath(os.fspath(tarname)))
|
||||
with tarfile.TarFile.open(tarname, mode=self.mode) as tar:
|
||||
self.assertIsInstance(tar.name, str)
|
||||
self.assertEqual(tar.name, os.path.abspath(os.fspath(tarname)))
|
||||
if self.suffix == '':
|
||||
with tarfile.TarFile(tarname, mode='r') as tar:
|
||||
self.assertIsInstance(tar.name, str)
|
||||
self.assertEqual(tar.name, os.path.abspath(os.fspath(tarname)))
|
||||
|
||||
def test_illegal_mode_arg(self):
|
||||
with open(tmpname, 'wb'):
|
||||
pass
|
||||
|
@ -582,6 +599,26 @@ class MiscReadTestBase(CommonReadTest):
|
|||
finally:
|
||||
support.rmtree(DIR)
|
||||
|
||||
def test_extractall_pathlike_name(self):
|
||||
DIR = pathlib.Path(TEMPDIR) / "extractall"
|
||||
with support.temp_dir(DIR), \
|
||||
tarfile.open(tarname, encoding="iso8859-1") as tar:
|
||||
directories = [t for t in tar if t.isdir()]
|
||||
tar.extractall(DIR, directories)
|
||||
for tarinfo in directories:
|
||||
path = DIR / tarinfo.name
|
||||
self.assertEqual(os.path.getmtime(path), tarinfo.mtime)
|
||||
|
||||
def test_extract_pathlike_name(self):
|
||||
dirtype = "ustar/dirtype"
|
||||
DIR = pathlib.Path(TEMPDIR) / "extractall"
|
||||
with support.temp_dir(DIR), \
|
||||
tarfile.open(tarname, encoding="iso8859-1") as tar:
|
||||
tarinfo = tar.getmember(dirtype)
|
||||
tar.extract(tarinfo, path=DIR)
|
||||
extracted = DIR / dirtype
|
||||
self.assertEqual(os.path.getmtime(extracted), tarinfo.mtime)
|
||||
|
||||
def test_init_close_fobj(self):
|
||||
# Issue #7341: Close the internal file object in the TarFile
|
||||
# constructor in case of an error. For the test we rely on
|
||||
|
@ -1092,6 +1129,17 @@ class WriteTest(WriteTestBase, unittest.TestCase):
|
|||
finally:
|
||||
support.rmdir(path)
|
||||
|
||||
def test_gettarinfo_pathlike_name(self):
|
||||
with tarfile.open(tmpname, self.mode) as tar:
|
||||
path = pathlib.Path(TEMPDIR) / "file"
|
||||
with open(path, "wb") as fobj:
|
||||
fobj.write(b"aaa")
|
||||
tarinfo = tar.gettarinfo(path)
|
||||
tarinfo2 = tar.gettarinfo(os.fspath(path))
|
||||
self.assertIsInstance(tarinfo.name, str)
|
||||
self.assertEqual(tarinfo.name, tarinfo2.name)
|
||||
self.assertEqual(tarinfo.size, 3)
|
||||
|
||||
@unittest.skipUnless(hasattr(os, "link"),
|
||||
"Missing hardlink implementation")
|
||||
def test_link_size(self):
|
||||
|
@ -1501,6 +1549,34 @@ class CreateTest(WriteTestBase, unittest.TestCase):
|
|||
self.assertEqual(len(names), 1)
|
||||
self.assertIn("spameggs42", names[0])
|
||||
|
||||
def test_create_pathlike_name(self):
|
||||
with tarfile.open(pathlib.Path(tmpname), self.mode) as tobj:
|
||||
self.assertIsInstance(tobj.name, str)
|
||||
self.assertEqual(tobj.name, os.path.abspath(tmpname))
|
||||
tobj.add(pathlib.Path(self.file_path))
|
||||
names = tobj.getnames()
|
||||
self.assertEqual(len(names), 1)
|
||||
self.assertIn('spameggs42', names[0])
|
||||
|
||||
with self.taropen(tmpname) as tobj:
|
||||
names = tobj.getnames()
|
||||
self.assertEqual(len(names), 1)
|
||||
self.assertIn('spameggs42', names[0])
|
||||
|
||||
def test_create_taropen_pathlike_name(self):
|
||||
with self.taropen(pathlib.Path(tmpname), "x") as tobj:
|
||||
self.assertIsInstance(tobj.name, str)
|
||||
self.assertEqual(tobj.name, os.path.abspath(tmpname))
|
||||
tobj.add(pathlib.Path(self.file_path))
|
||||
names = tobj.getnames()
|
||||
self.assertEqual(len(names), 1)
|
||||
self.assertIn('spameggs42', names[0])
|
||||
|
||||
with self.taropen(tmpname) as tobj:
|
||||
names = tobj.getnames()
|
||||
self.assertEqual(len(names), 1)
|
||||
self.assertIn('spameggs42', names[0])
|
||||
|
||||
|
||||
class GzipCreateTest(GzipTest, CreateTest):
|
||||
pass
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue