Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d23ed12467 | ||
|
|
d6248e9cf1 | ||
|
|
3f04a62f68 | ||
|
|
8da192f9ca | ||
|
|
56b6b6dbc2 | ||
|
|
449d0f316c | ||
|
|
e04576de22 | ||
|
|
cf1c6a11f7 | ||
|
|
d29b2b7cf4 | ||
|
|
0477b9bc0c | ||
|
|
ecad17d24e | ||
|
|
485e0a5e56 | ||
|
|
995365c712 |
@ -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"]
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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/
|
||||
|
||||
@ -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
|
||||
----------------------
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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/
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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().
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user