def indices( shape: Shape, *, min_dims: int = 0, max_dims: Optional[int] = None, allow_ellipsis: bool = True, ) -> st.SearchStrategy[BasicIndex]: """Return a strategy for :xp-ref:`valid indices <indexing.html>` of arrays with the specified shape, which may include dimensions of size zero. It generates tuples containing some mix of integers, :obj:`python:slice` objects, and ``...`` (an ``Ellipsis``). When a length-one tuple would be generated, this strategy may instead return the element which will index the first axis, e.g. ``5`` instead of ``(5,)``. * ``shape`` is the shape of the array that will be indexed, as a tuple of integers >= 0. This must be at least two-dimensional for a tuple to be a valid index; for one-dimensional arrays use :func:`~hypothesis.strategies.slices` instead. * ``min_dims`` is the minimum dimensionality of the resulting array from use of the generated index. * ``max_dims`` is the the maximum dimensionality of the resulting array, defaulting to ``len(shape)``. * ``allow_ellipsis`` specifies whether ``...`` is allowed in the index. """ check_type(tuple, shape, "shape") check_argument( all(isinstance(x, int) and x >= 0 for x in shape), f"shape={shape!r}, but all dimensions must be non-negative integers.", ) check_type(bool, allow_ellipsis, "allow_ellipsis") check_type(int, min_dims, "min_dims") check_argument( min_dims <= len(shape), f"min_dims={min_dims} is larger than len(shape)={len(shape)}, " "but it is impossible for an indexing operation to add dimensions.", ) check_valid_dims(min_dims, "min_dims") if max_dims is None: max_dims = min(len(shape), NDIM_MAX) check_type(int, max_dims, "max_dims") assert isinstance(max_dims, int) check_argument( max_dims <= len(shape), f"max_dims={max_dims} is larger than len(shape)={len(shape)}, " "but it is impossible for an indexing operation to add dimensions.", ) check_valid_dims(max_dims, "max_dims") order_check("dims", 0, min_dims, max_dims) return BasicIndexStrategy( shape, min_dims=min_dims, max_dims=max_dims, allow_ellipsis=allow_ellipsis, allow_newaxis=False, allow_fewer_indices_than_dims=False, )
def array_dtypes( subtype_strategy: st.SearchStrategy[np.dtype] = scalar_dtypes(), *, min_size: int = 1, max_size: int = 5, allow_subarrays: bool = False, ) -> st.SearchStrategy[np.dtype]: """Return a strategy for generating array (compound) dtypes, with members drawn from the given subtype strategy.""" order_check("size", 0, min_size, max_size) # The empty string is replaced by f{idx}; see #1963 for details. Much easier to # insist that field names be unique and just boost f{idx} strings manually. field_names = st.integers(0, 127).map("f{}".format) | st.text(min_size=1) name_titles = st.one_of( field_names, st.tuples(field_names, field_names).filter(lambda ns: ns[0] != ns[1]), ) elements = st.tuples(name_titles, subtype_strategy) if allow_subarrays: elements |= st.tuples(name_titles, subtype_strategy, array_shapes(max_dims=2, max_side=2)) return st.lists( elements=elements, min_size=min_size, max_size=max_size, unique_by=( # Deduplicate by both name and title for efficiency before filtering. # (Field names must be unique, as must titles, and no intersections) lambda d: d[0] if isinstance(d[0], str) else d[0][0], lambda d: d[0] if isinstance(d[0], str) else d[0][1], ), ).filter(_no_title_is_name_of_a_titled_field)
def unicode_string_dtypes( *, endianness: str = "?", min_len: int = 1, max_len: int = 16 ) -> st.SearchStrategy[np.dtype]: """Return a strategy for generating unicode string dtypes, of various lengths and byteorder. While Hypothesis' string strategies can generate empty strings, string dtypes with length 0 indicate that size is still to be determined, so the minimum length for string dtypes is 1. """ order_check("len", 1, min_len, max_len) return dtype_factory("U", list(range(min_len, max_len + 1)), None, endianness)
def basic_indices( shape: Shape, *, min_dims: int = 0, max_dims: Optional[int] = None, allow_newaxis: bool = False, allow_ellipsis: bool = True, ) -> st.SearchStrategy[BasicIndex]: """Return a strategy for :doc:`basic indexes <numpy:reference/arrays.indexing>` of arrays with the specified shape, which may include dimensions of size zero. It generates tuples containing some mix of integers, :obj:`python:slice` objects, ``...`` (an ``Ellipsis``), and ``None``. When a length-one tuple would be generated, this strategy may instead return the element which will index the first axis, e.g. ``5`` instead of ``(5,)``. * ``shape`` is the shape of the array that will be indexed, as a tuple of positive integers. This must be at least two-dimensional for a tuple to be a valid index; for one-dimensional arrays use :func:`~hypothesis.strategies.slices` instead. * ``min_dims`` is the minimum dimensionality of the resulting array from use of the generated index. When ``min_dims == 0``, scalars and zero-dimensional arrays are both allowed. * ``max_dims`` is the the maximum dimensionality of the resulting array, defaulting to ``len(shape) if not allow_newaxis else max(len(shape), min_dims) + 2``. * ``allow_newaxis`` specifies whether ``None`` is allowed in the index. * ``allow_ellipsis`` specifies whether ``...`` is allowed in the index. """ # Arguments to exclude scalars, zero-dim arrays, and dims of size zero were # all considered and rejected. We want users to explicitly consider those # cases if they're dealing in general indexers, and while it's fiddly we can # back-compatibly add them later (hence using kwonlyargs). check_type(tuple, shape, "shape") check_argument( all(isinstance(x, int) and x >= 0 for x in shape), f"shape={shape!r}, but all dimensions must be non-negative integers.", ) check_type(bool, allow_ellipsis, "allow_ellipsis") check_type(bool, allow_newaxis, "allow_newaxis") check_type(int, min_dims, "min_dims") if min_dims > len(shape) and not allow_newaxis: note_deprecation( f"min_dims={min_dims} is larger than len(shape)={len(shape)}, " "but allow_newaxis=False makes it impossible for an indexing " "operation to add dimensions.", since="2021-09-15", has_codemod=False, ) check_valid_dims(min_dims, "min_dims") if max_dims is None: if allow_newaxis: max_dims = min(max(len(shape), min_dims) + 2, NDIM_MAX) else: max_dims = min(len(shape), NDIM_MAX) else: check_type(int, max_dims, "max_dims") if max_dims > len(shape) and not allow_newaxis: note_deprecation( f"max_dims={max_dims} is larger than len(shape)={len(shape)}, " "but allow_newaxis=False makes it impossible for an indexing " "operation to add dimensions.", since="2021-09-15", has_codemod=False, ) check_valid_dims(max_dims, "max_dims") order_check("dims", 0, min_dims, max_dims) return BasicIndexStrategy( shape, min_dims=min_dims, max_dims=max_dims, allow_ellipsis=allow_ellipsis, allow_newaxis=allow_newaxis, allow_fewer_indices_than_dims=True, )