zarr.testing.strategies
Strategies¶
zarr.testing.strategies ¶
array_shapes
module-attribute
¶
array_shapes = npst.array_shapes(
max_dims=4, min_side=3, max_side=5
) | npst.array_shapes(max_dims=4, min_side=0)
attrs
module-attribute
¶
attrs: SearchStrategy[Mapping[str, JSON] | None] = (
st.none() | st.dictionaries(_attr_keys, _attr_values)
)
node_names
module-attribute
¶
node_names = (
st.text(zarr_key_chars, min_size=1)
.filter(
lambda t: (
t not in (".", "..")
and not t.startswith("__")
)
)
.filter(lambda name: name.lower() != "zarr.json")
)
sharding_inner_codecs
module-attribute
¶
sharding_inner_codecs: SearchStrategy[
list[BytesCodec | ZstdCodec]
] = st.sampled_from(
[[BytesCodec()], [BytesCodec(), ZstdCodec()]]
)
short_node_names
module-attribute
¶
short_node_names = (
st.text(zarr_key_chars, max_size=3, min_size=1)
.filter(
lambda t: (
t not in (".", "..")
and not t.startswith("__")
)
)
.filter(lambda name: name.lower() != "zarr.json")
)
subchunk_write_orders
module-attribute
¶
subchunk_write_orders: SearchStrategy[
SubchunkWriteOrder
] = st.sampled_from(SUBCHUNK_WRITE_ORDER)
zarr_formats
module-attribute
¶
zarr_key_chars
module-attribute
¶
zarr_key_chars = st.sampled_from(
".-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"
)
array_metadata ¶
array_metadata(
draw: DrawFn,
*,
array_shapes: Callable[
..., SearchStrategy[tuple[int, ...]]
] = array_shapes,
zarr_formats: SearchStrategy[ZarrFormat] = zarr_formats,
attributes: SearchStrategy[
Mapping[str, JSON] | None
] = attrs,
) -> ArrayV2Metadata | ArrayV3Metadata
Source code in zarr/testing/strategies.py
arrays ¶
arrays(
draw: DrawFn,
*,
shapes: SearchStrategy[tuple[int, ...]] = array_shapes,
compressors: SearchStrategy = compressors,
stores: SearchStrategy[StoreLike] = stores,
paths: SearchStrategy[str] = paths(),
array_names: SearchStrategy = array_names,
arrays: SearchStrategy | None = None,
attrs: SearchStrategy = attrs,
zarr_formats: SearchStrategy = zarr_formats,
subchunk_write_orders: SearchStrategy[
SubchunkWriteOrder
] = subchunk_write_orders,
open_mode: AccessModeLiteral = "w",
) -> AnyArray
Source code in zarr/testing/strategies.py
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 | |
basic_indices ¶
basic_indices(
draw: DrawFn,
*,
shape: tuple[int, ...],
min_dims: int = 0,
max_dims: int | None = None,
allow_newaxis: TrueOrFalse = False,
allow_ellipsis: TrueOrFalse = True,
) -> Any
Basic indices without unsupported negative slices.
Source code in zarr/testing/strategies.py
block_indices ¶
block_indices(
draw: DrawFn,
*,
chunk_sizes: tuple[tuple[int, ...], ...],
) -> tuple[tuple[int | slice, ...], tuple[slice, ...]]
Strategy for block-selection indexers over a chunk grid.
Block indexing is basic indexing applied to the block grid (the grid of
chunks), so each axis is drawn with basic_indices over that axis's chunk
count, mirroring how orthogonal_indices reuses basic_indices per
axis. chunk_sizes gives the per-chunk data sizes of the array's outer
(block) grid for every axis — i.e. Array.write_chunk_sizes, the grid that
Array.blocks addresses (the shard grid when sharding is used). For
example (3, 3, 3, 1) for a length-10 axis with a regular chunk size of 3,
or the explicit edges of a rectilinear axis; nchunks for an axis is
len(chunk_sizes[axis]).
The array-space translation uses the cumulative sum of those sizes, matching
BlockIndexer's use of dim_grid.chunk_offset. Because the sizes are
clipped to the array extent, the final offset equals the extent and the
translation is exact for regular (uniform), rectilinear, and sharded grids
alike.
Block indexing only supports integers and step-1 slices whose start references an existing chunk, so strided slices and slices starting at the grid edge are filtered out.
Returns:
-
block_indexer–A per-axis tuple of ints / step-1 slices addressing whole chunks, suitable for
Array.blocks/get_block_selection/set_block_selection. -
array_indexer–The equivalent array-space selection (a tuple of slices) for indexing the corresponding numpy array, used as the comparison oracle.
Source code in zarr/testing/strategies.py
739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 | |
block_test_arrays ¶
Draw an array for block-indexing property tests, with its source contents.
Two arms, selected with equal probability:
- regular: a regular chunk grid, optionally wrapped in sharding.
- rectilinear: a variable (rectilinear) chunk grid, always unsharded.
Returns (zarray, nparray). The per-axis block sizes the oracle needs are
zarray.write_chunk_sizes — the array's outer (block / shard) grid, which
is exactly the grid Array.blocks addresses; the caller reads it directly.
Source code in zarr/testing/strategies.py
chunk_grids ¶
chunk_grids(
draw: DrawFn, *, shape: tuple[int, ...]
) -> (
RegularChunkGridMetadata | RectilinearChunkGridMetadata
)
Generate either a RegularChunkGridMetadata or RectilinearChunkGridMetadata.
This strategy depends on the global state of the config having rectilinear chunk grids enabled or not. This means that it may be a possible source of a hypothesis FlakyStrategy error due dependence on global state. However, in practice this seems unlikely to happen.
This allows property tests to exercise both chunk grid types.
Source code in zarr/testing/strategies.py
chunk_paths ¶
Source code in zarr/testing/strategies.py
chunk_shapes ¶
Source code in zarr/testing/strategies.py
chunks_param_from_rectilinear ¶
Convert rectilinear chunk grid metadata into a chunks= argument.
Explicit edge tuples become lists. Bare ints — the spec's step-size shorthand meaning "repeat to cover the axis" — pass through unchanged; wrapping one in a single-element list would instead declare exactly one chunk, which fails normalization whenever the axis needs more than one.
Source code in zarr/testing/strategies.py
clear_store ¶
complex_rectilinear_arrays ¶
complex_rectilinear_arrays(
draw: DrawFn,
*,
stores: SearchStrategy[StoreLike] = stores,
paths: SearchStrategy[str] = paths(),
array_names: SearchStrategy = array_names,
attrs: SearchStrategy = attrs,
) -> tuple[NDArray[Any], AnyArray]
Generate a rectilinear array with many small chunks.
The shape is derived from the chunk edges (5-10 chunks per dim,
sizes 1-5), exercising higher chunk counts than rectilinear_arrays.
Source code in zarr/testing/strategies.py
dimension_names ¶
Source code in zarr/testing/strategies.py
dtypes ¶
Source code in zarr/testing/strategies.py
end_slices ¶
A strategy that slices ranges that include the last chunk. This is intended to stress-test handling of a possibly smaller last chunk.
Source code in zarr/testing/strategies.py
is_negative_slice ¶
key_ranges ¶
key_ranges(
keys: SearchStrategy[str] = node_names,
max_size: int = maxsize,
) -> SearchStrategy[list[tuple[str, ByteRequest | None]]]
Function to generate key_ranges strategy for get_partial_values() returns list strategy w/ form::
[(key, byte_request),
(key, byte_request),...]
where byte_request is None or any of the concrete ByteRequest
subtypes. The bounds are drawn independently of each value's length, so the
offsets/suffixes routinely exceed the data and exercise the clamping logic
in _normalize_byte_range_index.
Source code in zarr/testing/strategies.py
keys ¶
np_array_and_chunks ¶
np_array_and_chunks(
draw: DrawFn,
*,
arrays: SearchStrategy[NDArray[Any]] = numpy_arrays(),
) -> tuple[ndarray[Any, Any], tuple[int, ...]]
A hypothesis strategy to generate small sized random arrays.
Returns: a tuple of the array and a suitable random chunking for it.
Source code in zarr/testing/strategies.py
numpy_arrays ¶
numpy_arrays(
draw: DrawFn,
*,
shapes: SearchStrategy[tuple[int, ...]] = array_shapes,
dtype: dtype[Any] | None = None,
) -> NDArray[Any]
Generate numpy arrays that can be saved in the provided Zarr format.
Source code in zarr/testing/strategies.py
orthogonal_indices ¶
orthogonal_indices(
draw: DrawFn, *, shape: tuple[int, ...]
) -> tuple[
tuple[int | slice | ndarray[Any, Any], ...],
tuple[ndarray[Any, Any], ...],
]
Strategy that returns
(1) a tuple of per-axis selectors (integer array, slice, or bare integer) for
orthogonal indexing of Zarr arrays.
(2) a tuple of broadcast integer arrays that index a numpy array to the same
result. A bare integer drops its axis, as oindex does, so it is
given as a 0-d array and does not contribute a result dimension.
Source code in zarr/testing/strategies.py
paths ¶
rectilinear_arrays ¶
rectilinear_arrays(
draw: DrawFn,
*,
shapes: SearchStrategy[
tuple[int, ...]
] = _rectilinear_shapes,
) -> Any
Generate a zarr v3 array with rectilinear (variable) chunk grid.
Source code in zarr/testing/strategies.py
rectilinear_chunks ¶
Generate valid rectilinear chunk shapes for a given array shape.
Uses two modes per dimension: - "expanded": random divider points create arbitrary chunk sizes - "rle": uniform chunks with optional remainder, optionally shuffled
Keeps max chunks per dimension <= 20 to avoid performance issues in property tests. With higher dimensions, the total chunk count grows multiplicatively.
Source code in zarr/testing/strategies.py
safe_unicode_for_dtype ¶
Generate UTF-8-safe text constrained to max_len of dtype.
Source code in zarr/testing/strategies.py
shard_shapes ¶
shard_shapes(
draw: DrawFn,
*,
shape: tuple[int, ...],
chunk_shape: tuple[int, ...],
) -> tuple[int, ...]
Source code in zarr/testing/strategies.py
sharded_arrays ¶
sharded_arrays(
draw: DrawFn,
*,
shapes: SearchStrategy[
tuple[int, ...]
] = _sharded_shapes,
nested: bool | None = None,
) -> Any
Generate a zarr v3 array whose chunks are grouped into shards.
arrays shards only a small fraction of its draws (a v3 array with a
regular chunk grid, every axis larger than a chunk that is itself larger
than 1, and then only half the time), so a property test that must
exercise the sharding codec should draw from this strategy directly. Every
draw is sharded: the chunk shape and the shard shape (an integral number of
chunks per axis, possibly a single chunk) are drawn from shapes, and
the codec's subchunk write order and inner codec chain are drawn as in
arrays. shapes must generate shapes with at least one element on
every axis.
nested selects one level of recursive sharding: the drawn chunks are
grouped into inner shards, which are themselves grouped into the shards
stored in the array, so the outer ShardingCodec wraps an inner one with
its own subchunk write order. None (the default) draws it, so half the
examples nest. For a nested array Array.chunks is the inner shard shape
(the outer codec's chunk shape); the innermost chunk shape is the inner
codec's chunk_shape.
Source code in zarr/testing/strategies.py
simple_arrays ¶
simple_arrays(
draw: DrawFn,
*,
shapes: SearchStrategy[tuple[int, ...]] = array_shapes,
) -> Any