-
-
Notifications
You must be signed in to change notification settings - Fork 342
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
Nursery: don't act as a checkpoint when not running anything #1696
Changes from 2 commits
5c7e5ef
a3d9d25
3641411
e66c5a5
85f61dd
4b1c815
3907400
27ac88a
06c176c
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 |
---|---|---|
|
@@ -32,6 +32,7 @@ | |
Sequencer, | ||
assert_checkpoints, | ||
) | ||
from ...testing._checkpoints import assert_yields_or_not | ||
|
||
|
||
# slightly different from _timeouts.sleep_forever because it returns the value | ||
|
@@ -433,12 +434,12 @@ async def crasher(): | |
# nursery block exited, all cancellations inside the | ||
# nursery block continue propagating to reach the | ||
# outer scope. | ||
assert len(multi_exc.exceptions) == 5 | ||
assert len(multi_exc.exceptions) == 4 | ||
summary = {} | ||
for exc in multi_exc.exceptions: | ||
summary.setdefault(type(exc), 0) | ||
summary[type(exc)] += 1 | ||
assert summary == {_core.Cancelled: 4, KeyError: 1} | ||
assert summary == {_core.Cancelled: 3, KeyError: 1} | ||
raise | ||
except AssertionError: # pragma: no cover | ||
raise | ||
|
@@ -1605,20 +1606,15 @@ async def test_trivial_yields(): | |
await _core.checkpoint_if_cancelled() | ||
await _core.cancel_shielded_checkpoint() | ||
|
||
with assert_checkpoints(): | ||
with assert_yields_or_not(expect_cancel_point=False, expect_schedule_point=True): | ||
async with _core.open_nursery(): | ||
pass | ||
|
||
with _core.CancelScope() as cancel_scope: | ||
cancel_scope.cancel() | ||
with pytest.raises(_core.MultiError) as excinfo: | ||
with pytest.raises(KeyError): | ||
async with _core.open_nursery(): | ||
raise KeyError | ||
assert len(excinfo.value.exceptions) == 2 | ||
assert {type(e) for e in excinfo.value.exceptions} == { | ||
KeyError, | ||
_core.Cancelled, | ||
} | ||
|
||
|
||
async def test_nursery_start(autojump_clock): | ||
|
@@ -1685,13 +1681,24 @@ async def nothing(task_status=_core.TASK_STATUS_IGNORED): | |
# is ignored; start() raises Cancelled. | ||
async def just_started(task_status=_core.TASK_STATUS_IGNORED): | ||
task_status.started("hi") | ||
await _core.checkpoint() | ||
|
||
async with _core.open_nursery() as nursery: | ||
with _core.CancelScope() as cs: | ||
cs.cancel() | ||
with pytest.raises(_core.Cancelled): | ||
await nursery.start(just_started) | ||
|
||
# but if the task does not execute any checkpoints, and exits, then start() | ||
# doesn't raise Cancelled, since the task completed successfully. | ||
async def started_with_no_checkpoint(task_status=_core.TASK_STATUS_IGNORED): | ||
task_status.started("hi") | ||
|
||
async with _core.open_nursery() as nursery: | ||
with _core.CancelScope() as cs: | ||
cs.cancel() | ||
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. In the case where you cancel from inside the nursery after having started tasks with checkpoints, won't counts of expected cancels change as well or is that entirely covered by the one test change in |
||
await nursery.start(started_with_no_checkpoint) | ||
|
||
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. Some more implications here. This is because a Nursery is used in the implementation of start(). I'd argue that this is correct. |
||
# and if after the no-op started(), the child crashes, the error comes out | ||
# of start() | ||
async def raise_keyerror_after_started(task_status=_core.TASK_STATUS_IGNORED,): | ||
|
@@ -1701,12 +1708,8 @@ async def raise_keyerror_after_started(task_status=_core.TASK_STATUS_IGNORED,): | |
async with _core.open_nursery() as nursery: | ||
with _core.CancelScope() as cs: | ||
cs.cancel() | ||
with pytest.raises(_core.MultiError) as excinfo: | ||
with pytest.raises(KeyError): | ||
await nursery.start(raise_keyerror_after_started) | ||
assert {type(e) for e in excinfo.value.exceptions} == { | ||
_core.Cancelled, | ||
KeyError, | ||
} | ||
|
||
# trying to start in a closed nursery raises an error immediately | ||
async with _core.open_nursery() as closed_nursery: | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clarifying the cancelled count in a comment might be clearer here for those unfamiliar with the recent change?
Something like we only receive cancelleds from subtasks not from the nursery itself?