Skip to content

Commit 49df8a6

Browse files
committed
fix: validate the amount in Interval.range
A zero amount made range() yield the same start value forever: the advance step add(**{unit: i}) with i == 0 never moves, so the loop condition start <= end never turns false and any consuming for-loop hangs. A negative amount runs away from the stated end in the opposite direction, unbounded, for the same missing-validation reason. Reject non-positive amounts with ValueError, matching the documented direction handling (the direction itself is applied via add/subtract and le/ge, so the step magnitude must be positive in both directions). Fixes #1080 Co-authored-by: rahul05ranjan <11793455+rahul05ranjan@users.noreply.github.com>
1 parent e06dace commit 49df8a6

3 files changed

Lines changed: 23 additions & 0 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Change Log
22

3+
## Unreleased
4+
5+
### Fixed
6+
- `Interval.range()` now raises `ValueError` for a non-positive `amount` instead of silently producing an infinite (amount <= 0... zero repeats the start forever, negative runs away from the end) or unbounded generator [#1080](https://github.com/python-pendulum/pendulum/issues/1080)
7+
38
## [3.3.0] - 2026-10-12
49

510
### Added

‎src/pendulum/interval.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,10 @@ def in_words(self, locale: str | None = None, separator: str = " ") -> str:
288288
return separator.join(parts)
289289

290290
def range(self, unit: str, amount: int = 1) -> Iterator[_T]:
291+
if amount <= 0:
292+
msg = f"amount must be a positive integer, got {amount!r}"
293+
raise ValueError(msg)
294+
291295
method = "add"
292296
op = operator.le
293297
if not self._absolute and self.invert:

‎tests/interval/test_range.py‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from __future__ import annotations
22

3+
import pytest
4+
35
import pendulum
46

57
from pendulum.interval import Interval
@@ -117,3 +119,15 @@ def test_range_amount():
117119
assert_datetime(r[1], 2016, 10, 16, 1, 0, 0)
118120
assert_datetime(r[2], 2016, 10, 18, 0, 0, 0)
119121
assert_datetime(r[3], 2016, 10, 20, 0, 0, 0)
122+
123+
124+
def test_range_zero_amount_raises():
125+
p = Interval(pendulum.datetime(2016, 1, 1), pendulum.datetime(2016, 2, 1))
126+
with pytest.raises(ValueError, match="positive integer"):
127+
list(p.range("days", 0))
128+
129+
130+
def test_range_negative_amount_raises():
131+
p = Interval(pendulum.datetime(2016, 1, 1), pendulum.datetime(2016, 2, 1))
132+
with pytest.raises(ValueError, match="positive integer"):
133+
list(p.range("days", -1))

0 commit comments

Comments
 (0)