@@ -5,7 +5,7 @@ from abc import ABC, abstractmethod
5
5
from collections .abc import AsyncGenerator , AsyncIterator , Awaitable , Callable , Generator , Iterator
6
6
from types import TracebackType
7
7
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
9
9
10
10
__all__ = [
11
11
"contextmanager" ,
@@ -32,9 +32,11 @@ _T = TypeVar("_T")
32
32
_T_co = TypeVar ("_T_co" , covariant = True )
33
33
_T_io = TypeVar ("_T_io" , bound = IO [str ] | None )
34
34
_ExitT_co = TypeVar ("_ExitT_co" , covariant = True , bound = bool | None , default = bool | None )
35
+ _SuppressedExcReturnT = TypeVar ("_SuppressedExcReturnT" , Never , None , default = Never )
35
36
_F = TypeVar ("_F" , bound = Callable [..., Any ])
36
37
_G_co = TypeVar ("_G_co" , bound = Generator [Any , Any , Any ] | AsyncGenerator [Any , Any ], covariant = True )
37
38
_P = ParamSpec ("_P" )
39
+ _R = TypeVar ("_R" )
38
40
39
41
_SendT_contra = TypeVar ("_SendT_contra" , contravariant = True , default = None )
40
42
_ReturnT_co = TypeVar ("_ReturnT_co" , covariant = True , default = None )
@@ -64,9 +66,14 @@ class AbstractAsyncContextManager(ABC, Protocol[_T_co, _ExitT_co]): # type: ign
64
66
self , exc_type : type [BaseException ] | None , exc_value : BaseException | None , traceback : TracebackType | None , /
65
67
) -> _ExitT_co : ...
66
68
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 ]):
68
75
def _recreate_cm (self ) -> Self : ...
69
- def __call__ (self , func : _F ) -> _F : ...
76
+ def __call__ (self , func : Callable [ _P , _R ] ) -> Callable [ _P , _R | _SuppressedExcReturnT ] : ...
70
77
71
78
class _GeneratorContextManagerBase (Generic [_G_co ]):
72
79
# 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]):
79
86
class _GeneratorContextManager (
80
87
_GeneratorContextManagerBase [Generator [_T_co , _SendT_contra , _ReturnT_co ]],
81
88
AbstractContextManager [_T_co , bool | None ],
82
- ContextDecorator ,
89
+ ContextDecorator [ None ] ,
83
90
):
84
91
def __exit__ (
85
92
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
90
97
if sys .version_info >= (3 , 10 ):
91
98
_AF = TypeVar ("_AF" , bound = Callable [..., Awaitable [Any ]])
92
99
93
- class AsyncContextDecorator :
100
+ # _SuppressedReturnT: see ContextDecorator.
101
+ class AsyncContextDecorator (Generic [_SuppressedExcReturnT ]):
94
102
def _recreate_cm (self ) -> Self : ...
95
- def __call__ (self , func : _AF ) -> _AF : ...
103
+ def __call__ (self , func : Callable [ _P , _R ] ) -> Callable [ _P , _R | _SuppressedExcReturnT ] : ...
96
104
97
105
class _AsyncGeneratorContextManager (
98
106
_GeneratorContextManagerBase [AsyncGenerator [_T_co , _SendT_contra ]],
99
107
AbstractAsyncContextManager [_T_co , bool | None ],
100
- AsyncContextDecorator ,
108
+ AsyncContextDecorator [ None ] ,
101
109
):
102
110
async def __aexit__ (
103
111
self , typ : type [BaseException ] | None , value : BaseException | None , traceback : TracebackType | None
0 commit comments