Merge branch 'master' of github.com:mongodb/mongo-python-driver

This commit is contained in:
Steven Silvester 2024-04-16 21:31:20 -05:00
commit 7bcc7b6409
No known key found for this signature in database
GPG Key ID: B1BF5EC3A8B32F91
7 changed files with 85 additions and 18 deletions

View File

@ -200,7 +200,7 @@ the pages will re-render and the browser will automatically refresh.
- Append `test/<mod_name>.py::<class_name>::<test_name>` to run
specific tests. You can omit the `<test_name>` to test a full class
and the `<class_name>` to test a full module. For example:
`tox -m test test/test_change_stream.py::TestUnifiedChangeStreamsErrors::test_change_stream_errors_on_ElectionInProgress`.
`tox -m test -- test/test_change_stream.py::TestUnifiedChangeStreamsErrors::test_change_stream_errors_on_ElectionInProgress`.
- Use the `-k` argument to select tests by pattern.
## Running Load Balancer Tests Locally

View File

@ -85,6 +85,21 @@ Unavoidable breaking changes
- The "aws" extra now requires minimum version of ``1.1.0`` for ``pymongo_auth_aws``.
Changes in Version 4.6.3
------------------------
PyMongo 4.6.3 fixes the following bug:
- Fixed a potential memory access violation when decoding invalid bson.
Issues Resolved
...............
See the `PyMongo 4.6.3 release notes in JIRA`_ for the list of resolved issues
in this release.
.. _PyMongo 4.6.3 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=38360
Changes in Version 4.6.2
------------------------
@ -93,6 +108,14 @@ PyMongo 4.6.2 fixes the following bug:
- Fixed a bug appearing in Python 3.12 where "RuntimeError: can't create new thread at interpreter shutdown"
could be written to stderr when a MongoClient's thread starts as the python interpreter is shutting down.
Issues Resolved
...............
See the `PyMongo 4.6.2 release notes in JIRA`_ for the list of resolved issues
in this release.
.. _PyMongo 4.6.2 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=37906
Changes in Version 4.6.1
------------------------
@ -100,6 +123,14 @@ PyMongo 4.6.1 fixes the following bug:
- Ensure retryable read ``OperationFailure`` errors re-raise exception when 0 or NoneType error code is provided.
Issues Resolved
...............
See the `PyMongo 4.6.1 release notes in JIRA`_ for the list of resolved issues
in this release.
.. _PyMongo 4.6.1 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=37138
Changes in Version 4.6
----------------------
@ -132,6 +163,14 @@ PyMongo 4.6 brings a number of improvements including:
- Added the :ref:`network-compression-example` documentation page.
- Added more timeout information to network errors.
Issues Resolved
...............
See the `PyMongo 4.6 release notes in JIRA`_ for the list of resolved issues
in this release.
.. _PyMongo 4.6 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=36542
Changes in Version 4.5
----------------------

View File

@ -879,8 +879,11 @@ class MongoClient(common.BaseObject, Generic[_DocumentType]):
# This will be used later if we fork.
MongoClient._clients[self._topology._topology_id] = self
def _init_background(self) -> None:
def _init_background(self, old_pid: Optional[int] = None) -> None:
self._topology = Topology(self._topology_settings)
# Seed the topology with the old one's pid so we can detect clients
# that are opened before a fork and used after.
self._topology._pid = old_pid
def target() -> bool:
client = self_ref()
@ -903,7 +906,7 @@ class MongoClient(common.BaseObject, Generic[_DocumentType]):
def _after_fork(self) -> None:
"""Resets topology in a child after successfully forking."""
self._init_background()
self._init_background(self._topology._pid)
def _duplicate(self, **kwargs: Any) -> MongoClient:
args = self.__init_kwargs.copy()
@ -921,7 +924,7 @@ class MongoClient(common.BaseObject, Generic[_DocumentType]):
the server may change. In such cases, store a local reference to a
ServerDescription first, then use its properties.
"""
server = self._topology.select_server(writable_server_selector, _Op.TEST)
server = self._get_topology().select_server(writable_server_selector, _Op.TEST)
return getattr(server.description, attr_name)

View File

@ -20,9 +20,11 @@ import logging
import os
import queue
import random
import sys
import time
import warnings
import weakref
from pathlib import Path
from typing import TYPE_CHECKING, Any, Callable, Mapping, Optional, cast
from pymongo import _csot, common, helpers, periodic_executor
@ -70,6 +72,9 @@ if TYPE_CHECKING:
from pymongo.typings import ClusterTime, _Address
_pymongo_dir = str(Path(__file__).parent)
def process_events_queue(queue_ref: weakref.ReferenceType[queue.Queue]) -> bool:
q = queue_ref()
if not q:
@ -187,12 +192,17 @@ class Topology:
self._pid = pid
elif pid != self._pid:
self._pid = pid
warnings.warn(
if sys.version_info[:2] >= (3, 12):
kwargs = {"skip_file_prefixes": (_pymongo_dir,)}
else:
kwargs = {"stacklevel": 6}
# Ignore B028 warning for missing stacklevel.
warnings.warn( # type: ignore[call-overload] # noqa: B028
"MongoClient opened before fork. May not be entirely fork-safe, "
"proceed with caution. See PyMongo's documentation for details: "
"https://pymongo.readthedocs.io/en/stable/faq.html#"
"is-pymongo-fork-safe",
stacklevel=2,
**kwargs,
)
with self._lock:
# Close servers and clear the pools.

View File

@ -20,8 +20,6 @@ import socketserver
import sys
import threading
from pymongo.monitoring import ServerHeartbeatFailedEvent, ServerHeartbeatStartedEvent
sys.path[0:0] = [""]
from test import IntegrationTest, unittest
@ -52,6 +50,7 @@ from pymongo.errors import (
)
from pymongo.hello import Hello, HelloCompat
from pymongo.helpers import _check_command_response, _check_write_command_response
from pymongo.monitoring import ServerHeartbeatFailedEvent, ServerHeartbeatStartedEvent
from pymongo.server_description import SERVER_TYPE, ServerDescription
from pymongo.settings import TopologySettings
from pymongo.topology import Topology, _ErrorContext
@ -408,17 +407,21 @@ class MockTCPHandler(socketserver.BaseRequestHandler):
self.request.close()
class TestHeartbeatStartOrdering(unittest.TestCase):
def start_server(self, events):
server = socketserver.TCPServer(("localhost", 9999), MockTCPHandler)
server.events = events
server.handle_request()
server.server_close()
class TCPServer(socketserver.TCPServer):
allow_reuse_address = True
def handle_request_and_shutdown(self):
self.handle_request()
self.server_close()
class TestHeartbeatStartOrdering(unittest.TestCase):
def test_heartbeat_start_ordering(self):
events = []
listener = HeartbeatEventsListListener(events)
server_thread = threading.Thread(target=self.start_server, args=(events,))
server = TCPServer(("localhost", 9999), MockTCPHandler)
server.events = events
server_thread = threading.Thread(target=server.handle_request_and_shutdown)
server_thread.start()
_c = MongoClient(
"mongodb://localhost:9999", serverSelectionTimeoutMS=500, event_listeners=(listener,)

View File

@ -26,6 +26,7 @@ import sys
import textwrap
import traceback
import uuid
import warnings
from threading import Thread
from typing import Any, Dict, Mapping
@ -348,7 +349,9 @@ class TestClientSimple(EncryptionIntegrationTest):
self.addCleanup(client.close)
def target():
client.admin.command("ping")
with warnings.catch_warnings():
warnings.simplefilter("ignore")
client.admin.command("ping")
with self.fork(target):
target()

View File

@ -18,6 +18,7 @@ from __future__ import annotations
import os
import sys
import unittest
import warnings
from multiprocessing import Pipe
sys.path[0:0] = [""]
@ -43,7 +44,9 @@ class TestFork(IntegrationTest):
with self.client._MongoClient__lock:
def target():
self.client.admin.command("ping")
with warnings.catch_warnings():
warnings.simplefilter("ignore")
self.client.admin.command("ping")
with self.fork(target):
pass
@ -72,7 +75,11 @@ class TestFork(IntegrationTest):
parent_cursor_exc = self.client._kill_cursors_executor
def target():
self.client.admin.command("ping")
# Catch the fork warning and send to the parent for assertion.
with warnings.catch_warnings(record=True) as ctx:
warnings.simplefilter("always")
self.client.admin.command("ping")
child_conn.send(str(ctx[0]))
child_conn.send(self.client._topology._pid)
child_conn.send(
(
@ -83,6 +90,8 @@ class TestFork(IntegrationTest):
with self.fork(target):
self.assertEqual(self.client._topology._pid, init_id)
fork_warning = parent_conn.recv()
self.assertIn("MongoClient opened before fork", fork_warning)
child_id = parent_conn.recv()
self.assertNotEqual(child_id, init_id)
passed, msg = parent_conn.recv()