From aea9be7995fb7e5564a7a28232734397aeecf197 Mon Sep 17 00:00:00 2001 From: Francis CLAIRICIA-ROSE-CLAIRE-JOSEPHINE Date: Mon, 2 Oct 2023 07:39:11 +0200 Subject: [PATCH] [FIX] Fixed CancelScope's timeout when entering the context --- src/easynetwork_asyncio/tasks.py | 6 ++--- .../test_backend/test_asyncio_backend.py | 26 ++++++++++++++++--- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/easynetwork_asyncio/tasks.py b/src/easynetwork_asyncio/tasks.py index 80d74fbf..1154d874 100644 --- a/src/easynetwork_asyncio/tasks.py +++ b/src/easynetwork_asyncio/tasks.py @@ -160,7 +160,7 @@ def __init__(self, *, deadline: float = math.inf) -> None: self.__cancel_called: bool = False self.__cancelled_caught: bool = False self.__deadline: float = math.inf - self.__timeout_handle: asyncio.TimerHandle | None = None + self.__timeout_handle: asyncio.Handle | None = None self.reschedule(deadline) def __repr__(self) -> str: @@ -278,9 +278,9 @@ def __timeout(self) -> None: if self.__deadline != math.inf: loop = asyncio.get_running_loop() if loop.time() >= self.__deadline: - self.cancel() + self.__timeout_handle = loop.call_soon(self.cancel) else: - self.__timeout_handle = loop.call_at(self.__deadline, self.__timeout) + self.__timeout_handle = loop.call_at(self.__deadline, self.cancel) @classmethod def _current_task_scope(cls, task: asyncio.Task[Any]) -> CancelScope | None: diff --git a/tests/functional_test/test_async/test_backend/test_asyncio_backend.py b/tests/functional_test/test_async/test_backend/test_asyncio_backend.py index b90b8450..b2871cda 100644 --- a/tests/functional_test/test_async/test_backend/test_asyncio_backend.py +++ b/tests/functional_test/test_async/test_backend/test_asyncio_backend.py @@ -1240,7 +1240,6 @@ async def coroutine() -> None: await event_loop.create_task(coroutine()) - @pytest.mark.xfail(raises=asyncio.CancelledError, reason="Task.cancel() cannot be erased", strict=True) async def test____cancel_shielded_coroutine____scope_cancellation_edge_case_3( self, event_loop: asyncio.AbstractEventLoop, @@ -1255,12 +1254,13 @@ async def coroutine() -> None: await backend.coro_yield() - assert inner_scope.cancel_called() + assert not inner_scope.cancel_called() assert not inner_scope.cancelled_caught() await event_loop.create_task(coroutine()) + @pytest.mark.xfail(raises=asyncio.CancelledError, reason="Task.cancel() cannot be erased", strict=True) async def test____cancel_shielded_coroutine____scope_cancellation_edge_case_4( self, event_loop: asyncio.AbstractEventLoop, @@ -1270,6 +1270,26 @@ async def coroutine() -> None: current_task = asyncio.current_task() assert current_task is not None + with backend.open_cancel_scope() as inner_scope: + inner_scope.cancel() + + await backend.coro_yield() + + assert inner_scope.cancel_called() + + assert not inner_scope.cancelled_caught() + + await event_loop.create_task(coroutine()) + + async def test____cancel_shielded_coroutine____scope_cancellation_edge_case_5( + self, + event_loop: asyncio.AbstractEventLoop, + backend: AsyncIOBackend, + ) -> None: + async def coroutine() -> None: + current_task = asyncio.current_task() + assert current_task is not None + outer_scope = backend.open_cancel_scope() inner_scope = backend.open_cancel_scope() with outer_scope: @@ -1292,7 +1312,7 @@ async def coroutine() -> None: await event_loop.create_task(coroutine()) - async def test____cancel_shielded_coroutine____scope_cancellation_edge_case_5( + async def test____cancel_shielded_coroutine____scope_cancellation_edge_case_6( self, event_loop: asyncio.AbstractEventLoop, backend: AsyncIOBackend,