import contextlib import io import pathlib import unittest import zipfile import functools from test.support.os_helper import TESTFN, unlink, rmtree, temp_dir, temp_cwd def add_dirs(zf): """ Given a writable zip file zf, inject directory entries for any directories implied by the presence of children. """ for name in zipfile.CompleteDirs._implied_dirs(zf.namelist()): zf.writestr(name, b"") return zf def build_alpharep_fixture(): """ Create a zip file with this structure: . ├── a.txt ├── b │ ├── c.txt │ ├── d │ │ └── e.txt │ └── f.txt └── g └── h └── i.txt 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) "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") zf.filename = "alpharep.zip" return zf def pass_alpharep(meth): """ Given a method, wrap it in a for loop that invokes method with each subtest. """ @functools.wraps(meth) def wrapper(self): for alpharep in self.zipfile_alpharep(): meth(self, alpharep=alpharep) return wrapper class TestPath(unittest.TestCase): def setUp(self): self.fixtures = contextlib.ExitStack() self.addCleanup(self.fixtures.close) def zipfile_alpharep(self): with self.subTest(): yield build_alpharep_fixture() with self.subTest(): yield add_dirs(build_alpharep_fixture()) 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_pathlike_construction(self, alpharep): """ zipfile.Path should be constructable from a path-like object """ zipfile_ondisk = self.zipfile_ondisk(alpharep) pathlike = pathlib.Path(str(zipfile_ondisk)) zipfile.Path(pathlike) @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() TestPath = TestPath() TestPath.setUp() TestPath.test_read_does_not_close() # TestPath.test_pathlike_construction() # if __name__ == "__main__": # unittest.main()