bpo-40816 Add AsyncContextDecorator class (GH-20516)
Co-authored-by: Yury Selivanov <yury@edgedb.com>
diff --git a/Doc/library/contextlib.rst b/Doc/library/contextlib.rst
index e42f5a9..ee2becb 100644
--- a/Doc/library/contextlib.rst
+++ b/Doc/library/contextlib.rst
@@ -126,6 +126,31 @@
.. versionadded:: 3.7
+ Context managers defined with :func:`asynccontextmanager` can be used
+ either as decorators or with :keyword:`async with` statements::
+
+ import time
+
+ async def timeit():
+ now = time.monotonic()
+ try:
+ yield
+ finally:
+ print(f'it took {time.monotonic() - now}s to run')
+
+ @timeit()
+ async def main():
+ # ... async code ...
+
+ When used as a decorator, a new generator instance is implicitly created on
+ each function call. This allows the otherwise "one-shot" context managers
+ created by :func:`asynccontextmanager` to meet the requirement that context
+ managers support multiple invocations in order to be used as decorators.
+
+ .. versionchanged:: 3.10
+ Async context managers created with :func:`asynccontextmanager` can
+ be used as decorators.
+
.. function:: closing(thing)
@@ -384,6 +409,43 @@
.. versionadded:: 3.2
+.. class:: AsyncContextManager
+
+ Similar as ContextManger only for async
+
+ Example of ``ContextDecorator``::
+
+ from asyncio import run
+ from contextlib import AsyncContextDecorator
+
+ class mycontext(AsyncContextDecorator):
+ async def __aenter__(self):
+ print('Starting')
+ return self
+
+ async def __aexit__(self, *exc):
+ print('Finishing')
+ return False
+
+ >>> @mycontext()
+ ... async def function():
+ ... print('The bit in the middle')
+ ...
+ >>> run(function())
+ Starting
+ The bit in the middle
+ Finishing
+
+ >>> async def function():
+ ... async with mycontext():
+ ... print('The bit in the middle')
+ ...
+ >>> run(function())
+ Starting
+ The bit in the middle
+ Finishing
+
+
.. class:: ExitStack()
A context manager that is designed to make it easy to programmatically