From 8ec21b414b9d26eb51240ce0dbf6c872540af6fb Mon Sep 17 00:00:00 2001 From: Eneg <42005170+Enegg@users.noreply.github.com> Date: Mon, 30 Dec 2024 01:27:36 +0100 Subject: [PATCH 1/9] Fix `__exit__` of various context managers --- src/anyio/_backends/_asyncio.py | 4 ++-- src/anyio/_backends/_trio.py | 5 ++--- src/anyio/_core/_synchronization.py | 2 +- src/anyio/_core/_tasks.py | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/anyio/_backends/_asyncio.py b/src/anyio/_backends/_asyncio.py index 5a0aa936..f93af73c 100644 --- a/src/anyio/_backends/_asyncio.py +++ b/src/anyio/_backends/_asyncio.py @@ -449,7 +449,7 @@ def __exit__( exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None, - ) -> bool | None: + ) -> bool: del exc_tb if not self._active: @@ -2116,7 +2116,7 @@ def __exit__( exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None, - ) -> bool | None: + ) -> None: for sig in self._handled_signals: self._loop.remove_signal_handler(sig) return None diff --git a/src/anyio/_backends/_trio.py b/src/anyio/_backends/_trio.py index 70a0a605..c776de4a 100644 --- a/src/anyio/_backends/_trio.py +++ b/src/anyio/_backends/_trio.py @@ -132,8 +132,7 @@ def __exit__( exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None, - ) -> bool | None: - # https://github.com/python-trio/trio-typing/pull/79 + ) -> bool: return self.__original.__exit__(exc_type, exc_val, exc_tb) def cancel(self) -> None: @@ -186,7 +185,7 @@ async def __aexit__( exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None, - ) -> bool | None: + ) -> bool: try: return await self._nursery_manager.__aexit__(exc_type, exc_val, exc_tb) except BaseExceptionGroup as exc: diff --git a/src/anyio/_core/_synchronization.py b/src/anyio/_core/_synchronization.py index 7878ba66..ec774a89 100644 --- a/src/anyio/_core/_synchronization.py +++ b/src/anyio/_core/_synchronization.py @@ -728,6 +728,6 @@ def __exit__( exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None, - ) -> bool | None: + ) -> None: self._guarded = False return None diff --git a/src/anyio/_core/_tasks.py b/src/anyio/_core/_tasks.py index 2f21ea20..fe490151 100644 --- a/src/anyio/_core/_tasks.py +++ b/src/anyio/_core/_tasks.py @@ -88,7 +88,7 @@ def __exit__( exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None, - ) -> bool | None: + ) -> bool: raise NotImplementedError From c85b9a63fa4cdae2e0d9d90f9661444ea44e254f Mon Sep 17 00:00:00 2001 From: Eneg <42005170+Enegg@users.noreply.github.com> Date: Mon, 30 Dec 2024 01:40:45 +0100 Subject: [PATCH 2/9] Update changelog --- docs/versionhistory.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/versionhistory.rst b/docs/versionhistory.rst index 4901da4c..c9984f5e 100644 --- a/docs/versionhistory.rst +++ b/docs/versionhistory.rst @@ -11,6 +11,8 @@ This library adheres to `Semantic Versioning 2.0 `_. (`#836 `_; PR by @graingert) - Fixed ``AssertionError`` when using ``nest-asyncio`` (`#840 `_) +- Fixed return type annotation of various context managers' ``__exit__`` method + (`#847 `_) **4.7.0** From b94f06e444010de4090106f0dbef4f7966f18adc Mon Sep 17 00:00:00 2001 From: Eneg <42005170+Enegg@users.noreply.github.com> Date: Mon, 30 Dec 2024 02:02:05 +0100 Subject: [PATCH 3/9] Credit myself in changelog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Alex Grönholm --- docs/versionhistory.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/versionhistory.rst b/docs/versionhistory.rst index c9984f5e..da4c3a46 100644 --- a/docs/versionhistory.rst +++ b/docs/versionhistory.rst @@ -12,7 +12,7 @@ This library adheres to `Semantic Versioning 2.0 `_. - Fixed ``AssertionError`` when using ``nest-asyncio`` (`#840 `_) - Fixed return type annotation of various context managers' ``__exit__`` method - (`#847 `_) + (`#847 `_; PR by @Enegg) **4.7.0** From 436358bfa70c6d43391aa9dade111778be3c3054 Mon Sep 17 00:00:00 2001 From: Eneg <42005170+Enegg@users.noreply.github.com> Date: Mon, 30 Dec 2024 02:49:43 +0100 Subject: [PATCH 4/9] Remove returns --- src/anyio/_backends/_asyncio.py | 1 - src/anyio/_core/_synchronization.py | 1 - 2 files changed, 2 deletions(-) diff --git a/src/anyio/_backends/_asyncio.py b/src/anyio/_backends/_asyncio.py index f93af73c..f8b8bca3 100644 --- a/src/anyio/_backends/_asyncio.py +++ b/src/anyio/_backends/_asyncio.py @@ -2119,7 +2119,6 @@ def __exit__( ) -> None: for sig in self._handled_signals: self._loop.remove_signal_handler(sig) - return None def __aiter__(self) -> _SignalReceiver: return self diff --git a/src/anyio/_core/_synchronization.py b/src/anyio/_core/_synchronization.py index ec774a89..a6331328 100644 --- a/src/anyio/_core/_synchronization.py +++ b/src/anyio/_core/_synchronization.py @@ -730,4 +730,3 @@ def __exit__( exc_tb: TracebackType | None, ) -> None: self._guarded = False - return None From 9e6bb2afcdeb084828c82bb4012960ff5f858fcc Mon Sep 17 00:00:00 2001 From: Eneg <42005170+Enegg@users.noreply.github.com> Date: Wed, 1 Jan 2025 20:12:15 +0100 Subject: [PATCH 5/9] Revert `bool | None` on CancelScope --- src/anyio/_backends/_asyncio.py | 4 ++-- src/anyio/_backends/_trio.py | 5 +++-- src/anyio/_core/_tasks.py | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/anyio/_backends/_asyncio.py b/src/anyio/_backends/_asyncio.py index f8b8bca3..4fe66b7e 100644 --- a/src/anyio/_backends/_asyncio.py +++ b/src/anyio/_backends/_asyncio.py @@ -449,7 +449,7 @@ def __exit__( exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None, - ) -> bool: + ) -> bool | None: del exc_tb if not self._active: @@ -485,7 +485,7 @@ def __exit__( # scope if necessary self._restart_cancellation_in_parent() - # We only swallow the exception iff it was an AnyIO CancelledError, either + # We only swallow the exception if it was an AnyIO CancelledError, either # directly as exc_val or inside an exception group and there are no cancelled # parent cancel scopes visible to us here if self._cancel_called and not self._parent_cancellation_is_visible_to_us: diff --git a/src/anyio/_backends/_trio.py b/src/anyio/_backends/_trio.py index c776de4a..7c46f0d4 100644 --- a/src/anyio/_backends/_trio.py +++ b/src/anyio/_backends/_trio.py @@ -132,7 +132,7 @@ def __exit__( exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None, - ) -> bool: + ) -> bool | None: return self.__original.__exit__(exc_type, exc_val, exc_tb) def cancel(self) -> None: @@ -187,7 +187,8 @@ async def __aexit__( exc_tb: TracebackType | None, ) -> bool: try: - return await self._nursery_manager.__aexit__(exc_type, exc_val, exc_tb) + # trio.Nursery.__exit__ returns bool; .open_nursery has wrong type + return await self._nursery_manager.__aexit__(exc_type, exc_val, exc_tb) # type: ignore[return-value] except BaseExceptionGroup as exc: if not exc.split(trio.Cancelled)[1]: raise trio.Cancelled._create() from exc diff --git a/src/anyio/_core/_tasks.py b/src/anyio/_core/_tasks.py index fe490151..2f21ea20 100644 --- a/src/anyio/_core/_tasks.py +++ b/src/anyio/_core/_tasks.py @@ -88,7 +88,7 @@ def __exit__( exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None, - ) -> bool: + ) -> bool | None: raise NotImplementedError From dc82e5018c0f0237dbac4a81916c3f4c1d6f0731 Mon Sep 17 00:00:00 2001 From: Eneg <42005170+Enegg@users.noreply.github.com> Date: Wed, 1 Jan 2025 22:40:24 +0100 Subject: [PATCH 6/9] Undo comment change --- src/anyio/_backends/_asyncio.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/anyio/_backends/_asyncio.py b/src/anyio/_backends/_asyncio.py index 4fe66b7e..c20d9860 100644 --- a/src/anyio/_backends/_asyncio.py +++ b/src/anyio/_backends/_asyncio.py @@ -485,7 +485,7 @@ def __exit__( # scope if necessary self._restart_cancellation_in_parent() - # We only swallow the exception if it was an AnyIO CancelledError, either + # We only swallow the exception iff it was an AnyIO CancelledError, either # directly as exc_val or inside an exception group and there are no cancelled # parent cancel scopes visible to us here if self._cancel_called and not self._parent_cancellation_is_visible_to_us: From 064224c82801243cfd9584fadb649ba44aefe877 Mon Sep 17 00:00:00 2001 From: Eneg <42005170+Enegg@users.noreply.github.com> Date: Thu, 2 Jan 2025 01:08:51 +0100 Subject: [PATCH 7/9] Redo changes --- src/anyio/_backends/_asyncio.py | 2 +- src/anyio/_backends/_trio.py | 2 +- src/anyio/_core/_tasks.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/anyio/_backends/_asyncio.py b/src/anyio/_backends/_asyncio.py index c20d9860..f8b8bca3 100644 --- a/src/anyio/_backends/_asyncio.py +++ b/src/anyio/_backends/_asyncio.py @@ -449,7 +449,7 @@ def __exit__( exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None, - ) -> bool | None: + ) -> bool: del exc_tb if not self._active: diff --git a/src/anyio/_backends/_trio.py b/src/anyio/_backends/_trio.py index 7c46f0d4..32ae8ace 100644 --- a/src/anyio/_backends/_trio.py +++ b/src/anyio/_backends/_trio.py @@ -132,7 +132,7 @@ def __exit__( exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None, - ) -> bool | None: + ) -> bool: return self.__original.__exit__(exc_type, exc_val, exc_tb) def cancel(self) -> None: diff --git a/src/anyio/_core/_tasks.py b/src/anyio/_core/_tasks.py index 2f21ea20..fe490151 100644 --- a/src/anyio/_core/_tasks.py +++ b/src/anyio/_core/_tasks.py @@ -88,7 +88,7 @@ def __exit__( exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None, - ) -> bool | None: + ) -> bool: raise NotImplementedError From e5c43c47797c9318c6279f739610e51900b1e4a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Gr=C3=B6nholm?= Date: Thu, 2 Jan 2025 15:48:05 +0200 Subject: [PATCH 8/9] Fixed implicit return in test_shielding_mutate() --- tests/test_taskgroups.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_taskgroups.py b/tests/test_taskgroups.py index d20565c1..bae3ca40 100644 --- a/tests/test_taskgroups.py +++ b/tests/test_taskgroups.py @@ -853,7 +853,8 @@ async def task(task_status: TaskStatus) -> NoReturn: completed = True scope.shield = False await sleep(1) - pytest.fail("Execution should not reach this point") + + pytest.fail("Execution should not reach this point") async with create_task_group() as tg: await tg.start(task) From 2c9c79e701c74209b826b2207476c9d8bc3b7f67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Gr=C3=B6nholm?= Date: Thu, 2 Jan 2025 20:16:15 +0200 Subject: [PATCH 9/9] Added type ignore comments to cover the remaining mypy errors --- src/anyio/_backends/_asyncio.py | 4 ++-- src/anyio/to_process.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/anyio/_backends/_asyncio.py b/src/anyio/_backends/_asyncio.py index f8b8bca3..11582529 100644 --- a/src/anyio/_backends/_asyncio.py +++ b/src/anyio/_backends/_asyncio.py @@ -2447,7 +2447,7 @@ def create_capacity_limiter(cls, total_tokens: float) -> abc.CapacityLimiter: return CapacityLimiter(total_tokens) @classmethod - async def run_sync_in_worker_thread( + async def run_sync_in_worker_thread( # type: ignore[return] cls, func: Callable[[Unpack[PosArgsT]], T_Retval], args: tuple[Unpack[PosArgsT]], @@ -2469,7 +2469,7 @@ async def run_sync_in_worker_thread( async with limiter or cls.current_default_thread_limiter(): with CancelScope(shield=not abandon_on_cancel) as scope: - future: asyncio.Future = asyncio.Future() + future = asyncio.Future[T_Retval]() root_task = find_root_task() if not idle_workers: worker = WorkerThread(root_task, workers, idle_workers) diff --git a/src/anyio/to_process.py b/src/anyio/to_process.py index 5050dee2..495de2ae 100644 --- a/src/anyio/to_process.py +++ b/src/anyio/to_process.py @@ -35,7 +35,7 @@ _default_process_limiter: RunVar[CapacityLimiter] = RunVar("_default_process_limiter") -async def run_sync( +async def run_sync( # type: ignore[return] func: Callable[[Unpack[PosArgsT]], T_Retval], *args: Unpack[PosArgsT], cancellable: bool = False,