From 781c7662cb9835e131a1a32975ec20f60f0b6619 Mon Sep 17 00:00:00 2001 From: KotlinIsland <65446343+kotlinisland@users.noreply.github.com> Date: Thu, 5 Mar 2026 09:55:11 +1000 Subject: [PATCH] make `ExitStack`/`AsyncExitStack` not appear as abstract --- stdlib/contextlib.pyi | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/stdlib/contextlib.pyi b/stdlib/contextlib.pyi index 4ea50e5eb34c..0da5ff27b9da 100644 --- a/stdlib/contextlib.pyi +++ b/stdlib/contextlib.pyi @@ -178,9 +178,15 @@ class _BaseExitStack(Generic[_ExitT_co]): def callback(self, callback: Callable[_P, _T], /, *args: _P.args, **kwds: _P.kwargs) -> Callable[_P, _T]: ... def pop_all(self) -> Self: ... +# this class is to avoid putting `metaclass=abc.ABCMeta` on the implementations directly, as this would make them +# appear explicitly abstract to some tools. this is due to the implementations not subclassing `AbstractContextManager` +# see note on the subclasses +@type_check_only +class _BaseExitStackAbstract(_BaseExitStack[_ExitT_co], metaclass=abc.ABCMeta): ... + # In reality this is a subclass of `AbstractContextManager`; # see #7961 for why we don't do that in the stub -class ExitStack(_BaseExitStack[_ExitT_co], metaclass=abc.ABCMeta): +class ExitStack(_BaseExitStackAbstract[_ExitT_co]): def close(self) -> None: ... def __enter__(self) -> Self: ... def __exit__( @@ -194,7 +200,7 @@ _ACM_EF = TypeVar("_ACM_EF", bound=AbstractAsyncContextManager[Any, Any] | _Exit # In reality this is a subclass of `AbstractAsyncContextManager`; # see #7961 for why we don't do that in the stub -class AsyncExitStack(_BaseExitStack[_ExitT_co], metaclass=abc.ABCMeta): +class AsyncExitStack(_BaseExitStackAbstract[_ExitT_co]): async def enter_async_context(self, cm: AbstractAsyncContextManager[_T, _ExitT_co]) -> _T: ... def push_async_exit(self, exit: _ACM_EF) -> _ACM_EF: ... def push_async_callback(