From 51027de6d48bf2f766feb05898f378db71921b15 Mon Sep 17 00:00:00 2001 From: Martin Durant Date: Thu, 7 Dec 2023 16:04:52 -0500 Subject: [PATCH] Allow append mode for ZIP (#1453) --- fsspec/implementations/local.py | 3 +++ fsspec/implementations/tests/test_zip.py | 26 ++++++++++++++++++++++++ fsspec/implementations/zip.py | 6 +++++- 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/fsspec/implementations/local.py b/fsspec/implementations/local.py index 1d8e21fd2..e7861e2ea 100644 --- a/fsspec/implementations/local.py +++ b/fsspec/implementations/local.py @@ -386,6 +386,9 @@ def readlines(self, *args, **kwargs): def close(self): return self.f.close() + def truncate(self, size=None) -> int: + return self.f.truncate(size) + @property def closed(self): return self.f.closed diff --git a/fsspec/implementations/tests/test_zip.py b/fsspec/implementations/tests/test_zip.py index 3c6c50b63..afd0c3fe2 100644 --- a/fsspec/implementations/tests/test_zip.py +++ b/fsspec/implementations/tests/test_zip.py @@ -94,3 +94,29 @@ def test_zip_glob_star(m): fs, _ = fsspec.core.url_to_fs("zip::memory://out.zip") outfiles = fs.glob("*") assert len(outfiles) == 1 + + +def test_append(m, tmpdir): + fs = fsspec.filesystem("zip", fo="memory://out.zip", mode="w") + with fs.open("afile", "wb") as f: + f.write(b"data") + fs.close() + + fs = fsspec.filesystem("zip", fo="memory://out.zip", mode="a") + with fs.open("bfile", "wb") as f: + f.write(b"data") + fs.close() + + assert len(fsspec.open_files("zip://*::memory://out.zip")) == 2 + + fs = fsspec.filesystem("zip", fo=f"{tmpdir}/out.zip", mode="w") + with fs.open("afile", "wb") as f: + f.write(b"data") + fs.close() + + fs = fsspec.filesystem("zip", fo=f"{tmpdir}/out.zip", mode="a") + with fs.open("bfile", "wb") as f: + f.write(b"data") + fs.close() + + assert len(fsspec.open_files("zip://*::memory://out.zip")) == 2 diff --git a/fsspec/implementations/zip.py b/fsspec/implementations/zip.py index dae927bc0..b8b2a645a 100644 --- a/fsspec/implementations/zip.py +++ b/fsspec/implementations/zip.py @@ -49,8 +49,12 @@ def __init__( raise ValueError(f"mode '{mode}' no understood") self.mode = mode if isinstance(fo, str): + if mode == "a": + m = "r+b" + else: + m = mode + "b" fo = fsspec.open( - fo, mode=mode + "b", protocol=target_protocol, **(target_options or {}) + fo, mode=m, protocol=target_protocol, **(target_options or {}) ) self.of = fo self.fo = fo.__enter__() # the whole instance is a context