diff --git a/newsfragments/3562.bugfix.rst b/newsfragments/3562.bugfix.rst new file mode 100644 index 0000000000..1d9a0e84ad --- /dev/null +++ b/newsfragments/3562.bugfix.rst @@ -0,0 +1 @@ +Passing a NaN ``rate`` to :class:`trio.testing.MockClock` now raises :exc:`ValueError`, like a negative rate, instead of silently making the clock return NaN. diff --git a/src/trio/_core/_mock_clock.py b/src/trio/_core/_mock_clock.py index e437464b65..bc530115f5 100644 --- a/src/trio/_core/_mock_clock.py +++ b/src/trio/_core/_mock_clock.py @@ -1,5 +1,5 @@ import time -from math import inf +from math import inf, isnan from .. import _core from .._abc import Clock @@ -87,8 +87,8 @@ def rate(self) -> float: @rate.setter def rate(self, new_rate: float) -> None: - if new_rate < 0: - raise ValueError("rate must be >= 0") + if isnan(new_rate) or new_rate < 0: + raise ValueError(f"rate must be a non-negative number, not {new_rate!r}") else: real = self._real_clock() virtual = self._real_to_virtual(real) diff --git a/src/trio/_core/_tests/test_mock_clock.py b/src/trio/_core/_tests/test_mock_clock.py index 6131e7ba3f..47ee1ff2a4 100644 --- a/src/trio/_core/_tests/test_mock_clock.py +++ b/src/trio/_core/_tests/test_mock_clock.py @@ -28,10 +28,23 @@ def test_mock_clock() -> None: assert c.deadline_to_sleep_time(1.2) == 0 assert c.deadline_to_sleep_time(1.3) > 999999 - with pytest.raises(ValueError, match=r"^rate must be >= 0$"): + with pytest.raises( + ValueError, match=r"^rate must be a non-negative number, not -1$" + ): c.rate = -1 assert c.rate == 0 + with pytest.raises( + ValueError, match=r"^rate must be a non-negative number, not nan$" + ): + c.rate = float("nan") + assert c.rate == 0 + + with pytest.raises( + ValueError, match=r"^rate must be a non-negative number, not nan$" + ): + MockClock(rate=float("nan")) + c.rate = 2 assert c.current_time() == 1.2 REAL_NOW += 1