Skip to content

Commit 4edbe0c

Browse files
committed
Implement _SuppressedExcReturnT
1 parent ddd8434 commit 4edbe0c

File tree

1 file changed

+16
-8
lines changed

1 file changed

+16
-8
lines changed

stdlib/contextlib.pyi

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

1010
__all__ = [
@@ -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: ...
96-
103+
def __call__(self, func: Callable[_P, _R]) -> Callable[_P, _R | _SuppressedExcReturnT]: ...
104+
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)