From: Federico Caselli Date: Tue, 13 Sep 2022 19:23:12 +0000 (+0200) Subject: Improved usage of ``asyncio.shield()`` X-Git-Tag: rel_1_4_42~29^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f1ff837f84d7dc405ad23ad010912bceae0727bc;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Improved usage of ``asyncio.shield()`` Fixes: #8516 Change-Id: Ifd8f5e5f42d9fbcd5b8d00bddc81ff6be690a75e (cherry picked from commit e2e85de93daef31c75d397251cee2fbee7a5de65) --- diff --git a/doc/build/changelog/unreleased_14/8516.rst b/doc/build/changelog/unreleased_14/8516.rst new file mode 100644 index 0000000000..2f83586e2a --- /dev/null +++ b/doc/build/changelog/unreleased_14/8516.rst @@ -0,0 +1,9 @@ +.. change:: + :tags: bug, asyncio + :tickets: 8516 + + Improved implementation of ``asyncio.shield()`` used in context managers as + added in :ticket:`8145`, such that the "close" operation is enclosed within + an ``asyncio.Task`` which is then strongly referenced as the operation + proceeds. This is per Python documentation indicating that the task is + otherwise not strongly referenced. diff --git a/lib/sqlalchemy/ext/asyncio/base.py b/lib/sqlalchemy/ext/asyncio/base.py index 3f77f55007..ae100ecf5f 100644 --- a/lib/sqlalchemy/ext/asyncio/base.py +++ b/lib/sqlalchemy/ext/asyncio/base.py @@ -1,3 +1,9 @@ +# ext/asyncio/base.py +# Copyright (C) 2020-2022 the SQLAlchemy authors and contributors +# +# +# This module is part of SQLAlchemy and is released under +# the MIT License: https://www.opensource.org/licenses/mit-license.php import abc import functools import weakref diff --git a/lib/sqlalchemy/ext/asyncio/engine.py b/lib/sqlalchemy/ext/asyncio/engine.py index 4fbe4f7a59..5bfda15070 100644 --- a/lib/sqlalchemy/ext/asyncio/engine.py +++ b/lib/sqlalchemy/ext/asyncio/engine.py @@ -551,7 +551,8 @@ class AsyncConnection(ProxyComparable, StartableContext, AsyncConnectable): return self.start().__await__() async def __aexit__(self, type_, value, traceback): - await asyncio.shield(self.close()) + task = asyncio.create_task(self.close()) + await asyncio.shield(task) @util.create_proxy_methods( @@ -606,7 +607,8 @@ class AsyncEngine(ProxyComparable, AsyncConnectable): await self.transaction.__aexit__(type_, value, traceback) await self.conn.close() - await asyncio.shield(go()) + task = asyncio.create_task(go()) + await asyncio.shield(task) def __init__(self, sync_engine): if not sync_engine.dialect.is_async: diff --git a/lib/sqlalchemy/ext/asyncio/session.py b/lib/sqlalchemy/ext/asyncio/session.py index 378cbcbf2f..7346840579 100644 --- a/lib/sqlalchemy/ext/asyncio/session.py +++ b/lib/sqlalchemy/ext/asyncio/session.py @@ -4,7 +4,6 @@ # # This module is part of SQLAlchemy and is released under # the MIT License: https://www.opensource.org/licenses/mit-license.php - import asyncio from . import engine @@ -628,7 +627,8 @@ class AsyncSession(ReversibleProxy): return self async def __aexit__(self, type_, value, traceback): - await asyncio.shield(self.close()) + task = asyncio.create_task(self.close()) + await asyncio.shield(task) def _maker_context_manager(self): # no @contextlib.asynccontextmanager until python3.7, gr @@ -649,7 +649,8 @@ class _AsyncSessionContextManager: await self.trans.__aexit__(type_, value, traceback) await self.async_session.__aexit__(type_, value, traceback) - await asyncio.shield(go()) + task = asyncio.create_task(go()) + await asyncio.shield(task) class AsyncSessionTransaction(ReversibleProxy, StartableContext):