PYTHON-1153 - Make docs build and test under python 3
This commit is contained in:
parent
f37be740e2
commit
2c232e78b2
@ -31,7 +31,7 @@ Example usage (serialization):
|
||||
>>> dumps([{'foo': [1, 2]},
|
||||
... {'bar': {'hello': 'world'}},
|
||||
... {'code': Code("function x() { return 1; }")},
|
||||
... {'bin': Binary("\x01\x02\x03\x04")}])
|
||||
... {'bin': Binary(b"\x01\x02\x03\x04")}])
|
||||
'[{"foo": [1, 2]}, {"bar": {"hello": "world"}}, {"code": {"$code": "function x() { return 1; }", "$scope": {}}}, {"bin": {"$binary": "AQIDBA==", "$type": "00"}}]'
|
||||
|
||||
Example usage (deserialization):
|
||||
|
||||
17
doc/conf.py
17
doc/conf.py
@ -4,8 +4,17 @@
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its containing dir.
|
||||
|
||||
import sys, os
|
||||
sys.path[0:0] = [os.path.abspath('..')]
|
||||
import os
|
||||
import sys
|
||||
|
||||
_path = os.path.abspath('..')
|
||||
sys.path[0:0] = [_path]
|
||||
if sys.version_info[0] >= 3:
|
||||
import glob
|
||||
ver = '.'.join(map(str, sys.version_info[:2]))
|
||||
_path = glob.glob(
|
||||
os.path.join(os.path.abspath('..'), 'build', 'lib*' + ver))[0]
|
||||
sys.path[0:0] = [_path]
|
||||
|
||||
import pymongo
|
||||
|
||||
@ -65,9 +74,9 @@ pygments_style = 'sphinx'
|
||||
# -- Options for extensions ----------------------------------------------------
|
||||
autoclass_content = 'init'
|
||||
|
||||
doctest_path = os.path.abspath('..')
|
||||
doctest_path = [_path]
|
||||
|
||||
doctest_test_doctest_blocks = False
|
||||
doctest_test_doctest_blocks = ''
|
||||
|
||||
doctest_global_setup = """
|
||||
from pymongo.mongo_client import MongoClient
|
||||
|
||||
@ -51,15 +51,20 @@ eg "$sort":
|
||||
PyMongo version **>= 2.3**.
|
||||
|
||||
.. doctest::
|
||||
:options: +NORMALIZE_WHITESPACE
|
||||
|
||||
>>> from bson.son import SON
|
||||
>>> db.things.aggregate([
|
||||
>>> import pprint
|
||||
>>> pprint.pprint(db.things.aggregate([
|
||||
... {"$unwind": "$tags"},
|
||||
... {"$group": {"_id": "$tags", "count": {"$sum": 1}}},
|
||||
... {"$sort": SON([("count", -1), ("_id", -1)])}
|
||||
... ])
|
||||
... ]))
|
||||
...
|
||||
{u'ok': 1.0, u'result': [{u'count': 3, u'_id': u'cat'}, {u'count': 2, u'_id': u'dog'}, {u'count': 1, u'_id': u'mouse'}]}
|
||||
{u'ok': 1.0,
|
||||
u'result': [{u'_id': u'cat', u'count': 3},
|
||||
{u'_id': u'dog', u'count': 2},
|
||||
{u'_id': u'mouse', u'count': 1}]}
|
||||
|
||||
|
||||
As well as simple aggregations the aggregation framework provides projection
|
||||
@ -115,7 +120,7 @@ iterate over the result collection:
|
||||
|
||||
>>> result = db.things.map_reduce(mapper, reducer, "myresults")
|
||||
>>> for doc in result.find():
|
||||
... print doc
|
||||
... pprint.pprint(doc)
|
||||
...
|
||||
{u'_id': u'cat', u'value': 3.0}
|
||||
{u'_id': u'dog', u'value': 2.0}
|
||||
@ -132,8 +137,12 @@ response to the map/reduce command, rather than just the result collection:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> db.things.map_reduce(mapper, reducer, "myresults", full_response=True)
|
||||
{u'counts': {u'input': 4, u'reduce': 2, u'emit': 6, u'output': 3}, u'timeMillis': ..., u'ok': ..., u'result': u'...'}
|
||||
>>> pprint.pprint(
|
||||
... db.things.map_reduce(mapper, reducer, "myresults", full_response=True))
|
||||
{u'counts': {u'emit': 6, u'input': 4, u'output': 3, u'reduce': 2},
|
||||
u'ok': ...,
|
||||
u'result': u'...',
|
||||
u'timeMillis': ...}
|
||||
|
||||
All of the optional map/reduce parameters are also supported, simply pass them
|
||||
as keyword arguments. In this example we use the `query` parameter to limit the
|
||||
@ -141,9 +150,10 @@ documents that will be mapped over:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> result = db.things.map_reduce(mapper, reducer, "myresults", query={"x": {"$lt": 2}})
|
||||
>>> for doc in result.find():
|
||||
... print doc
|
||||
>>> results = db.things.map_reduce(
|
||||
... mapper, reducer, "myresults", query={"x": {"$lt": 2}})
|
||||
>>> for doc in results.find():
|
||||
... pprint.pprint(doc)
|
||||
...
|
||||
{u'_id': u'cat', u'value': 1.0}
|
||||
{u'_id': u'dog', u'value': 1.0}
|
||||
@ -155,8 +165,16 @@ result collection:
|
||||
.. doctest::
|
||||
|
||||
>>> from bson.son import SON
|
||||
>>> db.things.map_reduce(mapper, reducer, out=SON([("replace", "results"), ("db", "outdb")]), full_response=True)
|
||||
{u'counts': {u'input': 4, u'reduce': 2, u'emit': 6, u'output': 3}, u'timeMillis': ..., u'ok': ..., u'result': {u'db': ..., u'collection': ...}}
|
||||
>>> pprint.pprint(
|
||||
... db.things.map_reduce(
|
||||
... mapper,
|
||||
... reducer,
|
||||
... out=SON([("replace", "results"), ("db", "outdb")]),
|
||||
... full_response=True))
|
||||
{u'counts': {u'emit': 6, u'input': 4, u'output': 3, u'reduce': 2},
|
||||
u'ok': ...,
|
||||
u'result': {u'collection': ..., u'db': ...},
|
||||
u'timeMillis': ...}
|
||||
|
||||
.. seealso:: The full list of options for MongoDB's `map reduce engine <http://www.mongodb.org/display/DOCS/MapReduce>`_
|
||||
|
||||
@ -184,7 +202,7 @@ Here we are doing a simple group and count of the occurrences of ``x`` values:
|
||||
...
|
||||
>>> results = db.things.group(key={"x":1}, condition={}, initial={"count": 0}, reduce=reducer)
|
||||
>>> for doc in results:
|
||||
... print doc
|
||||
... pprint.pprint(doc)
|
||||
{u'count': 1.0, u'x': 1.0}
|
||||
{u'count': 2.0, u'x': 2.0}
|
||||
{u'count': 1.0, u'x': 3.0}
|
||||
|
||||
@ -27,7 +27,7 @@ bulk insert operations.
|
||||
|
||||
>>> import pymongo
|
||||
>>> db = pymongo.MongoClient().bulk_example
|
||||
>>> db.test.insert(({'i': i} for i in xrange(10000)))
|
||||
>>> db.test.insert(({'i': i} for i in range(10000)))
|
||||
[...]
|
||||
>>> db.test.count()
|
||||
10000
|
||||
@ -58,6 +58,7 @@ order provided for serial execution. The return value is a document
|
||||
describing the type and count of operations performed.
|
||||
|
||||
.. doctest::
|
||||
:options: +NORMALIZE_WHITESPACE
|
||||
|
||||
>>> from pprint import pprint
|
||||
>>>
|
||||
@ -95,6 +96,7 @@ occurred and details about the failure - including the operation that caused
|
||||
the failure.
|
||||
|
||||
.. doctest::
|
||||
:options: +NORMALIZE_WHITESPACE
|
||||
|
||||
>>> from pymongo.errors import BulkWriteError
|
||||
>>> bulk = db.test.initialize_ordered_bulk_op()
|
||||
@ -106,7 +108,7 @@ the failure.
|
||||
>>> try:
|
||||
... bulk.execute()
|
||||
... except BulkWriteError as bwe:
|
||||
... pprint(bwe.details) # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
|
||||
... pprint(bwe.details)
|
||||
...
|
||||
{'nInserted': 0,
|
||||
'nMatched': 1,
|
||||
@ -134,6 +136,7 @@ constraint on _id. Since we are doing unordered execution the second
|
||||
and fourth operations succeed.
|
||||
|
||||
.. doctest::
|
||||
:options: +NORMALIZE_WHITESPACE
|
||||
|
||||
>>> bulk = db.test.initialize_unordered_bulk_op()
|
||||
>>> bulk.insert({'_id': 1})
|
||||
@ -143,7 +146,7 @@ and fourth operations succeed.
|
||||
>>> try:
|
||||
... bulk.execute()
|
||||
... except BulkWriteError as bwe:
|
||||
... pprint(bwe.details) # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
|
||||
... pprint(bwe.details)
|
||||
...
|
||||
{'nInserted': 0,
|
||||
'nMatched': 1,
|
||||
@ -172,6 +175,7 @@ errors (e.g. wtimeout) will be reported after all operations are attempted,
|
||||
regardless of execution order.
|
||||
|
||||
.. doctest::
|
||||
:options: +NORMALIZE_WHITESPACE
|
||||
|
||||
>>> bulk = db.test.initialize_ordered_bulk_op()
|
||||
>>> bulk.insert({'a': 0})
|
||||
|
||||
@ -68,10 +68,12 @@ use them with PyMongo:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> import pprint
|
||||
>>> db.test.insert({"custom": encode_custom(Custom(5))})
|
||||
ObjectId('...')
|
||||
>>> db.test.find_one()
|
||||
{u'_id': ObjectId('...'), u'custom': {u'x': 5, u'_type': u'custom'}}
|
||||
>>> pprint.pprint(db.test.find_one())
|
||||
{u'_id': ObjectId('...'),
|
||||
u'custom': {u'_type': u'custom', u'x': 5}}
|
||||
>>> decode_custom(db.test.find_one()["custom"])
|
||||
<Custom object at ...>
|
||||
>>> decode_custom(db.test.find_one()["custom"]).x()
|
||||
@ -122,8 +124,9 @@ After doing so we can save and restore :class:`Custom` instances seamlessly:
|
||||
{...}
|
||||
>>> db.test.insert({"custom": Custom(5)})
|
||||
ObjectId('...')
|
||||
>>> db.test.find_one()
|
||||
{u'_id': ObjectId('...'), u'custom': <Custom object at ...>}
|
||||
>>> pprint.pprint(db.test.find_one())
|
||||
{u'_id': ObjectId('...'),
|
||||
u'custom': <Custom object at ...>}
|
||||
>>> db.test.find_one()["custom"].x()
|
||||
5
|
||||
|
||||
@ -139,8 +142,9 @@ This allows us to see what was actually saved to the database:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> db.test.find_one()
|
||||
{u'_id': ObjectId('...'), u'custom': {u'x': 5, u'_type': u'custom'}}
|
||||
>>> pprint.pprint(db.test.find_one())
|
||||
{u'_id': ObjectId('...'),
|
||||
u'custom': {u'_type': u'custom', u'x': 5}}
|
||||
|
||||
which is the same format that we encode to with our
|
||||
:meth:`encode_custom` method!
|
||||
@ -163,7 +167,7 @@ from :class:`~bson.binary.Binary` instances:
|
||||
|
||||
>>> from bson.binary import Binary
|
||||
>>> def to_binary(custom):
|
||||
... return Binary(str(custom.x()), 128)
|
||||
... return Binary(str(custom.x()).encode(), 128)
|
||||
...
|
||||
>>> def from_binary(binary):
|
||||
... return Custom(int(binary))
|
||||
@ -209,8 +213,9 @@ seamlessly:
|
||||
|
||||
>>> db.test.insert({"custom": Custom(5)})
|
||||
ObjectId('...')
|
||||
>>> db.test.find_one()
|
||||
{u'_id': ObjectId('...'), u'custom': <Custom object at ...>}
|
||||
>>> pprint.pprint(db.test.find_one())
|
||||
{u'_id': ObjectId('...'),
|
||||
u'custom': <Custom object at ...>}
|
||||
>>> db.test.find_one()["custom"].x()
|
||||
5
|
||||
|
||||
@ -222,5 +227,5 @@ clearing out the manipulators and repeating our
|
||||
.. doctest::
|
||||
|
||||
>>> db = client.custom_type_example
|
||||
>>> db.test.find_one()
|
||||
>>> pprint.pprint(db.test.find_one())
|
||||
{u'_id': ObjectId('...'), u'custom': Binary('5', 128)}
|
||||
|
||||
@ -49,12 +49,13 @@ Using the geospatial index we can find documents near another point:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> import pprint
|
||||
>>> for doc in db.places.find({"loc": {"$near": [3, 6]}}).limit(3):
|
||||
... repr(doc) # doctest: +ELLIPSIS
|
||||
... pprint.pprint(doc)
|
||||
...
|
||||
"{u'loc': [2, 5], u'_id': ObjectId('...')}"
|
||||
"{u'loc': [4, 4], u'_id': ObjectId('...')}"
|
||||
"{u'loc': [1, 2], u'_id': ObjectId('...')}"
|
||||
{u'_id': ObjectId('...'), u'loc': [2, 5]}
|
||||
{u'_id': ObjectId('...'), u'loc': [4, 4]}
|
||||
{u'_id': ObjectId('...'), u'loc': [1, 2]}
|
||||
|
||||
The $maxDistance operator requires the use of :class:`~bson.son.SON`:
|
||||
|
||||
@ -63,11 +64,11 @@ The $maxDistance operator requires the use of :class:`~bson.son.SON`:
|
||||
>>> from bson.son import SON
|
||||
>>> query = {"loc": SON([("$near", [3, 6]), ("$maxDistance", 100)])}
|
||||
>>> for doc in db.places.find(query).limit(3):
|
||||
... repr(doc) # doctest: +ELLIPSIS
|
||||
... pprint.pprint(doc)
|
||||
...
|
||||
"{u'loc': [2, 5], u'_id': ObjectId('...')}"
|
||||
"{u'loc': [4, 4], u'_id': ObjectId('...')}"
|
||||
"{u'loc': [1, 2], u'_id': ObjectId('...')}"
|
||||
{u'_id': ObjectId('...'), u'loc': [2, 5]}
|
||||
{u'_id': ObjectId('...'), u'loc': [4, 4]}
|
||||
{u'_id': ObjectId('...'), u'loc': [1, 2]}
|
||||
|
||||
It's also possible to query for all items within a given rectangle
|
||||
(specified by lower-left and upper-right coordinates):
|
||||
@ -76,10 +77,10 @@ It's also possible to query for all items within a given rectangle
|
||||
|
||||
>>> query = {"loc": {"$within": {"$box": [[2, 2], [5, 6]]}}}
|
||||
>>> for doc in db.places.find(query).sort('_id'):
|
||||
... repr(doc) # doctest: +ELLIPSIS
|
||||
... pprint.pprint(doc)
|
||||
...
|
||||
"{u'loc': [2, 5], u'_id': ObjectId('...')}"
|
||||
"{u'loc': [4, 4], u'_id': ObjectId('...')}"
|
||||
{u'_id': ObjectId('...'), u'loc': [2, 5]}
|
||||
{u'_id': ObjectId('...'), u'loc': [4, 4]}
|
||||
|
||||
Or circle (specified by center point and radius):
|
||||
|
||||
@ -87,11 +88,11 @@ Or circle (specified by center point and radius):
|
||||
|
||||
>>> query = {"loc": {"$within": {"$center": [[0, 0], 6]}}}
|
||||
>>> for doc in db.places.find(query).sort('_id'):
|
||||
... repr(doc) # doctest: +ELLIPSIS
|
||||
... pprint.pprint(doc)
|
||||
...
|
||||
"{u'loc': [2, 5], u'_id': ObjectId('...')}"
|
||||
"{u'loc': [1, 2], u'_id': ObjectId('...')}"
|
||||
"{u'loc': [4, 4], u'_id': ObjectId('...')}"
|
||||
{u'_id': ObjectId('...'), u'loc': [2, 5]}
|
||||
{u'_id': ObjectId('...'), u'loc': [1, 2]}
|
||||
{u'_id': ObjectId('...'), u'loc': [4, 4]}
|
||||
|
||||
geoNear queries are also supported using :class:`~bson.son.SON`::
|
||||
|
||||
|
||||
@ -42,7 +42,7 @@ interface (the :meth:`~gridfs.GridFS.put` and
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> a = fs.put("hello world")
|
||||
>>> a = fs.put(b"hello world")
|
||||
|
||||
:meth:`~gridfs.GridFS.put` creates a new file in GridFS, and returns
|
||||
the value of the file document's ``"_id"`` key. Given that ``"_id"``
|
||||
|
||||
36
doc/faq.rst
36
doc/faq.rst
@ -126,31 +126,25 @@ is displayed:
|
||||
|
||||
PyMongo represents BSON documents as Python dicts by default, and the order
|
||||
of keys in dicts is not defined. That is, a dict declared with the "a" key
|
||||
first is the same, to Python, as one with "b" first:
|
||||
first is the same, to Python, as one with "b" first::
|
||||
|
||||
.. doctest:: key-order
|
||||
|
||||
>>> print {'a': 1.0, 'b': 1.0}
|
||||
>>> print({'a': 1.0, 'b': 1.0})
|
||||
{'a': 1.0, 'b': 1.0}
|
||||
>>> print {'b': 1.0, 'a': 1.0}
|
||||
>>> print({'b': 1.0, 'a': 1.0})
|
||||
{'a': 1.0, 'b': 1.0}
|
||||
|
||||
Therefore, Python dicts are not guaranteed to show keys in the order they are
|
||||
stored in BSON. Here, "a" is shown before "b":
|
||||
stored in BSON. Here, "a" is shown before "b"::
|
||||
|
||||
.. doctest:: key-order
|
||||
|
||||
>>> print collection.find_one()
|
||||
>>> print(collection.find_one())
|
||||
{u'_id': 1.0, u'subdocument': {u'a': 1.0, u'b': 1.0}}
|
||||
|
||||
To preserve order when reading BSON, use the :class:`~bson.son.SON` class,
|
||||
which is a dict that remembers its key order. Now, documents and subdocuments
|
||||
in query results are represented with :class:`~bson.son.SON` objects:
|
||||
|
||||
.. doctest:: key-order
|
||||
in query results are represented with :class:`~bson.son.SON` objects::
|
||||
|
||||
>>> from bson.son import SON
|
||||
>>> print collection.find_one(as_class=SON)
|
||||
>>> print(collection.find_one(as_class=SON))
|
||||
SON([(u'_id', 1.0), (u'subdocument', SON([(u'b', 1.0), (u'a', 1.0)]))])
|
||||
|
||||
The subdocument's actual storage layout is now visible: "b" is before "a".
|
||||
@ -158,25 +152,19 @@ The subdocument's actual storage layout is now visible: "b" is before "a".
|
||||
Because a dict's key order is not defined, you cannot predict how it will be
|
||||
serialized **to** BSON. But MongoDB considers subdocuments equal only if their
|
||||
keys have the same order. So if you use a dict to query on a subdocument it may
|
||||
not match:
|
||||
|
||||
.. doctest:: key-order
|
||||
not match::
|
||||
|
||||
>>> collection.find_one({'subdocument': {'a': 1.0, 'b': 1.0}}) is None
|
||||
True
|
||||
|
||||
Swapping the key order in your query makes no difference:
|
||||
|
||||
.. doctest:: key-order
|
||||
Swapping the key order in your query makes no difference::
|
||||
|
||||
>>> collection.find_one({'subdocument': {'b': 1.0, 'a': 1.0}}) is None
|
||||
True
|
||||
|
||||
... because, as we saw above, Python considers the two dicts the same.
|
||||
|
||||
There are two solutions. First, you can match the subdocument field-by-field:
|
||||
|
||||
.. doctest:: key-order
|
||||
There are two solutions. First, you can match the subdocument field-by-field::
|
||||
|
||||
>>> collection.find_one({'subdocument.a': 1.0,
|
||||
... 'subdocument.b': 1.0})
|
||||
@ -187,9 +175,7 @@ regardless of the order you specify them in Python or the order they are stored
|
||||
in BSON. Additionally, this query now matches subdocuments with additional
|
||||
keys besides "a" and "b", whereas the previous query required an exact match.
|
||||
|
||||
The second solution is to use a :class:`~bson.son.SON` to specify the key order:
|
||||
|
||||
.. doctest:: key-order
|
||||
The second solution is to use a :class:`~bson.son.SON` to specify the key order::
|
||||
|
||||
>>> query = {'subdocument': SON([('b', 1.0), ('a', 1.0)])}
|
||||
>>> collection.find_one(query)
|
||||
|
||||
@ -162,8 +162,13 @@ document from the posts collection:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> posts.find_one()
|
||||
{u'date': datetime.datetime(...), u'text': u'My first blog post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'mongodb', u'python', u'pymongo']}
|
||||
>>> import pprint
|
||||
>>> pprint.pprint(posts.find_one())
|
||||
{u'_id': ObjectId('...'),
|
||||
u'author': u'Mike',
|
||||
u'date': datetime.datetime(...),
|
||||
u'tags': [u'mongodb', u'python', u'pymongo'],
|
||||
u'text': u'My first blog post!'}
|
||||
|
||||
The result is a dictionary matching the one that we inserted previously.
|
||||
|
||||
@ -176,8 +181,12 @@ our results to a document with author "Mike" we do:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> posts.find_one({"author": "Mike"})
|
||||
{u'date': datetime.datetime(...), u'text': u'My first blog post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'mongodb', u'python', u'pymongo']}
|
||||
>>> pprint.pprint(posts.find_one({"author": "Mike"}))
|
||||
{u'_id': ObjectId('...'),
|
||||
u'author': u'Mike',
|
||||
u'date': datetime.datetime(...),
|
||||
u'tags': [u'mongodb', u'python', u'pymongo'],
|
||||
u'text': u'My first blog post!'}
|
||||
|
||||
If we try with a different author, like "Eliot", we'll get no result:
|
||||
|
||||
@ -194,10 +203,14 @@ We can also find a post by its ``_id``, which in our example is an ObjectId:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> post_id
|
||||
ObjectId(...)
|
||||
>>> posts.find_one({"_id": post_id})
|
||||
{u'date': datetime.datetime(...), u'text': u'My first blog post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'mongodb', u'python', u'pymongo']}
|
||||
>>> post_id
|
||||
ObjectId(...)
|
||||
>>> pprint.pprint(posts.find_one({"_id": post_id}))
|
||||
{u'_id': ObjectId('...'),
|
||||
u'author': u'Mike',
|
||||
u'date': datetime.datetime(...),
|
||||
u'tags': [u'mongodb', u'python', u'pymongo'],
|
||||
u'text': u'My first blog post!'}
|
||||
|
||||
Note that an ObjectId is not the same as its string representation:
|
||||
|
||||
@ -282,11 +295,23 @@ document in the ``posts`` collection:
|
||||
.. doctest::
|
||||
|
||||
>>> for post in posts.find():
|
||||
... post
|
||||
... pprint.pprint(post)
|
||||
...
|
||||
{u'date': datetime.datetime(...), u'text': u'My first blog post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'mongodb', u'python', u'pymongo']}
|
||||
{u'date': datetime.datetime(2009, 11, 12, 11, 14), u'text': u'Another post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'bulk', u'insert']}
|
||||
{u'date': datetime.datetime(2009, 11, 10, 10, 45), u'text': u'and pretty easy too!', u'_id': ObjectId('...'), u'author': u'Eliot', u'title': u'MongoDB is fun'}
|
||||
{u'_id': ObjectId('...'),
|
||||
u'author': u'Mike',
|
||||
u'date': datetime.datetime(...),
|
||||
u'tags': [u'mongodb', u'python', u'pymongo'],
|
||||
u'text': u'My first blog post!'}
|
||||
{u'_id': ObjectId('...'),
|
||||
u'author': u'Mike',
|
||||
u'date': datetime.datetime(...),
|
||||
u'tags': [u'bulk', u'insert'],
|
||||
u'text': u'Another post!'}
|
||||
{u'_id': ObjectId('...'),
|
||||
u'author': u'Eliot',
|
||||
u'date': datetime.datetime(...),
|
||||
u'text': u'and pretty easy too!',
|
||||
u'title': u'MongoDB is fun'}
|
||||
|
||||
Just like we did with :meth:`~pymongo.collection.Collection.find_one`,
|
||||
we can pass a document to :meth:`~pymongo.collection.Collection.find`
|
||||
@ -296,10 +321,18 @@ author is "Mike":
|
||||
.. doctest::
|
||||
|
||||
>>> for post in posts.find({"author": "Mike"}):
|
||||
... post
|
||||
... pprint.pprint(post)
|
||||
...
|
||||
{u'date': datetime.datetime(...), u'text': u'My first blog post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'mongodb', u'python', u'pymongo']}
|
||||
{u'date': datetime.datetime(2009, 11, 12, 11, 14), u'text': u'Another post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'bulk', u'insert']}
|
||||
{u'_id': ObjectId('...'),
|
||||
u'author': u'Mike',
|
||||
u'date': datetime.datetime(...),
|
||||
u'tags': [u'mongodb', u'python', u'pymongo'],
|
||||
u'text': u'My first blog post!'}
|
||||
{u'_id': ObjectId('...'),
|
||||
u'author': u'Mike',
|
||||
u'date': datetime.datetime(...),
|
||||
u'tags': [u'bulk', u'insert'],
|
||||
u'text': u'Another post!'}
|
||||
|
||||
Counting
|
||||
--------
|
||||
@ -331,10 +364,18 @@ than a certain date, but also sort the results by author:
|
||||
|
||||
>>> d = datetime.datetime(2009, 11, 12, 12)
|
||||
>>> for post in posts.find({"date": {"$lt": d}}).sort("author"):
|
||||
... print post
|
||||
... pprint.pprint(post)
|
||||
...
|
||||
{u'date': datetime.datetime(2009, 11, 10, 10, 45), u'text': u'and pretty easy too!', u'_id': ObjectId('...'), u'author': u'Eliot', u'title': u'MongoDB is fun'}
|
||||
{u'date': datetime.datetime(2009, 11, 12, 11, 14), u'text': u'Another post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'bulk', u'insert']}
|
||||
{u'_id': ObjectId('...'),
|
||||
u'author': u'Eliot',
|
||||
u'date': datetime.datetime(...),
|
||||
u'text': u'and pretty easy too!',
|
||||
u'title': u'MongoDB is fun'}
|
||||
{u'_id': ObjectId('...'),
|
||||
u'author': u'Mike',
|
||||
u'date': datetime.datetime(...),
|
||||
u'tags': [u'bulk', u'insert'],
|
||||
u'text': u'Another post!'}
|
||||
|
||||
Here we use the special ``"$lt"`` operator to do a range query, and
|
||||
also call :meth:`~pymongo.cursor.Cursor.sort` to sort the results
|
||||
@ -355,8 +396,8 @@ First, we'll need to create the index:
|
||||
|
||||
>>> result = db.profiles.create_index([('user_id', pymongo.ASCENDING)],
|
||||
... unique=True)
|
||||
>>> list(db.profiles.index_information())
|
||||
[u'user_id_1', u'_id_']
|
||||
>>> sorted(list(db.profiles.index_information()))
|
||||
[u'_id_', u'user_id_1']
|
||||
|
||||
Notice that we have two indexes now: one is the index on ``_id`` that MongoDB
|
||||
creates automatically, and the other is the index on ``user_id`` we just
|
||||
|
||||
@ -645,12 +645,13 @@ class Collection(common.BaseObject):
|
||||
|
||||
>>> db.test.insert({"x": "y", "a": "b"})
|
||||
ObjectId('...')
|
||||
>>> list(db.test.find())
|
||||
[{u'a': u'b', u'x': u'y', u'_id': ObjectId('...')}]
|
||||
>>> import pprint
|
||||
>>> pprint.pprint(list(db.test.find()))
|
||||
[{u'_id': ObjectId('...'), u'a': u'b', u'x': u'y'}]
|
||||
>>> db.test.update({"x": "y"}, {"$set": {"a": "c"}})
|
||||
{...}
|
||||
>>> list(db.test.find())
|
||||
[{u'a': u'c', u'x': u'y', u'_id': ObjectId('...')}]
|
||||
>>> pprint.pprint(list(db.test.find()))
|
||||
[{u'_id': ObjectId('...'), u'a': u'c', u'x': u'y'}]
|
||||
|
||||
:Parameters:
|
||||
- `spec`: a ``dict`` or :class:`~bson.son.SON` instance
|
||||
|
||||
75
setup.py
75
setup.py
@ -2,7 +2,6 @@ import glob
|
||||
import os
|
||||
import platform
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
@ -22,17 +21,24 @@ except ImportError:
|
||||
# we have to.
|
||||
try:
|
||||
from setuptools import setup
|
||||
from setuptools.command.build_py import build_py
|
||||
except ImportError:
|
||||
from ez_setup import use_setuptools
|
||||
use_setuptools()
|
||||
from setuptools import setup
|
||||
from setuptools.command.build_py import build_py
|
||||
|
||||
from distutils.cmd import Command
|
||||
from distutils.command.build_ext import build_ext
|
||||
from distutils.errors import CCompilerError
|
||||
from distutils.errors import DistutilsPlatformError, DistutilsExecError
|
||||
from distutils.core import Extension
|
||||
|
||||
try:
|
||||
import sphinx
|
||||
_HAVE_SPHINX = True
|
||||
except ImportError:
|
||||
_HAVE_SPHINX = False
|
||||
|
||||
version = "2.9.4.dev0"
|
||||
|
||||
f = open("README.rst")
|
||||
@ -88,22 +94,70 @@ if "test" in sys.argv or "nosetests" in sys.argv:
|
||||
should_run_tests = True
|
||||
|
||||
|
||||
class doc(Command):
|
||||
class doc(build_py):
|
||||
|
||||
description = "generate or test documentation"
|
||||
|
||||
user_options = [("test", "t",
|
||||
"run doctests instead of generating documentation")]
|
||||
build_py.user_options.append(
|
||||
("test", "t", "run doctests instead of generating documentation"))
|
||||
|
||||
boolean_options = ["test"]
|
||||
build_py.boolean_options.append('test')
|
||||
|
||||
def initialize_options(self):
|
||||
self.test = False
|
||||
|
||||
def finalize_options(self):
|
||||
pass
|
||||
build_py.initialize_options(self)
|
||||
|
||||
def run(self):
|
||||
if not _HAVE_SPHINX:
|
||||
raise RuntimeError(
|
||||
"You must install Sphinx to build or test the documentation.")
|
||||
|
||||
if PY3:
|
||||
import doctest
|
||||
from doctest import OutputChecker as _OutputChecker
|
||||
|
||||
# Match u or U (possibly followed by r or R), removing it.
|
||||
# r/R can follow u/U but not precede it. Don't match the
|
||||
# single character string 'u' or 'U'.
|
||||
_u_literal_re = re.compile(
|
||||
r"(\W|^)(?<![\'\"])[uU]([rR]?[\'\"])", re.UNICODE)
|
||||
# Match b or B (possibly followed by r or R), removing.
|
||||
# r/R can follow b/B but not precede it. Don't match the
|
||||
# single character string 'b' or 'B'.
|
||||
_b_literal_re = re.compile(
|
||||
r"(\W|^)(?<![\'\"])[bB]([rR]?[\'\"])", re.UNICODE)
|
||||
|
||||
class _StringPrefixFixer(_OutputChecker):
|
||||
|
||||
def check_output(self, want, got, optionflags):
|
||||
if sys.version_info[0] >= 3:
|
||||
# The docstrings are written with python 2.x in mind.
|
||||
# To make the doctests pass in python 3 we have to
|
||||
# strip the 'u' prefix from the expected results. The
|
||||
# actual results won't have that prefix.
|
||||
want = re.sub(_u_literal_re, r'\1\2', want)
|
||||
# We also have to strip the 'b' prefix from the actual
|
||||
# results since python 2.x expected results won't have
|
||||
# that prefix.
|
||||
got = re.sub(_b_literal_re, r'\1\2', got)
|
||||
return super(
|
||||
_StringPrefixFixer, self).check_output(
|
||||
want, got, optionflags)
|
||||
|
||||
def output_difference(self, example, got, optionflags):
|
||||
if sys.version_info[0] >= 3:
|
||||
example.want = re.sub(
|
||||
_u_literal_re, r'\1\2', example.want)
|
||||
got = re.sub(_b_literal_re, r'\1\2', got)
|
||||
return super(
|
||||
_StringPrefixFixer, self).output_difference(
|
||||
example, got, optionflags)
|
||||
|
||||
doctest.OutputChecker = _StringPrefixFixer
|
||||
|
||||
# No need to run build_py for python 2.x.
|
||||
build_py.run(self)
|
||||
|
||||
if self.test:
|
||||
path = "doc/_build/doctest"
|
||||
mode = "doctest"
|
||||
@ -116,8 +170,7 @@ class doc(Command):
|
||||
except:
|
||||
pass
|
||||
|
||||
status = subprocess.call(["sphinx-build", "-E",
|
||||
"-b", mode, "doc", path])
|
||||
status = sphinx.build_main(["-E", "-b", mode, "doc", path])
|
||||
|
||||
if status:
|
||||
raise RuntimeError("documentation step '%s' failed" % (mode,))
|
||||
|
||||
Loading…
Reference in New Issue
Block a user