summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/library/tarfile.rst7
-rw-r--r--Lib/tarfile.py22
-rw-r--r--Lib/test/test_tarfile.py9
-rw-r--r--Misc/NEWS2
4 files changed, 29 insertions, 11 deletions
diff --git a/Doc/library/tarfile.rst b/Doc/library/tarfile.rst
index 0dfb065..d7fbf39 100644
--- a/Doc/library/tarfile.rst
+++ b/Doc/library/tarfile.rst
@@ -336,12 +336,13 @@ be finalized; only the internally used file object will be closed. See the
dots ``".."``.
-.. method:: TarFile.extract(member, path="")
+.. method:: TarFile.extract(member, path="", set_attrs=True)
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*.
+ directory using *path*. File attributes (owner, mtime, mode) are set unless
+ *set_attrs* is False.
.. note::
@@ -352,6 +353,8 @@ be finalized; only the internally used file object will be closed. See the
See the warning for :meth:`extractall`.
+ .. versionchanged:: 3.2
+ Added the *set_attrs* parameter.
.. method:: TarFile.extractfile(member)
diff --git a/Lib/tarfile.py b/Lib/tarfile.py
index d49e82f..fd898c7 100644
--- a/Lib/tarfile.py
+++ b/Lib/tarfile.py
@@ -2131,7 +2131,8 @@ class TarFile(object):
directories.append(tarinfo)
tarinfo = copy.copy(tarinfo)
tarinfo.mode = 0o700
- self.extract(tarinfo, path)
+ # Do not set_attrs directories, as we will do that further down
+ self.extract(tarinfo, path, set_attrs=not tarinfo.isdir())
# Reverse sort directories.
directories.sort(key=lambda a: a.name)
@@ -2150,11 +2151,12 @@ class TarFile(object):
else:
self._dbg(1, "tarfile: %s" % e)
- def extract(self, member, path=""):
+ def extract(self, member, path="", set_attrs=True):
"""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 TarInfo object. You can
- specify a different directory using `path'.
+ specify a different directory using `path'. File attributes (owner,
+ mtime, mode) are set unless `set_attrs' is False.
"""
self._check("r")
@@ -2168,7 +2170,8 @@ class TarFile(object):
tarinfo._link_target = os.path.join(path, tarinfo.linkname)
try:
- self._extract_member(tarinfo, os.path.join(path, tarinfo.name))
+ self._extract_member(tarinfo, os.path.join(path, tarinfo.name),
+ set_attrs=set_attrs)
except EnvironmentError as e:
if self.errorlevel > 0:
raise
@@ -2221,7 +2224,7 @@ class TarFile(object):
# blkdev, etc.), return None instead of a file object.
return None
- def _extract_member(self, tarinfo, targetpath):
+ def _extract_member(self, tarinfo, targetpath, set_attrs=True):
"""Extract the TarInfo object tarinfo to a physical
file called targetpath.
"""
@@ -2258,10 +2261,11 @@ class TarFile(object):
else:
self.makefile(tarinfo, targetpath)
- self.chown(tarinfo, targetpath)
- if not tarinfo.issym():
- self.chmod(tarinfo, targetpath)
- self.utime(tarinfo, targetpath)
+ if set_attrs:
+ self.chown(tarinfo, targetpath)
+ if not tarinfo.issym():
+ self.chmod(tarinfo, targetpath)
+ self.utime(tarinfo, targetpath)
#--------------------------------------------------------------------------
# Below are the different file methods. They are called via
diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py
index 302ee85..daf46f7 100644
--- a/Lib/test/test_tarfile.py
+++ b/Lib/test/test_tarfile.py
@@ -377,6 +377,15 @@ class MiscReadTest(CommonReadTest):
finally:
tar.close()
+ def test_extract_directory(self):
+ dirtype = "ustar/dirtype"
+ with tarfile.open(tarname, encoding="iso8859-1") as tar:
+ tarinfo = tar.getmember(dirtype)
+ tar.extract(tarinfo)
+ self.assertEqual(os.path.getmtime(dirtype), tarinfo.mtime)
+ if sys.platform != "win32":
+ self.assertEqual(os.stat(dirtype).st_mode & 0o777, 0o755)
+
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
diff --git a/Misc/NEWS b/Misc/NEWS
index 9cb2589..9e6c113 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -59,6 +59,8 @@ Core and Builtins
Library
-------
+- Issue #10184: Touch directories only once when extracting a tarfile.
+
- Issue #10199: New package, ``turtledemo`` now contains selected demo
scripts that were formerly found under Demo/turtle.