Skip to content

Commit 6d4b5e7

Browse files
shoyerd-v-b
andauthored
Remove Store.set_partial_writes (#3413)
* Remove Store.set_partial_writes This feature was unused by the rest of Zarr-Python, and was only implemented for LocalStore and stores that wrap other stores. The Zarr v3 spec still mentions partial writes, so it should probably also be updated. * ruff fix * include fsspec --------- Co-authored-by: Davis Bennett <davis.v.bennett@gmail.com>
1 parent 710f5df commit 6d4b5e7

19 files changed

+15
-153
lines changed

changes/2859.removal.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
The ``Store.set_partial_writes`` method, which was not used by Zarr-Python, has been removed.
2+
``store.supports_partial_writes`` is now always ``False``.

src/zarr/abc/store.py

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,14 @@
44
from asyncio import gather
55
from dataclasses import dataclass
66
from itertools import starmap
7-
from typing import TYPE_CHECKING, Protocol, runtime_checkable
7+
from typing import TYPE_CHECKING, Literal, Protocol, runtime_checkable
88

99
if TYPE_CHECKING:
1010
from collections.abc import AsyncGenerator, AsyncIterator, Iterable
1111
from types import TracebackType
1212
from typing import Any, Self, TypeAlias
1313

1414
from zarr.core.buffer import Buffer, BufferPrototype
15-
from zarr.core.common import BytesLike
1615

1716
__all__ = ["ByteGetter", "ByteSetter", "Store", "set_or_delete"]
1817

@@ -310,25 +309,12 @@ async def delete(self, key: str) -> None:
310309
...
311310

312311
@property
313-
@abstractmethod
314-
def supports_partial_writes(self) -> bool:
315-
"""Does the store support partial writes?"""
316-
...
317-
318-
@abstractmethod
319-
async def set_partial_values(
320-
self, key_start_values: Iterable[tuple[str, int, BytesLike]]
321-
) -> None:
322-
"""Store values at a given key, starting at byte range_start.
312+
def supports_partial_writes(self) -> Literal[False]:
313+
"""Does the store support partial writes?
323314
324-
Parameters
325-
----------
326-
key_start_values : list[tuple[str, int, BytesLike]]
327-
set of key, range_start, values triples, a key may occur multiple times with different
328-
range_starts, range_starts (considering the length of the respective values) must not
329-
specify overlapping ranges for the same key
315+
Partial writes are no longer used by Zarr, so this is always false.
330316
"""
331-
...
317+
return False
332318

333319
@property
334320
@abstractmethod
@@ -499,7 +485,7 @@ async def get(
499485
self, prototype: BufferPrototype, byte_range: ByteRequest | None = None
500486
) -> Buffer | None: ...
501487

502-
async def set(self, value: Buffer, byte_range: ByteRequest | None = None) -> None: ...
488+
async def set(self, value: Buffer) -> None: ...
503489

504490
async def delete(self) -> None: ...
505491

src/zarr/storage/_common.py

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -163,24 +163,15 @@ async def get(
163163
prototype = default_buffer_prototype()
164164
return await self.store.get(self.path, prototype=prototype, byte_range=byte_range)
165165

166-
async def set(self, value: Buffer, byte_range: ByteRequest | None = None) -> None:
166+
async def set(self, value: Buffer) -> None:
167167
"""
168168
Write bytes to the store.
169169
170170
Parameters
171171
----------
172172
value : Buffer
173173
The buffer to write.
174-
byte_range : ByteRequest, optional
175-
The range of bytes to write. If None, the entire buffer is written.
176-
177-
Raises
178-
------
179-
NotImplementedError
180-
If `byte_range` is not None, because Store.set does not support partial writes yet.
181174
"""
182-
if byte_range is not None:
183-
raise NotImplementedError("Store.set does not have partial writes yet")
184175
await self.store.set(self.path, value)
185176

186177
async def delete(self) -> None:

src/zarr/storage/_fsspec.py

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
from fsspec.mapping import FSMap
2727

2828
from zarr.core.buffer import BufferPrototype
29-
from zarr.core.common import BytesLike
3029

3130

3231
ALLOWED_EXCEPTIONS: tuple[type[Exception], ...] = (
@@ -90,7 +89,6 @@ class FsspecStore(Store):
9089
allowed_exceptions
9190
supports_writes
9291
supports_deletes
93-
supports_partial_writes
9492
supports_listing
9593
9694
Raises
@@ -114,7 +112,6 @@ class FsspecStore(Store):
114112
# based on FSSpec
115113
supports_writes: bool = True
116114
supports_deletes: bool = True
117-
supports_partial_writes: bool = False
118115
supports_listing: bool = True
119116

120117
fs: AsyncFileSystem
@@ -418,12 +415,6 @@ async def get_partial_values(
418415

419416
return [None if isinstance(r, Exception) else prototype.buffer.from_bytes(r) for r in res]
420417

421-
async def set_partial_values(
422-
self, key_start_values: Iterable[tuple[str, int, BytesLike]]
423-
) -> None:
424-
# docstring inherited
425-
raise NotImplementedError
426-
427418
async def list(self) -> AsyncIterator[str]:
428419
# docstring inherited
429420
allfiles = await self.fs._find(self.path, detail=False, withdirs=False)

src/zarr/storage/_local.py

Lines changed: 4 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -77,23 +77,12 @@ def _atomic_write(
7777
raise
7878

7979

80-
def _put(
81-
path: Path,
82-
value: Buffer,
83-
start: int | None = None,
84-
exclusive: bool = False,
85-
) -> int | None:
80+
def _put(path: Path, value: Buffer, exclusive: bool = False) -> int:
8681
path.parent.mkdir(parents=True, exist_ok=True)
8782
# write takes any object supporting the buffer protocol
8883
view = value.as_buffer_like()
89-
if start is not None:
90-
with path.open("r+b") as f:
91-
f.seek(start)
92-
f.write(view)
93-
return None
94-
else:
95-
with _atomic_write(path, "wb", exclusive=exclusive) as f:
96-
return f.write(view)
84+
with _atomic_write(path, "wb", exclusive=exclusive) as f:
85+
return f.write(view)
9786

9887

9988
class LocalStore(Store):
@@ -111,14 +100,12 @@ class LocalStore(Store):
111100
----------
112101
supports_writes
113102
supports_deletes
114-
supports_partial_writes
115103
supports_listing
116104
root
117105
"""
118106

119107
supports_writes: bool = True
120108
supports_deletes: bool = True
121-
supports_partial_writes: bool = True
122109
supports_listing: bool = True
123110

124111
root: Path
@@ -253,19 +240,7 @@ async def _set(self, key: str, value: Buffer, exclusive: bool = False) -> None:
253240
f"LocalStore.set(): `value` must be a Buffer instance. Got an instance of {type(value)} instead."
254241
)
255242
path = self.root / key
256-
await asyncio.to_thread(_put, path, value, start=None, exclusive=exclusive)
257-
258-
async def set_partial_values(
259-
self, key_start_values: Iterable[tuple[str, int, bytes | bytearray | memoryview]]
260-
) -> None:
261-
# docstring inherited
262-
self._check_writable()
263-
args = []
264-
for key, start, value in key_start_values:
265-
assert isinstance(key, str)
266-
path = self.root / key
267-
args.append((_put, path, value, start))
268-
await concurrent_map(args, asyncio.to_thread, limit=None) # TODO: fix limit
243+
await asyncio.to_thread(_put, path, value, exclusive=exclusive)
269244

270245
async def delete(self, key: str) -> None:
271246
"""

src/zarr/storage/_logging.py

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,6 @@ def supports_deletes(self) -> bool:
115115
with self.log():
116116
return self._store.supports_deletes
117117

118-
@property
119-
def supports_partial_writes(self) -> bool:
120-
with self.log():
121-
return self._store.supports_partial_writes
122-
123118
@property
124119
def supports_listing(self) -> bool:
125120
with self.log():
@@ -207,14 +202,6 @@ async def delete(self, key: str) -> None:
207202
with self.log(key):
208203
return await self._store.delete(key=key)
209204

210-
async def set_partial_values(
211-
self, key_start_values: Iterable[tuple[str, int, bytes | bytearray | memoryview]]
212-
) -> None:
213-
# docstring inherited
214-
keys = ",".join([k[0] for k in key_start_values])
215-
with self.log(keys):
216-
return await self._store.set_partial_values(key_start_values=key_start_values)
217-
218205
async def list(self) -> AsyncGenerator[str, None]:
219206
# docstring inherited
220207
with self.log():

src/zarr/storage/_memory.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,11 @@ class MemoryStore(Store):
3232
----------
3333
supports_writes
3434
supports_deletes
35-
supports_partial_writes
3635
supports_listing
3736
"""
3837

3938
supports_writes: bool = True
4039
supports_deletes: bool = True
41-
supports_partial_writes: bool = True
4240
supports_listing: bool = True
4341

4442
_store_dict: MutableMapping[str, Buffer]
@@ -143,12 +141,6 @@ async def delete(self, key: str) -> None:
143141
except KeyError:
144142
logger.debug("Key %s does not exist.", key)
145143

146-
async def set_partial_values(
147-
self, key_start_values: Iterable[tuple[str, int, bytes | bytearray | memoryview[int]]]
148-
) -> None:
149-
# docstring inherited
150-
raise NotImplementedError
151-
152144
async def list(self) -> AsyncIterator[str]:
153145
# docstring inherited
154146
for key in self._store_dict:

src/zarr/storage/_obstore.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
from obstore.store import ObjectStore as _UpstreamObjectStore
2424

2525
from zarr.core.buffer import Buffer, BufferPrototype
26-
from zarr.core.common import BytesLike
2726

2827
__all__ = ["ObjectStore"]
2928

@@ -196,17 +195,6 @@ async def delete(self, key: str) -> None:
196195
with contextlib.suppress(FileNotFoundError):
197196
await obs.delete_async(self.store, key)
198197

199-
@property
200-
def supports_partial_writes(self) -> bool:
201-
# docstring inherited
202-
return False
203-
204-
async def set_partial_values(
205-
self, key_start_values: Iterable[tuple[str, int, BytesLike]]
206-
) -> None:
207-
# docstring inherited
208-
raise NotImplementedError
209-
210198
@property
211199
def supports_listing(self) -> bool:
212200
# docstring inherited

src/zarr/storage/_wrapper.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
from zarr.abc.store import ByteRequest
1111
from zarr.core.buffer import Buffer, BufferPrototype
12-
from zarr.core.common import BytesLike
1312

1413
from zarr.abc.store import Store
1514

@@ -119,15 +118,6 @@ def supports_deletes(self) -> bool:
119118
async def delete(self, key: str) -> None:
120119
await self._store.delete(key)
121120

122-
@property
123-
def supports_partial_writes(self) -> bool:
124-
return self._store.supports_partial_writes
125-
126-
async def set_partial_values(
127-
self, key_start_values: Iterable[tuple[str, int, BytesLike]]
128-
) -> None:
129-
return await self._store.set_partial_values(key_start_values)
130-
131121
@property
132122
def supports_listing(self) -> bool:
133123
return self._store.supports_listing

src/zarr/storage/_zip.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ class ZipStore(Store):
4848
allowed_exceptions
4949
supports_writes
5050
supports_deletes
51-
supports_partial_writes
5251
supports_listing
5352
path
5453
compression
@@ -57,7 +56,6 @@ class ZipStore(Store):
5756

5857
supports_writes: bool = True
5958
supports_deletes: bool = False
60-
supports_partial_writes: bool = False
6159
supports_listing: bool = True
6260

6361
path: Path
@@ -222,11 +220,6 @@ async def set(self, key: str, value: Buffer) -> None:
222220
with self._lock:
223221
self._set(key, value)
224222

225-
async def set_partial_values(
226-
self, key_start_values: Iterable[tuple[str, int, bytes | bytearray | memoryview[int]]]
227-
) -> None:
228-
raise NotImplementedError
229-
230223
async def set_if_not_exists(self, key: str, value: Buffer) -> None:
231224
self._check_writable()
232225
with self._lock:

0 commit comments

Comments
 (0)