From 00a73e7715eb9bba3203aea6caa326f3f54a0d20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Fri, 4 Mar 2005 19:40:34 +0000 Subject: Patch #1043890: tarfile: add extractall() method. --- Doc/lib/libtarfile.tex | 25 +++++++++++++++++++++++++ Lib/tarfile.py | 41 +++++++++++++++++++++++++++++++++++++++++ Misc/NEWS | 2 ++ 3 files changed, 68 insertions(+) diff --git a/Doc/lib/libtarfile.tex b/Doc/lib/libtarfile.tex index f7800de..018e8b9 100644 --- a/Doc/lib/libtarfile.tex +++ b/Doc/lib/libtarfile.tex @@ -196,12 +196,29 @@ tar archive several times. Each archive member is represented by a more available. \end{methoddesc} +\begin{methoddesc}{extractall}{\optional{path\optional{, members}}} + Extract all members from the archive to the current working directory + or directory \var{path}. If optional \var{members} is given, it must be + a subset of the list returned by \method{getmembers()}. + Directory informations like owner, modification time and permissions are + set after all members have been extracted. This is done to work around two + problems: A directory's modification time is reset each time a file is + created in it. And, if a directory's permissions do not allow writing, + extracting files to it will fail. + \versionadded{2.5} +\end{methoddesc} + \begin{methoddesc}{extract}{member\optional{, path}} Extract a member from the archive to the current working directory, using its full name. Its file information is extracted as accurately as possible. \var{member} may be a filename or a \class{TarInfo} object. You can specify a different directory using \var{path}. + \begin{notice} + Because the \method{extract()} method allows random access to a tar + archive there are some issues you must take care of yourself. See the + description for \method{extractall()} above. + \end{notice} \end{methoddesc} \begin{methoddesc}{extractfile}{member} @@ -416,6 +433,14 @@ A \class{TarInfo} object also provides some convenient query methods: \subsection{Examples \label{tar-examples}} +How to extract an entire tar archive to the current working directory: +\begin{verbatim} +import tarfile +tar = tarfile.open("sample.tar.gz") +tar.extractall() +tar.close() +\end{verbatim} + How to create an uncompressed tar archive from a list of filenames: \begin{verbatim} import tarfile diff --git a/Lib/tarfile.py b/Lib/tarfile.py index 06f3ab3..8bce5d0 100644 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -1321,6 +1321,47 @@ class TarFile(object): self.members.append(tarinfo) + def extractall(self, path=".", members=None): + """Extract all members from the archive to the current working + directory and set owner, modification time and permissions on + directories afterwards. `path' specifies a different directory + to extract to. `members' is optional and must be a subset of the + list returned by getmembers(). + """ + directories = [] + + if members is None: + members = self + + for tarinfo in members: + if tarinfo.isdir(): + # Extract directory with a safe mode, so that + # all files below can be extracted as well. + try: + os.makedirs(os.path.join(path, tarinfo.name), 0777) + except EnvironmentError: + pass + directories.append(tarinfo) + else: + self.extract(tarinfo, path) + + # Reverse sort directories. + directories.sort(lambda a, b: cmp(a.name, b.name)) + directories.reverse() + + # Set correct owner, mtime and filemode on directories. + for tarinfo in directories: + path = os.path.join(path, tarinfo.name) + try: + self.chown(tarinfo, path) + self.utime(tarinfo, path) + self.chmod(tarinfo, path) + except ExtractError, e: + if self.errorlevel > 1: + raise + else: + self._dbg(1, "tarfile: %s" % e) + def extract(self, member, path=""): """Extract a member from the archive to the current working directory, using its full name. Its file information is extracted as accurately diff --git a/Misc/NEWS b/Misc/NEWS index 9f7dbdd..59c630d 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -75,6 +75,8 @@ Extension Modules Library ------- +- Patch #1043890: Add extractall method to tarfile. + - Patch #1075887: Don't require MSVC in distutils if there is nothing to build. -- cgit v0.12