Skip to content

Commit 83c3c1b

Browse files
committed
Finish merge with remove-release-banner
2 parents a203f4c + 6182488 commit 83c3c1b

File tree

10 files changed

+39
-150
lines changed

10 files changed

+39
-150
lines changed

.github/workflows/hypothesis.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ jobs:
8787
&& steps.status.outcome == 'failure'
8888
&& github.event_name == 'schedule'
8989
&& github.repository_owner == 'zarr-developers'
90-
uses: xarray-contrib/issue-from-pytest-log@v1
90+
uses: scientific-python/issue-from-pytest-log-action@v1
9191
with:
9292
log-path: output-${{ matrix.python-version }}-log.jsonl
9393
issue-title: "Nightly Hypothesis tests failed"

changes/2819.chore.rst

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,18 @@
11
Ensure that invocations of ``create_array`` use consistent keyword arguments, with consistent defaults.
2-
Specifically, ``zarr.api.synchronous.create_array`` now takes a ``write_data`` keyword argument; The
3-
``create_array`` method on ``zarr.Group`` takes ``data`` and ``write_data`` keyword arguments. The ``fill_value``
4-
keyword argument of the various invocations of ``create_array`` has been consistently set to ``None``, where previously it was either ``None`` or ``0``.
2+
3+
- ``zarr.api.synchronous.create_array`` now takes a ``write_data`` keyword argument
4+
- The ``Group.create_array`` method takes ``data`` and ``write_data`` keyword arguments.
5+
- The functions ``api.asynchronous.create``, ``api.asynchronous.create_array``
6+
and the methods ``Group.create_array``, ``Group.array``, had the default
7+
``fill_value`` changed from ``0`` to the ``DEFAULT_FILL_VALUE`` value, which instructs Zarr to
8+
use the default scalar value associated with the array's data type as the fill value. These are
9+
all functions or methods for array creation that mirror, wrap or are wrapped by, another function
10+
that already has a default ``fill_value`` set to ``DEFAULT_FILL_VALUE``. This change is necessary
11+
to make these functions consistent across the entire codebase, but as this changes default values,
12+
new data might have a different fill value than expected after this change.
13+
14+
For data types where 0 is meaningful, like integers or floats, the default scalar is 0, so this
15+
change should not be noticeable. For data types where 0 is ambiguous, like fixed-length unicode
16+
strings, the default fill value might be different after this change. Users who were relying on how
17+
Zarr interpreted ``0`` as a non-numeric scalar value should set their desired fill value explicitly
18+
after this change.

changes/2874.feature.rst

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
1-
Adds zarr-specific data type classes. This replaces the internal use of numpy data types for zarr
2-
v2 and a fixed set of string enums for zarr v3. This change is largely internal, but it does
3-
change the type of the ``dtype`` and ``data_type`` fields on the ``ArrayV2Metadata`` and
4-
``ArrayV3Metadata`` classes. It also changes the JSON metadata representation of the
5-
variable-length string data type, but the old metadata representation can still be
6-
used when reading arrays. The logic for automatically choosing the chunk encoding for a given data
7-
type has also changed, and this necessitated changes to the ``config`` API.
1+
Adds zarr-specific data type classes.
2+
3+
This change adds a ``ZDType`` base class for Zarr V2 and Zarr V3 data types. Child classes are
4+
defined for each NumPy data type. Each child class defines routines for ``JSON`` serialization.
5+
New data types can be created and registered dynamically.
6+
7+
Prior to this change, Zarr Python had two streams for handling data types. For Zarr V2 arrays,
8+
we used NumPy data type identifiers. For Zarr V3 arrays, we used a fixed set of string enums. Both
9+
of these systems proved hard to extend.
10+
11+
This change is largely internal, but it does change the type of the ``dtype`` and ``data_type``
12+
fields on the ``ArrayV2Metadata`` and ``ArrayV3Metadata`` classes. Previously, ``ArrayV2Metadata.dtype``
13+
was a NumPy ``dtype`` object, and ``ArrayV3Metadata.data_type`` was an internally-defined ``enum``.
14+
After this change, both ``ArrayV2Metadata.dtype`` and ``ArrayV3Metadata.data_type`` are instances of
15+
``ZDType``. A NumPy data type can be generated from a ``ZDType`` via the ``ZDType.to_native_dtype()``
16+
method. The internally-defined Zarr V3 ``enum`` class is gone entirely, but the ``ZDType.to_json(zarr_format=3)``
17+
method can be used to generate either a string, or dictionary that has a string ``name`` field, that
18+
represents the string value previously associated with that ``enum``.
819

920
For more on this new feature, see the `documentation </user-guide/data_types.html>`_

src/zarr/api/synchronous.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
import zarr.api.asynchronous as async_api
88
import zarr.core.array
9-
from zarr._compat import _deprecate_positional_args
109
from zarr.core.array import DEFAULT_FILL_VALUE, Array, AsyncArray, CompressorLike
1110
from zarr.core.group import Group
1211
from zarr.core.sync import sync
@@ -160,7 +159,6 @@ def load(
160159
)
161160

162161

163-
@_deprecate_positional_args
164162
def open(
165163
store: StoreLike | None = None,
166164
*,
@@ -255,7 +253,6 @@ def save(
255253
)
256254

257255

258-
@_deprecate_positional_args
259256
def save_array(
260257
store: StoreLike,
261258
arr: NDArrayLike,
@@ -387,7 +384,6 @@ def array(data: npt.ArrayLike | Array, **kwargs: Any) -> Array:
387384
return Array(sync(async_api.array(data=data, **kwargs)))
388385

389386

390-
@_deprecate_positional_args
391387
def group(
392388
store: StoreLike | None = None,
393389
*,
@@ -455,7 +451,6 @@ def group(
455451
)
456452

457453

458-
@_deprecate_positional_args
459454
def open_group(
460455
store: StoreLike | None = None,
461456
*,

src/zarr/core/array.py

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
from typing_extensions import deprecated
2626

2727
import zarr
28-
from zarr._compat import _deprecate_positional_args
2928
from zarr.abc.codec import ArrayArrayCodec, ArrayBytesCodec, BytesBytesCodec, Codec
3029
from zarr.abc.store import Store, set_or_delete
3130
from zarr.codecs._v2 import V2Codec
@@ -442,7 +441,6 @@ async def create(
442441

443442
@classmethod
444443
@deprecated("Use zarr.api.asynchronous.create_array instead.")
445-
@_deprecate_positional_args
446444
async def create(
447445
cls,
448446
store: StoreLike,
@@ -1794,7 +1792,6 @@ class Array:
17941792

17951793
@classmethod
17961794
@deprecated("Use zarr.create_array instead.")
1797-
@_deprecate_positional_args
17981795
def create(
17991796
cls,
18001797
store: StoreLike,
@@ -2607,7 +2604,6 @@ def __setitem__(self, selection: Selection, value: npt.ArrayLike) -> None:
26072604
else:
26082605
self.set_basic_selection(cast("BasicSelection", pure_selection), value, fields=fields)
26092606

2610-
@_deprecate_positional_args
26112607
def get_basic_selection(
26122608
self,
26132609
selection: BasicSelection = Ellipsis,
@@ -2731,7 +2727,6 @@ def get_basic_selection(
27312727
)
27322728
)
27332729

2734-
@_deprecate_positional_args
27352730
def set_basic_selection(
27362731
self,
27372732
selection: BasicSelection,
@@ -2827,7 +2822,6 @@ def set_basic_selection(
28272822
indexer = BasicIndexer(selection, self.shape, self.metadata.chunk_grid)
28282823
sync(self._async_array._set_selection(indexer, value, fields=fields, prototype=prototype))
28292824

2830-
@_deprecate_positional_args
28312825
def get_orthogonal_selection(
28322826
self,
28332827
selection: OrthogonalSelection,
@@ -2952,7 +2946,6 @@ def get_orthogonal_selection(
29522946
)
29532947
)
29542948

2955-
@_deprecate_positional_args
29562949
def set_orthogonal_selection(
29572950
self,
29582951
selection: OrthogonalSelection,
@@ -3063,7 +3056,6 @@ def set_orthogonal_selection(
30633056
self._async_array._set_selection(indexer, value, fields=fields, prototype=prototype)
30643057
)
30653058

3066-
@_deprecate_positional_args
30673059
def get_mask_selection(
30683060
self,
30693061
mask: MaskSelection,
@@ -3146,7 +3138,6 @@ def get_mask_selection(
31463138
)
31473139
)
31483140

3149-
@_deprecate_positional_args
31503141
def set_mask_selection(
31513142
self,
31523143
mask: MaskSelection,
@@ -3225,7 +3216,6 @@ def set_mask_selection(
32253216
indexer = MaskIndexer(mask, self.shape, self.metadata.chunk_grid)
32263217
sync(self._async_array._set_selection(indexer, value, fields=fields, prototype=prototype))
32273218

3228-
@_deprecate_positional_args
32293219
def get_coordinate_selection(
32303220
self,
32313221
selection: CoordinateSelection,
@@ -3315,7 +3305,6 @@ def get_coordinate_selection(
33153305
out_array = np.array(out_array).reshape(indexer.sel_shape)
33163306
return out_array
33173307

3318-
@_deprecate_positional_args
33193308
def set_coordinate_selection(
33203309
self,
33213310
selection: CoordinateSelection,
@@ -3413,7 +3402,6 @@ def set_coordinate_selection(
34133402

34143403
sync(self._async_array._set_selection(indexer, value, fields=fields, prototype=prototype))
34153404

3416-
@_deprecate_positional_args
34173405
def get_block_selection(
34183406
self,
34193407
selection: BasicSelection,
@@ -3512,7 +3500,6 @@ def get_block_selection(
35123500
)
35133501
)
35143502

3515-
@_deprecate_positional_args
35163503
def set_block_selection(
35173504
self,
35183505
selection: BasicSelection,

src/zarr/core/group.py

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
from typing_extensions import deprecated
1616

1717
import zarr.api.asynchronous as async_api
18-
from zarr._compat import _deprecate_positional_args
1918
from zarr.abc.metadata import Metadata
2019
from zarr.abc.store import Store, set_or_delete
2120
from zarr.core._info import GroupInfo
@@ -2417,7 +2416,6 @@ def create(self, *args: Any, **kwargs: Any) -> Array:
24172416
# Backwards compatibility for 2.x
24182417
return self.create_array(*args, **kwargs)
24192418

2420-
@_deprecate_positional_args
24212419
def create_array(
24222420
self,
24232421
name: str,
@@ -2635,7 +2633,6 @@ def require_array(self, name: str, *, shape: ShapeLike, **kwargs: Any) -> Array:
26352633
"""
26362634
return Array(self._sync(self._async_group.require_array(name, shape=shape, **kwargs)))
26372635

2638-
@_deprecate_positional_args
26392636
def empty(self, *, name: str, shape: ChunkCoords, **kwargs: Any) -> Array:
26402637
"""Create an empty array with the specified shape in this Group. The contents will be filled with
26412638
the array's fill value or zeros if no fill value is provided.
@@ -2657,7 +2654,6 @@ def empty(self, *, name: str, shape: ChunkCoords, **kwargs: Any) -> Array:
26572654
"""
26582655
return Array(self._sync(self._async_group.empty(name=name, shape=shape, **kwargs)))
26592656

2660-
@_deprecate_positional_args
26612657
def zeros(self, *, name: str, shape: ChunkCoords, **kwargs: Any) -> Array:
26622658
"""Create an array, with zero being used as the default value for uninitialized portions of the array.
26632659
@@ -2677,7 +2673,6 @@ def zeros(self, *, name: str, shape: ChunkCoords, **kwargs: Any) -> Array:
26772673
"""
26782674
return Array(self._sync(self._async_group.zeros(name=name, shape=shape, **kwargs)))
26792675

2680-
@_deprecate_positional_args
26812676
def ones(self, *, name: str, shape: ChunkCoords, **kwargs: Any) -> Array:
26822677
"""Create an array, with one being used as the default value for uninitialized portions of the array.
26832678
@@ -2697,7 +2692,6 @@ def ones(self, *, name: str, shape: ChunkCoords, **kwargs: Any) -> Array:
26972692
"""
26982693
return Array(self._sync(self._async_group.ones(name=name, shape=shape, **kwargs)))
26992694

2700-
@_deprecate_positional_args
27012695
def full(
27022696
self, *, name: str, shape: ChunkCoords, fill_value: Any | None, **kwargs: Any
27032697
) -> Array:
@@ -2725,7 +2719,6 @@ def full(
27252719
)
27262720
)
27272721

2728-
@_deprecate_positional_args
27292722
def empty_like(self, *, name: str, data: async_api.ArrayLike, **kwargs: Any) -> Array:
27302723
"""Create an empty sub-array like `data`. The contents will be filled
27312724
with the array's fill value or zeros if no fill value is provided.
@@ -2752,7 +2745,6 @@ def empty_like(self, *, name: str, data: async_api.ArrayLike, **kwargs: Any) ->
27522745
"""
27532746
return Array(self._sync(self._async_group.empty_like(name=name, data=data, **kwargs)))
27542747

2755-
@_deprecate_positional_args
27562748
def zeros_like(self, *, name: str, data: async_api.ArrayLike, **kwargs: Any) -> Array:
27572749
"""Create a sub-array of zeros like `data`.
27582750
@@ -2773,7 +2765,6 @@ def zeros_like(self, *, name: str, data: async_api.ArrayLike, **kwargs: Any) ->
27732765

27742766
return Array(self._sync(self._async_group.zeros_like(name=name, data=data, **kwargs)))
27752767

2776-
@_deprecate_positional_args
27772768
def ones_like(self, *, name: str, data: async_api.ArrayLike, **kwargs: Any) -> Array:
27782769
"""Create a sub-array of ones like `data`.
27792770
@@ -2793,7 +2784,6 @@ def ones_like(self, *, name: str, data: async_api.ArrayLike, **kwargs: Any) -> A
27932784
"""
27942785
return Array(self._sync(self._async_group.ones_like(name=name, data=data, **kwargs)))
27952786

2796-
@_deprecate_positional_args
27972787
def full_like(self, *, name: str, data: async_api.ArrayLike, **kwargs: Any) -> Array:
27982788
"""Create a sub-array like `data` filled with the `fill_value` of `data` .
27992789
@@ -2823,7 +2813,6 @@ def move(self, source: str, dest: str) -> None:
28232813
return self._sync(self._async_group.move(source, dest))
28242814

28252815
@deprecated("Use Group.create_array instead.")
2826-
@_deprecate_positional_args
28272816
def array(
28282817
self,
28292818
name: str,

tests/test_api.py

Lines changed: 3 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
from zarr.core.common import JSON, MemoryOrder, ZarrFormat
1717

1818
import contextlib
19-
import warnings
2019
from typing import Literal
2120

2221
import numpy as np
@@ -263,7 +262,7 @@ def test_save_errors() -> None:
263262
save_group("data/group.zarr")
264263
with pytest.raises(TypeError):
265264
# no array provided
266-
save_array("data/group.zarr")
265+
save_array("data/group.zarr") # type: ignore[call-arg]
267266
with pytest.raises(ValueError):
268267
# no arrays provided
269268
save("data/group.zarr")
@@ -1116,40 +1115,6 @@ def test_tree() -> None:
11161115
# copy(source["foo"], dest, dry_run=True, log=True)
11171116

11181117

1119-
def test_open_positional_args_deprecated() -> None:
1120-
store = MemoryStore()
1121-
with pytest.warns(FutureWarning, match="pass"):
1122-
zarr.api.synchronous.open(store, "w", shape=(1,))
1123-
1124-
1125-
def test_save_array_positional_args_deprecated() -> None:
1126-
store = MemoryStore()
1127-
with warnings.catch_warnings():
1128-
warnings.filterwarnings(
1129-
"ignore", message="zarr_version is deprecated", category=DeprecationWarning
1130-
)
1131-
with pytest.warns(FutureWarning, match="pass"):
1132-
save_array(
1133-
store,
1134-
np.ones(
1135-
1,
1136-
),
1137-
3,
1138-
)
1139-
1140-
1141-
def test_group_positional_args_deprecated() -> None:
1142-
store = MemoryStore()
1143-
with pytest.warns(FutureWarning, match="pass"):
1144-
group(store, True)
1145-
1146-
1147-
def test_open_group_positional_args_deprecated() -> None:
1148-
store = MemoryStore()
1149-
with pytest.warns(FutureWarning, match="pass"):
1150-
open_group(store, "w")
1151-
1152-
11531118
def test_open_falls_back_to_open_group() -> None:
11541119
# https://github.com/zarr-developers/zarr-python/issues/2309
11551120
store = MemoryStore()
@@ -1180,9 +1145,9 @@ def test_open_modes_creates_group(tmp_path: pathlib.Path, mode: str) -> None:
11801145
if mode in ["r", "r+"]:
11811146
# Expect FileNotFoundError to be raised if 'r' or 'r+' mode
11821147
with pytest.raises(FileNotFoundError):
1183-
zarr.open(store=zarr_dir, mode=mode)
1148+
zarr.open(store=zarr_dir, mode=mode) # type: ignore[arg-type]
11841149
else:
1185-
group = zarr.open(store=zarr_dir, mode=mode)
1150+
group = zarr.open(store=zarr_dir, mode=mode) # type: ignore[arg-type]
11861151
assert isinstance(group, Group)
11871152

11881153

0 commit comments

Comments
 (0)