summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2022-08-04 14:50:54 (GMT)
committerGitHub <noreply@github.com>2022-08-04 14:50:54 (GMT)
commit2d84fe59c0a8bba689d79cefa7110970dd781d46 (patch)
tree1b7d617b72b1c83e7e7b30c5fedacab07588c775
parentf2926358d1cd70625222eaf4b541584d2f2a1272 (diff)
downloadcpython-2d84fe59c0a8bba689d79cefa7110970dd781d46.zip
cpython-2d84fe59c0a8bba689d79cefa7110970dd781d46.tar.gz
cpython-2d84fe59c0a8bba689d79cefa7110970dd781d46.tar.bz2
GH-95289: Always call uncancel() when parent cancellation is requested (GH-95602)
Co-authored-by: Guido van Rossum <guido@python.org> (cherry picked from commit 2fef27589e44c91042c2598b5cad6c6ad0516d93) Co-authored-by: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com>
-rw-r--r--Lib/asyncio/taskgroups.py17
-rw-r--r--Lib/test/test_asyncio/test_taskgroups.py33
-rw-r--r--Misc/NEWS.d/next/Library/2022-08-03-16-52-32.gh-issue-95289.FMnHlV.rst1
3 files changed, 42 insertions, 9 deletions
diff --git a/Lib/asyncio/taskgroups.py b/Lib/asyncio/taskgroups.py
index 3ca6506..097b486 100644
--- a/Lib/asyncio/taskgroups.py
+++ b/Lib/asyncio/taskgroups.py
@@ -54,21 +54,22 @@ class TaskGroup:
async def __aexit__(self, et, exc, tb):
self._exiting = True
- propagate_cancellation_error = None
if (exc is not None and
self._is_base_error(exc) and
self._base_error is None):
self._base_error = exc
- if et is not None:
- if et is exceptions.CancelledError:
- if self._parent_cancel_requested and not self._parent_task.uncancel():
- # Do nothing, i.e. swallow the error.
- pass
- else:
- propagate_cancellation_error = exc
+ propagate_cancellation_error = \
+ exc if et is exceptions.CancelledError else None
+ if self._parent_cancel_requested:
+ # If this flag is set we *must* call uncancel().
+ if self._parent_task.uncancel() == 0:
+ # If there are no pending cancellations left,
+ # don't propagate CancelledError.
+ propagate_cancellation_error = None
+ if et is not None:
if not self._aborting:
# Our parent task is being cancelled:
#
diff --git a/Lib/test/test_asyncio/test_taskgroups.py b/Lib/test/test_asyncio/test_taskgroups.py
index 26fb5e4..99498e7 100644
--- a/Lib/test/test_asyncio/test_taskgroups.py
+++ b/Lib/test/test_asyncio/test_taskgroups.py
@@ -3,7 +3,7 @@
import asyncio
import contextvars
-
+import contextlib
from asyncio import taskgroups
import unittest
@@ -741,6 +741,37 @@ class TestTaskGroup(unittest.IsolatedAsyncioTestCase):
self.assertEqual(get_error_types(cm.exception), {ZeroDivisionError})
+ async def test_taskgroup_context_manager_exit_raises(self):
+ # See https://github.com/python/cpython/issues/95289
+ class CustomException(Exception):
+ pass
+
+ async def raise_exc():
+ raise CustomException
+
+ @contextlib.asynccontextmanager
+ async def database():
+ try:
+ yield
+ finally:
+ raise CustomException
+
+ async def main():
+ task = asyncio.current_task()
+ try:
+ async with taskgroups.TaskGroup() as tg:
+ async with database():
+ tg.create_task(raise_exc())
+ await asyncio.sleep(1)
+ except* CustomException as err:
+ self.assertEqual(task.cancelling(), 0)
+ self.assertEqual(len(err.exceptions), 2)
+
+ else:
+ self.fail('CustomException not raised')
+
+ await asyncio.create_task(main())
+
if __name__ == "__main__":
unittest.main()
diff --git a/Misc/NEWS.d/next/Library/2022-08-03-16-52-32.gh-issue-95289.FMnHlV.rst b/Misc/NEWS.d/next/Library/2022-08-03-16-52-32.gh-issue-95289.FMnHlV.rst
new file mode 100644
index 0000000..d802f55
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-08-03-16-52-32.gh-issue-95289.FMnHlV.rst
@@ -0,0 +1 @@
+Fix :class:`asyncio.TaskGroup` to propagate exception when :exc:`asyncio.CancelledError` was replaced with another exception by a context manger. Patch by Kumar Aditya and Guido van Rossum.