diff options
| author | shadchin <[email protected]> | 2022-04-18 12:39:32 +0300 |
|---|---|---|
| committer | shadchin <[email protected]> | 2022-04-18 12:39:32 +0300 |
| commit | d4be68e361f4258cf0848fc70018dfe37a2acc24 (patch) | |
| tree | 153e294cd97ac8b5d7a989612704a0c1f58e8ad4 /contrib/tools/python3/src/Lib/contextlib.py | |
| parent | 260c02f5ccf242d9d9b8a873afaf6588c00237d6 (diff) | |
IGNIETFERRO-1816 Update Python 3 from 3.9.12 to 3.10.4
ref:9f96be6d02ee8044fdd6f124b799b270c20ce641
Diffstat (limited to 'contrib/tools/python3/src/Lib/contextlib.py')
| -rw-r--r-- | contrib/tools/python3/src/Lib/contextlib.py | 64 |
1 files changed, 57 insertions, 7 deletions
diff --git a/contrib/tools/python3/src/Lib/contextlib.py b/contrib/tools/python3/src/Lib/contextlib.py index 4e8f5f75939..c63a8492e2d 100644 --- a/contrib/tools/python3/src/Lib/contextlib.py +++ b/contrib/tools/python3/src/Lib/contextlib.py @@ -9,7 +9,7 @@ from types import MethodType, GenericAlias __all__ = ["asynccontextmanager", "contextmanager", "closing", "nullcontext", "AbstractContextManager", "AbstractAsyncContextManager", "AsyncExitStack", "ContextDecorator", "ExitStack", - "redirect_stdout", "redirect_stderr", "suppress"] + "redirect_stdout", "redirect_stderr", "suppress", "aclosing"] class AbstractContextManager(abc.ABC): @@ -80,6 +80,22 @@ class ContextDecorator(object): return inner +class AsyncContextDecorator(object): + "A base class or mixin that enables async context managers to work as decorators." + + def _recreate_cm(self): + """Return a recreated instance of self. + """ + return self + + def __call__(self, func): + @wraps(func) + async def inner(*args, **kwds): + async with self._recreate_cm(): + return await func(*args, **kwds) + return inner + + class _GeneratorContextManagerBase: """Shared functionality for @contextmanager and @asynccontextmanager.""" @@ -168,9 +184,11 @@ class _GeneratorContextManager( return False raise RuntimeError("generator didn't stop after throw()") - -class _AsyncGeneratorContextManager(_GeneratorContextManagerBase, - AbstractAsyncContextManager): +class _AsyncGeneratorContextManager( + _GeneratorContextManagerBase, + AbstractAsyncContextManager, + AsyncContextDecorator, +): """Helper for @asynccontextmanager decorator.""" async def __aenter__(self): @@ -178,14 +196,14 @@ class _AsyncGeneratorContextManager(_GeneratorContextManagerBase, # they are only needed for recreation, which is not possible anymore del self.args, self.kwds, self.func try: - return await self.gen.__anext__() + return await anext(self.gen) except StopAsyncIteration: raise RuntimeError("generator didn't yield") from None async def __aexit__(self, typ, value, traceback): if typ is None: try: - await self.gen.__anext__() + await anext(self.gen) except StopAsyncIteration: return False else: @@ -322,6 +340,32 @@ class closing(AbstractContextManager): self.thing.close() +class aclosing(AbstractAsyncContextManager): + """Async context manager for safely finalizing an asynchronously cleaned-up + resource such as an async generator, calling its ``aclose()`` method. + + Code like this: + + async with aclosing(<module>.fetch(<arguments>)) as agen: + <block> + + is equivalent to this: + + agen = <module>.fetch(<arguments>) + try: + <block> + finally: + await agen.aclose() + + """ + def __init__(self, thing): + self.thing = thing + async def __aenter__(self): + return self.thing + async def __aexit__(self, *exc_info): + await self.thing.aclose() + + class _RedirectStream(AbstractContextManager): _stream = None @@ -674,7 +718,7 @@ class AsyncExitStack(_BaseExitStack, AbstractAsyncContextManager): return received_exc and suppressed_exc -class nullcontext(AbstractContextManager): +class nullcontext(AbstractContextManager, AbstractAsyncContextManager): """Context manager that does no additional processing. Used as a stand-in for a normal context manager, when a particular @@ -693,3 +737,9 @@ class nullcontext(AbstractContextManager): def __exit__(self, *excinfo): pass + + async def __aenter__(self): + return self.enter_result + + async def __aexit__(self, *excinfo): + pass |
