Skip to content

Commit

Permalink
pythongh-127371 Avoid unbounded growth SpooledTempfile.writelines (py…
Browse files Browse the repository at this point in the history
  • Loading branch information
bertptrs authored Mar 4, 2025
1 parent 691354c commit cb67b44
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 4 deletions.
12 changes: 8 additions & 4 deletions Lib/tempfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -868,10 +868,14 @@ def write(self, s):
return rv

def writelines(self, iterable):
file = self._file
rv = file.writelines(iterable)
self._check(file)
return rv
if self._max_size == 0 or self._rolled:
return self._file.writelines(iterable)

it = iter(iterable)
for line in it:
self.write(line)
if self._rolled:
return self._file.writelines(it)

def detach(self):
return self._file.detach()
Expand Down
28 changes: 28 additions & 0 deletions Lib/test/test_tempfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -1284,6 +1284,34 @@ def test_writelines(self):
buf = f.read()
self.assertEqual(buf, b'xyz')

def test_writelines_rollover(self):
# Verify writelines rolls over before exhausting the iterator
f = self.do_create(max_size=2)

def it():
yield b'xy'
self.assertFalse(f._rolled)
yield b'z'
self.assertTrue(f._rolled)

f.writelines(it())
pos = f.seek(0)
self.assertEqual(pos, 0)
buf = f.read()
self.assertEqual(buf, b'xyz')

def test_writelines_fast_path(self):
f = self.do_create(max_size=2)
f.write(b'abc')
self.assertTrue(f._rolled)

f.writelines([b'd', b'e', b'f'])
pos = f.seek(0)
self.assertEqual(pos, 0)
buf = f.read()
self.assertEqual(buf, b'abcdef')


def test_writelines_sequential(self):
# A SpooledTemporaryFile should hold exactly max_size bytes, and roll
# over afterward
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Avoid unbounded buffering for :meth:`!tempfile.SpooledTemporaryFile.writelines`.
Previously, disk spillover was only checked after the lines iterator had been
exhausted. This is now done after each line is written.

0 comments on commit cb67b44

Please sign in to comment.