Index: Lib/tarfile.py =================================================================== --- Lib/tarfile.py (revision 46822) +++ Lib/tarfile.py (working copy) @@ -1010,11 +1010,16 @@ if mode in ("r", "r:*"): # Find out which *open() is appropriate for opening the file. + if (fileobj): + orig_pos = fileobj.tell() # in case a failed opener moves it + for comptype in cls.OPEN_METH: func = getattr(cls, cls.OPEN_METH[comptype]) try: return func(name, "r", fileobj) except (ReadError, CompressionError): + if (fileobj): # test failed, restor the file position + fileobj.seek(orig_pos) continue raise ReadError("file could not be opened successfully") Index: Lib/test/test_tarfile.py =================================================================== --- Lib/test/test_tarfile.py (revision 46822) +++ Lib/test/test_tarfile.py (working copy) @@ -3,6 +3,7 @@ import shutil import tempfile import StringIO +import random import unittest import tarfile @@ -524,7 +525,36 @@ self.assertEqual(tarinfo.type, tarfile.REGTYPE, "dereferencing hardlink failed") +class ShuffleDict(dict): + def __iter__(self): + keys = self.keys() + random.shuffle(keys) + return iter(keys) +class OpenOrderTest(BaseTest): + """ make sure that we can try all the openers in OPEN_METH and + one doesn't step on the toes of another. + """ + shuffle_tries = 3 # min number that triggers the error 90%+ + def test_opener(self): + # test as many formats as possible + testable = [tarname()] + if gzip: + testable.append(tarname('gz')) + if bz2: + testable.append(tarname('bz')) + + orig_OPEN_METH = tarfile.TarFile.OPEN_METH + tarfile.TarFile.OPEN_METH = ShuffleDict(orig_OPEN_METH) + try: + for (dummy) in range(self.shuffle_tries): + for (testfile) in testable: + print "FOO", dummy, testfile + fob = open(testfile, 'rb') + tarfile.open('', 'r', fileobj=fob) + finally: + tarfile.TarFile.OPEN_METH = orig_OPEN_METH + # Gzip TestCases class ReadTestGzip(ReadTest): comp = "gz" @@ -606,6 +636,7 @@ WriteStreamTest, WriteGNULongTest, ReadGNULongTest, + OpenOrderTest, ] if hasattr(os, "link"):