Skip to content

Commit 335843e

Browse files
Add test case for handling non-PyMongoError
1 parent 480a61d commit 335843e

File tree

6 files changed

+88
-6
lines changed

6 files changed

+88
-6
lines changed

pymongo/asynchronous/mongo_client.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2562,7 +2562,9 @@ async def run(self) -> T:
25622562
if not self._retryable:
25632563
raise
25642564
if isinstance(exc, ClientBulkWriteException) and exc.error:
2565-
retryable_write_error_exc = exc.error.has_error_label("RetryableWriteError")
2565+
retryable_write_error_exc = isinstance(
2566+
exc.error, PyMongoError
2567+
) and exc.error.has_error_label("RetryableWriteError")
25662568
else:
25672569
retryable_write_error_exc = exc.has_error_label("RetryableWriteError")
25682570
if retryable_write_error_exc:

pymongo/synchronous/mongo_client.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2549,7 +2549,9 @@ def run(self) -> T:
25492549
if not self._retryable:
25502550
raise
25512551
if isinstance(exc, ClientBulkWriteException) and exc.error:
2552-
retryable_write_error_exc = exc.error.has_error_label("RetryableWriteError")
2552+
retryable_write_error_exc = isinstance(
2553+
exc.error, PyMongoError
2554+
) and exc.error.has_error_label("RetryableWriteError")
25532555
else:
25542556
retryable_write_error_exc = exc.has_error_label("RetryableWriteError")
25552557
if retryable_write_error_exc:

test/asynchronous/pymongo_mocks.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,14 @@
2222
from test.asynchronous import async_client_context
2323

2424
from pymongo import AsyncMongoClient, common
25+
from pymongo.asynchronous.client_bulk import _AsyncClientBulk
2526
from pymongo.asynchronous.monitor import Monitor
2627
from pymongo.asynchronous.pool import Pool
27-
from pymongo.errors import AutoReconnect, NetworkTimeout
28+
from pymongo.errors import AutoReconnect, ClientBulkWriteException, NetworkTimeout
2829
from pymongo.hello import Hello, HelloCompat
30+
from pymongo.operations import _Op
2931
from pymongo.server_description import ServerDescription
32+
from pymongo.write_concern import WriteConcern
3033

3134
_IS_SYNC = False
3235

@@ -246,7 +249,18 @@ def mock_hello(self, host):
246249

247250
return response, rtt
248251

252+
async def mock_client_bulk_write(self, models):
253+
blk = _AsyncMockClientBulk(self, write_concern=WriteConcern(w=1))
254+
for model in models:
255+
model._add_to_client_bulk(blk)
256+
return await blk.execute(None, _Op.BULK_WRITE)
257+
249258
def _process_periodic_tasks(self):
250259
# Avoid the background thread causing races, e.g. a surprising
251260
# reconnect while we're trying to test a disconnected client.
252261
pass
262+
263+
264+
class _AsyncMockClientBulk(_AsyncClientBulk):
265+
async def write_command(self, bwc, cmd, request_id, msg, to_send_ops, to_send_ns, client):
266+
return {"error": TypeError("mock type error")}

test/asynchronous/test_client_bulk_write.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,13 @@
1919

2020
sys.path[0:0] = [""]
2121

22-
from test.asynchronous import AsyncIntegrationTest, async_client_context, unittest
22+
from test.asynchronous import (
23+
AsyncIntegrationTest,
24+
AsyncMockClientTest,
25+
async_client_context,
26+
unittest,
27+
)
28+
from test.asynchronous.pymongo_mocks import AsyncMockClient
2329
from test.utils import (
2430
OvertCommandListener,
2531
async_rs_or_single_client,
@@ -577,3 +583,22 @@ async def test_timeout_in_multi_batch_bulk_write(self):
577583
if event.command_name == "bulkWrite":
578584
bulk_write_events.append(event)
579585
self.assertEqual(len(bulk_write_events), 2)
586+
587+
588+
class TestClientBulkWriteMock(AsyncMockClientTest):
589+
@async_client_context.require_version_min(8, 0, 0, -24)
590+
async def test_handles_non_pymongo_error(self):
591+
mock_client = await AsyncMockClient.get_async_mock_client(
592+
standalones=[],
593+
members=["a:1", "b:2", "c:3"],
594+
mongoses=[],
595+
host="b:2", # Pass a secondary.
596+
replicaSet="rs",
597+
heartbeatFrequencyMS=500,
598+
)
599+
self.addAsyncCleanup(mock_client.aclose)
600+
models = [InsertOne(namespace="db.coll", document={"a": "b"})]
601+
with self.assertRaises(ClientBulkWriteException) as context:
602+
await mock_client.mock_client_bulk_write(models=models)
603+
self.assertIsInstance(context.exception.error, TypeError)
604+
self.assertFalse(hasattr(context.exception.error, "details"))

test/pymongo_mocks.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,14 @@
2121
from test import client_context
2222

2323
from pymongo import MongoClient, common
24-
from pymongo.errors import AutoReconnect, NetworkTimeout
24+
from pymongo.errors import AutoReconnect, ClientBulkWriteException, NetworkTimeout
2525
from pymongo.hello import Hello, HelloCompat
26+
from pymongo.operations import _Op
2627
from pymongo.server_description import ServerDescription
28+
from pymongo.synchronous.client_bulk import _ClientBulk
2729
from pymongo.synchronous.monitor import Monitor
2830
from pymongo.synchronous.pool import Pool
31+
from pymongo.write_concern import WriteConcern
2932

3033
_IS_SYNC = True
3134

@@ -245,7 +248,18 @@ def mock_hello(self, host):
245248

246249
return response, rtt
247250

251+
def mock_client_bulk_write(self, models):
252+
blk = _MockClientBulk(self, write_concern=WriteConcern(w=1))
253+
for model in models:
254+
model._add_to_client_bulk(blk)
255+
return blk.execute(None, _Op.BULK_WRITE)
256+
248257
def _process_periodic_tasks(self):
249258
# Avoid the background thread causing races, e.g. a surprising
250259
# reconnect while we're trying to test a disconnected client.
251260
pass
261+
262+
263+
class _MockClientBulk(_ClientBulk):
264+
def write_command(self, bwc, cmd, request_id, msg, to_send_ops, to_send_ns, client):
265+
return {"error": TypeError("mock type error")}

test/test_client_bulk_write.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,13 @@
1919

2020
sys.path[0:0] = [""]
2121

22-
from test import IntegrationTest, client_context, unittest
22+
from test import (
23+
IntegrationTest,
24+
MockClientTest,
25+
client_context,
26+
unittest,
27+
)
28+
from test.pymongo_mocks import MockClient
2329
from test.utils import (
2430
OvertCommandListener,
2531
rs_or_single_client,
@@ -577,3 +583,22 @@ def test_timeout_in_multi_batch_bulk_write(self):
577583
if event.command_name == "bulkWrite":
578584
bulk_write_events.append(event)
579585
self.assertEqual(len(bulk_write_events), 2)
586+
587+
588+
class TestClientBulkWriteMock(MockClientTest):
589+
@client_context.require_version_min(8, 0, 0, -24)
590+
def test_handles_non_pymongo_error(self):
591+
mock_client = MockClient.get_mock_client(
592+
standalones=[],
593+
members=["a:1", "b:2", "c:3"],
594+
mongoses=[],
595+
host="b:2", # Pass a secondary.
596+
replicaSet="rs",
597+
heartbeatFrequencyMS=500,
598+
)
599+
self.addCleanup(mock_client.close)
600+
models = [InsertOne(namespace="db.coll", document={"a": "b"})]
601+
with self.assertRaises(ClientBulkWriteException) as context:
602+
mock_client.mock_client_bulk_write(models=models)
603+
self.assertIsInstance(context.exception.error, TypeError)
604+
self.assertFalse(hasattr(context.exception.error, "details"))

0 commit comments

Comments
 (0)