Compare commits

...

13 Commits
master ... v4.6

Author SHA1 Message Date
Steven Silvester
d23ed12467
PYTHON-4305 [v4.6]: Add changelog for 4.6.3 (#1608)
Co-authored-by: Shane Harvey <shnhrv@gmail.com>
2024-04-18 13:29:31 -05:00
Alessio Castrica
d6248e9cf1 PYTHON-4298 Raise ConfigurationError not TypeError when round_trip_time is None in server selection (#1566)
Co-authored-by: Alessio <alessio.castrica@investsuite.com>
(cherry picked from commit 167b9648ca)
2024-04-04 15:10:15 -07:00
Steven Silvester
3f04a62f68
BUMP 4.6.4.dev0 2024-03-27 18:54:02 -05:00
Steven Silvester
8da192f9ca
BUMP 4.6.3 2024-03-27 18:53:29 -05:00
Shane Harvey
56b6b6dbc2
PYTHON-4305 Fix bson size check (#1564)
(cherry picked from commit 372b5d68d5)
2024-03-27 18:52:36 -05:00
Steven Silvester
449d0f316c
BUMP to 4.6.3.dev0 2024-02-21 13:33:09 -06:00
Steven Silvester
e04576de22
DEVPROD-3871 Use teardown_task when there is one function/command (#1533) 2024-02-21 12:04:14 -06:00
Steven Silvester
cf1c6a11f7
PYTHON-4219 Prep for 4.6.2 Release (#1530) 2024-02-20 14:30:46 -06:00
Steven Silvester
d29b2b7cf4
PYTHON-4147 [v4.6]: Silence noisy thread.start() RuntimeError at shutdown (#1532)
Co-authored-by: Jib <jib.adegunloye@mongodb.com>
2024-02-20 14:29:01 -06:00
Steven Silvester
0477b9bc0c
PYTHON-4077 [v4.6]: Ensure there is a MacOS wheel for Python 3.7 (#1527)
Co-authored-by: Casey Clements <caseyclements@users.noreply.github.com>
Co-authored-by: Shane Harvey <shnhrv@gmail.com>
2024-02-16 14:56:59 -06:00
Steven Silvester
ecad17d24e BUMP 4.6.2.dev0 2023-11-27 13:45:51 -06:00
Steven Silvester
485e0a5e56 BUMP 4.6.1 2023-11-27 13:44:40 -06:00
Jib
995365c712
PYTHON-4038 [v4.6]: Ensure retryable read OperationFailures re-raise exception when 0 or NoneType error code is provided. (#1425) (#1429) 2023-11-16 14:10:42 -05:00
15 changed files with 130 additions and 20 deletions

View File

@ -12,7 +12,7 @@ stepback: true
# Actual testing tasks are marked with `type: test`
command_type: system
# Protect ourself against rogue test case, or curl gone wild, that runs forever
# Protect ourselves against rogue test case, or curl gone wild, that runs forever
# Good rule of thumb: the averageish length a task takes, times 5
# That roughly accounts for variable system performance for various buildvariants
exec_timeout_secs: 3600 # 60 minutes is the longest we'll ever run (primarily
@ -1058,7 +1058,7 @@ task_groups:
- command: expansions.update
params:
file: src/atlas-expansion.yml
teardown_group:
teardown_task:
- command: subprocess.exec
params:
working_dir: src
@ -1098,7 +1098,7 @@ task_groups:
- command: expansions.update
params:
file: src/atlas-expansion.yml
teardown_group:
teardown_task:
- command: subprocess.exec
params:
working_dir: src
@ -1174,6 +1174,7 @@ tasks:
- func: "build release"
vars:
VERSION: "3.7"
- func: "upload release"
- name: "release-windows"
tags: ["release_tag"]

View File

@ -2405,6 +2405,7 @@ static PyObject* get_value(PyObject* self, PyObject* name, const char* buffer,
uint32_t c_w_s_size;
uint32_t code_size;
uint32_t scope_size;
uint32_t len;
PyObject* code;
PyObject* scope;
PyObject* code_type;
@ -2424,7 +2425,8 @@ static PyObject* get_value(PyObject* self, PyObject* name, const char* buffer,
memcpy(&code_size, buffer + *position, 4);
code_size = BSON_UINT32_FROM_LE(code_size);
/* code_w_scope length + code length + code + scope length */
if (!code_size || max < code_size || max < 4 + 4 + code_size + 4) {
len = 4 + 4 + code_size + 4;
if (!code_size || max < code_size || max < len || len < code_size) {
goto invalid;
}
*position += 4;
@ -2442,12 +2444,9 @@ static PyObject* get_value(PyObject* self, PyObject* name, const char* buffer,
memcpy(&scope_size, buffer + *position, 4);
scope_size = BSON_UINT32_FROM_LE(scope_size);
if (scope_size < BSON_MIN_SIZE) {
Py_DECREF(code);
goto invalid;
}
/* code length + code + scope length + scope */
if ((4 + code_size + 4 + scope_size) != c_w_s_size) {
len = 4 + 4 + code_size + scope_size;
if (scope_size < BSON_MIN_SIZE || len != c_w_s_size || len < scope_size) {
Py_DECREF(code);
goto invalid;
}

View File

@ -35,7 +35,7 @@ Connections to Atlas require TLS/SSL.
You can read more about TLS versions and their security implications here:
`<https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Protection_Cheat_Sheet.html#only-support-strong-protocols>`_
`<https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Security_Cheat_Sheet.html#only-support-strong-protocols>`_
.. _python.org: https://www.python.org/downloads/
.. _homebrew: https://brew.sh/

View File

@ -1,6 +1,52 @@
Changelog
=========
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
------------------------
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
------------------------
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
----------------------
@ -33,6 +79,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

@ -59,4 +59,4 @@ deprecated PyMongo features.
.. _the warnings module: https://docs.python.org/3/library/warnings.html
.. _the -W command line option: https://docs.python.org/3/using/cmdline.html#cmdoption-w
.. _the -W command line option: https://docs.python.org/3/using/cmdline.html#cmdoption-W

View File

@ -32,7 +32,7 @@ MongoDB.
You can read more about TLS versions and their security implications here:
`<https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Protection_Cheat_Sheet.html#only-support-strong-protocols>`_
`<https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Security_Cheat_Sheet.html#only-support-strong-protocols>`_
.. _python.org: https://www.python.org/downloads/
.. _homebrew: https://brew.sh/

View File

@ -44,7 +44,7 @@ MincePy
workflow as possible.
Ming
`Ming <http://merciless.sourceforge.net/>`_ (the Merciless) is a
`Ming <https://ming.readthedocs.io/en/latest/>`_ is a
library that allows you to enforce schemas on a MongoDB database in
your Python application. It was developed by `SourceForge
<http://sourceforge.net/>`_ in the course of their migration to

View File

@ -17,7 +17,7 @@ from __future__ import annotations
from typing import Tuple, Union
version_tuple: Tuple[Union[int, str], ...] = (4, 6, 0)
version_tuple: Tuple[Union[int, str], ...] = (4, 6, 4, ".dev0")
def get_version_string() -> str:

View File

@ -2898,7 +2898,7 @@ class Collection(common.BaseObject, Generic[_DocumentType]):
.. seealso:: The MongoDB documentation on `changeStreams <https://mongodb.com/docs/manual/changeStreams/>`_.
.. _change streams specification:
https://github.com/mongodb/specifications/blob/master/source/change-streams/change-streams.rst
https://github.com/mongodb/specifications/blob/master/source/change-streams/change-streams.md
"""
return CollectionChangeStream(
self,

View File

@ -666,7 +666,7 @@ class Database(common.BaseObject, Generic[_DocumentType]):
.. seealso:: The MongoDB documentation on `changeStreams <https://mongodb.com/docs/manual/changeStreams/>`_.
.. _change streams specification:
https://github.com/mongodb/specifications/blob/master/source/change-streams/change-streams.rst
https://github.com/mongodb/specifications/blob/master/source/change-streams/change-streams.md
"""
return DatabaseChangeStream(
self,

View File

@ -1030,7 +1030,7 @@ class MongoClient(common.BaseObject, Generic[_DocumentType]):
.. seealso:: The MongoDB documentation on `changeStreams <https://mongodb.com/docs/manual/changeStreams/>`_.
.. _change streams specification:
https://github.com/mongodb/specifications/blob/master/source/change-streams/change-streams.rst
https://github.com/mongodb/specifications/blob/master/source/change-streams/change-streams.md
"""
return ClusterChangeStream(
self.admin,
@ -2329,7 +2329,8 @@ class _ClientConnectionRetryable(Generic[T]):
# ConnectionFailures do not supply a code property
exc_code = getattr(exc, "code", None)
if self._is_not_eligible_for_retry() or (
exc_code and exc_code not in helpers._RETRYABLE_ERROR_CODES
isinstance(exc, OperationFailure)
and exc_code not in helpers._RETRYABLE_ERROR_CODES
):
raise
self._retrying = True

View File

@ -16,6 +16,7 @@
from __future__ import annotations
import sys
import threading
import time
import weakref
@ -92,7 +93,15 @@ class PeriodicExecutor:
thread.daemon = True
self._thread = weakref.proxy(thread)
_register_executor(self)
thread.start()
# Mitigation to RuntimeError firing when thread starts on shutdown
# https://github.com/python/cpython/issues/114570
try:
thread.start()
except RuntimeError as e:
if "interpreter shutdown" in str(e) or sys.is_finalizing():
self._thread = None
return
raise
def close(self, dummy: Any = None) -> None:
"""Stop. To restart, call open().

View File

@ -266,8 +266,14 @@ class TopologyDescription:
def _apply_local_threshold(self, selection: Optional[Selection]) -> list[ServerDescription]:
if not selection:
return []
round_trip_times: list[float] = []
for server in selection.server_descriptions:
if server.round_trip_time is None:
config_err_msg = f"round_trip_time for server {server.address} is unexpectedly None: {self}, servers: {selection.server_descriptions}"
raise ConfigurationError(config_err_msg)
round_trip_times.append(server.round_trip_time)
# Round trip time in seconds.
fastest = min(cast(float, s.round_trip_time) for s in selection.server_descriptions)
fastest = min(round_trip_times)
threshold = self._topology_settings.local_threshold_ms / 1000.0
return [
s

View File

@ -16,11 +16,13 @@
from __future__ import annotations
import unittest
from test import PyMongoTestCase
from mockupdb import MockupDB, OpMsg, going
from bson.objectid import ObjectId
from pymongo import MongoClient
from pymongo.errors import OperationFailure
class TestCursor(unittest.TestCase):
@ -57,5 +59,31 @@ class TestCursor(unittest.TestCase):
request.replies({"cursor": {"id": cursor_id, "nextBatch": [{}]}})
class TestRetryableErrorCodeCatch(PyMongoTestCase):
def _test_fail_on_operation_failure_with_code(self, code):
"""Test reads on error codes that should not be retried"""
server = MockupDB()
server.run()
self.addCleanup(server.stop)
server.autoresponds("ismaster", maxWireVersion=6)
client = MongoClient(server.uri)
with going(lambda: server.receives(OpMsg({"find": "collection"})).command_err(code=code)):
cursor = client.db.collection.find()
with self.assertRaises(OperationFailure) as ctx:
cursor.next()
self.assertEqual(ctx.exception.code, code)
def test_fail_on_operation_failure_none(self):
self._test_fail_on_operation_failure_with_code(None)
def test_fail_on_operation_failure_zero(self):
self._test_fail_on_operation_failure_with_code(0)
def test_fail_on_operation_failure_one(self):
self._test_fail_on_operation_failure_with_code(1)
if __name__ == "__main__":
unittest.main()

View File

@ -16,6 +16,7 @@
from __future__ import annotations
import gc
import subprocess
import sys
from functools import partial
@ -79,6 +80,17 @@ class TestMonitor(IntegrationTest):
for executor in executors:
wait_until(lambda: executor._stopped, f"closed executor: {executor._name}", timeout=5)
def test_no_thread_start_runtime_err_on_shutdown(self):
"""Test we silence noisy runtime errors fired when the MongoClient spawns a new thread
on process shutdown."""
command = [sys.executable, "-c", "from pymongo import MongoClient; c = MongoClient()"]
completed_process: subprocess.CompletedProcess = subprocess.run(
command, capture_output=True
)
self.assertFalse(completed_process.stderr)
self.assertFalse(completed_process.stdout)
if __name__ == "__main__":
unittest.main()