Skip to content

Commit 903913b

Browse files
eendebakptclaude
andcommitted
gh-157509: Speed up reading mbox, MMDF and Babyl mailboxes
Track line offsets in _generate_toc() with len(line) instead of calling tell(), which is a system call, for every line. Also compute the MMDF and Babyl separator bytes once instead of per line. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent c674116 commit 903913b

2 files changed

Lines changed: 18 additions & 9 deletions

File tree

Lib/mailbox.py

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -922,9 +922,11 @@ def _generate_toc(self):
922922
starts, stops = [], []
923923
last_was_empty = False
924924
self._file.seek(0)
925+
next_pos = 0
925926
while True:
926-
line_pos = self._file.tell()
927+
line_pos = next_pos
927928
line = self._file.readline()
929+
next_pos += len(line)
928930
if line.startswith(b'From '):
929931
if len(stops) < len(starts):
930932
if last_was_empty:
@@ -972,17 +974,18 @@ def _generate_toc(self):
972974
starts, stops = [], []
973975
self._file.seek(0)
974976
next_pos = 0
977+
sep = b'\001\001\001\001' + linesep
975978
while True:
976979
line_pos = next_pos
977980
line = self._file.readline()
978-
next_pos = self._file.tell()
979-
if line.startswith(b'\001\001\001\001' + linesep):
981+
next_pos += len(line)
982+
if line.startswith(sep):
980983
starts.append(next_pos)
981984
while True:
982985
line_pos = next_pos
983986
line = self._file.readline()
984-
next_pos = self._file.tell()
985-
if line == b'\001\001\001\001' + linesep:
987+
next_pos += len(line)
988+
if line == sep:
986989
stops.append(line_pos - len(linesep))
987990
break
988991
elif not line:
@@ -1418,19 +1421,23 @@ def _generate_toc(self):
14181421
self._file.seek(0)
14191422
next_pos = 0
14201423
label_lists = []
1424+
msg_sep = b'\037\014' + linesep
1425+
end_sep = b'\037' + linesep
14211426
while True:
14221427
line_pos = next_pos
14231428
line = self._file.readline()
1424-
next_pos = self._file.tell()
1425-
if line == b'\037\014' + linesep:
1429+
next_pos += len(line)
1430+
if line == msg_sep:
14261431
if len(stops) < len(starts):
14271432
stops.append(line_pos - len(linesep))
14281433
starts.append(next_pos)
1434+
label_line = self._file.readline()
1435+
next_pos += len(label_line)
14291436
labels = [label.strip() for label
1430-
in self._file.readline()[1:].split(b',')
1437+
in label_line[1:].split(b',')
14311438
if label.strip()]
14321439
label_lists.append(labels)
1433-
elif line == b'\037' or line == b'\037' + linesep:
1440+
elif line == b'\037' or line == end_sep:
14341441
if len(stops) < len(starts):
14351442
stops.append(line_pos - len(linesep))
14361443
elif not line:
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Speed up reading :class:`mailbox.mbox`, :class:`mailbox.MMDF` and
2+
:class:`mailbox.Babyl` mailboxes.

0 commit comments

Comments
 (0)