Skip to content

Commit 1d39d87

Browse files
committed
Merge branch 'master' of github.com:mongodb/mongo-python-driver
2 parents bab9849 + e28f49c commit 1d39d87

38 files changed

+556
-245
lines changed

.evergreen/scripts/bootstrap-mongo-orchestration.sh

Lines changed: 10 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,38 +2,21 @@
22

33
set -eu
44

5-
6-
# Enable core dumps if enabled on the machine
7-
# Copied from https://github.com/mongodb/mongo/blob/master/etc/evergreen.yml
8-
if [ -f /proc/self/coredump_filter ]; then
9-
# Set the shell process (and its children processes) to dump ELF headers (bit 4),
10-
# anonymous shared mappings (bit 1), and anonymous private mappings (bit 0).
11-
echo 0x13 >/proc/self/coredump_filter
12-
13-
if [ -f /sbin/sysctl ]; then
14-
# Check that the core pattern is set explicitly on our distro image instead
15-
# of being the OS's default value. This ensures that coredump names are consistent
16-
# across distros and can be picked up by Evergreen.
17-
core_pattern=$(/sbin/sysctl -n "kernel.core_pattern")
18-
if [ "$core_pattern" = "dump_%e.%p.core" ]; then
19-
echo "Enabling coredumps"
20-
ulimit -c unlimited
21-
fi
22-
fi
23-
fi
24-
25-
if [ "$(uname -s)" = "Darwin" ]; then
26-
core_pattern_mac=$(/usr/sbin/sysctl -n "kern.corefile")
27-
if [ "$core_pattern_mac" = "dump_%N.%P.core" ]; then
28-
echo "Enabling coredumps"
29-
ulimit -c unlimited
30-
fi
31-
fi
5+
HERE=$(dirname ${BASH_SOURCE:-$0})
6+
HERE="$( cd -- "$HERE" > /dev/null 2>&1 && pwd )"
7+
ROOT=$(dirname "$(dirname $HERE)")
328

339
if [ -z "${TEST_CRYPT_SHARED:-}" ]; then
3410
export SKIP_CRYPT_SHARED=1
3511
fi
3612

13+
# Override the tls files if applicable.
14+
if [ "${SSL:-}" == "ssl" ]; then
15+
export TLS_CERT_KEY_FILE=${ROOT}/test/certificates/client.pem
16+
export TLS_PEM_KEY_FILE=${ROOT}/test/certificates/server.pem
17+
export TLS_CA_FILE=${ROOT}/test/certificates/ca.pem
18+
fi
19+
3720
MONGODB_VERSION=${VERSION:-} \
3821
TOPOLOGY=${TOPOLOGY:-} \
3922
AUTH=${AUTH:-} \

.evergreen/scripts/configure-env.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,9 @@ EOT
7676

7777
# Write the .env file for drivers-tools.
7878
rm -rf $DRIVERS_TOOLS
79-
git clone https://github.com/mongodb-labs/drivers-evergreen-tools.git $DRIVERS_TOOLS
79+
BRANCH=master
80+
ORG=mongodb-labs
81+
git clone --branch $BRANCH https://github.com/$ORG/drivers-evergreen-tools.git $DRIVERS_TOOLS
8082

8183
cat <<EOT > ${DRIVERS_TOOLS}/.env
8284
SKIP_LEGACY_SHELL=1

.evergreen/scripts/prepare-resources.sh

Lines changed: 0 additions & 24 deletions
This file was deleted.

.evergreen/scripts/setup-system.sh

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,35 @@ pushd "$(dirname "$(dirname $HERE)")"
77
echo "Setting up system..."
88
bash .evergreen/scripts/configure-env.sh
99
source .evergreen/scripts/env.sh
10-
bash .evergreen/scripts/prepare-resources.sh
1110
bash $DRIVERS_TOOLS/.evergreen/setup.sh
1211
bash .evergreen/scripts/install-dependencies.sh
1312
popd
13+
14+
# Enable core dumps if enabled on the machine
15+
# Copied from https://github.com/mongodb/mongo/blob/master/etc/evergreen.yml
16+
if [ -f /proc/self/coredump_filter ]; then
17+
# Set the shell process (and its children processes) to dump ELF headers (bit 4),
18+
# anonymous shared mappings (bit 1), and anonymous private mappings (bit 0).
19+
echo 0x13 >/proc/self/coredump_filter
20+
21+
if [ -f /sbin/sysctl ]; then
22+
# Check that the core pattern is set explicitly on our distro image instead
23+
# of being the OS's default value. This ensures that coredump names are consistent
24+
# across distros and can be picked up by Evergreen.
25+
core_pattern=$(/sbin/sysctl -n "kernel.core_pattern")
26+
if [ "$core_pattern" = "dump_%e.%p.core" ]; then
27+
echo "Enabling coredumps"
28+
ulimit -c unlimited
29+
fi
30+
fi
31+
fi
32+
33+
if [ "$(uname -s)" = "Darwin" ]; then
34+
core_pattern_mac=$(/usr/sbin/sysctl -n "kern.corefile")
35+
if [ "$core_pattern_mac" = "dump_%N.%P.core" ]; then
36+
echo "Enabling coredumps"
37+
ulimit -c unlimited
38+
fi
39+
fi
40+
1441
echo "Setting up system... done."

doc/changelog.rst

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,26 @@
11
Changelog
22
=========
33

4-
Changes in Version 4.11.0 (YYYY/MM/DD)
4+
Changes in Version 4.11.2 (YYYY/MM/DD)
5+
--------------------------------------
6+
7+
Version 4.11.2 is a bug fix release.
8+
9+
- Fixed a bug where :meth:`~pymongo.database.Database.command` would fail when attempting to run the bulkWrite command.
10+
11+
Issues Resolved
12+
...............
13+
14+
See the `PyMongo 4.11.2 release notes in JIRA`_ for the list of resolved issues in this release.
15+
16+
.. _PyMongo 4.11.2 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=42506
17+
18+
Changes in Version 4.11.1 (2025/02/10)
19+
--------------------------------------
20+
21+
- Fixed support for prebuilt ``ppc64le`` and ``s390x`` wheels.
22+
23+
Changes in Version 4.11.0 (2025/01/28)
524
--------------------------------------
625

726
.. warning:: PyMongo 4.11 drops support for Python 3.8 and PyPy 3.9: Python 3.9+ or PyPy 3.10+ is now required.

gridfs/asynchronous/grid_file.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1301,11 +1301,8 @@ async def write(self, data: Any) -> None:
13011301
raise ValueError("cannot write to a closed file")
13021302

13031303
try:
1304-
if isinstance(data, AsyncGridOut):
1305-
read = data.read
1306-
else:
1307-
# file-like
1308-
read = data.read
1304+
# file-like
1305+
read = data.read
13091306
except AttributeError:
13101307
# string
13111308
if not isinstance(data, (str, bytes)):
@@ -1317,7 +1314,7 @@ async def write(self, data: Any) -> None:
13171314
raise TypeError(
13181315
"must specify an encoding for file in order to write str"
13191316
) from None
1320-
read = io.BytesIO(data).read # type: ignore[assignment]
1317+
read = io.BytesIO(data).read
13211318

13221319
if inspect.iscoroutinefunction(read):
13231320
await self._write_async(read)
@@ -1331,15 +1328,15 @@ async def write(self, data: Any) -> None:
13311328
except BaseException:
13321329
await self.abort()
13331330
raise
1334-
self._buffer.write(to_write) # type: ignore
1335-
if len(to_write) < space: # type: ignore
1331+
self._buffer.write(to_write)
1332+
if len(to_write) < space:
13361333
return # EOF or incomplete
13371334
await self._flush_buffer()
13381335
to_write = read(self.chunk_size)
1339-
while to_write and len(to_write) == self.chunk_size: # type: ignore
1336+
while to_write and len(to_write) == self.chunk_size:
13401337
await self._flush_data(to_write)
13411338
to_write = read(self.chunk_size)
1342-
self._buffer.write(to_write) # type: ignore
1339+
self._buffer.write(to_write)
13431340

13441341
async def _write_async(self, read: Any) -> None:
13451342
if self._buffer.tell() > 0:

gridfs/synchronous/grid_file.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1291,11 +1291,8 @@ def write(self, data: Any) -> None:
12911291
raise ValueError("cannot write to a closed file")
12921292

12931293
try:
1294-
if isinstance(data, GridOut):
1295-
read = data.read
1296-
else:
1297-
# file-like
1298-
read = data.read
1294+
# file-like
1295+
read = data.read
12991296
except AttributeError:
13001297
# string
13011298
if not isinstance(data, (str, bytes)):
@@ -1307,7 +1304,7 @@ def write(self, data: Any) -> None:
13071304
raise TypeError(
13081305
"must specify an encoding for file in order to write str"
13091306
) from None
1310-
read = io.BytesIO(data).read # type: ignore[assignment]
1307+
read = io.BytesIO(data).read
13111308

13121309
if inspect.iscoroutinefunction(read):
13131310
self._write_async(read)
@@ -1321,15 +1318,15 @@ def write(self, data: Any) -> None:
13211318
except BaseException:
13221319
self.abort()
13231320
raise
1324-
self._buffer.write(to_write) # type: ignore
1325-
if len(to_write) < space: # type: ignore
1321+
self._buffer.write(to_write)
1322+
if len(to_write) < space:
13261323
return # EOF or incomplete
13271324
self._flush_buffer()
13281325
to_write = read(self.chunk_size)
1329-
while to_write and len(to_write) == self.chunk_size: # type: ignore
1326+
while to_write and len(to_write) == self.chunk_size:
13301327
self._flush_data(to_write)
13311328
to_write = read(self.chunk_size)
1332-
self._buffer.write(to_write) # type: ignore
1329+
self._buffer.write(to_write)
13331330

13341331
def _write_async(self, read: Any) -> None:
13351332
if self._buffer.tell() > 0:

pymongo/asynchronous/monitor.py

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@
2121
import logging
2222
import time
2323
import weakref
24-
from typing import TYPE_CHECKING, Any, Mapping, Optional, cast
24+
from typing import TYPE_CHECKING, Any, Optional
2525

2626
from pymongo import common, periodic_executor
2727
from pymongo._csot import MovingMinimum
28-
from pymongo.errors import NetworkTimeout, NotPrimaryError, OperationFailure, _OperationCancelled
28+
from pymongo.errors import NetworkTimeout, _OperationCancelled
2929
from pymongo.hello import Hello
3030
from pymongo.lock import _async_create_lock
3131
from pymongo.logger import _SDAM_LOGGER, _debug_log, _SDAMStatusMessage
@@ -255,13 +255,7 @@ async def _check_server(self) -> ServerDescription:
255255
self._conn_id = None
256256
start = time.monotonic()
257257
try:
258-
try:
259-
return await self._check_once()
260-
except (OperationFailure, NotPrimaryError) as exc:
261-
# Update max cluster time even when hello fails.
262-
details = cast(Mapping[str, Any], exc.details)
263-
await self._topology.receive_cluster_time(details.get("$clusterTime"))
264-
raise
258+
return await self._check_once()
265259
except ReferenceError:
266260
raise
267261
except Exception as error:
@@ -358,7 +352,6 @@ async def _check_with_socket(self, conn: AsyncConnection) -> tuple[Hello, float]
358352
359353
Can raise ConnectionFailure or OperationFailure.
360354
"""
361-
cluster_time = self._topology.max_cluster_time()
362355
start = time.monotonic()
363356
if conn.more_to_come:
364357
# Read the next streaming hello (MongoDB 4.4+).
@@ -368,13 +361,12 @@ async def _check_with_socket(self, conn: AsyncConnection) -> tuple[Hello, float]
368361
):
369362
# Initiate streaming hello (MongoDB 4.4+).
370363
response = await conn._hello(
371-
cluster_time,
372364
self._server_description.topology_version,
373365
self._settings.heartbeat_frequency,
374366
)
375367
else:
376368
# New connection handshake or polling hello (MongoDB <4.4).
377-
response = await conn._hello(cluster_time, None, None)
369+
response = await conn._hello(None, None)
378370
duration = _monotonic_duration(start)
379371
return response, duration
380372

pymongo/asynchronous/network.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,10 @@ async def command(
207207
)
208208

209209
response_doc = unpacked_docs[0]
210+
if not conn.ready:
211+
cluster_time = response_doc.get("$clusterTime")
212+
if cluster_time:
213+
conn._cluster_time = cluster_time
210214
if client:
211215
await client._process_response(response_doc, session)
212216
if check:

pymongo/asynchronous/pool.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@
102102
from pymongo.pyopenssl_context import _sslConn
103103
from pymongo.read_concern import ReadConcern
104104
from pymongo.read_preferences import _ServerMode
105-
from pymongo.typings import ClusterTime, _Address, _CollationIn
105+
from pymongo.typings import _Address, _CollationIn
106106
from pymongo.write_concern import WriteConcern
107107

108108
try:
@@ -310,6 +310,8 @@ def __init__(
310310
self.connect_rtt = 0.0
311311
self._client_id = pool._client_id
312312
self.creation_time = time.monotonic()
313+
# For gossiping $clusterTime from the connection handshake to the client.
314+
self._cluster_time = None
313315

314316
def set_conn_timeout(self, timeout: Optional[float]) -> None:
315317
"""Cache last timeout to avoid duplicate calls to conn.settimeout."""
@@ -374,11 +376,10 @@ def hello_cmd(self) -> dict[str, Any]:
374376
return {HelloCompat.LEGACY_CMD: 1, "helloOk": True}
375377

376378
async def hello(self) -> Hello:
377-
return await self._hello(None, None, None)
379+
return await self._hello(None, None)
378380

379381
async def _hello(
380382
self,
381-
cluster_time: Optional[ClusterTime],
382383
topology_version: Optional[Any],
383384
heartbeat_frequency: Optional[int],
384385
) -> Hello[dict[str, Any]]:
@@ -401,9 +402,6 @@ async def _hello(
401402
if self.opts.connect_timeout:
402403
self.set_conn_timeout(self.opts.connect_timeout + heartbeat_frequency)
403404

404-
if not performing_handshake and cluster_time is not None:
405-
cmd["$clusterTime"] = cluster_time
406-
407405
creds = self.opts._credentials
408406
if creds:
409407
if creds.mechanism == "DEFAULT" and creds.username:
@@ -1316,6 +1314,9 @@ async def connect(self, handler: Optional[_MongoClientErrorHandler] = None) -> A
13161314
conn.close_conn(ConnectionClosedReason.ERROR)
13171315
raise
13181316

1317+
if handler:
1318+
await handler.client._topology.receive_cluster_time(conn._cluster_time)
1319+
13191320
return conn
13201321

13211322
@contextlib.asynccontextmanager

0 commit comments

Comments
 (0)