Finalize option locations and exports.
- Move ReturnDocument to pymongo.collection. - Change ReturnDocument.Before to ReturnDocument.BEFORE - Change ReturnDocument.After to ReturnDocument.AFTER - Add pymongo.cursor.CursorType. - Move pymongo.cursor.NON_TAILABLE and friends to attributes of CursorType. - read_preferences.ReadPreference is once again an "enum". - Fix docs for read_preferences.ReadPreference. - Rename pymongo.options to pymongo.operations. - Export CursorType, ReturnDocument, WriteConcern, and public classes from pymongo.opertions through pymongo/__init__.py - Fix up a number of documentation issues in the process.
This commit is contained in:
parent
fcc06e52d5
commit
d69f76d380
@ -11,10 +11,13 @@
|
||||
.. autodata:: pymongo.GEOSPHERE
|
||||
.. autodata:: pymongo.HASHED
|
||||
.. autodata:: pymongo.TEXT
|
||||
.. autodata:: pymongo.cursor.NON_TAILABLE
|
||||
.. autodata:: pymongo.cursor.TAILABLE
|
||||
.. autodata:: pymongo.cursor.TAILABLE_AWAIT
|
||||
.. autodata:: pymongo.cursor.EXHAUST
|
||||
|
||||
.. autoclass:: pymongo.collection.ReturnDocument
|
||||
|
||||
.. autoattribute:: BEFORE
|
||||
:annotation:
|
||||
.. autoattribute:: AFTER
|
||||
:annotation:
|
||||
|
||||
.. autoclass:: pymongo.collection.Collection(database, name, create=False, **kwargs)
|
||||
|
||||
@ -41,7 +44,7 @@
|
||||
.. automethod:: delete_one
|
||||
.. automethod:: delete_many
|
||||
.. automethod:: aggregate
|
||||
.. automethod:: find(filter=None, projection=None, skip=0, limit=0, no_cursor_timeout=False, cursor_type=NON_TAILABLE, sort=None, allow_partial_results=False, oplog_replay=False, modifiers=None, manipulate=True)
|
||||
.. automethod:: find(filter=None, projection=None, skip=0, limit=0, no_cursor_timeout=False, cursor_type=CursorType.NON_TAILABLE, sort=None, allow_partial_results=False, oplog_replay=False, modifiers=None, manipulate=True)
|
||||
.. automethod:: find_one(filter_or_id=None, *args, **kwargs)
|
||||
.. automethod:: find_one_and_delete
|
||||
.. automethod:: find_one_and_replace(filter, replacement, projection=None, sort=None, return_document=ReturnDocument.Before, **kwargs)
|
||||
|
||||
@ -4,7 +4,18 @@
|
||||
.. automodule:: pymongo.cursor
|
||||
:synopsis: Tools for iterating over MongoDB query results
|
||||
|
||||
.. autoclass:: pymongo.cursor.Cursor(collection, filter=None, projection=None, skip=0, limit=0, no_cursor_timeout=False, cursor_type=NON_TAILABLE, sort=None, allow_partial_results=False, oplog_replay=False, modifiers=None, manipulate=True)
|
||||
.. autoclass:: pymongo.cursor.CursorType
|
||||
|
||||
.. autoattribute:: NON_TAILABLE
|
||||
:annotation:
|
||||
.. autoattribute:: TAILABLE
|
||||
:annotation:
|
||||
.. autoattribute:: TAILABLE_AWAIT
|
||||
:annotation:
|
||||
.. autoattribute:: EXHAUST
|
||||
:annotation:
|
||||
|
||||
.. autoclass:: pymongo.cursor.Cursor(collection, filter=None, projection=None, skip=0, limit=0, no_cursor_timeout=False, cursor_type=CursorType.NON_TAILABLE, sort=None, allow_partial_results=False, oplog_replay=False, modifiers=None, manipulate=True)
|
||||
:members:
|
||||
|
||||
.. describe:: c[index]
|
||||
|
||||
@ -40,7 +40,7 @@ Sub-modules:
|
||||
message
|
||||
mongo_client
|
||||
mongo_replica_set_client
|
||||
options
|
||||
operations
|
||||
pool
|
||||
read_preferences
|
||||
results
|
||||
|
||||
6
doc/api/pymongo/operations.rst
Normal file
6
doc/api/pymongo/operations.rst
Normal file
@ -0,0 +1,6 @@
|
||||
:mod:`operations` -- Operation class definitions
|
||||
================================================
|
||||
|
||||
.. automodule:: pymongo.operations
|
||||
:synopsis: Operation class definitions
|
||||
:members:
|
||||
@ -1,6 +0,0 @@
|
||||
:mod:`options` -- Option class definitions
|
||||
==========================================
|
||||
|
||||
.. automodule:: pymongo.options
|
||||
:synopsis: Option class definitions
|
||||
:members:
|
||||
@ -15,5 +15,11 @@
|
||||
.. autoclass:: pymongo.read_preferences.Nearest
|
||||
:inherited-members:
|
||||
|
||||
.. autodata:: ReadPreference
|
||||
.. autoclass:: ReadPreference
|
||||
|
||||
.. autoattribute:: PRIMARY
|
||||
.. autoattribute:: PRIMARY_PREFERRED
|
||||
.. autoattribute:: SECONDARY
|
||||
.. autoattribute:: SECONDARY_PREFERRED
|
||||
.. autoattribute:: NEAREST
|
||||
|
||||
|
||||
@ -80,11 +80,20 @@ def get_version_string():
|
||||
version = get_version_string()
|
||||
"""Current version of PyMongo."""
|
||||
|
||||
from pymongo.collection import ReturnDocument
|
||||
from pymongo.common import (MIN_SUPPORTED_WIRE_VERSION,
|
||||
MAX_SUPPORTED_WIRE_VERSION)
|
||||
from pymongo.cursor import CursorType
|
||||
from pymongo.mongo_client import MongoClient
|
||||
from pymongo.mongo_replica_set_client import MongoReplicaSetClient
|
||||
from pymongo.operations import (InsertOne,
|
||||
DeleteOne,
|
||||
DeleteMany,
|
||||
UpdateOne,
|
||||
UpdateMany,
|
||||
ReplaceOne)
|
||||
from pymongo.read_preferences import ReadPreference
|
||||
from pymongo.write_concern import WriteConcern
|
||||
|
||||
def has_c():
|
||||
"""Is the C extension installed?"""
|
||||
|
||||
@ -35,7 +35,7 @@ from pymongo.cursor import Cursor
|
||||
from pymongo.errors import ConfigurationError, InvalidName, OperationFailure
|
||||
from pymongo.helpers import _check_write_command_response, _command
|
||||
from pymongo.message import _INSERT, _UPDATE, _DELETE
|
||||
from pymongo.options import ReturnDocument, _WriteOp
|
||||
from pymongo.operations import _WriteOp
|
||||
from pymongo.read_preferences import ReadPreference
|
||||
from pymongo.results import (BulkWriteResult,
|
||||
DeleteResult,
|
||||
@ -44,7 +44,6 @@ from pymongo.results import (BulkWriteResult,
|
||||
UpdateResult)
|
||||
from pymongo.write_concern import WriteConcern
|
||||
|
||||
|
||||
try:
|
||||
from collections import OrderedDict
|
||||
_ORDERED_TYPES = (SON, OrderedDict)
|
||||
@ -54,6 +53,19 @@ except ImportError:
|
||||
_NO_OBJ_ERROR = "No matching object found"
|
||||
|
||||
|
||||
class ReturnDocument(object):
|
||||
"""An enum used with
|
||||
:meth:`~pymongo.collection.Collection.find_one_and_replace` and
|
||||
:meth:`~pymongo.collection.Collection.find_one_and_update`.
|
||||
"""
|
||||
BEFORE = False
|
||||
"""Return the original document before it was updated/replaced, or
|
||||
``None`` if no document matches the query.
|
||||
"""
|
||||
AFTER = True
|
||||
"""Return the updated/replaced or inserted document."""
|
||||
|
||||
|
||||
def _gen_index_name(keys):
|
||||
"""Generate an index name from the set of fields it is over.
|
||||
"""
|
||||
@ -287,8 +299,13 @@ class Collection(common.BaseObject):
|
||||
def bulk_write(self, requests, ordered=True):
|
||||
"""Send a batch of write operations to the server.
|
||||
|
||||
Write operations are passed as a list using the write operation classes
|
||||
from the :mod:`~pymongo.options` module::
|
||||
Requests are passed as a list of write operation instances (
|
||||
:class:`~pymongo.operations.InsertOne`,
|
||||
:class:`~pymongo.operations.UpdateOne`,
|
||||
:class:`~pymongo.operations.UpdateMany`,
|
||||
:class:`~pymongo.operations.ReplaceOne`,
|
||||
:class:`~pymongo.operations.DeleteOne`, or
|
||||
:class:`~pymongo.operations.DeleteMany`).
|
||||
|
||||
>>> for doc in db.test.find({}):
|
||||
... print(doc)
|
||||
@ -297,7 +314,7 @@ class Collection(common.BaseObject):
|
||||
{u'x': 1, u'_id': ObjectId('54f62e60fba5226811f634f0')}
|
||||
>>> # DeleteMany, UpdateOne, and UpdateMany are also available.
|
||||
...
|
||||
>>> from pymongo.options import InsertOne, DeleteOne, ReplaceOne
|
||||
>>> from pymongo import InsertOne, DeleteOne, ReplaceOne
|
||||
>>> requests = [InsertOne({'y': 1}), DeleteOne({'x': 1}),
|
||||
... ReplaceOne({'w': 1}, {'z': 1}, upsert=True)]
|
||||
>>> result = db.test.bulk_write(requests)
|
||||
@ -797,27 +814,27 @@ class Collection(common.BaseObject):
|
||||
time out on the server. Care should be taken to ensure that
|
||||
cursors with no_cursor_timeout turned on are properly closed.
|
||||
- `cursor_type` (optional): the type of cursor to return. The valid
|
||||
options are:
|
||||
options are defined by :class:`~pymongo.cursor.CursorType`:
|
||||
|
||||
- :data:`~pymongo.cursor.NON_TAILABLE` - the result of this find
|
||||
call will return a standard cursor over the result set.
|
||||
- :data:`~pymongo.cursor.TAILABLE` - the result of this find call
|
||||
will be a tailable cursor - tailable cursors are only for use
|
||||
with capped collections. They are not closed when the last data
|
||||
is retrieved but are kept open and the cursor location marks the
|
||||
final document position. If more data is received iteration of
|
||||
the cursor will continue from the last document received. For
|
||||
details, see the `tailable cursor documentation
|
||||
- :attr:`~pymongo.cursor.CursorType.NON_TAILABLE` - the result of
|
||||
this find call will return a standard cursor over the result set.
|
||||
- :attr:`~pymongo.cursor.CursorType.TAILABLE` - the result of this
|
||||
find call will be a tailable cursor - tailable cursors are only
|
||||
for use with capped collections. They are not closed when the
|
||||
last data is retrieved but are kept open and the cursor location
|
||||
marks the final document position. If more data is received
|
||||
iteration of the cursor will continue from the last document
|
||||
received. For details, see the `tailable cursor documentation
|
||||
<http://www.mongodb.org/display/DOCS/Tailable+Cursors>`_.
|
||||
- :data:`~pymongo.cursor.TAILABLE_AWAIT` - the result of this find
|
||||
call will be a tailable cursor with the await flag set. The
|
||||
server will wait for a few seconds after returning the full
|
||||
result set so that it can capture and return additional data
|
||||
- :attr:`~pymongo.cursor.CursorType.TAILABLE_AWAIT` - the result
|
||||
of this find call will be a tailable cursor with the await flag
|
||||
set. The server will wait for a few seconds after returning the
|
||||
full result set so that it can capture and return additional data
|
||||
added during the query.
|
||||
- :data:`~pymongo.cursor.EXHAUST` - the result of this find call
|
||||
will be an exhaust cursor. MongoDB will stream batched results to
|
||||
the client without waiting for the client to request each batch,
|
||||
reducing latency. See notes on compatibility below.
|
||||
- :attr:`~pymongo.cursor.CursorType.EXHAUST` - the result of this
|
||||
find call will be an exhaust cursor. MongoDB will stream batched
|
||||
results to the client without waiting for the client to request
|
||||
each batch, reducing latency. See notes on compatibility below.
|
||||
|
||||
- `sort` (optional): a list of (key, direction) pairs
|
||||
specifying the sort order for this query. See
|
||||
@ -833,7 +850,7 @@ class Collection(common.BaseObject):
|
||||
apply any outgoing SON manipulators before returning.
|
||||
|
||||
.. note:: There are a number of caveats to using
|
||||
:data:`~pymongo.cursor.EXHAUST` as cursor_type:
|
||||
:attr:`~pymongo.cursor.CursorType.EXHAUST` as cursor_type:
|
||||
|
||||
1. The `limit` option can not be used with an exhaust cursor.
|
||||
|
||||
@ -841,8 +858,8 @@ class Collection(common.BaseObject):
|
||||
used with a sharded cluster.
|
||||
|
||||
3. A :class:`~pymongo.cursor.Cursor` instance created with the
|
||||
cursor.EXHAUST cursor_type requires an exclusive
|
||||
:class:`~socket.socket` connection to MongoDB. If the
|
||||
:attr:`~pymongo.cursor.CursorType.EXHAUST` cursor_type requires an
|
||||
exclusive :class:`~socket.socket` connection to MongoDB. If the
|
||||
:class:`~pymongo.cursor.Cursor` is discarded without being
|
||||
completely iterated the underlying :class:`~socket.socket`
|
||||
connection will be closed and discarded without being returned to
|
||||
@ -1654,12 +1671,12 @@ class Collection(common.BaseObject):
|
||||
return res.get("results")
|
||||
|
||||
def __find_and_modify(self, filter, projection, sort, upsert=None,
|
||||
return_document=ReturnDocument.Before, **kwargs):
|
||||
return_document=ReturnDocument.BEFORE, **kwargs):
|
||||
"""Internal findAndModify helper."""
|
||||
common.validate_is_mapping("filter", filter)
|
||||
if not isinstance(return_document, bool):
|
||||
raise ValueError("return_document must be "
|
||||
"ReturnDocument.Before or ReturnDocument.After")
|
||||
"ReturnDocument.BEFORE or ReturnDocument.AFTER")
|
||||
cmd = SON([("findAndModify", self.__name),
|
||||
("query", filter),
|
||||
("new", return_document)])
|
||||
@ -1726,13 +1743,13 @@ class Collection(common.BaseObject):
|
||||
|
||||
def find_one_and_replace(self, filter, replacement,
|
||||
projection=None, sort=None, upsert=False,
|
||||
return_document=ReturnDocument.Before, **kwargs):
|
||||
return_document=ReturnDocument.BEFORE, **kwargs):
|
||||
"""Finds a single document and replaces it, returning either the
|
||||
original or the replaced document.
|
||||
|
||||
The `find_one_and_replace` method differs from `find_one_and_update`
|
||||
by replacing the document matched by *filter*, rather than modifying
|
||||
the existing document.
|
||||
The :meth:`find_one_and_replace` method differs from
|
||||
:meth:`find_one_and_update` by replacing the document matched by
|
||||
*filter*, rather than modifying the existing document.
|
||||
|
||||
>>> for doc in db.test.find({}):
|
||||
... print(doc)
|
||||
@ -1763,10 +1780,10 @@ class Collection(common.BaseObject):
|
||||
- `upsert` (optional): When ``True``, inserts a new document if no
|
||||
document matches the query. Defaults to ``False``.
|
||||
- `return_document`: If
|
||||
:attr:`~pymongo.options.ReturnDocument.Before` (the default),
|
||||
:attr:`ReturnDocument.BEFORE` (the default),
|
||||
returns the original document before it was replaced, or ``None``
|
||||
if no document matches. If
|
||||
:attr:`~pymongo.options.ReturnDocument.After`, returns the replaced
|
||||
:attr:`ReturnDocument.AFTER`, returns the replaced
|
||||
or inserted document.
|
||||
- `**kwargs` (optional): additional command arguments can be passed
|
||||
as keyword arguments (for example maxTimeMS can be used with
|
||||
@ -1781,7 +1798,7 @@ class Collection(common.BaseObject):
|
||||
|
||||
def find_one_and_update(self, filter, update,
|
||||
projection=None, sort=None, upsert=False,
|
||||
return_document=ReturnDocument.Before, **kwargs):
|
||||
return_document=ReturnDocument.BEFORE, **kwargs):
|
||||
"""Finds a single document and updates it, returning either the
|
||||
original or the updated document.
|
||||
|
||||
@ -1789,11 +1806,11 @@ class Collection(common.BaseObject):
|
||||
... {'_id': 665}, {'$inc': {'count': 1}, '$set': {'done': True}})
|
||||
{u'_id': 665, u'done': False, u'count': 25}}
|
||||
|
||||
By default `find_one_and_update` returns the original version of the
|
||||
document before the update was applied. To return the updated version
|
||||
of the document instead, use the *return_document* option.
|
||||
By default :meth:`find_one_and_update` returns the original version of
|
||||
the document before the update was applied. To return the updated
|
||||
version of the document instead, use the *return_document* option.
|
||||
|
||||
>>> from pymongo.options import ReturnDocument
|
||||
>>> from pymongo import ReturnDocument
|
||||
>>> db.example.find_one_and_update(
|
||||
... {'_id': 'userid'},
|
||||
... {'$inc': {'seq': 1}},
|
||||
@ -1849,10 +1866,10 @@ class Collection(common.BaseObject):
|
||||
- `upsert` (optional): When ``True``, inserts a new document if no
|
||||
document matches the query. Defaults to ``False``.
|
||||
- `return_document`: If
|
||||
:attr:`~pymongo.options.ReturnDocument.Before` (the default),
|
||||
:attr:`ReturnDocument.BEFORE` (the default),
|
||||
returns the original document before it was updated, or ``None``
|
||||
if no document matches. If
|
||||
:attr:`~pymongo.options.ReturnDocument.After`, returns the updated
|
||||
:attr:`ReturnDocument.AFTER`, returns the updated
|
||||
or inserted document.
|
||||
- `**kwargs` (optional): additional command arguments can be passed
|
||||
as keyword arguments (for example maxTimeMS can be used with
|
||||
|
||||
@ -43,32 +43,33 @@ _QUERY_OPTIONS = {
|
||||
"partial": 128}
|
||||
|
||||
|
||||
NON_TAILABLE = 0
|
||||
"""The standard cursor type."""
|
||||
class CursorType(object):
|
||||
NON_TAILABLE = 0
|
||||
"""The standard cursor type."""
|
||||
|
||||
TAILABLE = _QUERY_OPTIONS["tailable_cursor"]
|
||||
"""The tailable cursor type.
|
||||
TAILABLE = _QUERY_OPTIONS["tailable_cursor"]
|
||||
"""The tailable cursor type.
|
||||
|
||||
Tailable cursors are only for use with capped collections. They are not closed
|
||||
when the last data is retrieved but are kept open and the cursor location marks
|
||||
the final document position. If more data is received iteration of the cursor
|
||||
will continue from the last document received.
|
||||
"""
|
||||
Tailable cursors are only for use with capped collections. They are not
|
||||
closed when the last data is retrieved but are kept open and the cursor
|
||||
location marks the final document position. If more data is received
|
||||
iteration of the cursor will continue from the last document received.
|
||||
"""
|
||||
|
||||
TAILABLE_AWAIT = TAILABLE | _QUERY_OPTIONS["await_data"]
|
||||
"""A tailable cursor with the await option set.
|
||||
TAILABLE_AWAIT = TAILABLE | _QUERY_OPTIONS["await_data"]
|
||||
"""A tailable cursor with the await option set.
|
||||
|
||||
Creates a tailable cursor that will wait for a few seconds after returning the
|
||||
full result set so that it can capture and return additional data added during
|
||||
the query.
|
||||
"""
|
||||
Creates a tailable cursor that will wait for a few seconds after returning
|
||||
the full result set so that it can capture and return additional data added
|
||||
during the query.
|
||||
"""
|
||||
|
||||
EXHAUST = _QUERY_OPTIONS["exhaust"]
|
||||
"""An exhaust cursor.
|
||||
EXHAUST = _QUERY_OPTIONS["exhaust"]
|
||||
"""An exhaust cursor.
|
||||
|
||||
MongoDB will stream batched results to the client without waiting for the
|
||||
client to request each batch, reducing latency.
|
||||
"""
|
||||
MongoDB will stream batched results to the client without waiting for the
|
||||
client to request each batch, reducing latency.
|
||||
"""
|
||||
|
||||
|
||||
# This has to be an old style class due to
|
||||
@ -98,7 +99,8 @@ class Cursor(object):
|
||||
"""
|
||||
|
||||
def __init__(self, collection, filter=None, projection=None, skip=0,
|
||||
limit=0, no_cursor_timeout=False, cursor_type=NON_TAILABLE,
|
||||
limit=0, no_cursor_timeout=False,
|
||||
cursor_type=CursorType.NON_TAILABLE,
|
||||
sort=None, allow_partial_results=False, oplog_replay=False,
|
||||
modifiers=None, manipulate=True):
|
||||
"""Create a new cursor.
|
||||
@ -120,8 +122,8 @@ class Cursor(object):
|
||||
if not isinstance(limit, int):
|
||||
raise TypeError("limit must be an instance of int")
|
||||
validate_boolean("no_cursor_timeout", no_cursor_timeout)
|
||||
if cursor_type not in (NON_TAILABLE, TAILABLE,
|
||||
TAILABLE_AWAIT, EXHAUST):
|
||||
if cursor_type not in (CursorType.NON_TAILABLE, CursorType.TAILABLE,
|
||||
CursorType.TAILABLE_AWAIT, CursorType.EXHAUST):
|
||||
raise ValueError("not a valid value for cursor_type")
|
||||
validate_boolean("allow_partial_results", allow_partial_results)
|
||||
validate_boolean("oplog_replay", oplog_replay)
|
||||
@ -153,7 +155,7 @@ class Cursor(object):
|
||||
# Exhaust cursor support
|
||||
self.__exhaust = False
|
||||
self.__exhaust_mgr = None
|
||||
if cursor_type == EXHAUST:
|
||||
if cursor_type == CursorType.EXHAUST:
|
||||
if self.__collection.database.client.is_mongos:
|
||||
raise InvalidOperation('Exhaust cursors are '
|
||||
'not supported by mongos')
|
||||
|
||||
@ -12,22 +12,10 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""Option class definitions."""
|
||||
"""Operation class definitions."""
|
||||
|
||||
from pymongo.common import validate_boolean, validate_is_mapping
|
||||
|
||||
class ReturnDocument(object):
|
||||
"""An enum used with
|
||||
:meth:`~pymongo.collection.Collection.find_one_and_replace` and
|
||||
:meth:`~pymongo.collection.Collection.find_one_and_update`.
|
||||
"""
|
||||
Before = False
|
||||
"""Return the original document before it was updated/replaced, or
|
||||
``None`` if no document matches the query.
|
||||
"""
|
||||
After = True
|
||||
"""Return the updated/replaced or inserted document."""
|
||||
|
||||
|
||||
class _WriteOp(object):
|
||||
"""Private base class for all write operations."""
|
||||
@ -14,7 +14,7 @@
|
||||
|
||||
"""Utilities for choosing which member of a replica set to read from."""
|
||||
|
||||
from collections import Mapping, namedtuple
|
||||
from collections import Mapping
|
||||
|
||||
from pymongo.errors import ConfigurationError
|
||||
from pymongo.server_selectors import (member_with_tags_server_selector,
|
||||
@ -278,66 +278,61 @@ _MODES = (
|
||||
)
|
||||
|
||||
|
||||
ReadPreference = namedtuple("ReadPreference", _MODES)(
|
||||
Primary(), PrimaryPreferred(), Secondary(), SecondaryPreferred(), Nearest())
|
||||
"""An enum that defines the read preference modes supported by PyMongo.
|
||||
class ReadPreference(object):
|
||||
"""An enum that defines the read preference modes supported by PyMongo.
|
||||
|
||||
See :doc:`/examples/high_availability` for code examples.
|
||||
See :doc:`/examples/high_availability` for code examples.
|
||||
|
||||
A read preference is used in three cases:
|
||||
A read preference is used in three cases:
|
||||
|
||||
:class:`~pymongo.mongo_client.MongoClient` connected to a single mongod:
|
||||
:class:`~pymongo.mongo_client.MongoClient` connected to a single mongod:
|
||||
|
||||
- ``PRIMARY``: Queries are allowed if the server is standalone or a replica
|
||||
set primary.
|
||||
- All other modes allow queries to standalone servers, to a replica set
|
||||
primary, or to replica set secondaries.
|
||||
- ``PRIMARY``: Queries are allowed if the server is standalone or a replica
|
||||
set primary.
|
||||
- All other modes allow queries to standalone servers, to a replica set
|
||||
primary, or to replica set secondaries.
|
||||
|
||||
:class:`~pymongo.mongo_client.MongoClient` initialized with the
|
||||
``replicaSet`` option:
|
||||
:class:`~pymongo.mongo_client.MongoClient` initialized with the
|
||||
``replicaSet`` option:
|
||||
|
||||
- ``PRIMARY``: Read from the primary. This is the default, and provides the
|
||||
strongest consistency. If no primary is available, raise
|
||||
:class:`~pymongo.errors.AutoReconnect`.
|
||||
- ``PRIMARY``: Read from the primary. This is the default, and provides the
|
||||
strongest consistency. If no primary is available, raise
|
||||
:class:`~pymongo.errors.AutoReconnect`.
|
||||
|
||||
- ``PRIMARY_PREFERRED``: Read from the primary if available, or if there is
|
||||
none, read from a secondary matching your choice of ``tag_sets`` and
|
||||
``local_threshold_ms``.
|
||||
- ``PRIMARY_PREFERRED``: Read from the primary if available, or if there is
|
||||
none, read from a secondary.
|
||||
|
||||
- ``SECONDARY``: Read from a secondary matching your choice of ``tag_sets`` and
|
||||
``local_threshold_ms``. If no matching secondary is available,
|
||||
raise :class:`~pymongo.errors.AutoReconnect`.
|
||||
- ``SECONDARY``: Read from a secondary. If no secondary is available,
|
||||
raise :class:`~pymongo.errors.AutoReconnect`.
|
||||
|
||||
- ``SECONDARY_PREFERRED``: Read from a secondary matching your choice of
|
||||
``tag_sets`` and ``local_threshold_ms`` if available, otherwise
|
||||
from primary (regardless of the primary's tags and local threshold).
|
||||
- ``SECONDARY_PREFERRED``: Read from a secondary if available, otherwise
|
||||
from the primary.
|
||||
|
||||
- ``NEAREST``: Read from any member matching your choice of ``tag_sets`` and
|
||||
``local_threshold_ms``.
|
||||
- ``NEAREST``: Read from any member.
|
||||
|
||||
:class:`~pymongo.mongo_client.MongoClient` connected to a mongos, with a
|
||||
sharded cluster of replica sets:
|
||||
:class:`~pymongo.mongo_client.MongoClient` connected to a mongos, with a
|
||||
sharded cluster of replica sets:
|
||||
|
||||
- ``PRIMARY``: Read from the primary of the shard, or raise
|
||||
:class:`~pymongo.errors.OperationFailure` if there is none.
|
||||
This is the default.
|
||||
- ``PRIMARY``: Read from the primary of the shard, or raise
|
||||
:class:`~pymongo.errors.OperationFailure` if there is none.
|
||||
This is the default.
|
||||
|
||||
- ``PRIMARY_PREFERRED``: Read from the primary of the shard, or if there is
|
||||
none, read from a secondary matching your choice of ``tag_sets``.
|
||||
- ``PRIMARY_PREFERRED``: Read from the primary of the shard, or if there is
|
||||
none, read from a secondary of the shard.
|
||||
|
||||
- ``SECONDARY``: Read from a secondary matching your choice of ``tag_sets``,
|
||||
or raise :class:`~pymongo.errors.OperationFailure` if there is none.
|
||||
- ``SECONDARY``: Read from a secondary of the shard, or raise
|
||||
:class:`~pymongo.errors.OperationFailure` if there is none.
|
||||
|
||||
- ``SECONDARY_PREFERRED``: Read from a secondary matching your choice of
|
||||
``tag_sets``, otherwise from primary.
|
||||
- ``SECONDARY_PREFERRED``: Read from a secondary of the shard if available,
|
||||
otherwise from the shard primary.
|
||||
|
||||
- ``NEAREST``: Read from any member matching your choice of ``tag_sets``.
|
||||
|
||||
.. note:: ``local_threshold_ms`` is ignored when talking to a
|
||||
replica set *through* a mongos. The equivalent is the
|
||||
`localThreshold <http://docs.mongodb.org/manual/reference/mongos/#cmdoption--localThreshold>`_
|
||||
command line option.
|
||||
"""
|
||||
- ``NEAREST``: Read from any shard member.
|
||||
"""
|
||||
PRIMARY = Primary()
|
||||
PRIMARY_PREFERRED = PrimaryPreferred()
|
||||
SECONDARY = Secondary()
|
||||
SECONDARY_PREFERRED = SecondaryPreferred()
|
||||
NEAREST = Nearest()
|
||||
|
||||
|
||||
def read_pref_mode_from_name(name):
|
||||
|
||||
@ -38,7 +38,8 @@ class _WriteResult(object):
|
||||
|
||||
|
||||
class InsertOneResult(_WriteResult):
|
||||
"""The return type for :meth:`Collection.insert_one`."""
|
||||
"""The return type for :meth:`~pymongo.collection.Collection.insert_one`.
|
||||
"""
|
||||
|
||||
__slots__ = ("__inserted_id", "__acknowledged")
|
||||
|
||||
@ -75,8 +76,10 @@ class InsertManyResult(_WriteResult):
|
||||
|
||||
|
||||
class UpdateResult(_WriteResult):
|
||||
"""The return type for :meth:`~pymongo.collection.Collection.update_one`
|
||||
and :meth:`~pymongo.collection.Collection.update_many`"""
|
||||
"""The return type for :meth:`~pymongo.collection.Collection.update_one`,
|
||||
:meth:`~pymongo.collection.Collection.update_many`, and
|
||||
:meth:`~pymongo.collection.Collection.replace_one`.
|
||||
"""
|
||||
|
||||
__slots__ = ("__raw_result", "__acknowledged")
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@ from bson import InvalidDocument, SON
|
||||
from bson.objectid import ObjectId
|
||||
from bson.py3compat import string_type
|
||||
from pymongo import MongoClient
|
||||
from pymongo.options import *
|
||||
from pymongo.operations import *
|
||||
from pymongo.common import partition_node
|
||||
from pymongo.errors import (BulkWriteError,
|
||||
ConfigurationError,
|
||||
|
||||
@ -32,7 +32,7 @@ from bson.py3compat import thread, u
|
||||
from bson.son import SON
|
||||
from bson.tz_util import utc
|
||||
from pymongo import auth, message
|
||||
from pymongo.cursor import EXHAUST
|
||||
from pymongo.cursor import CursorType
|
||||
from pymongo.database import Database
|
||||
from pymongo.errors import (AutoReconnect,
|
||||
ConfigurationError,
|
||||
@ -756,7 +756,7 @@ class TestClient(IntegrationTest):
|
||||
# Cause a network error.
|
||||
sock_info = one(pool.sockets)
|
||||
sock_info.sock.close()
|
||||
cursor = collection.find(cursor_type=EXHAUST)
|
||||
cursor = collection.find(cursor_type=CursorType.EXHAUST)
|
||||
with self.assertRaises(ConnectionFailure):
|
||||
next(cursor)
|
||||
|
||||
@ -848,7 +848,8 @@ class TestExhaustCursor(IntegrationTest):
|
||||
# This will cause OperationFailure in all mongo versions since
|
||||
# the value for $orderby must be a document.
|
||||
cursor = collection.find(
|
||||
SON([('$query', {}), ('$orderby', True)]), cursor_type=EXHAUST)
|
||||
SON([('$query', {}), ('$orderby', True)]),
|
||||
cursor_type=CursorType.EXHAUST)
|
||||
|
||||
self.assertRaises(OperationFailure, cursor.next)
|
||||
self.assertFalse(sock_info.closed)
|
||||
@ -871,7 +872,7 @@ class TestExhaustCursor(IntegrationTest):
|
||||
pool._check_interval_seconds = None # Never check.
|
||||
sock_info = one(pool.sockets)
|
||||
|
||||
cursor = collection.find(cursor_type=EXHAUST)
|
||||
cursor = collection.find(cursor_type=CursorType.EXHAUST)
|
||||
|
||||
# Initial query succeeds.
|
||||
cursor.next()
|
||||
@ -907,7 +908,7 @@ class TestExhaustCursor(IntegrationTest):
|
||||
sock_info = one(pool.sockets)
|
||||
sock_info.sock.close()
|
||||
|
||||
cursor = collection.find(cursor_type=EXHAUST)
|
||||
cursor = collection.find(cursor_type=CursorType.EXHAUST)
|
||||
self.assertRaises(ConnectionFailure, cursor.next)
|
||||
self.assertTrue(sock_info.closed)
|
||||
|
||||
@ -925,7 +926,7 @@ class TestExhaustCursor(IntegrationTest):
|
||||
pool = get_pool(client)
|
||||
pool._check_interval_seconds = None # Never check.
|
||||
|
||||
cursor = collection.find(cursor_type=EXHAUST)
|
||||
cursor = collection.find(cursor_type=CursorType.EXHAUST)
|
||||
|
||||
# Initial query succeeds.
|
||||
cursor.next()
|
||||
|
||||
@ -32,15 +32,14 @@ from bson.son import SON
|
||||
from pymongo import (ASCENDING, DESCENDING, GEO2D,
|
||||
GEOHAYSTACK, GEOSPHERE, HASHED, TEXT)
|
||||
from pymongo import MongoClient
|
||||
from pymongo.collection import Collection
|
||||
from pymongo.collection import Collection, ReturnDocument
|
||||
from pymongo.command_cursor import CommandCursor
|
||||
from pymongo.cursor import EXHAUST
|
||||
from pymongo.cursor import CursorType
|
||||
from pymongo.errors import (DuplicateKeyError,
|
||||
InvalidDocument,
|
||||
InvalidName,
|
||||
InvalidOperation,
|
||||
OperationFailure)
|
||||
from pymongo.options import ReturnDocument
|
||||
from pymongo.read_preferences import ReadPreference
|
||||
from pymongo.results import (InsertOneResult,
|
||||
InsertManyResult,
|
||||
@ -1374,13 +1373,16 @@ class TestCollection(IntegrationTest):
|
||||
def test_exhaust(self):
|
||||
if is_mongos(self.db.client):
|
||||
self.assertRaises(InvalidOperation,
|
||||
self.db.test.find, cursor_type=EXHAUST)
|
||||
self.db.test.find,
|
||||
cursor_type=CursorType.EXHAUST)
|
||||
return
|
||||
|
||||
# Limit is incompatible with exhaust.
|
||||
self.assertRaises(InvalidOperation,
|
||||
self.db.test.find, cursor_type=EXHAUST, limit=5)
|
||||
cur = self.db.test.find(cursor_type=EXHAUST)
|
||||
self.db.test.find,
|
||||
cursor_type=CursorType.EXHAUST,
|
||||
limit=5)
|
||||
cur = self.db.test.find(cursor_type=CursorType.EXHAUST)
|
||||
self.assertRaises(InvalidOperation, cur.limit, 5)
|
||||
cur = self.db.test.find(limit=5)
|
||||
self.assertRaises(InvalidOperation, cur.add_option, 64)
|
||||
@ -1396,7 +1398,7 @@ class TestCollection(IntegrationTest):
|
||||
socks = get_pool(client).sockets
|
||||
|
||||
# Make sure the socket is returned after exhaustion.
|
||||
cur = client[self.db.name].test.find(cursor_type=EXHAUST)
|
||||
cur = client[self.db.name].test.find(cursor_type=CursorType.EXHAUST)
|
||||
next(cur)
|
||||
self.assertEqual(0, len(socks))
|
||||
for _ in cur:
|
||||
@ -1404,14 +1406,14 @@ class TestCollection(IntegrationTest):
|
||||
self.assertEqual(1, len(socks))
|
||||
|
||||
# Same as previous but don't call next()
|
||||
for _ in client[self.db.name].test.find(cursor_type=EXHAUST):
|
||||
for _ in client[self.db.name].test.find(cursor_type=CursorType.EXHAUST):
|
||||
pass
|
||||
self.assertEqual(1, len(socks))
|
||||
|
||||
# If the Cursor instance is discarded before being
|
||||
# completely iterated we have to close and
|
||||
# discard the socket.
|
||||
cur = client[self.db.name].test.find(cursor_type=EXHAUST)
|
||||
cur = client[self.db.name].test.find(cursor_type=CursorType.EXHAUST)
|
||||
next(cur)
|
||||
self.assertEqual(0, len(socks))
|
||||
if sys.platform.startswith('java') or 'PyPy' in sys.version:
|
||||
@ -1606,7 +1608,7 @@ class TestCollection(IntegrationTest):
|
||||
self.assertEqual({'_id': 1, 'i': 3},
|
||||
c.find_one_and_update(
|
||||
{'_id': 1}, {'$inc': {'i': 1}},
|
||||
return_document=ReturnDocument.After))
|
||||
return_document=ReturnDocument.AFTER))
|
||||
|
||||
self.assertEqual({'_id': 1, 'i': 3},
|
||||
c.find_one_and_delete({'_id': 1}))
|
||||
@ -1617,23 +1619,23 @@ class TestCollection(IntegrationTest):
|
||||
self.assertEqual({'_id': 1, 'i': 1},
|
||||
c.find_one_and_update(
|
||||
{'_id': 1}, {'$inc': {'i': 1}},
|
||||
return_document=ReturnDocument.After,
|
||||
return_document=ReturnDocument.AFTER,
|
||||
upsert=True))
|
||||
self.assertEqual({'_id': 1, 'i': 2},
|
||||
c.find_one_and_update(
|
||||
{'_id': 1}, {'$inc': {'i': 1}},
|
||||
return_document=ReturnDocument.After))
|
||||
return_document=ReturnDocument.AFTER))
|
||||
|
||||
self.assertEqual({'_id': 1, 'i': 3},
|
||||
c.find_one_and_replace(
|
||||
{'_id': 1}, {'i': 3, 'j': 1},
|
||||
projection=['i'],
|
||||
return_document=ReturnDocument.After))
|
||||
return_document=ReturnDocument.AFTER))
|
||||
self.assertEqual({'i': 4},
|
||||
c.find_one_and_update(
|
||||
{'_id': 1}, {'$inc': {'i': 1}},
|
||||
projection={'i': 1, '_id': 0},
|
||||
return_document=ReturnDocument.After))
|
||||
return_document=ReturnDocument.AFTER))
|
||||
|
||||
c.drop()
|
||||
for j in range(5):
|
||||
|
||||
@ -30,7 +30,7 @@ from pymongo import (MongoClient,
|
||||
ALL,
|
||||
OFF)
|
||||
from pymongo.command_cursor import CommandCursor
|
||||
from pymongo.cursor import TAILABLE, TAILABLE_AWAIT, EXHAUST
|
||||
from pymongo.cursor import CursorType
|
||||
from pymongo.cursor_manager import CursorManager
|
||||
from pymongo.errors import (InvalidOperation,
|
||||
OperationFailure,
|
||||
@ -68,17 +68,18 @@ class TestCursorNoConnect(unittest.TestCase):
|
||||
cursor = self.db.test.find()
|
||||
self.assertEqual(0, cursor._Cursor__query_flags)
|
||||
cursor.add_option(2)
|
||||
cursor2 = self.db.test.find(cursor_type=TAILABLE)
|
||||
cursor2 = self.db.test.find(cursor_type=CursorType.TAILABLE)
|
||||
self.assertEqual(2, cursor2._Cursor__query_flags)
|
||||
self.assertEqual(cursor._Cursor__query_flags,
|
||||
cursor2._Cursor__query_flags)
|
||||
cursor.add_option(32)
|
||||
cursor2 = self.db.test.find(cursor_type=TAILABLE_AWAIT)
|
||||
cursor2 = self.db.test.find(cursor_type=CursorType.TAILABLE_AWAIT)
|
||||
self.assertEqual(34, cursor2._Cursor__query_flags)
|
||||
self.assertEqual(cursor._Cursor__query_flags,
|
||||
cursor2._Cursor__query_flags)
|
||||
cursor.add_option(128)
|
||||
cursor2 = self.db.test.find(cursor_type=TAILABLE_AWAIT).add_option(128)
|
||||
cursor2 = self.db.test.find(
|
||||
cursor_type=CursorType.TAILABLE_AWAIT).add_option(128)
|
||||
self.assertEqual(162, cursor2._Cursor__query_flags)
|
||||
self.assertEqual(cursor._Cursor__query_flags,
|
||||
cursor2._Cursor__query_flags)
|
||||
@ -88,12 +89,12 @@ class TestCursorNoConnect(unittest.TestCase):
|
||||
self.assertEqual(162, cursor._Cursor__query_flags)
|
||||
|
||||
cursor.remove_option(128)
|
||||
cursor2 = self.db.test.find(cursor_type=TAILABLE_AWAIT)
|
||||
cursor2 = self.db.test.find(cursor_type=CursorType.TAILABLE_AWAIT)
|
||||
self.assertEqual(34, cursor2._Cursor__query_flags)
|
||||
self.assertEqual(cursor._Cursor__query_flags,
|
||||
cursor2._Cursor__query_flags)
|
||||
cursor.remove_option(32)
|
||||
cursor2 = self.db.test.find(cursor_type=TAILABLE)
|
||||
cursor2 = self.db.test.find(cursor_type=CursorType.TAILABLE)
|
||||
self.assertEqual(2, cursor2._Cursor__query_flags)
|
||||
self.assertEqual(cursor._Cursor__query_flags,
|
||||
cursor2._Cursor__query_flags)
|
||||
@ -112,7 +113,7 @@ class TestCursorNoConnect(unittest.TestCase):
|
||||
self.assertEqual(0, cursor._Cursor__query_flags)
|
||||
|
||||
# Tailable / Await data
|
||||
cursor = self.db.test.find(cursor_type=TAILABLE_AWAIT)
|
||||
cursor = self.db.test.find(cursor_type=CursorType.TAILABLE_AWAIT)
|
||||
self.assertEqual(34, cursor._Cursor__query_flags)
|
||||
cursor2 = self.db.test.find().add_option(34)
|
||||
self.assertEqual(cursor._Cursor__query_flags,
|
||||
@ -121,7 +122,7 @@ class TestCursorNoConnect(unittest.TestCase):
|
||||
self.assertEqual(2, cursor._Cursor__query_flags)
|
||||
|
||||
# Exhaust - which mongos doesn't support
|
||||
cursor = self.db.test.find(cursor_type=EXHAUST)
|
||||
cursor = self.db.test.find(cursor_type=CursorType.EXHAUST)
|
||||
self.assertEqual(64, cursor._Cursor__query_flags)
|
||||
cursor2 = self.db.test.find().add_option(64)
|
||||
self.assertEqual(cursor._Cursor__query_flags,
|
||||
@ -723,7 +724,7 @@ class TestCursor(IntegrationTest):
|
||||
cursor = self.db.test.find({"x": re.compile("^hello.*")},
|
||||
skip=1,
|
||||
no_cursor_timeout=True,
|
||||
cursor_type=TAILABLE_AWAIT,
|
||||
cursor_type=CursorType.TAILABLE_AWAIT,
|
||||
allow_partial_results=True,
|
||||
manipulate=False,
|
||||
projection={'_id': False}).limit(2)
|
||||
@ -916,7 +917,7 @@ class TestCursor(IntegrationTest):
|
||||
db.drop_collection("test")
|
||||
db.create_collection("test", capped=True, size=1000, max=3)
|
||||
self.addCleanup(db.drop_collection, "test")
|
||||
cursor = db.test.find(cursor_type=TAILABLE)
|
||||
cursor = db.test.find(cursor_type=CursorType.TAILABLE)
|
||||
|
||||
db.test.insert_one({"x": 1})
|
||||
count = 0
|
||||
|
||||
@ -91,7 +91,11 @@ class TestReadPreferencesBase(TestReplicaSetClientBase):
|
||||
|
||||
class TestReadPreferences(TestReadPreferencesBase):
|
||||
def test_mode_validation(self):
|
||||
for mode in ReadPreference:
|
||||
for mode in (ReadPreference.PRIMARY,
|
||||
ReadPreference.PRIMARY_PREFERRED,
|
||||
ReadPreference.SECONDARY,
|
||||
ReadPreference.SECONDARY_PREFERRED,
|
||||
ReadPreference.NEAREST):
|
||||
self.assertEqual(
|
||||
mode,
|
||||
rs_client(read_preference=mode).read_preference)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user