diff --git a/changes/2762.bugfix.rst b/changes/2762.bugfix.rst new file mode 100644 index 0000000000..4995d33edd --- /dev/null +++ b/changes/2762.bugfix.rst @@ -0,0 +1,2 @@ +Fixed ZipStore to make sure the correct attributes are saved when instances are pickled. +This fixes a previous bug that prevent using ZipStore with a ProcessPoolExecutor. diff --git a/src/zarr/storage/_zip.py b/src/zarr/storage/_zip.py index e808b80e4e..5a8b51196a 100644 --- a/src/zarr/storage/_zip.py +++ b/src/zarr/storage/_zip.py @@ -107,11 +107,14 @@ def _sync_open(self) -> None: async def _open(self) -> None: self._sync_open() - def __getstate__(self) -> tuple[Path, ZipStoreAccessModeLiteral, int, bool]: - return self.path, self._zmode, self.compression, self.allowZip64 - - def __setstate__(self, state: Any) -> None: - self.path, self._zmode, self.compression, self.allowZip64 = state + def __getstate__(self) -> dict[str, Any]: + state = self.__dict__ + for attr in ["_zf", "_lock"]: + state.pop(attr, None) + return state + + def __setstate__(self, state: dict[str, Any]) -> None: + self.__dict__ = state self._is_open = False self._sync_open() diff --git a/src/zarr/testing/store.py b/src/zarr/testing/store.py index 602d001693..7de88a2a80 100644 --- a/src/zarr/testing/store.py +++ b/src/zarr/testing/store.py @@ -76,8 +76,9 @@ def test_store_eq(self, store: S, store_kwargs: dict[str, Any]) -> None: assert store == store2 def test_serializable_store(self, store: S) -> None: - foo = pickle.dumps(store) - assert pickle.loads(foo) == store + new_store: S = pickle.loads(pickle.dumps(store)) + assert new_store == store + assert new_store.read_only == store.read_only def test_store_read_only(self, store: S) -> None: assert not store.read_only