Compare commits
17 Commits
master
...
cherry-pic
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b7236ed1fc | ||
|
|
dc73514cba | ||
|
|
112e29b30f | ||
|
|
ca0ed96eca | ||
|
|
c27fa509fd | ||
|
|
c17011ae7f | ||
|
|
0fa3475835 | ||
|
|
315f3cd1b2 | ||
|
|
736aa56be1 | ||
|
|
d175edff9f | ||
|
|
4a6aae8f43 | ||
|
|
c83f34c826 | ||
|
|
e15b820f71 | ||
|
|
3c9a248bba | ||
|
|
f1a8af160d | ||
|
|
d0301307a0 | ||
|
|
ed21a18172 |
@ -30,8 +30,8 @@ if [ ! -d $BIN_DIR ]; then
|
||||
fi
|
||||
export UV_PYTHON=${PYTHON_BINARY}
|
||||
echo "export UV_PYTHON=$UV_PYTHON" >> $HERE/env.sh
|
||||
echo "Using python $UV_PYTHON"
|
||||
fi
|
||||
echo "Using python $UV_PYTHON"
|
||||
uv sync --frozen
|
||||
uv run --frozen --with pip pip install -e .
|
||||
echo "Setting up python environment... done."
|
||||
|
||||
15
.github/workflows/dist.yml
vendored
15
.github/workflows/dist.yml
vendored
@ -34,12 +34,11 @@ jobs:
|
||||
# Github Actions doesn't support pairing matrix values together, let's improvise
|
||||
# https://github.com/github/feedback/discussions/7835#discussioncomment-1769026
|
||||
buildplat:
|
||||
- [ubuntu-20.04, "manylinux_x86_64", "cp3*-manylinux_x86_64"]
|
||||
- [ubuntu-24.04-arm, "manylinux_aarch64", "cp3*-manylinux_aarch64"]
|
||||
# Disabled pending PYTHON-5058
|
||||
# - [ubuntu-24.04, "manylinux_ppc64le", "cp3*-manylinux_ppc64le"]
|
||||
# - [ubuntu-24.04, "manylinux_s390x", "cp3*-manylinux_s390x"]
|
||||
- [ubuntu-20.04, "manylinux_i686", "cp3*-manylinux_i686"]
|
||||
- [ubuntu-latest, "manylinux_x86_64", "cp3*-manylinux_x86_64"]
|
||||
- [ubuntu-latest, "manylinux_aarch64", "cp3*-manylinux_aarch64"]
|
||||
- [ubuntu-latest, "manylinux_ppc64le", "cp3*-manylinux_ppc64le"]
|
||||
- [ubuntu-latest, "manylinux_s390x", "cp3*-manylinux_s390x"]
|
||||
- [ubuntu-latest, "manylinux_i686", "cp3*-manylinux_i686"]
|
||||
- [windows-2019, "win_amd6", "cp3*-win_amd64"]
|
||||
- [windows-2019, "win32", "cp3*-win32"]
|
||||
- [macos-14, "macos", "cp*-macosx_*"]
|
||||
@ -63,6 +62,10 @@ jobs:
|
||||
if: runner.os == 'Linux'
|
||||
uses: docker/setup-qemu-action@v3
|
||||
with:
|
||||
# setup-qemu-action by default uses `tonistiigi/binfmt:latest` image,
|
||||
# which is out of date. This causes seg faults during build.
|
||||
# Here we manually fix the version.
|
||||
image: tonistiigi/binfmt:qemu-v8.1.5
|
||||
platforms: all
|
||||
|
||||
- name: Install cibuildwheel
|
||||
|
||||
9
.github/workflows/release-python.yml
vendored
9
.github/workflows/release-python.yml
vendored
@ -20,10 +20,12 @@ env:
|
||||
# Changes per repo
|
||||
PRODUCT_NAME: PyMongo
|
||||
# Changes per branch
|
||||
SILK_ASSET_GROUP: mongodb-python-driver
|
||||
EVERGREEN_PROJECT: mongo-python-driver
|
||||
SILK_ASSET_GROUP: mongodb-python-driver-4.11
|
||||
EVERGREEN_PROJECT: mongo-python-driver-release
|
||||
# Constant
|
||||
DRY_RUN: ${{ inputs.dry_run == 'true' }}
|
||||
# inputs will be empty on a scheduled run. so, we only set dry_run
|
||||
# to 'false' when the input is set to 'false'.
|
||||
DRY_RUN: ${{ ! contains(inputs.dry_run, 'false') }}
|
||||
FOLLOWING_VERSION: ${{ inputs.following_version || '' }}
|
||||
VERSION: ${{ inputs.version || '10.10.10.10' }}
|
||||
|
||||
@ -35,6 +37,7 @@ jobs:
|
||||
pre-publish:
|
||||
environment: release
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository_owner == 'mongodb' || github.event_name == 'workflow_dispatch'
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: write
|
||||
|
||||
2
.github/workflows/test-python.yml
vendored
2
.github/workflows/test-python.yml
vendored
@ -54,7 +54,7 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-20.04]
|
||||
os: [ubuntu-latest]
|
||||
python-version: ["3.9", "pypy-3.10", "3.13", "3.13t"]
|
||||
name: CPython ${{ matrix.python-version }}-${{ matrix.os }}
|
||||
steps:
|
||||
|
||||
@ -1,7 +1,26 @@
|
||||
Changelog
|
||||
=========
|
||||
|
||||
Changes in Version 4.11.0 (YYYY/MM/DD)
|
||||
Changes in Version 4.11.2 (YYYY/MM/DD)
|
||||
--------------------------------------
|
||||
|
||||
Version 4.11.2 is a bug fix release.
|
||||
|
||||
- Fixed a bug where :meth:`~pymongo.database.Database.command` would fail when attempting to run the bulkWrite command.
|
||||
|
||||
Issues Resolved
|
||||
...............
|
||||
|
||||
See the `PyMongo 4.11.2 release notes in JIRA`_ for the list of resolved issues in this release.
|
||||
|
||||
.. _PyMongo 4.11.2 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=42506
|
||||
|
||||
Changes in Version 4.11.1 (2025/02/10)
|
||||
--------------------------------------
|
||||
|
||||
- Fixed support for prebuilt ``ppc64le`` and ``s390x`` wheels.
|
||||
|
||||
Changes in Version 4.11.0 (2025/01/28)
|
||||
--------------------------------------
|
||||
|
||||
.. warning:: PyMongo 4.11 drops support for Python 3.8 and PyPy 3.9: Python 3.9+ or PyPy 3.10+ is now required.
|
||||
@ -180,7 +199,7 @@ PyMongo 4.9 brings a number of improvements including:
|
||||
unction-as-a-service (FaaS) like AWS Lambda, Google Cloud Functions, and Microsoft Azure Functions.
|
||||
On some FaaS systems, there is a ``fork()`` operation at function
|
||||
startup. By delaying the connection to the first operation, we avoid a deadlock. See
|
||||
`Is PyMongo Fork-Safe`_ for more information.
|
||||
:ref:`pymongo-fork-safe` for more information.
|
||||
|
||||
|
||||
Issues Resolved
|
||||
@ -189,7 +208,6 @@ Issues Resolved
|
||||
See the `PyMongo 4.9 release notes in JIRA`_ for the list of resolved issues
|
||||
in this release.
|
||||
|
||||
.. _Is PyMongo Fork-Safe : https://www.mongodb.com/docs/languages/python/pymongo-driver/current/faq/#is-pymongo-fork-safe-
|
||||
.. _PyMongo 4.9 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=39940
|
||||
|
||||
|
||||
|
||||
@ -67,6 +67,14 @@ uMongo
|
||||
mongomock. The source `is available on GitHub
|
||||
<https://github.com/Scille/umongo>`_
|
||||
|
||||
Django MongoDB Backend
|
||||
`Django MongoDB Backend <https://django-mongodb-backend.readthedocs.io>`_ is a
|
||||
database backend library specifically made for Django. The integration takes
|
||||
advantage of MongoDB's unique document model capabilities, which align
|
||||
naturally with Django's philosophy of simplified data modeling and
|
||||
reduced development complexity. The source is available
|
||||
`on GitHub <https://github.com/mongodb-labs/django-mongodb-backend>`_.
|
||||
|
||||
No longer maintained
|
||||
""""""""""""""""""""
|
||||
|
||||
|
||||
@ -18,7 +18,7 @@ from __future__ import annotations
|
||||
import re
|
||||
from typing import List, Tuple, Union
|
||||
|
||||
__version__ = "4.11"
|
||||
__version__ = "4.11.3.dev0"
|
||||
|
||||
|
||||
def get_version_tuple(version: str) -> Tuple[Union[int, str], ...]:
|
||||
|
||||
@ -40,6 +40,7 @@ from pymongo.errors import (
|
||||
OperationFailure,
|
||||
PyMongoError,
|
||||
ServerSelectionTimeoutError,
|
||||
WaitQueueTimeoutError,
|
||||
WriteError,
|
||||
)
|
||||
from pymongo.hello import Hello
|
||||
@ -232,9 +233,7 @@ class Topology:
|
||||
warnings.warn( # type: ignore[call-overload] # noqa: B028
|
||||
"AsyncMongoClient opened before fork. May not be entirely fork-safe, "
|
||||
"proceed with caution. See PyMongo's documentation for details: "
|
||||
"https://www.mongodb.com/docs/languages/"
|
||||
"python/pymongo-driver/current/faq/"
|
||||
"#is-pymongo-fork-safe-",
|
||||
"https://dochub.mongodb.org/core/pymongo-fork-deadlock",
|
||||
**kwargs,
|
||||
)
|
||||
async with self._lock:
|
||||
@ -879,6 +878,8 @@ class Topology:
|
||||
# Clear the pool.
|
||||
await server.reset(service_id)
|
||||
elif isinstance(error, ConnectionFailure):
|
||||
if isinstance(error, WaitQueueTimeoutError):
|
||||
return
|
||||
# "Client MUST replace the server's description with type Unknown
|
||||
# ... MUST NOT request an immediate check of the server."
|
||||
if not self._settings.load_balanced:
|
||||
|
||||
@ -105,7 +105,7 @@ _FIELD_MAP = {
|
||||
"insert": "documents",
|
||||
"update": "updates",
|
||||
"delete": "deletes",
|
||||
"bulkWrite": "bulkWrite",
|
||||
"bulkWrite": "ops",
|
||||
}
|
||||
|
||||
_UNICODE_REPLACE_CODEC_OPTIONS: CodecOptions[Mapping[str, Any]] = CodecOptions(
|
||||
|
||||
@ -36,6 +36,7 @@ from pymongo.errors import (
|
||||
OperationFailure,
|
||||
PyMongoError,
|
||||
ServerSelectionTimeoutError,
|
||||
WaitQueueTimeoutError,
|
||||
WriteError,
|
||||
)
|
||||
from pymongo.hello import Hello
|
||||
@ -232,9 +233,7 @@ class Topology:
|
||||
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://www.mongodb.com/docs/languages/"
|
||||
"python/pymongo-driver/current/faq/"
|
||||
"#is-pymongo-fork-safe-",
|
||||
"https://dochub.mongodb.org/core/pymongo-fork-deadlock",
|
||||
**kwargs,
|
||||
)
|
||||
with self._lock:
|
||||
@ -877,6 +876,8 @@ class Topology:
|
||||
# Clear the pool.
|
||||
server.reset(service_id)
|
||||
elif isinstance(error, ConnectionFailure):
|
||||
if isinstance(error, WaitQueueTimeoutError):
|
||||
return
|
||||
# "Client MUST replace the server's description with type Unknown
|
||||
# ... MUST NOT request an immediate check of the server."
|
||||
if not self._settings.load_balanced:
|
||||
|
||||
21
sbom.json
21
sbom.json
@ -1,11 +1,12 @@
|
||||
{
|
||||
"metadata": {
|
||||
"timestamp": "2024-05-02T17:36:12.698229+00:00"
|
||||
},
|
||||
"components": [],
|
||||
"serialNumber": "urn:uuid:9876a8a6-060e-486f-b128-910aecf0fe7b",
|
||||
"version": 1,
|
||||
"$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
|
||||
"bomFormat": "CycloneDX",
|
||||
"specVersion": "1.5"
|
||||
}
|
||||
"metadata": {
|
||||
"timestamp": "2025-02-06T23:38:31.503894+00:00"
|
||||
},
|
||||
"components": [],
|
||||
"serialNumber": "urn:uuid:04738005-86f1-4d21-866f-ce4560f03f00",
|
||||
"version": 1,
|
||||
"$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
|
||||
"bomFormat": "CycloneDX",
|
||||
"specVersion": "1.5",
|
||||
"vulnerabilities": []
|
||||
}
|
||||
|
||||
@ -111,6 +111,7 @@ from pymongo.errors import (
|
||||
NetworkTimeout,
|
||||
OperationFailure,
|
||||
ServerSelectionTimeoutError,
|
||||
WaitQueueTimeoutError,
|
||||
WriteConcernError,
|
||||
)
|
||||
from pymongo.monitoring import ServerHeartbeatListener, ServerHeartbeatStartedEvent
|
||||
@ -1311,8 +1312,16 @@ class TestClient(AsyncIntegrationTest):
|
||||
self.assertAlmostEqual(30, client.options.server_selection_timeout)
|
||||
|
||||
async def test_waitQueueTimeoutMS(self):
|
||||
client = await self.async_rs_or_single_client(waitQueueTimeoutMS=2000)
|
||||
self.assertEqual((await async_get_pool(client)).opts.wait_queue_timeout, 2)
|
||||
listener = CMAPListener()
|
||||
client = await self.async_rs_or_single_client(
|
||||
waitQueueTimeoutMS=10, maxPoolSize=1, event_listeners=[listener]
|
||||
)
|
||||
pool = await async_get_pool(client)
|
||||
self.assertEqual(pool.opts.wait_queue_timeout, 0.01)
|
||||
async with pool.checkout():
|
||||
with self.assertRaises(WaitQueueTimeoutError):
|
||||
await client.test.command("ping")
|
||||
self.assertFalse(listener.events_by_type(monitoring.PoolClearedEvent))
|
||||
|
||||
async def test_socketKeepAlive(self):
|
||||
pool = await async_get_pool(self.client)
|
||||
|
||||
@ -430,6 +430,21 @@ class TestDatabase(AsyncIntegrationTest):
|
||||
for doc in result["cursor"]["firstBatch"]:
|
||||
self.assertTrue(isinstance(doc["r"], Regex))
|
||||
|
||||
async def test_command_bulkWrite(self):
|
||||
# Ensure bulk write commands can be run directly via db.command().
|
||||
if async_client_context.version.at_least(8, 0):
|
||||
await self.client.admin.command(
|
||||
{
|
||||
"bulkWrite": 1,
|
||||
"nsInfo": [{"ns": self.db.test.full_name}],
|
||||
"ops": [{"insert": 0, "document": {}}],
|
||||
}
|
||||
)
|
||||
await self.db.command({"insert": "test", "documents": [{}]})
|
||||
await self.db.command({"update": "test", "updates": [{"q": {}, "u": {"$set": {"x": 1}}}]})
|
||||
await self.db.command({"delete": "test", "deletes": [{"q": {}, "limit": 1}]})
|
||||
await self.db.test.drop()
|
||||
|
||||
async def test_cursor_command(self):
|
||||
db = self.client.pymongo_test
|
||||
await db.test.drop()
|
||||
|
||||
@ -2982,9 +2982,10 @@ class TestAutomaticDecryptionKeys(AsyncEncryptionIntegrationTest):
|
||||
)
|
||||
|
||||
async def test_03_invalid_keyid(self):
|
||||
# checkAuthForCreateCollection can be removed when SERVER-102101 is fixed.
|
||||
with self.assertRaisesRegex(
|
||||
EncryptedCollectionError,
|
||||
"create.encryptedFields.fields.keyId' is the wrong type 'bool', expected type 'binData",
|
||||
"(create|checkAuthForCreateCollection).encryptedFields.fields.keyId' is the wrong type 'bool', expected type 'binData",
|
||||
):
|
||||
await self.client_encryption.create_encrypted_collection(
|
||||
database=self.db,
|
||||
|
||||
@ -100,6 +100,7 @@ from pymongo.errors import (
|
||||
NetworkTimeout,
|
||||
OperationFailure,
|
||||
ServerSelectionTimeoutError,
|
||||
WaitQueueTimeoutError,
|
||||
WriteConcernError,
|
||||
)
|
||||
from pymongo.monitoring import ServerHeartbeatListener, ServerHeartbeatStartedEvent
|
||||
@ -1270,8 +1271,16 @@ class TestClient(IntegrationTest):
|
||||
self.assertAlmostEqual(30, client.options.server_selection_timeout)
|
||||
|
||||
def test_waitQueueTimeoutMS(self):
|
||||
client = self.rs_or_single_client(waitQueueTimeoutMS=2000)
|
||||
self.assertEqual((get_pool(client)).opts.wait_queue_timeout, 2)
|
||||
listener = CMAPListener()
|
||||
client = self.rs_or_single_client(
|
||||
waitQueueTimeoutMS=10, maxPoolSize=1, event_listeners=[listener]
|
||||
)
|
||||
pool = get_pool(client)
|
||||
self.assertEqual(pool.opts.wait_queue_timeout, 0.01)
|
||||
with pool.checkout():
|
||||
with self.assertRaises(WaitQueueTimeoutError):
|
||||
client.test.command("ping")
|
||||
self.assertFalse(listener.events_by_type(monitoring.PoolClearedEvent))
|
||||
|
||||
def test_socketKeepAlive(self):
|
||||
pool = get_pool(self.client)
|
||||
|
||||
@ -425,6 +425,21 @@ class TestDatabase(IntegrationTest):
|
||||
for doc in result["cursor"]["firstBatch"]:
|
||||
self.assertTrue(isinstance(doc["r"], Regex))
|
||||
|
||||
def test_command_bulkWrite(self):
|
||||
# Ensure bulk write commands can be run directly via db.command().
|
||||
if client_context.version.at_least(8, 0):
|
||||
self.client.admin.command(
|
||||
{
|
||||
"bulkWrite": 1,
|
||||
"nsInfo": [{"ns": self.db.test.full_name}],
|
||||
"ops": [{"insert": 0, "document": {}}],
|
||||
}
|
||||
)
|
||||
self.db.command({"insert": "test", "documents": [{}]})
|
||||
self.db.command({"update": "test", "updates": [{"q": {}, "u": {"$set": {"x": 1}}}]})
|
||||
self.db.command({"delete": "test", "deletes": [{"q": {}, "limit": 1}]})
|
||||
self.db.test.drop()
|
||||
|
||||
def test_cursor_command(self):
|
||||
db = self.client.pymongo_test
|
||||
db.test.drop()
|
||||
|
||||
@ -2964,9 +2964,10 @@ class TestAutomaticDecryptionKeys(EncryptionIntegrationTest):
|
||||
)
|
||||
|
||||
def test_03_invalid_keyid(self):
|
||||
# checkAuthForCreateCollection can be removed when SERVER-102101 is fixed.
|
||||
with self.assertRaisesRegex(
|
||||
EncryptedCollectionError,
|
||||
"create.encryptedFields.fields.keyId' is the wrong type 'bool', expected type 'binData",
|
||||
"(create|checkAuthForCreateCollection).encryptedFields.fields.keyId' is the wrong type 'bool', expected type 'binData",
|
||||
):
|
||||
self.client_encryption.create_encrypted_collection(
|
||||
database=self.db,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user