Patch #1652681: create nonexistent files in append mode and

allow appending to empty files.
This commit is contained in:
Lars Gustäbel 2007-02-06 18:38:13 +00:00
parent 5f9c6ae545
commit 3f8aca1164
4 changed files with 68 additions and 3 deletions

View File

@ -36,7 +36,8 @@ Some facts and figures:
\lineii{'r:'}{Open for reading exclusively without compression.}
\lineii{'r:gz'}{Open for reading with gzip compression.}
\lineii{'r:bz2'}{Open for reading with bzip2 compression.}
\lineii{'a' or 'a:'}{Open for appending with no compression.}
\lineii{'a' or 'a:'}{Open for appending with no compression. The file
is created if it does not exist.}
\lineii{'w' or 'w:'}{Open for uncompressed writing.}
\lineii{'w:gz'}{Open for gzip compressed writing.}
\lineii{'w:bz2'}{Open for bzip2 compressed writing.}

View File

@ -1060,6 +1060,10 @@ class TarFile(object):
self.mode = {"r": "rb", "a": "r+b", "w": "wb"}[mode]
if not fileobj:
if self._mode == "a" and not os.path.exists(self.name):
# Create nonexistent files in append mode.
self._mode = "w"
self.mode = "wb"
fileobj = file(self.name, self.mode)
self._extfileobj = False
else:
@ -1093,7 +1097,8 @@ class TarFile(object):
self.fileobj.seek(0)
break
if tarinfo is None:
self.fileobj.seek(- BLOCKSIZE, 1)
if self.offset > 0:
self.fileobj.seek(- BLOCKSIZE, 1)
break
if self._mode in "aw":
@ -1120,7 +1125,7 @@ class TarFile(object):
'r:' open for reading exclusively uncompressed
'r:gz' open for reading with gzip compression
'r:bz2' open for reading with bzip2 compression
'a' or 'a:' open for appending
'a' or 'a:' open for appending, creating the file if necessary
'w' or 'w:' open for writing without compression
'w:gz' open for writing with gzip compression
'w:bz2' open for writing with bzip2 compression

View File

@ -305,6 +305,61 @@ class WriteTest(BaseTest):
self.assertEqual(self.dst.getnames(), [], "added the archive to itself")
class AppendTest(unittest.TestCase):
# Test append mode (cp. patch #1652681).
def setUp(self):
self.tarname = tmpname()
if os.path.exists(self.tarname):
os.remove(self.tarname)
def _add_testfile(self, fileobj=None):
tar = tarfile.open(self.tarname, "a", fileobj=fileobj)
tar.addfile(tarfile.TarInfo("bar"))
tar.close()
def _create_testtar(self):
src = tarfile.open(tarname())
t = src.getmember("0-REGTYPE")
t.name = "foo"
f = src.extractfile(t)
tar = tarfile.open(self.tarname, "w")
tar.addfile(t, f)
tar.close()
def _test(self, names=["bar"], fileobj=None):
tar = tarfile.open(self.tarname, fileobj=fileobj)
self.assert_(tar.getnames() == names)
def test_non_existing(self):
self._add_testfile()
self._test()
def test_empty(self):
open(self.tarname, "w").close()
self._add_testfile()
self._test()
def test_empty_fileobj(self):
fobj = StringIO.StringIO()
self._add_testfile(fobj)
fobj.seek(0)
self._test(fileobj=fobj)
def test_fileobj(self):
self._create_testtar()
data = open(self.tarname).read()
fobj = StringIO.StringIO(data)
self._add_testfile(fobj)
fobj.seek(0)
self._test(names=["foo", "bar"], fileobj=fobj)
def test_existing(self):
self._create_testtar()
self._add_testfile()
self._test(names=["foo", "bar"])
class Write100Test(BaseTest):
# The name field in a tar header stores strings of at most 100 chars.
# If a string is shorter than 100 chars it has to be padded with '\0',
@ -711,6 +766,7 @@ def test_main():
ReadAsteriskTest,
ReadStreamAsteriskTest,
WriteTest,
AppendTest,
Write100Test,
WriteSize0Test,
WriteStreamTest,

View File

@ -126,6 +126,9 @@ Core and builtins
Library
-------
- Patch #1652681: tarfile.py: create nonexistent files in append mode and
allow appending to empty files.
- Bug #1124861: Automatically create pipes if GetStdHandle fails in
subprocess.