Added new methods :meth:`_asyncio.AsyncConnection.aclose` as a synonym for
:meth:`_asyncio.AsyncConnection.close` and
:meth:`_asyncio.AsyncSession.aclose` as a synonym for
:meth:`_asyncio.AsyncSession.close` to the
:class:`_asyncio.AsyncConnection` and :class:`_asyncio.AsyncSession`
objects, to provide compatibility with Python standard library
``@contextlib.aclosing`` construct. Pull request courtesy Grigoriev Semyon.
Fixes: #9698
Closes: #10106
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/10106
Pull-request-sha:
9dbe87324d496323f1da4a131b4c3d485a8eea1b
Change-Id: I861d1fd4586018c2bdd6b45d7918af4f7d48d193
--- /dev/null
+.. change::
+ :tags: usecase, asyncio
+ :tickets: 9698
+
+ Added new methods :meth:`_asyncio.AsyncConnection.aclose` as a synonym for
+ :meth:`_asyncio.AsyncConnection.close` and
+ :meth:`_asyncio.AsyncSession.aclose` as a synonym for
+ :meth:`_asyncio.AsyncSession.close` to the
+ :class:`_asyncio.AsyncConnection` and :class:`_asyncio.AsyncSession`
+ objects, to provide compatibility with Python standard library
+ ``@contextlib.aclosing`` construct. Pull request courtesy Grigoriev Semyon.
"""
await greenlet_spawn(self._proxied.close)
+ async def aclose(self) -> None:
+ """A synonym for :meth:`_asyncio.AsyncConnection.close`.
+
+ The :meth:`_asyncio.AsyncConnection.aclose` name is specifically
+ to support the Python standard library ``@contextlib.aclosing``
+ context manager function.
+
+ .. versionadded:: 2.0.20
+
+ """
+ await self.close()
+
async def exec_driver_sql(
self,
statement: str,
methods=[
"__contains__",
"__iter__",
+ "aclose",
"add",
"add_all",
"begin",
return self._proxied.__iter__()
+ async def aclose(self) -> None:
+ r"""A synonym for :meth:`_asyncio.AsyncSession.close`.
+
+ .. container:: class_bases
+
+ Proxied for the :class:`_asyncio.AsyncSession` class on
+ behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
+
+ The :meth:`_asyncio.AsyncSession.aclose` name is specifically
+ to support the Python standard library ``@contextlib.aclosing``
+ context manager function.
+
+ .. versionadded:: 2.0.20
+
+
+ """ # noqa: E501
+
+ return await self._proxied.aclose()
+
def add(self, instance: object, _warn: bool = True) -> None:
r"""Place an object into this :class:`_orm.Session`.
"""
await greenlet_spawn(self.sync_session.close)
+ async def aclose(self) -> None:
+ """A synonym for :meth:`_asyncio.AsyncSession.close`.
+
+ The :meth:`_asyncio.AsyncSession.aclose` name is specifically
+ to support the Python standard library ``@contextlib.aclosing``
+ context manager function.
+
+ .. versionadded:: 2.0.20
+
+ """
+ await self.close()
+
async def invalidate(self) -> None:
"""Close this Session, using connection invalidation.
import asyncio
+import contextlib
import inspect as stdlib_inspect
from unittest.mock import patch
with expect_raises(exc.TimeoutError):
await engine.connect()
+ @testing.requires.python310
+ @async_test
+ async def test_engine_aclose(self, async_engine):
+ users = self.tables.users
+ async with contextlib.aclosing(async_engine.connect()) as conn:
+ await conn.start()
+ trans = conn.begin()
+ await trans.start()
+ await conn.execute(delete(users))
+ await trans.commit()
+ assert conn.closed
+
@testing.requires.queue_pool
@async_test
async def test_pool_exhausted_no_timeout(self, async_engine):
from __future__ import annotations
+import contextlib
from typing import List
from typing import Optional
result = await async_session.scalar(stmt)
eq_(result, 7)
+ @testing.requires.python310
+ @async_test
+ async def test_session_aclose(self, async_session):
+ User = self.classes.User
+ u = User(name="u")
+ async with contextlib.aclosing(async_session) as session:
+ session.add(u)
+ await session.commit()
+ assert async_session.sync_session.identity_map.values() == []
+
@testing.combinations(
("scalars",), ("stream_scalars",), argnames="filter_"
)