-
-
Notifications
You must be signed in to change notification settings - Fork 366
Feat/latency store #2474
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Feat/latency store #2474
Changes from 8 commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
8407c64
feat: add wrapperstore
d-v-b 5e9ffb8
feat: add latencystore
d-v-b 5d7abf4
rename noisysetter -> noisygetter
d-v-b c486351
rename _wrapped to _store
d-v-b f97b27c
loggingstore inherits from wrapperstore
d-v-b 5ba51af
Merge branch 'main' into feat/latency-store
d-v-b 53c8738
Merge branch 'main' of github.com:zarr-developers/zarr-python into fe…
d-v-b 04bac27
Merge branch 'main' into feat/latency-store
d-v-b cd02e97
Update src/zarr/storage/wrapper.py
d-v-b e9f414b
back to asynciterators
d-v-b e826940
update docstrings
d-v-b a992bbb
Merge branch 'main' into feat/latency-store
d-v-b 12d3f75
Merge branch 'main' into feat/latency-store
d-v-b 328e290
Merge branch 'main' into feat/latency-store
dcherian File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,139 @@ | ||
| from __future__ import annotations | ||
|
|
||
| from typing import TYPE_CHECKING, Generic, TypeVar | ||
|
|
||
| if TYPE_CHECKING: | ||
| from collections.abc import AsyncGenerator, AsyncIterator, Iterable | ||
| from types import TracebackType | ||
| from typing import Any, Self | ||
|
|
||
| from zarr.abc.store import ByteRangeRequest | ||
| from zarr.core.buffer import Buffer, BufferPrototype | ||
| from zarr.core.common import BytesLike | ||
|
|
||
| from zarr.abc.store import Store | ||
|
|
||
| T_Store = TypeVar("T_Store", bound=Store) | ||
|
|
||
|
|
||
| class WrapperStore(Store, Generic[T_Store]): | ||
| """ | ||
| A store class that wraps an existing ``Store`` instance. | ||
| By default all of the store methods are delegated to the wrapped store instance, which is | ||
| accessible via the ``._wrapped`` attribute of this class. | ||
d-v-b marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| Use this class to modify or extend the behavior of the other store classes. | ||
| """ | ||
|
|
||
| _store: T_Store | ||
|
|
||
| def __init__(self, store: T_Store) -> None: | ||
| self._store = store | ||
|
|
||
| @classmethod | ||
| async def open(cls: type[Self], store_cls: type[T_Store], *args: Any, **kwargs: Any) -> Self: | ||
| store = store_cls(*args, **kwargs) | ||
| await store._open() | ||
| return cls(store=store) | ||
|
|
||
| def __enter__(self) -> Self: | ||
| return type(self)(self._store.__enter__()) | ||
|
|
||
| def __exit__( | ||
| self, | ||
| exc_type: type[BaseException] | None, | ||
| exc_value: BaseException | None, | ||
| traceback: TracebackType | None, | ||
| ) -> None: | ||
| return self._store.__exit__(exc_type, exc_value, traceback) | ||
|
|
||
| async def _open(self) -> None: | ||
| await self._store._open() | ||
|
|
||
| async def _ensure_open(self) -> None: | ||
| await self._store._ensure_open() | ||
|
|
||
| async def is_empty(self, prefix: str) -> bool: | ||
| return await self._store.is_empty(prefix) | ||
|
|
||
| async def clear(self) -> None: | ||
| return await self._store.clear() | ||
|
|
||
| @property | ||
| def read_only(self) -> bool: | ||
| return self._store.read_only | ||
|
|
||
| def _check_writable(self) -> None: | ||
| return self._store._check_writable() | ||
|
|
||
| def __eq__(self, value: object) -> bool: | ||
| return type(self) is type(value) and self._store.__eq__(value) | ||
|
|
||
| async def get( | ||
| self, key: str, prototype: BufferPrototype, byte_range: ByteRangeRequest | None = None | ||
| ) -> Buffer | None: | ||
| return await self._store.get(key, prototype, byte_range) | ||
|
|
||
| async def get_partial_values( | ||
| self, | ||
| prototype: BufferPrototype, | ||
| key_ranges: Iterable[tuple[str, ByteRangeRequest]], | ||
| ) -> list[Buffer | None]: | ||
| return await self._store.get_partial_values(prototype, key_ranges) | ||
|
|
||
| async def exists(self, key: str) -> bool: | ||
| return await self._store.exists(key) | ||
|
|
||
| async def set(self, key: str, value: Buffer) -> None: | ||
| await self._store.set(key, value) | ||
|
|
||
| async def set_if_not_exists(self, key: str, value: Buffer) -> None: | ||
| return await self._store.set_if_not_exists(key, value) | ||
|
|
||
| async def _set_many(self, values: Iterable[tuple[str, Buffer]]) -> None: | ||
| await self._store._set_many(values) | ||
|
|
||
| @property | ||
| def supports_writes(self) -> bool: | ||
| return self._store.supports_writes | ||
|
|
||
| @property | ||
| def supports_deletes(self) -> bool: | ||
| return self._store.supports_deletes | ||
|
|
||
| async def delete(self, key: str) -> None: | ||
| await self._store.delete(key) | ||
|
|
||
| @property | ||
| def supports_partial_writes(self) -> bool: | ||
| return self._store.supports_partial_writes | ||
|
|
||
| async def set_partial_values( | ||
| self, key_start_values: Iterable[tuple[str, int, BytesLike]] | ||
| ) -> None: | ||
| return await self._store.set_partial_values(key_start_values) | ||
|
|
||
| @property | ||
| def supports_listing(self) -> bool: | ||
| return self._store.supports_listing | ||
|
|
||
| def list(self) -> AsyncIterator[str]: | ||
| return self._store.list() | ||
|
|
||
| def list_prefix(self, prefix: str) -> AsyncIterator[str]: | ||
| return self._store.list_prefix(prefix) | ||
|
|
||
| def list_dir(self, prefix: str) -> AsyncIterator[str]: | ||
| return self._store.list_dir(prefix) | ||
|
|
||
| async def delete_dir(self, prefix: str) -> None: | ||
| return await self._store.delete_dir(prefix) | ||
|
|
||
| def close(self) -> None: | ||
| self._store.close() | ||
|
|
||
| async def _get_many( | ||
| self, requests: Iterable[tuple[str, BufferPrototype, ByteRangeRequest | None]] | ||
| ) -> AsyncGenerator[tuple[str, Buffer | None], None]: | ||
| async for req in self._store._get_many(requests): | ||
| yield req | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| from __future__ import annotations | ||
|
|
||
| from typing import TYPE_CHECKING | ||
|
|
||
| import pytest | ||
|
|
||
| from zarr.core.buffer.cpu import Buffer, buffer_prototype | ||
| from zarr.storage.wrapper import WrapperStore | ||
|
|
||
| if TYPE_CHECKING: | ||
| from zarr.abc.store import Store | ||
| from zarr.core.buffer.core import BufferPrototype | ||
|
|
||
|
|
||
| @pytest.mark.parametrize("store", ["local", "memory", "zip"], indirect=True) | ||
| async def test_wrapped_set(store: Store, capsys: pytest.CaptureFixture[str]) -> None: | ||
| # define a class that prints when it sets | ||
| class NoisySetter(WrapperStore): | ||
| async def set(self, key: str, value: Buffer) -> None: | ||
| print(f"setting {key}") | ||
| await super().set(key, value) | ||
|
|
||
| key = "foo" | ||
| value = Buffer.from_bytes(b"bar") | ||
| store_wrapped = NoisySetter(store) | ||
| await store_wrapped.set(key, value) | ||
| captured = capsys.readouterr() | ||
| assert f"setting {key}" in captured.out | ||
| assert await store_wrapped.get(key, buffer_prototype) == value | ||
|
|
||
|
|
||
| @pytest.mark.parametrize("store", ["local", "memory", "zip"], indirect=True) | ||
| async def test_wrapped_get(store: Store, capsys: pytest.CaptureFixture[str]) -> None: | ||
| # define a class that prints when it sets | ||
| class NoisyGetter(WrapperStore): | ||
| def get(self, key: str, prototype: BufferPrototype) -> None: | ||
| print(f"getting {key}") | ||
| return super().get(key, prototype=prototype) | ||
|
|
||
| key = "foo" | ||
| value = Buffer.from_bytes(b"bar") | ||
| store_wrapped = NoisyGetter(store) | ||
| await store_wrapped.set(key, value) | ||
| assert await store_wrapped.get(key, buffer_prototype) == value | ||
| captured = capsys.readouterr() | ||
| assert f"getting {key}" in captured.out |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.