Skip to content

Commit c6c8843

Browse files
committed
add _path attribute to localstore that caches a pathlib.Path version of the path attribute
1 parent b4b9c28 commit c6c8843

File tree

1 file changed

+14
-13
lines changed

1 file changed

+14
-13
lines changed

src/zarr/storage/local.py

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121

2222
def _get(
23-
path: str, prototype: BufferPrototype, byte_range: tuple[int | None, int | None] | None
23+
path: Path, prototype: BufferPrototype, byte_range: tuple[int | None, int | None] | None
2424
) -> Buffer:
2525
"""
2626
Fetch a contiguous region of bytes from a file.
@@ -35,7 +35,6 @@ def _get(
3535
and the second value specifies the total number of bytes to read. If the total value is
3636
`None`, then the entire file after the first byte will be read.
3737
"""
38-
target = Path(path)
3938
if byte_range is not None:
4039
if byte_range[0] is None:
4140
start = 0
@@ -44,8 +43,8 @@ def _get(
4443

4544
end = (start + byte_range[1]) if byte_range[1] is not None else None
4645
else:
47-
return prototype.buffer.from_bytes(target.read_bytes())
48-
with target.open("rb") as f:
46+
return prototype.buffer.from_bytes(path.read_bytes())
47+
with path.open("rb") as f:
4948
size = f.seek(0, io.SEEK_END)
5049
if start is not None:
5150
if start >= 0:
@@ -105,13 +104,15 @@ class LocalStore(Store):
105104
supports_deletes: bool = True
106105
supports_partial_writes: bool = True
107106
supports_listing: bool = True
107+
_path: Path
108108

109109
def __init__(self, path: Path | str, *, mode: AccessModeLiteral = "r") -> None:
110110
super().__init__(mode=mode, path=str(path))
111+
self._path = Path(self.path)
111112

112113
async def _open(self) -> None:
113114
if not self.mode.readonly:
114-
Path(self.path).mkdir(parents=True, exist_ok=True)
115+
self._path.mkdir(parents=True, exist_ok=True)
115116
return await super()._open()
116117

117118
async def clear(self) -> None:
@@ -156,7 +157,7 @@ async def get(
156157
if not self._is_open:
157158
await self._open()
158159

159-
path = os.path.join(self.path, key)
160+
path = self._path / key
160161

161162
try:
162163
return await asyncio.to_thread(_get, path, prototype, byte_range)
@@ -172,7 +173,7 @@ async def get_partial_values(
172173
args = []
173174
for key, byte_range in key_ranges:
174175
assert isinstance(key, str)
175-
path = os.path.join(self.path, key)
176+
path = self._path / key
176177
args.append((_get, path, prototype, byte_range))
177178
return await concurrent_map(args, asyncio.to_thread, limit=None) # TODO: fix limit
178179

@@ -194,7 +195,7 @@ async def _set(self, key: str, value: Buffer, exclusive: bool = False) -> None:
194195
assert isinstance(key, str)
195196
if not isinstance(value, Buffer):
196197
raise TypeError("LocalStore.set(): `value` must a Buffer instance")
197-
path = Path(self.path) / key
198+
path = self._path / key
198199
await asyncio.to_thread(_put, path, value, start=None, exclusive=exclusive)
199200

200201
async def set_partial_values(
@@ -212,15 +213,15 @@ async def set_partial_values(
212213
async def delete(self, key: str) -> None:
213214
# docstring inherited
214215
self._check_writable()
215-
path = Path(self.path) / key
216+
path = self._path / key
216217
if path.is_dir(): # TODO: support deleting directories? shutil.rmtree?
217218
shutil.rmtree(path)
218219
else:
219220
await asyncio.to_thread(path.unlink, True) # Q: we may want to raise if path is missing
220221

221222
async def exists(self, key: str) -> bool:
222223
# docstring inherited
223-
path = Path(self.path) / key
224+
path = self._path / key
224225
return await asyncio.to_thread(path.is_file)
225226

226227
async def list(self) -> AsyncGenerator[str, None]:
@@ -232,21 +233,21 @@ async def list(self) -> AsyncGenerator[str, None]:
232233
"""
233234
# TODO: just invoke list_prefix with the prefix "/"
234235
to_strip = self.path + "/"
235-
for p in Path(self.path).rglob("*"):
236+
for p in self._path.rglob("*"):
236237
if p.is_file():
237238
yield str(p.relative_to(to_strip))
238239

239240
async def list_prefix(self, prefix: str) -> AsyncGenerator[str, None]:
240241
# docstring inherited
241242
to_strip = os.path.join(self.path, prefix)
242-
for p in (Path(self.path) / prefix).rglob("*"):
243+
for p in (self._path / prefix).rglob("*"):
243244
if p.is_file():
244245
yield str(p.relative_to(to_strip))
245246

246247
async def list_dir(self, prefix: str) -> AsyncGenerator[str, None]:
247248
# docstring inherited
248249
base = os.path.join(self.path, prefix)
249-
to_strip = str(base) + "/"
250+
to_strip = base + "/"
250251

251252
try:
252253
key_iter = Path(base).iterdir()

0 commit comments

Comments
 (0)