From 11601f1fa95186a6865d7e93b1e99fe131928e1d Mon Sep 17 00:00:00 2001 From: Eitan Date: Tue, 17 Feb 2026 12:59:53 +0200 Subject: [PATCH 1/5] Make TaskGroup.__aexit__ return Literal[False] Defining TaskGroup.__aexit__ explicitly always return False allows type checkers to safely assume that all code inside of it ran to completion without swallowing exceptions. This in turn prevents type errors about variables defined inside the `async with` block being possibly undefined. --- asyncer/_main.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/asyncer/_main.py b/asyncer/_main.py index 6056a108..137fc09b 100644 --- a/asyncer/_main.py +++ b/asyncer/_main.py @@ -2,10 +2,12 @@ import sys from collections.abc import Awaitable, Coroutine from importlib import import_module +from types import TracebackType from typing import ( Any, Callable, Generic, + Literal, Optional, TypeVar, Union, @@ -177,6 +179,15 @@ async def __aenter__(self) -> "TaskGroup": # pragma: nocover """Enter the task group context and allow starting new tasks.""" return await super().__aenter__() # type: ignore + # This is only for the return type annotation, but it won't really be called + async def __aexit__(self, + exc_type: Optional[type[BaseException]], + exc_value: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> Literal[False]: # pragma: nocover + """Exit the task group context once all tasks are completed.""" + return await super().__aexit__(exc_type, exc_value, exc_tb) + def create_task_group() -> "TaskGroup": """ From 95bc591b6aa33a48181e2b715a7f7342c6f33ffd Mon Sep 17 00:00:00 2001 From: "pre-commit-ci-lite[bot]" <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Date: Tue, 17 Feb 2026 11:02:20 +0000 Subject: [PATCH 2/5] =?UTF-8?q?=F0=9F=8E=A8=20Auto=20format?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- asyncer/_main.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/asyncer/_main.py b/asyncer/_main.py index 137fc09b..7e8cf439 100644 --- a/asyncer/_main.py +++ b/asyncer/_main.py @@ -180,7 +180,8 @@ async def __aenter__(self) -> "TaskGroup": # pragma: nocover return await super().__aenter__() # type: ignore # This is only for the return type annotation, but it won't really be called - async def __aexit__(self, + async def __aexit__( + self, exc_type: Optional[type[BaseException]], exc_value: Optional[BaseException], exc_tb: Optional[TracebackType], From cf97758ab5a45422be63a9ed0a0672e37de2c0b5 Mon Sep 17 00:00:00 2001 From: Eitan Date: Tue, 17 Feb 2026 13:08:19 +0200 Subject: [PATCH 3/5] Add type: ignore --- asyncer/_main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/asyncer/_main.py b/asyncer/_main.py index 7e8cf439..c099689f 100644 --- a/asyncer/_main.py +++ b/asyncer/_main.py @@ -187,7 +187,7 @@ async def __aexit__( exc_tb: Optional[TracebackType], ) -> Literal[False]: # pragma: nocover """Exit the task group context once all tasks are completed.""" - return await super().__aexit__(exc_type, exc_value, exc_tb) + return await super().__aexit__(exc_type, exc_value, exc_tb) # type: ignore def create_task_group() -> "TaskGroup": From 4486bbf49afe1498b294609195371d7c4c2877e0 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci-lite[bot]" <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Date: Sun, 22 Feb 2026 07:35:34 +0000 Subject: [PATCH 4/5] =?UTF-8?q?=F0=9F=8E=A8=20Auto=20format?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- asyncer/_main.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/asyncer/_main.py b/asyncer/_main.py index 9effd689..c00788a0 100644 --- a/asyncer/_main.py +++ b/asyncer/_main.py @@ -7,7 +7,6 @@ Any, Generic, Literal, - Optional, ParamSpec, TypeVar, ) @@ -175,9 +174,9 @@ async def __aenter__(self) -> "TaskGroup": # pragma: nocover # This is only for the return type annotation, but it won't really be called async def __aexit__( self, - exc_type: Optional[type[BaseException]], - exc_value: Optional[BaseException], - exc_tb: Optional[TracebackType], + exc_type: type[BaseException] | None, + exc_value: BaseException | None, + exc_tb: TracebackType | None, ) -> Literal[False]: # pragma: nocover """Exit the task group context once all tasks are completed.""" return await super().__aexit__(exc_type, exc_value, exc_tb) # type: ignore From ff57904a5b408c948f7f512db7dba46005efe1a2 Mon Sep 17 00:00:00 2001 From: Eitan Date: Wed, 20 May 2026 15:22:22 +0300 Subject: [PATCH 5/5] Fix signature mismatch --- asyncer/_main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/asyncer/_main.py b/asyncer/_main.py index f0672880..067ea7a5 100644 --- a/asyncer/_main.py +++ b/asyncer/_main.py @@ -175,11 +175,11 @@ async def __aenter__(self) -> "TaskGroup": # pragma: nocover async def __aexit__( self, exc_type: type[BaseException] | None, - exc_value: BaseException | None, + exc_val: BaseException | None, exc_tb: TracebackType | None, ) -> Literal[False]: # pragma: nocover """Exit the task group context once all tasks are completed.""" - return await super().__aexit__(exc_type, exc_value, exc_tb) # type: ignore + return await super().__aexit__(exc_type, exc_val, exc_tb) # type: ignore def create_task_group() -> "TaskGroup":