Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 049d2aa

Browse files
committed
Merged revisions 74750 via svnmerge from
svn+ssh://[email protected]/python/trunk ........ r74750 | lars.gustaebel | 2009-09-12 12:28:15 +0200 (Sat, 12 Sep 2009) | 9 lines 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. ........
1 parent 01054d7 commit 049d2aa

4 files changed

Lines changed: 76 additions & 8 deletions

File tree

Doc/library/tarfile.rst

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -357,15 +357,26 @@ object, see :ref:`tarinfo-objects` for details.
357357
and :meth:`close`, and also supports iteration over its lines.
358358

359359

360-
.. method:: TarFile.add(name, arcname=None, recursive=True, exclude=None)
360+
.. method:: TarFile.add(name, arcname=None, recursive=True, exclude=None, filter=None)
361361

362362
Add the file *name* to the archive. *name* may be any type of file (directory,
363363
fifo, symbolic link, etc.). If given, *arcname* specifies an alternative name
364364
for the file in the archive. Directories are added recursively by default. This
365365
can be avoided by setting *recursive* to :const:`False`. If *exclude* is given,
366366
it must be a function that takes one filename argument and returns a boolean
367367
value. Depending on this value the respective file is either excluded
368-
(:const:`True`) or added (:const:`False`).
368+
(:const:`True`) or added (:const:`False`). If *filter* is specified it must
369+
be a function that takes a :class:`TarInfo` object argument and returns the
370+
changed TarInfo object. If it instead returns :const:`None` the TarInfo
371+
object will be excluded from the archive. See :ref:`tar-examples` for an
372+
example.
373+
374+
.. versionchanged:: 3.2
375+
Added the *filter* parameter.
376+
377+
.. deprecated:: 3.2
378+
The *exclude* parameter is deprecated, please use the *filter* parameter
379+
instead.
369380

370381

371382
.. method:: TarFile.addfile(tarinfo, fileobj=None)
@@ -598,6 +609,18 @@ How to read a gzip compressed tar archive and display some member information::
598609
print("something else.")
599610
tar.close()
600611

612+
How to create an archive and reset the user information using the *filter*
613+
parameter in :meth:`TarFile.add`::
614+
615+
import tarfile
616+
def reset(tarinfo):
617+
tarinfo.uid = tarinfo.gid = 0
618+
tarinfo.uname = tarinfo.gname = "root"
619+
return tarinfo
620+
tar = tarfile.open("sample.tar.gz", "w:gz")
621+
tar.add("foo", filter=reset)
622+
tar.close()
623+
601624

602625
.. _tar-formats:
603626

Lib/tarfile.py

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1898,23 +1898,30 @@ def list(self, verbose=True):
18981898
print("link to", tarinfo.linkname, end=' ')
18991899
print()
19001900

1901-
def add(self, name, arcname=None, recursive=True, exclude=None):
1901+
def add(self, name, arcname=None, recursive=True, exclude=None, filter=None):
19021902
"""Add the file `name' to the archive. `name' may be any type of file
19031903
(directory, fifo, symbolic link, etc.). If given, `arcname'
19041904
specifies an alternative name for the file in the archive.
19051905
Directories are added recursively by default. This can be avoided by
19061906
setting `recursive' to False. `exclude' is a function that should
1907-
return True for each filename to be excluded.
1907+
return True for each filename to be excluded. `filter' is a function
1908+
that expects a TarInfo object argument and returns the changed
1909+
TarInfo object, if it returns None the TarInfo object will be
1910+
excluded from the archive.
19081911
"""
19091912
self._check("aw")
19101913

19111914
if arcname is None:
19121915
arcname = name
19131916

19141917
# Exclude pathnames.
1915-
if exclude is not None and exclude(name):
1916-
self._dbg(2, "tarfile: Excluded %r" % name)
1917-
return
1918+
if exclude is not None:
1919+
import warnings
1920+
warnings.warn("use the filter argument instead",
1921+
DeprecationWarning, 2)
1922+
if exclude(name):
1923+
self._dbg(2, "tarfile: Excluded %r" % name)
1924+
return
19181925

19191926
# Skip if somebody tries to archive the archive...
19201927
if self.name is not None and os.path.abspath(name) == self.name:
@@ -1930,6 +1937,13 @@ def add(self, name, arcname=None, recursive=True, exclude=None):
19301937
self._dbg(1, "tarfile: Unsupported type %r" % name)
19311938
return
19321939

1940+
# Change or exclude the TarInfo object.
1941+
if filter is not None:
1942+
tarinfo = filter(tarinfo)
1943+
if tarinfo is None:
1944+
self._dbg(2, "tarfile: Excluded %r" % name)
1945+
return
1946+
19331947
# Append the tar header and data to the archive.
19341948
if tarinfo.isreg():
19351949
f = bltn_open(name, "rb")
@@ -1940,7 +1954,8 @@ def add(self, name, arcname=None, recursive=True, exclude=None):
19401954
self.addfile(tarinfo)
19411955
if recursive:
19421956
for f in os.listdir(name):
1943-
self.add(os.path.join(name, f), os.path.join(arcname, f), recursive, exclude)
1957+
self.add(os.path.join(name, f), os.path.join(arcname, f),
1958+
recursive, exclude, filter)
19441959

19451960
else:
19461961
self.addfile(tarinfo)

Lib/test/test_tarfile.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,34 @@ def exclude(name):
659659
finally:
660660
shutil.rmtree(tempdir)
661661

662+
def test_filter(self):
663+
tempdir = os.path.join(TEMPDIR, "filter")
664+
os.mkdir(tempdir)
665+
try:
666+
for name in ("foo", "bar", "baz"):
667+
name = os.path.join(tempdir, name)
668+
open(name, "wb").close()
669+
670+
def filter(tarinfo):
671+
if os.path.basename(tarinfo.name) == "bar":
672+
return
673+
tarinfo.uid = 123
674+
tarinfo.uname = "foo"
675+
return tarinfo
676+
677+
tar = tarfile.open(tmpname, self.mode, encoding="iso8859-1")
678+
tar.add(tempdir, arcname="empty_dir", filter=filter)
679+
tar.close()
680+
681+
tar = tarfile.open(tmpname, "r")
682+
for tarinfo in tar:
683+
self.assertEqual(tarinfo.uid, 123)
684+
self.assertEqual(tarinfo.uname, "foo")
685+
self.assertEqual(len(tar.getmembers()), 3)
686+
tar.close()
687+
finally:
688+
shutil.rmtree(tempdir)
689+
662690
# Guarantee that stored pathnames are not modified. Don't
663691
# remove ./ or ../ or double slashes. Still make absolute
664692
# pathnames relative.

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ C-API
7070
Library
7171
-------
7272

73+
- Issue #6856: Add a filter keyword argument to TarFile.add().
74+
7375
- Issue #6888: pdb's alias command was broken when no arguments were given.
7476

7577
- Issue #6857: Default format() alignment should be '>' for Decimal

0 commit comments

Comments
 (0)