Skip to content

Commit ca6196d

Browse files
committed
Merge branch 'main' of https://github.com/zarr-developers/zarr-python into widen-parse-data-type
2 parents ed56505 + 798b57b commit ca6196d

13 files changed

Lines changed: 114 additions & 54 deletions

File tree

changes/+c563f4d4.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Register 'gpu' marker with pytest for downstream StoreTests.

changes/2819.chore.rst

Lines changed: 0 additions & 18 deletions
This file was deleted.

changes/3249.doc.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Expand the data type docs to include a demonstration of the ``parse_data_type`` function.
2+
Expand the docstring for the ``parse_data_type`` function.

changes/3251.fix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Ensure that all abstract methods of ``ZDType`` raise a ``NotImplementedError`` when invoked.

docs/about.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Funding
1818
-------
1919
The project is fiscally sponsored by `NumFOCUS <https://numfocus.org/>`_, a US
2020
501(c)(3) public charity, and development is supported by the
21-
`MRC Centre for Genomics and Global Health <https://www.cggh.org>`_
21+
`MRC Centre for Genomics and Global Health <https://github.com/cggh/>`_
2222
and the `Chan Zuckerberg Initiative <https://chanzuckerberg.com/>`_.
2323

2424
.. _NumCodecs: https://numcodecs.readthedocs.io/

docs/conf.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,17 @@ def skip_submodules(
167167
# documentation.
168168
html_theme_options = {
169169
"github_url": "https://github.com/zarr-developers/zarr-python",
170-
"twitter_url": "https://twitter.com/zarr_dev",
171170
"icon_links": [
171+
{
172+
"name": "Bluesky",
173+
"url": "https://bsky.app/profile/zarr.dev",
174+
"icon": "fa-brands fa-bluesky",
175+
},
176+
{
177+
"name": "Mastodon",
178+
"url": "https://fosstodon.org/@zarr",
179+
"icon": "fa-brands fa-mastodon",
180+
},
172181
{
173182
"name": "Zarr Dev",
174183
"url": "https://zarr.dev/",
@@ -178,7 +187,6 @@ def skip_submodules(
178187
],
179188
"collapse_navigation": True,
180189
"navigation_with_keys": False,
181-
"announcement": "Zarr-Python 3 is here! Check out the release announcement <a href='https://zarr.dev/blog/zarr-python-3-release/'>here.</a>",
182190
}
183191

184192
# Add any paths that contain custom themes here, relative to this directory.

docs/release-notes.rst

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,24 @@ Release notes
88

99
Features
1010
~~~~~~~~
11-
11+
- Ensure that invocations of ``create_array`` use consistent keyword arguments, with consistent defaults.
12+
13+
``zarr.api.synchronous.create_array`` now takes a ``write_data`` keyword argument
14+
The ``Group.create_array`` method takes ``data`` and ``write_data`` keyword arguments.
15+
The functions ``api.asynchronous.create``, ``api.asynchronous.create_array``
16+
and the methods ``Group.create_array``, ``Group.array``, had the default
17+
``fill_value`` changed from ``0`` to the ``DEFAULT_FILL_VALUE`` value, which instructs Zarr to
18+
use the default scalar value associated with the array's data type as the fill value. These are
19+
all functions or methods for array creation that mirror, wrap or are wrapped by, another function
20+
that already has a default ``fill_value`` set to ``DEFAULT_FILL_VALUE``. This change is necessary
21+
to make these functions consistent across the entire codebase, but as this changes default values,
22+
new data might have a different fill value than expected after this change.
23+
24+
For data types where 0 is meaningful, like integers or floats, the default scalar is 0, so this
25+
change should not be noticeable. For data types where 0 is ambiguous, like fixed-length unicode
26+
strings, the default fill value might be different after this change. Users who were relying on how
27+
Zarr interpreted ``0`` as a non-numeric scalar value should set their desired fill value explicitly
28+
after this change.
1229
- Added public API for Buffer ABCs and implementations.
1330

1431
Use :mod:`zarr.buffer` to access buffer implementations, and

docs/user-guide/data_types.rst

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,4 +409,47 @@ We want to avoid a situation where the same native data type matches multiple Za
409409
a NumPy data type should *uniquely* specify a single Zarr data type. But data type resolution is
410410
dynamic, so it's not possible to statically guarantee this uniqueness constraint. Therefore, we
411411
attempt data type resolution against *every* data type class, and if, for some reason, a native data
412-
type matches multiple Zarr data types, we treat this as an error and raise an exception.
412+
type matches multiple Zarr data types, we treat this as an error and raise an exception.
413+
414+
If you have a NumPy data type and you want to get the corresponding ``ZDType`` instance, you can use
415+
the ``parse_data_type`` function, which will use the dynamic resolution described above. ``parse_data_type``
416+
handles a range of input types:
417+
418+
- NumPy data types:
419+
420+
.. code-block:: python
421+
422+
>>> import numpy as np
423+
>>> from zarr.dtype import parse_data_type
424+
>>> my_dtype = np.dtype('>M8[10s]')
425+
>>> parse_data_type(my_dtype, zarr_format=2)
426+
DateTime64(endianness='big', scale_factor=10, unit='s')
427+
428+
429+
- NumPy data type-compatible strings:
430+
431+
.. code-block:: python
432+
433+
>>> dtype_str = '>M8[10s]'
434+
>>> parse_data_type(dtype_str, zarr_format=2)
435+
DateTime64(endianness='big', scale_factor=10, unit='s')
436+
437+
- ``ZDType`` instances:
438+
439+
.. code-block:: python
440+
441+
>>> from zarr.dtype import DateTime64
442+
>>> zdt = DateTime64(endianness='big', scale_factor=10, unit='s')
443+
>>> parse_data_type(zdt, zarr_format=2) # Use a ZDType (this is a no-op)
444+
DateTime64(endianness='big', scale_factor=10, unit='s')
445+
446+
- Python dictionaries (requires ``zarr_format=3``). These dictionaries must be consistent with the
447+
``JSON`` form of the data type:
448+
449+
.. code-block:: python
450+
451+
>>> dt_dict = {"name": "numpy.datetime64", "configuration": {"unit": "s", "scale_factor": 10}}
452+
>>> parse_data_type(dt_dict, zarr_format=3)
453+
DateTime64(endianness='little', scale_factor=10, unit='s')
454+
>>> parse_data_type(dt_dict, zarr_format=3).to_json(zarr_format=3)
455+
{'name': 'numpy.datetime64', 'configuration': {'unit': 's', 'scale_factor': 10}}

pyproject.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ exclude_lines = [
138138
[tool.coverage.run]
139139
omit = [
140140
"bench/compress_normal.py",
141+
"src/zarr/testing/conftest.py", # only for downstream projects
141142
]
142143

143144
[tool.hatch]
@@ -455,3 +456,6 @@ issue_format = ":issue:`{issue}`"
455456

456457
[tool.codespell]
457458
ignore-words-list = "astroid"
459+
460+
[project.entry-points.pytest11]
461+
zarr = "zarr.testing"

src/zarr/core/dtype/wrapper.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,6 @@ def from_native_dtype(cls: type[Self], dtype: TBaseDType) -> Self:
102102
"""
103103
Create a ZDType instance from a native data type.
104104
105-
The base implementation first performs a type check via ``cls._check_native_dtype``.
106-
If that type check succeeds, the ZDType class instance is created.
107-
108105
This method is used when taking a user-provided native data type, like a NumPy data type,
109106
and creating the corresponding ZDType instance from them.
110107
@@ -123,7 +120,7 @@ def from_native_dtype(cls: type[Self], dtype: TBaseDType) -> Self:
123120
TypeError
124121
If the native data type is not consistent with the wrapped data type.
125122
"""
126-
...
123+
raise NotImplementedError # pragma: no cover
127124

128125
@abstractmethod
129126
def to_native_dtype(self: Self) -> TDType_co:
@@ -135,15 +132,17 @@ def to_native_dtype(self: Self) -> TDType_co:
135132
TDType
136133
The native data type wrapped by this ZDType.
137134
"""
138-
...
135+
raise NotImplementedError # pragma: no cover
139136

140137
@classmethod
141138
@abstractmethod
142-
def _from_json_v2(cls: type[Self], data: DTypeJSON) -> Self: ...
139+
def _from_json_v2(cls: type[Self], data: DTypeJSON) -> Self:
140+
raise NotImplementedError # pragma: no cover
143141

144142
@classmethod
145143
@abstractmethod
146-
def _from_json_v3(cls: type[Self], data: DTypeJSON) -> Self: ...
144+
def _from_json_v3(cls: type[Self], data: DTypeJSON) -> Self:
145+
raise NotImplementedError # pragma: no cover
147146

148147
@classmethod
149148
def from_json(cls: type[Self], data: DTypeJSON, *, zarr_format: ZarrFormat) -> Self:
@@ -190,7 +189,7 @@ def to_json(self, zarr_format: ZarrFormat) -> DTypeSpec_V2 | DTypeSpec_V3:
190189
DTypeJSON_V2 | DTypeJSON_V3
191190
The JSON-serializable representation of the wrapped data type
192191
"""
193-
...
192+
raise NotImplementedError # pragma: no cover
194193

195194
@abstractmethod
196195
def _check_scalar(self, data: object) -> bool:
@@ -207,7 +206,7 @@ def _check_scalar(self, data: object) -> bool:
207206
Bool
208207
True if the object is valid, False otherwise.
209208
"""
210-
...
209+
raise NotImplementedError # pragma: no cover
211210

212211
@abstractmethod
213212
def cast_scalar(self, data: object) -> TScalar_co:
@@ -227,6 +226,7 @@ def cast_scalar(self, data: object) -> TScalar_co:
227226
TScalar
228227
The cast value.
229228
"""
229+
raise NotImplementedError # pragma: no cover
230230

231231
@abstractmethod
232232
def default_scalar(self) -> TScalar_co:
@@ -242,7 +242,7 @@ def default_scalar(self) -> TScalar_co:
242242
TScalar
243243
The default value for this data type.
244244
"""
245-
...
245+
raise NotImplementedError # pragma: no cover
246246

247247
@abstractmethod
248248
def from_json_scalar(self: Self, data: JSON, *, zarr_format: ZarrFormat) -> TScalar_co:
@@ -262,7 +262,7 @@ def from_json_scalar(self: Self, data: JSON, *, zarr_format: ZarrFormat) -> TSca
262262
TScalar
263263
The deserialized scalar value.
264264
"""
265-
...
265+
raise NotImplementedError # pragma: no cover
266266

267267
@abstractmethod
268268
def to_json_scalar(self, data: object, *, zarr_format: ZarrFormat) -> JSON:
@@ -285,7 +285,7 @@ def to_json_scalar(self, data: object, *, zarr_format: ZarrFormat) -> JSON:
285285
JSON
286286
The JSON-serialized scalar.
287287
"""
288-
...
288+
raise NotImplementedError # pragma: no cover
289289

290290

291291
def scalar_failed_type_check_msg(

0 commit comments

Comments
 (0)