mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
gh-127371 Avoid unbounded growth SpooledTempfile.writelines (GH-127372)
This commit is contained in:
parent
691354ccb0
commit
cb67b44ca9
3 changed files with 39 additions and 4 deletions
|
@ -868,10 +868,14 @@ class SpooledTemporaryFile(_io.IOBase):
|
||||||
return rv
|
return rv
|
||||||
|
|
||||||
def writelines(self, iterable):
|
def writelines(self, iterable):
|
||||||
file = self._file
|
if self._max_size == 0 or self._rolled:
|
||||||
rv = file.writelines(iterable)
|
return self._file.writelines(iterable)
|
||||||
self._check(file)
|
|
||||||
return rv
|
it = iter(iterable)
|
||||||
|
for line in it:
|
||||||
|
self.write(line)
|
||||||
|
if self._rolled:
|
||||||
|
return self._file.writelines(it)
|
||||||
|
|
||||||
def detach(self):
|
def detach(self):
|
||||||
return self._file.detach()
|
return self._file.detach()
|
||||||
|
|
|
@ -1284,6 +1284,34 @@ class TestSpooledTemporaryFile(BaseTestCase):
|
||||||
buf = f.read()
|
buf = f.read()
|
||||||
self.assertEqual(buf, b'xyz')
|
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):
|
def test_writelines_sequential(self):
|
||||||
# A SpooledTemporaryFile should hold exactly max_size bytes, and roll
|
# A SpooledTemporaryFile should hold exactly max_size bytes, and roll
|
||||||
# over afterward
|
# over afterward
|
||||||
|
|
|
@ -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.
|
Loading…
Add table
Add a link
Reference in a new issue