@@ -276,11 +276,7 @@ def test_array_map_dependent_axis_reports_no_axis() -> None:
276276
277277
278278def test_scalar_on_a_fancy_axis_collapses_to_a_constant () -> None :
279- """The degenerate-collapse rule: an all-singleton ArrayMap becomes a ConstantMap.
280-
281- Without it the map keeps an `input_dimension` naming an axis the integer
282- index just removed, which after renumbering aliases a different axis.
283- """
279+ """Scalar selection collapses an all-singleton ArrayMap to a ConstantMap."""
284280 view = IndexTransform .from_shape ((7 , 5 )).oindex [np .array ([3 , 1 ]), slice (None )][0 ]
285281 assert view .output [0 ] == ConstantMap (offset = 3 )
286282 assert isinstance (view .output [1 ], DimensionMap )
@@ -926,13 +922,10 @@ def test_a_boolean_mask_composes_onto_a_fancy_view() -> None:
926922
927923
928924def test_an_ellipsis_only_vindex_step_preserves_a_correlated_gather () -> None :
929- """Regression: a slice -only vindex step misread correlated maps as orthogonal .
925+ """Ellipsis -only vectorized selection preserves correlated coordinates .
930926
931- `vindex[...]` (and `vindex[..., scalar]`, whose remainder after the scalar
932- is split off is ellipsis-only) used to stamp each correlated map with its
933- block axis as an orthogonal binding. Two "orthogonal" maps then shared one
934- input axis, and the partition walk rejected its own transform mid-read.
935- """
927+ This also applies after scalar indices have been split off. The selected
928+ values must agree across partitionings."""
936929 base = np .arange (16 ).reshape (4 , 4 )
937930
938931 for parts in (None , (2 , 2 ), (4 , 4 ), (1 , 3 )):
@@ -2435,15 +2428,7 @@ def test_a_masked_source_keeps_its_mask_under_every_partitioning(parts: Any) ->
24352428
24362429@pytest .mark .parametrize ("parts" , [None , (2 , 2 ), (3 , 4 )])
24372430def test_a_masked_source_keeps_its_mask_when_the_view_is_empty (parts : Any ) -> None :
2438- """An empty result is still a result, and its type must not depend on the parts.
2439-
2440- An empty view is answered without reading the source at all, and that
2441- shortcut reached for the array namespace's own `empty` — which knows nothing
2442- about masks — so an unpartitioned empty view came back a plain array while
2443- the same view partitioned came back masked. No cells either way, so nothing
2444- about the values changed; the caller just got a different type depending on
2445- how the read had been divided.
2446- """
2431+ """Empty views of masked sources return masked arrays for every partitioning."""
24472432 data = np .ma .masked_greater (np .arange (12 ).reshape (3 , 4 ), 7 )
24482433 got = repartition (LazyArray (data ), parts ).lazy [:, 2 :2 ].result ()
24492434 assert isinstance (got , np .ma .MaskedArray ), parts
@@ -2453,11 +2438,7 @@ def test_a_masked_source_keeps_its_mask_when_the_view_is_empty(parts: Any) -> No
24532438def test_a_large_array_without_dask_refuses_to_claim_equality (
24542439 monkeypatch : pytest .MonkeyPatch ,
24552440) -> None :
2456- """Above the digest limit the fallback must miss a cache rather than lie.
2457-
2458- Two arrays differing in one element used to token identically, because the
2459- fallback described the shape and dtype and gave up on the contents.
2460- """
2441+ """Without Dask, arrays above the digest limit receive distinct fallback tokens."""
24612442 import sys
24622443
24632444 monkeypatch .setitem (sys .modules , "dask.base" , None )
@@ -2521,15 +2502,7 @@ def test_a_zero_chunk_on_a_nonempty_axis_is_still_rejected() -> None:
25212502def test_the_coverage_count_agrees_with_numpy_for_reversed_selections (
25222503 selection : tuple [Any , ...],
25232504) -> None :
2524- """The safety net behind `result()`'s coverage assertion, checked on its own.
2525-
2526- `_out_selection_cell_count` sizes a partition's `out_selection` without
2527- materializing it, and `result()` trusts that count to decide whether the
2528- walk covered the view. Nothing pinned it for a reversed slice, so dropping
2529- its `start <= stop` guard — or wrapping the subtraction in `abs()` — left
2530- the suite green. A net nobody tests only matters once something else breaks,
2531- which is exactly when it needs to be right.
2532- """
2505+ """Coverage counts match NumPy selection sizes for reversed slices."""
25332506 data = reference ()
25342507 view = LazyArray (data ).with_parts ((2 , 2 , 2 )).lazy [selection ]
25352508 out_shape = view .shape
@@ -2556,26 +2529,14 @@ def test_the_coverage_count_agrees_with_numpy_for_reversed_selections(
25562529def test_the_coverage_count_matches_numpy_for_intervals_the_fast_path_declines (
25572530 selection : tuple [Any , ...], out_shape : tuple [int , ...], expected : int
25582531) -> None :
2559- """The guard on `result()`'s safety net, exercised where the walk cannot reach it.
2560-
2561- A partition walk only ever produces concrete forward in-bounds intervals, so
2562- the guard that keeps everything else off the subtraction fast path is not
2563- reachable through `parts()` at all — which is why removing it left the whole
2564- suite green. It is the net's own contract, so it is checked directly.
2565- """
2532+ """Coverage counts match NumPy for intervals outside the subtraction fast path."""
25662533 counted = _out_selection_cell_count (selection , out_shape )
25672534 assert counted == np .empty (out_shape )[selection ].size
25682535 assert counted == expected
25692536
25702537
25712538def test_a_zero_dimensional_index_array_drops_its_axis_like_a_scalar () -> None :
2572- """`a[np.array(2), :]` is `a[2, :]` in NumPy, and now here too.
2573-
2574- Only Python and NumPy integers counted as scalars, so a 0-d array fell
2575- through to the fancy path and was widened into a length-1 index array —
2576- keeping an axis NumPy drops. That was a third answer, agreeing with neither
2577- NumPy nor eager zarr, which rejects it.
2578- """
2539+ """Zero-dimensional integer arrays drop axes in orthogonal and vectorized selections."""
25792540 data = np .arange (20 ).reshape (4 , 5 )
25802541 for mode , expected in (
25812542 ("oindex" , data [np .array (2 ), :]),
@@ -2591,12 +2552,7 @@ def test_a_zero_dimensional_index_array_drops_its_axis_like_a_scalar() -> None:
25912552
25922553
25932554def test_a_multidimensional_array_in_an_orthogonal_selection_is_refused () -> None :
2594- """The rule belongs to the selection, so the message speaks its vocabulary.
2595-
2596- Left to the engine, this surfaced as a rank complaint about an `index_array`
2597- the caller never wrote — the transform layer's words for a mistake made two
2598- layers above it.
2599- """
2555+ """Reject multidimensional orthogonal index arrays with a selection-level error."""
26002556 with pytest .raises (IndexError , match = "must be 1-dimensional" ):
26012557 LazyArray (np .arange (20 ).reshape (4 , 5 )).lazy .oindex [[[0 , 1 ], [2 , 3 ]], slice (None )]
26022558
@@ -2611,13 +2567,7 @@ def test_with_parts_rejects_a_bare_integer() -> None:
26112567
26122568
26132569def test_fancy_composition_over_an_empty_axis () -> None :
2614- """Regression: composing fancy steps over an empty axis stays unpinned.
2615-
2616- The empty-domain branch of `compose` produces index arrays that are
2617- singleton on every non-empty axis; pinning one to an axis it merely
2618- broadcasts along made a later basic step index a size-1 axis positionally
2619- and raise, deep inside a legal chain.
2620- """
2570+ """Fancy composition over an empty axis preserves shape through later selections."""
26212571 base = np .empty ((3 , 0 , 6 ), dtype = np .int64 )
26222572 view = LazyArray (base ).lazy .oindex [[2 , 1 ], :, [5 , 0 , 3 ]]
26232573 assert view .shape == (2 , 0 , 3 )
0 commit comments