[TASK]-[PYTHON-5623]: [v4.15] Change with_transaction callback return type to Awaitable (#2612)

Co-authored-by: Noah Stapp <noah.stapp@mongodb.com>
Co-authored-by: Logan Pulley <logan@pulley.host>
This commit is contained in:
Steven Silvester 2025-11-11 13:42:52 -06:00 committed by GitHub
parent f3ea3738bf
commit 477217f666
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 53 additions and 5 deletions

View File

@ -100,7 +100,7 @@ jobs:
make_sdist:
name: Make SDist
runs-on: macos-13
runs-on: macos-14
steps:
- uses: actions/checkout@v5
with:

View File

@ -1,6 +1,22 @@
Changelog
=========
Changes in Version 4.15.4 (2025/11/11)
--------------------------------------
Version 4.15.4 is a bug fix release.
- Relaxed the callback type of :meth:`~pymongo.asynchronous.client_session.AsyncClientSession.with_transaction` to allow the broader Awaitable type rather than only Coroutine objects.
- Added the missing Python 3.14 trove classifier to the package metadata.
Issues Resolved
...............
See the `PyMongo 4.15.4 release notes in JIRA`_ for the list of resolved issues
in this release.
.. _PyMongo 4.15.4 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=47237
Changes in Version 4.15.3 (2025/10/07)
--------------------------------------

View File

@ -22,7 +22,7 @@ work with MongoDB from Python.
Getting Help
------------
If you're having trouble or have questions about PyMongo, ask your question on
our `MongoDB Community Forum <https://www.mongodb.com/community/forums/tag/python>`_.
one of the platforms listed on `Technical Support <https://www.mongodb.com/docs/manual/support/>`_.
You may also want to consider a
`commercial support subscription <https://support.mongodb.com/welcome>`_.
Once you get an answer, it'd be great if you could work it back into this
@ -37,7 +37,7 @@ project.
Feature Requests / Feedback
---------------------------
Use our `feedback engine <https://feedback.mongodb.com/forums/924286-drivers>`_
Use our `feedback engine <https://feedback.mongodb.com/?category=7548141816650747033>`_
to send us feature requests and general feedback about PyMongo.
Contributing

View File

@ -143,8 +143,8 @@ from typing import (
TYPE_CHECKING,
Any,
AsyncContextManager,
Awaitable,
Callable,
Coroutine,
Mapping,
MutableMapping,
NoReturn,
@ -600,7 +600,7 @@ class AsyncClientSession:
async def with_transaction(
self,
callback: Callable[[AsyncClientSession], Coroutine[Any, Any, _T]],
callback: Callable[[AsyncClientSession], Awaitable[_T]],
read_concern: Optional[ReadConcern] = None,
write_concern: Optional[WriteConcern] = None,
read_preference: Optional[_ServerMode] = None,

View File

@ -15,6 +15,7 @@
"""Execute Transactions Spec tests."""
from __future__ import annotations
import asyncio
import sys
from io import BytesIO
from test.asynchronous.utils_spec_runner import AsyncSpecRunner
@ -469,6 +470,17 @@ class TestTransactionsConvenientAPI(AsyncTransactionsBase):
async with self.client.start_session() as s:
self.assertEqual(await s.with_transaction(callback2), "Foo")
@async_client_context.require_transactions
@async_client_context.require_async
async def test_callback_awaitable_no_coroutine(self):
def callback(_):
future = asyncio.Future()
future.set_result("Foo")
return future
async with self.client.start_session() as s:
self.assertEqual(await s.with_transaction(callback), "Foo")
@async_client_context.require_transactions
async def test_callback_not_retried_after_timeout(self):
listener = OvertCommandListener()

View File

@ -15,6 +15,7 @@
"""Execute Transactions Spec tests."""
from __future__ import annotations
import asyncio
import sys
from io import BytesIO
from test.utils_spec_runner import SpecRunner
@ -461,6 +462,17 @@ class TestTransactionsConvenientAPI(TransactionsBase):
with self.client.start_session() as s:
self.assertEqual(s.with_transaction(callback2), "Foo")
@client_context.require_transactions
@client_context.require_async
def test_callback_awaitable_no_coroutine(self):
def callback(_):
future = asyncio.Future()
future.set_result("Foo")
return future
with self.client.start_session() as s:
self.assertEqual(s.with_transaction(callback), "Foo")
@client_context.require_transactions
def test_callback_not_retried_after_timeout(self):
listener = OvertCommandListener()

View File

@ -322,6 +322,14 @@ def translate_coroutine_types(lines: list[str]) -> list[str]:
index = lines.index(type)
new = type.replace(old, res.group(3))
lines[index] = new
coroutine_types = [line for line in lines if "Awaitable[" in line]
for type in coroutine_types:
res = re.search(r"Awaitable\[([A-z]+)\]", type)
if res:
old = res[0]
index = lines.index(type)
new = type.replace(old, res.group(1))
lines[index] = new
return lines