mirror of https://github.com/python/cpython
merge #11767: use context manager to close file in __getitem__ to prevent FD leak
This commit is contained in:
commit
4c7d21e2b3
|
@ -20,6 +20,7 @@ import email
|
||||||
import email.message
|
import email.message
|
||||||
import email.generator
|
import email.generator
|
||||||
import io
|
import io
|
||||||
|
import contextlib
|
||||||
try:
|
try:
|
||||||
if sys.platform == 'os2emx':
|
if sys.platform == 'os2emx':
|
||||||
# OS/2 EMX fcntl() not adequate
|
# OS/2 EMX fcntl() not adequate
|
||||||
|
@ -76,7 +77,8 @@ class Mailbox:
|
||||||
if not self._factory:
|
if not self._factory:
|
||||||
return self.get_message(key)
|
return self.get_message(key)
|
||||||
else:
|
else:
|
||||||
return self._factory(self.get_file(key))
|
with contextlib.closing(self.get_file(key)) as file:
|
||||||
|
return self._factory(file)
|
||||||
|
|
||||||
def get_message(self, key):
|
def get_message(self, key):
|
||||||
"""Return a Message representation or raise a KeyError."""
|
"""Return a Message representation or raise a KeyError."""
|
||||||
|
|
|
@ -1201,6 +1201,37 @@ class TestBabyl(TestMailbox):
|
||||||
self.assertEqual(set(self._box.get_labels()), set(['blah']))
|
self.assertEqual(set(self._box.get_labels()), set(['blah']))
|
||||||
|
|
||||||
|
|
||||||
|
class FakeFileLikeObject:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.closed = False
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self.closed = True
|
||||||
|
|
||||||
|
|
||||||
|
class FakeMailBox(mailbox.Mailbox):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
mailbox.Mailbox.__init__(self, '', lambda file: None)
|
||||||
|
self.files = [FakeFileLikeObject() for i in range(10)]
|
||||||
|
|
||||||
|
def get_file(self, key):
|
||||||
|
return self.files[key]
|
||||||
|
|
||||||
|
|
||||||
|
class TestFakeMailBox(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_closing_fd(self):
|
||||||
|
box = FakeMailBox()
|
||||||
|
for i in range(10):
|
||||||
|
self.assertFalse(box.files[i].closed)
|
||||||
|
for i in range(10):
|
||||||
|
box[i]
|
||||||
|
for i in range(10):
|
||||||
|
self.assertTrue(box.files[i].closed)
|
||||||
|
|
||||||
|
|
||||||
class TestMessage(TestBase):
|
class TestMessage(TestBase):
|
||||||
|
|
||||||
_factory = mailbox.Message # Overridden by subclasses to reuse tests
|
_factory = mailbox.Message # Overridden by subclasses to reuse tests
|
||||||
|
@ -2113,7 +2144,7 @@ def test_main():
|
||||||
TestBabyl, TestMessage, TestMaildirMessage, TestMboxMessage,
|
TestBabyl, TestMessage, TestMaildirMessage, TestMboxMessage,
|
||||||
TestMHMessage, TestBabylMessage, TestMMDFMessage,
|
TestMHMessage, TestBabylMessage, TestMMDFMessage,
|
||||||
TestMessageConversion, TestProxyFile, TestPartialFile,
|
TestMessageConversion, TestProxyFile, TestPartialFile,
|
||||||
MaildirTestCase)
|
MaildirTestCase, TestFakeMailBox)
|
||||||
support.run_unittest(*tests)
|
support.run_unittest(*tests)
|
||||||
support.reap_children()
|
support.reap_children()
|
||||||
|
|
||||||
|
|
|
@ -193,6 +193,8 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #11767: Correct file descriptor leak in mailbox's __getitem__ method.
|
||||||
|
|
||||||
- Issue #12133: AbstractHTTPHandler.do_open() of urllib.request closes the HTTP
|
- Issue #12133: AbstractHTTPHandler.do_open() of urllib.request closes the HTTP
|
||||||
connection if its getresponse() method fails with a socket error. Patch
|
connection if its getresponse() method fails with a socket error. Patch
|
||||||
written by Ezio Melotti.
|
written by Ezio Melotti.
|
||||||
|
|
Loading…
Reference in New Issue