2121 import bz2
2222except ImportError :
2323 bz2 = None
24+ try :
25+ import lzma
26+ except ImportError :
27+ lzma = None
2428
2529def md5sum (data ):
2630 return md5 (data ).hexdigest ()
@@ -29,6 +33,7 @@ def md5sum(data):
2933tarname = support .findfile ("testtar.tar" )
3034gzipname = os .path .join (TEMPDIR , "testtar.tar.gz" )
3135bz2name = os .path .join (TEMPDIR , "testtar.tar.bz2" )
36+ xzname = os .path .join (TEMPDIR , "testtar.tar.xz" )
3237tmpname = os .path .join (TEMPDIR , "tmp.tar" )
3338
3439md5_regtype = "65f477c818ad9e15f7feab0c6d37742f"
@@ -201,13 +206,15 @@ def test_ignore_zeros(self):
201206 _open = gzip .GzipFile
202207 elif self .mode .endswith (":bz2" ):
203208 _open = bz2 .BZ2File
209+ elif self .mode .endswith (":xz" ):
210+ _open = lzma .LZMAFile
204211 else :
205- _open = open
212+ _open = io . FileIO
206213
207214 for char in (b'\0 ' , b'a' ):
208215 # Test if EOFHeaderError ('\0') and InvalidHeaderError ('a')
209216 # are ignored correctly.
210- with _open (tmpname , "wb " ) as fobj :
217+ with _open (tmpname , "w " ) as fobj :
211218 fobj .write (char * 1024 )
212219 fobj .write (tarfile .TarInfo ("foo" ).tobuf ())
213220
@@ -222,9 +229,10 @@ def test_ignore_zeros(self):
222229class MiscReadTest (CommonReadTest ):
223230
224231 def test_no_name_argument (self ):
225- if self .mode .endswith ("bz2" ):
226- # BZ2File has no name attribute.
227- return
232+ if self .mode .endswith (("bz2" , "xz" )):
233+ # BZ2File and LZMAFile have no name attribute.
234+ self .skipTest ("no name attribute" )
235+
228236 with open (self .tarname , "rb" ) as fobj :
229237 tar = tarfile .open (fileobj = fobj , mode = self .mode )
230238 self .assertEqual (tar .name , os .path .abspath (fobj .name ))
@@ -265,10 +273,12 @@ def test_fileobj_with_offset(self):
265273 _open = gzip .GzipFile
266274 elif self .mode .endswith (":bz2" ):
267275 _open = bz2 .BZ2File
276+ elif self .mode .endswith (":xz" ):
277+ _open = lzma .LZMAFile
268278 else :
269- _open = open
270- fobj = _open ( self . tarname , "rb" )
271- try :
279+ _open = io . FileIO
280+
281+ with _open ( self . tarname ) as fobj :
272282 fobj .seek (offset )
273283
274284 # Test if the tarfile starts with the second member.
@@ -281,8 +291,6 @@ def test_fileobj_with_offset(self):
281291 self .assertEqual (tar .extractfile (t ).read (), data ,
282292 "seek back did not work" )
283293 tar .close ()
284- finally :
285- fobj .close ()
286294
287295 def test_fail_comp (self ):
288296 # For Gzip and Bz2 Tests: fail with a ReadError on an uncompressed file.
@@ -526,6 +534,18 @@ def _test_modes(self, testfunc):
526534 testfunc (bz2name , "r|*" )
527535 testfunc (bz2name , "r|bz2" )
528536
537+ if lzma :
538+ self .assertRaises (tarfile .ReadError , tarfile .open , tarname , mode = "r:xz" )
539+ self .assertRaises (tarfile .ReadError , tarfile .open , tarname , mode = "r|xz" )
540+ self .assertRaises (tarfile .ReadError , tarfile .open , xzname , mode = "r:" )
541+ self .assertRaises (tarfile .ReadError , tarfile .open , xzname , mode = "r|" )
542+
543+ testfunc (xzname , "r" )
544+ testfunc (xzname , "r:*" )
545+ testfunc (xzname , "r:xz" )
546+ testfunc (xzname , "r|*" )
547+ testfunc (xzname , "r|xz" )
548+
529549 def test_detect_file (self ):
530550 self ._test_modes (self ._testfunc_file )
531551
@@ -1096,6 +1116,9 @@ def test_stream_padding(self):
10961116 data = dec .decompress (data )
10971117 self .assertTrue (len (dec .unused_data ) == 0 ,
10981118 "found trailing data" )
1119+ elif self .mode .endswith ("xz" ):
1120+ with lzma .LZMAFile (tmpname ) as fobj :
1121+ data = fobj .read ()
10991122 else :
11001123 with open (tmpname , "rb" ) as fobj :
11011124 data = fobj .read ()
@@ -1510,6 +1533,12 @@ def test_append_bz2(self):
15101533 self ._create_testtar ("w:bz2" )
15111534 self .assertRaises (tarfile .ReadError , tarfile .open , tmpname , "a" )
15121535
1536+ def test_append_lzma (self ):
1537+ if lzma is None :
1538+ self .skipTest ("lzma module not available" )
1539+ self ._create_testtar ("w:xz" )
1540+ self .assertRaises (tarfile .ReadError , tarfile .open , tmpname , "a" )
1541+
15131542 # Append mode is supposed to fail if the tarfile to append to
15141543 # does not end with a zero block.
15151544 def _test_error (self , data ):
@@ -1788,6 +1817,21 @@ def test_partial_input_bz2(self):
17881817 self ._test_partial_input ("r:bz2" )
17891818
17901819
1820+ class LzmaMiscReadTest (MiscReadTest ):
1821+ tarname = xzname
1822+ mode = "r:xz"
1823+ class LzmaUstarReadTest (UstarReadTest ):
1824+ tarname = xzname
1825+ mode = "r:xz"
1826+ class LzmaStreamReadTest (StreamReadTest ):
1827+ tarname = xzname
1828+ mode = "r|xz"
1829+ class LzmaWriteTest (WriteTest ):
1830+ mode = "w:xz"
1831+ class LzmaStreamWriteTest (StreamWriteTest ):
1832+ mode = "w|xz"
1833+
1834+
17911835def test_main ():
17921836 support .unlink (TEMPDIR )
17931837 os .makedirs (TEMPDIR )
@@ -1850,6 +1894,20 @@ def test_main():
18501894 Bz2PartialReadTest ,
18511895 ]
18521896
1897+ if lzma :
1898+ # Create testtar.tar.xz and add lzma-specific tests.
1899+ support .unlink (xzname )
1900+ with lzma .LZMAFile (xzname , "w" ) as tar :
1901+ tar .write (data )
1902+
1903+ tests += [
1904+ LzmaMiscReadTest ,
1905+ LzmaUstarReadTest ,
1906+ LzmaStreamReadTest ,
1907+ LzmaWriteTest ,
1908+ LzmaStreamWriteTest ,
1909+ ]
1910+
18531911 try :
18541912 support .run_unittest (* tests )
18551913 finally :
0 commit comments