~ubuntu-branches/ubuntu/wily/pymongo/wily-proposed

« back to all changes in this revision

Viewing changes to test/test_cursor.py

  • Committer: Package Import Robot
  • Author(s): Federico Ceratto
  • Date: 2015-04-26 22:43:13 UTC
  • mfrom: (24.1.5 sid)
  • Revision ID: package-import@ubuntu.com-20150426224313-0hga2jphvf0rrmfe
Tags: 3.0.1-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright 2009-2014 MongoDB, Inc.
 
1
# Copyright 2009-2015 MongoDB, Inc.
2
2
#
3
3
# Licensed under the Apache License, Version 2.0 (the "License");
4
4
# you may not use this file except in compliance with the License.
18
18
import random
19
19
import re
20
20
import sys
21
 
import unittest
22
 
import warnings
23
21
 
24
22
sys.path[0:0] = [""]
25
23
 
26
 
from nose.plugins.skip import SkipTest
27
 
 
28
24
from bson.code import Code
 
25
from bson.py3compat import u, PY3
29
26
from bson.son import SON
30
 
from pymongo import (ASCENDING,
 
27
from pymongo import (MongoClient,
 
28
                     ASCENDING,
31
29
                     DESCENDING,
32
30
                     ALL,
33
31
                     OFF)
34
32
from pymongo.command_cursor import CommandCursor
 
33
from pymongo.cursor import CursorType
35
34
from pymongo.cursor_manager import CursorManager
36
 
from pymongo.database import Database
37
35
from pymongo.errors import (InvalidOperation,
38
36
                            OperationFailure,
39
37
                            ExecutionTimeout)
40
 
from test import version
41
 
from test.test_client import get_client
42
 
from test.utils import (catch_warnings, is_mongos,
43
 
                        get_command_line, server_started_with_auth)
44
 
 
45
 
 
46
 
class TestCursor(unittest.TestCase):
47
 
 
48
 
    def setUp(self):
49
 
        self.client = get_client()
50
 
        self.db = Database(self.client, "pymongo_test")
51
 
 
52
 
    def tearDown(self):
53
 
        self.db = None
54
 
 
 
38
from test import (client_context,
 
39
                  SkipTest,
 
40
                  unittest,
 
41
                  host,
 
42
                  port,
 
43
                  IntegrationTest)
 
44
from test.utils import server_started_with_auth
 
45
 
 
46
if PY3:
 
47
    long = int
 
48
 
 
49
 
 
50
class TestCursorNoConnect(unittest.TestCase):
 
51
 
 
52
    @classmethod
 
53
    def setUpClass(cls):
 
54
        client = MongoClient(host, port, connect=False)
 
55
        cls.db = client.test
 
56
 
 
57
    def test_deepcopy_cursor_littered_with_regexes(self):
 
58
        cursor = self.db.test.find({
 
59
            "x": re.compile("^hmmm.*"),
 
60
            "y": [re.compile("^hmm.*")],
 
61
            "z": {"a": [re.compile("^hm.*")]},
 
62
            re.compile("^key.*"): {"a": [re.compile("^hm.*")]}})
 
63
 
 
64
        cursor2 = copy.deepcopy(cursor)
 
65
        self.assertEqual(cursor._Cursor__spec, cursor2._Cursor__spec)
 
66
 
 
67
    def test_add_remove_option(self):
 
68
        cursor = self.db.test.find()
 
69
        self.assertEqual(0, cursor._Cursor__query_flags)
 
70
        cursor.add_option(2)
 
71
        cursor2 = self.db.test.find(cursor_type=CursorType.TAILABLE)
 
72
        self.assertEqual(2, cursor2._Cursor__query_flags)
 
73
        self.assertEqual(cursor._Cursor__query_flags,
 
74
                         cursor2._Cursor__query_flags)
 
75
        cursor.add_option(32)
 
76
        cursor2 = self.db.test.find(cursor_type=CursorType.TAILABLE_AWAIT)
 
77
        self.assertEqual(34, cursor2._Cursor__query_flags)
 
78
        self.assertEqual(cursor._Cursor__query_flags,
 
79
                         cursor2._Cursor__query_flags)
 
80
        cursor.add_option(128)
 
81
        cursor2 = self.db.test.find(
 
82
            cursor_type=CursorType.TAILABLE_AWAIT).add_option(128)
 
83
        self.assertEqual(162, cursor2._Cursor__query_flags)
 
84
        self.assertEqual(cursor._Cursor__query_flags,
 
85
                         cursor2._Cursor__query_flags)
 
86
 
 
87
        self.assertEqual(162, cursor._Cursor__query_flags)
 
88
        cursor.add_option(128)
 
89
        self.assertEqual(162, cursor._Cursor__query_flags)
 
90
 
 
91
        cursor.remove_option(128)
 
92
        cursor2 = self.db.test.find(cursor_type=CursorType.TAILABLE_AWAIT)
 
93
        self.assertEqual(34, cursor2._Cursor__query_flags)
 
94
        self.assertEqual(cursor._Cursor__query_flags,
 
95
                         cursor2._Cursor__query_flags)
 
96
        cursor.remove_option(32)
 
97
        cursor2 = self.db.test.find(cursor_type=CursorType.TAILABLE)
 
98
        self.assertEqual(2, cursor2._Cursor__query_flags)
 
99
        self.assertEqual(cursor._Cursor__query_flags,
 
100
                         cursor2._Cursor__query_flags)
 
101
 
 
102
        self.assertEqual(2, cursor._Cursor__query_flags)
 
103
        cursor.remove_option(32)
 
104
        self.assertEqual(2, cursor._Cursor__query_flags)
 
105
 
 
106
        # Timeout
 
107
        cursor = self.db.test.find(no_cursor_timeout=True)
 
108
        self.assertEqual(16, cursor._Cursor__query_flags)
 
109
        cursor2 = self.db.test.find().add_option(16)
 
110
        self.assertEqual(cursor._Cursor__query_flags,
 
111
                         cursor2._Cursor__query_flags)
 
112
        cursor.remove_option(16)
 
113
        self.assertEqual(0, cursor._Cursor__query_flags)
 
114
 
 
115
        # Tailable / Await data
 
116
        cursor = self.db.test.find(cursor_type=CursorType.TAILABLE_AWAIT)
 
117
        self.assertEqual(34, cursor._Cursor__query_flags)
 
118
        cursor2 = self.db.test.find().add_option(34)
 
119
        self.assertEqual(cursor._Cursor__query_flags,
 
120
                         cursor2._Cursor__query_flags)
 
121
        cursor.remove_option(32)
 
122
        self.assertEqual(2, cursor._Cursor__query_flags)
 
123
 
 
124
        # Exhaust - which mongos doesn't support
 
125
        cursor = self.db.test.find(cursor_type=CursorType.EXHAUST)
 
126
        self.assertEqual(64, cursor._Cursor__query_flags)
 
127
        cursor2 = self.db.test.find().add_option(64)
 
128
        self.assertEqual(cursor._Cursor__query_flags,
 
129
                         cursor2._Cursor__query_flags)
 
130
        self.assertTrue(cursor._Cursor__exhaust)
 
131
        cursor.remove_option(64)
 
132
        self.assertEqual(0, cursor._Cursor__query_flags)
 
133
        self.assertFalse(cursor._Cursor__exhaust)
 
134
 
 
135
        # Partial
 
136
        cursor = self.db.test.find(allow_partial_results=True)
 
137
        self.assertEqual(128, cursor._Cursor__query_flags)
 
138
        cursor2 = self.db.test.find().add_option(128)
 
139
        self.assertEqual(cursor._Cursor__query_flags,
 
140
                         cursor2._Cursor__query_flags)
 
141
        cursor.remove_option(128)
 
142
        self.assertEqual(0, cursor._Cursor__query_flags)
 
143
 
 
144
 
 
145
class TestCursor(IntegrationTest):
 
146
 
 
147
    @client_context.require_version_min(2, 5, 3, -1)
55
148
    def test_max_time_ms(self):
56
 
        if not version.at_least(self.db.connection, (2, 5, 3, -1)):
57
 
            raise SkipTest("MaxTimeMS requires MongoDB >= 2.5.3")
58
 
 
59
149
        db = self.db
60
150
        db.pymongo_test.drop()
61
151
        coll = db.pymongo_test
62
152
        self.assertRaises(TypeError, coll.find().max_time_ms, 'foo')
63
 
        coll.insert({"amalia": 1})
64
 
        coll.insert({"amalia": 2})
 
153
        coll.insert_one({"amalia": 1})
 
154
        coll.insert_one({"amalia": 2})
65
155
 
66
156
        coll.find().max_time_ms(None)
67
 
        coll.find().max_time_ms(1L)
 
157
        coll.find().max_time_ms(long(1))
68
158
 
69
159
        cursor = coll.find().max_time_ms(999)
70
160
        self.assertEqual(999, cursor._Cursor__max_time_ms)
79
169
 
80
170
        self.assertTrue(coll.find_one(max_time_ms=1000))
81
171
 
82
 
        if "enableTestCommands=1" in get_command_line(self.client)["argv"]:
 
172
        client = self.client
 
173
        if "enableTestCommands=1" in client_context.cmd_line['argv']:
83
174
            # Cursor parses server timeout error in response to initial query.
84
 
            self.client.admin.command("configureFailPoint",
85
 
                                      "maxTimeAlwaysTimeOut",
86
 
                                      mode="alwaysOn")
 
175
            client.admin.command("configureFailPoint",
 
176
                                 "maxTimeAlwaysTimeOut",
 
177
                                 mode="alwaysOn")
87
178
            try:
88
179
                cursor = coll.find().max_time_ms(1)
89
180
                try:
90
 
                    cursor.next()
 
181
                    next(cursor)
91
182
                except ExecutionTimeout:
92
183
                    pass
93
184
                else:
95
186
                self.assertRaises(ExecutionTimeout,
96
187
                                  coll.find_one, max_time_ms=1)
97
188
            finally:
98
 
                self.client.admin.command("configureFailPoint",
99
 
                                          "maxTimeAlwaysTimeOut",
100
 
                                          mode="off")
 
189
                client.admin.command("configureFailPoint",
 
190
                                     "maxTimeAlwaysTimeOut",
 
191
                                     mode="off")
101
192
 
 
193
    @client_context.require_version_min(2, 5, 3, -1)
 
194
    @client_context.require_test_commands
102
195
    def test_max_time_ms_getmore(self):
103
196
        # Test that Cursor handles server timeout error in response to getmore.
104
 
        if "enableTestCommands=1" not in get_command_line(self.client)["argv"]:
105
 
            raise SkipTest("Need test commands enabled")
106
 
 
107
 
        if not version.at_least(self.db.connection, (2, 5, 3, -1)):
108
 
            raise SkipTest("MaxTimeMS requires MongoDB >= 2.5.3")
109
 
 
110
197
        coll = self.db.pymongo_test
111
 
        coll.insert({} for _ in range(200))
 
198
        coll.insert_many([{} for _ in range(200)])
112
199
        cursor = coll.find().max_time_ms(100)
113
200
 
114
201
        # Send initial query before turning on failpoint.
115
 
        cursor.next()
 
202
        next(cursor)
116
203
        self.client.admin.command("configureFailPoint",
117
204
                                  "maxTimeAlwaysTimeOut",
118
205
                                  mode="alwaysOn")
131
218
 
132
219
    def test_explain(self):
133
220
        a = self.db.test.find()
 
221
        a.explain()
 
222
        for _ in a:
 
223
            break
134
224
        b = a.explain()
135
 
        for _ in a:
136
 
            break
137
 
        c = a.explain()
138
 
        del b["millis"]
139
 
        b.pop("oldPlan", None)
140
 
        del c["millis"]
141
 
        c.pop("oldPlan", None)
142
 
        self.assertEqual(b, c)
143
 
        self.assertTrue("cursor" in b)
 
225
        # "cursor" pre MongoDB 2.7.6, "executionStats" post
 
226
        self.assertTrue("cursor" in b or "executionStats" in b)
144
227
 
145
228
    def test_hint(self):
146
229
        db = self.db
147
230
        self.assertRaises(TypeError, db.test.find().hint, 5.5)
148
231
        db.test.drop()
149
232
 
150
 
        for i in range(100):
151
 
            db.test.insert({"num": i, "foo": i})
 
233
        db.test.insert_many([{"num": i, "foo": i} for i in range(100)])
152
234
 
153
235
        self.assertRaises(OperationFailure,
154
236
                          db.test.find({"num": 17, "foo": 17})
157
239
                          db.test.find({"num": 17, "foo": 17})
158
240
                          .hint([("foo", ASCENDING)]).explain)
159
241
 
160
 
        index = db.test.create_index("num")
 
242
        spec = [("num", DESCENDING)]
 
243
        index = db.test.create_index(spec)
161
244
 
162
 
        spec = [("num", ASCENDING)]
163
 
        self.assertEqual(db.test.find({}).explain()["cursor"], "BasicCursor")
164
 
        self.assertEqual(db.test.find({}).hint(spec).explain()["cursor"],
165
 
                         "BtreeCursor %s" % index)
166
 
        self.assertEqual(db.test.find({}).hint(spec).hint(None)
167
 
                         .explain()["cursor"],
168
 
                         "BasicCursor")
 
245
        first = next(db.test.find())
 
246
        self.assertEqual(0, first.get('num'))
 
247
        first = next(db.test.find().hint(spec))
 
248
        self.assertEqual(99, first.get('num'))
169
249
        self.assertRaises(OperationFailure,
170
250
                          db.test.find({"num": 17, "foo": 17})
171
251
                          .hint([("foo", ASCENDING)]).explain)
176
256
            break
177
257
        self.assertRaises(InvalidOperation, a.hint, spec)
178
258
 
179
 
        self.assertRaises(TypeError, db.test.find().hint, index)
 
259
    def test_hint_by_name(self):
 
260
        db = self.db
 
261
        db.test.drop()
 
262
 
 
263
        db.test.insert_many([{"i": i} for i in range(100)])
 
264
 
 
265
        db.test.create_index([('i', DESCENDING)], name='fooindex')
 
266
        first = next(db.test.find())
 
267
        self.assertEqual(0, first.get('i'))
 
268
        first = next(db.test.find().hint('fooindex'))
 
269
        self.assertEqual(99, first.get('i'))
180
270
 
181
271
    def test_limit(self):
182
272
        db = self.db
184
274
        self.assertRaises(TypeError, db.test.find().limit, None)
185
275
        self.assertRaises(TypeError, db.test.find().limit, "hello")
186
276
        self.assertRaises(TypeError, db.test.find().limit, 5.5)
187
 
        self.assertTrue(db.test.find().limit(5L))
 
277
        self.assertTrue(db.test.find().limit(long(5)))
188
278
 
189
279
        db.test.drop()
190
 
        for i in range(100):
191
 
            db.test.save({"x": i})
 
280
        db.test.insert_many([{"x": i} for i in range(100)])
192
281
 
193
282
        count = 0
194
283
        for _ in db.test.find():
229
318
    def test_max(self):
230
319
        db = self.db
231
320
        db.test.drop()
232
 
        db.test.ensure_index([("j", ASCENDING)])
 
321
        db.test.create_index([("j", ASCENDING)])
233
322
 
234
 
        for j in range(10):
235
 
            db.test.insert({"j": j, "k": j})
 
323
        db.test.insert_many([{"j": j, "k": j} for j in range(10)])
236
324
 
237
325
        cursor = db.test.find().max([("j", 3)])
238
326
        self.assertEqual(len(list(cursor)), 3)
242
330
        self.assertEqual(len(list(cursor)), 3)
243
331
 
244
332
        # Compound index.
245
 
        db.test.ensure_index([("j", ASCENDING), ("k", ASCENDING)])
 
333
        db.test.create_index([("j", ASCENDING), ("k", ASCENDING)])
246
334
        cursor = db.test.find().max([("j", 3), ("k", 3)])
247
335
        self.assertEqual(len(list(cursor)), 3)
248
336
 
260
348
    def test_min(self):
261
349
        db = self.db
262
350
        db.test.drop()
263
 
        db.test.ensure_index([("j", ASCENDING)])
 
351
        db.test.create_index([("j", ASCENDING)])
264
352
 
265
 
        for j in range(10):
266
 
            db.test.insert({"j": j, "k": j})
 
353
        db.test.insert_many([{"j": j, "k": j} for j in range(10)])
267
354
 
268
355
        cursor = db.test.find().min([("j", 3)])
269
356
        self.assertEqual(len(list(cursor)), 7)
273
360
        self.assertEqual(len(list(cursor)), 7)
274
361
 
275
362
        # Compound index.
276
 
        db.test.ensure_index([("j", ASCENDING), ("k", ASCENDING)])
 
363
        db.test.create_index([("j", ASCENDING), ("k", ASCENDING)])
277
364
        cursor = db.test.find().min([("j", 3), ("k", 3)])
278
365
        self.assertEqual(len(list(cursor)), 7)
279
366
 
291
378
    def test_batch_size(self):
292
379
        db = self.db
293
380
        db.test.drop()
294
 
        for x in range(200):
295
 
            db.test.save({"x": x})
 
381
        db.test.insert_many([{"x": x} for x in range(200)])
296
382
 
297
383
        self.assertRaises(TypeError, db.test.find().batch_size, None)
298
384
        self.assertRaises(TypeError, db.test.find().batch_size, "hello")
299
385
        self.assertRaises(TypeError, db.test.find().batch_size, 5.5)
300
386
        self.assertRaises(ValueError, db.test.find().batch_size, -1)
301
 
        self.assertTrue(db.test.find().batch_size(5L))
 
387
        self.assertTrue(db.test.find().batch_size(long(5)))
302
388
        a = db.test.find()
303
389
        for _ in a:
304
390
            break
334
420
    def test_limit_and_batch_size(self):
335
421
        db = self.db
336
422
        db.test.drop()
337
 
        for x in range(500):
338
 
            db.test.save({"x": x})
 
423
        db.test.insert_many([{"x": x} for x in range(500)])
339
424
 
340
425
        curs = db.test.find().limit(0).batch_size(10)
341
 
        curs.next()
 
426
        next(curs)
 
427
        self.assertEqual(10, curs._Cursor__retrieved)
 
428
 
 
429
        curs = db.test.find(limit=0, batch_size=10)
 
430
        next(curs)
342
431
        self.assertEqual(10, curs._Cursor__retrieved)
343
432
 
344
433
        curs = db.test.find().limit(-2).batch_size(0)
345
 
        curs.next()
 
434
        next(curs)
 
435
        self.assertEqual(2, curs._Cursor__retrieved)
 
436
 
 
437
        curs = db.test.find(limit=-2, batch_size=0)
 
438
        next(curs)
346
439
        self.assertEqual(2, curs._Cursor__retrieved)
347
440
 
348
441
        curs = db.test.find().limit(-4).batch_size(5)
349
 
        curs.next()
 
442
        next(curs)
 
443
        self.assertEqual(4, curs._Cursor__retrieved)
 
444
 
 
445
        curs = db.test.find(limit=-4, batch_size=5)
 
446
        next(curs)
350
447
        self.assertEqual(4, curs._Cursor__retrieved)
351
448
 
352
449
        curs = db.test.find().limit(50).batch_size(500)
353
 
        curs.next()
 
450
        next(curs)
 
451
        self.assertEqual(50, curs._Cursor__retrieved)
 
452
 
 
453
        curs = db.test.find(limit=50, batch_size=500)
 
454
        next(curs)
354
455
        self.assertEqual(50, curs._Cursor__retrieved)
355
456
 
356
457
        curs = db.test.find().batch_size(500)
357
 
        curs.next()
 
458
        next(curs)
 
459
        self.assertEqual(500, curs._Cursor__retrieved)
 
460
 
 
461
        curs = db.test.find(batch_size=500)
 
462
        next(curs)
358
463
        self.assertEqual(500, curs._Cursor__retrieved)
359
464
 
360
465
        curs = db.test.find().limit(50)
361
 
        curs.next()
 
466
        next(curs)
 
467
        self.assertEqual(50, curs._Cursor__retrieved)
 
468
 
 
469
        curs = db.test.find(limit=50)
 
470
        next(curs)
362
471
        self.assertEqual(50, curs._Cursor__retrieved)
363
472
 
364
473
        # these two might be shaky, as the default
366
475
        # or 1MB (whichever is smaller) is default
367
476
        # for queries without ntoreturn
368
477
        curs = db.test.find()
369
 
        curs.next()
 
478
        next(curs)
370
479
        self.assertEqual(101, curs._Cursor__retrieved)
371
480
 
372
481
        curs = db.test.find().limit(0).batch_size(0)
373
 
        curs.next()
 
482
        next(curs)
 
483
        self.assertEqual(101, curs._Cursor__retrieved)
 
484
 
 
485
        curs = db.test.find(limit=0, batch_size=0)
 
486
        next(curs)
374
487
        self.assertEqual(101, curs._Cursor__retrieved)
375
488
 
376
489
    def test_skip(self):
380
493
        self.assertRaises(TypeError, db.test.find().skip, "hello")
381
494
        self.assertRaises(TypeError, db.test.find().skip, 5.5)
382
495
        self.assertRaises(ValueError, db.test.find().skip, -5)
383
 
        self.assertTrue(db.test.find().skip(5L))
 
496
        self.assertTrue(db.test.find().skip(long(5)))
384
497
 
385
498
        db.drop_collection("test")
386
499
 
387
 
        for i in range(100):
388
 
            db.test.save({"x": i})
 
500
        db.test.insert_many([{"x": i} for i in range(100)])
389
501
 
390
502
        for i in db.test.find():
391
503
            self.assertEqual(i["x"], 0)
431
543
 
432
544
        db.test.drop()
433
545
 
434
 
        unsort = range(10)
 
546
        unsort = list(range(10))
435
547
        random.shuffle(unsort)
436
548
 
437
 
        for i in unsort:
438
 
            db.test.save({"x": i})
 
549
        db.test.insert_many([{"x": i} for i in unsort])
439
550
 
440
551
        asc = [i["x"] for i in db.test.find().sort("x", ASCENDING)]
441
 
        self.assertEqual(asc, range(10))
 
552
        self.assertEqual(asc, list(range(10)))
442
553
        asc = [i["x"] for i in db.test.find().sort("x")]
443
 
        self.assertEqual(asc, range(10))
 
554
        self.assertEqual(asc, list(range(10)))
444
555
        asc = [i["x"] for i in db.test.find().sort([("x", ASCENDING)])]
445
 
        self.assertEqual(asc, range(10))
 
556
        self.assertEqual(asc, list(range(10)))
446
557
 
447
 
        expect = range(10)
448
 
        expect.reverse()
 
558
        expect = list(reversed(range(10)))
449
559
        desc = [i["x"] for i in db.test.find().sort("x", DESCENDING)]
450
560
        self.assertEqual(desc, expect)
451
561
        desc = [i["x"] for i in db.test.find().sort([("x", DESCENDING)])]
460
570
 
461
571
        db.test.drop()
462
572
        for (a, b) in shuffled:
463
 
            db.test.save({"a": a, "b": b})
 
573
            db.test.insert_one({"a": a, "b": b})
464
574
 
465
575
        result = [(i["a"], i["b"]) for i in
466
576
                  db.test.find().sort([("b", DESCENDING),
479
589
 
480
590
        self.assertEqual(0, db.test.find().count())
481
591
 
482
 
        for i in range(10):
483
 
            db.test.save({"x": i})
 
592
        db.test.insert_many([{"x": i} for i in range(10)])
484
593
 
485
594
        self.assertEqual(10, db.test.find().count())
486
595
        self.assertTrue(isinstance(db.test.find().count(), int))
498
607
 
499
608
        self.assertEqual(0, db.test.acollectionthatdoesntexist.find().count())
500
609
 
 
610
    def test_count_with_hint(self):
 
611
        collection = self.db.test
 
612
        collection.drop()
 
613
 
 
614
        collection.insert_many([{'i': 1}, {'i': 2}])
 
615
        self.assertEqual(2, collection.find().count())
 
616
 
 
617
        collection.create_index([('i', 1)])
 
618
 
 
619
        self.assertEqual(1, collection.find({'i': 1}).hint("_id_").count())
 
620
        self.assertEqual(2, collection.find().hint("_id_").count())
 
621
 
 
622
        if client_context.version.at_least(2, 6, 0):
 
623
            # Count supports hint
 
624
            self.assertRaises(OperationFailure,
 
625
                              collection.find({'i': 1}).hint("BAD HINT").count)
 
626
        else:
 
627
            # Hint is ignored
 
628
            self.assertEqual(
 
629
                1, collection.find({'i': 1}).hint("BAD HINT").count())
 
630
 
 
631
        # Create a sparse index which should have no entries.
 
632
        collection.create_index([('x', 1)], sparse=True)
 
633
 
 
634
        if client_context.version.at_least(2, 6, 0):
 
635
            # Count supports hint
 
636
            self.assertEqual(0, collection.find({'i': 1}).hint("x_1").count())
 
637
            self.assertEqual(
 
638
                0, collection.find({'i': 1}).hint([("x", 1)]).count())
 
639
        else:
 
640
            # Hint is ignored
 
641
            self.assertEqual(1, collection.find({'i': 1}).hint("x_1").count())
 
642
            self.assertEqual(
 
643
                1, collection.find({'i': 1}).hint([("x", 1)]).count())
 
644
 
 
645
        self.assertEqual(2, collection.find().hint("x_1").count())
 
646
        self.assertEqual(2, collection.find().hint([("x", 1)]).count())
 
647
 
501
648
    def test_where(self):
502
649
        db = self.db
503
650
        db.test.drop()
507
654
        self.assertRaises(TypeError, a.where, None)
508
655
        self.assertRaises(TypeError, a.where, {})
509
656
 
510
 
        for i in range(10):
511
 
            db.test.save({"x": i})
 
657
        db.test.insert_many([{"x": i} for i in range(10)])
512
658
 
513
659
        self.assertEqual(3, len(list(db.test.find().where('this.x < 3'))))
514
660
        self.assertEqual(3,
519
665
 
520
666
        self.assertEqual(3, db.test.find().where('this.x < 3').count())
521
667
        self.assertEqual(10, db.test.find().count())
522
 
        self.assertEqual(3, db.test.find().where(u'this.x < 3').count())
 
668
        self.assertEqual(3, db.test.find().where(u('this.x < 3')).count())
523
669
        self.assertEqual([0, 1, 2],
524
670
                         [a["x"] for a in
525
671
                          db.test.find().where('this.x < 3')])
540
686
        self.assertRaises(InvalidOperation, a.where, 'this.x < 3')
541
687
 
542
688
    def test_rewind(self):
543
 
        self.db.test.save({"x": 1})
544
 
        self.db.test.save({"x": 2})
545
 
        self.db.test.save({"x": 3})
 
689
        self.db.test.insert_many([{"x": i} for i in range(1, 4)])
546
690
 
547
691
        cursor = self.db.test.find().limit(2)
548
692
 
574
718
        self.assertEqual(cursor, cursor.rewind())
575
719
 
576
720
    def test_clone(self):
577
 
        self.db.test.save({"x": 1})
578
 
        self.db.test.save({"x": 2})
579
 
        self.db.test.save({"x": 3})
 
721
        self.db.test.insert_many([{"x": i} for i in range(1, 4)])
580
722
 
581
723
        cursor = self.db.test.find().limit(2)
582
724
 
611
753
 
612
754
        self.assertNotEqual(cursor, cursor.clone())
613
755
 
614
 
        class MyClass(dict):
615
 
            pass
616
 
 
617
 
        cursor = self.db.test.find(as_class=MyClass)
618
 
        for e in cursor:
619
 
            self.assertEqual(type(MyClass()), type(e))
620
 
        cursor = self.db.test.find(as_class=MyClass)
621
 
        self.assertEqual(type(MyClass()), type(cursor[0]))
622
 
 
623
756
        # Just test attributes
624
757
        cursor = self.db.test.find({"x": re.compile("^hello.*")},
625
758
                                   skip=1,
626
 
                                   timeout=False,
627
 
                                   snapshot=True,
628
 
                                   tailable=True,
629
 
                                   as_class=MyClass,
630
 
                                   slave_okay=True,
631
 
                                   await_data=True,
632
 
                                   partial=True,
 
759
                                   no_cursor_timeout=True,
 
760
                                   cursor_type=CursorType.TAILABLE_AWAIT,
 
761
                                   allow_partial_results=True,
633
762
                                   manipulate=False,
634
 
                                   compile_re=False,
635
 
                                   fields={'_id': False}).limit(2)
 
763
                                   projection={'_id': False}).limit(2)
636
764
        cursor.min([('a', 1)]).max([('b', 3)])
637
765
        cursor.add_option(128)
638
766
        cursor.comment('hi!')
640
768
        cursor2 = cursor.clone()
641
769
        self.assertEqual(cursor._Cursor__skip, cursor2._Cursor__skip)
642
770
        self.assertEqual(cursor._Cursor__limit, cursor2._Cursor__limit)
643
 
        self.assertEqual(cursor._Cursor__snapshot, cursor2._Cursor__snapshot)
644
 
        self.assertEqual(type(cursor._Cursor__as_class),
645
 
                         type(cursor2._Cursor__as_class))
646
 
        self.assertEqual(cursor._Cursor__slave_okay,
647
 
                         cursor2._Cursor__slave_okay)
 
771
        self.assertEqual(type(cursor._Cursor__codec_options),
 
772
                         type(cursor2._Cursor__codec_options))
648
773
        self.assertEqual(cursor._Cursor__manipulate,
649
774
                         cursor2._Cursor__manipulate)
650
 
        self.assertEqual(cursor._Cursor__compile_re,
651
 
                         cursor2._Cursor__compile_re)
652
775
        self.assertEqual(cursor._Cursor__query_flags,
653
776
                         cursor2._Cursor__query_flags)
654
777
        self.assertEqual(cursor._Cursor__comment,
660
783
 
661
784
        # Shallow copies can so can mutate
662
785
        cursor2 = copy.copy(cursor)
663
 
        cursor2._Cursor__fields['cursor2'] = False
664
 
        self.assertTrue('cursor2' in cursor._Cursor__fields)
 
786
        cursor2._Cursor__projection['cursor2'] = False
 
787
        self.assertTrue('cursor2' in cursor._Cursor__projection)
665
788
 
666
789
        # Deepcopies and shouldn't mutate
667
790
        cursor3 = copy.deepcopy(cursor)
668
 
        cursor3._Cursor__fields['cursor3'] = False
669
 
        self.assertFalse('cursor3' in cursor._Cursor__fields)
 
791
        cursor3._Cursor__projection['cursor3'] = False
 
792
        self.assertFalse('cursor3' in cursor._Cursor__projection)
670
793
 
671
794
        cursor4 = cursor.clone()
672
 
        cursor4._Cursor__fields['cursor4'] = False
673
 
        self.assertFalse('cursor4' in cursor._Cursor__fields)
 
795
        cursor4._Cursor__projection['cursor4'] = False
 
796
        self.assertFalse('cursor4' in cursor._Cursor__projection)
674
797
 
675
798
        # Test memo when deepcopying queries
676
799
        query = {"hello": "world"}
691
814
        self.assertTrue(isinstance(cursor2._Cursor__hint, SON))
692
815
        self.assertEqual(cursor._Cursor__hint, cursor2._Cursor__hint)
693
816
 
694
 
    def test_deepcopy_cursor_littered_with_regexes(self):
695
 
 
696
 
        cursor = self.db.test.find({"x": re.compile("^hmmm.*"),
697
 
                                    "y": [re.compile("^hmm.*")],
698
 
                                    "z": {"a": [re.compile("^hm.*")]},
699
 
                                    re.compile("^key.*"): {"a": [re.compile("^hm.*")]}})
700
 
 
701
 
        cursor2 = copy.deepcopy(cursor)
702
 
        self.assertEqual(cursor._Cursor__spec, cursor2._Cursor__spec)
703
 
 
704
 
    def test_add_remove_option(self):
705
 
        cursor = self.db.test.find()
706
 
        self.assertEqual(0, cursor._Cursor__query_options())
707
 
        cursor.add_option(2)
708
 
        cursor2 = self.db.test.find(tailable=True)
709
 
        self.assertEqual(2, cursor2._Cursor__query_options())
710
 
        self.assertEqual(cursor._Cursor__query_options(),
711
 
                         cursor2._Cursor__query_options())
712
 
        cursor.add_option(32)
713
 
        cursor2 = self.db.test.find(tailable=True, await_data=True)
714
 
        self.assertEqual(34, cursor2._Cursor__query_options())
715
 
        self.assertEqual(cursor._Cursor__query_options(),
716
 
                         cursor2._Cursor__query_options())
717
 
        cursor.add_option(128)
718
 
        cursor2 = self.db.test.find(tailable=True,
719
 
                                    await_data=True).add_option(128)
720
 
        self.assertEqual(162, cursor2._Cursor__query_options())
721
 
        self.assertEqual(cursor._Cursor__query_options(),
722
 
                         cursor2._Cursor__query_options())
723
 
 
724
 
        self.assertEqual(162, cursor._Cursor__query_options())
725
 
        cursor.add_option(128)
726
 
        self.assertEqual(162, cursor._Cursor__query_options())
727
 
 
728
 
        cursor.remove_option(128)
729
 
        cursor2 = self.db.test.find(tailable=True, await_data=True)
730
 
        self.assertEqual(34, cursor2._Cursor__query_options())
731
 
        self.assertEqual(cursor._Cursor__query_options(),
732
 
                         cursor2._Cursor__query_options())
733
 
        cursor.remove_option(32)
734
 
        cursor2 = self.db.test.find(tailable=True)
735
 
        self.assertEqual(2, cursor2._Cursor__query_options())
736
 
        self.assertEqual(cursor._Cursor__query_options(),
737
 
                         cursor2._Cursor__query_options())
738
 
 
739
 
        self.assertEqual(2, cursor._Cursor__query_options())
740
 
        cursor.remove_option(32)
741
 
        self.assertEqual(2, cursor._Cursor__query_options())
742
 
 
743
 
        # Slave OK
744
 
        cursor = self.db.test.find(slave_okay=True)
745
 
        self.assertEqual(4, cursor._Cursor__query_options())
746
 
        cursor2 = self.db.test.find().add_option(4)
747
 
        self.assertEqual(cursor._Cursor__query_options(),
748
 
                         cursor2._Cursor__query_options())
749
 
        self.assertTrue(cursor._Cursor__slave_okay)
750
 
        cursor.remove_option(4)
751
 
        self.assertEqual(0, cursor._Cursor__query_options())
752
 
        self.assertFalse(cursor._Cursor__slave_okay)
753
 
 
754
 
        # Timeout
755
 
        cursor = self.db.test.find(timeout=False)
756
 
        self.assertEqual(16, cursor._Cursor__query_options())
757
 
        cursor2 = self.db.test.find().add_option(16)
758
 
        self.assertEqual(cursor._Cursor__query_options(),
759
 
                         cursor2._Cursor__query_options())
760
 
        cursor.remove_option(16)
761
 
        self.assertEqual(0, cursor._Cursor__query_options())
762
 
 
763
 
        # Tailable / Await data
764
 
        cursor = self.db.test.find(tailable=True, await_data=True)
765
 
        self.assertEqual(34, cursor._Cursor__query_options())
766
 
        cursor2 = self.db.test.find().add_option(34)
767
 
        self.assertEqual(cursor._Cursor__query_options(),
768
 
                         cursor2._Cursor__query_options())
769
 
        cursor.remove_option(32)
770
 
        self.assertEqual(2, cursor._Cursor__query_options())
771
 
 
772
 
        # Exhaust - which mongos doesn't support
773
 
        if not is_mongos(self.db.connection):
774
 
            cursor = self.db.test.find(exhaust=True)
775
 
            self.assertEqual(64, cursor._Cursor__query_options())
776
 
            cursor2 = self.db.test.find().add_option(64)
777
 
            self.assertEqual(cursor._Cursor__query_options(),
778
 
                             cursor2._Cursor__query_options())
779
 
            self.assertTrue(cursor._Cursor__exhaust)
780
 
            cursor.remove_option(64)
781
 
            self.assertEqual(0, cursor._Cursor__query_options())
782
 
            self.assertFalse(cursor._Cursor__exhaust)
783
 
 
784
 
        # Partial
785
 
        cursor = self.db.test.find(partial=True)
786
 
        self.assertEqual(128, cursor._Cursor__query_options())
787
 
        cursor2 = self.db.test.find().add_option(128)
788
 
        self.assertEqual(cursor._Cursor__query_options(),
789
 
                         cursor2._Cursor__query_options())
790
 
        cursor.remove_option(128)
791
 
        self.assertEqual(0, cursor._Cursor__query_options())
792
 
 
793
817
    def test_count_with_fields(self):
794
818
        self.db.test.drop()
795
 
        self.db.test.save({"x": 1})
796
 
 
797
 
        if not version.at_least(self.db.connection, (1, 1, 3, -1)):
798
 
            for _ in self.db.test.find({}, ["a"]):
799
 
                self.fail()
800
 
 
801
 
            self.assertEqual(0, self.db.test.find({}, ["a"]).count())
802
 
        else:
803
 
            self.assertEqual(1, self.db.test.find({}, ["a"]).count())
 
819
        self.db.test.insert_one({"x": 1})
 
820
        self.assertEqual(1, self.db.test.find({}, ["a"]).count())
804
821
 
805
822
    def test_bad_getitem(self):
806
823
        self.assertRaises(TypeError, lambda x: self.db.test.find()[x], "hello")
809
826
 
810
827
    def test_getitem_slice_index(self):
811
828
        self.db.drop_collection("test")
812
 
        for i in range(100):
813
 
            self.db.test.save({"i": i})
 
829
        self.db.test.insert_many([{"i": i} for i in range(100)])
814
830
 
815
831
        count = itertools.count
816
832
 
835
851
            self.fail()
836
852
 
837
853
        self.assertEqual(5, len(list(self.db.test.find()[20:25])))
838
 
        self.assertEqual(5, len(list(self.db.test.find()[20L:25L])))
 
854
        self.assertEqual(5, len(list(
 
855
            self.db.test.find()[long(20):long(25)])))
839
856
        for a, b in zip(count(20), self.db.test.find()[20:25]):
840
857
            self.assertEqual(a, b['i'])
841
858
 
874
891
 
875
892
    def test_getitem_numeric_index(self):
876
893
        self.db.drop_collection("test")
877
 
        for i in range(100):
878
 
            self.db.test.save({"i": i})
 
894
        self.db.test.insert_many([{"i": i} for i in range(100)])
879
895
 
880
896
        self.assertEqual(0, self.db.test.find()[0]['i'])
881
897
        self.assertEqual(50, self.db.test.find()[50]['i'])
882
898
        self.assertEqual(50, self.db.test.find().skip(50)[0]['i'])
883
899
        self.assertEqual(50, self.db.test.find().skip(49)[1]['i'])
884
 
        self.assertEqual(50, self.db.test.find()[50L]['i'])
 
900
        self.assertEqual(50, self.db.test.find()[long(50)]['i'])
885
901
        self.assertEqual(99, self.db.test.find()[99]['i'])
886
902
 
887
903
        self.assertRaises(IndexError, lambda x: self.db.test.find()[x], -1)
890
906
                          lambda x: self.db.test.find().skip(50)[x], 50)
891
907
 
892
908
    def test_count_with_limit_and_skip(self):
893
 
        if not version.at_least(self.db.connection, (1, 1, 4, -1)):
894
 
            raise SkipTest("count with limit / skip requires MongoDB >= 1.1.4")
895
 
 
896
909
        self.assertRaises(TypeError, self.db.test.find().count, "foo")
897
910
 
898
911
        def check_len(cursor, length):
900
913
            self.assertEqual(length, cursor.count(True))
901
914
 
902
915
        self.db.drop_collection("test")
903
 
        for i in range(100):
904
 
            self.db.test.save({"i": i})
 
916
        self.db.test.insert_many([{"i": i} for i in range(100)])
905
917
 
906
918
        check_len(self.db.test.find(), 100)
907
919
 
930
942
    def test_get_more(self):
931
943
        db = self.db
932
944
        db.drop_collection("test")
933
 
        db.test.insert([{'i': i} for i in range(10)])
 
945
        db.test.insert_many([{'i': i} for i in range(10)])
934
946
        self.assertEqual(10, len(list(db.test.find().batch_size(5))))
935
947
 
936
948
    def test_tailable(self):
937
949
        db = self.db
938
950
        db.drop_collection("test")
939
951
        db.create_collection("test", capped=True, size=1000, max=3)
940
 
 
941
 
        try:
942
 
            cursor = db.test.find(tailable=True)
943
 
 
944
 
            db.test.insert({"x": 1})
945
 
            count = 0
946
 
            for doc in cursor:
947
 
                count += 1
948
 
                self.assertEqual(1, doc["x"])
949
 
            self.assertEqual(1, count)
950
 
 
951
 
            db.test.insert({"x": 2})
952
 
            count = 0
953
 
            for doc in cursor:
954
 
                count += 1
955
 
                self.assertEqual(2, doc["x"])
956
 
            self.assertEqual(1, count)
957
 
 
958
 
            db.test.insert({"x": 3})
959
 
            count = 0
960
 
            for doc in cursor:
961
 
                count += 1
962
 
                self.assertEqual(3, doc["x"])
963
 
            self.assertEqual(1, count)
964
 
 
965
 
            # Capped rollover - the collection can never
966
 
            # have more than 3 documents. Just make sure
967
 
            # this doesn't raise...
968
 
            db.test.insert(({"x": i} for i in xrange(4, 7)))
969
 
            self.assertEqual(0, len(list(cursor)))
970
 
 
971
 
            # and that the cursor doesn't think it's still alive.
972
 
            self.assertFalse(cursor.alive)
973
 
 
974
 
            self.assertEqual(3, db.test.count())
975
 
        finally:
976
 
            db.drop_collection("test")
 
952
        self.addCleanup(db.drop_collection, "test")
 
953
        cursor = db.test.find(cursor_type=CursorType.TAILABLE)
 
954
 
 
955
        db.test.insert_one({"x": 1})
 
956
        count = 0
 
957
        for doc in cursor:
 
958
            count += 1
 
959
            self.assertEqual(1, doc["x"])
 
960
        self.assertEqual(1, count)
 
961
 
 
962
        db.test.insert_one({"x": 2})
 
963
        count = 0
 
964
        for doc in cursor:
 
965
            count += 1
 
966
            self.assertEqual(2, doc["x"])
 
967
        self.assertEqual(1, count)
 
968
 
 
969
        db.test.insert_one({"x": 3})
 
970
        count = 0
 
971
        for doc in cursor:
 
972
            count += 1
 
973
            self.assertEqual(3, doc["x"])
 
974
        self.assertEqual(1, count)
 
975
 
 
976
        # Capped rollover - the collection can never
 
977
        # have more than 3 documents. Just make sure
 
978
        # this doesn't raise...
 
979
        db.test.insert_many([{"x": i} for i in range(4, 7)])
 
980
        self.assertEqual(0, len(list(cursor)))
 
981
 
 
982
        # and that the cursor doesn't think it's still alive.
 
983
        self.assertFalse(cursor.alive)
 
984
 
 
985
        self.assertEqual(3, db.test.count())
 
986
 
977
987
 
978
988
    def test_distinct(self):
979
 
        if not version.at_least(self.db.connection, (1, 1, 3, 1)):
980
 
            raise SkipTest("distinct with query requires MongoDB >= 1.1.3")
981
 
 
982
989
        self.db.drop_collection("test")
983
990
 
984
 
        self.db.test.save({"a": 1})
985
 
        self.db.test.save({"a": 2})
986
 
        self.db.test.save({"a": 2})
987
 
        self.db.test.save({"a": 2})
988
 
        self.db.test.save({"a": 3})
 
991
        self.db.test.insert_many(
 
992
            [{"a": 1}, {"a": 2}, {"a": 2}, {"a": 2}, {"a": 3}])
989
993
 
990
994
        distinct = self.db.test.find({"a": {"$lt": 3}}).distinct("a")
991
995
        distinct.sort()
994
998
 
995
999
        self.db.drop_collection("test")
996
1000
 
997
 
        self.db.test.save({"a": {"b": "a"}, "c": 12})
998
 
        self.db.test.save({"a": {"b": "b"}, "c": 8})
999
 
        self.db.test.save({"a": {"b": "c"}, "c": 12})
1000
 
        self.db.test.save({"a": {"b": "c"}, "c": 8})
 
1001
        self.db.test.insert_one({"a": {"b": "a"}, "c": 12})
 
1002
        self.db.test.insert_one({"a": {"b": "b"}, "c": 8})
 
1003
        self.db.test.insert_one({"a": {"b": "c"}, "c": 12})
 
1004
        self.db.test.insert_one({"a": {"b": "c"}, "c": 8})
1001
1005
 
1002
1006
        distinct = self.db.test.find({"c": 8}).distinct("a.b")
1003
1007
        distinct.sort()
1005
1009
        self.assertEqual(["b", "c"], distinct)
1006
1010
 
1007
1011
    def test_max_scan(self):
1008
 
        if not version.at_least(self.db.connection, (1, 5, 1)):
1009
 
            raise SkipTest("maxScan requires MongoDB >= 1.5.1")
1010
 
 
1011
1012
        self.db.drop_collection("test")
1012
 
        for _ in range(100):
1013
 
            self.db.test.insert({})
 
1013
        self.db.test.insert_many([{} for _ in range(100)])
1014
1014
 
1015
1015
        self.assertEqual(100, len(list(self.db.test.find())))
1016
 
        self.assertEqual(50, len(list(self.db.test.find(max_scan=50))))
 
1016
        self.assertEqual(50, len(list(self.db.test.find().max_scan(50))))
1017
1017
        self.assertEqual(50, len(list(self.db.test.find()
1018
1018
                                      .max_scan(90).max_scan(50))))
1019
1019
 
1020
1020
    def test_with_statement(self):
1021
 
        if sys.version_info < (2, 6):
1022
 
            raise SkipTest("With statement requires Python >= 2.6")
1023
 
 
1024
1021
        self.db.drop_collection("test")
1025
 
        for _ in range(100):
1026
 
            self.db.test.insert({})
 
1022
        self.db.test.insert_many([{} for _ in range(100)])
1027
1023
 
1028
1024
        c1 = self.db.test.find()
1029
 
        exec """
1030
 
with self.db.test.find() as c2:
1031
 
    self.assertTrue(c2.alive)
1032
 
self.assertFalse(c2.alive)
 
1025
        with self.db.test.find() as c2:
 
1026
            self.assertTrue(c2.alive)
 
1027
        self.assertFalse(c2.alive)
1033
1028
 
1034
 
with self.db.test.find() as c2:
1035
 
    self.assertEqual(100, len(list(c2)))
1036
 
self.assertFalse(c2.alive)
1037
 
"""
 
1029
        with self.db.test.find() as c2:
 
1030
            self.assertEqual(100, len(list(c2)))
 
1031
        self.assertFalse(c2.alive)
1038
1032
        self.assertTrue(c1.alive)
1039
1033
 
 
1034
    @client_context.require_no_mongos
1040
1035
    def test_comment(self):
1041
 
        if is_mongos(self.client):
1042
 
            raise SkipTest("profile is not supported by mongos")
1043
 
        if not version.at_least(self.db.connection, (2, 0)):
1044
 
            raise SkipTest("Requires server >= 2.0")
1045
 
        if server_started_with_auth(self.db.connection):
 
1036
        if server_started_with_auth(self.db.client):
1046
1037
            raise SkipTest("SERVER-4754 - This test uses profiling.")
1047
1038
 
1048
1039
        def run_with_profiling(func):
1081
1072
 
1082
1073
        run_with_profiling(distinct)
1083
1074
 
1084
 
        self.db.test.insert([{}, {}])
 
1075
        self.db.test.insert_many([{}, {}])
1085
1076
        cursor = self.db.test.find()
1086
 
        cursor.next()
 
1077
        next(cursor)
1087
1078
        self.assertRaises(InvalidOperation, cursor.comment, 'hello')
1088
1079
 
1089
1080
        self.db.system.profile.drop()
1091
1082
    def test_cursor_transfer(self):
1092
1083
 
1093
1084
        # This is just a test, don't try this at home...
1094
 
        self.db.test.remove({})
1095
 
        self.db.test.insert({'_id': i} for i in xrange(200))
 
1085
 
 
1086
        client = client_context.rs_or_standalone_client
 
1087
        db = client.pymongo_test
 
1088
 
 
1089
        db.test.delete_many({})
 
1090
        db.test.insert_many([{'_id': i} for i in range(200)])
1096
1091
 
1097
1092
        class CManager(CursorManager):
1098
 
            def __init__(self, connection):
1099
 
                super(CManager, self).__init__(connection)
 
1093
            def __init__(self, client):
 
1094
                super(CManager, self).__init__(client)
1100
1095
 
1101
 
            def close(self, dummy):
 
1096
            def close(self, dummy, dummy2):
1102
1097
                # Do absolutely nothing...
1103
1098
                pass
1104
1099
 
1105
 
        client = self.db.connection
1106
 
        ctx = catch_warnings()
1107
 
        try:
1108
 
            warnings.simplefilter("ignore", DeprecationWarning)
1109
 
            client.set_cursor_manager(CManager)
1110
 
 
1111
 
            docs = []
1112
 
            cursor = self.db.test.find().batch_size(10)
1113
 
            docs.append(cursor.next())
1114
 
            cursor.close()
1115
 
            docs.extend(cursor)
1116
 
            self.assertEqual(len(docs), 10)
1117
 
            cmd_cursor = {'id': cursor.cursor_id, 'firstBatch': []}
1118
 
            ccursor = CommandCursor(cursor.collection, cmd_cursor,
1119
 
                                    cursor.conn_id, retrieved=cursor.retrieved)
1120
 
            docs.extend(ccursor)
1121
 
            self.assertEqual(len(docs), 200)
1122
 
        finally:
1123
 
            client.set_cursor_manager(CursorManager)
1124
 
            ctx.exit()
 
1100
        client.set_cursor_manager(CManager)
 
1101
        self.addCleanup(client.set_cursor_manager, CursorManager)
 
1102
        docs = []
 
1103
        cursor = db.test.find().batch_size(10)
 
1104
        docs.append(next(cursor))
 
1105
        cursor.close()
 
1106
        docs.extend(cursor)
 
1107
        self.assertEqual(len(docs), 10)
 
1108
        cmd_cursor = {'id': cursor.cursor_id, 'firstBatch': []}
 
1109
        ccursor = CommandCursor(cursor.collection, cmd_cursor,
 
1110
                                cursor.address, retrieved=cursor.retrieved)
 
1111
        docs.extend(ccursor)
 
1112
        self.assertEqual(len(docs), 200)
 
1113
 
 
1114
    def test_modifiers(self):
 
1115
        cur = self.db.test.find()
 
1116
        self.assertTrue('$query' not in cur._Cursor__query_spec())
 
1117
        cur = self.db.test.find().comment("testing").max_time_ms(500)
 
1118
        self.assertTrue('$query' in cur._Cursor__query_spec())
 
1119
        self.assertEqual(cur._Cursor__query_spec()["$comment"], "testing")
 
1120
        self.assertEqual(cur._Cursor__query_spec()["$maxTimeMS"], 500)
 
1121
        cur = self.db.test.find(
 
1122
            modifiers={"$maxTimeMS": 500, "$comment": "testing"})
 
1123
        self.assertTrue('$query' in cur._Cursor__query_spec())
 
1124
        self.assertEqual(cur._Cursor__query_spec()["$comment"], "testing")
 
1125
        self.assertEqual(cur._Cursor__query_spec()["$maxTimeMS"], 500)
 
1126
 
 
1127
    def test_alive(self):
 
1128
        self.db.test.delete_many({})
 
1129
        self.db.test.insert_many([{} for _ in range(3)])
 
1130
        self.addCleanup(self.db.test.delete_many, {})
 
1131
        cursor = self.db.test.find().batch_size(2)
 
1132
        n = 0
 
1133
        while True:
 
1134
            cursor.next()
 
1135
            n += 1
 
1136
            if 3 == n:
 
1137
                self.assertFalse(cursor.alive)
 
1138
                break
 
1139
 
 
1140
            self.assertTrue(cursor.alive)
 
1141
 
1125
1142
 
1126
1143
if __name__ == "__main__":
1127
1144
    unittest.main()