class MetadataError(Exception):
    pass class BadCompressorError(_BaseZarrError):
    _msg = "bad compressor; expected Codec object, found {0!r}" class ContainsArrayError(_BaseZarrError):
    _msg = "path {0!r} contains an array" class ContainsGroupError(_BaseZarrError):
    _msg = "path {0!r} contains a group" class FSPathExistNotDir(GroupNotFoundError):
    _msg = "path exists but is not a directory: %r" class ReadOnlyError(PermissionError):
    def __init__(self):
        super().__init__("object is read-only") @classmethod
def encode_array_metadata(cls, meta: MappingType[str, Any]) -> bytes:
    dtype = meta["dtype"]
    sdshape = ()
    if dtype.subdtype is not None:
        dtype, sdshape = dtype.subdtype

    dimension_separator = meta.get("dimension_separator")
    if dtype.hasobject:
        import numcodecs
        object_codec = numcodecs.get_codec(meta['filters'][0])
    else:
        object_codec = None

    meta = dict(
        zarr_format=cls.ZARR_FORMAT,
        shape=meta["shape"] + sdshape,
        chunks=meta["chunks"],
        dtype=cls.encode_dtype(dtype),
        compressor=meta["compressor"],
        fill_value=cls.encode_fill_value(meta["fill_value"], dtype, object_codec),
        order=meta["order"],
        filters=meta["filters"],
    )
    if dimension_separator:
        meta['dimension_separator'] = dimension_separator

    if dimension_separator:
        meta["dimension_separator"] = dimension_separator

    return json_dumps(meta) @classmethod
def encode_group_metadata(cls, meta=None) -> bytes:
    meta = dict(zarr_format=cls.ZARR_FORMAT)
    return json_dumps(meta) def flatten(arg: Iterable) -> Iterable:
def json_dumps(o: Any) -> bytes:
def json_loads(s: str) -> Dict[str, Any]:
def normalize_shape(shape) -> Tuple[int]:
def guess_chunks(shape: Tuple[int, ...], typesize: int) -> Tuple[int, ...]:
def normalize_chunks(
    chunks: Any, shape: Tuple[int, ...], typesize: int
) -> Tuple[int, ...]:
def normalize_dtype(dtype: Union[str, np.dtype], object_codec) -> Tuple[np.dtype, Any]:
def is_total_slice(item, shape: Tuple[int]) -> bool:
def normalize_resize_args(old_shape, *args):
def human_readable_size(size) -> str:
def normalize_order(order: str) -> str:
def normalize_dimension_separator(sep: Optional[str]) -> Optional[str]:
def normalize_fill_value(fill_value, dtype: np.dtype):
def normalize_storage_path(path: Union[str, bytes, None]) -> str:
def buffer_size(v) -> int:
def info_text_report(items: Dict[Any, Any]) -> str:
def info_html_report(items) -> str:
    def __init__(self, obj):
    def __repr__(self):
    def _repr_html_(self):
    def __init__(self, obj, depth=0, level=None):
    def get_children(self):
    def get_text(self):
    def get_type(self):
    def get_children(self, node):
    def get_root(self, tree):
    def get_text(self, node):
def tree_get_icon(stype: str) -> str:
def tree_widget_sublist(node, root=False, expand=False):
def tree_widget(group, expand, level):
    def __init__(self, group, expand=False, level=None):
    def __bytes__(self):
    def __unicode__(self):
    def __repr__(self):
    def _ipython_display_(self):
def check_array_shape(param, array, shape):
def is_valid_python_name(name):
    def __enter__(self):
    def __exit__(self, *args):
    def __init__(self, store_key, chunk_store):
    def prepare_chunk(self):
    def read_part(self, start, nitems):
    def read_full(self):
def retry_call(callabl: Callable,
               args=None,
               kwargs=None,
               exceptions: Tuple[Any, ...] = (),
               retries: int = 10,
               wait: float = 0.1) -> Any:
def all_equal(value: Any, array: Any):
CHUNK_BASE = 256*1024  # Multiplier by which chunks are adjusted
CHUNK_MIN = 128*1024  # Soft lower limit (128k)
CHUNK_MAX = 64*1024*1024  # Hard upper limit
class InfoReporter:
class TreeNode:
class TreeTraversal(Traversal):
class TreeViewer:
class NoLock:
class PartialReadBuffer: class ABSStore(Store):
    """Storage class using Azure Blob Storage (ABS).

    Parameters
    ----------
    container : string
        The name of the ABS container to use.

        .. deprecated::
           Use ``client`` instead.

    prefix : string
        Location of the "directory" to use as the root of the storage hierarchy
        within the container.

    account_name : string
        The Azure blob storage account name.

        .. deprecated:: 2.8.3
           Use ``client`` instead.

    account_key : string
        The Azure blob storage account access key.

        .. deprecated:: 2.8.3
           Use ``client`` instead.

    blob_service_kwargs : dictionary
        Extra arguments to be passed into the azure blob client, for e.g. when
        using the emulator, pass in blob_service_kwargs={'is_emulated': True}.

        .. deprecated:: 2.8.3
           Use ``client`` instead.

    dimension_separator : {'.', '/'}, optional
        Separator placed between the dimensions of a chunk.

    client : azure.storage.blob.ContainerClient, optional
        And ``azure.storage.blob.ContainerClient`` to connect with. See
        `here <https://docs.microsoft.com/en-us/python/api/azure-storage-blob/azure.storage.blob.containerclient?view=azure-python>`_  # noqa
        for more.

        .. versionadded:: 2.8.3

    Notes
    -----
    In order to use this store, you must install the Microsoft Azure Storage SDK for Python,
    ``azure-storage-blob>=12.5.0``.
    """

    def __init__(self, container=None, prefix='', account_name=None, account_key=None,
                 blob_service_kwargs=None, dimension_separator=None,
                 client=None,
                 ):
        self._dimension_separator = dimension_separator
        self.prefix = normalize_storage_path(prefix)
        if client is None:
            # deprecated option, try to construct the client for them
            msg = (
                "Providing 'container', 'account_name', 'account_key', and 'blob_service_kwargs'"
                "is deprecated. Provide and instance of 'azure.storage.blob.ContainerClient' "
                "'client' instead."
            )
            warnings.warn(msg, FutureWarning, stacklevel=2)
            from azure.storage.blob import ContainerClient
            blob_service_kwargs = blob_service_kwargs or {}
            client = ContainerClient(
                "https://{}.blob.core.windows.net/".format(account_name), container,
                credential=account_key, **blob_service_kwargs
                )

        self.client = client
        self._container = container
        self._account_name = account_name
        self._account_key = account_key

    @staticmethod
    def _warn_deprecated(property_):
        msg = ("The {} property is deprecated and will be removed in a future "
               "version. Get the property from 'ABSStore.client' instead.")
        warnings.warn(msg.format(property_), FutureWarning, stacklevel=3)

    @property
    def container(self):
        self._warn_deprecated("container")
        return self._container

    @property
    def account_name(self):
        self._warn_deprecated("account_name")
        return self._account_name

    @property
    def account_key(self):
        self._warn_deprecated("account_key")
        return self._account_key

    def _append_path_to_prefix(self, path):
        if self.prefix == '':
            return normalize_storage_path(path)
        else:
            return '/'.join([self.prefix, normalize_storage_path(path)])

    @staticmethod
    def _strip_prefix_from_path(path, prefix):
        # normalized things will not have any leading or trailing slashes
        path_norm = normalize_storage_path(path)
        prefix_norm = normalize_storage_path(prefix)
        if prefix:
            return path_norm[(len(prefix_norm)+1):]
        else:
            return path_norm

    def __getitem__(self, key):
        from azure.core.exceptions import ResourceNotFoundError
        blob_name = self._append_path_to_prefix(key)
        try:
            return self.client.download_blob(blob_name).readall()
        except ResourceNotFoundError:
            raise KeyError('Blob %s not found' % blob_name)

    def __setitem__(self, key, value):
        value = ensure_bytes(value)
        blob_name = self._append_path_to_prefix(key)
        self.client.upload_blob(blob_name, value, overwrite=True)

    def __delitem__(self, key):
        from azure.core.exceptions import ResourceNotFoundError
        try:
            self.client.delete_blob(self._append_path_to_prefix(key))
        except ResourceNotFoundError:
            raise KeyError('Blob %s not found' % key)

    def __eq__(self, other):
        return (
            isinstance(other, ABSStore) and
            self.client == other.client and
            self.prefix == other.prefix
        )

    def keys(self):
        return list(self.__iter__())

    def __iter__(self):
        if self.prefix:
            list_blobs_prefix = self.prefix + '/'
        else:
            list_blobs_prefix = None
        for blob in self.client.list_blobs(list_blobs_prefix):
            yield self._strip_prefix_from_path(blob.name, self.prefix)

    def __len__(self):
        return len(self.keys())

    def __contains__(self, key):
        blob_name = self._append_path_to_prefix(key)
        return self.client.get_blob_client(blob_name).exists()

    def listdir(self, path=None):
        dir_path = normalize_storage_path(self._append_path_to_prefix(path))
        if dir_path:
            dir_path += '/'
        items = [
            self._strip_prefix_from_path(blob.name, dir_path)
            for blob in self.client.walk_blobs(name_starts_with=dir_path, delimiter='/')
        ]
        return items

    def rmdir(self, path=None):
        dir_path = normalize_storage_path(self._append_path_to_prefix(path))
        if dir_path:
            dir_path += '/'
        for blob in self.client.list_blobs(name_starts_with=dir_path):
            self.client.delete_blob(blob)

    def getsize(self, path=None):
        store_path = normalize_storage_path(path)
        fs_path = self._append_path_to_prefix(store_path)
        if fs_path:
            blob_client = self.client.get_blob_client(fs_path)
        else:
            blob_client = None

        if blob_client and blob_client.exists():
            return blob_client.get_blob_properties().size
        else:
            size = 0
            if fs_path == '':
                fs_path = None
            elif not fs_path.endswith('/'):
                fs_path += '/'
            for blob in self.client.walk_blobs(name_starts_with=fs_path, delimiter='/'):
                blob_client = self.client.get_blob_client(blob)
                if blob_client.exists():
                    size += blob_client.get_blob_properties().size
            return size

    def clear(self):
        self.rmdir() class BaseStore(MutableMapping):
class Store(BaseStore):
    def is_readable(self):
    def is_writeable(self):
    def is_listable(self):
    def is_erasable(self):
    def __enter__(self):
    def __exit__(self, exc_type, exc_value, traceback):
    def close(self) -> None:
    def rename(self, src_path: str, dst_path: str) -> None:
    def _ensure_store(store: Any):
    def listdir(self, path: str = "") -> List[str]:
    def rmdir(self, path: str = "") -> None:
def _path_to_prefix(path: Optional[str]) -> str:
def _rename_from_keys(store: BaseStore, src_path: str, dst_path: str) -> None:
def _rmdir_from_keys(store: Union[BaseStore, MutableMapping], path: Optional[str] = None) -> None:
def _listdir_from_keys(store: BaseStore, path: Optional[str] = None) -> List[str]:
import atexit
import errno
import glob
import multiprocessing
import operator
import os
import re
import shutil
import sys
import tempfile
import warnings
import zipfile
import uuid
import time
        import fsspec
            import dbm
        import lmdb
        import sqlite3
        import pymongo
        import redis
from collections import OrderedDict
from collections.abc import MutableMapping
from os import scandir
from pickle import PicklingError
from threading import Lock, RLock
from typing import Optional, Union, List, Tuple, Dict, Any
from numcodecs.compat import (
    ensure_bytes,
    ensure_text,
    ensure_contiguous_ndarray
)
from numcodecs.registry import codec_registry
from zarr.errors import (
    MetadataError,
    BadCompressorError,
    ContainsArrayError,
    ContainsGroupError,
    FSPathExistNotDir,
    ReadOnlyError,
)
from zarr.meta import encode_array_metadata, encode_group_metadata
from zarr.util import (buffer_size, json_loads, nolock, normalize_chunks,
                       normalize_dimension_separator,
                       normalize_dtype, normalize_fill_value, normalize_order,
                       normalize_shape, normalize_storage_path, retry_call)
from zarr._storage.absstore import ABSStore  # noqa: F401
from zarr._storage.store import (_listdir_from_keys,
                                 _path_to_prefix,
                                 _rename_from_keys,
                                 _rmdir_from_keys,
                                 array_meta_key,
                                 group_meta_key,
                                 attrs_key,
                                 BaseStore,
                                 Store)
    from zarr.codecs import Blosc
    from zarr.codecs import Zlib
            from zarr.n5 import N5Store
    from zarr import meta_v1
    chunks = normalize_chunks(chunks, shape, dtype.itemsize)
    order = normalize_order(order)
    fill_value = normalize_fill_value(fill_value, dtype)

    # optional array metadata
    if dimension_separator is None:
        dimension_separator = getattr(store, "_dimension_separator", None)
    dimension_separator = normalize_dimension_separator(dimension_separator)

    # compressor prep
    if shape == ():
        # no point in compressing a 0-dimensional array, only a single value
        compressor = None
    elif compressor == 'none':
        # compatibility
        compressor = None
    elif compressor == 'default':
        compressor = default_compressor

    # obtain compressor config
    compressor_config = None
    if compressor:
        try:
            compressor_config = compressor.get_config()
        except AttributeError as e:
            raise BadCompressorError(compressor) from e

    # obtain filters config
    if filters:
        filters_config = [f.get_config() for f in filters]
    else:
        filters_config = []

    # deal with object encoding
    if dtype.hasobject:
        if object_codec is None:
            if not filters:
                # there are no filters so we can be sure there is no object codec
                raise ValueError('missing object_codec for object array')
            else:
                # one of the filters may be an object codec, issue a warning rather
                # than raise an error to maintain backwards-compatibility
                warnings.warn('missing object_codec for object array; this will raise a '
                              'ValueError in version 3.0', FutureWarning)
        else:
            filters_config.insert(0, object_codec.get_config())
    elif object_codec is not None:
        warnings.warn('an object_codec is only needed for object arrays')

    # use null to indicate no filters
    if not filters_config:
        filters_config = None  # type: ignore

    # initialize metadata
    meta = dict(shape=shape, chunks=chunks, dtype=dtype,
                compressor=compressor_config, fill_value=fill_value,
                order=order, filters=filters_config,
                dimension_separator=dimension_separator)
    key = _path_to_prefix(path) + array_meta_key
    if hasattr(store, '_metadata_class'):
        store[key] = store._metadata_class.encode_array_metadata(meta)  # type: ignore
    else:
        store[key] = encode_array_metadata(meta)


# backwards compatibility
init_store = init_array


def init_group(
    store: StoreLike,
    overwrite: bool = False,
    path: Path = None,
    chunk_store: StoreLike = None,
):
    """Initialize a group store. Note that this is a low-level function and there should be no
    need to call this directly from user code.

    Parameters
    ----------
    store : Store
        A mapping that supports string keys and byte sequence values.
    overwrite : bool, optional
        If True, erase all data in `store` prior to initialisation.
    path : string, optional
        Path under which array is stored.
    chunk_store : Store, optional
        Separate storage for chunks. If not provided, `store` will be used
        for storage of both chunks and metadata.

    """

    # normalize path
    path = normalize_storage_path(path)

    # ensure parent group initialized
    _require_parent_group(path, store=store, chunk_store=chunk_store,
                          overwrite=overwrite)

    # initialise metadata
    _init_group_metadata(store=store, overwrite=overwrite, path=path,
                         chunk_store=chunk_store)


def _init_group_metadata(
    store: StoreLike,
    overwrite: Optional[bool] = False,
    path: Optional[str] = None,
    chunk_store: StoreLike = None,
):

    # guard conditions
    if overwrite:
        # attempt to delete any pre-existing items in store
        rmdir(store, path)
        if chunk_store is not None:
            rmdir(chunk_store, path)
    elif contains_array(store, path):
        raise ContainsArrayError(path)
    elif contains_group(store, path):

        raise ContainsGroupError(path)