From 702af0905b3b002cb18220959011073bcd270466 Mon Sep 17 00:00:00 2001 From: Zac-HD Date: Thu, 9 Sep 2021 12:45:56 +1000 Subject: [PATCH] Fix undefined slice error --- hypothesis-python/RELEASE.rst | 3 +++ .../src/hypothesis/strategies/_internal/core.py | 7 ++----- hypothesis-python/tests/cover/test_slices.py | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/hypothesis-python/RELEASE.rst b/hypothesis-python/RELEASE.rst index d572a1e809..7105c9f34a 100644 --- a/hypothesis-python/RELEASE.rst +++ b/hypothesis-python/RELEASE.rst @@ -1,3 +1,6 @@ RELEASE_TYPE: minor This release allows :func:`~hypothesis.strategies.slices` to generate ``step=None``, +and fixes an off-by-one error where the ``start`` index could be equal to ``size``. +This works fine for all Python sequences and Numpy arrays, but is undefined behaviour +in the `Array API standard `__ (see :pull:`3065`). diff --git a/hypothesis-python/src/hypothesis/strategies/_internal/core.py b/hypothesis-python/src/hypothesis/strategies/_internal/core.py index 12a2bd3539..de7ec1058a 100644 --- a/hypothesis-python/src/hypothesis/strategies/_internal/core.py +++ b/hypothesis-python/src/hypothesis/strategies/_internal/core.py @@ -1901,12 +1901,9 @@ def slices(draw: Any, size: int) -> slice: if size == 0: step = draw(none() | integers().filter(bool)) return slice(None, None, step) - - min_start = min_stop = 0 - max_start = max_stop = size # For slices start is inclusive and stop is exclusive - start = draw(integers(min_start, max_start) | none()) - stop = draw(integers(min_stop, max_stop) | none()) + start = draw(integers(0, size - 1) | none()) + stop = draw(integers(0, size) | none()) # Limit step size to be reasonable if start is None and stop is None: diff --git a/hypothesis-python/tests/cover/test_slices.py b/hypothesis-python/tests/cover/test_slices.py index eb1915cc41..8d6563d336 100644 --- a/hypothesis-python/tests/cover/test_slices.py +++ b/hypothesis-python/tests/cover/test_slices.py @@ -33,8 +33,8 @@ def test_stop_stays_within_bounds(size): @use_several_sizes def test_start_stay_within_bounds(size): assert_all_examples( - st.slices(size), - lambda x: x.start is None or (x.start >= -size and x.start <= size), + st.slices(size).filter(lambda x: x.start is not None), + lambda x: range(size)[x.start] or True, # no IndexError raised )