-
-
Notifications
You must be signed in to change notification settings - Fork 369
Change fail_after
&move_on_after
to set deadline relative to entering. Add CancelScope.relative_deadline
#3010
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 26 commits
dea2e79
d6e91cc
dc3bd3d
da25949
7a8262a
d028037
5447f45
1381560
742c013
0075b56
9d3d0b9
b29db0d
480681d
00ba1ca
510aaa1
7079d71
3474128
df5876d
a240948
0183b43
ca63354
7591297
75fc52b
5a32eb0
c2a3d8e
f8e9417
36786a6
8e863b8
6a7650d
02ac588
bf12a80
9961abc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
:func:`trio.move_on_after` and :func:`trio.fail_after` previously set the deadline relative to initialization time, instead of more intuitively upon entering the context manager. Any code where these two points in time do not line up (according to :func:`trio.current_time`) will now issue a `DeprecationWarning`. To silence the warning and adopt the new behaviour, pass ``timeout_from_enter = True``. For more information see :ref:`saved_relative_timeouts`. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
:func:`trio.move_on_after` and :func:`trio.fail_after` now allows setting the deadline to be relative to entering the context manager. This will be the default in the future, and to opt into the new behaviour you can pass ``timeout_from_enter=True``. This does not matter in the vast majority of cases where initialization and entering of the context manager is in the same place, and those cases will not raise any :class:`DeprecationWarning`. For more information see :ref:`saved_relative_timeouts`. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,9 +4,20 @@ | |
import outcome | ||
import pytest | ||
|
||
import trio | ||
|
||
from .. import _core | ||
from .._core._tests.tutil import slow | ||
from .._timeouts import * | ||
from .._timeouts import ( | ||
TooSlowError, | ||
fail_after, | ||
fail_at, | ||
move_on_after, | ||
move_on_at, | ||
sleep, | ||
sleep_forever, | ||
sleep_until, | ||
) | ||
from ..testing import assert_checkpoints | ||
|
||
T = TypeVar("T") | ||
|
@@ -169,7 +180,79 @@ | |
): | ||
with pytest.raises( | ||
ValueError, | ||
match="^(duration|deadline|timeout) must (not )*be (non-negative|NaN)$", | ||
match="^(duration|deadline|timeout|relative deadline) must (not )*be (non-negative|NaN)$", | ||
): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is a mess. For non-relative timeouts the term is always "deadline", but for relative timeouts there are multiple terms used in different parts of the code:
Using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think I'd just update the error messages to refer to the argument name in all cases, using backticks to make it clear that this is an argument name if needed (e.g. maybe for "seconds"?) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since both
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Duplicating validation logic seems least bad of these options 🤔 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is another option we could do. Given how many names this parameter has, we could just add an additional parameter to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. that sounds quite overcomplicated imo, esp since that would probably include both |
||
with cm(val): | ||
pass # pragma: no cover | ||
|
||
|
||
async def test_timeout_deadline_on_entry(mock_clock: _core.MockClock) -> None: | ||
rcs = move_on_after(5) | ||
assert rcs.relative_deadline == 5 | ||
|
||
mock_clock.jump(3) | ||
start = _core.current_time() | ||
with rcs as cs: | ||
assert cs.is_relative is None | ||
|
||
# This would previously be start+2 | ||
assert cs.deadline == start + 5 | ||
assert cs.relative_deadline == 5 | ||
|
||
cs.deadline = start + 3 | ||
assert cs.deadline == start + 3 | ||
assert cs.relative_deadline == 3 | ||
|
||
cs.relative_deadline = 4 | ||
assert cs.deadline == start + 4 | ||
assert cs.relative_deadline == 4 | ||
|
||
rcs = move_on_after(5) | ||
assert rcs.shield is False | ||
rcs.shield = True | ||
assert rcs.shield is True | ||
|
||
mock_clock.jump(3) | ||
start = _core.current_time() | ||
with rcs as cs: | ||
assert cs.deadline == start + 5 | ||
|
||
assert rcs is cs | ||
|
||
|
||
async def test_invalid_access_unentered(mock_clock: _core.MockClock) -> None: | ||
cs = move_on_after(5) | ||
mock_clock.jump(3) | ||
start = _core.current_time() | ||
|
||
match_str = "^unentered relative cancel scope does not have an absolute deadline" | ||
with pytest.warns(DeprecationWarning, match=match_str): | ||
assert cs.deadline == start + 5 | ||
mock_clock.jump(1) | ||
# this is hella sketchy, but they *have* been warned | ||
with pytest.warns(DeprecationWarning, match=match_str): | ||
assert cs.deadline == start + 6 | ||
|
||
with pytest.warns(DeprecationWarning, match=match_str): | ||
cs.deadline = 7 | ||
# now transformed into absolute | ||
assert cs.deadline == 7 | ||
assert not cs.is_relative | ||
|
||
cs = move_on_at(5) | ||
|
||
match_str = ( | ||
"^unentered non-relative cancel scope does not have a relative deadline$" | ||
) | ||
with pytest.raises(RuntimeError, match=match_str): | ||
assert cs.relative_deadline | ||
with pytest.raises(RuntimeError, match=match_str): | ||
cs.relative_deadline = 7 | ||
|
||
|
||
@pytest.mark.xfail(reason="not implemented") | ||
async def test_fail_access_before_entering() -> None: | ||
my_fail_at = fail_at(5) | ||
assert my_fail_at.deadline # type: ignore[attr-defined] | ||
my_fail_after = fail_after(5) | ||
assert my_fail_after.relative_deadline # type: ignore[attr-defined] | ||
Uh oh!
There was an error while loading. Please reload this page.