-
-
Notifications
You must be signed in to change notification settings - Fork 371
Adding copy_store convenience method for Group
#3612
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
base: main
Are you sure you want to change the base?
Changes from 17 commits
e3ee33b
83550a3
d473d6e
bb1405e
c62543a
cdbc2f7
e6e10df
9c42567
63c652e
d4924f5
e83dda5
59b18ea
b65d257
1056b9e
eadb647
8c3471c
2cbb9b9
128b924
fa95e9c
848811f
3398325
ae205b5
06ad2d7
6b81a07
3e92ee9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| Added the convenience method for `zarr.Group` to copy to a destination store which | ||
| can be of a different type than the original store of the `zarr.Group` to be | ||
| copied. This will also copy over the metadata as is. |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -472,6 +472,7 @@ async def from_store( | |||||||||||||||||||||||||||||||||
| store: StoreLike, | ||||||||||||||||||||||||||||||||||
| *, | ||||||||||||||||||||||||||||||||||
| attributes: dict[str, Any] | None = None, | ||||||||||||||||||||||||||||||||||
| consolidated_metadata: ConsolidatedMetadata | None = None, | ||||||||||||||||||||||||||||||||||
| overwrite: bool = False, | ||||||||||||||||||||||||||||||||||
| zarr_format: ZarrFormat = 3, | ||||||||||||||||||||||||||||||||||
| ) -> AsyncGroup: | ||||||||||||||||||||||||||||||||||
|
|
@@ -486,7 +487,11 @@ async def from_store( | |||||||||||||||||||||||||||||||||
| await ensure_no_existing_node(store_path, zarr_format=zarr_format) | ||||||||||||||||||||||||||||||||||
| attributes = attributes or {} | ||||||||||||||||||||||||||||||||||
| group = cls( | ||||||||||||||||||||||||||||||||||
| metadata=GroupMetadata(attributes=attributes, zarr_format=zarr_format), | ||||||||||||||||||||||||||||||||||
| metadata=GroupMetadata( | ||||||||||||||||||||||||||||||||||
| attributes=attributes, | ||||||||||||||||||||||||||||||||||
| consolidated_metadata=consolidated_metadata, | ||||||||||||||||||||||||||||||||||
| zarr_format=zarr_format, | ||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||
| store_path=store_path, | ||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||
| await group._save_metadata(ensure_parents=True) | ||||||||||||||||||||||||||||||||||
|
|
@@ -697,6 +702,91 @@ def from_dict( | |||||||||||||||||||||||||||||||||
| store_path=store_path, | ||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| async def copy_to( | ||||||||||||||||||||||||||||||||||
| self, | ||||||||||||||||||||||||||||||||||
| store: StoreLike, | ||||||||||||||||||||||||||||||||||
| *, | ||||||||||||||||||||||||||||||||||
| overwrite: bool = False, | ||||||||||||||||||||||||||||||||||
| use_consolidated_for_children: bool = True, | ||||||||||||||||||||||||||||||||||
| ) -> AsyncGroup: | ||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||
| Copy this group and all its contents to a new store. | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| Parameters | ||||||||||||||||||||||||||||||||||
| ---------- | ||||||||||||||||||||||||||||||||||
| store : StoreLike | ||||||||||||||||||||||||||||||||||
| The store to copy to. | ||||||||||||||||||||||||||||||||||
| overwrite : bool, optional | ||||||||||||||||||||||||||||||||||
| If True, overwrite any existing data in the target store. Default is False. | ||||||||||||||||||||||||||||||||||
| use_consolidated_for_children : bool, default True | ||||||||||||||||||||||||||||||||||
| Whether to use the consolidated metadata of child groups when iterating over the store contents. | ||||||||||||||||||||||||||||||||||
| Note that this only affects groups loaded from the store. If the current Group already has | ||||||||||||||||||||||||||||||||||
| consolidated metadata, it will always be used. | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| Returns | ||||||||||||||||||||||||||||||||||
| ------- | ||||||||||||||||||||||||||||||||||
| AsyncGroup | ||||||||||||||||||||||||||||||||||
| The new group in the target store. | ||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||
| target_zarr_format = self.metadata.zarr_format | ||||||||||||||||||||||||||||||||||
| group = await self.open(self.store, zarr_format=target_zarr_format) | ||||||||||||||||||||||||||||||||||
melonora marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||
| consolidated_metadata = group.metadata.consolidated_metadata | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| new_group = await AsyncGroup.from_store( | ||||||||||||||||||||||||||||||||||
| store, | ||||||||||||||||||||||||||||||||||
| overwrite=overwrite, | ||||||||||||||||||||||||||||||||||
| attributes=self.metadata.attributes, | ||||||||||||||||||||||||||||||||||
| consolidated_metadata=consolidated_metadata, | ||||||||||||||||||||||||||||||||||
| zarr_format=target_zarr_format, | ||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| async for _, member in self.members( | ||||||||||||||||||||||||||||||||||
| max_depth=None, use_consolidated_for_children=use_consolidated_for_children | ||||||||||||||||||||||||||||||||||
| ): | ||||||||||||||||||||||||||||||||||
| child_path = member.store_path.path | ||||||||||||||||||||||||||||||||||
| target_path = StorePath(store=new_group.store, path=child_path) | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| if isinstance(member, AsyncGroup): | ||||||||||||||||||||||||||||||||||
| await AsyncGroup.from_store( | ||||||||||||||||||||||||||||||||||
| store=target_path, | ||||||||||||||||||||||||||||||||||
| zarr_format=target_zarr_format, | ||||||||||||||||||||||||||||||||||
| overwrite=overwrite, | ||||||||||||||||||||||||||||||||||
| attributes=member.metadata.attributes, | ||||||||||||||||||||||||||||||||||
| consolidated_metadata=member.metadata.consolidated_metadata, | ||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||
| kwargs = {} | ||||||||||||||||||||||||||||||||||
| if target_zarr_format == 3: | ||||||||||||||||||||||||||||||||||
| kwargs["chunk_key_encoding"] = member.metadata.chunk_key_encoding | ||||||||||||||||||||||||||||||||||
| kwargs["dimension_names"] = member.metadata.dimension_names | ||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||
| kwargs["chunk_key_encoding"] = { | ||||||||||||||||||||||||||||||||||
| "name": "v2", | ||||||||||||||||||||||||||||||||||
| "separator": member.metadata.dimension_separator, | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| # Serializer done this way in case of having zarr_format 2, otherwise mypy complains. | ||||||||||||||||||||||||||||||||||
| new_array = await new_group.create_array( | ||||||||||||||||||||||||||||||||||
| name=child_path, | ||||||||||||||||||||||||||||||||||
| shape=member.shape, | ||||||||||||||||||||||||||||||||||
| dtype=member.dtype, | ||||||||||||||||||||||||||||||||||
| chunks=member.chunks, | ||||||||||||||||||||||||||||||||||
| shards=member.shards, | ||||||||||||||||||||||||||||||||||
| filters=member.filters, | ||||||||||||||||||||||||||||||||||
| compressors=member.compressors, | ||||||||||||||||||||||||||||||||||
| serializer=member.serializer if member.serializer is not None else "auto", | ||||||||||||||||||||||||||||||||||
| fill_value=member.metadata.fill_value, | ||||||||||||||||||||||||||||||||||
| attributes=member.attrs, | ||||||||||||||||||||||||||||||||||
| overwrite=overwrite, | ||||||||||||||||||||||||||||||||||
| config={"order": member.order}, | ||||||||||||||||||||||||||||||||||
| **kwargs, | ||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| for region in member._iter_shard_regions(): | ||||||||||||||||||||||||||||||||||
| data = await member.getitem(selection=region) | ||||||||||||||||||||||||||||||||||
| await new_array.setitem(selection=region, value=data) | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| return new_group | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| async def setitem(self, key: str, value: Any) -> None: | ||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||
| Fastpath for creating a new array | ||||||||||||||||||||||||||||||||||
|
|
@@ -945,6 +1035,7 @@ async def create_group( | |||||||||||||||||||||||||||||||||
| *, | ||||||||||||||||||||||||||||||||||
| overwrite: bool = False, | ||||||||||||||||||||||||||||||||||
| attributes: dict[str, Any] | None = None, | ||||||||||||||||||||||||||||||||||
| consolidated_metadata: ConsolidatedMetadata | None = None, | ||||||||||||||||||||||||||||||||||
| ) -> AsyncGroup: | ||||||||||||||||||||||||||||||||||
| """Create a sub-group. | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
|
|
@@ -965,6 +1056,7 @@ async def create_group( | |||||||||||||||||||||||||||||||||
| return await type(self).from_store( | ||||||||||||||||||||||||||||||||||
| self.store_path / name, | ||||||||||||||||||||||||||||||||||
| attributes=attributes, | ||||||||||||||||||||||||||||||||||
| consolidated_metadata=consolidated_metadata, | ||||||||||||||||||||||||||||||||||
| overwrite=overwrite, | ||||||||||||||||||||||||||||||||||
| zarr_format=self.metadata.zarr_format, | ||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||
|
|
@@ -1810,6 +1902,7 @@ def from_store( | |||||||||||||||||||||||||||||||||
| store: StoreLike, | ||||||||||||||||||||||||||||||||||
| *, | ||||||||||||||||||||||||||||||||||
| attributes: dict[str, Any] | None = None, | ||||||||||||||||||||||||||||||||||
| consolidated_metadata: ConsolidatedMetadata | None = None, | ||||||||||||||||||||||||||||||||||
| zarr_format: ZarrFormat = 3, | ||||||||||||||||||||||||||||||||||
| overwrite: bool = False, | ||||||||||||||||||||||||||||||||||
| ) -> Group: | ||||||||||||||||||||||||||||||||||
|
|
@@ -1823,6 +1916,8 @@ def from_store( | |||||||||||||||||||||||||||||||||
| for a description of all valid StoreLike values. | ||||||||||||||||||||||||||||||||||
| attributes : dict, optional | ||||||||||||||||||||||||||||||||||
| A dictionary of JSON-serializable values with user-defined attributes. | ||||||||||||||||||||||||||||||||||
| consolidated_metadata : ConsolidatedMetadata, optional | ||||||||||||||||||||||||||||||||||
| Consolidated Metadata for this Group. This should contain metadata of child nodes below this group. | ||||||||||||||||||||||||||||||||||
| zarr_format : {2, 3}, optional | ||||||||||||||||||||||||||||||||||
| Zarr storage format version. | ||||||||||||||||||||||||||||||||||
| overwrite : bool, optional | ||||||||||||||||||||||||||||||||||
|
|
@@ -1842,6 +1937,7 @@ def from_store( | |||||||||||||||||||||||||||||||||
| AsyncGroup.from_store( | ||||||||||||||||||||||||||||||||||
| store, | ||||||||||||||||||||||||||||||||||
| attributes=attributes, | ||||||||||||||||||||||||||||||||||
| consolidated_metadata=consolidated_metadata, | ||||||||||||||||||||||||||||||||||
| overwrite=overwrite, | ||||||||||||||||||||||||||||||||||
| zarr_format=zarr_format, | ||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||
|
|
@@ -1874,6 +1970,42 @@ def open( | |||||||||||||||||||||||||||||||||
| obj = sync(AsyncGroup.open(store, zarr_format=zarr_format)) | ||||||||||||||||||||||||||||||||||
| return cls(obj) | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| def copy_to( | ||||||||||||||||||||||||||||||||||
| self, | ||||||||||||||||||||||||||||||||||
| store: StoreLike, | ||||||||||||||||||||||||||||||||||
| *, | ||||||||||||||||||||||||||||||||||
| overwrite: bool = False, | ||||||||||||||||||||||||||||||||||
| use_consolidated_for_children: bool = True, | ||||||||||||||||||||||||||||||||||
|
Comment on lines
1985
to
1990
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we should add a test that checks the signature of this function against the signature of the async version. otherwise, they have a tendency to drift. Here's an example of such a test: zarr-python/tests/test_api/test_synchronous.py Lines 26 to 41 in ee0e69a
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. so I did not do the actual docstrings itself, but I did write a test for all methods for classes and their async counterparts. I think this is generalizable to other classes as well, though currently only
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please see |
||||||||||||||||||||||||||||||||||
| ) -> Group: | ||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||
| Copy this group and all its contents to a new store. | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| Parameters | ||||||||||||||||||||||||||||||||||
| ---------- | ||||||||||||||||||||||||||||||||||
| store : StoreLike | ||||||||||||||||||||||||||||||||||
| The store to copy to. | ||||||||||||||||||||||||||||||||||
| overwrite : bool, optional | ||||||||||||||||||||||||||||||||||
| If True, overwrite any existing data in the target store. Default is False. | ||||||||||||||||||||||||||||||||||
| use_consolidated_for_children : bool, default True | ||||||||||||||||||||||||||||||||||
| Whether to use the consolidated metadata of child groups when iterating over the store contents. | ||||||||||||||||||||||||||||||||||
| Note that this only affects groups loaded from the store. If the current Group already has | ||||||||||||||||||||||||||||||||||
| consolidated metadata, it will always be used. | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| Returns | ||||||||||||||||||||||||||||||||||
| ------- | ||||||||||||||||||||||||||||||||||
| AsyncGroup | ||||||||||||||||||||||||||||||||||
| The new group in the target store. | ||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||
| return Group( | ||||||||||||||||||||||||||||||||||
| sync( | ||||||||||||||||||||||||||||||||||
| self._async_group.copy_to( | ||||||||||||||||||||||||||||||||||
| store=store, | ||||||||||||||||||||||||||||||||||
| overwrite=overwrite, | ||||||||||||||||||||||||||||||||||
| use_consolidated_for_children=use_consolidated_for_children, | ||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| def __getitem__(self, path: str) -> AnyArray | Group: | ||||||||||||||||||||||||||||||||||
| """Obtain a group member. | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.