]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-32234: Allow mailbox instances as context managers (GH-4770)
authorsblondon <stephane.blondon@gmail.com>
Mon, 16 Feb 2026 13:14:26 +0000 (14:14 +0100)
committerGitHub <noreply@github.com>
Mon, 16 Feb 2026 13:14:26 +0000 (14:14 +0100)
Co-authored-by: Petr Viktorin <encukou@gmail.com>
Co-authored-by: R. David Murray <rdmurray@bitdance.com>
Doc/library/mailbox.rst
Lib/mailbox.py
Lib/test/test_mailbox.py
Misc/NEWS.d/next/Library/2017-12-15-09-32-57.bpo-32234.XaOkhR.rst [new file with mode: 0644]

index ed135bf02cb968d0658d4e7bc7e0754b5fa2f6e9..3b0c17c838c87957af8aa557e29232c43f557df6 100644 (file)
@@ -78,6 +78,14 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF.
       message.  Failing to lock the mailbox runs the risk of losing messages or
       corrupting the entire mailbox.
 
+   The :class:`!Mailbox` class supports the :keyword:`with` statement.  When used
+   as a context manager, :class:`!Mailbox` calls :meth:`lock` when the context is entered,
+   returns the mailbox object as the context object, and at context end calls :meth:`close`,
+   thereby releasing the lock.
+
+   .. versionchanged:: next
+      Support for the :keyword:`with` statement was added.
+
    :class:`!Mailbox` instances have the following methods:
 
 
index 65923e9c5de3246adc71b743693791722a2378d7..99426220154360b707a531335e0f318e404078e2 100644 (file)
@@ -39,6 +39,13 @@ class Mailbox:
         self._path = os.path.abspath(os.path.expanduser(path))
         self._factory = factory
 
+    def __enter__(self):
+        self.lock()
+        return self
+
+    def __exit__(self, type, value, traceback):
+        self.close()
+
     def add(self, message):
         """Add message and return assigned key."""
         raise NotImplementedError('Method must be implemented by subclass')
index 288b2c4496faa1e4ed774edcc00a7a72856b76e8..7421076ddd4c3ad6d0b3e2d49d3b47ae27d35ac1 100644 (file)
@@ -542,6 +542,11 @@ class TestMailbox(TestBase):
             self.assertIn(self._box.get_string(key), contents)
         oldbox.close()
 
+    def test_use_context_manager(self):
+        # Mailboxes are usable as a context manager
+        with self._box as box:
+            self.assertIs(self._box, box)
+
     def test_dump_message(self):
         # Write message representations to disk
         for input in (email.message_from_string(_sample_message),
@@ -1122,6 +1127,16 @@ class _TestSingleFile(TestMailbox):
         self.assertEqual(st.st_gid, other_gid)
         self.assertEqual(st.st_mode, mode)
 
+    def test_context_manager_locks_and_closes(self):
+        # Context manager locks/unlocks and closes.
+        # (This test uses an implementation detail to get the state.)
+        self.assertFalse(self._box._locked)
+        with self._box as context_object:
+            self.assertIs(self._box, context_object)
+            self.assertTrue(self._box._locked)
+            self.assertFalse(self._box._file.closed)
+        self.assertFalse(self._box._locked)
+        self.assertTrue(self._box._file.closed)
 
 class _TestMboxMMDF(_TestSingleFile):
 
diff --git a/Misc/NEWS.d/next/Library/2017-12-15-09-32-57.bpo-32234.XaOkhR.rst b/Misc/NEWS.d/next/Library/2017-12-15-09-32-57.bpo-32234.XaOkhR.rst
new file mode 100644 (file)
index 0000000..b222898
--- /dev/null
@@ -0,0 +1,2 @@
+:class:`mailbox.Mailbox` instances can now be used as a context manager.
+The Mailbox is locked on context entry and unlocked and closed at context exit.