diff --git a/pyproject.toml b/pyproject.toml index 85517d8d0a..f488b1ff96 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -414,7 +414,7 @@ filterwarnings = [ "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:Use zarr.create_array instead.:zarr.errors.ZarrDeprecationWarning", "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", diff --git a/src/zarr/_compat.py b/src/zarr/_compat.py index 52d96005cc..87427b486e 100644 --- a/src/zarr/_compat.py +++ b/src/zarr/_compat.py @@ -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 @@ -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)) diff --git a/src/zarr/api/asynchronous.py b/src/zarr/api/asynchronous.py index 8f244f4b25..428c62857c 100644 --- a/src/zarr/api/asynchronous.py +++ b/src/zarr/api/asynchronous.py @@ -40,7 +40,7 @@ create_hierarchy, ) from zarr.core.metadata import ArrayMetadataDict, ArrayV2Metadata, ArrayV3Metadata -from zarr.errors import GroupNotFoundError, NodeTypeValidationError +from zarr.errors import GroupNotFoundError, NodeTypeValidationError, ZarrDeprecationWarning from zarr.storage import StorePath from zarr.storage._common import make_store_path @@ -163,7 +163,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 @@ -537,7 +537,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. diff --git a/src/zarr/api/synchronous.py b/src/zarr/api/synchronous.py index 92b80b1ac8..81bc25cd90 100644 --- a/src/zarr/api/synchronous.py +++ b/src/zarr/api/synchronous.py @@ -11,6 +11,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 @@ -342,7 +343,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. diff --git a/src/zarr/convenience.py b/src/zarr/convenience.py index 88f10663b7..3ca4ffcb4b 100644 --- a/src/zarr/convenience.py +++ b/src/zarr/convenience.py @@ -22,6 +22,7 @@ save_group, tree, ) +from zarr.errors import ZarrDeprecationWarning __all__ = [ "consolidate_metadata", @@ -40,6 +41,6 @@ warnings.warn( "zarr.convenience is deprecated. " "Import these functions from the top level zarr. namespace instead.", - DeprecationWarning, + ZarrDeprecationWarning, stacklevel=2, ) diff --git a/src/zarr/core/array.py b/src/zarr/core/array.py index a4f7fc086a..6fa0fb0ac5 100644 --- a/src/zarr/core/array.py +++ b/src/zarr/core/array.py @@ -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 from zarr.registry import ( _parse_array_array_codec, _parse_array_bytes_codec, @@ -429,7 +429,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) @_deprecate_positional_args async def create( cls, @@ -1050,7 +1050,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. @@ -1781,7 +1781,7 @@ class Array: _async_array: AsyncArray[ArrayV3Metadata] | AsyncArray[ArrayV2Metadata] @classmethod - @deprecated("Use zarr.create_array instead.") + @deprecated("Use zarr.create_array instead.", category=ZarrDeprecationWarning) @_deprecate_positional_args def create( cls, @@ -2169,7 +2169,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. diff --git a/src/zarr/core/dtype/common.py b/src/zarr/core/dtype/common.py index 3cc31df9e3..040201aa2a 100644 --- a/src/zarr/core/dtype/common.py +++ b/src/zarr/core/dtype/common.py @@ -16,6 +16,7 @@ from typing_extensions import ReadOnly from zarr.core.common import NamedConfig +from zarr.errors import ZarrFutureWarning EndiannessStr = Literal["little", "big"] ENDIANNESS_STR: Final = "little", "big" @@ -216,7 +217,7 @@ class HasObjectCodec: object_codec_id: ClassVar[str] -class UnstableSpecificationWarning(FutureWarning): ... +class UnstableSpecificationWarning(ZarrFutureWarning): ... def v3_unstable_dtype_warning(dtype: object) -> None: diff --git a/src/zarr/core/group.py b/src/zarr/core/group.py index 0f57495e61..3ce4e79f62 100644 --- a/src/zarr/core/group.py +++ b/src/zarr/core/group.py @@ -51,7 +51,12 @@ from zarr.core.config import config from zarr.core.metadata import ArrayV2Metadata, ArrayV3Metadata from zarr.core.sync import SyncMixin, sync -from zarr.errors import ContainsArrayError, ContainsGroupError, MetadataValidationError +from zarr.errors import ( + ContainsArrayError, + ContainsGroupError, + MetadataValidationError, + ZarrDeprecationWarning, +) from zarr.storage import StoreLike, StorePath from zarr.storage._common import ensure_no_existing_node, make_store_path from zarr.storage._utils import _join_paths, _normalize_path_keys, normalize_path @@ -1143,7 +1148,7 @@ async def create_array( write_data=write_data, ) - @deprecated("Use AsyncGroup.create_array instead.") + @deprecated("Use AsyncGroup.create_array instead.", category=ZarrDeprecationWarning) async def create_dataset( self, name: str, *, shape: ShapeLike, **kwargs: Any ) -> AsyncArray[ArrayV2Metadata] | AsyncArray[ArrayV3Metadata]: @@ -1177,7 +1182,7 @@ async def create_dataset( await array.setitem(slice(None), data) return array - @deprecated("Use AsyncGroup.require_array instead.") + @deprecated("Use AsyncGroup.require_array instead.", category=ZarrDeprecationWarning) async def require_dataset( self, name: str, @@ -2568,7 +2573,7 @@ def create_array( ) ) - @deprecated("Use Group.create_array instead.") + @deprecated("Use Group.create_array instead.", category=ZarrDeprecationWarning) def create_dataset(self, name: str, **kwargs: Any) -> Array: """Create an array. @@ -2592,7 +2597,7 @@ def create_dataset(self, name: str, **kwargs: Any) -> Array: """ return Array(self._sync(self._async_group.create_dataset(name, **kwargs))) - @deprecated("Use Group.require_array instead.") + @deprecated("Use Group.require_array instead.", category=ZarrDeprecationWarning) def require_dataset(self, name: str, *, shape: ShapeLike, **kwargs: Any) -> Array: """Obtain an array, creating if it doesn't exist. @@ -2822,7 +2827,7 @@ def move(self, source: str, dest: str) -> None: """ return self._sync(self._async_group.move(source, dest)) - @deprecated("Use Group.create_array instead.") + @deprecated("Use Group.create_array instead.", category=ZarrDeprecationWarning) @_deprecate_positional_args def array( self, diff --git a/src/zarr/creation.py b/src/zarr/creation.py index 8197c4950c..622406ed75 100644 --- a/src/zarr/creation.py +++ b/src/zarr/creation.py @@ -23,6 +23,7 @@ zeros, zeros_like, ) +from zarr.errors import ZarrDeprecationWarning __all__ = [ "array", @@ -42,6 +43,6 @@ warnings.warn( "zarr.creation is deprecated. " "Import these functions from the top level zarr. namespace instead.", - DeprecationWarning, + ZarrDeprecationWarning, stacklevel=2, ) diff --git a/src/zarr/errors.py b/src/zarr/errors.py index 4f972a6703..fea18e7720 100644 --- a/src/zarr/errors.py +++ b/src/zarr/errors.py @@ -66,3 +66,9 @@ class NodeTypeValidationError(MetadataValidationError): This can be raised when the value is invalid or unexpected given the context, for example an 'array' node when we expected a 'group'. """ + + +class ZarrFutureWarning(FutureWarning): ... + + +class ZarrDeprecationWarning(DeprecationWarning): ... diff --git a/src/zarr/storage/__init__.py b/src/zarr/storage/__init__.py index 6721139375..00df50214f 100644 --- a/src/zarr/storage/__init__.py +++ b/src/zarr/storage/__init__.py @@ -3,6 +3,7 @@ from types import ModuleType from typing import Any +from zarr.errors import ZarrDeprecationWarning from zarr.storage._common import StoreLike, StorePath from zarr.storage._fsspec import FsspecStore from zarr.storage._local import LocalStore @@ -33,7 +34,7 @@ def __setattr__(self, attr: str, value: Any) -> None: "setting zarr.storage.default_compressor is deprecated, use " "zarr.config to configure array.v2_default_compressor " "e.g. config.set({'codecs.zstd':'numcodecs.Zstd', 'array.v2_default_compressor.numeric': 'zstd'})", - DeprecationWarning, + ZarrDeprecationWarning, stacklevel=1, ) else: diff --git a/tests/test_api.py b/tests/test_api.py index b4f25a375e..65fdb81b98 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -7,6 +7,8 @@ import zarr.codecs import zarr.storage +from zarr.storage._local import LocalStore +from zarr.storage._zip import ZipStore if TYPE_CHECKING: import pathlib @@ -41,8 +43,8 @@ save_group, ) from zarr.core.buffer import NDArrayLike -from zarr.errors import MetadataValidationError -from zarr.storage import LocalStore, MemoryStore, ZipStore +from zarr.errors import MetadataValidationError, ZarrDeprecationWarning, ZarrFutureWarning +from zarr.storage import MemoryStore from zarr.storage._utils import normalize_path from zarr.testing.utils import gpu_test @@ -444,7 +446,7 @@ def test_tree() -> None: g3.create_group("baz") g5 = g3.create_group("qux") g5.create_array("baz", shape=(100,), chunks=(10,), dtype="float64") - with pytest.warns(DeprecationWarning): + with pytest.warns(ZarrDeprecationWarning): assert repr(zarr.tree(g1)) == repr(g1.tree()) assert str(zarr.tree(g1)) == str(g1.tree()) @@ -1118,7 +1120,7 @@ def test_tree() -> None: def test_open_positional_args_deprecated() -> None: store = MemoryStore() - with pytest.warns(FutureWarning, match="pass"): + with pytest.warns(ZarrFutureWarning, match="pass"): zarr.api.synchronous.open(store, "w", shape=(1,)) @@ -1126,9 +1128,9 @@ def test_save_array_positional_args_deprecated() -> None: store = MemoryStore() with warnings.catch_warnings(): warnings.filterwarnings( - "ignore", message="zarr_version is deprecated", category=DeprecationWarning + "ignore", message="zarr_version is deprecated", category=ZarrDeprecationWarning ) - with pytest.warns(FutureWarning, match="pass"): + with pytest.warns(ZarrFutureWarning, match="pass"): save_array( store, np.ones( @@ -1140,13 +1142,13 @@ def test_save_array_positional_args_deprecated() -> None: def test_group_positional_args_deprecated() -> None: store = MemoryStore() - with pytest.warns(FutureWarning, match="pass"): + with pytest.warns(ZarrFutureWarning, match="pass"): group(store, True) def test_open_group_positional_args_deprecated() -> None: store = MemoryStore() - with pytest.warns(FutureWarning, match="pass"): + with pytest.warns(ZarrFutureWarning, match="pass"): open_group(store, "w") diff --git a/tests/test_array.py b/tests/test_array.py index 4783bca05c..12c37b97d0 100644 --- a/tests/test_array.py +++ b/tests/test_array.py @@ -63,7 +63,12 @@ from zarr.core.indexing import BasicIndexer, ceildiv from zarr.core.metadata.v2 import ArrayV2Metadata from zarr.core.sync import sync -from zarr.errors import ContainsArrayError, ContainsGroupError +from zarr.errors import ( + ContainsArrayError, + ContainsGroupError, + ZarrDeprecationWarning, + ZarrFutureWarning, +) from zarr.storage import LocalStore, MemoryStore, StorePath from .test_dtype.conftest import zdtype_examples @@ -258,11 +263,11 @@ def test_array_v3_fill_value(store: MemoryStore, fill_value: int, dtype_str: str async def test_create_deprecated() -> None: - with pytest.warns(DeprecationWarning): - with pytest.warns(FutureWarning, match=re.escape("Pass shape=(2, 2) as keyword args")): + with pytest.warns(ZarrDeprecationWarning): + with pytest.warns(ZarrFutureWarning, match=re.escape("Pass shape=(2, 2) as keyword args")): await zarr.AsyncArray.create(MemoryStore(), (2, 2), dtype="f8") # type: ignore[call-overload] - with pytest.warns(DeprecationWarning): - with pytest.warns(FutureWarning, match=re.escape("Pass shape=(2, 2) as keyword args")): + with pytest.warns(ZarrDeprecationWarning): + with pytest.warns(ZarrFutureWarning, match=re.escape("Pass shape=(2, 2) as keyword args")): zarr.Array.create(MemoryStore(), (2, 2), dtype="f8") @@ -270,34 +275,34 @@ def test_selection_positional_args_deprecated() -> None: store = MemoryStore() arr = zarr.create_array(store, shape=(2, 2), dtype="f8") - with pytest.warns(FutureWarning, match="Pass out"): + with pytest.warns(ZarrFutureWarning, match="Pass out"): arr.get_basic_selection(..., NDBuffer(array=np.empty((2, 2)))) - with pytest.warns(FutureWarning, match="Pass fields"): + with pytest.warns(ZarrFutureWarning, match="Pass fields"): arr.set_basic_selection(..., 1, None) - with pytest.warns(FutureWarning, match="Pass out"): + with pytest.warns(ZarrFutureWarning, match="Pass out"): arr.get_orthogonal_selection(..., NDBuffer(array=np.empty((2, 2)))) - with pytest.warns(FutureWarning, match="Pass"): + with pytest.warns(ZarrFutureWarning, match="Pass"): arr.set_orthogonal_selection(..., 1, None) - with pytest.warns(FutureWarning, match="Pass"): + with pytest.warns(ZarrFutureWarning, match="Pass"): arr.get_mask_selection(np.zeros((2, 2), dtype=bool), NDBuffer(array=np.empty((0,)))) - with pytest.warns(FutureWarning, match="Pass"): + with pytest.warns(ZarrFutureWarning, match="Pass"): arr.set_mask_selection(np.zeros((2, 2), dtype=bool), 1, None) - with pytest.warns(FutureWarning, match="Pass"): + with pytest.warns(ZarrFutureWarning, match="Pass"): arr.get_coordinate_selection(([0, 1], [0, 1]), NDBuffer(array=np.empty((2,)))) - with pytest.warns(FutureWarning, match="Pass"): + with pytest.warns(ZarrFutureWarning, match="Pass"): arr.set_coordinate_selection(([0, 1], [0, 1]), 1, None) - with pytest.warns(FutureWarning, match="Pass"): + with pytest.warns(ZarrFutureWarning, match="Pass"): arr.get_block_selection((0, slice(None)), NDBuffer(array=np.empty((2, 2)))) - with pytest.warns(FutureWarning, match="Pass"): + with pytest.warns(ZarrFutureWarning, match="Pass"): arr.set_block_selection((0, slice(None)), 1, None) diff --git a/tests/test_dtype/test_npy/test_bytes.py b/tests/test_dtype/test_npy/test_bytes.py index 78980f7809..233a6bbd6b 100644 --- a/tests/test_dtype/test_npy/test_bytes.py +++ b/tests/test_dtype/test_npy/test_bytes.py @@ -150,7 +150,7 @@ def test_unstable_dtype_warning( Test that we get a warning when serializing a dtype without a zarr v3 spec to json when zarr_format is 3 """ - with pytest.raises(UnstableSpecificationWarning): + with pytest.warns(UnstableSpecificationWarning): zdtype.to_json(zarr_format=3) diff --git a/tests/test_dtype/test_npy/test_string.py b/tests/test_dtype/test_npy/test_string.py index 2cde6a1ac1..c5b3713dca 100644 --- a/tests/test_dtype/test_npy/test_string.py +++ b/tests/test_dtype/test_npy/test_string.py @@ -136,7 +136,7 @@ def test_unstable_dtype_warning(zdtype: FixedLengthUTF32 | VariableLengthUTF8) - Test that we get a warning when serializing a dtype without a zarr v3 spec to json when zarr_format is 3 """ - with pytest.raises(UnstableSpecificationWarning): + with pytest.warns(UnstableSpecificationWarning): zdtype.to_json(zarr_format=3) diff --git a/tests/test_group.py b/tests/test_group.py index ee2317ade4..76d7f50a11 100644 --- a/tests/test_group.py +++ b/tests/test_group.py @@ -39,7 +39,13 @@ ) from zarr.core.metadata.v3 import ArrayV3Metadata from zarr.core.sync import _collect_aiterator, sync -from zarr.errors import ContainsArrayError, ContainsGroupError, MetadataValidationError +from zarr.errors import ( + ContainsArrayError, + ContainsGroupError, + MetadataValidationError, + ZarrDeprecationWarning, + ZarrFutureWarning, +) from zarr.storage import LocalStore, MemoryStore, StorePath, ZipStore from zarr.storage._common import make_store_path from zarr.storage._utils import _join_paths, normalize_path @@ -648,7 +654,7 @@ def test_group_create_array( array = group.create_array(name=name, shape=shape, dtype=dtype) array[:] = data elif method == "array": - with pytest.warns(DeprecationWarning): + with pytest.warns(ZarrDeprecationWarning): array = group.array(name=name, data=data, shape=shape, dtype=dtype) else: raise AssertionError @@ -659,7 +665,7 @@ def test_group_create_array( a = group.create_array(name=name, shape=shape, dtype=dtype) a[:] = data elif method == "array": - with pytest.raises(ContainsArrayError), pytest.warns(DeprecationWarning): + with pytest.raises(ContainsArrayError), pytest.warns(ZarrDeprecationWarning): a = group.array(name=name, shape=shape, dtype=dtype) a[:] = data @@ -1183,22 +1189,22 @@ def test_create_dataset_with_data(store: Store, zarr_format: ZarrFormat) -> None """ root = Group.from_store(store=store, zarr_format=zarr_format) arr = np.random.random((5, 5)) - with pytest.warns(DeprecationWarning): + with pytest.warns(ZarrDeprecationWarning): data = root.create_dataset("random", data=arr, shape=arr.shape) np.testing.assert_array_equal(np.asarray(data), arr) async def test_create_dataset(store: Store, zarr_format: ZarrFormat) -> None: root = await AsyncGroup.from_store(store=store, zarr_format=zarr_format) - with pytest.warns(DeprecationWarning): + with pytest.warns(ZarrDeprecationWarning): foo = await root.create_dataset("foo", shape=(10,), dtype="uint8") assert foo.shape == (10,) - with pytest.raises(ContainsArrayError), pytest.warns(DeprecationWarning): + with pytest.raises(ContainsArrayError), pytest.warns(ZarrDeprecationWarning): await root.create_dataset("foo", shape=(100,), dtype="int8") _ = await root.create_group("bar") - with pytest.raises(ContainsGroupError), pytest.warns(DeprecationWarning): + with pytest.raises(ContainsGroupError), pytest.warns(ZarrDeprecationWarning): await root.create_dataset("bar", shape=(100,), dtype="int8") @@ -1454,14 +1460,14 @@ def test_group_deprecated_positional_args(method: str) -> None: kwargs = {} root = zarr.group() - with pytest.warns(FutureWarning, match=r"Pass name=.* as keyword args."): + with pytest.warns(ZarrFutureWarning, match=r"Pass name=.* as keyword args."): arr = getattr(root, method)("foo", shape=1, **kwargs) assert arr.shape == (1,) method += "_like" data = np.ones(1) - with pytest.warns(FutureWarning, match=r"Pass name=.*, data=.* as keyword args."): + with pytest.warns(ZarrFutureWarning, match=r"Pass name=.*, data=.* as keyword args."): arr = getattr(root, method)("foo_like", data, **kwargs) assert arr.shape == data.shape diff --git a/tests/test_sync.py b/tests/test_sync.py index 13b475f8da..0061d41727 100644 --- a/tests/test_sync.py +++ b/tests/test_sync.py @@ -15,6 +15,7 @@ loop, sync, ) +from zarr.errors import ZarrFutureWarning from zarr.storage import MemoryStore @@ -145,7 +146,7 @@ def bar(self) -> list[int]: def test_open_positional_args_deprecate(): store = MemoryStore() - with pytest.warns(FutureWarning, match="pass"): + with pytest.warns(ZarrFutureWarning, match="pass"): zarr.open(store, "w", shape=(1,)) diff --git a/tests/test_v2.py b/tests/test_v2.py index 4d17305995..70e8f2923f 100644 --- a/tests/test_v2.py +++ b/tests/test_v2.py @@ -21,6 +21,7 @@ from zarr.core.dtype.wrapper import ZDType from zarr.core.group import Group from zarr.core.sync import sync +from zarr.errors import ZarrDeprecationWarning from zarr.storage import MemoryStore, StorePath @@ -226,7 +227,7 @@ def test_v2_non_contiguous(numpy_order: Literal["C", "F"], zarr_order: Literal[" def test_default_compressor_deprecation_warning() -> None: - with pytest.warns(DeprecationWarning, match="default_compressor is deprecated"): + with pytest.warns(ZarrDeprecationWarning, match="default_compressor is deprecated"): zarr.storage.default_compressor = "zarr.codecs.zstd.ZstdCodec()" # type: ignore[attr-defined]