Skip to content

Commit 837166f

Browse files
sblondonencukoubitdancer
authored
bpo-32234: Allow mailbox instances as context managers (GH-4770)
Co-authored-by: Petr Viktorin <encukou@gmail.com> Co-authored-by: R. David Murray <rdmurray@bitdance.com>
1 parent 8b7b5a9 commit 837166f

File tree

4 files changed

+32
-0
lines changed

4 files changed

+32
-0
lines changed

Doc/library/mailbox.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,14 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF.
7878
message. Failing to lock the mailbox runs the risk of losing messages or
7979
corrupting the entire mailbox.
8080

81+
The :class:`!Mailbox` class supports the :keyword:`with` statement. When used
82+
as a context manager, :class:`!Mailbox` calls :meth:`lock` when the context is entered,
83+
returns the mailbox object as the context object, and at context end calls :meth:`close`,
84+
thereby releasing the lock.
85+
86+
.. versionchanged:: next
87+
Support for the :keyword:`with` statement was added.
88+
8189
:class:`!Mailbox` instances have the following methods:
8290

8391

Lib/mailbox.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@ def __init__(self, path, factory=None, create=True):
3939
self._path = os.path.abspath(os.path.expanduser(path))
4040
self._factory = factory
4141

42+
def __enter__(self):
43+
self.lock()
44+
return self
45+
46+
def __exit__(self, type, value, traceback):
47+
self.close()
48+
4249
def add(self, message):
4350
"""Add message and return assigned key."""
4451
raise NotImplementedError('Method must be implemented by subclass')

Lib/test/test_mailbox.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,11 @@ def _test_flush_or_close(self, method, should_call_close):
542542
self.assertIn(self._box.get_string(key), contents)
543543
oldbox.close()
544544

545+
def test_use_context_manager(self):
546+
# Mailboxes are usable as a context manager
547+
with self._box as box:
548+
self.assertIs(self._box, box)
549+
545550
def test_dump_message(self):
546551
# Write message representations to disk
547552
for input in (email.message_from_string(_sample_message),
@@ -1122,6 +1127,16 @@ def test_ownership_after_flush(self):
11221127
self.assertEqual(st.st_gid, other_gid)
11231128
self.assertEqual(st.st_mode, mode)
11241129

1130+
def test_context_manager_locks_and_closes(self):
1131+
# Context manager locks/unlocks and closes.
1132+
# (This test uses an implementation detail to get the state.)
1133+
self.assertFalse(self._box._locked)
1134+
with self._box as context_object:
1135+
self.assertIs(self._box, context_object)
1136+
self.assertTrue(self._box._locked)
1137+
self.assertFalse(self._box._file.closed)
1138+
self.assertFalse(self._box._locked)
1139+
self.assertTrue(self._box._file.closed)
11251140

11261141
class _TestMboxMMDF(_TestSingleFile):
11271142

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
:class:`mailbox.Mailbox` instances can now be used as a context manager.
2+
The Mailbox is locked on context entry and unlocked and closed at context exit.

0 commit comments

Comments
 (0)