From ff42b6c53cd1b9991de687e79b7f989daf5e5984 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Tue, 29 Jul 2025 14:09:31 -0500 Subject: [PATCH 01/19] wip --- .evergreen/config.yml | 4 ++-- .github/workflows/test-python.yml | 4 ++-- bindings/python/.evergreen/test.sh | 19 +++++++++------ bindings/python/.evergreen/utils.sh | 36 ++++++++++++----------------- bindings/python/pyproject.toml | 5 ++-- bindings/python/requirements.txt | 2 +- 6 files changed, 34 insertions(+), 36 deletions(-) diff --git a/.evergreen/config.yml b/.evergreen/config.yml index 44ab23faa..d92e8e7a1 100755 --- a/.evergreen/config.yml +++ b/.evergreen/config.yml @@ -563,7 +563,7 @@ tasks: commands: - func: "fetch source" - func: "build python release" - vars: { PYTHON: /opt/python/3.8/bin/python3 } + vars: { PYTHON: /opt/python/3.10/bin/python3 } - func: "upload python release" - name: "release-python-windows" @@ -572,7 +572,7 @@ tasks: commands: - func: "fetch source" - func: "build python release" - vars: { PYTHON: C:/python/Python38/python.exe } + vars: { PYTHON: C:/python/Python310/python.exe } - func: "upload python release" - name: "release-python-combine" diff --git a/.github/workflows/test-python.yml b/.github/workflows/test-python.yml index b818692be..8e5c3661c 100644 --- a/.github/workflows/test-python.yml +++ b/.github/workflows/test-python.yml @@ -43,7 +43,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-latest] - python-version: ["3.8", "3.13"] + python-version: ["3.10", "3.13", "3.14t"] steps: - uses: actions/checkout@v4 @@ -57,7 +57,7 @@ jobs: python-version: ${{ matrix.python-version }} - name: Build and test dist files run: | - if [ "${{ matrix.python-version }}" == "3.13" ]; then + if [ "${{ matrix.python-version }}" == "3.14" ]; then export PIP_PRE=1 fi export LIBMONGOCRYPT_VERSION=$(cat ./scripts/libmongocrypt-version.txt) diff --git a/bindings/python/.evergreen/test.sh b/bindings/python/.evergreen/test.sh index e49577c6f..ab3361a57 100755 --- a/bindings/python/.evergreen/test.sh +++ b/bindings/python/.evergreen/test.sh @@ -18,11 +18,13 @@ if [ "Windows_NT" = "$OS" ]; then # Magic variable in cygwin PYMONGOCRYPT_LIB=${MONGOCRYPT_DIR}/nocrypto/bin/mongocrypt.dll PYMONGOCRYPT_LIB_CRYPTO=$(cygpath -m ${MONGOCRYPT_DIR}/bin/mongocrypt.dll) export PYMONGOCRYPT_LIB=$(cygpath -m $PYMONGOCRYPT_LIB) - PYTHONS=("C:/python/Python38/python.exe" - "C:/python/Python39/python.exe" + PYTHONS=("C:/python/Python39/python.exe" "C:/python/Python310/python.exe" "C:/python/Python311/python.exe" - "C:/python/Python312/python.exe") + "C:/python/Python312/python.exe" + "C:/python/Python313/python.exe" + "C:/python/Python314/python.exe" + "C:/python/Python314/python3.14t.exe") export CRYPT_SHARED_PATH=../crypt_shared/bin/mongo_crypt_v1.dll C:/python/Python310/python.exe drivers-evergreen-tools/.evergreen/mongodl.py --component crypt_shared \ --version latest --out ../crypt_shared/ @@ -30,10 +32,12 @@ elif [ "Darwin" = "$(uname -s)" ]; then export PYMONGOCRYPT_LIB=${MONGOCRYPT_DIR}/nocrypto/lib/libmongocrypt.dylib PYMONGOCRYPT_LIB_CRYPTO=${MONGOCRYPT_DIR}/lib/libmongocrypt.dylib PYTHONS=( - "/Library/Frameworks/Python.framework/Versions/3.9/bin/python3" "/Library/Frameworks/Python.framework/Versions/3.10/bin/python3" "/Library/Frameworks/Python.framework/Versions/3.11/bin/python3" "/Library/Frameworks/Python.framework/Versions/3.12/bin/python3" + "/Library/Frameworks/Python.framework/Versions/3.13/bin/python3" + "/Library/Frameworks/Python.framework/Versions/3.14/bin/python3" + "/Library/Frameworks/PythonT.framework/Versions/3.14/bin/python3" ) export CRYPT_SHARED_PATH="../crypt_shared/lib/mongo_crypt_v1.dylib" @@ -55,12 +59,13 @@ else "/opt/mongodbtoolchain/v4/bin/python3" ) else - PYTHONS=("/opt/python/3.8/bin/python3" - "/opt/python/3.9/bin/python3" + PYTHONS=( "/opt/python/3.10/bin/python3" "/opt/python/3.11/bin/python3" "/opt/python/3.12/bin/python3" "/opt/python/3.13/bin/python3" + "/opt/python/3.14/bin/python3" + "/opt/python/3.14t/bin/python3" ) fi /opt/mongodbtoolchain/v3/bin/python3 drivers-evergreen-tools/.evergreen/mongodl.py --component \ @@ -72,7 +77,7 @@ for PYTHON_BINARY in "${PYTHONS[@]}"; do $PYTHON_BINARY -c 'import sys; print(sys.version)' git clean -dffx createvirtualenv $PYTHON_BINARY .venv - python -m pip install --prefer-binary -v -e ".[test]" + python -m pip install --prefer-binary -v -e ".[test]" || python -m pip install --pre --prefer-binary -v -e ".[test]" echo "Running tests with crypto enabled libmongocrypt..." PYMONGOCRYPT_LIB=$PYMONGOCRYPT_LIB_CRYPTO python -c 'from pymongocrypt.binding import lib;assert lib.mongocrypt_is_crypto_available(), "mongocrypt_is_crypto_available() returned False"' PYMONGOCRYPT_LIB=$PYMONGOCRYPT_LIB_CRYPTO python -m pytest -v --ignore=test/performance . diff --git a/bindings/python/.evergreen/utils.sh b/bindings/python/.evergreen/utils.sh index 57055fb1e..3d5c078f2 100755 --- a/bindings/python/.evergreen/utils.sh +++ b/bindings/python/.evergreen/utils.sh @@ -36,47 +36,41 @@ createvirtualenv () { # PYTHON = find_python3 find_python3() { PYTHON="" - # Add a fallback system python3 if it is available and Python 3.8+. - if is_python_38 "$(command -v python3)"; then + # Add a fallback system python3 if it is available and Python 3.10+. + if is_python_310 "$(command -v python3)"; then PYTHON="$(command -v python3)" fi # Find a suitable toolchain version, if available. if [ "$(uname -s)" = "Darwin" ]; then - # macos 11.00 - if [ -d "/Library/Frameworks/Python.Framework/Versions/3.10" ]; then - PYTHON="/Library/Frameworks/Python.Framework/Versions/3.10/bin/python3" - # macos 10.14 - elif [ -d "/Library/Frameworks/Python.Framework/Versions/3.8" ]; then - PYTHON="/Library/Frameworks/Python.Framework/Versions/3.8/bin/python3" - fi + PYTHON="/Library/Frameworks/Python.Framework/Versions/3.10/bin/python3" elif [ "Windows_NT" = "${OS:-}" ]; then # Magic variable in cygwin - PYTHON="C:/python/Python38/python.exe" + PYTHON="C:/python/Python310/python.exe" else - # Prefer our own toolchain, fall back to mongodb toolchain if it has Python 3.8+. - if [ -f "/opt/python/3.8/bin/python3" ]; then - PYTHON="/opt/python/3.8/bin/python3" - elif is_python_38 "$(command -v /opt/mongodbtoolchain/v4/bin/python3)"; then + # Prefer our own toolchain, fall back to mongodb toolchain if it has Python 3.10+. + if [ -f "/opt/python/3.10/bin/python3" ]; then + PYTHON="/opt/python/3.10/bin/python3" + elif is_python_310 "$(command -v /opt/mongodbtoolchain/v4/bin/python3)"; then PYTHON="/opt/mongodbtoolchain/v4/bin/python3" - elif is_python_38 "$(command -v /opt/mongodbtoolchain/v3/bin/python3)"; then + elif is_python_310 "$(command -v /opt/mongodbtoolchain/v3/bin/python3)"; then PYTHON="/opt/mongodbtoolchain/v3/bin/python3" fi fi if [ -z "$PYTHON" ]; then - echo "Cannot run pre-commit without python3.8+ installed!" + echo "Cannot run pre-commit without python3.10+ installed!" exit 1 fi echo "$PYTHON" } -# Function that returns success if the provided Python binary is version 3.8 or later +# Function that returns success if the provided Python binary is version 3.10 or later # Usage: -# is_python_38 /path/to/python +# is_python_310 /path/to/python # * param1: Python binary -is_python_38() { +is_python_310() { if [ -z "$1" ]; then return 1 - elif $1 -c "import sys; exit(sys.version_info[:2] < (3, 8))"; then - # runs when sys.version_info[:2] >= (3, 8) + elif $1 -c "import sys; exit(sys.version_info[:2] < (3, 10))"; then + # runs when sys.version_info[:2] >= (3, 10) return 0 else return 1 diff --git a/bindings/python/pyproject.toml b/bindings/python/pyproject.toml index f69cf3c57..5c83f6dfc 100644 --- a/bindings/python/pyproject.toml +++ b/bindings/python/pyproject.toml @@ -8,7 +8,7 @@ dynamic = ["version", "dependencies", "optional-dependencies"] description = "Python bindings for libmongocrypt" readme = "README.rst" license = {file="LICENSE"} -requires-python = ">=3.8" +requires-python = ">=3.10" authors = [ { name = "Shane Harvey", email = "mongodb-user@googlegroups.com" }, ] @@ -29,14 +29,13 @@ classifiers = [ "Operating System :: POSIX", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Topic :: Database", ] diff --git a/bindings/python/requirements.txt b/bindings/python/requirements.txt index f95140da6..3440d1ddf 100644 --- a/bindings/python/requirements.txt +++ b/bindings/python/requirements.txt @@ -1,4 +1,4 @@ -cffi>=1.12.0,<2 +cffi>=1.12.0,<3;python_version<"3.14" cryptography>=40 packaging>=21.0 httpx>=0.25.0 From f32a8ebeb0b86f5c4395171267df4b16fe98f87b Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Tue, 29 Jul 2025 14:13:35 -0500 Subject: [PATCH 02/19] run workflows --- .github/workflows/dist-python.yml | 2 +- .github/workflows/test-python.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dist-python.yml b/.github/workflows/dist-python.yml index b25b84c18..95c64e968 100644 --- a/.github/workflows/dist-python.yml +++ b/.github/workflows/dist-python.yml @@ -30,7 +30,7 @@ defaults: jobs: build_dist: - if: github.repository_owner == 'mongodb' || (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') + if: github.repository_owner == 'blink1073' || (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') runs-on: ${{ matrix.os }} strategy: matrix: diff --git a/.github/workflows/test-python.yml b/.github/workflows/test-python.yml index 8e5c3661c..a33271f76 100644 --- a/.github/workflows/test-python.yml +++ b/.github/workflows/test-python.yml @@ -20,7 +20,7 @@ defaults: jobs: static: - if: github.repository_owner == 'mongodb' + if: github.repository_owner == 'blink1073' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -37,7 +37,7 @@ jobs: check-manifest -v build: - if: github.repository_owner == 'mongodb' + if: github.repository_owner == 'blink1073' runs-on: ${{ matrix.os }} strategy: fail-fast: false From f1387267cec36e80bfb27c23be4f75d5bd16cdb1 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Tue, 29 Jul 2025 18:23:07 -0500 Subject: [PATCH 03/19] fixup test --- .github/workflows/test-python.yml | 3 --- bindings/python/.evergreen/test.sh | 2 +- bindings/python/requirements.txt | 1 + 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test-python.yml b/.github/workflows/test-python.yml index a33271f76..a44853fdf 100644 --- a/.github/workflows/test-python.yml +++ b/.github/workflows/test-python.yml @@ -57,9 +57,6 @@ jobs: python-version: ${{ matrix.python-version }} - name: Build and test dist files run: | - if [ "${{ matrix.python-version }}" == "3.14" ]; then - export PIP_PRE=1 - fi export LIBMONGOCRYPT_VERSION=$(cat ./scripts/libmongocrypt-version.txt) git fetch origin $LIBMONGOCRYPT_VERSION bash ./scripts/release.sh diff --git a/bindings/python/.evergreen/test.sh b/bindings/python/.evergreen/test.sh index ab3361a57..65f548e93 100755 --- a/bindings/python/.evergreen/test.sh +++ b/bindings/python/.evergreen/test.sh @@ -77,7 +77,7 @@ for PYTHON_BINARY in "${PYTHONS[@]}"; do $PYTHON_BINARY -c 'import sys; print(sys.version)' git clean -dffx createvirtualenv $PYTHON_BINARY .venv - python -m pip install --prefer-binary -v -e ".[test]" || python -m pip install --pre --prefer-binary -v -e ".[test]" + python -m pip install --prefer-binary -v -e ".[test]" echo "Running tests with crypto enabled libmongocrypt..." PYMONGOCRYPT_LIB=$PYMONGOCRYPT_LIB_CRYPTO python -c 'from pymongocrypt.binding import lib;assert lib.mongocrypt_is_crypto_available(), "mongocrypt_is_crypto_available() returned False"' PYMONGOCRYPT_LIB=$PYMONGOCRYPT_LIB_CRYPTO python -m pytest -v --ignore=test/performance . diff --git a/bindings/python/requirements.txt b/bindings/python/requirements.txt index 3440d1ddf..51ce01e3d 100644 --- a/bindings/python/requirements.txt +++ b/bindings/python/requirements.txt @@ -1,4 +1,5 @@ cffi>=1.12.0,<3;python_version<"3.14" +cffi>=2.0.0b3,<3;python_version=="3.14" cryptography>=40 packaging>=21.0 httpx>=0.25.0 From f6cf56db2d19fb885b58015b640c42e9e3faba3a Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Tue, 29 Jul 2025 18:41:26 -0500 Subject: [PATCH 04/19] fixup --- .github/workflows/dist-python.yml | 2 +- bindings/python/requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dist-python.yml b/.github/workflows/dist-python.yml index 95c64e968..96536c847 100644 --- a/.github/workflows/dist-python.yml +++ b/.github/workflows/dist-python.yml @@ -47,7 +47,7 @@ jobs: - uses: actions/setup-python@v5 with: - python-version: 3.8 + python-version: "3.10" cache: 'pip' cache-dependency-path: 'bindings/python/pyproject.toml' allow-prereleases: true diff --git a/bindings/python/requirements.txt b/bindings/python/requirements.txt index 51ce01e3d..507493e57 100644 --- a/bindings/python/requirements.txt +++ b/bindings/python/requirements.txt @@ -1,5 +1,5 @@ cffi>=1.12.0,<3;python_version<"3.14" -cffi>=2.0.0b3,<3;python_version=="3.14" +cffi>=2.0.0b1,<3;python_version=="3.14" cryptography>=40 packaging>=21.0 httpx>=0.25.0 From 24b8aee69d99ba5b50bef97d79ada731daf8384f Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Tue, 29 Jul 2025 18:46:59 -0500 Subject: [PATCH 05/19] drop 3.14t for now --- .github/workflows/test-python.yml | 2 +- bindings/python/.evergreen/test.sh | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/test-python.yml b/.github/workflows/test-python.yml index a44853fdf..5f0322f67 100644 --- a/.github/workflows/test-python.yml +++ b/.github/workflows/test-python.yml @@ -43,7 +43,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-latest] - python-version: ["3.10", "3.13", "3.14t"] + python-version: ["3.10", "3.13", "3.14"] steps: - uses: actions/checkout@v4 diff --git a/bindings/python/.evergreen/test.sh b/bindings/python/.evergreen/test.sh index 65f548e93..fe17d95b8 100755 --- a/bindings/python/.evergreen/test.sh +++ b/bindings/python/.evergreen/test.sh @@ -23,8 +23,7 @@ if [ "Windows_NT" = "$OS" ]; then # Magic variable in cygwin "C:/python/Python311/python.exe" "C:/python/Python312/python.exe" "C:/python/Python313/python.exe" - "C:/python/Python314/python.exe" - "C:/python/Python314/python3.14t.exe") + "C:/python/Python314/python.exe") export CRYPT_SHARED_PATH=../crypt_shared/bin/mongo_crypt_v1.dll C:/python/Python310/python.exe drivers-evergreen-tools/.evergreen/mongodl.py --component crypt_shared \ --version latest --out ../crypt_shared/ @@ -37,7 +36,6 @@ elif [ "Darwin" = "$(uname -s)" ]; then "/Library/Frameworks/Python.framework/Versions/3.12/bin/python3" "/Library/Frameworks/Python.framework/Versions/3.13/bin/python3" "/Library/Frameworks/Python.framework/Versions/3.14/bin/python3" - "/Library/Frameworks/PythonT.framework/Versions/3.14/bin/python3" ) export CRYPT_SHARED_PATH="../crypt_shared/lib/mongo_crypt_v1.dylib" @@ -65,7 +63,6 @@ else "/opt/python/3.12/bin/python3" "/opt/python/3.13/bin/python3" "/opt/python/3.14/bin/python3" - "/opt/python/3.14t/bin/python3" ) fi /opt/mongodbtoolchain/v3/bin/python3 drivers-evergreen-tools/.evergreen/mongodl.py --component \ From 5f1b8552cd0619a83cbb13e26fd65167fd740aa6 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Tue, 29 Jul 2025 18:51:23 -0500 Subject: [PATCH 06/19] lint --- bindings/python/pymongocrypt/mongocrypt.py | 2 +- bindings/python/pymongocrypt/options.py | 6 +++--- bindings/python/test/performance/perf_test.py | 3 +-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/bindings/python/pymongocrypt/mongocrypt.py b/bindings/python/pymongocrypt/mongocrypt.py index 608d39e32..46520b6f9 100644 --- a/bindings/python/pymongocrypt/mongocrypt.py +++ b/bindings/python/pymongocrypt/mongocrypt.py @@ -52,7 +52,7 @@ def __init__(self, options, callback): if not isinstance(options, MongoCryptOptions): raise TypeError("options must be a MongoCryptOptions") - if not isinstance(callback, (AsyncMongoCryptCallback, MongoCryptCallback)): + if not isinstance(callback, AsyncMongoCryptCallback | MongoCryptCallback): raise TypeError( "callback must be a MongoCryptCallback or AsyncMongoCryptCallback" ) diff --git a/bindings/python/pymongocrypt/options.py b/bindings/python/pymongocrypt/options.py index c1e27b1d5..a709ed3e5 100644 --- a/bindings/python/pymongocrypt/options.py +++ b/bindings/python/pymongocrypt/options.py @@ -114,7 +114,7 @@ def __init__( f"kms_providers[{name!r}] must contain " "'email' and 'privateKey'" ) - if not isinstance(provider["privateKey"], (bytes, unicode_type)): + if not isinstance(provider["privateKey"], bytes | unicode_type): raise TypeError( f"kms_providers[{name!r}]['privateKey'] must " "be an instance of bytes or str" @@ -122,7 +122,7 @@ def __init__( elif provider_type == "kmip": if "endpoint" not in provider: raise ValueError(f"kms_providers[{name!r}] must contain 'endpoint'") - if not isinstance(provider["endpoint"], (str, unicode_type)): + if not isinstance(provider["endpoint"], str | unicode_type): raise TypeError( f"kms_providers[{name!r}]['endpoint'] must " "be an instance of str" @@ -130,7 +130,7 @@ def __init__( elif provider_type == "local": if "key" not in provider: raise ValueError(f"kms_providers[{name!r}] must contain 'key'") - if not isinstance(provider["key"], (bytes, unicode_type)): + if not isinstance(provider["key"], bytes | unicode_type): raise TypeError( f"kms_providers[{name!r}]['key'] must be an " "instance of bytes or str" diff --git a/bindings/python/test/performance/perf_test.py b/bindings/python/test/performance/perf_test.py index 2d66063d7..8a11a7c3a 100644 --- a/bindings/python/test/performance/perf_test.py +++ b/bindings/python/test/performance/perf_test.py @@ -20,7 +20,6 @@ import time import unittest from concurrent.futures import ThreadPoolExecutor -from typing import List try: import simplejson as json @@ -52,7 +51,7 @@ OUTPUT_FILE = os.environ.get("OUTPUT_FILE") -result_data: List = [] +result_data: list = [] def read(filename, **kwargs): From d335cf62446a9efb1468b49c6240b8b91bcd947b Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Tue, 29 Jul 2025 19:02:25 -0500 Subject: [PATCH 07/19] restore 3.9 support --- .github/workflows/dist-python.yml | 2 +- .github/workflows/test-python.yml | 2 +- bindings/python/.evergreen/test.sh | 2 ++ bindings/python/.evergreen/utils.sh | 24 ++++++++++++------------ bindings/python/pyproject.toml | 3 ++- 5 files changed, 18 insertions(+), 15 deletions(-) diff --git a/.github/workflows/dist-python.yml b/.github/workflows/dist-python.yml index 96536c847..325b64e03 100644 --- a/.github/workflows/dist-python.yml +++ b/.github/workflows/dist-python.yml @@ -47,7 +47,7 @@ jobs: - uses: actions/setup-python@v5 with: - python-version: "3.10" + python-version: "3.9" cache: 'pip' cache-dependency-path: 'bindings/python/pyproject.toml' allow-prereleases: true diff --git a/.github/workflows/test-python.yml b/.github/workflows/test-python.yml index 5f0322f67..8f9b589ed 100644 --- a/.github/workflows/test-python.yml +++ b/.github/workflows/test-python.yml @@ -43,7 +43,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-latest] - python-version: ["3.10", "3.13", "3.14"] + python-version: ["3.9", "3.13", "3.14"] steps: - uses: actions/checkout@v4 diff --git a/bindings/python/.evergreen/test.sh b/bindings/python/.evergreen/test.sh index fe17d95b8..5295c73e6 100755 --- a/bindings/python/.evergreen/test.sh +++ b/bindings/python/.evergreen/test.sh @@ -31,6 +31,7 @@ elif [ "Darwin" = "$(uname -s)" ]; then export PYMONGOCRYPT_LIB=${MONGOCRYPT_DIR}/nocrypto/lib/libmongocrypt.dylib PYMONGOCRYPT_LIB_CRYPTO=${MONGOCRYPT_DIR}/lib/libmongocrypt.dylib PYTHONS=( + "/Library/Frameworks/Python.framework/Versions/3.9/bin/python3" "/Library/Frameworks/Python.framework/Versions/3.10/bin/python3" "/Library/Frameworks/Python.framework/Versions/3.11/bin/python3" "/Library/Frameworks/Python.framework/Versions/3.12/bin/python3" @@ -58,6 +59,7 @@ else ) else PYTHONS=( + "/opt/python/3.9/bin/python3" "/opt/python/3.10/bin/python3" "/opt/python/3.11/bin/python3" "/opt/python/3.12/bin/python3" diff --git a/bindings/python/.evergreen/utils.sh b/bindings/python/.evergreen/utils.sh index 3d5c078f2..e2d3923d5 100755 --- a/bindings/python/.evergreen/utils.sh +++ b/bindings/python/.evergreen/utils.sh @@ -36,37 +36,37 @@ createvirtualenv () { # PYTHON = find_python3 find_python3() { PYTHON="" - # Add a fallback system python3 if it is available and Python 3.10+. - if is_python_310 "$(command -v python3)"; then + # Add a fallback system python3 if it is available and Python 3.9+. + if is_python_39 "$(command -v python3)"; then PYTHON="$(command -v python3)" fi # Find a suitable toolchain version, if available. if [ "$(uname -s)" = "Darwin" ]; then - PYTHON="/Library/Frameworks/Python.Framework/Versions/3.10/bin/python3" + PYTHON="/Library/Frameworks/Python.Framework/Versions/3.9/bin/python3" elif [ "Windows_NT" = "${OS:-}" ]; then # Magic variable in cygwin PYTHON="C:/python/Python310/python.exe" else - # Prefer our own toolchain, fall back to mongodb toolchain if it has Python 3.10+. - if [ -f "/opt/python/3.10/bin/python3" ]; then - PYTHON="/opt/python/3.10/bin/python3" - elif is_python_310 "$(command -v /opt/mongodbtoolchain/v4/bin/python3)"; then + # Prefer our own toolchain, fall back to mongodb toolchain if it has Python 3.9+. + if [ -f "/opt/python/3.9/bin/python3" ]; then + PYTHON="/opt/python/3.9/bin/python3" + elif is_python_39 "$(command -v /opt/mongodbtoolchain/v4/bin/python3)"; then PYTHON="/opt/mongodbtoolchain/v4/bin/python3" - elif is_python_310 "$(command -v /opt/mongodbtoolchain/v3/bin/python3)"; then + elif is_python_39 "$(command -v /opt/mongodbtoolchain/v3/bin/python3)"; then PYTHON="/opt/mongodbtoolchain/v3/bin/python3" fi fi if [ -z "$PYTHON" ]; then - echo "Cannot run pre-commit without python3.10+ installed!" + echo "Cannot run pre-commit without python3.9+ installed!" exit 1 fi echo "$PYTHON" } -# Function that returns success if the provided Python binary is version 3.10 or later +# Function that returns success if the provided Python binary is version 3.9 or later # Usage: -# is_python_310 /path/to/python +# is_python_39 /path/to/python # * param1: Python binary -is_python_310() { +is_python_39() { if [ -z "$1" ]; then return 1 elif $1 -c "import sys; exit(sys.version_info[:2] < (3, 10))"; then diff --git a/bindings/python/pyproject.toml b/bindings/python/pyproject.toml index 5c83f6dfc..5859d13bf 100644 --- a/bindings/python/pyproject.toml +++ b/bindings/python/pyproject.toml @@ -8,7 +8,7 @@ dynamic = ["version", "dependencies", "optional-dependencies"] description = "Python bindings for libmongocrypt" readme = "README.rst" license = {file="LICENSE"} -requires-python = ">=3.10" +requires-python = ">=3.9" authors = [ { name = "Shane Harvey", email = "mongodb-user@googlegroups.com" }, ] @@ -31,6 +31,7 @@ classifiers = [ "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", + "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", From 2e2376763fe69290186863622aab0e5233aa35fa Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Tue, 29 Jul 2025 19:07:52 -0500 Subject: [PATCH 08/19] fix up 3.14 support --- .github/workflows/test-python.yml | 5 ++++- bindings/python/.evergreen/test.sh | 2 +- bindings/python/requirements.txt | 3 +-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test-python.yml b/.github/workflows/test-python.yml index 8f9b589ed..0493e3106 100644 --- a/.github/workflows/test-python.yml +++ b/.github/workflows/test-python.yml @@ -43,7 +43,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-latest] - python-version: ["3.9", "3.13", "3.14"] + python-version: ["3.9", "3.13", "3.14t"] steps: - uses: actions/checkout@v4 @@ -57,6 +57,9 @@ jobs: python-version: ${{ matrix.python-version }} - name: Build and test dist files run: | + if [ "${{ matrix.python-version }}" == "3.14" ]; then + export PIP_PRE=1 + fi export LIBMONGOCRYPT_VERSION=$(cat ./scripts/libmongocrypt-version.txt) git fetch origin $LIBMONGOCRYPT_VERSION bash ./scripts/release.sh diff --git a/bindings/python/.evergreen/test.sh b/bindings/python/.evergreen/test.sh index 5295c73e6..0c2f56dca 100755 --- a/bindings/python/.evergreen/test.sh +++ b/bindings/python/.evergreen/test.sh @@ -76,7 +76,7 @@ for PYTHON_BINARY in "${PYTHONS[@]}"; do $PYTHON_BINARY -c 'import sys; print(sys.version)' git clean -dffx createvirtualenv $PYTHON_BINARY .venv - python -m pip install --prefer-binary -v -e ".[test]" + python -m pip install --prefer-binary -v -e ".[test]" || python -m pip install --pre --prefer-binary -v -e ".[test]" echo "Running tests with crypto enabled libmongocrypt..." PYMONGOCRYPT_LIB=$PYMONGOCRYPT_LIB_CRYPTO python -c 'from pymongocrypt.binding import lib;assert lib.mongocrypt_is_crypto_available(), "mongocrypt_is_crypto_available() returned False"' PYMONGOCRYPT_LIB=$PYMONGOCRYPT_LIB_CRYPTO python -m pytest -v --ignore=test/performance . diff --git a/bindings/python/requirements.txt b/bindings/python/requirements.txt index 507493e57..c64bcb573 100644 --- a/bindings/python/requirements.txt +++ b/bindings/python/requirements.txt @@ -1,5 +1,4 @@ -cffi>=1.12.0,<3;python_version<"3.14" -cffi>=2.0.0b1,<3;python_version=="3.14" +cffi>=1.12.0,<3 cryptography>=40 packaging>=21.0 httpx>=0.25.0 From ab4617e75ece95ede895cc2476a14ea06e40ad77 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Tue, 29 Jul 2025 19:12:40 -0500 Subject: [PATCH 09/19] fix up 3.14 support --- .github/workflows/test-python.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-python.yml b/.github/workflows/test-python.yml index 0493e3106..bdce36520 100644 --- a/.github/workflows/test-python.yml +++ b/.github/workflows/test-python.yml @@ -43,7 +43,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-latest] - python-version: ["3.9", "3.13", "3.14t"] + python-version: ["3.9", "3.13", "3.14"] steps: - uses: actions/checkout@v4 From fcd004685d7a668410bc0aca0842b5e4b1c32cfd Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 30 Jul 2025 06:16:27 -0500 Subject: [PATCH 10/19] Revert "lint" This reverts commit 5f1b8552cd0619a83cbb13e26fd65167fd740aa6. --- bindings/python/pymongocrypt/mongocrypt.py | 2 +- bindings/python/pymongocrypt/options.py | 6 +++--- bindings/python/test/performance/perf_test.py | 3 ++- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/bindings/python/pymongocrypt/mongocrypt.py b/bindings/python/pymongocrypt/mongocrypt.py index 46520b6f9..608d39e32 100644 --- a/bindings/python/pymongocrypt/mongocrypt.py +++ b/bindings/python/pymongocrypt/mongocrypt.py @@ -52,7 +52,7 @@ def __init__(self, options, callback): if not isinstance(options, MongoCryptOptions): raise TypeError("options must be a MongoCryptOptions") - if not isinstance(callback, AsyncMongoCryptCallback | MongoCryptCallback): + if not isinstance(callback, (AsyncMongoCryptCallback, MongoCryptCallback)): raise TypeError( "callback must be a MongoCryptCallback or AsyncMongoCryptCallback" ) diff --git a/bindings/python/pymongocrypt/options.py b/bindings/python/pymongocrypt/options.py index a709ed3e5..c1e27b1d5 100644 --- a/bindings/python/pymongocrypt/options.py +++ b/bindings/python/pymongocrypt/options.py @@ -114,7 +114,7 @@ def __init__( f"kms_providers[{name!r}] must contain " "'email' and 'privateKey'" ) - if not isinstance(provider["privateKey"], bytes | unicode_type): + if not isinstance(provider["privateKey"], (bytes, unicode_type)): raise TypeError( f"kms_providers[{name!r}]['privateKey'] must " "be an instance of bytes or str" @@ -122,7 +122,7 @@ def __init__( elif provider_type == "kmip": if "endpoint" not in provider: raise ValueError(f"kms_providers[{name!r}] must contain 'endpoint'") - if not isinstance(provider["endpoint"], str | unicode_type): + if not isinstance(provider["endpoint"], (str, unicode_type)): raise TypeError( f"kms_providers[{name!r}]['endpoint'] must " "be an instance of str" @@ -130,7 +130,7 @@ def __init__( elif provider_type == "local": if "key" not in provider: raise ValueError(f"kms_providers[{name!r}] must contain 'key'") - if not isinstance(provider["key"], bytes | unicode_type): + if not isinstance(provider["key"], (bytes, unicode_type)): raise TypeError( f"kms_providers[{name!r}]['key'] must be an " "instance of bytes or str" diff --git a/bindings/python/test/performance/perf_test.py b/bindings/python/test/performance/perf_test.py index 8a11a7c3a..2d66063d7 100644 --- a/bindings/python/test/performance/perf_test.py +++ b/bindings/python/test/performance/perf_test.py @@ -20,6 +20,7 @@ import time import unittest from concurrent.futures import ThreadPoolExecutor +from typing import List try: import simplejson as json @@ -51,7 +52,7 @@ OUTPUT_FILE = os.environ.get("OUTPUT_FILE") -result_data: list = [] +result_data: List = [] def read(filename, **kwargs): From 3fe310dc9adc7b67b8510a5ebcaf154687bac65c Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 30 Jul 2025 06:17:13 -0500 Subject: [PATCH 11/19] fix up 3.9 support --- bindings/python/test/performance/perf_test.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bindings/python/test/performance/perf_test.py b/bindings/python/test/performance/perf_test.py index 2d66063d7..8a11a7c3a 100644 --- a/bindings/python/test/performance/perf_test.py +++ b/bindings/python/test/performance/perf_test.py @@ -20,7 +20,6 @@ import time import unittest from concurrent.futures import ThreadPoolExecutor -from typing import List try: import simplejson as json @@ -52,7 +51,7 @@ OUTPUT_FILE = os.environ.get("OUTPUT_FILE") -result_data: List = [] +result_data: list = [] def read(filename, **kwargs): From 75c925b99934de626b2cc512be1aba5635da1b3c Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 30 Jul 2025 06:58:15 -0500 Subject: [PATCH 12/19] update changelog --- bindings/python/CHANGELOG.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/bindings/python/CHANGELOG.rst b/bindings/python/CHANGELOG.rst index e7fb9bf8a..b1349361f 100644 --- a/bindings/python/CHANGELOG.rst +++ b/bindings/python/CHANGELOG.rst @@ -1,6 +1,12 @@ Changelog ========= +Changes in Version 1.15.0 +------------------------- + +- Add support for Python 3.14. +- Drop support for Python 3.8. + Changes in Version 1.14.1 ------------------------- From 4650bebd695f93778aac7da15aa71ceb353ba6cf Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 30 Jul 2025 06:59:27 -0500 Subject: [PATCH 13/19] update workflows --- .github/workflows/dist-python.yml | 2 +- .github/workflows/test-python.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dist-python.yml b/.github/workflows/dist-python.yml index 325b64e03..554c0f357 100644 --- a/.github/workflows/dist-python.yml +++ b/.github/workflows/dist-python.yml @@ -30,7 +30,7 @@ defaults: jobs: build_dist: - if: github.repository_owner == 'blink1073' || (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') + if: github.repository_owner == 'mongodb' || (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') runs-on: ${{ matrix.os }} strategy: matrix: diff --git a/.github/workflows/test-python.yml b/.github/workflows/test-python.yml index bdce36520..c4356e7a2 100644 --- a/.github/workflows/test-python.yml +++ b/.github/workflows/test-python.yml @@ -20,7 +20,7 @@ defaults: jobs: static: - if: github.repository_owner == 'blink1073' + if: github.repository_owner == 'mongodb' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -37,7 +37,7 @@ jobs: check-manifest -v build: - if: github.repository_owner == 'blink1073' + if: github.repository_owner == 'mongodb' runs-on: ${{ matrix.os }} strategy: fail-fast: false From 51a4483ba5b110e0505f28aa374c6a4008518c05 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 30 Jul 2025 07:01:35 -0500 Subject: [PATCH 14/19] update config.yml --- .evergreen/config.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.evergreen/config.yml b/.evergreen/config.yml index d92e8e7a1..fb9b920d5 100755 --- a/.evergreen/config.yml +++ b/.evergreen/config.yml @@ -553,7 +553,7 @@ tasks: commands: - func: "fetch source" - func: "build python release" - vars: { PYTHON: /Library/Frameworks/Python.framework/Versions/3.10/bin/python3 } + vars: { PYTHON: /Library/Frameworks/Python.framework/Versions/3.9/bin/python3 } - func: "upload python release" - name: "release-python-linux" @@ -563,7 +563,7 @@ tasks: commands: - func: "fetch source" - func: "build python release" - vars: { PYTHON: /opt/python/3.10/bin/python3 } + vars: { PYTHON: /opt/python/3.9/bin/python3 } - func: "upload python release" - name: "release-python-windows" @@ -572,7 +572,7 @@ tasks: commands: - func: "fetch source" - func: "build python release" - vars: { PYTHON: C:/python/Python310/python.exe } + vars: { PYTHON: C:/python/Python39/python.exe } - func: "upload python release" - name: "release-python-combine" From 80b72179897b01d8c1d9d178d0f4e2a31f3401a2 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 30 Jul 2025 07:01:56 -0500 Subject: [PATCH 15/19] update config.yml --- .evergreen/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.evergreen/config.yml b/.evergreen/config.yml index fb9b920d5..15ce3419b 100755 --- a/.evergreen/config.yml +++ b/.evergreen/config.yml @@ -553,7 +553,7 @@ tasks: commands: - func: "fetch source" - func: "build python release" - vars: { PYTHON: /Library/Frameworks/Python.framework/Versions/3.9/bin/python3 } + vars: { PYTHON: /Library/Frameworks/Python.framework/Versions/3.10/bin/python3 } - func: "upload python release" - name: "release-python-linux" From 4344ce9157949e4e0569ce93c411ece084b4a2c2 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 30 Jul 2025 07:02:51 -0500 Subject: [PATCH 16/19] update utils.sh --- bindings/python/.evergreen/utils.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/python/.evergreen/utils.sh b/bindings/python/.evergreen/utils.sh index e2d3923d5..99c41a72b 100755 --- a/bindings/python/.evergreen/utils.sh +++ b/bindings/python/.evergreen/utils.sh @@ -44,7 +44,7 @@ find_python3() { if [ "$(uname -s)" = "Darwin" ]; then PYTHON="/Library/Frameworks/Python.Framework/Versions/3.9/bin/python3" elif [ "Windows_NT" = "${OS:-}" ]; then # Magic variable in cygwin - PYTHON="C:/python/Python310/python.exe" + PYTHON="C:/python/Python39/python.exe" else # Prefer our own toolchain, fall back to mongodb toolchain if it has Python 3.9+. if [ -f "/opt/python/3.9/bin/python3" ]; then From 50ccbc63ff007e3ed96eaa4ae7c0b49093ebfa64 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 30 Jul 2025 07:03:19 -0500 Subject: [PATCH 17/19] update utils.sh --- bindings/python/.evergreen/utils.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bindings/python/.evergreen/utils.sh b/bindings/python/.evergreen/utils.sh index 99c41a72b..b96521e98 100755 --- a/bindings/python/.evergreen/utils.sh +++ b/bindings/python/.evergreen/utils.sh @@ -69,8 +69,8 @@ find_python3() { is_python_39() { if [ -z "$1" ]; then return 1 - elif $1 -c "import sys; exit(sys.version_info[:2] < (3, 10))"; then - # runs when sys.version_info[:2] >= (3, 10) + elif $1 -c "import sys; exit(sys.version_info[:2] < (3, 9))"; then + # runs when sys.version_info[:2] >= (3, 9) return 0 else return 1 From f1ce39286789900265545b8600f837cc346fb12c Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 30 Jul 2025 10:27:44 -0500 Subject: [PATCH 18/19] test on macos14 --- .evergreen/config.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.evergreen/config.yml b/.evergreen/config.yml index 15ce3419b..f84e659f5 100755 --- a/.evergreen/config.yml +++ b/.evergreen/config.yml @@ -1627,6 +1627,14 @@ buildvariants: tasks: - build-and-test-and-upload - test-python +- name: macos-14 + display_name: macOS 14 (arm) + run_on: macos-14-arm64 + expansions: + compile_env: MACOS_UNIVERSAL=ON CMAKE=/opt/homebrew/bin/cmake + tasks: + - build-and-test-and-upload + - test-python - name: windows-vs2017-32bit # Test Windows 32 bit builds for PHPC. PHPC builds libmongocrypt from source. See MONGOCRYPT-391. display_name: "Windows VS 2017 32-bit compile" From 4b493147846d449922b8e1e197dbbf2f01821ee7 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 30 Jul 2025 10:49:10 -0500 Subject: [PATCH 19/19] skip 3.14 test on macos --- .evergreen/config.yml | 8 -------- bindings/python/.evergreen/test.sh | 3 ++- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/.evergreen/config.yml b/.evergreen/config.yml index f84e659f5..15ce3419b 100755 --- a/.evergreen/config.yml +++ b/.evergreen/config.yml @@ -1627,14 +1627,6 @@ buildvariants: tasks: - build-and-test-and-upload - test-python -- name: macos-14 - display_name: macOS 14 (arm) - run_on: macos-14-arm64 - expansions: - compile_env: MACOS_UNIVERSAL=ON CMAKE=/opt/homebrew/bin/cmake - tasks: - - build-and-test-and-upload - - test-python - name: windows-vs2017-32bit # Test Windows 32 bit builds for PHPC. PHPC builds libmongocrypt from source. See MONGOCRYPT-391. display_name: "Windows VS 2017 32-bit compile" diff --git a/bindings/python/.evergreen/test.sh b/bindings/python/.evergreen/test.sh index 0c2f56dca..ccc916481 100755 --- a/bindings/python/.evergreen/test.sh +++ b/bindings/python/.evergreen/test.sh @@ -36,7 +36,8 @@ elif [ "Darwin" = "$(uname -s)" ]; then "/Library/Frameworks/Python.framework/Versions/3.11/bin/python3" "/Library/Frameworks/Python.framework/Versions/3.12/bin/python3" "/Library/Frameworks/Python.framework/Versions/3.13/bin/python3" - "/Library/Frameworks/Python.framework/Versions/3.14/bin/python3" + # TODO: PYTHON-5466 + #"/Library/Frameworks/Python.framework/Versions/3.14/bin/python3" ) export CRYPT_SHARED_PATH="../crypt_shared/lib/mongo_crypt_v1.dylib"