Skip to content

Commit 5f00966

Browse files
NoahStapplpulley
andauthored
[TASK]-[PYTHON-5623]: Change with_transaction callback return type to Awaitable (#2594)
Co-authored-by: Logan Pulley <logan@pulley.host>
1 parent b607ef1 commit 5f00966

File tree

5 files changed

+50
-2
lines changed

5 files changed

+50
-2
lines changed

doc/changelog.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,22 @@ PyMongo 4.16 brings a number of changes including:
1717
- Removed support for Eventlet.
1818
Eventlet is actively being sunset by its maintainers and has compatibility issues with PyMongo's dnspython dependency.
1919

20+
Changes in Version 4.15.4 (2025/10/21)
21+
--------------------------------------
22+
23+
Version 4.15.4 is a bug fix release.
24+
25+
- Relaxed the callback type of :meth:`~pymongo.asynchronous.client_session.AsyncClientSession.with_transaction` to allow the broader Awaitable type rather than only Coroutine objects.
26+
- Added the missing Python 3.14 trove classifier to the package metadata.
27+
28+
Issues Resolved
29+
...............
30+
31+
See the `PyMongo 4.15.4 release notes in JIRA`_ for the list of resolved issues
32+
in this release.
33+
34+
.. _PyMongo 4.15.4 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=47237
35+
2036
Changes in Version 4.15.3 (2025/10/07)
2137
--------------------------------------
2238

pymongo/asynchronous/client_session.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,8 @@
143143
TYPE_CHECKING,
144144
Any,
145145
AsyncContextManager,
146+
Awaitable,
146147
Callable,
147-
Coroutine,
148148
Mapping,
149149
MutableMapping,
150150
NoReturn,
@@ -604,7 +604,7 @@ def _inherit_option(self, name: str, val: _T) -> _T:
604604

605605
async def with_transaction(
606606
self,
607-
callback: Callable[[AsyncClientSession], Coroutine[Any, Any, _T]],
607+
callback: Callable[[AsyncClientSession], Awaitable[_T]],
608608
read_concern: Optional[ReadConcern] = None,
609609
write_concern: Optional[WriteConcern] = None,
610610
read_preference: Optional[_ServerMode] = None,

test/asynchronous/test_transactions.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"""Execute Transactions Spec tests."""
1616
from __future__ import annotations
1717

18+
import asyncio
1819
import sys
1920
from io import BytesIO
2021
from test.asynchronous.utils_spec_runner import AsyncSpecRunner
@@ -468,6 +469,17 @@ async def callback2(session):
468469
async with self.client.start_session() as s:
469470
self.assertEqual(await s.with_transaction(callback2), "Foo")
470471

472+
@async_client_context.require_transactions
473+
@async_client_context.require_async
474+
async def test_callback_awaitable_no_coroutine(self):
475+
def callback(_):
476+
future = asyncio.Future()
477+
future.set_result("Foo")
478+
return future
479+
480+
async with self.client.start_session() as s:
481+
self.assertEqual(await s.with_transaction(callback), "Foo")
482+
471483
@async_client_context.require_transactions
472484
async def test_callback_not_retried_after_timeout(self):
473485
listener = OvertCommandListener()

test/test_transactions.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"""Execute Transactions Spec tests."""
1616
from __future__ import annotations
1717

18+
import asyncio
1819
import sys
1920
from io import BytesIO
2021
from test.utils_spec_runner import SpecRunner
@@ -460,6 +461,17 @@ def callback2(session):
460461
with self.client.start_session() as s:
461462
self.assertEqual(s.with_transaction(callback2), "Foo")
462463

464+
@client_context.require_transactions
465+
@client_context.require_async
466+
def test_callback_awaitable_no_coroutine(self):
467+
def callback(_):
468+
future = asyncio.Future()
469+
future.set_result("Foo")
470+
return future
471+
472+
with self.client.start_session() as s:
473+
self.assertEqual(s.with_transaction(callback), "Foo")
474+
463475
@client_context.require_transactions
464476
def test_callback_not_retried_after_timeout(self):
465477
listener = OvertCommandListener()

tools/synchro.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,14 @@ def translate_coroutine_types(lines: list[str]) -> list[str]:
322322
index = lines.index(type)
323323
new = type.replace(old, res.group(3))
324324
lines[index] = new
325+
coroutine_types = [line for line in lines if "Awaitable[" in line]
326+
for type in coroutine_types:
327+
res = re.search(r"Awaitable\[([A-z]+)\]", type)
328+
if res:
329+
old = res[0]
330+
index = lines.index(type)
331+
new = type.replace(old, res.group(1))
332+
lines[index] = new
325333
return lines
326334

327335

0 commit comments

Comments
 (0)