-
-
Notifications
You must be signed in to change notification settings - Fork 32.1k
gh-108951: add TaskGroup.cancel() #127214
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
base: main
Are you sure you want to change the base?
Changes from 5 commits
8ec2f60
907f1d0
2cfa1e6
bce1fb1
7754aad
452042d
f077241
8345647
7235c20
243db79
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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. copying comment from @graingert (please make all comments on the code so that there can be a thread and Resolve button)
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -997,6 +997,72 @@ class MyKeyboardInterrupt(KeyboardInterrupt): | |
self.assertIsNotNone(exc) | ||
self.assertListEqual(gc.get_referrers(exc), no_other_refs()) | ||
|
||
async def test_taskgroup_stop_children(self): | ||
belm0 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
# (asserting that TimeoutError is not raised) | ||
async with asyncio.timeout(1): | ||
async with asyncio.TaskGroup() as tg: | ||
tg.create_task(asyncio.sleep(10)) | ||
tg.create_task(asyncio.sleep(10)) | ||
await asyncio.sleep(0) | ||
tg.stop() | ||
|
||
async def test_taskgroup_stop_body(self): | ||
count = 0 | ||
async with asyncio.TaskGroup() as tg: | ||
tg.stop() | ||
count += 1 | ||
await asyncio.sleep(0) | ||
count += 1 | ||
self.assertEqual(count, 1) | ||
|
||
async def test_taskgroup_stop_idempotent(self): | ||
count = 0 | ||
async with asyncio.TaskGroup() as tg: | ||
tg.stop() | ||
tg.stop() | ||
count += 1 | ||
await asyncio.sleep(0) | ||
count += 1 | ||
self.assertEqual(count, 1) | ||
|
||
async def test_taskgroup_stop_after_exit(self): | ||
async with asyncio.TaskGroup() as tg: | ||
await asyncio.sleep(0) | ||
# (asserting that exception is not raised) | ||
tg.stop() | ||
|
||
async def test_taskgroup_stop_before_enter(self): | ||
tg = asyncio.TaskGroup() | ||
tg.stop() | ||
count = 0 | ||
async with tg: | ||
count += 1 | ||
await asyncio.sleep(0) | ||
count += 1 | ||
self.assertEqual(count, 1) | ||
|
||
async def test_taskgroup_stop_before_exception(self): | ||
async def raise_exc(parent_tg: asyncio.TaskGroup): | ||
parent_tg.stop() | ||
raise RuntimeError | ||
|
||
with self.assertRaises(ExceptionGroup): | ||
async with asyncio.TaskGroup() as tg: | ||
tg.create_task(raise_exc(tg)) | ||
await asyncio.sleep(1) | ||
|
||
async def test_taskgroup_stop_after_exception(self): | ||
async def raise_exc(parent_tg: asyncio.TaskGroup): | ||
try: | ||
raise RuntimeError | ||
finally: | ||
parent_tg.stop() | ||
|
||
with self.assertRaises(ExceptionGroup): | ||
async with asyncio.TaskGroup() as tg: | ||
tg.create_task(raise_exc(tg)) | ||
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. What will happen if some tasks cancels itself? How would this interact with 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. Do you mean the case where a child task calls 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. Cancellations (and thus taskgroup stops) happen when the next |
||
await asyncio.sleep(1) | ||
|
||
|
||
if __name__ == "__main__": | ||
unittest.main() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Add :meth:`~asyncio.TaskGroup.stop`. |
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.
These docs make sense for older versions.
Uh oh!
There was an error while loading. Please reload this page.
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.
Probably recommending a backport module on PyPI would be better
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.
These docs were just added in September, and backported to 3.13 and 3.12.
It's my understanding that the deletion here wouldn't affect the docs of previous versions.
As for this PR, I'd expected it to be backported as far back as is allowed by policy.
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.
@belm0 are you interested in applying this change and any previous changes to my taskgroup backport?
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.
This is new API, so we won't backport it.
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.
I'm talking about backporting to pypi
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.
Ah, sure. PyPI is off limits :)