def test_generate_long_ellipsis(): """Strategy can replace runs of slice(None) with Ellipsis. We specifically test if [0,...,0] is generated alongside [0,:,:,:,0] """ strat = xps.indices(shape=(1, 0, 0, 0, 1), max_dims=3, allow_ellipsis=True) find_any(strat, lambda ix: len(ix) == 3 and ix[1] == Ellipsis) find_any( strat, lambda ix: len(ix) == 5 and all(isinstance(key, slice) and key == slice(None) for key in ix[1:3]), )
def test_generate_valid_indices(shape, allow_ellipsis, data): """Strategy generates valid indices.""" min_dims = data.draw(st.integers(0, len(shape)), label="min_dims") max_dims = data.draw( st.none() | st.integers(min_dims, len(shape)), label="max_dims" ) indexer = data.draw( xps.indices( shape, min_dims=min_dims, max_dims=max_dims, allow_ellipsis=allow_ellipsis, ), label="indexer", ) _indexer = indexer if isinstance(indexer, tuple) else (indexer,) # Check that disallowed things are indeed absent if not allow_ellipsis: assert Ellipsis not in _indexer assert None not in _indexer # i.e. np.newaxis # Check index is composed of valid objects for i in _indexer: assert isinstance(i, int) or isinstance(i, slice) or i == Ellipsis # Check indexer does not flat index if Ellipsis in _indexer: assert sum(i == Ellipsis for i in _indexer) == 1 assert len(_indexer) <= len(shape) + 1 # Ellipsis can index 0 axes else: assert len(_indexer) == len(shape) if 0 in shape: # If there's a zero in the shape, the array will have no elements. array = xp.zeros(shape) assert array.size == 0 # sanity check elif math.prod(shape) <= 10**5: # If it's small enough to instantiate, do so with distinct elements. array = xp.reshape(xp.arange(math.prod(shape)), shape) else: # We can't cheat on this one, so just try another. assume(False) # Finally, check that we can use our indexer without error array[indexer]
def test_indices_generate_valid_indexers(shape, allow_ellipsis, data): """Strategy generates valid indices.""" min_dims = data.draw(st.integers(0, len(shape)), label="min_dims") max_dims = data.draw(st.none() | st.integers(min_dims, len(shape)), label="max_dims") indexer = data.draw( xps.indices( shape, min_dims=min_dims, max_dims=max_dims, allow_ellipsis=allow_ellipsis, ), label="indexer", ) # Check that disallowed things are indeed absent if isinstance(indexer, tuple): assert 0 <= len(indexer) <= len(shape) + int(allow_ellipsis) else: assert 1 <= len(shape) + int(allow_ellipsis) assert None not in shape if not allow_ellipsis: assert Ellipsis not in shape if 0 in shape: # If there's a zero in the shape, the array will have no elements. array = xp.zeros(shape) assert array.size == 0 elif math.prod(shape) <= 10**5: # If it's small enough to instantiate, do so with distinct elements. array = xp.reshape(xp.arange(math.prod(shape)), shape) else: # We can't cheat on this one, so just try another. assume(False) # Finally, check that we can use our indexer without error array[indexer]
def test_generate_tuples_and_non_tuples_for_1d_shape(): """Strategy can generate tuple and non-tuple indices with a 1-dimensional shape.""" strat = xps.indices(shape=(1,), allow_ellipsis=True) find_any(strat, lambda ix: isinstance(ix, tuple)) find_any(strat, lambda ix: not isinstance(ix, tuple))
from tests.array_api.common import xp, xps from tests.common.debug import find_any def test_generate_indices_with_and_without_ellipsis(): """Strategy can generate indices with and without Ellipsis.""" strat = ( xps.array_shapes(min_dims=1, max_dims=32) .flatmap(xps.indices) .map(lambda idx: idx if isinstance(idx, tuple) else (idx,)) ) find_any(strat, lambda ix: Ellipsis in ix) find_any(strat, lambda ix: Ellipsis not in ix) @given(xps.indices(shape=(), allow_ellipsis=True)) def test_generate_indices_for_0d_shape(idx): """Strategy only generates empty tuples or Ellipsis as indices for an empty shape.""" assert idx in [(), Ellipsis, (Ellipsis,)] def test_generate_tuples_and_non_tuples_for_1d_shape(): """Strategy can generate tuple and non-tuple indices with a 1-dimensional shape.""" strat = xps.indices(shape=(1,), allow_ellipsis=True) find_any(strat, lambda ix: isinstance(ix, tuple)) find_any(strat, lambda ix: not isinstance(ix, tuple)) def test_generate_long_ellipsis(): """Strategy can replace runs of slice(None) with Ellipsis.
# top-level methods by binding the passed xp argument, and so the namespace # it returns should not expose xp in any of its function signatures. assert "xp" not in signature(func).parameters.keys() @pytest.mark.parametrize( "name, strat", [ ("from_dtype", xps.from_dtype(xp.int8)), ("arrays", xps.arrays(xp.int8, 5)), ("array_shapes", xps.array_shapes()), ("scalar_dtypes", xps.scalar_dtypes()), ("boolean_dtypes", xps.boolean_dtypes()), ("numeric_dtypes", xps.numeric_dtypes()), ("integer_dtypes", xps.integer_dtypes()), ("unsigned_integer_dtypes", xps.unsigned_integer_dtypes()), ("floating_dtypes", xps.floating_dtypes()), ("valid_tuple_axes", xps.valid_tuple_axes(0)), ("broadcastable_shapes", xps.broadcastable_shapes(())), ("mutually_broadcastable_shapes", xps.mutually_broadcastable_shapes(3)), ("indices", xps.indices((5, ))), ], ) def test_namespaced_strategies_repr(name, strat): """Namespaced strategies have good repr.""" assert repr(strat).startswith(name + "("), f"{name} not in strat repr {strat!r}" assert len(repr(strat)) < 100, "strat repr looks too long" assert xp.__name__ not in repr(strat), f"{xp.__name__} in strat repr"
def test_generate_non_tuples(): """Strategy generates non-tuples as indices.""" find_any( xps.indices(shape=(0, 0), allow_ellipsis=True), lambda ix: not isinstance(ix, tuple), )
def test_generate_empty_tuple(): """Strategy generates empty tuples as indices.""" find_any(xps.indices(shape=(0, 0), allow_ellipsis=True), lambda ix: ix == ())