Skip to content
15 changes: 11 additions & 4 deletions Lib/tempfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -848,10 +848,17 @@ 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:
break

return self._file.writelines(it)

def detach(self):
return self._file.detach()
Expand Down
12 changes: 12 additions & 0 deletions Lib/test/test_tempfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -1288,6 +1288,18 @@ 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())

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 @@
Avoid unbounded buffering for :class:`tempfile.SpooledTemporaryFile`. Previously, when the :meth:`tempfile.SpooledTemporaryFile.writelines` method was called, disk-spillover was only checked after the lines iterator had been exhausted. This is now done while writing instead.
Loading