17db96d56Sopenharmony_ciimport array 27db96d56Sopenharmony_ciimport contextlib 37db96d56Sopenharmony_ciimport importlib.util 47db96d56Sopenharmony_ciimport io 57db96d56Sopenharmony_ciimport itertools 67db96d56Sopenharmony_ciimport os 77db96d56Sopenharmony_ciimport pathlib 87db96d56Sopenharmony_ciimport posixpath 97db96d56Sopenharmony_ciimport string 107db96d56Sopenharmony_ciimport struct 117db96d56Sopenharmony_ciimport subprocess 127db96d56Sopenharmony_ciimport sys 137db96d56Sopenharmony_cifrom test.support.script_helper import assert_python_ok 147db96d56Sopenharmony_ciimport time 157db96d56Sopenharmony_ciimport unittest 167db96d56Sopenharmony_ciimport unittest.mock as mock 177db96d56Sopenharmony_ciimport zipfile 187db96d56Sopenharmony_ciimport functools 197db96d56Sopenharmony_ci 207db96d56Sopenharmony_ci 217db96d56Sopenharmony_cifrom tempfile import TemporaryFile 227db96d56Sopenharmony_cifrom random import randint, random, randbytes 237db96d56Sopenharmony_ci 247db96d56Sopenharmony_cifrom test.support import script_helper 257db96d56Sopenharmony_cifrom test.support import ( 267db96d56Sopenharmony_ci findfile, requires_zlib, requires_bz2, requires_lzma, 277db96d56Sopenharmony_ci captured_stdout, captured_stderr, requires_subprocess 287db96d56Sopenharmony_ci) 297db96d56Sopenharmony_cifrom test.support.os_helper import ( 307db96d56Sopenharmony_ci TESTFN, unlink, rmtree, temp_dir, temp_cwd, fd_count 317db96d56Sopenharmony_ci) 327db96d56Sopenharmony_ci 337db96d56Sopenharmony_ci 347db96d56Sopenharmony_ciTESTFN2 = TESTFN + "2" 357db96d56Sopenharmony_ciTESTFNDIR = TESTFN + "d" 367db96d56Sopenharmony_ciFIXEDTEST_SIZE = 1000 377db96d56Sopenharmony_ciDATAFILES_DIR = 'zipfile_datafiles' 387db96d56Sopenharmony_ci 397db96d56Sopenharmony_ciSMALL_TEST_DATA = [('_ziptest1', '1q2w3e4r5t'), 407db96d56Sopenharmony_ci ('ziptest2dir/_ziptest2', 'qawsedrftg'), 417db96d56Sopenharmony_ci ('ziptest2dir/ziptest3dir/_ziptest3', 'azsxdcfvgb'), 427db96d56Sopenharmony_ci ('ziptest2dir/ziptest3dir/ziptest4dir/_ziptest3', '6y7u8i9o0p')] 437db96d56Sopenharmony_ci 447db96d56Sopenharmony_cidef get_files(test): 457db96d56Sopenharmony_ci yield TESTFN2 467db96d56Sopenharmony_ci with TemporaryFile() as f: 477db96d56Sopenharmony_ci yield f 487db96d56Sopenharmony_ci test.assertFalse(f.closed) 497db96d56Sopenharmony_ci with io.BytesIO() as f: 507db96d56Sopenharmony_ci yield f 517db96d56Sopenharmony_ci test.assertFalse(f.closed) 527db96d56Sopenharmony_ci 537db96d56Sopenharmony_ciclass AbstractTestsWithSourceFile: 547db96d56Sopenharmony_ci @classmethod 557db96d56Sopenharmony_ci def setUpClass(cls): 567db96d56Sopenharmony_ci cls.line_gen = [bytes("Zipfile test line %d. random float: %f\n" % 577db96d56Sopenharmony_ci (i, random()), "ascii") 587db96d56Sopenharmony_ci for i in range(FIXEDTEST_SIZE)] 597db96d56Sopenharmony_ci cls.data = b''.join(cls.line_gen) 607db96d56Sopenharmony_ci 617db96d56Sopenharmony_ci def setUp(self): 627db96d56Sopenharmony_ci # Make a source file with some lines 637db96d56Sopenharmony_ci with open(TESTFN, "wb") as fp: 647db96d56Sopenharmony_ci fp.write(self.data) 657db96d56Sopenharmony_ci 667db96d56Sopenharmony_ci def make_test_archive(self, f, compression, compresslevel=None): 677db96d56Sopenharmony_ci kwargs = {'compression': compression, 'compresslevel': compresslevel} 687db96d56Sopenharmony_ci # Create the ZIP archive 697db96d56Sopenharmony_ci with zipfile.ZipFile(f, "w", **kwargs) as zipfp: 707db96d56Sopenharmony_ci zipfp.write(TESTFN, "another.name") 717db96d56Sopenharmony_ci zipfp.write(TESTFN, TESTFN) 727db96d56Sopenharmony_ci zipfp.writestr("strfile", self.data) 737db96d56Sopenharmony_ci with zipfp.open('written-open-w', mode='w') as f: 747db96d56Sopenharmony_ci for line in self.line_gen: 757db96d56Sopenharmony_ci f.write(line) 767db96d56Sopenharmony_ci 777db96d56Sopenharmony_ci def zip_test(self, f, compression, compresslevel=None): 787db96d56Sopenharmony_ci self.make_test_archive(f, compression, compresslevel) 797db96d56Sopenharmony_ci 807db96d56Sopenharmony_ci # Read the ZIP archive 817db96d56Sopenharmony_ci with zipfile.ZipFile(f, "r", compression) as zipfp: 827db96d56Sopenharmony_ci self.assertEqual(zipfp.read(TESTFN), self.data) 837db96d56Sopenharmony_ci self.assertEqual(zipfp.read("another.name"), self.data) 847db96d56Sopenharmony_ci self.assertEqual(zipfp.read("strfile"), self.data) 857db96d56Sopenharmony_ci 867db96d56Sopenharmony_ci # Print the ZIP directory 877db96d56Sopenharmony_ci fp = io.StringIO() 887db96d56Sopenharmony_ci zipfp.printdir(file=fp) 897db96d56Sopenharmony_ci directory = fp.getvalue() 907db96d56Sopenharmony_ci lines = directory.splitlines() 917db96d56Sopenharmony_ci self.assertEqual(len(lines), 5) # Number of files + header 927db96d56Sopenharmony_ci 937db96d56Sopenharmony_ci self.assertIn('File Name', lines[0]) 947db96d56Sopenharmony_ci self.assertIn('Modified', lines[0]) 957db96d56Sopenharmony_ci self.assertIn('Size', lines[0]) 967db96d56Sopenharmony_ci 977db96d56Sopenharmony_ci fn, date, time_, size = lines[1].split() 987db96d56Sopenharmony_ci self.assertEqual(fn, 'another.name') 997db96d56Sopenharmony_ci self.assertTrue(time.strptime(date, '%Y-%m-%d')) 1007db96d56Sopenharmony_ci self.assertTrue(time.strptime(time_, '%H:%M:%S')) 1017db96d56Sopenharmony_ci self.assertEqual(size, str(len(self.data))) 1027db96d56Sopenharmony_ci 1037db96d56Sopenharmony_ci # Check the namelist 1047db96d56Sopenharmony_ci names = zipfp.namelist() 1057db96d56Sopenharmony_ci self.assertEqual(len(names), 4) 1067db96d56Sopenharmony_ci self.assertIn(TESTFN, names) 1077db96d56Sopenharmony_ci self.assertIn("another.name", names) 1087db96d56Sopenharmony_ci self.assertIn("strfile", names) 1097db96d56Sopenharmony_ci self.assertIn("written-open-w", names) 1107db96d56Sopenharmony_ci 1117db96d56Sopenharmony_ci # Check infolist 1127db96d56Sopenharmony_ci infos = zipfp.infolist() 1137db96d56Sopenharmony_ci names = [i.filename for i in infos] 1147db96d56Sopenharmony_ci self.assertEqual(len(names), 4) 1157db96d56Sopenharmony_ci self.assertIn(TESTFN, names) 1167db96d56Sopenharmony_ci self.assertIn("another.name", names) 1177db96d56Sopenharmony_ci self.assertIn("strfile", names) 1187db96d56Sopenharmony_ci self.assertIn("written-open-w", names) 1197db96d56Sopenharmony_ci for i in infos: 1207db96d56Sopenharmony_ci self.assertEqual(i.file_size, len(self.data)) 1217db96d56Sopenharmony_ci 1227db96d56Sopenharmony_ci # check getinfo 1237db96d56Sopenharmony_ci for nm in (TESTFN, "another.name", "strfile", "written-open-w"): 1247db96d56Sopenharmony_ci info = zipfp.getinfo(nm) 1257db96d56Sopenharmony_ci self.assertEqual(info.filename, nm) 1267db96d56Sopenharmony_ci self.assertEqual(info.file_size, len(self.data)) 1277db96d56Sopenharmony_ci 1287db96d56Sopenharmony_ci # Check that testzip doesn't raise an exception 1297db96d56Sopenharmony_ci zipfp.testzip() 1307db96d56Sopenharmony_ci 1317db96d56Sopenharmony_ci def test_basic(self): 1327db96d56Sopenharmony_ci for f in get_files(self): 1337db96d56Sopenharmony_ci self.zip_test(f, self.compression) 1347db96d56Sopenharmony_ci 1357db96d56Sopenharmony_ci def zip_open_test(self, f, compression): 1367db96d56Sopenharmony_ci self.make_test_archive(f, compression) 1377db96d56Sopenharmony_ci 1387db96d56Sopenharmony_ci # Read the ZIP archive 1397db96d56Sopenharmony_ci with zipfile.ZipFile(f, "r", compression) as zipfp: 1407db96d56Sopenharmony_ci zipdata1 = [] 1417db96d56Sopenharmony_ci with zipfp.open(TESTFN) as zipopen1: 1427db96d56Sopenharmony_ci while True: 1437db96d56Sopenharmony_ci read_data = zipopen1.read(256) 1447db96d56Sopenharmony_ci if not read_data: 1457db96d56Sopenharmony_ci break 1467db96d56Sopenharmony_ci zipdata1.append(read_data) 1477db96d56Sopenharmony_ci 1487db96d56Sopenharmony_ci zipdata2 = [] 1497db96d56Sopenharmony_ci with zipfp.open("another.name") as zipopen2: 1507db96d56Sopenharmony_ci while True: 1517db96d56Sopenharmony_ci read_data = zipopen2.read(256) 1527db96d56Sopenharmony_ci if not read_data: 1537db96d56Sopenharmony_ci break 1547db96d56Sopenharmony_ci zipdata2.append(read_data) 1557db96d56Sopenharmony_ci 1567db96d56Sopenharmony_ci self.assertEqual(b''.join(zipdata1), self.data) 1577db96d56Sopenharmony_ci self.assertEqual(b''.join(zipdata2), self.data) 1587db96d56Sopenharmony_ci 1597db96d56Sopenharmony_ci def test_open(self): 1607db96d56Sopenharmony_ci for f in get_files(self): 1617db96d56Sopenharmony_ci self.zip_open_test(f, self.compression) 1627db96d56Sopenharmony_ci 1637db96d56Sopenharmony_ci def test_open_with_pathlike(self): 1647db96d56Sopenharmony_ci path = pathlib.Path(TESTFN2) 1657db96d56Sopenharmony_ci self.zip_open_test(path, self.compression) 1667db96d56Sopenharmony_ci with zipfile.ZipFile(path, "r", self.compression) as zipfp: 1677db96d56Sopenharmony_ci self.assertIsInstance(zipfp.filename, str) 1687db96d56Sopenharmony_ci 1697db96d56Sopenharmony_ci def zip_random_open_test(self, f, compression): 1707db96d56Sopenharmony_ci self.make_test_archive(f, compression) 1717db96d56Sopenharmony_ci 1727db96d56Sopenharmony_ci # Read the ZIP archive 1737db96d56Sopenharmony_ci with zipfile.ZipFile(f, "r", compression) as zipfp: 1747db96d56Sopenharmony_ci zipdata1 = [] 1757db96d56Sopenharmony_ci with zipfp.open(TESTFN) as zipopen1: 1767db96d56Sopenharmony_ci while True: 1777db96d56Sopenharmony_ci read_data = zipopen1.read(randint(1, 1024)) 1787db96d56Sopenharmony_ci if not read_data: 1797db96d56Sopenharmony_ci break 1807db96d56Sopenharmony_ci zipdata1.append(read_data) 1817db96d56Sopenharmony_ci 1827db96d56Sopenharmony_ci self.assertEqual(b''.join(zipdata1), self.data) 1837db96d56Sopenharmony_ci 1847db96d56Sopenharmony_ci def test_random_open(self): 1857db96d56Sopenharmony_ci for f in get_files(self): 1867db96d56Sopenharmony_ci self.zip_random_open_test(f, self.compression) 1877db96d56Sopenharmony_ci 1887db96d56Sopenharmony_ci def zip_read1_test(self, f, compression): 1897db96d56Sopenharmony_ci self.make_test_archive(f, compression) 1907db96d56Sopenharmony_ci 1917db96d56Sopenharmony_ci # Read the ZIP archive 1927db96d56Sopenharmony_ci with zipfile.ZipFile(f, "r") as zipfp, \ 1937db96d56Sopenharmony_ci zipfp.open(TESTFN) as zipopen: 1947db96d56Sopenharmony_ci zipdata = [] 1957db96d56Sopenharmony_ci while True: 1967db96d56Sopenharmony_ci read_data = zipopen.read1(-1) 1977db96d56Sopenharmony_ci if not read_data: 1987db96d56Sopenharmony_ci break 1997db96d56Sopenharmony_ci zipdata.append(read_data) 2007db96d56Sopenharmony_ci 2017db96d56Sopenharmony_ci self.assertEqual(b''.join(zipdata), self.data) 2027db96d56Sopenharmony_ci 2037db96d56Sopenharmony_ci def test_read1(self): 2047db96d56Sopenharmony_ci for f in get_files(self): 2057db96d56Sopenharmony_ci self.zip_read1_test(f, self.compression) 2067db96d56Sopenharmony_ci 2077db96d56Sopenharmony_ci def zip_read1_10_test(self, f, compression): 2087db96d56Sopenharmony_ci self.make_test_archive(f, compression) 2097db96d56Sopenharmony_ci 2107db96d56Sopenharmony_ci # Read the ZIP archive 2117db96d56Sopenharmony_ci with zipfile.ZipFile(f, "r") as zipfp, \ 2127db96d56Sopenharmony_ci zipfp.open(TESTFN) as zipopen: 2137db96d56Sopenharmony_ci zipdata = [] 2147db96d56Sopenharmony_ci while True: 2157db96d56Sopenharmony_ci read_data = zipopen.read1(10) 2167db96d56Sopenharmony_ci self.assertLessEqual(len(read_data), 10) 2177db96d56Sopenharmony_ci if not read_data: 2187db96d56Sopenharmony_ci break 2197db96d56Sopenharmony_ci zipdata.append(read_data) 2207db96d56Sopenharmony_ci 2217db96d56Sopenharmony_ci self.assertEqual(b''.join(zipdata), self.data) 2227db96d56Sopenharmony_ci 2237db96d56Sopenharmony_ci def test_read1_10(self): 2247db96d56Sopenharmony_ci for f in get_files(self): 2257db96d56Sopenharmony_ci self.zip_read1_10_test(f, self.compression) 2267db96d56Sopenharmony_ci 2277db96d56Sopenharmony_ci def zip_readline_read_test(self, f, compression): 2287db96d56Sopenharmony_ci self.make_test_archive(f, compression) 2297db96d56Sopenharmony_ci 2307db96d56Sopenharmony_ci # Read the ZIP archive 2317db96d56Sopenharmony_ci with zipfile.ZipFile(f, "r") as zipfp, \ 2327db96d56Sopenharmony_ci zipfp.open(TESTFN) as zipopen: 2337db96d56Sopenharmony_ci data = b'' 2347db96d56Sopenharmony_ci while True: 2357db96d56Sopenharmony_ci read = zipopen.readline() 2367db96d56Sopenharmony_ci if not read: 2377db96d56Sopenharmony_ci break 2387db96d56Sopenharmony_ci data += read 2397db96d56Sopenharmony_ci 2407db96d56Sopenharmony_ci read = zipopen.read(100) 2417db96d56Sopenharmony_ci if not read: 2427db96d56Sopenharmony_ci break 2437db96d56Sopenharmony_ci data += read 2447db96d56Sopenharmony_ci 2457db96d56Sopenharmony_ci self.assertEqual(data, self.data) 2467db96d56Sopenharmony_ci 2477db96d56Sopenharmony_ci def test_readline_read(self): 2487db96d56Sopenharmony_ci # Issue #7610: calls to readline() interleaved with calls to read(). 2497db96d56Sopenharmony_ci for f in get_files(self): 2507db96d56Sopenharmony_ci self.zip_readline_read_test(f, self.compression) 2517db96d56Sopenharmony_ci 2527db96d56Sopenharmony_ci def zip_readline_test(self, f, compression): 2537db96d56Sopenharmony_ci self.make_test_archive(f, compression) 2547db96d56Sopenharmony_ci 2557db96d56Sopenharmony_ci # Read the ZIP archive 2567db96d56Sopenharmony_ci with zipfile.ZipFile(f, "r") as zipfp: 2577db96d56Sopenharmony_ci with zipfp.open(TESTFN) as zipopen: 2587db96d56Sopenharmony_ci for line in self.line_gen: 2597db96d56Sopenharmony_ci linedata = zipopen.readline() 2607db96d56Sopenharmony_ci self.assertEqual(linedata, line) 2617db96d56Sopenharmony_ci 2627db96d56Sopenharmony_ci def test_readline(self): 2637db96d56Sopenharmony_ci for f in get_files(self): 2647db96d56Sopenharmony_ci self.zip_readline_test(f, self.compression) 2657db96d56Sopenharmony_ci 2667db96d56Sopenharmony_ci def zip_readlines_test(self, f, compression): 2677db96d56Sopenharmony_ci self.make_test_archive(f, compression) 2687db96d56Sopenharmony_ci 2697db96d56Sopenharmony_ci # Read the ZIP archive 2707db96d56Sopenharmony_ci with zipfile.ZipFile(f, "r") as zipfp: 2717db96d56Sopenharmony_ci with zipfp.open(TESTFN) as zipopen: 2727db96d56Sopenharmony_ci ziplines = zipopen.readlines() 2737db96d56Sopenharmony_ci for line, zipline in zip(self.line_gen, ziplines): 2747db96d56Sopenharmony_ci self.assertEqual(zipline, line) 2757db96d56Sopenharmony_ci 2767db96d56Sopenharmony_ci def test_readlines(self): 2777db96d56Sopenharmony_ci for f in get_files(self): 2787db96d56Sopenharmony_ci self.zip_readlines_test(f, self.compression) 2797db96d56Sopenharmony_ci 2807db96d56Sopenharmony_ci def zip_iterlines_test(self, f, compression): 2817db96d56Sopenharmony_ci self.make_test_archive(f, compression) 2827db96d56Sopenharmony_ci 2837db96d56Sopenharmony_ci # Read the ZIP archive 2847db96d56Sopenharmony_ci with zipfile.ZipFile(f, "r") as zipfp: 2857db96d56Sopenharmony_ci with zipfp.open(TESTFN) as zipopen: 2867db96d56Sopenharmony_ci for line, zipline in zip(self.line_gen, zipopen): 2877db96d56Sopenharmony_ci self.assertEqual(zipline, line) 2887db96d56Sopenharmony_ci 2897db96d56Sopenharmony_ci def test_iterlines(self): 2907db96d56Sopenharmony_ci for f in get_files(self): 2917db96d56Sopenharmony_ci self.zip_iterlines_test(f, self.compression) 2927db96d56Sopenharmony_ci 2937db96d56Sopenharmony_ci def test_low_compression(self): 2947db96d56Sopenharmony_ci """Check for cases where compressed data is larger than original.""" 2957db96d56Sopenharmony_ci # Create the ZIP archive 2967db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "w", self.compression) as zipfp: 2977db96d56Sopenharmony_ci zipfp.writestr("strfile", '12') 2987db96d56Sopenharmony_ci 2997db96d56Sopenharmony_ci # Get an open object for strfile 3007db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "r", self.compression) as zipfp: 3017db96d56Sopenharmony_ci with zipfp.open("strfile") as openobj: 3027db96d56Sopenharmony_ci self.assertEqual(openobj.read(1), b'1') 3037db96d56Sopenharmony_ci self.assertEqual(openobj.read(1), b'2') 3047db96d56Sopenharmony_ci 3057db96d56Sopenharmony_ci def test_writestr_compression(self): 3067db96d56Sopenharmony_ci zipfp = zipfile.ZipFile(TESTFN2, "w") 3077db96d56Sopenharmony_ci zipfp.writestr("b.txt", "hello world", compress_type=self.compression) 3087db96d56Sopenharmony_ci info = zipfp.getinfo('b.txt') 3097db96d56Sopenharmony_ci self.assertEqual(info.compress_type, self.compression) 3107db96d56Sopenharmony_ci 3117db96d56Sopenharmony_ci def test_writestr_compresslevel(self): 3127db96d56Sopenharmony_ci zipfp = zipfile.ZipFile(TESTFN2, "w", compresslevel=1) 3137db96d56Sopenharmony_ci zipfp.writestr("a.txt", "hello world", compress_type=self.compression) 3147db96d56Sopenharmony_ci zipfp.writestr("b.txt", "hello world", compress_type=self.compression, 3157db96d56Sopenharmony_ci compresslevel=2) 3167db96d56Sopenharmony_ci 3177db96d56Sopenharmony_ci # Compression level follows the constructor. 3187db96d56Sopenharmony_ci a_info = zipfp.getinfo('a.txt') 3197db96d56Sopenharmony_ci self.assertEqual(a_info.compress_type, self.compression) 3207db96d56Sopenharmony_ci self.assertEqual(a_info._compresslevel, 1) 3217db96d56Sopenharmony_ci 3227db96d56Sopenharmony_ci # Compression level is overridden. 3237db96d56Sopenharmony_ci b_info = zipfp.getinfo('b.txt') 3247db96d56Sopenharmony_ci self.assertEqual(b_info.compress_type, self.compression) 3257db96d56Sopenharmony_ci self.assertEqual(b_info._compresslevel, 2) 3267db96d56Sopenharmony_ci 3277db96d56Sopenharmony_ci def test_read_return_size(self): 3287db96d56Sopenharmony_ci # Issue #9837: ZipExtFile.read() shouldn't return more bytes 3297db96d56Sopenharmony_ci # than requested. 3307db96d56Sopenharmony_ci for test_size in (1, 4095, 4096, 4097, 16384): 3317db96d56Sopenharmony_ci file_size = test_size + 1 3327db96d56Sopenharmony_ci junk = randbytes(file_size) 3337db96d56Sopenharmony_ci with zipfile.ZipFile(io.BytesIO(), "w", self.compression) as zipf: 3347db96d56Sopenharmony_ci zipf.writestr('foo', junk) 3357db96d56Sopenharmony_ci with zipf.open('foo', 'r') as fp: 3367db96d56Sopenharmony_ci buf = fp.read(test_size) 3377db96d56Sopenharmony_ci self.assertEqual(len(buf), test_size) 3387db96d56Sopenharmony_ci 3397db96d56Sopenharmony_ci def test_truncated_zipfile(self): 3407db96d56Sopenharmony_ci fp = io.BytesIO() 3417db96d56Sopenharmony_ci with zipfile.ZipFile(fp, mode='w') as zipf: 3427db96d56Sopenharmony_ci zipf.writestr('strfile', self.data, compress_type=self.compression) 3437db96d56Sopenharmony_ci end_offset = fp.tell() 3447db96d56Sopenharmony_ci zipfiledata = fp.getvalue() 3457db96d56Sopenharmony_ci 3467db96d56Sopenharmony_ci fp = io.BytesIO(zipfiledata) 3477db96d56Sopenharmony_ci with zipfile.ZipFile(fp) as zipf: 3487db96d56Sopenharmony_ci with zipf.open('strfile') as zipopen: 3497db96d56Sopenharmony_ci fp.truncate(end_offset - 20) 3507db96d56Sopenharmony_ci with self.assertRaises(EOFError): 3517db96d56Sopenharmony_ci zipopen.read() 3527db96d56Sopenharmony_ci 3537db96d56Sopenharmony_ci fp = io.BytesIO(zipfiledata) 3547db96d56Sopenharmony_ci with zipfile.ZipFile(fp) as zipf: 3557db96d56Sopenharmony_ci with zipf.open('strfile') as zipopen: 3567db96d56Sopenharmony_ci fp.truncate(end_offset - 20) 3577db96d56Sopenharmony_ci with self.assertRaises(EOFError): 3587db96d56Sopenharmony_ci while zipopen.read(100): 3597db96d56Sopenharmony_ci pass 3607db96d56Sopenharmony_ci 3617db96d56Sopenharmony_ci fp = io.BytesIO(zipfiledata) 3627db96d56Sopenharmony_ci with zipfile.ZipFile(fp) as zipf: 3637db96d56Sopenharmony_ci with zipf.open('strfile') as zipopen: 3647db96d56Sopenharmony_ci fp.truncate(end_offset - 20) 3657db96d56Sopenharmony_ci with self.assertRaises(EOFError): 3667db96d56Sopenharmony_ci while zipopen.read1(100): 3677db96d56Sopenharmony_ci pass 3687db96d56Sopenharmony_ci 3697db96d56Sopenharmony_ci def test_repr(self): 3707db96d56Sopenharmony_ci fname = 'file.name' 3717db96d56Sopenharmony_ci for f in get_files(self): 3727db96d56Sopenharmony_ci with zipfile.ZipFile(f, 'w', self.compression) as zipfp: 3737db96d56Sopenharmony_ci zipfp.write(TESTFN, fname) 3747db96d56Sopenharmony_ci r = repr(zipfp) 3757db96d56Sopenharmony_ci self.assertIn("mode='w'", r) 3767db96d56Sopenharmony_ci 3777db96d56Sopenharmony_ci with zipfile.ZipFile(f, 'r') as zipfp: 3787db96d56Sopenharmony_ci r = repr(zipfp) 3797db96d56Sopenharmony_ci if isinstance(f, str): 3807db96d56Sopenharmony_ci self.assertIn('filename=%r' % f, r) 3817db96d56Sopenharmony_ci else: 3827db96d56Sopenharmony_ci self.assertIn('file=%r' % f, r) 3837db96d56Sopenharmony_ci self.assertIn("mode='r'", r) 3847db96d56Sopenharmony_ci r = repr(zipfp.getinfo(fname)) 3857db96d56Sopenharmony_ci self.assertIn('filename=%r' % fname, r) 3867db96d56Sopenharmony_ci self.assertIn('filemode=', r) 3877db96d56Sopenharmony_ci self.assertIn('file_size=', r) 3887db96d56Sopenharmony_ci if self.compression != zipfile.ZIP_STORED: 3897db96d56Sopenharmony_ci self.assertIn('compress_type=', r) 3907db96d56Sopenharmony_ci self.assertIn('compress_size=', r) 3917db96d56Sopenharmony_ci with zipfp.open(fname) as zipopen: 3927db96d56Sopenharmony_ci r = repr(zipopen) 3937db96d56Sopenharmony_ci self.assertIn('name=%r' % fname, r) 3947db96d56Sopenharmony_ci self.assertIn("mode='r'", r) 3957db96d56Sopenharmony_ci if self.compression != zipfile.ZIP_STORED: 3967db96d56Sopenharmony_ci self.assertIn('compress_type=', r) 3977db96d56Sopenharmony_ci self.assertIn('[closed]', repr(zipopen)) 3987db96d56Sopenharmony_ci self.assertIn('[closed]', repr(zipfp)) 3997db96d56Sopenharmony_ci 4007db96d56Sopenharmony_ci def test_compresslevel_basic(self): 4017db96d56Sopenharmony_ci for f in get_files(self): 4027db96d56Sopenharmony_ci self.zip_test(f, self.compression, compresslevel=9) 4037db96d56Sopenharmony_ci 4047db96d56Sopenharmony_ci def test_per_file_compresslevel(self): 4057db96d56Sopenharmony_ci """Check that files within a Zip archive can have different 4067db96d56Sopenharmony_ci compression levels.""" 4077db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "w", compresslevel=1) as zipfp: 4087db96d56Sopenharmony_ci zipfp.write(TESTFN, 'compress_1') 4097db96d56Sopenharmony_ci zipfp.write(TESTFN, 'compress_9', compresslevel=9) 4107db96d56Sopenharmony_ci one_info = zipfp.getinfo('compress_1') 4117db96d56Sopenharmony_ci nine_info = zipfp.getinfo('compress_9') 4127db96d56Sopenharmony_ci self.assertEqual(one_info._compresslevel, 1) 4137db96d56Sopenharmony_ci self.assertEqual(nine_info._compresslevel, 9) 4147db96d56Sopenharmony_ci 4157db96d56Sopenharmony_ci def test_writing_errors(self): 4167db96d56Sopenharmony_ci class BrokenFile(io.BytesIO): 4177db96d56Sopenharmony_ci def write(self, data): 4187db96d56Sopenharmony_ci nonlocal count 4197db96d56Sopenharmony_ci if count is not None: 4207db96d56Sopenharmony_ci if count == stop: 4217db96d56Sopenharmony_ci raise OSError 4227db96d56Sopenharmony_ci count += 1 4237db96d56Sopenharmony_ci super().write(data) 4247db96d56Sopenharmony_ci 4257db96d56Sopenharmony_ci stop = 0 4267db96d56Sopenharmony_ci while True: 4277db96d56Sopenharmony_ci testfile = BrokenFile() 4287db96d56Sopenharmony_ci count = None 4297db96d56Sopenharmony_ci with zipfile.ZipFile(testfile, 'w', self.compression) as zipfp: 4307db96d56Sopenharmony_ci with zipfp.open('file1', 'w') as f: 4317db96d56Sopenharmony_ci f.write(b'data1') 4327db96d56Sopenharmony_ci count = 0 4337db96d56Sopenharmony_ci try: 4347db96d56Sopenharmony_ci with zipfp.open('file2', 'w') as f: 4357db96d56Sopenharmony_ci f.write(b'data2') 4367db96d56Sopenharmony_ci except OSError: 4377db96d56Sopenharmony_ci stop += 1 4387db96d56Sopenharmony_ci else: 4397db96d56Sopenharmony_ci break 4407db96d56Sopenharmony_ci finally: 4417db96d56Sopenharmony_ci count = None 4427db96d56Sopenharmony_ci with zipfile.ZipFile(io.BytesIO(testfile.getvalue())) as zipfp: 4437db96d56Sopenharmony_ci self.assertEqual(zipfp.namelist(), ['file1']) 4447db96d56Sopenharmony_ci self.assertEqual(zipfp.read('file1'), b'data1') 4457db96d56Sopenharmony_ci 4467db96d56Sopenharmony_ci with zipfile.ZipFile(io.BytesIO(testfile.getvalue())) as zipfp: 4477db96d56Sopenharmony_ci self.assertEqual(zipfp.namelist(), ['file1', 'file2']) 4487db96d56Sopenharmony_ci self.assertEqual(zipfp.read('file1'), b'data1') 4497db96d56Sopenharmony_ci self.assertEqual(zipfp.read('file2'), b'data2') 4507db96d56Sopenharmony_ci 4517db96d56Sopenharmony_ci 4527db96d56Sopenharmony_ci def tearDown(self): 4537db96d56Sopenharmony_ci unlink(TESTFN) 4547db96d56Sopenharmony_ci unlink(TESTFN2) 4557db96d56Sopenharmony_ci 4567db96d56Sopenharmony_ci 4577db96d56Sopenharmony_ciclass StoredTestsWithSourceFile(AbstractTestsWithSourceFile, 4587db96d56Sopenharmony_ci unittest.TestCase): 4597db96d56Sopenharmony_ci compression = zipfile.ZIP_STORED 4607db96d56Sopenharmony_ci test_low_compression = None 4617db96d56Sopenharmony_ci 4627db96d56Sopenharmony_ci def zip_test_writestr_permissions(self, f, compression): 4637db96d56Sopenharmony_ci # Make sure that writestr and open(... mode='w') create files with 4647db96d56Sopenharmony_ci # mode 0600, when they are passed a name rather than a ZipInfo 4657db96d56Sopenharmony_ci # instance. 4667db96d56Sopenharmony_ci 4677db96d56Sopenharmony_ci self.make_test_archive(f, compression) 4687db96d56Sopenharmony_ci with zipfile.ZipFile(f, "r") as zipfp: 4697db96d56Sopenharmony_ci zinfo = zipfp.getinfo('strfile') 4707db96d56Sopenharmony_ci self.assertEqual(zinfo.external_attr, 0o600 << 16) 4717db96d56Sopenharmony_ci 4727db96d56Sopenharmony_ci zinfo2 = zipfp.getinfo('written-open-w') 4737db96d56Sopenharmony_ci self.assertEqual(zinfo2.external_attr, 0o600 << 16) 4747db96d56Sopenharmony_ci 4757db96d56Sopenharmony_ci def test_writestr_permissions(self): 4767db96d56Sopenharmony_ci for f in get_files(self): 4777db96d56Sopenharmony_ci self.zip_test_writestr_permissions(f, zipfile.ZIP_STORED) 4787db96d56Sopenharmony_ci 4797db96d56Sopenharmony_ci def test_absolute_arcnames(self): 4807db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED) as zipfp: 4817db96d56Sopenharmony_ci zipfp.write(TESTFN, "/absolute") 4827db96d56Sopenharmony_ci 4837db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "r", zipfile.ZIP_STORED) as zipfp: 4847db96d56Sopenharmony_ci self.assertEqual(zipfp.namelist(), ["absolute"]) 4857db96d56Sopenharmony_ci 4867db96d56Sopenharmony_ci def test_append_to_zip_file(self): 4877db96d56Sopenharmony_ci """Test appending to an existing zipfile.""" 4887db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED) as zipfp: 4897db96d56Sopenharmony_ci zipfp.write(TESTFN, TESTFN) 4907db96d56Sopenharmony_ci 4917db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "a", zipfile.ZIP_STORED) as zipfp: 4927db96d56Sopenharmony_ci zipfp.writestr("strfile", self.data) 4937db96d56Sopenharmony_ci self.assertEqual(zipfp.namelist(), [TESTFN, "strfile"]) 4947db96d56Sopenharmony_ci 4957db96d56Sopenharmony_ci def test_append_to_non_zip_file(self): 4967db96d56Sopenharmony_ci """Test appending to an existing file that is not a zipfile.""" 4977db96d56Sopenharmony_ci # NOTE: this test fails if len(d) < 22 because of the first 4987db96d56Sopenharmony_ci # line "fpin.seek(-22, 2)" in _EndRecData 4997db96d56Sopenharmony_ci data = b'I am not a ZipFile!'*10 5007db96d56Sopenharmony_ci with open(TESTFN2, 'wb') as f: 5017db96d56Sopenharmony_ci f.write(data) 5027db96d56Sopenharmony_ci 5037db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "a", zipfile.ZIP_STORED) as zipfp: 5047db96d56Sopenharmony_ci zipfp.write(TESTFN, TESTFN) 5057db96d56Sopenharmony_ci 5067db96d56Sopenharmony_ci with open(TESTFN2, 'rb') as f: 5077db96d56Sopenharmony_ci f.seek(len(data)) 5087db96d56Sopenharmony_ci with zipfile.ZipFile(f, "r") as zipfp: 5097db96d56Sopenharmony_ci self.assertEqual(zipfp.namelist(), [TESTFN]) 5107db96d56Sopenharmony_ci self.assertEqual(zipfp.read(TESTFN), self.data) 5117db96d56Sopenharmony_ci with open(TESTFN2, 'rb') as f: 5127db96d56Sopenharmony_ci self.assertEqual(f.read(len(data)), data) 5137db96d56Sopenharmony_ci zipfiledata = f.read() 5147db96d56Sopenharmony_ci with io.BytesIO(zipfiledata) as bio, zipfile.ZipFile(bio) as zipfp: 5157db96d56Sopenharmony_ci self.assertEqual(zipfp.namelist(), [TESTFN]) 5167db96d56Sopenharmony_ci self.assertEqual(zipfp.read(TESTFN), self.data) 5177db96d56Sopenharmony_ci 5187db96d56Sopenharmony_ci def test_read_concatenated_zip_file(self): 5197db96d56Sopenharmony_ci with io.BytesIO() as bio: 5207db96d56Sopenharmony_ci with zipfile.ZipFile(bio, 'w', zipfile.ZIP_STORED) as zipfp: 5217db96d56Sopenharmony_ci zipfp.write(TESTFN, TESTFN) 5227db96d56Sopenharmony_ci zipfiledata = bio.getvalue() 5237db96d56Sopenharmony_ci data = b'I am not a ZipFile!'*10 5247db96d56Sopenharmony_ci with open(TESTFN2, 'wb') as f: 5257db96d56Sopenharmony_ci f.write(data) 5267db96d56Sopenharmony_ci f.write(zipfiledata) 5277db96d56Sopenharmony_ci 5287db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2) as zipfp: 5297db96d56Sopenharmony_ci self.assertEqual(zipfp.namelist(), [TESTFN]) 5307db96d56Sopenharmony_ci self.assertEqual(zipfp.read(TESTFN), self.data) 5317db96d56Sopenharmony_ci 5327db96d56Sopenharmony_ci def test_append_to_concatenated_zip_file(self): 5337db96d56Sopenharmony_ci with io.BytesIO() as bio: 5347db96d56Sopenharmony_ci with zipfile.ZipFile(bio, 'w', zipfile.ZIP_STORED) as zipfp: 5357db96d56Sopenharmony_ci zipfp.write(TESTFN, TESTFN) 5367db96d56Sopenharmony_ci zipfiledata = bio.getvalue() 5377db96d56Sopenharmony_ci data = b'I am not a ZipFile!'*1000000 5387db96d56Sopenharmony_ci with open(TESTFN2, 'wb') as f: 5397db96d56Sopenharmony_ci f.write(data) 5407db96d56Sopenharmony_ci f.write(zipfiledata) 5417db96d56Sopenharmony_ci 5427db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, 'a') as zipfp: 5437db96d56Sopenharmony_ci self.assertEqual(zipfp.namelist(), [TESTFN]) 5447db96d56Sopenharmony_ci zipfp.writestr('strfile', self.data) 5457db96d56Sopenharmony_ci 5467db96d56Sopenharmony_ci with open(TESTFN2, 'rb') as f: 5477db96d56Sopenharmony_ci self.assertEqual(f.read(len(data)), data) 5487db96d56Sopenharmony_ci zipfiledata = f.read() 5497db96d56Sopenharmony_ci with io.BytesIO(zipfiledata) as bio, zipfile.ZipFile(bio) as zipfp: 5507db96d56Sopenharmony_ci self.assertEqual(zipfp.namelist(), [TESTFN, 'strfile']) 5517db96d56Sopenharmony_ci self.assertEqual(zipfp.read(TESTFN), self.data) 5527db96d56Sopenharmony_ci self.assertEqual(zipfp.read('strfile'), self.data) 5537db96d56Sopenharmony_ci 5547db96d56Sopenharmony_ci def test_ignores_newline_at_end(self): 5557db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED) as zipfp: 5567db96d56Sopenharmony_ci zipfp.write(TESTFN, TESTFN) 5577db96d56Sopenharmony_ci with open(TESTFN2, 'a', encoding='utf-8') as f: 5587db96d56Sopenharmony_ci f.write("\r\n\00\00\00") 5597db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "r") as zipfp: 5607db96d56Sopenharmony_ci self.assertIsInstance(zipfp, zipfile.ZipFile) 5617db96d56Sopenharmony_ci 5627db96d56Sopenharmony_ci def test_ignores_stuff_appended_past_comments(self): 5637db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED) as zipfp: 5647db96d56Sopenharmony_ci zipfp.comment = b"this is a comment" 5657db96d56Sopenharmony_ci zipfp.write(TESTFN, TESTFN) 5667db96d56Sopenharmony_ci with open(TESTFN2, 'a', encoding='utf-8') as f: 5677db96d56Sopenharmony_ci f.write("abcdef\r\n") 5687db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "r") as zipfp: 5697db96d56Sopenharmony_ci self.assertIsInstance(zipfp, zipfile.ZipFile) 5707db96d56Sopenharmony_ci self.assertEqual(zipfp.comment, b"this is a comment") 5717db96d56Sopenharmony_ci 5727db96d56Sopenharmony_ci def test_write_default_name(self): 5737db96d56Sopenharmony_ci """Check that calling ZipFile.write without arcname specified 5747db96d56Sopenharmony_ci produces the expected result.""" 5757db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "w") as zipfp: 5767db96d56Sopenharmony_ci zipfp.write(TESTFN) 5777db96d56Sopenharmony_ci with open(TESTFN, "rb") as f: 5787db96d56Sopenharmony_ci self.assertEqual(zipfp.read(TESTFN), f.read()) 5797db96d56Sopenharmony_ci 5807db96d56Sopenharmony_ci def test_io_on_closed_zipextfile(self): 5817db96d56Sopenharmony_ci fname = "somefile.txt" 5827db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, mode="w") as zipfp: 5837db96d56Sopenharmony_ci zipfp.writestr(fname, "bogus") 5847db96d56Sopenharmony_ci 5857db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, mode="r") as zipfp: 5867db96d56Sopenharmony_ci with zipfp.open(fname) as fid: 5877db96d56Sopenharmony_ci fid.close() 5887db96d56Sopenharmony_ci self.assertRaises(ValueError, fid.read) 5897db96d56Sopenharmony_ci self.assertRaises(ValueError, fid.seek, 0) 5907db96d56Sopenharmony_ci self.assertRaises(ValueError, fid.tell) 5917db96d56Sopenharmony_ci self.assertRaises(ValueError, fid.readable) 5927db96d56Sopenharmony_ci self.assertRaises(ValueError, fid.seekable) 5937db96d56Sopenharmony_ci 5947db96d56Sopenharmony_ci def test_write_to_readonly(self): 5957db96d56Sopenharmony_ci """Check that trying to call write() on a readonly ZipFile object 5967db96d56Sopenharmony_ci raises a ValueError.""" 5977db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, mode="w") as zipfp: 5987db96d56Sopenharmony_ci zipfp.writestr("somefile.txt", "bogus") 5997db96d56Sopenharmony_ci 6007db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, mode="r") as zipfp: 6017db96d56Sopenharmony_ci self.assertRaises(ValueError, zipfp.write, TESTFN) 6027db96d56Sopenharmony_ci 6037db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, mode="r") as zipfp: 6047db96d56Sopenharmony_ci with self.assertRaises(ValueError): 6057db96d56Sopenharmony_ci zipfp.open(TESTFN, mode='w') 6067db96d56Sopenharmony_ci 6077db96d56Sopenharmony_ci def test_add_file_before_1980(self): 6087db96d56Sopenharmony_ci # Set atime and mtime to 1970-01-01 6097db96d56Sopenharmony_ci os.utime(TESTFN, (0, 0)) 6107db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "w") as zipfp: 6117db96d56Sopenharmony_ci self.assertRaises(ValueError, zipfp.write, TESTFN) 6127db96d56Sopenharmony_ci 6137db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "w", strict_timestamps=False) as zipfp: 6147db96d56Sopenharmony_ci zipfp.write(TESTFN) 6157db96d56Sopenharmony_ci zinfo = zipfp.getinfo(TESTFN) 6167db96d56Sopenharmony_ci self.assertEqual(zinfo.date_time, (1980, 1, 1, 0, 0, 0)) 6177db96d56Sopenharmony_ci 6187db96d56Sopenharmony_ci def test_add_file_after_2107(self): 6197db96d56Sopenharmony_ci # Set atime and mtime to 2108-12-30 6207db96d56Sopenharmony_ci ts = 4386268800 6217db96d56Sopenharmony_ci try: 6227db96d56Sopenharmony_ci time.localtime(ts) 6237db96d56Sopenharmony_ci except OverflowError: 6247db96d56Sopenharmony_ci self.skipTest(f'time.localtime({ts}) raises OverflowError') 6257db96d56Sopenharmony_ci try: 6267db96d56Sopenharmony_ci os.utime(TESTFN, (ts, ts)) 6277db96d56Sopenharmony_ci except OverflowError: 6287db96d56Sopenharmony_ci self.skipTest('Host fs cannot set timestamp to required value.') 6297db96d56Sopenharmony_ci 6307db96d56Sopenharmony_ci mtime_ns = os.stat(TESTFN).st_mtime_ns 6317db96d56Sopenharmony_ci if mtime_ns != (4386268800 * 10**9): 6327db96d56Sopenharmony_ci # XFS filesystem is limited to 32-bit timestamp, but the syscall 6337db96d56Sopenharmony_ci # didn't fail. Moreover, there is a VFS bug which returns 6347db96d56Sopenharmony_ci # a cached timestamp which is different than the value on disk. 6357db96d56Sopenharmony_ci # 6367db96d56Sopenharmony_ci # Test st_mtime_ns rather than st_mtime to avoid rounding issues. 6377db96d56Sopenharmony_ci # 6387db96d56Sopenharmony_ci # https://bugzilla.redhat.com/show_bug.cgi?id=1795576 6397db96d56Sopenharmony_ci # https://bugs.python.org/issue39460#msg360952 6407db96d56Sopenharmony_ci self.skipTest(f"Linux VFS/XFS kernel bug detected: {mtime_ns=}") 6417db96d56Sopenharmony_ci 6427db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "w") as zipfp: 6437db96d56Sopenharmony_ci self.assertRaises(struct.error, zipfp.write, TESTFN) 6447db96d56Sopenharmony_ci 6457db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "w", strict_timestamps=False) as zipfp: 6467db96d56Sopenharmony_ci zipfp.write(TESTFN) 6477db96d56Sopenharmony_ci zinfo = zipfp.getinfo(TESTFN) 6487db96d56Sopenharmony_ci self.assertEqual(zinfo.date_time, (2107, 12, 31, 23, 59, 59)) 6497db96d56Sopenharmony_ci 6507db96d56Sopenharmony_ci 6517db96d56Sopenharmony_ci@requires_zlib() 6527db96d56Sopenharmony_ciclass DeflateTestsWithSourceFile(AbstractTestsWithSourceFile, 6537db96d56Sopenharmony_ci unittest.TestCase): 6547db96d56Sopenharmony_ci compression = zipfile.ZIP_DEFLATED 6557db96d56Sopenharmony_ci 6567db96d56Sopenharmony_ci def test_per_file_compression(self): 6577db96d56Sopenharmony_ci """Check that files within a Zip archive can have different 6587db96d56Sopenharmony_ci compression options.""" 6597db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "w") as zipfp: 6607db96d56Sopenharmony_ci zipfp.write(TESTFN, 'storeme', zipfile.ZIP_STORED) 6617db96d56Sopenharmony_ci zipfp.write(TESTFN, 'deflateme', zipfile.ZIP_DEFLATED) 6627db96d56Sopenharmony_ci sinfo = zipfp.getinfo('storeme') 6637db96d56Sopenharmony_ci dinfo = zipfp.getinfo('deflateme') 6647db96d56Sopenharmony_ci self.assertEqual(sinfo.compress_type, zipfile.ZIP_STORED) 6657db96d56Sopenharmony_ci self.assertEqual(dinfo.compress_type, zipfile.ZIP_DEFLATED) 6667db96d56Sopenharmony_ci 6677db96d56Sopenharmony_ci@requires_bz2() 6687db96d56Sopenharmony_ciclass Bzip2TestsWithSourceFile(AbstractTestsWithSourceFile, 6697db96d56Sopenharmony_ci unittest.TestCase): 6707db96d56Sopenharmony_ci compression = zipfile.ZIP_BZIP2 6717db96d56Sopenharmony_ci 6727db96d56Sopenharmony_ci@requires_lzma() 6737db96d56Sopenharmony_ciclass LzmaTestsWithSourceFile(AbstractTestsWithSourceFile, 6747db96d56Sopenharmony_ci unittest.TestCase): 6757db96d56Sopenharmony_ci compression = zipfile.ZIP_LZMA 6767db96d56Sopenharmony_ci 6777db96d56Sopenharmony_ci 6787db96d56Sopenharmony_ciclass AbstractTestZip64InSmallFiles: 6797db96d56Sopenharmony_ci # These tests test the ZIP64 functionality without using large files, 6807db96d56Sopenharmony_ci # see test_zipfile64 for proper tests. 6817db96d56Sopenharmony_ci 6827db96d56Sopenharmony_ci @classmethod 6837db96d56Sopenharmony_ci def setUpClass(cls): 6847db96d56Sopenharmony_ci line_gen = (bytes("Test of zipfile line %d." % i, "ascii") 6857db96d56Sopenharmony_ci for i in range(0, FIXEDTEST_SIZE)) 6867db96d56Sopenharmony_ci cls.data = b'\n'.join(line_gen) 6877db96d56Sopenharmony_ci 6887db96d56Sopenharmony_ci def setUp(self): 6897db96d56Sopenharmony_ci self._limit = zipfile.ZIP64_LIMIT 6907db96d56Sopenharmony_ci self._filecount_limit = zipfile.ZIP_FILECOUNT_LIMIT 6917db96d56Sopenharmony_ci zipfile.ZIP64_LIMIT = 1000 6927db96d56Sopenharmony_ci zipfile.ZIP_FILECOUNT_LIMIT = 9 6937db96d56Sopenharmony_ci 6947db96d56Sopenharmony_ci # Make a source file with some lines 6957db96d56Sopenharmony_ci with open(TESTFN, "wb") as fp: 6967db96d56Sopenharmony_ci fp.write(self.data) 6977db96d56Sopenharmony_ci 6987db96d56Sopenharmony_ci def zip_test(self, f, compression): 6997db96d56Sopenharmony_ci # Create the ZIP archive 7007db96d56Sopenharmony_ci with zipfile.ZipFile(f, "w", compression, allowZip64=True) as zipfp: 7017db96d56Sopenharmony_ci zipfp.write(TESTFN, "another.name") 7027db96d56Sopenharmony_ci zipfp.write(TESTFN, TESTFN) 7037db96d56Sopenharmony_ci zipfp.writestr("strfile", self.data) 7047db96d56Sopenharmony_ci 7057db96d56Sopenharmony_ci # Read the ZIP archive 7067db96d56Sopenharmony_ci with zipfile.ZipFile(f, "r", compression) as zipfp: 7077db96d56Sopenharmony_ci self.assertEqual(zipfp.read(TESTFN), self.data) 7087db96d56Sopenharmony_ci self.assertEqual(zipfp.read("another.name"), self.data) 7097db96d56Sopenharmony_ci self.assertEqual(zipfp.read("strfile"), self.data) 7107db96d56Sopenharmony_ci 7117db96d56Sopenharmony_ci # Print the ZIP directory 7127db96d56Sopenharmony_ci fp = io.StringIO() 7137db96d56Sopenharmony_ci zipfp.printdir(fp) 7147db96d56Sopenharmony_ci 7157db96d56Sopenharmony_ci directory = fp.getvalue() 7167db96d56Sopenharmony_ci lines = directory.splitlines() 7177db96d56Sopenharmony_ci self.assertEqual(len(lines), 4) # Number of files + header 7187db96d56Sopenharmony_ci 7197db96d56Sopenharmony_ci self.assertIn('File Name', lines[0]) 7207db96d56Sopenharmony_ci self.assertIn('Modified', lines[0]) 7217db96d56Sopenharmony_ci self.assertIn('Size', lines[0]) 7227db96d56Sopenharmony_ci 7237db96d56Sopenharmony_ci fn, date, time_, size = lines[1].split() 7247db96d56Sopenharmony_ci self.assertEqual(fn, 'another.name') 7257db96d56Sopenharmony_ci self.assertTrue(time.strptime(date, '%Y-%m-%d')) 7267db96d56Sopenharmony_ci self.assertTrue(time.strptime(time_, '%H:%M:%S')) 7277db96d56Sopenharmony_ci self.assertEqual(size, str(len(self.data))) 7287db96d56Sopenharmony_ci 7297db96d56Sopenharmony_ci # Check the namelist 7307db96d56Sopenharmony_ci names = zipfp.namelist() 7317db96d56Sopenharmony_ci self.assertEqual(len(names), 3) 7327db96d56Sopenharmony_ci self.assertIn(TESTFN, names) 7337db96d56Sopenharmony_ci self.assertIn("another.name", names) 7347db96d56Sopenharmony_ci self.assertIn("strfile", names) 7357db96d56Sopenharmony_ci 7367db96d56Sopenharmony_ci # Check infolist 7377db96d56Sopenharmony_ci infos = zipfp.infolist() 7387db96d56Sopenharmony_ci names = [i.filename for i in infos] 7397db96d56Sopenharmony_ci self.assertEqual(len(names), 3) 7407db96d56Sopenharmony_ci self.assertIn(TESTFN, names) 7417db96d56Sopenharmony_ci self.assertIn("another.name", names) 7427db96d56Sopenharmony_ci self.assertIn("strfile", names) 7437db96d56Sopenharmony_ci for i in infos: 7447db96d56Sopenharmony_ci self.assertEqual(i.file_size, len(self.data)) 7457db96d56Sopenharmony_ci 7467db96d56Sopenharmony_ci # check getinfo 7477db96d56Sopenharmony_ci for nm in (TESTFN, "another.name", "strfile"): 7487db96d56Sopenharmony_ci info = zipfp.getinfo(nm) 7497db96d56Sopenharmony_ci self.assertEqual(info.filename, nm) 7507db96d56Sopenharmony_ci self.assertEqual(info.file_size, len(self.data)) 7517db96d56Sopenharmony_ci 7527db96d56Sopenharmony_ci # Check that testzip doesn't raise an exception 7537db96d56Sopenharmony_ci zipfp.testzip() 7547db96d56Sopenharmony_ci 7557db96d56Sopenharmony_ci def test_basic(self): 7567db96d56Sopenharmony_ci for f in get_files(self): 7577db96d56Sopenharmony_ci self.zip_test(f, self.compression) 7587db96d56Sopenharmony_ci 7597db96d56Sopenharmony_ci def test_too_many_files(self): 7607db96d56Sopenharmony_ci # This test checks that more than 64k files can be added to an archive, 7617db96d56Sopenharmony_ci # and that the resulting archive can be read properly by ZipFile 7627db96d56Sopenharmony_ci zipf = zipfile.ZipFile(TESTFN, "w", self.compression, 7637db96d56Sopenharmony_ci allowZip64=True) 7647db96d56Sopenharmony_ci zipf.debug = 100 7657db96d56Sopenharmony_ci numfiles = 15 7667db96d56Sopenharmony_ci for i in range(numfiles): 7677db96d56Sopenharmony_ci zipf.writestr("foo%08d" % i, "%d" % (i**3 % 57)) 7687db96d56Sopenharmony_ci self.assertEqual(len(zipf.namelist()), numfiles) 7697db96d56Sopenharmony_ci zipf.close() 7707db96d56Sopenharmony_ci 7717db96d56Sopenharmony_ci zipf2 = zipfile.ZipFile(TESTFN, "r", self.compression) 7727db96d56Sopenharmony_ci self.assertEqual(len(zipf2.namelist()), numfiles) 7737db96d56Sopenharmony_ci for i in range(numfiles): 7747db96d56Sopenharmony_ci content = zipf2.read("foo%08d" % i).decode('ascii') 7757db96d56Sopenharmony_ci self.assertEqual(content, "%d" % (i**3 % 57)) 7767db96d56Sopenharmony_ci zipf2.close() 7777db96d56Sopenharmony_ci 7787db96d56Sopenharmony_ci def test_too_many_files_append(self): 7797db96d56Sopenharmony_ci zipf = zipfile.ZipFile(TESTFN, "w", self.compression, 7807db96d56Sopenharmony_ci allowZip64=False) 7817db96d56Sopenharmony_ci zipf.debug = 100 7827db96d56Sopenharmony_ci numfiles = 9 7837db96d56Sopenharmony_ci for i in range(numfiles): 7847db96d56Sopenharmony_ci zipf.writestr("foo%08d" % i, "%d" % (i**3 % 57)) 7857db96d56Sopenharmony_ci self.assertEqual(len(zipf.namelist()), numfiles) 7867db96d56Sopenharmony_ci with self.assertRaises(zipfile.LargeZipFile): 7877db96d56Sopenharmony_ci zipf.writestr("foo%08d" % numfiles, b'') 7887db96d56Sopenharmony_ci self.assertEqual(len(zipf.namelist()), numfiles) 7897db96d56Sopenharmony_ci zipf.close() 7907db96d56Sopenharmony_ci 7917db96d56Sopenharmony_ci zipf = zipfile.ZipFile(TESTFN, "a", self.compression, 7927db96d56Sopenharmony_ci allowZip64=False) 7937db96d56Sopenharmony_ci zipf.debug = 100 7947db96d56Sopenharmony_ci self.assertEqual(len(zipf.namelist()), numfiles) 7957db96d56Sopenharmony_ci with self.assertRaises(zipfile.LargeZipFile): 7967db96d56Sopenharmony_ci zipf.writestr("foo%08d" % numfiles, b'') 7977db96d56Sopenharmony_ci self.assertEqual(len(zipf.namelist()), numfiles) 7987db96d56Sopenharmony_ci zipf.close() 7997db96d56Sopenharmony_ci 8007db96d56Sopenharmony_ci zipf = zipfile.ZipFile(TESTFN, "a", self.compression, 8017db96d56Sopenharmony_ci allowZip64=True) 8027db96d56Sopenharmony_ci zipf.debug = 100 8037db96d56Sopenharmony_ci self.assertEqual(len(zipf.namelist()), numfiles) 8047db96d56Sopenharmony_ci numfiles2 = 15 8057db96d56Sopenharmony_ci for i in range(numfiles, numfiles2): 8067db96d56Sopenharmony_ci zipf.writestr("foo%08d" % i, "%d" % (i**3 % 57)) 8077db96d56Sopenharmony_ci self.assertEqual(len(zipf.namelist()), numfiles2) 8087db96d56Sopenharmony_ci zipf.close() 8097db96d56Sopenharmony_ci 8107db96d56Sopenharmony_ci zipf2 = zipfile.ZipFile(TESTFN, "r", self.compression) 8117db96d56Sopenharmony_ci self.assertEqual(len(zipf2.namelist()), numfiles2) 8127db96d56Sopenharmony_ci for i in range(numfiles2): 8137db96d56Sopenharmony_ci content = zipf2.read("foo%08d" % i).decode('ascii') 8147db96d56Sopenharmony_ci self.assertEqual(content, "%d" % (i**3 % 57)) 8157db96d56Sopenharmony_ci zipf2.close() 8167db96d56Sopenharmony_ci 8177db96d56Sopenharmony_ci def tearDown(self): 8187db96d56Sopenharmony_ci zipfile.ZIP64_LIMIT = self._limit 8197db96d56Sopenharmony_ci zipfile.ZIP_FILECOUNT_LIMIT = self._filecount_limit 8207db96d56Sopenharmony_ci unlink(TESTFN) 8217db96d56Sopenharmony_ci unlink(TESTFN2) 8227db96d56Sopenharmony_ci 8237db96d56Sopenharmony_ci 8247db96d56Sopenharmony_ciclass StoredTestZip64InSmallFiles(AbstractTestZip64InSmallFiles, 8257db96d56Sopenharmony_ci unittest.TestCase): 8267db96d56Sopenharmony_ci compression = zipfile.ZIP_STORED 8277db96d56Sopenharmony_ci 8287db96d56Sopenharmony_ci def large_file_exception_test(self, f, compression): 8297db96d56Sopenharmony_ci with zipfile.ZipFile(f, "w", compression, allowZip64=False) as zipfp: 8307db96d56Sopenharmony_ci self.assertRaises(zipfile.LargeZipFile, 8317db96d56Sopenharmony_ci zipfp.write, TESTFN, "another.name") 8327db96d56Sopenharmony_ci 8337db96d56Sopenharmony_ci def large_file_exception_test2(self, f, compression): 8347db96d56Sopenharmony_ci with zipfile.ZipFile(f, "w", compression, allowZip64=False) as zipfp: 8357db96d56Sopenharmony_ci self.assertRaises(zipfile.LargeZipFile, 8367db96d56Sopenharmony_ci zipfp.writestr, "another.name", self.data) 8377db96d56Sopenharmony_ci 8387db96d56Sopenharmony_ci def test_large_file_exception(self): 8397db96d56Sopenharmony_ci for f in get_files(self): 8407db96d56Sopenharmony_ci self.large_file_exception_test(f, zipfile.ZIP_STORED) 8417db96d56Sopenharmony_ci self.large_file_exception_test2(f, zipfile.ZIP_STORED) 8427db96d56Sopenharmony_ci 8437db96d56Sopenharmony_ci def test_absolute_arcnames(self): 8447db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED, 8457db96d56Sopenharmony_ci allowZip64=True) as zipfp: 8467db96d56Sopenharmony_ci zipfp.write(TESTFN, "/absolute") 8477db96d56Sopenharmony_ci 8487db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "r", zipfile.ZIP_STORED) as zipfp: 8497db96d56Sopenharmony_ci self.assertEqual(zipfp.namelist(), ["absolute"]) 8507db96d56Sopenharmony_ci 8517db96d56Sopenharmony_ci def test_append(self): 8527db96d56Sopenharmony_ci # Test that appending to the Zip64 archive doesn't change 8537db96d56Sopenharmony_ci # extra fields of existing entries. 8547db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "w", allowZip64=True) as zipfp: 8557db96d56Sopenharmony_ci zipfp.writestr("strfile", self.data) 8567db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "r", allowZip64=True) as zipfp: 8577db96d56Sopenharmony_ci zinfo = zipfp.getinfo("strfile") 8587db96d56Sopenharmony_ci extra = zinfo.extra 8597db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "a", allowZip64=True) as zipfp: 8607db96d56Sopenharmony_ci zipfp.writestr("strfile2", self.data) 8617db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "r", allowZip64=True) as zipfp: 8627db96d56Sopenharmony_ci zinfo = zipfp.getinfo("strfile") 8637db96d56Sopenharmony_ci self.assertEqual(zinfo.extra, extra) 8647db96d56Sopenharmony_ci 8657db96d56Sopenharmony_ci def make_zip64_file( 8667db96d56Sopenharmony_ci self, file_size_64_set=False, file_size_extra=False, 8677db96d56Sopenharmony_ci compress_size_64_set=False, compress_size_extra=False, 8687db96d56Sopenharmony_ci header_offset_64_set=False, header_offset_extra=False, 8697db96d56Sopenharmony_ci ): 8707db96d56Sopenharmony_ci """Generate bytes sequence for a zip with (incomplete) zip64 data. 8717db96d56Sopenharmony_ci 8727db96d56Sopenharmony_ci The actual values (not the zip 64 0xffffffff values) stored in the file 8737db96d56Sopenharmony_ci are: 8747db96d56Sopenharmony_ci file_size: 8 8757db96d56Sopenharmony_ci compress_size: 8 8767db96d56Sopenharmony_ci header_offset: 0 8777db96d56Sopenharmony_ci """ 8787db96d56Sopenharmony_ci actual_size = 8 8797db96d56Sopenharmony_ci actual_header_offset = 0 8807db96d56Sopenharmony_ci local_zip64_fields = [] 8817db96d56Sopenharmony_ci central_zip64_fields = [] 8827db96d56Sopenharmony_ci 8837db96d56Sopenharmony_ci file_size = actual_size 8847db96d56Sopenharmony_ci if file_size_64_set: 8857db96d56Sopenharmony_ci file_size = 0xffffffff 8867db96d56Sopenharmony_ci if file_size_extra: 8877db96d56Sopenharmony_ci local_zip64_fields.append(actual_size) 8887db96d56Sopenharmony_ci central_zip64_fields.append(actual_size) 8897db96d56Sopenharmony_ci file_size = struct.pack("<L", file_size) 8907db96d56Sopenharmony_ci 8917db96d56Sopenharmony_ci compress_size = actual_size 8927db96d56Sopenharmony_ci if compress_size_64_set: 8937db96d56Sopenharmony_ci compress_size = 0xffffffff 8947db96d56Sopenharmony_ci if compress_size_extra: 8957db96d56Sopenharmony_ci local_zip64_fields.append(actual_size) 8967db96d56Sopenharmony_ci central_zip64_fields.append(actual_size) 8977db96d56Sopenharmony_ci compress_size = struct.pack("<L", compress_size) 8987db96d56Sopenharmony_ci 8997db96d56Sopenharmony_ci header_offset = actual_header_offset 9007db96d56Sopenharmony_ci if header_offset_64_set: 9017db96d56Sopenharmony_ci header_offset = 0xffffffff 9027db96d56Sopenharmony_ci if header_offset_extra: 9037db96d56Sopenharmony_ci central_zip64_fields.append(actual_header_offset) 9047db96d56Sopenharmony_ci header_offset = struct.pack("<L", header_offset) 9057db96d56Sopenharmony_ci 9067db96d56Sopenharmony_ci local_extra = struct.pack( 9077db96d56Sopenharmony_ci '<HH' + 'Q'*len(local_zip64_fields), 9087db96d56Sopenharmony_ci 0x0001, 9097db96d56Sopenharmony_ci 8*len(local_zip64_fields), 9107db96d56Sopenharmony_ci *local_zip64_fields 9117db96d56Sopenharmony_ci ) 9127db96d56Sopenharmony_ci 9137db96d56Sopenharmony_ci central_extra = struct.pack( 9147db96d56Sopenharmony_ci '<HH' + 'Q'*len(central_zip64_fields), 9157db96d56Sopenharmony_ci 0x0001, 9167db96d56Sopenharmony_ci 8*len(central_zip64_fields), 9177db96d56Sopenharmony_ci *central_zip64_fields 9187db96d56Sopenharmony_ci ) 9197db96d56Sopenharmony_ci 9207db96d56Sopenharmony_ci central_dir_size = struct.pack('<Q', 58 + 8 * len(central_zip64_fields)) 9217db96d56Sopenharmony_ci offset_to_central_dir = struct.pack('<Q', 50 + 8 * len(local_zip64_fields)) 9227db96d56Sopenharmony_ci 9237db96d56Sopenharmony_ci local_extra_length = struct.pack("<H", 4 + 8 * len(local_zip64_fields)) 9247db96d56Sopenharmony_ci central_extra_length = struct.pack("<H", 4 + 8 * len(central_zip64_fields)) 9257db96d56Sopenharmony_ci 9267db96d56Sopenharmony_ci filename = b"test.txt" 9277db96d56Sopenharmony_ci content = b"test1234" 9287db96d56Sopenharmony_ci filename_length = struct.pack("<H", len(filename)) 9297db96d56Sopenharmony_ci zip64_contents = ( 9307db96d56Sopenharmony_ci # Local file header 9317db96d56Sopenharmony_ci b"PK\x03\x04\x14\x00\x00\x00\x00\x00\x00\x00!\x00\x9e%\xf5\xaf" 9327db96d56Sopenharmony_ci + compress_size 9337db96d56Sopenharmony_ci + file_size 9347db96d56Sopenharmony_ci + filename_length 9357db96d56Sopenharmony_ci + local_extra_length 9367db96d56Sopenharmony_ci + filename 9377db96d56Sopenharmony_ci + local_extra 9387db96d56Sopenharmony_ci + content 9397db96d56Sopenharmony_ci # Central directory: 9407db96d56Sopenharmony_ci + b"PK\x01\x02-\x03-\x00\x00\x00\x00\x00\x00\x00!\x00\x9e%\xf5\xaf" 9417db96d56Sopenharmony_ci + compress_size 9427db96d56Sopenharmony_ci + file_size 9437db96d56Sopenharmony_ci + filename_length 9447db96d56Sopenharmony_ci + central_extra_length 9457db96d56Sopenharmony_ci + b"\x00\x00\x00\x00\x00\x00\x00\x00\x80\x01" 9467db96d56Sopenharmony_ci + header_offset 9477db96d56Sopenharmony_ci + filename 9487db96d56Sopenharmony_ci + central_extra 9497db96d56Sopenharmony_ci # Zip64 end of central directory 9507db96d56Sopenharmony_ci + b"PK\x06\x06,\x00\x00\x00\x00\x00\x00\x00-\x00-" 9517db96d56Sopenharmony_ci + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00" 9527db96d56Sopenharmony_ci + b"\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" 9537db96d56Sopenharmony_ci + central_dir_size 9547db96d56Sopenharmony_ci + offset_to_central_dir 9557db96d56Sopenharmony_ci # Zip64 end of central directory locator 9567db96d56Sopenharmony_ci + b"PK\x06\x07\x00\x00\x00\x00l\x00\x00\x00\x00\x00\x00\x00\x01" 9577db96d56Sopenharmony_ci + b"\x00\x00\x00" 9587db96d56Sopenharmony_ci # end of central directory 9597db96d56Sopenharmony_ci + b"PK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x00:\x00\x00\x002\x00" 9607db96d56Sopenharmony_ci + b"\x00\x00\x00\x00" 9617db96d56Sopenharmony_ci ) 9627db96d56Sopenharmony_ci return zip64_contents 9637db96d56Sopenharmony_ci 9647db96d56Sopenharmony_ci def test_bad_zip64_extra(self): 9657db96d56Sopenharmony_ci """Missing zip64 extra records raises an exception. 9667db96d56Sopenharmony_ci 9677db96d56Sopenharmony_ci There are 4 fields that the zip64 format handles (the disk number is 9687db96d56Sopenharmony_ci not used in this module and so is ignored here). According to the zip 9697db96d56Sopenharmony_ci spec: 9707db96d56Sopenharmony_ci The order of the fields in the zip64 extended 9717db96d56Sopenharmony_ci information record is fixed, but the fields MUST 9727db96d56Sopenharmony_ci only appear if the corresponding Local or Central 9737db96d56Sopenharmony_ci directory record field is set to 0xFFFF or 0xFFFFFFFF. 9747db96d56Sopenharmony_ci 9757db96d56Sopenharmony_ci If the zip64 extra content doesn't contain enough entries for the 9767db96d56Sopenharmony_ci number of fields marked with 0xFFFF or 0xFFFFFFFF, we raise an error. 9777db96d56Sopenharmony_ci This test mismatches the length of the zip64 extra field and the number 9787db96d56Sopenharmony_ci of fields set to indicate the presence of zip64 data. 9797db96d56Sopenharmony_ci """ 9807db96d56Sopenharmony_ci # zip64 file size present, no fields in extra, expecting one, equals 9817db96d56Sopenharmony_ci # missing file size. 9827db96d56Sopenharmony_ci missing_file_size_extra = self.make_zip64_file( 9837db96d56Sopenharmony_ci file_size_64_set=True, 9847db96d56Sopenharmony_ci ) 9857db96d56Sopenharmony_ci with self.assertRaises(zipfile.BadZipFile) as e: 9867db96d56Sopenharmony_ci zipfile.ZipFile(io.BytesIO(missing_file_size_extra)) 9877db96d56Sopenharmony_ci self.assertIn('file size', str(e.exception).lower()) 9887db96d56Sopenharmony_ci 9897db96d56Sopenharmony_ci # zip64 file size present, zip64 compress size present, one field in 9907db96d56Sopenharmony_ci # extra, expecting two, equals missing compress size. 9917db96d56Sopenharmony_ci missing_compress_size_extra = self.make_zip64_file( 9927db96d56Sopenharmony_ci file_size_64_set=True, 9937db96d56Sopenharmony_ci file_size_extra=True, 9947db96d56Sopenharmony_ci compress_size_64_set=True, 9957db96d56Sopenharmony_ci ) 9967db96d56Sopenharmony_ci with self.assertRaises(zipfile.BadZipFile) as e: 9977db96d56Sopenharmony_ci zipfile.ZipFile(io.BytesIO(missing_compress_size_extra)) 9987db96d56Sopenharmony_ci self.assertIn('compress size', str(e.exception).lower()) 9997db96d56Sopenharmony_ci 10007db96d56Sopenharmony_ci # zip64 compress size present, no fields in extra, expecting one, 10017db96d56Sopenharmony_ci # equals missing compress size. 10027db96d56Sopenharmony_ci missing_compress_size_extra = self.make_zip64_file( 10037db96d56Sopenharmony_ci compress_size_64_set=True, 10047db96d56Sopenharmony_ci ) 10057db96d56Sopenharmony_ci with self.assertRaises(zipfile.BadZipFile) as e: 10067db96d56Sopenharmony_ci zipfile.ZipFile(io.BytesIO(missing_compress_size_extra)) 10077db96d56Sopenharmony_ci self.assertIn('compress size', str(e.exception).lower()) 10087db96d56Sopenharmony_ci 10097db96d56Sopenharmony_ci # zip64 file size present, zip64 compress size present, zip64 header 10107db96d56Sopenharmony_ci # offset present, two fields in extra, expecting three, equals missing 10117db96d56Sopenharmony_ci # header offset 10127db96d56Sopenharmony_ci missing_header_offset_extra = self.make_zip64_file( 10137db96d56Sopenharmony_ci file_size_64_set=True, 10147db96d56Sopenharmony_ci file_size_extra=True, 10157db96d56Sopenharmony_ci compress_size_64_set=True, 10167db96d56Sopenharmony_ci compress_size_extra=True, 10177db96d56Sopenharmony_ci header_offset_64_set=True, 10187db96d56Sopenharmony_ci ) 10197db96d56Sopenharmony_ci with self.assertRaises(zipfile.BadZipFile) as e: 10207db96d56Sopenharmony_ci zipfile.ZipFile(io.BytesIO(missing_header_offset_extra)) 10217db96d56Sopenharmony_ci self.assertIn('header offset', str(e.exception).lower()) 10227db96d56Sopenharmony_ci 10237db96d56Sopenharmony_ci # zip64 compress size present, zip64 header offset present, one field 10247db96d56Sopenharmony_ci # in extra, expecting two, equals missing header offset 10257db96d56Sopenharmony_ci missing_header_offset_extra = self.make_zip64_file( 10267db96d56Sopenharmony_ci file_size_64_set=False, 10277db96d56Sopenharmony_ci compress_size_64_set=True, 10287db96d56Sopenharmony_ci compress_size_extra=True, 10297db96d56Sopenharmony_ci header_offset_64_set=True, 10307db96d56Sopenharmony_ci ) 10317db96d56Sopenharmony_ci with self.assertRaises(zipfile.BadZipFile) as e: 10327db96d56Sopenharmony_ci zipfile.ZipFile(io.BytesIO(missing_header_offset_extra)) 10337db96d56Sopenharmony_ci self.assertIn('header offset', str(e.exception).lower()) 10347db96d56Sopenharmony_ci 10357db96d56Sopenharmony_ci # zip64 file size present, zip64 header offset present, one field in 10367db96d56Sopenharmony_ci # extra, expecting two, equals missing header offset 10377db96d56Sopenharmony_ci missing_header_offset_extra = self.make_zip64_file( 10387db96d56Sopenharmony_ci file_size_64_set=True, 10397db96d56Sopenharmony_ci file_size_extra=True, 10407db96d56Sopenharmony_ci compress_size_64_set=False, 10417db96d56Sopenharmony_ci header_offset_64_set=True, 10427db96d56Sopenharmony_ci ) 10437db96d56Sopenharmony_ci with self.assertRaises(zipfile.BadZipFile) as e: 10447db96d56Sopenharmony_ci zipfile.ZipFile(io.BytesIO(missing_header_offset_extra)) 10457db96d56Sopenharmony_ci self.assertIn('header offset', str(e.exception).lower()) 10467db96d56Sopenharmony_ci 10477db96d56Sopenharmony_ci # zip64 header offset present, no fields in extra, expecting one, 10487db96d56Sopenharmony_ci # equals missing header offset 10497db96d56Sopenharmony_ci missing_header_offset_extra = self.make_zip64_file( 10507db96d56Sopenharmony_ci file_size_64_set=False, 10517db96d56Sopenharmony_ci compress_size_64_set=False, 10527db96d56Sopenharmony_ci header_offset_64_set=True, 10537db96d56Sopenharmony_ci ) 10547db96d56Sopenharmony_ci with self.assertRaises(zipfile.BadZipFile) as e: 10557db96d56Sopenharmony_ci zipfile.ZipFile(io.BytesIO(missing_header_offset_extra)) 10567db96d56Sopenharmony_ci self.assertIn('header offset', str(e.exception).lower()) 10577db96d56Sopenharmony_ci 10587db96d56Sopenharmony_ci def test_generated_valid_zip64_extra(self): 10597db96d56Sopenharmony_ci # These values are what is set in the make_zip64_file method. 10607db96d56Sopenharmony_ci expected_file_size = 8 10617db96d56Sopenharmony_ci expected_compress_size = 8 10627db96d56Sopenharmony_ci expected_header_offset = 0 10637db96d56Sopenharmony_ci expected_content = b"test1234" 10647db96d56Sopenharmony_ci 10657db96d56Sopenharmony_ci # Loop through the various valid combinations of zip64 masks 10667db96d56Sopenharmony_ci # present and extra fields present. 10677db96d56Sopenharmony_ci params = ( 10687db96d56Sopenharmony_ci {"file_size_64_set": True, "file_size_extra": True}, 10697db96d56Sopenharmony_ci {"compress_size_64_set": True, "compress_size_extra": True}, 10707db96d56Sopenharmony_ci {"header_offset_64_set": True, "header_offset_extra": True}, 10717db96d56Sopenharmony_ci ) 10727db96d56Sopenharmony_ci 10737db96d56Sopenharmony_ci for r in range(1, len(params) + 1): 10747db96d56Sopenharmony_ci for combo in itertools.combinations(params, r): 10757db96d56Sopenharmony_ci kwargs = {} 10767db96d56Sopenharmony_ci for c in combo: 10777db96d56Sopenharmony_ci kwargs.update(c) 10787db96d56Sopenharmony_ci with zipfile.ZipFile(io.BytesIO(self.make_zip64_file(**kwargs))) as zf: 10797db96d56Sopenharmony_ci zinfo = zf.infolist()[0] 10807db96d56Sopenharmony_ci self.assertEqual(zinfo.file_size, expected_file_size) 10817db96d56Sopenharmony_ci self.assertEqual(zinfo.compress_size, expected_compress_size) 10827db96d56Sopenharmony_ci self.assertEqual(zinfo.header_offset, expected_header_offset) 10837db96d56Sopenharmony_ci self.assertEqual(zf.read(zinfo), expected_content) 10847db96d56Sopenharmony_ci 10857db96d56Sopenharmony_ci def test_force_zip64(self): 10867db96d56Sopenharmony_ci """Test that forcing zip64 extensions correctly notes this in the zip file""" 10877db96d56Sopenharmony_ci 10887db96d56Sopenharmony_ci # GH-103861 describes an issue where forcing a small file to use zip64 10897db96d56Sopenharmony_ci # extensions would add a zip64 extra record, but not change the data 10907db96d56Sopenharmony_ci # sizes to 0xFFFFFFFF to indicate to the extractor that the zip64 10917db96d56Sopenharmony_ci # record should be read. Additionally, it would not set the required 10927db96d56Sopenharmony_ci # version to indicate that zip64 extensions are required to extract it. 10937db96d56Sopenharmony_ci # This test replicates the situation and reads the raw data to specifically ensure: 10947db96d56Sopenharmony_ci # - The required extract version is always >= ZIP64_VERSION 10957db96d56Sopenharmony_ci # - The compressed and uncompressed size in the file headers are both 10967db96d56Sopenharmony_ci # 0xFFFFFFFF (ie. point to zip64 record) 10977db96d56Sopenharmony_ci # - The zip64 record is provided and has the correct sizes in it 10987db96d56Sopenharmony_ci # Other aspects of the zip are checked as well, but verifying the above is the main goal. 10997db96d56Sopenharmony_ci # Because this is hard to verify by parsing the data as a zip, the raw 11007db96d56Sopenharmony_ci # bytes are checked to ensure that they line up with the zip spec. 11017db96d56Sopenharmony_ci # The spec for this can be found at: https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT 11027db96d56Sopenharmony_ci # The relevent sections for this test are: 11037db96d56Sopenharmony_ci # - 4.3.7 for local file header 11047db96d56Sopenharmony_ci # - 4.5.3 for zip64 extra field 11057db96d56Sopenharmony_ci 11067db96d56Sopenharmony_ci data = io.BytesIO() 11077db96d56Sopenharmony_ci with zipfile.ZipFile(data, mode="w", allowZip64=True) as zf: 11087db96d56Sopenharmony_ci with zf.open("text.txt", mode="w", force_zip64=True) as zi: 11097db96d56Sopenharmony_ci zi.write(b"_") 11107db96d56Sopenharmony_ci 11117db96d56Sopenharmony_ci zipdata = data.getvalue() 11127db96d56Sopenharmony_ci 11137db96d56Sopenharmony_ci # pull out and check zip information 11147db96d56Sopenharmony_ci ( 11157db96d56Sopenharmony_ci header, vers, os, flags, comp, csize, usize, fn_len, 11167db96d56Sopenharmony_ci ex_total_len, filename, ex_id, ex_len, ex_usize, ex_csize, cd_sig 11177db96d56Sopenharmony_ci ) = struct.unpack("<4sBBHH8xIIHH8shhQQx4s", zipdata[:63]) 11187db96d56Sopenharmony_ci 11197db96d56Sopenharmony_ci self.assertEqual(header, b"PK\x03\x04") # local file header 11207db96d56Sopenharmony_ci self.assertGreaterEqual(vers, zipfile.ZIP64_VERSION) # requires zip64 to extract 11217db96d56Sopenharmony_ci self.assertEqual(os, 0) # compatible with MS-DOS 11227db96d56Sopenharmony_ci self.assertEqual(flags, 0) # no flags 11237db96d56Sopenharmony_ci self.assertEqual(comp, 0) # compression method = stored 11247db96d56Sopenharmony_ci self.assertEqual(csize, 0xFFFFFFFF) # sizes are in zip64 extra 11257db96d56Sopenharmony_ci self.assertEqual(usize, 0xFFFFFFFF) 11267db96d56Sopenharmony_ci self.assertEqual(fn_len, 8) # filename len 11277db96d56Sopenharmony_ci self.assertEqual(ex_total_len, 20) # size of extra records 11287db96d56Sopenharmony_ci self.assertEqual(ex_id, 1) # Zip64 extra record 11297db96d56Sopenharmony_ci self.assertEqual(ex_len, 16) # 16 bytes of data 11307db96d56Sopenharmony_ci self.assertEqual(ex_usize, 1) # uncompressed size 11317db96d56Sopenharmony_ci self.assertEqual(ex_csize, 1) # compressed size 11327db96d56Sopenharmony_ci self.assertEqual(cd_sig, b"PK\x01\x02") # ensure the central directory header is next 11337db96d56Sopenharmony_ci 11347db96d56Sopenharmony_ci z = zipfile.ZipFile(io.BytesIO(zipdata)) 11357db96d56Sopenharmony_ci zinfos = z.infolist() 11367db96d56Sopenharmony_ci self.assertEqual(len(zinfos), 1) 11377db96d56Sopenharmony_ci self.assertGreaterEqual(zinfos[0].extract_version, zipfile.ZIP64_VERSION) # requires zip64 to extract 11387db96d56Sopenharmony_ci 11397db96d56Sopenharmony_ci def test_unseekable_zip_unknown_filesize(self): 11407db96d56Sopenharmony_ci """Test that creating a zip with/without seeking will raise a RuntimeError if zip64 was required but not used""" 11417db96d56Sopenharmony_ci 11427db96d56Sopenharmony_ci def make_zip(fp): 11437db96d56Sopenharmony_ci with zipfile.ZipFile(fp, mode="w", allowZip64=True) as zf: 11447db96d56Sopenharmony_ci with zf.open("text.txt", mode="w", force_zip64=False) as zi: 11457db96d56Sopenharmony_ci zi.write(b"_" * (zipfile.ZIP64_LIMIT + 1)) 11467db96d56Sopenharmony_ci 11477db96d56Sopenharmony_ci self.assertRaises(RuntimeError, make_zip, io.BytesIO()) 11487db96d56Sopenharmony_ci self.assertRaises(RuntimeError, make_zip, Unseekable(io.BytesIO())) 11497db96d56Sopenharmony_ci 11507db96d56Sopenharmony_ci def test_zip64_required_not_allowed_fail(self): 11517db96d56Sopenharmony_ci """Test that trying to add a large file to a zip that doesn't allow zip64 extensions fails on add""" 11527db96d56Sopenharmony_ci def make_zip(fp): 11537db96d56Sopenharmony_ci with zipfile.ZipFile(fp, mode="w", allowZip64=False) as zf: 11547db96d56Sopenharmony_ci # pretend zipfile.ZipInfo.from_file was used to get the name and filesize 11557db96d56Sopenharmony_ci info = zipfile.ZipInfo("text.txt") 11567db96d56Sopenharmony_ci info.file_size = zipfile.ZIP64_LIMIT + 1 11577db96d56Sopenharmony_ci zf.open(info, mode="w") 11587db96d56Sopenharmony_ci 11597db96d56Sopenharmony_ci self.assertRaises(zipfile.LargeZipFile, make_zip, io.BytesIO()) 11607db96d56Sopenharmony_ci self.assertRaises(zipfile.LargeZipFile, make_zip, Unseekable(io.BytesIO())) 11617db96d56Sopenharmony_ci 11627db96d56Sopenharmony_ci def test_unseekable_zip_known_filesize(self): 11637db96d56Sopenharmony_ci """Test that creating a zip without seeking will use zip64 extensions if the file size is provided up-front""" 11647db96d56Sopenharmony_ci 11657db96d56Sopenharmony_ci # This test ensures that the zip will use a zip64 data descriptor (same 11667db96d56Sopenharmony_ci # as a regular data descriptor except the sizes are 8 bytes instead of 11677db96d56Sopenharmony_ci # 4) record to communicate the size of a file if the zip is being 11687db96d56Sopenharmony_ci # written to an unseekable stream. 11697db96d56Sopenharmony_ci # Because this sort of thing is hard to verify by parsing the data back 11707db96d56Sopenharmony_ci # in as a zip, this test looks at the raw bytes created to ensure that 11717db96d56Sopenharmony_ci # the correct data has been generated. 11727db96d56Sopenharmony_ci # The spec for this can be found at: https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT 11737db96d56Sopenharmony_ci # The relevent sections for this test are: 11747db96d56Sopenharmony_ci # - 4.3.7 for local file header 11757db96d56Sopenharmony_ci # - 4.3.9 for the data descriptor 11767db96d56Sopenharmony_ci # - 4.5.3 for zip64 extra field 11777db96d56Sopenharmony_ci 11787db96d56Sopenharmony_ci file_size = zipfile.ZIP64_LIMIT + 1 11797db96d56Sopenharmony_ci 11807db96d56Sopenharmony_ci def make_zip(fp): 11817db96d56Sopenharmony_ci with zipfile.ZipFile(fp, mode="w", allowZip64=True) as zf: 11827db96d56Sopenharmony_ci # pretend zipfile.ZipInfo.from_file was used to get the name and filesize 11837db96d56Sopenharmony_ci info = zipfile.ZipInfo("text.txt") 11847db96d56Sopenharmony_ci info.file_size = file_size 11857db96d56Sopenharmony_ci with zf.open(info, mode="w", force_zip64=False) as zi: 11867db96d56Sopenharmony_ci zi.write(b"_" * file_size) 11877db96d56Sopenharmony_ci return fp 11887db96d56Sopenharmony_ci 11897db96d56Sopenharmony_ci # check seekable file information 11907db96d56Sopenharmony_ci seekable_data = make_zip(io.BytesIO()).getvalue() 11917db96d56Sopenharmony_ci ( 11927db96d56Sopenharmony_ci header, vers, os, flags, comp, csize, usize, fn_len, 11937db96d56Sopenharmony_ci ex_total_len, filename, ex_id, ex_len, ex_usize, ex_csize, 11947db96d56Sopenharmony_ci cd_sig 11957db96d56Sopenharmony_ci ) = struct.unpack("<4sBBHH8xIIHH8shhQQ{}x4s".format(file_size), seekable_data[:62 + file_size]) 11967db96d56Sopenharmony_ci 11977db96d56Sopenharmony_ci self.assertEqual(header, b"PK\x03\x04") # local file header 11987db96d56Sopenharmony_ci self.assertGreaterEqual(vers, zipfile.ZIP64_VERSION) # requires zip64 to extract 11997db96d56Sopenharmony_ci self.assertEqual(os, 0) # compatible with MS-DOS 12007db96d56Sopenharmony_ci self.assertEqual(flags, 0) # no flags set 12017db96d56Sopenharmony_ci self.assertEqual(comp, 0) # compression method = stored 12027db96d56Sopenharmony_ci self.assertEqual(csize, 0xFFFFFFFF) # sizes are in zip64 extra 12037db96d56Sopenharmony_ci self.assertEqual(usize, 0xFFFFFFFF) 12047db96d56Sopenharmony_ci self.assertEqual(fn_len, 8) # filename len 12057db96d56Sopenharmony_ci self.assertEqual(ex_total_len, 20) # size of extra records 12067db96d56Sopenharmony_ci self.assertEqual(ex_id, 1) # Zip64 extra record 12077db96d56Sopenharmony_ci self.assertEqual(ex_len, 16) # 16 bytes of data 12087db96d56Sopenharmony_ci self.assertEqual(ex_usize, file_size) # uncompressed size 12097db96d56Sopenharmony_ci self.assertEqual(ex_csize, file_size) # compressed size 12107db96d56Sopenharmony_ci self.assertEqual(cd_sig, b"PK\x01\x02") # ensure the central directory header is next 12117db96d56Sopenharmony_ci 12127db96d56Sopenharmony_ci # check unseekable file information 12137db96d56Sopenharmony_ci unseekable_data = make_zip(Unseekable(io.BytesIO())).fp.getvalue() 12147db96d56Sopenharmony_ci ( 12157db96d56Sopenharmony_ci header, vers, os, flags, comp, csize, usize, fn_len, 12167db96d56Sopenharmony_ci ex_total_len, filename, ex_id, ex_len, ex_usize, ex_csize, 12177db96d56Sopenharmony_ci dd_header, dd_usize, dd_csize, cd_sig 12187db96d56Sopenharmony_ci ) = struct.unpack("<4sBBHH8xIIHH8shhQQ{}x4s4xQQ4s".format(file_size), unseekable_data[:86 + file_size]) 12197db96d56Sopenharmony_ci 12207db96d56Sopenharmony_ci self.assertEqual(header, b"PK\x03\x04") # local file header 12217db96d56Sopenharmony_ci self.assertGreaterEqual(vers, zipfile.ZIP64_VERSION) # requires zip64 to extract 12227db96d56Sopenharmony_ci self.assertEqual(os, 0) # compatible with MS-DOS 12237db96d56Sopenharmony_ci self.assertEqual("{:b}".format(flags), "1000") # streaming flag set 12247db96d56Sopenharmony_ci self.assertEqual(comp, 0) # compression method = stored 12257db96d56Sopenharmony_ci self.assertEqual(csize, 0xFFFFFFFF) # sizes are in zip64 extra 12267db96d56Sopenharmony_ci self.assertEqual(usize, 0xFFFFFFFF) 12277db96d56Sopenharmony_ci self.assertEqual(fn_len, 8) # filename len 12287db96d56Sopenharmony_ci self.assertEqual(ex_total_len, 20) # size of extra records 12297db96d56Sopenharmony_ci self.assertEqual(ex_id, 1) # Zip64 extra record 12307db96d56Sopenharmony_ci self.assertEqual(ex_len, 16) # 16 bytes of data 12317db96d56Sopenharmony_ci self.assertEqual(ex_usize, 0) # uncompressed size - 0 to defer to data descriptor 12327db96d56Sopenharmony_ci self.assertEqual(ex_csize, 0) # compressed size - 0 to defer to data descriptor 12337db96d56Sopenharmony_ci self.assertEqual(dd_header, b"PK\07\x08") # data descriptor 12347db96d56Sopenharmony_ci self.assertEqual(dd_usize, file_size) # file size (8 bytes because zip64) 12357db96d56Sopenharmony_ci self.assertEqual(dd_csize, file_size) # compressed size (8 bytes because zip64) 12367db96d56Sopenharmony_ci self.assertEqual(cd_sig, b"PK\x01\x02") # ensure the central directory header is next 12377db96d56Sopenharmony_ci 12387db96d56Sopenharmony_ci 12397db96d56Sopenharmony_ci@requires_zlib() 12407db96d56Sopenharmony_ciclass DeflateTestZip64InSmallFiles(AbstractTestZip64InSmallFiles, 12417db96d56Sopenharmony_ci unittest.TestCase): 12427db96d56Sopenharmony_ci compression = zipfile.ZIP_DEFLATED 12437db96d56Sopenharmony_ci 12447db96d56Sopenharmony_ci@requires_bz2() 12457db96d56Sopenharmony_ciclass Bzip2TestZip64InSmallFiles(AbstractTestZip64InSmallFiles, 12467db96d56Sopenharmony_ci unittest.TestCase): 12477db96d56Sopenharmony_ci compression = zipfile.ZIP_BZIP2 12487db96d56Sopenharmony_ci 12497db96d56Sopenharmony_ci@requires_lzma() 12507db96d56Sopenharmony_ciclass LzmaTestZip64InSmallFiles(AbstractTestZip64InSmallFiles, 12517db96d56Sopenharmony_ci unittest.TestCase): 12527db96d56Sopenharmony_ci compression = zipfile.ZIP_LZMA 12537db96d56Sopenharmony_ci 12547db96d56Sopenharmony_ci 12557db96d56Sopenharmony_ciclass AbstractWriterTests: 12567db96d56Sopenharmony_ci 12577db96d56Sopenharmony_ci def tearDown(self): 12587db96d56Sopenharmony_ci unlink(TESTFN2) 12597db96d56Sopenharmony_ci 12607db96d56Sopenharmony_ci def test_close_after_close(self): 12617db96d56Sopenharmony_ci data = b'content' 12627db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "w", self.compression) as zipf: 12637db96d56Sopenharmony_ci w = zipf.open('test', 'w') 12647db96d56Sopenharmony_ci w.write(data) 12657db96d56Sopenharmony_ci w.close() 12667db96d56Sopenharmony_ci self.assertTrue(w.closed) 12677db96d56Sopenharmony_ci w.close() 12687db96d56Sopenharmony_ci self.assertTrue(w.closed) 12697db96d56Sopenharmony_ci self.assertEqual(zipf.read('test'), data) 12707db96d56Sopenharmony_ci 12717db96d56Sopenharmony_ci def test_write_after_close(self): 12727db96d56Sopenharmony_ci data = b'content' 12737db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "w", self.compression) as zipf: 12747db96d56Sopenharmony_ci w = zipf.open('test', 'w') 12757db96d56Sopenharmony_ci w.write(data) 12767db96d56Sopenharmony_ci w.close() 12777db96d56Sopenharmony_ci self.assertTrue(w.closed) 12787db96d56Sopenharmony_ci self.assertRaises(ValueError, w.write, b'') 12797db96d56Sopenharmony_ci self.assertEqual(zipf.read('test'), data) 12807db96d56Sopenharmony_ci 12817db96d56Sopenharmony_ci def test_issue44439(self): 12827db96d56Sopenharmony_ci q = array.array('Q', [1, 2, 3, 4, 5]) 12837db96d56Sopenharmony_ci LENGTH = len(q) * q.itemsize 12847db96d56Sopenharmony_ci with zipfile.ZipFile(io.BytesIO(), 'w', self.compression) as zip: 12857db96d56Sopenharmony_ci with zip.open('data', 'w') as data: 12867db96d56Sopenharmony_ci self.assertEqual(data.write(q), LENGTH) 12877db96d56Sopenharmony_ci self.assertEqual(zip.getinfo('data').file_size, LENGTH) 12887db96d56Sopenharmony_ci 12897db96d56Sopenharmony_ciclass StoredWriterTests(AbstractWriterTests, unittest.TestCase): 12907db96d56Sopenharmony_ci compression = zipfile.ZIP_STORED 12917db96d56Sopenharmony_ci 12927db96d56Sopenharmony_ci@requires_zlib() 12937db96d56Sopenharmony_ciclass DeflateWriterTests(AbstractWriterTests, unittest.TestCase): 12947db96d56Sopenharmony_ci compression = zipfile.ZIP_DEFLATED 12957db96d56Sopenharmony_ci 12967db96d56Sopenharmony_ci@requires_bz2() 12977db96d56Sopenharmony_ciclass Bzip2WriterTests(AbstractWriterTests, unittest.TestCase): 12987db96d56Sopenharmony_ci compression = zipfile.ZIP_BZIP2 12997db96d56Sopenharmony_ci 13007db96d56Sopenharmony_ci@requires_lzma() 13017db96d56Sopenharmony_ciclass LzmaWriterTests(AbstractWriterTests, unittest.TestCase): 13027db96d56Sopenharmony_ci compression = zipfile.ZIP_LZMA 13037db96d56Sopenharmony_ci 13047db96d56Sopenharmony_ci 13057db96d56Sopenharmony_ciclass PyZipFileTests(unittest.TestCase): 13067db96d56Sopenharmony_ci def assertCompiledIn(self, name, namelist): 13077db96d56Sopenharmony_ci if name + 'o' not in namelist: 13087db96d56Sopenharmony_ci self.assertIn(name + 'c', namelist) 13097db96d56Sopenharmony_ci 13107db96d56Sopenharmony_ci def requiresWriteAccess(self, path): 13117db96d56Sopenharmony_ci # effective_ids unavailable on windows 13127db96d56Sopenharmony_ci if not os.access(path, os.W_OK, 13137db96d56Sopenharmony_ci effective_ids=os.access in os.supports_effective_ids): 13147db96d56Sopenharmony_ci self.skipTest('requires write access to the installed location') 13157db96d56Sopenharmony_ci filename = os.path.join(path, 'test_zipfile.try') 13167db96d56Sopenharmony_ci try: 13177db96d56Sopenharmony_ci fd = os.open(filename, os.O_WRONLY | os.O_CREAT) 13187db96d56Sopenharmony_ci os.close(fd) 13197db96d56Sopenharmony_ci except Exception: 13207db96d56Sopenharmony_ci self.skipTest('requires write access to the installed location') 13217db96d56Sopenharmony_ci unlink(filename) 13227db96d56Sopenharmony_ci 13237db96d56Sopenharmony_ci def test_write_pyfile(self): 13247db96d56Sopenharmony_ci self.requiresWriteAccess(os.path.dirname(__file__)) 13257db96d56Sopenharmony_ci with TemporaryFile() as t, zipfile.PyZipFile(t, "w") as zipfp: 13267db96d56Sopenharmony_ci fn = __file__ 13277db96d56Sopenharmony_ci if fn.endswith('.pyc'): 13287db96d56Sopenharmony_ci path_split = fn.split(os.sep) 13297db96d56Sopenharmony_ci if os.altsep is not None: 13307db96d56Sopenharmony_ci path_split.extend(fn.split(os.altsep)) 13317db96d56Sopenharmony_ci if '__pycache__' in path_split: 13327db96d56Sopenharmony_ci fn = importlib.util.source_from_cache(fn) 13337db96d56Sopenharmony_ci else: 13347db96d56Sopenharmony_ci fn = fn[:-1] 13357db96d56Sopenharmony_ci 13367db96d56Sopenharmony_ci zipfp.writepy(fn) 13377db96d56Sopenharmony_ci 13387db96d56Sopenharmony_ci bn = os.path.basename(fn) 13397db96d56Sopenharmony_ci self.assertNotIn(bn, zipfp.namelist()) 13407db96d56Sopenharmony_ci self.assertCompiledIn(bn, zipfp.namelist()) 13417db96d56Sopenharmony_ci 13427db96d56Sopenharmony_ci with TemporaryFile() as t, zipfile.PyZipFile(t, "w") as zipfp: 13437db96d56Sopenharmony_ci fn = __file__ 13447db96d56Sopenharmony_ci if fn.endswith('.pyc'): 13457db96d56Sopenharmony_ci fn = fn[:-1] 13467db96d56Sopenharmony_ci 13477db96d56Sopenharmony_ci zipfp.writepy(fn, "testpackage") 13487db96d56Sopenharmony_ci 13497db96d56Sopenharmony_ci bn = "%s/%s" % ("testpackage", os.path.basename(fn)) 13507db96d56Sopenharmony_ci self.assertNotIn(bn, zipfp.namelist()) 13517db96d56Sopenharmony_ci self.assertCompiledIn(bn, zipfp.namelist()) 13527db96d56Sopenharmony_ci 13537db96d56Sopenharmony_ci def test_write_python_package(self): 13547db96d56Sopenharmony_ci import email 13557db96d56Sopenharmony_ci packagedir = os.path.dirname(email.__file__) 13567db96d56Sopenharmony_ci self.requiresWriteAccess(packagedir) 13577db96d56Sopenharmony_ci 13587db96d56Sopenharmony_ci with TemporaryFile() as t, zipfile.PyZipFile(t, "w") as zipfp: 13597db96d56Sopenharmony_ci zipfp.writepy(packagedir) 13607db96d56Sopenharmony_ci 13617db96d56Sopenharmony_ci # Check for a couple of modules at different levels of the 13627db96d56Sopenharmony_ci # hierarchy 13637db96d56Sopenharmony_ci names = zipfp.namelist() 13647db96d56Sopenharmony_ci self.assertCompiledIn('email/__init__.py', names) 13657db96d56Sopenharmony_ci self.assertCompiledIn('email/mime/text.py', names) 13667db96d56Sopenharmony_ci 13677db96d56Sopenharmony_ci def test_write_filtered_python_package(self): 13687db96d56Sopenharmony_ci import test 13697db96d56Sopenharmony_ci packagedir = os.path.dirname(test.__file__) 13707db96d56Sopenharmony_ci self.requiresWriteAccess(packagedir) 13717db96d56Sopenharmony_ci 13727db96d56Sopenharmony_ci with TemporaryFile() as t, zipfile.PyZipFile(t, "w") as zipfp: 13737db96d56Sopenharmony_ci 13747db96d56Sopenharmony_ci # first make sure that the test folder gives error messages 13757db96d56Sopenharmony_ci # (on the badsyntax_... files) 13767db96d56Sopenharmony_ci with captured_stdout() as reportSIO: 13777db96d56Sopenharmony_ci zipfp.writepy(packagedir) 13787db96d56Sopenharmony_ci reportStr = reportSIO.getvalue() 13797db96d56Sopenharmony_ci self.assertTrue('SyntaxError' in reportStr) 13807db96d56Sopenharmony_ci 13817db96d56Sopenharmony_ci # then check that the filter works on the whole package 13827db96d56Sopenharmony_ci with captured_stdout() as reportSIO: 13837db96d56Sopenharmony_ci zipfp.writepy(packagedir, filterfunc=lambda whatever: False) 13847db96d56Sopenharmony_ci reportStr = reportSIO.getvalue() 13857db96d56Sopenharmony_ci self.assertTrue('SyntaxError' not in reportStr) 13867db96d56Sopenharmony_ci 13877db96d56Sopenharmony_ci # then check that the filter works on individual files 13887db96d56Sopenharmony_ci def filter(path): 13897db96d56Sopenharmony_ci return not os.path.basename(path).startswith("bad") 13907db96d56Sopenharmony_ci with captured_stdout() as reportSIO, self.assertWarns(UserWarning): 13917db96d56Sopenharmony_ci zipfp.writepy(packagedir, filterfunc=filter) 13927db96d56Sopenharmony_ci reportStr = reportSIO.getvalue() 13937db96d56Sopenharmony_ci if reportStr: 13947db96d56Sopenharmony_ci print(reportStr) 13957db96d56Sopenharmony_ci self.assertTrue('SyntaxError' not in reportStr) 13967db96d56Sopenharmony_ci 13977db96d56Sopenharmony_ci def test_write_with_optimization(self): 13987db96d56Sopenharmony_ci import email 13997db96d56Sopenharmony_ci packagedir = os.path.dirname(email.__file__) 14007db96d56Sopenharmony_ci self.requiresWriteAccess(packagedir) 14017db96d56Sopenharmony_ci optlevel = 1 if __debug__ else 0 14027db96d56Sopenharmony_ci ext = '.pyc' 14037db96d56Sopenharmony_ci 14047db96d56Sopenharmony_ci with TemporaryFile() as t, \ 14057db96d56Sopenharmony_ci zipfile.PyZipFile(t, "w", optimize=optlevel) as zipfp: 14067db96d56Sopenharmony_ci zipfp.writepy(packagedir) 14077db96d56Sopenharmony_ci 14087db96d56Sopenharmony_ci names = zipfp.namelist() 14097db96d56Sopenharmony_ci self.assertIn('email/__init__' + ext, names) 14107db96d56Sopenharmony_ci self.assertIn('email/mime/text' + ext, names) 14117db96d56Sopenharmony_ci 14127db96d56Sopenharmony_ci def test_write_python_directory(self): 14137db96d56Sopenharmony_ci os.mkdir(TESTFN2) 14147db96d56Sopenharmony_ci try: 14157db96d56Sopenharmony_ci with open(os.path.join(TESTFN2, "mod1.py"), "w", encoding='utf-8') as fp: 14167db96d56Sopenharmony_ci fp.write("print(42)\n") 14177db96d56Sopenharmony_ci 14187db96d56Sopenharmony_ci with open(os.path.join(TESTFN2, "mod2.py"), "w", encoding='utf-8') as fp: 14197db96d56Sopenharmony_ci fp.write("print(42 * 42)\n") 14207db96d56Sopenharmony_ci 14217db96d56Sopenharmony_ci with open(os.path.join(TESTFN2, "mod2.txt"), "w", encoding='utf-8') as fp: 14227db96d56Sopenharmony_ci fp.write("bla bla bla\n") 14237db96d56Sopenharmony_ci 14247db96d56Sopenharmony_ci with TemporaryFile() as t, zipfile.PyZipFile(t, "w") as zipfp: 14257db96d56Sopenharmony_ci zipfp.writepy(TESTFN2) 14267db96d56Sopenharmony_ci 14277db96d56Sopenharmony_ci names = zipfp.namelist() 14287db96d56Sopenharmony_ci self.assertCompiledIn('mod1.py', names) 14297db96d56Sopenharmony_ci self.assertCompiledIn('mod2.py', names) 14307db96d56Sopenharmony_ci self.assertNotIn('mod2.txt', names) 14317db96d56Sopenharmony_ci 14327db96d56Sopenharmony_ci finally: 14337db96d56Sopenharmony_ci rmtree(TESTFN2) 14347db96d56Sopenharmony_ci 14357db96d56Sopenharmony_ci def test_write_python_directory_filtered(self): 14367db96d56Sopenharmony_ci os.mkdir(TESTFN2) 14377db96d56Sopenharmony_ci try: 14387db96d56Sopenharmony_ci with open(os.path.join(TESTFN2, "mod1.py"), "w", encoding='utf-8') as fp: 14397db96d56Sopenharmony_ci fp.write("print(42)\n") 14407db96d56Sopenharmony_ci 14417db96d56Sopenharmony_ci with open(os.path.join(TESTFN2, "mod2.py"), "w", encoding='utf-8') as fp: 14427db96d56Sopenharmony_ci fp.write("print(42 * 42)\n") 14437db96d56Sopenharmony_ci 14447db96d56Sopenharmony_ci with TemporaryFile() as t, zipfile.PyZipFile(t, "w") as zipfp: 14457db96d56Sopenharmony_ci zipfp.writepy(TESTFN2, filterfunc=lambda fn: 14467db96d56Sopenharmony_ci not fn.endswith('mod2.py')) 14477db96d56Sopenharmony_ci 14487db96d56Sopenharmony_ci names = zipfp.namelist() 14497db96d56Sopenharmony_ci self.assertCompiledIn('mod1.py', names) 14507db96d56Sopenharmony_ci self.assertNotIn('mod2.py', names) 14517db96d56Sopenharmony_ci 14527db96d56Sopenharmony_ci finally: 14537db96d56Sopenharmony_ci rmtree(TESTFN2) 14547db96d56Sopenharmony_ci 14557db96d56Sopenharmony_ci def test_write_non_pyfile(self): 14567db96d56Sopenharmony_ci with TemporaryFile() as t, zipfile.PyZipFile(t, "w") as zipfp: 14577db96d56Sopenharmony_ci with open(TESTFN, 'w', encoding='utf-8') as f: 14587db96d56Sopenharmony_ci f.write('most definitely not a python file') 14597db96d56Sopenharmony_ci self.assertRaises(RuntimeError, zipfp.writepy, TESTFN) 14607db96d56Sopenharmony_ci unlink(TESTFN) 14617db96d56Sopenharmony_ci 14627db96d56Sopenharmony_ci def test_write_pyfile_bad_syntax(self): 14637db96d56Sopenharmony_ci os.mkdir(TESTFN2) 14647db96d56Sopenharmony_ci try: 14657db96d56Sopenharmony_ci with open(os.path.join(TESTFN2, "mod1.py"), "w", encoding='utf-8') as fp: 14667db96d56Sopenharmony_ci fp.write("Bad syntax in python file\n") 14677db96d56Sopenharmony_ci 14687db96d56Sopenharmony_ci with TemporaryFile() as t, zipfile.PyZipFile(t, "w") as zipfp: 14697db96d56Sopenharmony_ci # syntax errors are printed to stdout 14707db96d56Sopenharmony_ci with captured_stdout() as s: 14717db96d56Sopenharmony_ci zipfp.writepy(os.path.join(TESTFN2, "mod1.py")) 14727db96d56Sopenharmony_ci 14737db96d56Sopenharmony_ci self.assertIn("SyntaxError", s.getvalue()) 14747db96d56Sopenharmony_ci 14757db96d56Sopenharmony_ci # as it will not have compiled the python file, it will 14767db96d56Sopenharmony_ci # include the .py file not .pyc 14777db96d56Sopenharmony_ci names = zipfp.namelist() 14787db96d56Sopenharmony_ci self.assertIn('mod1.py', names) 14797db96d56Sopenharmony_ci self.assertNotIn('mod1.pyc', names) 14807db96d56Sopenharmony_ci 14817db96d56Sopenharmony_ci finally: 14827db96d56Sopenharmony_ci rmtree(TESTFN2) 14837db96d56Sopenharmony_ci 14847db96d56Sopenharmony_ci def test_write_pathlike(self): 14857db96d56Sopenharmony_ci os.mkdir(TESTFN2) 14867db96d56Sopenharmony_ci try: 14877db96d56Sopenharmony_ci with open(os.path.join(TESTFN2, "mod1.py"), "w", encoding='utf-8') as fp: 14887db96d56Sopenharmony_ci fp.write("print(42)\n") 14897db96d56Sopenharmony_ci 14907db96d56Sopenharmony_ci with TemporaryFile() as t, zipfile.PyZipFile(t, "w") as zipfp: 14917db96d56Sopenharmony_ci zipfp.writepy(pathlib.Path(TESTFN2) / "mod1.py") 14927db96d56Sopenharmony_ci names = zipfp.namelist() 14937db96d56Sopenharmony_ci self.assertCompiledIn('mod1.py', names) 14947db96d56Sopenharmony_ci finally: 14957db96d56Sopenharmony_ci rmtree(TESTFN2) 14967db96d56Sopenharmony_ci 14977db96d56Sopenharmony_ci 14987db96d56Sopenharmony_ciclass ExtractTests(unittest.TestCase): 14997db96d56Sopenharmony_ci 15007db96d56Sopenharmony_ci def make_test_file(self): 15017db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED) as zipfp: 15027db96d56Sopenharmony_ci for fpath, fdata in SMALL_TEST_DATA: 15037db96d56Sopenharmony_ci zipfp.writestr(fpath, fdata) 15047db96d56Sopenharmony_ci 15057db96d56Sopenharmony_ci def test_extract(self): 15067db96d56Sopenharmony_ci with temp_cwd(): 15077db96d56Sopenharmony_ci self.make_test_file() 15087db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "r") as zipfp: 15097db96d56Sopenharmony_ci for fpath, fdata in SMALL_TEST_DATA: 15107db96d56Sopenharmony_ci writtenfile = zipfp.extract(fpath) 15117db96d56Sopenharmony_ci 15127db96d56Sopenharmony_ci # make sure it was written to the right place 15137db96d56Sopenharmony_ci correctfile = os.path.join(os.getcwd(), fpath) 15147db96d56Sopenharmony_ci correctfile = os.path.normpath(correctfile) 15157db96d56Sopenharmony_ci 15167db96d56Sopenharmony_ci self.assertEqual(writtenfile, correctfile) 15177db96d56Sopenharmony_ci 15187db96d56Sopenharmony_ci # make sure correct data is in correct file 15197db96d56Sopenharmony_ci with open(writtenfile, "rb") as f: 15207db96d56Sopenharmony_ci self.assertEqual(fdata.encode(), f.read()) 15217db96d56Sopenharmony_ci 15227db96d56Sopenharmony_ci unlink(writtenfile) 15237db96d56Sopenharmony_ci 15247db96d56Sopenharmony_ci def _test_extract_with_target(self, target): 15257db96d56Sopenharmony_ci self.make_test_file() 15267db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "r") as zipfp: 15277db96d56Sopenharmony_ci for fpath, fdata in SMALL_TEST_DATA: 15287db96d56Sopenharmony_ci writtenfile = zipfp.extract(fpath, target) 15297db96d56Sopenharmony_ci 15307db96d56Sopenharmony_ci # make sure it was written to the right place 15317db96d56Sopenharmony_ci correctfile = os.path.join(target, fpath) 15327db96d56Sopenharmony_ci correctfile = os.path.normpath(correctfile) 15337db96d56Sopenharmony_ci self.assertTrue(os.path.samefile(writtenfile, correctfile), (writtenfile, target)) 15347db96d56Sopenharmony_ci 15357db96d56Sopenharmony_ci # make sure correct data is in correct file 15367db96d56Sopenharmony_ci with open(writtenfile, "rb") as f: 15377db96d56Sopenharmony_ci self.assertEqual(fdata.encode(), f.read()) 15387db96d56Sopenharmony_ci 15397db96d56Sopenharmony_ci unlink(writtenfile) 15407db96d56Sopenharmony_ci 15417db96d56Sopenharmony_ci unlink(TESTFN2) 15427db96d56Sopenharmony_ci 15437db96d56Sopenharmony_ci def test_extract_with_target(self): 15447db96d56Sopenharmony_ci with temp_dir() as extdir: 15457db96d56Sopenharmony_ci self._test_extract_with_target(extdir) 15467db96d56Sopenharmony_ci 15477db96d56Sopenharmony_ci def test_extract_with_target_pathlike(self): 15487db96d56Sopenharmony_ci with temp_dir() as extdir: 15497db96d56Sopenharmony_ci self._test_extract_with_target(pathlib.Path(extdir)) 15507db96d56Sopenharmony_ci 15517db96d56Sopenharmony_ci def test_extract_all(self): 15527db96d56Sopenharmony_ci with temp_cwd(): 15537db96d56Sopenharmony_ci self.make_test_file() 15547db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "r") as zipfp: 15557db96d56Sopenharmony_ci zipfp.extractall() 15567db96d56Sopenharmony_ci for fpath, fdata in SMALL_TEST_DATA: 15577db96d56Sopenharmony_ci outfile = os.path.join(os.getcwd(), fpath) 15587db96d56Sopenharmony_ci 15597db96d56Sopenharmony_ci with open(outfile, "rb") as f: 15607db96d56Sopenharmony_ci self.assertEqual(fdata.encode(), f.read()) 15617db96d56Sopenharmony_ci 15627db96d56Sopenharmony_ci unlink(outfile) 15637db96d56Sopenharmony_ci 15647db96d56Sopenharmony_ci def _test_extract_all_with_target(self, target): 15657db96d56Sopenharmony_ci self.make_test_file() 15667db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "r") as zipfp: 15677db96d56Sopenharmony_ci zipfp.extractall(target) 15687db96d56Sopenharmony_ci for fpath, fdata in SMALL_TEST_DATA: 15697db96d56Sopenharmony_ci outfile = os.path.join(target, fpath) 15707db96d56Sopenharmony_ci 15717db96d56Sopenharmony_ci with open(outfile, "rb") as f: 15727db96d56Sopenharmony_ci self.assertEqual(fdata.encode(), f.read()) 15737db96d56Sopenharmony_ci 15747db96d56Sopenharmony_ci unlink(outfile) 15757db96d56Sopenharmony_ci 15767db96d56Sopenharmony_ci unlink(TESTFN2) 15777db96d56Sopenharmony_ci 15787db96d56Sopenharmony_ci def test_extract_all_with_target(self): 15797db96d56Sopenharmony_ci with temp_dir() as extdir: 15807db96d56Sopenharmony_ci self._test_extract_all_with_target(extdir) 15817db96d56Sopenharmony_ci 15827db96d56Sopenharmony_ci def test_extract_all_with_target_pathlike(self): 15837db96d56Sopenharmony_ci with temp_dir() as extdir: 15847db96d56Sopenharmony_ci self._test_extract_all_with_target(pathlib.Path(extdir)) 15857db96d56Sopenharmony_ci 15867db96d56Sopenharmony_ci def check_file(self, filename, content): 15877db96d56Sopenharmony_ci self.assertTrue(os.path.isfile(filename)) 15887db96d56Sopenharmony_ci with open(filename, 'rb') as f: 15897db96d56Sopenharmony_ci self.assertEqual(f.read(), content) 15907db96d56Sopenharmony_ci 15917db96d56Sopenharmony_ci def test_sanitize_windows_name(self): 15927db96d56Sopenharmony_ci san = zipfile.ZipFile._sanitize_windows_name 15937db96d56Sopenharmony_ci # Passing pathsep in allows this test to work regardless of platform. 15947db96d56Sopenharmony_ci self.assertEqual(san(r',,?,C:,foo,bar/z', ','), r'_,C_,foo,bar/z') 15957db96d56Sopenharmony_ci self.assertEqual(san(r'a\b,c<d>e|f"g?h*i', ','), r'a\b,c_d_e_f_g_h_i') 15967db96d56Sopenharmony_ci self.assertEqual(san('../../foo../../ba..r', '/'), r'foo/ba..r') 15977db96d56Sopenharmony_ci 15987db96d56Sopenharmony_ci def test_extract_hackers_arcnames_common_cases(self): 15997db96d56Sopenharmony_ci common_hacknames = [ 16007db96d56Sopenharmony_ci ('../foo/bar', 'foo/bar'), 16017db96d56Sopenharmony_ci ('foo/../bar', 'foo/bar'), 16027db96d56Sopenharmony_ci ('foo/../../bar', 'foo/bar'), 16037db96d56Sopenharmony_ci ('foo/bar/..', 'foo/bar'), 16047db96d56Sopenharmony_ci ('./../foo/bar', 'foo/bar'), 16057db96d56Sopenharmony_ci ('/foo/bar', 'foo/bar'), 16067db96d56Sopenharmony_ci ('/foo/../bar', 'foo/bar'), 16077db96d56Sopenharmony_ci ('/foo/../../bar', 'foo/bar'), 16087db96d56Sopenharmony_ci ] 16097db96d56Sopenharmony_ci self._test_extract_hackers_arcnames(common_hacknames) 16107db96d56Sopenharmony_ci 16117db96d56Sopenharmony_ci @unittest.skipIf(os.path.sep != '\\', 'Requires \\ as path separator.') 16127db96d56Sopenharmony_ci def test_extract_hackers_arcnames_windows_only(self): 16137db96d56Sopenharmony_ci """Test combination of path fixing and windows name sanitization.""" 16147db96d56Sopenharmony_ci windows_hacknames = [ 16157db96d56Sopenharmony_ci (r'..\foo\bar', 'foo/bar'), 16167db96d56Sopenharmony_ci (r'..\/foo\/bar', 'foo/bar'), 16177db96d56Sopenharmony_ci (r'foo/\..\/bar', 'foo/bar'), 16187db96d56Sopenharmony_ci (r'foo\/../\bar', 'foo/bar'), 16197db96d56Sopenharmony_ci (r'C:foo/bar', 'foo/bar'), 16207db96d56Sopenharmony_ci (r'C:/foo/bar', 'foo/bar'), 16217db96d56Sopenharmony_ci (r'C://foo/bar', 'foo/bar'), 16227db96d56Sopenharmony_ci (r'C:\foo\bar', 'foo/bar'), 16237db96d56Sopenharmony_ci (r'//conky/mountpoint/foo/bar', 'foo/bar'), 16247db96d56Sopenharmony_ci (r'\\conky\mountpoint\foo\bar', 'foo/bar'), 16257db96d56Sopenharmony_ci (r'///conky/mountpoint/foo/bar', 'mountpoint/foo/bar'), 16267db96d56Sopenharmony_ci (r'\\\conky\mountpoint\foo\bar', 'mountpoint/foo/bar'), 16277db96d56Sopenharmony_ci (r'//conky//mountpoint/foo/bar', 'mountpoint/foo/bar'), 16287db96d56Sopenharmony_ci (r'\\conky\\mountpoint\foo\bar', 'mountpoint/foo/bar'), 16297db96d56Sopenharmony_ci (r'//?/C:/foo/bar', 'foo/bar'), 16307db96d56Sopenharmony_ci (r'\\?\C:\foo\bar', 'foo/bar'), 16317db96d56Sopenharmony_ci (r'C:/../C:/foo/bar', 'C_/foo/bar'), 16327db96d56Sopenharmony_ci (r'a:b\c<d>e|f"g?h*i', 'b/c_d_e_f_g_h_i'), 16337db96d56Sopenharmony_ci ('../../foo../../ba..r', 'foo/ba..r'), 16347db96d56Sopenharmony_ci ] 16357db96d56Sopenharmony_ci self._test_extract_hackers_arcnames(windows_hacknames) 16367db96d56Sopenharmony_ci 16377db96d56Sopenharmony_ci @unittest.skipIf(os.path.sep != '/', r'Requires / as path separator.') 16387db96d56Sopenharmony_ci def test_extract_hackers_arcnames_posix_only(self): 16397db96d56Sopenharmony_ci posix_hacknames = [ 16407db96d56Sopenharmony_ci ('//foo/bar', 'foo/bar'), 16417db96d56Sopenharmony_ci ('../../foo../../ba..r', 'foo../ba..r'), 16427db96d56Sopenharmony_ci (r'foo/..\bar', r'foo/..\bar'), 16437db96d56Sopenharmony_ci ] 16447db96d56Sopenharmony_ci self._test_extract_hackers_arcnames(posix_hacknames) 16457db96d56Sopenharmony_ci 16467db96d56Sopenharmony_ci def _test_extract_hackers_arcnames(self, hacknames): 16477db96d56Sopenharmony_ci for arcname, fixedname in hacknames: 16487db96d56Sopenharmony_ci content = b'foobar' + arcname.encode() 16497db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, 'w', zipfile.ZIP_STORED) as zipfp: 16507db96d56Sopenharmony_ci zinfo = zipfile.ZipInfo() 16517db96d56Sopenharmony_ci # preserve backslashes 16527db96d56Sopenharmony_ci zinfo.filename = arcname 16537db96d56Sopenharmony_ci zinfo.external_attr = 0o600 << 16 16547db96d56Sopenharmony_ci zipfp.writestr(zinfo, content) 16557db96d56Sopenharmony_ci 16567db96d56Sopenharmony_ci arcname = arcname.replace(os.sep, "/") 16577db96d56Sopenharmony_ci targetpath = os.path.join('target', 'subdir', 'subsub') 16587db96d56Sopenharmony_ci correctfile = os.path.join(targetpath, *fixedname.split('/')) 16597db96d56Sopenharmony_ci 16607db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, 'r') as zipfp: 16617db96d56Sopenharmony_ci writtenfile = zipfp.extract(arcname, targetpath) 16627db96d56Sopenharmony_ci self.assertEqual(writtenfile, correctfile, 16637db96d56Sopenharmony_ci msg='extract %r: %r != %r' % 16647db96d56Sopenharmony_ci (arcname, writtenfile, correctfile)) 16657db96d56Sopenharmony_ci self.check_file(correctfile, content) 16667db96d56Sopenharmony_ci rmtree('target') 16677db96d56Sopenharmony_ci 16687db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, 'r') as zipfp: 16697db96d56Sopenharmony_ci zipfp.extractall(targetpath) 16707db96d56Sopenharmony_ci self.check_file(correctfile, content) 16717db96d56Sopenharmony_ci rmtree('target') 16727db96d56Sopenharmony_ci 16737db96d56Sopenharmony_ci correctfile = os.path.join(os.getcwd(), *fixedname.split('/')) 16747db96d56Sopenharmony_ci 16757db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, 'r') as zipfp: 16767db96d56Sopenharmony_ci writtenfile = zipfp.extract(arcname) 16777db96d56Sopenharmony_ci self.assertEqual(writtenfile, correctfile, 16787db96d56Sopenharmony_ci msg="extract %r" % arcname) 16797db96d56Sopenharmony_ci self.check_file(correctfile, content) 16807db96d56Sopenharmony_ci rmtree(fixedname.split('/')[0]) 16817db96d56Sopenharmony_ci 16827db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, 'r') as zipfp: 16837db96d56Sopenharmony_ci zipfp.extractall() 16847db96d56Sopenharmony_ci self.check_file(correctfile, content) 16857db96d56Sopenharmony_ci rmtree(fixedname.split('/')[0]) 16867db96d56Sopenharmony_ci 16877db96d56Sopenharmony_ci unlink(TESTFN2) 16887db96d56Sopenharmony_ci 16897db96d56Sopenharmony_ci 16907db96d56Sopenharmony_ciclass OtherTests(unittest.TestCase): 16917db96d56Sopenharmony_ci def test_open_via_zip_info(self): 16927db96d56Sopenharmony_ci # Create the ZIP archive 16937db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED) as zipfp: 16947db96d56Sopenharmony_ci zipfp.writestr("name", "foo") 16957db96d56Sopenharmony_ci with self.assertWarns(UserWarning): 16967db96d56Sopenharmony_ci zipfp.writestr("name", "bar") 16977db96d56Sopenharmony_ci self.assertEqual(zipfp.namelist(), ["name"] * 2) 16987db96d56Sopenharmony_ci 16997db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "r") as zipfp: 17007db96d56Sopenharmony_ci infos = zipfp.infolist() 17017db96d56Sopenharmony_ci data = b"" 17027db96d56Sopenharmony_ci for info in infos: 17037db96d56Sopenharmony_ci with zipfp.open(info) as zipopen: 17047db96d56Sopenharmony_ci data += zipopen.read() 17057db96d56Sopenharmony_ci self.assertIn(data, {b"foobar", b"barfoo"}) 17067db96d56Sopenharmony_ci data = b"" 17077db96d56Sopenharmony_ci for info in infos: 17087db96d56Sopenharmony_ci data += zipfp.read(info) 17097db96d56Sopenharmony_ci self.assertIn(data, {b"foobar", b"barfoo"}) 17107db96d56Sopenharmony_ci 17117db96d56Sopenharmony_ci def test_writestr_extended_local_header_issue1202(self): 17127db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, 'w') as orig_zip: 17137db96d56Sopenharmony_ci for data in 'abcdefghijklmnop': 17147db96d56Sopenharmony_ci zinfo = zipfile.ZipInfo(data) 17157db96d56Sopenharmony_ci zinfo.flag_bits |= zipfile._MASK_USE_DATA_DESCRIPTOR # Include an extended local header. 17167db96d56Sopenharmony_ci orig_zip.writestr(zinfo, data) 17177db96d56Sopenharmony_ci 17187db96d56Sopenharmony_ci def test_close(self): 17197db96d56Sopenharmony_ci """Check that the zipfile is closed after the 'with' block.""" 17207db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "w") as zipfp: 17217db96d56Sopenharmony_ci for fpath, fdata in SMALL_TEST_DATA: 17227db96d56Sopenharmony_ci zipfp.writestr(fpath, fdata) 17237db96d56Sopenharmony_ci self.assertIsNotNone(zipfp.fp, 'zipfp is not open') 17247db96d56Sopenharmony_ci self.assertIsNone(zipfp.fp, 'zipfp is not closed') 17257db96d56Sopenharmony_ci 17267db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "r") as zipfp: 17277db96d56Sopenharmony_ci self.assertIsNotNone(zipfp.fp, 'zipfp is not open') 17287db96d56Sopenharmony_ci self.assertIsNone(zipfp.fp, 'zipfp is not closed') 17297db96d56Sopenharmony_ci 17307db96d56Sopenharmony_ci def test_close_on_exception(self): 17317db96d56Sopenharmony_ci """Check that the zipfile is closed if an exception is raised in the 17327db96d56Sopenharmony_ci 'with' block.""" 17337db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "w") as zipfp: 17347db96d56Sopenharmony_ci for fpath, fdata in SMALL_TEST_DATA: 17357db96d56Sopenharmony_ci zipfp.writestr(fpath, fdata) 17367db96d56Sopenharmony_ci 17377db96d56Sopenharmony_ci try: 17387db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "r") as zipfp2: 17397db96d56Sopenharmony_ci raise zipfile.BadZipFile() 17407db96d56Sopenharmony_ci except zipfile.BadZipFile: 17417db96d56Sopenharmony_ci self.assertIsNone(zipfp2.fp, 'zipfp is not closed') 17427db96d56Sopenharmony_ci 17437db96d56Sopenharmony_ci def test_unsupported_version(self): 17447db96d56Sopenharmony_ci # File has an extract_version of 120 17457db96d56Sopenharmony_ci data = (b'PK\x03\x04x\x00\x00\x00\x00\x00!p\xa1@\x00\x00\x00\x00\x00\x00' 17467db96d56Sopenharmony_ci b'\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00xPK\x01\x02x\x03x\x00\x00\x00\x00' 17477db96d56Sopenharmony_ci b'\x00!p\xa1@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00' 17487db96d56Sopenharmony_ci b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x01\x00\x00\x00\x00xPK\x05\x06' 17497db96d56Sopenharmony_ci b'\x00\x00\x00\x00\x01\x00\x01\x00/\x00\x00\x00\x1f\x00\x00\x00\x00\x00') 17507db96d56Sopenharmony_ci 17517db96d56Sopenharmony_ci self.assertRaises(NotImplementedError, zipfile.ZipFile, 17527db96d56Sopenharmony_ci io.BytesIO(data), 'r') 17537db96d56Sopenharmony_ci 17547db96d56Sopenharmony_ci @requires_zlib() 17557db96d56Sopenharmony_ci def test_read_unicode_filenames(self): 17567db96d56Sopenharmony_ci # bug #10801 17577db96d56Sopenharmony_ci fname = findfile('zip_cp437_header.zip') 17587db96d56Sopenharmony_ci with zipfile.ZipFile(fname) as zipfp: 17597db96d56Sopenharmony_ci for name in zipfp.namelist(): 17607db96d56Sopenharmony_ci zipfp.open(name).close() 17617db96d56Sopenharmony_ci 17627db96d56Sopenharmony_ci def test_write_unicode_filenames(self): 17637db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, "w") as zf: 17647db96d56Sopenharmony_ci zf.writestr("foo.txt", "Test for unicode filename") 17657db96d56Sopenharmony_ci zf.writestr("\xf6.txt", "Test for unicode filename") 17667db96d56Sopenharmony_ci self.assertIsInstance(zf.infolist()[0].filename, str) 17677db96d56Sopenharmony_ci 17687db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, "r") as zf: 17697db96d56Sopenharmony_ci self.assertEqual(zf.filelist[0].filename, "foo.txt") 17707db96d56Sopenharmony_ci self.assertEqual(zf.filelist[1].filename, "\xf6.txt") 17717db96d56Sopenharmony_ci 17727db96d56Sopenharmony_ci def test_read_after_write_unicode_filenames(self): 17737db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, 'w') as zipfp: 17747db96d56Sopenharmony_ci zipfp.writestr('приклад', b'sample') 17757db96d56Sopenharmony_ci self.assertEqual(zipfp.read('приклад'), b'sample') 17767db96d56Sopenharmony_ci 17777db96d56Sopenharmony_ci def test_exclusive_create_zip_file(self): 17787db96d56Sopenharmony_ci """Test exclusive creating a new zipfile.""" 17797db96d56Sopenharmony_ci unlink(TESTFN2) 17807db96d56Sopenharmony_ci filename = 'testfile.txt' 17817db96d56Sopenharmony_ci content = b'hello, world. this is some content.' 17827db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "x", zipfile.ZIP_STORED) as zipfp: 17837db96d56Sopenharmony_ci zipfp.writestr(filename, content) 17847db96d56Sopenharmony_ci with self.assertRaises(FileExistsError): 17857db96d56Sopenharmony_ci zipfile.ZipFile(TESTFN2, "x", zipfile.ZIP_STORED) 17867db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, "r") as zipfp: 17877db96d56Sopenharmony_ci self.assertEqual(zipfp.namelist(), [filename]) 17887db96d56Sopenharmony_ci self.assertEqual(zipfp.read(filename), content) 17897db96d56Sopenharmony_ci 17907db96d56Sopenharmony_ci def test_create_non_existent_file_for_append(self): 17917db96d56Sopenharmony_ci if os.path.exists(TESTFN): 17927db96d56Sopenharmony_ci os.unlink(TESTFN) 17937db96d56Sopenharmony_ci 17947db96d56Sopenharmony_ci filename = 'testfile.txt' 17957db96d56Sopenharmony_ci content = b'hello, world. this is some content.' 17967db96d56Sopenharmony_ci 17977db96d56Sopenharmony_ci try: 17987db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, 'a') as zf: 17997db96d56Sopenharmony_ci zf.writestr(filename, content) 18007db96d56Sopenharmony_ci except OSError: 18017db96d56Sopenharmony_ci self.fail('Could not append data to a non-existent zip file.') 18027db96d56Sopenharmony_ci 18037db96d56Sopenharmony_ci self.assertTrue(os.path.exists(TESTFN)) 18047db96d56Sopenharmony_ci 18057db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, 'r') as zf: 18067db96d56Sopenharmony_ci self.assertEqual(zf.read(filename), content) 18077db96d56Sopenharmony_ci 18087db96d56Sopenharmony_ci def test_close_erroneous_file(self): 18097db96d56Sopenharmony_ci # This test checks that the ZipFile constructor closes the file object 18107db96d56Sopenharmony_ci # it opens if there's an error in the file. If it doesn't, the 18117db96d56Sopenharmony_ci # traceback holds a reference to the ZipFile object and, indirectly, 18127db96d56Sopenharmony_ci # the file object. 18137db96d56Sopenharmony_ci # On Windows, this causes the os.unlink() call to fail because the 18147db96d56Sopenharmony_ci # underlying file is still open. This is SF bug #412214. 18157db96d56Sopenharmony_ci # 18167db96d56Sopenharmony_ci with open(TESTFN, "w", encoding="utf-8") as fp: 18177db96d56Sopenharmony_ci fp.write("this is not a legal zip file\n") 18187db96d56Sopenharmony_ci try: 18197db96d56Sopenharmony_ci zf = zipfile.ZipFile(TESTFN) 18207db96d56Sopenharmony_ci except zipfile.BadZipFile: 18217db96d56Sopenharmony_ci pass 18227db96d56Sopenharmony_ci 18237db96d56Sopenharmony_ci def test_is_zip_erroneous_file(self): 18247db96d56Sopenharmony_ci """Check that is_zipfile() correctly identifies non-zip files.""" 18257db96d56Sopenharmony_ci # - passing a filename 18267db96d56Sopenharmony_ci with open(TESTFN, "w", encoding='utf-8') as fp: 18277db96d56Sopenharmony_ci fp.write("this is not a legal zip file\n") 18287db96d56Sopenharmony_ci self.assertFalse(zipfile.is_zipfile(TESTFN)) 18297db96d56Sopenharmony_ci # - passing a path-like object 18307db96d56Sopenharmony_ci self.assertFalse(zipfile.is_zipfile(pathlib.Path(TESTFN))) 18317db96d56Sopenharmony_ci # - passing a file object 18327db96d56Sopenharmony_ci with open(TESTFN, "rb") as fp: 18337db96d56Sopenharmony_ci self.assertFalse(zipfile.is_zipfile(fp)) 18347db96d56Sopenharmony_ci # - passing a file-like object 18357db96d56Sopenharmony_ci fp = io.BytesIO() 18367db96d56Sopenharmony_ci fp.write(b"this is not a legal zip file\n") 18377db96d56Sopenharmony_ci self.assertFalse(zipfile.is_zipfile(fp)) 18387db96d56Sopenharmony_ci fp.seek(0, 0) 18397db96d56Sopenharmony_ci self.assertFalse(zipfile.is_zipfile(fp)) 18407db96d56Sopenharmony_ci 18417db96d56Sopenharmony_ci def test_damaged_zipfile(self): 18427db96d56Sopenharmony_ci """Check that zipfiles with missing bytes at the end raise BadZipFile.""" 18437db96d56Sopenharmony_ci # - Create a valid zip file 18447db96d56Sopenharmony_ci fp = io.BytesIO() 18457db96d56Sopenharmony_ci with zipfile.ZipFile(fp, mode="w") as zipf: 18467db96d56Sopenharmony_ci zipf.writestr("foo.txt", b"O, for a Muse of Fire!") 18477db96d56Sopenharmony_ci zipfiledata = fp.getvalue() 18487db96d56Sopenharmony_ci 18497db96d56Sopenharmony_ci # - Now create copies of it missing the last N bytes and make sure 18507db96d56Sopenharmony_ci # a BadZipFile exception is raised when we try to open it 18517db96d56Sopenharmony_ci for N in range(len(zipfiledata)): 18527db96d56Sopenharmony_ci fp = io.BytesIO(zipfiledata[:N]) 18537db96d56Sopenharmony_ci self.assertRaises(zipfile.BadZipFile, zipfile.ZipFile, fp) 18547db96d56Sopenharmony_ci 18557db96d56Sopenharmony_ci def test_is_zip_valid_file(self): 18567db96d56Sopenharmony_ci """Check that is_zipfile() correctly identifies zip files.""" 18577db96d56Sopenharmony_ci # - passing a filename 18587db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, mode="w") as zipf: 18597db96d56Sopenharmony_ci zipf.writestr("foo.txt", b"O, for a Muse of Fire!") 18607db96d56Sopenharmony_ci 18617db96d56Sopenharmony_ci self.assertTrue(zipfile.is_zipfile(TESTFN)) 18627db96d56Sopenharmony_ci # - passing a file object 18637db96d56Sopenharmony_ci with open(TESTFN, "rb") as fp: 18647db96d56Sopenharmony_ci self.assertTrue(zipfile.is_zipfile(fp)) 18657db96d56Sopenharmony_ci fp.seek(0, 0) 18667db96d56Sopenharmony_ci zip_contents = fp.read() 18677db96d56Sopenharmony_ci # - passing a file-like object 18687db96d56Sopenharmony_ci fp = io.BytesIO() 18697db96d56Sopenharmony_ci fp.write(zip_contents) 18707db96d56Sopenharmony_ci self.assertTrue(zipfile.is_zipfile(fp)) 18717db96d56Sopenharmony_ci fp.seek(0, 0) 18727db96d56Sopenharmony_ci self.assertTrue(zipfile.is_zipfile(fp)) 18737db96d56Sopenharmony_ci 18747db96d56Sopenharmony_ci def test_non_existent_file_raises_OSError(self): 18757db96d56Sopenharmony_ci # make sure we don't raise an AttributeError when a partially-constructed 18767db96d56Sopenharmony_ci # ZipFile instance is finalized; this tests for regression on SF tracker 18777db96d56Sopenharmony_ci # bug #403871. 18787db96d56Sopenharmony_ci 18797db96d56Sopenharmony_ci # The bug we're testing for caused an AttributeError to be raised 18807db96d56Sopenharmony_ci # when a ZipFile instance was created for a file that did not 18817db96d56Sopenharmony_ci # exist; the .fp member was not initialized but was needed by the 18827db96d56Sopenharmony_ci # __del__() method. Since the AttributeError is in the __del__(), 18837db96d56Sopenharmony_ci # it is ignored, but the user should be sufficiently annoyed by 18847db96d56Sopenharmony_ci # the message on the output that regression will be noticed 18857db96d56Sopenharmony_ci # quickly. 18867db96d56Sopenharmony_ci self.assertRaises(OSError, zipfile.ZipFile, TESTFN) 18877db96d56Sopenharmony_ci 18887db96d56Sopenharmony_ci def test_empty_file_raises_BadZipFile(self): 18897db96d56Sopenharmony_ci f = open(TESTFN, 'w', encoding='utf-8') 18907db96d56Sopenharmony_ci f.close() 18917db96d56Sopenharmony_ci self.assertRaises(zipfile.BadZipFile, zipfile.ZipFile, TESTFN) 18927db96d56Sopenharmony_ci 18937db96d56Sopenharmony_ci with open(TESTFN, 'w', encoding='utf-8') as fp: 18947db96d56Sopenharmony_ci fp.write("short file") 18957db96d56Sopenharmony_ci self.assertRaises(zipfile.BadZipFile, zipfile.ZipFile, TESTFN) 18967db96d56Sopenharmony_ci 18977db96d56Sopenharmony_ci def test_negative_central_directory_offset_raises_BadZipFile(self): 18987db96d56Sopenharmony_ci # Zip file containing an empty EOCD record 18997db96d56Sopenharmony_ci buffer = bytearray(b'PK\x05\x06' + b'\0'*18) 19007db96d56Sopenharmony_ci 19017db96d56Sopenharmony_ci # Set the size of the central directory bytes to become 1, 19027db96d56Sopenharmony_ci # causing the central directory offset to become negative 19037db96d56Sopenharmony_ci for dirsize in 1, 2**32-1: 19047db96d56Sopenharmony_ci buffer[12:16] = struct.pack('<L', dirsize) 19057db96d56Sopenharmony_ci f = io.BytesIO(buffer) 19067db96d56Sopenharmony_ci self.assertRaises(zipfile.BadZipFile, zipfile.ZipFile, f) 19077db96d56Sopenharmony_ci 19087db96d56Sopenharmony_ci def test_closed_zip_raises_ValueError(self): 19097db96d56Sopenharmony_ci """Verify that testzip() doesn't swallow inappropriate exceptions.""" 19107db96d56Sopenharmony_ci data = io.BytesIO() 19117db96d56Sopenharmony_ci with zipfile.ZipFile(data, mode="w") as zipf: 19127db96d56Sopenharmony_ci zipf.writestr("foo.txt", "O, for a Muse of Fire!") 19137db96d56Sopenharmony_ci 19147db96d56Sopenharmony_ci # This is correct; calling .read on a closed ZipFile should raise 19157db96d56Sopenharmony_ci # a ValueError, and so should calling .testzip. An earlier 19167db96d56Sopenharmony_ci # version of .testzip would swallow this exception (and any other) 19177db96d56Sopenharmony_ci # and report that the first file in the archive was corrupt. 19187db96d56Sopenharmony_ci self.assertRaises(ValueError, zipf.read, "foo.txt") 19197db96d56Sopenharmony_ci self.assertRaises(ValueError, zipf.open, "foo.txt") 19207db96d56Sopenharmony_ci self.assertRaises(ValueError, zipf.testzip) 19217db96d56Sopenharmony_ci self.assertRaises(ValueError, zipf.writestr, "bogus.txt", "bogus") 19227db96d56Sopenharmony_ci with open(TESTFN, 'w', encoding='utf-8') as f: 19237db96d56Sopenharmony_ci f.write('zipfile test data') 19247db96d56Sopenharmony_ci self.assertRaises(ValueError, zipf.write, TESTFN) 19257db96d56Sopenharmony_ci 19267db96d56Sopenharmony_ci def test_bad_constructor_mode(self): 19277db96d56Sopenharmony_ci """Check that bad modes passed to ZipFile constructor are caught.""" 19287db96d56Sopenharmony_ci self.assertRaises(ValueError, zipfile.ZipFile, TESTFN, "q") 19297db96d56Sopenharmony_ci 19307db96d56Sopenharmony_ci def test_bad_open_mode(self): 19317db96d56Sopenharmony_ci """Check that bad modes passed to ZipFile.open are caught.""" 19327db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, mode="w") as zipf: 19337db96d56Sopenharmony_ci zipf.writestr("foo.txt", "O, for a Muse of Fire!") 19347db96d56Sopenharmony_ci 19357db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, mode="r") as zipf: 19367db96d56Sopenharmony_ci # read the data to make sure the file is there 19377db96d56Sopenharmony_ci zipf.read("foo.txt") 19387db96d56Sopenharmony_ci self.assertRaises(ValueError, zipf.open, "foo.txt", "q") 19397db96d56Sopenharmony_ci # universal newlines support is removed 19407db96d56Sopenharmony_ci self.assertRaises(ValueError, zipf.open, "foo.txt", "U") 19417db96d56Sopenharmony_ci self.assertRaises(ValueError, zipf.open, "foo.txt", "rU") 19427db96d56Sopenharmony_ci 19437db96d56Sopenharmony_ci def test_read0(self): 19447db96d56Sopenharmony_ci """Check that calling read(0) on a ZipExtFile object returns an empty 19457db96d56Sopenharmony_ci string and doesn't advance file pointer.""" 19467db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, mode="w") as zipf: 19477db96d56Sopenharmony_ci zipf.writestr("foo.txt", "O, for a Muse of Fire!") 19487db96d56Sopenharmony_ci # read the data to make sure the file is there 19497db96d56Sopenharmony_ci with zipf.open("foo.txt") as f: 19507db96d56Sopenharmony_ci for i in range(FIXEDTEST_SIZE): 19517db96d56Sopenharmony_ci self.assertEqual(f.read(0), b'') 19527db96d56Sopenharmony_ci 19537db96d56Sopenharmony_ci self.assertEqual(f.read(), b"O, for a Muse of Fire!") 19547db96d56Sopenharmony_ci 19557db96d56Sopenharmony_ci def test_open_non_existent_item(self): 19567db96d56Sopenharmony_ci """Check that attempting to call open() for an item that doesn't 19577db96d56Sopenharmony_ci exist in the archive raises a RuntimeError.""" 19587db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, mode="w") as zipf: 19597db96d56Sopenharmony_ci self.assertRaises(KeyError, zipf.open, "foo.txt", "r") 19607db96d56Sopenharmony_ci 19617db96d56Sopenharmony_ci def test_bad_compression_mode(self): 19627db96d56Sopenharmony_ci """Check that bad compression methods passed to ZipFile.open are 19637db96d56Sopenharmony_ci caught.""" 19647db96d56Sopenharmony_ci self.assertRaises(NotImplementedError, zipfile.ZipFile, TESTFN, "w", -1) 19657db96d56Sopenharmony_ci 19667db96d56Sopenharmony_ci def test_unsupported_compression(self): 19677db96d56Sopenharmony_ci # data is declared as shrunk, but actually deflated 19687db96d56Sopenharmony_ci data = (b'PK\x03\x04.\x00\x00\x00\x01\x00\xe4C\xa1@\x00\x00\x00' 19697db96d56Sopenharmony_ci b'\x00\x02\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00x\x03\x00PK\x01' 19707db96d56Sopenharmony_ci b'\x02.\x03.\x00\x00\x00\x01\x00\xe4C\xa1@\x00\x00\x00\x00\x02\x00\x00' 19717db96d56Sopenharmony_ci b'\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' 19727db96d56Sopenharmony_ci b'\x80\x01\x00\x00\x00\x00xPK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x00' 19737db96d56Sopenharmony_ci b'/\x00\x00\x00!\x00\x00\x00\x00\x00') 19747db96d56Sopenharmony_ci with zipfile.ZipFile(io.BytesIO(data), 'r') as zipf: 19757db96d56Sopenharmony_ci self.assertRaises(NotImplementedError, zipf.open, 'x') 19767db96d56Sopenharmony_ci 19777db96d56Sopenharmony_ci def test_null_byte_in_filename(self): 19787db96d56Sopenharmony_ci """Check that a filename containing a null byte is properly 19797db96d56Sopenharmony_ci terminated.""" 19807db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, mode="w") as zipf: 19817db96d56Sopenharmony_ci zipf.writestr("foo.txt\x00qqq", b"O, for a Muse of Fire!") 19827db96d56Sopenharmony_ci self.assertEqual(zipf.namelist(), ['foo.txt']) 19837db96d56Sopenharmony_ci 19847db96d56Sopenharmony_ci def test_struct_sizes(self): 19857db96d56Sopenharmony_ci """Check that ZIP internal structure sizes are calculated correctly.""" 19867db96d56Sopenharmony_ci self.assertEqual(zipfile.sizeEndCentDir, 22) 19877db96d56Sopenharmony_ci self.assertEqual(zipfile.sizeCentralDir, 46) 19887db96d56Sopenharmony_ci self.assertEqual(zipfile.sizeEndCentDir64, 56) 19897db96d56Sopenharmony_ci self.assertEqual(zipfile.sizeEndCentDir64Locator, 20) 19907db96d56Sopenharmony_ci 19917db96d56Sopenharmony_ci def test_comments(self): 19927db96d56Sopenharmony_ci """Check that comments on the archive are handled properly.""" 19937db96d56Sopenharmony_ci 19947db96d56Sopenharmony_ci # check default comment is empty 19957db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, mode="w") as zipf: 19967db96d56Sopenharmony_ci self.assertEqual(zipf.comment, b'') 19977db96d56Sopenharmony_ci zipf.writestr("foo.txt", "O, for a Muse of Fire!") 19987db96d56Sopenharmony_ci 19997db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, mode="r") as zipfr: 20007db96d56Sopenharmony_ci self.assertEqual(zipfr.comment, b'') 20017db96d56Sopenharmony_ci 20027db96d56Sopenharmony_ci # check a simple short comment 20037db96d56Sopenharmony_ci comment = b'Bravely taking to his feet, he beat a very brave retreat.' 20047db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, mode="w") as zipf: 20057db96d56Sopenharmony_ci zipf.comment = comment 20067db96d56Sopenharmony_ci zipf.writestr("foo.txt", "O, for a Muse of Fire!") 20077db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, mode="r") as zipfr: 20087db96d56Sopenharmony_ci self.assertEqual(zipf.comment, comment) 20097db96d56Sopenharmony_ci 20107db96d56Sopenharmony_ci # check a comment of max length 20117db96d56Sopenharmony_ci comment2 = ''.join(['%d' % (i**3 % 10) for i in range((1 << 16)-1)]) 20127db96d56Sopenharmony_ci comment2 = comment2.encode("ascii") 20137db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, mode="w") as zipf: 20147db96d56Sopenharmony_ci zipf.comment = comment2 20157db96d56Sopenharmony_ci zipf.writestr("foo.txt", "O, for a Muse of Fire!") 20167db96d56Sopenharmony_ci 20177db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, mode="r") as zipfr: 20187db96d56Sopenharmony_ci self.assertEqual(zipfr.comment, comment2) 20197db96d56Sopenharmony_ci 20207db96d56Sopenharmony_ci # check a comment that is too long is truncated 20217db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, mode="w") as zipf: 20227db96d56Sopenharmony_ci with self.assertWarns(UserWarning): 20237db96d56Sopenharmony_ci zipf.comment = comment2 + b'oops' 20247db96d56Sopenharmony_ci zipf.writestr("foo.txt", "O, for a Muse of Fire!") 20257db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, mode="r") as zipfr: 20267db96d56Sopenharmony_ci self.assertEqual(zipfr.comment, comment2) 20277db96d56Sopenharmony_ci 20287db96d56Sopenharmony_ci # check that comments are correctly modified in append mode 20297db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN,mode="w") as zipf: 20307db96d56Sopenharmony_ci zipf.comment = b"original comment" 20317db96d56Sopenharmony_ci zipf.writestr("foo.txt", "O, for a Muse of Fire!") 20327db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN,mode="a") as zipf: 20337db96d56Sopenharmony_ci zipf.comment = b"an updated comment" 20347db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN,mode="r") as zipf: 20357db96d56Sopenharmony_ci self.assertEqual(zipf.comment, b"an updated comment") 20367db96d56Sopenharmony_ci 20377db96d56Sopenharmony_ci # check that comments are correctly shortened in append mode 20387db96d56Sopenharmony_ci # and the file is indeed truncated 20397db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN,mode="w") as zipf: 20407db96d56Sopenharmony_ci zipf.comment = b"original comment that's longer" 20417db96d56Sopenharmony_ci zipf.writestr("foo.txt", "O, for a Muse of Fire!") 20427db96d56Sopenharmony_ci original_zip_size = os.path.getsize(TESTFN) 20437db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN,mode="a") as zipf: 20447db96d56Sopenharmony_ci zipf.comment = b"shorter comment" 20457db96d56Sopenharmony_ci self.assertTrue(original_zip_size > os.path.getsize(TESTFN)) 20467db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN,mode="r") as zipf: 20477db96d56Sopenharmony_ci self.assertEqual(zipf.comment, b"shorter comment") 20487db96d56Sopenharmony_ci 20497db96d56Sopenharmony_ci def test_unicode_comment(self): 20507db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, "w", zipfile.ZIP_STORED) as zipf: 20517db96d56Sopenharmony_ci zipf.writestr("foo.txt", "O, for a Muse of Fire!") 20527db96d56Sopenharmony_ci with self.assertRaises(TypeError): 20537db96d56Sopenharmony_ci zipf.comment = "this is an error" 20547db96d56Sopenharmony_ci 20557db96d56Sopenharmony_ci def test_change_comment_in_empty_archive(self): 20567db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, "a", zipfile.ZIP_STORED) as zipf: 20577db96d56Sopenharmony_ci self.assertFalse(zipf.filelist) 20587db96d56Sopenharmony_ci zipf.comment = b"this is a comment" 20597db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, "r") as zipf: 20607db96d56Sopenharmony_ci self.assertEqual(zipf.comment, b"this is a comment") 20617db96d56Sopenharmony_ci 20627db96d56Sopenharmony_ci def test_change_comment_in_nonempty_archive(self): 20637db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, "w", zipfile.ZIP_STORED) as zipf: 20647db96d56Sopenharmony_ci zipf.writestr("foo.txt", "O, for a Muse of Fire!") 20657db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, "a", zipfile.ZIP_STORED) as zipf: 20667db96d56Sopenharmony_ci self.assertTrue(zipf.filelist) 20677db96d56Sopenharmony_ci zipf.comment = b"this is a comment" 20687db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, "r") as zipf: 20697db96d56Sopenharmony_ci self.assertEqual(zipf.comment, b"this is a comment") 20707db96d56Sopenharmony_ci 20717db96d56Sopenharmony_ci def test_empty_zipfile(self): 20727db96d56Sopenharmony_ci # Check that creating a file in 'w' or 'a' mode and closing without 20737db96d56Sopenharmony_ci # adding any files to the archives creates a valid empty ZIP file 20747db96d56Sopenharmony_ci zipf = zipfile.ZipFile(TESTFN, mode="w") 20757db96d56Sopenharmony_ci zipf.close() 20767db96d56Sopenharmony_ci try: 20777db96d56Sopenharmony_ci zipf = zipfile.ZipFile(TESTFN, mode="r") 20787db96d56Sopenharmony_ci except zipfile.BadZipFile: 20797db96d56Sopenharmony_ci self.fail("Unable to create empty ZIP file in 'w' mode") 20807db96d56Sopenharmony_ci 20817db96d56Sopenharmony_ci zipf = zipfile.ZipFile(TESTFN, mode="a") 20827db96d56Sopenharmony_ci zipf.close() 20837db96d56Sopenharmony_ci try: 20847db96d56Sopenharmony_ci zipf = zipfile.ZipFile(TESTFN, mode="r") 20857db96d56Sopenharmony_ci except: 20867db96d56Sopenharmony_ci self.fail("Unable to create empty ZIP file in 'a' mode") 20877db96d56Sopenharmony_ci 20887db96d56Sopenharmony_ci def test_open_empty_file(self): 20897db96d56Sopenharmony_ci # Issue 1710703: Check that opening a file with less than 22 bytes 20907db96d56Sopenharmony_ci # raises a BadZipFile exception (rather than the previously unhelpful 20917db96d56Sopenharmony_ci # OSError) 20927db96d56Sopenharmony_ci f = open(TESTFN, 'w', encoding='utf-8') 20937db96d56Sopenharmony_ci f.close() 20947db96d56Sopenharmony_ci self.assertRaises(zipfile.BadZipFile, zipfile.ZipFile, TESTFN, 'r') 20957db96d56Sopenharmony_ci 20967db96d56Sopenharmony_ci def test_create_zipinfo_before_1980(self): 20977db96d56Sopenharmony_ci self.assertRaises(ValueError, 20987db96d56Sopenharmony_ci zipfile.ZipInfo, 'seventies', (1979, 1, 1, 0, 0, 0)) 20997db96d56Sopenharmony_ci 21007db96d56Sopenharmony_ci def test_create_empty_zipinfo_repr(self): 21017db96d56Sopenharmony_ci """Before bpo-26185, repr() on empty ZipInfo object was failing.""" 21027db96d56Sopenharmony_ci zi = zipfile.ZipInfo(filename="empty") 21037db96d56Sopenharmony_ci self.assertEqual(repr(zi), "<ZipInfo filename='empty' file_size=0>") 21047db96d56Sopenharmony_ci 21057db96d56Sopenharmony_ci def test_create_empty_zipinfo_default_attributes(self): 21067db96d56Sopenharmony_ci """Ensure all required attributes are set.""" 21077db96d56Sopenharmony_ci zi = zipfile.ZipInfo() 21087db96d56Sopenharmony_ci self.assertEqual(zi.orig_filename, "NoName") 21097db96d56Sopenharmony_ci self.assertEqual(zi.filename, "NoName") 21107db96d56Sopenharmony_ci self.assertEqual(zi.date_time, (1980, 1, 1, 0, 0, 0)) 21117db96d56Sopenharmony_ci self.assertEqual(zi.compress_type, zipfile.ZIP_STORED) 21127db96d56Sopenharmony_ci self.assertEqual(zi.comment, b"") 21137db96d56Sopenharmony_ci self.assertEqual(zi.extra, b"") 21147db96d56Sopenharmony_ci self.assertIn(zi.create_system, (0, 3)) 21157db96d56Sopenharmony_ci self.assertEqual(zi.create_version, zipfile.DEFAULT_VERSION) 21167db96d56Sopenharmony_ci self.assertEqual(zi.extract_version, zipfile.DEFAULT_VERSION) 21177db96d56Sopenharmony_ci self.assertEqual(zi.reserved, 0) 21187db96d56Sopenharmony_ci self.assertEqual(zi.flag_bits, 0) 21197db96d56Sopenharmony_ci self.assertEqual(zi.volume, 0) 21207db96d56Sopenharmony_ci self.assertEqual(zi.internal_attr, 0) 21217db96d56Sopenharmony_ci self.assertEqual(zi.external_attr, 0) 21227db96d56Sopenharmony_ci 21237db96d56Sopenharmony_ci # Before bpo-26185, both were missing 21247db96d56Sopenharmony_ci self.assertEqual(zi.file_size, 0) 21257db96d56Sopenharmony_ci self.assertEqual(zi.compress_size, 0) 21267db96d56Sopenharmony_ci 21277db96d56Sopenharmony_ci def test_zipfile_with_short_extra_field(self): 21287db96d56Sopenharmony_ci """If an extra field in the header is less than 4 bytes, skip it.""" 21297db96d56Sopenharmony_ci zipdata = ( 21307db96d56Sopenharmony_ci b'PK\x03\x04\x14\x00\x00\x00\x00\x00\x93\x9b\xad@\x8b\x9e' 21317db96d56Sopenharmony_ci b'\xd9\xd3\x01\x00\x00\x00\x01\x00\x00\x00\x03\x00\x03\x00ab' 21327db96d56Sopenharmony_ci b'c\x00\x00\x00APK\x01\x02\x14\x03\x14\x00\x00\x00\x00' 21337db96d56Sopenharmony_ci b'\x00\x93\x9b\xad@\x8b\x9e\xd9\xd3\x01\x00\x00\x00\x01\x00\x00' 21347db96d56Sopenharmony_ci b'\x00\x03\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x00' 21357db96d56Sopenharmony_ci b'\x00\x00\x00abc\x00\x00PK\x05\x06\x00\x00\x00\x00' 21367db96d56Sopenharmony_ci b'\x01\x00\x01\x003\x00\x00\x00%\x00\x00\x00\x00\x00' 21377db96d56Sopenharmony_ci ) 21387db96d56Sopenharmony_ci with zipfile.ZipFile(io.BytesIO(zipdata), 'r') as zipf: 21397db96d56Sopenharmony_ci # testzip returns the name of the first corrupt file, or None 21407db96d56Sopenharmony_ci self.assertIsNone(zipf.testzip()) 21417db96d56Sopenharmony_ci 21427db96d56Sopenharmony_ci def test_open_conflicting_handles(self): 21437db96d56Sopenharmony_ci # It's only possible to open one writable file handle at a time 21447db96d56Sopenharmony_ci msg1 = b"It's fun to charter an accountant!" 21457db96d56Sopenharmony_ci msg2 = b"And sail the wide accountant sea" 21467db96d56Sopenharmony_ci msg3 = b"To find, explore the funds offshore" 21477db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, 'w', zipfile.ZIP_STORED) as zipf: 21487db96d56Sopenharmony_ci with zipf.open('foo', mode='w') as w2: 21497db96d56Sopenharmony_ci w2.write(msg1) 21507db96d56Sopenharmony_ci with zipf.open('bar', mode='w') as w1: 21517db96d56Sopenharmony_ci with self.assertRaises(ValueError): 21527db96d56Sopenharmony_ci zipf.open('handle', mode='w') 21537db96d56Sopenharmony_ci with self.assertRaises(ValueError): 21547db96d56Sopenharmony_ci zipf.open('foo', mode='r') 21557db96d56Sopenharmony_ci with self.assertRaises(ValueError): 21567db96d56Sopenharmony_ci zipf.writestr('str', 'abcde') 21577db96d56Sopenharmony_ci with self.assertRaises(ValueError): 21587db96d56Sopenharmony_ci zipf.write(__file__, 'file') 21597db96d56Sopenharmony_ci with self.assertRaises(ValueError): 21607db96d56Sopenharmony_ci zipf.close() 21617db96d56Sopenharmony_ci w1.write(msg2) 21627db96d56Sopenharmony_ci with zipf.open('baz', mode='w') as w2: 21637db96d56Sopenharmony_ci w2.write(msg3) 21647db96d56Sopenharmony_ci 21657db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, 'r') as zipf: 21667db96d56Sopenharmony_ci self.assertEqual(zipf.read('foo'), msg1) 21677db96d56Sopenharmony_ci self.assertEqual(zipf.read('bar'), msg2) 21687db96d56Sopenharmony_ci self.assertEqual(zipf.read('baz'), msg3) 21697db96d56Sopenharmony_ci self.assertEqual(zipf.namelist(), ['foo', 'bar', 'baz']) 21707db96d56Sopenharmony_ci 21717db96d56Sopenharmony_ci def test_seek_tell(self): 21727db96d56Sopenharmony_ci # Test seek functionality 21737db96d56Sopenharmony_ci txt = b"Where's Bruce?" 21747db96d56Sopenharmony_ci bloc = txt.find(b"Bruce") 21757db96d56Sopenharmony_ci # Check seek on a file 21767db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, "w") as zipf: 21777db96d56Sopenharmony_ci zipf.writestr("foo.txt", txt) 21787db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, "r") as zipf: 21797db96d56Sopenharmony_ci with zipf.open("foo.txt", "r") as fp: 21807db96d56Sopenharmony_ci fp.seek(bloc, os.SEEK_SET) 21817db96d56Sopenharmony_ci self.assertEqual(fp.tell(), bloc) 21827db96d56Sopenharmony_ci fp.seek(-bloc, os.SEEK_CUR) 21837db96d56Sopenharmony_ci self.assertEqual(fp.tell(), 0) 21847db96d56Sopenharmony_ci fp.seek(bloc, os.SEEK_CUR) 21857db96d56Sopenharmony_ci self.assertEqual(fp.tell(), bloc) 21867db96d56Sopenharmony_ci self.assertEqual(fp.read(5), txt[bloc:bloc+5]) 21877db96d56Sopenharmony_ci fp.seek(0, os.SEEK_END) 21887db96d56Sopenharmony_ci self.assertEqual(fp.tell(), len(txt)) 21897db96d56Sopenharmony_ci fp.seek(0, os.SEEK_SET) 21907db96d56Sopenharmony_ci self.assertEqual(fp.tell(), 0) 21917db96d56Sopenharmony_ci # Check seek on memory file 21927db96d56Sopenharmony_ci data = io.BytesIO() 21937db96d56Sopenharmony_ci with zipfile.ZipFile(data, mode="w") as zipf: 21947db96d56Sopenharmony_ci zipf.writestr("foo.txt", txt) 21957db96d56Sopenharmony_ci with zipfile.ZipFile(data, mode="r") as zipf: 21967db96d56Sopenharmony_ci with zipf.open("foo.txt", "r") as fp: 21977db96d56Sopenharmony_ci fp.seek(bloc, os.SEEK_SET) 21987db96d56Sopenharmony_ci self.assertEqual(fp.tell(), bloc) 21997db96d56Sopenharmony_ci fp.seek(-bloc, os.SEEK_CUR) 22007db96d56Sopenharmony_ci self.assertEqual(fp.tell(), 0) 22017db96d56Sopenharmony_ci fp.seek(bloc, os.SEEK_CUR) 22027db96d56Sopenharmony_ci self.assertEqual(fp.tell(), bloc) 22037db96d56Sopenharmony_ci self.assertEqual(fp.read(5), txt[bloc:bloc+5]) 22047db96d56Sopenharmony_ci fp.seek(0, os.SEEK_END) 22057db96d56Sopenharmony_ci self.assertEqual(fp.tell(), len(txt)) 22067db96d56Sopenharmony_ci fp.seek(0, os.SEEK_SET) 22077db96d56Sopenharmony_ci self.assertEqual(fp.tell(), 0) 22087db96d56Sopenharmony_ci 22097db96d56Sopenharmony_ci @requires_bz2() 22107db96d56Sopenharmony_ci def test_decompress_without_3rd_party_library(self): 22117db96d56Sopenharmony_ci data = b'PK\x05\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' 22127db96d56Sopenharmony_ci zip_file = io.BytesIO(data) 22137db96d56Sopenharmony_ci with zipfile.ZipFile(zip_file, 'w', compression=zipfile.ZIP_BZIP2) as zf: 22147db96d56Sopenharmony_ci zf.writestr('a.txt', b'a') 22157db96d56Sopenharmony_ci with mock.patch('zipfile.bz2', None): 22167db96d56Sopenharmony_ci with zipfile.ZipFile(zip_file) as zf: 22177db96d56Sopenharmony_ci self.assertRaises(RuntimeError, zf.extract, 'a.txt') 22187db96d56Sopenharmony_ci 22197db96d56Sopenharmony_ci @requires_zlib() 22207db96d56Sopenharmony_ci def test_full_overlap(self): 22217db96d56Sopenharmony_ci data = ( 22227db96d56Sopenharmony_ci b'PK\x03\x04\x14\x00\x00\x00\x08\x00\xa0lH\x05\xe2\x1e' 22237db96d56Sopenharmony_ci b'8\xbb\x10\x00\x00\x00\t\x04\x00\x00\x01\x00\x00\x00a\xed' 22247db96d56Sopenharmony_ci b'\xc0\x81\x08\x00\x00\x00\xc00\xd6\xfbK\\d\x0b`P' 22257db96d56Sopenharmony_ci b'K\x01\x02\x14\x00\x14\x00\x00\x00\x08\x00\xa0lH\x05\xe2' 22267db96d56Sopenharmony_ci b'\x1e8\xbb\x10\x00\x00\x00\t\x04\x00\x00\x01\x00\x00\x00\x00' 22277db96d56Sopenharmony_ci b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00aPK' 22287db96d56Sopenharmony_ci b'\x01\x02\x14\x00\x14\x00\x00\x00\x08\x00\xa0lH\x05\xe2\x1e' 22297db96d56Sopenharmony_ci b'8\xbb\x10\x00\x00\x00\t\x04\x00\x00\x01\x00\x00\x00\x00\x00' 22307db96d56Sopenharmony_ci b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00bPK\x05' 22317db96d56Sopenharmony_ci b'\x06\x00\x00\x00\x00\x02\x00\x02\x00^\x00\x00\x00/\x00\x00' 22327db96d56Sopenharmony_ci b'\x00\x00\x00' 22337db96d56Sopenharmony_ci ) 22347db96d56Sopenharmony_ci with zipfile.ZipFile(io.BytesIO(data), 'r') as zipf: 22357db96d56Sopenharmony_ci self.assertEqual(zipf.namelist(), ['a', 'b']) 22367db96d56Sopenharmony_ci zi = zipf.getinfo('a') 22377db96d56Sopenharmony_ci self.assertEqual(zi.header_offset, 0) 22387db96d56Sopenharmony_ci self.assertEqual(zi.compress_size, 16) 22397db96d56Sopenharmony_ci self.assertEqual(zi.file_size, 1033) 22407db96d56Sopenharmony_ci zi = zipf.getinfo('b') 22417db96d56Sopenharmony_ci self.assertEqual(zi.header_offset, 0) 22427db96d56Sopenharmony_ci self.assertEqual(zi.compress_size, 16) 22437db96d56Sopenharmony_ci self.assertEqual(zi.file_size, 1033) 22447db96d56Sopenharmony_ci self.assertEqual(len(zipf.read('a')), 1033) 22457db96d56Sopenharmony_ci with self.assertRaisesRegex(zipfile.BadZipFile, 'File name.*differ'): 22467db96d56Sopenharmony_ci zipf.read('b') 22477db96d56Sopenharmony_ci 22487db96d56Sopenharmony_ci @requires_zlib() 22497db96d56Sopenharmony_ci def test_quoted_overlap(self): 22507db96d56Sopenharmony_ci data = ( 22517db96d56Sopenharmony_ci b'PK\x03\x04\x14\x00\x00\x00\x08\x00\xa0lH\x05Y\xfc' 22527db96d56Sopenharmony_ci b'8\x044\x00\x00\x00(\x04\x00\x00\x01\x00\x00\x00a\x00' 22537db96d56Sopenharmony_ci b'\x1f\x00\xe0\xffPK\x03\x04\x14\x00\x00\x00\x08\x00\xa0l' 22547db96d56Sopenharmony_ci b'H\x05\xe2\x1e8\xbb\x10\x00\x00\x00\t\x04\x00\x00\x01\x00' 22557db96d56Sopenharmony_ci b'\x00\x00b\xed\xc0\x81\x08\x00\x00\x00\xc00\xd6\xfbK\\' 22567db96d56Sopenharmony_ci b'd\x0b`PK\x01\x02\x14\x00\x14\x00\x00\x00\x08\x00\xa0' 22577db96d56Sopenharmony_ci b'lH\x05Y\xfc8\x044\x00\x00\x00(\x04\x00\x00\x01' 22587db96d56Sopenharmony_ci b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' 22597db96d56Sopenharmony_ci b'\x00aPK\x01\x02\x14\x00\x14\x00\x00\x00\x08\x00\xa0l' 22607db96d56Sopenharmony_ci b'H\x05\xe2\x1e8\xbb\x10\x00\x00\x00\t\x04\x00\x00\x01\x00' 22617db96d56Sopenharmony_ci b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00$\x00\x00\x00' 22627db96d56Sopenharmony_ci b'bPK\x05\x06\x00\x00\x00\x00\x02\x00\x02\x00^\x00\x00' 22637db96d56Sopenharmony_ci b'\x00S\x00\x00\x00\x00\x00' 22647db96d56Sopenharmony_ci ) 22657db96d56Sopenharmony_ci with zipfile.ZipFile(io.BytesIO(data), 'r') as zipf: 22667db96d56Sopenharmony_ci self.assertEqual(zipf.namelist(), ['a', 'b']) 22677db96d56Sopenharmony_ci zi = zipf.getinfo('a') 22687db96d56Sopenharmony_ci self.assertEqual(zi.header_offset, 0) 22697db96d56Sopenharmony_ci self.assertEqual(zi.compress_size, 52) 22707db96d56Sopenharmony_ci self.assertEqual(zi.file_size, 1064) 22717db96d56Sopenharmony_ci zi = zipf.getinfo('b') 22727db96d56Sopenharmony_ci self.assertEqual(zi.header_offset, 36) 22737db96d56Sopenharmony_ci self.assertEqual(zi.compress_size, 16) 22747db96d56Sopenharmony_ci self.assertEqual(zi.file_size, 1033) 22757db96d56Sopenharmony_ci with self.assertRaisesRegex(zipfile.BadZipFile, 'Overlapped entries'): 22767db96d56Sopenharmony_ci zipf.read('a') 22777db96d56Sopenharmony_ci self.assertEqual(len(zipf.read('b')), 1033) 22787db96d56Sopenharmony_ci 22797db96d56Sopenharmony_ci def tearDown(self): 22807db96d56Sopenharmony_ci unlink(TESTFN) 22817db96d56Sopenharmony_ci unlink(TESTFN2) 22827db96d56Sopenharmony_ci 22837db96d56Sopenharmony_ci 22847db96d56Sopenharmony_ciclass AbstractBadCrcTests: 22857db96d56Sopenharmony_ci def test_testzip_with_bad_crc(self): 22867db96d56Sopenharmony_ci """Tests that files with bad CRCs return their name from testzip.""" 22877db96d56Sopenharmony_ci zipdata = self.zip_with_bad_crc 22887db96d56Sopenharmony_ci 22897db96d56Sopenharmony_ci with zipfile.ZipFile(io.BytesIO(zipdata), mode="r") as zipf: 22907db96d56Sopenharmony_ci # testzip returns the name of the first corrupt file, or None 22917db96d56Sopenharmony_ci self.assertEqual('afile', zipf.testzip()) 22927db96d56Sopenharmony_ci 22937db96d56Sopenharmony_ci def test_read_with_bad_crc(self): 22947db96d56Sopenharmony_ci """Tests that files with bad CRCs raise a BadZipFile exception when read.""" 22957db96d56Sopenharmony_ci zipdata = self.zip_with_bad_crc 22967db96d56Sopenharmony_ci 22977db96d56Sopenharmony_ci # Using ZipFile.read() 22987db96d56Sopenharmony_ci with zipfile.ZipFile(io.BytesIO(zipdata), mode="r") as zipf: 22997db96d56Sopenharmony_ci self.assertRaises(zipfile.BadZipFile, zipf.read, 'afile') 23007db96d56Sopenharmony_ci 23017db96d56Sopenharmony_ci # Using ZipExtFile.read() 23027db96d56Sopenharmony_ci with zipfile.ZipFile(io.BytesIO(zipdata), mode="r") as zipf: 23037db96d56Sopenharmony_ci with zipf.open('afile', 'r') as corrupt_file: 23047db96d56Sopenharmony_ci self.assertRaises(zipfile.BadZipFile, corrupt_file.read) 23057db96d56Sopenharmony_ci 23067db96d56Sopenharmony_ci # Same with small reads (in order to exercise the buffering logic) 23077db96d56Sopenharmony_ci with zipfile.ZipFile(io.BytesIO(zipdata), mode="r") as zipf: 23087db96d56Sopenharmony_ci with zipf.open('afile', 'r') as corrupt_file: 23097db96d56Sopenharmony_ci corrupt_file.MIN_READ_SIZE = 2 23107db96d56Sopenharmony_ci with self.assertRaises(zipfile.BadZipFile): 23117db96d56Sopenharmony_ci while corrupt_file.read(2): 23127db96d56Sopenharmony_ci pass 23137db96d56Sopenharmony_ci 23147db96d56Sopenharmony_ci 23157db96d56Sopenharmony_ciclass StoredBadCrcTests(AbstractBadCrcTests, unittest.TestCase): 23167db96d56Sopenharmony_ci compression = zipfile.ZIP_STORED 23177db96d56Sopenharmony_ci zip_with_bad_crc = ( 23187db96d56Sopenharmony_ci b'PK\003\004\024\0\0\0\0\0 \213\212;:r' 23197db96d56Sopenharmony_ci b'\253\377\f\0\0\0\f\0\0\0\005\0\0\000af' 23207db96d56Sopenharmony_ci b'ilehello,AworldP' 23217db96d56Sopenharmony_ci b'K\001\002\024\003\024\0\0\0\0\0 \213\212;:' 23227db96d56Sopenharmony_ci b'r\253\377\f\0\0\0\f\0\0\0\005\0\0\0\0' 23237db96d56Sopenharmony_ci b'\0\0\0\0\0\0\0\200\001\0\0\0\000afi' 23247db96d56Sopenharmony_ci b'lePK\005\006\0\0\0\0\001\0\001\0003\000' 23257db96d56Sopenharmony_ci b'\0\0/\0\0\0\0\0') 23267db96d56Sopenharmony_ci 23277db96d56Sopenharmony_ci@requires_zlib() 23287db96d56Sopenharmony_ciclass DeflateBadCrcTests(AbstractBadCrcTests, unittest.TestCase): 23297db96d56Sopenharmony_ci compression = zipfile.ZIP_DEFLATED 23307db96d56Sopenharmony_ci zip_with_bad_crc = ( 23317db96d56Sopenharmony_ci b'PK\x03\x04\x14\x00\x00\x00\x08\x00n}\x0c=FA' 23327db96d56Sopenharmony_ci b'KE\x10\x00\x00\x00n\x00\x00\x00\x05\x00\x00\x00af' 23337db96d56Sopenharmony_ci b'ile\xcbH\xcd\xc9\xc9W(\xcf/\xcaI\xc9\xa0' 23347db96d56Sopenharmony_ci b'=\x13\x00PK\x01\x02\x14\x03\x14\x00\x00\x00\x08\x00n' 23357db96d56Sopenharmony_ci b'}\x0c=FAKE\x10\x00\x00\x00n\x00\x00\x00\x05' 23367db96d56Sopenharmony_ci b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x01\x00\x00\x00' 23377db96d56Sopenharmony_ci b'\x00afilePK\x05\x06\x00\x00\x00\x00\x01\x00' 23387db96d56Sopenharmony_ci b'\x01\x003\x00\x00\x003\x00\x00\x00\x00\x00') 23397db96d56Sopenharmony_ci 23407db96d56Sopenharmony_ci@requires_bz2() 23417db96d56Sopenharmony_ciclass Bzip2BadCrcTests(AbstractBadCrcTests, unittest.TestCase): 23427db96d56Sopenharmony_ci compression = zipfile.ZIP_BZIP2 23437db96d56Sopenharmony_ci zip_with_bad_crc = ( 23447db96d56Sopenharmony_ci b'PK\x03\x04\x14\x03\x00\x00\x0c\x00nu\x0c=FA' 23457db96d56Sopenharmony_ci b'KE8\x00\x00\x00n\x00\x00\x00\x05\x00\x00\x00af' 23467db96d56Sopenharmony_ci b'ileBZh91AY&SY\xd4\xa8\xca' 23477db96d56Sopenharmony_ci b'\x7f\x00\x00\x0f\x11\x80@\x00\x06D\x90\x80 \x00 \xa5' 23487db96d56Sopenharmony_ci b'P\xd9!\x03\x03\x13\x13\x13\x89\xa9\xa9\xc2u5:\x9f' 23497db96d56Sopenharmony_ci b'\x8b\xb9"\x9c(HjTe?\x80PK\x01\x02\x14' 23507db96d56Sopenharmony_ci b'\x03\x14\x03\x00\x00\x0c\x00nu\x0c=FAKE8' 23517db96d56Sopenharmony_ci b'\x00\x00\x00n\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00' 23527db96d56Sopenharmony_ci b'\x00 \x80\x80\x81\x00\x00\x00\x00afilePK' 23537db96d56Sopenharmony_ci b'\x05\x06\x00\x00\x00\x00\x01\x00\x01\x003\x00\x00\x00[\x00' 23547db96d56Sopenharmony_ci b'\x00\x00\x00\x00') 23557db96d56Sopenharmony_ci 23567db96d56Sopenharmony_ci@requires_lzma() 23577db96d56Sopenharmony_ciclass LzmaBadCrcTests(AbstractBadCrcTests, unittest.TestCase): 23587db96d56Sopenharmony_ci compression = zipfile.ZIP_LZMA 23597db96d56Sopenharmony_ci zip_with_bad_crc = ( 23607db96d56Sopenharmony_ci b'PK\x03\x04\x14\x03\x00\x00\x0e\x00nu\x0c=FA' 23617db96d56Sopenharmony_ci b'KE\x1b\x00\x00\x00n\x00\x00\x00\x05\x00\x00\x00af' 23627db96d56Sopenharmony_ci b'ile\t\x04\x05\x00]\x00\x00\x00\x04\x004\x19I' 23637db96d56Sopenharmony_ci b'\xee\x8d\xe9\x17\x89:3`\tq!.8\x00PK' 23647db96d56Sopenharmony_ci b'\x01\x02\x14\x03\x14\x03\x00\x00\x0e\x00nu\x0c=FA' 23657db96d56Sopenharmony_ci b'KE\x1b\x00\x00\x00n\x00\x00\x00\x05\x00\x00\x00\x00\x00' 23667db96d56Sopenharmony_ci b'\x00\x00\x00\x00 \x80\x80\x81\x00\x00\x00\x00afil' 23677db96d56Sopenharmony_ci b'ePK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x003\x00\x00' 23687db96d56Sopenharmony_ci b'\x00>\x00\x00\x00\x00\x00') 23697db96d56Sopenharmony_ci 23707db96d56Sopenharmony_ci 23717db96d56Sopenharmony_ciclass DecryptionTests(unittest.TestCase): 23727db96d56Sopenharmony_ci """Check that ZIP decryption works. Since the library does not 23737db96d56Sopenharmony_ci support encryption at the moment, we use a pre-generated encrypted 23747db96d56Sopenharmony_ci ZIP file.""" 23757db96d56Sopenharmony_ci 23767db96d56Sopenharmony_ci data = ( 23777db96d56Sopenharmony_ci b'PK\x03\x04\x14\x00\x01\x00\x00\x00n\x92i.#y\xef?&\x00\x00\x00\x1a\x00' 23787db96d56Sopenharmony_ci b'\x00\x00\x08\x00\x00\x00test.txt\xfa\x10\xa0gly|\xfa-\xc5\xc0=\xf9y' 23797db96d56Sopenharmony_ci b'\x18\xe0\xa8r\xb3Z}Lg\xbc\xae\xf9|\x9b\x19\xe4\x8b\xba\xbb)\x8c\xb0\xdbl' 23807db96d56Sopenharmony_ci b'PK\x01\x02\x14\x00\x14\x00\x01\x00\x00\x00n\x92i.#y\xef?&\x00\x00\x00' 23817db96d56Sopenharmony_ci b'\x1a\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x01\x00 \x00\xb6\x81' 23827db96d56Sopenharmony_ci b'\x00\x00\x00\x00test.txtPK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x006\x00' 23837db96d56Sopenharmony_ci b'\x00\x00L\x00\x00\x00\x00\x00' ) 23847db96d56Sopenharmony_ci data2 = ( 23857db96d56Sopenharmony_ci b'PK\x03\x04\x14\x00\t\x00\x08\x00\xcf}38xu\xaa\xb2\x14\x00\x00\x00\x00\x02' 23867db96d56Sopenharmony_ci b'\x00\x00\x04\x00\x15\x00zeroUT\t\x00\x03\xd6\x8b\x92G\xda\x8b\x92GUx\x04' 23877db96d56Sopenharmony_ci b'\x00\xe8\x03\xe8\x03\xc7<M\xb5a\xceX\xa3Y&\x8b{oE\xd7\x9d\x8c\x98\x02\xc0' 23887db96d56Sopenharmony_ci b'PK\x07\x08xu\xaa\xb2\x14\x00\x00\x00\x00\x02\x00\x00PK\x01\x02\x17\x03' 23897db96d56Sopenharmony_ci b'\x14\x00\t\x00\x08\x00\xcf}38xu\xaa\xb2\x14\x00\x00\x00\x00\x02\x00\x00' 23907db96d56Sopenharmony_ci b'\x04\x00\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x00\x00\x00\x00ze' 23917db96d56Sopenharmony_ci b'roUT\x05\x00\x03\xd6\x8b\x92GUx\x00\x00PK\x05\x06\x00\x00\x00\x00\x01' 23927db96d56Sopenharmony_ci b'\x00\x01\x00?\x00\x00\x00[\x00\x00\x00\x00\x00' ) 23937db96d56Sopenharmony_ci 23947db96d56Sopenharmony_ci plain = b'zipfile.py encryption test' 23957db96d56Sopenharmony_ci plain2 = b'\x00'*512 23967db96d56Sopenharmony_ci 23977db96d56Sopenharmony_ci def setUp(self): 23987db96d56Sopenharmony_ci with open(TESTFN, "wb") as fp: 23997db96d56Sopenharmony_ci fp.write(self.data) 24007db96d56Sopenharmony_ci self.zip = zipfile.ZipFile(TESTFN, "r") 24017db96d56Sopenharmony_ci with open(TESTFN2, "wb") as fp: 24027db96d56Sopenharmony_ci fp.write(self.data2) 24037db96d56Sopenharmony_ci self.zip2 = zipfile.ZipFile(TESTFN2, "r") 24047db96d56Sopenharmony_ci 24057db96d56Sopenharmony_ci def tearDown(self): 24067db96d56Sopenharmony_ci self.zip.close() 24077db96d56Sopenharmony_ci os.unlink(TESTFN) 24087db96d56Sopenharmony_ci self.zip2.close() 24097db96d56Sopenharmony_ci os.unlink(TESTFN2) 24107db96d56Sopenharmony_ci 24117db96d56Sopenharmony_ci def test_no_password(self): 24127db96d56Sopenharmony_ci # Reading the encrypted file without password 24137db96d56Sopenharmony_ci # must generate a RunTime exception 24147db96d56Sopenharmony_ci self.assertRaises(RuntimeError, self.zip.read, "test.txt") 24157db96d56Sopenharmony_ci self.assertRaises(RuntimeError, self.zip2.read, "zero") 24167db96d56Sopenharmony_ci 24177db96d56Sopenharmony_ci def test_bad_password(self): 24187db96d56Sopenharmony_ci self.zip.setpassword(b"perl") 24197db96d56Sopenharmony_ci self.assertRaises(RuntimeError, self.zip.read, "test.txt") 24207db96d56Sopenharmony_ci self.zip2.setpassword(b"perl") 24217db96d56Sopenharmony_ci self.assertRaises(RuntimeError, self.zip2.read, "zero") 24227db96d56Sopenharmony_ci 24237db96d56Sopenharmony_ci @requires_zlib() 24247db96d56Sopenharmony_ci def test_good_password(self): 24257db96d56Sopenharmony_ci self.zip.setpassword(b"python") 24267db96d56Sopenharmony_ci self.assertEqual(self.zip.read("test.txt"), self.plain) 24277db96d56Sopenharmony_ci self.zip2.setpassword(b"12345") 24287db96d56Sopenharmony_ci self.assertEqual(self.zip2.read("zero"), self.plain2) 24297db96d56Sopenharmony_ci 24307db96d56Sopenharmony_ci def test_unicode_password(self): 24317db96d56Sopenharmony_ci expected_msg = "pwd: expected bytes, got str" 24327db96d56Sopenharmony_ci 24337db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, expected_msg): 24347db96d56Sopenharmony_ci self.zip.setpassword("unicode") 24357db96d56Sopenharmony_ci 24367db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, expected_msg): 24377db96d56Sopenharmony_ci self.zip.read("test.txt", "python") 24387db96d56Sopenharmony_ci 24397db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, expected_msg): 24407db96d56Sopenharmony_ci self.zip.open("test.txt", pwd="python") 24417db96d56Sopenharmony_ci 24427db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, expected_msg): 24437db96d56Sopenharmony_ci self.zip.extract("test.txt", pwd="python") 24447db96d56Sopenharmony_ci 24457db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, expected_msg): 24467db96d56Sopenharmony_ci self.zip.pwd = "python" 24477db96d56Sopenharmony_ci self.zip.open("test.txt") 24487db96d56Sopenharmony_ci 24497db96d56Sopenharmony_ci def test_seek_tell(self): 24507db96d56Sopenharmony_ci self.zip.setpassword(b"python") 24517db96d56Sopenharmony_ci txt = self.plain 24527db96d56Sopenharmony_ci test_word = b'encryption' 24537db96d56Sopenharmony_ci bloc = txt.find(test_word) 24547db96d56Sopenharmony_ci bloc_len = len(test_word) 24557db96d56Sopenharmony_ci with self.zip.open("test.txt", "r") as fp: 24567db96d56Sopenharmony_ci fp.seek(bloc, os.SEEK_SET) 24577db96d56Sopenharmony_ci self.assertEqual(fp.tell(), bloc) 24587db96d56Sopenharmony_ci fp.seek(-bloc, os.SEEK_CUR) 24597db96d56Sopenharmony_ci self.assertEqual(fp.tell(), 0) 24607db96d56Sopenharmony_ci fp.seek(bloc, os.SEEK_CUR) 24617db96d56Sopenharmony_ci self.assertEqual(fp.tell(), bloc) 24627db96d56Sopenharmony_ci self.assertEqual(fp.read(bloc_len), txt[bloc:bloc+bloc_len]) 24637db96d56Sopenharmony_ci 24647db96d56Sopenharmony_ci # Make sure that the second read after seeking back beyond 24657db96d56Sopenharmony_ci # _readbuffer returns the same content (ie. rewind to the start of 24667db96d56Sopenharmony_ci # the file to read forward to the required position). 24677db96d56Sopenharmony_ci old_read_size = fp.MIN_READ_SIZE 24687db96d56Sopenharmony_ci fp.MIN_READ_SIZE = 1 24697db96d56Sopenharmony_ci fp._readbuffer = b'' 24707db96d56Sopenharmony_ci fp._offset = 0 24717db96d56Sopenharmony_ci fp.seek(0, os.SEEK_SET) 24727db96d56Sopenharmony_ci self.assertEqual(fp.tell(), 0) 24737db96d56Sopenharmony_ci fp.seek(bloc, os.SEEK_CUR) 24747db96d56Sopenharmony_ci self.assertEqual(fp.read(bloc_len), txt[bloc:bloc+bloc_len]) 24757db96d56Sopenharmony_ci fp.MIN_READ_SIZE = old_read_size 24767db96d56Sopenharmony_ci 24777db96d56Sopenharmony_ci fp.seek(0, os.SEEK_END) 24787db96d56Sopenharmony_ci self.assertEqual(fp.tell(), len(txt)) 24797db96d56Sopenharmony_ci fp.seek(0, os.SEEK_SET) 24807db96d56Sopenharmony_ci self.assertEqual(fp.tell(), 0) 24817db96d56Sopenharmony_ci 24827db96d56Sopenharmony_ci # Read the file completely to definitely call any eof integrity 24837db96d56Sopenharmony_ci # checks (crc) and make sure they still pass. 24847db96d56Sopenharmony_ci fp.read() 24857db96d56Sopenharmony_ci 24867db96d56Sopenharmony_ci 24877db96d56Sopenharmony_ciclass AbstractTestsWithRandomBinaryFiles: 24887db96d56Sopenharmony_ci @classmethod 24897db96d56Sopenharmony_ci def setUpClass(cls): 24907db96d56Sopenharmony_ci datacount = randint(16, 64)*1024 + randint(1, 1024) 24917db96d56Sopenharmony_ci cls.data = b''.join(struct.pack('<f', random()*randint(-1000, 1000)) 24927db96d56Sopenharmony_ci for i in range(datacount)) 24937db96d56Sopenharmony_ci 24947db96d56Sopenharmony_ci def setUp(self): 24957db96d56Sopenharmony_ci # Make a source file with some lines 24967db96d56Sopenharmony_ci with open(TESTFN, "wb") as fp: 24977db96d56Sopenharmony_ci fp.write(self.data) 24987db96d56Sopenharmony_ci 24997db96d56Sopenharmony_ci def tearDown(self): 25007db96d56Sopenharmony_ci unlink(TESTFN) 25017db96d56Sopenharmony_ci unlink(TESTFN2) 25027db96d56Sopenharmony_ci 25037db96d56Sopenharmony_ci def make_test_archive(self, f, compression): 25047db96d56Sopenharmony_ci # Create the ZIP archive 25057db96d56Sopenharmony_ci with zipfile.ZipFile(f, "w", compression) as zipfp: 25067db96d56Sopenharmony_ci zipfp.write(TESTFN, "another.name") 25077db96d56Sopenharmony_ci zipfp.write(TESTFN, TESTFN) 25087db96d56Sopenharmony_ci 25097db96d56Sopenharmony_ci def zip_test(self, f, compression): 25107db96d56Sopenharmony_ci self.make_test_archive(f, compression) 25117db96d56Sopenharmony_ci 25127db96d56Sopenharmony_ci # Read the ZIP archive 25137db96d56Sopenharmony_ci with zipfile.ZipFile(f, "r", compression) as zipfp: 25147db96d56Sopenharmony_ci testdata = zipfp.read(TESTFN) 25157db96d56Sopenharmony_ci self.assertEqual(len(testdata), len(self.data)) 25167db96d56Sopenharmony_ci self.assertEqual(testdata, self.data) 25177db96d56Sopenharmony_ci self.assertEqual(zipfp.read("another.name"), self.data) 25187db96d56Sopenharmony_ci 25197db96d56Sopenharmony_ci def test_read(self): 25207db96d56Sopenharmony_ci for f in get_files(self): 25217db96d56Sopenharmony_ci self.zip_test(f, self.compression) 25227db96d56Sopenharmony_ci 25237db96d56Sopenharmony_ci def zip_open_test(self, f, compression): 25247db96d56Sopenharmony_ci self.make_test_archive(f, compression) 25257db96d56Sopenharmony_ci 25267db96d56Sopenharmony_ci # Read the ZIP archive 25277db96d56Sopenharmony_ci with zipfile.ZipFile(f, "r", compression) as zipfp: 25287db96d56Sopenharmony_ci zipdata1 = [] 25297db96d56Sopenharmony_ci with zipfp.open(TESTFN) as zipopen1: 25307db96d56Sopenharmony_ci while True: 25317db96d56Sopenharmony_ci read_data = zipopen1.read(256) 25327db96d56Sopenharmony_ci if not read_data: 25337db96d56Sopenharmony_ci break 25347db96d56Sopenharmony_ci zipdata1.append(read_data) 25357db96d56Sopenharmony_ci 25367db96d56Sopenharmony_ci zipdata2 = [] 25377db96d56Sopenharmony_ci with zipfp.open("another.name") as zipopen2: 25387db96d56Sopenharmony_ci while True: 25397db96d56Sopenharmony_ci read_data = zipopen2.read(256) 25407db96d56Sopenharmony_ci if not read_data: 25417db96d56Sopenharmony_ci break 25427db96d56Sopenharmony_ci zipdata2.append(read_data) 25437db96d56Sopenharmony_ci 25447db96d56Sopenharmony_ci testdata1 = b''.join(zipdata1) 25457db96d56Sopenharmony_ci self.assertEqual(len(testdata1), len(self.data)) 25467db96d56Sopenharmony_ci self.assertEqual(testdata1, self.data) 25477db96d56Sopenharmony_ci 25487db96d56Sopenharmony_ci testdata2 = b''.join(zipdata2) 25497db96d56Sopenharmony_ci self.assertEqual(len(testdata2), len(self.data)) 25507db96d56Sopenharmony_ci self.assertEqual(testdata2, self.data) 25517db96d56Sopenharmony_ci 25527db96d56Sopenharmony_ci def test_open(self): 25537db96d56Sopenharmony_ci for f in get_files(self): 25547db96d56Sopenharmony_ci self.zip_open_test(f, self.compression) 25557db96d56Sopenharmony_ci 25567db96d56Sopenharmony_ci def zip_random_open_test(self, f, compression): 25577db96d56Sopenharmony_ci self.make_test_archive(f, compression) 25587db96d56Sopenharmony_ci 25597db96d56Sopenharmony_ci # Read the ZIP archive 25607db96d56Sopenharmony_ci with zipfile.ZipFile(f, "r", compression) as zipfp: 25617db96d56Sopenharmony_ci zipdata1 = [] 25627db96d56Sopenharmony_ci with zipfp.open(TESTFN) as zipopen1: 25637db96d56Sopenharmony_ci while True: 25647db96d56Sopenharmony_ci read_data = zipopen1.read(randint(1, 1024)) 25657db96d56Sopenharmony_ci if not read_data: 25667db96d56Sopenharmony_ci break 25677db96d56Sopenharmony_ci zipdata1.append(read_data) 25687db96d56Sopenharmony_ci 25697db96d56Sopenharmony_ci testdata = b''.join(zipdata1) 25707db96d56Sopenharmony_ci self.assertEqual(len(testdata), len(self.data)) 25717db96d56Sopenharmony_ci self.assertEqual(testdata, self.data) 25727db96d56Sopenharmony_ci 25737db96d56Sopenharmony_ci def test_random_open(self): 25747db96d56Sopenharmony_ci for f in get_files(self): 25757db96d56Sopenharmony_ci self.zip_random_open_test(f, self.compression) 25767db96d56Sopenharmony_ci 25777db96d56Sopenharmony_ci 25787db96d56Sopenharmony_ciclass StoredTestsWithRandomBinaryFiles(AbstractTestsWithRandomBinaryFiles, 25797db96d56Sopenharmony_ci unittest.TestCase): 25807db96d56Sopenharmony_ci compression = zipfile.ZIP_STORED 25817db96d56Sopenharmony_ci 25827db96d56Sopenharmony_ci@requires_zlib() 25837db96d56Sopenharmony_ciclass DeflateTestsWithRandomBinaryFiles(AbstractTestsWithRandomBinaryFiles, 25847db96d56Sopenharmony_ci unittest.TestCase): 25857db96d56Sopenharmony_ci compression = zipfile.ZIP_DEFLATED 25867db96d56Sopenharmony_ci 25877db96d56Sopenharmony_ci@requires_bz2() 25887db96d56Sopenharmony_ciclass Bzip2TestsWithRandomBinaryFiles(AbstractTestsWithRandomBinaryFiles, 25897db96d56Sopenharmony_ci unittest.TestCase): 25907db96d56Sopenharmony_ci compression = zipfile.ZIP_BZIP2 25917db96d56Sopenharmony_ci 25927db96d56Sopenharmony_ci@requires_lzma() 25937db96d56Sopenharmony_ciclass LzmaTestsWithRandomBinaryFiles(AbstractTestsWithRandomBinaryFiles, 25947db96d56Sopenharmony_ci unittest.TestCase): 25957db96d56Sopenharmony_ci compression = zipfile.ZIP_LZMA 25967db96d56Sopenharmony_ci 25977db96d56Sopenharmony_ci 25987db96d56Sopenharmony_ci# Provide the tell() method but not seek() 25997db96d56Sopenharmony_ciclass Tellable: 26007db96d56Sopenharmony_ci def __init__(self, fp): 26017db96d56Sopenharmony_ci self.fp = fp 26027db96d56Sopenharmony_ci self.offset = 0 26037db96d56Sopenharmony_ci 26047db96d56Sopenharmony_ci def write(self, data): 26057db96d56Sopenharmony_ci n = self.fp.write(data) 26067db96d56Sopenharmony_ci self.offset += n 26077db96d56Sopenharmony_ci return n 26087db96d56Sopenharmony_ci 26097db96d56Sopenharmony_ci def tell(self): 26107db96d56Sopenharmony_ci return self.offset 26117db96d56Sopenharmony_ci 26127db96d56Sopenharmony_ci def flush(self): 26137db96d56Sopenharmony_ci self.fp.flush() 26147db96d56Sopenharmony_ci 26157db96d56Sopenharmony_ciclass Unseekable: 26167db96d56Sopenharmony_ci def __init__(self, fp): 26177db96d56Sopenharmony_ci self.fp = fp 26187db96d56Sopenharmony_ci 26197db96d56Sopenharmony_ci def write(self, data): 26207db96d56Sopenharmony_ci return self.fp.write(data) 26217db96d56Sopenharmony_ci 26227db96d56Sopenharmony_ci def flush(self): 26237db96d56Sopenharmony_ci self.fp.flush() 26247db96d56Sopenharmony_ci 26257db96d56Sopenharmony_ciclass UnseekableTests(unittest.TestCase): 26267db96d56Sopenharmony_ci def test_writestr(self): 26277db96d56Sopenharmony_ci for wrapper in (lambda f: f), Tellable, Unseekable: 26287db96d56Sopenharmony_ci with self.subTest(wrapper=wrapper): 26297db96d56Sopenharmony_ci f = io.BytesIO() 26307db96d56Sopenharmony_ci f.write(b'abc') 26317db96d56Sopenharmony_ci bf = io.BufferedWriter(f) 26327db96d56Sopenharmony_ci with zipfile.ZipFile(wrapper(bf), 'w', zipfile.ZIP_STORED) as zipfp: 26337db96d56Sopenharmony_ci zipfp.writestr('ones', b'111') 26347db96d56Sopenharmony_ci zipfp.writestr('twos', b'222') 26357db96d56Sopenharmony_ci self.assertEqual(f.getvalue()[:5], b'abcPK') 26367db96d56Sopenharmony_ci with zipfile.ZipFile(f, mode='r') as zipf: 26377db96d56Sopenharmony_ci with zipf.open('ones') as zopen: 26387db96d56Sopenharmony_ci self.assertEqual(zopen.read(), b'111') 26397db96d56Sopenharmony_ci with zipf.open('twos') as zopen: 26407db96d56Sopenharmony_ci self.assertEqual(zopen.read(), b'222') 26417db96d56Sopenharmony_ci 26427db96d56Sopenharmony_ci def test_write(self): 26437db96d56Sopenharmony_ci for wrapper in (lambda f: f), Tellable, Unseekable: 26447db96d56Sopenharmony_ci with self.subTest(wrapper=wrapper): 26457db96d56Sopenharmony_ci f = io.BytesIO() 26467db96d56Sopenharmony_ci f.write(b'abc') 26477db96d56Sopenharmony_ci bf = io.BufferedWriter(f) 26487db96d56Sopenharmony_ci with zipfile.ZipFile(wrapper(bf), 'w', zipfile.ZIP_STORED) as zipfp: 26497db96d56Sopenharmony_ci self.addCleanup(unlink, TESTFN) 26507db96d56Sopenharmony_ci with open(TESTFN, 'wb') as f2: 26517db96d56Sopenharmony_ci f2.write(b'111') 26527db96d56Sopenharmony_ci zipfp.write(TESTFN, 'ones') 26537db96d56Sopenharmony_ci with open(TESTFN, 'wb') as f2: 26547db96d56Sopenharmony_ci f2.write(b'222') 26557db96d56Sopenharmony_ci zipfp.write(TESTFN, 'twos') 26567db96d56Sopenharmony_ci self.assertEqual(f.getvalue()[:5], b'abcPK') 26577db96d56Sopenharmony_ci with zipfile.ZipFile(f, mode='r') as zipf: 26587db96d56Sopenharmony_ci with zipf.open('ones') as zopen: 26597db96d56Sopenharmony_ci self.assertEqual(zopen.read(), b'111') 26607db96d56Sopenharmony_ci with zipf.open('twos') as zopen: 26617db96d56Sopenharmony_ci self.assertEqual(zopen.read(), b'222') 26627db96d56Sopenharmony_ci 26637db96d56Sopenharmony_ci def test_open_write(self): 26647db96d56Sopenharmony_ci for wrapper in (lambda f: f), Tellable, Unseekable: 26657db96d56Sopenharmony_ci with self.subTest(wrapper=wrapper): 26667db96d56Sopenharmony_ci f = io.BytesIO() 26677db96d56Sopenharmony_ci f.write(b'abc') 26687db96d56Sopenharmony_ci bf = io.BufferedWriter(f) 26697db96d56Sopenharmony_ci with zipfile.ZipFile(wrapper(bf), 'w', zipfile.ZIP_STORED) as zipf: 26707db96d56Sopenharmony_ci with zipf.open('ones', 'w') as zopen: 26717db96d56Sopenharmony_ci zopen.write(b'111') 26727db96d56Sopenharmony_ci with zipf.open('twos', 'w') as zopen: 26737db96d56Sopenharmony_ci zopen.write(b'222') 26747db96d56Sopenharmony_ci self.assertEqual(f.getvalue()[:5], b'abcPK') 26757db96d56Sopenharmony_ci with zipfile.ZipFile(f) as zipf: 26767db96d56Sopenharmony_ci self.assertEqual(zipf.read('ones'), b'111') 26777db96d56Sopenharmony_ci self.assertEqual(zipf.read('twos'), b'222') 26787db96d56Sopenharmony_ci 26797db96d56Sopenharmony_ci 26807db96d56Sopenharmony_ci@requires_zlib() 26817db96d56Sopenharmony_ciclass TestsWithMultipleOpens(unittest.TestCase): 26827db96d56Sopenharmony_ci @classmethod 26837db96d56Sopenharmony_ci def setUpClass(cls): 26847db96d56Sopenharmony_ci cls.data1 = b'111' + randbytes(10000) 26857db96d56Sopenharmony_ci cls.data2 = b'222' + randbytes(10000) 26867db96d56Sopenharmony_ci 26877db96d56Sopenharmony_ci def make_test_archive(self, f): 26887db96d56Sopenharmony_ci # Create the ZIP archive 26897db96d56Sopenharmony_ci with zipfile.ZipFile(f, "w", zipfile.ZIP_DEFLATED) as zipfp: 26907db96d56Sopenharmony_ci zipfp.writestr('ones', self.data1) 26917db96d56Sopenharmony_ci zipfp.writestr('twos', self.data2) 26927db96d56Sopenharmony_ci 26937db96d56Sopenharmony_ci def test_same_file(self): 26947db96d56Sopenharmony_ci # Verify that (when the ZipFile is in control of creating file objects) 26957db96d56Sopenharmony_ci # multiple open() calls can be made without interfering with each other. 26967db96d56Sopenharmony_ci for f in get_files(self): 26977db96d56Sopenharmony_ci self.make_test_archive(f) 26987db96d56Sopenharmony_ci with zipfile.ZipFile(f, mode="r") as zipf: 26997db96d56Sopenharmony_ci with zipf.open('ones') as zopen1, zipf.open('ones') as zopen2: 27007db96d56Sopenharmony_ci data1 = zopen1.read(500) 27017db96d56Sopenharmony_ci data2 = zopen2.read(500) 27027db96d56Sopenharmony_ci data1 += zopen1.read() 27037db96d56Sopenharmony_ci data2 += zopen2.read() 27047db96d56Sopenharmony_ci self.assertEqual(data1, data2) 27057db96d56Sopenharmony_ci self.assertEqual(data1, self.data1) 27067db96d56Sopenharmony_ci 27077db96d56Sopenharmony_ci def test_different_file(self): 27087db96d56Sopenharmony_ci # Verify that (when the ZipFile is in control of creating file objects) 27097db96d56Sopenharmony_ci # multiple open() calls can be made without interfering with each other. 27107db96d56Sopenharmony_ci for f in get_files(self): 27117db96d56Sopenharmony_ci self.make_test_archive(f) 27127db96d56Sopenharmony_ci with zipfile.ZipFile(f, mode="r") as zipf: 27137db96d56Sopenharmony_ci with zipf.open('ones') as zopen1, zipf.open('twos') as zopen2: 27147db96d56Sopenharmony_ci data1 = zopen1.read(500) 27157db96d56Sopenharmony_ci data2 = zopen2.read(500) 27167db96d56Sopenharmony_ci data1 += zopen1.read() 27177db96d56Sopenharmony_ci data2 += zopen2.read() 27187db96d56Sopenharmony_ci self.assertEqual(data1, self.data1) 27197db96d56Sopenharmony_ci self.assertEqual(data2, self.data2) 27207db96d56Sopenharmony_ci 27217db96d56Sopenharmony_ci def test_interleaved(self): 27227db96d56Sopenharmony_ci # Verify that (when the ZipFile is in control of creating file objects) 27237db96d56Sopenharmony_ci # multiple open() calls can be made without interfering with each other. 27247db96d56Sopenharmony_ci for f in get_files(self): 27257db96d56Sopenharmony_ci self.make_test_archive(f) 27267db96d56Sopenharmony_ci with zipfile.ZipFile(f, mode="r") as zipf: 27277db96d56Sopenharmony_ci with zipf.open('ones') as zopen1: 27287db96d56Sopenharmony_ci data1 = zopen1.read(500) 27297db96d56Sopenharmony_ci with zipf.open('twos') as zopen2: 27307db96d56Sopenharmony_ci data2 = zopen2.read(500) 27317db96d56Sopenharmony_ci data1 += zopen1.read() 27327db96d56Sopenharmony_ci data2 += zopen2.read() 27337db96d56Sopenharmony_ci self.assertEqual(data1, self.data1) 27347db96d56Sopenharmony_ci self.assertEqual(data2, self.data2) 27357db96d56Sopenharmony_ci 27367db96d56Sopenharmony_ci def test_read_after_close(self): 27377db96d56Sopenharmony_ci for f in get_files(self): 27387db96d56Sopenharmony_ci self.make_test_archive(f) 27397db96d56Sopenharmony_ci with contextlib.ExitStack() as stack: 27407db96d56Sopenharmony_ci with zipfile.ZipFile(f, 'r') as zipf: 27417db96d56Sopenharmony_ci zopen1 = stack.enter_context(zipf.open('ones')) 27427db96d56Sopenharmony_ci zopen2 = stack.enter_context(zipf.open('twos')) 27437db96d56Sopenharmony_ci data1 = zopen1.read(500) 27447db96d56Sopenharmony_ci data2 = zopen2.read(500) 27457db96d56Sopenharmony_ci data1 += zopen1.read() 27467db96d56Sopenharmony_ci data2 += zopen2.read() 27477db96d56Sopenharmony_ci self.assertEqual(data1, self.data1) 27487db96d56Sopenharmony_ci self.assertEqual(data2, self.data2) 27497db96d56Sopenharmony_ci 27507db96d56Sopenharmony_ci def test_read_after_write(self): 27517db96d56Sopenharmony_ci for f in get_files(self): 27527db96d56Sopenharmony_ci with zipfile.ZipFile(f, 'w', zipfile.ZIP_DEFLATED) as zipf: 27537db96d56Sopenharmony_ci zipf.writestr('ones', self.data1) 27547db96d56Sopenharmony_ci zipf.writestr('twos', self.data2) 27557db96d56Sopenharmony_ci with zipf.open('ones') as zopen1: 27567db96d56Sopenharmony_ci data1 = zopen1.read(500) 27577db96d56Sopenharmony_ci self.assertEqual(data1, self.data1[:500]) 27587db96d56Sopenharmony_ci with zipfile.ZipFile(f, 'r') as zipf: 27597db96d56Sopenharmony_ci data1 = zipf.read('ones') 27607db96d56Sopenharmony_ci data2 = zipf.read('twos') 27617db96d56Sopenharmony_ci self.assertEqual(data1, self.data1) 27627db96d56Sopenharmony_ci self.assertEqual(data2, self.data2) 27637db96d56Sopenharmony_ci 27647db96d56Sopenharmony_ci def test_write_after_read(self): 27657db96d56Sopenharmony_ci for f in get_files(self): 27667db96d56Sopenharmony_ci with zipfile.ZipFile(f, "w", zipfile.ZIP_DEFLATED) as zipf: 27677db96d56Sopenharmony_ci zipf.writestr('ones', self.data1) 27687db96d56Sopenharmony_ci with zipf.open('ones') as zopen1: 27697db96d56Sopenharmony_ci zopen1.read(500) 27707db96d56Sopenharmony_ci zipf.writestr('twos', self.data2) 27717db96d56Sopenharmony_ci with zipfile.ZipFile(f, 'r') as zipf: 27727db96d56Sopenharmony_ci data1 = zipf.read('ones') 27737db96d56Sopenharmony_ci data2 = zipf.read('twos') 27747db96d56Sopenharmony_ci self.assertEqual(data1, self.data1) 27757db96d56Sopenharmony_ci self.assertEqual(data2, self.data2) 27767db96d56Sopenharmony_ci 27777db96d56Sopenharmony_ci def test_many_opens(self): 27787db96d56Sopenharmony_ci # Verify that read() and open() promptly close the file descriptor, 27797db96d56Sopenharmony_ci # and don't rely on the garbage collector to free resources. 27807db96d56Sopenharmony_ci startcount = fd_count() 27817db96d56Sopenharmony_ci self.make_test_archive(TESTFN2) 27827db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, mode="r") as zipf: 27837db96d56Sopenharmony_ci for x in range(100): 27847db96d56Sopenharmony_ci zipf.read('ones') 27857db96d56Sopenharmony_ci with zipf.open('ones') as zopen1: 27867db96d56Sopenharmony_ci pass 27877db96d56Sopenharmony_ci self.assertEqual(startcount, fd_count()) 27887db96d56Sopenharmony_ci 27897db96d56Sopenharmony_ci def test_write_while_reading(self): 27907db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, 'w', zipfile.ZIP_DEFLATED) as zipf: 27917db96d56Sopenharmony_ci zipf.writestr('ones', self.data1) 27927db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2, 'a', zipfile.ZIP_DEFLATED) as zipf: 27937db96d56Sopenharmony_ci with zipf.open('ones', 'r') as r1: 27947db96d56Sopenharmony_ci data1 = r1.read(500) 27957db96d56Sopenharmony_ci with zipf.open('twos', 'w') as w1: 27967db96d56Sopenharmony_ci w1.write(self.data2) 27977db96d56Sopenharmony_ci data1 += r1.read() 27987db96d56Sopenharmony_ci self.assertEqual(data1, self.data1) 27997db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2) as zipf: 28007db96d56Sopenharmony_ci self.assertEqual(zipf.read('twos'), self.data2) 28017db96d56Sopenharmony_ci 28027db96d56Sopenharmony_ci def tearDown(self): 28037db96d56Sopenharmony_ci unlink(TESTFN2) 28047db96d56Sopenharmony_ci 28057db96d56Sopenharmony_ci 28067db96d56Sopenharmony_ciclass TestWithDirectory(unittest.TestCase): 28077db96d56Sopenharmony_ci def setUp(self): 28087db96d56Sopenharmony_ci os.mkdir(TESTFN2) 28097db96d56Sopenharmony_ci 28107db96d56Sopenharmony_ci def test_extract_dir(self): 28117db96d56Sopenharmony_ci with zipfile.ZipFile(findfile("zipdir.zip")) as zipf: 28127db96d56Sopenharmony_ci zipf.extractall(TESTFN2) 28137db96d56Sopenharmony_ci self.assertTrue(os.path.isdir(os.path.join(TESTFN2, "a"))) 28147db96d56Sopenharmony_ci self.assertTrue(os.path.isdir(os.path.join(TESTFN2, "a", "b"))) 28157db96d56Sopenharmony_ci self.assertTrue(os.path.exists(os.path.join(TESTFN2, "a", "b", "c"))) 28167db96d56Sopenharmony_ci 28177db96d56Sopenharmony_ci def test_bug_6050(self): 28187db96d56Sopenharmony_ci # Extraction should succeed if directories already exist 28197db96d56Sopenharmony_ci os.mkdir(os.path.join(TESTFN2, "a")) 28207db96d56Sopenharmony_ci self.test_extract_dir() 28217db96d56Sopenharmony_ci 28227db96d56Sopenharmony_ci def test_write_dir(self): 28237db96d56Sopenharmony_ci dirpath = os.path.join(TESTFN2, "x") 28247db96d56Sopenharmony_ci os.mkdir(dirpath) 28257db96d56Sopenharmony_ci mode = os.stat(dirpath).st_mode & 0xFFFF 28267db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, "w") as zipf: 28277db96d56Sopenharmony_ci zipf.write(dirpath) 28287db96d56Sopenharmony_ci zinfo = zipf.filelist[0] 28297db96d56Sopenharmony_ci self.assertTrue(zinfo.filename.endswith("/x/")) 28307db96d56Sopenharmony_ci self.assertEqual(zinfo.external_attr, (mode << 16) | 0x10) 28317db96d56Sopenharmony_ci zipf.write(dirpath, "y") 28327db96d56Sopenharmony_ci zinfo = zipf.filelist[1] 28337db96d56Sopenharmony_ci self.assertTrue(zinfo.filename, "y/") 28347db96d56Sopenharmony_ci self.assertEqual(zinfo.external_attr, (mode << 16) | 0x10) 28357db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, "r") as zipf: 28367db96d56Sopenharmony_ci zinfo = zipf.filelist[0] 28377db96d56Sopenharmony_ci self.assertTrue(zinfo.filename.endswith("/x/")) 28387db96d56Sopenharmony_ci self.assertEqual(zinfo.external_attr, (mode << 16) | 0x10) 28397db96d56Sopenharmony_ci zinfo = zipf.filelist[1] 28407db96d56Sopenharmony_ci self.assertTrue(zinfo.filename, "y/") 28417db96d56Sopenharmony_ci self.assertEqual(zinfo.external_attr, (mode << 16) | 0x10) 28427db96d56Sopenharmony_ci target = os.path.join(TESTFN2, "target") 28437db96d56Sopenharmony_ci os.mkdir(target) 28447db96d56Sopenharmony_ci zipf.extractall(target) 28457db96d56Sopenharmony_ci self.assertTrue(os.path.isdir(os.path.join(target, "y"))) 28467db96d56Sopenharmony_ci self.assertEqual(len(os.listdir(target)), 2) 28477db96d56Sopenharmony_ci 28487db96d56Sopenharmony_ci def test_writestr_dir(self): 28497db96d56Sopenharmony_ci os.mkdir(os.path.join(TESTFN2, "x")) 28507db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, "w") as zipf: 28517db96d56Sopenharmony_ci zipf.writestr("x/", b'') 28527db96d56Sopenharmony_ci zinfo = zipf.filelist[0] 28537db96d56Sopenharmony_ci self.assertEqual(zinfo.filename, "x/") 28547db96d56Sopenharmony_ci self.assertEqual(zinfo.external_attr, (0o40775 << 16) | 0x10) 28557db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, "r") as zipf: 28567db96d56Sopenharmony_ci zinfo = zipf.filelist[0] 28577db96d56Sopenharmony_ci self.assertTrue(zinfo.filename.endswith("x/")) 28587db96d56Sopenharmony_ci self.assertEqual(zinfo.external_attr, (0o40775 << 16) | 0x10) 28597db96d56Sopenharmony_ci target = os.path.join(TESTFN2, "target") 28607db96d56Sopenharmony_ci os.mkdir(target) 28617db96d56Sopenharmony_ci zipf.extractall(target) 28627db96d56Sopenharmony_ci self.assertTrue(os.path.isdir(os.path.join(target, "x"))) 28637db96d56Sopenharmony_ci self.assertEqual(os.listdir(target), ["x"]) 28647db96d56Sopenharmony_ci 28657db96d56Sopenharmony_ci def test_mkdir(self): 28667db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, "w") as zf: 28677db96d56Sopenharmony_ci zf.mkdir("directory") 28687db96d56Sopenharmony_ci zinfo = zf.filelist[0] 28697db96d56Sopenharmony_ci self.assertEqual(zinfo.filename, "directory/") 28707db96d56Sopenharmony_ci self.assertEqual(zinfo.external_attr, (0o40777 << 16) | 0x10) 28717db96d56Sopenharmony_ci 28727db96d56Sopenharmony_ci zf.mkdir("directory2/") 28737db96d56Sopenharmony_ci zinfo = zf.filelist[1] 28747db96d56Sopenharmony_ci self.assertEqual(zinfo.filename, "directory2/") 28757db96d56Sopenharmony_ci self.assertEqual(zinfo.external_attr, (0o40777 << 16) | 0x10) 28767db96d56Sopenharmony_ci 28777db96d56Sopenharmony_ci zf.mkdir("directory3", mode=0o777) 28787db96d56Sopenharmony_ci zinfo = zf.filelist[2] 28797db96d56Sopenharmony_ci self.assertEqual(zinfo.filename, "directory3/") 28807db96d56Sopenharmony_ci self.assertEqual(zinfo.external_attr, (0o40777 << 16) | 0x10) 28817db96d56Sopenharmony_ci 28827db96d56Sopenharmony_ci old_zinfo = zipfile.ZipInfo("directory4/") 28837db96d56Sopenharmony_ci old_zinfo.external_attr = (0o40777 << 16) | 0x10 28847db96d56Sopenharmony_ci old_zinfo.CRC = 0 28857db96d56Sopenharmony_ci old_zinfo.file_size = 0 28867db96d56Sopenharmony_ci old_zinfo.compress_size = 0 28877db96d56Sopenharmony_ci zf.mkdir(old_zinfo) 28887db96d56Sopenharmony_ci new_zinfo = zf.filelist[3] 28897db96d56Sopenharmony_ci self.assertEqual(old_zinfo.filename, "directory4/") 28907db96d56Sopenharmony_ci self.assertEqual(old_zinfo.external_attr, new_zinfo.external_attr) 28917db96d56Sopenharmony_ci 28927db96d56Sopenharmony_ci target = os.path.join(TESTFN2, "target") 28937db96d56Sopenharmony_ci os.mkdir(target) 28947db96d56Sopenharmony_ci zf.extractall(target) 28957db96d56Sopenharmony_ci self.assertEqual(set(os.listdir(target)), {"directory", "directory2", "directory3", "directory4"}) 28967db96d56Sopenharmony_ci 28977db96d56Sopenharmony_ci def test_create_directory_with_write(self): 28987db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, "w") as zf: 28997db96d56Sopenharmony_ci zf.writestr(zipfile.ZipInfo('directory/'), '') 29007db96d56Sopenharmony_ci 29017db96d56Sopenharmony_ci zinfo = zf.filelist[0] 29027db96d56Sopenharmony_ci self.assertEqual(zinfo.filename, "directory/") 29037db96d56Sopenharmony_ci 29047db96d56Sopenharmony_ci directory = os.path.join(TESTFN2, "directory2") 29057db96d56Sopenharmony_ci os.mkdir(directory) 29067db96d56Sopenharmony_ci mode = os.stat(directory).st_mode 29077db96d56Sopenharmony_ci zf.write(directory, arcname="directory2/") 29087db96d56Sopenharmony_ci zinfo = zf.filelist[1] 29097db96d56Sopenharmony_ci self.assertEqual(zinfo.filename, "directory2/") 29107db96d56Sopenharmony_ci self.assertEqual(zinfo.external_attr, (mode << 16) | 0x10) 29117db96d56Sopenharmony_ci 29127db96d56Sopenharmony_ci target = os.path.join(TESTFN2, "target") 29137db96d56Sopenharmony_ci os.mkdir(target) 29147db96d56Sopenharmony_ci zf.extractall(target) 29157db96d56Sopenharmony_ci 29167db96d56Sopenharmony_ci self.assertEqual(set(os.listdir(target)), {"directory", "directory2"}) 29177db96d56Sopenharmony_ci 29187db96d56Sopenharmony_ci def tearDown(self): 29197db96d56Sopenharmony_ci rmtree(TESTFN2) 29207db96d56Sopenharmony_ci if os.path.exists(TESTFN): 29217db96d56Sopenharmony_ci unlink(TESTFN) 29227db96d56Sopenharmony_ci 29237db96d56Sopenharmony_ci 29247db96d56Sopenharmony_ciclass ZipInfoTests(unittest.TestCase): 29257db96d56Sopenharmony_ci def test_from_file(self): 29267db96d56Sopenharmony_ci zi = zipfile.ZipInfo.from_file(__file__) 29277db96d56Sopenharmony_ci self.assertEqual(posixpath.basename(zi.filename), 'test_zipfile.py') 29287db96d56Sopenharmony_ci self.assertFalse(zi.is_dir()) 29297db96d56Sopenharmony_ci self.assertEqual(zi.file_size, os.path.getsize(__file__)) 29307db96d56Sopenharmony_ci 29317db96d56Sopenharmony_ci def test_from_file_pathlike(self): 29327db96d56Sopenharmony_ci zi = zipfile.ZipInfo.from_file(pathlib.Path(__file__)) 29337db96d56Sopenharmony_ci self.assertEqual(posixpath.basename(zi.filename), 'test_zipfile.py') 29347db96d56Sopenharmony_ci self.assertFalse(zi.is_dir()) 29357db96d56Sopenharmony_ci self.assertEqual(zi.file_size, os.path.getsize(__file__)) 29367db96d56Sopenharmony_ci 29377db96d56Sopenharmony_ci def test_from_file_bytes(self): 29387db96d56Sopenharmony_ci zi = zipfile.ZipInfo.from_file(os.fsencode(__file__), 'test') 29397db96d56Sopenharmony_ci self.assertEqual(posixpath.basename(zi.filename), 'test') 29407db96d56Sopenharmony_ci self.assertFalse(zi.is_dir()) 29417db96d56Sopenharmony_ci self.assertEqual(zi.file_size, os.path.getsize(__file__)) 29427db96d56Sopenharmony_ci 29437db96d56Sopenharmony_ci def test_from_file_fileno(self): 29447db96d56Sopenharmony_ci with open(__file__, 'rb') as f: 29457db96d56Sopenharmony_ci zi = zipfile.ZipInfo.from_file(f.fileno(), 'test') 29467db96d56Sopenharmony_ci self.assertEqual(posixpath.basename(zi.filename), 'test') 29477db96d56Sopenharmony_ci self.assertFalse(zi.is_dir()) 29487db96d56Sopenharmony_ci self.assertEqual(zi.file_size, os.path.getsize(__file__)) 29497db96d56Sopenharmony_ci 29507db96d56Sopenharmony_ci def test_from_dir(self): 29517db96d56Sopenharmony_ci dirpath = os.path.dirname(os.path.abspath(__file__)) 29527db96d56Sopenharmony_ci zi = zipfile.ZipInfo.from_file(dirpath, 'stdlib_tests') 29537db96d56Sopenharmony_ci self.assertEqual(zi.filename, 'stdlib_tests/') 29547db96d56Sopenharmony_ci self.assertTrue(zi.is_dir()) 29557db96d56Sopenharmony_ci self.assertEqual(zi.compress_type, zipfile.ZIP_STORED) 29567db96d56Sopenharmony_ci self.assertEqual(zi.file_size, 0) 29577db96d56Sopenharmony_ci 29587db96d56Sopenharmony_ci 29597db96d56Sopenharmony_ciclass CommandLineTest(unittest.TestCase): 29607db96d56Sopenharmony_ci 29617db96d56Sopenharmony_ci def zipfilecmd(self, *args, **kwargs): 29627db96d56Sopenharmony_ci rc, out, err = script_helper.assert_python_ok('-m', 'zipfile', *args, 29637db96d56Sopenharmony_ci **kwargs) 29647db96d56Sopenharmony_ci return out.replace(os.linesep.encode(), b'\n') 29657db96d56Sopenharmony_ci 29667db96d56Sopenharmony_ci def zipfilecmd_failure(self, *args): 29677db96d56Sopenharmony_ci return script_helper.assert_python_failure('-m', 'zipfile', *args) 29687db96d56Sopenharmony_ci 29697db96d56Sopenharmony_ci def test_bad_use(self): 29707db96d56Sopenharmony_ci rc, out, err = self.zipfilecmd_failure() 29717db96d56Sopenharmony_ci self.assertEqual(out, b'') 29727db96d56Sopenharmony_ci self.assertIn(b'usage', err.lower()) 29737db96d56Sopenharmony_ci self.assertIn(b'error', err.lower()) 29747db96d56Sopenharmony_ci self.assertIn(b'required', err.lower()) 29757db96d56Sopenharmony_ci rc, out, err = self.zipfilecmd_failure('-l', '') 29767db96d56Sopenharmony_ci self.assertEqual(out, b'') 29777db96d56Sopenharmony_ci self.assertNotEqual(err.strip(), b'') 29787db96d56Sopenharmony_ci 29797db96d56Sopenharmony_ci def test_test_command(self): 29807db96d56Sopenharmony_ci zip_name = findfile('zipdir.zip') 29817db96d56Sopenharmony_ci for opt in '-t', '--test': 29827db96d56Sopenharmony_ci out = self.zipfilecmd(opt, zip_name) 29837db96d56Sopenharmony_ci self.assertEqual(out.rstrip(), b'Done testing') 29847db96d56Sopenharmony_ci zip_name = findfile('testtar.tar') 29857db96d56Sopenharmony_ci rc, out, err = self.zipfilecmd_failure('-t', zip_name) 29867db96d56Sopenharmony_ci self.assertEqual(out, b'') 29877db96d56Sopenharmony_ci 29887db96d56Sopenharmony_ci def test_list_command(self): 29897db96d56Sopenharmony_ci zip_name = findfile('zipdir.zip') 29907db96d56Sopenharmony_ci t = io.StringIO() 29917db96d56Sopenharmony_ci with zipfile.ZipFile(zip_name, 'r') as tf: 29927db96d56Sopenharmony_ci tf.printdir(t) 29937db96d56Sopenharmony_ci expected = t.getvalue().encode('ascii', 'backslashreplace') 29947db96d56Sopenharmony_ci for opt in '-l', '--list': 29957db96d56Sopenharmony_ci out = self.zipfilecmd(opt, zip_name, 29967db96d56Sopenharmony_ci PYTHONIOENCODING='ascii:backslashreplace') 29977db96d56Sopenharmony_ci self.assertEqual(out, expected) 29987db96d56Sopenharmony_ci 29997db96d56Sopenharmony_ci @requires_zlib() 30007db96d56Sopenharmony_ci def test_create_command(self): 30017db96d56Sopenharmony_ci self.addCleanup(unlink, TESTFN) 30027db96d56Sopenharmony_ci with open(TESTFN, 'w', encoding='utf-8') as f: 30037db96d56Sopenharmony_ci f.write('test 1') 30047db96d56Sopenharmony_ci os.mkdir(TESTFNDIR) 30057db96d56Sopenharmony_ci self.addCleanup(rmtree, TESTFNDIR) 30067db96d56Sopenharmony_ci with open(os.path.join(TESTFNDIR, 'file.txt'), 'w', encoding='utf-8') as f: 30077db96d56Sopenharmony_ci f.write('test 2') 30087db96d56Sopenharmony_ci files = [TESTFN, TESTFNDIR] 30097db96d56Sopenharmony_ci namelist = [TESTFN, TESTFNDIR + '/', TESTFNDIR + '/file.txt'] 30107db96d56Sopenharmony_ci for opt in '-c', '--create': 30117db96d56Sopenharmony_ci try: 30127db96d56Sopenharmony_ci out = self.zipfilecmd(opt, TESTFN2, *files) 30137db96d56Sopenharmony_ci self.assertEqual(out, b'') 30147db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN2) as zf: 30157db96d56Sopenharmony_ci self.assertEqual(zf.namelist(), namelist) 30167db96d56Sopenharmony_ci self.assertEqual(zf.read(namelist[0]), b'test 1') 30177db96d56Sopenharmony_ci self.assertEqual(zf.read(namelist[2]), b'test 2') 30187db96d56Sopenharmony_ci finally: 30197db96d56Sopenharmony_ci unlink(TESTFN2) 30207db96d56Sopenharmony_ci 30217db96d56Sopenharmony_ci def test_extract_command(self): 30227db96d56Sopenharmony_ci zip_name = findfile('zipdir.zip') 30237db96d56Sopenharmony_ci for opt in '-e', '--extract': 30247db96d56Sopenharmony_ci with temp_dir() as extdir: 30257db96d56Sopenharmony_ci out = self.zipfilecmd(opt, zip_name, extdir) 30267db96d56Sopenharmony_ci self.assertEqual(out, b'') 30277db96d56Sopenharmony_ci with zipfile.ZipFile(zip_name) as zf: 30287db96d56Sopenharmony_ci for zi in zf.infolist(): 30297db96d56Sopenharmony_ci path = os.path.join(extdir, 30307db96d56Sopenharmony_ci zi.filename.replace('/', os.sep)) 30317db96d56Sopenharmony_ci if zi.is_dir(): 30327db96d56Sopenharmony_ci self.assertTrue(os.path.isdir(path)) 30337db96d56Sopenharmony_ci else: 30347db96d56Sopenharmony_ci self.assertTrue(os.path.isfile(path)) 30357db96d56Sopenharmony_ci with open(path, 'rb') as f: 30367db96d56Sopenharmony_ci self.assertEqual(f.read(), zf.read(zi)) 30377db96d56Sopenharmony_ci 30387db96d56Sopenharmony_ci 30397db96d56Sopenharmony_ciclass TestExecutablePrependedZip(unittest.TestCase): 30407db96d56Sopenharmony_ci """Test our ability to open zip files with an executable prepended.""" 30417db96d56Sopenharmony_ci 30427db96d56Sopenharmony_ci def setUp(self): 30437db96d56Sopenharmony_ci self.exe_zip = findfile('exe_with_zip', subdir='ziptestdata') 30447db96d56Sopenharmony_ci self.exe_zip64 = findfile('exe_with_z64', subdir='ziptestdata') 30457db96d56Sopenharmony_ci 30467db96d56Sopenharmony_ci def _test_zip_works(self, name): 30477db96d56Sopenharmony_ci # bpo28494 sanity check: ensure is_zipfile works on these. 30487db96d56Sopenharmony_ci self.assertTrue(zipfile.is_zipfile(name), 30497db96d56Sopenharmony_ci f'is_zipfile failed on {name}') 30507db96d56Sopenharmony_ci # Ensure we can operate on these via ZipFile. 30517db96d56Sopenharmony_ci with zipfile.ZipFile(name) as zipfp: 30527db96d56Sopenharmony_ci for n in zipfp.namelist(): 30537db96d56Sopenharmony_ci data = zipfp.read(n) 30547db96d56Sopenharmony_ci self.assertIn(b'FAVORITE_NUMBER', data) 30557db96d56Sopenharmony_ci 30567db96d56Sopenharmony_ci def test_read_zip_with_exe_prepended(self): 30577db96d56Sopenharmony_ci self._test_zip_works(self.exe_zip) 30587db96d56Sopenharmony_ci 30597db96d56Sopenharmony_ci def test_read_zip64_with_exe_prepended(self): 30607db96d56Sopenharmony_ci self._test_zip_works(self.exe_zip64) 30617db96d56Sopenharmony_ci 30627db96d56Sopenharmony_ci @unittest.skipUnless(sys.executable, 'sys.executable required.') 30637db96d56Sopenharmony_ci @unittest.skipUnless(os.access('/bin/bash', os.X_OK), 30647db96d56Sopenharmony_ci 'Test relies on #!/bin/bash working.') 30657db96d56Sopenharmony_ci @requires_subprocess() 30667db96d56Sopenharmony_ci def test_execute_zip2(self): 30677db96d56Sopenharmony_ci output = subprocess.check_output([self.exe_zip, sys.executable]) 30687db96d56Sopenharmony_ci self.assertIn(b'number in executable: 5', output) 30697db96d56Sopenharmony_ci 30707db96d56Sopenharmony_ci @unittest.skipUnless(sys.executable, 'sys.executable required.') 30717db96d56Sopenharmony_ci @unittest.skipUnless(os.access('/bin/bash', os.X_OK), 30727db96d56Sopenharmony_ci 'Test relies on #!/bin/bash working.') 30737db96d56Sopenharmony_ci @requires_subprocess() 30747db96d56Sopenharmony_ci def test_execute_zip64(self): 30757db96d56Sopenharmony_ci output = subprocess.check_output([self.exe_zip64, sys.executable]) 30767db96d56Sopenharmony_ci self.assertIn(b'number in executable: 5', output) 30777db96d56Sopenharmony_ci 30787db96d56Sopenharmony_ci 30797db96d56Sopenharmony_ci# Poor man's technique to consume a (smallish) iterable. 30807db96d56Sopenharmony_ciconsume = tuple 30817db96d56Sopenharmony_ci 30827db96d56Sopenharmony_ci 30837db96d56Sopenharmony_ci# from jaraco.itertools 5.0 30847db96d56Sopenharmony_ciclass jaraco: 30857db96d56Sopenharmony_ci class itertools: 30867db96d56Sopenharmony_ci class Counter: 30877db96d56Sopenharmony_ci def __init__(self, i): 30887db96d56Sopenharmony_ci self.count = 0 30897db96d56Sopenharmony_ci self._orig_iter = iter(i) 30907db96d56Sopenharmony_ci 30917db96d56Sopenharmony_ci def __iter__(self): 30927db96d56Sopenharmony_ci return self 30937db96d56Sopenharmony_ci 30947db96d56Sopenharmony_ci def __next__(self): 30957db96d56Sopenharmony_ci result = next(self._orig_iter) 30967db96d56Sopenharmony_ci self.count += 1 30977db96d56Sopenharmony_ci return result 30987db96d56Sopenharmony_ci 30997db96d56Sopenharmony_ci 31007db96d56Sopenharmony_cidef add_dirs(zf): 31017db96d56Sopenharmony_ci """ 31027db96d56Sopenharmony_ci Given a writable zip file zf, inject directory entries for 31037db96d56Sopenharmony_ci any directories implied by the presence of children. 31047db96d56Sopenharmony_ci """ 31057db96d56Sopenharmony_ci for name in zipfile.CompleteDirs._implied_dirs(zf.namelist()): 31067db96d56Sopenharmony_ci zf.writestr(name, b"") 31077db96d56Sopenharmony_ci return zf 31087db96d56Sopenharmony_ci 31097db96d56Sopenharmony_ci 31107db96d56Sopenharmony_cidef build_alpharep_fixture(): 31117db96d56Sopenharmony_ci """ 31127db96d56Sopenharmony_ci Create a zip file with this structure: 31137db96d56Sopenharmony_ci 31147db96d56Sopenharmony_ci . 31157db96d56Sopenharmony_ci ├── a.txt 31167db96d56Sopenharmony_ci ├── b 31177db96d56Sopenharmony_ci │ ├── c.txt 31187db96d56Sopenharmony_ci │ ├── d 31197db96d56Sopenharmony_ci │ │ └── e.txt 31207db96d56Sopenharmony_ci │ └── f.txt 31217db96d56Sopenharmony_ci └── g 31227db96d56Sopenharmony_ci └── h 31237db96d56Sopenharmony_ci └── i.txt 31247db96d56Sopenharmony_ci 31257db96d56Sopenharmony_ci This fixture has the following key characteristics: 31267db96d56Sopenharmony_ci 31277db96d56Sopenharmony_ci - a file at the root (a) 31287db96d56Sopenharmony_ci - a file two levels deep (b/d/e) 31297db96d56Sopenharmony_ci - multiple files in a directory (b/c, b/f) 31307db96d56Sopenharmony_ci - a directory containing only a directory (g/h) 31317db96d56Sopenharmony_ci 31327db96d56Sopenharmony_ci "alpha" because it uses alphabet 31337db96d56Sopenharmony_ci "rep" because it's a representative example 31347db96d56Sopenharmony_ci """ 31357db96d56Sopenharmony_ci data = io.BytesIO() 31367db96d56Sopenharmony_ci zf = zipfile.ZipFile(data, "w") 31377db96d56Sopenharmony_ci zf.writestr("a.txt", b"content of a") 31387db96d56Sopenharmony_ci zf.writestr("b/c.txt", b"content of c") 31397db96d56Sopenharmony_ci zf.writestr("b/d/e.txt", b"content of e") 31407db96d56Sopenharmony_ci zf.writestr("b/f.txt", b"content of f") 31417db96d56Sopenharmony_ci zf.writestr("g/h/i.txt", b"content of i") 31427db96d56Sopenharmony_ci zf.filename = "alpharep.zip" 31437db96d56Sopenharmony_ci return zf 31447db96d56Sopenharmony_ci 31457db96d56Sopenharmony_ci 31467db96d56Sopenharmony_cidef pass_alpharep(meth): 31477db96d56Sopenharmony_ci """ 31487db96d56Sopenharmony_ci Given a method, wrap it in a for loop that invokes method 31497db96d56Sopenharmony_ci with each subtest. 31507db96d56Sopenharmony_ci """ 31517db96d56Sopenharmony_ci 31527db96d56Sopenharmony_ci @functools.wraps(meth) 31537db96d56Sopenharmony_ci def wrapper(self): 31547db96d56Sopenharmony_ci for alpharep in self.zipfile_alpharep(): 31557db96d56Sopenharmony_ci meth(self, alpharep=alpharep) 31567db96d56Sopenharmony_ci 31577db96d56Sopenharmony_ci return wrapper 31587db96d56Sopenharmony_ci 31597db96d56Sopenharmony_ci 31607db96d56Sopenharmony_ciclass TestPath(unittest.TestCase): 31617db96d56Sopenharmony_ci def setUp(self): 31627db96d56Sopenharmony_ci self.fixtures = contextlib.ExitStack() 31637db96d56Sopenharmony_ci self.addCleanup(self.fixtures.close) 31647db96d56Sopenharmony_ci 31657db96d56Sopenharmony_ci def zipfile_alpharep(self): 31667db96d56Sopenharmony_ci with self.subTest(): 31677db96d56Sopenharmony_ci yield build_alpharep_fixture() 31687db96d56Sopenharmony_ci with self.subTest(): 31697db96d56Sopenharmony_ci yield add_dirs(build_alpharep_fixture()) 31707db96d56Sopenharmony_ci 31717db96d56Sopenharmony_ci def zipfile_ondisk(self, alpharep): 31727db96d56Sopenharmony_ci tmpdir = pathlib.Path(self.fixtures.enter_context(temp_dir())) 31737db96d56Sopenharmony_ci buffer = alpharep.fp 31747db96d56Sopenharmony_ci alpharep.close() 31757db96d56Sopenharmony_ci path = tmpdir / alpharep.filename 31767db96d56Sopenharmony_ci with path.open("wb") as strm: 31777db96d56Sopenharmony_ci strm.write(buffer.getvalue()) 31787db96d56Sopenharmony_ci return path 31797db96d56Sopenharmony_ci 31807db96d56Sopenharmony_ci @pass_alpharep 31817db96d56Sopenharmony_ci def test_iterdir_and_types(self, alpharep): 31827db96d56Sopenharmony_ci root = zipfile.Path(alpharep) 31837db96d56Sopenharmony_ci assert root.is_dir() 31847db96d56Sopenharmony_ci a, b, g = root.iterdir() 31857db96d56Sopenharmony_ci assert a.is_file() 31867db96d56Sopenharmony_ci assert b.is_dir() 31877db96d56Sopenharmony_ci assert g.is_dir() 31887db96d56Sopenharmony_ci c, f, d = b.iterdir() 31897db96d56Sopenharmony_ci assert c.is_file() and f.is_file() 31907db96d56Sopenharmony_ci (e,) = d.iterdir() 31917db96d56Sopenharmony_ci assert e.is_file() 31927db96d56Sopenharmony_ci (h,) = g.iterdir() 31937db96d56Sopenharmony_ci (i,) = h.iterdir() 31947db96d56Sopenharmony_ci assert i.is_file() 31957db96d56Sopenharmony_ci 31967db96d56Sopenharmony_ci @pass_alpharep 31977db96d56Sopenharmony_ci def test_is_file_missing(self, alpharep): 31987db96d56Sopenharmony_ci root = zipfile.Path(alpharep) 31997db96d56Sopenharmony_ci assert not root.joinpath('missing.txt').is_file() 32007db96d56Sopenharmony_ci 32017db96d56Sopenharmony_ci @pass_alpharep 32027db96d56Sopenharmony_ci def test_iterdir_on_file(self, alpharep): 32037db96d56Sopenharmony_ci root = zipfile.Path(alpharep) 32047db96d56Sopenharmony_ci a, b, g = root.iterdir() 32057db96d56Sopenharmony_ci with self.assertRaises(ValueError): 32067db96d56Sopenharmony_ci a.iterdir() 32077db96d56Sopenharmony_ci 32087db96d56Sopenharmony_ci @pass_alpharep 32097db96d56Sopenharmony_ci def test_subdir_is_dir(self, alpharep): 32107db96d56Sopenharmony_ci root = zipfile.Path(alpharep) 32117db96d56Sopenharmony_ci assert (root / 'b').is_dir() 32127db96d56Sopenharmony_ci assert (root / 'b/').is_dir() 32137db96d56Sopenharmony_ci assert (root / 'g').is_dir() 32147db96d56Sopenharmony_ci assert (root / 'g/').is_dir() 32157db96d56Sopenharmony_ci 32167db96d56Sopenharmony_ci @pass_alpharep 32177db96d56Sopenharmony_ci def test_open(self, alpharep): 32187db96d56Sopenharmony_ci root = zipfile.Path(alpharep) 32197db96d56Sopenharmony_ci a, b, g = root.iterdir() 32207db96d56Sopenharmony_ci with a.open(encoding="utf-8") as strm: 32217db96d56Sopenharmony_ci data = strm.read() 32227db96d56Sopenharmony_ci self.assertEqual(data, "content of a") 32237db96d56Sopenharmony_ci with a.open('r', "utf-8") as strm: # not a kw, no gh-101144 TypeError 32247db96d56Sopenharmony_ci data = strm.read() 32257db96d56Sopenharmony_ci self.assertEqual(data, "content of a") 32267db96d56Sopenharmony_ci 32277db96d56Sopenharmony_ci def test_open_encoding_utf16(self): 32287db96d56Sopenharmony_ci in_memory_file = io.BytesIO() 32297db96d56Sopenharmony_ci zf = zipfile.ZipFile(in_memory_file, "w") 32307db96d56Sopenharmony_ci zf.writestr("path/16.txt", "This was utf-16".encode("utf-16")) 32317db96d56Sopenharmony_ci zf.filename = "test_open_utf16.zip" 32327db96d56Sopenharmony_ci root = zipfile.Path(zf) 32337db96d56Sopenharmony_ci (path,) = root.iterdir() 32347db96d56Sopenharmony_ci u16 = path.joinpath("16.txt") 32357db96d56Sopenharmony_ci with u16.open('r', "utf-16") as strm: 32367db96d56Sopenharmony_ci data = strm.read() 32377db96d56Sopenharmony_ci self.assertEqual(data, "This was utf-16") 32387db96d56Sopenharmony_ci with u16.open(encoding="utf-16") as strm: 32397db96d56Sopenharmony_ci data = strm.read() 32407db96d56Sopenharmony_ci self.assertEqual(data, "This was utf-16") 32417db96d56Sopenharmony_ci 32427db96d56Sopenharmony_ci def test_open_encoding_errors(self): 32437db96d56Sopenharmony_ci in_memory_file = io.BytesIO() 32447db96d56Sopenharmony_ci zf = zipfile.ZipFile(in_memory_file, "w") 32457db96d56Sopenharmony_ci zf.writestr("path/bad-utf8.bin", b"invalid utf-8: \xff\xff.") 32467db96d56Sopenharmony_ci zf.filename = "test_read_text_encoding_errors.zip" 32477db96d56Sopenharmony_ci root = zipfile.Path(zf) 32487db96d56Sopenharmony_ci (path,) = root.iterdir() 32497db96d56Sopenharmony_ci u16 = path.joinpath("bad-utf8.bin") 32507db96d56Sopenharmony_ci 32517db96d56Sopenharmony_ci # encoding= as a positional argument for gh-101144. 32527db96d56Sopenharmony_ci data = u16.read_text("utf-8", errors="ignore") 32537db96d56Sopenharmony_ci self.assertEqual(data, "invalid utf-8: .") 32547db96d56Sopenharmony_ci with u16.open("r", "utf-8", errors="surrogateescape") as f: 32557db96d56Sopenharmony_ci self.assertEqual(f.read(), "invalid utf-8: \udcff\udcff.") 32567db96d56Sopenharmony_ci 32577db96d56Sopenharmony_ci # encoding= both positional and keyword is an error; gh-101144. 32587db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, "encoding"): 32597db96d56Sopenharmony_ci data = u16.read_text("utf-8", encoding="utf-8") 32607db96d56Sopenharmony_ci 32617db96d56Sopenharmony_ci # both keyword arguments work. 32627db96d56Sopenharmony_ci with u16.open("r", encoding="utf-8", errors="strict") as f: 32637db96d56Sopenharmony_ci # error during decoding with wrong codec. 32647db96d56Sopenharmony_ci with self.assertRaises(UnicodeDecodeError): 32657db96d56Sopenharmony_ci f.read() 32667db96d56Sopenharmony_ci 32677db96d56Sopenharmony_ci def test_encoding_warnings(self): 32687db96d56Sopenharmony_ci """EncodingWarning must blame the read_text and open calls.""" 32697db96d56Sopenharmony_ci code = '''\ 32707db96d56Sopenharmony_ciimport io, zipfile 32717db96d56Sopenharmony_ciwith zipfile.ZipFile(io.BytesIO(), "w") as zf: 32727db96d56Sopenharmony_ci zf.filename = '<test_encoding_warnings in memory zip file>' 32737db96d56Sopenharmony_ci zf.writestr("path/file.txt", b"Spanish Inquisition") 32747db96d56Sopenharmony_ci root = zipfile.Path(zf) 32757db96d56Sopenharmony_ci (path,) = root.iterdir() 32767db96d56Sopenharmony_ci file_path = path.joinpath("file.txt") 32777db96d56Sopenharmony_ci unused = file_path.read_text() # should warn 32787db96d56Sopenharmony_ci file_path.open("r").close() # should warn 32797db96d56Sopenharmony_ci''' 32807db96d56Sopenharmony_ci proc = assert_python_ok('-X', 'warn_default_encoding', '-c', code) 32817db96d56Sopenharmony_ci warnings = proc.err.splitlines() 32827db96d56Sopenharmony_ci self.assertEqual(len(warnings), 2, proc.err) 32837db96d56Sopenharmony_ci self.assertRegex(warnings[0], rb"^<string>:8: EncodingWarning:") 32847db96d56Sopenharmony_ci self.assertRegex(warnings[1], rb"^<string>:9: EncodingWarning:") 32857db96d56Sopenharmony_ci 32867db96d56Sopenharmony_ci def test_open_write(self): 32877db96d56Sopenharmony_ci """ 32887db96d56Sopenharmony_ci If the zipfile is open for write, it should be possible to 32897db96d56Sopenharmony_ci write bytes or text to it. 32907db96d56Sopenharmony_ci """ 32917db96d56Sopenharmony_ci zf = zipfile.Path(zipfile.ZipFile(io.BytesIO(), mode='w')) 32927db96d56Sopenharmony_ci with zf.joinpath('file.bin').open('wb') as strm: 32937db96d56Sopenharmony_ci strm.write(b'binary contents') 32947db96d56Sopenharmony_ci with zf.joinpath('file.txt').open('w', encoding="utf-8") as strm: 32957db96d56Sopenharmony_ci strm.write('text file') 32967db96d56Sopenharmony_ci 32977db96d56Sopenharmony_ci def test_open_extant_directory(self): 32987db96d56Sopenharmony_ci """ 32997db96d56Sopenharmony_ci Attempting to open a directory raises IsADirectoryError. 33007db96d56Sopenharmony_ci """ 33017db96d56Sopenharmony_ci zf = zipfile.Path(add_dirs(build_alpharep_fixture())) 33027db96d56Sopenharmony_ci with self.assertRaises(IsADirectoryError): 33037db96d56Sopenharmony_ci zf.joinpath('b').open() 33047db96d56Sopenharmony_ci 33057db96d56Sopenharmony_ci @pass_alpharep 33067db96d56Sopenharmony_ci def test_open_binary_invalid_args(self, alpharep): 33077db96d56Sopenharmony_ci root = zipfile.Path(alpharep) 33087db96d56Sopenharmony_ci with self.assertRaises(ValueError): 33097db96d56Sopenharmony_ci root.joinpath('a.txt').open('rb', encoding='utf-8') 33107db96d56Sopenharmony_ci with self.assertRaises(ValueError): 33117db96d56Sopenharmony_ci root.joinpath('a.txt').open('rb', 'utf-8') 33127db96d56Sopenharmony_ci 33137db96d56Sopenharmony_ci def test_open_missing_directory(self): 33147db96d56Sopenharmony_ci """ 33157db96d56Sopenharmony_ci Attempting to open a missing directory raises FileNotFoundError. 33167db96d56Sopenharmony_ci """ 33177db96d56Sopenharmony_ci zf = zipfile.Path(add_dirs(build_alpharep_fixture())) 33187db96d56Sopenharmony_ci with self.assertRaises(FileNotFoundError): 33197db96d56Sopenharmony_ci zf.joinpath('z').open() 33207db96d56Sopenharmony_ci 33217db96d56Sopenharmony_ci @pass_alpharep 33227db96d56Sopenharmony_ci def test_read(self, alpharep): 33237db96d56Sopenharmony_ci root = zipfile.Path(alpharep) 33247db96d56Sopenharmony_ci a, b, g = root.iterdir() 33257db96d56Sopenharmony_ci assert a.read_text(encoding="utf-8") == "content of a" 33267db96d56Sopenharmony_ci a.read_text("utf-8") # No positional arg TypeError per gh-101144. 33277db96d56Sopenharmony_ci assert a.read_bytes() == b"content of a" 33287db96d56Sopenharmony_ci 33297db96d56Sopenharmony_ci @pass_alpharep 33307db96d56Sopenharmony_ci def test_joinpath(self, alpharep): 33317db96d56Sopenharmony_ci root = zipfile.Path(alpharep) 33327db96d56Sopenharmony_ci a = root.joinpath("a.txt") 33337db96d56Sopenharmony_ci assert a.is_file() 33347db96d56Sopenharmony_ci e = root.joinpath("b").joinpath("d").joinpath("e.txt") 33357db96d56Sopenharmony_ci assert e.read_text(encoding="utf-8") == "content of e" 33367db96d56Sopenharmony_ci 33377db96d56Sopenharmony_ci @pass_alpharep 33387db96d56Sopenharmony_ci def test_joinpath_multiple(self, alpharep): 33397db96d56Sopenharmony_ci root = zipfile.Path(alpharep) 33407db96d56Sopenharmony_ci e = root.joinpath("b", "d", "e.txt") 33417db96d56Sopenharmony_ci assert e.read_text(encoding="utf-8") == "content of e" 33427db96d56Sopenharmony_ci 33437db96d56Sopenharmony_ci @pass_alpharep 33447db96d56Sopenharmony_ci def test_traverse_truediv(self, alpharep): 33457db96d56Sopenharmony_ci root = zipfile.Path(alpharep) 33467db96d56Sopenharmony_ci a = root / "a.txt" 33477db96d56Sopenharmony_ci assert a.is_file() 33487db96d56Sopenharmony_ci e = root / "b" / "d" / "e.txt" 33497db96d56Sopenharmony_ci assert e.read_text(encoding="utf-8") == "content of e" 33507db96d56Sopenharmony_ci 33517db96d56Sopenharmony_ci @pass_alpharep 33527db96d56Sopenharmony_ci def test_traverse_simplediv(self, alpharep): 33537db96d56Sopenharmony_ci """ 33547db96d56Sopenharmony_ci Disable the __future__.division when testing traversal. 33557db96d56Sopenharmony_ci """ 33567db96d56Sopenharmony_ci code = compile( 33577db96d56Sopenharmony_ci source="zipfile.Path(alpharep) / 'a'", 33587db96d56Sopenharmony_ci filename="(test)", 33597db96d56Sopenharmony_ci mode="eval", 33607db96d56Sopenharmony_ci dont_inherit=True, 33617db96d56Sopenharmony_ci ) 33627db96d56Sopenharmony_ci eval(code) 33637db96d56Sopenharmony_ci 33647db96d56Sopenharmony_ci @pass_alpharep 33657db96d56Sopenharmony_ci def test_pathlike_construction(self, alpharep): 33667db96d56Sopenharmony_ci """ 33677db96d56Sopenharmony_ci zipfile.Path should be constructable from a path-like object 33687db96d56Sopenharmony_ci """ 33697db96d56Sopenharmony_ci zipfile_ondisk = self.zipfile_ondisk(alpharep) 33707db96d56Sopenharmony_ci pathlike = pathlib.Path(str(zipfile_ondisk)) 33717db96d56Sopenharmony_ci zipfile.Path(pathlike) 33727db96d56Sopenharmony_ci 33737db96d56Sopenharmony_ci @pass_alpharep 33747db96d56Sopenharmony_ci def test_traverse_pathlike(self, alpharep): 33757db96d56Sopenharmony_ci root = zipfile.Path(alpharep) 33767db96d56Sopenharmony_ci root / pathlib.Path("a") 33777db96d56Sopenharmony_ci 33787db96d56Sopenharmony_ci @pass_alpharep 33797db96d56Sopenharmony_ci def test_parent(self, alpharep): 33807db96d56Sopenharmony_ci root = zipfile.Path(alpharep) 33817db96d56Sopenharmony_ci assert (root / 'a').parent.at == '' 33827db96d56Sopenharmony_ci assert (root / 'a' / 'b').parent.at == 'a/' 33837db96d56Sopenharmony_ci 33847db96d56Sopenharmony_ci @pass_alpharep 33857db96d56Sopenharmony_ci def test_dir_parent(self, alpharep): 33867db96d56Sopenharmony_ci root = zipfile.Path(alpharep) 33877db96d56Sopenharmony_ci assert (root / 'b').parent.at == '' 33887db96d56Sopenharmony_ci assert (root / 'b/').parent.at == '' 33897db96d56Sopenharmony_ci 33907db96d56Sopenharmony_ci @pass_alpharep 33917db96d56Sopenharmony_ci def test_missing_dir_parent(self, alpharep): 33927db96d56Sopenharmony_ci root = zipfile.Path(alpharep) 33937db96d56Sopenharmony_ci assert (root / 'missing dir/').parent.at == '' 33947db96d56Sopenharmony_ci 33957db96d56Sopenharmony_ci @pass_alpharep 33967db96d56Sopenharmony_ci def test_mutability(self, alpharep): 33977db96d56Sopenharmony_ci """ 33987db96d56Sopenharmony_ci If the underlying zipfile is changed, the Path object should 33997db96d56Sopenharmony_ci reflect that change. 34007db96d56Sopenharmony_ci """ 34017db96d56Sopenharmony_ci root = zipfile.Path(alpharep) 34027db96d56Sopenharmony_ci a, b, g = root.iterdir() 34037db96d56Sopenharmony_ci alpharep.writestr('foo.txt', 'foo') 34047db96d56Sopenharmony_ci alpharep.writestr('bar/baz.txt', 'baz') 34057db96d56Sopenharmony_ci assert any(child.name == 'foo.txt' for child in root.iterdir()) 34067db96d56Sopenharmony_ci assert (root / 'foo.txt').read_text(encoding="utf-8") == 'foo' 34077db96d56Sopenharmony_ci (baz,) = (root / 'bar').iterdir() 34087db96d56Sopenharmony_ci assert baz.read_text(encoding="utf-8") == 'baz' 34097db96d56Sopenharmony_ci 34107db96d56Sopenharmony_ci HUGE_ZIPFILE_NUM_ENTRIES = 2 ** 13 34117db96d56Sopenharmony_ci 34127db96d56Sopenharmony_ci def huge_zipfile(self): 34137db96d56Sopenharmony_ci """Create a read-only zipfile with a huge number of entries entries.""" 34147db96d56Sopenharmony_ci strm = io.BytesIO() 34157db96d56Sopenharmony_ci zf = zipfile.ZipFile(strm, "w") 34167db96d56Sopenharmony_ci for entry in map(str, range(self.HUGE_ZIPFILE_NUM_ENTRIES)): 34177db96d56Sopenharmony_ci zf.writestr(entry, entry) 34187db96d56Sopenharmony_ci zf.mode = 'r' 34197db96d56Sopenharmony_ci return zf 34207db96d56Sopenharmony_ci 34217db96d56Sopenharmony_ci def test_joinpath_constant_time(self): 34227db96d56Sopenharmony_ci """ 34237db96d56Sopenharmony_ci Ensure joinpath on items in zipfile is linear time. 34247db96d56Sopenharmony_ci """ 34257db96d56Sopenharmony_ci root = zipfile.Path(self.huge_zipfile()) 34267db96d56Sopenharmony_ci entries = jaraco.itertools.Counter(root.iterdir()) 34277db96d56Sopenharmony_ci for entry in entries: 34287db96d56Sopenharmony_ci entry.joinpath('suffix') 34297db96d56Sopenharmony_ci # Check the file iterated all items 34307db96d56Sopenharmony_ci assert entries.count == self.HUGE_ZIPFILE_NUM_ENTRIES 34317db96d56Sopenharmony_ci 34327db96d56Sopenharmony_ci # @func_timeout.func_set_timeout(3) 34337db96d56Sopenharmony_ci def test_implied_dirs_performance(self): 34347db96d56Sopenharmony_ci data = ['/'.join(string.ascii_lowercase + str(n)) for n in range(10000)] 34357db96d56Sopenharmony_ci zipfile.CompleteDirs._implied_dirs(data) 34367db96d56Sopenharmony_ci 34377db96d56Sopenharmony_ci @pass_alpharep 34387db96d56Sopenharmony_ci def test_read_does_not_close(self, alpharep): 34397db96d56Sopenharmony_ci alpharep = self.zipfile_ondisk(alpharep) 34407db96d56Sopenharmony_ci with zipfile.ZipFile(alpharep) as file: 34417db96d56Sopenharmony_ci for rep in range(2): 34427db96d56Sopenharmony_ci zipfile.Path(file, 'a.txt').read_text(encoding="utf-8") 34437db96d56Sopenharmony_ci 34447db96d56Sopenharmony_ci @pass_alpharep 34457db96d56Sopenharmony_ci def test_subclass(self, alpharep): 34467db96d56Sopenharmony_ci class Subclass(zipfile.Path): 34477db96d56Sopenharmony_ci pass 34487db96d56Sopenharmony_ci 34497db96d56Sopenharmony_ci root = Subclass(alpharep) 34507db96d56Sopenharmony_ci assert isinstance(root / 'b', Subclass) 34517db96d56Sopenharmony_ci 34527db96d56Sopenharmony_ci @pass_alpharep 34537db96d56Sopenharmony_ci def test_filename(self, alpharep): 34547db96d56Sopenharmony_ci root = zipfile.Path(alpharep) 34557db96d56Sopenharmony_ci assert root.filename == pathlib.Path('alpharep.zip') 34567db96d56Sopenharmony_ci 34577db96d56Sopenharmony_ci @pass_alpharep 34587db96d56Sopenharmony_ci def test_root_name(self, alpharep): 34597db96d56Sopenharmony_ci """ 34607db96d56Sopenharmony_ci The name of the root should be the name of the zipfile 34617db96d56Sopenharmony_ci """ 34627db96d56Sopenharmony_ci root = zipfile.Path(alpharep) 34637db96d56Sopenharmony_ci assert root.name == 'alpharep.zip' == root.filename.name 34647db96d56Sopenharmony_ci 34657db96d56Sopenharmony_ci @pass_alpharep 34667db96d56Sopenharmony_ci def test_suffix(self, alpharep): 34677db96d56Sopenharmony_ci """ 34687db96d56Sopenharmony_ci The suffix of the root should be the suffix of the zipfile. 34697db96d56Sopenharmony_ci The suffix of each nested file is the final component's last suffix, if any. 34707db96d56Sopenharmony_ci Includes the leading period, just like pathlib.Path. 34717db96d56Sopenharmony_ci """ 34727db96d56Sopenharmony_ci root = zipfile.Path(alpharep) 34737db96d56Sopenharmony_ci assert root.suffix == '.zip' == root.filename.suffix 34747db96d56Sopenharmony_ci 34757db96d56Sopenharmony_ci b = root / "b.txt" 34767db96d56Sopenharmony_ci assert b.suffix == ".txt" 34777db96d56Sopenharmony_ci 34787db96d56Sopenharmony_ci c = root / "c" / "filename.tar.gz" 34797db96d56Sopenharmony_ci assert c.suffix == ".gz" 34807db96d56Sopenharmony_ci 34817db96d56Sopenharmony_ci d = root / "d" 34827db96d56Sopenharmony_ci assert d.suffix == "" 34837db96d56Sopenharmony_ci 34847db96d56Sopenharmony_ci @pass_alpharep 34857db96d56Sopenharmony_ci def test_suffixes(self, alpharep): 34867db96d56Sopenharmony_ci """ 34877db96d56Sopenharmony_ci The suffix of the root should be the suffix of the zipfile. 34887db96d56Sopenharmony_ci The suffix of each nested file is the final component's last suffix, if any. 34897db96d56Sopenharmony_ci Includes the leading period, just like pathlib.Path. 34907db96d56Sopenharmony_ci """ 34917db96d56Sopenharmony_ci root = zipfile.Path(alpharep) 34927db96d56Sopenharmony_ci assert root.suffixes == ['.zip'] == root.filename.suffixes 34937db96d56Sopenharmony_ci 34947db96d56Sopenharmony_ci b = root / 'b.txt' 34957db96d56Sopenharmony_ci assert b.suffixes == ['.txt'] 34967db96d56Sopenharmony_ci 34977db96d56Sopenharmony_ci c = root / 'c' / 'filename.tar.gz' 34987db96d56Sopenharmony_ci assert c.suffixes == ['.tar', '.gz'] 34997db96d56Sopenharmony_ci 35007db96d56Sopenharmony_ci d = root / 'd' 35017db96d56Sopenharmony_ci assert d.suffixes == [] 35027db96d56Sopenharmony_ci 35037db96d56Sopenharmony_ci e = root / '.hgrc' 35047db96d56Sopenharmony_ci assert e.suffixes == [] 35057db96d56Sopenharmony_ci 35067db96d56Sopenharmony_ci @pass_alpharep 35077db96d56Sopenharmony_ci def test_stem(self, alpharep): 35087db96d56Sopenharmony_ci """ 35097db96d56Sopenharmony_ci The final path component, without its suffix 35107db96d56Sopenharmony_ci """ 35117db96d56Sopenharmony_ci root = zipfile.Path(alpharep) 35127db96d56Sopenharmony_ci assert root.stem == 'alpharep' == root.filename.stem 35137db96d56Sopenharmony_ci 35147db96d56Sopenharmony_ci b = root / "b.txt" 35157db96d56Sopenharmony_ci assert b.stem == "b" 35167db96d56Sopenharmony_ci 35177db96d56Sopenharmony_ci c = root / "c" / "filename.tar.gz" 35187db96d56Sopenharmony_ci assert c.stem == "filename.tar" 35197db96d56Sopenharmony_ci 35207db96d56Sopenharmony_ci d = root / "d" 35217db96d56Sopenharmony_ci assert d.stem == "d" 35227db96d56Sopenharmony_ci 35237db96d56Sopenharmony_ci @pass_alpharep 35247db96d56Sopenharmony_ci def test_root_parent(self, alpharep): 35257db96d56Sopenharmony_ci root = zipfile.Path(alpharep) 35267db96d56Sopenharmony_ci assert root.parent == pathlib.Path('.') 35277db96d56Sopenharmony_ci root.root.filename = 'foo/bar.zip' 35287db96d56Sopenharmony_ci assert root.parent == pathlib.Path('foo') 35297db96d56Sopenharmony_ci 35307db96d56Sopenharmony_ci @pass_alpharep 35317db96d56Sopenharmony_ci def test_root_unnamed(self, alpharep): 35327db96d56Sopenharmony_ci """ 35337db96d56Sopenharmony_ci It is an error to attempt to get the name 35347db96d56Sopenharmony_ci or parent of an unnamed zipfile. 35357db96d56Sopenharmony_ci """ 35367db96d56Sopenharmony_ci alpharep.filename = None 35377db96d56Sopenharmony_ci root = zipfile.Path(alpharep) 35387db96d56Sopenharmony_ci with self.assertRaises(TypeError): 35397db96d56Sopenharmony_ci root.name 35407db96d56Sopenharmony_ci with self.assertRaises(TypeError): 35417db96d56Sopenharmony_ci root.parent 35427db96d56Sopenharmony_ci 35437db96d56Sopenharmony_ci # .name and .parent should still work on subs 35447db96d56Sopenharmony_ci sub = root / "b" 35457db96d56Sopenharmony_ci assert sub.name == "b" 35467db96d56Sopenharmony_ci assert sub.parent 35477db96d56Sopenharmony_ci 35487db96d56Sopenharmony_ci @pass_alpharep 35497db96d56Sopenharmony_ci def test_inheritance(self, alpharep): 35507db96d56Sopenharmony_ci cls = type('PathChild', (zipfile.Path,), {}) 35517db96d56Sopenharmony_ci for alpharep in self.zipfile_alpharep(): 35527db96d56Sopenharmony_ci file = cls(alpharep).joinpath('some dir').parent 35537db96d56Sopenharmony_ci assert isinstance(file, cls) 35547db96d56Sopenharmony_ci 35557db96d56Sopenharmony_ci @pass_alpharep 35567db96d56Sopenharmony_ci def test_extract_orig_with_implied_dirs(self, alpharep): 35577db96d56Sopenharmony_ci """ 35587db96d56Sopenharmony_ci A zip file wrapped in a Path should extract even with implied dirs. 35597db96d56Sopenharmony_ci """ 35607db96d56Sopenharmony_ci source_path = self.zipfile_ondisk(alpharep) 35617db96d56Sopenharmony_ci zf = zipfile.ZipFile(source_path) 35627db96d56Sopenharmony_ci # wrap the zipfile for its side effect 35637db96d56Sopenharmony_ci zipfile.Path(zf) 35647db96d56Sopenharmony_ci zf.extractall(source_path.parent) 35657db96d56Sopenharmony_ci 35667db96d56Sopenharmony_ci def test_malformed_paths(self): 35677db96d56Sopenharmony_ci """ 35687db96d56Sopenharmony_ci Path should handle malformed paths. 35697db96d56Sopenharmony_ci """ 35707db96d56Sopenharmony_ci data = io.BytesIO() 35717db96d56Sopenharmony_ci zf = zipfile.ZipFile(data, "w") 35727db96d56Sopenharmony_ci zf.writestr("/one-slash.txt", b"content") 35737db96d56Sopenharmony_ci zf.writestr("//two-slash.txt", b"content") 35747db96d56Sopenharmony_ci zf.writestr("../parent.txt", b"content") 35757db96d56Sopenharmony_ci zf.filename = '' 35767db96d56Sopenharmony_ci root = zipfile.Path(zf) 35777db96d56Sopenharmony_ci assert list(map(str, root.iterdir())) == [ 35787db96d56Sopenharmony_ci 'one-slash.txt', 35797db96d56Sopenharmony_ci 'two-slash.txt', 35807db96d56Sopenharmony_ci 'parent.txt', 35817db96d56Sopenharmony_ci ] 35827db96d56Sopenharmony_ci 35837db96d56Sopenharmony_ci 35847db96d56Sopenharmony_ciclass EncodedMetadataTests(unittest.TestCase): 35857db96d56Sopenharmony_ci file_names = ['\u4e00', '\u4e8c', '\u4e09'] # Han 'one', 'two', 'three' 35867db96d56Sopenharmony_ci file_content = [ 35877db96d56Sopenharmony_ci "This is pure ASCII.\n".encode('ascii'), 35887db96d56Sopenharmony_ci # This is modern Japanese. (UTF-8) 35897db96d56Sopenharmony_ci "\u3053\u308c\u306f\u73fe\u4ee3\u7684\u65e5\u672c\u8a9e\u3067\u3059\u3002\n".encode('utf-8'), 35907db96d56Sopenharmony_ci # This is obsolete Japanese. (Shift JIS) 35917db96d56Sopenharmony_ci "\u3053\u308c\u306f\u53e4\u3044\u65e5\u672c\u8a9e\u3067\u3059\u3002\n".encode('shift_jis'), 35927db96d56Sopenharmony_ci ] 35937db96d56Sopenharmony_ci 35947db96d56Sopenharmony_ci def setUp(self): 35957db96d56Sopenharmony_ci self.addCleanup(unlink, TESTFN) 35967db96d56Sopenharmony_ci # Create .zip of 3 members with Han names encoded in Shift JIS. 35977db96d56Sopenharmony_ci # Each name is 1 Han character encoding to 2 bytes in Shift JIS. 35987db96d56Sopenharmony_ci # The ASCII names are arbitrary as long as they are length 2 and 35997db96d56Sopenharmony_ci # not otherwise contained in the zip file. 36007db96d56Sopenharmony_ci # Data elements are encoded bytes (ascii, utf-8, shift_jis). 36017db96d56Sopenharmony_ci placeholders = ["n1", "n2"] + self.file_names[2:] 36027db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, mode="w") as tf: 36037db96d56Sopenharmony_ci for temp, content in zip(placeholders, self.file_content): 36047db96d56Sopenharmony_ci tf.writestr(temp, content, zipfile.ZIP_STORED) 36057db96d56Sopenharmony_ci # Hack in the Shift JIS names with flag bit 11 (UTF-8) unset. 36067db96d56Sopenharmony_ci with open(TESTFN, "rb") as tf: 36077db96d56Sopenharmony_ci data = tf.read() 36087db96d56Sopenharmony_ci for name, temp in zip(self.file_names, placeholders[:2]): 36097db96d56Sopenharmony_ci data = data.replace(temp.encode('ascii'), 36107db96d56Sopenharmony_ci name.encode('shift_jis')) 36117db96d56Sopenharmony_ci with open(TESTFN, "wb") as tf: 36127db96d56Sopenharmony_ci tf.write(data) 36137db96d56Sopenharmony_ci 36147db96d56Sopenharmony_ci def _test_read(self, zipfp, expected_names, expected_content): 36157db96d56Sopenharmony_ci # Check the namelist 36167db96d56Sopenharmony_ci names = zipfp.namelist() 36177db96d56Sopenharmony_ci self.assertEqual(sorted(names), sorted(expected_names)) 36187db96d56Sopenharmony_ci 36197db96d56Sopenharmony_ci # Check infolist 36207db96d56Sopenharmony_ci infos = zipfp.infolist() 36217db96d56Sopenharmony_ci names = [zi.filename for zi in infos] 36227db96d56Sopenharmony_ci self.assertEqual(sorted(names), sorted(expected_names)) 36237db96d56Sopenharmony_ci 36247db96d56Sopenharmony_ci # check getinfo 36257db96d56Sopenharmony_ci for name, content in zip(expected_names, expected_content): 36267db96d56Sopenharmony_ci info = zipfp.getinfo(name) 36277db96d56Sopenharmony_ci self.assertEqual(info.filename, name) 36287db96d56Sopenharmony_ci self.assertEqual(info.file_size, len(content)) 36297db96d56Sopenharmony_ci self.assertEqual(zipfp.read(name), content) 36307db96d56Sopenharmony_ci 36317db96d56Sopenharmony_ci def test_read_with_metadata_encoding(self): 36327db96d56Sopenharmony_ci # Read the ZIP archive with correct metadata_encoding 36337db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, "r", metadata_encoding='shift_jis') as zipfp: 36347db96d56Sopenharmony_ci self._test_read(zipfp, self.file_names, self.file_content) 36357db96d56Sopenharmony_ci 36367db96d56Sopenharmony_ci def test_read_without_metadata_encoding(self): 36377db96d56Sopenharmony_ci # Read the ZIP archive without metadata_encoding 36387db96d56Sopenharmony_ci expected_names = [name.encode('shift_jis').decode('cp437') 36397db96d56Sopenharmony_ci for name in self.file_names[:2]] + self.file_names[2:] 36407db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, "r") as zipfp: 36417db96d56Sopenharmony_ci self._test_read(zipfp, expected_names, self.file_content) 36427db96d56Sopenharmony_ci 36437db96d56Sopenharmony_ci def test_read_with_incorrect_metadata_encoding(self): 36447db96d56Sopenharmony_ci # Read the ZIP archive with incorrect metadata_encoding 36457db96d56Sopenharmony_ci expected_names = [name.encode('shift_jis').decode('koi8-u') 36467db96d56Sopenharmony_ci for name in self.file_names[:2]] + self.file_names[2:] 36477db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, "r", metadata_encoding='koi8-u') as zipfp: 36487db96d56Sopenharmony_ci self._test_read(zipfp, expected_names, self.file_content) 36497db96d56Sopenharmony_ci 36507db96d56Sopenharmony_ci def test_read_with_unsuitable_metadata_encoding(self): 36517db96d56Sopenharmony_ci # Read the ZIP archive with metadata_encoding unsuitable for 36527db96d56Sopenharmony_ci # decoding metadata 36537db96d56Sopenharmony_ci with self.assertRaises(UnicodeDecodeError): 36547db96d56Sopenharmony_ci zipfile.ZipFile(TESTFN, "r", metadata_encoding='ascii') 36557db96d56Sopenharmony_ci with self.assertRaises(UnicodeDecodeError): 36567db96d56Sopenharmony_ci zipfile.ZipFile(TESTFN, "r", metadata_encoding='utf-8') 36577db96d56Sopenharmony_ci 36587db96d56Sopenharmony_ci def test_read_after_append(self): 36597db96d56Sopenharmony_ci newname = '\u56db' # Han 'four' 36607db96d56Sopenharmony_ci expected_names = [name.encode('shift_jis').decode('cp437') 36617db96d56Sopenharmony_ci for name in self.file_names[:2]] + self.file_names[2:] 36627db96d56Sopenharmony_ci expected_names.append(newname) 36637db96d56Sopenharmony_ci expected_content = (*self.file_content, b"newcontent") 36647db96d56Sopenharmony_ci 36657db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, "a") as zipfp: 36667db96d56Sopenharmony_ci zipfp.writestr(newname, "newcontent") 36677db96d56Sopenharmony_ci self.assertEqual(sorted(zipfp.namelist()), sorted(expected_names)) 36687db96d56Sopenharmony_ci 36697db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, "r") as zipfp: 36707db96d56Sopenharmony_ci self._test_read(zipfp, expected_names, expected_content) 36717db96d56Sopenharmony_ci 36727db96d56Sopenharmony_ci with zipfile.ZipFile(TESTFN, "r", metadata_encoding='shift_jis') as zipfp: 36737db96d56Sopenharmony_ci self.assertEqual(sorted(zipfp.namelist()), sorted(expected_names)) 36747db96d56Sopenharmony_ci for i, (name, content) in enumerate(zip(expected_names, expected_content)): 36757db96d56Sopenharmony_ci info = zipfp.getinfo(name) 36767db96d56Sopenharmony_ci self.assertEqual(info.filename, name) 36777db96d56Sopenharmony_ci self.assertEqual(info.file_size, len(content)) 36787db96d56Sopenharmony_ci if i < 2: 36797db96d56Sopenharmony_ci with self.assertRaises(zipfile.BadZipFile): 36807db96d56Sopenharmony_ci zipfp.read(name) 36817db96d56Sopenharmony_ci else: 36827db96d56Sopenharmony_ci self.assertEqual(zipfp.read(name), content) 36837db96d56Sopenharmony_ci 36847db96d56Sopenharmony_ci def test_write_with_metadata_encoding(self): 36857db96d56Sopenharmony_ci ZF = zipfile.ZipFile 36867db96d56Sopenharmony_ci for mode in ("w", "x", "a"): 36877db96d56Sopenharmony_ci with self.assertRaisesRegex(ValueError, 36887db96d56Sopenharmony_ci "^metadata_encoding is only"): 36897db96d56Sopenharmony_ci ZF("nonesuch.zip", mode, metadata_encoding="shift_jis") 36907db96d56Sopenharmony_ci 36917db96d56Sopenharmony_ci def test_cli_with_metadata_encoding(self): 36927db96d56Sopenharmony_ci errmsg = "Non-conforming encodings not supported with -c." 36937db96d56Sopenharmony_ci args = ["--metadata-encoding=shift_jis", "-c", "nonesuch", "nonesuch"] 36947db96d56Sopenharmony_ci with captured_stdout() as stdout: 36957db96d56Sopenharmony_ci with captured_stderr() as stderr: 36967db96d56Sopenharmony_ci self.assertRaises(SystemExit, zipfile.main, args) 36977db96d56Sopenharmony_ci self.assertEqual(stdout.getvalue(), "") 36987db96d56Sopenharmony_ci self.assertIn(errmsg, stderr.getvalue()) 36997db96d56Sopenharmony_ci 37007db96d56Sopenharmony_ci with captured_stdout() as stdout: 37017db96d56Sopenharmony_ci zipfile.main(["--metadata-encoding=shift_jis", "-t", TESTFN]) 37027db96d56Sopenharmony_ci listing = stdout.getvalue() 37037db96d56Sopenharmony_ci 37047db96d56Sopenharmony_ci with captured_stdout() as stdout: 37057db96d56Sopenharmony_ci zipfile.main(["--metadata-encoding=shift_jis", "-l", TESTFN]) 37067db96d56Sopenharmony_ci listing = stdout.getvalue() 37077db96d56Sopenharmony_ci for name in self.file_names: 37087db96d56Sopenharmony_ci self.assertIn(name, listing) 37097db96d56Sopenharmony_ci 37107db96d56Sopenharmony_ci def test_cli_with_metadata_encoding_extract(self): 37117db96d56Sopenharmony_ci os.mkdir(TESTFN2) 37127db96d56Sopenharmony_ci self.addCleanup(rmtree, TESTFN2) 37137db96d56Sopenharmony_ci # Depending on locale, extracted file names can be not encodable 37147db96d56Sopenharmony_ci # with the filesystem encoding. 37157db96d56Sopenharmony_ci for fn in self.file_names: 37167db96d56Sopenharmony_ci try: 37177db96d56Sopenharmony_ci os.stat(os.path.join(TESTFN2, fn)) 37187db96d56Sopenharmony_ci except OSError: 37197db96d56Sopenharmony_ci pass 37207db96d56Sopenharmony_ci except UnicodeEncodeError: 37217db96d56Sopenharmony_ci self.skipTest(f'cannot encode file name {fn!r}') 37227db96d56Sopenharmony_ci 37237db96d56Sopenharmony_ci zipfile.main(["--metadata-encoding=shift_jis", "-e", TESTFN, TESTFN2]) 37247db96d56Sopenharmony_ci listing = os.listdir(TESTFN2) 37257db96d56Sopenharmony_ci for name in self.file_names: 37267db96d56Sopenharmony_ci self.assertIn(name, listing) 37277db96d56Sopenharmony_ci 37287db96d56Sopenharmony_ci 37297db96d56Sopenharmony_ciclass StripExtraTests(unittest.TestCase): 37307db96d56Sopenharmony_ci # Note: all of the "z" characters are technically invalid, but up 37317db96d56Sopenharmony_ci # to 3 bytes at the end of the extra will be passed through as they 37327db96d56Sopenharmony_ci # are too short to encode a valid extra. 37337db96d56Sopenharmony_ci 37347db96d56Sopenharmony_ci ZIP64_EXTRA = 1 37357db96d56Sopenharmony_ci 37367db96d56Sopenharmony_ci def test_no_data(self): 37377db96d56Sopenharmony_ci s = struct.Struct("<HH") 37387db96d56Sopenharmony_ci a = s.pack(self.ZIP64_EXTRA, 0) 37397db96d56Sopenharmony_ci b = s.pack(2, 0) 37407db96d56Sopenharmony_ci c = s.pack(3, 0) 37417db96d56Sopenharmony_ci 37427db96d56Sopenharmony_ci self.assertEqual(b'', zipfile._strip_extra(a, (self.ZIP64_EXTRA,))) 37437db96d56Sopenharmony_ci self.assertEqual(b, zipfile._strip_extra(b, (self.ZIP64_EXTRA,))) 37447db96d56Sopenharmony_ci self.assertEqual( 37457db96d56Sopenharmony_ci b+b"z", zipfile._strip_extra(b+b"z", (self.ZIP64_EXTRA,))) 37467db96d56Sopenharmony_ci 37477db96d56Sopenharmony_ci self.assertEqual(b+c, zipfile._strip_extra(a+b+c, (self.ZIP64_EXTRA,))) 37487db96d56Sopenharmony_ci self.assertEqual(b+c, zipfile._strip_extra(b+a+c, (self.ZIP64_EXTRA,))) 37497db96d56Sopenharmony_ci self.assertEqual(b+c, zipfile._strip_extra(b+c+a, (self.ZIP64_EXTRA,))) 37507db96d56Sopenharmony_ci 37517db96d56Sopenharmony_ci def test_with_data(self): 37527db96d56Sopenharmony_ci s = struct.Struct("<HH") 37537db96d56Sopenharmony_ci a = s.pack(self.ZIP64_EXTRA, 1) + b"a" 37547db96d56Sopenharmony_ci b = s.pack(2, 2) + b"bb" 37557db96d56Sopenharmony_ci c = s.pack(3, 3) + b"ccc" 37567db96d56Sopenharmony_ci 37577db96d56Sopenharmony_ci self.assertEqual(b"", zipfile._strip_extra(a, (self.ZIP64_EXTRA,))) 37587db96d56Sopenharmony_ci self.assertEqual(b, zipfile._strip_extra(b, (self.ZIP64_EXTRA,))) 37597db96d56Sopenharmony_ci self.assertEqual( 37607db96d56Sopenharmony_ci b+b"z", zipfile._strip_extra(b+b"z", (self.ZIP64_EXTRA,))) 37617db96d56Sopenharmony_ci 37627db96d56Sopenharmony_ci self.assertEqual(b+c, zipfile._strip_extra(a+b+c, (self.ZIP64_EXTRA,))) 37637db96d56Sopenharmony_ci self.assertEqual(b+c, zipfile._strip_extra(b+a+c, (self.ZIP64_EXTRA,))) 37647db96d56Sopenharmony_ci self.assertEqual(b+c, zipfile._strip_extra(b+c+a, (self.ZIP64_EXTRA,))) 37657db96d56Sopenharmony_ci 37667db96d56Sopenharmony_ci def test_multiples(self): 37677db96d56Sopenharmony_ci s = struct.Struct("<HH") 37687db96d56Sopenharmony_ci a = s.pack(self.ZIP64_EXTRA, 1) + b"a" 37697db96d56Sopenharmony_ci b = s.pack(2, 2) + b"bb" 37707db96d56Sopenharmony_ci 37717db96d56Sopenharmony_ci self.assertEqual(b"", zipfile._strip_extra(a+a, (self.ZIP64_EXTRA,))) 37727db96d56Sopenharmony_ci self.assertEqual(b"", zipfile._strip_extra(a+a+a, (self.ZIP64_EXTRA,))) 37737db96d56Sopenharmony_ci self.assertEqual( 37747db96d56Sopenharmony_ci b"z", zipfile._strip_extra(a+a+b"z", (self.ZIP64_EXTRA,))) 37757db96d56Sopenharmony_ci self.assertEqual( 37767db96d56Sopenharmony_ci b+b"z", zipfile._strip_extra(a+a+b+b"z", (self.ZIP64_EXTRA,))) 37777db96d56Sopenharmony_ci 37787db96d56Sopenharmony_ci self.assertEqual(b, zipfile._strip_extra(a+a+b, (self.ZIP64_EXTRA,))) 37797db96d56Sopenharmony_ci self.assertEqual(b, zipfile._strip_extra(a+b+a, (self.ZIP64_EXTRA,))) 37807db96d56Sopenharmony_ci self.assertEqual(b, zipfile._strip_extra(b+a+a, (self.ZIP64_EXTRA,))) 37817db96d56Sopenharmony_ci 37827db96d56Sopenharmony_ci def test_too_short(self): 37837db96d56Sopenharmony_ci self.assertEqual(b"", zipfile._strip_extra(b"", (self.ZIP64_EXTRA,))) 37847db96d56Sopenharmony_ci self.assertEqual(b"z", zipfile._strip_extra(b"z", (self.ZIP64_EXTRA,))) 37857db96d56Sopenharmony_ci self.assertEqual( 37867db96d56Sopenharmony_ci b"zz", zipfile._strip_extra(b"zz", (self.ZIP64_EXTRA,))) 37877db96d56Sopenharmony_ci self.assertEqual( 37887db96d56Sopenharmony_ci b"zzz", zipfile._strip_extra(b"zzz", (self.ZIP64_EXTRA,))) 37897db96d56Sopenharmony_ci 37907db96d56Sopenharmony_ci 37917db96d56Sopenharmony_ciif __name__ == "__main__": 37927db96d56Sopenharmony_ci unittest.main() 3793