Skip to content

Commit 3146638

Browse files
authored
Merge pull request #2667 from jakkdl/sleep_nan
timeout functions now raise ValueError on NaN inputs
2 parents e917f7c + d1cbbd3 commit 3146638

File tree

3 files changed

+46
-14
lines changed

3 files changed

+46
-14
lines changed

newsfragments/2493.breaking.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Timeout functions now raise `ValueError` if passed `math.nan`. This includes `trio.sleep`, `trio.sleep_until`, `trio.move_on_at`, `trio.move_on_after`, `trio.fail_at` and `trio.fail_after`.

trio/_tests/test_timeouts.py

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,6 @@ async def sleep_2():
5353

5454
await check_takes_about(sleep_2, TARGET)
5555

56-
with pytest.raises(ValueError):
57-
await sleep(-1)
58-
5956
with assert_checkpoints():
6057
await sleep(0)
6158
# This also serves as a test of the trivial move_on_at
@@ -66,10 +63,6 @@ async def sleep_2():
6663

6764
@slow
6865
async def test_move_on_after():
69-
with pytest.raises(ValueError):
70-
with move_on_after(-1):
71-
pass # pragma: no cover
72-
7366
async def sleep_3():
7467
with move_on_after(TARGET):
7568
await sleep(100)
@@ -99,6 +92,29 @@ async def sleep_5():
9992
with fail_after(100):
10093
await sleep(0)
10194

102-
with pytest.raises(ValueError):
103-
with fail_after(-1):
104-
pass # pragma: no cover
95+
96+
async def test_timeouts_raise_value_error():
97+
# deadlines are allowed to be negative, but not delays.
98+
# neither delays nor deadlines are allowed to be NaN
99+
100+
nan = float("nan")
101+
102+
for fun, val in (
103+
(sleep, -1),
104+
(sleep, nan),
105+
(sleep_until, nan),
106+
):
107+
with pytest.raises(ValueError):
108+
await fun(val)
109+
110+
for cm, val in (
111+
(fail_after, -1),
112+
(fail_after, nan),
113+
(fail_at, nan),
114+
(move_on_after, -1),
115+
(move_on_after, nan),
116+
(move_on_at, nan),
117+
):
118+
with pytest.raises(ValueError):
119+
with cm(val):
120+
pass # pragma: no cover

trio/_timeouts.py

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import math
12
from contextlib import contextmanager
23

34
import trio
@@ -10,7 +11,12 @@ def move_on_at(deadline):
1011
Args:
1112
deadline (float): The deadline.
1213
14+
Raises:
15+
ValueError: if deadline is NaN.
16+
1317
"""
18+
if math.isnan(deadline):
19+
raise ValueError("deadline must not be NaN")
1420
return trio.CancelScope(deadline=deadline)
1521

1622

@@ -22,10 +28,9 @@ def move_on_after(seconds):
2228
seconds (float): The timeout.
2329
2430
Raises:
25-
ValueError: if timeout is less than zero.
31+
ValueError: if timeout is less than zero or NaN.
2632
2733
"""
28-
2934
if seconds < 0:
3035
raise ValueError("timeout must be non-negative")
3136
return move_on_at(trio.current_time() + seconds)
@@ -52,6 +57,9 @@ async def sleep_until(deadline):
5257
the past, in which case this function executes a checkpoint but
5358
does not block.
5459
60+
Raises:
61+
ValueError: if deadline is NaN.
62+
5563
"""
5664
with move_on_at(deadline):
5765
await sleep_forever()
@@ -65,7 +73,7 @@ async def sleep(seconds):
6573
insert a checkpoint without actually blocking.
6674
6775
Raises:
68-
ValueError: if *seconds* is negative.
76+
ValueError: if *seconds* is negative or NaN.
6977
7078
"""
7179
if seconds < 0:
@@ -96,9 +104,13 @@ def fail_at(deadline):
96104
:func:`fail_at`, then it's caught and :exc:`TooSlowError` is raised in its
97105
place.
98106
107+
Args:
108+
deadline (float): The deadline.
109+
99110
Raises:
100111
TooSlowError: if a :exc:`Cancelled` exception is raised in this scope
101112
and caught by the context manager.
113+
ValueError: if deadline is NaN.
102114
103115
"""
104116

@@ -119,10 +131,13 @@ def fail_after(seconds):
119131
it's caught and discarded. When it reaches :func:`fail_after`, then it's
120132
caught and :exc:`TooSlowError` is raised in its place.
121133
134+
Args:
135+
seconds (float): The timeout.
136+
122137
Raises:
123138
TooSlowError: if a :exc:`Cancelled` exception is raised in this scope
124139
and caught by the context manager.
125-
ValueError: if *seconds* is less than zero.
140+
ValueError: if *seconds* is less than zero or NaN.
126141
127142
"""
128143
if seconds < 0:

0 commit comments

Comments
 (0)