Skip to content

Commit

Permalink
Merge "AsyncConnection[AsyncSession].aclose implementation" into main
Browse files Browse the repository at this point in the history
  • Loading branch information
zzzeek authored and Gerrit Code Review committed Aug 1, 2023
2 parents 7c26d90 + a1e8a26 commit 581338f
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 0 deletions.
11 changes: 11 additions & 0 deletions doc/build/changelog/unreleased_20/9698.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.. 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.
12 changes: 12 additions & 0 deletions lib/sqlalchemy/ext/asyncio/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,18 @@ async def close(self) -> None:
"""
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,
Expand Down
20 changes: 20 additions & 0 deletions lib/sqlalchemy/ext/asyncio/scoping.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
methods=[
"__contains__",
"__iter__",
"aclose",
"add",
"add_all",
"begin",
Expand Down Expand Up @@ -300,6 +301,25 @@ def __iter__(self) -> Iterator[object]:

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`.
Expand Down
12 changes: 12 additions & 0 deletions lib/sqlalchemy/ext/asyncio/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -973,6 +973,18 @@ async def close(self) -> None:
"""
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.
Expand Down
13 changes: 13 additions & 0 deletions test/ext/asyncio/test_engine_py3k.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import asyncio
import contextlib
import inspect as stdlib_inspect
from unittest.mock import patch

Expand Down Expand Up @@ -663,6 +664,18 @@ async def test_pool_exhausted_some_timeout(self, async_engine):
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):
Expand Down
11 changes: 11 additions & 0 deletions test/ext/asyncio/test_session_py3k.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import contextlib
from typing import List
from typing import Optional

Expand Down Expand Up @@ -148,6 +149,16 @@ async def test_scalar(self, async_session):
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_"
)
Expand Down

0 comments on commit 581338f

Please sign in to comment.