Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpo-40816 Add AsyncContextDecorator class #20516

Merged
merged 12 commits into from
Nov 5, 2020
Next Next commit
Add basic AsyncContextDecorator implementation
  • Loading branch information
heckad committed May 29, 2020
commit db99d4a562bacab013c664e5419eccc5020fe40a
25 changes: 24 additions & 1 deletion Lib/contextlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,22 @@ def inner(*args, **kwds):
return inner


class AsyncContextDecorator(object):
"A base class or mixin that enables async context managers to work as decorators."

def __recreate_cm(self):
heckad marked this conversation as resolved.
Show resolved Hide resolved
"""Return a recreated instance of self.
"""
return self

def __call__(self, func):
@wraps(func)
def inner(*args, **kwds):
async with self._recreate_cm():
return await func(*args, **kwds)
return inner


class _GeneratorContextManagerBase:
"""Shared functionality for @contextmanager and @asynccontextmanager."""

Expand Down Expand Up @@ -167,9 +183,16 @@ def __exit__(self, type, value, traceback):


class _AsyncGeneratorContextManager(_GeneratorContextManagerBase,
AbstractAsyncContextManager):
AbstractAsyncContextManager,
AsyncContextDecorator):
"""Helper for @asynccontextmanager."""

def _recreate_cm(self):
# _AGCM instances are one-shot context managers, so the
# ACM must be recreated each time a decorated function is
# called
return self.__class__(self.func, self.args, self.kwds)

async def __aenter__(self):
try:
return await self.gen.__anext__()
Expand Down