MOTOR-1352 Update APIs to Support PyMongo 4.9 (#297)

This commit is contained in:
Steven Silvester 2024-08-17 07:21:45 -05:00 committed by GitHub
parent 72e68b7569
commit 972b7ffef9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 61 additions and 60 deletions

View File

@ -27,7 +27,8 @@ from pymongo.change_stream import ChangeStream
from pymongo.client_session import ClientSession
from pymongo.collection import Collection
from pymongo.command_cursor import CommandCursor, RawBatchCommandCursor
from pymongo.cursor import _QUERY_OPTIONS, Cursor, RawBatchCursor
from pymongo.cursor import Cursor, RawBatchCursor
from pymongo.cursor_shared import _QUERY_OPTIONS
from pymongo.database import Database
from pymongo.driver_info import DriverInfo
from pymongo.encryption import ClientEncryption
@ -1769,8 +1770,6 @@ class AgnosticCursor(AgnosticBaseCursor):
comment = MotorCursorChainingMethod()
allow_disk_use = MotorCursorChainingMethod()
_Cursor__die = AsyncRead()
def rewind(self):
"""Rewind this cursor to its unevaluated state."""
self.delegate.rewind()
@ -1788,13 +1787,13 @@ class AgnosticCursor(AgnosticBaseCursor):
return self.__class__(self.delegate.__deepcopy__(memo), self.collection)
def _query_flags(self):
return self.delegate._Cursor__query_flags
return self.delegate._query_flags
def _data(self):
return self.delegate._Cursor__data
return self.delegate._data
def _killed(self):
return self.delegate._Cursor__killed
return self.delegate._killed
class AgnosticRawBatchCursor(AgnosticCursor):
@ -1806,8 +1805,6 @@ class AgnosticCommandCursor(AgnosticBaseCursor):
__motor_class_name__ = "MotorCommandCursor"
__delegate_class__ = CommandCursor
_CommandCursor__die = AsyncRead()
async def try_next(self):
"""Advance the cursor without blocking indefinitely.
@ -1834,10 +1831,10 @@ class AgnosticCommandCursor(AgnosticBaseCursor):
return 0
def _data(self):
return self.delegate._CommandCursor__data
return self.delegate._data
def _killed(self):
return self.delegate._CommandCursor__killed
return self.delegate._killed
class AgnosticRawBatchCommandCursor(AgnosticCommandCursor):
@ -1849,25 +1846,25 @@ class _LatentCursor:
"""Take the place of a PyMongo CommandCursor until aggregate() begins."""
alive = True
_CommandCursor__data = []
_CommandCursor__id = None
_CommandCursor__killed = False
_CommandCursor__sock_mgr = None
_CommandCursor__session = None
_CommandCursor__explicit_session = None
_data = []
_id = None
_killed = False
_sock_mgr = None
_session = None
_explicit_session = None
cursor_id = None
def __init__(self, collection):
self._CommandCursor__collection = collection.delegate
self._collection = collection.delegate
def _CommandCursor__end_session(self, *args, **kwargs):
def _end_session(self, *args, **kwargs):
pass
def _CommandCursor__die(self, *args, **kwargs):
def _die_lock(self, *args, **kwargs):
pass
def clone(self):
return _LatentCursor(self._CommandCursor__collection)
return _LatentCursor(self._collection)
def rewind(self):
pass
@ -1924,9 +1921,9 @@ class AgnosticLatentCommandCursor(AgnosticCommandCursor):
# Return early if the task was cancelled.
if original_future.done():
return
if self.delegate._CommandCursor__data or not self.delegate.alive:
if self.delegate._data or not self.delegate.alive:
# _get_more is complete.
original_future.set_result(len(self.delegate._CommandCursor__data))
original_future.set_result(len(self.delegate._data))
else:
# Send a getMore.
future = super()._get_more()

View File

@ -40,10 +40,11 @@ from bson.raw_bson import RawBSONDocument
from pymongo import IndexModel, ReadPreference, WriteConcern
from pymongo.change_stream import ChangeStream
from pymongo.client_options import ClientOptions
from pymongo.client_session import _T, ClientSession, SessionOptions, TransactionOptions
from pymongo.collection import Collection, ReturnDocument, _WriteOp # noqa: F401
from pymongo.client_session import ClientSession, SessionOptions, TransactionOptions
from pymongo.collection import Collection, ReturnDocument # noqa: F401
from pymongo.command_cursor import CommandCursor, RawBatchCommandCursor
from pymongo.cursor import Cursor, RawBatchCursor, _Hint, _Sort
from pymongo.cursor import Cursor, RawBatchCursor
from pymongo.cursor_shared import _Hint, _Sort
from pymongo.database import Database
from pymongo.encryption import ClientEncryption, RewrapManyDataKeyResult
from pymongo.encryption_options import RangeOpts
@ -57,6 +58,8 @@ from pymongo.results import (
InsertOneResult,
UpdateResult,
)
from pymongo.synchronous.client_session import _T
from pymongo.synchronous.collection import _WriteOp
from pymongo.topology_description import TopologyDescription
from pymongo.typings import (
_Address,
@ -756,8 +759,7 @@ class AgnosticRawBatchCommandCursor(AgnosticCommandCursor[_DocumentType]):
class _LatentCursor(Generic[_DocumentType]):
def __init__(self, collection: AgnosticCollection[_DocumentType]): ...
def _CommandCursor__end_session(self, *args: Any, **kwargs: Any) -> None: ...
def _CommandCursor__die(self, *args: Any, **kwargs: Any) -> None: ...
def _end_session(self, *args: Any, **kwargs: Any) -> None: ...
def clone(self) -> _LatentCursor[_DocumentType]: ...
def rewind(self) -> _LatentCursor[_DocumentType]: ...

View File

@ -3,7 +3,7 @@ from typing import Any, Mapping, MutableMapping, Optional, Union
from bson import Code, CodecOptions, Timestamp
from bson.raw_bson import RawBSONDocument
from pymongo.client_session import TransactionOptions
from pymongo.cursor import _Hint, _Sort
from pymongo.cursor_shared import _Hint, _Sort
from pymongo.read_concern import ReadConcern
from pymongo.read_preferences import ReadPreference, _ServerMode
from pymongo.typings import _CollationIn, _DocumentType, _DocumentTypeArg, _Pipeline

View File

@ -37,9 +37,6 @@ class AgnosticGridOutCursor(AgnosticCursor):
__motor_class_name__ = "MotorGridOutCursor"
__delegate_class__ = gridfs.GridOutCursor
# PyMongo's GridOutCursor inherits __die from Cursor.
_Cursor__die = AsyncCommand()
def next_object(self):
"""**DEPRECATED** - Get next GridOut object from cursor."""
# Note: the super() call will raise a warning for the deprecation.
@ -88,7 +85,6 @@ class AgnosticGridOut:
__motor_class_name__ = "MotorGridOut"
__delegate_class__ = gridfs.GridOut
_ensure_file = AsyncCommand()
_id = MotorGridOutProperty()
aliases = MotorGridOutProperty()
chunk_size = MotorGridOutProperty()
@ -98,6 +94,7 @@ class AgnosticGridOut:
length = MotorGridOutProperty()
metadata = MotorGridOutProperty()
name = MotorGridOutProperty()
_open = AsyncCommand(attr_name="open")
read = AsyncRead()
readable = DelegateMethod()
readchunk = AsyncRead()
@ -160,7 +157,7 @@ class AgnosticGridOut:
:class:`~motor.MotorGridOut` now opens itself on demand, calling
``open`` explicitly is rarely needed.
"""
return self._framework.chain_return_value(self._ensure_file(), self.get_io_loop(), self)
return self._framework.chain_return_value(self._open(), self.get_io_loop(), self)
def get_io_loop(self):
return self.io_loop

View File

@ -35,7 +35,6 @@ _SEEK_END = os.SEEK_END
class AgnosticGridOutCursor(AgnosticCursor):
__motor_class_name__: str
__delegate_class__: type[GridOutCursor]
async def _Cursor__die(self, synchronous: bool = False) -> None: ...
def next_object(self) -> AgnosticGridOutCursor: ...
class AgnosticGridOut:
@ -50,7 +49,7 @@ class AgnosticGridOut:
length: int
upload_date: datetime.datetime
metadata: Optional[Mapping[str, Any]]
async def _ensure_file(self) -> None: ...
async def _open(self) -> None: ...
def close(self) -> None: ...
async def read(self, size: int = -1) -> NoReturn: ...
def readable(self) -> bool: ...

View File

@ -3,7 +3,7 @@ from typing import Any, Mapping, MutableMapping, Optional, Union
from bson import Code, CodecOptions, Timestamp
from bson.raw_bson import RawBSONDocument
from pymongo.client_session import TransactionOptions
from pymongo.cursor import _Hint, _Sort
from pymongo.cursor_shared import _Hint, _Sort
from pymongo.read_concern import ReadConcern
from pymongo.read_preferences import ReadPreference, _ServerMode
from pymongo.typings import _CollationIn, _DocumentType, _DocumentTypeArg, _Pipeline

View File

@ -52,6 +52,10 @@ Tracker = "https://jira.mongodb.org/projects/MOTOR/issues"
path = "motor/_version.py"
validate-bump = false
[tool.hatch.metadata]
# TODO: MOTOR-1351 Remove before releasing Motor 3.6.
allow-direct-references = true
[tool.hatch.metadata.hooks.requirements_txt]
files = ["requirements.txt"]

View File

@ -1 +1 @@
pymongo>=4.5,<5
pymongo @ git+https://github.com/mongodb/mongo-python-driver.git

View File

@ -98,7 +98,7 @@ class AIOMotorTestBasic(AsyncIOTestCase):
motor_cursor = collection.find()
cursor = motor_cursor.delegate
self.assertEqual(Nearest(tag_sets=[{"yay": "jesse"}]), cursor._read_preference())
self.assertEqual(Nearest(tag_sets=[{"yay": "jesse"}]), cursor._get_read_preference())
cx.close()

View File

@ -287,6 +287,7 @@ class TestAsyncIOCollection(AsyncIOTestCase):
self.assertEqual(exc.exception.code, 121)
await self.db.drop_collection("testing1", encrypted_fields=ef)
@env.require_version_min(8, 0, -1, -1)
@asyncio_test
async def test_async_encrypt_expression(self):
c = self.collection
@ -299,12 +300,12 @@ class TestAsyncIOCollection(AsyncIOTestCase):
"local", key_alt_names=["pymongo_encryption_example_1"]
)
name = "DoubleNoPrecision"
range_opts = RangeOpts(sparsity=1)
range_opts = RangeOpts(sparsity=1, trim_factor=1)
for i in [6.0, 30.0, 200.0]:
insert_payload = await client_encryption.encrypt(
float(i),
key_id=data_key,
algorithm=Algorithm.RANGEPREVIEW,
algorithm=Algorithm.RANGE,
contention_factor=0,
range_opts=range_opts,
)
@ -323,8 +324,8 @@ class TestAsyncIOCollection(AsyncIOTestCase):
]
},
key_id=data_key,
algorithm=Algorithm.RANGEPREVIEW,
query_type=QueryType.RANGEPREVIEW,
algorithm=Algorithm.RANGE,
query_type=QueryType.RANGE,
contention_factor=0,
range_opts=range_opts,
)

View File

@ -133,7 +133,7 @@ class TestAsyncIOCursor(AsyncIOMockServerTestCase):
self.assertTrue(cursor.next_object())
# Not valid on server, causes CursorNotFound.
cursor.delegate._Cursor__id = bson.int64.Int64(1234)
cursor.delegate._id = bson.int64.Int64(1234)
with self.assertRaises(OperationFailure):
await cursor.fetch_next
@ -355,7 +355,7 @@ class TestAsyncIOCursor(AsyncIOMockServerTestCase):
def canceled():
try:
self.assertFalse(cursor.delegate._Cursor__killed)
self.assertFalse(cursor.delegate._killed)
self.assertTrue(cursor.alive)
# Resume iteration

View File

@ -127,7 +127,7 @@ class MotorGridFileTest(AsyncIOTestCase):
# The call tree should include PyMongo code we ran on a thread.
formatted = "\n".join(traceback.format_tb(tb))
self.assertTrue("_ensure_file" in formatted)
self.assertTrue("open" in formatted)
@asyncio_test
async def test_alternate_collection(self):

View File

@ -100,7 +100,7 @@ class MotorTestBasic(MotorTest):
motor_cursor = collection.find()
cursor = motor_cursor.delegate
self.assertEqual(Nearest(tag_sets=[{"yay": "jesse"}]), cursor._read_preference())
self.assertEqual(Nearest(tag_sets=[{"yay": "jesse"}]), cursor._get_read_preference())
cx.close()

View File

@ -289,6 +289,7 @@ class MotorCollectionTest(MotorTest):
self.assertEqual(exc.exception.code, 121)
await self.db.drop_collection("testing1", encrypted_fields=ef)
@env.require_version_min(8, 0, -1, -1)
@gen_test
async def test_async_encrypt_expression(self):
c = self.collection
@ -301,12 +302,12 @@ class MotorCollectionTest(MotorTest):
"local", key_alt_names=["pymongo_encryption_example_1"]
)
name = "DoubleNoPrecision"
range_opts = RangeOpts(sparsity=1)
range_opts = RangeOpts(sparsity=1, trim_factor=1)
for i in [6.0, 30.0, 200.0]:
insert_payload = await client_encryption.encrypt(
float(i),
key_id=data_key,
algorithm=Algorithm.RANGEPREVIEW,
algorithm=Algorithm.RANGE,
contention_factor=0,
range_opts=range_opts,
)
@ -325,8 +326,8 @@ class MotorCollectionTest(MotorTest):
]
},
key_id=data_key,
algorithm=Algorithm.RANGEPREVIEW,
query_type=QueryType.RANGEPREVIEW,
algorithm=Algorithm.RANGE,
query_type=QueryType.RANGE,
contention_factor=0,
range_opts=range_opts,
)

View File

@ -33,15 +33,15 @@ pymongo_only = set(["next"])
motor_client_only = motor_only.union(["open"])
pymongo_client_only = set([]).union(pymongo_only)
pymongo_client_only = set(["bulk_write"]).union(pymongo_only)
pymongo_database_only = set([]).union(pymongo_only)
pymongo_collection_only = set([]).union(pymongo_only)
motor_cursor_only = set(
["fetch_next", "to_list", "each", "started", "next_object", "closed"]
).union(motor_only)
motor_cursor_only = set(["fetch_next", "each", "started", "next_object", "closed"]).union(
motor_only
)
pymongo_cursor_only = set(["retrieved"])
@ -118,7 +118,7 @@ class MotorCoreTestGridFS(MotorTest):
)
def test_gridin_attrs(self):
motor_gridin_only = set(["set"]).union(motor_only)
motor_gridin_only = set([]).union(motor_only)
gridin_only = set(["md5"])
self.assertEqual(
@ -137,6 +137,7 @@ class MotorCoreTestGridFS(MotorTest):
"truncate",
"flush",
"fileno",
"open",
"closed",
"writelines",
"isatty",

View File

@ -138,7 +138,7 @@ class MotorCursorTest(MotorMockServerTest):
self.assertTrue(cursor.next_object())
# Not valid on server, causes CursorNotFound.
cursor.delegate._Cursor__id = bson.int64.Int64(1234)
cursor.delegate._id = bson.int64.Int64(1234)
with self.assertRaises(OperationFailure):
await cursor.fetch_next
@ -309,7 +309,7 @@ class MotorCursorTest(MotorMockServerTest):
def canceled():
try:
self.assertFalse(cursor.delegate._Cursor__killed)
self.assertFalse(cursor.delegate._killed)
self.assertTrue(cursor.alive)
# Resume iteration

View File

@ -126,7 +126,7 @@ class MotorGridFileTest(MotorTest):
# The call tree should include PyMongo code we ran on a thread.
formatted = "\n".join(traceback.format_tb(tb))
self.assertTrue("_ensure_file" in formatted)
self.assertTrue("open" in formatted)
@gen_test
async def test_alternate_collection(self):

View File

@ -101,8 +101,7 @@ extras =
encryption
test
commands =
# TODO: Use "master" as part of MOTOR-1330
pip install git+https://github.com/mongodb/mongo-python-driver.git@v4.8
pip install git+https://github.com/mongodb/mongo-python-driver.git
pip install -q --pre --prefer-binary pymongocrypt
python --version
python -c "import pymongo; print('PyMongo %s' % (pymongo.version,))"