Repository: numpy/numpy
File: numpy/lib/_stride_tricks_impl.py (Python)

Code before:
    ... c = as_strided(b, shape=(2,), strides=(400,), check_bounds=True)
    ... c[0], c[1]
    (0, 50)
    """

    # first convert input to array, possibly keeping subclass
    base = np.array(x, copy=None, subok=subok)
    interface = dict(base.__array_interface__)
    if shape is not None:
        interface['shape'] = tuple(shape)
    if strides is not None:
        interface['strides'] = tuple(strides)

    array = np.asarray(DummyArray(interface, base=base))
    # The route via `__interface__` does not preserve structured
    # dtypes. Since dtype should remain unchanged, we set it explicitly.
    array.dtype = base.dtype

    view = _maybe_view_as_subclass(base, array)

    if view.flags.writeable and not writeable:
        view.flags.writeable = False

    if check_bounds:
        while base.base is not None:
            base = base.base

        base_low, base_high = byte_bounds(base)
        view_low, view_high = byte_bounds(view)

        if view_low < base_low:
            raise ValueError(
                f"Given shape and strides would access memory out of bounds. "
                f"View starts {base_low - view_low} before starts"
            )

        if view_high > base_high:
            raise ValueError(
                f"Given shape and strides would access memory out of bounds. "
                f"View ends {view_high - base_high} after ends"
            )

    return view


def _sliding_window_view_dispatcher(x, window_shape, axis=None, *,
                                    subok=None, writeable=None):
    return (x,)


@array_function_dispatch(

Review comment (suggestion):
I am OK with walking the base. But you have to refine it so that you also stop when `not isinstance(base.base, np.ndarray)`.  I suppose since `None` isn't an instance of ndarray and there is probably no reason to fret over a few ns here that would be sufficient also.

Marked as triage-review. (with it now beings just a new kwarg, I don't really see why not just add it.)

(I suppose unrelated, but wonder if we should add a `.. note::` that tells people to prefer `sliding_window_view`.  Such a note seems a bit missing.)

Code after:
    ... c = as_strided(b, shape=(2,), strides=(400,), check_bounds=True)
    ... c[0], c[1]
    (0, 50)
    """

    # first convert input to array, possibly keeping subclass
    base = np.array(x, copy=None, subok=subok)
    interface = dict(base.__array_interface__)
    if shape is not None:
        interface['shape'] = tuple(shape)
    if strides is not None:
        interface['strides'] = tuple(strides)

    array = np.asarray(DummyArray(interface, base=base))
    # The route via `__interface__` does not preserve structured
    # dtypes. Since dtype should remain unchanged, we set it explicitly.
    array.dtype = base.dtype

    view = _maybe_view_as_subclass(base, array)

    if view.flags.writeable and not writeable:
        view.flags.writeable = False

    if check_bounds:
        while isinstance(base.base, np.ndarray):
            base = base.base

        base_low, base_high = byte_bounds(base)
        view_low, view_high = byte_bounds(view)

        if view_low < base_low:
            raise ValueError(
                f"Given shape and strides would access memory out of bounds. "
                f"View starts {base_low - view_low} bytes before lowest address"
            )

        if view_high > base_high:
            raise ValueError(
                f"Given shape and strides would access memory out of bounds. "
                f"View ends {view_high - base_high} bytes after highest address"
            )

    return view


def _sliding_window_view_dispatcher(x, window_shape, axis=None, *,
                                    subok=None, writeable=None):
    return (x,)


@array_function_dispatch(