Skip to content

Commit 40af3ef

Browse files
committed
Raise DuplicateKeyError for commands PYTHON-507
Only when appropriate. The findAndModify command can return duplicate key error when doing an upsert.
1 parent 1ea8c74 commit 40af3ef

File tree

4 files changed

+18
-5
lines changed

4 files changed

+18
-5
lines changed

pymongo/helpers.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from bson.binary import OLD_UUID_SUBTYPE
2424
from bson.son import SON
2525
from pymongo.errors import (AutoReconnect,
26+
DuplicateKeyError,
2627
OperationFailure,
2728
TimeoutError)
2829

@@ -139,7 +140,11 @@ def _check_command_response(response, reset, msg="%s", allowable_errors=[]):
139140
ex_msg += (", assertionCode: %d" %
140141
(details["assertionCode"],))
141142
raise OperationFailure(ex_msg, details.get("assertionCode"))
142-
raise OperationFailure(msg % errmsg)
143+
code = details.get("code")
144+
# findAndModify with upsert can raise duplicate key error
145+
if code in (11000, 11001, 12582):
146+
raise DuplicateKeyError(errmsg, code)
147+
raise OperationFailure(msg % errmsg, code)
143148

144149

145150
def _fields_list_to_dict(fields):

pymongo/mongo_client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -855,8 +855,8 @@ def __check_response_to_last_error(self, response):
855855
break
856856

857857
if "code" in details:
858-
if details["code"] in [11000, 11001, 12582]:
859-
raise DuplicateKeyError(details["err"])
858+
if details["code"] in (11000, 11001, 12582):
859+
raise DuplicateKeyError(details["err"], details["code"])
860860
else:
861861
raise OperationFailure(details["err"], details["code"])
862862
else:

pymongo/mongo_replica_set_client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,8 +1073,8 @@ def __check_response_to_last_error(self, response):
10731073
raise AutoReconnect(error_msg)
10741074

10751075
if "code" in error:
1076-
if error["code"] in [11000, 11001, 12582]:
1077-
raise DuplicateKeyError(error["err"])
1076+
if error["code"] in (11000, 11001, 12582):
1077+
raise DuplicateKeyError(error["err"], error["code"])
10781078
else:
10791079
raise OperationFailure(error["err"], error["code"])
10801080
else:

test/test_collection.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1700,6 +1700,14 @@ def test_find_and_modify(self):
17001700
c.drop()
17011701
c.insert({'_id': 1, 'i': 1})
17021702

1703+
# Test that we raise DuplicateKeyError when appropriate.
1704+
c.ensure_index('i', unique=True)
1705+
self.assertRaises(DuplicateKeyError,
1706+
c.find_and_modify, query={'i': 1, 'j': 1},
1707+
update={'$set': {'k': 1}}, upsert=True)
1708+
c.drop_indexes()
1709+
1710+
# Test correct findAndModify
17031711
self.assertEqual({'_id': 1, 'i': 1},
17041712
c.find_and_modify({'_id': 1}, {'$inc': {'i': 1}}))
17051713
self.assertEqual({'_id': 1, 'i': 3},

0 commit comments

Comments
 (0)