Skip to content

Commit

Permalink
Merge pull request #2511 from Sangarshanan/negative-indices-slices
Browse files Browse the repository at this point in the history
  • Loading branch information
Zac-HD authored Jul 25, 2020
2 parents 1a116eb + a8d46ce commit 2559bc5
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 10 deletions.
1 change: 1 addition & 0 deletions CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ their individual contributions.
* `Ryan Turner <https://github.com/rdturnermtl>`_ ([email protected])
* `Sam Bishop (TechDragon) <https://github.com/techdragon>`_ ([email protected])
* `Sam Hames <https://www.github.com/SamHames>`_
* `Sangarshanan <https://www.github.com/sangarshanan>`_ ([email protected])
* `Sanyam Khurana <https://github.com/CuriousLearner>`_
* `Saul Shanabrook <https://www.github.com/saulshanabrook>`_ ([email protected])
* `Stuart Cook <https://www.github.com/Zalathar>`_
Expand Down
7 changes: 7 additions & 0 deletions hypothesis-python/RELEASE.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
RELEASE_TYPE: minor

The :func:`~hypothesis.strategies.slices` strategy can now generate slices for empty sequences,
slices with negative start and stop indices (from the end of the sequence),
and ``step=None`` in place of ``step=1``.

Thanks to Sangarshanan for implementing this feature at the EuroPython sprints!
2 changes: 1 addition & 1 deletion hypothesis-python/src/hypothesis/internal/validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def check_valid_size(value, name):
Otherwise raises InvalidArgument.
"""
if value is None and name != "min_size":
if value is None and name not in ("min_size", "size"):
return
check_type(int, value, name)
if value < 0:
Expand Down
14 changes: 10 additions & 4 deletions hypothesis-python/src/hypothesis/strategies/_internal/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -2173,15 +2173,16 @@ def functions(
def slices(draw: Any, size: int) -> slice:
"""Generates slices that will select indices up to the supplied size
Generated slices will have start and stop indices that range from 0 to size - 1
Generated slices will have start and stop indices that range from -size to size - 1
and will step in the appropriate direction. Slices should only produce an empty selection
if the start and end are the same.
Examples from this strategy shrink toward 0 and smaller values
"""
check_valid_integer(size, "size")
if size is None or size < 1:
raise InvalidArgument("size=%r must be at least one" % size)
check_valid_size(size, "size")
if size == 0:
step = draw(none() | integers().filter(bool))
return slice(None, None, step)

min_start = min_stop = 0
max_start = max_stop = size
Expand All @@ -2205,4 +2206,9 @@ def slices(draw: Any, size: int) -> slice:
if (stop or 0) < (start or 0):
step *= -1

if draw(booleans()) and start is not None:
start -= size
if draw(booleans()) and stop is not None:
stop -= size

return slice(start, stop, step)
1 change: 0 additions & 1 deletion hypothesis-python/tests/cover/test_direct_strategies.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,6 @@ def fn_ktest(*fnkwargs):
(ds.characters, {"max_codepoint": "1"}),
(ds.characters, {"whitelist_categories": []}),
(ds.characters, {"whitelist_categories": ["Nd"], "blacklist_categories": ["Nd"]}),
(ds.slices, {"size": 0}),
(ds.slices, {"size": None}),
(ds.slices, {"size": "chips"}),
(ds.slices, {"size": -1}),
Expand Down
16 changes: 12 additions & 4 deletions hypothesis-python/tests/cover/test_slices.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,16 @@
@use_several_sizes
def test_stop_stays_within_bounds(size):
assert_all_examples(
st.slices(size), lambda x: x.stop is None or (x.stop >= 0 and x.stop <= size)
st.slices(size),
lambda x: x.stop is None or (x.stop >= -size and x.stop <= 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 >= 0 and x.start <= size)
st.slices(size),
lambda x: x.start is None or (x.start >= -size and x.start <= size),
)


Expand All @@ -45,9 +47,9 @@ def test_step_stays_within_bounds(size):
st.slices(size),
lambda x: (
x.indices(size)[0] + x.indices(size)[2] <= size
and x.indices(size)[0] + x.indices(size)[2] >= -1
and x.indices(size)[0] + x.indices(size)[2] >= -size
)
or x.start == x.stop,
or x.start % size == x.stop % size,
)


Expand Down Expand Up @@ -98,3 +100,9 @@ def test_start_will_equal_0(size):
@settings(deadline=None)
def test_start_will_equal_stop(size):
find_any(st.slices(size), lambda x: x.start == x.stop)


def test_size_is_equal_0():
assert_all_examples(
st.slices(0), lambda x: x.step != 0 and x.start is None and x.stop is None
)

0 comments on commit 2559bc5

Please sign in to comment.