From 42382fedccf1306c09055b68c0b67351118f8065 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Giampaolo=20Rodol=C3=A0?= Date: Tue, 17 Aug 2010 16:09:53 +0000 Subject: [PATCH] fix issue #8807: adds a context parameter to POP3_SSL class. --- Doc/library/poplib.rst | 10 ++++++++-- Doc/whatsnew/3.2.rst | 7 +++++++ Lib/poplib.py | 18 ++++++++++++++---- Lib/test/test_poplib.py | 21 +++++++++++++++++++-- Misc/NEWS | 5 +++++ 5 files changed, 53 insertions(+), 8 deletions(-) diff --git a/Doc/library/poplib.rst b/Doc/library/poplib.rst index b397b4b26c7..b60ad0ea4b0 100644 --- a/Doc/library/poplib.rst +++ b/Doc/library/poplib.rst @@ -32,13 +32,19 @@ A single class is provided by the :mod:`poplib` module: be used). -.. class:: POP3_SSL(host, port=POP3_SSL_PORT, keyfile=None, certfile=None[, timeout]) +.. class:: POP3_SSL(host, port=POP3_SSL_PORT, keyfile=None, certfile=None, timeout=None, context=None) This is a subclass of :class:`POP3` that connects to the server over an SSL encrypted socket. If *port* is not specified, 995, the standard POP3-over-SSL port is used. *keyfile* and *certfile* are also optional - they can contain a PEM formatted private key and certificate chain file for the SSL connection. - *timeout* works as in the :class:`POP3` constructor. + *timeout* works as in the :class:`POP3` constructor. *context* parameter is a + :class:`ssl.SSLContext` object which allows bundling SSL configuration + options, certificates and private keys into a single (potentially long-lived) + structure. + + .. versionchanged:: 3.2 + *context* parameter added. One exception is defined as an attribute of the :mod:`poplib` module: diff --git a/Doc/whatsnew/3.2.rst b/Doc/whatsnew/3.2.rst index d03a67fd6a5..a2b7af4d934 100644 --- a/Doc/whatsnew/3.2.rst +++ b/Doc/whatsnew/3.2.rst @@ -186,6 +186,13 @@ New, Improved, and Deprecated Modules (Contributed by Giampaolo RodolĂ ; :issue:`8866`.) +* :class:`~poplib.POP3_SSL` class now accepts a *context* parameter, which is a + :class:`ssl.SSLContext` object allowing bundling SSL configuration options, + certificates and private keys into a single (potentially long-lived) + structure. + + (Contributed by Giampaolo RodolĂ ; :issue:`8807`.) + Multi-threading =============== diff --git a/Lib/poplib.py b/Lib/poplib.py index 1a529d0a138..84ea88de46b 100644 --- a/Lib/poplib.py +++ b/Lib/poplib.py @@ -331,16 +331,26 @@ else: See the methods of the parent class POP3 for more documentation. """ - def __init__(self, host, port=POP3_SSL_PORT, - keyfile=None, certfile=None, - timeout=socket._GLOBAL_DEFAULT_TIMEOUT): + def __init__(self, host, port=POP3_SSL_PORT, keyfile=None, certfile=None, + timeout=socket._GLOBAL_DEFAULT_TIMEOUT, context=None): + if context is not None and keyfile is not None: + raise ValueError("context and keyfile arguments are mutually " + "exclusive") + if context is not None and certfile is not None: + raise ValueError("context and certfile arguments are mutually " + "exclusive") self.keyfile = keyfile self.certfile = certfile + self.context = context POP3.__init__(self, host, port, timeout) def _create_socket(self, timeout): sock = POP3._create_socket(self, timeout) - return ssl.wrap_socket(sock, self.keyfile, self.certfile) + if self.context is not None: + sock = self.context.wrap_socket(sock) + else: + sock = ssl.wrap_socket(sock, self.keyfile, self.certfile) + return sock __all__.append("POP3_SSL") diff --git a/Lib/test/test_poplib.py b/Lib/test/test_poplib.py index c831fb467a6..2adc8492823 100644 --- a/Lib/test/test_poplib.py +++ b/Lib/test/test_poplib.py @@ -122,6 +122,7 @@ class DummyPOP3Server(asyncore.dispatcher, threading.Thread): self.active = False self.active_lock = threading.Lock() self.host, self.port = self.socket.getsockname()[:2] + self.handler_instance = None def start(self): assert not self.active @@ -145,8 +146,7 @@ class DummyPOP3Server(asyncore.dispatcher, threading.Thread): def handle_accept(self): conn, addr = self.accept() - self.handler = self.handler(conn) - self.close() + self.handler_instance = self.handler(conn) def handle_connect(self): self.close() @@ -287,6 +287,23 @@ if hasattr(poplib, 'POP3_SSL'): def test__all__(self): self.assertIn('POP3_SSL', poplib.__all__) + def test_context(self): + ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) + self.assertRaises(ValueError, poplib.POP3_SSL, self.server.host, + self.server.port, keyfile=CERTFILE, context=ctx) + self.assertRaises(ValueError, poplib.POP3_SSL, self.server.host, + self.server.port, certfile=CERTFILE, context=ctx) + self.assertRaises(ValueError, poplib.POP3_SSL, self.server.host, + self.server.port, keyfile=CERTFILE, + certfile=CERTFILE, context=ctx) + + self.client.quit() + self.client = poplib.POP3_SSL(self.server.host, self.server.port, + context=ctx) + self.assertIsInstance(self.client.sock, ssl.SSLSocket) + self.assertIs(self.client.sock.context, ctx) + self.assertTrue(self.client.noop().startswith(b'+OK')) + class TestTimeouts(TestCase): diff --git a/Misc/NEWS b/Misc/NEWS index 8e68e71d0e6..95a9d58f7a4 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -93,6 +93,11 @@ Extensions Library ------- +- Issue #8807: poplib.POP3_SSL class now accepts a context parameter, which is a + ssl.SSLContext object allowing bundling SSL configuration options, + certificates and private keys into a single (potentially long-lived) + structure. + - Issue #8866: parameters passed to socket.getaddrinfo can now be specified as single keyword arguments.