Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions changes/4414.bugfix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
An array `config` with a key that is not a runtime configuration option (for example a misspelled `write_empty_chunk`) now raises a `TypeError` naming the unknown and valid keys. Previously `create_array`, `create`, `open_array` and other functions silently ignored such keys.
9 changes: 8 additions & 1 deletion src/zarr/core/array_spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,15 @@ def from_dict(cls, data: ArrayConfigParams) -> Self:
"""
Create an ArrayConfig from a dict. The keys of that dict are a subset of the
attributes of the ArrayConfig class. Any keys missing from that dict will be set to the
the values in the ``array`` namespace of ``zarr.config``.
the values in the ``array`` namespace of ``zarr.config``. Keys that are not
attributes of the ArrayConfig class raise a `TypeError`.
"""
unknown = set(data) - {f.name for f in fields(ArrayConfig)}
if unknown:
raise TypeError(
f"Unknown array config keys: {sorted(unknown)}. "
f"Valid keys are {[f.name for f in fields(ArrayConfig)]}."
)
kwargs_out: ArrayConfigParams = {}
for f in fields(ArrayConfig):
field_name = cast(
Expand Down
46 changes: 45 additions & 1 deletion tests/test_array_spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
import numpy as np
import pytest

from zarr.core.array_spec import ArrayConfig, ArraySpec
import zarr
from zarr.core.array_spec import ArrayConfig, ArrayConfigParams, ArraySpec
from zarr.core.buffer import BufferPrototype, default_buffer_prototype
from zarr.core.buffer.cpu import NDBuffer
from zarr.core.dtype import get_data_type_from_native_dtype
Expand Down Expand Up @@ -177,3 +178,46 @@ def test_signed_zero_fills_are_distinct(native_dtype: Any, neg_fill: Any, pos_fi
def test_unequal_with_invalid_type(obj: Any) -> None:
assert (_make_spec() == obj) is False
assert _make_spec() != obj


@pytest.mark.parametrize(
"data",
[
{},
{"order": "F"},
{"write_empty_chunks": True, "read_missing_chunks": False},
{
"order": "F",
"write_empty_chunks": True,
"read_missing_chunks": False,
"sharding_coalesce_max_gap_bytes": 1,
"sharding_coalesce_max_bytes": 2,
},
],
)
def test_array_config_from_dict(data: ArrayConfigParams) -> None:
"""
ArrayConfig.from_dict takes the given keys from `data` and the rest from the global
configuration.
"""
observed = ArrayConfig.from_dict(data).to_dict()
for key, value in observed.items():
assert value == data.get(key, zarr.config.get(f"array.{key}"))


@pytest.mark.parametrize(
"build",
[
lambda config: ArrayConfig.from_dict(config),
lambda config: zarr.create_array({}, shape=(4,), dtype="uint8", config=config),
lambda config: zarr.create(shape=(4,), dtype="uint8", config=config),
],
ids=["from_dict", "create_array", "create"],
)
def test_array_config_unknown_key(build: Callable[[Any], object]) -> None:
"""
An array config with a key that is not an ArrayConfig attribute raises TypeError instead of
being ignored.
"""
with pytest.raises(TypeError, match=r"Unknown array config keys: \['nope'\]"):
build({"order": "C", "nope": 1})
Loading