| 
									
										
										
										
											2022-11-26 09:44:13 -05:00
										 |  |  | import io | 
					
						
							| 
									
										
										
										
											2023-01-19 23:04:30 -08:00
										 |  |  | import itertools | 
					
						
							| 
									
										
										
										
											2022-11-26 09:44:13 -05:00
										 |  |  | import contextlib | 
					
						
							|  |  |  | import pathlib | 
					
						
							| 
									
										
										
										
											2022-11-26 13:05:41 -05:00
										 |  |  | import pickle | 
					
						
							| 
									
										
										
										
											2024-06-03 11:13:07 -04:00
										 |  |  | import stat | 
					
						
							| 
									
										
										
										
											2023-02-20 16:01:58 -05:00
										 |  |  | import sys | 
					
						
							| 
									
										
										
										
											2023-01-19 23:04:30 -08:00
										 |  |  | import unittest | 
					
						
							|  |  |  | import zipfile | 
					
						
							| 
									
										
										
										
											2024-03-14 17:53:50 -04:00
										 |  |  | import zipfile._path | 
					
						
							| 
									
										
										
										
											2022-11-26 13:05:41 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-26 21:33:16 -04:00
										 |  |  | from test.support.os_helper import temp_dir, FakePath | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-26 13:05:41 -05:00
										 |  |  | from ._functools import compose | 
					
						
							| 
									
										
										
										
											2023-02-20 16:01:58 -05:00
										 |  |  | from ._itertools import Counter | 
					
						
							| 
									
										
										
										
											2022-11-26 13:05:41 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-20 16:01:58 -05:00
										 |  |  | from ._test_params import parameterize, Invoked | 
					
						
							| 
									
										
										
										
											2022-11-26 09:44:13 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class jaraco: | 
					
						
							|  |  |  |     class itertools: | 
					
						
							| 
									
										
										
										
											2023-02-20 16:01:58 -05:00
										 |  |  |         Counter = Counter | 
					
						
							| 
									
										
										
										
											2022-11-26 09:44:13 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-03 11:13:07 -04:00
										 |  |  | def _make_link(info: zipfile.ZipInfo):  # type: ignore[name-defined] | 
					
						
							|  |  |  |     info.external_attr |= stat.S_IFLNK << 16 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-26 09:44:13 -05:00
										 |  |  | def build_alpharep_fixture(): | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     Create a zip file with this structure: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     . | 
					
						
							|  |  |  |     ├── a.txt | 
					
						
							| 
									
										
										
										
											2024-06-03 11:13:07 -04:00
										 |  |  |     ├── n.txt (-> a.txt) | 
					
						
							| 
									
										
										
										
											2022-11-26 09:44:13 -05:00
										 |  |  |     ├── b | 
					
						
							|  |  |  |     │   ├── c.txt | 
					
						
							|  |  |  |     │   ├── d | 
					
						
							|  |  |  |     │   │   └── e.txt | 
					
						
							|  |  |  |     │   └── f.txt | 
					
						
							| 
									
										
										
										
											2023-07-15 09:21:17 -04:00
										 |  |  |     ├── g | 
					
						
							|  |  |  |     │   └── h | 
					
						
							|  |  |  |     │       └── i.txt | 
					
						
							|  |  |  |     └── j | 
					
						
							|  |  |  |         ├── k.bin | 
					
						
							|  |  |  |         ├── l.baz | 
					
						
							|  |  |  |         └── m.bar | 
					
						
							| 
									
										
										
										
											2022-11-26 09:44:13 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     This fixture has the following key characteristics: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     - a file at the root (a) | 
					
						
							|  |  |  |     - a file two levels deep (b/d/e) | 
					
						
							|  |  |  |     - multiple files in a directory (b/c, b/f) | 
					
						
							|  |  |  |     - a directory containing only a directory (g/h) | 
					
						
							| 
									
										
										
										
											2023-07-15 09:21:17 -04:00
										 |  |  |     - a directory with files of different extensions (j/klm) | 
					
						
							| 
									
										
										
										
											2024-06-03 11:13:07 -04:00
										 |  |  |     - a symlink (n) pointing to (a) | 
					
						
							| 
									
										
										
										
											2022-11-26 09:44:13 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     "alpha" because it uses alphabet | 
					
						
							|  |  |  |     "rep" because it's a representative example | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     data = io.BytesIO() | 
					
						
							|  |  |  |     zf = zipfile.ZipFile(data, "w") | 
					
						
							|  |  |  |     zf.writestr("a.txt", b"content of a") | 
					
						
							|  |  |  |     zf.writestr("b/c.txt", b"content of c") | 
					
						
							|  |  |  |     zf.writestr("b/d/e.txt", b"content of e") | 
					
						
							|  |  |  |     zf.writestr("b/f.txt", b"content of f") | 
					
						
							|  |  |  |     zf.writestr("g/h/i.txt", b"content of i") | 
					
						
							| 
									
										
										
										
											2023-07-15 09:21:17 -04:00
										 |  |  |     zf.writestr("j/k.bin", b"content of k") | 
					
						
							|  |  |  |     zf.writestr("j/l.baz", b"content of l") | 
					
						
							|  |  |  |     zf.writestr("j/m.bar", b"content of m") | 
					
						
							| 
									
										
										
										
											2024-06-03 11:13:07 -04:00
										 |  |  |     zf.writestr("n.txt", b"a.txt") | 
					
						
							|  |  |  |     _make_link(zf.infolist()[-1]) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-26 09:44:13 -05:00
										 |  |  |     zf.filename = "alpharep.zip" | 
					
						
							|  |  |  |     return zf | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-26 13:05:41 -05:00
										 |  |  | alpharep_generators = [ | 
					
						
							|  |  |  |     Invoked.wrap(build_alpharep_fixture), | 
					
						
							| 
									
										
										
										
											2024-03-14 17:53:50 -04:00
										 |  |  |     Invoked.wrap(compose(zipfile._path.CompleteDirs.inject, build_alpharep_fixture)), | 
					
						
							| 
									
										
										
										
											2022-11-26 13:05:41 -05:00
										 |  |  | ] | 
					
						
							| 
									
										
										
										
											2022-11-26 09:44:13 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-26 13:05:41 -05:00
										 |  |  | pass_alpharep = parameterize(['alpharep'], alpharep_generators) | 
					
						
							| 
									
										
										
										
											2022-11-26 09:44:13 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class TestPath(unittest.TestCase): | 
					
						
							|  |  |  |     def setUp(self): | 
					
						
							|  |  |  |         self.fixtures = contextlib.ExitStack() | 
					
						
							|  |  |  |         self.addCleanup(self.fixtures.close) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def zipfile_ondisk(self, alpharep): | 
					
						
							|  |  |  |         tmpdir = pathlib.Path(self.fixtures.enter_context(temp_dir())) | 
					
						
							|  |  |  |         buffer = alpharep.fp | 
					
						
							|  |  |  |         alpharep.close() | 
					
						
							|  |  |  |         path = tmpdir / alpharep.filename | 
					
						
							|  |  |  |         with path.open("wb") as strm: | 
					
						
							|  |  |  |             strm.write(buffer.getvalue()) | 
					
						
							|  |  |  |         return path | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_iterdir_and_types(self, alpharep): | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							|  |  |  |         assert root.is_dir() | 
					
						
							| 
									
										
										
										
											2024-08-11 20:33:33 -04:00
										 |  |  |         a, n, b, g, j = root.iterdir() | 
					
						
							| 
									
										
										
										
											2022-11-26 09:44:13 -05:00
										 |  |  |         assert a.is_file() | 
					
						
							|  |  |  |         assert b.is_dir() | 
					
						
							|  |  |  |         assert g.is_dir() | 
					
						
							|  |  |  |         c, f, d = b.iterdir() | 
					
						
							|  |  |  |         assert c.is_file() and f.is_file() | 
					
						
							|  |  |  |         (e,) = d.iterdir() | 
					
						
							|  |  |  |         assert e.is_file() | 
					
						
							|  |  |  |         (h,) = g.iterdir() | 
					
						
							|  |  |  |         (i,) = h.iterdir() | 
					
						
							|  |  |  |         assert i.is_file() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_is_file_missing(self, alpharep): | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							|  |  |  |         assert not root.joinpath('missing.txt').is_file() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_iterdir_on_file(self, alpharep): | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							| 
									
										
										
										
											2024-08-11 20:33:33 -04:00
										 |  |  |         a, n, b, g, j = root.iterdir() | 
					
						
							| 
									
										
										
										
											2022-11-26 09:44:13 -05:00
										 |  |  |         with self.assertRaises(ValueError): | 
					
						
							|  |  |  |             a.iterdir() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_subdir_is_dir(self, alpharep): | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							|  |  |  |         assert (root / 'b').is_dir() | 
					
						
							|  |  |  |         assert (root / 'b/').is_dir() | 
					
						
							|  |  |  |         assert (root / 'g').is_dir() | 
					
						
							|  |  |  |         assert (root / 'g/').is_dir() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_open(self, alpharep): | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							| 
									
										
										
										
											2024-08-11 20:33:33 -04:00
										 |  |  |         a, n, b, g, j = root.iterdir() | 
					
						
							| 
									
										
										
										
											2022-11-26 09:44:13 -05:00
										 |  |  |         with a.open(encoding="utf-8") as strm: | 
					
						
							|  |  |  |             data = strm.read() | 
					
						
							| 
									
										
										
										
											2023-01-19 23:04:30 -08:00
										 |  |  |         self.assertEqual(data, "content of a") | 
					
						
							|  |  |  |         with a.open('r', "utf-8") as strm:  # not a kw, no gh-101144 TypeError | 
					
						
							|  |  |  |             data = strm.read() | 
					
						
							|  |  |  |         self.assertEqual(data, "content of a") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_open_encoding_utf16(self): | 
					
						
							|  |  |  |         in_memory_file = io.BytesIO() | 
					
						
							|  |  |  |         zf = zipfile.ZipFile(in_memory_file, "w") | 
					
						
							|  |  |  |         zf.writestr("path/16.txt", "This was utf-16".encode("utf-16")) | 
					
						
							|  |  |  |         zf.filename = "test_open_utf16.zip" | 
					
						
							|  |  |  |         root = zipfile.Path(zf) | 
					
						
							|  |  |  |         (path,) = root.iterdir() | 
					
						
							|  |  |  |         u16 = path.joinpath("16.txt") | 
					
						
							|  |  |  |         with u16.open('r', "utf-16") as strm: | 
					
						
							|  |  |  |             data = strm.read() | 
					
						
							| 
									
										
										
										
											2023-02-20 16:01:58 -05:00
										 |  |  |         assert data == "This was utf-16" | 
					
						
							| 
									
										
										
										
											2023-01-19 23:04:30 -08:00
										 |  |  |         with u16.open(encoding="utf-16") as strm: | 
					
						
							|  |  |  |             data = strm.read() | 
					
						
							| 
									
										
										
										
											2023-02-20 16:01:58 -05:00
										 |  |  |         assert data == "This was utf-16" | 
					
						
							| 
									
										
										
										
											2023-01-19 23:04:30 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_open_encoding_errors(self): | 
					
						
							|  |  |  |         in_memory_file = io.BytesIO() | 
					
						
							|  |  |  |         zf = zipfile.ZipFile(in_memory_file, "w") | 
					
						
							|  |  |  |         zf.writestr("path/bad-utf8.bin", b"invalid utf-8: \xff\xff.") | 
					
						
							|  |  |  |         zf.filename = "test_read_text_encoding_errors.zip" | 
					
						
							|  |  |  |         root = zipfile.Path(zf) | 
					
						
							|  |  |  |         (path,) = root.iterdir() | 
					
						
							|  |  |  |         u16 = path.joinpath("bad-utf8.bin") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # encoding= as a positional argument for gh-101144. | 
					
						
							|  |  |  |         data = u16.read_text("utf-8", errors="ignore") | 
					
						
							| 
									
										
										
										
											2023-02-20 16:01:58 -05:00
										 |  |  |         assert data == "invalid utf-8: ." | 
					
						
							| 
									
										
										
										
											2023-01-19 23:04:30 -08:00
										 |  |  |         with u16.open("r", "utf-8", errors="surrogateescape") as f: | 
					
						
							| 
									
										
										
										
											2023-02-20 16:01:58 -05:00
										 |  |  |             assert f.read() == "invalid utf-8: \udcff\udcff." | 
					
						
							| 
									
										
										
										
											2023-01-19 23:04:30 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # encoding= both positional and keyword is an error; gh-101144. | 
					
						
							|  |  |  |         with self.assertRaisesRegex(TypeError, "encoding"): | 
					
						
							|  |  |  |             data = u16.read_text("utf-8", encoding="utf-8") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # both keyword arguments work. | 
					
						
							|  |  |  |         with u16.open("r", encoding="utf-8", errors="strict") as f: | 
					
						
							|  |  |  |             # error during decoding with wrong codec. | 
					
						
							|  |  |  |             with self.assertRaises(UnicodeDecodeError): | 
					
						
							|  |  |  |                 f.read() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-20 16:01:58 -05:00
										 |  |  |     @unittest.skipIf( | 
					
						
							|  |  |  |         not getattr(sys.flags, 'warn_default_encoding', 0), | 
					
						
							|  |  |  |         "Requires warn_default_encoding", | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_encoding_warnings(self, alpharep): | 
					
						
							| 
									
										
										
										
											2023-01-19 23:04:30 -08:00
										 |  |  |         """EncodingWarning must blame the read_text and open calls.""" | 
					
						
							| 
									
										
										
										
											2023-02-20 16:01:58 -05:00
										 |  |  |         assert sys.flags.warn_default_encoding | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							|  |  |  |         with self.assertWarns(EncodingWarning) as wc: | 
					
						
							|  |  |  |             root.joinpath("a.txt").read_text() | 
					
						
							|  |  |  |         assert __file__ == wc.filename | 
					
						
							|  |  |  |         with self.assertWarns(EncodingWarning) as wc: | 
					
						
							|  |  |  |             root.joinpath("a.txt").open("r").close() | 
					
						
							|  |  |  |         assert __file__ == wc.filename | 
					
						
							| 
									
										
										
										
											2022-11-26 09:44:13 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_open_write(self): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         If the zipfile is open for write, it should be possible to | 
					
						
							|  |  |  |         write bytes or text to it. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         zf = zipfile.Path(zipfile.ZipFile(io.BytesIO(), mode='w')) | 
					
						
							|  |  |  |         with zf.joinpath('file.bin').open('wb') as strm: | 
					
						
							|  |  |  |             strm.write(b'binary contents') | 
					
						
							|  |  |  |         with zf.joinpath('file.txt').open('w', encoding="utf-8") as strm: | 
					
						
							|  |  |  |             strm.write('text file') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-14 17:53:50 -04:00
										 |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_open_extant_directory(self, alpharep): | 
					
						
							| 
									
										
										
										
											2022-11-26 09:44:13 -05:00
										 |  |  |         """
 | 
					
						
							|  |  |  |         Attempting to open a directory raises IsADirectoryError. | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2024-03-14 17:53:50 -04:00
										 |  |  |         zf = zipfile.Path(alpharep) | 
					
						
							| 
									
										
										
										
											2022-11-26 09:44:13 -05:00
										 |  |  |         with self.assertRaises(IsADirectoryError): | 
					
						
							|  |  |  |             zf.joinpath('b').open() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_open_binary_invalid_args(self, alpharep): | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							|  |  |  |         with self.assertRaises(ValueError): | 
					
						
							|  |  |  |             root.joinpath('a.txt').open('rb', encoding='utf-8') | 
					
						
							|  |  |  |         with self.assertRaises(ValueError): | 
					
						
							|  |  |  |             root.joinpath('a.txt').open('rb', 'utf-8') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-14 17:53:50 -04:00
										 |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_open_missing_directory(self, alpharep): | 
					
						
							| 
									
										
										
										
											2022-11-26 09:44:13 -05:00
										 |  |  |         """
 | 
					
						
							|  |  |  |         Attempting to open a missing directory raises FileNotFoundError. | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2024-03-14 17:53:50 -04:00
										 |  |  |         zf = zipfile.Path(alpharep) | 
					
						
							| 
									
										
										
										
											2022-11-26 09:44:13 -05:00
										 |  |  |         with self.assertRaises(FileNotFoundError): | 
					
						
							|  |  |  |             zf.joinpath('z').open() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_read(self, alpharep): | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							| 
									
										
										
										
											2024-08-11 20:33:33 -04:00
										 |  |  |         a, n, b, g, j = root.iterdir() | 
					
						
							| 
									
										
										
										
											2022-11-26 09:44:13 -05:00
										 |  |  |         assert a.read_text(encoding="utf-8") == "content of a" | 
					
						
							| 
									
										
										
										
											2023-02-20 16:01:58 -05:00
										 |  |  |         # Also check positional encoding arg (gh-101144). | 
					
						
							|  |  |  |         assert a.read_text("utf-8") == "content of a" | 
					
						
							| 
									
										
										
										
											2022-11-26 09:44:13 -05:00
										 |  |  |         assert a.read_bytes() == b"content of a" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_joinpath(self, alpharep): | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							|  |  |  |         a = root.joinpath("a.txt") | 
					
						
							|  |  |  |         assert a.is_file() | 
					
						
							|  |  |  |         e = root.joinpath("b").joinpath("d").joinpath("e.txt") | 
					
						
							|  |  |  |         assert e.read_text(encoding="utf-8") == "content of e" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_joinpath_multiple(self, alpharep): | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							|  |  |  |         e = root.joinpath("b", "d", "e.txt") | 
					
						
							|  |  |  |         assert e.read_text(encoding="utf-8") == "content of e" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_traverse_truediv(self, alpharep): | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							|  |  |  |         a = root / "a.txt" | 
					
						
							|  |  |  |         assert a.is_file() | 
					
						
							|  |  |  |         e = root / "b" / "d" / "e.txt" | 
					
						
							|  |  |  |         assert e.read_text(encoding="utf-8") == "content of e" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_pathlike_construction(self, alpharep): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         zipfile.Path should be constructable from a path-like object | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         zipfile_ondisk = self.zipfile_ondisk(alpharep) | 
					
						
							| 
									
										
										
										
											2024-05-16 10:25:10 +03:00
										 |  |  |         pathlike = FakePath(str(zipfile_ondisk)) | 
					
						
							| 
									
										
										
										
											2022-11-26 09:44:13 -05:00
										 |  |  |         zipfile.Path(pathlike) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_traverse_pathlike(self, alpharep): | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							| 
									
										
										
										
											2024-05-16 10:25:10 +03:00
										 |  |  |         root / FakePath("a") | 
					
						
							| 
									
										
										
										
											2022-11-26 09:44:13 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_parent(self, alpharep): | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							|  |  |  |         assert (root / 'a').parent.at == '' | 
					
						
							|  |  |  |         assert (root / 'a' / 'b').parent.at == 'a/' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_dir_parent(self, alpharep): | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							|  |  |  |         assert (root / 'b').parent.at == '' | 
					
						
							|  |  |  |         assert (root / 'b/').parent.at == '' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_missing_dir_parent(self, alpharep): | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							|  |  |  |         assert (root / 'missing dir/').parent.at == '' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_mutability(self, alpharep): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         If the underlying zipfile is changed, the Path object should | 
					
						
							|  |  |  |         reflect that change. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							| 
									
										
										
										
											2024-08-11 20:33:33 -04:00
										 |  |  |         a, n, b, g, j = root.iterdir() | 
					
						
							| 
									
										
										
										
											2022-11-26 09:44:13 -05:00
										 |  |  |         alpharep.writestr('foo.txt', 'foo') | 
					
						
							|  |  |  |         alpharep.writestr('bar/baz.txt', 'baz') | 
					
						
							|  |  |  |         assert any(child.name == 'foo.txt' for child in root.iterdir()) | 
					
						
							|  |  |  |         assert (root / 'foo.txt').read_text(encoding="utf-8") == 'foo' | 
					
						
							|  |  |  |         (baz,) = (root / 'bar').iterdir() | 
					
						
							|  |  |  |         assert baz.read_text(encoding="utf-8") == 'baz' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     HUGE_ZIPFILE_NUM_ENTRIES = 2**13 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def huge_zipfile(self): | 
					
						
							|  |  |  |         """Create a read-only zipfile with a huge number of entries entries.""" | 
					
						
							|  |  |  |         strm = io.BytesIO() | 
					
						
							|  |  |  |         zf = zipfile.ZipFile(strm, "w") | 
					
						
							|  |  |  |         for entry in map(str, range(self.HUGE_ZIPFILE_NUM_ENTRIES)): | 
					
						
							|  |  |  |             zf.writestr(entry, entry) | 
					
						
							|  |  |  |         zf.mode = 'r' | 
					
						
							|  |  |  |         return zf | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_joinpath_constant_time(self): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         Ensure joinpath on items in zipfile is linear time. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         root = zipfile.Path(self.huge_zipfile()) | 
					
						
							|  |  |  |         entries = jaraco.itertools.Counter(root.iterdir()) | 
					
						
							|  |  |  |         for entry in entries: | 
					
						
							|  |  |  |             entry.joinpath('suffix') | 
					
						
							|  |  |  |         # Check the file iterated all items | 
					
						
							|  |  |  |         assert entries.count == self.HUGE_ZIPFILE_NUM_ENTRIES | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_read_does_not_close(self, alpharep): | 
					
						
							|  |  |  |         alpharep = self.zipfile_ondisk(alpharep) | 
					
						
							|  |  |  |         with zipfile.ZipFile(alpharep) as file: | 
					
						
							|  |  |  |             for rep in range(2): | 
					
						
							|  |  |  |                 zipfile.Path(file, 'a.txt').read_text(encoding="utf-8") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_subclass(self, alpharep): | 
					
						
							|  |  |  |         class Subclass(zipfile.Path): | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         root = Subclass(alpharep) | 
					
						
							|  |  |  |         assert isinstance(root / 'b', Subclass) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_filename(self, alpharep): | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							|  |  |  |         assert root.filename == pathlib.Path('alpharep.zip') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_root_name(self, alpharep): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         The name of the root should be the name of the zipfile | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							|  |  |  |         assert root.name == 'alpharep.zip' == root.filename.name | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_suffix(self, alpharep): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         The suffix of the root should be the suffix of the zipfile. | 
					
						
							|  |  |  |         The suffix of each nested file is the final component's last suffix, if any. | 
					
						
							|  |  |  |         Includes the leading period, just like pathlib.Path. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							|  |  |  |         assert root.suffix == '.zip' == root.filename.suffix | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         b = root / "b.txt" | 
					
						
							|  |  |  |         assert b.suffix == ".txt" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         c = root / "c" / "filename.tar.gz" | 
					
						
							|  |  |  |         assert c.suffix == ".gz" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         d = root / "d" | 
					
						
							|  |  |  |         assert d.suffix == "" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_suffixes(self, alpharep): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         The suffix of the root should be the suffix of the zipfile. | 
					
						
							|  |  |  |         The suffix of each nested file is the final component's last suffix, if any. | 
					
						
							|  |  |  |         Includes the leading period, just like pathlib.Path. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							|  |  |  |         assert root.suffixes == ['.zip'] == root.filename.suffixes | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         b = root / 'b.txt' | 
					
						
							|  |  |  |         assert b.suffixes == ['.txt'] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         c = root / 'c' / 'filename.tar.gz' | 
					
						
							|  |  |  |         assert c.suffixes == ['.tar', '.gz'] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         d = root / 'd' | 
					
						
							|  |  |  |         assert d.suffixes == [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         e = root / '.hgrc' | 
					
						
							|  |  |  |         assert e.suffixes == [] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-15 09:21:17 -04:00
										 |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_suffix_no_filename(self, alpharep): | 
					
						
							|  |  |  |         alpharep.filename = None | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							|  |  |  |         assert root.joinpath('example').suffix == "" | 
					
						
							|  |  |  |         assert root.joinpath('example').suffixes == [] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-26 09:44:13 -05:00
										 |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_stem(self, alpharep): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         The final path component, without its suffix | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							|  |  |  |         assert root.stem == 'alpharep' == root.filename.stem | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         b = root / "b.txt" | 
					
						
							|  |  |  |         assert b.stem == "b" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         c = root / "c" / "filename.tar.gz" | 
					
						
							|  |  |  |         assert c.stem == "filename.tar" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         d = root / "d" | 
					
						
							|  |  |  |         assert d.stem == "d" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-15 09:21:17 -04:00
										 |  |  |         assert (root / ".gitignore").stem == ".gitignore" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-26 09:44:13 -05:00
										 |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_root_parent(self, alpharep): | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							|  |  |  |         assert root.parent == pathlib.Path('.') | 
					
						
							|  |  |  |         root.root.filename = 'foo/bar.zip' | 
					
						
							|  |  |  |         assert root.parent == pathlib.Path('foo') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_root_unnamed(self, alpharep): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         It is an error to attempt to get the name | 
					
						
							|  |  |  |         or parent of an unnamed zipfile. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         alpharep.filename = None | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							|  |  |  |         with self.assertRaises(TypeError): | 
					
						
							|  |  |  |             root.name | 
					
						
							|  |  |  |         with self.assertRaises(TypeError): | 
					
						
							|  |  |  |             root.parent | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # .name and .parent should still work on subs | 
					
						
							|  |  |  |         sub = root / "b" | 
					
						
							|  |  |  |         assert sub.name == "b" | 
					
						
							|  |  |  |         assert sub.parent | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-20 16:01:58 -05:00
										 |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_match_and_glob(self, alpharep): | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							|  |  |  |         assert not root.match("*.txt") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         assert list(root.glob("b/c.*")) == [zipfile.Path(alpharep, "b/c.txt")] | 
					
						
							| 
									
										
										
										
											2023-07-15 09:21:17 -04:00
										 |  |  |         assert list(root.glob("b/*.txt")) == [ | 
					
						
							|  |  |  |             zipfile.Path(alpharep, "b/c.txt"), | 
					
						
							|  |  |  |             zipfile.Path(alpharep, "b/f.txt"), | 
					
						
							|  |  |  |         ] | 
					
						
							| 
									
										
										
										
											2023-02-20 16:01:58 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-15 09:21:17 -04:00
										 |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_glob_recursive(self, alpharep): | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							| 
									
										
										
										
											2023-02-20 16:01:58 -05:00
										 |  |  |         files = root.glob("**/*.txt") | 
					
						
							|  |  |  |         assert all(each.match("*.txt") for each in files) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         assert list(root.glob("**/*.txt")) == list(root.rglob("*.txt")) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-11 20:33:33 -04:00
										 |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_glob_dirs(self, alpharep): | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							|  |  |  |         assert list(root.glob('b')) == [zipfile.Path(alpharep, "b/")] | 
					
						
							|  |  |  |         assert list(root.glob('b*')) == [zipfile.Path(alpharep, "b/")] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_glob_subdir(self, alpharep): | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							|  |  |  |         assert list(root.glob('g/h')) == [zipfile.Path(alpharep, "g/h/")] | 
					
						
							|  |  |  |         assert list(root.glob('g*/h*')) == [zipfile.Path(alpharep, "g/h/")] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-15 09:21:17 -04:00
										 |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_glob_subdirs(self, alpharep): | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         assert list(root.glob("*/i.txt")) == [] | 
					
						
							|  |  |  |         assert list(root.rglob("*/i.txt")) == [zipfile.Path(alpharep, "g/h/i.txt")] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_glob_does_not_overmatch_dot(self, alpharep): | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         assert list(root.glob("*.xt")) == [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_glob_single_char(self, alpharep): | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         assert list(root.glob("a?txt")) == [zipfile.Path(alpharep, "a.txt")] | 
					
						
							|  |  |  |         assert list(root.glob("a[.]txt")) == [zipfile.Path(alpharep, "a.txt")] | 
					
						
							|  |  |  |         assert list(root.glob("a[?]txt")) == [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_glob_chars(self, alpharep): | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         assert list(root.glob("j/?.b[ai][nz]")) == [ | 
					
						
							|  |  |  |             zipfile.Path(alpharep, "j/k.bin"), | 
					
						
							|  |  |  |             zipfile.Path(alpharep, "j/l.baz"), | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-20 16:01:58 -05:00
										 |  |  |     def test_glob_empty(self): | 
					
						
							|  |  |  |         root = zipfile.Path(zipfile.ZipFile(io.BytesIO(), 'w')) | 
					
						
							|  |  |  |         with self.assertRaises(ValueError): | 
					
						
							|  |  |  |             root.glob('') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_eq_hash(self, alpharep): | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							|  |  |  |         assert root == zipfile.Path(alpharep) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         assert root != (root / "a.txt") | 
					
						
							|  |  |  |         assert (root / "a.txt") == (root / "a.txt") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							|  |  |  |         assert root in {root} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_is_symlink(self, alpharep): | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							| 
									
										
										
										
											2024-06-03 11:13:07 -04:00
										 |  |  |         assert not root.joinpath('a.txt').is_symlink() | 
					
						
							|  |  |  |         assert root.joinpath('n.txt').is_symlink() | 
					
						
							| 
									
										
										
										
											2023-02-20 16:01:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_relative_to(self, alpharep): | 
					
						
							|  |  |  |         root = zipfile.Path(alpharep) | 
					
						
							|  |  |  |         relative = root.joinpath("b", "c.txt").relative_to(root / "b") | 
					
						
							|  |  |  |         assert str(relative) == "c.txt" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         relative = root.joinpath("b", "d", "e.txt").relative_to(root / "b") | 
					
						
							|  |  |  |         assert str(relative) == "d/e.txt" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-26 09:44:13 -05:00
										 |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_inheritance(self, alpharep): | 
					
						
							|  |  |  |         cls = type('PathChild', (zipfile.Path,), {}) | 
					
						
							| 
									
										
										
										
											2022-11-26 13:05:41 -05:00
										 |  |  |         file = cls(alpharep).joinpath('some dir').parent | 
					
						
							|  |  |  |         assert isinstance(file, cls) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @parameterize( | 
					
						
							|  |  |  |         ['alpharep', 'path_type', 'subpath'], | 
					
						
							|  |  |  |         itertools.product( | 
					
						
							|  |  |  |             alpharep_generators, | 
					
						
							| 
									
										
										
										
											2024-05-16 10:25:10 +03:00
										 |  |  |             [str, FakePath], | 
					
						
							| 
									
										
										
										
											2022-11-26 13:05:41 -05:00
										 |  |  |             ['', 'b/'], | 
					
						
							|  |  |  |         ), | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     def test_pickle(self, alpharep, path_type, subpath): | 
					
						
							| 
									
										
										
										
											2024-05-16 10:25:10 +03:00
										 |  |  |         zipfile_ondisk = path_type(str(self.zipfile_ondisk(alpharep))) | 
					
						
							| 
									
										
										
										
											2022-11-26 13:05:41 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         saved_1 = pickle.dumps(zipfile.Path(zipfile_ondisk, at=subpath)) | 
					
						
							|  |  |  |         restored_1 = pickle.loads(saved_1) | 
					
						
							|  |  |  |         first, *rest = restored_1.iterdir() | 
					
						
							| 
									
										
										
										
											2023-02-25 11:15:48 -05:00
										 |  |  |         assert first.read_text(encoding='utf-8').startswith('content of ') | 
					
						
							| 
									
										
										
										
											2023-02-20 16:01:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_extract_orig_with_implied_dirs(self, alpharep): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         A zip file wrapped in a Path should extract even with implied dirs. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         source_path = self.zipfile_ondisk(alpharep) | 
					
						
							|  |  |  |         zf = zipfile.ZipFile(source_path) | 
					
						
							|  |  |  |         # wrap the zipfile for its side effect | 
					
						
							|  |  |  |         zipfile.Path(zf) | 
					
						
							|  |  |  |         zf.extractall(source_path.parent) | 
					
						
							| 
									
										
										
										
											2023-02-25 11:15:48 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_getinfo_missing(self, alpharep): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         Validate behavior of getinfo on original zipfile after wrapping. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         zipfile.Path(alpharep) | 
					
						
							|  |  |  |         with self.assertRaises(KeyError): | 
					
						
							|  |  |  |             alpharep.getinfo('does-not-exist') | 
					
						
							| 
									
										
										
										
											2024-08-11 19:48:50 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_malformed_paths(self): | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2024-08-27 17:10:30 -04:00
										 |  |  |         Path should handle malformed paths gracefully. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Paths with leading slashes are not visible. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Paths with dots are treated like regular files. | 
					
						
							| 
									
										
										
										
											2024-08-11 19:48:50 -04:00
										 |  |  |         """
 | 
					
						
							|  |  |  |         data = io.BytesIO() | 
					
						
							|  |  |  |         zf = zipfile.ZipFile(data, "w") | 
					
						
							|  |  |  |         zf.writestr("/one-slash.txt", b"content") | 
					
						
							|  |  |  |         zf.writestr("//two-slash.txt", b"content") | 
					
						
							|  |  |  |         zf.writestr("../parent.txt", b"content") | 
					
						
							|  |  |  |         zf.filename = '' | 
					
						
							|  |  |  |         root = zipfile.Path(zf) | 
					
						
							| 
									
										
										
										
											2024-08-27 17:10:30 -04:00
										 |  |  |         assert list(map(str, root.iterdir())) == ['../'] | 
					
						
							|  |  |  |         assert root.joinpath('..').joinpath('parent.txt').read_bytes() == b'content' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_unsupported_names(self): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         Path segments with special characters are readable. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         On some platforms or file systems, characters like | 
					
						
							|  |  |  |         ``:`` and ``?`` are not allowed, but they are valid | 
					
						
							|  |  |  |         in the zip file. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         data = io.BytesIO() | 
					
						
							|  |  |  |         zf = zipfile.ZipFile(data, "w") | 
					
						
							|  |  |  |         zf.writestr("path?", b"content") | 
					
						
							|  |  |  |         zf.writestr("V: NMS.flac", b"fLaC...") | 
					
						
							|  |  |  |         zf.filename = '' | 
					
						
							|  |  |  |         root = zipfile.Path(zf) | 
					
						
							|  |  |  |         contents = root.iterdir() | 
					
						
							|  |  |  |         assert next(contents).name == 'path?' | 
					
						
							|  |  |  |         assert next(contents).name == 'V: NMS.flac' | 
					
						
							|  |  |  |         assert root.joinpath('V: NMS.flac').read_bytes() == b"fLaC..." | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_backslash_not_separator(self): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         In a zip file, backslashes are not separators. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         data = io.BytesIO() | 
					
						
							|  |  |  |         zf = zipfile.ZipFile(data, "w") | 
					
						
							| 
									
										
										
										
											2024-12-29 19:30:53 +01:00
										 |  |  |         zf.writestr(DirtyZipInfo("foo\\bar")._for_archive(zf), b"content") | 
					
						
							| 
									
										
										
										
											2024-08-27 17:10:30 -04:00
										 |  |  |         zf.filename = '' | 
					
						
							|  |  |  |         root = zipfile.Path(zf) | 
					
						
							|  |  |  |         (first,) = root.iterdir() | 
					
						
							|  |  |  |         assert not first.is_dir() | 
					
						
							|  |  |  |         assert first.name == 'foo\\bar' | 
					
						
							| 
									
										
										
										
											2024-08-11 20:33:33 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     @pass_alpharep | 
					
						
							|  |  |  |     def test_interface(self, alpharep): | 
					
						
							|  |  |  |         from importlib.resources.abc import Traversable | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         zf = zipfile.Path(alpharep) | 
					
						
							|  |  |  |         assert isinstance(zf, Traversable) | 
					
						
							| 
									
										
										
										
											2024-08-27 17:10:30 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class DirtyZipInfo(zipfile.ZipInfo): | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     Bypass name sanitization. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, filename, *args, **kwargs): | 
					
						
							|  |  |  |         super().__init__(filename, *args, **kwargs) | 
					
						
							|  |  |  |         self.filename = filename |