]> git.notmuchmail.org Git - notmuch/commitdiff
bindings/python-cffi: allow reopening a database
authorAnton Khirnov <anton@khirnov.net>
Sun, 14 Sep 2025 15:07:43 +0000 (17:07 +0200)
committerDavid Bremner <david@tethera.net>
Sun, 14 Sep 2025 16:24:59 +0000 (13:24 -0300)
This will be useful for handling NOTMUCH_STATUS_OPERATION_INVALIDATED
errors that will be exposed through the bindings in a following commit.

bindings/python-cffi/notmuch2/_build.py
bindings/python-cffi/notmuch2/_database.py
bindings/python-cffi/tests/test_database.py

index 65d7dcb6024cb576ffa0c887591b8d35a773d667..0429691a1453059ab478d0b897877e76a71a0f76 100644 (file)
@@ -118,6 +118,9 @@ ffibuilder.cdef(
                                        notmuch_database_t **database,
                                        char **error_message);
     notmuch_status_t
+    notmuch_database_reopen (notmuch_database_t *database,
+                             notmuch_database_mode_t new_mode);
+    notmuch_status_t
     notmuch_database_close (notmuch_database_t *database);
     notmuch_status_t
     notmuch_database_destroy (notmuch_database_t *database);
index c13d9fcfe5321830a32bfcb5501f2a0ed585a92b..a47049bae4f8d4a888beae111007a15904b865ec 100644 (file)
@@ -285,6 +285,30 @@ class Database(base.NotmuchObject):
             raise errors.NotmuchError(ret)
         self.closed = True
 
+    def reopen(self, mode=None):
+        """Reopen an opened notmuch database.
+
+        :param mode: Mode to reopen the database with. When None, the previously
+           active mode is preserved.
+        :type mode: :attr:`MODE`, str, or None.
+
+        This is useful e.g. for:
+        - switching the mode between read-only and read-write
+        - recovering from OperationInvalidatedError
+        """
+        if isinstance(mode, str):
+            try:
+                mode = self.STR_MODE_MAP[mode]
+            except KeyError:
+                raise ValueError('Invalid mode: %s' % mode)
+        else:
+            mode = mode or self.mode
+        self.mode = mode
+
+        ret = capi.lib.notmuch_database_reopen(self._db_p, mode.value)
+        if ret != capi.lib.NOTMUCH_STATUS_SUCCESS:
+            raise errors.NotmuchError(ret)
+
     def __enter__(self):
         return self
 
index 1557235d76ea7b354dcc53042964a1ad2b7f2368..1143cf33bc3cd27b2c08f99ab03c23c3a453c450 100644 (file)
@@ -173,6 +173,32 @@ class TestRevision:
 
     # XXX add tests for revisions comparisons
 
+
+class TestMode:
+
+    def test_readonly_raises(self, db, maildir):
+        with pytest.raises(errors.ReadOnlyDatabaseError):
+            with dbmod.Database(maildir.path, 'ro',
+                                config=notmuch2.Database.CONFIG.EMPTY) as db_ro:
+                _, pathname = maildir.deliver()
+                db_ro.add(pathname)
+
+    def test_reopen_ro(self, db, maildir):
+        db.reopen(mode = dbmod.Mode.READ_ONLY)
+        with pytest.raises(errors.ReadOnlyDatabaseError):
+            _, pathname = maildir.deliver()
+            db.add(pathname)
+
+    def test_reopen_rw(self, db, maildir):
+        # release the write lock
+        db.close()
+
+        with dbmod.Database(maildir.path, 'ro',
+                            config=notmuch2.Database.CONFIG.EMPTY) as db:
+            _, pathname = maildir.deliver()
+            db.reopen(mode = dbmod.Mode.READ_WRITE)
+            db.add(pathname)
+
 class TestMessages:
 
     def test_add_message(self, db, maildir):