@@ -80,6 +80,22 @@ def inner(*args, **kwds):
8080 return inner
8181
8282
83+ class AsyncContextDecorator (object ):
84+ "A base class or mixin that enables async context managers to work as decorators."
85+
86+ def _recreate_cm (self ):
87+ """Return a recreated instance of self.
88+ """
89+ return self
90+
91+ def __call__ (self , func ):
92+ @wraps (func )
93+ async def inner (* args , ** kwds ):
94+ async with self ._recreate_cm ():
95+ return await func (* args , ** kwds )
96+ return inner
97+
98+
8399class _GeneratorContextManagerBase :
84100 """Shared functionality for @contextmanager and @asynccontextmanager."""
85101
@@ -167,9 +183,16 @@ def __exit__(self, type, value, traceback):
167183
168184
169185class _AsyncGeneratorContextManager (_GeneratorContextManagerBase ,
170- AbstractAsyncContextManager ):
186+ AbstractAsyncContextManager ,
187+ AsyncContextDecorator ):
171188 """Helper for @asynccontextmanager."""
172189
190+ def _recreate_cm (self ):
191+ # _AGCM instances are one-shot context managers, so the
192+ # ACM must be recreated each time a decorated function is
193+ # called
194+ return self .__class__ (self .func , self .args , self .kwds )
195+
173196 async def __aenter__ (self ):
174197 try :
175198 return await self .gen .__anext__ ()
0 commit comments