Skip to content

refactor warnings #3098

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

Open
wants to merge 24 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
79dd9e2
define zarr-specific FutureWarning and DeprecationWarning
d-v-b May 25, 2025
b2e25cf
Merge branch 'main' of github.com:zarr-developers/zarr-python into re…
d-v-b Jun 30, 2025
7c644eb
make unstablespecificationwarning an instance of zarrfuturewarning
d-v-b Jun 30, 2025
c604075
use pytest.warns instead of pytest.raises
d-v-b Jun 30, 2025
b964ff6
Merge branch 'main' into refactor-warnings
d-v-b Jul 11, 2025
12bea9c
Merge branch 'main' into refactor-warnings
d-v-b Jul 11, 2025
8267c0c
Merge branch 'main' into refactor-warnings
d-v-b Jul 11, 2025
702ef09
Merge branch 'main' of https://github.com/zarr-developers/zarr-python…
d-v-b Jul 31, 2025
64e1405
changelog
d-v-b Jul 31, 2025
d322cad
ensure that all deprecations are ZarrDeprecations
d-v-b Aug 1, 2025
31e63aa
add docstrings and export warnings
d-v-b Aug 1, 2025
917fd3d
fix imports
d-v-b Aug 1, 2025
9055d3b
handle warnings in tests explicitly; make userwarnings ZarrUserWarning
d-v-b Aug 1, 2025
fee48d3
fix doctests by making them more realistic
d-v-b Aug 1, 2025
6a208eb
lint and fix typo
d-v-b Aug 1, 2025
8a2bb9e
Merge branch 'main' into refactor-warnings
d-v-b Aug 1, 2025
a235660
move unstable spec warning to errors
d-v-b Aug 1, 2025
8afdce9
Merge branch 'refactor-warnings' of https://github.com/d-v-b/zarr-pyt…
d-v-b Aug 1, 2025
33a9184
handle warnings in gpu tests
d-v-b Aug 1, 2025
fc72752
handle more warnings
d-v-b Aug 1, 2025
42b4cb5
handle another warning
d-v-b Aug 1, 2025
713bda9
Fix exports
d-v-b Aug 1, 2025
f483eb8
Update src/zarr/errors.py
d-v-b Aug 2, 2025
d029800
Update changes/3098.misc.rst
d-v-b Aug 2, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions changes/3098.misc.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Define Zarr-specific warning classes `ZarrDeprecationWarning` and `ZarrFutureWarning`, that
subclass `DeprecationWarning` and `FutureWarning`, respectively.
2 changes: 2 additions & 0 deletions docs/user-guide/arrays.rst
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,8 @@ built-in delta filter::

>>> import lzma
>>> from numcodecs.zarr3 import LZMA
>>> import warnings
>>> warnings.filterwarnings("ignore", category=UserWarning)
>>>
>>> lzma_filters = [dict(id=lzma.FILTER_DELTA, dist=4), dict(id=lzma.FILTER_LZMA2, preset=1)]
>>> compressors = LZMA(filters=lzma_filters)
Expand Down
2 changes: 2 additions & 0 deletions docs/user-guide/consolidated_metadata.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ In Python, the consolidated metadata is available on the ``.consolidated_metadat
attribute of the ``GroupMetadata`` object.

>>> import zarr
>>> import warnings
>>> warnings.filterwarnings("ignore", category=UserWarning)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to remove these new lines, and instead include the warnings in the docstest output? Instead of hiding the warnings, it would be nice to be honest about them 😄

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, I don't think we want to do that in our docs.

>>>
>>> store = zarr.storage.MemoryStore()
>>> group = zarr.create_group(store=store)
Expand Down
10 changes: 0 additions & 10 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -403,16 +403,6 @@ addopts = [
]
filterwarnings = [
"error",
# TODO: explicitly filter or catch the warnings below where we expect them to be emitted in the tests
"ignore:Consolidated metadata is currently not part in the Zarr format 3 specification.*:UserWarning",
"ignore:Creating a zarr.buffer.gpu.Buffer with an array that does not support the __cuda_array_interface__.*:UserWarning",
"ignore:Automatic shard shape inference is experimental and may change without notice.*:UserWarning",
"ignore:The codec .* is currently not part in the Zarr format 3 specification.*:UserWarning",
"ignore:The dtype .* is currently not part in the Zarr format 3 specification.*:UserWarning",
"ignore:Use zarr.create_array instead.:DeprecationWarning",
"ignore:Duplicate name.*:UserWarning",
"ignore:The `compressor` argument is deprecated. Use `compressors` instead.:UserWarning",
"ignore:Numcodecs codecs are not in the Zarr version 3 specification and may not be supported by other zarr implementations.:UserWarning",
"ignore:Unclosed client session <aiohttp.client.ClientSession.*:ResourceWarning"
]
markers = [
Expand Down
4 changes: 3 additions & 1 deletion src/zarr/_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
from inspect import Parameter, signature
from typing import Any, TypeVar

from zarr.errors import ZarrFutureWarning

T = TypeVar("T")

# Based off https://github.com/scikit-learn/scikit-learn/blob/e87b32a81c70abed8f2e97483758eb64df8255e9/sklearn/utils/validation.py#L63
Expand Down Expand Up @@ -54,7 +56,7 @@ def inner_f(*args: Any, **kwargs: Any) -> T:
f"{version} passing these as positional arguments "
"will result in an error"
),
FutureWarning,
ZarrFutureWarning,
stacklevel=2,
)
kwargs.update(zip(sig.parameters, args, strict=False))
Expand Down
46 changes: 26 additions & 20 deletions src/zarr/api/asynchronous.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,13 @@
create_hierarchy,
)
from zarr.core.metadata import ArrayMetadataDict, ArrayV2Metadata, ArrayV3Metadata
from zarr.errors import GroupNotFoundError, NodeTypeValidationError
from zarr.errors import (
GroupNotFoundError,
NodeTypeValidationError,
ZarrDeprecationWarning,
ZarrRuntimeWarning,
ZarrUserWarning,
)
from zarr.storage import StorePath
from zarr.storage._common import make_store_path

Expand Down Expand Up @@ -162,7 +168,7 @@ def _handle_zarr_version_or_format(
)
if zarr_version is not None:
warnings.warn(
"zarr_version is deprecated, use zarr_format", DeprecationWarning, stacklevel=2
"zarr_version is deprecated, use zarr_format", ZarrDeprecationWarning, stacklevel=2
)
return zarr_version
return zarr_format
Expand Down Expand Up @@ -228,7 +234,7 @@ async def consolidate_metadata(
warnings.warn(
"Consolidated metadata is currently not part in the Zarr format 3 specification. It "
"may not be supported by other zarr implementations and may change in the future.",
category=UserWarning,
category=ZarrUserWarning,
stacklevel=1,
)

Expand Down Expand Up @@ -536,7 +542,7 @@ async def save_group(
await asyncio.gather(*aws)


@deprecated("Use AsyncGroup.tree instead.")
@deprecated("Use AsyncGroup.tree instead.", category=ZarrDeprecationWarning)
async def tree(grp: AsyncGroup, expand: bool | None = None, level: int | None = None) -> Any:
"""Provide a rich display of the hierarchy.

Expand Down Expand Up @@ -674,13 +680,13 @@ async def group(
store_path = await make_store_path(store, path=path, mode=mode, storage_options=storage_options)

if chunk_store is not None:
warnings.warn("chunk_store is not yet implemented", RuntimeWarning, stacklevel=2)
warnings.warn("chunk_store is not yet implemented", ZarrRuntimeWarning, stacklevel=2)
if cache_attrs is not None:
warnings.warn("cache_attrs is not yet implemented", RuntimeWarning, stacklevel=2)
warnings.warn("cache_attrs is not yet implemented", ZarrRuntimeWarning, stacklevel=2)
if synchronizer is not None:
warnings.warn("synchronizer is not yet implemented", RuntimeWarning, stacklevel=2)
warnings.warn("synchronizer is not yet implemented", ZarrRuntimeWarning, stacklevel=2)
if meta_array is not None:
warnings.warn("meta_array is not yet implemented", RuntimeWarning, stacklevel=2)
warnings.warn("meta_array is not yet implemented", ZarrRuntimeWarning, stacklevel=2)

if attributes is None:
attributes = {}
Expand Down Expand Up @@ -827,13 +833,13 @@ async def open_group(
zarr_format = _handle_zarr_version_or_format(zarr_version=zarr_version, zarr_format=zarr_format)

if cache_attrs is not None:
warnings.warn("cache_attrs is not yet implemented", RuntimeWarning, stacklevel=2)
warnings.warn("cache_attrs is not yet implemented", ZarrRuntimeWarning, stacklevel=2)
if synchronizer is not None:
warnings.warn("synchronizer is not yet implemented", RuntimeWarning, stacklevel=2)
warnings.warn("synchronizer is not yet implemented", ZarrRuntimeWarning, stacklevel=2)
if meta_array is not None:
warnings.warn("meta_array is not yet implemented", RuntimeWarning, stacklevel=2)
warnings.warn("meta_array is not yet implemented", ZarrRuntimeWarning, stacklevel=2)
if chunk_store is not None:
warnings.warn("chunk_store is not yet implemented", RuntimeWarning, stacklevel=2)
warnings.warn("chunk_store is not yet implemented", ZarrRuntimeWarning, stacklevel=2)

store_path = await make_store_path(store, mode=mode, storage_options=storage_options, path=path)
if attributes is None:
Expand Down Expand Up @@ -1011,19 +1017,19 @@ async def create(
)

if synchronizer is not None:
warnings.warn("synchronizer is not yet implemented", RuntimeWarning, stacklevel=2)
warnings.warn("synchronizer is not yet implemented", ZarrRuntimeWarning, stacklevel=2)
if chunk_store is not None:
warnings.warn("chunk_store is not yet implemented", RuntimeWarning, stacklevel=2)
warnings.warn("chunk_store is not yet implemented", ZarrRuntimeWarning, stacklevel=2)
if cache_metadata is not None:
warnings.warn("cache_metadata is not yet implemented", RuntimeWarning, stacklevel=2)
warnings.warn("cache_metadata is not yet implemented", ZarrRuntimeWarning, stacklevel=2)
if cache_attrs is not None:
warnings.warn("cache_attrs is not yet implemented", RuntimeWarning, stacklevel=2)
warnings.warn("cache_attrs is not yet implemented", ZarrRuntimeWarning, stacklevel=2)
if object_codec is not None:
warnings.warn("object_codec is not yet implemented", RuntimeWarning, stacklevel=2)
warnings.warn("object_codec is not yet implemented", ZarrRuntimeWarning, stacklevel=2)
if read_only is not None:
warnings.warn("read_only is not yet implemented", RuntimeWarning, stacklevel=2)
warnings.warn("read_only is not yet implemented", ZarrRuntimeWarning, stacklevel=2)
if meta_array is not None:
warnings.warn("meta_array is not yet implemented", RuntimeWarning, stacklevel=2)
warnings.warn("meta_array is not yet implemented", ZarrRuntimeWarning, stacklevel=2)

if write_empty_chunks is not None:
_warn_write_empty_chunks_kwarg()
Expand All @@ -1042,7 +1048,7 @@ async def create(
"This is redundant. When both are set, write_empty_chunks will be used instead "
"of the value in config."
)
warnings.warn(UserWarning(msg), stacklevel=1)
warnings.warn(ZarrUserWarning(msg), stacklevel=1)
config_parsed = dataclasses.replace(config_parsed, write_empty_chunks=write_empty_chunks)

return await AsyncArray._create(
Expand Down
3 changes: 2 additions & 1 deletion src/zarr/api/synchronous.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from zarr.core.group import Group
from zarr.core.sync import sync
from zarr.core.sync_group import create_hierarchy
from zarr.errors import ZarrDeprecationWarning

if TYPE_CHECKING:
from collections.abc import Iterable
Expand Down Expand Up @@ -339,7 +340,7 @@ def save_group(
)


@deprecated("Use Group.tree instead.")
@deprecated("Use Group.tree instead.", category=ZarrDeprecationWarning)
def tree(grp: Group, expand: bool | None = None, level: int | None = None) -> Any:
"""Provide a rich display of the hierarchy.

Expand Down
4 changes: 2 additions & 2 deletions src/zarr/codecs/transpose.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def validate(
) -> None:
if len(self.order) != len(shape):
raise ValueError(
f"The `order` tuple needs have as many entries as there are dimensions in the array. Got {self.order}."
f"The `order` tuple must have as many entries as there are dimensions in the array. Got {self.order}."
)
if len(self.order) != len(set(self.order)):
raise ValueError(
Expand All @@ -71,7 +71,7 @@ def evolve_from_array_spec(self, array_spec: ArraySpec) -> Self:
ndim = array_spec.ndim
if len(self.order) != ndim:
raise ValueError(
f"The `order` tuple needs have as many entries as there are dimensions in the array. Got {self.order}."
f"The `order` tuple must have as many entries as there are dimensions in the array. Got {self.order}."
)
if len(self.order) != len(set(self.order)):
raise ValueError(
Expand Down
3 changes: 2 additions & 1 deletion src/zarr/convenience.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
save_group,
tree,
)
from zarr.errors import ZarrDeprecationWarning

__all__ = [
"consolidate_metadata",
Expand All @@ -40,6 +41,6 @@
warnings.warn(
"zarr.convenience is deprecated. "
"Import these functions from the top level zarr. namespace instead.",
DeprecationWarning,
ZarrDeprecationWarning,
stacklevel=2,
)
16 changes: 8 additions & 8 deletions src/zarr/core/array.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@
)
from zarr.core.metadata.v3 import parse_node_type_array
from zarr.core.sync import sync
from zarr.errors import MetadataValidationError
from zarr.errors import MetadataValidationError, ZarrDeprecationWarning, ZarrUserWarning
from zarr.registry import (
_parse_array_array_codec,
_parse_array_bytes_codec,
Expand Down Expand Up @@ -232,7 +232,7 @@ async def get_array_metadata(
if zarr_json_bytes is not None and zarray_bytes is not None:
# warn and favor v3
msg = f"Both zarr.json (Zarr format 3) and .zarray (Zarr format 2) metadata objects exist at {store_path}. Zarr v3 will be used."
warnings.warn(msg, stacklevel=1)
warnings.warn(msg, category=ZarrUserWarning, stacklevel=1)
if zarr_json_bytes is None and zarray_bytes is None:
raise FileNotFoundError(store_path)
# set zarr_format based on which keys were found
Expand Down Expand Up @@ -441,7 +441,7 @@ async def create(
) -> AsyncArray[ArrayV3Metadata] | AsyncArray[ArrayV2Metadata]: ...

@classmethod
@deprecated("Use zarr.api.asynchronous.create_array instead.")
@deprecated("Use zarr.api.asynchronous.create_array instead.", category=ZarrDeprecationWarning)
async def create(
cls,
store: StoreLike,
Expand Down Expand Up @@ -1061,7 +1061,7 @@ def serializer(self) -> ArrayBytesCodec | None:
)

@property
@deprecated("Use AsyncArray.compressors instead.")
@deprecated("Use AsyncArray.compressors instead.", category=ZarrDeprecationWarning)
def compressor(self) -> numcodecs.abc.Codec | None:
"""
Compressor that is applied to each chunk of the array.
Expand Down Expand Up @@ -1855,7 +1855,7 @@ class Array:
_async_array: AsyncArray[ArrayV3Metadata] | AsyncArray[ArrayV2Metadata]

@classmethod
@deprecated("Use zarr.create_array instead.")
@deprecated("Use zarr.create_array instead.", category=ZarrDeprecationWarning)
def create(
cls,
store: StoreLike,
Expand Down Expand Up @@ -2242,7 +2242,7 @@ def serializer(self) -> None | ArrayBytesCodec:
return self._async_array.serializer

@property
@deprecated("Use Array.compressors instead.")
@deprecated("Use Array.compressors instead.", category=ZarrDeprecationWarning)
def compressor(self) -> numcodecs.abc.Codec | None:
"""
Compressor that is applied to each chunk of the array.
Expand Down Expand Up @@ -4648,7 +4648,7 @@ def _parse_keep_array_attr(
warnings.warn(
"The 'order' attribute of a Zarr format 2 array does not have a direct analogue in Zarr format 3. "
"The existing order='F' of the source Zarr format 2 array will be ignored.",
UserWarning,
ZarrUserWarning,
stacklevel=2,
)
elif order is None and zarr_format == 2:
Expand Down Expand Up @@ -4937,7 +4937,7 @@ def _parse_deprecated_compressor(
if zarr_format == 3:
warn(
"The `compressor` argument is deprecated. Use `compressors` instead.",
category=UserWarning,
category=ZarrUserWarning,
stacklevel=2,
)
if compressor is None:
Expand Down
2 changes: 2 additions & 0 deletions src/zarr/core/buffer/gpu.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

from zarr.core.buffer import core
from zarr.core.buffer.core import ArrayLike, BufferPrototype, NDArrayLike
from zarr.errors import ZarrUserWarning
from zarr.registry import (
register_buffer,
register_ndbuffer,
Expand Down Expand Up @@ -72,6 +73,7 @@ def __init__(self, array_like: ArrayLike) -> None:
)
warnings.warn(
msg,
category=ZarrUserWarning,
stacklevel=2,
)
self._data = cp.asarray(array_like)
Expand Down
3 changes: 2 additions & 1 deletion src/zarr/core/chunk_grids.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
parse_named_configuration,
parse_shapelike,
)
from zarr.errors import ZarrUserWarning

if TYPE_CHECKING:
from collections.abc import Iterator
Expand Down Expand Up @@ -233,7 +234,7 @@ def _auto_partition(
if shard_shape == "auto":
warnings.warn(
"Automatic shard shape inference is experimental and may change without notice.",
UserWarning,
ZarrUserWarning,
stacklevel=2,
)
_shards_out = ()
Expand Down
2 changes: 2 additions & 0 deletions src/zarr/core/codec_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from zarr.core.common import ChunkCoords, concurrent_map
from zarr.core.config import config
from zarr.core.indexing import SelectorTuple, is_scalar
from zarr.errors import ZarrUserWarning
from zarr.registry import register_pipeline

if TYPE_CHECKING:
Expand Down Expand Up @@ -501,6 +502,7 @@ def codecs_from_list(
warn(
"Combining a `sharding_indexed` codec disables partial reads and "
"writes, which may lead to inefficient performance.",
category=ZarrUserWarning,
stacklevel=3,
)

Expand Down
5 changes: 3 additions & 2 deletions src/zarr/core/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from typing_extensions import ReadOnly

from zarr.core.config import config as zarr_config
from zarr.errors import ZarrRuntimeWarning

if TYPE_CHECKING:
from collections.abc import Awaitable, Callable, Iterator
Expand Down Expand Up @@ -205,7 +206,7 @@ def _warn_write_empty_chunks_kwarg() -> None:
"argument, as in `config={'write_empty_chunks': True}`,"
"or change the global 'array.write_empty_chunks' configuration variable."
)
warnings.warn(msg, RuntimeWarning, stacklevel=2)
warnings.warn(msg, ZarrRuntimeWarning, stacklevel=2)


def _warn_order_kwarg() -> None:
Expand All @@ -216,7 +217,7 @@ def _warn_order_kwarg() -> None:
"argument, as in `config={'order': 'C'}`,"
"or change the global 'array.order' configuration variable."
)
warnings.warn(msg, RuntimeWarning, stacklevel=2)
warnings.warn(msg, ZarrRuntimeWarning, stacklevel=2)


def _default_zarr_format() -> ZarrFormat:
Expand Down
4 changes: 1 addition & 3 deletions src/zarr/core/dtype/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from typing_extensions import ReadOnly

from zarr.core.common import NamedConfig
from zarr.errors import UnstableSpecificationWarning

EndiannessStr = Literal["little", "big"]
ENDIANNESS_STR: Final = "little", "big"
Expand Down Expand Up @@ -216,9 +217,6 @@ class HasObjectCodec:
object_codec_id: ClassVar[str]


class UnstableSpecificationWarning(FutureWarning): ...


def v3_unstable_dtype_warning(dtype: object) -> None:
"""
Emit this warning when a data type does not have a stable zarr v3 spec
Expand Down
Loading
Loading