Skip to content

Commit fff6ca5

Browse files
committed
Implement _SuppressedExcReturnT
1 parent ddd8434 commit fff6ca5

File tree

1 file changed

+15
-7
lines changed

1 file changed

+15
-7
lines changed

stdlib/contextlib.pyi

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ from abc import ABC, abstractmethod
55
from collections.abc import AsyncGenerator, AsyncIterator, Awaitable, Callable, Generator, Iterator
66
from types import TracebackType
77
from typing import IO, Any, Generic, Protocol, TypeVar, overload, runtime_checkable
8-
from typing_extensions import ParamSpec, Self, TypeAlias
8+
from typing_extensions import Never, ParamSpec, Self, TypeAlias
99

1010
__all__ = [
1111
"contextmanager",
@@ -32,9 +32,11 @@ _T = TypeVar("_T")
3232
_T_co = TypeVar("_T_co", covariant=True)
3333
_T_io = TypeVar("_T_io", bound=IO[str] | None)
3434
_ExitT_co = TypeVar("_ExitT_co", covariant=True, bound=bool | None, default=bool | None)
35+
_SuppressedExcReturnT = TypeVar("_SuppressedExcReturnT", Never, None, default=Never)
3536
_F = TypeVar("_F", bound=Callable[..., Any])
3637
_G_co = TypeVar("_G_co", bound=Generator[Any, Any, Any] | AsyncGenerator[Any, Any], covariant=True)
3738
_P = ParamSpec("_P")
39+
_R = TypeVar("_R")
3840

3941
_SendT_contra = TypeVar("_SendT_contra", contravariant=True, default=None)
4042
_ReturnT_co = TypeVar("_ReturnT_co", covariant=True, default=None)
@@ -64,9 +66,14 @@ class AbstractAsyncContextManager(ABC, Protocol[_T_co, _ExitT_co]): # type: ign
6466
self, exc_type: type[BaseException] | None, exc_value: BaseException | None, traceback: TracebackType | None, /
6567
) -> _ExitT_co: ...
6668

67-
class ContextDecorator:
69+
# __exit__ can suppress exceptions by returning a true value.
70+
# _SuppressedReturnT extends the decorated function's return type with
71+
# - Never, if the decorating context manager never suppresses exceptions;
72+
# - None, if the decorating context manager may suppress exceptions.
73+
# See #13512.
74+
class ContextDecorator(Generic[_SuppressedExcReturnT]):
6875
def _recreate_cm(self) -> Self: ...
69-
def __call__(self, func: _F) -> _F: ...
76+
def __call__(self, func: Callable[_P, _R]) -> Callable[_P, _R | _SuppressedExcReturnT]: ...
7077

7178
class _GeneratorContextManagerBase(Generic[_G_co]):
7279
# Ideally this would use ParamSpec, but that requires (*args, **kwargs), which this isn't. see #6676
@@ -79,7 +86,7 @@ class _GeneratorContextManagerBase(Generic[_G_co]):
7986
class _GeneratorContextManager(
8087
_GeneratorContextManagerBase[Generator[_T_co, _SendT_contra, _ReturnT_co]],
8188
AbstractContextManager[_T_co, bool | None],
82-
ContextDecorator,
89+
ContextDecorator[None],
8390
):
8491
def __exit__(
8592
self, typ: type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None
@@ -90,14 +97,15 @@ def contextmanager(func: Callable[_P, Iterator[_T_co]]) -> Callable[_P, _Generat
9097
if sys.version_info >= (3, 10):
9198
_AF = TypeVar("_AF", bound=Callable[..., Awaitable[Any]])
9299

93-
class AsyncContextDecorator:
100+
# _SuppressedReturnT: see ContextDecorator.
101+
class AsyncContextDecorator(Generic[_SuppressedExcReturnT]):
94102
def _recreate_cm(self) -> Self: ...
95-
def __call__(self, func: _AF) -> _AF: ...
103+
def __call__(self, func: Callable[_P, _R]) -> Callable[_P, _R | _SuppressedExcReturnT]: ...
96104

97105
class _AsyncGeneratorContextManager(
98106
_GeneratorContextManagerBase[AsyncGenerator[_T_co, _SendT_contra]],
99107
AbstractAsyncContextManager[_T_co, bool | None],
100-
AsyncContextDecorator,
108+
AsyncContextDecorator[None],
101109
):
102110
async def __aexit__(
103111
self, typ: type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None

0 commit comments

Comments
 (0)