Merge branch 'master' of github.com:mongodb/mongo-python-driver
This commit is contained in:
commit
7bcc7b6409
@ -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
|
||||
|
||||
@ -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
|
||||
----------------------
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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,)
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user