66from functools import wraps
77
88__all__ = ["asynccontextmanager" , "contextmanager" , "closing" , "nullcontext" ,
9- "AbstractContextManager" , "ContextDecorator" , "ExitStack" ,
9+ "AbstractContextManager" , "AbstractAsyncContextManager" ,
10+ "ContextDecorator" , "ExitStack" ,
1011 "redirect_stdout" , "redirect_stderr" , "suppress" ]
1112
1213
@@ -30,6 +31,27 @@ def __subclasshook__(cls, C):
3031 return NotImplemented
3132
3233
34+ class AbstractAsyncContextManager (abc .ABC ):
35+
36+ """An abstract base class for asynchronous context managers."""
37+
38+ async def __aenter__ (self ):
39+ """Return `self` upon entering the runtime context."""
40+ return self
41+
42+ @abc .abstractmethod
43+ async def __aexit__ (self , exc_type , exc_value , traceback ):
44+ """Raise any exception triggered within the runtime context."""
45+ return None
46+
47+ @classmethod
48+ def __subclasshook__ (cls , C ):
49+ if cls is AbstractAsyncContextManager :
50+ return _collections_abc ._check_methods (C , "__aenter__" ,
51+ "__aexit__" )
52+ return NotImplemented
53+
54+
3355class ContextDecorator (object ):
3456 "A base class or mixin that enables context managers to work as decorators."
3557
@@ -136,7 +158,8 @@ def __exit__(self, type, value, traceback):
136158 raise RuntimeError ("generator didn't stop after throw()" )
137159
138160
139- class _AsyncGeneratorContextManager (_GeneratorContextManagerBase ):
161+ class _AsyncGeneratorContextManager (_GeneratorContextManagerBase ,
162+ AbstractAsyncContextManager ):
140163 """Helper for @asynccontextmanager."""
141164
142165 async def __aenter__ (self ):
0 commit comments