MOTOR-1423 Restore compatibility with latest pymongo (#319)

This commit is contained in:
Steven Silvester 2025-01-29 13:16:09 -06:00 committed by GitHub
parent 1433773db4
commit 932bb7382e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 199 additions and 156 deletions

View File

@ -346,33 +346,6 @@ tasks:
# Test tasks {{{ # Test tasks {{{
- name: "test-3.6-standalone"
tags: ["3.6", "standalone"]
commands:
- func: "bootstrap mongo-orchestration"
vars:
VERSION: "3.6"
TOPOLOGY: "server"
- func: "run tox"
- name: "test-3.6-replica_set"
tags: ["3.6", "replica_set"]
commands:
- func: "bootstrap mongo-orchestration"
vars:
VERSION: "3.6"
TOPOLOGY: "replica_set"
- func: "run tox"
- name: "test-3.6-sharded_cluster"
tags: ["3.6", "sharded_cluster"]
commands:
- func: "bootstrap mongo-orchestration"
vars:
VERSION: "3.6"
TOPOLOGY: "sharded_cluster"
- func: "run tox"
- name: "test-4.0-standalone" - name: "test-4.0-standalone"
tags: ["4.0", "standalone"] tags: ["4.0", "standalone"]
commands: commands:
@ -684,10 +657,6 @@ axes:
variables: variables:
TOX_ENV: "test" TOX_ENV: "test"
PYTHON_BINARY: "/opt/python/pypy3.9/bin/python3" PYTHON_BINARY: "/opt/python/pypy3.9/bin/python3"
- id: "test-py38"
variables:
TOX_ENV: "test"
PYTHON_BINARY: "/opt/python/3.8/bin/python3"
- id: "test-py39" - id: "test-py39"
variables: variables:
TOX_ENV: "test" TOX_ENV: "test"
@ -708,14 +677,26 @@ axes:
variables: variables:
TOX_ENV: "test" TOX_ENV: "test"
PYTHON_BINARY: "/opt/python/3.13/bin/python3" PYTHON_BINARY: "/opt/python/3.13/bin/python3"
- id: "test-pymongo-4.9"
variables:
TOX_ENV: "test-pymongo-4.9"
PYTHON_BINARY: "/opt/python/3.9/bin/python3"
- id: "test-pymongo-4.10"
variables:
TOX_ENV: "test-pymongo-4.10"
PYTHON_BINARY: "/opt/python/3.9/bin/python3"
- id: "test-pymongo-4.11"
variables:
TOX_ENV: "test-pymongo-4.11"
PYTHON_BINARY: "/opt/python/3.9/bin/python3"
- id: "test-pymongo-latest" - id: "test-pymongo-latest"
variables: variables:
TOX_ENV: "test-pymongo-latest" TOX_ENV: "test-pymongo-latest"
PYTHON_BINARY: "/opt/python/3.8/bin/python3" PYTHON_BINARY: "/opt/python/3.9/bin/python3"
- id: "synchro-py38" - id: "synchro-py39"
variables: variables:
TOX_ENV: "synchro" TOX_ENV: "synchro"
PYTHON_BINARY: "/opt/python/3.8/bin/python3" PYTHON_BINARY: "/opt/python/3.9/bin/python3"
- id: "synchro-py312" - id: "synchro-py312"
variables: variables:
TOX_ENV: "synchro" TOX_ENV: "synchro"
@ -729,22 +710,18 @@ axes:
TOX_ENV: "test" TOX_ENV: "test"
PYTHON_BINARY: "/opt/python/3.9/bin/python3" PYTHON_BINARY: "/opt/python/3.9/bin/python3"
# Test Python 3.8 only on Mac. # Test Python 3.9 only on Mac.
- id: tox-env-osx - id: tox-env-osx
display_name: "Tox Env OSX" display_name: "Tox Env OSX"
values: values:
- id: "test" - id: "test"
variables: variables:
TOX_ENV: "test" TOX_ENV: "test"
PYTHON_BINARY: "/Library/Frameworks/Python.framework/Versions/3.8/bin/python3" PYTHON_BINARY: "/Library/Frameworks/Python.framework/Versions/3.9/bin/python3"
- id: tox-env-win - id: tox-env-win
display_name: "Tox Env Windows" display_name: "Tox Env Windows"
values: values:
- id: "test-py38"
variables:
TOX_ENV: "test"
PYTHON_BINARY: "c:/python/Python39/python.exe"
- id: "test-py39" - id: "test-py39"
variables: variables:
TOX_ENV: "test" TOX_ENV: "test"
@ -791,7 +768,7 @@ buildvariants:
# TODO: synchro needs PyMongo's updated SSL test certs, # TODO: synchro needs PyMongo's updated SSL test certs,
# which may require Motor test suite changes. # which may require Motor test suite changes.
- os: "*" - os: "*"
tox-env: ["synchro-py38", "synchro-py312"] tox-env: ["synchro-py39", "synchro-py312"]
ssl: "ssl" ssl: "ssl"
tasks: tasks:
- ".rapid" - ".rapid"
@ -803,7 +780,6 @@ buildvariants:
- ".4.4" - ".4.4"
- ".4.2" - ".4.2"
- ".4.0" - ".4.0"
- ".3.6"
- matrix_name: "test-rhel7" - matrix_name: "test-rhel7"
display_name: "${os}-${tox-env-rhel7}-${ssl}" display_name: "${os}-${tox-env-rhel7}-${ssl}"
@ -852,7 +828,7 @@ buildvariants:
- matrix_name: "enterprise-auth" - matrix_name: "enterprise-auth"
display_name: "Enterprise Auth-${tox-env}" display_name: "Enterprise Auth-${tox-env}"
matrix_spec: {"tox-env": ["synchro-py38", "synchro-py312"], ssl: "ssl"} matrix_spec: {"tox-env": ["synchro-py39", "synchro-py312"], ssl: "ssl"}
run_on: run_on:
- "rhel84-small" - "rhel84-small"
tasks: tasks:
@ -864,7 +840,7 @@ buildvariants:
- "rhel84-small" - "rhel84-small"
expansions: expansions:
TOX_ENV: "docs" TOX_ENV: "docs"
PYTHON_BINARY: "/opt/python/3.8/bin/python3" PYTHON_BINARY: "/opt/python/3.9/bin/python3"
tasks: tasks:
- name: "docs" - name: "docs"
@ -874,7 +850,7 @@ buildvariants:
- "rhel84-small" - "rhel84-small"
expansions: expansions:
TOX_ENV: "doctest" TOX_ENV: "doctest"
PYTHON_BINARY: "/opt/python/3.8/bin/python3" PYTHON_BINARY: "/opt/python/3.9/bin/python3"
tasks: tasks:
- name: "doctest" - name: "doctest"

View File

@ -67,17 +67,12 @@ createvirtualenv () {
} }
if $PYTHON_BINARY -m tox --version; then # Set up a virtualenv and install tox.
run_tox() { createvirtualenv "$PYTHON_BINARY" toxenv
$PYTHON_BINARY -m tox -m $TOX_ENV "$@" trap "deactivate; rm -rf toxenv" EXIT HUP
} python -m pip install tox
else # No toolchain present, set up virtualenv before installing tox run_tox() {
createvirtualenv "$PYTHON_BINARY" toxenv python -m tox -m $TOX_ENV "$@"
trap "deactivate; rm -rf toxenv" EXIT HUP }
python -m pip install tox
run_tox() {
python -m tox -m $TOX_ENV "$@"
}
fi
run_tox "${@:1}" run_tox "${@:1}"

View File

@ -20,7 +20,7 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [ubuntu-20.04] os: [ubuntu-20.04]
python-version: ["3.8", "3.12", "3.13"] python-version: ["3.9", "3.12", "3.13"]
fail-fast: false fail-fast: false
name: CPython ${{ matrix.python-version }}-${{ matrix.os }} name: CPython ${{ matrix.python-version }}-${{ matrix.os }}
steps: steps:
@ -53,7 +53,7 @@ jobs:
persist-credentials: false persist-credentials: false
- uses: actions/setup-python@v5 - uses: actions/setup-python@v5
with: with:
python-version: 3.8 python-version: 3.9
cache: 'pip' cache: 'pip'
cache-dependency-path: 'pyproject.toml' cache-dependency-path: 'pyproject.toml'
- name: Install Python dependencies - name: Install Python dependencies
@ -71,7 +71,7 @@ jobs:
persist-credentials: false persist-credentials: false
- uses: actions/setup-python@v5 - uses: actions/setup-python@v5
with: with:
python-version: 3.8 python-version: 3.9
cache: 'pip' cache: 'pip'
cache-dependency-path: 'pyproject.toml' cache-dependency-path: 'pyproject.toml'
- name: Install Python dependencies - name: Install Python dependencies
@ -96,7 +96,7 @@ jobs:
persist-credentials: false persist-credentials: false
- uses: actions/setup-python@v5 - uses: actions/setup-python@v5
with: with:
python-version: 3.8 python-version: 3.9
cache: 'pip' cache: 'pip'
cache-dependency-path: 'pyproject.toml' cache-dependency-path: 'pyproject.toml'
- name: Install Python dependencies - name: Install Python dependencies

1
.gitignore vendored
View File

@ -14,3 +14,4 @@ doc/_build/
xunit-results xunit-results
xunit-synchro-results xunit-synchro-results
.eggs .eggs
toxenv

View File

@ -35,7 +35,7 @@ Python version on your path, and run:
tox -m test tox -m test
``` ```
The doctests pass with Python 3.8+ and a MongoDB 5.0 instance running on The doctests pass with Python 3.9+ and a MongoDB 5.0 instance running on
port 27017: port 27017:
```bash ```bash

View File

@ -108,8 +108,8 @@ Motor works in all the environments officially supported by Tornado or
by asyncio. It requires: by asyncio. It requires:
- Unix (including macOS) or Windows. - Unix (including macOS) or Windows.
- [PyMongo](http://pypi.python.org/pypi/pymongo/) >=4.1,<5 - [PyMongo](http://pypi.python.org/pypi/pymongo/) >=4.9,<5
- Python 3.8+ - Python 3.9+
Optional dependencies: Optional dependencies:
@ -185,7 +185,7 @@ ReadTheDocs](https://motor.readthedocs.io/en/stable/examples/index.html).
Motor's documentation is on Motor's documentation is on
[ReadTheDocs](https://motor.readthedocs.io/en/stable/). [ReadTheDocs](https://motor.readthedocs.io/en/stable/).
Build the documentation with Python 3.8+. Install Build the documentation with Python 3.9+. Install
[sphinx](http://sphinx.pocoo.org/), [Tornado](http://tornadoweb.org/), [sphinx](http://sphinx.pocoo.org/), [Tornado](http://tornadoweb.org/),
and [aiohttp](https://github.com/aio-libs/aiohttp), and do and [aiohttp](https://github.com/aio-libs/aiohttp), and do
`cd doc; make html`. `cd doc; make html`.

View File

@ -3,6 +3,13 @@ Changelog
.. currentmodule:: motor.motor_tornado .. currentmodule:: motor.motor_tornado
Motor 3.7.0
-----------
- Add support for PyMongo 4.10.
- Drop support for Python 3.8.
- Drop support for MongoDB 3.6.
Motor 3.6.1 Motor 3.6.1
----------- -----------
- Add return type to to_list method in stub file. - Add return type to to_list method in stub file.
@ -735,7 +742,7 @@ Motor 1.0
Motor now depends on PyMongo 3.3 and later. The move from PyMongo 2 to 3 brings Motor now depends on PyMongo 3.3 and later. The move from PyMongo 2 to 3 brings
a large number of API changes, read the `the PyMongo 3 changelog`_ carefully. a large number of API changes, read the `the PyMongo 3 changelog`_ carefully.
.. _the PyMongo 3 changelog: https://pymongo.readthedocs.io/en/stable/changelog.html#changes-in-version-3-0 .. _the PyMongo 3 changelog: https://pymongo.readthedocs.io/en/4.0/changelog.html#changes-in-version-3-0
:class:`MotorReplicaSetClient` is removed :class:`MotorReplicaSetClient` is removed
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -1271,8 +1278,7 @@ therefore inheriting
`PyMongo 2.7.2's bug fixes <https://jira.mongodb.org/browse/PYTHON/fixforversion/14005>`_ `PyMongo 2.7.2's bug fixes <https://jira.mongodb.org/browse/PYTHON/fixforversion/14005>`_
and and
`PyMongo 2.8's bug fixes <https://jira.mongodb.org/browse/PYTHON/fixforversion/14223>`_ `PyMongo 2.8's bug fixes <https://jira.mongodb.org/browse/PYTHON/fixforversion/14223>`_
and `features and features.
<https://pymongo.readthedocs.io/en/stable/changelog.html#changes-in-version-2-8>`_.
Fixes `a connection-pool timeout when waitQueueMultipleMS is set Fixes `a connection-pool timeout when waitQueueMultipleMS is set
<https://jira.mongodb.org/browse/MOTOR-62>`_ and `two bugs in replica set <https://jira.mongodb.org/browse/MOTOR-62>`_ and `two bugs in replica set

View File

@ -19,8 +19,8 @@ Motor works in all the environments officially supported by Tornado or by
asyncio. It requires: asyncio. It requires:
* Unix (including macOS) or Windows. * Unix (including macOS) or Windows.
* PyMongo_ >=4.1,<5 * PyMongo_ >=4.9,<5
* Python 3.8+ * Python 3.9+
Optional dependencies: Optional dependencies:

View File

@ -3,12 +3,12 @@ Requirements
The current version of Motor requires: The current version of Motor requires:
* CPython 3.8 and later. * CPython 3.9 and later.
* PyMongo_ 4.5 and later. * PyMongo_ 4.9 and later.
Motor can integrate with either Tornado or asyncio. Motor can integrate with either Tornado or asyncio.
The default authentication mechanism for MongoDB 3.0+ is SCRAM-SHA-1. The default authentication mechanism for MongoDB is SCRAM-SHA-1.
Building the docs requires `sphinx`_. Building the docs requires `sphinx`_.
@ -37,29 +37,41 @@ Motor and PyMongo
+-------------------+-----------------+ +-------------------+-----------------+
| 3.3 | 4.5+ | | 3.3 | 4.5+ |
+-------------------+-----------------+ +-------------------+-----------------+
| 3.4 | 4.6+ | | 3.4 | 4.5+ |
+-------------------+-----------------+
| 3.5 | 4.5+ |
+-------------------+-----------------+
| 3.6 | 4.9 |
+-------------------+-----------------+
| 3.7 | 4.9+ |
+-------------------+-----------------+ +-------------------+-----------------+
Motor and MongoDB Motor and MongoDB
````````````````` `````````````````
+---------------------------------------------------------------+ +---------------------------------------------------------------------+
| MongoDB Version | | MongoDB Version |
+=====================+=====+=====+=====+=====+=====+=====+=====+ +=====================+=====+=====+=====+=====+=====+=====+=====+=====+
| | 3.6 | 4.0 | 4.2 | 4.4 | 5.0 | 6.0 | 7.0 | | | 3.6 | 4.0 | 4.2 | 4.4 | 5.0 | 6.0 | 7.0 | 8.0 |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+ +---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| Motor Version | 2.5 | Y | Y | Y | Y | Y |**N**|**N**| | Motor Version | 2.5 | Y | Y | Y | Y | Y |**N**|**N**|**N**|
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+ +---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| | 3.0 | Y | Y | Y | Y | Y |**N**|**N**| | | 3.0 | Y | Y | Y | Y | Y |**N**|**N**|**N**|
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+ +---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| | 3.1 | Y | Y | Y | Y | Y | Y |**N**| | | 3.1 | Y | Y | Y | Y | Y | Y |**N**|**N**|
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+ +---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| | 3.2 | Y | Y | Y | Y | Y | Y | Y | | | 3.2 | Y | Y | Y | Y | Y | Y | Y |**N**|
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+ +---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| | 3.3 | Y | Y | Y | Y | Y | Y | Y | | | 3.3 | Y | Y | Y | Y | Y | Y | Y |**N**|
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+ +---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| | 3.4 | Y | Y | Y | Y | Y | Y | Y | | | 3.4 | Y | Y | Y | Y | Y | Y | Y |**N**|
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+ +---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| | 3.5 | Y | Y | Y | Y | Y | Y | Y | Y |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| | 3.6 | Y | Y | Y | Y | Y | Y | Y | Y |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| | 3.7 | N | Y | Y | Y | Y | Y | Y | Y |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
There is no relationship between PyMongo and MongoDB version numbers, although There is no relationship between PyMongo and MongoDB version numbers, although
the numbers happen to be close or equal in recent releases of PyMongo and MongoDB. the numbers happen to be close or equal in recent releases of PyMongo and MongoDB.
@ -102,45 +114,51 @@ Motor 3.1.1 added support for Python 3.11.
Motor 3.3 added support for Python 3.12. Motor 3.3 added support for Python 3.12.
Motor 3.5 dropped support for Python 3.7. Motor 3.5 dropped support for Python 3.7 and added support for Python 3.13.
+---------------------------------------------------------------+ Motor 3.7 dropped support for Python 3.8.
| Python Version |
+=====================+=====+=====+=====+=====+=====+=====+=====+ +---------------------------------------------------------------------+
| | 3.6 | 3.7 | 3.8 | 3.9 | 3.10| 3.11| 3.12| | Python Version |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+ +=====================+=====+=====+=====+=====+=====+=====+=====+=====+
| Motor Version | 1.0 | Y |**N**|**N**|**N**|**N**|**N**|**N**| | | 3.6 | 3.7 | 3.8 | 3.9 | 3.10| 3.11| 3.12| 3.13|
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+ +---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| | 1.1 | Y |**N**|**N**|**N**|**N**|**N**|**N**| | Motor Version | 1.0 | Y |**N**|**N**|**N**|**N**|**N**|**N**|**N**|
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+ +---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| | 1.2 | Y | Y |**N**|**N**|**N**|**N**|**N**| | | 1.1 | Y |**N**|**N**|**N**|**N**|**N**|**N**|**N**|
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+ +---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| | 1.3 | Y | Y |**N**|**N**|**N**|**N**|**N**| | | 1.2 | Y | Y |**N**|**N**|**N**|**N**|**N**|**N**|
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+ +---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| | 2.0 | Y | Y |**N**|**N**|**N**|**N**|**N**| | | 1.3 | Y | Y |**N**|**N**|**N**|**N**|**N**|**N**|
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+ +---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| | 2.1 | Y | Y | Y |**N**|**N**|**N**|**N**| | | 2.0 | Y | Y |**N**|**N**|**N**|**N**|**N**|**N**|
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+ +---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| | 2.2 | Y | Y | Y |**N**|**N**|**N**|**N**| | | 2.1 | Y | Y | Y |**N**|**N**|**N**|**N**|**N**|
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+ +---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| | 2.3 | Y | Y | Y |**N**|**N**|**N**|**N**| | | 2.2 | Y | Y | Y |**N**|**N**|**N**|**N**|**N**|
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+ +---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| | 2.4 | Y | Y | Y | Y |**N**|**N**|**N**| | | 2.3 | Y | Y | Y |**N**|**N**|**N**|**N**|**N**|
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+ +---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| | 2.5 | Y | Y | Y | Y | Y |**N**|**N**| | | 2.4 | Y | Y | Y | Y |**N**|**N**|**N**|**N**|
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+ +---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| | 3.0 |**N**| Y | Y | Y | Y |**N**|**N**| | | 2.5 | Y | Y | Y | Y | Y |**N**|**N**|**N**|
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+ +---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| | 3.1 |**N**| Y | Y | Y | Y |**Y**|**N**| | | 3.0 |**N**| Y | Y | Y | Y |**N**|**N**|**N**|
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+ +---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| | 3.2 |**N**| Y | Y | Y | Y | Y |**N**| | | 3.1 |**N**| Y | Y | Y | Y | Y |**N**|**N**|
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+ +---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| | 3.3 |**N**| Y | Y | Y | Y | Y |**Y**| | | 3.2 |**N**| Y | Y | Y | Y | Y |**N**|**N**|
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+ +---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| | 3.4 |**N**| Y | Y | Y | Y | Y |**Y**| | | 3.3 |**N**| Y | Y | Y | Y | Y | Y |**N**|
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+ +---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| | 3.5 |**N**|**N**| Y | Y | Y | Y |**Y**| | | 3.4 |**N**| Y | Y | Y | Y | Y | Y |**N**|
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+ +---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| | 3.5 |**N**|**N**| Y | Y | Y | Y | Y |**N**|
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| | 3.6 |**N**|**N**| Y | Y | Y | Y | Y | Y |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| | 3.7 |**N**|**N**|**N**| Y | Y | Y | Y | Y |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
Not Supported Not Supported
------------- -------------

View File

@ -8,7 +8,7 @@ dynamic = ["version", "dependencies", "optional-dependencies"]
description = "Non-blocking MongoDB driver for Tornado or asyncio" description = "Non-blocking MongoDB driver for Tornado or asyncio"
readme = "README.md" readme = "README.md"
license = { file = "LICENSE" } license = { file = "LICENSE" }
requires-python = ">=3.8" requires-python = ">=3.9"
authors = [ authors = [
{ name = "A. Jesse Jiryu Davis", email = "jesse@mongodb.com" }, { name = "A. Jesse Jiryu Davis", email = "jesse@mongodb.com" },
] ]
@ -33,7 +33,6 @@ classifiers = [
"Typing :: Typed", "Typing :: Typed",
"Programming Language :: Python", "Programming Language :: Python",
"Programming Language :: Python :: 3", "Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.9",
"Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy", "Programming Language :: Python :: Implementation :: PyPy",
@ -67,7 +66,7 @@ test = ["requirements/test.txt"]
zstd = ["requirements/zstd.txt"] zstd = ["requirements/zstd.txt"]
[tool.mypy] [tool.mypy]
python_version = "3.8" python_version = "3.9"
strict = true strict = true
pretty = true pretty = true
show_error_context = true show_error_context = true

View File

@ -1 +1 @@
pymongo>=4.9,<4.10 pymongo>=4.9,<5.0

View File

@ -93,6 +93,8 @@ from pymongo.monitoring import *
from pymongo.monitoring import _LISTENERS, _Listeners from pymongo.monitoring import _LISTENERS, _Listeners
from pymongo.ocsp_cache import _OCSPCache from pymongo.ocsp_cache import _OCSPCache
from pymongo.operations import * from pymongo.operations import *
from pymongo.periodic_executor import *
from pymongo.periodic_executor import _EXECUTORS
from pymongo.pool import * from pymongo.pool import *
from pymongo.pool import Connection, Pool from pymongo.pool import Connection, Pool
from pymongo.read_concern import * from pymongo.read_concern import *
@ -107,8 +109,6 @@ from pymongo.ssl_support import *
from pymongo.synchronous.client_session import _TxnState from pymongo.synchronous.client_session import _TxnState
from pymongo.synchronous.encryption import _Encrypter from pymongo.synchronous.encryption import _Encrypter
from pymongo.synchronous.monitor import * from pymongo.synchronous.monitor import *
from pymongo.synchronous.periodic_executor import *
from pymongo.synchronous.periodic_executor import _EXECUTORS
from pymongo.synchronous.pool import _PoolClosedError from pymongo.synchronous.pool import _PoolClosedError
from pymongo.synchronous.server import * from pymongo.synchronous.server import *
from pymongo.synchronous.settings import * from pymongo.synchronous.settings import *

View File

@ -356,8 +356,12 @@ if __name__ == "__main__":
# Run the tests from the pymongo target dir with our custom plugin. # Run the tests from the pymongo target dir with our custom plugin.
os.chdir(sys.argv[1]) os.chdir(sys.argv[1])
if "-m" in sys.argv[2:]:
markers = []
else:
markers = ["-m", "default"]
code = pytest.main( code = pytest.main(
sys.argv[2:] + ["-m", "default"] + ["-p", "no:warnings"], plugins=[SynchroPytestPlugin()] sys.argv[2:] + markers + ["-p", "no:warnings"], plugins=[SynchroPytestPlugin()]
) )
if code != 0: if code != 0:

View File

@ -33,7 +33,7 @@ from test.asyncio_tests import (
remove_all_users, remove_all_users,
) )
from test.test_environment import db_password, db_user, env from test.test_environment import db_password, db_user, env
from test.utils import get_primary_pool from test.utils import AUTO_ISMASTER, get_primary_pool
import pymongo import pymongo
from bson import CodecOptions from bson import CodecOptions
@ -257,7 +257,7 @@ class TestAsyncIOClient(AsyncIOTestCase):
class TestAsyncIOClientTimeout(AsyncIOMockServerTestCase): class TestAsyncIOClientTimeout(AsyncIOMockServerTestCase):
@asyncio_test @asyncio_test
async def test_timeout(self): async def test_timeout(self):
server = self.server(auto_ismaster=True) server = self.server(auto_ismaster=AUTO_ISMASTER)
client = motor_asyncio.AsyncIOMotorClient( client = motor_asyncio.AsyncIOMotorClient(
server.uri, socketTimeoutMS=100, io_loop=self.loop server.uri, socketTimeoutMS=100, io_loop=self.loop
) )
@ -281,7 +281,7 @@ class TestAsyncIOClientHandshake(AsyncIOMockServerTestCase):
future = client.db.command("ping") future = client.db.command("ping")
ismaster = await self.run_thread(server.receives, "ismaster") ismaster = await self.run_thread(server.receives, "ismaster")
meta = ismaster.doc["client"] meta = ismaster.doc["client"]
self.assertEqual("PyMongo|Motor", meta["driver"]["name"]) self.assertIn("|Motor", meta["driver"]["name"])
# AsyncIOMotorClient adds nothing to platform. # AsyncIOMotorClient adds nothing to platform.
self.assertNotIn("Tornado", meta["platform"]) self.assertNotIn("Tornado", meta["platform"])
self.assertTrue( self.assertTrue(

View File

@ -29,6 +29,7 @@ from test.asyncio_tests import (
) )
from test.test_environment import env from test.test_environment import env
from test.utils import ( from test.utils import (
AUTO_ISMASTER,
FailPoint, FailPoint,
TestListener, TestListener,
get_async_test_timeout, get_async_test_timeout,
@ -86,7 +87,7 @@ class TestAsyncIOCursor(AsyncIOMockServerTestCase):
@unittest.skipIf("PyPy" in sys.version, "PyPy") @unittest.skipIf("PyPy" in sys.version, "PyPy")
@asyncio_test @asyncio_test
async def test_fetch_next_delete(self): async def test_fetch_next_delete(self):
client, server = self.client_server(auto_ismaster=True) client, server = self.client_server(auto_ismaster=AUTO_ISMASTER)
cursor = client.test.coll.find() cursor = client.test.coll.find()
self.fetch_next(cursor) self.fetch_next(cursor)
@ -308,7 +309,7 @@ class TestAsyncIOCursor(AsyncIOMockServerTestCase):
@asyncio_test @asyncio_test
async def test_cursor_explicit_close(self): async def test_cursor_explicit_close(self):
client, server = self.client_server(auto_ismaster=True) client, server = self.client_server(auto_ismaster=AUTO_ISMASTER)
collection = client.test.coll collection = client.test.coll
cursor = collection.find() cursor = collection.find()
@ -411,7 +412,7 @@ class TestAsyncIOCursor(AsyncIOMockServerTestCase):
@unittest.skipIf("PyPy" in sys.version, "PyPy") @unittest.skipIf("PyPy" in sys.version, "PyPy")
@asyncio_test @asyncio_test
async def test_cursor_del(self): async def test_cursor_del(self):
client, server = self.client_server(auto_ismaster=True) client, server = self.client_server(auto_ismaster=AUTO_ISMASTER)
cursor = client.test.coll.find() cursor = client.test.coll.find()
future = self.fetch_next(cursor) future = self.fetch_next(cursor)

View File

@ -20,13 +20,14 @@ import unittest
from test import SkipTest from test import SkipTest
from test.test_environment import db_password, db_user, env from test.test_environment import db_password, db_user, env
from test.tornado_tests import MotorMockServerTest, MotorTest, remove_all_users from test.tornado_tests import MotorMockServerTest, MotorTest, remove_all_users
from test.utils import get_primary_pool, one from test.utils import AUTO_ISMASTER, get_primary_pool, one
import pymongo import pymongo
import pymongo.mongo_client import pymongo.mongo_client
from bson import CodecOptions from bson import CodecOptions
from mockupdb import OpQuery from mockupdb import OpQuery
from pymongo import CursorType, ReadPreference, WriteConcern from pymongo import CursorType, ReadPreference, WriteConcern
from pymongo.common import MIN_SUPPORTED_WIRE_VERSION
from pymongo.driver_info import DriverInfo from pymongo.driver_info import DriverInfo
from pymongo.errors import ConnectionFailure, OperationFailure from pymongo.errors import ConnectionFailure, OperationFailure
from tornado import gen from tornado import gen
@ -191,7 +192,7 @@ class MotorClientTest(MotorTest):
class MotorClientTimeoutTest(MotorMockServerTest): class MotorClientTimeoutTest(MotorMockServerTest):
@gen_test @gen_test
async def test_timeout(self): async def test_timeout(self):
server = self.server(auto_ismaster=True) server = self.server(auto_ismaster=AUTO_ISMASTER)
client = motor.MotorClient(server.uri, socketTimeoutMS=100) client = motor.MotorClient(server.uri, socketTimeoutMS=100)
with self.assertRaises(pymongo.errors.AutoReconnect) as context: with self.assertRaises(pymongo.errors.AutoReconnect) as context:
@ -205,7 +206,13 @@ class MotorClientExhaustCursorTest(MotorMockServerTest):
def primary_server(self): def primary_server(self):
primary = self.server() primary = self.server()
hosts = [primary.address_string] hosts = [primary.address_string]
primary.autoresponds("ismaster", ismaster=True, setName="rs", hosts=hosts, maxWireVersion=6) primary.autoresponds(
"ismaster",
ismaster=True,
setName="rs",
hosts=hosts,
maxWireVersion=MIN_SUPPORTED_WIRE_VERSION,
)
return primary return primary
@ -213,7 +220,7 @@ class MotorClientExhaustCursorTest(MotorMockServerTest):
if rs: if rs:
return self.primary_server() return self.primary_server()
else: else:
return self.server(auto_ismaster=True) return self.server(auto_ismaster=AUTO_ISMASTER)
async def _test_exhaust_query_server_error(self, rs): async def _test_exhaust_query_server_error(self, rs):
# When doing an exhaust query, the socket stays checked out on success # When doing an exhaust query, the socket stays checked out on success
@ -290,7 +297,7 @@ class MotorClientHandshakeTest(MotorMockServerTest):
future = client.db.command("ping") future = client.db.command("ping")
ismaster = await self.run_thread(server.receives, "ismaster") ismaster = await self.run_thread(server.receives, "ismaster")
meta = ismaster.doc["client"] meta = ismaster.doc["client"]
self.assertEqual("PyMongo|Motor", meta["driver"]["name"]) self.assertIn("|Motor", meta["driver"]["name"])
self.assertIn("Tornado", meta["platform"]) self.assertIn("Tornado", meta["platform"])
self.assertTrue( self.assertTrue(
meta["driver"]["version"].endswith(motor.version), meta["driver"]["version"].endswith(motor.version),
@ -316,7 +323,7 @@ class MotorClientHandshakeTest(MotorMockServerTest):
future = client.db.command("ping") future = client.db.command("ping")
handshake = await self.run_thread(server.receives, "ismaster") handshake = await self.run_thread(server.receives, "ismaster")
meta = handshake.doc["client"] meta = handshake.doc["client"]
self.assertEqual(f"PyMongo|Motor|{driver_info.name}", meta["driver"]["name"]) self.assertIn(f"|Motor|{driver_info.name}", meta["driver"]["name"])
self.assertIn("Tornado", meta["platform"]) self.assertIn("Tornado", meta["platform"])
self.assertIn(f"|{driver_info.platform}", meta["platform"]) self.assertIn(f"|{driver_info.platform}", meta["platform"])
self.assertTrue( self.assertTrue(

View File

@ -27,6 +27,7 @@ from test.tornado_tests import (
server_is_mongos, server_is_mongos,
) )
from test.utils import ( from test.utils import (
AUTO_ISMASTER,
TestListener, TestListener,
get_async_test_timeout, get_async_test_timeout,
get_primary_pool, get_primary_pool,
@ -90,7 +91,7 @@ class MotorCursorTest(MotorMockServerTest):
if "PyPy" in sys.version: if "PyPy" in sys.version:
raise SkipTest("PyPy") raise SkipTest("PyPy")
client, server = self.client_server(auto_ismaster=True) client, server = self.client_server(auto_ismaster=AUTO_ISMASTER)
cursor = client.test.coll.find() cursor = client.test.coll.find()
# With Tornado, simply accessing fetch_next starts the fetch. # With Tornado, simply accessing fetch_next starts the fetch.
@ -266,7 +267,7 @@ class MotorCursorTest(MotorMockServerTest):
@gen_test @gen_test
async def test_cursor_explicit_close(self): async def test_cursor_explicit_close(self):
client, server = self.client_server(auto_ismaster=True) client, server = self.client_server(auto_ismaster=AUTO_ISMASTER)
collection = client.test.coll collection = client.test.coll
cursor = collection.find() cursor = collection.find()
@ -368,7 +369,7 @@ class MotorCursorTest(MotorMockServerTest):
if "PyPy" in sys.version: if "PyPy" in sys.version:
raise SkipTest("PyPy") raise SkipTest("PyPy")
client, server = self.client_server(auto_ismaster=True) client, server = self.client_server(auto_ismaster=AUTO_ISMASTER)
cursor = client.test.coll.find() cursor = client.test.coll.find()
future = cursor.fetch_next future = cursor.fetch_next

View File

@ -15,7 +15,7 @@
from collections import defaultdict from collections import defaultdict
from bson import SON from bson import SON
from pymongo import monitoring from pymongo import common, monitoring
"""Utilities for testing Motor with any framework.""" """Utilities for testing Motor with any framework."""
@ -28,6 +28,9 @@ import warnings
# mypy: ignore-errors # mypy: ignore-errors
AUTO_ISMASTER = {"maxWireVersion": common.MIN_SUPPORTED_WIRE_VERSION}
def one(s): def one(s):
"""Get one element of a set""" """Get one element of a set"""
return next(iter(s)) return next(iter(s))

40
tox.ini
View File

@ -18,6 +18,11 @@ envlist =
linkcheck, linkcheck,
# Test with the latest PyMongo. # Test with the latest PyMongo.
test-pymongo-latest, test-pymongo-latest,
# Test with oldest supported PyMongo.
test-pymongo-4.9,
# Test with other supported stable PyMongos.
test-pymongo-4.10,
test-pymongo-4.11,
# Apply PyMongo's test suite to Motor via Synchro. # Apply PyMongo's test suite to Motor via Synchro.
synchro synchro
# Run synchro tests with enterprise auth # Run synchro tests with enterprise auth
@ -38,6 +43,9 @@ labels = # Use labels and -m instead of -e so that tox -m <label> fails instantl
doctest = doctest doctest = doctest
checklink = checklink checklink = checklink
test-pymongo-latest = test-pymongo-latest test-pymongo-latest = test-pymongo-latest
test-pymongo-4.9 = test-pymongo-4.9
test-pymongo-4.10 = test-pymongo-4.10
test-pymongo-4.11 = test-pymongo-4.11
synchro = synchro synchro = synchro
enterprise-synchro = enterprise-synchro enterprise-synchro = enterprise-synchro
lint = lint lint = lint
@ -101,10 +109,34 @@ extras =
encryption encryption
test test
commands = commands =
pip install https://github.com/mongodb/mongo-python-driver/archive/v4.9.tar.gz pip install https://github.com/mongodb/mongo-python-driver/archive/master.tar.gz
pip install -q --pre --prefer-binary pymongocrypt pip install -q --pre --prefer-binary pymongocrypt
python --version python --version
python -c "import pymongo; print('PyMongo %s' % (pymongo.version,))" python -c "import pymongo; print('PyMongo %s' % (pymongo.version,))"
python -m pytest -s -v {posargs}
[testenv:test-pymongo-4.9]
extras =
encryption
test
commands =
pip install pymongo==4.9
python -m pytest -v {posargs}
[testenv:test-pymongo-4.10]
extras =
encryption
test
commands =
pip install pymongo==4.10
python -m pytest -v {posargs}
[testenv:test-pymongo-4.11]
extras =
encryption
test
commands =
pip install pymongo==4.11
python -m pytest -v {posargs} python -m pytest -v {posargs}
[testenv:synchro] [testenv:synchro]
@ -115,7 +147,7 @@ allowlist_externals =
setenv = setenv =
PYTHONPATH = {envtmpdir}/mongo-python-driver PYTHONPATH = {envtmpdir}/mongo-python-driver
commands = commands =
git clone --depth 1 --branch v4.9 https://github.com/mongodb/mongo-python-driver {envtmpdir}/mongo-python-driver git clone --depth 1 --branch master https://github.com/mongodb/mongo-python-driver {envtmpdir}/mongo-python-driver
python -m pip install -e {envtmpdir}/mongo-python-driver python -m pip install -e {envtmpdir}/mongo-python-driver
python -m synchro.synchrotest {envtmpdir}/mongo-python-driver -v {posargs} python -m synchro.synchrotest {envtmpdir}/mongo-python-driver -v {posargs}
@ -130,9 +162,9 @@ passenv =
setenv = setenv =
PYTHONPATH = {envtmpdir}/mongo-python-driver PYTHONPATH = {envtmpdir}/mongo-python-driver
commands = commands =
git clone --depth 1 --branch v4.9 https://github.com/mongodb/mongo-python-driver {envtmpdir}/mongo-python-driver git clone --depth 1 --branch master https://github.com/mongodb/mongo-python-driver {envtmpdir}/mongo-python-driver
python -m pip install -e {envtmpdir}/mongo-python-driver python -m pip install -e {envtmpdir}/mongo-python-driver
python -m synchro.synchrotest {envtmpdir}/mongo-python-driver -v test/test_auth.py python -m synchro.synchrotest {envtmpdir}/mongo-python-driver -m auth -v test/test_auth.py
[testenv:lint] [testenv:lint]
deps = deps =