Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
26047379cf | ||
|
|
24ec78a32b | ||
|
|
19e0ce7cbb | ||
|
|
da422872fd | ||
|
|
dfe61f1aa0 | ||
|
|
6c71039837 | ||
|
|
50006e30ba | ||
|
|
8bfa1ff03b | ||
|
|
a5a00a6357 | ||
|
|
226c98df6a | ||
|
|
453d206382 |
@ -3,6 +3,40 @@ Changelog
|
||||
|
||||
.. currentmodule:: motor.motor_tornado
|
||||
|
||||
Motor 1.3.1
|
||||
-----------
|
||||
|
||||
Fix a Python 3.7 compatibility bug caused by importing "async", which is a
|
||||
keyword in Python 3.7. Drop support for Python 3.4.3 and older.
|
||||
|
||||
Motor 1.3.0
|
||||
-----------
|
||||
|
||||
Deprecate Motor's old callback-based async API in preparation for removing it in
|
||||
Motor 2.0. Raise ``DeprecationWarning`` whenever a callback is passed.
|
||||
|
||||
See the :doc:`migrate-to-motor-2`.
|
||||
|
||||
Motor 1.2.4
|
||||
-----------
|
||||
|
||||
Fix a Python 3.7 compatibility bug in the :class:`MotorChangeStream` class
|
||||
returned by :meth:`MotorCollection.watch`. It is now possible to use change
|
||||
streams in ``async for`` loops in Python 3.7.
|
||||
|
||||
Motor 1.2.3
|
||||
-----------
|
||||
|
||||
Compatibility with latest Sphinx and document how to use the latest TLS
|
||||
protocols.
|
||||
|
||||
Motor 1.2.2
|
||||
-----------
|
||||
|
||||
Motor 1.2.x requires PyMongo 3.6 or later. The dependency was properly
|
||||
documented, but not enforced in ``setup.py``. PyMongo 3.6 is now an install-time
|
||||
requirement; thanks to Shane Harvey for the fix.
|
||||
|
||||
Motor 1.2.1
|
||||
-----------
|
||||
|
||||
@ -124,7 +158,7 @@ Motor 1.0
|
||||
---------
|
||||
|
||||
Motor now depends on PyMongo 3.3 and later. The move from PyMongo 2 to 3 brings
|
||||
a large number of API changes, read :doc:`migrate-to-motor-1` and
|
||||
a large number of API changes, read
|
||||
`the PyMongo 3 changelog`_ carefully.
|
||||
|
||||
.. _the PyMongo 3 changelog: http://api.mongodb.com/python/current/changelog.html#changes-in-version-3-0
|
||||
@ -335,8 +369,7 @@ This version updates the PyMongo dependency from 2.8.0 to 2.9.x, and wraps
|
||||
PyMongo 2.9's new APIs.
|
||||
|
||||
Most of Motor 1.0's API is now implemented, and APIs that will be removed in
|
||||
Motor 1.0 are now deprecated and raise warnings. See the
|
||||
:doc:`/migrate-to-motor-1` to prepare your code for Motor 1.0.
|
||||
Motor 1.0 are now deprecated and raise warnings.
|
||||
|
||||
:class:`MotorClient` changes
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@ -62,7 +62,7 @@ Contents
|
||||
tutorial-asyncio
|
||||
examples/index
|
||||
changelog
|
||||
migrate-to-motor-1
|
||||
migrate-to-motor-2
|
||||
developer-guide
|
||||
contributors
|
||||
|
||||
|
||||
@ -1,400 +0,0 @@
|
||||
Motor 1.0 Migration Guide
|
||||
=========================
|
||||
|
||||
.. currentmodule:: motor.motor_tornado
|
||||
|
||||
Motor 1.0 brings a number of backward breaking changes to the pre-1.0 API.
|
||||
Follow this guide to migrate an existing application that had used an older
|
||||
version of Motor.
|
||||
|
||||
Removed features with no migration path
|
||||
---------------------------------------
|
||||
|
||||
:class:`MotorReplicaSetClient` is removed
|
||||
..........................................
|
||||
|
||||
In Motor 1.0, :class:`MotorClient` is the only class. Connect to a replica set with
|
||||
a "replicaSet" URI option or parameter::
|
||||
|
||||
MotorClient("mongodb://localhost/?replicaSet=my-rs")
|
||||
MotorClient(host, port, replicaSet="my-rs")
|
||||
|
||||
The "compile_re" option is removed
|
||||
..................................
|
||||
|
||||
In Motor 1.0 regular expressions are never compiled to Python `re.match`
|
||||
objects.
|
||||
|
||||
Motor 0.7
|
||||
---------
|
||||
|
||||
The first step in migrating to Motor 1.0 is to upgrade to at least Motor 0.7.
|
||||
If your project has a
|
||||
requirements.txt file, add the line::
|
||||
|
||||
motor >= 0.7, < 1.0
|
||||
|
||||
Most of the key new
|
||||
methods and options from Motor 1.0 are backported in Motor 0.7 making
|
||||
migration much easier.
|
||||
|
||||
Enable Deprecation Warnings
|
||||
---------------------------
|
||||
|
||||
Starting with Motor 0.7, :exc:`DeprecationWarning` is raised by most methods
|
||||
removed in Motor 1.0. Make sure you enable runtime warnings to see
|
||||
where deprecated functions and methods are being used in your application::
|
||||
|
||||
python -Wd <your application>
|
||||
|
||||
Warnings can also be changed to errors::
|
||||
|
||||
python -Wd -Werror <your application>
|
||||
|
||||
Not all deprecated features raise `DeprecationWarning` when
|
||||
used. For example, `~motor.motor_tornado.MotorReplicaSetClient` will be
|
||||
removed in Motor 1.0 but it does not raise `DeprecationWarning`
|
||||
in Motor 0.7. See also `Removed features with no migration path`_.
|
||||
|
||||
CRUD API
|
||||
--------
|
||||
|
||||
Changes to find() and find_one()
|
||||
................................
|
||||
|
||||
"spec" renamed "filter"
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ``spec`` option has been renamed to ``filter``. Code like this::
|
||||
|
||||
cursor = collection.find(spec={"a": 1})
|
||||
|
||||
can be changed to this with Motor 0.7 or later::
|
||||
|
||||
cursor = collection.find(filter={"a": 1})
|
||||
|
||||
or this with any version of Motor::
|
||||
|
||||
cursor = collection.find({"a": 1})
|
||||
|
||||
"fields" renamed "projection"
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ``fields`` option has been renamed to ``projection``. Code like this::
|
||||
|
||||
cursor = collection.find({"a": 1}, fields={"_id": False})
|
||||
|
||||
can be changed to this with Motor 0.7 or later::
|
||||
|
||||
cursor = collection.find({"a": 1}, projection={"_id": False})
|
||||
|
||||
or this with any version of Motor::
|
||||
|
||||
cursor = collection.find({"a": 1}, {"_id": False})
|
||||
|
||||
"partial" renamed "allow_partial_results"
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ``partial`` option has been renamed to ``allow_partial_results``. Code like
|
||||
this::
|
||||
|
||||
cursor = collection.find({"a": 1}, partial=True)
|
||||
|
||||
can be changed to this with Motor 0.7 or later::
|
||||
|
||||
cursor = collection.find({"a": 1}, allow_partial_results=True)
|
||||
|
||||
"timeout" replaced by "no_cursor_timeout"
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ``timeout`` option has been replaced by ``no_cursor_timeout``. Code like this::
|
||||
|
||||
cursor = collection.find({"a": 1}, timeout=False)
|
||||
|
||||
can be changed to this with Motor 0.7 or later::
|
||||
|
||||
cursor = collection.find({"a": 1}, no_cursor_timeout=True)
|
||||
|
||||
"snapshot" and "max_scan" replaced by "modifiers"
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ``snapshot`` and ``max_scan`` options have been removed. They can now be set,
|
||||
along with other $ query modifiers, through the ``modifiers`` option. Code like
|
||||
this::
|
||||
|
||||
cursor = collection.find({"a": 1}, snapshot=True)
|
||||
|
||||
can be changed to this with Motor 0.7 or later::
|
||||
|
||||
cursor = collection.find({"a": 1}, modifiers={"$snapshot": True})
|
||||
|
||||
or with any version of Motor::
|
||||
|
||||
cursor = collection.find({"$query": {"a": 1}, "$snapshot": True})
|
||||
|
||||
"network_timeout" is removed
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ``network_timeout`` option has been removed. This option was always the
|
||||
wrong solution for timing out long running queries and should never be used
|
||||
in production. Starting with **MongoDB 2.6** you can use the $maxTimeMS query
|
||||
modifier. Code like this::
|
||||
|
||||
# Set a 5 second select() timeout.
|
||||
cursor = collection.find({"a": 1}, network_timeout=5)
|
||||
|
||||
can be changed to this with Motor 0.7 or later::
|
||||
|
||||
# Set a 5 second (5000 millisecond) server side query timeout.
|
||||
cursor = collection.find({"a": 1}, modifiers={"$maxTimeMS": 5000})
|
||||
|
||||
or with any version of Motor::
|
||||
|
||||
cursor = collection.find({"$query": {"a": 1}, "$maxTimeMS": 5000})
|
||||
|
||||
.. seealso:: `$maxTimeMS
|
||||
<http://docs.mongodb.org/manual/reference/operator/meta/maxTimeMS/>`_
|
||||
|
||||
Tailable cursors
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
The ``tailable`` and ``await_data`` options have been replaced by ``cursor_type``.
|
||||
Code like this::
|
||||
|
||||
cursor = collection.find({"a": 1}, tailable=True)
|
||||
cursor = collection.find({"a": 1}, tailable=True, await_data=True)
|
||||
|
||||
can be changed to this with Motor 0.7 or later::
|
||||
|
||||
from pymongo import CursorType
|
||||
cursor = collection.find({"a": 1}, cursor_type=CursorType.TAILABLE)
|
||||
cursor = collection.find({"a": 1}, cursor_type=CursorType.TAILABLE_AWAIT)
|
||||
|
||||
Other removed options
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ``read_preference``, ``tag_sets``,
|
||||
and ``secondary_acceptable_latency_ms`` options have been removed. See the `Read
|
||||
Preferences`_ section for solutions.
|
||||
|
||||
Read Preferences
|
||||
----------------
|
||||
|
||||
The "read_preference" attribute is immutable
|
||||
............................................
|
||||
|
||||
Code like this::
|
||||
|
||||
from pymongo import ReadPreference
|
||||
db = client.my_database
|
||||
db.read_preference = ReadPreference.SECONDARY
|
||||
|
||||
can be changed to this with Motor 0.7 or later::
|
||||
|
||||
db = client.get_database("my_database",
|
||||
read_preference=ReadPreference.SECONDARY)
|
||||
|
||||
Code like this::
|
||||
|
||||
cursor = collection.find({"a": 1},
|
||||
read_preference=ReadPreference.SECONDARY)
|
||||
|
||||
can be changed to this with Motor 0.7 or later::
|
||||
|
||||
coll2 = collection.with_options(read_preference=ReadPreference.SECONDARY)
|
||||
cursor = coll2.find({"a": 1})
|
||||
|
||||
.. seealso:: :meth:`~MotorDatabase.get_collection`
|
||||
|
||||
The "tag_sets" option and attribute are removed
|
||||
...............................................
|
||||
|
||||
The ``tag_sets`` MotorClient option is removed. The ``read_preference``
|
||||
option can be used instead. Code like this::
|
||||
|
||||
client = MotorClient(
|
||||
read_preference=ReadPreference.SECONDARY,
|
||||
tag_sets=[{"dc": "ny"}, {"dc": "sf"}])
|
||||
|
||||
can be changed to this with Motor 0.7 or later::
|
||||
|
||||
from pymongo.read_preferences import Secondary
|
||||
client = MotorClient(read_preference=Secondary([{"dc": "ny"}]))
|
||||
|
||||
To change the tags sets for a MotorDatabase or MotorCollection, code like this::
|
||||
|
||||
db = client.my_database
|
||||
db.read_preference = ReadPreference.SECONDARY
|
||||
db.tag_sets = [{"dc": "ny"}]
|
||||
|
||||
can be changed to this with Motor 0.7 or later::
|
||||
|
||||
db = client.get_database("my_database",
|
||||
read_preference=Secondary([{"dc": "ny"}]))
|
||||
|
||||
Code like this::
|
||||
|
||||
cursor = collection.find(
|
||||
{"a": 1},
|
||||
read_preference=ReadPreference.SECONDARY,
|
||||
tag_sets=[{"dc": "ny"}])
|
||||
|
||||
can be changed to this with Motor 0.7 or later::
|
||||
|
||||
from pymongo.read_preferences import Secondary
|
||||
coll2 = collection.with_options(
|
||||
read_preference=Secondary([{"dc": "ny"}]))
|
||||
cursor = coll2.find({"a": 1})
|
||||
|
||||
.. seealso:: :meth:`~MotorDatabase.get_collection`
|
||||
|
||||
The "secondary_acceptable_latency_ms" option and attribute are removed
|
||||
......................................................................
|
||||
|
||||
Motor 0.x supports ``secondary_acceptable_latency_ms`` as an option to methods
|
||||
throughout the driver, but mongos only supports a global latency option.
|
||||
Motor 1.0 has changed to match the behavior of mongos, allowing migration
|
||||
from a single server, to a replica set, to a sharded cluster without a
|
||||
surprising change in server selection behavior. A new option,
|
||||
``localThresholdMS``, is available through MotorClient and should be used in
|
||||
place of ``secondaryAcceptableLatencyMS``. Code like this::
|
||||
|
||||
client = MotorClient(readPreference="nearest",
|
||||
secondaryAcceptableLatencyMS=100)
|
||||
|
||||
can be changed to this with Motor 0.7 or later::
|
||||
|
||||
client = MotorClient(readPreference="nearest",
|
||||
localThresholdMS=100)
|
||||
|
||||
Write Concern
|
||||
-------------
|
||||
|
||||
The "write_concern" attribute is immutable
|
||||
..........................................
|
||||
|
||||
The ``write_concern`` attribute is immutable in Motor 1.0. Code like this::
|
||||
|
||||
client = MotorClient()
|
||||
client.write_concern = {"w": "majority"}
|
||||
|
||||
can be changed to this with any version of Motor::
|
||||
|
||||
client = MotorClient(w="majority")
|
||||
|
||||
Code like this::
|
||||
|
||||
db = client.my_database
|
||||
db.write_concern = {"w": "majority"}
|
||||
|
||||
can be changed to this with Motor 0.7 or later::
|
||||
|
||||
from pymongo import WriteConcern
|
||||
db = client.get_database("my_database",
|
||||
write_concern=WriteConcern(w="majority"))
|
||||
|
||||
The new CRUD API write methods do not accept write concern options. Code like
|
||||
this::
|
||||
|
||||
oid = collection.insert({"a": 2}, w="majority")
|
||||
|
||||
can be changed to this with Motor 0.7 or later::
|
||||
|
||||
from pymongo import WriteConcern
|
||||
coll2 = collection.with_options(
|
||||
write_concern=WriteConcern(w="majority"))
|
||||
oid = coll2.insert({"a": 2})
|
||||
|
||||
.. seealso:: :meth:`~MotorDatabase.get_collection`
|
||||
|
||||
Codec Options
|
||||
-------------
|
||||
|
||||
The "document_class" attribute is removed
|
||||
.........................................
|
||||
|
||||
Code like this::
|
||||
|
||||
from bson.son import SON
|
||||
client = MotorClient()
|
||||
client.document_class = SON
|
||||
|
||||
can be replaced by this in any version of Motor::
|
||||
|
||||
from bson.son import SON
|
||||
client = MotorClient(document_class=SON)
|
||||
|
||||
or to change the ``document_class`` for a :class:`MotorDatabase`
|
||||
with Motor 0.7 or later::
|
||||
|
||||
from bson.codec_options import CodecOptions
|
||||
from bson.son import SON
|
||||
db = client.get_database("my_database", CodecOptions(SON))
|
||||
|
||||
.. seealso:: :meth:`~MotorDatabase.get_collection` and
|
||||
:meth:`~MotorCollection.with_options`
|
||||
|
||||
The "uuid_subtype" option and attribute are removed
|
||||
...................................................
|
||||
|
||||
Code like this::
|
||||
|
||||
from bson.binary import JAVA_LEGACY
|
||||
db = client.my_database
|
||||
db.uuid_subtype = JAVA_LEGACY
|
||||
|
||||
can be replaced by this with Motor 0.7 or later::
|
||||
|
||||
from bson.binary import JAVA_LEGACY
|
||||
from bson.codec_options import CodecOptions
|
||||
db = client.get_database("my_database",
|
||||
CodecOptions(uuid_representation=JAVA_LEGACY))
|
||||
|
||||
.. seealso:: :meth:`~MotorDatabase.get_collection` and
|
||||
:meth:`~MotorCollection.with_options`
|
||||
|
||||
MotorClient
|
||||
-----------
|
||||
|
||||
The ``open`` method
|
||||
...................
|
||||
|
||||
The :meth:`~MotorClient.open` method is removed in Motor 1.0.
|
||||
Motor clients have opened themselves on demand since Motor 0.2.
|
||||
|
||||
The max_pool_size parameter is removed
|
||||
......................................
|
||||
|
||||
Motor 1.0 replaced the max_pool_size parameter with support for the MongoDB URI
|
||||
``maxPoolSize`` option. Code like this::
|
||||
|
||||
client = MotorClient(max_pool_size=10)
|
||||
|
||||
can be replaced by this with Motor 0.7 or later::
|
||||
|
||||
client = MotorClient(maxPoolSize=10)
|
||||
client = MotorClient("mongodb://localhost:27017/?maxPoolSize=10")
|
||||
|
||||
The "disconnect" method is removed
|
||||
..................................
|
||||
|
||||
Code like this::
|
||||
|
||||
client.disconnect()
|
||||
|
||||
can be replaced by this::
|
||||
|
||||
client.close()
|
||||
|
||||
The host and port attributes are removed
|
||||
........................................
|
||||
|
||||
Code like this::
|
||||
|
||||
host = client.host
|
||||
port = client.port
|
||||
|
||||
can be replaced by this with Motor 0.7 or later::
|
||||
|
||||
address = client.address
|
||||
host, port = address or (None, None)
|
||||
206
doc/migrate-to-motor-2.rst
Normal file
206
doc/migrate-to-motor-2.rst
Normal file
@ -0,0 +1,206 @@
|
||||
Motor 2.0 Migration Guide
|
||||
=========================
|
||||
|
||||
.. currentmodule:: motor.motor_tornado
|
||||
|
||||
Motor 2.0 brings a number of changes to Motor 1.0's API. The major version is
|
||||
required in order to update the session API to support multi-document
|
||||
transactions, introduced in MongoDB 4.0; this feature is so valuable that it
|
||||
motivated me to make the breaking change and bump the version number to 2.0.
|
||||
Since this is the first major version number in almost two years, it removes a
|
||||
large number of APIs that have been deprecated in the time since Motor 1.0.
|
||||
|
||||
Follow this guide to migrate an existing application that had used Motor 1.x.
|
||||
|
||||
Check compatibility
|
||||
-------------------
|
||||
|
||||
Read the :doc:`requirements` page and ensure your MongoDB server and Python
|
||||
interpreter are compatible, and your Tornado version if you are using Tornado.
|
||||
If you use aiohttp, upgrade to at least 3.0.
|
||||
|
||||
Upgrade to Motor 1.3
|
||||
--------------------
|
||||
|
||||
The first step in migrating to Motor 2.0 is to upgrade to at least Motor 1.3.
|
||||
If your project has a
|
||||
requirements.txt file, add the line::
|
||||
|
||||
motor >= 1.3, < 2.0
|
||||
|
||||
Enable Deprecation Warnings
|
||||
---------------------------
|
||||
|
||||
Starting with Motor 1.3, :exc:`DeprecationWarning` is raised by most methods
|
||||
removed in Motor 2.0. Make sure you enable runtime warnings to see where
|
||||
deprecated functions and methods are being used in your application::
|
||||
|
||||
python -Wd <your application>
|
||||
|
||||
Warnings can also be changed to errors::
|
||||
|
||||
python -Wd -Werror <your application>
|
||||
|
||||
Migrate from deprecated APIs
|
||||
----------------------------
|
||||
|
||||
The following features are deprecated by PyMongo and scheduled for removal;
|
||||
they are now deleted from Motor:
|
||||
|
||||
- ``MotorClient.kill_cursors`` and ``close_cursor``.
|
||||
Allow :class:`MotorCursor` to handle its own cleanup.
|
||||
- ``MotorClient.get_default_database``. Call :meth:`MotorClient.get_database`
|
||||
with a database name of ``None`` for the same effect.
|
||||
- ``MotorDatabase.add_son_manipulator``. Transform documents to and from
|
||||
their MongoDB representations in your application code instead.
|
||||
|
||||
- The server command ``getLastError`` and related commands are deprecated,
|
||||
their helper functions are deleted from Motor:
|
||||
|
||||
- ``MotorDatabase.last_status``
|
||||
- ``MotorDatabase.error``
|
||||
- ``MotorDatabase.previous_error``
|
||||
- ``MotorDatabase.reset_error_history``
|
||||
|
||||
Use acknowledged writes and rely on Motor to raise exceptions.
|
||||
|
||||
- The server command ``parallelCollectionScan`` is deprecated and
|
||||
``MotorCollection.parallel_scan`` is removed. Use a regular
|
||||
:meth:`MotorCollection.find` cursor.
|
||||
- ``MotorClient.database_names``. Use
|
||||
:meth:`~MotorClient.list_database_names`.
|
||||
- ``MotorDatabase.eval``. The server command is deprecated but
|
||||
still available with ``MotorDatabase.command("eval", ...)``.
|
||||
- ``MotorDatabase.group``. The server command is deprecated but
|
||||
still available with ``MotorDatabase.command("group", ...)``.
|
||||
- ``MotorDatabase.authenticate`` and ``MotorDatabase.logout``. Add credentials
|
||||
to the URI or ``MotorClient`` options instead of calling ``authenticate``.
|
||||
To authenticate as multiple users on the same database, instead of using
|
||||
``authenticate`` and ``logout`` use a separate client for each user.
|
||||
- ``MotorCollection.initialize_unordered_bulk_op``,
|
||||
``initialize_unordered_bulk_op``, and ``MotorBulkOperationBuilder``. Use
|
||||
:meth:`MotorCollection.bulk_write``, see :ref:`Bulk Writes Tutorial
|
||||
<bulk-write-tutorial>`.
|
||||
- ``MotorCollection.count``. Use :meth:`~MotorCollection.count_documents` or
|
||||
:meth:`~MotorCollection.estimated_document_count`.
|
||||
- ``MotorCollection.ensure_index``. Use
|
||||
:meth:`MotorCollection.create_indexes`.
|
||||
- Deprecated write methods have been deleted from :class:`MotorCollection`.
|
||||
|
||||
- ``save`` and ``insert``: Use :meth:`~MotorCollection.insert_one` or
|
||||
:meth:`~MotorCollection.insert_many`.
|
||||
- ``update``: Use :meth:`~MotorCollection.update_one`,
|
||||
:meth:`~MotorCollection.update_many`, or
|
||||
:meth:`~MotorCollection.replace_one`.
|
||||
- ``remove``: Use :meth:`~MotorCollection.delete_one` or
|
||||
:meth:`~MotorCollection.delete_many`.
|
||||
- ``find_and_modify``: Use :meth:`~MotorCollection.find_one_and_update`,
|
||||
:meth:`~MotorCollection.find_one_and_replace`, or
|
||||
:meth:`~MotorCollection.find_one_and_delete`.
|
||||
|
||||
- ``MotorCursor.count`` and ``MotorGridOutCursor.count``. Use
|
||||
:meth:`MotorCollection.count_documents` or
|
||||
:meth:`MotorCollection.estimated_document_count`.
|
||||
|
||||
Migrate from the original callback API
|
||||
--------------------------------------
|
||||
|
||||
Motor was first released before Tornado had introduced Futures, generator-based
|
||||
coroutines, and the ``yield`` syntax, and long before the async features
|
||||
developed during Python 3's career. Therefore Motor's original asynchronous API
|
||||
used callbacks:
|
||||
|
||||
.. code-block:: python3
|
||||
|
||||
def callback(result, error):
|
||||
if error:
|
||||
print(error)
|
||||
else:
|
||||
print(result)
|
||||
|
||||
collection.find_one({}, callback=callback)
|
||||
|
||||
Callbacks have been largely superseded by a Futures API intended for use with
|
||||
coroutines, see :doc:`tutorial-tornado`. You can still use callbacks with Motor when
|
||||
appropriate but you must add the callback to a Future instead of passing it as
|
||||
a parameter:
|
||||
|
||||
.. code-block:: python3
|
||||
|
||||
def callback(future):
|
||||
try:
|
||||
result = future.result()
|
||||
print(result)
|
||||
except Exception as exc:
|
||||
print(exc)
|
||||
|
||||
future = collection.find_one({})
|
||||
future.add_done_callback(callback)
|
||||
|
||||
The :meth:`~asyncio.Future.add_done_callback` call can be placed on the same
|
||||
line:
|
||||
|
||||
.. code-block:: python3
|
||||
|
||||
collection.find_one({}).add_done_callback(callback)
|
||||
|
||||
In almost all cases the modern coroutine API is more readable and provides
|
||||
better exception handling:
|
||||
|
||||
.. code-block:: python3
|
||||
|
||||
async def do_find():
|
||||
try:
|
||||
result = await collection.find_one({})
|
||||
print(result)
|
||||
except Exception as exc:
|
||||
print(exc)
|
||||
|
||||
Upgrade to Motor 2.0
|
||||
--------------------
|
||||
|
||||
Once your application runs without deprecation warnings with Motor 1.3, upgrade
|
||||
to Motor 2.0. Update any calls in your code to
|
||||
:meth:`MotorClient.start_session` or
|
||||
:meth:`~pymongo.client_session.ClientSession.end_session` to handle the
|
||||
following change.
|
||||
|
||||
:meth:`MotorClient.start_session` is a coroutine
|
||||
------------------------------------------------
|
||||
|
||||
In the past, you could use a client session like:
|
||||
|
||||
.. code-block:: python3
|
||||
|
||||
session = client.start_session()
|
||||
doc = await client.db.collection.find_one({}, session=session)
|
||||
session.end_session()
|
||||
|
||||
Or:
|
||||
|
||||
.. code-block:: python3
|
||||
|
||||
with client.start_session() as session:
|
||||
doc = client.db.collection.find_one({}, session=session)
|
||||
|
||||
To support multi-document transactions, in Motor 2.0
|
||||
:meth:`MotorClient.start_session` is a coroutine, not a regular method. It must
|
||||
be used like ``await client.start_session()`` or ``async with await
|
||||
client.start_session()``. The coroutine now returns a new class
|
||||
:class:`~motor.motor_tornado.MotorClientSession`, not PyMongo's
|
||||
:class:`~pymongo.client_session.ClientSession`. The ``end_session`` method on
|
||||
the returned :class:`~motor.motor_tornado.MotorClientSession` is also now a
|
||||
coroutine instead of a regular method. Use it like:
|
||||
|
||||
.. code-block:: python3
|
||||
|
||||
session = await client.start_session()
|
||||
doc = await client.db.collection.find_one({}, session=session)
|
||||
await session.end_session()
|
||||
|
||||
Or:
|
||||
|
||||
.. code-block:: python3
|
||||
|
||||
async with client.start_session() as session:
|
||||
doc = await client.db.collection.find_one({}, session=session)
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright 2009-2015 MongoDB, Inc.
|
||||
# Copyright 2009-present MongoDB, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@ -15,8 +15,8 @@
|
||||
"""MongoDB specific extensions to Sphinx."""
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.parsers import rst
|
||||
from sphinx import addnodes
|
||||
from sphinx.util.compat import Directive
|
||||
|
||||
|
||||
class mongodoc(nodes.Admonition, nodes.Element):
|
||||
@ -28,7 +28,7 @@ class mongoref(nodes.reference):
|
||||
|
||||
|
||||
def visit_mongodoc_node(self, node):
|
||||
self.visit_admonition(node)
|
||||
self.visit_admonition(node, "seealso")
|
||||
|
||||
|
||||
def depart_mongodoc_node(self, node):
|
||||
@ -48,7 +48,7 @@ def depart_mongoref_node(self, node):
|
||||
self.body.append('\n')
|
||||
|
||||
|
||||
class MongodocDirective(Directive):
|
||||
class MongodocDirective(rst.Directive):
|
||||
|
||||
has_content = True
|
||||
required_arguments = 0
|
||||
@ -58,7 +58,7 @@ class MongodocDirective(Directive):
|
||||
|
||||
def run(self):
|
||||
node = mongodoc()
|
||||
title = 'See general MongoDB documentation'
|
||||
title = 'The MongoDB documentation on'
|
||||
node += nodes.title(title, title)
|
||||
self.state.nested_parse(self.content, self.content_offset, node)
|
||||
return [node]
|
||||
@ -94,6 +94,4 @@ def setup(app):
|
||||
html=(visit_mongoref_node, depart_mongoref_node))
|
||||
|
||||
app.add_directive("mongodoc", MongodocDirective)
|
||||
|
||||
app.connect("doctree-resolved", process_mongodoc_nodes)
|
||||
return {'parallel_write_safe': True, 'parallel_read_safe': True}
|
||||
|
||||
@ -36,67 +36,38 @@ Compatibility Matrix
|
||||
Motor and PyMongo
|
||||
`````````````````
|
||||
|
||||
Older versions of Motor depended on exact PyMongo versions. Version 0.7 requires
|
||||
the latest PyMongo 2.9.x release beginning with 2.9.4, Version 1.0 works
|
||||
with any PyMongo version beginning with 3.3.0, and Version 1.1 works with any
|
||||
PyMongo version beginning with 3.4.0.
|
||||
|
||||
+-------------------+-----------------+
|
||||
| Motor Version | PyMongo Version |
|
||||
+===================+=================+
|
||||
| 0.1 | 2.5.0 |
|
||||
+-------------------+-----------------+
|
||||
| 0.2 | 2.7.0 |
|
||||
+-------------------+-----------------+
|
||||
| 0.3 | 2.7.1 |
|
||||
+-------------------+-----------------+
|
||||
| 0.4 | 2.8.0 |
|
||||
+-------------------+-----------------+
|
||||
| 0.5 | 2.8.0 |
|
||||
+-------------------+-----------------+
|
||||
| 0.6 | 2.8.0 |
|
||||
+-------------------+-----------------+
|
||||
| 0.7 | 2.9.4+ |
|
||||
+-------------------+-----------------+
|
||||
| 1.0 | 3.3+ |
|
||||
+-------------------+-----------------+
|
||||
| 1.1 | 3.4+ |
|
||||
+-------------------+-----------------+
|
||||
| 1.2 | 3.6+ |
|
||||
+-------------------+-----------------+
|
||||
| 1.3 | 3.6+ |
|
||||
+-------------------+-----------------+
|
||||
| 2.0 | 3.7+ |
|
||||
+-------------------+-----------------+
|
||||
|
||||
Motor and MongoDB
|
||||
`````````````````
|
||||
|
||||
All Motor versions are usable with all MongoDB versions as old as 2.2.
|
||||
Where "N" appears there are some incompatibilities and
|
||||
unsupported server features.
|
||||
|
||||
+---------------------------------------------------------+
|
||||
| MongoDB Version |
|
||||
+=====================+=====+=====+=====+=====+=====+=====+
|
||||
| | 2.2 | 2.4 | 2.6 | 3.0 | 3.2 | 3.4 |
|
||||
+---------------+-----+-----+-----+-----+-----+-----+-----+
|
||||
| Motor Version | 0.1 | Y | Y |**N**|**N**|**N**|**N**|
|
||||
+---------------+-----+-----+-----+-----+-----+-----+-----+
|
||||
| | 0.2 | Y | Y | Y |**N**|**N**|**N**|
|
||||
+---------------+-----+-----+-----+-----+-----+-----+-----+
|
||||
| | 0.3 | Y | Y | Y |**N**|**N**|**N**|
|
||||
+---------------+-----+-----+-----+-----+-----+-----+-----+
|
||||
| | 0.4 | Y | Y | Y | Y |**N**|**N**|
|
||||
+---------------+-----+-----+-----+-----+-----+-----+-----+
|
||||
| | 0.5 | Y | Y | Y | Y |**N**|**N**|
|
||||
+---------------+-----+-----+-----+-----+-----+-----+-----+
|
||||
| | 0.6 | Y | Y | Y | Y |**N**|**N**|
|
||||
+---------------+-----+-----+-----+-----+-----+-----+-----+
|
||||
| | 0.7 | Y | Y | Y | Y | Y |**N**|
|
||||
+---------------+-----+-----+-----+-----+-----+-----+-----+
|
||||
| | 1.0 | Y | Y | Y | Y | Y |**N**|
|
||||
+---------------+-----+-----+-----+-----+-----+-----+-----+
|
||||
| | 1.1 | Y | Y | Y | Y | Y | Y |
|
||||
+---------------+-----+-----+-----+-----+-----+-----+-----+
|
||||
| | 1.2 |**N**|**N**| Y | Y | Y | Y |
|
||||
+---------------+-----+-----+-----+-----+-----+-----+-----+
|
||||
+---------------------------------------------------------+-----+-----+
|
||||
| MongoDB Version | | |
|
||||
+=====================+=====+=====+=====+=====+=====+=====+=====+=====+
|
||||
| | 2.2 | 2.4 | 2.6 | 3.0 | 3.2 | 3.4 | 3.6 | 4.0 |
|
||||
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
| Motor Version | 1.0 | Y | Y | Y | Y | Y |**N**|**N**|**N**|
|
||||
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
| | 1.1 | Y | Y | Y | Y | Y | Y |**N**|**N**|
|
||||
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
| | 1.2 |**N**|**N**| Y | Y | Y | Y | Y |**N**|
|
||||
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
| | 1.3 |**N**|**N**| Y | Y | Y | Y | Y |**N**|
|
||||
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
| | 2.0 |**N**|**N**|**N**| Y | Y | Y | Y | Y |
|
||||
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
|
||||
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.
|
||||
@ -112,70 +83,44 @@ Motor and Tornado
|
||||
Where "N" appears in this matrix, the versions of Motor and Tornado are
|
||||
known to be incompatible, or have not been tested together.
|
||||
|
||||
+---------------------------------+
|
||||
| Tornado Version |
|
||||
+=====================+=====+=====+
|
||||
| | 3.x | 4.x |
|
||||
+---------------+-----+-----+-----+
|
||||
| Motor Version | 0.1 | Y |**N**|
|
||||
+---------------+-----+-----+-----+
|
||||
| | 0.2 | Y | Y |
|
||||
+---------------+-----+-----+-----+
|
||||
| | 0.3 | Y | Y |
|
||||
+---------------+-----+-----+-----+
|
||||
| | 0.4 | Y | Y |
|
||||
+---------------+-----+-----+-----+
|
||||
| | 0.5 | Y | Y |
|
||||
+---------------+-----+-----+-----+
|
||||
| | 0.6 | Y | Y |
|
||||
+---------------+-----+-----+-----+
|
||||
| | 0.7 | Y | Y |
|
||||
+---------------+-----+-----+-----+
|
||||
| | 1.0 | Y | Y |
|
||||
+---------------+-----+-----+-----+
|
||||
| | 1.1 | Y | Y |
|
||||
+---------------+-----+-----+-----+
|
||||
| | 1.2 |**N**| Y |
|
||||
+---------------+-----+-----+-----+
|
||||
+---------------------------------------+
|
||||
| Tornado Version |
|
||||
+=====================+=====+=====+=====+
|
||||
| | 3.x | 4.x | 5.x |
|
||||
+---------------+-----+-----+-----+-----+
|
||||
| Motor Version | 1.0 | Y | Y |**N**|
|
||||
+---------------+-----+-----+-----+-----+
|
||||
| | 1.1 | Y | Y |**N**|
|
||||
+---------------+-----+-----+-----+-----+
|
||||
| | 1.2 |**N**| Y |**N**|
|
||||
+---------------+-----+-----+-----+-----+
|
||||
| | 1.3 |**N**| Y |**N**|
|
||||
+---------------+-----+-----+-----+-----+
|
||||
| | 2.0 |**N**| Y | Y |
|
||||
+---------------+-----+-----+-----+-----+
|
||||
|
||||
Motor and Python
|
||||
````````````````
|
||||
|
||||
Until version 0.5, Motor required Tornado, and it supported the same version of
|
||||
Python as its supported Tornado versions did.
|
||||
|
||||
Beginning in version 0.5, Motor integrates with asyncio or Tornado.
|
||||
|
||||
Beginning in version 0.5, supports the "async for" syntax with cursors in
|
||||
Python 3.5 and later. Motor 1.2 dropped support for the short-lived version of
|
||||
Motor 1.2 dropped support for the short-lived version of
|
||||
the "async for" protocol implemented in Python 3.5.0 and 3.5.1. Motor continues
|
||||
to work with "async for" loops in Python 3.5.2 and later.
|
||||
|
||||
+-------------------------------------------------------------------------+
|
||||
| Python Version |
|
||||
+=====================+=====+=====+=====+=====+=====+=======+=======+=====+
|
||||
| | 2.5 | 2.6 | 2.7 | 3.3 | 3.4 | 3.5.0 | 3.5.2 | 3.6 |
|
||||
+---------------+-----+-----+-----+-----+-----+-----+-------+-------+-----+
|
||||
| Motor Version | 0.1 | Y | Y | Y | Y |**N**|**N** |**N** |**N**|
|
||||
+---------------+-----+-----+-----+-----+-----+-----+-------+-------+-----+
|
||||
| | 0.2 |**N**| Y | Y | Y |**N**|**N** |**N** |**N**|
|
||||
+---------------+-----+-----+-----+-----+-----+-----+-------+-------+-----+
|
||||
| | 0.3 |**N**| Y | Y | Y | Y |**N** |**N** |**N**|
|
||||
+---------------+-----+-----+-----+-----+-----+-----+-------+-------+-----+
|
||||
| | 0.4 |**N**| Y | Y | Y | Y |**N** |**N** |**N**|
|
||||
+---------------+-----+-----+-----+-----+-----+-----+-------+-------+-----+
|
||||
| | 0.5 |**N**| Y | Y | Y | Y | Y | Y |**N**|
|
||||
+---------------+-----+-----+-----+-----+-----+-----+-------+-------+-----+
|
||||
| | 0.6 |**N**| Y | Y | Y | Y | Y | Y |**N**|
|
||||
+---------------+-----+-----+-----+-----+-----+-----+-------+-------+-----+
|
||||
| | 0.7 |**N**| Y | Y | Y | Y | Y | Y |**N**|
|
||||
+---------------+-----+-----+-----+-----+-----+-----+-------+-------+-----+
|
||||
| | 1.0 |**N**| Y | Y | Y | Y | Y | Y | Y |
|
||||
+---------------+-----+-----+-----+-----+-----+-----+-------+-------+-----+
|
||||
| | 1.1 |**N**| Y | Y | Y | Y | Y | Y | Y |
|
||||
+---------------+-----+-----+-----+-----+-----+-----+-------+-------+-----+
|
||||
| | 1.2 |**N**|**N**| Y |**N**| Y |**N** | Y | Y |
|
||||
+---------------+-----+-----+-----+-----+-----+-----+-------+-------+-----+
|
||||
+-------------------------------------------------------------------------------+
|
||||
| Python Version |
|
||||
+=====================+=====+=====+=====+=====+=====+=======+=======+=====+=====+
|
||||
| | 2.5 | 2.6 | 2.7 | 3.3 | 3.4 | 3.5.0 | 3.5.2 | 3.6 | 3.7 |
|
||||
+---------------+-----+-----+-----+-----+-----+-----+-------+-------+-----+-----+
|
||||
| Motor Version | 1.0 |**N**| Y | Y | Y | Y | Y | Y | Y |**N**|
|
||||
+---------------+-----+-----+-----+-----+-----+-----+-------+-------+-----+-----+
|
||||
| | 1.1 |**N**| Y | Y | Y | Y | Y | Y | Y |**N**|
|
||||
+---------------+-----+-----+-----+-----+-----+-----+-------+-------+-----+-----+
|
||||
| | 1.2 |**N**|**N**| Y |**N**| Y |**N** | Y | Y |**N**|
|
||||
+---------------+-----+-----+-----+-----+-----+-----+-------+-------+-----+-----+
|
||||
| | 1.3 |**N**|**N**| Y |**N**| Y |**N** | Y | Y |**N**|
|
||||
+---------------+-----+-----+-----+-----+-----+-----+-------+-------+-----+-----+
|
||||
| | 2.0 |**N**|**N**| Y |**N**| Y |**N** | Y | Y | Y |
|
||||
+---------------+-----+-----+-----+-----+-----+-----+-------+-------+-----+-----+
|
||||
|
||||
.. _asyncio package from PyPI: https://pypi.python.org/pypi/asyncio
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@ import pymongo
|
||||
|
||||
from motor.motor_py3_compat import text_type
|
||||
|
||||
version_tuple = (1, 3, 'dev0')
|
||||
version_tuple = (1, 3, 2, 'dev0')
|
||||
|
||||
|
||||
def get_version_string():
|
||||
|
||||
@ -1336,7 +1336,7 @@ class AgnosticChangeStream(AgnosticBase):
|
||||
|
||||
if PY35:
|
||||
exec(textwrap.dedent("""
|
||||
async def __aiter__(self):
|
||||
def __aiter__(self):
|
||||
return self
|
||||
|
||||
__anext__ = next
|
||||
|
||||
@ -26,11 +26,6 @@ import functools
|
||||
import multiprocessing
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
|
||||
try:
|
||||
from asyncio import ensure_future
|
||||
except ImportError:
|
||||
from asyncio import async as ensure_future
|
||||
|
||||
CLASS_PREFIX = 'AsyncIO'
|
||||
|
||||
|
||||
|
||||
@ -21,6 +21,7 @@ See "Frameworks" in the Developer Guide.
|
||||
|
||||
import functools
|
||||
import os
|
||||
import warnings
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
|
||||
import tornado.process
|
||||
@ -89,6 +90,10 @@ def future_or_callback(future, callback, io_loop, return_value=_DEFAULT):
|
||||
internally.
|
||||
"""
|
||||
if callback:
|
||||
warnings.warn(
|
||||
'Motor\'s callback interface is deprecated, see the "Migrating'
|
||||
' to Motor 2.0" guide', DeprecationWarning, stacklevel=2)
|
||||
|
||||
if not callable(callback):
|
||||
raise callback_type_error
|
||||
|
||||
|
||||
2
setup.py
2
setup.py
@ -152,7 +152,7 @@ if sys.version_info[0] >= 3:
|
||||
packages.append('motor.aiohttp')
|
||||
|
||||
setup(name='motor',
|
||||
version='1.3.dev0',
|
||||
version='1.3.2.dev0',
|
||||
packages=packages,
|
||||
description=description,
|
||||
long_description=long_description,
|
||||
|
||||
@ -16,8 +16,10 @@ from __future__ import unicode_literals
|
||||
|
||||
"""Test Motor, an asynchronous driver for MongoDB and Tornado."""
|
||||
|
||||
import contextlib
|
||||
import logging
|
||||
import unittest
|
||||
import warnings
|
||||
from unittest import SkipTest
|
||||
|
||||
from test.test_environment import env, db_user, CLIENT_PEM
|
||||
@ -77,3 +79,13 @@ class MockRequestHandler(object):
|
||||
|
||||
def flush(self):
|
||||
pass
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def assert_deprecation_warnings(n=1):
|
||||
with warnings.catch_warnings(record=True) as records:
|
||||
warnings.filterwarnings('always', category=DeprecationWarning)
|
||||
yield
|
||||
|
||||
assert len(records) == n, \
|
||||
"Expected %d DeprecationWarning, not %r" % (n, records,)
|
||||
|
||||
@ -20,13 +20,9 @@ import gc
|
||||
import inspect
|
||||
import os
|
||||
import unittest
|
||||
from asyncio import ensure_future
|
||||
from unittest import SkipTest
|
||||
|
||||
try:
|
||||
from asyncio import ensure_future
|
||||
except ImportError:
|
||||
from asyncio import async as ensure_future
|
||||
|
||||
from mockupdb import MockupDB
|
||||
|
||||
from motor import motor_asyncio
|
||||
|
||||
@ -153,7 +153,11 @@ class TestAsyncIOCursor(AsyncIOMockServerTestCase):
|
||||
# Done iterating.
|
||||
future.set_result(True)
|
||||
|
||||
cursor.each(callback)
|
||||
with warnings.catch_warnings():
|
||||
# Should not raise, and not deprecated.
|
||||
warnings.filterwarnings('error')
|
||||
cursor.each(callback)
|
||||
|
||||
yield from future
|
||||
expected = [{'_id': i} for i in range(200)]
|
||||
self.assertEqual(expected, results)
|
||||
|
||||
@ -142,8 +142,10 @@ class MotorCollectionTest(MotorTest):
|
||||
def test_save_callback(self):
|
||||
yield self.collection.save({}, callback=None)
|
||||
|
||||
# Should not raise
|
||||
(result, error), _ = yield gen.Task(self.collection.save, {})
|
||||
# PyMongo deprecated "save", Motor deprecated the callback API used by
|
||||
# gen.Task.
|
||||
with test.assert_deprecation_warnings(2):
|
||||
(result, error), _ = yield gen.Task(self.collection.save, {})
|
||||
if error:
|
||||
raise error
|
||||
|
||||
@ -399,7 +401,9 @@ class MotorCollectionTest(MotorTest):
|
||||
else:
|
||||
future.set_result(result)
|
||||
|
||||
cursor.to_list(collection_size, callback=cb)
|
||||
with test.assert_deprecation_warnings():
|
||||
cursor.to_list(collection_size, callback=cb)
|
||||
|
||||
docs = yield future
|
||||
self.assertAllDocs(expected_sum, docs)
|
||||
|
||||
|
||||
@ -32,7 +32,7 @@ from pymongo.errors import OperationFailure
|
||||
|
||||
import motor
|
||||
import motor.motor_tornado
|
||||
from test import SkipTest, env
|
||||
from test import SkipTest, env, assert_deprecation_warnings
|
||||
from test.tornado_tests import (get_command_line,
|
||||
MotorTest,
|
||||
MotorMockServerTest,
|
||||
@ -182,7 +182,11 @@ class MotorCursorTest(MotorMockServerTest):
|
||||
# Done iterating.
|
||||
future.set_result(True)
|
||||
|
||||
cursor.each(callback)
|
||||
with warnings.catch_warnings():
|
||||
# Should not raise, and not deprecated.
|
||||
warnings.filterwarnings('error')
|
||||
cursor.each(callback)
|
||||
|
||||
yield future
|
||||
expected = [{'_id': i} for i in range(200)]
|
||||
self.assertEqual(expected, results)
|
||||
@ -205,11 +209,15 @@ class MotorCursorTest(MotorMockServerTest):
|
||||
cursor = self.collection.find({}, {'_id': 1})
|
||||
cursor.sort([('_id', pymongo.ASCENDING)])
|
||||
expected = [{'_id': i} for i in range(200)]
|
||||
(result, error), _ = yield gen.Task(cursor.to_list, length=1000)
|
||||
with assert_deprecation_warnings():
|
||||
(result, error), _ = yield gen.Task(cursor.to_list, length=1000)
|
||||
|
||||
self.assertEqual(expected, result)
|
||||
|
||||
cursor = self.collection.find().where('return foo')
|
||||
(result, error), _ = yield gen.Task(cursor.to_list, length=1000)
|
||||
with assert_deprecation_warnings():
|
||||
(result, error), _ = yield gen.Task(cursor.to_list, length=1000)
|
||||
|
||||
self.assertEqual(None, result)
|
||||
self.assertTrue(isinstance(error, OperationFailure))
|
||||
|
||||
|
||||
@ -28,6 +28,7 @@ from tornado.testing import gen_test
|
||||
|
||||
import motor
|
||||
from motor.motor_py3_compat import StringIO
|
||||
from test import assert_deprecation_warnings
|
||||
from test.tornado_tests import MotorTest
|
||||
|
||||
|
||||
@ -147,13 +148,15 @@ class MotorGridfsTest(MotorTest):
|
||||
|
||||
@gen_test
|
||||
def test_put_callback(self):
|
||||
(oid, error), _ = yield gen.Task(self.fs.put, b"hello")
|
||||
self.assertTrue(isinstance(oid, ObjectId))
|
||||
self.assertEqual(None, error)
|
||||
with assert_deprecation_warnings():
|
||||
(oid, error), _ = yield gen.Task(self.fs.put, b"hello")
|
||||
self.assertTrue(isinstance(oid, ObjectId))
|
||||
self.assertEqual(None, error)
|
||||
|
||||
(result, error), _ = yield gen.Task(self.fs.put, b"hello", _id=oid)
|
||||
self.assertEqual(None, result)
|
||||
self.assertTrue(isinstance(error, FileExists))
|
||||
with assert_deprecation_warnings():
|
||||
(result, error), _ = yield gen.Task(self.fs.put, b"hello", _id=oid)
|
||||
self.assertEqual(None, result)
|
||||
self.assertTrue(isinstance(error, FileExists))
|
||||
|
||||
@gen_test
|
||||
def test_put_duplicate(self):
|
||||
|
||||
Loading…
Reference in New Issue
Block a user