summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorLars Gustäbel <lars@gustaebel.de>2009-09-12 10:28:15 (GMT)
committerLars Gustäbel <lars@gustaebel.de>2009-09-12 10:28:15 (GMT)
commit21121e64b4245e51b85b9d2bc9b29acb86ae79eb (patch)
tree8ffeaf69afab8ef548aea364b49b6c86476f80ab /Lib
parentd4c7eb16475f6ca662120aeda4518051f031c0d8 (diff)
downloadcpython-21121e64b4245e51b85b9d2bc9b29acb86ae79eb.zip
cpython-21121e64b4245e51b85b9d2bc9b29acb86ae79eb.tar.gz
cpython-21121e64b4245e51b85b9d2bc9b29acb86ae79eb.tar.bz2
Issue #6856: Add a filter keyword argument to TarFile.add().
The filter argument must be a function that takes a TarInfo object argument, changes it and returns it again. If the function returns None the TarInfo object will be excluded from the archive. The exclude argument is deprecated from now on, because it does something similar but is not as flexible.
Diffstat (limited to 'Lib')
-rw-r--r--Lib/tarfile.py27
-rw-r--r--Lib/test/test_tarfile.py28
2 files changed, 49 insertions, 6 deletions
diff --git a/Lib/tarfile.py b/Lib/tarfile.py
index 54a2606..a87fe22 100644
--- a/Lib/tarfile.py
+++ b/Lib/tarfile.py
@@ -1918,13 +1918,16 @@ class TarFile(object):
print "link to", tarinfo.linkname,
print
- def add(self, name, arcname=None, recursive=True, exclude=None):
+ def add(self, name, arcname=None, recursive=True, exclude=None, filter=None):
"""Add the file `name' to the archive. `name' may be any type of file
(directory, fifo, symbolic link, etc.). If given, `arcname'
specifies an alternative name for the file in the archive.
Directories are added recursively by default. This can be avoided by
setting `recursive' to False. `exclude' is a function that should
- return True for each filename to be excluded.
+ return True for each filename to be excluded. `filter' is a function
+ that expects a TarInfo object argument and returns the changed
+ TarInfo object, if it returns None the TarInfo object will be
+ excluded from the archive.
"""
self._check("aw")
@@ -1932,9 +1935,13 @@ class TarFile(object):
arcname = name
# Exclude pathnames.
- if exclude is not None and exclude(name):
- self._dbg(2, "tarfile: Excluded %r" % name)
- return
+ if exclude is not None:
+ import warnings
+ warnings.warn("use the filter argument instead",
+ DeprecationWarning, 2)
+ if exclude(name):
+ self._dbg(2, "tarfile: Excluded %r" % name)
+ return
# Skip if somebody tries to archive the archive...
if self.name is not None and os.path.abspath(name) == self.name:
@@ -1950,6 +1957,13 @@ class TarFile(object):
self._dbg(1, "tarfile: Unsupported type %r" % name)
return
+ # Change or exclude the TarInfo object.
+ if filter is not None:
+ tarinfo = filter(tarinfo)
+ if tarinfo is None:
+ self._dbg(2, "tarfile: Excluded %r" % name)
+ return
+
# Append the tar header and data to the archive.
if tarinfo.isreg():
f = bltn_open(name, "rb")
@@ -1960,7 +1974,8 @@ class TarFile(object):
self.addfile(tarinfo)
if recursive:
for f in os.listdir(name):
- self.add(os.path.join(name, f), os.path.join(arcname, f), recursive, exclude)
+ self.add(os.path.join(name, f), os.path.join(arcname, f),
+ recursive, exclude, filter)
else:
self.addfile(tarinfo)
diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py
index 8c9b0ec..1240e1a 100644
--- a/Lib/test/test_tarfile.py
+++ b/Lib/test/test_tarfile.py
@@ -660,6 +660,34 @@ class WriteTest(WriteTestBase):
finally:
shutil.rmtree(tempdir)
+ def test_filter(self):
+ tempdir = os.path.join(TEMPDIR, "filter")
+ os.mkdir(tempdir)
+ try:
+ for name in ("foo", "bar", "baz"):
+ name = os.path.join(tempdir, name)
+ open(name, "wb").close()
+
+ def filter(tarinfo):
+ if os.path.basename(tarinfo.name) == "bar":
+ return
+ tarinfo.uid = 123
+ tarinfo.uname = "foo"
+ return tarinfo
+
+ tar = tarfile.open(tmpname, self.mode, encoding="iso8859-1")
+ tar.add(tempdir, arcname="empty_dir", filter=filter)
+ tar.close()
+
+ tar = tarfile.open(tmpname, "r")
+ for tarinfo in tar:
+ self.assertEqual(tarinfo.uid, 123)
+ self.assertEqual(tarinfo.uname, "foo")
+ self.assertEqual(len(tar.getmembers()), 3)
+ tar.close()
+ finally:
+ shutil.rmtree(tempdir)
+
# Guarantee that stored pathnames are not modified. Don't
# remove ./ or ../ or double slashes. Still make absolute
# pathnames relative.