From b718bdbabbea1d36c265020b3e33386eb33520e4 Mon Sep 17 00:00:00 2001 From: AC Date: Thu, 8 Oct 2026 12:11:33 +0800 Subject: [PATCH] Fix empty and non-advancing chunk ranges --- boltons/iterutils.py | 7 +++++++ tests/test_iterutils.py | 17 +++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/boltons/iterutils.py b/boltons/iterutils.py index adefc31a..cb062f7b 100644 --- a/boltons/iterutils.py +++ b/boltons/iterutils.py @@ -366,6 +366,8 @@ def chunk_ranges(input_size, chunk_size, input_offset=0, overlap_size=0, align=F are always at the beginning of the chunk. Returns an iterator of (start, end) tuples, one tuple per chunk. + An empty input yields no chunks. *overlap_size* must be less than + *chunk_size*, so each chunk advances through the input. >>> list(chunk_ranges(input_offset=10, input_size=10, chunk_size=5)) [(10, 15), (15, 20)] @@ -394,6 +396,11 @@ def chunk_ranges(input_size, chunk_size, input_offset=0, overlap_size=0, align=F overlap_size = _validate_positive_int( overlap_size, 'overlap_size', strictly_positive=False) + if overlap_size >= chunk_size: + raise ValueError('overlap_size must be less than chunk_size') + if input_size == 0: + return + input_stop = input_offset + input_size if align: diff --git a/tests/test_iterutils.py b/tests/test_iterutils.py index a1f9dc01..cd656f3e 100644 --- a/tests/test_iterutils.py +++ b/tests/test_iterutils.py @@ -697,3 +697,20 @@ def test_frange_xfrange_zero_step(): frange(10, step=0) with pytest.raises(ValueError): list(xfrange(10, step=0)) + + +@pytest.mark.parametrize('align', [False, True]) +@pytest.mark.parametrize('input_offset', [0, 1, 4, 10]) +def test_chunk_ranges_empty(align, input_offset): + from boltons.iterutils import chunk_ranges + + assert list(chunk_ranges(0, 5, input_offset=input_offset, align=align)) == [] + + +@pytest.mark.parametrize('align', [False, True]) +@pytest.mark.parametrize('overlap_size', [5, 6, 10]) +def test_chunk_ranges_invalid_overlap(align, overlap_size): + from boltons.iterutils import chunk_ranges + + with pytest.raises(ValueError, match='overlap_size.*chunk_size'): + list(chunk_ranges(12, 5, overlap_size=overlap_size, align=align))