From 5a9f61c3d1bc005cac10cf68476052d2c953c2aa Mon Sep 17 00:00:00 2001 From: Monisha Ranjan Date: Wed, 25 Jun 2025 22:41:15 -0400 Subject: [PATCH] Add write concern support for issue #6 - Add WriteConcern import from pymongo - Add write concern parsing in DatabaseWrapper.__init__() - Support dict, string, and int write concern formats - Apply write concern to collections in get_collection() - Add comprehensive tests for write concern functionality --- django_mongodb_backend/base.py | 22 +++++++++ tests/backend_/test_write_concern.py | 73 ++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 tests/backend_/test_write_concern.py diff --git a/django_mongodb_backend/base.py b/django_mongodb_backend/base.py index fc21fa5b..fc7d2801 100644 --- a/django_mongodb_backend/base.py +++ b/django_mongodb_backend/base.py @@ -10,6 +10,7 @@ from pymongo.collection import Collection from pymongo.driver_info import DriverInfo from pymongo.mongo_client import MongoClient +from pymongo.write_concern import WriteConcern from . import __version__ as django_mongodb_backend_version from . import dbapi as Database @@ -156,8 +157,29 @@ def _isnull_operator(a, b): def __init__(self, settings_dict, alias=DEFAULT_DB_ALIAS): super().__init__(settings_dict, alias=alias) self.session = None + self._write_concern = self._parse_write_concern(settings_dict.get('OPTIONS', {}).get('WRITE_CONCERN')) + + def _parse_write_concern(self, write_concern_config): + """Parse write concern configuration from Django settings.""" + if write_concern_config is None: + return None + + if isinstance(write_concern_config, dict): + return WriteConcern(**write_concern_config) + elif isinstance(write_concern_config, str): + return WriteConcern(w=write_concern_config) + elif isinstance(write_concern_config, int): + return WriteConcern(w=write_concern_config) + else: + raise ImproperlyConfigured( + f"WRITE_CONCERN must be a dict, str, or int, got {type(write_concern_config)}" + ) def get_collection(self, name, **kwargs): + # Apply write concern if configured + if self._write_concern is not None: + kwargs.setdefault('write_concern', self._write_concern) + collection = Collection(self.database, name, **kwargs) if self.queries_logged: collection = OperationDebugWrapper(self, collection) diff --git a/tests/backend_/test_write_concern.py b/tests/backend_/test_write_concern.py new file mode 100644 index 00000000..aaadf927 --- /dev/null +++ b/tests/backend_/test_write_concern.py @@ -0,0 +1,73 @@ +from django.core.exceptions import ImproperlyConfigured +from django.test import TestCase +from pymongo.write_concern import WriteConcern + +from django_mongodb_backend.base import DatabaseWrapper + + +class WriteConcerrTests(TestCase): + def test_parse_write_concern_dict(self): + """Test parsing write concern from dictionary configuration.""" + settings_dict = { + 'NAME': 'test_db', + 'OPTIONS': { + 'WRITE_CONCERN': {'w': 'majority', 'j': True, 'wtimeout': 5000} + } + } + wrapper = DatabaseWrapper(settings_dict) + + self.assertIsInstance(wrapper._write_concern, WriteConcern) + self.assertIsNotNone(wrapper._write_concern) + self.assertEqual(wrapper._write_concern.document['w'], 'majority') + self.assertEqual(wrapper._write_concern.document['j'], True) + self.assertEqual(wrapper._write_concern.document['wtimeout'], 5000) + + def test_parse_write_concern_string(self): + """Test parsing write concern from string configuration.""" + settings_dict = { + 'NAME': 'test_db', + 'OPTIONS': { + 'WRITE_CONCERN': 'majority' + } + } + wrapper = DatabaseWrapper(settings_dict) + + self.assertIsInstance(wrapper._write_concern, WriteConcern) + self.assertIsNotNone(wrapper._write_concern) + self.assertEqual(wrapper._write_concern.document['w'], 'majority') + + def test_parse_write_concern_int(self): + """Test parsing write concern from integer configuration.""" + settings_dict = { + 'NAME': 'test_db', + 'OPTIONS': { + 'WRITE_CONCERN': 2 + } + } + wrapper = DatabaseWrapper(settings_dict) + + self.assertIsInstance(wrapper._write_concern, WriteConcern) + self.assertIsNotNone(wrapper._write_concern) + self.assertEqual(wrapper._write_concern.document['w'], 2) + + def test_parse_write_concern_none(self): + """Test that None write concern config results in None.""" + settings_dict = { + 'NAME': 'test_db', + 'OPTIONS': {} + } + wrapper = DatabaseWrapper(settings_dict) + + self.assertIsNone(wrapper._write_concern) + + def test_parse_write_concern_invalid_type(self): + """Test that invalid write concern type raises ImproperlyConfigured.""" + settings_dict = { + 'NAME': 'test_db', + 'OPTIONS': { + 'WRITE_CONCERN': ['invalid', 'type'] + } + } + + with self.assertRaises(ImproperlyConfigured): + DatabaseWrapper(settings_dict) \ No newline at end of file