[Python-checkins] r86102 - in python/branches/py3k: Doc/library/tarfile.rst Lib/tarfile.py Lib/test/test_tarfile.py Misc/NEWS

martin.v.loewis python-checkins at python.org
Mon Nov 1 22:39:13 CET 2010


Author: martin.v.loewis
Date: Mon Nov  1 22:39:13 2010
New Revision: 86102

Log:
Issue #10184: Touch directories only once when extracting a tarfile.


Modified:
   python/branches/py3k/Doc/library/tarfile.rst
   python/branches/py3k/Lib/tarfile.py
   python/branches/py3k/Lib/test/test_tarfile.py
   python/branches/py3k/Misc/NEWS

Modified: python/branches/py3k/Doc/library/tarfile.rst
==============================================================================
--- python/branches/py3k/Doc/library/tarfile.rst	(original)
+++ python/branches/py3k/Doc/library/tarfile.rst	Mon Nov  1 22:39:13 2010
@@ -336,12 +336,13 @@
       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 @@
 
       See the warning for :meth:`extractall`.
 
+   .. versionchanged:: 3.2
+      Added the *set_attrs* parameter.
 
 .. method:: TarFile.extractfile(member)
 

Modified: python/branches/py3k/Lib/tarfile.py
==============================================================================
--- python/branches/py3k/Lib/tarfile.py	(original)
+++ python/branches/py3k/Lib/tarfile.py	Mon Nov  1 22:39:13 2010
@@ -2131,7 +2131,8 @@
                 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 @@
                 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 @@
             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 @@
             # 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 @@
         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

Modified: python/branches/py3k/Lib/test/test_tarfile.py
==============================================================================
--- python/branches/py3k/Lib/test/test_tarfile.py	(original)
+++ python/branches/py3k/Lib/test/test_tarfile.py	Mon Nov  1 22:39:13 2010
@@ -377,6 +377,15 @@
         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

Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS	(original)
+++ python/branches/py3k/Misc/NEWS	Mon Nov  1 22:39:13 2010
@@ -59,6 +59,8 @@
 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.
 


More information about the Python-checkins mailing list