Skip to content

Commit 9556805

Browse files
committed
PYTHON-952 - Add spec test runner and fix bugs
1 parent f5eed97 commit 9556805

File tree

13 files changed

+1732
-21
lines changed

13 files changed

+1732
-21
lines changed

pymongo/bulk.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -337,14 +337,16 @@ def execute_no_results(self, sock_info, generator):
337337
check_keys,
338338
operation['multi'],
339339
write_concern=write_concern,
340-
op_id=op_id)
340+
op_id=op_id,
341+
ordered=self.ordered)
341342
else:
342343
for operation in run.ops:
343344
coll._delete(sock_info,
344345
operation['q'],
345346
not operation['limit'],
346347
write_concern,
347-
op_id)
348+
op_id,
349+
self.ordered)
348350
except OperationFailure:
349351
if self.ordered:
350352
break
@@ -373,6 +375,7 @@ def execute_legacy(self, sock_info, generator, write_concern):
373375
if run.op_type == _INSERT:
374376
coll._insert(sock_info,
375377
operation,
378+
self.ordered,
376379
write_concern=write_concern,
377380
op_id=op_id)
378381
result = {}
@@ -388,13 +391,15 @@ def execute_legacy(self, sock_info, generator, write_concern):
388391
check_keys,
389392
operation['multi'],
390393
write_concern=write_concern,
391-
op_id=op_id)
394+
op_id=op_id,
395+
ordered=self.ordered)
392396
else:
393397
result = coll._delete(sock_info,
394398
operation['q'],
395399
not operation['limit'],
396400
write_concern,
397-
op_id)
401+
op_id,
402+
self.ordered)
398403
_merge_legacy(run, full_result, result, idx)
399404
except DocumentTooLarge as exc:
400405
# MongoDB 2.6 uses error code 2 for "too large".

pymongo/collection.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -411,17 +411,19 @@ def _legacy_write(
411411
dur, details, name, rqst_id, sock_info.address, op_id)
412412
raise
413413
if publish:
414-
# Comply with APM spec.
415-
reply = {'ok': 1}
416-
if result:
414+
if result is not None:
417415
reply = message._convert_write_result(name, cmd, result)
416+
else:
417+
# Comply with APM spec.
418+
reply = {'ok': 1}
418419
duration = (datetime.datetime.now() - start) + duration
419420
monitoring.publish_command_success(
420421
duration, reply, name, rqst_id, sock_info.address, op_id)
421422
return result
422423

423424
def _insert_one(
424-
self, sock_info, doc, check_keys, manipulate, write_concern, op_id):
425+
self, sock_info, doc, ordered,
426+
check_keys, manipulate, write_concern, op_id):
425427
"""Internal helper for inserting a single document."""
426428
if manipulate:
427429
doc = self.__database._apply_incoming_manipulators(doc, self)
@@ -432,7 +434,7 @@ def _insert_one(
432434
concern = (write_concern or self.write_concern).document
433435
acknowledged = concern.get("w") != 0
434436
command = SON([('insert', self.name),
435-
('ordered', True),
437+
('ordered', ordered),
436438
('documents', [doc])])
437439
if concern:
438440
command['writeConcern'] = concern
@@ -457,7 +459,8 @@ def _insert(self, sock_info, docs, ordered=True, check_keys=True,
457459
"""Internal insert helper."""
458460
if isinstance(docs, collections.MutableMapping):
459461
return self._insert_one(
460-
sock_info, docs, check_keys, manipulate, write_concern, op_id)
462+
sock_info, docs, ordered,
463+
check_keys, manipulate, write_concern, op_id)
461464

462465
ids = []
463466

@@ -580,15 +583,15 @@ def gen():
580583

581584
def _update(self, sock_info, criteria, document, upsert=False,
582585
check_keys=True, multi=False, manipulate=False,
583-
write_concern=None, op_id=None):
586+
write_concern=None, op_id=None, ordered=True):
584587
"""Internal update / replace helper."""
585588
common.validate_boolean("upsert", upsert)
586589
if manipulate:
587590
document = self.__database._fix_incoming(document, self)
588591
concern = (write_concern or self.write_concern).document
589592
acknowledged = concern.get("w") != 0
590593
command = SON([('update', self.name),
591-
('ordered', True),
594+
('ordered', ordered),
592595
('updates', [SON([('q', criteria),
593596
('u', document),
594597
('multi', multi),
@@ -758,13 +761,14 @@ def drop(self):
758761
self.__database.drop_collection(self.__name)
759762

760763
def _delete(
761-
self, sock_info, criteria, multi, write_concern=None, op_id=None):
764+
self, sock_info, criteria, multi,
765+
write_concern=None, op_id=None, ordered=True):
762766
"""Internal delete helper."""
763767
common.validate_is_mapping("filter", criteria)
764768
concern = (write_concern or self.write_concern).document
765769
acknowledged = concern.get("w") != 0
766770
command = SON([('delete', self.name),
767-
('ordered', True),
771+
('ordered', ordered),
768772
('deletes', [SON([('q', criteria),
769773
('limit', int(not multi))])])])
770774
if concern:

pymongo/message.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,8 @@ def _convert_write_result(operation, command, result):
115115
elif result.get("updatedExisting") is False and affected == 1:
116116
# If _id is in both the update document *and* the query spec
117117
# the update document _id takes precedence.
118-
_id = command["u"].get("_id", command["q"].get("_id"))
118+
update = command['updates'][0]
119+
_id = update["u"].get("_id", update["q"].get("_id"))
119120
res["upserted"] = [{"index": 0, "_id": _id}]
120121
return res
121122

@@ -479,14 +480,16 @@ def legacy_write(self, request_id, msg, max_doc_size, acknowledged, docs):
479480
cmd = self._start(request_id, docs)
480481
start = datetime.datetime.now()
481482
try:
482-
reply = self.sock_info.legacy_write(
483+
result = self.sock_info.legacy_write(
483484
request_id, msg, max_doc_size, acknowledged)
484485
if self.publish:
485486
duration = (datetime.datetime.now() - start) + duration
486-
self._succeed(
487-
request_id,
488-
_convert_write_result(self.name, cmd, reply),
489-
duration)
487+
if result is not None:
488+
reply = _convert_write_result(self.name, cmd, result)
489+
else:
490+
# Comply with APM spec.
491+
reply = {'ok': 1}
492+
self._succeed(request_id, reply, duration)
490493
except OperationFailure as exc:
491494
if self.publish:
492495
duration = (datetime.datetime.now() - start) + duration
@@ -498,7 +501,7 @@ def legacy_write(self, request_id, msg, max_doc_size, acknowledged, docs):
498501
raise
499502
finally:
500503
self.start_time = datetime.datetime.now()
501-
return reply
504+
return result
502505

503506
def write_command(self, request_id, msg, docs):
504507
"""A proxy for SocketInfo.write_command that handles event publishing.
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
{
2+
"data": [
3+
{
4+
"_id": 1,
5+
"x": 11
6+
},
7+
{
8+
"_id": 2,
9+
"x": 22
10+
},
11+
{
12+
"_id": 3,
13+
"x": 33
14+
}
15+
],
16+
"collection_name": "test",
17+
"database_name": "command-monitoring-tests",
18+
"tests": [
19+
{
20+
"description": "A successful mixed bulk write",
21+
"operation": {
22+
"name": "bulkWrite",
23+
"arguments": {
24+
"requests": [
25+
{
26+
"insertOne": {
27+
"document": {
28+
"_id": 4,
29+
"x": 44
30+
}
31+
}
32+
},
33+
{
34+
"updateOne": {
35+
"filter": {
36+
"_id": 3
37+
},
38+
"update": {
39+
"$set": {
40+
"x": 333
41+
}
42+
}
43+
}
44+
}
45+
]
46+
}
47+
},
48+
"expectations": [
49+
{
50+
"command_started_event": {
51+
"command": {
52+
"insert": "test",
53+
"documents": [
54+
{
55+
"_id": 4,
56+
"x": 44
57+
}
58+
],
59+
"ordered": true
60+
},
61+
"command_name": "insert",
62+
"database_name": "command-monitoring-tests"
63+
}
64+
},
65+
{
66+
"command_succeeded_event": {
67+
"reply": {
68+
"ok": 1.0,
69+
"n": 1
70+
},
71+
"command_name": "insert"
72+
}
73+
},
74+
{
75+
"command_started_event": {
76+
"command": {
77+
"update": "test",
78+
"updates": [
79+
{
80+
"q": {
81+
"_id": 3
82+
},
83+
"u": {
84+
"$set": {
85+
"x": 333
86+
}
87+
},
88+
"upsert": false,
89+
"multi": false
90+
}
91+
],
92+
"ordered": true
93+
},
94+
"command_name": "update",
95+
"database_name": "command-monitoring-tests"
96+
}
97+
},
98+
{
99+
"command_succeeded_event": {
100+
"reply": {
101+
"ok": 1.0,
102+
"n": 1
103+
},
104+
"command_name": "update"
105+
}
106+
}
107+
]
108+
},
109+
{
110+
"description": "A successful unordered bulk write with an unacknowledged write concern",
111+
"operation": {
112+
"name": "bulkWrite",
113+
"arguments": {
114+
"requests": [
115+
{
116+
"insertOne": {
117+
"document": {
118+
"_id": 4,
119+
"x": 44
120+
}
121+
}
122+
}
123+
],
124+
"ordered": false,
125+
"writeConcern": {
126+
"w": 0
127+
}
128+
}
129+
},
130+
"expectations": [
131+
{
132+
"command_started_event": {
133+
"command": {
134+
"insert": "test",
135+
"documents": [
136+
{
137+
"_id": 4,
138+
"x": 44
139+
}
140+
],
141+
"ordered": false,
142+
"writeConcern": {
143+
"w": 0
144+
}
145+
},
146+
"command_name": "insert",
147+
"database_name": "command-monitoring-tests"
148+
}
149+
},
150+
{
151+
"command_succeeded_event": {
152+
"reply": {
153+
"ok": 1.0
154+
},
155+
"command_name": "insert"
156+
}
157+
}
158+
]
159+
}
160+
]
161+
}

0 commit comments

Comments
 (0)