Skip to content

Commit

Permalink
Bootstrap v3 branch with zarrita (zarr-developers#1584)
Browse files Browse the repository at this point in the history
* Pull Zarrita into Zarr-Python @ 78274781ad64aef95772eb4b083f7ea9b7d03d06

No code changes to Zarrita were made.

* apply zarr lint rules

* zarrita -> v3

* v3/abc [wip]

* use abcs plus implementation notes
  • Loading branch information
jhamman committed Jan 24, 2024
1 parent a81db07 commit 017d9a0
Show file tree
Hide file tree
Showing 17 changed files with 4,090 additions and 0 deletions.
40 changes: 40 additions & 0 deletions zarr/v3/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from __future__ import annotations

from typing import Union

import zarr.v3.codecs # noqa: F401
from zarr.v3.array import Array # noqa: F401
from zarr.v3.array_v2 import ArrayV2 # noqa: F401
from zarr.v3.group import Group # noqa: F401
from zarr.v3.group_v2 import GroupV2 # noqa: F401
from zarr.v3.metadata import RuntimeConfiguration, runtime_configuration # noqa: F401
from zarr.v3.store import ( # noqa: F401
LocalStore,
RemoteStore,
Store,
StoreLike,
StorePath,
make_store_path,
)
from zarr.v3.sync import sync as _sync


async def open_auto_async(
store: StoreLike,
runtime_configuration_: RuntimeConfiguration = RuntimeConfiguration(),
) -> Union[Array, ArrayV2, Group, GroupV2]:
store_path = make_store_path(store)
try:
return await Group.open_or_array(store_path, runtime_configuration=runtime_configuration_)
except KeyError:
return await GroupV2.open_or_array(store_path, runtime_configuration_)


def open_auto(
store: StoreLike,
runtime_configuration_: RuntimeConfiguration = RuntimeConfiguration(),
) -> Union[Array, ArrayV2, Group, GroupV2]:
return _sync(
open_auto_async(store, runtime_configuration_),
runtime_configuration_.asyncio_loop,
)
Empty file added zarr/v3/abc/__init__.py
Empty file.
140 changes: 140 additions & 0 deletions zarr/v3/abc/array.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
from __future__ import annotations
from abc import abstractproperty, abstractmethod, ABC
from typing import Tuple, Any, Dict

import numpy as np

from zarr.v3.abc.store import ReadStore, WriteStore
from zarr.v3.common import Selection


class BaseArray(ABC):
@abstractproperty
def store_path(self) -> str: # TODO: rename to `path`?
"""Path to this array in the underlying store."""
...

@abstractproperty
def dtype(self) -> np.dtype:
"""Data type of the array elements.
Returns
-------
dtype
array data type
"""
...

@abstractproperty
def ndim(self) -> int:
"""Number of array dimensions (axes).
Returns
-------
int
number of array dimensions (axes)
"""
...

@abstractproperty
def shape(self) -> Tuple[int, ...]:
"""Array dimensions.
Returns
-------
tuple of int
array dimensions
"""
...

@abstractproperty
def size(self) -> int:
"""Number of elements in the array.
Returns
-------
int
number of elements in an array.
"""

@abstractproperty
def attrs(self) -> Dict[str, Any]:
"""Array attributes.
Returns
-------
dict
user defined attributes
"""
...

@abstractproperty
def info(self) -> Any:
"""Report some diagnostic information about the array.
Returns
-------
out
"""
...


class AsynchronousArray(BaseArray):
"""This class can be implemented as a v2 or v3 array"""

@classmethod
@abstractmethod
async def from_json(cls, zarr_json: Any, store: ReadStore) -> AsynchronousArray:
...

@classmethod
@abstractmethod
async def open(cls, store: ReadStore) -> AsynchronousArray:
...

@classmethod
@abstractmethod
async def create(cls, store: WriteStore, *, shape, **kwargs) -> AsynchronousArray:
...

@abstractmethod
async def getitem(self, selection: Selection):
...

@abstractmethod
async def setitem(self, selection: Selection, value: np.ndarray) -> None:
...


class SynchronousArray(BaseArray):
"""
This class can be implemented as a v2 or v3 array
"""

@classmethod
@abstractmethod
def from_json(cls, zarr_json: Any, store: ReadStore) -> SynchronousArray:
...

@classmethod
@abstractmethod
def open(cls, store: ReadStore) -> SynchronousArray:
...

@classmethod
@abstractmethod
def create(cls, store: WriteStore, *, shape, **kwargs) -> SynchronousArray:
...

@abstractmethod
def __getitem__(self, selection: Selection): # TODO: type as np.ndarray | scalar
...

@abstractmethod
def __setitem__(self, selection: Selection, value: np.ndarray) -> None:
...

# some day ;)
# @property
# def __array_api_version__(self) -> str:
# return "2022.12"
84 changes: 84 additions & 0 deletions zarr/v3/abc/codec.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Notes:
# 1. These are missing methods described in the spec. I expected to see these method definitions:
# def compute_encoded_representation_type(self, decoded_representation_type):
# def encode(self, decoded_value):
# def decode(self, encoded_value, decoded_representation_type):
# def partial_decode(self, input_handle, decoded_representation_type, decoded_regions):
# def compute_encoded_size(self, input_size):
# 2. Understand why array metadata is included on all codecs


from __future__ import annotations

from abc import abstractmethod, ABC
from typing import TYPE_CHECKING, Optional

import numpy as np

from zarr.v3.common import BytesLike


if TYPE_CHECKING:
from zarr.v3.metadata import CoreArrayMetadata


class Codec(ABC):
supports_partial_decode: bool
supports_partial_encode: bool
is_fixed_size: bool
array_metadata: CoreArrayMetadata

@abstractmethod
def compute_encoded_size(self, input_byte_length: int) -> int:
pass

def resolve_metadata(self) -> CoreArrayMetadata:
return self.array_metadata


class ArrayArrayCodec(Codec):
@abstractmethod
async def decode(
self,
chunk_array: np.ndarray,
) -> np.ndarray:
pass

@abstractmethod
async def encode(
self,
chunk_array: np.ndarray,
) -> Optional[np.ndarray]:
pass


class ArrayBytesCodec(Codec):
@abstractmethod
async def decode(
self,
chunk_array: BytesLike,
) -> np.ndarray:
pass

@abstractmethod
async def encode(
self,
chunk_array: np.ndarray,
) -> Optional[BytesLike]:
pass


class BytesBytesCodec(Codec):
@abstractmethod
async def decode(
self,
chunk_array: BytesLike,
) -> BytesLike:
pass

@abstractmethod
async def encode(
self,
chunk_array: BytesLike,
) -> Optional[BytesLike]:
pass
86 changes: 86 additions & 0 deletions zarr/v3/abc/group.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
from __future__ import annotations

from abc import abstractproperty, ABC
from collections.abc import MutableMapping
from typing import Dict, Any


class BaseGroup(ABC):
@abstractproperty
def attrs(self) -> Dict[str, Any]:
"""User-defined attributes."""
...

@abstractproperty
def info(self) -> Any: # TODO: type this later
"""Return diagnostic information about the group."""
...


class AsynchronousGroup(BaseGroup):
pass
# TODO: (considering the following api)
# store_path (rename to path?)
# nchildren - number of child groups + arrays
# children (async iterator)
# contains - check if child exists
# getitem - get child
# group_keys (async iterator)
# groups (async iterator)
# array_keys (async iterator)
# arrays (async iterator)
# visit
# visitkeys
# visitvalues
# tree
# create_group
# require_group
# create_groups
# require_groups
# create_dataset
# require_dataset
# create
# empty
# zeros
# ones
# full
# array
# empty_like
# zeros_like
# ones_like
# full_like
# move


class SynchronousGroup(BaseGroup, MutableMapping):
# TODO - think about if we want to keep the MutableMapping abstraction or
pass
# store_path (rename to path?)
# __enter__
# __exit__
# group_keys
# groups
# array_keys
# arrays
# visit
# visitkeys
# visitvalues
# visititems
# tree
# create_group
# require_group
# create_groups
# require_groups
# create_dataset
# require_dataset
# create
# empty
# zeros
# ones
# full
# array
# empty_like
# zeros_like
# ones_like
# full_like
# move
Loading

0 comments on commit 017d9a0

Please sign in to comment.