Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
27fac499c1 | ||
|
|
0d2a4b462e | ||
|
|
550d234f71 | ||
|
|
d98049c630 | ||
|
|
f66ec0ff23 | ||
|
|
6611bec9e7 | ||
|
|
7692bd67b9 | ||
|
|
aa0b920566 | ||
|
|
1c480163f4 | ||
|
|
7055ad1944 | ||
|
|
e80f4f4199 | ||
|
|
c4e866d5d7 | ||
|
|
ce2812d974 | ||
|
|
952fa82c24 | ||
|
|
6354d6cae7 |
@ -535,6 +535,8 @@ buildvariants:
|
|||||||
display_name: "* MongoDB v4.2"
|
display_name: "* MongoDB v4.2"
|
||||||
run_on:
|
run_on:
|
||||||
- rhel87-small
|
- rhel87-small
|
||||||
|
expansions:
|
||||||
|
VERSION: "4.2"
|
||||||
tags: [coverage_tag]
|
tags: [coverage_tag]
|
||||||
- name: mongodb-v4.4
|
- name: mongodb-v4.4
|
||||||
tasks:
|
tasks:
|
||||||
@ -542,6 +544,8 @@ buildvariants:
|
|||||||
display_name: "* MongoDB v4.4"
|
display_name: "* MongoDB v4.4"
|
||||||
run_on:
|
run_on:
|
||||||
- rhel87-small
|
- rhel87-small
|
||||||
|
expansions:
|
||||||
|
VERSION: "4.4"
|
||||||
tags: [coverage_tag]
|
tags: [coverage_tag]
|
||||||
- name: mongodb-v5.0
|
- name: mongodb-v5.0
|
||||||
tasks:
|
tasks:
|
||||||
@ -549,6 +553,8 @@ buildvariants:
|
|||||||
display_name: "* MongoDB v5.0"
|
display_name: "* MongoDB v5.0"
|
||||||
run_on:
|
run_on:
|
||||||
- rhel87-small
|
- rhel87-small
|
||||||
|
expansions:
|
||||||
|
VERSION: "5.0"
|
||||||
tags: [coverage_tag]
|
tags: [coverage_tag]
|
||||||
- name: mongodb-v6.0
|
- name: mongodb-v6.0
|
||||||
tasks:
|
tasks:
|
||||||
@ -556,6 +562,8 @@ buildvariants:
|
|||||||
display_name: "* MongoDB v6.0"
|
display_name: "* MongoDB v6.0"
|
||||||
run_on:
|
run_on:
|
||||||
- rhel87-small
|
- rhel87-small
|
||||||
|
expansions:
|
||||||
|
VERSION: "6.0"
|
||||||
tags: [coverage_tag]
|
tags: [coverage_tag]
|
||||||
- name: mongodb-v7.0
|
- name: mongodb-v7.0
|
||||||
tasks:
|
tasks:
|
||||||
@ -563,6 +571,8 @@ buildvariants:
|
|||||||
display_name: "* MongoDB v7.0"
|
display_name: "* MongoDB v7.0"
|
||||||
run_on:
|
run_on:
|
||||||
- rhel87-small
|
- rhel87-small
|
||||||
|
expansions:
|
||||||
|
VERSION: "7.0"
|
||||||
tags: [coverage_tag]
|
tags: [coverage_tag]
|
||||||
- name: mongodb-v8.0
|
- name: mongodb-v8.0
|
||||||
tasks:
|
tasks:
|
||||||
@ -570,6 +580,8 @@ buildvariants:
|
|||||||
display_name: "* MongoDB v8.0"
|
display_name: "* MongoDB v8.0"
|
||||||
run_on:
|
run_on:
|
||||||
- rhel87-small
|
- rhel87-small
|
||||||
|
expansions:
|
||||||
|
VERSION: "8.0"
|
||||||
tags: [coverage_tag]
|
tags: [coverage_tag]
|
||||||
- name: mongodb-rapid
|
- name: mongodb-rapid
|
||||||
tasks:
|
tasks:
|
||||||
@ -577,6 +589,8 @@ buildvariants:
|
|||||||
display_name: "* MongoDB rapid"
|
display_name: "* MongoDB rapid"
|
||||||
run_on:
|
run_on:
|
||||||
- rhel87-small
|
- rhel87-small
|
||||||
|
expansions:
|
||||||
|
VERSION: rapid
|
||||||
tags: [coverage_tag]
|
tags: [coverage_tag]
|
||||||
- name: mongodb-latest
|
- name: mongodb-latest
|
||||||
tasks:
|
tasks:
|
||||||
@ -584,6 +598,8 @@ buildvariants:
|
|||||||
display_name: "* MongoDB latest"
|
display_name: "* MongoDB latest"
|
||||||
run_on:
|
run_on:
|
||||||
- rhel87-small
|
- rhel87-small
|
||||||
|
expansions:
|
||||||
|
VERSION: latest
|
||||||
tags: [coverage_tag]
|
tags: [coverage_tag]
|
||||||
|
|
||||||
# Stable api tests
|
# Stable api tests
|
||||||
|
|||||||
@ -8,7 +8,9 @@ if [ ${OIDC_ENV} == "k8s" ]; then
|
|||||||
SUB_TEST_NAME=$K8S_VARIANT-remote
|
SUB_TEST_NAME=$K8S_VARIANT-remote
|
||||||
else
|
else
|
||||||
SUB_TEST_NAME=$OIDC_ENV-remote
|
SUB_TEST_NAME=$OIDC_ENV-remote
|
||||||
|
sudo apt-get install -y python3-dev build-essential
|
||||||
fi
|
fi
|
||||||
|
|
||||||
bash ./.evergreen/just.sh setup-tests auth_oidc $SUB_TEST_NAME
|
bash ./.evergreen/just.sh setup-tests auth_oidc $SUB_TEST_NAME
|
||||||
bash ./.evergreen/just.sh run-tests "${@:1}"
|
bash ./.evergreen/just.sh run-tests "${@:1}"
|
||||||
|
|
||||||
|
|||||||
@ -74,7 +74,11 @@ def create_server_version_variants() -> list[BuildVariant]:
|
|||||||
for version in ALL_VERSIONS:
|
for version in ALL_VERSIONS:
|
||||||
display_name = get_variant_name("* MongoDB", version=version)
|
display_name = get_variant_name("* MongoDB", version=version)
|
||||||
variant = create_variant(
|
variant = create_variant(
|
||||||
[".server-version"], display_name, host=DEFAULT_HOST, tags=["coverage_tag"]
|
[".server-version"],
|
||||||
|
display_name,
|
||||||
|
version=version,
|
||||||
|
host=DEFAULT_HOST,
|
||||||
|
tags=["coverage_tag"],
|
||||||
)
|
)
|
||||||
variants.append(variant)
|
variants.append(variant)
|
||||||
return variants
|
return variants
|
||||||
|
|||||||
@ -48,9 +48,12 @@ if ! command -v just &>/dev/null; then
|
|||||||
_TARGET="--target x86_64-pc-windows-msvc"
|
_TARGET="--target x86_64-pc-windows-msvc"
|
||||||
fi
|
fi
|
||||||
_BIN_DIR=$PYMONGO_BIN_DIR
|
_BIN_DIR=$PYMONGO_BIN_DIR
|
||||||
|
mkdir -p ${_BIN_DIR}
|
||||||
echo "Installing just..."
|
echo "Installing just..."
|
||||||
mkdir -p "$_BIN_DIR" 2>/dev/null || true
|
mkdir -p "$_BIN_DIR" 2>/dev/null || true
|
||||||
curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- $_TARGET --to "$_BIN_DIR" || {
|
curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- $_TARGET --to "$_BIN_DIR" || {
|
||||||
|
# Remove just file if it exists (can be created if there was an install error).
|
||||||
|
rm -f ${_BIN_DIR}/just
|
||||||
_pip_install rust-just just
|
_pip_install rust-just just
|
||||||
}
|
}
|
||||||
echo "Installing just... done."
|
echo "Installing just... done."
|
||||||
@ -59,6 +62,7 @@ fi
|
|||||||
# Ensure uv is installed.
|
# Ensure uv is installed.
|
||||||
if ! command -v uv &>/dev/null; then
|
if ! command -v uv &>/dev/null; then
|
||||||
_BIN_DIR=$PYMONGO_BIN_DIR
|
_BIN_DIR=$PYMONGO_BIN_DIR
|
||||||
|
mkdir -p ${_BIN_DIR}
|
||||||
echo "Installing uv..."
|
echo "Installing uv..."
|
||||||
# On most systems we can install directly.
|
# On most systems we can install directly.
|
||||||
curl -LsSf https://astral.sh/uv/install.sh | env UV_INSTALL_DIR="$_BIN_DIR" INSTALLER_NO_MODIFY_PATH=1 sh || {
|
curl -LsSf https://astral.sh/uv/install.sh | env UV_INSTALL_DIR="$_BIN_DIR" INSTALLER_NO_MODIFY_PATH=1 sh || {
|
||||||
|
|||||||
@ -30,6 +30,9 @@ def _setup_azure_vm(base_env: dict[str, str]) -> None:
|
|||||||
env["AZUREKMS_CMD"] = "tar xf mongo-python-driver.tgz"
|
env["AZUREKMS_CMD"] = "tar xf mongo-python-driver.tgz"
|
||||||
run_command(f"{azure_dir}/run-command.sh", env=env)
|
run_command(f"{azure_dir}/run-command.sh", env=env)
|
||||||
|
|
||||||
|
env["AZUREKMS_CMD"] = "sudo apt-get install -y python3-dev build-essential"
|
||||||
|
run_command(f"{azure_dir}/run-command.sh", env=env)
|
||||||
|
|
||||||
env["AZUREKMS_CMD"] = "bash .evergreen/just.sh setup-tests kms azure-remote"
|
env["AZUREKMS_CMD"] = "bash .evergreen/just.sh setup-tests kms azure-remote"
|
||||||
run_command(f"{azure_dir}/run-command.sh", env=env)
|
run_command(f"{azure_dir}/run-command.sh", env=env)
|
||||||
LOGGER.info("Setting up Azure VM... done.")
|
LOGGER.info("Setting up Azure VM... done.")
|
||||||
@ -47,6 +50,9 @@ def _setup_gcp_vm(base_env: dict[str, str]) -> None:
|
|||||||
env["GCPKMS_CMD"] = "tar xf mongo-python-driver.tgz"
|
env["GCPKMS_CMD"] = "tar xf mongo-python-driver.tgz"
|
||||||
run_command(f"{gcp_dir}/run-command.sh", env=env)
|
run_command(f"{gcp_dir}/run-command.sh", env=env)
|
||||||
|
|
||||||
|
env["GCPKMS_CMD"] = "sudo apt-get install -y python3-dev build-essential"
|
||||||
|
run_command(f"{gcp_dir}/run-command.sh", env=env)
|
||||||
|
|
||||||
env["GCPKMS_CMD"] = "bash ./.evergreen/just.sh setup-tests kms gcp-remote"
|
env["GCPKMS_CMD"] = "bash ./.evergreen/just.sh setup-tests kms gcp-remote"
|
||||||
run_command(f"{gcp_dir}/run-command.sh", env=env)
|
run_command(f"{gcp_dir}/run-command.sh", env=env)
|
||||||
LOGGER.info("Setting up GCP VM...")
|
LOGGER.info("Setting up GCP VM...")
|
||||||
|
|||||||
@ -2,7 +2,14 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from utils import DRIVERS_TOOLS, TMP_DRIVER_FILE, create_archive, read_env, run_command, write_env
|
from utils import (
|
||||||
|
DRIVERS_TOOLS,
|
||||||
|
TMP_DRIVER_FILE,
|
||||||
|
create_archive,
|
||||||
|
read_env,
|
||||||
|
run_command,
|
||||||
|
write_env,
|
||||||
|
)
|
||||||
|
|
||||||
K8S_NAMES = ["aks", "gke", "eks"]
|
K8S_NAMES = ["aks", "gke", "eks"]
|
||||||
K8S_REMOTE_NAMES = [f"{n}-remote" for n in K8S_NAMES]
|
K8S_REMOTE_NAMES = [f"{n}-remote" for n in K8S_NAMES]
|
||||||
|
|||||||
99
.evergreen/spec-patch/PYTHON-5493.patch
Normal file
99
.evergreen/spec-patch/PYTHON-5493.patch
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
diff --git a/test/connection_logging/connection-logging.json b/test/connection_logging/connection-logging.json
|
||||||
|
index d40cfbb7e..5799e834d 100644
|
||||||
|
--- a/test/connection_logging/connection-logging.json
|
||||||
|
+++ b/test/connection_logging/connection-logging.json
|
||||||
|
@@ -272,7 +272,13 @@
|
||||||
|
"level": "debug",
|
||||||
|
"component": "connection",
|
||||||
|
"data": {
|
||||||
|
- "message": "Connection pool closed",
|
||||||
|
+ "message": "Connection closed",
|
||||||
|
+ "driverConnectionId": {
|
||||||
|
+ "$$type": [
|
||||||
|
+ "int",
|
||||||
|
+ "long"
|
||||||
|
+ ]
|
||||||
|
+ },
|
||||||
|
"serverHost": {
|
||||||
|
"$$type": "string"
|
||||||
|
},
|
||||||
|
@@ -281,20 +287,15 @@
|
||||||
|
"int",
|
||||||
|
"long"
|
||||||
|
]
|
||||||
|
- }
|
||||||
|
+ },
|
||||||
|
+ "reason": "Connection pool was closed"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": "debug",
|
||||||
|
"component": "connection",
|
||||||
|
"data": {
|
||||||
|
- "message": "Connection closed",
|
||||||
|
- "driverConnectionId": {
|
||||||
|
- "$$type": [
|
||||||
|
- "int",
|
||||||
|
- "long"
|
||||||
|
- ]
|
||||||
|
- },
|
||||||
|
+ "message": "Connection pool closed",
|
||||||
|
"serverHost": {
|
||||||
|
"$$type": "string"
|
||||||
|
},
|
||||||
|
@@ -303,8 +304,7 @@
|
||||||
|
"int",
|
||||||
|
"long"
|
||||||
|
]
|
||||||
|
- },
|
||||||
|
- "reason": "Connection pool was closed"
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
@@ -446,22 +446,6 @@
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
- {
|
||||||
|
- "level": "debug",
|
||||||
|
- "component": "connection",
|
||||||
|
- "data": {
|
||||||
|
- "message": "Connection pool cleared",
|
||||||
|
- "serverHost": {
|
||||||
|
- "$$type": "string"
|
||||||
|
- },
|
||||||
|
- "serverPort": {
|
||||||
|
- "$$type": [
|
||||||
|
- "int",
|
||||||
|
- "long"
|
||||||
|
- ]
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- },
|
||||||
|
{
|
||||||
|
"level": "debug",
|
||||||
|
"component": "connection",
|
||||||
|
@@ -514,6 +498,22 @@
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ "level": "debug",
|
||||||
|
+ "component": "connection",
|
||||||
|
+ "data": {
|
||||||
|
+ "message": "Connection pool cleared",
|
||||||
|
+ "serverHost": {
|
||||||
|
+ "$$type": "string"
|
||||||
|
+ },
|
||||||
|
+ "serverPort": {
|
||||||
|
+ "$$type": [
|
||||||
|
+ "int",
|
||||||
|
+ "long"
|
||||||
|
+ ]
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
2
.github/workflows/release-python.yml
vendored
2
.github/workflows/release-python.yml
vendored
@ -16,7 +16,7 @@ env:
|
|||||||
# Changes per repo
|
# Changes per repo
|
||||||
PRODUCT_NAME: PyMongo
|
PRODUCT_NAME: PyMongo
|
||||||
# Changes per branch
|
# Changes per branch
|
||||||
EVERGREEN_PROJECT: mongo-python-driver
|
EVERGREEN_PROJECT: mongo-python-driver-release
|
||||||
# Constant
|
# Constant
|
||||||
# inputs will be empty on a scheduled run. so, we only set dry_run
|
# inputs will be empty on a scheduled run. so, we only set dry_run
|
||||||
# to 'false' when the input is set to 'false'.
|
# to 'false' when the input is set to 'false'.
|
||||||
|
|||||||
54
.github/workflows/test-python.yml
vendored
54
.github/workflows/test-python.yml
vendored
@ -22,13 +22,13 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- name: Install just
|
|
||||||
uses: extractions/setup-just@e33e0265a09d6d736e2ee1e0eb685ef1de4669ff # v3
|
|
||||||
- name: Install uv
|
- name: Install uv
|
||||||
uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v5
|
uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v5
|
||||||
with:
|
with:
|
||||||
enable-cache: true
|
enable-cache: true
|
||||||
python-version: "3.9"
|
python-version: "3.9"
|
||||||
|
- name: Install just
|
||||||
|
run: uv tool install rust-just
|
||||||
- name: Install Python dependencies
|
- name: Install Python dependencies
|
||||||
run: |
|
run: |
|
||||||
just install
|
just install
|
||||||
@ -50,33 +50,31 @@ jobs:
|
|||||||
cppcheck pymongo
|
cppcheck pymongo
|
||||||
|
|
||||||
build:
|
build:
|
||||||
# supercharge/mongodb-github-action requires containers so we don't test other platforms
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
|
# Tests currently only pass on ubuntu on GitHub Actions.
|
||||||
os: [ubuntu-latest]
|
os: [ubuntu-latest]
|
||||||
python-version: ["3.9", "pypy-3.10", "3.13", "3.13t"]
|
python-version: ["3.9", "pypy-3.10", "3.13t"]
|
||||||
|
mongodb-version: ["8.0"]
|
||||||
|
|
||||||
name: CPython ${{ matrix.python-version }}-${{ matrix.os }}
|
name: CPython ${{ matrix.python-version }}-${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- name: Install just
|
|
||||||
uses: extractions/setup-just@e33e0265a09d6d736e2ee1e0eb685ef1de4669ff # v3
|
|
||||||
- name: Install uv
|
- name: Install uv
|
||||||
uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v5
|
uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v5
|
||||||
with:
|
with:
|
||||||
enable-cache: true
|
enable-cache: true
|
||||||
python-version: ${{ matrix.python-version }}
|
python-version: ${{ matrix.python-version }}
|
||||||
- name: Install dependencies
|
- id: setup-mongodb
|
||||||
run: just install
|
uses: mongodb-labs/drivers-evergreen-tools@master
|
||||||
- name: Start MongoDB
|
|
||||||
uses: supercharge/mongodb-github-action@90004df786821b6308fb02299e5835d0dae05d0d # 1.12.0
|
|
||||||
with:
|
with:
|
||||||
mongodb-version: 6.0
|
version: "${{ matrix.mongodb-version }}"
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: just test
|
run: uv run --extra test pytest -v
|
||||||
|
|
||||||
doctest:
|
doctest:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@ -85,17 +83,17 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- name: Install just
|
|
||||||
uses: extractions/setup-just@e33e0265a09d6d736e2ee1e0eb685ef1de4669ff # v3
|
|
||||||
- name: Install uv
|
- name: Install uv
|
||||||
uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v5
|
uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v5
|
||||||
with:
|
with:
|
||||||
enable-cache: true
|
enable-cache: true
|
||||||
python-version: "3.9"
|
python-version: "3.9"
|
||||||
- name: Start MongoDB
|
- name: Install just
|
||||||
uses: supercharge/mongodb-github-action@90004df786821b6308fb02299e5835d0dae05d0d # 1.12.0
|
run: uv tool install rust-just
|
||||||
|
- id: setup-mongodb
|
||||||
|
uses: mongodb-labs/drivers-evergreen-tools@master
|
||||||
with:
|
with:
|
||||||
mongodb-version: '8.0.0-rc4'
|
version: "8.0"
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: just install
|
run: just install
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
@ -116,7 +114,7 @@ jobs:
|
|||||||
enable-cache: true
|
enable-cache: true
|
||||||
python-version: "3.9"
|
python-version: "3.9"
|
||||||
- name: Install just
|
- name: Install just
|
||||||
uses: extractions/setup-just@e33e0265a09d6d736e2ee1e0eb685ef1de4669ff # v3
|
run: uv tool install rust-just
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: just install
|
run: just install
|
||||||
- name: Build docs
|
- name: Build docs
|
||||||
@ -135,7 +133,7 @@ jobs:
|
|||||||
enable-cache: true
|
enable-cache: true
|
||||||
python-version: "3.9"
|
python-version: "3.9"
|
||||||
- name: Install just
|
- name: Install just
|
||||||
uses: extractions/setup-just@e33e0265a09d6d736e2ee1e0eb685ef1de4669ff # v3
|
run: uv tool install rust-just
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: just install
|
run: just install
|
||||||
- name: Build docs
|
- name: Build docs
|
||||||
@ -157,7 +155,7 @@ jobs:
|
|||||||
enable-cache: true
|
enable-cache: true
|
||||||
python-version: "${{matrix.python}}"
|
python-version: "${{matrix.python}}"
|
||||||
- name: Install just
|
- name: Install just
|
||||||
uses: extractions/setup-just@e33e0265a09d6d736e2ee1e0eb685ef1de4669ff # v3
|
run: uv tool install rust-just
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
just install
|
just install
|
||||||
@ -210,8 +208,8 @@ jobs:
|
|||||||
cache-dependency-path: 'sdist/test/pyproject.toml'
|
cache-dependency-path: 'sdist/test/pyproject.toml'
|
||||||
# Test sdist on lowest supported Python
|
# Test sdist on lowest supported Python
|
||||||
python-version: '3.9'
|
python-version: '3.9'
|
||||||
- name: Start MongoDB
|
- id: setup-mongodb
|
||||||
uses: supercharge/mongodb-github-action@90004df786821b6308fb02299e5835d0dae05d0d # 1.12.0
|
uses: mongodb-labs/drivers-evergreen-tools@master
|
||||||
- name: Run connect test from sdist
|
- name: Run connect test from sdist
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
@ -234,10 +232,10 @@ jobs:
|
|||||||
uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v5
|
uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v5
|
||||||
with:
|
with:
|
||||||
python-version: '3.9'
|
python-version: '3.9'
|
||||||
- name: Start MongoDB
|
- id: setup-mongodb
|
||||||
uses: supercharge/mongodb-github-action@90004df786821b6308fb02299e5835d0dae05d0d # 1.12.0
|
uses: mongodb-labs/drivers-evergreen-tools@master
|
||||||
with:
|
with:
|
||||||
mongodb-version: 6.0
|
version: "8.0"
|
||||||
# Async and our test_dns do not support dnspython 1.X, so we don't run async or dns tests here
|
# Async and our test_dns do not support dnspython 1.X, so we don't run async or dns tests here
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
shell: bash
|
shell: bash
|
||||||
@ -260,10 +258,10 @@ jobs:
|
|||||||
uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v5
|
uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v5
|
||||||
with:
|
with:
|
||||||
python-version: '3.9'
|
python-version: '3.9'
|
||||||
- name: Start MongoDB
|
- id: setup-mongodb
|
||||||
uses: supercharge/mongodb-github-action@90004df786821b6308fb02299e5835d0dae05d0d # 1.12.0
|
uses: mongodb-labs/drivers-evergreen-tools@master
|
||||||
with:
|
with:
|
||||||
mongodb-version: 6.0
|
version: "8.0"
|
||||||
# The lifetime kwarg we use in srv resolution was added to the async resolver API in dnspython 2.1.0
|
# The lifetime kwarg we use in srv resolution was added to the async resolver API in dnspython 2.1.0
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|||||||
7
.github/zizmor.yml
vendored
Normal file
7
.github/zizmor.yml
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
rules:
|
||||||
|
unpinned-uses:
|
||||||
|
config:
|
||||||
|
policies:
|
||||||
|
actions/*: ref-pin
|
||||||
|
mongodb-labs/drivers-github-tools/*: ref-pin
|
||||||
|
mongodb-labs/drivers-evergreen-tools: ref-pin
|
||||||
@ -1,25 +1,61 @@
|
|||||||
Changelog
|
Changelog
|
||||||
=========
|
=========
|
||||||
|
Changes in Version 4.14.1 (2025/08/19)
|
||||||
Changes in Version 4.14.0 (XXXX/XX/XX)
|
|
||||||
--------------------------------------
|
--------------------------------------
|
||||||
|
|
||||||
|
Version 4.14.1 is a bug fix release.
|
||||||
|
|
||||||
|
- Fixed a bug in ``MongoClient.append_metadata()`` and ``AsyncMongoClient.append_metadata()``
|
||||||
|
that allowed duplicate ``DriverInfo.name`` to be appended to the metadata.
|
||||||
|
|
||||||
|
Issues Resolved
|
||||||
|
...............
|
||||||
|
|
||||||
|
See the `PyMongo 4.14.1 release notes in JIRA`_ for the list of resolved issues
|
||||||
|
in this release.
|
||||||
|
|
||||||
|
.. _PyMongo 4.14.1 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=45256
|
||||||
|
|
||||||
|
Changes in Version 4.14.0 (2025/08/06)
|
||||||
|
--------------------------------------
|
||||||
|
|
||||||
|
.. warning:: PyMongo 4.14 drops support for MongoDB 4.0. PyMongo now supports
|
||||||
|
MongoDB 4.2+.
|
||||||
|
|
||||||
PyMongo 4.14 brings a number of changes including:
|
PyMongo 4.14 brings a number of changes including:
|
||||||
|
|
||||||
- Added preliminary support for Python 3.14 and 3.14 with free-threading. We do not yet support the following with Python 3.14:
|
- Dropped support for MongoDB 4.0.
|
||||||
- Subinterpreters (``concurrent.interpreters``)
|
- Added preliminary support for Python 3.14 and 3.14 with free-threading. We do
|
||||||
- Free-threading with Encryption
|
not yet support the following with Python 3.14:
|
||||||
- mod_wsgi
|
|
||||||
- Removed experimental support for free-threading support in Python 3.13.
|
|
||||||
- Added :attr:`bson.codec_options.TypeRegistry.codecs` and :attr:`bson.codec_options.TypeRegistry.fallback_encoder` properties
|
|
||||||
to allow users to directly access the type codecs and fallback encoder for a given :class:`bson.codec_options.TypeRegistry`.
|
|
||||||
- Added :meth:`pymongo.asynchronous.mongo_client.AsyncMongoClient.append_metadata` and
|
|
||||||
:meth:`pymongo.mongo_client.MongoClient.append_metadata` to allow instantiated MongoClients to send client metadata
|
|
||||||
on-demand
|
|
||||||
- Improved performance of selecting a server with the Primary selector.
|
|
||||||
|
|
||||||
- Introduces a minor breaking change. When encoding :class:`bson.binary.BinaryVector`, a ``ValueError`` will be raised
|
- Subinterpreters (``concurrent.interpreters``)
|
||||||
if the 'padding' metadata field is < 0 or > 7, or non-zero for any type other than PACKED_BIT.
|
- Free-threading with Encryption
|
||||||
- Changed :meth:`~pymongo.uri_parser.parse_uri`'s ``options`` parameter to be type ``dict`` instead of ``_CaseInsensitiveDictionary``.
|
- mod_wsgi
|
||||||
|
|
||||||
|
- Removed experimental support for free-threading support in Python 3.13.
|
||||||
|
- Added :attr:`bson.codec_options.TypeRegistry.codecs` and
|
||||||
|
:attr:`bson.codec_options.TypeRegistry.fallback_encoder` properties
|
||||||
|
to allow users to directly access the type codecs and fallback encoder for a
|
||||||
|
given :class:`bson.codec_options.TypeRegistry`.
|
||||||
|
- Added
|
||||||
|
:meth:`pymongo.asynchronous.mongo_client.AsyncMongoClient.append_metadata` and
|
||||||
|
:meth:`pymongo.mongo_client.MongoClient.append_metadata` to allow instantiated
|
||||||
|
MongoClients to send client metadata on-demand
|
||||||
|
- Improved performance of selecting a server with the Primary selector.
|
||||||
|
- Introduces a minor breaking change. When encoding
|
||||||
|
:class:`bson.binary.BinaryVector`, a ``ValueError`` will be raised if the
|
||||||
|
'padding' metadata field is < 0 or > 7, or non-zero for any type other than
|
||||||
|
PACKED_BIT.
|
||||||
|
- Changed :meth:`~pymongo.uri_parser.parse_uri`'s ``options`` return value to be
|
||||||
|
type ``dict`` instead of ``_CaseInsensitiveDictionary``.
|
||||||
|
|
||||||
|
Issues Resolved
|
||||||
|
...............
|
||||||
|
|
||||||
|
See the `PyMongo 4.14 release notes in JIRA`_ for the list of resolved issues
|
||||||
|
in this release.
|
||||||
|
|
||||||
|
.. _PyMongo 4.14 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=43041
|
||||||
|
|
||||||
Changes in Version 4.13.2 (2025/06/17)
|
Changes in Version 4.13.2 (2025/06/17)
|
||||||
--------------------------------------
|
--------------------------------------
|
||||||
|
|||||||
@ -18,7 +18,7 @@ from __future__ import annotations
|
|||||||
import re
|
import re
|
||||||
from typing import List, Tuple, Union
|
from typing import List, Tuple, Union
|
||||||
|
|
||||||
__version__ = "4.14.0.dev0"
|
__version__ = "4.14.2.dev0"
|
||||||
|
|
||||||
|
|
||||||
def get_version_tuple(version: str) -> Tuple[Union[int, str], ...]:
|
def get_version_tuple(version: str) -> Tuple[Union[int, str], ...]:
|
||||||
|
|||||||
@ -75,12 +75,12 @@ from pymongo.errors import (
|
|||||||
NetworkTimeout,
|
NetworkTimeout,
|
||||||
ServerSelectionTimeoutError,
|
ServerSelectionTimeoutError,
|
||||||
)
|
)
|
||||||
|
from pymongo.helpers_shared import _get_timeout_details
|
||||||
from pymongo.network_layer import async_socket_sendall
|
from pymongo.network_layer import async_socket_sendall
|
||||||
from pymongo.operations import UpdateOne
|
from pymongo.operations import UpdateOne
|
||||||
from pymongo.pool_options import PoolOptions
|
from pymongo.pool_options import PoolOptions
|
||||||
from pymongo.pool_shared import (
|
from pymongo.pool_shared import (
|
||||||
_async_configured_socket,
|
_async_configured_socket,
|
||||||
_get_timeout_details,
|
|
||||||
_raise_connection_failure,
|
_raise_connection_failure,
|
||||||
)
|
)
|
||||||
from pymongo.read_concern import ReadConcern
|
from pymongo.read_concern import ReadConcern
|
||||||
|
|||||||
@ -58,6 +58,7 @@ from pymongo.errors import ( # type:ignore[attr-defined]
|
|||||||
WaitQueueTimeoutError,
|
WaitQueueTimeoutError,
|
||||||
)
|
)
|
||||||
from pymongo.hello import Hello, HelloCompat
|
from pymongo.hello import Hello, HelloCompat
|
||||||
|
from pymongo.helpers_shared import _get_timeout_details, format_timeout_details
|
||||||
from pymongo.lock import (
|
from pymongo.lock import (
|
||||||
_async_cond_wait,
|
_async_cond_wait,
|
||||||
_async_create_condition,
|
_async_create_condition,
|
||||||
@ -79,9 +80,7 @@ from pymongo.pool_shared import (
|
|||||||
SSLErrors,
|
SSLErrors,
|
||||||
_CancellationContext,
|
_CancellationContext,
|
||||||
_configured_protocol_interface,
|
_configured_protocol_interface,
|
||||||
_get_timeout_details,
|
|
||||||
_raise_connection_failure,
|
_raise_connection_failure,
|
||||||
format_timeout_details,
|
|
||||||
)
|
)
|
||||||
from pymongo.read_preferences import ReadPreference
|
from pymongo.read_preferences import ReadPreference
|
||||||
from pymongo.server_api import _add_to_command
|
from pymongo.server_api import _add_to_command
|
||||||
|
|||||||
@ -224,7 +224,7 @@ class Server:
|
|||||||
if use_cmd:
|
if use_cmd:
|
||||||
first = docs[0]
|
first = docs[0]
|
||||||
await operation.client._process_response(first, operation.session) # type: ignore[misc, arg-type]
|
await operation.client._process_response(first, operation.session) # type: ignore[misc, arg-type]
|
||||||
_check_command_response(first, conn.max_wire_version)
|
_check_command_response(first, conn.max_wire_version, pool_opts=conn.opts) # type:ignore[has-type]
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
duration = datetime.now() - start
|
duration = datetime.now() - start
|
||||||
if isinstance(exc, (NotPrimaryError, OperationFailure)):
|
if isinstance(exc, (NotPrimaryError, OperationFailure)):
|
||||||
|
|||||||
@ -47,6 +47,7 @@ from pymongo.hello import HelloCompat
|
|||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from pymongo.cursor_shared import _Hint
|
from pymongo.cursor_shared import _Hint
|
||||||
from pymongo.operations import _IndexList
|
from pymongo.operations import _IndexList
|
||||||
|
from pymongo.pool_options import PoolOptions
|
||||||
from pymongo.typings import _DocumentOut
|
from pymongo.typings import _DocumentOut
|
||||||
|
|
||||||
|
|
||||||
@ -108,6 +109,34 @@ _SENSITIVE_COMMANDS: set = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _get_timeout_details(options: PoolOptions) -> dict[str, float]:
|
||||||
|
from pymongo import _csot
|
||||||
|
|
||||||
|
details = {}
|
||||||
|
timeout = _csot.get_timeout()
|
||||||
|
socket_timeout = options.socket_timeout
|
||||||
|
connect_timeout = options.connect_timeout
|
||||||
|
if timeout:
|
||||||
|
details["timeoutMS"] = timeout * 1000
|
||||||
|
if socket_timeout and not timeout:
|
||||||
|
details["socketTimeoutMS"] = socket_timeout * 1000
|
||||||
|
if connect_timeout:
|
||||||
|
details["connectTimeoutMS"] = connect_timeout * 1000
|
||||||
|
return details
|
||||||
|
|
||||||
|
|
||||||
|
def format_timeout_details(details: Optional[dict[str, float]]) -> str:
|
||||||
|
result = ""
|
||||||
|
if details:
|
||||||
|
result += " (configured timeouts:"
|
||||||
|
for timeout in ["socketTimeoutMS", "timeoutMS", "connectTimeoutMS"]:
|
||||||
|
if timeout in details:
|
||||||
|
result += f" {timeout}: {details[timeout]}ms,"
|
||||||
|
result = result[:-1]
|
||||||
|
result += ")"
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def _gen_index_name(keys: _IndexList) -> str:
|
def _gen_index_name(keys: _IndexList) -> str:
|
||||||
"""Generate an index name from the set of fields it is over."""
|
"""Generate an index name from the set of fields it is over."""
|
||||||
return "_".join(["{}_{}".format(*item) for item in keys])
|
return "_".join(["{}_{}".format(*item) for item in keys])
|
||||||
@ -188,6 +217,7 @@ def _check_command_response(
|
|||||||
max_wire_version: Optional[int],
|
max_wire_version: Optional[int],
|
||||||
allowable_errors: Optional[Container[Union[int, str]]] = None,
|
allowable_errors: Optional[Container[Union[int, str]]] = None,
|
||||||
parse_write_concern_error: bool = False,
|
parse_write_concern_error: bool = False,
|
||||||
|
pool_opts: Optional[PoolOptions] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Check the response to a command for errors."""
|
"""Check the response to a command for errors."""
|
||||||
if "ok" not in response:
|
if "ok" not in response:
|
||||||
@ -243,6 +273,10 @@ def _check_command_response(
|
|||||||
if code in (11000, 11001, 12582):
|
if code in (11000, 11001, 12582):
|
||||||
raise DuplicateKeyError(errmsg, code, response, max_wire_version)
|
raise DuplicateKeyError(errmsg, code, response, max_wire_version)
|
||||||
elif code == 50:
|
elif code == 50:
|
||||||
|
# Append timeout details to MaxTimeMSExpired responses.
|
||||||
|
if pool_opts:
|
||||||
|
timeout_details = _get_timeout_details(pool_opts)
|
||||||
|
errmsg += format_timeout_details(timeout_details)
|
||||||
raise ExecutionTimeout(errmsg, code, response, max_wire_version)
|
raise ExecutionTimeout(errmsg, code, response, max_wire_version)
|
||||||
elif code == 43:
|
elif code == 43:
|
||||||
raise CursorNotFound(errmsg, code, response, max_wire_version)
|
raise CursorNotFound(errmsg, code, response, max_wire_version)
|
||||||
|
|||||||
@ -386,8 +386,13 @@ class PoolOptions:
|
|||||||
|
|
||||||
def _update_metadata(self, driver: DriverInfo) -> None:
|
def _update_metadata(self, driver: DriverInfo) -> None:
|
||||||
"""Updates the client's metadata"""
|
"""Updates the client's metadata"""
|
||||||
|
if driver.name and driver.name.lower() in self.__metadata["driver"]["name"].lower().split(
|
||||||
|
"|"
|
||||||
|
):
|
||||||
|
return
|
||||||
|
|
||||||
metadata = copy.deepcopy(self.__metadata)
|
metadata = copy.deepcopy(self.__metadata)
|
||||||
|
|
||||||
if driver.name:
|
if driver.name:
|
||||||
metadata["driver"]["name"] = "{}|{}".format(
|
metadata["driver"]["name"] = "{}|{}".format(
|
||||||
metadata["driver"]["name"],
|
metadata["driver"]["name"],
|
||||||
|
|||||||
@ -36,6 +36,7 @@ from pymongo.errors import ( # type:ignore[attr-defined]
|
|||||||
NetworkTimeout,
|
NetworkTimeout,
|
||||||
_CertificateError,
|
_CertificateError,
|
||||||
)
|
)
|
||||||
|
from pymongo.helpers_shared import _get_timeout_details, format_timeout_details
|
||||||
from pymongo.network_layer import AsyncNetworkingInterface, NetworkingInterface, PyMongoProtocol
|
from pymongo.network_layer import AsyncNetworkingInterface, NetworkingInterface, PyMongoProtocol
|
||||||
from pymongo.pool_options import PoolOptions
|
from pymongo.pool_options import PoolOptions
|
||||||
from pymongo.ssl_support import PYSSLError, SSLError, _has_sni
|
from pymongo.ssl_support import PYSSLError, SSLError, _has_sni
|
||||||
@ -149,32 +150,6 @@ def _raise_connection_failure(
|
|||||||
raise AutoReconnect(msg) from error
|
raise AutoReconnect(msg) from error
|
||||||
|
|
||||||
|
|
||||||
def _get_timeout_details(options: PoolOptions) -> dict[str, float]:
|
|
||||||
details = {}
|
|
||||||
timeout = _csot.get_timeout()
|
|
||||||
socket_timeout = options.socket_timeout
|
|
||||||
connect_timeout = options.connect_timeout
|
|
||||||
if timeout:
|
|
||||||
details["timeoutMS"] = timeout * 1000
|
|
||||||
if socket_timeout and not timeout:
|
|
||||||
details["socketTimeoutMS"] = socket_timeout * 1000
|
|
||||||
if connect_timeout:
|
|
||||||
details["connectTimeoutMS"] = connect_timeout * 1000
|
|
||||||
return details
|
|
||||||
|
|
||||||
|
|
||||||
def format_timeout_details(details: Optional[dict[str, float]]) -> str:
|
|
||||||
result = ""
|
|
||||||
if details:
|
|
||||||
result += " (configured timeouts:"
|
|
||||||
for timeout in ["socketTimeoutMS", "timeoutMS", "connectTimeoutMS"]:
|
|
||||||
if timeout in details:
|
|
||||||
result += f" {timeout}: {details[timeout]}ms,"
|
|
||||||
result = result[:-1]
|
|
||||||
result += ")"
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
class _CancellationContext:
|
class _CancellationContext:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self._cancelled = False
|
self._cancelled = False
|
||||||
|
|||||||
@ -70,12 +70,12 @@ from pymongo.errors import (
|
|||||||
NetworkTimeout,
|
NetworkTimeout,
|
||||||
ServerSelectionTimeoutError,
|
ServerSelectionTimeoutError,
|
||||||
)
|
)
|
||||||
|
from pymongo.helpers_shared import _get_timeout_details
|
||||||
from pymongo.network_layer import sendall
|
from pymongo.network_layer import sendall
|
||||||
from pymongo.operations import UpdateOne
|
from pymongo.operations import UpdateOne
|
||||||
from pymongo.pool_options import PoolOptions
|
from pymongo.pool_options import PoolOptions
|
||||||
from pymongo.pool_shared import (
|
from pymongo.pool_shared import (
|
||||||
_configured_socket,
|
_configured_socket,
|
||||||
_get_timeout_details,
|
|
||||||
_raise_connection_failure,
|
_raise_connection_failure,
|
||||||
)
|
)
|
||||||
from pymongo.read_concern import ReadConcern
|
from pymongo.read_concern import ReadConcern
|
||||||
|
|||||||
@ -55,6 +55,7 @@ from pymongo.errors import ( # type:ignore[attr-defined]
|
|||||||
WaitQueueTimeoutError,
|
WaitQueueTimeoutError,
|
||||||
)
|
)
|
||||||
from pymongo.hello import Hello, HelloCompat
|
from pymongo.hello import Hello, HelloCompat
|
||||||
|
from pymongo.helpers_shared import _get_timeout_details, format_timeout_details
|
||||||
from pymongo.lock import (
|
from pymongo.lock import (
|
||||||
_cond_wait,
|
_cond_wait,
|
||||||
_create_condition,
|
_create_condition,
|
||||||
@ -76,9 +77,7 @@ from pymongo.pool_shared import (
|
|||||||
SSLErrors,
|
SSLErrors,
|
||||||
_CancellationContext,
|
_CancellationContext,
|
||||||
_configured_socket_interface,
|
_configured_socket_interface,
|
||||||
_get_timeout_details,
|
|
||||||
_raise_connection_failure,
|
_raise_connection_failure,
|
||||||
format_timeout_details,
|
|
||||||
)
|
)
|
||||||
from pymongo.read_preferences import ReadPreference
|
from pymongo.read_preferences import ReadPreference
|
||||||
from pymongo.server_api import _add_to_command
|
from pymongo.server_api import _add_to_command
|
||||||
|
|||||||
@ -224,7 +224,7 @@ class Server:
|
|||||||
if use_cmd:
|
if use_cmd:
|
||||||
first = docs[0]
|
first = docs[0]
|
||||||
operation.client._process_response(first, operation.session) # type: ignore[misc, arg-type]
|
operation.client._process_response(first, operation.session) # type: ignore[misc, arg-type]
|
||||||
_check_command_response(first, conn.max_wire_version)
|
_check_command_response(first, conn.max_wire_version, pool_opts=conn.opts) # type:ignore[has-type]
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
duration = datetime.now() - start
|
duration = datetime.now() - start
|
||||||
if isinstance(exc, (NotPrimaryError, OperationFailure)):
|
if isinstance(exc, (NotPrimaryError, OperationFailure)):
|
||||||
|
|||||||
@ -107,15 +107,20 @@ class TestClientMetadataProse(AsyncIntegrationTest):
|
|||||||
new_name, new_version, new_platform, new_metadata = await self.send_ping_and_get_metadata(
|
new_name, new_version, new_platform, new_metadata = await self.send_ping_and_get_metadata(
|
||||||
client, True
|
client, True
|
||||||
)
|
)
|
||||||
self.assertEqual(new_name, f"{name}|{add_name}" if add_name is not None else name)
|
if add_name is not None and add_name.lower() in name.lower().split("|"):
|
||||||
self.assertEqual(
|
self.assertEqual(name, new_name)
|
||||||
new_version,
|
self.assertEqual(version, new_version)
|
||||||
f"{version}|{add_version}" if add_version is not None else version,
|
self.assertEqual(platform, new_platform)
|
||||||
)
|
else:
|
||||||
self.assertEqual(
|
self.assertEqual(new_name, f"{name}|{add_name}" if add_name is not None else name)
|
||||||
new_platform,
|
self.assertEqual(
|
||||||
f"{platform}|{add_platform}" if add_platform is not None else platform,
|
new_version,
|
||||||
)
|
f"{version}|{add_version}" if add_version is not None else version,
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
new_platform,
|
||||||
|
f"{platform}|{add_platform}" if add_platform is not None else platform,
|
||||||
|
)
|
||||||
|
|
||||||
metadata.pop("driver")
|
metadata.pop("driver")
|
||||||
metadata.pop("platform")
|
metadata.pop("platform")
|
||||||
@ -210,6 +215,18 @@ class TestClientMetadataProse(AsyncIntegrationTest):
|
|||||||
self.assertIsNone(self.handshake_req)
|
self.assertIsNone(self.handshake_req)
|
||||||
self.assertEqual(listener.event_count(ConnectionClosedEvent), 0)
|
self.assertEqual(listener.event_count(ConnectionClosedEvent), 0)
|
||||||
|
|
||||||
|
async def test_duplicate_driver_name_no_op(self):
|
||||||
|
client = await self.async_rs_or_single_client(
|
||||||
|
"mongodb://" + self.server.address_string,
|
||||||
|
maxIdleTimeMS=1,
|
||||||
|
)
|
||||||
|
client.append_metadata(DriverInfo("library", "1.2", "Library Platform"))
|
||||||
|
await self.check_metadata_added(client, "framework", None, None)
|
||||||
|
# wait for connection to become idle
|
||||||
|
await asyncio.sleep(0.005)
|
||||||
|
# add same metadata again
|
||||||
|
await self.check_metadata_added(client, "Framework", None, None)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
@ -335,6 +335,8 @@ class AsyncTestCollection(AsyncIntegrationTest):
|
|||||||
await db.test.create_index(["hello", ("world", DESCENDING)])
|
await db.test.create_index(["hello", ("world", DESCENDING)])
|
||||||
await db.test.create_index({"hello": 1}.items()) # type:ignore[arg-type]
|
await db.test.create_index({"hello": 1}.items()) # type:ignore[arg-type]
|
||||||
|
|
||||||
|
# TODO: PYTHON-5491 - remove version max
|
||||||
|
@async_client_context.require_version_max(8, 0, -1)
|
||||||
async def test_drop_index(self):
|
async def test_drop_index(self):
|
||||||
db = self.db
|
db = self.db
|
||||||
await db.test.drop_indexes()
|
await db.test.drop_indexes()
|
||||||
|
|||||||
@ -43,6 +43,7 @@ from test.utils_shared import (
|
|||||||
|
|
||||||
from bson import decode_all
|
from bson import decode_all
|
||||||
from bson.code import Code
|
from bson.code import Code
|
||||||
|
from bson.raw_bson import RawBSONDocument
|
||||||
from pymongo import ASCENDING, DESCENDING
|
from pymongo import ASCENDING, DESCENDING
|
||||||
from pymongo.asynchronous.cursor import AsyncCursor, CursorType
|
from pymongo.asynchronous.cursor import AsyncCursor, CursorType
|
||||||
from pymongo.asynchronous.helpers import anext
|
from pymongo.asynchronous.helpers import anext
|
||||||
@ -199,6 +200,21 @@ class TestCursor(AsyncIntegrationTest):
|
|||||||
finally:
|
finally:
|
||||||
await client.admin.command("configureFailPoint", "maxTimeAlwaysTimeOut", mode="off")
|
await client.admin.command("configureFailPoint", "maxTimeAlwaysTimeOut", mode="off")
|
||||||
|
|
||||||
|
async def test_maxtime_ms_message(self):
|
||||||
|
db = self.db
|
||||||
|
await db.t.insert_one({"x": 1})
|
||||||
|
with self.assertRaises(Exception) as error:
|
||||||
|
await db.t.find_one({"$where": delay(2)}, max_time_ms=1)
|
||||||
|
|
||||||
|
self.assertIn("(configured timeouts: connectTimeoutMS: 20000.0ms", str(error.exception))
|
||||||
|
|
||||||
|
client = await self.async_rs_client(document_class=RawBSONDocument)
|
||||||
|
await client.db.t.insert_one({"x": 1})
|
||||||
|
with self.assertRaises(Exception) as error:
|
||||||
|
await client.db.t.find_one({"$where": delay(2)}, max_time_ms=1)
|
||||||
|
|
||||||
|
self.assertIn("(configured timeouts: connectTimeoutMS: 20000.0ms", str(error.exception))
|
||||||
|
|
||||||
async def test_max_await_time_ms(self):
|
async def test_max_await_time_ms(self):
|
||||||
db = self.db
|
db = self.db
|
||||||
await db.pymongo_test.drop()
|
await db.pymongo_test.drop()
|
||||||
|
|||||||
@ -21,7 +21,7 @@ import random
|
|||||||
import socket
|
import socket
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
from test.asynchronous.utils import async_get_pool, async_joinall
|
from test.asynchronous.utils import async_get_pool, async_joinall, flaky
|
||||||
|
|
||||||
from bson.codec_options import DEFAULT_CODEC_OPTIONS
|
from bson.codec_options import DEFAULT_CODEC_OPTIONS
|
||||||
from bson.son import SON
|
from bson.son import SON
|
||||||
|
|||||||
@ -564,6 +564,8 @@ class UnifiedSpecTestMixinV1(AsyncIntegrationTest):
|
|||||||
self.skipTest("CSOT not implemented for watch()")
|
self.skipTest("CSOT not implemented for watch()")
|
||||||
if "cursors" in class_name:
|
if "cursors" in class_name:
|
||||||
self.skipTest("CSOT not implemented for cursors")
|
self.skipTest("CSOT not implemented for cursors")
|
||||||
|
if "dropindex on collection" in description:
|
||||||
|
self.skipTest("PYTHON-5491")
|
||||||
if (
|
if (
|
||||||
"tailable" in class_name
|
"tailable" in class_name
|
||||||
or "tailable" in description
|
or "tailable" in description
|
||||||
|
|||||||
@ -446,22 +446,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"level": "debug",
|
|
||||||
"component": "connection",
|
|
||||||
"data": {
|
|
||||||
"message": "Connection pool cleared",
|
|
||||||
"serverHost": {
|
|
||||||
"$$type": "string"
|
|
||||||
},
|
|
||||||
"serverPort": {
|
|
||||||
"$$type": [
|
|
||||||
"int",
|
|
||||||
"long"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"level": "debug",
|
"level": "debug",
|
||||||
"component": "connection",
|
"component": "connection",
|
||||||
@ -514,6 +498,22 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": "debug",
|
||||||
|
"component": "connection",
|
||||||
|
"data": {
|
||||||
|
"message": "Connection pool cleared",
|
||||||
|
"serverHost": {
|
||||||
|
"$$type": "string"
|
||||||
|
},
|
||||||
|
"serverPort": {
|
||||||
|
"$$type": [
|
||||||
|
"int",
|
||||||
|
"long"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -107,15 +107,20 @@ class TestClientMetadataProse(IntegrationTest):
|
|||||||
new_name, new_version, new_platform, new_metadata = self.send_ping_and_get_metadata(
|
new_name, new_version, new_platform, new_metadata = self.send_ping_and_get_metadata(
|
||||||
client, True
|
client, True
|
||||||
)
|
)
|
||||||
self.assertEqual(new_name, f"{name}|{add_name}" if add_name is not None else name)
|
if add_name is not None and add_name.lower() in name.lower().split("|"):
|
||||||
self.assertEqual(
|
self.assertEqual(name, new_name)
|
||||||
new_version,
|
self.assertEqual(version, new_version)
|
||||||
f"{version}|{add_version}" if add_version is not None else version,
|
self.assertEqual(platform, new_platform)
|
||||||
)
|
else:
|
||||||
self.assertEqual(
|
self.assertEqual(new_name, f"{name}|{add_name}" if add_name is not None else name)
|
||||||
new_platform,
|
self.assertEqual(
|
||||||
f"{platform}|{add_platform}" if add_platform is not None else platform,
|
new_version,
|
||||||
)
|
f"{version}|{add_version}" if add_version is not None else version,
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
new_platform,
|
||||||
|
f"{platform}|{add_platform}" if add_platform is not None else platform,
|
||||||
|
)
|
||||||
|
|
||||||
metadata.pop("driver")
|
metadata.pop("driver")
|
||||||
metadata.pop("platform")
|
metadata.pop("platform")
|
||||||
@ -210,6 +215,18 @@ class TestClientMetadataProse(IntegrationTest):
|
|||||||
self.assertIsNone(self.handshake_req)
|
self.assertIsNone(self.handshake_req)
|
||||||
self.assertEqual(listener.event_count(ConnectionClosedEvent), 0)
|
self.assertEqual(listener.event_count(ConnectionClosedEvent), 0)
|
||||||
|
|
||||||
|
def test_duplicate_driver_name_no_op(self):
|
||||||
|
client = self.rs_or_single_client(
|
||||||
|
"mongodb://" + self.server.address_string,
|
||||||
|
maxIdleTimeMS=1,
|
||||||
|
)
|
||||||
|
client.append_metadata(DriverInfo("library", "1.2", "Library Platform"))
|
||||||
|
self.check_metadata_added(client, "framework", None, None)
|
||||||
|
# wait for connection to become idle
|
||||||
|
time.sleep(0.005)
|
||||||
|
# add same metadata again
|
||||||
|
self.check_metadata_added(client, "Framework", None, None)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
@ -333,6 +333,8 @@ class TestCollection(IntegrationTest):
|
|||||||
db.test.create_index(["hello", ("world", DESCENDING)])
|
db.test.create_index(["hello", ("world", DESCENDING)])
|
||||||
db.test.create_index({"hello": 1}.items()) # type:ignore[arg-type]
|
db.test.create_index({"hello": 1}.items()) # type:ignore[arg-type]
|
||||||
|
|
||||||
|
# TODO: PYTHON-5491 - remove version max
|
||||||
|
@client_context.require_version_max(8, 0, -1)
|
||||||
def test_drop_index(self):
|
def test_drop_index(self):
|
||||||
db = self.db
|
db = self.db
|
||||||
db.test.drop_indexes()
|
db.test.drop_indexes()
|
||||||
|
|||||||
@ -43,6 +43,7 @@ from test.utils_shared import (
|
|||||||
|
|
||||||
from bson import decode_all
|
from bson import decode_all
|
||||||
from bson.code import Code
|
from bson.code import Code
|
||||||
|
from bson.raw_bson import RawBSONDocument
|
||||||
from pymongo import ASCENDING, DESCENDING
|
from pymongo import ASCENDING, DESCENDING
|
||||||
from pymongo.collation import Collation
|
from pymongo.collation import Collation
|
||||||
from pymongo.errors import ExecutionTimeout, InvalidOperation, OperationFailure, PyMongoError
|
from pymongo.errors import ExecutionTimeout, InvalidOperation, OperationFailure, PyMongoError
|
||||||
@ -197,6 +198,21 @@ class TestCursor(IntegrationTest):
|
|||||||
finally:
|
finally:
|
||||||
client.admin.command("configureFailPoint", "maxTimeAlwaysTimeOut", mode="off")
|
client.admin.command("configureFailPoint", "maxTimeAlwaysTimeOut", mode="off")
|
||||||
|
|
||||||
|
def test_maxtime_ms_message(self):
|
||||||
|
db = self.db
|
||||||
|
db.t.insert_one({"x": 1})
|
||||||
|
with self.assertRaises(Exception) as error:
|
||||||
|
db.t.find_one({"$where": delay(2)}, max_time_ms=1)
|
||||||
|
|
||||||
|
self.assertIn("(configured timeouts: connectTimeoutMS: 20000.0ms", str(error.exception))
|
||||||
|
|
||||||
|
client = self.rs_client(document_class=RawBSONDocument)
|
||||||
|
client.db.t.insert_one({"x": 1})
|
||||||
|
with self.assertRaises(Exception) as error:
|
||||||
|
client.db.t.find_one({"$where": delay(2)}, max_time_ms=1)
|
||||||
|
|
||||||
|
self.assertIn("(configured timeouts: connectTimeoutMS: 20000.0ms", str(error.exception))
|
||||||
|
|
||||||
def test_max_await_time_ms(self):
|
def test_max_await_time_ms(self):
|
||||||
db = self.db
|
db = self.db
|
||||||
db.pymongo_test.drop()
|
db.pymongo_test.drop()
|
||||||
|
|||||||
@ -21,7 +21,7 @@ import random
|
|||||||
import socket
|
import socket
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
from test.utils import get_pool, joinall
|
from test.utils import flaky, get_pool, joinall
|
||||||
|
|
||||||
from bson.codec_options import DEFAULT_CODEC_OPTIONS
|
from bson.codec_options import DEFAULT_CODEC_OPTIONS
|
||||||
from bson.son import SON
|
from bson.son import SON
|
||||||
|
|||||||
@ -563,6 +563,8 @@ class UnifiedSpecTestMixinV1(IntegrationTest):
|
|||||||
self.skipTest("CSOT not implemented for watch()")
|
self.skipTest("CSOT not implemented for watch()")
|
||||||
if "cursors" in class_name:
|
if "cursors" in class_name:
|
||||||
self.skipTest("CSOT not implemented for cursors")
|
self.skipTest("CSOT not implemented for cursors")
|
||||||
|
if "dropindex on collection" in description:
|
||||||
|
self.skipTest("PYTHON-5491")
|
||||||
if (
|
if (
|
||||||
"tailable" in class_name
|
"tailable" in class_name
|
||||||
or "tailable" in description
|
or "tailable" in description
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user